Chapter 22 — Roadmap and Open Questions
What the DSL still has to become, where it is already on a path, and the questions no one on the team has answered yet.
The previous twenty-one chapters of this series have been, almost entirely, descriptive. They have taken the state of @frenchexdev/requirements as of 2026-04-14 and read it back — twenty-two Requirements, twenty-five Features, fifty-four tests without a single describe or it, five Styles, one scenario player frozen as a contract before any code was cut.
This chapter is not descriptive. It names, in plain terms, what the DSL still has to become — and does so from inside the DSL itself. The central roadmap items below are not bullet points on a wiki page; they are Requirement classes that exist on disk today, in Draft status, under packages/requirements/requirements/requirements/. Some of them carry readonly enabled = false on their companion Feature. All of them are part of the same traceability graph that the rest of the series has been dissecting.
Treating the roadmap this way has a concrete consequence: every item below has a stable identifier, a typed statement, a rationale with evidence, fit criteria, and a risk clause. It has the same shape as the Requirements shipped features are bound to. When the roadmap moves — when REQ-VERSIONED-TRACEABILITY moves from Draft to Approved, when the scenarii player ships its first green run — the move is a diff on a typed artefact, not a line-edit on a document.
Four horizons structure the chapter. I have named them after classes of concern, not quarters:
- Stabilize — what the DSL already does that still needs to settle: migration tools for the versioning work, hardening of the registry, sharper compliance diagnostics.
- Scale — what stops being tractable when the DSL leaves a single repo: cross-package REQ sharing, namespace import, registry service questions.
- AI — what the DSL has to say about LLMs as implementers, and what it refuses to say: the adapter port, the stub default, the contract with the scenarii player.
- Audit — what a regulated customer needs before accepting the DSL as an audit artefact: versioned traceability, signed history entries, 21 CFR Part 11 alignment.
Three of the four horizons already have named Requirements sitting in Draft. The fourth (Scale) is mostly open questions. That asymmetry is honest — Audit and AI are design-complete and implementation-pending, Stabilize is implementation-active, Scale is genuinely not yet shaped.
The horizon, drawn
The four swim-lanes below map each named spec to an approximate position across the next four quarters, ending mid-2027. Dates are planning fiction; the classes and the ordering relations are not.
The two load-bearing precedence arrows are inside the Audit lane. Versioning has to land before HistoryEntry migration tooling can do anything useful — the migration tool's whole job is to rewrite hashes and supersedes chains. Audit-trail hooks (Reviewed, ApprovedBy, SignedOff) have to land as typed no-ops before Tier-3 crypto can hang off them. Reverse those, and the schema either migrates twice or never migrates cleanly.
The Stabilize lane's arrows are softer — diagnostics improvements, migration tools, registry hardening can interleave. The AI lane is a single chain because each card assumes the previous one is in place. The Scale lane does not carry arrows because the items are open questions, not sequenced work.
Horizon 1 — Stabilize
Stabilize is the quietest horizon. Nothing here is a new idea. Everything here sharpens something that already exists.
Compliance diagnostics
Chapter 13c ran through the diagnostic paths compliance --strict takes when a run fails. What that chapter did not cover is the one pattern that still surfaces as noise: a Feature pinning a Requirement whose hash has drifted by a cosmetic edit. Today, a whitespace change on a Requirement's statement.response bumps the content hash, bumps the version, and produces a version-drift failure on every Feature that pins it.
The fix is the normalisation algorithm that REQ-VERSIONED-TRACEABILITY names as an assumption:
The content-hash function normalises formatting so cosmetic edits do not bump versions.
That line is load-bearing. Without it, the version column becomes a noise channel and maintainers will start adding // eslint-disable-next-line equivalents until the gate is worthless. With it, the version column becomes a signal — every bump means something, and the Feature author can re-pin with confidence.
What the Stabilize horizon owes: a published normalisation spec, a conformance test suite, and diagnostics on the strict-compliance failure path that say "this change is cosmetic; the content hash is unchanged; no action needed" versus "this change is semantic; please review Feature pins". Two sentences of diagnostic prose, but those two sentences decide whether the feature is usable at scale.
Migration tools
Once versioning lands, the corpus on disk will carry $schemaVersion: '2026-04-14' on every spec. The next schema change — whatever it is — will need a tool that reads, rewrites, and writes back every spec in place, preserving history, not losing supersedes chains, not collapsing append-only logs.
This is not a hypothetical. The @Reviewed / @SignedOff decorators named by REQ-AUDIT-TRAIL-HOOKS will ship as no-ops first and gain semantics later. That "gain semantics" step is a schema change even if it is a strictly additive one. Migration tools are the thing that lets the corpus accept the change without a flag-day rewrite.
What the Stabilize horizon owes: a requirements migrate subcommand that takes a --from and --to version, a normalising pass that is idempotent, and a dry-run mode that prints the diff before writing. Not glamorous; foundational.
Registry hardening
The style registry and the scaffolder registry are two of the most-used ports in the DSL. They are also two of the least-defended. Today, a project plugging a custom style can accidentally shadow a built-in style by ID collision, and the error surface is a confusing runtime lookup miss. The registry should reject collisions at registration time, with a diagnostic that names both the incoming style and the existing registration.
Similarly for the scaffolder registry: the level field is a discriminated union today, but the CLI does not enforce that two registered scaffolders never claim the same level. Two scaffolders claiming unit is a silent overwrite. This is a single-digit line change in the registry constructor; it has been on the backlog for six weeks because the failure mode has not yet bitten anyone. That is exactly the kind of latent risk the Stabilize horizon exists to retire.
Horizon 2 — Scale
Scale is the horizon of open questions. No Requirement in Draft status yet names any of the items below. The questions are real and the answers are not.
Namespace import DSL
A Requirement today lives in a single file and is imported by its class. A Feature satisfies it by listing the imported class inside @Satisfies(...). This works inside a single package. It starts to strain when one package wants to pin a Requirement defined in another.
One shape — the one most consistent with the rest of the DSL — is a namespace import:
// Hypothetical, not implemented.
import { Req as IndustrialReqs } from '@frenchexdev/requirements-industrial';
@Satisfies(IndustrialReqs.REQ_SIL_3_INSTRUMENTED_FUNCTION)
export abstract class MyFeature extends Feature {
// ...
}// Hypothetical, not implemented.
import { Req as IndustrialReqs } from '@frenchexdev/requirements-industrial';
@Satisfies(IndustrialReqs.REQ_SIL_3_INSTRUMENTED_FUNCTION)
export abstract class MyFeature extends Feature {
// ...
}The shape reads well. It also raises two questions the DSL has not answered:
- Version pinning across packages. If the industrial requirements package ships a minor version that bumps
REQ_SIL_3_INSTRUMENTED_FUNCTION, should the consumer's@Satisfiesbreak? The answer is "only if the Requirement's content hash changed semantically", which means the content-hash normalisation from the Stabilize horizon has to be inter-package-stable. That is a harder guarantee than intra-package stability. - Resolution at compliance time. The
compliance --strictcommand today reads a single package's traceability graph. Cross-package@Satisfiesmeans resolving into other packages' graphs, which means either bundling their traceability metadata into the consumer'snode_modules/or introducing a registry lookup. Both have costs.
The open question is not "should we support this?" — the answer is clearly yes, eventually. The open question is "which of the two failure modes (a cross-package hash break, or a missing registry lookup) is more acceptable to a user whose compliance --strict suddenly fails?"
Cross-package REQ sharing
Adjacent to the import question but not the same: can a Requirement be shared by multiple packages, in the sense that two sibling packages both own a piece of its satisfaction?
This shape appears naturally when a monorepo has, say, a billing-core package and a billing-ui package, and a Requirement REQ-NO-HIDDEN-SURCHARGE lives in a shared billing-domain package. Both siblings satisfy parts of it. Today the DSL has no word for "partial satisfaction" — a Feature either @Satisfies a Requirement or it does not.
Partial satisfaction is a real concept in SysML («refine» and «deriveReqt») and it is part of why REQ-VERSIONED-TRACEABILITY's fit criteria include a supersedes chain. But the current DSL leans on @Refines for Requirement → Requirement and @Satisfies for Feature → Requirement, and does not cover Feature → partial of Requirement.
The open question: do we add a @SatisfiesPartially(Req, 'clause-name') decorator, or do we instead refine the Requirement into sub-Requirements and let each Feature satisfy a sub-Requirement fully? The second approach keeps the decorator surface minimal, at the cost of forcing decomposition on every shared Requirement. The first approach adds a decorator but keeps the Requirement intact. Neither is obviously right.
A registry service, and the speculative leap to Requirements-as-a-Service
The further-out cards in the Scale lane are deliberately speculative. A registry service would be a hosted endpoint that packages publish their traceability graphs to, so consumers can resolve cross-package @Satisfies without bundling. A Requirements-as-a-Service layer would go further, hosting the corpus itself (not just the graph metadata), turning the DSL into a thin client.
Both ideas carry a political cost the rest of the series should not ignore. A DSL whose main artefact lives on someone else's server is no longer the same DSL. The Requirement classes would still compile locally — the types, the decorators, the rationale — but the authoritative graph would not. That is a different product, and whether it is a product this package wants to grow into is an open question with at least as much weight as the technical one.
For now, both cards sit on the horizon as prompts for future discussion. Nothing on the Audit horizon assumes them. Nothing on the AI horizon assumes them. If they are never built, the rest of the roadmap still works.
Horizon 3 — AI
Horizon 3 is where the DSL has the most opinion and the smallest code footprint. The opinion is that AI-implementer support is an adapter at the edge of a typed FSM, and that the rest of the system neither knows nor cares that the implementer is an LLM.
REQ-AI-AS-IMPLEMENTER-ADAPTER
The Requirement is already on disk, in Draft status, with the following statement:
When the player is invoked with
--ai, the PerAcFsm shall delegate AC implementation to an AiAdapter port; without--ai, it shall emit deterministic throw stubs and the project shall compile and its scaffolded tests fail with a clear "not yet implemented" message.
The shape of this statement is load-bearing. Three things to notice.
First, the default is not AI. The default is the deterministic stub. --ai is opt-in. This is not a hedge against LLM quality — it is a property of the adapter pattern. The player must be demonstrable offline, in CI, on a laptop without an API key, producing byte-identical artefacts for a given seed. The deterministic stub is how that promise is kept.
Second, the adapter is a port, not an agent. The type AiAdapter lives at src/cli/scenario/ports.ts. The Claude API implementation lives in a separate file. No @anthropic-ai/sdk import is allowed outside that file. No fetch( call is allowed outside that file. The fit criterion enforces this with a rg quality gate:
rg "anthropic|fetch\(" src/cli/scenario/ -g "!**/adapters/claude-*.ts"rg "anthropic|fetch\(" src/cli/scenario/ -g "!**/adapters/claude-*.ts"Must return zero matches. If it returns a match, compliance fails. This is the point of the adapter pattern expressed as a single shell command: "everything else, touch no network".
Third, the AI's job is scoped. It does not own the FSM. It does not decide transitions. It does not read the scenario file. It receives a prompt (generated from the AC signature and the test scaffold) and returns an implementation body. The FSM — PerAcFsm — owns the lifecycle; the AI owns only the body.
This last point is easy to understate. A lot of AI-coding tooling on the market today gives the model the repo, lets it read everything, lets it propose transitions. That is an agent. This is not that. The AI here is a typed function: (prompt: string) => Promise<string>, bounded on both sides by the FSM and by the scaffolded test. If the test does not pass, the FSM either retries (with failure context) or fails the AC. There is no magic.
Scenarii player — the three-FSM orchestration
Chapter 15 walked through the three FSMs — ProjectLifecycleFsm, PerFeatureFsm, PerAcFsm — at the level of state diagrams. The roadmap item here is narrower: the first end-to-end green run of a non-trivial scenario, emitting a full set of artefacts (Requirements, Features, ACs, scaffolded tests, AI-implemented bodies, passing test suite, compliance --strict success).
The design is frozen. The design document, packages/requirements/docs/scenarii-player-design.md, locks the three FSMs' states, events, guards, and entry actions. No new state is allowed into any FSM without a design-doc update. The implementation is deferred to what the package calls "Vague 3 agents" — a later wave of work. The roadmap promise for Q3 2026 is the first green run on a seed scenario large enough to stress all three FSMs (at minimum: two Requirements, three Features, ten ACs, two test levels per AC).
The coupling contract in the design document is worth re-quoting:
The three FSMs share no mutable state. Cross-FSM communication is a single typed event bus owned by the orchestrator. The orchestrator appends every event to a replay log. Replaying the log on a fresh set of FSMs must produce byte-identical final states and disk artifacts under a fixed
--seed.
This is the property that lets the AI adapter plug in cleanly. Replay is the forcing function. An AI that produces non-deterministic output breaks replay; the adapter must either be deterministic-under-seed (possible with some providers) or the replay log must record the response, not the prompt. The current design records both, because the response is cheap and the determinism story for LLMs is not settled.
Prompt caching as a quality gate
The claude-api skill mandates prompt caching on every Claude API adapter. The roadmap item for Q4 2026 is turning that into a compliance gate: a build that invokes the AI adapter without prompt caching active should fail. Whether the gate lives as a fit criterion on REQ-AI-AS-IMPLEMENTER-ADAPTER or as a new Requirement is an editorial decision the package has not made yet.
Deterministic-stub conformance suite
The last card in the AI lane is dual to the first. If the adapter pattern is the contract, the stub implementation must be conformance-tested against the same port as the AI implementation. The roadmap item is a conformance suite that runs every FSM transition twice — once with the stub adapter, once with a recorded-responses adapter driven by a captured Claude API session — and asserts that the state machines reach identical terminal states and the on-disk artefacts, minus the AC body content, are byte-identical.
This is the test that lets the package say, with a straight face, that the AI integration is a productivity boost and not a substrate. If the two runs diverge on anything except the AC body content, the claim fails.
Horizon 4 — Audit
The Audit horizon is where the DSL meets regulated work. Two Requirements sit on this horizon, both in Draft, both with explicit standards citations in their source field.
REQ-VERSIONED-TRACEABILITY
Versioned traceability is the more foundational of the two. Its statement:
compute a
VersionInfo(monotonic integer + deterministic content-hash + since-date) for every Requirement, Feature, and AC, and failcompliance --strictwhen a Feature pins a prior version of a Requirement whose current version differs.
Three fields, one gate. The monotonic integer is there for human readability — auditors want to see v7, not sha-3a1f…. The content hash is there for machine verification — a human can be fooled by a cosmetic edit, a hash cannot. The since-date is there for audit reconstruction — when did this Requirement last materially change, and which release included the change?
The source field names two standards:
- IEC 61508 — Functional safety of electrical / electronic / programmable electronic safety-related systems. 2010.
- 21 CFR Part 11 — Electronic Records; Electronic Signatures. US FDA, 1997.
Both regulations turn on the same pivot: an audit trail must be immutable. Git commits are the industrial precedent cited in the rationale — content-addressed storage has been the accepted pattern for immutable audit trails since Linus wrote the first prototype in 2005. The DSL is not inventing anything here; it is bringing a well-understood pattern into the Requirement / Feature / AC graph.
The risk clause is explicit:
Regulated customers (pharma / safety / finance) reject the DSL outright because the traceability artefact does not carry immutable version semantics.
Level: Critical. This is the ceiling on where the DSL can be adopted. Without versioning, the package is a productivity tool for software teams. With versioning, it becomes a candidate audit artefact for regulated teams. The gap between those two markets is the whole reason this horizon exists.
Two mitigations soften the landing. First, version-info ships as a pure additive field — an existing corpus continues to work, and the gate only fires on --strict. Second, unpinned @Satisfies are tolerated as warnings, not errors, to avoid breaking the dog-food corpus this series has been built on. A full cutover to hard failure is a later decision.
REQ-AUDIT-TRAIL-HOOKS
Audit-trail hooks extends versioning into the review / approval / sign-off pattern that 21 CFR Part 11 Part E (Electronic Signatures) requires. The statement:
support review / approval / sign-off semantics on history entries as typed no-op decorators and an optional
signaturefield, so 21 CFR Part 11 Part E integration can be added later without a schema migration.
The rationale names the economics directly:
Schema migrations are disproportionately expensive for traceability artefacts because every downstream consumer (auditors, regulators, other repos) re-reads the corpus. Reserving the hooks now is cheap; reserving them later is a breaking change.
The implementation footprint is small. The ChangeKind discriminated union gains three new variants (Reviewed, ApprovedBy, SignedOff). The HistoryEntry type gains an optional signature field typed as a discriminated union over Ed25519 and RSA-SHA256. Two decorators (@Reviewed, @SignedOff) ship as typed no-ops that register metadata without doing crypto.
Crypto is deferred. The mitigation clause is explicit: "Land only the hooks (types + no-op decorators), no crypto or verification logic — Tier 3 owns the signature implementation." This is the Q2 2027 card in the Audit lane — the Tier-3 wave that actually verifies signatures, checks certificate chains, and rejects tampered history entries. Until that card lands, @Reviewed and @SignedOff produce audit metadata but do not authenticate it.
That separation matters. A customer who does not need electronic signatures pays no complexity cost — the hooks are invisible. A customer who does need them finds the schema already shaped to accept them, no migration required. The pattern name for this is "reserved extension points"; the DSL calls it hooks and documents why.
Hooks to external systems
A separate, smaller piece of the Audit horizon is outward integration. REQ-AUDIT-TRAIL-HOOKS today names the inward shape — the ChangeKind union, the signature field, the no-op decorators. It does not yet name the outward shape: how audit events flow from the DSL to external trackers (Jira, Linear, a SIEM).
The outward hooks are not yet a Requirement. They are a design note. The expected shape is an AuditSink port with a single method emit(event: HistoryEntry): Promise<void> and adapters for the common systems. compliance --strict would invoke the sink on every history entry emitted during its run, and the sink would be pluggable per-project.
This is a Q1 2027 card and is the closest thing on the roadmap to a real cross-system integration. The risk is small: a failing sink should not fail the compliance gate (audit events should be retryable, not blocking), but a silent sink failure should surface in the compliance report. Both of those are diagnostics refinements, not new types.
Open questions
The four horizons above are the structured part of the roadmap. Below is the unstructured part — questions the team has been circling without resolving. They are listed deliberately without proposed answers.
Namespace import — revisited
Revisited because it appears in both the Scale lane and here. The Scale-lane framing is "how should it work?"; the open-question framing is "should it work at all, or should cross-package Requirements be a different artefact type?" There is a serious argument that cross-package Requirements ought to be compiled into the consuming package rather than imported across a package boundary — a pre-build step rather than a runtime resolution. That argument has not been made in writing. It should be.
Cross-package REQ sharing — revisited
Same dual: "how?" in the Scale lane, "should it exist as a distinct concept?" here. The closest adjacent pattern is shared SCSS mixins or shared type-only packages — two well-understood monorepo shapes. Neither maps cleanly onto traceability because traceability carries history, not just types. A shared type-only Requirement that bumps its version across packages needs a cross-package history story. Nobody has drafted one.
Registry service
The hosted-service question. The one sentence on it from the Scale lane is enough; the open question adds one more: if there were a registry service, what is its minimal API? GET /requirements/:org/:package/:id? A GraphQL endpoint over the traceability graph? A subscription channel for version bumps? All three are possible; the package has not picked.
Requirements-as-a-Service
The most speculative card. Enumerated here not because it is likely, but because naming it prevents it from drifting in later as an unexamined assumption. If someone on the team starts treating the traceability graph as something that "should" live on a server, this section exists to make them explain why.
Plugin surface beyond Styles and Scaffolders
The DSL's two main plugin points today are the Style registry and the Scaffolder registry. Both are heavily used. What is underused is the FitCriterionAdapter port — the seam where a project could plug Datadog, Grafana, or SonarQube into the metric kind of fit criterion. Today the port exists; no project has a production adapter. Is that a documentation gap or a design gap? The open question is whether the port needs to change shape, or whether a clear example is enough.
Style proliferation
Five Styles ship today: Default, Industrial, Lean, Agile, Kanban. Each has its own vocabulary, templates, and validators. The question is whether this is the right number. Styles are cheap to add; they are expensive to maintain because each one carries its own dog-food test suite. A sixth Style (a hypothetical "Academic" Style for research software) has been discussed; the implementation cost is real. The open question is whether the package should ship more Styles or invest in making the five it has deeper.
Audit-trail hooks, considered more carefully
REQ-AUDIT-TRAIL-HOOKS names a narrow extension to HistoryEntry: three new ChangeKind variants, one optional signature field, two no-op decorators. The narrowness is deliberate, and worth unpacking because it is the kind of design choice that is easy to get wrong.
Why the hooks ship before the crypto
The natural instinct is to ship the whole feature at once — the hooks and the signature verification, the decorators and the crypto adapters. The Requirement explicitly rejects that instinct. The relevant mitigation clause:
Land only the hooks (types + no-op decorators), no crypto or verification logic — Tier 3 owns the signature implementation.
The reason is timing. Tier 2 (the current roadmap wave) is about making the DSL schema stable enough to survive Tier 3's arrival. Crypto is a substantial implementation: key management, signature verification, certificate chain validation, revocation, timestamping. Each of those is its own problem. Shipping them together with the schema change means the schema has to wait for crypto to be correct. Shipping them separately lets the schema stabilise first.
There is a second reason, less visible. A schema change that ships with crypto must make crypto-related decisions — which algorithms, which key formats, which trust anchors. Those decisions are regulated — FIPS 140-3, eIDAS, 21 CFR Part 11 Part E all have opinions. Making those decisions in isolation, outside a crypto-focused design wave, is how schemas end up rigidly coupled to the first algorithm they supported. Reserving the optional field and deferring the decision leaves room to pick correctly.
The discriminated-union shape of the signature field
The roadmap statement names the signature shape explicitly:
HistoryEntry.signature is optional and typed as Ed25519 or RSA-SHA256 discriminated union.
Two algorithms, not one. The discriminated-union shape is the important part. It means a consumer reading a HistoryEntry can switch on the algorithm tag and know, at compile time, which fields to expect (public key format, signature byte length, key derivation metadata). It also means adding a third algorithm in Tier 3 is an additive change — a new variant in the union — rather than a breaking change to the field's type.
The two starting algorithms are chosen for the common regulatory pairing: Ed25519 is the modern choice (small signatures, constant-time verification, no parameter-choice attacks), RSA-SHA256 is the one many regulated industries still mandate (FIPS-validated libraries, long track record, acceptable to auditors who may not yet have Ed25519 on their approved list). Shipping both from day one signals that the DSL is not making a religious choice between modern and compliant.
The outward direction — audit sinks
The inward hooks (ChangeKind variants, signature field) make the DSL capable of recording an auditable history. The outward hooks (audit sinks) make that history visible to the systems the team already uses for audit — Jira for change management, Linear for product tracking, a SIEM for security events, a BI warehouse for compliance reporting.
The port shape is small:
export interface AuditSink {
readonly name: string;
emit(event: AuditEvent): Promise<AuditSinkResult>;
}
export type AuditEvent =
| { kind: 'requirement-bumped'; id: RequirementId; from: number; to: number; hash: string; since: IsoDate }
| { kind: 'feature-satisfies-added'; feature: FeatureId; requirement: RequirementId }
| { kind: 'history-signed'; entryId: string; signer: string; algorithm: 'ed25519' | 'rsa-sha256' }
// …
;export interface AuditSink {
readonly name: string;
emit(event: AuditEvent): Promise<AuditSinkResult>;
}
export type AuditEvent =
| { kind: 'requirement-bumped'; id: RequirementId; from: number; to: number; hash: string; since: IsoDate }
| { kind: 'feature-satisfies-added'; feature: FeatureId; requirement: RequirementId }
| { kind: 'history-signed'; entryId: string; signer: string; algorithm: 'ed25519' | 'rsa-sha256' }
// …
;The event shape is a discriminated union for the same reason the signature is: it lets consumers write exhaustive switches, and it lets the DSL add events additively.
Two choices remain open on the sink side. First, when does the sink fire — at every compliance run, or only on state transitions (Requirement bumped, Feature approved, history signed)? The state-transition option is closer to what downstream systems actually want; it is also harder to implement correctly because "state transitions" requires the DSL to diff two compliance runs. Second, how does failure propagate — fail the compliance gate on a sink error, or log and continue? Defaulting to log-and-continue matches the operational reality (audit sinks go down; compliance runs should not go down with them) but requires careful diagnostic surfacing so silent failures are detectable.
Regulated-customer validation
Before any of the Audit horizon ships to users, at least one regulated-customer review is needed. Not a sales review — a design review with someone who has lived through an IEC 61508 audit or a 21 CFR Part 11 inspection. The DSL's regulated-customer claim only holds if the artefacts it produces survive contact with a real auditor.
The validation has three components.
Schema review. An auditor looks at the HistoryEntry and VersionInfo JSON shapes and tells us whether they meet the regulation's letter. For 21 CFR Part 11 this means: can the record prove authorship? Can it prove integrity? Can it prove the signature was not forged after the fact? For IEC 61508 this means: does the version chain give enough trace from the safety requirement to the implementation to the test?
Replay review. An auditor is given a corpus, a seed, and a scenario file, and asked to independently recompute the content hashes and verify the replay matches. If the auditor cannot do this with only the documented algorithm, the algorithm is not documented enough.
Workflow review. An auditor walks through the author's workflow — writing a Requirement, appending a history entry, signing it, running compliance --strict — and confirms that the resulting artefacts would have been acceptable in the audits they have previously conducted.
None of these is a technical gate; all of them are social gates. But the roadmap is incomplete without naming them, because the Audit horizon's whole purpose is to produce artefacts that regulated customers will accept.
Sequencing the scenarii player
The AI horizon's three implementation cards (first green run, prompt-caching gate, deterministic-stub conformance) are not parallel. They are sequenced, and the sequence is load-bearing.
Phase 1 — stub-only end-to-end. Before any AI adapter is wired, the player must run end-to-end with the deterministic stub. Every FSM transition must fire correctly, every artefact must be emitted, every compliance --strict invocation must produce the expected report. The player must be able to complete a scenario without ever touching a network. This phase is the safety net for everything after.
Phase 2 — Claude adapter, recorded responses. The adapter is implemented against a recorded Claude API session (a JSON file of request-response pairs). No live API calls. The player runs against the recorded responses and produces an end-to-end green run. This phase proves the adapter interface is correct without introducing the noise of live API variability.
Phase 3 — Claude adapter, live API. The adapter is switched to live API calls. Prompt caching is turned on. The first run produces cache-miss metrics; subsequent runs produce cache-hit metrics. The gate from Horizon 3 starts failing on zero-hit runs once the cache is primed.
Phase 4 — conformance suite. Every FSM transition runs twice — once with the stub adapter, once with the recorded-responses adapter — and the terminal states and on-disk artefacts (minus AC body content) are diffed. Any divergence outside the body content fails the suite.
The reason for this sequencing, rather than building the adapter first, is risk isolation. If the player has a bug, Phase 1 surfaces it without network noise. If the adapter interface is wrong, Phase 2 surfaces it without API billing. If the cache is misconfigured, Phase 3 surfaces it under real conditions. If the conformance story is broken, Phase 4 surfaces it as a last check. Each phase retires a class of risk before the next phase adds a new one.
The Q3 2026 milestone is Phase 1 and Phase 2. Q4 2026 is Phase 3 with the caching gate. Q1 2027 is Phase 4 with the conformance suite. That is eighteen months of work, which sounds long until one remembers that the scenarii player is a sub-module with its own lifecycle, its own design-frozen contract, and its own test surface. The timeline is paced to avoid the trap of shipping a charismatic demo over a correct engine.
A closer look at the AI-as-adapter stance
The AI horizon deserves a second pass. The adapter stance — "AI is a just-another implementer behind a port" — is not a rhetorical flourish. It is a design commitment with consequences that ripple through the rest of the roadmap. This section unpacks those consequences.
The port is the contract, not the adapter
When the AiAdapter type is declared in src/cli/scenario/ports.ts, it becomes the contract every implementation has to honour. The file that ships first is the Claude API adapter. The files that could ship next are, in no particular order: an OpenAI adapter, a local model adapter (llama.cpp, for example), a record-and-replay adapter for deterministic CI, and the deterministic stub adapter that ships as the default.
The port declares a minimal surface:
// Shape sketch; final types live in src/cli/scenario/ports.ts.
export interface AiAdapter {
readonly name: string;
readonly version: string;
implementAc(request: AcImplementRequest): Promise<AcImplementResult>;
}// Shape sketch; final types live in src/cli/scenario/ports.ts.
export interface AiAdapter {
readonly name: string;
readonly version: string;
implementAc(request: AcImplementRequest): Promise<AcImplementResult>;
}The request carries the AC signature, the test scaffold, the Feature's full class text (as context), and the previous failure if this is a retry. The result carries the implementation body and a structured cost breakdown (tokens consumed, cache hit rate, wall clock). That cost breakdown is what feeds the prompt-caching quality gate; a compliance run that invokes the adapter and observes zero cache hits across all ACs is grounds for failing the gate, because it means caching is either turned off or misconfigured.
Why not an agent framework?
An adapter is a function. An agent is a loop. The DSL deliberately picks the smaller of the two shapes.
An agent framework would let the model read the repo, navigate files, invoke tools, and drive its own transitions. That is a powerful pattern for autonomous tasks. It is a poor pattern for the scenarii player, for three reasons.
First, determinism. The player promises byte-identical output under a fixed seed. Agents are in general not replay-deterministic, because their transition decisions depend on intermediate model outputs that vary run-to-run. A function that takes a request and returns a body is replay-deterministic when paired with a response recorder.
Second, isolation. The player owns the FSM. If the model owns the FSM — if it decides when to stop, retry, or fail — then the player becomes a passenger on the model's reasoning. The design document's opening line, "the player is a sub-module that replays a declarative Scenario JSON file end-to-end", is explicit: the player is the authority, the model is a service.
Third, auditability. Every agent transition becomes an event that has to be logged, explained, and replayed. Every function call, by contrast, is a single request-response pair, easy to serialise into the replay log and easy to re-verify. The simpler shape produces a simpler audit trail.
None of this is a claim that agents are wrong for other tools. It is a claim that for this tool — a traceability DSL whose central promise is replayability — the adapter shape is the right shape.
What the adapter is not allowed to decide
The PerAcFsm diagram in Chapter 15 shows the single transition where the adapter enters the picture: Scaffolded → ImplementedByAI. The adapter is invoked inside the entry action of that transition. It returns a string — the implementation body. The FSM then transitions to ImplementedByAI, and the player runs the scaffolded test.
What happens next is decided by the FSM, not by the adapter:
- If the test passes,
TestRunPassfires, the FSM transitions toTestPassing, and the parentPerFeatureFsmreceivesAcImplemented(acName). - If the test fails and retries remain,
TestRunFail(retry)fires as a self-loop, the FSM stays inImplementedByAI, and the adapter is re-invoked with the failure context appended to the prompt. - If the test fails and retries are exhausted,
TestRunFail(no retry)fires, the FSM transitions toFailed, and the parent aggregates.
The adapter never decides to retry. The adapter never decides to skip. The adapter never decides to mark the AC as Verified because "it looks right". The FSM owns every one of those decisions, and the FSM is pure TypeScript with no model in the loop.
The stub adapter is a first-class artefact
One of the choices the AI horizon forces early is how good the deterministic stub should be. Two extremes are available.
At one end: a trivial stub that emits throw new Error('not yet implemented') for every AC body. This is the current plan and it has a virtue — the scaffolded test fails immediately with a clear message, the player reports the failure, the author goes back and implements the AC. The player is demonstrable; nothing is hidden.
At the other end: a stub that inspects the test scaffold and emits a body that plausibly returns something type-correct — the right shape of ACResult, the right return type, the right number of arguments. This would let the test suite compile and run even without AI; it would produce passes where passes are trivial and failures where failures are meaningful.
The current plan stays at the trivial end. The reason is not technical but epistemic: a stub that fakes success masks the AC's real state. A stub that fails loudly keeps the author honest. The roadmap leaves the door open to a smarter stub, but only behind an explicit --stub=smart flag.
On cross-package traceability, considered more carefully
The Scale horizon listed cross-package @Satisfies as an open question. The section above framed it from the DSL's side — how would the decorator work, what would the registry look like. There is a second framing the section did not cover: the organisational shape such a feature would imply.
A cross-package @Satisfies has a social prerequisite: one package owns a Requirement, another package depends on that ownership. The first package becomes an upstream; the second becomes a downstream. Upstream changes — a Requirement's content hash drifting — become downstream breakages.
This is the same shape as any library-consumer relationship, but traceability has an additional load. A library's API breakage breaks the build. A Requirement's content-hash drift breaks the audit claim. The downstream package's compliance --strict can pass every other gate and still fail because an upstream Requirement changed in a way the downstream had not re-pinned against.
Three shapes have been discussed informally. None is chosen.
Shape A — Explicit re-pin. Every downstream @Satisfies carries an explicit version pin (@Satisfies(UpstreamReq, { version: 7 })). A new upstream version does not break the downstream until the downstream chooses to re-pin. This is the safest shape for regulated work because the audit claim is stable until the downstream affirmatively re-issues it.
Shape B — Semver-style compatibility. The upstream package follows semver rules on Requirement hashes: cosmetic changes are patch bumps, semantic changes are minor or major bumps. Downstream packages pin a range, not a version. This is the familiar npm shape and it works for code; whether it works for traceability claims is unclear.
Shape C — Graph-aware resolution. The compliance --strict tool resolves the cross-package graph at build time, loading every upstream package's traceability metadata and re-computing the downstream's coverage. No pins at all; drift is detected as part of compliance. This is the most "pull the load into the tool" shape and the most expensive to implement correctly.
My instinct is Shape A for regulated contexts and Shape B for permissive contexts, with Shape C as a later consolidation. Nothing in the current package forecloses any of the three. The open question is what the default should be, and which shape is so disliked that it should be explicitly ruled out.
Migration tools, in more detail
The Stabilize horizon named migration tools as a deliverable. This section walks through what "migration tools" actually means in the context of this DSL, because the phrase is easy to hear as "a database migration" and it is not that.
A database migration is imperative: alter a schema, rewrite columns, run a script. A Requirements DSL migration is structural: a Requirement or Feature class in a file gets edited, its content hash changes, its version is bumped, its history entry is appended. The migration tool's job is to perform those edits consistently across the corpus, so that the author does not have to remember every Requirement that needs to be re-pinned.
Three operations the tool has to support:
Normalise. Re-run the content-hash normalisation on every spec in the corpus. If a spec's normalised content differs from its stored hash, the tool offers to update the hash and append a history entry with change: 'normalised'. This is a no-op migration in the happy case and a cleanup migration when the normalisation algorithm itself changes.
Rename. Change a Requirement's id (say, REQ-OLD-NAME becomes REQ-NEW-NAME). The tool updates the file's export name, every @Satisfies reference across the corpus, every @Refines reference, and appends a supersedes: 'REQ-OLD-NAME' field so the chain is discoverable. Rename without supersedes would lose the history chain; rename with supersedes preserves it.
Split. One Requirement becomes two. The tool creates the two new classes, asks the author which existing @Satisfies references should move to which new class, and appends refinedFrom: 'REQ-OLD' on both. The old Requirement is kept as a stub with status: 'Superseded' so past history remains resolvable.
Each of these is a medium-size refactor expressed as a single command. The cost of not shipping them is that authors either avoid renames and splits (the corpus accretes legacy names) or perform them manually (the history chain breaks silently). Both are worse than a correct tool.
The open question inside migration tools is the UX: should it be an interactive wizard (requirements migrate rename REQ-OLD REQ-NEW), or a declarative plan (requirements migrate --plan migrations/2026-Q3-rename.yaml)? The wizard is easier for occasional use; the plan is easier for team review. Both are possible. Both are probably needed eventually.
Inheritance from typed-specs
This section closes the loop with the earlier series. The V2 roadmap published at typed-specs/07-roadmap.md named seven gaps. Here is where each one stands today.
Gap 1 — Workflow Integration. Closed. The compliance scanner is now wired into npm run test:all through the compliance --strict step, and into the local workflow menu via the requirements bin.
Gap 2 — Pre-Commit Hooks. Partially closed. Husky pre-push runs compliance in strict mode. Pre-commit remains deliberately loose because spec authoring is iterative and hard failures at commit time drive authors to bypass the hook.
Gap 3 — Historical Trend Tracking. Partially closed. The HistoryEntry append-only log captures timestamped changes on every Requirement / Feature / AC. What remains open is the cross-repo aggregate — a way to see coverage trends across multiple projects, which would require the registry-service piece of the Scale horizon.
Gap 4 — Reverse Mapping. Closed. npx requirements trace chain <id> <ac> walks from a Requirement down to the binding tests; npx requirements trace matrix <feature> walks from a Feature up to the Requirements it satisfies. Chapter 12 walked through both.
Gap 5 — ESLint Enforcement. Open. No ESLint rule ships today. The compiler catches keyof T violations at build time, which covers the most common failure mode, but edit-time feedback on missing @Verifies would still be a meaningful improvement. The effort versus payoff has not justified the work yet.
Gap 6 — Dynamic Test Granularity. Open in a different shape. The old plan was generated per-test decorators. The new shape is the scaffolder registry — each level emits a fresh file rather than batching ACs into a single test. The effect is the same (one failure points at one AC) with less machinery. Nominally closed, but the dynamic-generation idea has not been revisited since.
Gap 7 — Compliance as a Feature. Closed. The compliance gate itself is bound to several Requirements in the current package (REQ-COMPLIANCE-STRICTNESS, REQ-ORPHAN-DETECTION, REQ-TRACEABILITY-GRAPH). The self-reference this chapter opens with — a roadmap bound to Requirement classes — is the completion of that thread.
The honest remaining items from the old roadmap are Gap 5 (ESLint) and part of Gap 3 (cross-repo trends). Both are real, neither is urgent, both will be picked up when a user asks for them.
Versioned traceability, considered more carefully
The Audit horizon opened with REQ-VERSIONED-TRACEABILITY. The Requirement is compact — one statement, four fit criteria, two mitigation clauses. Behind that compactness is a set of design choices that deserve a closer look, because they constrain almost everything else in the Audit horizon.
Why three fields, not one
The VersionInfo record carries three fields: a monotonic integer, a content hash, and a since-date. One field would be simpler. Three fields are chosen because each one answers a different question.
The monotonic integer answers "which version?" Humans cannot reliably compare hashes. An auditor asked "is this the version we approved in March?" needs an answer they can see and remember. v7 is that answer. A bare hash is not.
The content hash answers "is this really that version?" An integer can be forged; a hash derived from the content cannot, provided the hash function is documented and the content is canonicalised. The hash is what makes the integer trustworthy.
The since-date answers "when did this version become the current one?" An auditor walking back through a release to understand what was committed to at the time of a decision needs to resolve a date to a version. The since-date is the index into that walk.
Drop any one field and the system loses a question it can answer. All three are needed. None is redundant.
The content-hash normalisation problem
The statement of REQ-VERSIONED-TRACEABILITY says the hash is "deterministic". The rationale's assumption clause says the hash must normalise formatting. Those two words carry a substantial design problem.
A naive content hash — say, sha256(readFileSync(path)) — is deterministic but not normalised. Any whitespace change bumps the hash, and the whole corpus churns whenever an editor reformats a file. This makes the versioning signal indistinguishable from cosmetic noise, and the compliance --strict gate becomes a nuisance rather than a signal.
The normalised hash must therefore operate on the semantic content of the spec, not its textual representation. That means parsing the TypeScript, extracting the Requirement's fields, canonicalising their order and formatting, serialising to a stable form (probably JSON with sorted keys, or a custom s-expression), and hashing that. The fields that must be excluded from the hash are the ones that track version state itself: the $schemaVersion, the history array, the version field. Include them in the hash and a version bump changes the hash, which causes another version bump — a loop.
The documentation burden is real. Auditors need to be able to re-compute the hash independently, which means the normalisation algorithm has to be specified in enough detail that a second implementation would agree byte-for-byte. This is the same discipline content-addressed storage systems have always needed; the DSL is not exempt from it.
Comparison to git as an audit substrate
The rationale for REQ-VERSIONED-TRACEABILITY cites git as a precedent:
Content-addressed storage is the accepted industrial pattern for immutable audit trails.
Git's model is worth thinking about more carefully, because it sets the standard the DSL's versioning has to meet or exceed.
Git addresses every object by the SHA-1 (now SHA-256 in modern git) of its content. A commit's hash covers its tree, its parents, its author, its message. Changing any of those produces a different hash. This property is what makes git's history immutable in the strong sense: a forged commit has the wrong hash, and every downstream commit that references it has the wrong hash too. A tampered history is mathematically detectable.
The DSL's versioning cannot inherit git's properties for free. A spec class is not a git object. The hash lives alongside the content in the same file; if both are rewritten, the tampering is undetectable without external witness. The history array is append-only by convention, not by storage. A malicious author can rewrite history and re-sign it, and the DSL cannot detect that without a reference to an external source of truth.
Two options close this gap. First, anchor to git. Every HistoryEntry carries a git commit hash at which it was written, and the DSL validates that the commit exists and contains the file at that path. This turns git into the DSL's external witness. Second, anchor to a timestamping service. Every HistoryEntry carries a trusted-timestamp token (RFC 3161 or similar) proving the entry existed at a given time. This turns a neutral third party into the witness.
The current plan is to support both as optional extensions to the HistoryEntry record. Neither is required for the basic audit story; both are available for customers whose regulators require stronger evidence. This is the same "reserve the hook, defer the crypto" pattern that REQ-AUDIT-TRAIL-HOOKS uses, extended one layer down.
The supersedes chain and rename safety
One clause of REQ-VERSIONED-TRACEABILITY's fit criteria mentions supersedes:
supersedes link chains semantic history across renames
A Requirement's identity is its id. Rename the id and a literal reading says the Requirement has vanished and a new one has appeared. That is almost never what the author means. The supersedes field is the cross-reference: REQ-NEW-NAME carries supersedes: 'REQ-OLD-NAME', and the traceability tools walk the chain backward to reconstruct history.
This is simple enough for one-step renames. It becomes subtler for splits and merges. If REQ-OLD splits into REQ-NEW-A and REQ-NEW-B, both new Requirements carry supersedes: 'REQ-OLD' and the old one stays as a stub with status: 'Superseded'. If REQ-NEW-A and REQ-NEW-B later merge into REQ-NEWER, the merged Requirement carries supersedes: ['REQ-NEW-A', 'REQ-NEW-B'] — an array, not a scalar.
The supersedes field is therefore typed as string | string[], with string for the common single-rename case. The tooling treats both shapes uniformly. The tests for this live in the same file as the versioning tests, and a property-based invariant asserts that the chain always terminates (no cycles, no orphan references).
Honesty about the roadmap's limits
Every roadmap has a half-life. This one is written on 2026-04-14 and will be wrong by 2027-04-14 in ways the author cannot currently predict. That is not a flaw of this roadmap; it is a property of roadmaps.
Three forces are likely to deform it.
User pull. The roadmap is shaped by what I think the DSL needs. Real users — once there are any — will have different priorities. A feature that is not on this page today may become urgent because a user needs it; a feature on the Audit horizon may be deprioritised because no one who matters is asking for it.
LLM shift. The AI horizon assumes the adapter pattern works cleanly with current LLMs. A substantial change in LLM capabilities (meaningful context-window expansion, a sharp improvement in determinism, a collapse in cost) could change what the adapter pattern should even be. The horizon is robust to small changes and fragile to large ones.
Regulatory shift. The Audit horizon cites IEC 61508 and 21 CFR Part 11. Both are durable regulations; neither is frozen. New standards (the EU AI Act, emerging cybersecurity regulations like the CRA, sector-specific updates) may add requirements the current horizon does not anticipate. The hook-reservation strategy is meant to soften those shifts, but it is not a magic shield.
Naming these forces here is itself a design choice. A roadmap that pretends it is a plan in the strong sense — "we will do these things in this order at these dates" — is easier to sell and harder to keep. A roadmap that says "these are the horizons we are walking toward, and here are the forces likely to bend the path" is more honest and more useful. The latter is what this chapter tries to be.
The dog-food loop and the roadmap
The series this chapter belongs to is titled "Dog-Fooding the Requirements DSL" for a reason. Every Requirement in the package is tested against the package's own code. Every Feature is exercised by the package's own tests. The decorators that prove compliance are the same decorators that compliance inspects. The meta-circle is real and is documented in Chapter 18.
The roadmap above has to fit inside that meta-circle. Each horizon item, when it ships, has to dog-food itself.
Versioning has to version its own spec. When REQ-VERSIONED-TRACEABILITY moves from Draft to Approved, its own version number is the first non-trivial test of the versioning system. If the system cannot track the version of its own requirement, it does not work.
The AI adapter has to ship a Feature that satisfies REQ-AI-AS-IMPLEMENTER-ADAPTER. The Feature already exists in skeleton form at packages/requirements/requirements/features/scenario/scenario-ai-adapter.ts with eleven ACs. When the adapter lands, each AC has a scaffolded test, and each test is bound by @FeatureTest / @Verifies — no describe, no it. If the AI adapter ships without its own compliance gate passing, REQ-DOG-FOOD is violated.
Audit-trail hooks have to log their own introduction. The first change entry in the hooks' history must itself carry the new ChangeKind variant. The first signed entry in the signature field's history must itself be signed. If the hooks cannot be demonstrated on themselves, they will not be convincing to anyone else.
This is a strong discipline and it has a cost. Every roadmap item ships with a compliance surface that has to be green before the item is considered complete. That slows delivery. It also means the roadmap cannot be hand-waved — a feature that ships without its own compliance binding is not complete, and the compliance --strict gate will say so.
The payoff is that every item on the roadmap is, by construction, a demonstration. When a regulated customer asks "does your versioning work?", the answer is not "here is the code" — the answer is "here is the versioning system's own compliance --strict report, showing its own version pinned to its own Feature's tests, all green". That is a different kind of answer.
On the Requirements-as-a-Service question, with skepticism
Since the Scale horizon included Requirements-as-a-Service as a speculative card, it deserves a skeptical read.
The appeal of RaaS is clear enough: a hosted service that owns the traceability graph centrally, so every team points at the same canonical Requirements, every audit pulls from the same source, every change is tracked in the same place. In a sufficiently large organisation this pattern is attractive.
The costs are equally clear. First, the traceability graph is the authority on what a team has committed to. Outsourcing that authority to a vendor — any vendor, including one you trust — changes the relationship between the team and its own specifications. A self-hosted DSL has a property a hosted service does not: the team can answer the question "what did we commit to?" without an external query. That property is valuable and non-obvious.
Second, the regulated-customer angle cuts against hosting. The audit trail that REQ-VERSIONED-TRACEABILITY exists to produce is most valuable when it is held by the team, not by a vendor. An auditor wants to verify that the team's own records match the team's own code. Pushing the records into a service introduces a third-party dependency in the audit chain, which regulated customers generally dislike.
Third, the dog-food property of the package does not survive hosting. @frenchexdev/requirements dog-foods itself because the corpus is on disk, in the repo, alongside the code. A hosted service would split the corpus from the code, and the meta-circle that Chapter 18 documents would stop being a property of the package.
None of these is a fatal argument. They are reasons to be skeptical of any proposal that frames hosting as "obviously the next step". If hosting happens, it should be additive — the self-hosted corpus remains authoritative, the hosted service is an optional projection for convenience. That shape preserves the properties the self-hosted DSL has. The opposite shape — hosting as the source of truth, self-hosting as a fallback — gives up the properties the DSL was built on.
This is a place where the roadmap deliberately says "probably not" rather than "maybe later". Other people on other teams may reach different conclusions; this package's answer, as of 2026-04-14, is that RaaS is not on the near roadmap and should not drift onto it without a substantial change in the arguments above.
A short list of what is not on the roadmap
Some things that might seem natural extensions are deliberately absent. Listing them makes the roadmap honest.
A GUI. The DSL is terminal-first and file-first. A GUI — for browsing the traceability graph, editing Requirements, visualising coverage — would be a reasonable product but is not on this roadmap. Every chapter of this series describes a tool that works through the terminal and the editor. That shape is deliberate, not a placeholder.
A plugin marketplace. The package has two plugin surfaces (Styles and Scaffolders) and a third port (FitCriterionAdapter). None of these is intended to grow into a marketplace-shaped ecosystem. The plugins that exist are hand-written, hand-reviewed, and shipped as part of the package. A marketplace would mean taking on a distribution and validation burden that is orthogonal to what the DSL is for.
A VS Code extension that goes beyond schema registration. The current requirements schema register command writes the JSON schema mappings into .vscode/settings.json so the editor's built-in JSON tooling provides autocomplete and validation. That is the extent of the editor integration on the roadmap. A full extension — with code lenses, inline diagnostics, refactorings — would duplicate work the TypeScript compiler already does correctly, and it would fragment effort. The better investment is improving the types and the CLI; the editor follows.
Natural-language Requirement authoring. A tempting idea is "describe the Requirement in plain English, let the DSL generate the class". This is deliberately rejected. The point of the Requirement class is that the structure is legible at type-check time. An LLM-generated class is only as good as its last generation; a hand-authored class, even a sparse one, carries author intent that survives regeneration. If the author cannot express the Requirement in the DSL, the answer is usually that the Requirement is not yet well-understood, and the solution is to think harder, not to delegate.
Real-time collaboration. Multi-author editing of a live Requirement graph is an interesting problem and is not this problem. The DSL assumes git-based collaboration: branches, merges, history entries. Nothing in the roadmap contradicts that.
Each of these absences is a place the package said "no" so it could say "yes" more clearly to the items that are on the roadmap. That is the only kind of prioritisation that survives contact with reality.
Beyond this series
A question I have left for last because it is the hardest to answer inside the series: what happens when @frenchexdev/requirements stops being a dog-food artefact and becomes a tool other teams run on their code?
The package has been shaped, deliberately, under the constraint that I am its only user. Every Requirement is a Requirement I wrote for myself. Every Style is a Style I chose. Every scaffolder emits tests I would write by hand. The dog-food loop is tight because the loop has one person in it.
Other teams will not have that property. Their Requirements will come from product managers, regulators, customers. Their Styles will be picked by whoever wrote the first one and became the defender of it. Their scaffolders will need to emit tests their existing harness accepts, which may not be Vitest. Everywhere the current package has a single default, a team deployment will have a plurality.
The horizons above — Stabilize, Scale, AI, Audit — are all partial answers to that transition. Stabilize sharpens the tool for the users who will arrive. Scale prepares for the cross-package, cross-team topology. AI frames the implementer as an adapter, not a substrate. Audit gives the tool standing with regulated customers.
None of the four horizons asks "is this tool for me?" That question the package cannot answer from inside itself. What the package can do is keep the surface small, the types strict, the Styles plural, and the audit trail immutable. If it does those four things, the question of adoption becomes a conversation rather than a pitch.
That is the shape of the roadmap, as of 2026-04-14. It is written in the DSL it describes. It will change. The next version of this chapter — when it is written — will be a diff on a typed spec, not a rewrite of a wiki page. That is the point.
Related Reading
- Chapter 15 — Scenarii and the Three FSMs — the state-machine orchestration the AI adapter plugs into.
- Chapter 13 — Quality Gates and Compliance — the gate that every roadmap item ultimately reports to.
- Chapter 13c — When Compliance Fails: Diagnostics and Recovery — the diagnostics surface the Stabilize horizon sharpens.
- Chapter 18 — The Meta-Circle in Diagrams — why a roadmap written in the DSL is a property of the DSL, not a quirk.
- typed-specs Part VII — V2 Roadmap — the predecessor roadmap whose seven gaps this chapter closes or leaves honestly open.