Skip to content

Commit a7d9768

Browse files
docs(metadata-protocol): re-anchor the dead tracker citations to the commits and ADR that decided them (#21233)
Part of #20595 Clause-②: no ## What changed Stage 1 of the `domain:engine` lane 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 `5749154545` on #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**: - **163 census sites** (155 lines, 8 files under `src/`): the whole `allocated-but-absent` population of the gate's own census in this package at the base; - **1 site in `tsup.config.ts`** (`:15`, `#11235`): same number, outside the census glob but inside the claimed file surface; - **129 test-comment sites** (123 lines, 45 test files), which the census defers, found by the supplementary reading below. Each cites a number the census itself reads as dead (41 of the 43 numbers are among the census set; `#10485` and `#8600` are 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.** `#11674` is split across two commits, one per half of what it named (see the table). Two `#12176` sites (`protocol.item-name-grammar.test.ts:6`, `:12`) drop the number without a new citation, because line `:4` of 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), `#11099` and `#8390` answer as pull requests and `#14767` answers 404 (see Sites left). **A `patch` changeset**: 52 of the rewritten non-test lines are in the published `dist` (the `.d.ts` keeps JSDoc on exported members, and esbuild keeps a few comments in the JS), and `dist` is not byte-identical with the base text (see Changeset). ## Census: `metadata-protocol`, before and after **Instrument (A1).** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged (it carries #20989's wider extractor, merge `a5bce40888`, an ancestor of the base). The count is its `allocated-but-absent` findings under `packages/metadata-protocol/`. | reading | tree | board | whole-repo `allocated-but-absent` | sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `e47355be5`, run ended 18:52:32Z | enumerated, 191 pages, frontier #21227, 19,048 records | 755 | **163** | 155 | 8 | 54 | | after | `06d41e512`, run 19:21:20Z to 19:25:08Z | enumerated, 191 pages, frontier #21228, 19,049 records (newest number #21228 read just before and just after the run) | 592 | **0** | 0 | 0 | 0 | The 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) and `cross-repo-unjudged` (1,139) did not move. The card's 162 was taken at `f11b5f20a2` with the older extractor; the base here reads 163, which includes the slash-joined `partial-index-probe.ts:395` `#16657` that the post-landing census (`5923084795`) named. The only commit after `06d41e512` adds 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 exported `extractCitations` (whole-file and comment-prose projections) and `namesThisRepository` over every tracked file in the package (235 `.ts`, 2 `.md`, 2 `.json`). A number is dead when the before census reported it `allocated-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`, `#11674` and `#16657` (the card's and the census's named sites) answer 404, `#5286` and `#12624` answer 200. | reading | citations | dead | src comment | test comment | test string | changelog | |---|---|---|---|---|---|---| | before, `e47355be5` | 6,383 | **434** | 164 | 151 | 63 | 56 | | after, head | 6,090 | **141** | 0 | 22 | 63 | 56 | `src comment` here includes `tsup.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 `src` counts census sites (plus `tsup.config.ts` for `#11235`), `test` counts 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-repository` false, 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 measured `shims: true` consequence). The one exception is `2a29caa53` (`#9741`): its message records the decision itself (`environmentId` recorded 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; `#11674` adds `9a884c6e4` beside their `1cba33f16`, because 25 of its 32 sites here describe the write-back half, which `git blame` puts in `9a884c6e4`). The other 19 had no prior anchor and were measured here. | number | src | test | anchor | kind | what it decided | |---|---|---|---|---|---| | `#6037` | 1 | 1 | `18189983d` | commit | validate-only data operation — DataProtocol.validateData | | `#6307` | 1 | 0 | `293476148` | commit | refuse a repeated `?version=` on `GET`/`DELETE /packages/:id` instead of handing the array to PackageService | | `#6478` | 1 | 4 | `474f131cf` | commit | rolls `flow`'s `allowOrgOverride` back to `false` per ADR-0005's original call, the write path refusing loudly | | `#6483` | 8 | 10 | `ee58392e1` | commit | enforces the ADR-0005 whitelist: nine unratified `allowOrgOverride: true` flags rolled back to `false`; its message records the 2026-08-08 three-part maintainer ruling it executes | | `#6608` | 4 | 2 | `ee58392e1` | commit | the same commit: `#6608` was the pull request whose squash it is | | `#8600` | 0 | 1 | `018d22cc3` | commit | require authored OWD at the runtime object door; retire ADR-0094 R2 external-wider arm; declare object in runtimeTypes | | `#8648` | 2 | 0 | `e5eeb499c` | commit | pin the SEARCH-axis remedy agreement, and correct the three comments that claimed word-identity | | `#8671` | 1 | 2 | `75e66fc8e` | commit | stop the meta diff endpoint serving credential values | | `#8818` | 1 | 1 | `fd6bdf89f` | commit | saveMetaItem's missing-item refusal declares 400 INVALID_REQUEST instead of answering 500 | | `#9740` | 1 | 0 | `11b779e0f` | commit | declare MetadataProtocol.getMetaItemLayered; drop the dead 'overlay' lockSource arm | | `#9741` | 1 | 0 | `2a29caa53` | commit | declare previewDrafts/state on meta-read requests; record environmentId as transport-level; retire REST door casts | | `#9798` | 1 | 0 | `c7655d472` | commit | restore the #4630 unscoped multi-delete refusal on sys_comment through the wired engine | | `#9817` | 1 | 1 | `855591fe7` | commit | discriminate a failed sys_organization probe from a genuinely empty one | | `#9934` | 13 | 2 | `79c46da90` | commit | producer-side user-facing marking for hook refusal messages — userMessage channel | | `#9967` | 2 | 1 | `8f266f1cd` | commit | serve a sandboxed body's declared HTTP status on /api/v1/data | | `#10063` | 5 | 1 | `9e04c3e35` | commit | let the publish door state the package it is promoting | | `#10159` | 1 | 0 | `1ec36b730` | commit | refuse a settings write issued before the engine is bound | | `#10340` | 3 | 4 | `26f3588fb` | commit | decide /meta org scope on the folded type, not the raw URL spelling | | `#10350` | 5 | 3 | `490879ad0` | commit | declare `packageId` on `publishMetaItem`'s request type, and correct three comments that say the per-item door names no package | | `#10382` | 1 | 4 | `ee09d2119` | commit | derive each live-MySQL suite's database from its own file, and enforce it repo-wide | | `#10485` | 0 | 10 | `35ad101bc` | commit | retire the `themes` carrier key and ThemeSchema — `app.branding` is the one colour surface | | `#10788` | 1 | 1 | `3a7ec2d3b` | commit | a raw-SQL seam that cannot answer is absent, not empty | | `#10789` | 6 | 1 | `38bc74ed1` | commit | a seam that cannot answer is absent, not empty | | `#10842` | 1 | 3 | `f334d662e` | commit | watch(_, since) replays from sys_metadata_history, and what a bare watch() owes is written down | | `#10886` | 3 | 10 | `809e61221` | commit | inventory the DESTRUCTIVE_CHANGE 409's faces and pin the sole carrier | | `#10888` | 5 | 4 | `d806081dd` | commit | render the spec-validation 422 findings clause per write face | | `#10895` | 1 | 1 | `a79bd3561` | commit | Publish refusals: declare failed[].issues + seedApplied.issues, then trim error to a headline | | `#11003` | 5 | 1 | `c74aefe63` | commit | thread packageId into both resolveDraftOrgScopeForPublish probes | | `#11014` | 1 | 2 | `2d8b92ff1` | commit | the destructive gate's reachable type set is `object` alone | | `#11015` | 6 | 9 | `82cb6e849` | commit | make the destructive-change remedy clause face-aware — stop prescribing `?force=true` on the duplicate door | | `#11021` | 3 | 1 | `7d81c889f` | commit | close() terminates watch iterators instead of emitting a drain event | | `#11235` | 6 | 1 | `376c70f98` | commit | derive discovery `version` instead of the hardcoded `'1.0'` literal | | `#11350` | 2 | 0 | `ece4dad31` | commit | re-export the three types the root entry's own inferred types mention | | `#11674` | 20 | 12 | `9a884c6e4` + `1cba33f16` | commit | seed pass 2 writes back by the internal id captured at insert time, healing keyless datasets / warn at load time when a seed defers a required column, and document the ordering constraint at the four pointer-pair sites | | `#12144` | 1 | 0 | `3a04b0125` | commit | pin the shared identifier schemas to the storage columns that bound them | | `#12176` | 2 | 3 | `311433f6b` | commit | Declare the metadata item-name grammar in spec and refuse it loudly at the publish door | | `#12194` | 6 | 5 | `311433f6b` | commit | Declare the metadata item-name grammar in spec and refuse it loudly at the publish door | | `#12195` | 1 | 0 | `7986d973f` | commit | Retire compound-name metadata addressing — un-mount the three `:section` arities and unify SDK URL spelling | | `#13185` | 1 | 1 | ADR-0005, design principle 3, its Correction note | ADR | the field-level patch model retired and deleted whole under ADR-0049 (executed as `9e0ba21a1`) | | `#13186` | 1 | 1 | `9e0ba21a1` | commit | Retire the paper metadata-customization protocol with its full coupling set | | `#13259` | 1 | 1 | `2a75270b1` | commit | honour `hidden` on getUiView's list priority pass | | `#13324` | 4 | 2 | `4cda78c9b` | commit | require a missing-table error to name the table that was read | | `#14390` | 1 | 0 | `9d7f7259f` | commit | `update` answers a driver unique violation with the `DUPLICATE_RECORD` envelope, on every driver | | `#14403` | 1 | 0 | `93d2d679b` | commit | pin the batch-row sink's disclose/withhold log coherence | | `#14409` | 2 | 3 | `3ecb7dc1a` | commit | measure what each dialect materialises for a datetime JS cannot hold | | `#14541` | 1 | 0 | `6d178a408` | commit | consult the bespoke structured arms before the declared-status passthrough, so both error doors answer one refusal with one body | | `#14683` | 6 | 5 | `96326040f` | commit | apply the allowOrgOverride read gate inside getMetaItems, so multi-type sweeps are scoped per type | | `#14723` | 3 | 1 | `65846bc46` | commit | a batch/import ROW reports a unique-constraint refusal as `UNIQUE_VIOLATION`, the route's one wire spelling | | `#14770` | 3 | 3 | `d5cbb44f3` | commit | gate `getMetaItem`'s overlay read on the metadata registry | | `#14907` | 1 | 2 | `e1d4f9e3f` | commit | `getMetaItemLayered` gates the org read, bound after the canonical fold | | `#14938` | 2 | 1 | `c383352cb` | commit | listDrafts emits the ISO-8601 string updatedAt declares | | `#15068` | 1 | 0 | `8744de9e9` | commit | collapse the published-seed read to the single env-wide read its gate produces | | `#16488` | 5 | 1 | `460d4b807` | commit | render a composite externalId in seed diagnostics instead of its NUL-joined key | | `#16657` | 3 | 1 | `5a95b0e93` | commit | read the dialect text out of `cause` for operator-facing records | | `#17167` | 4 | 5 | `dc709b2cf` | commit | the organization probe records the operator channel as is, empty included | | `#19306` | 1 | 1 | `f9e16d856` | commit | a packaged permission set's DELETE stops reporting a deletion it did not perform | `#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:8618` already names that record on the same line (「recorded as a correction inside principle 3 itself」), so there the number is dropped beside `commit 9e0ba21`. `get-meta-item-org-read-gate.test.ts:40` now names it (「ADR-0005 principle 3's correction」). For the other 55 numbers, `git grep` over `docs/adr` and `scripts/adr-anchors` finds no ADR or anchor that records the decision a site describes. ADR-0094 D5-R and ADR-0086 mention the `#6483` rollback, but only as a pointer to it; the narrative and the ruling are in `ee58392e1`'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 X` to `commit SHA's X`), the form the landed stages use. These are the ones that say more than the tag: - `protocol.ts:5697`: 「(#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 #14683 is about」 became 「the resurrection commit 9632604 closed」. - `protocol.ts:16640`: 「measured on the #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 #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 #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`: 「— #11674's B half, ruled by triage…」 became 「— commit 1cba33f, the B half, ruled by triage…」. - `protocol-publish-drafts-package-scope.test.ts:400` is 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`, and `c74aefe63`'s message does record the ruling. - `sys-metadata-repository.contract.test.ts:187` quotes 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:6` and `:12`: the number is dropped and nothing is substituted, since `:4` cites `311433f6b`. - No line was reflowed, so many are longer than their block's wrap (`eslint.config.mjs` declares no line-length rule, and reflowing would move neighbouring lines and every line citation into the file). ## Sites left - **In `src` comments and `tsup.config.ts`: none.** - **Test comments: 22 sites carry 13 numbers that answer 404 and that the census never reads** (they stand only in test files). By the dispatch's rule they are not this stage's population, so they are counted and not edited: `#6287`, `#10058`, `#10064` (2), `#10420`, `#10978` (2), `#11017`, `#13214`, `#13244`, `#13258`, `#14389`, `#14431` (5), `#14767`, `#17621` (4). `#14767` stands on a line this PR rewrote (`get-meta-item-org-read-gate.test.ts:10`): it is the pull-request number of `96326040f`'s squash, kept beside the new anchor as it stood. - **String literals: 63 test-string sites** (describe and `it` titles, assertion arguments) carry dead numbers: 56 with census-dead numbers (`#12194` 6, `#10789` 5, `#10886` 5, `#11014` 4, `#11674` 4, `#16488` 4, 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. - **Outside `src`:** the release-owned `CHANGELOG.md` names dead numbers on 56 sites (45 census-dead, 11 among the 404 reads); left. `README.md`, `package.json` and `tsconfig.json` name no number; `vitest.config.ts`'s two are live. ## Mechanical guard: no code token moves The guard compares, base `e47355be5` against the working tree, over all 54 touched `.ts` files: - **Reading 1**: the TypeScript 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. Punctuation and keywords are included and JSDoc nodes are skipped. String, template and numeric literals are compared in full on both readings. Results: - Real run at the head: 213,265 base tokens, **0 files with a token change** on either reading (exit 0). - Comment control (「The derived」 to 「The DERIVED」 on `protocol.ts:13`): 0 files changed (exit 0). - Positive control, a code identifier (`postureEnforcesWall` to `postureEnforcesWallX` in `protocol.ts`'s import): DIFFER in both readings (exit 1). - Positive control, a string literal (`'dashboard'` to `'dashboardX'` in `sys-metadata-repository.contract.test.ts`): DIFFER in both readings (exit 1). - Positive control, a numeric literal (`BULK_BATCH_SIZE = 200` to `201` in `seed-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 from `HEAD`. Each landed: anchor count 1 to 0, blob changed. Each restore was proven equal to its `HEAD` blob (`5be50ab59075`, `99ef73ef7562`, `41b999ca3ecc`), with `git diff HEAD` empty and a clean tree afterwards. ## Changeset: `patch` (`dist` measured) `files[]` is `dist`, `README.md` and `CHANGELOG.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 own `build` (tsup plus `check-dts-emitted`) ran three times under the shared verify lock: - **Leg 1**, at the head: 24 `dist` files hashed. Of the 154 rewritten non-test lines, 52 appear verbatim in `dist`: 36 from `protocol.ts`, 7 from `sys-metadata-repository.ts`, 5 from `seed-loader.ts` and 4 from `migrations/seed-tenancy-backfill.ts`. Most are in `index.d.ts` / `index.d.cts`; two from `seed-tenancy-backfill.ts` are in `index.js` / `index.cjs`, where esbuild keeps a comment inside an expression. - **Leg 2**, with the base text put back in the 8 non-test files (each proven equal to its base blob): `index.d.ts`, `index.d.cts`, `index.js` and `index.cjs` differ from leg 1, and so do the content-hashed chunk names, including the seed-loader chunks. - **Leg 3**, after the proven restore: all 24 files are byte-identical to leg 1, so the build is deterministic and the difference is the rewrite. So the rewrite ships, and `.changeset/20595-metadata-protocol-provenance-anchors.md` declares a `patch` for `@objectstack/metadata-protocol`, comment text only, with the claim's `Clause-②: no` line. ## Gates (head `3265b142f`) - **Citation judging, as CI runs it:** `node scripts/check-issue-citations.mjs` exits 0 (「every citation this change adds resolves」, 19 citations judged across 8 files). `pnpm check:issue-citations` exits 0 (self-test, 173 cases, 9 batteries). - **Doc authoring:** `pnpm check:doc-authoring` exits 0 (17,085 spec strings clean; the sibling-package prose-id baseline holds, no growth). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` at `3265b142f` (change set derived from git: 55 paths against merge base `e47355be5`) derived 62 commands. All 62 ran, each with its exit code captured before any pipe, and all 62 exit 0. `--ran` reports 62 derived, 62 run, 0 NOT-MEASURED (a derived zero), 0 unrun, and exits 0. A full `turbo run build` over `./packages/*` and `./packages/*/*` ran first under the shared verify lock (71 of 71 tasks), so no gate hit an unbuilt workspace. - **Roster families the derivation lists outside its commands** whose roster sits in a directory this diff touches: `node scripts/check-changeset-fixed.mjs`, `pnpm check:authz-resolver` and `pnpm check:error-code-casing`. Each exits 0. - **Tests and typecheck, under the verify lock, at `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 typecheck` exits 0, and `tsc --noEmit --listFiles` puts all 203 tracked test files in the program (233 package files). - **Lint, as a proven narrowing:** eslint with inline config disabled, over the 54 touched `.ts` files plus `dist/index.js` as the control, gives 55 results, 0 errors and 1 warning: the control's ignore notice. Its `--format json` output reports none of the 54 ignored. `eslint.config.mjs` never enables type-aware linting (its lines 327-328 say so), so a comment edit cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. - **Control bytes:** `pnpm check:nul-bytes` exits 0, and a raw scan of the 55 changed files for control bytes finds none. ## Acceptance notes - **Base.** The branch is on `main` at `e47355be5`. `main` has since moved five commits (to `62b90d74f`), and `dispatch-gates` flags that as a stale tree. None of the five touches a file in this diff, `scripts/check-issue-citations.mjs` or `scripts/pm/dispatch-gates.mjs`. One edits `protocol.meta-types-degenerate-derivation.test.ts` in 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. - **The before census was not bracketed by newest-number reads.** It enumerated 191 pages at frontier #21227; the newest number read at 19:21:20Z, before the after run, was #21228. - **Comment ids are outside the grammar.** `comment 5299845282` stands 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, and `75e66fc8e`, now cited beside it, carries the ruling's text in its message. Left as it is. - **Wording only:** 「the card」 / 「this card」 stands on 377 comment lines in 105 files under this package. It carries no number, neither instrument sees it, and this diff removes no antecedent except the one repaired at `protocol-publish-drafts-package-scope.test.ts:400`. - **A first guard reading was void.** The guard's first version read the token stream with a bare scanner, which has no parser context. It loses its place at template literals and reported 27 files changed; its parser-context reading reported 0 on that same run. That bare-scanner reading was replaced by the `forEachChild` walk above, and every figure in the guard section is from the replacement. --- _Generated by [Claude Code](https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 49d2a24 commit a7d9768

55 files changed

Lines changed: 295 additions & 280 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/metadata-protocol': patch
3+
---
4+
5+
Provenance comments in `@objectstack/metadata-protocol` cite the commits that decided them, not tracker numbers that no longer resolve
6+
7+
Clause-②: no
8+
9+
Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub.
10+
Each one now cites the commit in this repository's history that made the decision it describes
11+
(and ADR-0005's design-principle-3 correction where that record exists). Some of these docblocks sit
12+
on exported members, so the reworded text appears in the published `index.d.ts` / `index.d.cts`, and
13+
a few comments that esbuild keeps appear in the JavaScript output.
14+
15+
Comment only: no export, type, error code, status, message text or runtime behaviour changes.

‎packages/metadata-protocol/src/discovery-version.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #11235 — the `version` field `getDiscovery()` serves must be DERIVED: an
4+
* Commit 376c70f98 — the `version` field `getDiscovery()` serves must be DERIVED: an
55
* injected `OS_RUNTIME_VERSION` stamp, falling back to the resolved
66
* `@objectstack/metadata-protocol` package version — never the `'1.0'` literal
77
* this producer hardcoded before the fix, and never any other constant.

‎packages/metadata-protocol/src/discovery-version.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Resolves the value `ObjectStackProtocolImplementation.getDiscovery()` serves
55
* as the `DiscoverySchema` "System Identity" `version` field (`./protocol.ts`).
66
*
7-
* ## #11235 — why the literal it replaces was provably not a contract value
7+
* ## Commit 376c70f98 — why the literal it replaces was provably not a contract value
88
*
99
* This producer hardcoded `version: '1.0'`. It is the SECOND
1010
* `DiscoverySchema`-conforming producer; the first
@@ -23,7 +23,7 @@
2323
* `@objectstack/metadata-protocol`, not the reverse, so importing it would
2424
* invert the dependency direction. Hoisting a shared helper into
2525
* `@objectstack/types` or `@objectstack/core` (both already dependencies of
26-
* this package) was considered and declined at #11235 triage: a hoist widens
26+
* this package) was considered and declined when the derivation landed (commit 376c70f98): a hoist widens
2727
* two packages' published surface for ~10 lines serving two call sites.
2828
* Consolidation rides a later card if a third caller ever appears.
2929
*
@@ -103,7 +103,7 @@ function resolvePackageVersion(): string | undefined {
103103
* 3. `'unknown'` — only if BOTH of the above are unavailable (the package's own
104104
* `package.json` is unreadable). Honest about not knowing, rather than a
105105
* plausible-looking literal a caller could mistake for real identity — the
106-
* exact failure mode #10993 and #11235 exist to close.
106+
* exact failure mode #10993 and commit 376c70f98 close.
107107
*/
108108
export function resolveDiscoveryVersion(): string {
109109
return getEnv('OS_RUNTIME_VERSION') || resolvePackageVersion() || 'unknown';

‎packages/metadata-protocol/src/get-meta-item-layered-org-read-gate.test.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* [#14907] `getMetaItemLayered` — the THIRD `/meta` read verb — applies the
4+
* [commit e1d4f9e3f] `getMetaItemLayered` — the THIRD `/meta` read verb — applies the
55
* registry read gate ITSELF, so a caller cannot spend a raw active
66
* organization on a type that has no per-org read channel.
77
*
88
* ── The defect, and why this verb was graded on its own harm ──────────────
99
*
10-
* The series is #9454 → #14683 (plural `getMetaItems`) → #14770 (singular
10+
* The series is #9454 → commit 96326040f (plural `getMetaItems`) → commit d5cbb44f3 (singular
1111
* `getMetaItem`) → this one. On the plural verb an ungated organization can
1212
* only ADD a row; on the singular verb it SUBSTITUTES the served document.
1313
* Here the affected value is the `overlay` LAYER of a three-layer diagnostic
@@ -28,19 +28,19 @@
2828
* and it is correct there because the binding already sat AFTER
2929
* `canonicalizeMetaRequestType`. Here the binding sat BEFORE the fold, so the
3030
* one-liner does NOT port: dropping the same expression in place would gate on
31-
* the RAW type. #10340 measured what that costs — `declaresOrgOverride`
31+
* the RAW type. Commit 26f3588fb measured what that costs — `declaresOrgOverride`
3232
* tolerates the MANIFEST plurals but not the URL-only ones (`translations` /
3333
* `email_templates` have no manifest key), so a raw segment splits one item
3434
* across two partitions. The fix is therefore a REORDER, and §3 is what fails
3535
* if a later author moves the binding back above the fold: it asserts that a
3636
* URL-only spelling of an OVERRIDABLE type still reaches its org partition.
3737
*
38-
* ── §4–§5 are the idempotence proof the #14683 ruling made this conditional
38+
* ── §4–§5 are the idempotence proof the ruling behind commit 96326040f made this conditional
3939
* on, discharged over THIS door's caller population ──────────────────────
4040
*
4141
* That ruling makes a callee-side gate conditional on proving no already-gating
4242
* caller is double-scoped or wrongly denied, discharged PER DOOR over that
43-
* door's own callers. #14770's proof covers none of this verb's population, so
43+
* door's own callers. Commit d5cbb44f3's proof covers none of this verb's population, so
4444
* it is re-discharged here: §4 covers `f(t, undefined) === undefined` (the four
4545
* `plugin-security` invocations that name no organization) and §5 covers
4646
* `f(t, f(t, o)) === f(t, o)` over the COMPLETE accepted-spelling population
@@ -359,13 +359,13 @@ describe('§3 the gate resolves AFTER canonicalizeMetaRequestType', () => {
359359
expect(res.overlayScope, spelling).toBe('org');
360360
// ONLY the org partition: the org row wins, so the `overlay ===
361361
// null` env fallback never runs. Gated on the raw segment this
362-
// list is `[null]` instead — the partition split #10340 measured.
362+
// list is `[null]` instead — the partition split commit 26f3588fb measured.
363363
expect(partitions(findOnes), spelling).toEqual([ORG]);
364364
}
365365
});
366366

367367
it('answers the URL spelling and the canonical spelling identically', async () => {
368-
// The #10340 statement restated as an equality: one item, ONE
368+
// The statement of commit 26f3588fb restated as an equality: one item, ONE
369369
// partition, whichever accepted spelling addresses it.
370370
for (const spelling of URL_ONLY_OVERRIDABLE) {
371371
const canonical = canonicalMetaUrlType(spelling);

‎packages/metadata-protocol/src/get-meta-item-org-read-gate.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* [#14770] `getMetaItem` — the SINGULAR verb — applies the registry read gate
4+
* [commit d5cbb44f3] `getMetaItem` — the SINGULAR verb — applies the registry read gate
55
* ITSELF, so a caller cannot spend a raw active organization on a type that has
66
* no per-org read channel.
77
*
88
* ── The defect, and why the singular verb is the sharper half ─────────────
99
*
10-
* #14683 (PR #14767) moved {@link organizationIdForMetaRead} INSIDE the PLURAL
10+
* Commit 96326040f (PR #14767) moved {@link organizationIdForMetaRead} INSIDE the PLURAL
1111
* verb, `getMetaItems`, and deliberately did not carry to this one. There, the
1212
* two `queryByOrg` reads are UNIONed, so an ungated organization can only ADD
1313
* rows — the resurrection that card is about. Here the two `findOverlay` reads
@@ -37,7 +37,7 @@
3737
* The inner precedence rests on two other things: ADR-0005 design principle 3
3838
* stores the ENTIRE item document per overlay row (so a layering has nothing
3939
* to layer), and the field-level patch model that would have given "layering"
40-
* any meaning was retired and deleted whole under ADR-0049 (#13185, PR #13186,
40+
* any meaning was retired and deleted whole under ADR-0049 (ADR-0005 principle 3's correction, commit 9e0ba21a1,
4141
* maintainer ruling 2026-08-29), with ADR-0126 §6 ruling out the phase it was
4242
* held for; and `organizationIdForMetaRead`'s own docblock quotes this very
4343
* expression as the intended shape while defining #9454. ADR-0029 D9 reaches
@@ -374,7 +374,7 @@ describe('§4 an already-gating caller receives the same scope it did before', (
374374
//
375375
// ⛔ This is why the gate sits AFTER the fold. `declaresOrgOverride`
376376
// tolerates the MANIFEST plurals and not the URL-only ones
377-
// (`translations` / `email_templates` have no manifest key) — #10340
377+
// (`translations` / `email_templates` have no manifest key) — commit 26f3588fb
378378
// measured what that costs when a raw segment reaches the predicate.
379379
for (const spelling of ALL_SPELLINGS) {
380380
const doorGate = organizationIdForMetaRead(canonicalMetaUrlType(spelling), ORG);

‎packages/metadata-protocol/src/get-meta-items-org-read-gate.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* [#14683] `getMetaItems` applies the registry read gate ITSELF, so a sweep
4+
* [commit 96326040f] `getMetaItems` applies the registry read gate ITSELF, so a sweep
55
* that reads MORE THAN ONE type per request is scoped per type instead of per
66
* request.
77
*

‎packages/metadata-protocol/src/meta-overlay-cache.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ describe('[#11967] §7 distinct reads never share an entry', () => {
578578
expect((scoped.items as any[]).map((i) => i.name)).toEqual(['beta']);
579579
});
580580

581-
// ⚠️ [#14683] `view`, NOT `object`, and the type is LOAD-BEARING here in a
581+
// ⚠️ [commit 96326040f] `view`, NOT `object`, and the type is LOAD-BEARING here in a
582582
// way it is not in this section's three siblings. `getMetaItems` now
583583
// resolves its own read scope through `organizationIdForMetaRead`, so a
584584
// type the registry declares NON-overridable has exactly one partition to

‎packages/metadata-protocol/src/migrations/live-mysql-database.isolation.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #10382 — this package's live-MySQL suites must not be able to share one
4+
* Commit ee09d2119 — this package's live-MySQL suites must not be able to share one
55
* database.
66
*
77
* ## Why this suite is structural, and what it is a control FOR

‎packages/metadata-protocol/src/migrations/live-mysql-database.testkit.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #10382 — the per-file live MySQL database for this package's live suites.
4+
* Commit ee09d2119 — the per-file live MySQL database for this package's live suites.
55
*
66
* ## What was actually wrong, which is not what the card said
77
*

‎packages/metadata-protocol/src/migrations/partial-index-probe.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
* message that discloses neither the statement nor the diagnostic — and carries
4242
* the dialect error whole under a non-enumerable `cause`. Read bare, `detail`
4343
* became *"the database refused to run a raw statement"* for every caller that
44-
* stores it. `operatorFacingErrorText` (`@objectstack/types`, #16657) reads the
44+
* stores it. `operatorFacingErrorText` (`@objectstack/types`, commit 5a95b0e93) reads the
4545
* dialect's own words back out of that chain, so a stored record still names
4646
* `no such column: foo`. The envelope itself is left exactly as the driver
4747
* declared it: this is a READ of the cause, never a widening of the disclosure.
@@ -392,7 +392,7 @@ export async function probeThenReplaceIndex(
392392
} catch (err: unknown) {
393393
// `detail` is the OPERATOR-facing text: the dialect's own prose, read
394394
// out of the `cause` the raw seam attaches when it declares its fault
395-
// (#16019/#16657 — see the module header). Callers STORE it, and a
395+
// (#16019/commit 5a95b0e93 — see the module header). Callers STORE it, and a
396396
// stored record is the only copy its reader ever gets.
397397
// The VERDICT is taken from the error object itself, so a conflict
398398
// reported on `code` / `errno` / `cause` with unhelpful prose is still

0 commit comments

Comments
 (0)