Repository navigation
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 |
…ment-id citations in test comments (stage 2 of objectstack-ai#20595) (objectstack-ai#21246) Part of objectstack-ai#20595 Clause-②: no ## What changed Stage 2 of the `domain:engine` lane of the dead-citation sweep: the `packages/metadata-protocol` remainder that stage 1 (PR objectstack-ai#21233, landed as `a7d9768ec`) left, per the claim (`5940298570`). Comment and docblock prose only. objectstack-ai#20595 stays open for the next stages (`objectql` next). The population is what stage 1's contract review (`5939794396`) escalated to this sub-stage: - the **22 test-comment sites carrying 13 numbers that answer 404**, which the census never reads (it defers test files); - the **dead comment-id citation** `comment 5299845282`, on two lines; - the **dead convenience number** `PR objectstack-ai#14767` beside its anchor `96326040f`. Each is rewritten in ruling C+D's form C (record `5749154545` on objectstack-ai#19123): the commit in this repository's history that made the decision the sentence describes. **23 lines in 16 files** (21 lines for the 22 numbered sites, 2 for the comment id). **Anchors: 13 numbers and the comment id, all by commit sha; 0 by ADR or ruling record (none exists for any of them); 0 by words alone.** Seven numbers reuse the commit another lane already chose for them, `objectstack-ai#14767` and the comment id keep stage 1's commit already on their line, and five were measured here. Every file keeps its line count (+23 / -23). No code token moves (guard below). No citation number is added: the only numbers left on changed lines, `objectstack-ai#9612` and `objectstack-ai#13331`, stood there before and answer as issues. **No changeset, and `skip-changeset` is the declaration:** 22 of the 23 lines are in test files, which the `tsup` entry graph never reaches, and the one `protocol.ts` line is a `//` comment inside a method body that the build drops. Measured, not assumed (see Changeset). ## Population, before and after **H1, re-enumerated on `origin/main` (`a7d9768ec`).** The instrument is the gate's own code, read-only. `extractCitations` from `scripts/check-issue-citations.mjs` runs over every tracked file in the package (239), in both projections (whole file and comment prose), keeping the citations `namesThisRepository` assigns to this board. `classifyCitation` judges each one against a board read by the gate's own `enumerateBoard`: 191 pages, frontier objectstack-ai#21241, 19,062 records, read 20:54:38Z to 20:58:19Z on 2026-10-01. Then one REST read per number: all 13 answer **404**, and the lit controls `objectstack-ai#5286` and `objectstack-ai#12624` answer 200. | reading | tree | citations | dead | src comment | test comment | test string | changelog | |---|---|---|---|---|---|---|---| | before | base `a7d9768ec` | 6,092 | **141** | 0 | **22** | 63 | 56 | | after | head `16b5bf6c1` | 6,070 | **119** | 0 | **0** | 63 | 56 | - The before reading matches stage 1's own after reading (141: 0 / 22 / 63 / 56). - The drop of 22 citations is exactly the rewritten numbered sites. No live count moved: test comments resolve 1,586 and resolve-as-pull-request 111 at both. - **The count against the dispatch's 22 / 13: 22 sites, 13 numbers, on 21 lines.** One line carries two numbers. The lines are in **14** test files; the review counted 15. - Comment ids (10-digit, outside the citation grammar): 9 sites, 5 distinct ids at the base. Read one by one through the comments endpoint, `5299845282` answers **404** and the other four answer 200: `5302933802` (on objectstack-ai#8833), `5528370129` (objectstack-ai#13609), `5865708652` (objectstack-ai#20378) and `5875579209` (objectstack-ai#20451). The control `5940298570` (on objectstack-ai#20595) answers 200. After: 7 sites, 0 dead. ## Per-number table Every sha below resolves to exactly one commit (`git rev-parse --disambiguate`). Each is an ancestor of the base: `git merge-base --is-ancestor` exits 0 for all 14, on a full clone (`--is-shallow-repository` is false). Each one's message or diff names the number it replaces. `ADR`: `git grep` over `docs/adr` and `scripts/adr-anchors` names none of the 13 numbers or the comment id, so the ADR rung is empty for all of them. | number | sites | anchor | kind | named in | provenance | what it decided | |---|---|---|---|---|---|---| | `objectstack-ai#6287` | 1 | `84c86fb45` | commit | message (squash suffix) + diff | reused: runtime and spec lanes | `preview` / `trial` discovery folds declared, the fold table exhaustive over `EnvironmentType` | | `objectstack-ai#10058` | 1 | `6f5a44976` | commit | subject (the squash of that PR) | measured here | judge a package write against its own closure | | `objectstack-ai#10064` | 2 | `def0d3e63` | commit | message + diff | reused: lint lane | key publish-gate finding paths by name, not the private snapshot index | | `objectstack-ai#10420` | 1 | `05bc692e0` | commit | message + diff | measured here | run `SysMetadataRepository` through the shared repository contract suite (it adds this file) | | `objectstack-ai#10978` | 2 | `4c9780c7a` | commit | message + diff | reused: runtime lane | ObjectQL doubles enforce `limit` after the filter and by presence | | `objectstack-ai#11017` | 1 | `d806081dd` | commit | diff (it adds this file) | measured here | render the 422 findings clause per write face | | `objectstack-ai#13214` | 1 | `cc837dbfe` | commit | diff | reused: rest lane | require the resolved environment to belong to the caller at `GET /ui/view/:object/:type` | | `objectstack-ai#13244` | 1 | `889ec5b42` | commit | subject (squash) | reused: rest lane | measure identity resolution at `GET /ui/view/:object/:type` | | `objectstack-ai#13258` | 1 | `3d10755f0` | commit | subject (squash) | reused: rest lane | drive the tenancy axis of `GET /ui/view/:object/:type` (it adds the sibling harness) | | `objectstack-ai#14389` | 1 | `10220a7bf` | commit | diff | reused: rest lane | the 409 arm gated on the engine's envelope (name and code) | | `objectstack-ai#14431` | 5 | `a98b61b3e` | commit | subject (squash) | measured here | re-measure the deleted-datasource prolongation across replicas (it adds this file) | | `objectstack-ai#14767` | 1 | `96326040f` | commit | subject (squash) | stage 1's anchor, already on the line | the dead convenience number is dropped; the sha stays | | `objectstack-ai#17621` | 4 | `7e74af3df` | commit | message + diff | measured here | execute the read-probe PostgreSQL arm on a live server (it adds the live-postgres file) | | `comment 5299845282` | 2 | `75e66fc8e` | commit | message | stage 1's anchor, already beside both lines | its message records the ruling: diff raw, then redact (Option B) | Sentences that credit a commit with a finding, a ruling or a record were checked against that commit's own message: - `a98b61b3e` carries the finding all five `objectstack-ai#14431` sites describe: the bridge heals the registry, a read inside the residue window re-hydrates the deleted row, and the window is bounded only when no read lands in it. - `7e74af3df` records the no-coverage state: the PostgreSQL arm was pinned and run nowhere. - `6f5a44976` records the package-closure ruling. - `75e66fc8e` carries the Option B ruling. - `10220a7bf` records the name-and-code gate. - `4c9780c7a` records the after-the-filter, by-presence bound. - `d806081dd` records the per-face decision (silence keeps the full prose on the duplicate face) but not the ruling itself. So that site keeps the ruling's own date and now reads 「landed as」. This is stage 1's precedent for `objectstack-ai#9741` and `2a29caa53`. ## Wordings to check Most rewrites swap the tag in place, as the landed stages do: `(#N)` becomes `(commit SHA)`, `[#N]` becomes `[commit SHA]`, and `PR #N` becomes `commit SHA`. These say more than the tag: - `protocol.invalid-metadata-422-face-inventory.test.ts:22`: 「The maintainer ruling on objectstack-ai#11017 (2026-08-22, option D) resolved it by」 became 「The maintainer ruling of 2026-08-22 (option D, landed as commit d806081) resolved it by」. - `protocol.ui-view-hidden-columns.test.ts:46`: 「(objectstack-ai#13214 / PR objectstack-ai#13258) drives the same defect」 became 「(commit 3d10755, for the card commit cc837db fixed) drives the same defect」. Line `:47` says 「It belongs to that card」, and this wording keeps an antecedent for it. - `protocol.batch-row-http-status.test.ts:546`: 「(objectstack-ai#14389 §5)」 became 「(commit 10220a7)」. The `§5` named a section of the deleted card's body, so it goes with the number. - `get-meta-item-org-read-gate.test.ts:10`: 「Commit 9632604 (PR objectstack-ai#14767) moved」 became 「Commit 9632604 moved」. Ruling C allows a PR number only as a convenience link, and a link that answers 404 is not one. - `protocol.ts:22793`: 「maintainer ruling (comment 5299845282), Option B.」 became 「maintainer ruling (recorded in that commit's message), Option B.」. The line above opens with `[commit 75e66fc]`. - `protocol.diff-credential-redaction.test.ts:19`: 「(maintainer ruling, issue comment 5299845282 — Option B)」 became 「(maintainer ruling, recorded in commit 75e66fc's message — Option B)」. - `migrations/seed-tenancy-backfill.live-postgres.test.ts:55` and `:256`: 「the no-coverage state objectstack-ai#17621 records」 became 「the no-coverage state commit 7e74af3 records」, and 「objectstack-ai#17621 exists because it was」 became 「commit 7e74af3 exists because it was」. - No line was reflowed, so some lines now run past their block's wrap. `eslint.config.mjs` declares no line-length rule, and a reflow would move neighbouring lines and every line citation into the file. ## Sites left in this package - **Dead tracker numbers in comment prose (src, tests and `tsup.config.ts`): none.** Dead comment ids: none. - **63 test-string sites** (`describe` / `it` titles and assertion arguments) are not edited. 56 carry census-dead numbers and 7 carry `objectstack-ai#17621`. They are recorded on objectstack-ai#20595, and the claim excludes string literals. - **`CHANGELOG.md`, 56 sites**, is release-owned and not edited. ## Mechanical guard: no code token moves The guard compares the base blob with the working tree for all 16 touched files, with TypeScript 6.0.3, on two readings: - **Reading 1:** the parser's leaf nodes, from a `forEachChild` walk. Comments are trivia there, and JSDoc is never visited. - **Reading 2:** the full token stream in parser context, from a `getChildren` walk, with JSDoc nodes skipped. String, template and numeric literals are compared in full on both readings. - **Real run at head `16b5bf6c1`:** 104,684 base tokens, **0 files with a token change** (exit 0). - **Controls,** each through `scripts/ablation-replace.mjs` in wrap mode, under a shell trap that restores by absolute path from `HEAD`: - comment (`bodies untouched` to `bodies UNTOUCHED`, `protocol.ts`): 0 files changed, exit 0; - identifier (`const issues` to `const issuesX`, `runtime-authoring-gate.dataset-writes.test.ts`): DIFFER on both readings, exit 1; - string (`'organization probe'` to `'organization probeX'`, live-postgres test): DIFFER on both, exit 1; - numeric (`WINDOWS_PROBED = 10` to `11`, prolongation test): DIFFER on both, exit 1. - **Each control landed:** anchor count went from 1 to 0 and the blob changed. Each restore equals its `HEAD` blob (`766d14add061`, `9c4bcfec727d`, `3457d6e431ed`, `9931944568bb`). `git diff HEAD` is empty and the tree is clean afterwards. ## Changeset: none, with `skip-changeset` (`dist` measured) `files[]` is `dist`, `README.md` and `CHANGELOG.md`. The `tsup` entry is `src/index.ts`, and no test file is in its graph. For the one non-test line (H3), the dependency closure was built first (`turbo run build --filter='@objectstack/metadata-protocol^...'`, 12 of 12 tasks). Then the package's own `build` ran four times under the shared verify lock, and each leg hashed all 24 `dist` files: | leg | state of `protocol.ts` | `dist` against leg 1 | |---|---|---| | 1 | head | (reference) | | 2 | the base text put back on `:22793`, blob `5be50ab59075` (stage 1's recorded head blob for this file) | **0 of 24 files differ**; the marker `comment 5299845282` is in no built file | | positive control | a docblock line on an exported member changed (`refusal is being` to `refusal is BEING`) | `index.d.ts` and `index.d.cts` differ; `ablation-dist-preflight` finds the marker in 2 built files | | 3 | head again | 0 of 24 differ (deterministic); `ablation-dist-preflight --absent` passes | So a comment change that ships is visible to this instrument, and this one does not ship. Restore proof: the `protocol.ts` blob equals `HEAD` (`766d14add061`), `git diff HEAD` is empty and the tree is clean. ## Gates (head `16b5bf6c1`) - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derives 55 commands for 16 paths against merge base `a7d9768ec`. All 55 ran, each exit captured before any pipe, and **all 55 exit 0**. `--ran`, given `COMMAND :: exit CODE` lines, reports 「55 derived, 55 run, 0 NOT-MEASURED, 0 UNRUN」, a derived zero, and exits 0. A full `turbo run build` over `./packages/*` and `./packages/*/*` ran first under the verify lock (71 of 71 tasks), so no gate read an unbuilt workspace. - **Named readings among them:** - `node scripts/check-issue-citations.mjs` exits 0: 「no issue citations added against a7d9768」. - `pnpm check:issue-citations` exits 0: self-test, 173 cases, 9 batteries. - `pnpm check:doc-authoring` exits 0, and the sibling-package prose-id baseline holds with no growth. - `pnpm check:nul-bytes` exits 0 (9,902 files). A raw control-byte scan of the 16 changed files finds none (grep exit 1). - **Tests and typecheck, under the verify lock:** - `pnpm --filter @objectstack/metadata-protocol test`: 200 test files pass and 3 skip (203); 2,973 tests pass and 19 skip. These are the same totals as stage 1's. - `pnpm --filter @objectstack/metadata-protocol typecheck` exits 0, and `tsc --noEmit --listFiles` puts all 203 tracked test files and all 16 changed files in the program. - **Lint, as a proven narrowing:** eslint runs with inline config off (`--format json`) over the 16 touched files plus `dist/index.js` as the control. It gives 17 results, 0 errors and 1 warning, the control's ignore notice, and none of the 16 is reported ignored. `eslint.config.mjs:327-328` states that no type-aware linting is enabled, so a comment edit cannot move the verdict on an untouched file. The repo-wide `pnpm lint` is CI's run. ## Acceptance notes - **Base.** The branch is on `main` at `a7d9768ec`, the stage 1 squash. `main` has moved two commits since (`1a4c7f826`, `ef96c9ede`). Neither touches this package, `scripts/check-issue-citations.mjs` or `scripts/pm/dispatch-gates.mjs`. No merge was taken; the merge queue rebuilds on the merged generation. - **File count.** The review recorded the 22 sites as 「21 lines in 15 test files」. Measured here: 21 lines in 14 files. The site and number counts agree. - **The same family in other packages, not edited.** Two other packages carry similar test comments: `packages/rest` (`objectstack-ai#14389 §5` in `error-response-sandbox-arm-message.test.ts` and `rest-duplicate-record-arm.test.ts`) and `packages/lint` (`(objectstack-ai#10064)` in `runtime-gate.object-writes.test.ts` and `validate-object-field-refs.test.ts`). They are independent sites with the same rot, outside this claim's file surface. Their lanes' anchors are `10220a7bf` and `def0d3e63`. - **The census tool was not re-run.** Its surface defers test files, so this population is outside it by construction. The same extractor and classifier, over the census's comment-prose projection of the package's non-test files, read 0 dead both before and after. - **Wording only:** 「the card」 / 「this card」 stands on many comment lines in this package. It carries no number, and neither instrument sees it. This diff removes one antecedent of it, and the rewrite repairs that one in place (`protocol.ui-view-hidden-columns.test.ts:46`). --- _Generated by [Claude Code](https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp)_ Co-authored-by: Claude <noreply@anthropic.com>
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