p0: formalize the contract synchronization invariant#22
Merged
Conversation
THE INVARIANT: at every green commit on main, the canonical Astryx contract in dspack/examples and the copy consumed in packages/contracts are byte-identical. Repository synchronization is absolute byte equality; design-system fidelity (documented x-drift divergences from the Astryx component API, checked by drift-check.ts) lives inside the synchronized artifact — the two are never conflated. Enforcement: packages/contracts/scripts/check-sync.mjs, the dspack-gen check-sync pattern verbatim (node builtins + fetch, --write to re-sync), wired as check:sync and run by CI in place of the previous inline curl|diff step — same semantics, one implementation, locally runnable. The contract-change merge protocol is now the documented definition of done: canonical change lands in dspack first, the consuming studio PR carries the byte-copied file (intent-plus-scenario PRs stay atomic; they merge after their paired upstream PR), sync checks green in both repositories. Fail-first: run before dspack #22 merged, the check was red with DRIFT astryx.dspack.json (the Astryx contract — copy of the spec repo's source of truth) in sync shadcn-ui.dspack.json matching the CI failures main has carried since the milestone authored governance in the studio copy. After #22: both entries in sync, exit 0, and git-level byte identity confirmed directly against dspack main. PHASE-NEXT: P0 marked delivered; the invariant and protocol join the standing constraints; the take-home "byte-synced copy of dspack main" sentence is accurate again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR formalizes and enforces the “contract synchronization invariant” for @dspack-studio/contracts, ensuring the locally consumed contract JSON files remain byte-identical to the canonical copies in aestheticfunction/dspack at every green commit on main.
Changes:
- Adds a reusable sync-check script (
check-sync.mjs) to compare (and optionally re-write) local contract copies againstdspack/examples/*viaraw.githubusercontent.com. - Wires the sync check into package scripts (
check:sync) and replaces the CI inlinecurl | diffstep with the new script. - Updates the PHASE-NEXT roadmap to mark P0 delivered and document the invariant + merge protocol.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/contracts/scripts/check-sync.mjs | Introduces a Node script to detect/write byte-level drift vs canonical upstream contracts. |
| packages/contracts/package.json | Adds check:sync script entry to run the sync check locally/CI. |
| docs/PHASE-NEXT.md | Documents the invariant and marks P0 as delivered with updated protocol wording. |
| .github/workflows/ci.yml | Replaces inline `curl |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+71
to
+73
| copies. Enforcement: `packages/contracts/scripts/check-sync.mjs` | ||
| (`pnpm --filter @dspack-studio/contracts check:sync`, `--write` to | ||
| re-sync locally), run by CI on every push and PR; dspack-gen's existing |
Comment on lines
+81
to
+83
| console.error(` canonical change lands in dspack first; then either`); | ||
| console.error(` node scripts/check-sync.mjs --write, or copy this file upstream via a dspack PR.`); | ||
| } |
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.
Completes PHASE-NEXT P0 on the studio side, following dspack #22 (the one-time studio → dspack catch-up).
The invariant, now explicit and enforced: at every green commit on
main, the canonical Astryx contract indspack/examples/and the copy consumed inpackages/contracts/are byte-identical. Repository synchronization is absolute byte equality; design-system fidelity (x-driftdivergences from the Astryx component API, checked bydrift-check.ts) lives inside the synchronized artifact — never conflated.What ships:
packages/contracts/scripts/check-sync.mjs— the dspack-gen check-sync pattern verbatim (node builtins + fetch, one retry,--writeto re-sync), wired ascheck:sync.curl | diffsync step replaced by the script — same semantics, one implementation, locally runnable. (That inline step has been failing onmainsince the milestone authored governance in the studio copy; this PR makes it green again and impossible to quietly ignore.)dspackfirst → consuming studio PR carries the byte-copied file (intent-plus-scenario PRs stay atomic, merging after their paired upstream PR) → sync checks green in both repositories.Fail-first evidence (run before dspack #22 merged):
After #22: both entries
in sync, exit 0 — and byte identity confirmed at the git level directly against dspack main (not just through the CDN, which lagged ~4 minutes).Follow-up queued: dspack-gen's own check-sync now correctly flags its
fixtures/astryx.v0_1_2.dspack.jsonfor re-sync — that PR lands next with regenerated goldens.🤖 Generated with Claude Code