Skip to content

Commit f293d45

Browse files
os-zhuangclaude
andauthored
refactor(spec): split the migration registry's three append tables into per-entry files (#7297) (#7454)
* refactor(spec): split the migration registry's three append tables into per-entry files (#7297) The registry half of #6957's 2026-08-10 ruling, option (a): per-card entry files concatenated by a generator, the `.changeset/*.md` shape. `registry.ts` carried three hand-authored APPEND tables — each 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: `step17`'s semantic list and `RETIRED_KEYS_BY_MAJOR[17]` conflicted in 6 of 11 contended re-merge laps, 613 hand-resolved lines in four days. Both tables are consumed as SETS, so a resolution that drops a sibling's entry produces no error anywhere — that silent drop, not wall-clock, is what this removes. Entries now live one file per entry under `src/migrations/entries/` (59 semantic + 16 retired keys + 45 retired defs), concatenated into `registry.ts`'s `<os-generated …>` regions by `gen:migration-registry` and verified by `check:migration-registry`. The filename is a pure function of the entry id; order is derived by sorting on it; there is deliberately no index. This commit is MECHANICAL: every exported value is identical entry-for-entry, and the two projections reorder without changing a byte of content (their line multisets are unchanged). `scripts/adr-anchors/` (#7301) is the pilot mirrored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Py3V8MDCEEYhZrR3NvNVu5 * docs(spec): re-point the migration registry's positional cross-references at entry ids (#7297) Twelve notes in the split-out entries located a sibling by POSITION — "the entry above", "the notification pair above", "the trio at the top of this list", "`etl-pipeline-layer-retired` below". Position was a fact about append order, and append order is exactly what the split replaced with a derived sort, so each of these is now either wrong or about to be. Each is rewritten to name what it means: the sibling's id, the table it lives in, or — for the three copies of the "no backticks in `surface`" note, which pointed at whichever entry happened to carry the long form — the reason itself, inline. Content-only; the id set, every table's membership and the public API are untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Py3V8MDCEEYhZrR3NvNVu5 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 45cd354 commit f293d45

130 files changed

Lines changed: 5942 additions & 2368 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
refactor(spec): split the migration registry's three append tables into per-entry files (#7297)
6+
7+
`packages/spec/src/migrations/registry.ts` carried three hand-authored **append**
8+
tables — each protocol step's `semantic` list, `RETIRED_KEYS_BY_MAJOR` and
9+
`RETIRED_DEFS_BY_MAJOR`. Every retirement card appended to the same tail line of the
10+
same two of them, so two cards in one window were a textual conflict by construction.
11+
Measured on #6957 over 2026-08-06..10: `step17`'s semantic list and
12+
`RETIRED_KEYS_BY_MAJOR[17]` conflicted in **6 of 11** contended re-merge laps, for 613
13+
hand-resolved lines of conflict markers in four days.
14+
15+
Wall-clock was never the reason to fix it. **Both tables are consumed as sets**, so a
16+
conflict resolution that drops a sibling's entry produces **no error anywhere**: the
17+
tombstone `check:authorable-surface` was waiting for never arrives, and the D3
18+
prescription leaves the upgrade guide without a trace.
19+
20+
Per the maintainer ruling on #6957 (2026-08-10, option (a)), the entries now live one
21+
file per entry under `packages/spec/src/migrations/entries/`, concatenated into
22+
`registry.ts`'s `<os-generated …>` regions by `gen:migration-registry` and verified by
23+
`check:migration-registry` (wired into `check:generated`). The filename is a pure
24+
function of the entry id, so two cards registering different entries write different
25+
files and merge clean, while two cards editing one entry collide in git — which is
26+
correct and must stay true. Order is derived (sorted by id); there is deliberately no
27+
index file. `scripts/adr-anchors/` (#7301) is the pilot this mirrors.
28+
29+
**No behaviour change and no acceptance movement.** Every exported value is identical
30+
entry-for-entry — proved before and after by deep-comparing `MIGRATIONS_BY_MAJOR`,
31+
`RETIRED_KEYS_BY_MAJOR` and `RETIRED_DEFS_BY_MAJOR` across the change. What moved is
32+
order: `spec-changes.json` and `docs/protocol-upgrade-guide.md` now list the 59
33+
semantic migrations sorted by id rather than in append order, a one-time reorder whose
34+
line multiset is byte-identical to before. Twelve prose cross-references that pointed
35+
at a neighbour by POSITION ("the entry above", "the trio at the top of this list") were
36+
rewritten to name the entry, since position is no longer stable.
37+
38+
⚠️ Honest limit, carried from #6957: this removes the conflict **resolution**, not the
39+
regeneration **lap**. `spec-changes.json` and the upgrade guide are still committed
40+
projections (option B was rejected — the review diff is worth the laps it costs), so a
41+
retirement card is not faster, only much harder to lose.

‎.gitattributes‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@
3636
# WIDEN them), variant-docs.json and the migrations/conversions registries
3737
# (hand-written). Those conflicts are for a human. See NOT_DRIVER_MANAGED.
3838
#
39+
# The migrations registry is the interesting one since #7297: its three append
40+
# tables now come from `packages/spec/src/migrations/entries/` (one file per
41+
# entry, the `.changeset/*.md` shape), so the conflict two retirement cards used
42+
# to have is gone at the SOURCE — different entries are different files. The
43+
# file stays out of this list anyway, because it is now MIXED: a driver that
44+
# deferred it whole would resolve its still-hand-written prose by regenerating,
45+
# which loses an edit rather than a merge. `check:migration-registry` is what
46+
# guards the generated half instead.
47+
#
3948
# The strictness ledger's COUNTS file joined at #5107 — the ledger's numbers were
4049
# the repo's hottest conflict surface and merged in the one way that hides: two
4150
# batches each decrement a header by their own correct delta, the rows merge

‎docs/protocol-upgrade-guide.md‎

Lines changed: 120 additions & 120 deletions
Large diffs are not rendered by default.

‎packages/spec/package.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@
204204
"check:exported-any": "tsx scripts/check-exported-any.ts --self-test && tsx scripts/check-exported-any.ts",
205205
"check:dual-source-exports": "tsx scripts/check-dual-source-exports.ts --self-test && tsx scripts/check-dual-source-exports.ts",
206206
"check:authorable-surface": "OS_EAGER_SCHEMAS=1 tsx scripts/build-schemas.ts --check",
207+
"gen:migration-registry": "tsx scripts/build-migration-registry.ts",
208+
"check:migration-registry": "tsx scripts/build-migration-registry.ts --self-test --check",
207209
"gen:spec-changes": "tsx scripts/build-spec-changes.ts",
208210
"check:spec-changes": "tsx scripts/build-spec-changes.ts --check",
209211
"gen:upgrade-guide": "tsx scripts/build-upgrade-guide.ts",

0 commit comments

Comments
 (0)