Spec Studio

A Pack exports as one file, and every page prints as a document

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

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

Design: 5 design entries · 1 pinned declaration · no decisions

Findings: no errors, no warnings

specs/consumers/spec-studio.export.sdp.md

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

A design is sent and archived as well as browsed: attached to a message, handed to someone outside the repository, printed for a review meeting. Every build writes each Pack as one self-contained HTML file inside the page set, so a reader with only a link downloads it from the Pack page, and the file opens anywhere with nothing beside it. Every page also prints as a document.

Intent
outcome
Let a person take a Pack's whole design away as one file that opens anywhere, and print any page as a readable document.
Behavior
rule.exportPerPack line 25 · specs/consumers/spec-studio.export.sdp.md:25
The page set holds one export file per Pack, exports/<name>.html, its name formed from the Pack's id as the Pack's page name is.

spec:consumers.spec-studio.export.self-contained · enabled

rule.selfContained line 26 · specs/consumers/spec-studio.export.sdp.md:26
An export is one HTML file that loads nothing: its style is inline, it carries no script, and every diagram in it is inline SVG, so it opens from any folder or as an attachment with no other file.

spec:consumers.spec-studio.export.self-contained · enabled

rule.exportContent line 27 · specs/consumers/spec-studio.export.sdp.md:27
An export holds the Pack page's content and then each member's Spec page content in authored order, every disclosure written open; it leaves out the navigation, the rail, the search field, the stamp line, the composing panel and every control that needs the script.

spec:consumers.spec-studio.export.self-contained · enabled

rule.exportLinks line 28 · specs/consumers/spec-studio.export.sdp.md:28
Inside an export, a link to the Pack or to a member points at its section in the file, a link to an element of the Pack page or of a member's page points at that element in the file, and a link to anything else becomes its id as text, so no link leaves the file.

spec:consumers.spec-studio.export.self-contained · enabled

rule.uniqueExportIds line 29 · specs/consumers/spec-studio.export.sdp.md:29
Within an export, every element id copied from the Pack page takes the prefix pack/ and every id copied from a member's page the prefix <Spec id>/, while each member's section keeps its Spec id as its own id; every fragment link and every attribute that names an element id, such as aria-describedby or a label's for, is rewritten to the prefixed id, so no two elements in the file share an id.

spec:consumers.spec-studio.export.self-contained · enabled

rule.exportFromPackPage line 30 · specs/consumers/spec-studio.export.sdp.md:30
Each Pack page links its export under the header, as Download this Pack as one file.

no example exercises it

rule.printAsDocument line 31 · specs/consumers/spec-studio.export.sdp.md:31
Every page prints as a document: the print style hides the navigation, the rail, the search field, the composing panel and every control, gives the canvas the page's width, prints a diagram whole at that width, and prints every disclosure open except Mermaid source, which prints only when the reader opened it, the expander opening each before printing and restoring it after.

no example exercises it

rule.exportBytes line 32 · specs/consumers/spec-studio.export.sdp.md:32
An export is a function of the graph like every page: the same graph writes the same bytes, and an export holds no time, commit or stamp.

no example exercises it

0 unkeyed rules.

Verifying examples

A Pack's export opens alone and keeps its links inside it · spec:consumers.spec-studio.export.self-contained · ready floor ready

Executable Spec

Given a Pack of {members: 3} member Specs, one of which names a Spec outside the Pack
When the build writes the Pack's export file
Then the export loads {loads: 0} other files
Then the export holds {scripts: 0} script elements
Then every link in the export points inside it or is text: {linksInside: true}
Then no two elements in the export share an id: {idsUnique: true}
Then the export holds {sections: 3} member sections

Open example

Example space

Given a Pack of {members:number} member Specs, one of which names a Spec outside the Pack
When the build writes the Pack's export file
Then the export loads {loads:number} other files
Then the export holds {scripts:number} script elements
Then every link in the export points inside it or is text: {linksInside:boolean}
Then no two elements in the export share an id: {idsUnique:boolean}
Then the export holds {sections:number} member sections
Design
exportIds line 40 · specs/consumers/spec-studio.export.sdp.md:40
a copied id is written pack/<id> for the Pack page and <Spec id>/<id> for a member's page, so a member's section.behavior becomes its Spec id, a slash and section.behavior; the slash appears in no graph id, so a prefixed id never equals a member's section id or another prefixed id.
expanderPrint line 41 · specs/consumers/spec-studio.export.sdp.md:41
sdp-expander, before the page prints, opens every details inside it except a drawing's or the maturity map's Mermaid source, which keeps the state the reader left, and after printing restores each one's state.

no citation recorded

