feat: DX-3 bootstrap boundary — v0.4 emission, x-bootstrap ledger, refusal table (0.3.0)#9
Merged
Merged
Conversation
…fusal table (0.3.0) Implements dspack rfc/dx3-bootstrap-design.md: - Snapshots declare the current spec version (0.4) via SPEC_VERSION in the new src/emit/bootstrap.ts; the adoption journey's manual relabel step disappears. Populated sections unchanged — no governance content is ever emitted. - Every snapshot carries the non-semantic metadata["x-bootstrap"] ledger: spec version, content hash per generated section, awaitingAuthorship list. Deleting the ledger graduates the document to human-owned. - Regeneration refusal table: generate refuses on no-ledger, human-authored sections, or edited generated sections — naming what it found — and never destroys human-authored content. No force flag. --out writes to an explicit path. - validate checks against a vendored byte copy of the dspack v0.4 schema (shape gate only), guarded by scripts/check-sync.mjs. - CI test.yml and tag-triggered OIDC release.yml (ds-mcp pattern); package is publishable (private flag removed, files field, 0.3.0). Fail-first: src/tests/bootstrap.test.ts failed on the pre-boundary code (module absent, "Test Files 1 failed"); 13/13 after implementation. Full suite 106/106 including the ds-mcp round-trip; the four golden fixtures regenerate with exactly the header/ledger diff and untouched content sections. Refusal table exercised end to end via the real CLI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Implements the DX-3 bootstrap boundary for dspack-export, moving snapshot emission to spec v0.4, adding a non-semantic metadata["x-bootstrap"] ledger to track generated-section ownership, and enforcing a refusal table to prevent overwriting human-authored/enriched documents. This also prepares the project for an npm-published v0.3.0 release with CI and release automation.
Changes:
- Emit
dspack: "0.4"via a singleSPEC_VERSION, and attach anx-bootstrapledger (hashes for generated sections + awaiting-authorship checklist). - Add regeneration refusal logic (no ledger / human-authored sections present / generated sections edited) and support
generate --out <file>. - Update validation to gate against a vendored v0.4 schema copy with a drift-check script, plus CI/release workflows and updated fixtures/docs for v0.3.0 publishing.
Reviewed changes
Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/bootstrap.test.ts | New DX-3 boundary tests covering v0.4 emission, ledger behavior, and refusal table. |
| src/generate.ts | Bumps embedded generator version to 0.3.0. |
| src/emit/validate.ts | Switches schema validation from v0.2 to vendored v0.4 schema. |
| src/emit/schema/dspack.v0.4.schema.json | Adds vendored dspack v0.4 JSON Schema used as a shape gate. |
| src/emit/bootstrap.ts | Introduces SPEC_VERSION, ledger hashing, and regeneration refusal decision logic. |
| src/emit/assemble.ts | Emits current spec version and writes metadata["x-bootstrap"] ledger during assembly. |
| src/cli.ts | Adds refusal enforcement before writing, adds --out, updates messaging to v0.4/shape-only validation. |
| scripts/check-sync.mjs | Adds byte-for-byte drift check against upstream dspack schema (with --write resync). |
| README.md | Updates positioning/docs for v0.4 bootstrap boundary and npm installation. |
| package.json | Prepares npm publish (removes private, sets files, adds check:sync, bumps to 0.3.0). |
| fixtures/vuetify-demo/vuetify-demo.dspack.json | Regenerates fixture header + ledger for v0.4/bootstrap. |
| fixtures/shadcn-v4-demo/shadcn-v4-demo.dspack.json | Regenerates fixture header + ledger for v0.4/bootstrap. |
| fixtures/shadcn-demo/shadcn-demo.dspack.json | Regenerates fixture header + ledger for v0.4/bootstrap. |
| fixtures/dtcg-tokens-demo/dtcg-tokens-demo.dspack.json | Regenerates fixture header + ledger for v0.4/bootstrap. |
| CHANGELOG.md | Adds changelog entries for 0.3.0 and 0.2.0-alpha.0. |
| .gitignore | Adds .DS_Store. |
| .github/workflows/test.yml | Adds CI workflow running build/test + schema drift check. |
| .github/workflows/release.yml | Adds tag-triggered OIDC trusted-publisher npm release workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+94
to
+118
| const metadata = (existing.metadata ?? {}) as Record<string, unknown>; | ||
| const ledger = metadata['x-bootstrap'] as BootstrapLedger | undefined; | ||
| if (!ledger || typeof ledger !== 'object' || typeof ledger.generated !== 'object') { | ||
| return { | ||
| allow: false, | ||
| reason: `the existing document carries no bootstrap ledger (metadata["x-bootstrap"]), so it is human-owned and this tool will not touch it. ${WORKFLOW_HINT}`, | ||
| }; | ||
| } | ||
|
|
||
| const humanSections = Object.keys(existing).filter( | ||
| (key) => !BASE_KEYS.has(key) && !(key in ledger.generated), | ||
| ); | ||
| if (humanSections.length > 0) { | ||
| return { | ||
| allow: false, | ||
| reason: `the existing document contains human-authored sections (${humanSections.join(', ')}); regenerating would sit alongside content this tool does not own. ${WORKFLOW_HINT}`, | ||
| }; | ||
| } | ||
|
|
||
| const edited = Object.entries(ledger.generated) | ||
| .filter(([section, recorded]) => { | ||
| const value = existing[section]; | ||
| return value === undefined || sectionHash(value) !== recorded; | ||
| }) | ||
| .map(([section]) => section); |
| * generator. | ||
| */ | ||
| import { describe, it, expect } from 'vitest'; | ||
| import { readFileSync } from 'node:fs'; |
… node 20 The repo claimed engines >=20 but was never CI-tested; the first CI run caught it. Declare the real floor (engines >=22, CI node 22). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the accepted DX-3 bootstrap design (§2 boundary, §3 regeneration, §5 transition).
What changes
dspack: "0.4"(singleSPEC_VERSIONconstant); the adoption journey's manual relabel step disappears. Populated sections unchanged — the tool still never writes governance content.x-bootstrapledger (non-semantic, per the approved design): spec version, content hash per generated section,awaitingAuthorshiplist. No empty governance blocks. Deleting the ledger = graduation to human-owned.generaterefuses on no-ledger / human-authored sections present / edited generated sections — each refusal names what it found and points at the ADOPTING.md workflow and--out. No force flag. Pure untouched snapshots still regenerate in place.--out <file>on generate.validatenow gates against a vendored byte copy of the dspack v0.4 schema (shape only; contract semantics stay upstream), guarded byscripts/check-sync.mjs.privateremoved,filesfield, version 0.3.0, CHANGELOG; CI (test.yml) + tag-triggered OIDCrelease.ymlmirroring ds-mcp/dspack-gen.Invariants held (from the design approval)
intents; graduated/no-ledger → refused;--outfresh path → succeeds).Fail-first evidence
src/tests/bootstrap.test.tson pre-boundary code:Failed to load url ../emit/bootstrap.js … Test Files 1 failed (1). After implementation: 13/13. Full suite 106/106 including the ds-mcp round-trip gate. The four golden fixtures were regenerated deliberately; their diffs are exactly the header + ledger (content sections byte-identical).After merge
Tag
v0.3.0→ OIDC publish (requires one-time trusted-publisher registration on npmjs.com: repositoryaestheticfunction/dspack-export, workflowrelease.yml). Per the owner decision, publication ships only together with this change. The companion dspack PR updates ADOPTING.md (step 1 guarantee wording, step 2 removal) in lockstep.🤖 Generated with Claude Code