Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .changeset/migration-registry-per-entry-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
"@objectstack/spec": patch
---

refactor(spec): split the migration registry's three append tables into per-entry files (#7297)

`packages/spec/src/migrations/registry.ts` carried three hand-authored **append**
tables — each protocol step's `semantic` list, `RETIRED_KEYS_BY_MAJOR` and
`RETIRED_DEFS_BY_MAJOR`. Every retirement card appended to the same tail line of the
same two of them, so two cards in one window were a textual conflict by construction.
Measured on #6957 over 2026-08-06..10: `step17`'s semantic list and
`RETIRED_KEYS_BY_MAJOR[17]` conflicted in **6 of 11** contended re-merge laps, for 613
hand-resolved lines of conflict markers in four days.

Wall-clock was never the reason to fix it. **Both tables are consumed as sets**, so a
conflict resolution that drops a sibling's entry produces **no error anywhere**: the
tombstone `check:authorable-surface` was waiting for never arrives, and the D3
prescription leaves the upgrade guide without a trace.

Per the maintainer ruling on #6957 (2026-08-10, option (a)), the entries now live one
file per entry under `packages/spec/src/migrations/entries/`, concatenated into
`registry.ts`'s `<os-generated …>` regions by `gen:migration-registry` and verified by
`check:migration-registry` (wired into `check:generated`). The filename is a pure
function of the entry id, so two cards registering different entries write different
files and merge clean, while two cards editing one entry collide in git — which is
correct and must stay true. Order is derived (sorted by id); there is deliberately no
index file. `scripts/adr-anchors/` (#7301) is the pilot this mirrors.

**No behaviour change and no acceptance movement.** Every exported value is identical
entry-for-entry — proved before and after by deep-comparing `MIGRATIONS_BY_MAJOR`,
`RETIRED_KEYS_BY_MAJOR` and `RETIRED_DEFS_BY_MAJOR` across the change. What moved is
order: `spec-changes.json` and `docs/protocol-upgrade-guide.md` now list the 59
semantic migrations sorted by id rather than in append order, a one-time reorder whose
line multiset is byte-identical to before. Twelve prose cross-references that pointed
at a neighbour by POSITION ("the entry above", "the trio at the top of this list") were
rewritten to name the entry, since position is no longer stable.

⚠️ Honest limit, carried from #6957: this removes the conflict **resolution**, not the
regeneration **lap**. `spec-changes.json` and the upgrade guide are still committed
projections (option B was rejected — the review diff is worth the laps it costs), so a
retirement card is not faster, only much harder to lose.
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@
# WIDEN them), variant-docs.json and the migrations/conversions registries
# (hand-written). Those conflicts are for a human. See NOT_DRIVER_MANAGED.
#
# The migrations registry is the interesting one since #7297: its three append
# tables now come from `packages/spec/src/migrations/entries/` (one file per
# entry, the `.changeset/*.md` shape), so the conflict two retirement cards used
# to have is gone at the SOURCE — different entries are different files. The
# file stays out of this list anyway, because it is now MIXED: a driver that
# deferred it whole would resolve its still-hand-written prose by regenerating,
# which loses an edit rather than a merge. `check:migration-registry` is what
# guards the generated half instead.
#
# The strictness ledger's COUNTS file joined at #5107 — the ledger's numbers were
# the repo's hottest conflict surface and merged in the one way that hides: two
# batches each decrement a header by their own correct delta, the rows merge
Expand Down
240 changes: 120 additions & 120 deletions docs/protocol-upgrade-guide.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/spec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@
"check:exported-any": "tsx scripts/check-exported-any.ts --self-test && tsx scripts/check-exported-any.ts",
"check:dual-source-exports": "tsx scripts/check-dual-source-exports.ts --self-test && tsx scripts/check-dual-source-exports.ts",
"check:authorable-surface": "OS_EAGER_SCHEMAS=1 tsx scripts/build-schemas.ts --check",
"gen:migration-registry": "tsx scripts/build-migration-registry.ts",
"check:migration-registry": "tsx scripts/build-migration-registry.ts --self-test --check",
"gen:spec-changes": "tsx scripts/build-spec-changes.ts",
"check:spec-changes": "tsx scripts/build-spec-changes.ts --check",
"gen:upgrade-guide": "tsx scripts/build-upgrade-guide.ts",
Expand Down
Loading
Loading