Spec Studio

The diff page shows what changed in the design since a base graph

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

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

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

Findings: no errors, no warnings

specs/consumers/spec-studio.diff-page.sdp.md

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

Iterating on a design asks what changed since the last pass, or what a change proposal would change. Given the graph of an earlier commit, the build renders the design diff between it and the graph it built, so a reviewer reads the changed Specs, entries, relations and bindings, and each changed Spec's page says it changed.

Intent
outcome
Let a person read, from a link, what changed in the design between a base graph the build was given and the graph it built, down to each entry.
Behavior
rule.onlyWithBase line 22 · specs/consumers/spec-studio.diff-page.sdp.md:22
The page set holds diff.html only when the build was given a base graph; without one, no page, link or change note names a diff.

no example exercises it

rule.namesTheBase line 23 · specs/consumers/spec-studio.diff-page.sdp.md:23
The page opens by naming its input: the base graph, its label when the build was given one, its schema version and its Spec count beside the built graph's, and a sentence that the comparison reads the two graphs only.

no example exercises it

rule.diffSections line 24 · specs/consumers/spec-studio.diff-page.sdp.md:24
The page renders recipe 35's answer with detail: true over the whole corpus, in sections in this order: the totals as sentences; the Specs added, linked; the Specs removed, as their ids in text, since no page holds them; the Specs changed, each linked, with each changed part, its change in words, and for a changed value the base value and the built value as readable text blocks or lists, one above the other, never a raw JSON array; keyed changes list in the head's rule and flow order, each as one line with the entry's text rendered as on its Spec page beside its old and new address or none; the Packs whose membership, order or order meaning changed, an added Pack whose order is priority read as added as a roadmap, its added members in manifest order, a removed Pack whose order was priority read as removed as a roadmap, and a known change to priority read as now a roadmap or from priority as no longer a roadmap, stating the before and after order values for other changes of meaning; the bindings changed, kept apart and headed as derived from anchors; and the diagnostics.

spec:consumers.spec-studio.diff-page.changed-entry · enabled

rule.specChangeNotes line 25 · specs/consumers/spec-studio.diff-page.sdp.md:25
Given a base graph, each changed Spec's page adds a line under its header that names the base input, counts keyed parts apart as <n> rules keyed, wording unchanged beside any other changed parts it lists, and links to its row on the diff page; each added Spec's page says it is new since the base.

spec:consumers.spec-studio.diff-page.changed-entry · enabled

rule.packChangeNotes line 26 · specs/consumers/spec-studio.diff-page.sdp.md:26
Given a base graph, each Pack page adds a Changed since the base section after its maturity map, from recipe 35's answer for that Pack, listing its changed and added members, linked, and its own membership change, with the same roadmap and order-meaning wording as the diff page; a member whose only changes are keying is marked keyed only.

no example exercises it

rule.confersNothing line 27 · specs/consumers/spec-studio.diff-page.sdp.md:27
The page and the change notes state differences between two graphs and confer nothing: no approval, staleness or readiness, and no record that a design pass happened.

no example exercises it

0 unkeyed rules.

Verifying examples

The diff page shows a changed entry's base and built values · spec:consumers.spec-studio.diff-page.changed-entry · ready floor ready

Executable Spec

Given a base graph in which the Design entry {key: "limit"} of a Spec reads {before: "ten items"}
Given the built graph in which that entry reads {after: "twenty items"}
When the build renders the diff page
Then the Spec's row shows the base value {baseShown: "ten items"} and the built value {nowShown: "twenty items"}
Then the Spec's page carries the changed-since-base line: {changeNote: true}

Open example

Example space

