docs(spec): re-anchor the dead tracker citations in api/ to the commits that decided them (stage 2) - #20342
Conversation
…ts that decided them Comment and docblock lines under packages/spec/src/api (rest-server.zod.ts excluded) that cited a tracker number answering 404 now cite the commit in this repository that decided what the line describes, and say so in words. Every file keeps its line count; no code token moves; string literals are left as tokens. Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ Co-authored-by: Claude <noreply@anthropic.com>
… of the shared ack/redeliver spelling Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ Co-authored-by: Claude <noreply@anthropic.com>
…ovenance comments The rewritten docblocks ship: src/**/*.zod.ts is in files[], and the comments reach dist .d.ts and .js. Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ Co-authored-by: Claude <noreply@anthropic.com>
…ten docblocks project into Generated by `check:generated --fix` (gen:docs only, the one artifact it proved stale); five lines, each the same substitution as its source line. Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 7 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin b54babc701d040e17f27e6cf724c55170b279cf5 && git checkout b54babc701d040e17f27e6cf724c55170b279cf5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f 24d9fba6853632e578426586682669ebfb9d253a && git checkout -B drift-repro d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f && git merge --no-ff 24d9fba6853632e578426586682669ebfb9d253a
node scripts/docs-audit/affected-docs.mjs --json d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f
|
Part of #20234
Clause-②: no
What changed
This is stage 2 of the staged sweep. It covers
packages/spec/src/api/**and nothing else, and it leaves outpackages/spec/src/api/rest-server.zod.ts, which seat 2's #20295 claim holds. Later stages cover the other areas, so this PR saysPart of.Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on #19123). That is 107 sites on 105 lines in 22 files, covering 30 numbers. Each rewritten line now cites the commit in
origin/mainhistory that decided what the line describes, and it says in its own words what that commit decided. No ADR or ruling-record file indocs/adr/orscripts/adr-anchors/names any of the 32 dead numbers, so every anchor is a commit. Nothing was dropped: every number in scope had a deciding commit. One more comment site is left on purpose, because its number belongs to another repository (see Acceptance notes).Only comments changed. Every source file keeps its line count (112 lines out, 112 in), so no line citation into these files moves. Seven of those 112 lines carry no number; they are the second half of a sentence that had to be reflowed. No code token moves (see the guard below). The 34 string-literal sites that carry a dead number are tokens, so they are left as they were and listed below.
No citation number is added. Every tracker number on an added line was already on the line it replaces. No PR number stands beside a sha.
Two more kinds of file change, both mechanical:
content/docs/references/api/(dispatcher.mdx,error-code-ledger.mdx,plugin-rest-api.mdx).check:docsproved those three pages stale, andpnpm --filter @objectstack/spec check:generated --fixregenerated only them. The diff is five lines, each the same substitution as its source line.patchchangeset for@objectstack/spec(see Changeset below).Census:
api/, before and afterInstrument. This is stage 1's instrument. It sends REST
GET /repos/objectstack-ai/objectstack/issues/Nwithout following redirects, for every distinct in-repo number cited inpackages/spec/src/api. The population is:CITATION_RE, kept when the qualifier is none,objectstack,objectstack-ai/objectstack,framework,pre-orpost-;summon.Each site is classified by the TypeScript parser as a line comment, a docblock or a string.
Controls. The lit controls were
#16862,#16847and#17698. The dead controls were#16714,#16715and#16697. They were probed at the start, after every 100 numbers and at the end, which is 5 checkpoints per run. They read 15 of 15 lit (200) and 15 of 15 dead (404) in both runs.api/rest-server.zod.ts21ab41041, probed 2026-09-27T22:56Z to 22:58Z22a00c42d, probed 2026-09-27T23:10Z to 23:12Z;.tssources identical at the final headBefore, in scope, by class. 34 non-test docblock sites and 30 non-test line comments. 7 test docblock sites and 37 test line comments. 33 test string sites (describe and it titles). 1 non-test string.
After, in scope. 34 string sites and 1 comment site remain. The comment site is
export-job-family-retirement.test.ts:25, which names an objectui PR (see Acceptance notes). The head probe found no number newly dead since the base probe: 319 numbers answer 200 in both runs.PR #20226's area table read
api153 at an earlier base, and this census reads the same 153 at21ab41041. Of those, 11 sites sit inrest-server.zod.ts(#14369twice and#14691nine times, all comments). They wait for #20295 to land.pre-#Nspellings do occur inapi/: the at-tier review measured 15 sites on 15 lines in 13 files at the head, for examplediscovery.zod.ts:913pre-#4828. All 15 numbers answer 200, so the gate's blind spot for that spelling (#20330) hides no dead site in this stage. (Corrected by thedomain:specseat 4 at 2026-09-28T00:48Z, from the at-tier review record 5861396181. The draft said that no such spelling occurs.)Per-number table
The counts are in-scope sites and files.
rewritten / leftgives comment sites rewritten and string sites left. Every anchor was read in its diff or message, not only in its subject: it is the commit that made the change the line now describes, never a later refactor or a commit that merely mentions the number.#603718189983d: declaresDataProtocol.validateData, the validate-only operation, under #4633 ruling D#6239f549a0d4a: retiresViewProtocoland its ten request/response schemas (ADR-0049, route 3)#628784c86fb45:previewandtrialfold tosandboxby declaration, and the fold table is typed total overEnvironmentType#6306fec784863: the direct-mount routes read the one API base#636190bbf2510: the notification-listcursoris retired on both halves (maintainer ruling 2026-08-07, Option A)#636317d095413:unreadCountcounts the whole inbox, not the window#6704c3f491626:runAutomationsdeclares the default the import route applies, with the agreement pin#888530b1c636a: registers the nine REST wire codes that sweep found#974011b779e0f: declaresgetMetaItemLayered. The two cross-references to its test block now name the block by member#97412a29caa53: records the 2026-08-18 maintainer ruling.previewDraftsandstateare declared, andenvironmentIdstays transport-level#993479c46da90: the producer-sideuserMessagechannel#10264(objectui)#10330b9e9227e3: declaresmappingNameonImportRequestSchema#10338d2619fd0c:ApiEndpoint.targetis optional, and the publish gate holds the flow requirement#10726bc56e1881: retirescontributes.routes, ruled Option B (stage 1's anchor too)#11006cccbe51bf: declarespublishMetaItemunder the 2026-08-22 maintainer ruling, option B#114531a47a5368:ack()refuses a row that is notin_flight#11504f90e82024: registersFLOW_INPUT_SCHEMA_INVALID, the contract half (stage 1's anchor too)#118460c2334f6c: the preview-mode retirement, whose test states the same assertion-set reasoning (stage 1's anchor too)#11858(a PR)1a47a5368, its squash commit:ack()takes the sharedDELIVERY_NOT_ELIGIBLEspelling#11859d9cf78eaa:ack()binds the claim credential in its compare-and-set#12194311433f6b: declares the item-name grammar and refuses it loudly at the publish door#131359e0ba21a1: retires the paper metadata-customization protocol (stage 1's anchor too)#1319756c093c4d: the in-memory driver enforces field-levelunique#14474df657d9df: the install-time namespace conflict refusal carries an ADR-0112 envelope#14691b3a63d32c: retires the ten inertRestServerConfigkeys. All 16 sites are inrest-server.test.ts; the 9 inrest-server.zod.tsare out of scope#1472365846bc46: lands the 2026-09-03 maintainer ruling, so a unique-constraint refusal has one wire spelling,UNIQUE_VIOLATION, on every route#1474892b5d7f00: registersNAMESPACE_CONFLICT(its diff wrote the row this line glosses)#16649613bfbd3dfor 9 sites: registers the fourteen remainingdoor: 'none'codes.44c917a47for 2 sites: widens the vocabulary gate's face to every published package and retiresboot-refusal(each of its diffs wrote the line it now anchors)#1705894c930248: parses the dataset-query selection at the door, with its leniency sweep#193078f6d83147: thesys_permission_setduplicate-name refusal carriesUNIQUE_VIOLATIONEvery cited sha resolves to exactly one commit (
git rev-parse --disambiguate, count 1), and every one is an ancestor of the base (merge-base --is-ancestor, exit 0). That is 30 distinct shas.Two wordings to check, both true of their commit:
error-code-ledger.zod.ts:919: 「the contract review that passed commit 1a47a53 ruled option B」. The review record sat on PR fix(service-messaging): enforce ack()'s claimed-row precondition in both outbox implementations #11858, which answers 404 today. The line keeps that review's ruling as stated before and names the commit that landed it.discovery.zod.ts:291: 「route B toward the single API base that commit fec7848 gave the direct-mount routes」.@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 is live and stays, and the dead goal it pointed at is now named by the commit that delivered it.The 34 string sites left as tokens
protocol.test.ts12,rest-server.test.ts12,export.test.ts3,error-code-ledger.test.ts2,validate-data.test.ts2, and 1 each indiscovery.test.tsandendpoint.test.ts.error-code-ledger.zod.ts:1692, thereasonof theFLOW_INPUT_SCHEMA_INVALIDrow in the exportedPROVENANCE_WAIVERStable (it cites#11504). It ships in the package as data. The one reader,scripts/check-error-code-provenance.ts, checks the table and never prints areasonto an author. So it is neither a comment nor author-shown text in the form D sense, and it is not rewritten here.No author-shown text was found in
api/: nothing here is #20233's form D.Mechanical guard: no code token moves
The check is a comments-stripped token comparison, base
21ab41041against head22a00c42d(the later commits add only the changeset and the regenerated pages). It uses the TypeScript parser's leaf tokens, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 22 touched.tsfiles.rest-server.test.tstest-title string): 1 file reads DIFFER (exit 1).Changeset
This change ships bytes, so a
patchchangeset for@objectstack/specis included. It says only that the provenance comments were re-anchored.Measured on the built package: 8 of the touched sources are
src/**/*.zod.ts, whichfiles[]ships verbatim. The rewritten docblocks also reachdist:2a29caa53,cccbe51bf,84c86fb45,613bfbd3dand90bbf2510each appear in 1 declaration file, and613bfbd3dand79c46da90each appear in 6 bundled.jsfiles. The positive control, a pre-existingprotocol.zod.tsdocblock sentence, appears indist/api/index.d.ts.Gates (head
24d9fba68)pnpm check:issue-citations && node scripts/check-issue-citations.mjsexits 0. The self-test passes 73 cases in 7 batteries. The live run judged 13 citations across 8 files, and all 13 resolve. These are the live numbers left on changed lines, such as Import dry run green-lights a row the write then rejects: structured value shapes (address / location) are not pre-checked #4633, 两个 discovery 生产者都在线上返回 schema 未声明的顶层字段(scoping / features / endpoints),且 REST 形状永远无法通过 DiscoverySchema #4828,saveMetaItemis a declared REQUIRED member whose request schema declares 3 of the ~11 members the REST PUT door sends, so the call-site literal is castas any#12004,deleteMetaItemis a declared member whose request schema declares 2 of the 8 members the REST reset door sends, so the call-site cast cannot come off #11679 and [Decision] Clause ② on an UNREGISTERED error code carried by a thrown value: #14552 landedno, #15963 landsyes, and they are the same class #16404.pnpm check:doc-authoringexits 0.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat the final head derived 111 families, and all 111 exit 0.--ranreports 111 run, 0 NOT MEASURED, 0 unrun, and exits 0.check:docsexited 1 there; that is what proved the three pages stale.check:doc-formula-expressions,check:dual-build-cjs-loads,check:lean-entry-closure,check:type-check-debt) first exited 3, PREREQUISITE NOT MET. They exit 0 after a fullturbo run buildof./packages/*(71 tasks, exit 0, under the shared verify lock).pnpm --filter @objectstack/spec buildexits 0.vitest run --maxWorkers=2 src/apiinpackages/spec: 47 files and 1,518 tests pass. That covers all 13 touched test files.api/source text (check-error-code-provenance,file-description,schema-index) pass: 3 files, 144 tests.pnpm --filter @objectstack/spec typecheckexits 0, includingcheck:test-typecheck(53 files, 255 errors, 142 pinned signatures held).eslint --no-inline-config --format jsonover the 22 touched.tsfiles: 22 files, 0 errors, 0 warnings. All 22 are in eslint's own population (isPathIgnoredfalse for each). The config never enables type-aware linting, so a comment edit here cannot move the verdict on any untouched file. The repo-widepnpm lintis CI's run.Acceptance notes
export-job-family-retirement.test.ts:25reads 「objectui retired its side first (objectui#10247, merged as objectui PR dogfood: simulate a brand-new developer's first-run journey — README → create an app → skills-driven AI build → validate & test #10264)」. The number belongs to objectui's board, but the citation grammar readsobjectui PR #10264as a bare number of this repository, so the census counts it as dead here (it is 404 on this board).objectstack-ai/objectuianswers 403 to this session, on both REST and the web page, so whether that PR is live is NOT MEASURED. The line is left unchanged. This is the same grammar family as [finding]check-issue-citationsreads thepre-inpre-#N(andpost-inpost-#N) as a repository qualifier, so a dead number in that spelling is classed cross-repo and never judged #20330'spre-/post-blind spot, a qualifier the grammar does not recognise, and it is named there, not filed.origin/main(d3958bac6, read at 2026-09-28). Neither commit touchespackages/spec/src/apiorcontent/docs/references/api, and a no-drivermerge-treeof the head ontod3958bac6exits 0. So there was no merge.api.responseFormatandapi.documentation.enabled(4 keys); the envelope is fixed andenableOpenApialready decides the document #20295's branch. It editsrest-server.test.tstoo, in hunks at base lines 114 to 136, 152 to 185 and 663 to 679. This PR's four comment edits there are at lines 198, 206, 266 and 371. A no-drivermerge-treeof this head with that branch's head2e575f156exits 0.content/docs/references/api/are the one set of files outsidepackages/spec/src/api/**besides the changeset. They are generator output projected from the rewritten docblocks, and the requiredTypeScript Type Checkjob reds without them.Generated by Claude Code