Spec Studio

sdp studio --watch rebuilds the page set on each carrier change

spec:consumers.spec-studio.publisher.watchUse Case / Behavior · storyready floor ready

Packs: pack:self-hosting-v1, pack:spec-studio-v1

Design: no design entries · no pinned declarations · no decisions

Findings: no errors, no warnings

specs/consumers/spec-studio.publisher.watch.sdp.md

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

While an author edits, the watch rebuilds the page set on each carrier change, and a person reloads the page to read it. Each cycle writes exactly what a plain run with the same arguments writes, so the watch adds no server, no live reload and no script of its own.

Intent
outcome
Rebuild the Studio's page set on every carrier change while an author edits, each cycle byte for byte what a plain run writes, with no server and no injected script.
Behavior
rule.watch line 20 · specs/consumers/spec-studio.publisher.watch.sdp.md:20
sdp studio --watch installs the carrier watcher validate's watch installs, publishes once at start and again after every carrier create, change, delete or rename, each cycle writing the page set a plain sdp studio with the same arguments writes, byte for byte; it serves no page and injects no script, so a reader reloads to read the new build. Findings print each cycle and the process stays alive; a cycle whose extraction fails removes the page set; operator SIGINT exits 0; edits to source files and input files start no cycle; --watch cannot combine with --check-clean.

spec:consumers.spec-studio.publisher.watch.matches-plain-run · enabled

0 unkeyed rules.

Verifying examples

Each watch cycle writes the page set a plain run writes · spec:consumers.spec-studio.publisher.watch.matches-plain-run · ready floor ready

Executable Spec

Given an extraction root holding a Pack and its member Specs and a stale Studio page {stalePage: "specs/probe.departed.html"}
When the studio command runs under watch at that root while one member carrier changes {changes: 2} times
Then the watch exits {exitCode: 0} on SIGINT
Then each watch cycle wrote the page set a plain run writes: {cyclesMatchPlainRun: true}
Then the page set holds a script the plain run does not write: {injectedScript: false}
Then the stale page survives: {staleSurvives: false}
Then a temporary Studio sibling survives: {temporarySurvives: false}

Open example

Example space

Given an extraction root holding a Pack and its member Specs and a stale Studio page {stalePage:string}
When the studio command runs under watch at that root while one member carrier changes {changes:number} times
Then the watch exits {exitCode:number} on SIGINT
Then each watch cycle wrote the page set a plain run writes: {cyclesMatchPlainRun:boolean}
Then the page set holds a script the plain run does not write: {injectedScript:boolean}
Then the stale page survives: {staleSurvives:boolean}
Then a temporary Studio sibling survives: {temporarySurvives:boolean}
Verification