UI
exportTitle line 35 · specs/consumers/spec-studio.export.sdp.md:35
the export opens with the Pack's title, its id, and the line Exported from the Spec Studio, with no date or commit.
exportLink line 36 · specs/consumers/spec-studio.export.sdp.md:36
under the Pack page's header, a link reading Download this Pack as one file, with the download attribute naming the file.
memberSection line 37 · specs/consumers/spec-studio.export.sdp.md:37
each member's section has its Spec id as its element id and opens with the member's position, title and id.
Verification

Verifier bindings

  • spec:consumers.spec-studio.export.self-contained · A Pack's export opens alone and keeps its links inside it · declared · example enabled · specs/consumers/spec-studio.export.self-contained.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
  • test:protocol.studio-intent-handoff · anchored · test anchor binding present · test/studio-s5.test.ts:407

Example space

  • members · number · declared by a Pack of {members} member Specs, one of which names a Spec outside the Pack

Bound points

Oracle binding: present · oracle:protocol.studio-export · test/studio-s5.test.ts:302

Coverage

members: 3 · spec:consumers.spec-studio.export.self-contained · not enumerable

Unbound

  • members: None
Design view

Requirement drawing

Requirement drawing for spec:consumers.spec-studio.export
The diagram as text
  • spec:consumers.spec-studio.export: A Pack exports as one file, and every page prints as a document · declared Spec
  • spec:consumers.spec-studio.export.self-contained: A Pack's export opens alone and keeps its links inside it · declared Spec
  • spec:consumers.spec-studio: The Spec Studio is a static HTML workbench over the one graph · declared Spec
  • impl:protocol.studio-diagram-element: adds view-box pan, zoom and pinch to build-rendered SVG without changing its layout · anchored code · src/studio-elements/diagram.ts:23
  • impl:protocol.studio-expander: opens fragment ancestors and expands disclosures for print · anchored code · src/studio-elements/expander.ts:16
  • impl:protocol.studio-pack-export: copies rendered canvas content into one inline-styled document with prefixed element references · anchored code · src/projections/studio/pages/export-page.ts:35
  • impl:protocol.studio-pack-page: renders Pack members, maturity and boundary joins · anchored code · src/projections/studio/pages/pack-page.ts:68
  • oracle:protocol.studio-export: oracle:protocol.studio-export · anchored oracle binding · test/studio-s5.test.ts:302
  • test:protocol.studio-export-contained: test:protocol.studio-export-contained · anchored test binding · binding present · test/studio-s5.test.ts:312
  • test:protocol.studio-intent-handoff: test:protocol.studio-intent-handoff · anchored test binding · binding present · test/studio-s5.test.ts:407
  • spec:consumers.spec-studio.export refines spec:consumers.spec-studio · declared
  • spec:consumers.spec-studio.export.self-contained refines spec:consumers.spec-studio.export · declared
  • spec:consumers.spec-studio.export.self-contained verifies spec:consumers.spec-studio.export · declared
  • impl:protocol.studio-diagram-element satisfies spec:consumers.spec-studio.export · anchored
  • impl:protocol.studio-expander satisfies spec:consumers.spec-studio.export · anchored
  • impl:protocol.studio-pack-export satisfies spec:consumers.spec-studio.export · anchored
  • impl:protocol.studio-pack-page satisfies spec:consumers.spec-studio.export · anchored
  • oracle:protocol.studio-export models spec:consumers.spec-studio.export · anchored
  • test:protocol.studio-export-contained verifies spec:consumers.spec-studio.export.self-contained · anchored
  • test:protocol.studio-intent-handoff verifies spec:consumers.spec-studio.export · 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

No decision record named.

Runtime
  • component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    • 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.model · the authored contracts and stable ids · src/model/anchors.ts:100 · layer domain · context protocol
    • component:protocol.notation · the leaf step codec · src/notation/slots.ts:261 · layer domain · 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
  • component:protocol.studio-elements · optional browser behavior and proposal handoff · src/studio-elements/index.ts:13 · layer edge · context protocol

    Uses

    • 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
  • impl:protocol.studio-diagram-element · adds view-box pan, zoom and pinch to build-rendered SVG without changing its layout · src/studio-elements/diagram.ts:23

    Component: component:protocol.studio-elements · optional browser behavior and proposal handoff · src/studio-elements/index.ts:13 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.studio-expander · opens fragment ancestors and expands disclosures for print · src/studio-elements/expander.ts:16

    Component: component:protocol.studio-elements · optional browser behavior and proposal handoff · src/studio-elements/index.ts:13 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.studio-pack-export · copies rendered canvas content into one inline-styled document with prefixed element references · src/projections/studio/pages/export-page.ts:35

    Component: component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.studio-pack-page · renders Pack members, maturity and boundary joins · src/projections/studio/pages/pack-page.ts:68

    Component: component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · 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.export
