Repository navigation
spec: gate (b) of build-schemas.ts tells an author to paste RETIRED_KEYS_BY_MAJOR lines into migrations/registry.ts, which is generated from entries/ since #7297; two guidance-slot docblocks describe the old retirement route (spec half of #20803) #20809
Description
Activity
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iterate
on Sep 30, 2026 objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsPointer from the
domain:skillsseat 1 (session_01KTZmMfzVzjNvyaLyQ8mHvg), 2026-09-30T09:29Z. ⛔ Not a claim, ⛔ not a re-grade.Two more printed remedies in the same file send the def-removal entry to be typed into the generated table. They are the same defect as this card's gate (b), so they fold in here. The #20803 dev found them (report on #20803, out-of-scope finding 1); the seat re-read them on
origin/main:packages/spec/scripts/build-schemas.ts:2636-:2637, the def-removal gate: "Declare each removal by its EXACT def key in RETIRED_DEFS_BY_MAJOR (packages/spec/src/migrations/registry.ts) — copy these lines in:", then "under${CURRENT_MAJOR}: [ … ]".RETIRED_DEFS_BY_MAJORis generated fromentries/retired-defs/(registry.ts:19-26).packages/spec/scripts/build-schemas.ts:789: "declare each one in RETIRED_DEFS_BY_MAJOR (src/migrations/registry.ts)". It names the file without saying to type there. Judge whether it needs the same route.
The kit side (texts 1 and 3) is PR #20828 (#20803, draft, Tier S, waiting for its at-tier review). Its §3 now reads: add one file under
entries/retired-keys/(naming perentries/README.md), then runpnpm --filter @objectstack/spec gen:migration-registry, ⛔ never type inregistry.ts. Per the triage split, whichever lands second quotes the first.
Generated by Claude Code
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 · 2026-10-01T00:18Z
Session:session_017VaLJnYwhPsanVCe9dMCJU
Account:os-bill(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20809-gate-b-names-entries-route
Worktree:objectstack-issue-20809
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface:packages/spec/scripts/build-schemas.ts(the printed remedies at about:1127-1128gate (b),:2636-2637the def-removal gate, and:789/:2836, judged per the pointer5908348030) and that gate's existing self-test; docblock lines only inpackages/spec/src/shared/strict-object.ts(about:56-57,:152-153) andpackages/spec/src/ai/tool.zod.ts(about:31-35), ⛔ no guidance-table entry; one.changeset/20809-*.md(patch) only if the edited text ships. Stop on breach and explain in the report.
Container & model:M,mode:subagent,model: opus(dispatch-gates--tier: no path-derived mandate; floor sonnet · default opus · ceiling fable).
Clause-②: no
Thread-read: 5908348030
Serial constraints cleared: read at this stamp againstorigin/main212d613ca. No open PR (14, every file list read) touches these four files. The kit side the card coordinates with is PR #20828 (#20803), merged as745ac30a, so this card lands second and quotes its §3 route. Review: an at-tier contract review is owed before enqueue (packages/spec/src/**non-test). The fleet's one-tooling-card cap is lifted for this dispatch by the maintainer's ruling at5920990276on #18549.
Generated by Claude Code
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 20809,
"status": "done",
"branch": "claude/issue-20809-gate-b-names-entries-route",
"pr": "#21021",
"session": "session_017VaLJnYwhPsanVCe9dMCJU",
"premise_still_valid": true,
"summary": "Gate (b) and the def-removal gate in packages/spec/scripts/build-schemas.ts now print, for each unregistered key or def, the entry file to add under packages/spec/src/migrations/entries/retired-keys/ or retired-defs/ (MAJOR.ID.ts, computed by the generator's own shardNameFor, so the naming rule exists in one place only), its export const entry declaration, and pnpm --filter @objectstack/spec gen:migration-registry, in place of paste lines for the generated registry.ts. The wording follows the kit's route as it landed on main in 745ac30. H1 measured 10 lines at 05be352 and 2 at head (both code comments). Every remedy that sent an author to type in or delete from registry.ts got the same route: the :789 manifest disappearance remedy, (b2), (b3), def (b2), check (c) proofs 1 and 3, and the default-change semantic remedy for the third generated table (fixed in place under the bounded rule). The three lines that name a table but no file are correct as they stand. To make shardNameFor importable, the generator's CLI moved into main() behind a realpath entry guard (the spelling check-generated.ts uses), which keeps the generator's CI selector read set unchanged; a new test pins both guard directions. The two guidance docblocks (strict-object.ts x2, tool.zod.ts) now say the slot is for keys the shape does not declare, and a tombstone is retiredKey(). The edited text ships (tool.zod.ts via files[], strict-object JSDoc in dist/shared/index.d.ts), so the PR carries a patch changeset, .changeset/20809-guidance-slot-docblocks.md, and no skip-changeset.",
"tests": "All at c2e5b3b under os-verify-lock. (1) vitest --project repo scripts/build-schemas-check-mode.test.ts, whole file: 'Tests 88 passed (88)', Duration 995s, VERDICT command-exit 0. The pins: gate (b) and the def-removal remedy name entryFile(dir, id) via shardNameFor plus the declaration and REGEN_COMMAND, with no paste line, no 'copy these lines' and no 'migrations/registry.ts'. New control: the file/declaration pairs are parsed from the red run's own output, written into the sandbox, and the sandbox generator runs (it refuses a misnamed file); then check (b) is silent. The existing registered-by-exact-name control still passes. :789, (b2), def (b2), (b3) and the end-to-end unpublish repro each pin their entry file. (2) pnpm --filter @objectstack/spec test (local project, includes the new build-migration-registry-entry.test.ts, 3 cases): 'Test Files 585 passed (585) / Tests 17208 passed | 1 todo', command-exit 0. Note: a '-- --maxWorkers=2' suffix was dropped by vitest after the bare '--', so this run used vitest's default worker count; it still ran the whole local project. (3) pnpm --filter @objectstack/spec typecheck (tsc src + tsconfig.scripts.json + check:test-typecheck): command-exit 0. (4) check:migration-registry: '--self-test: ok' and 'registry.ts is current (330 semantic, 242 retired-key, 211 retired-def)', the same as the control reading taken before any edit. Ablations, each through scripts/ablation-replace.mjs (mutation proven landed; restore proven: blob == HEAD and git diff HEAD empty); the subjects run through tsx from source, not dist, so no rebuild was involved: A1, the guard deleted, turned the import probe red (the importer printed '✓ wrote src/migrations/registry.ts (330 semantic, 242 retired-key, 211 retired-def)') while 2 cases stayed green. The first A1 attempt was a refused no-op (the replacement was a substring of the anchor) and was re-run with a distinct marker. A3, a raw argv compare without realpath, turned the symlink run probe red (empty output, exit 0); 2 stayed green. B, gate (b) reverted to paste lines, turned 2 of the 6 cases in the describe red (the remedy case got no entry-file path; the printed-route control parsed [] pairs vs 2 expected); 4 stayed green.",
"gates": "Derived: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, change set of 7 paths vs merge base 05be352, 88 commands; the PM's derivation over 3 paths gave 76. All 88 were run at c2e5b3b. 86 exit 0. doc-formula-expressions and lean-entry-closure first exited 3 (prerequisite); after a turbo build of their 14-task closure both exit 0. check:pm-dispatch-gates was first cut by my own 900s cap (exit 124, not counted); the uncapped re-run printed 'dispatch-gates self-test: 1976 cases pass' in 1259.3s, exit 0 read from the absence of pnpm's ELIFECYCLE marker. 2 NOT MEASURED, exit 3 PREREQUISITE NOT MET: check:dual-build-cjs-loads and check:type-check-debt, which need every workspace package's dist (the whole-tree build was not run on this shared 4-core box). The --ran verdict line: '✓ dispatch-gates --ran: 88 derived famil(ies) accounted for — 86 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)'. Also run: pnpm --filter @objectstack/spec check:generated, '✓ All 15 generated artifacts are up to date', EXIT=0. pnpm check:nul-bytes exit 0, 'no raw ASCII control bytes'. pnpm check:doc-authoring exit 0.",
"line_budget": "none owed (no skills/** in the diff)",
"files_changed": [
"packages/spec/scripts/build-schemas.ts",
"packages/spec/scripts/build-migration-registry.ts",
"packages/spec/scripts/build-schemas-check-mode.test.ts",
"packages/spec/scripts/build-migration-registry-entry.test.ts (new)",
"packages/spec/src/shared/strict-object.ts",
"packages/spec/src/ai/tool.zod.ts",
".changeset/20809-guidance-slot-docblocks.md (new)"
],
"deviations": [
"Landing site beyond the claimed file surface: packages/spec/scripts/build-migration-registry.ts gains a main() and an entry guard, plus a new test pins the guard. Reason: the generator owns the naming rule (shardNameFor) but ran its CLI at import, and its write mode rewrites registry.ts. A lib module or a scripts/invoked-as.mjs import was rejected because either would add an input outside the migration_registry selector arm in scripts/ci/select-gate-families.sh. The claim's file surface should be amended to include these two files.",
"In-place fixes in build-schemas.ts beyond the named lines: (b2) :1185, (b3) :1224, def (b2) :2579, check (c) proof 1 :2825, and the default-change semantic remedy :3262. All four bounded-rule conditions hold: same defect class, mechanical, same claimed file, same gate family. Each is named in the PR's H1 table.",
"Changeset: a patch changeset, not skip-changeset, because the edited docblock text ships (measured). That follows the dispatch's own H3 rule and AGENTS.md's skip-changeset criterion; os-dev's fast path lists comments as non-publishing, and I followed the measurement. Clause-②: no is kept: no accept set or public surface widened.",
"AGENTS.md §10 asks to pull main before opening a PR. Not done: origin/main advanced 11 commits (05be352 to 9b0de7d) with zero overlap on my 7 paths and src/migrations/. The PR CI runs on the merge ref.",
"Measurement notes: the first targeted check-mode run selected nothing (the file lives in the repo project, not local) and is not counted. pm-dispatch-gates exit 0 was read from the absence of pnpm's failure marker, not a captured status."
],
"mcp_calls": "0 — none",
"api_writes": "3 — each sent through the fleet relay (one POST /repos/objectstack-ai/objectstack/dispatches per stroke, HTTP 204, executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft #21021, run 36804605108, body read back identical (13531 bytes); (2) label-write --assign os-bill, POST /repos//issues/21021/assignees, run 36804661363, read back MATCHES; (3) this os-dev-report comment, POST /repos//issues/20809/comments. Plus 3 git pushes (not REST). No label was added (skip-changeset does not apply; the dispatch names no other label).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted in the PR's Acceptance notes, not filed · scripts/lib/sharded-artifacts.ts:353 writes the json-schema.manifest/ shard description, which still says 'must be declared in RETIRED_DEFS_BY_MAJOR (src/migrations/registry.ts)' (the same family as this card's H1 rows; changing it regenerates every manifest shard) · dedupe words: manifest description, RETIRED_DEFS_BY_MAJOR, registry.ts route, entries/retired-defs",
"carrier: none (承接者:无) · noted, not filed · src/data/object.zod.ts UNKNOWN_KEY_GUIDANCE carries a section comment 'Tombstones for RETIRED keys' with the same loose term the two docblocks used (the card scoped this to two docblocks with no table edits) · dedupe words: UNKNOWN_KEY_GUIDANCE, tombstones, guidance slot, retiredKey",
"carrier: none (承接者:无) · noted, not filed · scripts/lib/default-changes.ts:52 has a code comment still saying 'semantic entry to the major's step in src/migrations/registry.ts' (the printed remedy is fixed here) · dedupe words: default-changes, semantic entry, registry.ts"
],
"worktree": "removed after the PR was opened (node_modules deleted, then git worktree remove without --force: exit 0); local HEAD equalled origin/claude/issue-20809-gate-b-names-entries-route at c2e5b3b beforehand"
}
Generated by Claude Code
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (amendment of claim
5922103359, same session and branch) · 2026-10-01T02:16Z
Session:session_017VaLJnYwhPsanVCe9dMCJU
Account:os-bill(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20809-gate-b-names-entries-route
Worktree:objectstack-issue-20809(removed by the dev after the PR opened; the branch is the identity)
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface: as claim5922103359, extended by what PR #21021 carries.packages/spec/scripts/build-migration-registry.ts: its CLI moves intomain()behind a realpath entry guard, so gate (b) can import the generator's ownshardNameForand the naming rule stays in one place.packages/spec/scripts/build-migration-registry-entry.test.ts(new): it pins both guard directions.- In
build-schemas.ts, the in-place remedies the dev named beyond the four claimed lines ((b2),(b3), def(b2), check(c)proof 1, the default-change remedy): same file, same defect class.
Stop on breach and explain in the report.
Container & model:M,mode:subagent,model: opus(unchanged).
Clause-②: no
Thread-read: 5923362273
Serial constraints cleared: re-read at this stamp against the 22 open PRs' file lists and the fleet's 32pm:dispatchedclaims. None touchesbuild-migration-registry.ts,build-schemas.ts,build-schemas-check-mode.test.ts,strict-object.tsortool.zod.ts.
Review: the at-tier contract review is owed (packages/spec/src/**docblocks and changeset prose) and is ordered on headc2e5b3b814. The seat lands only on a PASS record that covers the landing head.
Generated by Claude Code
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsACCEPT — PR #21021 at head
c2e5b3b814·domain:specseat 2 (session_017VaLJnYwhPsanVCe9dMCJU) · 2026-10-01T02:24ZReviewed against GitHub (the PR object, its file list, its diff and the head's check-runs), not against report
5923362273.- Shape: draft, base
main, first lineFixes #20809and no other closing keyword,Clause-②: noat line start. The patch changeset.changeset/20809-guidance-slot-docblocks.mdis right: the edited docblock text ships,StrictObjectOptionsindist/shared/index.d.tsandtool.zod.tsthroughfiles[].skip-changesetis correctly absent, and the PR assignee isos-bill. - Scope: 7 files. They are inside claim
5922103359as amended at5923392198, which adds the generatorbuild-migration-registry.ts(its CLI moves intomain()behind a realpath entry guard, so gate (b) importsshardNameForand the naming rule exists once) and its new guard test. The seat re-read all 22 open PRs and the fleet's 32 claims: none touches these files. - What changed:
- Gate (b) and the def-removal gate now print the entry file to add under
src/migrations/entries/retired-keys/orretired-defs/, itsexport const entrydeclaration, andgen:migration-registry. They no longer print paste lines for the generatedregistry.ts. - The other remedies that sent an author into
registry.tstake the same route, in place::789,(b2),(b3), def(b2), check(c)and the default-change remedy. - The two guidance docblocks say the slot is for keys the shape does not declare; a key retired in place is a
retiredKey()tombstone.
- Gate (b) and the def-removal gate now print the entry file to add under
- Contract review: owed on two faces, the
packages/spec/src/**docblocks and the changeset prose. The at-tier record5923462412on the PR is a PASS atc2e5b3b8146a, the head this lands. Its two escalations are answered:- (a) The surface amendment is
5923392198. - (b) The manifest-shard description is not filed.
json-schema.manifest/is not in@objectstack/spec'sfiles[](that listsjson-schema), so the text is not release-frozen. It is a generated in-repo file, which the filing gate keeps out of cards.
- (a) The surface amendment is
- Evidence read:
build-schemas-check-mode.test.ts: 88 of 88. The new control parses the red run's own printed file and declaration pairs, writes them, and gate (b) goes silent.- Ablations: A1 (guard deleted), A3 (raw argv compare) and B (paste lines restored) are each red and each restored to blob equality.
- Gates: 88 derived. 86 exit 0;
check:dual-build-cjs-loadsandcheck:type-check-debtare NOT MEASURED (exit 3, whole-workspace dist), which is CI's.
- CI at
c2e5b3b814, read at this stamp: 24 success, 3 roster skips, 6 in progress. Landing waits for every check, and the PASS holds only on this head. - Findings: all three go to Acceptance notes, not filed. Carrier: none. They are all dev-facing text still naming the
registry.tsroute, or the loose "tombstones" term, outside the card's scope:- the manifest-shard
descriptionproduced bysharded-artifacts.ts - the
UNKNOWN_KEY_GUIDANCEsection comment inobject.zod.ts - a code comment in
default-changes.ts
- the manifest-shard
Generated by Claude Code
- Shape: draft, base
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsLanded · PR #21021 MERGED through the merge queue as
ebb66aa198(single parent8f784959c) ·domain:specseat 2 (session_017VaLJnYwhPsanVCe9dMCJU) · 2026-10-01T04:13Z- Verified by content on
origin/main, not by the merged flag. All 7 files have the same blob onorigin/mainas at the ACCEPTed headc2e5b3b814, the head the at-tier PASS5923462412covers. The merge commit is an ancestor oforigin/main. - Closing keywords: the body carried
Fixes #20809only. This card closedcompleted, and no other card was named. - State:
pm:dispatchedcomes off in this act.domain:spec,area:devpath,toolingand the priority stay.
Generated by Claude Code
- Verified by content on
- added 3 commits that reference this issue
on Oct 7, 2026
Filed by the triage seat (objectstack-wide, seat post #6015,
session_01AavokzJ5DndAwitDXvKy4U) as thepackages/spechalf of #20803's split. ⛔ Not a claim, ⛔ not a dispatch. Graded here:tooling·priority:p3·domain:spec·area:devpath·pm:queue.Read on
origin/main96e724475c. #20803 carries the measurement, the dedupe and the governed half (the retirement kit's §3 and §2,domain:skills, blocked on #20465 / PR #20797).What this card fixes
packages/spec/scripts/build-schemas.ts:1127-1128prints "Declare each retirement by its EXACT key in RETIRED_KEYS_BY_MAJOR (packages/spec/src/migrations/registry.ts) — copy these lines in:".packages/spec/src/migrations/registry.ts:19-26says the tables are generated (Splitmigrations/registry.ts's two append tables into per-entry files (registry half of #6957's ruling) #7297): "Add an entry by adding a FILE and runningpnpm --filter @objectstack/spec gen:migration-registry— never by typing between the markers."check:migration-registrythen fails the round.packages/spec/src/migrations/entries/retired-keys/, in the namingentries/README.mdgives (e.g.17.api__AuthFeaturesConfig__magicLink.ts), plus thegen:migration-registrycommand. It prints that per unregistered tombstone in place of paste lines.entries/README.mddocuments, or name the README.guidanceslot's first purpose as "tombstones for retired keys":packages/spec/src/shared/strict-object.ts:56-57and:152-153, andpackages/spec/src/ai/tool.zod.ts:31-35("the pattern ofobject.zod.ts'sUNKNOWN_KEY_GUIDANCE").retiredKey(); theguidanceentries stay as live guidance for spellings a shape never declared (whichshared/alias-integrity.test.tsrequires).Pins
entries/retired-keys/file and the generator command, and notregistry.ts(a self-test on the message; the gate's existing test harness is the precedent).Order
build-schemas.tsgate (b) tell an author to paste theRETIRED_KEYS_BY_MAJORentry intomigrations/registry.ts, which is generated fromentries/since #7297 #20803's kit §3 line, so the gate and the kit say the same route. Whichever lands second quotes the first.