Skip to content

Split migrations/registry.ts's two append tables into per-entry files (registry half of #6957's ruling) #7297

Description

@os-help

Part of #6957. Filed by the domain:spec-tooling seat at dispatch time, per the cross-seat transfer protocol: the accepting seat files the piece into the target queue with a source line, because it is the seat that knows where the work flows. ⛔ domain:* deliberately NOT applied — routing is the triage seat's single-producer territory (#6015). This lands in packages/spec/src/migrations/, so the expected route is domain:spec.

Why this is a separate card

#6957's maintainer ruling (2026-08-10) adopted option (a) — per-card entry files concatenated by a generator — for both hand-authored append registries. The scripts/adr-anchors.json half is in flight from domain:spec-tooling (that seat's own file). This card is the packages/spec/src/migrations/registry.ts half, and it is not that seat's to schedule:

  • the file belongs to the domain:spec seat;
  • it is the file that seat's in-flight retirement cards append to — measured 37 of 691 commits in the 4-day window touched it;
  • a dev from another lane restructuring its shape mid-window would cause exactly the collision this card exists to remove.

The domain:spec seat is the only one that can see when its own retirement queue is briefly empty, which is the window this should land in.

The ruling, verbatim

hybrid — batch now, split the append surface as the durable fix.
Now: the PM landing relay batches same-window retirement cards into one PR … Queued: implement per-card registry entry files concatenated by a generator, the .changeset/*.md shape that already de-conflicted this repo's other hottest file; scripts/adr-anchors.json is in the same fix space and may ride the same mechanism. Option B (uncommitted build-time artifacts) is rejected — the review diff of spec-changes.json / the upgrade guide is worth the laps it costs.

⛔ Options (b) and (c) are settled. Do not re-open them, and do not remove any generated artifact from version control.

What the measurement established (already merged, not to be re-derived)

From #6957's measurement, PM-verified on its three load-bearing claims:

  • step17's semantic list and RETIRED_KEYS_BY_MAJOR[17] conflicted in 6 of 11 contended laps — 613 lines of hand-resolved conflict markers in 4 days. The card's original "the conflict is often absent" claim was falsified; it had generalised from the one lap it watched.
  • Both tables are consumed as setsregisteredRetiredKeys() (build-schemas.ts:699) builds a Map. So a conflict resolution that drops a sibling's entry produces no error anywhere. That silent-drop risk, not wall-clock, is the reason this is worth doing.
  • Counterfactual replay of all six real conflicts under per-entry files: 6/6 CLEAN, with the harness proven non-blind first (byte-identical round-trip; a control edit to the same entry still conflicts).

Known cost, measured

  • a one-time reorder of packages/spec/spec-changes.json and docs/protocol-upgrade-guide.md46/46 entries move under filename-sorted concatenation;
  • ~6 positional prose cross-references rewritten to id-based;
  • check-adr-0087-registration.mjs's LEDGER_SOURCES taught to read a directory.

Order: sort by entry id. ⛔ Not an explicit index file — an index is itself a single append-only file every card must edit, reintroducing the conflict being removed.

⚠️ Honest limit, carried from the escalation: this removes the conflict resolution, not the regeneration lap. The lap still fires from the merge queue and the os-regen pending marker. If the goal is "make retirement cards fast", this is not it; if the goal is "stop a retirement being silently dropped", it is.

Sequencing suggestion, not a constraint

The adr-anchors.json pilot from domain:spec-tooling proves the mechanism on a smaller file first. Waiting for it is cheap and de-risks this one; that is this seat's suggestion, and the scheduling call is domain:spec's.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions