Spec Studio

Every verb answers --help, and one verb writes every projection root

spec:consumers.command-lineUse Case / Behavior · storyready floor ready

Packs: pack:adopter-speed-v1, pack:self-hosting-v1

Design: 5 design entries · 2 pinned declarations · 1 decision

Findings: no errors, no warnings

specs/consumers/command-line.sdp.md

No open questions and no blocking questions; implementation binding present, verifier binding present, and expected-outcome oracle present.

An adopter meets the command line one verb at a time, and the verb itself is the natural place to ask how it works. Each publisher's build first removes all five projection roots, so after one publisher runs only its own root is current, and writing all five took a script private to this repository. One public verb writes every root from one graph in one run, so an adopter's checkout and its CI publish the same set the Protocol's own does.

Intent
actor
An adopter, or an agent working for one, at the command line or in CI.
problem
A verb refuses --help instead of explaining itself, and no public verb publishes every projection root at once, so an adopter runs the publishers one by one and is left with only the last one's root.
outcome
Let every verb explain itself through --help, and let one verb write every projection root from one graph in one run.
Behavior
rule.verbHelp line 31 · specs/consumers/command-line.sdp.md:31
Every verb answers --help: when --help is among a verb's arguments, the verb prints its help on standard output and exits 0, reading no other argument, deriving no graph and touching no file, a projection root included.

spec:consumers.command-line.verb-help-touches-nothing · enabled

rule.oneHelpText line 32 · specs/consumers/command-line.sdp.md:32
A verb's help opens with its usage and its paragraph from the top-level help, the same text, so a verb's help and sdp --help never disagree; only the scaffolder's help, for sdp new and sdp new spec, adds a paragraph of its own after that text.

spec:consumers.command-line.verb-help-touches-nothing · enabled

rule.generateVerb line 33 · specs/consumers/command-line.sdp.md:33
sdp generate [root] [--exclude PATH]... [--vault DIR] [--check-clean] enters the shared build once, validates the graph, synchronizes the vault, and writes all five projection roots from that one graph: the Design Review, the census, the Mermaid diagrams, the Gherkin-shaped view and the Studio.

spec:consumers.command-line.generate-writes-every-root · enabled

rule.sameBytes line 34 · specs/consumers/command-line.sdp.md:34
Each root the verb writes holds the bytes its own publisher writes from the same graph, written wholesale through its temporary sibling as that publisher writes it.

spec:consumers.command-line.generate-writes-every-root · enabled

rule.generateExit line 35 · specs/consumers/command-line.sdp.md:35
Findings never withhold a root: the verb writes all five and exits with the validation exit code, and a graph that does not derive writes no root and exits 1.

spec:consumers.command-line.generate-writes-every-root · enabled

rule.generateCheck line 36 · specs/consumers/command-line.sdp.md:36
With --check-clean, the verb applies to each root the check its publisher applies under --check-clean, to renders of the one graph; a root that fails its check is removed, the others are written, and the run exits 1.

spec:consumers.command-line.generate-check-failure · enabled

0 unkeyed rules.

Verifying examples

A root that fails its check is removed while sdp generate writes the others · spec:consumers.command-line.generate-check-failure · ready floor ready

Executable Spec

Given an extraction root holding two authored Specs and {roots: "five current projection roots, one stale page planted in the census root"}
When the command {command: "sdp generate --check-clean"} runs at that root
Then the command exits {exitCode: 1}
Then the stale pages survive: {staleSurvive: false}
Then the roots holding the current pages for those Specs are {currentRoots: "design-review, mermaid, gherkin, spec-studio"}
Then the absent projection roots are {absentRoots: "census"}

Open example

One run of sdp generate leaves all five roots current · spec:consumers.command-line.generate-writes-every-root · ready floor ready

Executable Spec

Given an extraction root holding two authored Specs and {roots: "a stale page in each of the five projection roots"}
When the command {command: "sdp generate"} runs at that root
Then the command exits {exitCode: 0}
Then the stale pages survive: {staleSurvive: false}
Then the roots holding the current pages for those Specs are {currentRoots: "design-review, census, mermaid, gherkin, spec-studio"}
Then the absent projection roots are {absentRoots: ""}

