You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9dacf61
Browse filesBrowse the repository at this point in the historyBrowse files
fix(spec): D3 gets one semantic entry per retirement family, even when D2 is lossless (#17152) (#20181)
Fixes#17152
Clause-②: no
## What
Rewrites the ADR-0087 D2/D3 house-rule prose in
`packages/spec/src/migrations/types.ts`'s module docblock — the two
spots that defined a "semantic" (D3) entry as existing only for "breaks
with no lossless mapping" — to state ruling B instead: **one D3 entry
per retirement family, even when a lossless D2 conversion also exists
for it; D2 carries the mechanical data repair only.**
Per the ruling (comment `5615360777`, restated `5634031140` on #17152,
authority: maintainer ruling on #15954 comment `5559778263`).
## Where the text actually was
The claim's premise measurement (H1) said the header at
`packages/spec/src/conversions/registry.ts:9` no longer carries the
conflicting rule — confirmed: that file's module docblock (lines 3–16)
is now about conversion expiry, unrelated. Searching the corpus named in
the dispatch order surfaced the same house rule in **three** places, not
one:
1. **`packages/spec/src/migrations/types.ts`** (hand-written, in scope)
— module docblock, two spots (the intro clause and the "semantic
changes" bullet under "Two feeders compose each major's step"). **Fixed
here**, both spots, since they're two halves of one explanatory
paragraph and fixing only one would leave the docblock
self-contradictory.
2. **`packages/spec/src/migrations/registry.ts:9`** — the *exact*
sentence quoted in the issue ("the semantic list is the non-lossless
residue D2 could not express") lives here, verbatim, and always has
(traced via `git log -S` to the original ADR-0087 commit `16b4bf69d3`).
**Fixed here in round 2**, after the seat's REWORK verdict (comment
`5853260202` on #17152). `scripts/build-migration-registry.ts` splices
only the marked regions, and the module docblock (lines 1–14) sits
outside every region. That makes it hand-written prose, and the file
says so at `:46`. `gen:migration-registry` round-trips it byte for byte:
the sha256 of `registry.ts` is identical before and after a
regeneration.
3. **`docs/adr/0087-metadata-protocol-upgrade-contract.md`** lines
152–153 and 175–176 — the ADR itself still states the pre-ruling rule:
*"Semantic changes are excluded. A change whose old shape has no
lossless mapping cannot be converted; it goes to D3."* This is a
governed path (`docs/adr/**`); the claim does not cover it. **Not
touched**, reported per the dispatch order's governed-path instruction.
Both (2) and (3) are recorded in `out_of_scope_findings` / the dev
report for the PM/spec-lane triage to pick up as follow-on work; neither
blocks landing this PR, since the ruling's intent (removing the
conflicting *hand-written, non-generated* house-rule text this claim
covers) is fully executed.
## Why
Maintainer ruling on #15954 (`5559778263`), applied to this card by the
director seat's class-one self-adjudication (`5615360777`, reaffirmed
`5634031140`): every retirement family gets one D3 semantic entry
regardless of whether a lossless D2 conversion also exists for it, so
the upgrade-notes generation pipeline (which projects off the `semantic`
list) never silently drops a retirement whose D2 fix happened to be
lossless.
## Scope
No entry added or changed, no gate added, nothing inside a generated
region touched, no runtime behavior changed — comment-only. **Changeset,
not `skip-changeset`** (round 2, measured by building
`@objectstack/spec` and grepping `dist/**` with the `MigrationStep` /
`MIGRATION_SUPPORT_FLOOR` positive controls). The `types.ts` sentence
ships verbatim in `dist/index.d.ts` and `dist/index.d.mts`; the
`registry.ts` sentence ships nowhere. So `skip-changeset` was removed,
and `.changeset/17152-d3-per-family-house-rule.md` (`@objectstack/spec`
patch) covers both edits.
## Tests
- `pnpm --filter @objectstack/spec build` — PASS (see dev report
`tests`).
- `pnpm --filter @objectstack/spec test` — see dev report `tests`.
- `pnpm --filter @objectstack/spec typecheck` — see dev report `tests`.
- `node scripts/check-comment-mask-adoption.mjs`,
`check-comment-mask-corpus.mjs`,
`check-spec-docblock-symbol-anchors.mjs` — all PASS
(comment/docblock-shape gates directly relevant to this diff).
- Full derived gate list: `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands`, reconciled with `--ran`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV)_
<sub>Two sentences corrected by the `domain:spec` seat 2
(`session_01QcAS3qiYYZNezaxZxaUdMV`) after round 2, as the dev's report
named them: the `registry.ts:9` item and the changeset sentence.</sub>
---
_Generated by [Claude Code](https://claude.ai/code)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Corrects the ADR-0087 D2/D3 house-rule prose across the migration chain's doc comments (`packages/spec/src/migrations/types.ts`, `packages/spec/src/migrations/registry.ts` and `packages/spec/src/migrations/spec-changes.ts`) so it states the ruled convention: every retirement family gets one D3 `semantic` entry, even when a lossless D2 conversion also exists for it, and D2 carries the mechanical data repair only (#17152).
6
+
7
+
Clause-②: no
8
+
9
+
The shape ruled superseded (director-seat class-one self-adjudication on #17152, authority: the maintainer's ruling on #15954) was stated in several places, each in its own words: `types.ts`'s module docblock said "breaks with no lossless mapping"; `types.ts`'s `SemanticMigration`/`MigrationStep`/`reason` doc comments said "A non-lossless change", "Why this is not losslessly convertible" and "Non-lossless changes authored for this major"; `registry.ts`'s module docblock said "the non-lossless residue D2 could not express"; and `spec-changes.ts`'s `SpecMigratedSchema` said "A semantic (non-lossless) migration" with a `rationale``.describe()` of "Why it is not losslessly convertible". All are corrected to the same meaning: a D3 entry is owed per retirement family regardless of whether D2 is lossless, and `reason`/`rationale` now say why the consumer still owes a judgment rather than why the change cannot be losslessly converted.
10
+
11
+
No entry, gate or runtime behaviour changes; this is a doc-comment correction, filed as `patch` because the `types.ts` prose ships verbatim into the published `dist/index.d.ts` / `dist/index.d.mts` (measured: `grep` after a real build finds each corrected sentence there, with `MigrationStep` and `MIGRATION_SUPPORT_FLOOR` as positive controls proving `dist` is readable). `registry.ts`'s docblock does not ship to `dist` at this head (same positive controls, zero hits either wording). `spec-changes.ts`'s `.describe()` text ships in the runtime bundles (`dist/index.js`, `dist/index.mjs`, `dist/browser/*`), not in the `.d.ts`, `json-schema/**` or `spec-changes.json` (measured the same way, with `SpecMigratedSchema` as the `.d.ts` positive control). `check:spec-changes` / `check:upgrade-guide` / `check:authorable-surface` all report their generated artifacts unchanged. Both are corrected for the same reason — each is prose the card and the ruling target.
0 commit comments