Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

The Requirements + Features Registry

Underneath every analyzer spec's parentRequirement: 'X' declaration is a real Requirement class living in ddd-spec. Underneath every test's @FeatureTest/@Verifies decoration is a Feature class living in ddd-spec-features. The two packages are the corpus's internal contract registry — small, load-bearing, the thing every pattern in this series quietly depends on. This article covers both because they are not separable in practice.


What the Spec Kernel Reifies

The corpus operates on a four-layer ontology. Requirements are named compliance anchors — BoundedContextCohesionRequirement, EventSourcingPersistedTruthRequirement, etc. They state what the corpus formally promises to enforce. Features are the AC-bearing test surfaces — one feature class per pattern's analyzer and codegen, with acceptance-criteria methods that the test suite implements. @FeatureTest/@Verifies decorations bind individual tests to specific ACs on specific features. The compliance gate walks the chain — Requirements should map to Features, Features should have ACs, ACs should be covered by tests with the right decorations.

ddd-spec owns the first layer. ddd-spec-features owns the second. The decorations live in @frenchexdev/requirements. The compliance gate runs from Compliance plugin. Four packages, one ontology.


The Runtime: ddd-spec

base.ts exports CanonicalDddRequirement, an abstract base class. The base pre-fills the conventional values for the corpus:

export abstract class CanonicalDddRequirement extends Requirement {
  readonly status             = 'Approved' as const;
  readonly kind               = 'Functional' as const;
  readonly verificationMethod = 'Test' as const;
  readonly source: RequirementProvenance = DDD_SPEC_SOURCE;
}

Subclasses declare only the parts that vary — id, title, priority, statement, rationale, fitCriteria, risk, optional tracedTo. The corpus's Requirements end up looking like:

export class BoundedContextCohesionRequirement extends CanonicalDddRequirement {
  readonly id        = 'REQ-BOUNDED-CONTEXT-COHESION';
  readonly title     = 'BoundedContext Cohesion';
  readonly priority  = Priority.Critical;
  readonly statement = 'A bounded context is a linguistic frontier inside which terms have one meaning.';
  readonly rationale = 'Cross-context drift is the most expensive class of strategic-DDD failure (Evans ch. 14).';
  readonly fitCriteria = ['Every @BoundedContext declares a name', 'No two BCs share a name', /* ... */];
  readonly risk        = 'High — strategic boundary errors survive multiple refactors.';
}

The Requirement is itself a class — discoverable, listable, graph-able. The Spec plugin's spec:list and spec:graph operate on these classes.


The Runtime: ddd-spec-features

ddd-spec-features (packages/ddd-spec-features) declares the Feature class shape every pattern's analyzer/codegen produces. Each Feature class names a set of ACs as abstract methods; the test suite extends the Feature class and implements each AC as a test method. The shape is what defineAnalyzerSpec and defineCodegenSpec ultimately generate — the spec's acceptanceCriteria list becomes the Feature class's method list.

The package also exports the codegen helpers (CodesGenerator, RulesGenerator, AnalyzerGenerator, TestSkeletonGenerator, PropertyTestGenerator) that the analyzer pipelines invoke. The pattern is mutually-recursive: ddd-spec-features/codegen is what generates analyzers and codegens that themselves declare specs from ddd-spec-features/codegen. The bootstrap is hand-written; everything else is generated.


Why a Single Article for Two Packages

The two packages are operationally inseparable. Every Requirement in ddd-spec is verified by Features in ddd-spec-features. Every Feature in ddd-spec-features points at a Requirement in ddd-spec. Splitting the article would force two reading paths that are always traversed together; the single article respects the actual usage shape.

The pattern this triplet uses is unusual for a triplet. There is no ddd-spec-analyzer or ddd-spec-codegen — the kernel is the bootstrap, and a self-generating analyzer would be a fixed-point problem the corpus does not currently solve. The hand-written shape is deliberate; everything else in the corpus generates from these two packages.


  • Every analyzer spec's parentRequirement: 'X' resolves to a CanonicalDddRequirement subclass in ddd-spec.
  • Every codegen spec's featureId: 'X' corresponds to a Feature class in ddd-spec-features.
  • The Compliance plugin reads from both packages to build the traceability matrix.
  • The Spec plugin lists and graphs the Requirements registered here.
  • The Preset's tacticalRequirements and applicationRequirements arrays name Requirements registered here.

Back to the series index.

⬇ Download