Open example

A publisher's --help prints its help and touches no root · spec:consumers.command-line.verb-help-touches-nothing · ready floor ready

Executable Spec

Given an extraction root holding two authored Specs and {roots: "a stale page in each of the five projection roots"}
When the command {command: "sdp view --help"} runs at that root
Then the command exits {exitCode: 0}
Then the stale pages survive: {staleSurvive: true}
Then the roots holding the current pages for those Specs are {currentRoots: ""}
Then the absent projection roots are {absentRoots: ""}
Then standard output opens with the line {firstLine: "Usage:"}

Open example

Example space

Given an extraction root holding two authored Specs and {roots:"a stale page in each of the five projection roots"|"five current projection roots, one stale page planted in the census root"}
When the command {command:"sdp generate"|"sdp generate --check-clean"|"sdp view --help"} runs at that root
Then the command exits {exitCode:number}
Then the stale pages survive: {staleSurvive:boolean}
Then the roots holding the current pages for those Specs are {currentRoots:string}
Then the absent projection roots are {absentRoots:string}
Then standard output opens with the line {firstLine:string}
Design
helpVerbs line 39 · specs/consumers/command-line.sdp.md:39
build, validate, view, census, mermaid, gherkin, studio, vault, stamp, generate, import, new and q answer --help.

no citation recorded

verbHelpText line 40 · specs/consumers/command-line.sdp.md:40
Usage: on its own line, then the verb's usage lines as sdp --help writes them, a blank line and the verb's paragraph from the Commands: list of sdp --help; sdp new --help and sdp new spec --help then add a blank line and the scaffolder's own paragraph on what PATH takes and what the scaffold writes.

no citation recorded

generateRoots line 41 · specs/consumers/command-line.sdp.md:41
in this order, generated/design-review/, generated/census/, generated/mermaid/, generated/gherkin/ and generated/spec-studio/.
generateOutput line 42 · specs/consumers/command-line.sdp.md:42
the build and validation summary lines once, then the vault's Wrote <out>/sdp (…) line unless --check-clean, then the line each publisher prints for its root, in the order of the roots.
vaultRoot line 43 · specs/consumers/command-line.sdp.md:43
the verb never removes a vault with the five roots; before it publishes any root it synchronizes the vault at the folder sdp vault uses for the same root, or at --vault DIR, resolved against the working directory, through the vault's own directory checks and guard, and a refusal there writes no root and exits 1; under --check-clean it leaves the vault alone, since the vault has no check mode and its tests hold its determinism.
Verification

Verifier bindings

  • spec:consumers.command-line.generate-check-failure · A root that fails its check is removed while sdp generate writes the others · declared · example enabled · specs/consumers/command-line.generate-check-failure.sdp.md

    External run evidence from test/self-hosting-command-line.test.ts

    Test anchors: test:protocol.command-line.generate-check-failure, test:protocol.command-line.generate-writes-every-root, test:protocol.command-line.verb-help-touches-nothing. Specs verified by those bindings: spec:consumers.command-line, spec:consumers.command-line.generate-check-failure, spec:consumers.command-line.generate-writes-every-root, spec:consumers.command-line.verb-help-touches-nothing.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 380 · Branch: feature/roadmap-and-slices-v0 · Commit: 34909918bf0be0e849959644401797191cae379f · Start: 2026-10-22T17:40:31.456Z · Stop: 2026-10-22T17:42:16.171Z

    NameSuiteResultDuration
    executes the bound example against a fresh worldOne run of sdp generate leaves all five roots current (spec:consumers.command-line.generate-writes-every-root)passed101.27 ms
    executes the bound example against a fresh worldA root that fails its check is removed while sdp generate writes the others (spec:consumers.command-line.generate-check-failure)passed68 ms
    executes the bound example against a fresh worldA publisher's --help prints its help and touches no root (spec:consumers.command-line.verb-help-touches-nothing)passed1.61 ms
  • spec:consumers.command-line.generate-writes-every-root · One run of sdp generate leaves all five roots current · declared · example enabled · specs/consumers/command-line.generate-writes-every-root.sdp.md
  • spec:consumers.command-line.verb-help-touches-nothing · A publisher's --help prints its help and touches no root · declared · example enabled · specs/consumers/command-line.verb-help-touches-nothing.sdp.md

