docs(types): re-anchor the dead tracker citations in packages/types/src to the commits that decided them - #20673
Conversation
…rc to the commits that decided them Every comment and docblock site under packages/types/src that cited a tracker number answering 404 now cites the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided. Comments only; every touched file keeps its line count. A patch changeset ships because the docblocks reach dist. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 3 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 ecd053b11c9c02415ea1f9771581d82cdbec6a5a && git checkout ecd053b11c9c02415ea1f9771581d82cdbec6a5a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6c11ef9ecbf3e99f4d8f45f81073eafc5eae3607 686a4c60cb76ea289772fe8e33d6a1be9208a9c0 && git checkout -B drift-repro 6c11ef9ecbf3e99f4d8f45f81073eafc5eae3607 && git merge --no-ff 686a4c60cb76ea289772fe8e33d6a1be9208a9c0
node scripts/docs-audit/affected-docs.mjs --json 6c11ef9ecbf3e99f4d8f45f81073eafc5eae3607
|
Contract reviewServed-tier: PR #20673 (draft, base ① Derived judgmentsAccept set and public surface: nothing moves. Every one of the 198 changed lines (104 added, 94 removed) outside the new changeset begins with a comment prefix ( (1) Comment-only, and the two tense moves.
(2) Anchors. All 12 shas answer the commits API, each has exactly one parent, and
No wrong or unsupported anchor found. Form C's first preference, an ADR or ruling record: a grep of (3) Numbers. Over the 94 line pairs: 12 numbers appear on removed lines only ( (4) Line counts. From the file list, every one of the 17 modified files has additions equal to deletions (4/4, 1/1, 3/3, 1/1, 16/16, 1/1, 1/1, 2/2, 2/2, 17/17, 30/30, 1/1, 1/1, 1/1, 7/7, 2/2, 4/4; 94/94), and the diff's hunk headers agree. The 18th file is the new 10-line changeset. Right. (5) See ②. (6) Part of, and nothing left behind. Line 1 of the body is Check-runs on ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Part of #20594
Clause-②: no
What changed
This is stage 4 of the
domain:clilane of the dead-citation sweep:packages/types/src/**. Every comment or docblock site in scope that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on #19123), the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided. PR #20533 is the method; PR #20624 (runtime), PR #20632 (rest) and PR #20656 (cli) are the landed stages this follows. The card stays open for the form-D stage and the rest of the lane, so this PR saysPart of.That is 83 comment sites on 83 lines in 17 files, covering 12 numbers: the census's 52 (all of them) and 31 more in test comments, which the census defers. Each rewritten line cites one of 12 distinct commits. No ADR or ruling-record file records any of these twelve decisions, so every anchor is a commit.
Only comments changed. Every touched file keeps its line count (94 lines out, 94 in, over 17 files), so no line citation into these files moves. Eleven of the 94 lines held no dead site; each is the other half of a sentence that had to change:
thrown-http-error.ts:316-319,node.ts:1103,:1429,:1447,:1452,:1476, andnode.test.ts:449,:2420(see "Wordings to check").No citation number is added. Over the 94 line pairs, every tracker number on an added line was already on the line it replaces (per-pair check: 0 added), and no PR number stands on an added line. No code token moves (see the guard below). No site was left: no dead comment site in scope lacked a deciding commit, and no open PR touches
packages/types/src.One file outside
packages/types/src: apatchchangeset for@objectstack/types, in PR #20632's form and level.Census:
packages/types, before and afterInstrument. The gate's own
node scripts/check-issue-citations.mjs --census --json, read-only and unchanged, run with the fleet token. Its surface is comment prose inpackages/**/src/**/*.tswith string literals blanked, and it defers*.test.ts. The count is itsallocated-but-absentfindings underpackages/types/. Both runs enumerated the whole board (185 pages), so neither read a truncated board.allocated-but-absent6bff748bbd, run 2026-09-29T15:31:59Z to 15:41:36Z686a4c60cb, run 2026-09-29T16:04:17Z to 16:12:39ZThe before count equals the card's 52 at
f11b5f20a2: no drift. The whole-repo drop is 52, exactly this diff's 52 sites, and the whole-repo resolving count rises by one (32,882 to 32,883): the live #12751 thatindex.ts:4now spells so the grammar reads it. Both runs read this worktree, the base and then the base plus this one commit, so no other change entered either count.Supplementary instrument, the whole scope. The census does not read test files or strings, and this stage's scope includes test comments. So a second reading runs the gate's own exported
extractCitations(whole-file and comment-prose projections) andclassifyCitationover every.tsfile underpackages/types/src(42 files), against a board from the gate's ownprobeBoard. The lit controls #20594, #19123 and #20656 answered 200 and are on both boards; the dead controls #11671, #10514 and #14828 answered 404 and are on neither.6bff748bbd686a4c60cbIts src-comment column equals the census's 52, site for site (the two site lists are identical), which is the control on the second instrument. The drop of 82 citations is the 83 dead sites removed plus one live number the grammar now reads:
index.ts:4spelled[#11343/#12751], whose second half the grammar skips after a slash, and now reads[commit c0714eb5d / #12751]like its module doc, so the live #12751 is judged (resolving src comments 273 to 274). Resolving pull requests (20), cross-repo citations (14) and the other resolving counts are unchanged. A separate scan for slash-joined pairs inpackages/types/srcfound six (#11343/#12751,#3878/#3899,#7525/#8016,#4728/#4825,#8621/#8622,#5352/#5367); every second half answers 200, so no dead number hid behind a slash here.Per-number table
Sites and files are the dead comment sites in scope at the base, test sites counted in brackets.
strings keptcounts string-literal sites, which are tokens and stay as they were. Every anchor was read in its message or its diff, not only its subject: it is the commit that made the change the line describes.#88248ac232306#993479c46da90#1094346d34ab7c#10944e598b1cbc#11343c0714eb5d#122810783d7b80#1319756c093c4d#132796a180e42d#133244cda78c9b#15044088f761e5#15045288fe9c34#166575a95b0e93Every cited sha matches exactly one object (
git rev-parse --disambiguate, count 1 for each of the 12), is a commit, has one parent, and is an ancestor of the base (merge-base --is-ancestor, exit 0 for all 12). The checkout is not shallow (--is-shallow-repositoryfalse); the control legf5a9bc2f3(2026-08-10, older than the oldest anchor,8ac232306of 2026-08-15) exits 0 and the negative control (this branch's own686a4c60cb, not onmain) exits 1.Anchors reused from earlier stages, so each number carries one anchor across the tree:
79c46da90for #9934 (stages 1 and 2, the spec lane),46d34ab7cfor #10943,e598b1cbcfor #10944 and288fe9c34for #15045 (stage 3),0783d7b80for #12281 (stage 1),56c093c4dfor #13197 (stage 2, the spec lane),6a180e42dfor #13279 (stages 1 and 2,plugin-sharing) andc0714eb5dfor #11343 (plugin-auth).New anchors, and how each was found:
#8824→8ac232306: docs(types): correct error-leak.ts's false MySQL dialect claim, and pin the uncovered dialect #8824 is that commit's own PR number (its subject ends(#8824)), so the sha is the object the number named.error-leak.test.ts:180read 「PR docs(types): correct error-leak.ts's false MySQL dialect claim, and pin the uncovered dialect #8824 corrected the」 and now reads 「Commit 8ac2323 corrected the」.#13324→4cda78c9b: its subject does not name the number, but its changeset heading does (「require a missing-table error to name the table that was READ (isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324)」), and its diff addsreadObjectand every[#13324]marker this module carries. It landed inpackages/metadata/src/utils/schema-sync-errors.ts, the file6a180e42dthen moved here (a rename at 86 percent similarity).#15044→088f761e5: 「Part ofpackageRootOfmatches the declaration KEY, so an aliased dual-published package silently loads itsrequirebuild on the succeeding (#13330) path #15044」, the only commit whose message names the number; it made the cli: serve's cluster-driver load registers into the CJS registry while the ESM Runtime reads the ESM one — OS_CLUSTER_DRIVER=redis silently downgrades to "not registered" (post-#10645) #13330 succeeding leg recognise the package root by the name the declaration promises, and added theBOUNDARYpin atnode.test.ts:1863that:2175and:2419point at.#16657→5a95b0e93: it addedoperatorFacingErrorText,DECLARED_DATABASE_FAULT_CODEand the raw-path fragment, and its message calls itself the fourth prose round on Raw-exec consumers that surfaceerror.messageas an operator-facingdetailnow read the composed DATABASE_ERROR sentence — readcausethere (follow-up to #16019) #16657.Wordings to check
thrown-http-error.ts:315-320said runtime: a declared 5xx carrying NOcodekeeps its prose on/analytics/querywhere/datawithholds it unconditionally #12281 「is a separate card with its own measurement-first step, so nothing here applies it; this function is the shape it will read」.a81aa9dd5wrote that on 2026-08-29;0783d7b80landed the next day and its message says 「the door now readsserverFaultProvenance」. Citing the commit in the future tense would contradict itself, so the six lines now read 「Commit 0783d7b — the prose axis of the same 2026-08-27 ruling — reads the'declared'limb of this same function … It landed separately, after its own measurement-first step, so nothing here applies it; this function is the shape it reads rather than a second copy it would have had to grow.」node.ts:1447-1452called where a relative specifier should resolve from 「an open policy question owned by A relativeplugins: ['./local-plugin.js']entry resolves against the CLI's own directory, so an app-relative plugin path can never work #10944」 and ended with 「Answering half of another card's undecided question」.e598b1cbc(A relativeplugins: ['./local-plugin.js']entry resolves against the CLI's own directory, so an app-relative plugin path can never work #10944's landing) had merged 40 minutes before46d34ab7cwrote those lines, and it refuses the relative spelling. The lines now read 「the policy question commit e598b1c settled forserve(it refuses a relativeplugins: [...]entry rather than silently re-basing it)」 and 「Answering half of another change's question」.node.ts:1102-1103「Alink:/file:install whose manifest name differs from the key still keeps the wrong INSTALL wording — the location-carrying sub-case #14278 could not reach #15045 is the card about telling an operator which one was measured」 now reads 「commit 288fe9c is the change that tells an operator which one was measured」.node.ts:1476「the second verification axis the card holds open」 now reads 「the second verification axis that commit left unbuilt」, which is what288fe9c34's message says (「deliberately not built here」).node.test.ts:449「The card's own 4-row matrix」 now reads 「The 4-row matrix behind that commit」.node.test.ts:1566reads 「Fixed by commit 088f761: the SUCCEEDING leg recognised the package by the DECLARATION KEY」 and:1881reads 「Reworded by commit 288fe9c: the location sub-case REFUSES correctly and EXPLAINED itself wrongly」 (288fe9c34changed the wording and kept the refusal). The dash-rule headings trim trailing dashes:node.ts:1381,node.test.ts:1566.node.test.ts:2160quoted 「Alink:/file:install whose manifest name differs from the key still keeps the wrong INSTALL wording — the location-carrying sub-case #14278 could not reach #15045's triage」; it now reads 「quoted from the triage commit 288fe9c landed」. That commit's changeset records the same decision in its own words: the key stays the expectation 「because widening it would accept any directory sitting at the key and trade a wrong REMEDY for a wrong LOAD」.node.test.ts:2053said Alink:/file:install whose manifest name differs from the key still keeps the wrong INSTALL wording — the location-carrying sub-case #14278 could not reach #15045 「asked for this sentence」; it now says288fe9c34「wrote this sentence」, and that commit's own test comment says the card asked for it.driver-error-classification.callers.test.ts:24-25said the omission is the shape 「isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324 existed to close」 and that prose 「is exactly what isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324 proved insufficient」; it now reads 「the … shape commit 4cda78c closed」 and 「prose is exactly what that commit's defect proved insufficient」.driver-error-classification.ts:608andnode.ts:1428, pluscallers.test.ts:20andnode.test.ts:594) now say 「before commit X」.Mechanical guard: no code token moves
The check compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, JSDoc nodes excluded, comments being trivia) of each touched file at base
6bff748bbdagainst the working tree at686a4c60cb, over all 17 touched files, and lists EVERY differing token, not only the first. Controls mutate the head text in memory only, so nothing on disk moved for them.node.ts): 0 differing tokens (exit 0).node.ts): the count differs and a difference appears at token 0 (exit 1).undeclaredMessageliteral atnode.ts:383): exactly 1 differing token, aStringLiteralat token 672 (exit 1).So H2 holds by the token guard. The emitted
distis not byte-identical, because the docblocks ship, which is why the changeset ispatch. Line balance: every touched file is +N/−N and every line count is equal at base and head (17 files). A raw scan of the 18 changed files for control bytes finds none (its positive control, a scratch file holding a U+0001 byte, matches).Changeset
This change ships bytes, so a
patchchangeset for@objectstack/typesis included, in PR #20632's form and level: 「Comments only: no error code, refusal text, type, export or runtime behaviour changes.」Measured on the built package:
files[]isdist,README.mdandCHANGELOG.md. After the build, the rewritten docblocks reachdist:0783d7b80,79c46da90,5a95b0e93andc0714eb5dare indist/index.d.tsandindex.d.mts,4cda78c9bin all fourindexfiles,6a180e42dinindex.jsandindex.mjs, and46d34ab7cand288fe9c34indist/node.d.tsandnode.d.mts. The positive control, the unchanged sentence 「sanitisation REGIME is the condition, not one of its two outcomes」 of the0783d7b80docblock, is indist/index.d.tsbeside it; a negative control phrase appears nowhere. Of the twelve dead numbers, only #10943 remains indist, twice, and both are the kept operator-facing string atnode.ts:383(see Acceptance notes).Gates (head
686a4c60cb)This host has no
flock, soos-verify-lock.shran in its declared unlocked mode. Its disclosure, verbatim, from each locked run at this head:origin/maindid not move after the branch was cut:git merge origin/mainanswered 「Already up to date」 at6bff748bbd, so the base is the merge base and nothing needed rebuilding.origin/mainhas since moved to6c11ef9ecb(PR #20663: two pages undercontent/docs/automation, read 16:13Z). It touches nothing this diff or its gates read, so the branch was not merged again and every reading here stays at686a4c60cb.@objectstack/types...:specthentypes) and then the whole workspace (71 tasks, 71 successful).check-dts-emittedfinds 2 of 2 declared declaration files. The build left the tree clean.--project local: 22 files, 685 tests pass.--project repo: 1 file (driver-error-classification.callers.test.ts, touched here), 7 tests pass. 22 + 1 is all 23 test files in the package, so every touched test file ran.pnpm --filter @objectstack/types typecheckexits 0.tsc --listFilescounts 42srcfiles undertsconfig.json, all 23 test files among them, so every touched test file is type-checked.pnpm lint(eslint . --no-inline-config) exits 0 at686a4c60cb(2026-09-29T16:01:23Z to 16:02:09Z). Not narrowed.node scripts/check-issue-citations.mjs --base origin/mainexits 0: 5 citations judged across 7 files (4 resolve, 1 cross-repo). These are the live numbers that stay on rewritten non-test lines. It defers*.test.ts, so the per-pair count over the whole diff covers the rest: 0 numbers added.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsat686a4c60cbderived 61 families. All 61 ran and exit 0, and--ranover a record carrying each exit code reads 「61 derived, 61 run, 0 NOT-MEASURED, 0 UNRUN」 (a derived zero). Among them:check:doc-authoring,check:nul-bytes,check:issue-citations(self-test),check:published-files,check:dts-closure,check:dual-build-cjs-loads,check:type-check-coverageandcheck:type-check-debt.686a4c60cb, the four whose rosters share a directory with this diff among them (check-changeset-fixed,check:authz-resolver,check:error-code-casing,check:filter-alias-parity). The other three,check-closing-target-claim,check-partof-closing-keywordandcheck-single-claim-paths, need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 checker-health-only rows were not run.Hypotheses (measured first)
6bff748bbd(52 lines, 7 files, 11 numbers), equal to the card's count atf11b5f20a2: no drift.packages/types/. No site is left for an open PR or an unfound anchor: the claim's read and this stage's read of the open PRs' file lists (15:40:08Z, 7 open PRs) found none touchingpackages/types/src(the Version Packages PR touches onlypackages/types/CHANGELOG.mdandpackage.json). A second read before this PR was opened (16:13:18Z, 11 open PRs) found the same.Acceptance notes
undeclaredMessagenote atnode.ts:383, 「a caller that needs its own resolution passes{ fallbackImport: (s) => import(s) },createHostImporter's undeclared fallback resolves from@objectstack/types, not from the calling package — its documented contract says otherwise #10943)」, printed when the host importer's undeclared fallback fails without a caller base. It is also the only dead number left indist. The comments around it (node.ts:368,:1381,:1428) now cite46d34ab7c. Ruling D (no number, the lesson in words) is a string change outside this comment-only stage; the card already carries a form-D stage for the lane (ACCEPT 5888034755), and this string is its author-shown first inpackages/types. A second one is a remedy an author reads: theREMEDYtext atcallers.test.ts:281, which that gate test prints for any call site that omitsreadObject(「Without it the predicate returns the pre-isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324 WIDE verdict」).packages/typesoutsidesrc/**holds one dead citation:vitest.config.ts:25cites [finding] vitest 的 --project 过滤器落空即静默成功 —— 点名一个 integration 文件跑 --project unit,报它是通过的文件、执行零个用例,并把它从文件计数里减掉 #17853 (404), the same number PR docs(runtime): re-anchor the dead tracker citations in packages/runtime/src to the commits that decided them #20624 and PR docs(rest): re-anchor the dead tracker citations in packages/rest/src to the commits that decided them #20632 reported in their packages'vitest.config.ts. The six other citations outsidesrc/**(CHANGELOG.mdexcluded) resolve. It stays for a later stage of this card.Deviations
thrown-http-error.ts:315-320move from the future tense to the present, because the claim they carried stopped being true when0783d7b80landed (see Wordings to check).Claude-SessionplusCo-authored-by: Claude), and the pre-push trailer check passed on every push; the harness's attribution reminder asked for a model-named trailer and a different PR footer, which AGENTS.md overrides.Generated by Claude Code