Given a base graph in which the Design entry {key:string} of a Spec reads {before:string}
Given the built graph in which that entry reads {after:string}
When the build renders the diff page
Then the Spec's row shows the base value {baseShown:string} and the built value {nowShown:string}
Then the Spec's page carries the changed-since-base line: {changeNote:boolean}
UI
baseLine line 30 · specs/consumers/spec-studio.diff-page.sdp.md:30
Compared with the base graph <label>, schema <version>, <n> Specs; the built graph has schema <version>, <m> Specs., the label left out when none was given.
changedSpec line 31 · specs/consumers/spec-studio.diff-page.sdp.md:31
the title linked, the id as code, then one row per part: the part as code, its change in words, keyed changes in the head's rule and flow order, each as one line with the entry's text rendered as on its Spec page beside Base and Now addresses or none, and for a changed value two labelled blocks, Base and Now, holding readable text or lists without a raw JSON array; the block's element id is the Spec's id, which the Spec page's change note links to.
bindingRow line 32 · specs/consumers/spec-studio.diff-page.sdp.md:32
the Spec linked, then for implementing units, referencing units, enabled verifiers and delivery facts the ids added and removed, under the heading Bindings, derived from anchors.
changeNote line 33 · specs/consumers/spec-studio.diff-page.sdp.md:33
Changed since the base graph <label>: followed by <n> rules keyed, wording unchanged when any parts are keyed, using rule for one, beside the other changed parts as code, linked to the Spec's row on the diff page.
Verification