Example space

  • roots · "a stale page in each of the five projection roots" | "five current projection roots, one stale page planted in the census root" · declared by an extraction root holding two authored Specs and {roots}
  • command · "sdp generate" | "sdp generate --check-clean" | "sdp view --help" · declared by the command {command} runs at that root

Bound points

Examplerootscommand
spec:consumers.command-line.generate-check-failure"five current projection roots, one stale page planted in the census root""sdp generate --check-clean"
spec:consumers.command-line.generate-writes-every-root"a stale page in each of the five projection roots""sdp generate"
spec:consumers.command-line.verb-help-touches-nothing"a stale page in each of the five projection roots""sdp view --help"

Oracle binding: present · oracle:protocol.command-line · test/self-hosting-command-line.test.ts:69

Coverage

roots
Declared valueExamples
"a stale page in each of the five projection roots"spec:consumers.command-line.generate-writes-every-root, spec:consumers.command-line.verb-help-touches-nothing
"five current projection roots, one stale page planted in the census root"spec:consumers.command-line.generate-check-failure

Unbound

  • roots: None
  • command: None
Design view

Requirement drawing

Requirement drawing for spec:consumers.command-line
Requirement drawing for spec:consumers.command-linesatisfies · anchoredsatisfies · anchoredverifies · anchoredverifies · anchoredverifies · anchoredverifies · anchoredmodels · anchoredrefines · declaredrefines, verifies · declaredrefines, verifies · declaredrefines, verifies · declaredrefines · declaredIntended Specsspec:consumers.command-lineEvery verb answers --help,and one verb writes everyprojection root…consumers.command-linedeclared Specspec:consumers.engine-provenanceThe CLI names the enginethat produced a result…consumers.engine-provenancedeclared SpecDeclared verifying examplesspec:consumers.command-line.generate-check-failureA root that fails its checkis removed while sdpgenerate writes the others…consumers.command-line.generate-check-failuredeclared Specspec:consumers.command-line.generate-writes-every-rootOne run of sdp generateleaves all five rootscurrent…consumers.command-line.generate-writes-every-rootdeclared Specspec:consumers.command-line.verb-help-touches-nothingA publisher's --help printsits help and touches no root…consumers.command-line.verb-help-touches-nothingdeclared SpecSatisfying or referencingunits6 satisfying units · anchored, folded6 satisfying units ·anchoredTest or oracle bindings4 test bindings · anchored, folded4 test bindings · anchoredoracle:protocol.command-lineoracle:protocol.command-line…protocol.command-lineanchored oracle bindingOutside the selected setspec:consumers.projections-modelProjections fan out fromone graph without becomingtruth stores…consumers.projections-modeldeclared Spec
The diagram as text
  • spec:consumers.command-line: Every verb answers --help, and one verb writes every projection root · declared Spec
  • spec:consumers.command-line.generate-check-failure: A root that fails its check is removed while sdp generate writes the others · declared Spec
  • spec:consumers.command-line.generate-writes-every-root: One run of sdp generate leaves all five roots current · declared Spec
  • spec:consumers.command-line.verb-help-touches-nothing: A publisher's --help prints its help and touches no root · declared Spec
  • spec:consumers.engine-provenance: The CLI names the engine that produced a result · declared Spec
  • spec:consumers.projections-model: Projections fan out from one graph without becoming truth stores · declared Spec
  • impl:protocol.adopter-help: SDP_HELP_TEXT indexes the shipped skills, recipe catalog, schema, walkthrough, glossary and specs/ by package-relative path · anchored code · src/cli/help.ts:167
  • impl:protocol.agent-surface-cli: CLI verb dispatcher and agent-surface front of the package CLI · anchored code · src/cli/sdp.ts:94
  • impl:protocol.build-args: shared build arguments and corpus-rule inputs · anchored code · src/cli/build-args.ts:11
  • impl:protocol.build-artifacts: the build step that writes each catalog recipe to dist/recipes and records the build commit beside the CLI · anchored code · src/cli/build-artifacts.ts:182
  • impl:protocol.engine-provenance-cli: prints sdp version and the commit parsed from the build-info file beside the compiled CLI · anchored code · src/cli/sdp.ts:102
  • impl:protocol.generate-command: prepares all prior roots before one shared build and publishes with each verb's checks · anchored code · src/cli/generate-command.ts:34
  • oracle:protocol.command-line: oracle:protocol.command-line · anchored oracle binding · test/self-hosting-command-line.test.ts:69
  • test:protocol.command-line.generate-check-failure: test:protocol.command-line.generate-check-failure · anchored test binding · binding present · test/self-hosting-command-line.test.ts:186
  • test:protocol.command-line.generate-writes-every-root: test:protocol.command-line.generate-writes-every-root · anchored test binding · binding present · test/self-hosting-command-line.test.ts:180
  • test:protocol.command-line.verb-help-touches-nothing: test:protocol.command-line.verb-help-touches-nothing · anchored test binding · binding present · test/self-hosting-command-line.test.ts:192
  • test:protocol.engine-provenance: version checks verify the engine provenance line and the build's commit record · anchored test binding · binding present · test/cli.test.ts:2371
  • spec:consumers.command-line refines spec:consumers.projections-model · declared — one verb publishes every projection root from one graph
  • spec:consumers.command-line.generate-check-failure refines spec:consumers.command-line · declared
  • spec:consumers.command-line.generate-check-failure verifies spec:consumers.command-line · declared
  • spec:consumers.command-line.generate-writes-every-root refines spec:consumers.command-line · declared
  • spec:consumers.command-line.generate-writes-every-root verifies spec:consumers.command-line · declared
  • spec:consumers.command-line.verb-help-touches-nothing refines spec:consumers.command-line · declared
  • spec:consumers.command-line.verb-help-touches-nothing verifies spec:consumers.command-line · declared
  • spec:consumers.engine-provenance refines spec:consumers.command-line · declared — the version flag is one more answer the command line gives an adopter
  • impl:protocol.adopter-help satisfies spec:consumers.command-line · anchored
  • impl:protocol.agent-surface-cli satisfies spec:consumers.command-line · anchored
  • impl:protocol.build-args satisfies spec:consumers.command-line · anchored
  • impl:protocol.build-artifacts satisfies spec:consumers.engine-provenance · anchored
  • impl:protocol.engine-provenance-cli satisfies spec:consumers.engine-provenance · anchored
  • impl:protocol.generate-command satisfies spec:consumers.command-line · anchored
  • oracle:protocol.command-line models spec:consumers.command-line · anchored
  • test:protocol.command-line.generate-check-failure verifies spec:consumers.command-line.generate-check-failure · anchored
  • test:protocol.command-line.generate-writes-every-root verifies spec:consumers.command-line.generate-writes-every-root · anchored
  • test:protocol.command-line.verb-help-touches-nothing verifies spec:consumers.command-line.verb-help-touches-nothing · anchored
  • test:protocol.engine-provenance verifies spec:consumers.engine-provenance · anchored
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: requirementDiagram. Chosen syntax: flowchart TB because models, folds require exact labels unavailable in requirement syntax.