Verifier bindings

  • spec:consumers.spec-studio.publisher.watch.matches-plain-run · Each watch cycle writes the page set a plain run writes · declared · example enabled · specs/consumers/spec-studio.publisher.watch.matches-plain-run.sdp.md

    External run evidence from test/studio-s5.test.ts

    Test anchors: test:protocol.studio-export-contained, test:protocol.studio-intent-handoff, test:protocol.studio-intents-refresh, test:protocol.studio-memo-shared, test:protocol.studio-watch-plain. Specs verified by those bindings: spec:consumers.edit-model, spec:consumers.intent-composition, spec:consumers.intent-composition.proposal.memo, spec:consumers.intent-composition.proposal.memo.shared, spec:consumers.spec-studio.components, spec:consumers.spec-studio.export, spec:consumers.spec-studio.export.self-contained, spec:consumers.spec-studio.intent-panel, spec:consumers.spec-studio.intent-panel.refresh-keeps-intents, spec:consumers.spec-studio.publisher.watch, spec:consumers.spec-studio.publisher.watch.matches-plain-run, spec:consumers.spec-studio.responsive.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 391 · Branch: cursor/media-plan-and-articles-09b1 · Commit: 076cd4f1f85640d8236e5cca1bffffa68ab79a33 · Start: 2026-10-31T15:32:20.471Z · Stop: 2026-10-31T15:34:02.073Z

    NameSuiteResultDuration
    executes the bound example against a fresh worldRefreshing a tab keeps every gathered intent (spec:consumers.spec-studio.intent-panel.refresh-keeps-intents)passed9.92 ms
    executes the bound example against a fresh worldRecipe 49 and the composing panel write one memo for one proposal (spec:consumers.intent-composition.proposal.memo.shared)passed4.43 ms
    executes the bound example against a fresh worldA Pack's export opens alone and keeps its links inside it (spec:consumers.spec-studio.export.self-contained)passed63.32 ms
    executes the bound example against a fresh worldEach watch cycle writes the page set a plain run writes (spec:consumers.spec-studio.publisher.watch.matches-plain-run)passed124.81 ms
    keeps unsupported intents apart and expands Pack members only against the stamped basenot recordedpassed2.27 ms
    returns the same schema problems as recipe 38 and renders in any corpusnot recordedpassed10.03 ms
    composes locally without changing source or requesting a network servicenot recordedpassed1.54 ms
    keeps the last local intents when storage refuses writesnot recordedpassed0.29 ms
    keeps unsaved local intents when storage remains readable but its quota refuses writesnot recordedpassed0.27 ms
    rewrites SVG and accessibility references without changing subject attributes or authored textnot recordedpassed6.38 ms
    opens disclosures for print and restores exactly their prior statenot recordedpassed1.43 ms
    leaves Mermaid source closed for print unless the reader opened itnot recordedpassed1.06 ms
    stops the actual Studio watch process with exit zero on SIGINTnot recordedpassed491.48 ms
    removes a failed watch publication, keeps watching and recovers on the next carrier editnot recordedpassed33.93 ms
    ships a phone layout and a print stylesheet for the whole canvasnot recordedpassed10.85 ms
    keeps exports graph-only when the browsing pages receive a base and run recordsnot recordedpassed27 ms
    starts no cycle for source or input-file eventsnot recordedpassed30.93 ms
    merges concurrent panels before gathering or discarding and flags rejected storage recordsnot recordedpassed0.6 ms
    refreshes the browser panel on storage and pageshow and removes those listeners on disconnectnot recordedpassed1.47 ms
    prefills compose with the authored entry text including code spans and no rendered annotationsnot recordedpassed15.53 ms
    omits blank exact text and reports whitespace requests in the compose dialognot recordedpassed2.42 ms
    uses the stamp base, labels fields, orders actions and copies and saves the named documentsnot recordedpassed5.09 ms
    copies distinct actions and recorded scopes for both Pack choices without a stampnot recordedpassed2.97 ms
    keeps Pack framing changes apart and gathers scenario editor steps verbatimnot recordedpassed2.66 ms
    matches the literal memo for the shared proposal, including the full relation and documentnot recordedpassed0.93 ms
    keeps the last watch pages when an optional base becomes unreadable, just like a plain runnot recordedpassed986.18 ms
    inlines the selected stylesheet asset in exports and publishes those same style bytesnot recordedpassed25.93 ms
    introduces studio before its watch option and gives recipe 49 a use casenot recordedpassed4.36 ms
    renders edit scenario steps outside inert templates without scriptnot recordedpassed1.08 ms
    renders propose scenario steps outside inert templates without scriptnot recordedpassed0.72 ms
    writes both memo reasons as code spans: "<details>Review the design.</details>", "`Keep` the ``literal`` reason`"not recordedpassed0.7 ms
    writes both memo reasons as code spans: "`Review` the ``design`` reason`", "<details>Keep the change.</details>"not recordedpassed0.43 ms
    fences requests so their Markdown cannot alter the memo: "Fix a typo.\n<!--"not recordedpassed0.89 ms
    fences requests so their Markdown cannot alter the memo: "Use this text.\n```\n## Forged heading\n``````\n<!--hidden-->"not recordedpassed0.7 ms
    contains phone navigation, stamp and wide tables within the viewportnot recordedpassed15.39 ms
    keeps the maturity caption readable and empty cells compact on a phonenot recordedpassed7.6 ms
    aligns maturity cell counts with the empty cell dashesnot recordedpassed4.92 ms
    keeps table headers and one-word cells intact while allowing word-boundary wrappingnot recordedpassed7.32 ms
    keeps natural desktop diagram size and fits only on phonesnot recordedpassed7.69 ms
    hides phone scroll advice and closed source in print while keeping opened source printablenot recordedpassed18.32 ms

Example space

  • stalePage · string · declared by an extraction root holding a Pack and its member Specs and a stale Studio page {stalePage}
  • changes · number · declared by the studio command runs under watch at that root while one member carrier changes {changes} times

