Pages are written to a temporary sibling of the view directory, the previous directory is removed, and the temporary is renamed into place — one rename, so no half-written view is ever readable and no temporary survives a completed run.
A run that cannot produce a current view removes the stale one instead of leaving it readable as current: an absent view is honest, a stale view is not.
Before extraction, the shared build removes generated/design-review/, generated/census/, generated/mermaid/ and generated/gherkin/, each with its temporary sibling, so a run that fails before rendering leaves no view behind; a removal failure refuses the build before extraction. Every command that enters this build, including validate and its watch runs and every publisher, has this invalidation effect, so a sibling root the command does not publish stays absent until a later publication. The Studio's root is removed beside these four, as spec:consumers.spec-studio.publisher#rule.buildInvalidates states.
Under --check-clean the view is rendered twice from the same graph and the run refuses when the two renders diverge, removing the view it could not certify.
Findings never withhold the view. A run whose checks report findings still writes the current view and returns the checks' own exit code, because the view is where those findings are read in context.
Given an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
Given the stale page is planted {planted: "before the run"}
When the {command: "build"} command runs at that root
Then the run exits {exitCode: 0}
Then the view directory survives: {viewSurvives: false}
Then the stale page survives: {staleSurvives: false}
Then a temporary view sibling survives: {temporarySurvives: false}
Given
an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
the stale page is planted {planted: "before the run"}
When
the {command: "build"} command runs at that root
Then
the run exits {exitCode: 0}
the view directory survives: {viewSurvives: false}
the stale page survives: {staleSurvives: false}
a temporary view sibling survives: {temporarySurvives: false}
Given an extraction root holding {corpus: "one authored spec the extractor refuses"} and a stale view page {stalePage: "spec/probe.departed.md"}
Given the stale page is planted {planted: "after the build has invalidated the view"}
When the {command: "view"} command runs at that root
Then the run exits {exitCode: 1}
Then the view directory survives: {viewSurvives: false}
Then the stale page survives: {staleSurvives: false}
Then a temporary view sibling survives: {temporarySurvives: false}
Given
an extraction root holding {corpus: "one authored spec the extractor refuses"} and a stale view page {stalePage: "spec/probe.departed.md"}
the stale page is planted {planted: "after the build has invalidated the view"}
When
the {command: "view"} command runs at that root
Then
the run exits {exitCode: 1}
the view directory survives: {viewSurvives: false}
the stale page survives: {staleSurvives: false}
a temporary view sibling survives: {temporarySurvives: false}
Given an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
Given the stale page is planted {planted: "after the build has invalidated the view"}
When the {command: "view"} command runs at that root
Then the run exits {exitCode: 0}
Then the view directory survives: {viewSurvives: true}
Then the view holds the current page {currentPage: "index.md"}
Then the stale page survives: {staleSurvives: false}
Then a temporary view sibling survives: {temporarySurvives: false}
Given
an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
the stale page is planted {planted: "after the build has invalidated the view"}
When
the {command: "view"} command runs at that root
Then
the run exits {exitCode: 0}
the view directory survives: {viewSurvives: true}
the view holds the current page {currentPage: "index.md"}
the stale page survives: {staleSurvives: false}
a temporary view sibling survives: {temporarySurvives: false}
Given an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
Given the stale page is planted {planted: "before the run"}
When the {command: "view"} command runs at that root
Then the run exits {exitCode: 0}
Then the view directory survives: {viewSurvives: true}
Then the view holds the current page {currentPage: "index.md"}
Then the stale page survives: {staleSurvives: false}
Then a temporary view sibling survives: {temporarySurvives: false}
Given
an extraction root holding {corpus: "one authored spec"} and a stale view page {stalePage: "spec/probe.departed.md"}
the stale page is planted {planted: "before the run"}
When
the {command: "view"} command runs at that root
Then
the run exits {exitCode: 0}
the view directory survives: {viewSurvives: true}
the view holds the current page {currentPage: "index.md"}
the stale page survives: {staleSurvives: false}
a temporary view sibling survives: {temporarySurvives: false}
Given an extraction root holding {corpus:"one authored spec"|"one authored spec the extractor refuses"} and a stale view page {stalePage:string}
Given the stale page is planted {planted:"before the run"|"after the build has invalidated the view"}
When the {command:"view"|"build"} command runs at that root
Then the run exits {exitCode:number}
Then the view directory survives: {viewSurvives:boolean}
Then the view holds the current page {currentPage:string}
Then the stale page survives: {staleSurvives:boolean}
Then a temporary view sibling survives: {temporarySurvives:boolean}
spec:consumers.wholesale-view-rewrite.late-stale-page · A page the build's invalidation never saw still does not survive the swap · declared · example enabled · specs/consumers/wholesale-view-rewrite.late-stale-page.sdp.md
corpus · "one authored spec" | "one authored spec the extractor refuses" · declared by an extraction root holding {corpus} and a stale view page {stalePage}
stalePage · string · declared by an extraction root holding {corpus} and a stale view page {stalePage}
planted · "before the run" | "after the build has invalidated the view" · declared by the stale page is planted {planted}
command · "view" | "build" · declared by the {command} command runs at that root
an extraction root holding {corpus:"one authored spec"|"one authored spec the extractor refuses"} and a stale view page {stalePage:string}
the stale page is planted {planted:"before the run"|"after the build has invalidated the view"}
When
the {command:"view"|"build"} command runs at that root
Then
the run exits {exitCode:number}
the view directory survives: {viewSurvives:boolean}
the view holds the current page {currentPage:string}
the stale page survives: {staleSurvives:boolean}
a temporary view sibling survives: {temporarySurvives:boolean}
Composing needs the script.
Design view
Requirement drawing
Requirement drawing for spec:consumers.wholesale-view-rewriteThe diagram as text
spec:consumers.wholesale-view-rewrite: Every view run rewrites the view wholesale · declared Spec
spec:consumers.wholesale-view-rewrite.build-invalidates-view: A build that never renders still takes the old view down · declared Spec
spec:consumers.wholesale-view-rewrite.failed-run-view-removed: A run that cannot produce a current view leaves no view at all · declared Spec
spec:consumers.wholesale-view-rewrite.late-stale-page: A page the build's invalidation never saw still does not survive the swap · declared Spec
spec:consumers.wholesale-view-rewrite.stale-page-removed: A page from an earlier run does not survive the next one · declared Spec
spec:consumers.design-review: Design Review renders graph context without becoming a gate · declared Spec
impl:protocol.wholesale-view-rewrite: publishes each Design Review as one wholesale temporary-directory replacement · anchored code · src/cli/validate-view-command.ts:128
test:protocol.wholesale-view-rewrite.build-invalidates-view: the build point verifies the up-front invalidation on a command that renders no view · anchored test binding · binding present · test/self-hosting-projections.test.ts:1064
test:protocol.wholesale-view-rewrite.failed-run-view-removed: the failed-run point verifies that an uncertifiable view is removed, not left readable · anchored test binding · binding present · test/self-hosting-projections.test.ts:1032
test:protocol.wholesale-view-rewrite.late-stale-page: the late-page point verifies that the swap itself evicts what invalidation missed · anchored test binding · binding present · test/self-hosting-projections.test.ts:996
test:protocol.wholesale-view-rewrite.stale-page-removed: the stale-page point verifies the wholesale rewrite of the view directory · anchored test binding · binding present · test/self-hosting-projections.test.ts:960
impl:protocol.wholesale-view-rewrite · publishes each Design Review as one wholesale temporary-directory replacement · src/cli/validate-view-command.ts:128
spec:consumers.census-page dependsOn spec:consumers.wholesale-view-rewrite · declared — the shared build invalidates the projection roots before this publisher renders
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.gherkin-view dependsOn spec:consumers.wholesale-view-rewrite · declared — the shared build invalidates the projection roots before this publisher renders
spec:consumers.mermaid-view dependsOn spec:consumers.wholesale-view-rewrite · declared — the shared build invalidates the projection roots before this publisher renders
spec:consumers.obsidian-vault dependsOn spec:consumers.wholesale-view-rewrite · declared — the shared build's invalidation removes the five projection roots and never the vault
spec:consumers.spec-studio.publisher dependsOn spec:consumers.wholesale-view-rewrite · declared — the Studio's root is written, invalidated and certified the way the shipped roots are
spec:consumers.wholesale-view-rewrite.late-stale-page · A page the build's invalidation never saw still does not survive the swap · declared · specs/consumers/wholesale-view-rewrite.late-stale-page.sdp.md · example enabled