Decisions

  • The shipped projections stay frozen

    Re-specifying the shipped Design Review, census, Mermaid, or Gherkin projection is refused. These four projections are the ruled read surfaces over the one graph. A later decision Spec that supersedes this one replaces the ruling whole; a decision Spec that refines this one narrows it for one projection or one rendering and leaves the rest frozen. Either passes the ADR three-part test.

Runtime
  • component:protocol.cli · entry points, shared build and publication · src/cli/build-command.ts:32 · layer edge · context protocol

    Uses

    • component:protocol.adapters · external runtime and source adapters · src/adapters/vitest.ts:23 · layer adapter · context protocol
    • component:protocol.codegen · contracts and registrar output · src/codegen/contracts.ts:633 · layer application · context protocol
    • component:protocol.extract · the carrier and source pipeline · src/extract/index.ts:192 · layer application · context protocol
    • component:protocol.graph · the one graph and its semantic decisions · src/graph/schema.ts:34 · layer domain · context protocol
    • component:protocol.import · canonical conversion with a fidelity boundary · src/import/import.ts:45 · layer application · context protocol
    • component:protocol.model · the authored contracts and stable ids · src/model/anchors.ts:100 · layer domain · context protocol
    • component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol
    • component:protocol.reader · the typed graph contract and body evaluator · src/reader/reader.ts:671 · layer application · context protocol
    • component:protocol.validate · one finding currency and ordered checks · src/validate/validators.ts:72 · layer domain · context protocol
  • impl:protocol.adopter-help · SDP_HELP_TEXT indexes the shipped skills, recipe catalog, schema, walkthrough, glossary and specs/ by package-relative path · src/cli/help.ts:167

    Component: component:protocol.cli · entry points, shared build and publication · src/cli/build-command.ts:32 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.agent-surface-cli · CLI verb dispatcher and agent-surface front of the package CLI · src/cli/sdp.ts:94

    Component: component:protocol.cli · entry points, shared build and publication · src/cli/build-command.ts:32 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.build-args · shared build arguments and corpus-rule inputs · src/cli/build-args.ts:11

    Component: component:protocol.cli · entry points, shared build and publication · src/cli/build-command.ts:32 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.generate-command · prepares all prior roots before one shared build and publishes with each verb's checks · src/cli/generate-command.ts:34

    Component: component:protocol.cli · entry points, shared build and publication · src/cli/build-command.ts:32 · layer edge · context protocol

    Uses

    None.

