test(spec): name each isomorphic pin for its module and schema, sorted - #19932
Conversation
Mechanical half of the re-key: every `IsoNNN` pin in type-alias-convention.pin.test.ts is renamed to `Iso_<module path key>__<schema export>` and the block is sorted by that name, one section per module. Bodies are byte-identical; the gate's `readIsomorphicPins` set is unchanged (789 = 789, difference 0). The runtime companion's pin counter now matches the name family instead of a numeral. Prose follows in the next commit. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
The naming and sort rule is written at the head of the pin list, with the two cohorts that used to head their own blocks (phase 2, the #4593 backfill) filed there. Notes that pointed at a pin by position or by a numeral now name it; "positional and stay vacant" goes, since no pin name is positional any more; the count history gains a +0 receipt saying the numerals it cites are the pins' former names. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Seat read — PR #19932 at head
|
| reading | base | head |
|---|---|---|
path::Schema pin set |
789 | 789 |
| only-before / only-after | — | 0 / 0 |
export type Iso… lines |
789 | 789 |
| duplicate names | — | 0 |
| pin bodies changed, multiset compared | — | 0 |
| names in code-unit order | false (control) | true |
Dark control: dropping one pin from the head file reads 788.
Changeset. Test-only, so the disposition is skip-changeset. This seat applies the label now (references/review-checklist.md: 「Tests/docs-only … 走 skip-changeset 标签,⛔ 不走空 changeset」). No .changeset/*.md is touched.
The dev's open question, packages/spec/src/shared/duration.test.ts:11 still naming Iso868, is answered A. This PR is what makes that line stale, so the one-line fix rides the round that re-runs the re-key after #19809.
Landing is held, per the claim (5804903772). PR #19809 also edits this file. This PR is not armed until #19809 has landed or closed and the re-key has been re-run on that base; that head then owes this read again.
|
Correction to this seat's read above, at 2026-09-24T01:15Z. It says 「no at-tier contract review is owed」 for this test-only diff. Under the enqueue gate, that is wrong.
|
Contract reviewServed-tier: 82/82 Isolated at-tier reviewer subagent, run by the ① Derived judgmentsInputs read: card #19665 body plus all 6 comments (incl. dev report 5805419416); PR #19932 body, Surface. Pin set, independently re-derived (not the PR's instrument). Same pin set, same 789 bodies, byte for byte right of Name rule and order. Same script, head.ts: The transform is what the PR says it is. Extracted the fenced Counter regex. base.ts:2151 Prose. Every pin the rewritten notes cite by its new name exists exactly once at head (22 names grepped, e.g. Verification claims in the PR body are consistent with the head's check-runs, which I did not re-run: all 39 runs completed; every name's latest run is ② Semver levelNone; Check Changeset on the head, two runs. Run id 107444969426 (workflow run 35939802837, the ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Base merge onto main 2c1011b to re-measure the head. The pin file is byte-identical on the merge base and on main, so it merges untouched. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
The pin file's isomorphic pins are now named for their module and schema; the EpochMs pin this test's header points at is `Iso_shared_epoch__EpochMs`, no longer `Iso868`. Comment text only. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
Fixes #19665
Clause-②: no
What this changes
packages/spec/src/type-alias-convention.pin.test.tskeyed its isomorphic pins on a dense, hand-kept counter (Iso0…Iso881). Two branches off one base each took "the next free number" for a different schema, at insertion points far apart, and git merged them cleanly into two declarations of one name:Iso871once already, thenIso877/Iso878on #19600, where onlycheck:test-typecheckcaught it.Each pin is now named for the pair that is already unique to it, its module path and its schema export name:
Iso_, then the module path belowpackages/spec/srcwithout.zod.ts, with each kebab segment camelCased and the segments joined by_(soai/knowledge-document.zod.tsbecomesai_knowledgeDocument), then__, then the schema export name. For example:Iso_shared_epoch__EpochMs.LC_ALL=C sortgives), with one heading per module. Each note about a module's pins sits under that module's heading and names the pins it covers. The schema alone now decides both a new pin's name and where it goes.There are four commits:
ece9f71d2c: the mechanical half. It is the transform below, run onfdeeea0cc9, byte for byte. That includes the runtime companion's pin counter, whose regex now matches the name family (Isofollowed by word characters) instead ofIsofollowed by digits.fc8eda2d62: prose only.789 -> 789entry.ea78da8908: a merge ofmainat2c1011b01b, to re-measure this head on currentmain.mainhas not touched the pin file since the merge base: its blob is5620656d04on bothfdeeea0cc9and2c1011b01b. So the merge leaves the file exactly asfc8eda2d62had it, and the re-key was not re-run.4a724cfbf3:packages/spec/src/shared/duration.test.ts:11cited theEpochMspin asIso868. It now citesIso_shared_epoch__EpochMs. This commit changes comment text only.The diff against
mainis two files: the pin file, and that one comment line induration.test.ts.No assertion is added and none is weakened. The exemption set is unchanged, and nothing is regenerated from a corpus measurement.
scripts/check-spec-parsed-alias.mjsis untouched, because its reader never reads the numeral.Acceptance: the assertion set is identical, member for member
Both sides are read with the gate's own
readIsomorphicPins: before isfdeeea0cc9and after isfc8eda2d62.readIsomorphicPinsentries=, keyed onpath.ts::Schema)Controls, to show the instrument can fire:
z.inferoperand to another schema keeps the set at 789 and reads 1 body changed.The module series is untouched: there are 174
import type * as M…lines before and after, and no import line is in the diff.The collision is gone: merge probe with a firing control
The probe ran
git merge-tree --write-treein a throwawaygit clone --bare --sharedwith no merge driver registered. The clone was removed afterwards. In each case, two branches off one base each add one pin for a different schema:fdeeea0cc9: both takeIso882, one inapi/analytics, one inui/viewIso882(the #19600 shape)fc8eda2d62:Iso_api_analytics__ProbeAlphaSchemaandIso_ui_view__ProbeBetaSchema, each at its sorted placeThe last row is the case that remains. Two new names with no existing pin between them insert at the same place, and git stops with a conflict; the resolution is to keep both lines. That failure is loud, and it cannot merge into a duplicate.
The module series (
M…) is left untouched, and it is not a measured collision: no one has yet seen two PRs that each import a new module. I ran one simulation of its mechanism only. Two branches that each appendimport type * as M189afterM188conflict at the tail of the import block (merge-tree exit 1). Keeping both lines when resolving would give tsc a duplicateM189. So in this simulation its failure mode is a conflict, not a silent clean merge.Landing order: this PR lands first, then #19809 re-runs the re-key on its own pin
On the maintainer's instruction, this PR lands before #19809. #19809 also edits this file: it re-pins
KanbanConfigSchemaasIso882and raises the count to 790. After this PR has landed, #19809 does this on its own branch:main. The pin file conflicts.limit#19809's own copy of the file, still on the old names, asF: rungit show H:packages/spec/src/type-alias-convention.pin.test.ts > F, whereHis fix(spec): one row bound per view — retire the unpublished per-kind viewlimit#19809's head before the merge. Then run the transform below onF. It renames and sorts every pin, including the new one, which becomesIso_ui_view__KanbanConfigSchema.limit#19809's pin set ismain's set plus its own pin. Atff13eece89it is: 790 pins, which aremain's 789 plusui/view.zod.ts::KanbanConfigSchema.git merge-file -p F BASE1 HEAD1 > out.BASE1is this file atece9f71d2c.HEAD1is this file atfc8eda2d62, which is the same bytesmainholds once this PR lands.789 -> 789entry first, then fix(spec): one row bound per view — retire the unpublished per-kind viewlimit#19809's entry restated as789 -> 790, with itstoHaveLength(790). In that entry, name the pinIso_ui_view__KanbanConfigSchemainstead ofIso882.limit#19809'sui/viewnote, name the pinIso_ui_view__KanbanConfigSchemainstead ofIso882, and drop "Iso829 stays vacant".readIsomorphicPinsonFbefore the transform with the result. The sets must be equal, the bodies unchanged, the names on the rule, and the block sorted.I dry-ran steps 2 and 3 against #19809's head
ff13eece89: 790 = 790, set difference 0 both ways, 0 bodies changed, 0 names off the rule, sorted, andIso_ui_view__KanbanConfigSchemadeclared once. The prose merge conflicts at that one hunk only.The transform is
node rekey.mjs FILE. It rewrites the file in place and is idempotent: running it onfc8eda2d62changes nothing. It is written without a less-than character so this body keeps it intact. Running exactly this text onfdeeea0cc9reproducesece9f71d2cbyte for byte.Verification
Round 2, on
4a724cfbf3, after the merge ofmainat2c1011b01b:fc8eda2d62's (blob8ae4405bd5).readIsomorphicPinsonmain's file and on this head's file reads 789 = 789, with a set difference of 0 both ways. Control: dropping one pin line reads 788, difference 1.pnpm --filter @objectstack/spec check:test-typecheck: OK (53 files / 255 errors / 142 signatures held).node scripts/check-spec-parsed-alias.mjs: "1459 bare z.input aliases, 789 pinned isomorphic, 670 paired with an XParsed. OK". Its--self-test: 18 assertions passed.pnpm --filter @objectstack/spec run typecheck: exit 0.vitest run --project localonsrc/type-alias-convention.pin.test.tsandsrc/shared/duration.test.ts: 2 files, 14 tests passed. The whole speclocalproject: 530 files, 15617 passed, 1 todo.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 77 commands, and all 77 were run. The--ranreconciliation reads 77 run, 0 NOT MEASURED, 0 unrun. Four gates first exited 3 for unbuilt prerequisites (check:doc-formula-expressions,check:lean-entry-closure,check:dual-build-cjs-loads,check:type-check-debt), and each exited 0 after its build.Round 1, on
fc8eda2d62. The pin file's bytes have not changed since, so these still describe it:node scripts/ablation-replace.mjsrenamedIso_ui_view__TreeConfigSchemato the existing nameIso_ui_view__RowHeightSchema, andcheck:test-typecheckturned red ("2 type error(s) in a file the ledger does not cover"). The file was then restored: blob == HEAD andgit diff HEADis empty.fdeeea0cc9and the merge probe are in the sections above.Changeset
None. The file is a test.
@objectstack/spec'sfilesshipssrc/**/*.zod.tsanddistbut never*.test.ts, so nothing published changes.check-empty-changeset.mjsrefuses a new empty-frontmatter changeset, so the repo's disposition for this diff is theskip-changesetlabel. The seat applied that label after the PR opened. The one redCheck Changesetrun onfc8eda2d62came from theopenedevent, before the label; on4a724cfbf3that check isskipped.Acceptance notes
api/errors.zod.tspins (FieldErrorCodeandFieldErrorSchema) sat under theapi/error-code-ledger.zod.tsheading. The sorted layout files them under their own module.packages/spec/src/shared/duration.test.ts:11cited this file'sIso868in the present tense. That pin isEpochMs, nowIso_shared_epoch__EpochMs, and4a724cfbf3updates the citation. The otherIso-plus-digits hits underpackages/spec/src, outside this file, areui/component.zod.tslines 2052, 2523 and 2929 andui/i18n.zod.tsline 198. They nameIso818,Iso819,Iso839andIso759, pins that were deleted before this PR, so they are history and stay as they are.Isonames are in code-unit order and that each one equals the rule applied to itsMnpath and schema.Generated by Claude Code
Generated by Claude Code