What it reifies
@frenchexdev/requirements-styles-demo is the most unusual package in the family. It does not analyze, generate, or orchestrate anything in production. Its job is to demonstrate the five RequirementStyle presets from Part 17 through a scenario-driven CLI player called rsd. A scenario is a JSON file declaring a sequence of actions — "author a Requirement", "transition its status", "satisfy it with a Feature", "verify the Feature's first AC" — and the demo player drives the kernel + vocabulary + styles through that sequence, showing at each step what the style's vocabulary, status workflow, and templates produce.
The package.json description: "Scenario-driven demo player (rsd) — 3-FSM orchestrator + built-in scenarios for @frenchexdev/requirements-styles."
The three FSMs name the orchestrator's architecture. The per-project-lifecycle FSM tracks the demo session as a whole — "loading", "running", "complete", "errored". The per-feature FSM tracks each Feature the scenario touches — "declared", "linked", "verified". The per-AC FSM tracks each Acceptance Criterion — "declared", "bound", "verified", "failing". Three independent state machines composing into the demo's behaviour, each with its own valid transitions, each driven by events the scenario emits.
The public surface
The package exposes a bin plus nine subpath exports:
"bin": { "rsd": "./bin/rsd-entry.mjs" },
"exports": {
".": "./dist/index.js",
"./ai-adapter": "./dist/ai-adapter.js",
"./commands": "./dist/commands.js",
"./event-bridge": "./dist/event-bridge.js",
"./orchestrator": "./dist/orchestrator.js",
"./orchestrator-port": "./dist/orchestrator-port.js",
"./per-ac-fsm": "./dist/per-ac-fsm.js",
"./per-feature-fsm": "./dist/per-feature-fsm.js",
"./project-lifecycle-fsm":"./dist/project-lifecycle-fsm.js",
"./types": "./dist/types.js",
"./ui": "./dist/ui.js"
}"bin": { "rsd": "./bin/rsd-entry.mjs" },
"exports": {
".": "./dist/index.js",
"./ai-adapter": "./dist/ai-adapter.js",
"./commands": "./dist/commands.js",
"./event-bridge": "./dist/event-bridge.js",
"./orchestrator": "./dist/orchestrator.js",
"./orchestrator-port": "./dist/orchestrator-port.js",
"./per-ac-fsm": "./dist/per-ac-fsm.js",
"./per-feature-fsm": "./dist/per-feature-fsm.js",
"./project-lifecycle-fsm":"./dist/project-lifecycle-fsm.js",
"./types": "./dist/types.js",
"./ui": "./dist/ui.js"
}The three FSMs are each their own subpath. The orchestrator is a separate subpath. The event-bridge connects the FSMs to each other via a typed event bus. The commands subpath is the action dispatcher — "author a Requirement", "transition status", "verify AC" — that scenarios invoke. The ai-adapter is an opt-in interface for driving the demo from an LLM rather than from a static JSON scenario (still experimental; the maintainer's notes flag it as a work-in-progress).
Scenarios live in packages/requirements-styles-demo/scenarios/*.json, shipped as package files. A scenario is a typed JSON value the schema for which lives alongside the package's own JSON Schemas (under schemas/).
The bin runs rsd <scenario-file> and the orchestrator takes over from there.
Where it sits
Cross-cutting. Not in the tier stack. Depends on requirements-core, requirements-lib (transitional), requirements-styles, commander, @clack/prompts, and ajv. Optional dep of the CLI — only installed when a user opts into running the demo player.
Three things the package must not do:
- Inherit the main CLI's bin. The
rsdbin is the demo player; therequirementsbin is the production CLI. Two separate bin entries means a user who runs the demo never accidentally writes to their real workspace, and a user who runsrequirements compliancenever accidentally loads a demo scenario. - Touch real source files. The scenarios drive in-memory registries. The demo can simulate writing a Requirement file but never actually writes one; the rendered output is shown in the terminal and discarded.
- Embed proprietary scenarios. The scenarios are released under the same licence as the rest of the family. A consumer can take a scenario, fork it, add their own steps, and ship the fork under their own name without licence friction.
A concrete call-site
A user demonstrating the Industrial style runs:
$ npx rsd packages/requirements-styles-demo/scenarios/industrial-walkthrough.json$ npx rsd packages/requirements-styles-demo/scenarios/industrial-walkthrough.jsonThe scenario file:
{
"name": "Industrial style walkthrough",
"style": "industrial",
"steps": [
{ "action": "author-requirement", "id": "SIL-3-CONTROL", "title": "Reactor temperature control loop must be SIL 3" },
{ "action": "transition-status", "id": "SIL-3-CONTROL", "to": "design-review" },
{ "action": "author-feature", "id": "TEMPERATURE-LOOP", "satisfies": ["SIL-3-CONTROL"] },
{ "action": "declare-ac", "feature": "TEMPERATURE-LOOP", "name": "loopRespondsWithin50ms" },
{ "action": "bind-test", "feature": "TEMPERATURE-LOOP", "ac": "loopRespondsWithin50ms", "test": "loop-timing.test.ts:42" },
{ "action": "verify", "feature": "TEMPERATURE-LOOP", "ac": "loopRespondsWithin50ms", "result": "satisfied" },
{ "action": "render-report" }
]
}{
"name": "Industrial style walkthrough",
"style": "industrial",
"steps": [
{ "action": "author-requirement", "id": "SIL-3-CONTROL", "title": "Reactor temperature control loop must be SIL 3" },
{ "action": "transition-status", "id": "SIL-3-CONTROL", "to": "design-review" },
{ "action": "author-feature", "id": "TEMPERATURE-LOOP", "satisfies": ["SIL-3-CONTROL"] },
{ "action": "declare-ac", "feature": "TEMPERATURE-LOOP", "name": "loopRespondsWithin50ms" },
{ "action": "bind-test", "feature": "TEMPERATURE-LOOP", "ac": "loopRespondsWithin50ms", "test": "loop-timing.test.ts:42" },
{ "action": "verify", "feature": "TEMPERATURE-LOOP", "ac": "loopRespondsWithin50ms", "result": "satisfied" },
{ "action": "render-report" }
]
}The orchestrator processes each step in order. The per-project-lifecycle FSM transitions to running. The first step authors a Requirement; the per-feature FSM is not yet touched because no Feature exists. The second step transitions the Requirement's status to design-review — the Industrial style permits the transition because its status workflow includes that state; a Default-style scenario would have rejected the transition because Default does not have a design-review state. The third step authors a Feature with @Satisfies(SIL_3_CONTROL); the per-feature FSM transitions from nascent to linked. The fourth step declares an AC; the per-AC FSM starts in declared. The fifth step binds a test; the per-AC FSM transitions to bound. The sixth step verifies the AC; the per-AC FSM transitions to verified. The seventh step renders the final compliance report.
Each transition is visible in the demo's terminal output, with the Industrial-specific vocabulary, validator results, and template formatting applied. The same scenario run against the Lean style would produce a much smaller status workflow (Lean has four states, Industrial has thirteen) and the terminal output would reflect the difference.
Why it is its own package
Three arguments.
First, the demo is a teaching tool, not a production tool. A user installing @frenchexdev/requirements for their own project does not want the demo's three-FSM orchestrator, its scenario JSON Schemas, or its ai-adapter experimentation. Packaging the demo separately as an optionalDependencies of the main CLI means production consumers skip it entirely. The clean separation also reflects the maintainer's mental model: "the demo is documentation that runs", and documentation should be installable on demand.
Second, the FSMs are reusable as study material. The three FSMs — per-project-lifecycle, per-feature, per-AC — are each small (≈ 50-100 lines) and follow the same pattern: typed state union, typed event union, transition function, guard predicates. Each is its own subpath export so a curious reader can import { perFeatureFsm } from '@frenchexdev/requirements-styles-demo/per-feature-fsm' and study the FSM in isolation, without booting the orchestrator. The maintainer's FSM tooling discipline (fsm-feature-audit, event-topology) applies to these FSMs too: each is linked to a Feature, each has its own coverage gates.
Third, the scenario format is a publishable schema. The JSON Schemas under packages/requirements-styles-demo/schemas/ are versioned alongside the package and shipped as files. A third party can write its own scenarios against the schema and run them through rsd. A future tutorial site might compile scenarios into static animations. None of those downstream uses should force a change in the main CLI; isolating the schema in this package keeps the surface narrow.
The package's ai-adapter subpath is the most experimental piece. The idea: instead of loading a pre-authored JSON scenario, the player consults an LLM to generate scenario steps interactively, producing a "converse-with-the-spec" mode for demonstrations. The adapter is wire-only today — no LLM is actually plugged in by default — and the maintainer's notes explicitly mark it as a work-in-progress.
That closes the catalogue. Eighteen packages walked through, one tier band per cluster, every package's responsibility named and bounded. The next two pages are the epilogue: how a new package gets added to any tier, and where the split is going next.