Bound points

ExamplestalePagechanges
spec:consumers.spec-studio.publisher.watch.matches-plain-run"specs/probe.departed.html"2

Oracle binding: present · oracle:protocol.studio-watch · test/studio-s5.test.ts:346

Coverage

stalePage: "specs/probe.departed.html" · spec:consumers.spec-studio.publisher.watch.matches-plain-run · not enumerable

changes: 2 · spec:consumers.spec-studio.publisher.watch.matches-plain-run · not enumerable

Unbound

  • stalePage: None
  • changes: None
Design view

Requirement drawing

Requirement drawing for spec:consumers.spec-studio.publisher.watch
The diagram as text
  • spec:consumers.spec-studio.publisher.watch: sdp studio --watch rebuilds the page set on each carrier change · declared Spec
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run: Each watch cycle writes the page set a plain run writes · declared Spec
  • spec:consumers.spec-studio.publisher: sdp studio publishes the Studio as one page set · declared Spec
  • impl:protocol.studio-watch: awaits the plain Studio publication in each coalesced carrier-watch cycle · anchored code · src/cli/studio-command.ts:122
  • oracle:protocol.studio-watch: oracle:protocol.studio-watch · anchored oracle binding · test/studio-s5.test.ts:346
  • test:protocol.studio-watch-plain: test:protocol.studio-watch-plain · anchored test binding · binding present · test/studio-s5.test.ts:359
  • spec:consumers.spec-studio.publisher.watch refines spec:consumers.spec-studio.publisher · declared
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run refines spec:consumers.spec-studio.publisher.watch · declared
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run verifies spec:consumers.spec-studio.publisher.watch · declared
  • impl:protocol.studio-watch satisfies spec:consumers.spec-studio.publisher.watch · anchored
  • oracle:protocol.studio-watch models spec:consumers.spec-studio.publisher.watch · anchored
  • test:protocol.studio-watch-plain verifies spec:consumers.spec-studio.publisher.watch.matches-plain-run · anchored
Mermaid source

Copyable source; the Studio draws static SVG.

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

Decisions

No decision record named.

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.studio-watch · awaits the plain Studio publication in each coalesced carrier-watch cycle · src/cli/studio-command.ts:122

    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.spec-studio.publisher.watch
  • E4: verifies · declared
The diagram as text
  • spec:consumers.spec-studio.publisher: sdp studio publishes the Studio as one page set
  • spec:consumers.spec-studio.publisher.watch: sdp studio --watch rebuilds the page set on each carrier change
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run: Each watch cycle writes the page set a plain run writes
  • spec:consumers.validate-watch: Validation re-runs while an author edits carriers
  • spec:consumers.spec-studio.publisher.watch dependsOn spec:consumers.validate-watch · declared — the watch reruns on the carrier events validate's watch follows
  • spec:consumers.spec-studio.publisher.watch refines spec:consumers.spec-studio.publisher · declared
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run refines spec:consumers.spec-studio.publisher.watch · declared
  • spec:consumers.spec-studio.publisher.watch.matches-plain-run verifies spec:consumers.spec-studio.publisher.watch · 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

Relations

Relation and directionOther endClaimReasonExercised keys
dependsOn · outgoingValidation re-runs while an author edits carriers
spec:consumers.validate-watch · resolves
declaredthe watch reruns on the carrier events validate's watch followsNone
refines · outgoingsdp studio publishes the Studio as one page set
spec:consumers.spec-studio.publisher · resolves
declaredNoneNone
refines · incomingEach watch cycle writes the page set a plain run writes
spec:consumers.spec-studio.publisher.watch.matches-plain-run · resolves
declaredNoneNone
verifies · incomingEach watch cycle writes the page set a plain run writes
spec:consumers.spec-studio.publisher.watch.matches-plain-run · resolves
declaredNonewatch

Bindings

Implementation binding: present

  • impl:protocol.studio-watch · awaits the plain Studio publication in each coalesced carrier-watch cycle · src/cli/studio-command.ts:122 · role service · component component:protocol.cli · layer edge · context protocol

Design reference: none

Verifier binding: present

Expected-outcome oracle: present

  • oracle:protocol.studio-watch · test/studio-s5.test.ts:346

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.