docs(metadata-protocol): re-anchor the dead tracker citations to the commits and ADR that decided them - #21233
Conversation
…ns to the commits that decided them Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude <noreply@anthropic.com>
…er citations to the commits that decided them Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude <noreply@anthropic.com>
…ions to the commits that decided them Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude <noreply@anthropic.com>
…patch) Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 15 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 11 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 9dc377977ea989154a4fdf4d6a9538eb32a38b7b && git checkout 9dc377977ea989154a4fdf4d6a9538eb32a38b7b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 3ddd3d0c4a355b58d074245ae6732ac91489c2a7 3265b142f09d14f46901728b80b5cff445c97f61 && git checkout -B drift-repro 3ddd3d0c4a355b58d074245ae6732ac91489c2a7 && git merge --no-ff 3265b142f09d14f46901728b80b5cff445c97f61
node scripts/docs-audit/affected-docs.mjs --json 3ddd3d0c4a355b58d074245ae6732ac91489c2a7
|
Contract reviewServed-tier: Inputs read, and nothing else: card #20595 (body and all five comments: the two lane pointers, the post-landing census ① Derived judgmentsDiff of record. GitHub's diff for #21233 (55 files, +295/-280, 236 hunks) is byte-equal, Accept set and public surface: nothing moves. Judged RIGHT, on this reading of the diff text: every Sampled hunks, 18 pairs across 12 files, each read as its Anchors. All 56 shas in the per-number table (54 distinct: The ADR anchor (#13185 to ADR-0005). The #11674 split. On the two commits' own diffs: No new tracker number; live numbers stayed. For every pair, the numbers on the Rewritten sentences stay true. Each sentence that credits a commit with a ruling, a measurement or a note was matched against that commit's message: Reach into ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Part of #20595
Clause-②: no
What changed
Stage 1 of the
domain:enginelane of the dead-citation sweep:packages/metadata-protocol/**, comment and docblock prose only, per the claim (5938223120). The next stages (objectql,driver-sql,driver-memory, then the rest) are separate claims, so #20595 remains open.Every comment or docblock site in the package that cited a tracker number answering 404 is rewritten in ruling C+D's form C (record
5749154545on #19123): the ADR or ruling record when one exists, otherwise the commit in this repository's history that made the decision the sentence describes. That is 293 sites on 279 lines in 54 files, covering 56 numbers:src/): the wholeallocated-but-absentpopulation of the gate's own census in this package at the base;tsup.config.ts(:15,#11235): same number, outside the census glob but inside the claimed file surface;#10485and#8600are dead elsewhere in the repository).Anchors: 55 numbers by commit sha, 1 by ADR (
#13185, ADR-0005's design-principle-3 correction), 0 by words alone.#11674is split across two commits, one per half of what it named (see the table). Two#12176sites (protocol.item-name-grammar.test.ts:6,:12) drop the number without a new citation, because line:4of the same docblock now cites the commit (311433f6b) that both sentences describe.Only comments changed. Every file keeps its line count (280 lines out, 280 in, plus the changeset), so no line citation into any of them moves. No code token moves (the guard below). No citation number is added: every number on an added line already stood on its line, and 20 of those 23 are live by the census's own judgement. Of the 3 it never reads (they stand only in test files),
#11099and#8390answer as pull requests and#14767answers 404 (see Sites left).A
patchchangeset: 52 of the rewritten non-test lines are in the publisheddist(the.d.tskeeps JSDoc on exported members, and esbuild keeps a few comments in the JS), anddistis not byte-identical with the base text (see Changeset).Census:
metadata-protocol, before and afterInstrument (A1). The gate's own
node scripts/check-issue-citations.mjs --census --json, read-only and unchanged (it carries #20989's wider extractor, mergea5bce40888, an ancestor of the base). The count is itsallocated-but-absentfindings underpackages/metadata-protocol/.allocated-but-absente47355be5, run ended 18:52:32Z06d41e512, run 19:21:20Z to 19:25:08ZThe whole-repo drop is 163, and the two finding sets differ by exactly the 163 rows of this package, removed; none was added.
resolves(34,516),resolves-as-pull-request(2,092) andcross-repo-unjudged(1,139) did not move. The card's 162 was taken atf11b5f20a2with the older extractor; the base here reads 163, which includes the slash-joinedpartial-index-probe.ts:395#16657that the post-landing census (5923084795) named. The only commit after06d41e512adds the changeset file, which is outside the census surface.Supplementary instrument, the whole package. The census reads neither test files nor strings nor files outside
src. A second reading runs the gate's own exportedextractCitations(whole-file and comment-prose projections) andnamesThisRepositoryover every tracked file in the package (235.ts, 2.md, 2.json). A number is dead when the before census reported itallocated-but-absent, and live when the census's own scope extraction judged it and did not report it. The 82 numbers neither covers (they stand only in test files, strings or the changelog) were each read on their own (issues endpoint, which also answers pull requests): 27 issues, 38 pull requests, 17 answer 404. Controls:#10888,#11674and#16657(the card's and the census's named sites) answer 404,#5286and#12624answer 200.e47355be5src commenthere includestsup.config.ts. Its before value is the census's 163 plus that one site, which is the control on the second instrument. The drop of 293 citations is exactly the rewritten sites. A third, raw reading (every#followed by 2 to 6 digits, whatever surrounds it) counts 6,479 before and 6,186 after: the same drop of 293. The 22 test-comment sites left all carry numbers outside the census's surface (see Sites left).Per-number table
srccounts census sites (plustsup.config.tsfor#11235),testcounts test-comment sites. Every sha below matches exactly one commit (git rev-parse --disambiguate, count 1) and is an ancestor of the base (git merge-base --is-ancestor, exit 0 for all 56; the clone was unshallowed first,--is-shallow-repositoryfalse, 15,415 commits at the base). Each one's message or diff names the number it replaces (diff counts are the added lines naming it), and for every sentence that credits a ruling, a measurement or a note to the number, the commit's own message carries that ruling, measurement or note:ee58392e1(the 2026-08-08 three-part ruling),c74aefe63(ruling 2026-08-22, option A),65846bc46(ruling A, 2026-09-03),75e66fc8e(Option B, diff raw then redact),96326040f(the idempotence proof the direction-A ruling was conditional on),8744de9e9(the second-rung ablation),82cb6e849(the two faces left open),376c70f98(the measuredshims: trueconsequence). The one exception is2a29caa53(#9741): its message records the decision itself (environmentIdrecorded as transport-level) but not the 2026-08-18 ruling, so that site keeps its own date and now reads 「recorded 2026-08-18, landed as commit 2a29caa」. 37 of the 56 numbers were already re-anchored by other lanes' stages, and for every one of them this stage uses a commit those stages used (none differs;#11674adds9a884c6e4beside their1cba33f16, because 25 of its 32 sites here describe the write-back half, whichgit blameputs in9a884c6e4). The other 19 had no prior anchor and were measured here.#603718189983d#6307293476148?version=onGET/DELETE /packages/:idinstead of handing the array to PackageService#6478474f131cfflow'sallowOrgOverrideback tofalseper ADR-0005's original call, the write path refusing loudly#6483ee58392e1allowOrgOverride: trueflags rolled back tofalse; its message records the 2026-08-08 three-part maintainer ruling it executes#6608ee58392e1#6608was the pull request whose squash it is#8600018d22cc3#8648e5eeb499c#867175e66fc8e#8818fd6bdf89f#974011b779e0f#97412a29caa53#9798c7655d472#9817855591fe7#993479c46da90#99678f266f1cd#100639e04c3e35#101591ec36b730#1034026f3588fb#10350490879ad0packageIdonpublishMetaItem's request type, and correct three comments that say the per-item door names no package#10382ee09d2119#1048535ad101bcthemescarrier key and ThemeSchema —app.brandingis the one colour surface#107883a7ec2d3b#1078938bc74ed1#10842f334d662e#10886809e61221#10888d806081dd#10895a79bd3561#11003c74aefe63#110142d8b92ff1objectalone#1101582cb6e849?force=trueon the duplicate door#110217d81c889f#11235376c70f98versioninstead of the hardcoded'1.0'literal#11350ece4dad31#116749a884c6e4+1cba33f16#121443a04b0125#12176311433f6b#12194311433f6b#121957986d973f:sectionarities and unify SDK URL spelling#131859e0ba21a1)#131869e0ba21a1#132592a75270b1hiddenon getUiView's list priority pass#133244cda78c9b#143909d7f7259fupdateanswers a driver unique violation with theDUPLICATE_RECORDenvelope, on every driver#1440393d2d679b#144093ecb7dc1a#145416d178a408#1468396326040f#1472365846bc46UNIQUE_VIOLATION, the route's one wire spelling#14770d5cbb44f3getMetaItem's overlay read on the metadata registry#14907e1d4f9e3fgetMetaItemLayeredgates the org read, bound after the canonical fold#14938c383352cb#150688744de9e9#16488460d4b807#166575a95b0e93causefor operator-facing records#17167dc709b2cf#19306f9e16d856#13185: the ADR rung is not empty there. ADR-0005's design principle 3 carries a dated Correction that records the 2026-08-29 retirement of the field-level patch model, so ruling C's first rung applies.protocol.ts:8618already names that record on the same line (「recorded as a correction inside principle 3 itself」), so there the number is dropped besidecommit 9e0ba21a1.get-meta-item-org-read-gate.test.ts:40now names it (「ADR-0005 principle 3's correction」). For the other 55 numbers,git grepoverdocs/adrandscripts/adr-anchorsfinds no ADR or anchor that records the decision a site describes. ADR-0094 D5-R and ADR-0086 mention the#6483rollback, but only as a pointer to it; the narrative and the ruling are inee58392e1's message. So ruling C's commit rung applies.Wordings to check
Most rewrites swap a tag in place (
(#N)to(commit SHA),[#N]to[commit SHA],#N's Xtocommit SHA's X), the form the landed stages use. These are the ones that say more than the tag:protocol.ts:5697: 「(The #4630 unscoped multi-write refusals on sys_comment never fire through the wired engine — per-row dispatch bypasses resolveTargetRows on both verbs #9798 declared-but-unenforced, …」 became 「(commit c7655d4 restored a declared-but-unenforced refusal, …」. The number named an instance of the class, and that commit is the one that restored it.protocol.ts:8590: 「the resurrection Where does the allowOrgOverride read gate belong for metadata sweeps that read MORE THAN ONE type per request?getMetaItemsapplies none of its own #14683 is about」 became 「the resurrection commit 9632604 closed」.protocol.ts:16640: 「measured on the Ban/in metadata item names — retire compound-name addressing (maintainer-ruled direction): census, migration surface, staged plan #12176 census before this landed」 became 「measured before this landed (the census commit 311433f records)」. The census results are written into that commit's test-file header.migrations/seed-tenancy-backfill.ts:964: 「Measured; recorded separately as SettingsService accepts a write before its engine is bound and answers "resolved" while nothing reaches sys_setting — everykernel:readyhook registered frominit()is inside that window #10159.」 became 「Measured; recorded separately, and refused since commit 1ec36b7.」 That commit refuses the settings write that answered "resolved" while persisting nothing.discovery-version.ts:26: 「considered and declined at [finding] a THIRD hardcoded discoveryversionliteral —getDiscovery()inpackages/metadata-protocol/src/protocol.ts, identical defect to #10993, different producer/package #11235 triage」 became 「considered and declined when the derivation landed (commit 376c70f)」. The triage discussion is not recorded in-repo. The commit is where the package-local resolver was chosen, and its message records why: the dependency direction forbids importing runtime's.seed-loader-pointer-pair.test.ts:871: 「— Seed pass-2 deferral is structurally unreachable for a KEYLESS dataset — so a declared pointer pair on an engine-owned object is order-dependent #11674's B half, ruled by triage…」 became 「— commit 1cba33f, the B half, ruled by triage…」.protocol-publish-drafts-package-scope.test.ts:400is the one changed line that carried no number. 「option A (recorded on the issue)」 became 「option A (recorded in that commit's message)」, because the issue it pointed at was the number removed on:399, andc74aefe63's message does record the ruling.sys-metadata-repository.contract.test.ts:187quotes a deleted line, 「declaredDivergences: { resumableWatch: '#10842' }」. The quoted value is elided to 「…」 rather than re-spelled, so the quote stays true.protocol.item-name-grammar.test.ts:6and:12: the number is dropped and nothing is substituted, since:4cites311433f6b.eslint.config.mjsdeclares no line-length rule, and reflowing would move neighbouring lines and every line citation into the file).Sites left
srccomments andtsup.config.ts: none.#6287,#10058,#10064(2),#10420,#10978(2),#11017,#13214,#13244,#13258,#14389,#14431(5),#14767,#17621(4).#14767stands on a line this PR rewrote (get-meta-item-org-read-gate.test.ts:10): it is the pull-request number of96326040f's squash, kept beside the new anchor as it stood.ittitles, assertion arguments) carry dead numbers: 56 with census-dead numbers (#121946,#107895,#108865,#110144,#116744,#164884, and 20 more numbers once to three times) and 7 with#17621. Non-test source strings carry none. Strings are outside this stage's file surface.src: the release-ownedCHANGELOG.mdnames dead numbers on 56 sites (45 census-dead, 11 among the 404 reads); left.README.md,package.jsonandtsconfig.jsonname no number;vitest.config.ts's two are live.Mechanical guard: no code token moves
The guard compares, base
e47355be5against the working tree, over all 54 touched.tsfiles:forEachChildwalk. Comments are trivia there, and JSDoc is never visited.getChildrenwalk. Punctuation and keywords are included and JSDoc nodes are skipped. String, template and numeric literals are compared in full on both readings.Results:
protocol.ts:13): 0 files changed (exit 0).postureEnforcesWalltopostureEnforcesWallXinprotocol.ts's import): DIFFER in both readings (exit 1).'dashboard'to'dashboardX'insys-metadata-repository.contract.test.ts): DIFFER in both readings (exit 1).BULK_BATCH_SIZE = 200to201inseed-loader.ts): DIFFER in both readings (exit 1).Every mutation went through
scripts/ablation-replace.mjs(wrap mode) under a shell trap that restores by absolute path fromHEAD. Each landed: anchor count 1 to 0, blob changed. Each restore was proven equal to itsHEADblob (5be50ab59075,99ef73ef7562,41b999ca3ecc), withgit diff HEADempty and a clean tree afterwards.Changeset:
patch(distmeasured)files[]isdist,README.mdandCHANGELOG.md, and the package is not private. The dependency closure was built first (turbo run build --filter='@objectstack/metadata-protocol^...', 12 tasks). Then the package's ownbuild(tsup pluscheck-dts-emitted) ran three times under the shared verify lock:distfiles hashed. Of the 154 rewritten non-test lines, 52 appear verbatim indist: 36 fromprotocol.ts, 7 fromsys-metadata-repository.ts, 5 fromseed-loader.tsand 4 frommigrations/seed-tenancy-backfill.ts. Most are inindex.d.ts/index.d.cts; two fromseed-tenancy-backfill.tsare inindex.js/index.cjs, where esbuild keeps a comment inside an expression.index.d.ts,index.d.cts,index.jsandindex.cjsdiffer from leg 1, and so do the content-hashed chunk names, including the seed-loader chunks.So the rewrite ships, and
.changeset/20595-metadata-protocol-provenance-anchors.mddeclares apatchfor@objectstack/metadata-protocol, comment text only, with the claim'sClause-②: noline.Gates (head
3265b142f)node scripts/check-issue-citations.mjsexits 0 (「every citation this change adds resolves」, 19 citations judged across 8 files).pnpm check:issue-citationsexits 0 (self-test, 173 cases, 9 batteries).pnpm check:doc-authoringexits 0 (17,085 spec strings clean; the sibling-package prose-id baseline holds, no growth).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsat3265b142f(change set derived from git: 55 paths against merge basee47355be5) derived 62 commands. All 62 ran, each with its exit code captured before any pipe, and all 62 exit 0.--ranreports 62 derived, 62 run, 0 NOT-MEASURED (a derived zero), 0 unrun, and exits 0. A fullturbo run buildover./packages/*and./packages/*/*ran first under the shared verify lock (71 of 71 tasks), so no gate hit an unbuilt workspace.node scripts/check-changeset-fixed.mjs,pnpm check:authz-resolverandpnpm check:error-code-casing. Each exits 0.3265b142f:pnpm --filter @objectstack/metadata-protocol test: 200 test files pass and 3 skip (203); 2,973 tests pass and 19 skip.pnpm --filter @objectstack/metadata-protocol typecheckexits 0, andtsc --noEmit --listFilesputs all 203 tracked test files in the program (233 package files)..tsfiles plusdist/index.jsas the control, gives 55 results, 0 errors and 1 warning: the control's ignore notice. Its--format jsonoutput reports none of the 54 ignored.eslint.config.mjsnever enables type-aware linting (its lines 327-328 say so), so a comment edit cannot move the verdict on any untouched file. The repo-widepnpm lintis CI's run.pnpm check:nul-bytesexits 0, and a raw scan of the 55 changed files for control bytes finds none.Acceptance notes
mainate47355be5.mainhas since moved five commits (to62b90d74f), anddispatch-gatesflags that as a stale tree. None of the five touches a file in this diff,scripts/check-issue-citations.mjsorscripts/pm/dispatch-gates.mjs. One editsprotocol.meta-types-degenerate-derivation.test.tsin this package, adding a citation beside a live one. The one derivation input that moved,scripts/doc-authoring-prose-id.baseline.json, lost 63 lines, none of them naming this package. No merge was taken; the merge queue rebuilds on the merged generation.comment 5299845282stands twice in this package (protocol.ts:22793,protocol.diff-credential-redaction.test.ts:19) and names a comment on the deleted#8671, so it no longer resolves either. Neither instrument reads it, and75e66fc8e, now cited beside it, carries the ruling's text in its message. Left as it is.protocol-publish-drafts-package-scope.test.ts:400.forEachChildwalk above, and every figure in the guard section is from the replacement.Generated by Claude Code