Verifier bindings

  • spec:consumers.spec-studio.diff-page.changed-entry · The diff page shows a changed entry's base and built values · declared · example enabled · specs/consumers/spec-studio.diff-page.changed-entry.sdp.md

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

    Test anchors: test:protocol.studio-diff-changed-entry, test:protocol.studio-glossary-same-word-twice, test:protocol.studio-navigation, test:protocol.studio-queue-dependency-first, test:protocol.studio-registers-blocking-first. Specs verified by those bindings: spec:consumers.spec-studio.diff-page, spec:consumers.spec-studio.diff-page.changed-entry, spec:consumers.spec-studio.glossary-page, spec:consumers.spec-studio.glossary-page.same-word-twice, spec:consumers.spec-studio.navigation, spec:consumers.spec-studio.owner-queue, spec:consumers.spec-studio.owner-queue.dependency-first, spec:consumers.spec-studio.registers, spec:consumers.spec-studio.registers.blocking-first.

    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 worldThe questions page lists the Specs with a blocking question first (spec:consumers.spec-studio.registers.blocking-first)passed35.62 ms
    executes the bound example against a fresh worldThe owner queue lists a waiting statement after the one it rests on (spec:consumers.spec-studio.owner-queue.dependency-first)passed19.95 ms
    executes the bound example against a fresh worldThe diff page shows a changed entry's base and built values (spec:consumers.spec-studio.diff-page.changed-entry)passed21.64 ms
    executes the bound example against a fresh worldA word two Specs define appears once per Spec on the glossary page (spec:consumers.spec-studio.glossary-page.same-word-twice)passed8.31 ms
    renders declaration citations, decision reasons and design backlog from the shipped answersStudio register pagespassed34.81 ms
    reaches each page in order, marks it current and omits every diff reference without a baseStudio register pagespassed10.2 ms
    refuses malformed base flags and unreadable JSON before extractionStudio register pagespassed1.96 ms
    refuses a base in generated output before writing through graphStudio base comparisonpassed21.29 ms
    refuses a base in generated output before writing through nestedStudio base comparisonpassed15.24 ms
    refuses a base in generated output before writing through file aliasStudio base comparisonpassed17.97 ms
    refuses a base in generated output before writing through root aliasStudio base comparisonpassed6.75 ms
    refuses a base in generated output before writing through input aliasStudio base comparisonpassed10.5 ms
    renders only existing sides for added and removed entries and one value for moved entriesStudio base comparisonpassed13.63 ms
    shows per-Pack diagnostics without no-change claims for invalid graphStudio base comparisonpassed19.84 ms
    shows per-Pack diagnostics without no-change claims for different schemaStudio base comparisonpassed15.35 ms
    keeps additions, removals, Pack order and anchor bindings apart and escapes compared valuesStudio base comparisonpassed24.48 ms
    shows unreadable graph values as the recipe's diagnostics on the named diff pageStudio base comparisonpassed2.54 ms
    leaves the base file unchanged and certifies repeat publication with the same inputStudio base comparisonpassed28.52 ms
    keeps a cycle's round separate from statements that rest on nothing, and lists owner holdsStudio base comparisonpassed12.27 ms
    sorts terms without locale collation and keeps non-letter headings addressableStudio base comparisonpassed5.74 ms
    orders queue floor options by rung and carries the Pack and floor on each rowStudio base comparisonpassed16.78 ms
    uses authored term keys and orders duplicate terms by Spec idStudio base comparisonpassed6.7 ms
    reads each owner question's provisional reading from its reader Spec and keynot recordedpassed9.69 ms
    renders a keying proposal as one line per keyed entry and readable changed rule textnot recordedpassed9.43 ms
    lists keyed lines in head rule order with rendered text for added, renamed and removed keysnot recordedpassed14.46 ms
    counts keyed rules apart from changed parts, mixed changes: falsenot recordedpassed6.09 ms
    counts keyed rules apart from changed parts, mixed changes: truenot recordedpassed6.9 ms
    names one keyed rule in the singularnot recordedpassed7.97 ms
    marks only members with exclusively keyed changes as keyed onlynot recordedpassed13.49 ms
    renders changed list values as lists instead of raw JSON arraysnot recordedpassed6.06 ms
    retains the owning list when readable rule text moves to a flownot recordedpassed5.57 ms
  • test:protocol.roadmap-priority · checks Pack priority extraction, comparison and Studio change notes · anchored · test anchor binding present · test/roadmap-priority.test.ts:44

    External run evidence from test/roadmap-priority.test.ts

    Test anchors: test:protocol.roadmap-priority. Specs verified by those bindings: spec:carrier.markdown-pack-authoring, spec:consumers.design-diff, spec:consumers.spec-studio.diff-page, spec:consumers.spec-studio.pack-page, spec:extraction.pack-member-order, spec:model.pack-aggregate.

    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
    derives equal Markdown and TypeScript Pack nodes and edges, serializes order last, and exposes it through the readerroadmap priority manifestpassed45.69 ms
    refuses the invalid Markdown value readingroadmap priority manifestpassed1.85 ms
    refuses the invalid Markdown value arbitraryroadmap priority manifestpassed1.57 ms
    refuses the invalid Markdown value trueroadmap priority manifestpassed1.49 ms
    refuses the invalid Markdown value nullroadmap priority manifestpassed1.94 ms
    refuses the invalid Markdown value []roadmap priority manifestpassed1.71 ms
    refuses the invalid Markdown value {}roadmap priority manifestpassed1.43 ms
    refuses the invalid TypeScript value "reading"roadmap priority manifestpassed7.24 ms
    refuses the invalid TypeScript value "arbitrary"roadmap priority manifestpassed2.88 ms
    refuses the invalid TypeScript value trueroadmap priority manifestpassed3.36 ms
    refuses the invalid TypeScript value nullroadmap priority manifestpassed3.31 ms
    refuses the invalid TypeScript value []roadmap priority manifestpassed9.61 ms
    refuses the invalid TypeScript value {}roadmap priority manifestpassed3.83 ms
    refuses the invalid TypeScript value undefinedroadmap priority manifestpassed2.87 ms
    refuses the invalid TypeScript value chosenOrderroadmap priority manifestpassed4.04 ms
    names a removed Pack by its order meaning (priority true)roadmap priority design diffpassed19.39 ms
    names a removed Pack by its order meaning (priority false)roadmap priority design diffpassed17.38 ms
    names an added roadmap and preserves manifest order in its member deltaroadmap priority design diffpassed26.27 ms
    labels Pack membership by its order meaning (priority true)roadmap priority design diffpassed15.16 ms
    labels Pack membership by its order meaning (priority false)roadmap priority design diffpassed6.39 ms
    states order values when a change is not a known roadmap transitionroadmap priority design diffpassed11.93 ms
    documents the order comparison fields, default and diagnostic in the recipe contractroadmap priority design diffpassed1.3 ms
    compares a priority transition to true without a membership editroadmap priority design diffpassed10.9 ms
    compares a priority transition to false without a membership editroadmap priority design diffpassed6.76 ms
    reads an absent order as reading order in a base schema that predates the fieldroadmap priority design diffpassed14.49 ms
    marks the absent side of an added or removed roadmap as null (true)roadmap priority design diffpassed10.48 ms
    marks the absent side of an added or removed roadmap as null (false)roadmap priority design diffpassed4.24 ms
    diagnoses an unknown order at the base without reporting an order changeroadmap priority design diffpassed3.41 ms
    diagnoses an unknown order at the head without reporting an order changeroadmap priority design diffpassed4.06 ms
    still compares membership and member order when the base order is unknownroadmap priority design diffpassed5.37 ms
    still compares membership and member order when the head order is unknownroadmap priority design diffpassed9.28 ms
    keeps an order-only change in the selected Pack's comparison scoperoadmap priority design diffpassed3.1 ms
    shows no roadmap transition for a membership-only change (priority true)roadmap priority design diffpassed8.38 ms
    shows no roadmap transition for a membership-only change (priority false)roadmap priority design diffpassed7.43 ms
    shows the roadmap transition to true on the diff and Pack pagesroadmap priority design diffpassed8.78 ms
    shows the roadmap transition to false on the diff and Pack pagesroadmap priority design diffpassed17.15 ms