Runtime observation: not tracked.

Evidence

Runtime observation: not tracked.

Build attestations: not tracked.

Deployments: not tracked.

Bills of materials: not tracked.

Impact
Relations of spec:consumers.command-line
The diagram as text
  • spec:consumers.adopter-on-ramp: An adopter learns graph homes, carrier grammar and shipped paths from the on-ramps
  • spec:consumers.command-line: Every verb answers --help, and one verb writes every projection root
  • spec:consumers.command-line.generate-check-failure: A root that fails its check is removed while sdp generate writes the others
  • spec:consumers.command-line.generate-writes-every-root: One run of sdp generate leaves all five roots current
  • spec:consumers.command-line.verb-help-touches-nothing: A publisher's --help prints its help and touches no root
  • spec:consumers.engine-provenance: The CLI names the engine that produced a result
  • spec:consumers.projections-model: Projections fan out from one graph without becoming truth stores
  • spec:consumers.spec-studio.publisher: sdp studio publishes the Studio as one page set
  • spec:consumers.wholesale-view-rewrite: Every view run rewrites the view wholesale
  • spec:decisions.shipped-projections-frozen: The shipped projections stay frozen
  • spec:consumers.command-line decidedBy spec:decisions.shipped-projections-frozen · declared — the verb writes the frozen roots unchanged and adds no projection of its own
  • spec:consumers.command-line dependsOn spec:consumers.adopter-on-ramp · declared — a verb's help repeats the top-level help that names the shipped on-ramps
  • spec:consumers.command-line dependsOn spec:consumers.spec-studio.publisher · declared — the Studio's page set is one of the roots the verb writes
  • spec:consumers.command-line dependsOn spec:consumers.wholesale-view-rewrite · declared — each root the verb writes is written and invalidated as every view run's is
  • spec:consumers.command-line refines spec:consumers.projections-model · declared — one verb publishes every projection root from one graph
  • spec:consumers.command-line.generate-check-failure refines spec:consumers.command-line · declared
  • spec:consumers.command-line.generate-writes-every-root refines spec:consumers.command-line · declared
  • spec:consumers.command-line.verb-help-touches-nothing refines spec:consumers.command-line · declared
  • spec:consumers.engine-provenance refines spec:consumers.command-line · declared — the version flag is one more answer the command line gives an adopter
  • spec:consumers.command-line.generate-check-failure verifies spec:consumers.command-line · declared
  • spec:consumers.command-line.generate-writes-every-root verifies spec:consumers.command-line · declared
  • spec:consumers.command-line.verb-help-touches-nothing verifies spec:consumers.command-line · declared
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: flowchart. Chosen syntax: labelled flowchart, preserving exact relations, claims and folds.

