Skip to content

Commit a186aea

Browse files
objectstack-fleet[bot]hotlongclaude
authored
docs(runtime): re-anchor the dead tracker citations in packages/runtime/src to the commits that decided them (#20624)
Part of #20594 Clause-②: no ## What changed This is stage 1 of the `domain:cli` lane of the dead-citation sweep: `packages/runtime/src/**`, the lane's largest package. Every comment or docblock site in scope that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on #19123), the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided. PR #20533 is the method and PR #20609 the closest sibling. Later stages cover `rest`, `cli`, `types` and the rest of the lane, so this PR says `Part of` and the card stays open. That is **513 comment sites on 508 lines in 118 files, covering 96 numbers**: 194 of the census's 217 sites, and 319 more in test comments, which the census defers. Three more sites carried a slash-joined dead number the citation grammar does not read (`#10629/#10630`, `#5811/#12281`, `#8421/#12194`), and they are rewritten too. Each rewritten line cites one of **95 distinct commits**. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records the decision behind any of these numbers. ADR-0126 and ADR-0131 name #10243 only as the incident, ADR-0126 names #11513 only for the flow-clone half, and ADR-0112 names #12281 only as another card. So every anchor is a commit. The anchors the landed stages already gave the same numbers are reused (24 numbers, for example `f19475c0a` for #14143, `e2798fab7` for #6345 and `79c46da90` for #9934), so each number carries one anchor across the tree. Only comments changed. Every touched file keeps its line count (508 lines out, 508 in, over 118 files), so no line citation into these files moves. Seven of the 508 lines held no census site. Five are the other half of a sentence that had to change: `action-governance-scope-divergence.test.ts:6` (「the card names」 to 「that diverged」, because line 4 no longer names the card), `action-record-load-denied.test.ts:560`, `dispatcher-5xx-demoted-code-withhold.test.ts:45` (「that card's change」 to 「that commit's change」), `hook-input-writeback-readonly-provenance.integration.test.ts:380` (「that card」 to 「that commit」) and `standalone-stack-seeder-declaration-copy.test.ts:88` (a trailing 「PR」 whose number wrapped onto line 89). Two carry only a slash-joined number: `dispatcher-plugin.ts:688` and `meta-compound-arity-mint-door.test.ts:4`. No code token moves (see the guard below). **No citation number is added.** Every tracker number on an added line was already on the line it replaces. No PR number stands on an added line, and none of the 95 shas is on a removed line. Twenty-eight dead comment sites are left on purpose: - **20 in `domains/meta.ts`.** PR #20615 (#20590's) opened at 2026-09-29T08:12:40Z, after this stage's claim and first read, and edits that file. So the file went back to its base blob (`b4ddb362cc`) in `a5cdfd8a46`, as PR #20612 did with `authoring-rules.ts`. The anchors are verified and listed below for the follow-up. - **8 with no deciding commit, or with a literal reader.** See "The sites left" below. One more file: a `patch` changeset for `@objectstack/runtime`, because the rewritten docblocks ship (see Changeset below). ## Census: `packages/runtime`, before and after **Instrument.** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged, run with the fleet token. Its surface is comment prose in `packages/**/src/**/*.ts` with string literals blanked, and it defers `*.test.ts`. The count is its `allocated-but-absent` findings under `packages/runtime/`. Both runs enumerated the whole board (185 pages), so neither read a truncated board. | reading | tree | board | whole-repo `allocated-but-absent` | runtime sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `eb4b17c346`, run 2026-09-29T07:55:51Z to 08:05:47Z | enumerated, 185 pages, frontier #20614, 18,441 numbers | 2,397 | **217** | 216 | 29 | 59 | | after | head `a5cdfd8a46`, run 09:08:23Z to 09:14:11Z | enumerated, 185 pages, frontier #20623, 18,450 numbers | 2,027 | **23** | 23 | 4 | 12 | The before count equals the card's 217 at `f11b5f20a2`. The 23 left are the 20 held `domains/meta.ts` sites and 3 deliberate ones (`api-exposure.ts:108`, `domains/mcp.ts:360`, `route-ledger.ts:300`). The whole-repo drop is 370: this diff's 194, plus the 97 and 79 of PR #20609 and PR #20612, which landed on `main` in between and came in with the merge. **Supplementary instrument, the whole scope.** The census does not read test files or strings, and this stage's scope includes test comments. So a second reading runs the gate's own exported `extractCitations` (whole-file and comment-prose projections) and `classifyCitation` over every `.ts` file under `packages/runtime/src` (373 files), against a board probed by REST for every number cited there. The lit controls #16862, #16847 and #17698 answered 200 and the dead controls #16714, #16715 and #16697 answered 404 in both runs. | reading | tree | citations | dead | src comment | test comment | src string | test string | |---|---|---|---|---|---|---|---| | before, 08:17:55Z | `eb4b17c346` | 5,364 | **641** | 217 | 324 | 5 | 95 | | after, 09:24:24Z | `a5cdfd8a46` | 4,851 | **128** | 23 | 5 | 5 | 95 | Its src-comment column equals the census's 217 and 23, which is the control on the second instrument. The 4,499 resolving citations, the 195 that resolve as pull requests and the 29 cross-repo ones are the same in both readings. The drop is 513, exactly this diff's grammar-read sites. ## Per-number table Sites and files are the dead comment sites in scope at the base, tests included. `held` is `domains/meta.ts` (see above) and `left` is a site with no deciding commit or with a literal reader. `strings kept` counts string-literal sites, which are tokens and stay as they were. Every anchor was read in its message or its diff, not only in its subject: it is the commit that made the change the line describes, and its own message or diff names the number it replaces. | number | comment sites / files | rewritten | held | left | strings kept | anchor | |---|---|---|---|---|---|---| | `#6065` | 1/1 | 1 | 0 | 0 | 0 | `026101660` | | `#6123` | 1/1 | 1 | 0 | 0 | 0 | `59d1933f9` | | `#6206` | 5/2 | 5 | 0 | 0 | 0 | `8e13ca876` | | `#6216` | 2/1 | 2 | 0 | 0 | 1 | `f586f1a89` | | `#6220` | 1/1 | 1 | 0 | 0 | 0 | `83df2fd73` | | `#6238` | 2/2 | 2 | 0 | 0 | 2 | `c8d6f6e08` | | `#6259` | 4/2 | 3 | 0 | 1 | 1 | `6968885ef` | | `#6265` | 12/2 | 12 | 0 | 0 | 4 | `cfb549db8` | | `#6268` | 9/3 | 9 | 0 | 0 | 0 | `68f5eccb1` | | `#6287` | 1/1 | 1 | 0 | 0 | 0 | `84c86fb45` | | `#6307` | 1/1 | 1 | 0 | 0 | 0 | `293476148` | | `#6316` | 6/3 | 6 | 0 | 0 | 0 | `448ac9565` | | `#6345` | 10/3 | 10 | 0 | 0 | 0 | `e2798fab7` | | `#6361` | 4/2 | 4 | 0 | 0 | 6 | `90bbf2510` | | `#6363` | 6/2 | 6 | 0 | 0 | 2 | `17d095413` | | `#6483` | 3/2 | 3 | 0 | 0 | 0 | `ee58392e1` | | `#8722` | 1/1 | 0 | 0 | 1 | 0 | — | | `#8724` | 1/1 | 1 | 0 | 0 | 0 | `ff4ba6a06` | | `#8726` | 8/4 | 7 | 1 | 0 | 1 | `e783e163d` | | `#8796` | 13/3 | 13 | 0 | 0 | 4 | `a4331227b` | | `#8848` | 3/2 | 1 | 2 | 0 | 1 | `4fc4a3c0b` | | `#8919` | 1/1 | 0 | 1 | 0 | 0 | `b5378550e` (held file) | | `#9934` | 17/7 | 17 | 0 | 0 | 4 | `79c46da90` | | `#9967` | 1/1 | 1 | 0 | 0 | 0 | `8f266f1cd` | | `#10179` | 1/1 | 0 | 0 | 1 | 2 | — | | `#10243` | 40/13 | 40 | 0 | 0 | 9 | `266436a7f`, `02b41232d` | | `#10293` | 3/3 | 3 | 0 | 0 | 0 | `92a69d813` | | `#10338` | 1/1 | 1 | 0 | 0 | 0 | `d2619fd0c` | | `#10340` | 3/2 | 2 | 1 | 0 | 1 | `26f3588fb` | | `#10380` | 12/2 | 12 | 0 | 0 | 0 | `dd8172ee2` | | `#10485` | 3/3 | 3 | 0 | 0 | 0 | `35ad101bc` | | `#10503` | 8/2 | 3 | 5 | 0 | 1 | `67ceb9aef` | | `#10537` | 2/1 | 2 | 0 | 0 | 0 | `e634ecf6a` | | `#10554` | 1/1 | 1 | 0 | 0 | 0 | `6abc4df03` | | `#10629` | 75/23 | 75 | 0 | 0 | 0 | `13a6cb4ad` | | `#10630` | 4/1 | 4 | 0 | 0 | 0 | `dd8172ee2` | | `#10789` | 2/1 | 2 | 0 | 0 | 1 | `38bc74ed1` | | `#10886` | 1/1 | 1 | 0 | 0 | 1 | `809e61221` | | `#10888` | 3/3 | 2 | 1 | 0 | 1 | `d806081dd` | | `#10961` | 5/3 | 5 | 0 | 0 | 3 | `222d06fc1` | | `#10965` | 2/1 | 2 | 0 | 0 | 1 | `ab47f6974` | | `#10978` | 1/1 | 1 | 0 | 0 | 0 | `4c9780c7a` | | `#10983` | 3/2 | 3 | 0 | 0 | 0 | `6a4e929f5` | | `#11006` | 4/4 | 3 | 1 | 0 | 0 | `cccbe51bf` | | `#11015` | 3/1 | 3 | 0 | 0 | 0 | `82cb6e849` | | `#11166` | 8/3 | 8 | 0 | 0 | 4 | `735f5c709` | | `#11333` | 1/1 | 1 | 0 | 0 | 0 | `ea4d16420` | | `#11504` | 3/2 | 3 | 0 | 0 | 0 | `f90e82024` | | `#11513` | 2/2 | 2 | 0 | 0 | 0 | `e170b0ae5` | | `#11703` | 8/3 | 8 | 0 | 0 | 1 | `5cb62d88b` | | `#12010` | 1/1 | 1 | 0 | 0 | 0 | `77b91bdb4` | | `#12176` | 5/5 | 5 | 0 | 0 | 0 | `7986d973f` | | `#12194` | 11/4 | 8 | 3 | 0 | 0 | `311433f6b` | | `#12195` | 9/4 | 4 | 5 | 0 | 10 | `7986d973f` | | `#12281` | 20/5 | 20 | 0 | 0 | 5 | `0783d7b80` | | `#12943` | 7/3 | 7 | 0 | 0 | 0 | `090f2302e` | | `#13037` | 8/2 | 8 | 0 | 0 | 5 | `e7dfb1d69` | | `#13233` | 5/1 | 5 | 0 | 0 | 0 | `3800e4293` | | `#13241` | 5/4 | 5 | 0 | 0 | 1 | `a21d2a9cf` | | `#13273` | 11/3 | 11 | 0 | 0 | 0 | `3a86a65e7` | | `#13279` | 3/2 | 3 | 0 | 0 | 0 | `6a180e42d` | | `#13325` | 3/1 | 3 | 0 | 0 | 0 | `2e0b7b18f` | | `#13644` | 5/4 | 5 | 0 | 0 | 1 | `34ce8e7db` | | `#13657` | 13/1 | 13 | 0 | 0 | 1 | `b003cf2e8` | | `#14143` | 26/8 | 26 | 0 | 0 | 4 | `f19475c0a` | | `#14390` | 1/1 | 1 | 0 | 0 | 0 | `9d7f7259f` | | `#14398` | 3/1 | 3 | 0 | 0 | 0 | `317132495` | | `#14403` | 6/1 | 6 | 0 | 0 | 0 | `93d2d679b` | | `#14421` | 2/1 | 2 | 0 | 0 | 0 | `bd8795ea1` | | `#14422` | 4/2 | 4 | 0 | 0 | 4 | `dc7c226b9` | | `#14423` | 3/1 | 3 | 0 | 0 | 1 | `a56baa2bd` | | `#14474` | 1/1 | 1 | 0 | 0 | 0 | `df657d9df` | | `#14667` | 2/1 | 2 | 0 | 0 | 0 | `dc7c226b9` | | `#14678` | 2/1 | 2 | 0 | 0 | 2 | `73ad0bba7` | | `#14683` | 2/2 | 2 | 0 | 0 | 0 | `96326040f` | | `#14723` | 1/1 | 1 | 0 | 0 | 0 | `65846bc46` | | `#14745` | 1/1 | 0 | 0 | 1 | 0 | — | | `#14748` | 1/1 | 1 | 0 | 0 | 1 | `92b5d7f00` | | `#14758` | 15/5 | 15 | 0 | 0 | 1 | `84199cb87` | | `#14760` | 6/2 | 6 | 0 | 0 | 2 | `ee32e1cb8` | | `#14864` | 3/3 | 3 | 0 | 0 | 3 | `066dd3bd0` | | `#14878` | 2/1 | 2 | 0 | 0 | 1 | `29db3cd2a` | | `#14908` | 3/2 | 3 | 0 | 0 | 0 | `d5cbb44f3` | | `#14921` | 2/1 | 2 | 0 | 0 | 0 | `c1d274de7` | | `#15063` | 2/1 | 2 | 0 | 0 | 0 | `ad35745e8` | | `#15068` | 2/2 | 2 | 0 | 0 | 4 | `8744de9e9` | | `#15071` | 5/2 | 5 | 0 | 0 | 0 | `cf6e0a193` | | `#16610` | 3/1 | 3 | 0 | 0 | 0 | `316a20fc5` | | `#16649` | 4/1 | 4 | 0 | 0 | 0 | `44c917a47`, `613bfbd3d` | | `#16755` | 1/1 | 1 | 0 | 0 | 0 | `44c849c7d` | | `#16758` | 1/1 | 1 | 0 | 0 | 0 | `6e9bee640` | | `#16783` | 1/1 | 1 | 0 | 0 | 0 | `854639b31` | | `#16919` | 1/1 | 1 | 0 | 0 | 0 | `2cd4c548e` | | `#17038` | 1/1 | 0 | 0 | 1 | 0 | — | | `#17039` | 1/1 | 1 | 0 | 0 | 0 | `edf59e359` | | `#17041` | 2/2 | 0 | 0 | 2 | 0 | — | | `#17114` | 2/2 | 2 | 0 | 0 | 2 | `4af758d47` | | `#17147` | 1/1 | 1 | 0 | 0 | 0 | `aaacf1d5c` | | `#17148` | 1/1 | 0 | 0 | 1 | 0 | — | | `#17195` | 1/1 | 1 | 0 | 0 | 0 | `d2c1d1980` | | `#17219` | 1/1 | 1 | 0 | 0 | 0 | `706ad0fcc` | | `#19364` | 2/2 | 2 | 0 | 0 | 0 | `ada701220` | | `#19394` | 5/2 | 5 | 0 | 0 | 0 | `0862063ba` | Every cited sha matches exactly one object (`git rev-parse --disambiguate`, count 1 for each of the 95), is a commit, has one parent, and is an ancestor of the base (`merge-base --is-ancestor`, exit 0 for all 95). The checkout is not shallow (`--is-shallow-repository` false), and the control leg `13a6cb4ad` exits 0 too. **Numbers with more than one anchor, by site:** - `#10243` (40 sites): `266436a7f` for the 26 sites that describe the 2026-08-23 ruling it implements (the enablement door joins the `manage_metadata` write set, with the `trigger` exclusion), and `02b41232d` for the 14 that name the leak itself (「the leak commit 02b4123 measured」). That commit recorded the measurement over HTTP and says it is part of that card. - `#16649` (4 sites): `613bfbd3d` for the first half (the fourteen remaining `boot-refusal` rows registered) and `44c917a47` for the second (the face refusal widened to every published package, and `boot-refusal` retired). - `#12176`, `#12194`, `#12195`: the stages of one ruled retirement. `311433f6b` is stage 1 (the item-name grammar refused at the publish door) and `7986d973f` is stage 3 (the compound arities un-mounted). These are the anchors the spec stages gave. **Wordings to check, each true of its commit:** - `#10293` (3 sites) cited the p1 flake whose signature had the expected-noise lines lifted into it. They now read 「(a vitest teardown race, fixed by commit 92a69d8)」. `92a69d813` names that number in its subject and fixed the flake by disarming vitest's console-forwarding teardown race, which is why the noise pointed the dispatch at the wrong mechanism. - `#16755` and `#16783` each cited an open PR that held a file at the time. They now read 「the change that landed as commit 44c849c held that file」 and 「then held by the change that landed as commit 854639b」. Each commit's diff edits the named file (`domains/automation.ts`, `seed-loader.test.ts`). - Quoted rulings keep their words. `dispatcher-plugin.declared-5xx-prose-withhold.test.ts:13` and `dispatcher-plugin.declared-user-message.test.ts:35` quote the 2026-08-27 ruling, and `dispatcher-5xx-demoted-code-withhold.test.ts:281` quotes an older note. There the commit stands in an editorial bracket (`[commit 79c46da]`, `[commit 0783d7b]`) in place of the number. - `#9934`'s 「second constraint」 and 「third constraint」 now read 「the ruling's second constraint, commit 79c46da」. That commit's own diff calls status-agnosticism 「the ruling's second constraint」. - `domains/packages.ts:841` read 「declares, since #19364:」 above the `enabled` line, but that line predates `ada701220` (#19364's commit). It now reads 「declares — a key commit ada7012 kept rather than retired:」. - `route-ledger.ts:288`: 「#16758 filed the second kind」 now reads 「Commit 6e9bee6 gated the second kind」, because that commit added the row census after the index-slice incident the sentence goes on to describe. - `flow-clone.ts:7` and `domains/automation.ts:2403` cite `e170b0ae5` for #11513: the commit that landed 「lock package-declared permission sets at the save door; clone to customize」, whose changeset names the number. ## The sites left **No deciding commit, or a literal reader (8 sites):** - `api-exposure.ts:108` (#6259): `api-exposure.test.ts:152` splits this `@param` block on the literal `'#6259'`, so rewriting the comment would change what the test measures. Its deciding commit is `6968885ef`, which the three test-comment sites of the same number now cite. - `domains/mcp.ts:360` (#8722): a wider contract change 「archived unscheduled」. It never landed, so no commit decided it. - `domains/meta-state-plural-tolerance.test.ts:130` (#10179): an untaken option on a tracking card. The only commit naming the card, `53a48c93f`, recorded the opposite state. - `package-door-namespace-conflict-code.test.ts:30` (#14745): a residue item on a review card. The only commit carrying the token is the one that added this file. - `route-ledger.conformance.test.ts:33` (#17038): an ablation measured on a PR whose squash commit, `6a7910abb`, neither records nor performs it. - `route-ledger.conformance.test.ts:38` and `route-ledger.ts:300` (#17041): a maintainer decision the lines call open. - `security/artifact-granted-permissions.test.ts:291` (#17148): a question the line itself says is unsettled. **Held with `domains/meta.ts` (20 sites), anchors verified for the follow-up:** `#8726` `:116` to `e783e163d`; `#8848` `:200`, `:1398` to `4fc4a3c0b`; `#8919` `:1247` to `b5378550e`; `#10340` `:1309` to `26f3588fb`; `#10503` `:14`, `:1143`, `:1159`, `:1250`, `:1308` to `67ceb9aef`; `#10888` `:1337` to `d806081dd`; `#11006` `:103` to `cccbe51bf`; `#12194` `:831`, `:1050`, `:1173` to `311433f6b`; `#12195` `:819`, `:827`, `:1046`, `:1167`, `:1960` to `7986d973f`. PR #20615's one hunk there is at `:1874`, disjoint from these lines, but the rule is file-level. **String sites kept as tokens (100).** 95 are test titles and test-code strings in 43 files. Five are non-test strings: the `route-ledger.ts` `note` fields at `:435`, `:441` and `:505`, a string at `dispatcher-error-vocabulary.ts:349`, and the enablement door's refusal text at `domains/activation-gate.ts:279`, which ends 「(#10243).」 (see Acceptance notes). ## Mechanical guard: no code token moves The check compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, JSDoc nodes excluded, so template literals are read in context) of each touched file at base `eb4b17c346` against the working tree at `a5cdfd8a46`, over all 118 touched `.ts` files. Controls mutate the head text in memory only, so nothing on disk moved for them. - Real run: 301,081 base tokens, **0 files with a token change** (exit 0). - Comment-insertion control (`domains/activation-gate.ts`): 0 files changed (exit 0). - Code-insertion positive control (a declaration in the same file): DIFFER at token 34 (exit 1). - String positive control (`(#10243)` to `(#10244)` inside the kept refusal string): DIFFER at token 339 (exit 1). Line balance: every touched file is +N/−N (508/508), and every line count is equal at base and head. A raw scan of the 119 changed files for control bytes finds none. ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/runtime` is included, in PR #20609's form and level. It says only that the provenance comments were re-anchored. Measured on the built package: `files[]` is `dist`, `README.md` and `CHANGELOG.md`. After `pnpm --filter @objectstack/runtime build`, the rewritten docblocks reach `dist`: for example `e2798fab7` appears 3 times and `68f5eccb1` 6 times in `dist/index.d.ts`, and `f19475c0a` 4 times in `dist/index.js`. The positive control, the unchanged sentence 「drags `@libsql/client` (native bindings included)」 of the same `turso-driver-factory.ts` docblock, is in `dist/index.d.ts`, and a negative control phrase appears nowhere. The only dead number left in `dist` is the kept refusal string's `#10243`. ## Gates (head `a5cdfd8a46`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its disclosure, verbatim, from each locked run at this head: ```text os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 5s · declare it in the PR body · pnpm --filter @objectstack/runtime build os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 99s (1m39s) · declare it in the PR body · pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 6s · declare it in the PR body · pnpm --filter @objectstack/runtime exec vitest run --project repo --maxWorkers=2 os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 8s · declare it in the PR body · pnpm --filter @objectstack/runtime typecheck ``` The dependency closure and the whole workspace were built first, at the merge head `ca6d13d6ab`, the same way: `turbo run build --filter='@objectstack/runtime...'` (30 tasks, exit 0) and `turbo run build --filter='./packages/*' --filter='./packages/*/*'` (71 tasks, exit 0). `a5cdfd8a46` differs from that head only in `domains/meta.ts`, which went back to base bytes, and `@objectstack/runtime` was rebuilt at `a5cdfd8a46`. - **Tests:** `vitest run --project local`: 288 files, 4,190 tests passed, 1 skipped. `--project repo` (which holds the touched `action-owner-key-single-source.test.ts`): 3 files, 727 tests passed. Together they cover every touched test file. - **Typecheck:** `pnpm --filter @objectstack/runtime typecheck` exits 0. `tsc --listFiles` counts 82 `src` files (no tests) under `tsconfig.json` and all 291 test files under `tsconfig.test.json`, which `check:test-typecheck` judges: 27 files, 190 errors, 68 pinned signatures held. - **Lint:** the repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at `a5cdfd8a46` (2026-09-29T09:23:06Z to 09:23:36Z). A narrowed run over the 118 touched `.ts` files through eslint's API agrees: 118 linted, 0 ignored, 0 errors, 0 warnings. - **Citation judging:** `node scripts/check-issue-citations.mjs --base origin/main` exits 0. The diff-scoped run judged 23 citations across 28 files, and all 23 resolve. These are the live numbers that stay on rewritten lines. It defers `*.test.ts`, so the added-minus-removed count over the whole diff covers the rest: 0 numbers added. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` at `a5cdfd8a46` derived 67 families, the same set as at the merge head. All 67 exit 0. `--ran` reads 「67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN」. - At the merge head, `check:dual-build-cjs-loads` and `check:type-check-debt` first exited 3 (PREREQUISITE NOT MET) on a partly built workspace. After the whole-workspace build both exited 0, and both exit 0 at the final head. - Among them: `check:doc-authoring` (the sibling prose-id baseline holds, 810 pinned sites, no growth), `check:nul-bytes` (9,250 files, no raw control bytes), `check:route-ledger-census`, `check:dispatcher-error-vocabulary` and `check:issue-citations` (self-test, 114 cases in 8 batteries). - **Artifact rosters:** 38 of the 41 non-self-test roster rows exit 0 at the merge head. The other three, `check-closing-target-claim`, `check-partof-closing-keyword` and `check-single-claim-paths`, answer 「NOT WIRED」 (exit 2) without a pull request's context, and are run against this PR and reported on the card. ## Hypotheses (measured first) - **H0 holds.** The filtered census answers 217 dead sites at `eb4b17c346` (29 files, 59 numbers), equal to the card's count at `f11b5f20a2`: no drift. - **H1 holds, with the listed exceptions.** After the rewrite the filtered census answers 23: the 20 sites held with `domains/meta.ts` for an open PR, and 3 deliberate ones (a literal reader, a card never landed, an open decision). The supplementary reading adds 5 test-comment sites of the same two kinds. - **H2 holds, by the token guard.** A comment-stripped comparison of every touched file (the parser's leaf tokens, JSDoc excluded) is empty, and its controls fire. The emitted `dist` is not byte-identical, because the docblocks ship, which is why the changeset is `patch`. ## Acceptance notes - **The held file.** The claim's read (07:51Z) and this stage's first read of the open PRs' file lists (08:06:32Z, 8 open PRs) found none touching `packages/runtime/src`. PR #20615 opened at 08:12:40Z and edits `domains/meta.ts`. The re-read at 09:07:08Z (7 open PRs) found it, and it is the only open PR touching the package. The file went back to its base blob in `a5cdfd8a46`, and `git hash-object` equals `b4ddb362cc`, the blob at the base and at `origin/main`. The 20 anchors above are ready for the follow-up once that PR lands. - **Form D, not touched here.** `domains/activation-gate.ts:279` is part of the enablement door's refusal message and ends 「(#10243).」. An author sees it, so it is ruling D's (no number, the lesson in words), a string change outside this comment-only scope. It needs a form-D carrier. The other four non-test string sites are ledger `note` data and a gate's own string. - **The grammar does not read a slash-joined number.** `CITATION_RE` refuses a `#` preceded by `/`, so the second number of `#A/#B` is never judged. In `packages/runtime/src`, 3 such dead numbers exist (`#10630`, `#12281`, `#12194`), and all 3 are rewritten here. The other 36 distinct slash-joined numbers there were probed by REST and answer 200. One more dead one, `#17219`, stands slash-joined inside a test title, a string, and is kept. This is the same shape as PR #20612's slash-joined `#5775/#6629`. It is noted, not filed. - **Outside the scope and the census surface.** `packages/runtime/vitest.config.ts:54` cites `#17853`, which answers 404. The file is outside `src/**`, so it is left for whoever owns the package's config. The other numbers there, and those in `tsup.config.ts` and `README.md`, answer 200. - **Base.** The branch merged `origin/main` once (`ca6d13d6ab`, merging `c1d8051e0a`) before the `--base origin/main` run, as the dispatch orders. That merge brought PR #20609's and PR #20612's landed stages and touched none of this diff's files. `origin/main` has since moved to `ed6f7348f9`, one commit that touches only `packages/cli`, so there was no second merge. - **Anchors shared with the landed stages.** 24 numbers keep the anchor the spec, lint or service-messaging stages already gave them, for example `f19475c0a` (#14143), `b003cf2e8` (#13657), `311433f6b` (#12194), `8e13ca876` (#6206) and `17d095413` (#6363). ## Deviations - Three changed lines hold only a slash-joined dead number, beyond the census's sites (see Acceptance notes). Five more are the other half of a rewritten sentence (listed under What changed). - Commit trailers are AGENTS.md's model-free pair (`Claude-Session` plus `Co-authored-by: Claude`), and the pre-push trailer check passed on every push. The merge commit carries git's default message. --- _Generated by [Claude Code](https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289)_ --------- Co-authored-by: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1322cc7 commit a186aea

119 files changed

Lines changed: 519 additions & 508 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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@objectstack/runtime': patch
3+
---
4+
5+
Provenance comments in `@objectstack/runtime` were re-anchored
6+
7+
Comment and docblock lines under `src/` that cited tracker numbers which no
8+
longer resolve on GitHub now cite the commit in this repository's history that
9+
decided the matter, and say in their own words what was decided. Comments
10+
only: no route, error code, refusal text, type, export or runtime behaviour
11+
changes.

‎packages/runtime/src/action-declarative-update.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ describe('#15079 point 3 — the authorization point: a caller who cannot read o
336336
expect(res.body.error.code).toBe('RECORD_NOT_FOUND');
337337
expect(res.body.error.message).toContain(RECORD_ID);
338338
expect(res.body.error.message).toContain(OBJECT);
339-
// ⛔ The #14143 class: a swallowed load must never become an implicit
339+
// ⛔ The class commit f19475c0a closed: a swallowed load must never become an implicit
340340
// grant. The verdict is CONSUMED — no write was even attempted.
341341
expect(rig.updates).toHaveLength(0);
342342
expect(rig.row.status).toBe('open');

‎packages/runtime/src/action-door-record-load-denied.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*
3333
* 1. **Both doors × both surfaces.** The flow door and the script/body door,
3434
* on the REST `/actions` route and on the MCP `run_action` bridge. A rule
35-
* implemented at one door is the failure class #14143 and #15168 each paid
35+
* implemented at one door is the failure class commit f19475c0a and #15168 each paid
3636
* for on this exact seam, so every case below is asserted on all four.
3737
* 2. **⛔ No run, no body.** The refusal lands BEFORE `automation.execute`
3838
* (no persisted run) and BEFORE `executeAction` (no trusted, RLS-bypassing
@@ -46,7 +46,7 @@
4646
* 4. **Record-less and new-record actions are byte-for-byte unchanged.** An
4747
* object-less action key never attempts a load, so its verdict is never
4848
* `true` and it still receives the `recordId` stamp — the regression that
49-
* #14143 deliberately kept and that this card must not take away.
49+
* commit f19475c0a deliberately kept and that this card must not take away.
5050
* 5. **A load that SUCCEEDS still runs.** The owner reaches the flow and the
5151
* handler exactly as before; this is the firing control that stops every
5252
* zero above from being a rig that dispatches nothing.
@@ -450,7 +450,7 @@ describe('[#16370] refuseDeniedSubjectLoad — the rule, isolated from every doo
450450

451451
it('returns silently when the verdict is `false` — and the stamp is NOT the predicate', () => {
452452
// ⛔ `record.id` is truthy in BOTH cases; re-deriving the verdict from
453-
// it is the #14143 defect verbatim, so this pair is what says the
453+
// it is the defect commit f19475c0a fixed, verbatim, so this pair is what says the
454454
// implementation reads the flag and nothing else.
455455
expect(() => refuseDeniedSubjectLoad(OBJECT, RECORD_ID,
456456
{ record: { id: RECORD_ID }, recordLoadDenied: false })).not.toThrow();

‎packages/runtime/src/action-execution.ts‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -900,14 +900,14 @@ export function isFlowActionRefusal(e: unknown): e is FlowActionRefusal {
900900
* and a downstream reader that had to tell them apart could only infer.
901901
*
902902
* [#15168] **The wiring takes the subject LOAD, not a bare record.** The flow
903-
* face of #14143's signal (`AutomationContext.recordLoadDenied`, declared by
903+
* face of commit f19475c0a's signal (`AutomationContext.recordLoadDenied`, declared by
904904
* #14244) is derived here, once, from {@link loadActionSubjectRecord}'s
905905
* outcome — so a caller cannot hand this door a record while dropping the
906906
* verdict that says the caller could not read it. Both call sites already held
907907
* that outcome and were passing `subject.record` out of it; taking the whole
908908
* `subject` removes the second de-facto source rather than adding a key beside
909909
* it, and makes the omission a compile error instead of a silent inertness one
910-
* door over (the shape #14143 was filed for).
910+
* door over (the shape commit f19475c0a fixed).
911911
*/
912912
export async function dispatchFlowAction(deps: ActionExecutionDeps,
913913
requestContext: HttpProtocolContext,
@@ -1685,10 +1685,10 @@ export function buildActionEngineFacade(_deps: ActionExecutionDeps, ql: any, ec?
16851685

16861686
/**
16871687
* The subject-record load's outcome, as the two action doors hand it to a
1688-
* handler (#14143).
1688+
* handler (commit f19475c0a).
16891689
*/
16901690
export interface ActionSubjectRecordLoad {
1691-
/** What the handler receives as `ctx.record`. Unchanged by #14143. */
1691+
/** What the handler receives as `ctx.record`. Unchanged by commit f19475c0a. */
16921692
record: Record<string, unknown>;
16931693
/**
16941694
* `true` exactly when a caller-scope load was ATTEMPTED and did not deliver
@@ -1700,7 +1700,7 @@ export interface ActionSubjectRecordLoad {
17001700

17011701
/**
17021702
* Load an action's subject record IN THE CALLER'S OWN SCOPE, and report whether
1703-
* that load actually delivered the row (#14143). ONE producer for both action
1703+
* that load actually delivered the row (commit f19475c0a). ONE producer for both action
17041704
* doors — the MCP `run_action` bridge below and the REST `/actions` route
17051705
* (`domains/actions.ts`) — because the signal it emits is documented to app
17061706
* authors, and a signal only one of two doors sets is an authorization guard
@@ -1793,7 +1793,7 @@ export function actionRecordLoadSignal(load: ActionSubjectRecordLoad): { recordL
17931793
* reading it left open ("whether the automation engine acts on it … is a
17941794
* separate reading") is this function. A swallowed load must never become an
17951795
* implicit grant — the rule is #15079's, and a rule implemented at one of three
1796-
* doors is the failure class #14143 and #15168 each already paid for here.
1796+
* doors is the failure class commit f19475c0a and #15168 each already paid for here.
17971797
*
17981798
* ## The predicate is the LOAD's verdict — ⛔ never the action's `locations`
17991799
*
@@ -1906,11 +1906,11 @@ function declarativeUpdateRefusal(message: string, status: number): Error {
19061906
* 'update'` + `patch` (#14092, maintainer ruling 2026-09-01, quoted on the
19071907
* card). ONE implementation, called by BOTH action doors.
19081908
*
1909-
* ## Shared on purpose, for the #14143 reason
1909+
* ## Shared on purpose, for the reason of commit f19475c0a
19101910
*
19111911
* The REST `/actions` door and the MCP `run_action` bridge are two doors onto
19121912
* one action model, and this repo has now paid twice for a rule implemented at
1913-
* one of them: #14143 (a `recordLoadDenied` signal only one door set) and
1913+
* one of them: commit f19475c0a (a `recordLoadDenied` signal only one door set) and
19141914
* #15168 (a flow face with no populator at all). An authorization rule is the
19151915
* worst possible thing to fork, and contract point 3 is an authorization rule
19161916
* — so the branch each door owns is three lines, and everything that decides
@@ -1944,7 +1944,7 @@ function declarativeUpdateRefusal(message: string, status: number): Error {
19441944
* the caller's own scope actually delivered it. A caller who cannot read the
19451945
* row is refused HERE, before any write is attempted, on
19461946
* `subject.recordLoadDenied`. Re-deriving that from `subject.record` is the
1947-
* #14143 defect verbatim: the door stamps `record.id = recordId` on a refused
1947+
* defect commit f19475c0a fixed, verbatim: the door stamps `record.id = recordId` on a refused
19481948
* load, so `record.id` is truthy either way and `if (!record?.id)` is false on
19491949
* a row the caller cannot see. A swallowed load must never become an implicit
19501950
* grant.
@@ -2202,7 +2202,7 @@ export async function invokeBusinessAction(deps: ActionExecutionDeps,
22022202

22032203
// Load the subject record under RLS when row-context (engages the same
22042204
// permission path as get_record — an unseen record reads as not-found).
2205-
// [#14143] Through the ONE shared producer, so this door and the REST
2205+
// [commit f19475c0a] Through the ONE shared producer, so this door and the REST
22062206
// `/actions` door emit the same `recordLoadDenied` signal to handlers.
22072207
const subject = await loadActionSubjectRecord(objectName, recordId, () =>
22082208
callData('get', { object: objectName, id: recordId }, driver, envId, ec));
@@ -2213,7 +2213,7 @@ export async function invokeBusinessAction(deps: ActionExecutionDeps,
22132213
// first, and an action with no handler has no body to elevate for. The
22142214
// shared executor the REST `/actions` door also calls, so the two doors
22152215
// cannot disagree about the identity the write carries — the failure class
2216-
// #14143 and #15168 each paid for once, on this exact seam.
2216+
// commit f19475c0a and #15168 each paid for once, on this exact seam.
22172217
if (isDeclarativeUpdateAction(action)) {
22182218
const result = await executeDeclarativeUpdateAction(deps, action, {
22192219
objectName, actionName: name, subject, recordId, params, ec, driver, envId, callData,
@@ -2281,7 +2281,7 @@ export async function invokeBusinessAction(deps: ActionExecutionDeps,
22812281
);
22822282
const actionContext: any = {
22832283
record,
2284-
// [#14143] The caller-scope load's verdict, on the same context the
2284+
// [commit f19475c0a] The caller-scope load's verdict, on the same context the
22852285
// record rides. `ctx.record.id` is present either way (the stamp is
22862286
// load-bearing for record-less actions), so this is the ONLY thing that
22872287
// tells a handler its subject row did not resolve for THIS caller —

‎packages/runtime/src/action-governance-scope-divergence.test.ts‎

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

33
/**
4-
* #14423 (a) — the AGREEMENT, where this file used to pin the divergence.
4+
* Commit a56baa2bd — the AGREEMENT, where this file used to pin the divergence.
55
*
6-
* The two sites the card names:
6+
* The two sites that diverged:
77
* - the AUDIT, `runActionGovernanceInventory` (`packages/objectql/src/
88
* action-governance.ts`), whose metadata-plane sources are now
99
* `loadStandaloneActionsKeyed = () => meta.loadManyKeyed('action')` and the
@@ -13,7 +13,7 @@
1313
* whose third rung is `meta.loadDiagnosed('action', name)` — resolved per
1414
* request off `deps.resolveService(requestContext, 'metadata', envId)`.
1515
*
16-
* PR #14421 closed the registry rung. This file measured the remaining one and
16+
* Commit bd8795ea1 closed the registry rung. This file measured the remaining one and
1717
* reproduced it four ways; the measurement is now the fix's pin, case for
1818
* case, with the same harness. **C1 and C5 are unchanged controls** — they
1919
* were green before and must stay green, because a "fix" that simply stopped
@@ -184,7 +184,7 @@ function auditAccused(warnings: Array<{ message: string; meta?: Record<string, u
184184
* ONE handler registered and NO object-embedded declaration and NO registry
185185
* item — so the metadata plane is the only source that can clear it.
186186
*
187-
* [#14423] Transcribed from the plugin's wiring after the fix, including its
187+
* [commit a56baa2bd] Transcribed from the plugin's wiring after the fix, including its
188188
* fallbacks: the keyed plural read when the plane offers one, the unkeyed one
189189
* otherwise, and the by-name rung preferring `loadDiagnosed` over `load`
190190
* exactly as `resolveRouteActionDeclaration` does. Keeping the branches rather
@@ -206,7 +206,7 @@ async function runAudit(meta: any) {
206206
loadStandaloneActionsKeyed: meta && typeof loadManyKeyed === 'function'
207207
? () => loadManyKeyed.call(meta, 'action')
208208
: undefined,
209-
lookupRegistryAction: () => undefined, // rung 2 holds nothing — #14421's rung is not the one under test
209+
lookupRegistryAction: () => undefined, // rung 2 holds nothing — commit bd8795ea1's rung is not the one under test
210210
lookupMetadataAction: meta && typeof loadDiagnosed === 'function'
211211
? async (name: string) => (await loadDiagnosed.call(meta, 'action', name))?.data
212212
: (meta && typeof load === 'function' ? (name: string) => load.call(meta, 'action', name) : undefined),
@@ -323,7 +323,7 @@ describe('#14423 (a) — the audit and the router now answer from one identity a
323323
// The keyed enumeration is short for the same reason — keying is not a
324324
// cure for an unreachable loader, and does not claim to be.
325325
expect(await meta.loadManyKeyed<any>('action')).toEqual([]);
326-
// [#14423 item 1] ...and the sibling enumeration no longer THROWS where
326+
// [commit a56baa2bd] ...and the sibling enumeration no longer THROWS where
327327
// its two siblings merely came back short.
328328
await expect(meta.listNames('action')).resolves.toEqual([]);
329329

@@ -335,7 +335,7 @@ describe('#14423 (a) — the audit and the router now answer from one identity a
335335
});
336336

337337
/**
338-
* C4 — a BOUNDARY, not a defect, and pinned as one. NARROWER since #16610.
338+
* C4 — a BOUNDARY, not a defect, and pinned as one. NARROWER since commit 316a20fc5.
339339
*
340340
* `metadata` is registered `SCOPED`, so `PluginLoader.getService` mints one
341341
* instance per `scopeId`. The kernel's RAW SYNCHRONOUS accessor
@@ -348,7 +348,7 @@ describe('#14423 (a) — the audit and the router now answer from one identity a
348348
* plane. That asymmetry is what every assertion below exercises — the
349349
* accessor, directly, never the plugin's wiring around it.
350350
*
351-
* ## What the PLUGIN does with that accessor, after #16610
351+
* ## What the PLUGIN does with that accessor, after commit 316a20fc5
352352
*
353353
* `ObjectQLPlugin.resolveGovernanceMetadataService` no longer calls the
354354
* synchronous accessor alone, so the throw is no longer swallowed into
@@ -363,7 +363,7 @@ describe('#14423 (a) — the audit and the router now answer from one identity a
363363
* ⚠ So do NOT read the paragraph above as a live defect in `plugin.ts`.
364364
* It describes the rung the plugin now reaches for SECOND, and this case
365365
* pins that rung's behaviour — which is why its assertions stay green and
366-
* stay true across #16610.
366+
* stay true across commit 316a20fc5.
367367
*
368368
* ## Why this stays accused, and why that is CORRECT
369369
*

‎packages/runtime/src/action-object-less-key-agreement.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-
* "Object-less" has ONE answer inside `action-execution.ts` (#14864).
4+
* "Object-less" has ONE answer inside `action-execution.ts` (commit 066dd3bd0).
55
*
66
* `isObjectLessActionKey` (`@objectstack/objectql`) is the canonical predicate:
77
* the routed object is object-less when it is the canonical

‎packages/runtime/src/action-owner-key-single-source.test.ts‎

Lines changed: 9 additions & 9 deletions
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-
* The standalone-action owner-key ladder has ONE spelling (#14422).
4+
* The standalone-action owner-key ladder has ONE spelling (commit dc7c226b9).
55
*
66
* `action.objectName` -> `action.object` -> the object-less
77
* `GLOBAL_ACTION_OBJECT_KEY` decides which engine key a standalone `action`
@@ -26,16 +26,16 @@
2626
* B reads this package's own source and fails if the ladder grows a second
2727
* body here.
2828
*
29-
* Half C closes the same hole one level down (#14678). #14422 converged the
29+
* Half C closes the same hole one level down (commit 73ad0bba7). Commit dc7c226b9 converged the
3030
* LADDER, and the runtime kept three bare `'global'` spellings elsewhere in
3131
* `action-execution.ts` that the ladder check could not see: a live comparison
3232
* in `seedFlowActionParams`, a warn-once log key in `enforceActionParams`, and
3333
* a docblock. All three were equal in value and invisible to every test in the
34-
* repo, which is the whole shape #14422 was filed to remove — so the same
34+
* repo, which is the whole shape commit dc7c226b9 was written to remove — so the same
3535
* convergence needed the same weld, or the next reader re-inlines one and
3636
* nothing says so.
3737
*
38-
* Half D (#14878) is the odd one out and says so at its own section below: it
38+
* Half D (commit 29db3cd2a) is the odd one out and says so at its own section below: it
3939
* is not about this package's source at all. It is the TREE-scoped absence pin
4040
* for the plugin member this convergence deleted, carried here as well as in
4141
* `@objectstack/objectql` so that losing either copy still leaves a guard.
@@ -157,14 +157,14 @@ describe('standalone-action owner key — half C: no bare literal (#14678)', ()
157157
// file was written to replace. Both controls are positive assertions
158158
// against text the converged file must carry.
159159
//
160-
// [#14864] The second control used to be the `seedFlowActionParams`
160+
// [commit 066dd3bd0] The second control used to be the `seedFlowActionParams`
161161
// comparison `objectName !== GLOBAL_ACTION_OBJECT_KEY`. That guard is
162162
// gone — it was one of the two rival answers to "is this route
163163
// object-less", and it now delegates to `isObjectLessActionKey` like
164164
// its neighbours. Re-anchored rather than deleted, and deliberately
165165
// onto a site this file's own subject does not move: the warn-once log
166166
// key in `enforceActionParams`, which is the SECOND of the three bare
167-
// literals #14678 converged and is untouched by the predicate work.
167+
// literals commit 73ad0bba7 converged and is untouched by the predicate work.
168168
// ⛔ Do not re-anchor a control onto the thing the next change is most
169169
// likely to edit — a control that moves with its subject stops being a
170170
// control.
@@ -184,9 +184,9 @@ describe('standalone-action owner key — half C: no bare literal (#14678)', ()
184184
});
185185

186186
/**
187-
* ── Half D [#14878]: the absence assertion is TREE-scoped, not FILE-scoped ───
187+
* ── Half D [commit 29db3cd2a]: the absence assertion is TREE-scoped, not FILE-scoped ───
188188
*
189-
* #14667 deleted a private `actionObjectKey` member from `ObjectQLPlugin` and
189+
* Commit dc7c226b9 deleted a private `actionObjectKey` member from `ObjectQLPlugin` and
190190
* DID write a guard for it — `not.toContain(...)` against `plugin.ts`. The kind
191191
* of guard was right; its SCOPE was the defect. A pin written by the deleting PR
192192
* can only look where its author thought to look, and the whole failure mode is
@@ -260,7 +260,7 @@ describe('standalone-action owner key — half C: no bare literal (#14678)', ()
260260
*/
261261

262262
/**
263-
* The member #14667 deleted from `ObjectQLPlugin`. Held as DATA: naming a symbol
263+
* The member commit dc7c226b9 deleted from `ObjectQLPlugin`. Held as DATA: naming a symbol
264264
* in a string cannot resurrect it, and this file is excluded from its own scan
265265
* precisely so it may carry the name.
266266
*/

‎packages/runtime/src/action-params-enforcement.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/**
44
* `enforceActionParams` — the ADR-0104 D2 gate itself, not its validator
5-
* (#14864).
5+
* (commit 066dd3bd0).
66
*
77
* ## What was measured, and why this file exists
88
*

‎packages/runtime/src/action-record-load-denied.test.ts‎

Lines changed: 4 additions & 4 deletions
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-
* [#14143] A handler must be able to tell "the caller cannot read this row"
4+
* [commit f19475c0a] A handler must be able to tell "the caller cannot read this row"
55
* from "this action legitimately has no record".
66
*
77
* ## The defect
@@ -493,7 +493,7 @@ describe('[#15168] the FLOW door and its verdict — MCP run_action', () => {
493493
* `AutomationContext.recordLoadDenied` is a declared spec key
494494
* (`contracts/automation-service.ts`, pinned in `packages/spec`), the
495495
* dispatcher is its ONE populator, and a populator that quietly stopped
496-
* populating would be exactly the inert-signal shape #14143 was filed for. So
496+
* populating would be exactly the inert-signal shape commit f19475c0a fixed. So
497497
* the assertions #15168 wrote at the doors are re-pinned HERE, on the
498498
* dispatcher itself, where a denied subject can still be constructed.
499499
*
@@ -556,8 +556,8 @@ describe('[#15168] dispatchFlowAction derives the verdict from the subject load'
556556

557557
/**
558558
* [#15168] The convergence itself. A per-door assertion is satisfied by two
559-
* copies of a rule, and two copies drifting apart is the defect #14143 was
560-
* filed for and the reason this card had to move both doors in one stroke — so
559+
* copies of a rule, and two copies drifting apart is the defect commit f19475c0a
560+
* fixed, and the reason this card had to move both doors in one stroke — so
561561
* the SAME caller against the SAME row is driven through both doors and the
562562
* signal is compared as a set.
563563
*/

0 commit comments

Comments
 (0)