Example space

  • key · string · declared by a base graph in which the Design entry {key} of a Spec reads {before}
  • before · string · declared by a base graph in which the Design entry {key} of a Spec reads {before}
  • after · string · declared by the built graph in which that entry reads {after}

Bound points

Examplekeybeforeafter
spec:consumers.spec-studio.diff-page.changed-entry"limit""ten items""twenty items"

Oracle binding: present · oracle:protocol.studio-diff-page · test/studio-s3.test.ts:196

Coverage

key: "limit" · spec:consumers.spec-studio.diff-page.changed-entry · not enumerable

before: "ten items" · spec:consumers.spec-studio.diff-page.changed-entry · not enumerable

after: "twenty items" · spec:consumers.spec-studio.diff-page.changed-entry · not enumerable

Unbound

  • key: None
  • before: None
  • after: None
Design view

Requirement drawing

Requirement drawing for spec:consumers.spec-studio.diff-page
The diagram as text
  • spec:consumers.spec-studio.diff-page: The diff page shows what changed in the design since a base graph · declared Spec
  • spec:consumers.spec-studio.diff-page.changed-entry: The diff page shows a changed entry's base and built values · declared Spec
  • spec:consumers.spec-studio: The Spec Studio is a static HTML workbench over the one graph · declared Spec
  • impl:protocol.studio-diff: renders declared design changes and binding changes separately · anchored code · src/projections/studio/pages/diff-page.ts:91
  • oracle:protocol.studio-diff-page: oracle:protocol.studio-diff-page · anchored oracle binding · test/studio-s3.test.ts:196
  • test:protocol.roadmap-priority: checks Pack priority extraction, comparison and Studio change notes · anchored test binding · binding present · test/roadmap-priority.test.ts:44
  • test:protocol.studio-diff-changed-entry: test:protocol.studio-diff-changed-entry · anchored test binding · binding present · test/studio-s3.test.ts:210
  • spec:consumers.spec-studio.diff-page refines spec:consumers.spec-studio · declared
  • spec:consumers.spec-studio.diff-page.changed-entry refines spec:consumers.spec-studio.diff-page · declared
  • spec:consumers.spec-studio.diff-page.changed-entry verifies spec:consumers.spec-studio.diff-page · declared
  • impl:protocol.studio-diff satisfies spec:consumers.spec-studio.diff-page · anchored
  • oracle:protocol.studio-diff-page models spec:consumers.spec-studio.diff-page · anchored
  • test:protocol.roadmap-priority verifies spec:consumers.spec-studio.diff-page · anchored
  • test:protocol.studio-diff-changed-entry verifies spec:consumers.spec-studio.diff-page.changed-entry · 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.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
  • impl:protocol.studio-diff · renders declared design changes and binding changes separately · src/projections/studio/pages/diff-page.ts:91

    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.diff-page