Rests on

Rested on by

Distance 1

Distance 2

Distance 3

Distance 4

Distance 5

Relations

Relation and directionOther endClaimReasonExercised keys
decidedBy · outgoingThe shipped projections stay frozen
spec:decisions.shipped-projections-frozen · resolves
declaredthe verb writes the frozen roots unchanged and adds no projection of its ownNone
dependsOn · outgoingAn adopter learns graph homes, carrier grammar and shipped paths from the on-ramps
spec:consumers.adopter-on-ramp · resolves
declareda verb's help repeats the top-level help that names the shipped on-rampsNone
dependsOn · outgoingsdp studio publishes the Studio as one page set
spec:consumers.spec-studio.publisher · resolves
declaredthe Studio's page set is one of the roots the verb writesNone
dependsOn · outgoingEvery view run rewrites the view wholesale
spec:consumers.wholesale-view-rewrite · resolves
declaredeach root the verb writes is written and invalidated as every view run's isNone
refines · outgoingProjections fan out from one graph without becoming truth stores
spec:consumers.projections-model · resolves
declaredone verb publishes every projection root from one graphNone
refines · incomingA root that fails its check is removed while sdp generate writes the others
spec:consumers.command-line.generate-check-failure · resolves
declaredNoneNone
refines · incomingOne run of sdp generate leaves all five roots current
spec:consumers.command-line.generate-writes-every-root · resolves
declaredNoneNone
refines · incomingA publisher's --help prints its help and touches no root
spec:consumers.command-line.verb-help-touches-nothing · resolves
declaredNoneNone
refines · incomingThe CLI names the engine that produced a result
spec:consumers.engine-provenance · resolves
declaredthe version flag is one more answer the command line gives an adopterNone
verifies · incomingA root that fails its check is removed while sdp generate writes the others
spec:consumers.command-line.generate-check-failure · resolves
declaredNonegenerateCheck
verifies · incomingOne run of sdp generate leaves all five roots current
spec:consumers.command-line.generate-writes-every-root · resolves
declaredNonegenerateVerb, sameBytes, generateExit
verifies · incomingA publisher's --help prints its help and touches no root
spec:consumers.command-line.verb-help-touches-nothing · resolves
declaredNoneverbHelp, oneHelpText

Bindings

Implementation binding: present

  • impl:protocol.adopter-help · SDP_HELP_TEXT indexes the shipped skills, recipe catalog, schema, walkthrough, glossary and specs/ by package-relative path · src/cli/help.ts:167 · role projection · component component:protocol.cli · layer edge · context protocol
  • impl:protocol.agent-surface-cli · CLI verb dispatcher and agent-surface front of the package CLI · src/cli/sdp.ts:94 · role service · component component:protocol.cli · layer edge · context protocol
  • impl:protocol.build-args · shared build arguments and corpus-rule inputs · src/cli/build-args.ts:11 · role codec · component component:protocol.cli · layer edge · context protocol
  • impl:protocol.generate-command · prepares all prior roots before one shared build and publishes with each verb's checks · src/cli/generate-command.ts:34 · role publisher · component component:protocol.cli · layer edge · context protocol

Design reference: none

Verifier binding: present

Expected-outcome oracle: present

  • oracle:protocol.command-line · test/self-hosting-command-line.test.ts:69

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.