The diagram as text
  • spec:consumers.spec-studio: The Spec Studio is a static HTML workbench over the one graph
  • spec:consumers.spec-studio.export: A Pack exports as one file, and every page prints as a document
  • spec:consumers.spec-studio.export.self-contained: A Pack's export opens alone and keeps its links inside it
  • spec:consumers.spec-studio.pack-page: A Pack page shows the Pack's design as one card per member
  • spec:consumers.spec-studio.publisher: sdp studio publishes the Studio as one page set
  • spec:consumers.spec-studio.spec-page: A Spec page shows one Spec in collapsible panels, in a fixed order
  • spec:consumers.studio-on-ramp: The Studio skill teaches agents to publish, share and read the Spec Studio
  • spec:extraction.determinism: Committed source derives byte-identical output
  • spec:consumers.spec-studio.export constrainedBy spec:extraction.determinism · declared
  • spec:consumers.spec-studio.export dependsOn spec:consumers.spec-studio.pack-page · declared — an export opens with its Pack page's content
  • spec:consumers.spec-studio.export dependsOn spec:consumers.spec-studio.publisher · declared — the export files are part of the page set the publisher writes
  • spec:consumers.spec-studio.export dependsOn spec:consumers.spec-studio.spec-page · declared — an export holds each member's Spec page content
  • spec:consumers.spec-studio.export refines spec:consumers.spec-studio · declared
  • spec:consumers.studio-on-ramp dependsOn spec:consumers.spec-studio.export · declared — the skill teaches the Pack export and what it leaves out
  • spec:consumers.spec-studio.export.self-contained refines spec:consumers.spec-studio.export · declared
  • spec:consumers.spec-studio.export.self-contained verifies spec:consumers.spec-studio.export · 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
constrainedBy · outgoingCommitted source derives byte-identical output
spec:extraction.determinism · resolves
declaredNoneNone
dependsOn · outgoingA Pack page shows the Pack's design as one card per member
spec:consumers.spec-studio.pack-page · resolves
declaredan export opens with its Pack page's contentNone
dependsOn · outgoingsdp studio publishes the Studio as one page set
spec:consumers.spec-studio.publisher · resolves
declaredthe export files are part of the page set the publisher writesNone
dependsOn · outgoingA Spec page shows one Spec in collapsible panels, in a fixed order
spec:consumers.spec-studio.spec-page · resolves
declaredan export holds each member's Spec page contentNone
refines · outgoingThe Spec Studio is a static HTML workbench over the one graph
spec:consumers.spec-studio · resolves
declaredNoneNone
dependsOn · incomingThe Studio skill teaches agents to publish, share and read the Spec Studio
spec:consumers.studio-on-ramp · resolves
declaredthe skill teaches the Pack export and what it leaves outNone
refines · incomingA Pack's export opens alone and keeps its links inside it
spec:consumers.spec-studio.export.self-contained · resolves
declaredNoneNone
verifies · incomingA Pack's export opens alone and keeps its links inside it
spec:consumers.spec-studio.export.self-contained · resolves
declaredNoneexportPerPack, selfContained, exportContent, exportLinks, uniqueExportIds

Bindings

Implementation binding: present

  • impl:protocol.studio-diagram-element · adds view-box pan, zoom and pinch to build-rendered SVG without changing its layout · src/studio-elements/diagram.ts:23 · role interaction · component component:protocol.studio-elements · layer edge · context protocol
  • impl:protocol.studio-expander · opens fragment ancestors and expands disclosures for print · src/studio-elements/expander.ts:16 · role interaction · component component:protocol.studio-elements · layer edge · context protocol
  • impl:protocol.studio-pack-export · copies rendered canvas content into one inline-styled document with prefixed element references · src/projections/studio/pages/export-page.ts:35 · role projection · component component:protocol.projections · layer edge · context protocol
  • impl:protocol.studio-pack-page · renders Pack members, maturity and boundary joins · src/projections/studio/pages/pack-page.ts:68 · role projection · component component:protocol.projections · layer edge · context protocol

Design reference: none

Verifier binding: present

  • spec:consumers.spec-studio.export.self-contained · A Pack's export opens alone and keeps its links inside it · declared · specs/consumers/spec-studio.export.self-contained.sdp.md · example enabled
  • test:protocol.studio-intent-handoff · anchored · test/studio-s5.test.ts:407 · test anchor

Expected-outcome oracle: present

  • oracle:protocol.studio-export · test/studio-s5.test.ts:302

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.