The diagram as text
  • spec:consumers.design-diff: Designs are compared between a base commit and the working tree at entry grain
  • spec:consumers.spec-studio: The Spec Studio is a static HTML workbench over the one graph
  • spec:consumers.spec-studio.data.inputs: The Studio reads two named inputs beside the graph, a base graph and run records
  • spec:consumers.spec-studio.diff-page: The diff page shows what changed in the design since a base graph
  • spec:consumers.spec-studio.diff-page.changed-entry: The diff page shows a changed entry's base and built values
  • spec:consumers.spec-studio.spec-page: A Spec page shows one Spec in collapsible panels, in a fixed order
  • spec:consumers.spec-studio.diff-page dependsOn spec:consumers.design-diff · declared — the page renders the design diff between the base graph and the graph built
  • spec:consumers.spec-studio.diff-page dependsOn spec:consumers.spec-studio.data.inputs · declared — the base graph reaches the page as the build's named base input
  • spec:consumers.spec-studio.diff-page refines spec:consumers.spec-studio · declared
  • spec:consumers.spec-studio.spec-page dependsOn spec:consumers.spec-studio.diff-page · declared — given a base graph, the header's change note links the Spec's row on the diff page
  • spec:consumers.spec-studio.diff-page.changed-entry refines spec:consumers.spec-studio.diff-page · declared
  • spec:consumers.spec-studio.diff-page.changed-entry verifies spec:consumers.spec-studio.diff-page · 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

Relations

Relation and directionOther endClaimReasonExercised keys
dependsOn · outgoingDesigns are compared between a base commit and the working tree at entry grain
spec:consumers.design-diff · resolves
declaredthe page renders the design diff between the base graph and the graph builtNone
dependsOn · outgoingThe Studio reads two named inputs beside the graph, a base graph and run records
spec:consumers.spec-studio.data.inputs · resolves
declaredthe base graph reaches the page as the build's named base inputNone
refines · outgoingThe Spec Studio is a static HTML workbench over the one graph
spec:consumers.spec-studio · resolves
declaredNoneNone
dependsOn · incomingA Spec page shows one Spec in collapsible panels, in a fixed order
spec:consumers.spec-studio.spec-page · resolves
declaredgiven a base graph, the header's change note links the Spec's row on the diff pageNone
refines · incomingThe diff page shows a changed entry's base and built values
spec:consumers.spec-studio.diff-page.changed-entry · resolves
declaredNoneNone
verifies · incomingThe diff page shows a changed entry's base and built values
spec:consumers.spec-studio.diff-page.changed-entry · resolves
declaredNonediffSections, specChangeNotes

Bindings

Implementation binding: present

  • impl:protocol.studio-diff · renders declared design changes and binding changes separately · src/projections/studio/pages/diff-page.ts:91 · role projection · component component:protocol.projections · layer edge · context protocol

Design reference: none

Verifier binding: present

  • spec:consumers.spec-studio.diff-page.changed-entry · The diff page shows a changed entry's base and built values · declared · specs/consumers/spec-studio.diff-page.changed-entry.sdp.md · example enabled
  • test:protocol.roadmap-priority · checks Pack priority extraction, comparison and Studio change notes · anchored · test/roadmap-priority.test.ts:44 · test anchor

Expected-outcome oracle: present

  • oracle:protocol.studio-diff-page · test/studio-s3.test.ts:196

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.