Repository navigation
docs(cloud-connection): re-anchor the dead tracker citations in packages/cloud-connection/src to the commits that decided them - #20735
Conversation
…ges/cloud-connection/src to the commits that decided them Ten comment sites (five in marketplace-install-local-plugin.ts, five in two test files) cited three tracker numbers that no longer resolve. Each now cites the commit that decided what the line describes, in ruling C+D's form C: 01074e5 for the install-local listing's authenticated floor and field narrowing, b537855 for the /meta promotion verbs' manage_metadata gate, and 6a180e4 for re-raising a permission-store outage instead of reading it as "nobody is authenticated". Comment prose only: ten lines out, ten in, every file keeps its line count. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude <noreply@anthropic.com>
…written docblocks reach dist Built at base and at head, index.js, index.cjs, index.d.ts and index.d.cts differ, and the difference is comment text only (parser tokens identical). Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 16 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 5 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 3 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8858ee03fecffe7e30ec0a005f5fadb086da7ad7 && git checkout 8858ee03fecffe7e30ec0a005f5fadb086da7ad7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 36d043be171971aae42d923281c262f910eecd8a 16a88d69b265a3cea7095230123125e80adf8ca7 && git checkout -B drift-repro 36d043be171971aae42d923281c262f910eecd8a && git merge --no-ff 16a88d69b265a3cea7095230123125e80adf8ca7
node scripts/docs-audit/affected-docs.mjs --json 36d043be171971aae42d923281c262f910eecd8a
|
Contract reviewServed-tier: PR #20735 (stage 9 of card #20594, What was read and sampled. The file list is one page of 4 entries (page 2 answers 0). The net diff (119 lines) and the per-file patches were read in full. The change has 10 rewritten sites on 10 lines in 3 files; the brief's sample floor (12 sites, 6 files) is above the population, so the sample is the whole population: all 10 sites, all 3 files, including both test files, and the whole of ① Derived judgmentsAccept-set and public-surface changes the diff implies: none. No route, error code, refusal text, type, export, identifier or test assertion moves. The one public consequence is the changeset: a (1) Comment-only: yes. A line diff of each touched file at base and head (both fetched by REST) shows exactly 10 changed line pairs (5 / 3 / 2) and every changed line is a docblock (2) Anchors, all 10 sites checked, no wrong or unsupported anchor:
(3) Numbers. Removed lines carry only #9011 (7), #8919 (2) and #13279 (1); each answers 404 by REST (probed by exit code, with #8976 as the 200 control). No number answering 200 was removed or rewritten: #8976 on the neighbouring (4) Line counts. The file list reads additions equal to deletions per source file (3/3, 2/2, 5/5), and the fetched files measure 1,969 / 377 / 308 lines at both base and head. The changeset is a new 11-line file. Right. (6) ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
…ts that decided them (objectstack-ai#20737) Part of objectstack-ai#20596 Clause-②: no ## What changed This is the ninth stage of the `domain:services` lane of the dead-citation sweep. It covers `packages/plugins/plugin-audit/src/**` and nothing else. By the seat's census at the claim (`5900808881`), it is the largest package in the lane that no in-flight work holds. Later stages cover the other packages, so this PR says `Part of` and the card stays open. Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), by the method of stages 1 to 8 (PR objectstack-ai#20609 as `422db788a`, PR objectstack-ai#20626 as `b80ab579d`, PR objectstack-ai#20634 as `4d04b6be3`, PR objectstack-ai#20658 as `9a4b2bb38`, PR objectstack-ai#20693 as `0e9ad74fb`, PR objectstack-ai#20708 as `9b384f63a`, PR objectstack-ai#20717 as `cbaf04c1f`, PR objectstack-ai#20729 as `d2820876f`). That is **56 sites on 55 lines in 16 files, covering 16 numbers**: - 23 census sites (every census site this package has); - 32 sites in test comments, which the census defers; - 1 site the gate's grammar cannot see: the slash-joined second number in `objectstack-ai#9719/objectstack-ai#9798` (`comment-access-hooks.ts:35`). Each rewritten line now cites the commit in `origin/main` history that decided what the line describes, and says in its own words what was decided: **15 distinct shas**. No number in this package has an ADR or ruling record of its own in the repository (a grep of `docs/adr/` for all 16 finds none; the rest of `docs/` cites `objectstack-ai#11507` and `objectstack-ai#11374` only as evidence, in an audit table and a QA checklist), so every anchor is a commit, per ruling C's order. No number was dropped. Only comments changed. Every touched source file keeps its line count (56 lines out, 56 in, over 16 files), so no line citation into these files moves. 1 of those 56 lines holds no dead citation: it is a reflow line, listed under Wordings below. 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: `objectstack-ai#10101` (3 lines), `objectstack-ai#8287` (3), `objectstack-ai#5928` (2), `objectstack-ai#9974` (2), `objectstack-ai#4630` (2), and `objectstack-ai#8144`, `objectstack-ai#9719`, `objectstack-ai#12069` and `objectstack-ai#19054` once each. Each resolves. Over the whole diff, added minus removed is 0 for every number, and no number is new to the diff. No PR number is the citation on an added line: the two `PR #N` spellings in scope became their pull request's squash commit. 23 dead sites are left on purpose, all of them string literals (see the list below). One more file: a `patch` changeset for `@objectstack/plugin-audit`, because some of the rewritten docblocks and inline comments ship (see Changeset below). ## Census: `plugin-audit`, before and after **Instrument (A1).** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged. The count below is its `allocated-but-absent` findings under `packages/plugins/plugin-audit/`. Each run counts as a reading only because its board frontier equals the newest issue number, read by a separate request just before and just after the run. | reading | tree | board | whole-repo `allocated-but-absent` | plugin-audit sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `d2820876f`, run 2026-09-29T23:11:55Z to 23:15:11Z | enumerated, 186 pages, frontier objectstack-ai#20735 (newest objectstack-ai#20735 before and after), 18,562 numbers | 1,110 | **23** | 22 | 6 | 12 | | after | head `a9a4ea478`, run 23:26:11Z to 23:29:20Z | enumerated, 186 pages, frontier objectstack-ai#20735 (newest objectstack-ai#20735 before and after), 18,562 numbers | 1,087 | **0** | 0 | 0 | 0 | The before count matches the seat's census at the claim and A1 (23 sites). The whole-repo drop is 23, exactly this diff's census sites. The `resolves` tally is 32,995 in both runs, and `resolves-as-pull-request` (1,984) and `cross-repo-unjudged` (995) did not move either. The after run was taken on `a9a4ea478`; the head `d6e67afa5` adds only the changeset. No run was truncated or discarded: both enumerations read 186 pages at the newest frontier. **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 `namesThisRepository` over every `.ts` file under `plugin-audit/src` (45 files). It takes its verdicts from the before census's own board reading rather than from a second enumeration: a number is dead when that census reported it `allocated-but-absent`, and alive when that census judged it on this board anywhere (its `--list` extraction, 37,084 citations over 2,613 files) and did not report it. The 10 numbers the census never saw, because they stand only in test files or strings here, were read one by one on the issues endpoint: 7 answer 200 (`objectstack-ai#602`, `objectstack-ai#1532`, `objectstack-ai#4186`, `objectstack-ai#7291`, `objectstack-ai#7333`, `objectstack-ai#16312`, `objectstack-ai#20494`), and `objectstack-ai#8852`, `objectstack-ai#12143` and `objectstack-ai#12147` answer 404, on the pulls endpoint too. | reading | citations | dead | src comment | test comment | src string | test string | |---|---|---|---|---|---|---| | before, `d2820876f` | 655 | **77** | 23 | 32 | 5 | 17 | | after, `a9a4ea478` | 600 | **22** | 0 | 0 | 5 | 17 | Its src-comment column equals the census's 23, which is the control on the second instrument. The 572 live citations and the 6 cross-repo citations are the same in both readings, and the drop of 55 citations is exactly the rewritten sites the gate's grammar sees. A third, raw reading (every `#` followed by 2 to 6 digits, whatever surrounds it) finds 672 occurrences and 79 dead before, 616 and 23 after. Beyond the gate's grammar it sees 2 dead sites before (the `objectstack-ai#9719/objectstack-ai#9798` comment, rewritten, and the `[objectstack-ai#8203/objectstack-ai#11507]` test title, left) and 1 after (that title). Its only unjudged tokens are `objectui#10520`, `cloud#340`, `cloud#1395` and the decision-batch ordinal `objectstack-ai#153`. ## Per-number table Sites and files count every dead occurrence in scope at the base (comments and strings, tests included). `rewritten / left` counts the sites rewritten and the sites left. Each anchor was read in its message and diff, not only its subject, and `git blame` at the base puts every rewritten line in its anchor commit or in a later commit that descends from it (`merge-base --is-ancestor` exit 0 for all 56 line and anchor pairs). | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#11507` | 26/8 | 10/16 | `88b9d749a`: `sys_activity.type` is declared an open, author-extensible vocabulary whose options are the built-in set, per the maintainer ruling of 2026-08-24, direction 4. Its body names `objectstack-ai#11507` twice. The spec stages' anchor | | `objectstack-ai#8707` | 12/2 | 9/3 | `1408fe385`: an audit row is stamped from the record's own organization, not the actor's, applying the maintainer's ruling on `objectstack-ai#8287`; the precedence flips to `recordOrgId ?? sess.tenantId`, and the organization column is resolved from the schema (`resolveRecordOrganizationField`, first written in this file). Its subject names it. Stage 7's anchor | | `objectstack-ai#9798` | 8/2 | 7/1 | `c7655d472` (PR objectstack-ai#9993): the `sys_comment` access-hook registration declares the whole-operation dispatch `objectstack-ai#9719` built, so the `objectstack-ai#4630` unscoped multi-delete refusal reaches the handler through the wired engine; the update half is split out. Its body ends with the closing line for `objectstack-ai#9798`. The `lint` stage's anchor | | `objectstack-ai#16829` | 7/3 | 6/1 | `8d4690b8f`: the read-audit ledger write declares `preserveAudit`, so a record-view row keeps the VIEW instant; `isSystem` is kept for the readonly strip, and the new integration pin runs the real stamp hook. Its body ends with the closing line for `objectstack-ai#16829`. New to the sweep | | `objectstack-ai#6575` | 4/2 | 4/0 | `69787f07b`: the hook registration surface gains `excludeObjects` ("global except these objects"), refusing `'*'` and blank members on it. The squash commit of the pull request that was `objectstack-ai#6575` (404 on the pulls endpoint too); `objectstack-ai#5928`, the card it answers, stays beside it. New to the sweep | | `objectstack-ai#11374` | 4/3 | 3/1 | `f64668d3c`, the squash commit of `objectstack-ai#12143`, for the two object comments: sourced bounds on the keyed text columns `sys_activity.record_id` and `sys_audit_log.record_id` (255, the physical `id` column), route A. `3954fb7df`, for the test's statement of the rule: the route A ruling that keyed identity columns declare a sourced `maxLength`; its subject names `objectstack-ai#11374 route A`. Both are stage 4's anchors for the sibling lines in `plugin-security` | | `objectstack-ai#10091` | 3/3 | 3/0 | `da891e0ef` (PR objectstack-ai#10169): `sys_attachment`'s `beforeUpdate` gate, uploader or parent editor, with the attach rule on the NEW parent when a row is re-pointed. Its body names `objectstack-ai#10091`. Stage 6's anchor | | `objectstack-ai#14927` | 3/2 | 3/0 | `ab489388b` (PR objectstack-ai#17450): a lost audit row is reported once per cause, keyed on the error `code`, and the datasource remedy prints only for the missing-table cause; its message records that the measured `ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED` refusal had sent its operator to a working datasource. It names `objectstack-ai#14927` in its diff only (the 3 lines it wrote). New to the sweep | | `objectstack-ai#8778` | 3/1 | 2/1 | `7901b2dd2` (PR objectstack-ai#8905): the stamp-only `tenancy.organizationField`, option A per the maintainer ruling on `objectstack-ai#8778`. Its subject names it. The anchor of stages 4, 6 and 7 | | `objectstack-ai#6523` | 2/2 | 2/0 | `aa4b90d9a` (PR objectstack-ai#7068): enforcement contracts take the full `ExecutionContext`. Its subject names `objectstack-ai#6523` | | `objectstack-ai#6206` | 2/2 | 2/0 | `aa4b90d9a`: the same commit, whose body applies "the objectstack-ai#6206 ruling default (converge on the full envelope, keep no per-site subset contracts)", written as the full-envelope ruling, the form of stages 2, 6 and 7 | | `objectstack-ai#8852` | 1/1 | 1/0 | `51bb277ef`: the `sys_activity.type` writer census; its message records the objectui mirror as unguarded in both directions, filed as `objectstack-ai#8852`, and not asserted here because this package cannot import objectui. The commit that wrote the line. New to the sweep | | `objectstack-ai#11674` | 1/1 | 1/0 | `1cba33f16` (PR objectstack-ai#11961): the load-time warning and the ordering constraint documented at the four pointer-pair sites. Its subject names it; blame puts the line in it. Stage 7's anchor | | `objectstack-ai#12147` | 1/1 | 1/0 | `945e91a13`: the class-level keyed-text-bounds gate over every `*.object.ts`, retiring the per-package rule this file carried. It names `objectstack-ai#12147` in its diff only. Stage 4's anchor for the sibling file | | `objectstack-ai#12143` | 1/1 | 1/0 | `f64668d3c`: the squash commit of the pull request that was `objectstack-ai#12143` (404 on both endpoints), where the dependency-graph measurement was made. Stage 4's anchor | | `objectstack-ai#11671` | 1/1 | 1/0 | `09b4f4e4e` (PR objectstack-ai#12557): records which source revision a generated translation leaf was filled from. The anchor the identical `translations/index.ts` line already carries in five packages on `main` | Every cited sha matches exactly one commit (`git rev-parse --disambiguate`, count 1 for each of the 15), and every one is an ancestor of the base (`merge-base --is-ancestor`, exit 0 for all 15; control leg: stage 1's landing `422db788a` exit 0; the history is complete, `--is-shallow-repository` false, 15,143 commits). Each of the 16 numbers answers 404 on the issues endpoint. ## Wordings to check - **Bracket tags.** `[#N]` became `[commit SHA]`; `[#N route A]` became `[commit f64668d, route A]`, the form stage 4 gave the sibling lines; `[objectstack-ai#8707 / objectstack-ai#10101]` and `[objectstack-ai#8144 / objectstack-ai#8707 / objectstack-ai#10101]` keep the live numbers beside the sha. - **`sys-activity.object.ts:59-60`.** 「Maintainer ruling 2026-08-24 on / objectstack-ai#11507 (direction 4 of the four that card framed)」 became 「Maintainer ruling 2026-08-24, / executed by commit 88b9d74 (direction 4 of the four weighed)」. Line 59 is the one reflow line: only its last word changed, and it carries no number. 「that card」 would have lost its referent. - **「re-open objectstack-ai#11507」**, `sys-activity.object.ts:92` and `activity-type-vocabulary-enforcement.test.ts:332`, became 「re-open the ruling (commit 88b9d74)」: a card that answers 404 cannot be re-opened, and the instruction is about the decision. - **`sys-activity-type-open-vocabulary.test.ts:14`**, the attribution above a verbatim maintainer ruling: 「on objectstack-ai#11507 (direction 4 of the four the card framed)」 became 「on the card behind commit 88b9d74 (direction 4 of the four it framed)」, so line 15's 「Recorded on the card as:」 keeps its referent. Line 15, which carries the ruling 「四维分析一致的,接手你的建议。」, and the quoted block under it are untouched. - **Headings.** 「what the ruling on objectstack-ai#11507 changed」 and 「the objectstack-ai#11507 ruling」 became 「the open-vocabulary ruling (commit 88b9d74)」; 「objectstack-ai#11507 — the declaration」 became 「Commit 88b9d74 — the declaration」. - **PR numbers.** 「objectstack-ai#5928 / PR objectstack-ai#6575」 (`audit-writers.ts:193`) and 「(objectstack-ai#5928, PR objectstack-ai#6575)」 (`audit-hook-object-scope.test.ts:19`) became `commit 69787f0` beside the kept `objectstack-ai#5928`; 「measured on PR objectstack-ai#12143」 (`plugin-keyed-text-bounds.test.ts:21`) became 「measured on commit f64668d」. - **The `objectstack-ai#8707` ruling phrases**, `audit-writers.test.ts:1882` and `:1922`. 「the ORDER the objectstack-ai#8707 ruling set」 became 「the ORDER commit 1408fe3 set」, and 「objectstack-ai#8707's ruling reasons about」 became 「commit 1408fe3 reasons about」: the ruling was the maintainer's on `objectstack-ai#8287`, which stays on those lines, and `1408fe385`'s message carries the reasoning. `audit-writers.ts:1402` 「because objectstack-ai#8707 reordered」 became 「because commit 1408fe3 reordered」, the flip its message states. - **`objectstack-ai#14927`, three lines.** 「the cause measured on objectstack-ai#14927」 became 「the cause commit ab48938 records」 (`audit-writers.ts:789`, `audit-writers.test.ts:1211`), and 「The measured objectstack-ai#14927 misdirection」 became 「The misdirection commit ab48938 records」 (`audit-writers.test.ts:1370`). - **`sys-activity-type-vocabulary.test.ts:91`.** 「Filed as objectstack-ai#8852;」 became 「Commit 51bb277 recorded it;」. - **`comment-access-hooks.test.ts:404-405`.** 「the objectstack-ai#6523 contract's unit is the envelope / and objectstack-ai#6206 forbids」 became 「the unit of commit aa4b90d's contract is the envelope / and the full-envelope ruling forbids」; `comment-access-hooks.ts:222` 「(objectstack-ai#6523 / the objectstack-ai#6206 ruling)」 became 「(commit aa4b90d / the full-envelope ruling)」. - **`audit-writers.test.ts:1648`**, a section rule: the trailing rule was shortened from 10 characters to 2 so the line stays near its old width. `:1653` 「That day is objectstack-ai#8778」 became 「That day came with commit 7901b2d」. - **`read-audit.test.ts:43`.** 「precisely how / objectstack-ai#16829 shipped」 became 「precisely how / the defect fixed by commit 8d4690b shipped」. - **`comment-access-hooks.ts:35`**, the gate-invisible site: 「(objectstack-ai#9719/objectstack-ai#9798 built」 became 「(objectstack-ai#9719/commit c7655d4 built」. ## The 23 sites left - **Source strings, 5 sites**, all `objectstack-ai#11507`: the `sys_activity.type` field's `description` (`objects/sys-activity.object.ts:121`) and its four generated copies (`translations/{en,es-ES,ja-JP,zh-CN}.objects.generated.ts:125`). They are runtime strings, all five are held by the shrink-only `doc-authoring-prose-id` baseline, and the generated files are left as A5 says. They ship in `dist` (see Changeset). - **Test strings, 18 sites**, left as stages 1 to 8 left theirs: - `describe` / `it` titles: `activity-type-vocabulary-enforcement.test.ts:315` (the gate-invisible `[objectstack-ai#8203/objectstack-ai#11507]`), `sys-activity-type-open-vocabulary.test.ts:70` (`objectstack-ai#11507`), `audit-writers.test.ts:1420`, `:1659` (two sites, `objectstack-ai#8707` and `objectstack-ai#8778`) and `:1873` (`objectstack-ai#8707`), `comment-access-hooks.test.ts:690` (`objectstack-ai#9798`), `plugin-keyed-text-bounds.test.ts:90` (`objectstack-ai#11374`), `read-audit-view-instant-preservation.integration.test.ts:121` (`objectstack-ai#16829`); - assertion and hint messages, all `objectstack-ai#11507`: `activity-type-vocabulary-enforcement.test.ts:249`, `:352`, `:355`, `:378`, `:380`, and `sys-activity-type-open-vocabulary.test.ts:83`, `:90`, `:110`, `:152`. - No quoted maintainer ruling in this package carries a dead number. The package's generated `*.source-hashes.generated.ts` headers carry none either (PR objectstack-ai#20656 fixed their producer). ## Mechanical guard: no code token moves The guard compares the TypeScript parser's leaf nodes, with comments as trivia and JSDoc nodes never visited, base `d2820876f` against head. Template literals are therefore read in context. It ran over all 16 touched `.ts` files. - Real run: 19,445 base leaf tokens, **0 files with a token change** (exit 0). - Comment control in `audit-writers.ts` (「the cause commit ab48938 records」 to 「… recorded」): 0 files changed, as expected (exit 0). - Positive control, a code token added in `audit-writers.ts` (`createRecordOrganizationResolver(engine)` given `as any`): DIFFER (exit 1). - Positive control, one digit changed inside a kept test title (`audit-writers.test.ts:1873`, `objectstack-ai#8707` to `objectstack-ai#8708`): DIFFER (exit 1). Every mutation went through `scripts/ablation-replace.mjs`, and each landed (anchor 1 to 0, blob changed). Each restore was proven byte-identical to the HEAD blob (`2dbd2059e8f5`, `8ec28790da22`), with `git diff HEAD` empty and a clean tree afterwards. ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/plugin-audit` (`.changeset/20596-plugin-audit-provenance-anchors.md`) is included. Its body is stage 8's, word for word, with the package name changed. Measured on the built package (A3): `files[]` is `dist`, `README.md` and `CHANGELOG.md`. After the build, part of the rewritten prose reaches `dist`: `c7655d472` twice in each of `dist/index.js` and `index.mjs` and once in each of `index.d.ts` and `index.d.mts` (the `CommentAccessEngine` option docblock is on an exported interface); `88b9d749a` and `f64668d3c` twice, and `1cba33f16` and `8d4690b8f` once, in each JS file (the object-definition comments and a `read-audit.ts` comment). The comments in `audit-writers.ts` and `translations/index.ts` do not reach `dist` (0 for each of their anchors). Positive controls: the unchanged line 「below carries into the contract; this comment carries the reasoning.」, in the same docblock as the shipped rewrite at `sys-activity.object.ts:60`, is found once in each JS file, and the unchanged line beside the shipped rewrite at `comment-access-hooks.ts:77` once in each declaration file. A never-written negative phrase appears nowhere in `dist`. Of the 16 dead numbers, only `objectstack-ai#11507` is left in `dist`, 5 times in each JS file: the kept `description` string and its four generated copies. ## Gates (head `d6e67afa5`) - **Citation judging, as CI runs it:** `pnpm check:issue-citations` (self-test, 114 cases, 8 batteries) exits 0. `node scripts/check-issue-citations.mjs` exits 0: the diff-scoped run judged 11 citations across 6 files, and all 11 resolve (they are the live numbers that already stood on the rewritten lines). - **Doc authoring:** `pnpm check:doc-authoring` exits 0; the sibling-package prose-id baseline holds (808 pinned sites, no growth), which includes the five kept `objectstack-ai#11507` strings. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `d6e67afa5` derived 64 commands: all 57 derived at dispatch, plus `check:dispatcher-error-vocabulary`, `check:engine-double-contract`, `check:objectql-double-limit`, `check:query-options-erasure`, `check:type-check-coverage`, `check:type-check-debt` and `check:where-matcher`. Each ran with its exit code captured before any pipe, and all 64 exit 0. `--ran`, fed each command with its exit code, reports 64 run, 0 NOT MEASURED (a derived zero), 0 unrun, and exits 0. A full `turbo run build` of `./packages/*` and `./packages/*/*` ran first under the shared verify lock (71 of 71 tasks, exit 0), so no gate hit an unbuilt workspace. - The derivation warns that its tree is 3 commits behind `origin/main` and that one input, `scripts/engine-double-contract.pinned.json`, changed there: `main` added one pinned row for `packages/objectql/src/protocol-packaged-dashboard-base.test.ts`, a file outside this diff. The family is in the 64 either way and exits 0 on this tree. - **Roster families the derivation lists outside its commands** (their rosters sit in directories this diff touches): `node scripts/check-changeset-fixed.mjs`, `pnpm check:authz-resolver`, `pnpm check:error-code-casing` and `pnpm check:filter-alias-parity`, each exit 0. - **Tests and typecheck, under the verify lock:** - `pnpm --filter @objectstack/plugin-audit test`: 26 files pass and 366 tests pass. `vitest list --filesOnly` names 26 files, all the tracked test files, the 10 touched ones included. - `pnpm --filter @objectstack/plugin-audit typecheck` exits 0. `tsc --listFiles`: `tsconfig.json` holds the 6 touched source files (19 `src` files; it excludes tests), and `tsconfig.test.json`, which the script's `check:test-typecheck` step compiles, holds all 45 files under `src/`, all 16 touched files included. - **Lint, as a proven narrowing:** `eslint --no-inline-config --format json` over the 16 touched `.ts` files gives 16 files, 0 errors and 0 warnings. All 16 are in eslint's own population (`isPathIgnored` is false for each; a `dist` file, as the control, is ignored). `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, as its own lines 327-328 state), so a comment edit here 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 17 changed files for control bytes finds none. ## Acceptance notes - **The gate-invisible spellings, grepped as the claim asked.** `CITATION_RE` refuses a hyphen after the digits and a `/` before the `#` (objectstack-ai#20636), and `NON_CITATION_HEADS` excuses a number after the word 「option」. In this package: - `#N-word`: none. - `#A/#B`: 11 lines, the claim's 11, over 14 distinct numbers. Two second numbers are dead: `objectstack-ai#9798` in `comment-access-hooks.ts:35`, rewritten, and `objectstack-ai#11507` in the test title `activity-type-vocabulary-enforcement.test.ts:315`, left as a string. The other 12 numbers resolve. - `option #N`: none. The raw scan agrees: nothing dead beyond the gate is left outside a kept string. - **The kept `description` string is a runtime string with a dead number.** `sys_activity.type`'s `description` ships to the metadata API, the i18n bundles and `dist`, and ends 「(maintainer ruling 2026-08-24, objectstack-ai#11507)」. It and its four generated copies are held by the `doc-authoring-prose-id` baseline, so they belong to the runtime-string lane (form D), not to this stage, as stages 1, 2 and 4 left theirs. - **「This card」 phrases are left.** 46 lines in 21 files of this package speak of 「this card」, 「that card」 or 「the card」. They carry no number and neither instrument sees them. Two were rewritten here because the rewrite on their own line removed their referent (`sys-activity.object.ts:60`, `sys-activity-type-open-vocabulary.test.ts:14`); the rest are unchanged, as in stage 8. - **Dead `objectstack-ai#11507` and `objectstack-ai#11374` outside the census surface.** `docs/qa/platform-checklist/areas/records-forms.json` (4 lines) and `docs/audits/gate-census-2026-09.md` (1 line) cite them as evidence. `docs/` is outside this stage's surface; noted for objectstack-ai#20556, the carrier of dead citations outside `packages/spec/src`. - **The census instrument did not truncate in this stage.** Both enumerations read 186 pages at the newest frontier. - **Anchors the next stages can reuse**, each checked here: `objectstack-ai#16829` → `8d4690b8f`; `objectstack-ai#6575` → `69787f07b`; `objectstack-ai#14927` → `ab489388b`; `objectstack-ai#8852` → `51bb277ef`; `objectstack-ai#9798` → `c7655d472`; `objectstack-ai#11507` → `88b9d749a`. - **Base.** The branch is on `main` at `d2820876f`. `main` has since moved three commits (`f05919b82`, `99786f930`, `1940afdaf`). They touch `packages/spec`, `packages/metadata-protocol`, one new `packages/objectql` test file, a design doc, three changesets and `scripts/engine-double-contract.pinned.json` (one added row for that test file), and no file under `plugin-audit`, `scripts/check-issue-citations.mjs` or `.changeset/config.json`, so no merge was taken; the merge queue rebuilds on the merged generation. --- _Generated by [Claude Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…kages/plugins/plugin-hono-server/src to the commits that decided them (objectstack-ai#20741) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 10 of the `domain:cli` lane of the dead-citation sweep: `packages/plugins/plugin-hono-server/src`. Every comment site there that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), the commit in this repository's history that decided what the line describes, and keeps saying in its own words what that commit decided. PR objectstack-ai#20533 is the method, and stages 1 to 9 of this card (PR objectstack-ai#20624, PR objectstack-ai#20632, PR objectstack-ai#20656, PR objectstack-ai#20673, PR objectstack-ai#20689, PR objectstack-ai#20703, PR objectstack-ai#20713, PR objectstack-ai#20723, PR objectstack-ai#20735) are the precedents. The card stays open for the lane's remaining packages, so this PR says `Part of`. That is **24 sites on 24 lines in 5 files, covering 5 numbers**, rewritten to **5 distinct commits**: - the census's **5 sites**: `src/adapter.ts` 4, `src/current-user-endpoints.ts` 1 (4 numbers); - **19 test-file comment sites** in 3 test files (the census defers `*.test.ts`; stages 1 to 9 took test comments too): `ui-plugin-auto-discovery.pin.test.ts` 16, `handler-throw-declared-envelope.test.ts` 2, `current-user-endpoints-localization.test.ts` 1. Only comments changed: **24 lines out, 24 in**, every one of them a site (no companion line), and every touched file keeps its line count (1,660 / 1,020 / 335 / 403 / 697), so no line citation into these files moves. **No citation number is added**: over the 24 line pairs, the added numbers are a subset of the removed ones (`objectstack-ai#16599` x2, `objectstack-ai#9864`, `objectstack-ai#16334`, all answering 200, stay where they stood), and no PR number stands on an added line. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records any of these 5 decisions (a grep for the 5 numbers there reads 0 hits; the control number `objectstack-ai#7329` reads 1 in the same tree), so every anchor is a commit. A **`patch` changeset** for `@objectstack/plugin-hono-server` rides along, because one rewritten comment reaches `dist` (measured below). That is stage 6's and stage 9's case (PR objectstack-ai#20703, PR objectstack-ai#20735), not stages 5 and 7's. ## Census: `packages/plugins/plugin-hono-server`, before and after **Instrument.** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged, run under `with-fleet.sh --read` for the token. The count is its `allocated-but-absent` findings under `packages/plugins/plugin-hono-server/`. Both runs enumerated the whole board. | reading | tree | board | whole-repo `allocated-but-absent` | package sites | lines | numbers | files | |---|---|---|---|---|---|---|---| | before | base `f927864ea0`, run 2026-09-29T23:42:29Z to 23:46:56Z | enumerated, 186 pages, frontier objectstack-ai#20735, 18,562 numbers | 1,105 | **5** | 5 | 4 | 2 | | after | `91ce7e5e8f`, run 23:58:22Z to 2026-09-30T00:02:19Z | enumerated, 186 pages, frontier objectstack-ai#20737, 18,564 numbers | 1,100 | **0** | 0 | 0 | 0 | The whole-repo drop of 5 is exactly these sites: a site-by-site diff of the two JSON outputs has 5 findings gone (`adapter.ts:225`, `:227`, `:308`, `:349`; `current-user-endpoints.ts:448`) and none added. The other three tallies (`resolves` 33,003, `resolves-as-pull-request` 1,984, `cross-repo-unjudged` 995) are equal in both runs. `packages/plugins/plugin-hono-server` is byte-identical at `91ce7e5e8f` and at the head. **Supplementary scan (test files, strings and files outside `src/` included).** The gate's exported `extractCitations` and `classifyCitation` over all 41 tracked files of the package (`CHANGELOG.md` excluded), comment-prose and whole-file projections, with the board from the gate's own `probeBoard`: 347 citations and 32 dead before, 323 and 8 after. Under `src/`: comments 5 dead to 0, test comments 19 to 0, strings 0 and test strings 2 unchanged. Its before list of `src/` comment sites equals the census's. The 8 left are 2 test strings and 6 sites outside `src/` (see Acceptance notes). ## Per-site table `git blame` at the base ties each line to the commit that wrote it, and each anchor was read in its message, changeset or diff, not only its subject. | number | sites (base line) | anchor: what it decided | |---|---|---| | `objectstack-ai#13279` | `adapter.ts:225`, `:227`; `handler-throw-declared-envelope.test.ts:84`; `current-user-endpoints-localization.test.ts:90` | `6a180e42d`: `tryFind` in `resolveAuthzContext` raises `AuthzStoreUnavailableError` (503 `SERVICE_UNAVAILABLE`) when a permission-store read is issued and throws, instead of answering it as an empty read, and each fail-closed transport `catch` (`requireDatasourceAdmin` in `service-datasource` among them) re-raises it: an unreadable store licenses no verdict, the maintainer's 2026-08-30 ruling recorded in its message. The first three lines blame to `cefe068702` (the declared-envelope rendering, PR objectstack-ai#17412) and the fourth to `5f7fa1de0`; both wrote them citing this ruling. PR objectstack-ai#13475 (200) names objectstack-ai#13279. Stages 1, 2, 4 and 9 gave the number this anchor. | | `objectstack-ai#9934` | `adapter.ts:308`; `handler-throw-declared-envelope.test.ts:152` | `79c46da90`: the producer-side user-facing marking for hook refusals, the `userMessage` channel, a text field a producer sets at throw time and every classified envelope carries. Both lines blame to `cefe068702`. The PR that landed it (PR objectstack-ai#9992) answers 404 too. Stages 1, 2, 4 and 6 gave the number this anchor. | | `objectstack-ai#6307` | `adapter.ts:349` | `293476148`: refuse a repeated `?version=` on `GET`/`DELETE /packages/:id` rather than pick one value, through `readSingleQueryValue`, which it introduces. The line blames to `7cdbcbb306` (surface repeated query parameters as arrays, PR objectstack-ai#7396), which says it follows that direction. Stages 2 and 8 gave the number this anchor. | | `objectstack-ai#6216` | `current-user-endpoints.ts:448` | `f586f1a89`: one `ExecutionContext` assembler with two named anonymous entries, `assembleExecutionContext` the default, fail-closed one and `assembleExecutionContextOrGuest` the explicit guest one, the maintainer's 2026-08-08 Option A recorded in its docblock. The line blames to `6615a024c3` (the current-user faces adopt the shared assembler). Stages 1, 2 and 7 gave the number this anchor. | | `objectstack-ai#16721` | `ui-plugin-auto-discovery.pin.test.ts:27`, `:37`, `:42`, `:180`, `:211`, `:217`, `:360`, `:363`, `:495`, `:498`, `:594`, `:596`, `:604`, `:608`, `:631`, `:646` | `51ae73123`: `LiteKernel.use()` runs the same `assertPluginContract` as `ObjectKernel.use()` and refuses the same plugin objects with the same envelope, the maintainer's 2026-09-08 option A (the kernels converge) recorded in its changeset. 15 lines blame to it; `:180` blames to `3c48234b3`, which re-wrapped that sentence and keeps its fact. Its `lite-kernel.ts` docblock records the measurement taken before converging, which `:604` describes ("before commit 51ae731"). `:363`, `:498` and `:631` said the `hono-plugin.ts` question was "noted on" the dead number; that note is the text this commit wrote into this file, so they now say "raised with" / "recorded with" it. New anchor; no other package has re-anchored this number yet. | **Anchor checks.** Every cited sha matches exactly one object (`git rev-parse --disambiguate`, count 1 for each of the 5), is a commit, has one parent, and is an ancestor of `main` (`merge-base --is-ancestor` against `f927864ea0`, exit 0 for all 5). The checkout is not shallow. The control leg `2672f855fa` (2026-08-09, the parent of the oldest anchor `293476148`) exits 0 against `origin/main`, and the negative control, this branch's own head, exits 1. Four anchors reuse the landed stages' (`6a180e42d`, `79c46da90`, `293476148`, `f586f1a89`), so each number carries one anchor across the tree; one is new (`51ae73123`). **Numbers.** All 5 dropped numbers answer 404 by REST (probed 2026-09-30T00:14:17Z). The numbers kept on or beside the changed lines answer 200: `objectstack-ai#16599`, `objectstack-ai#9864`, `objectstack-ai#16334`, `objectstack-ai#16363`, `objectstack-ai#16049`, `objectstack-ai#6878`, `objectstack-ai#3867`, `objectstack-ai#8086`, `objectstack-ai#16545`, `objectstack-ai#15999`, `objectstack-ai#5090`. `packages/plugins/plugin-hono-server/src` has no slash-joined `#A/#B` without spaces; the spaced pairs (`objectstack-ai#3867 / objectstack-ai#8086`, `objectstack-ai#2408 / objectstack-ai#3361`) are read by the grammar and every half answers 200. ## Mechanical guard: no code token moves **H2 holds on the parser-token reading; the emitted `dist` is NOT byte-identical, because one rewritten `//` comment sits inside a returned object literal and the bundler keeps it.** **Token guard.** It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, `getChildren` walk, JSDoc nodes excluded) of the 5 touched files at base `f927864ea0` and at the head. Controls mutate the head text in memory only. - Real run: 15,054 base tokens (4,831 / 2,134 / 3,559 / 2,363 / 2,167), 0 differing, exit 0. - Comment-insertion control: 0 differing, exit 0. - Code-insertion control: all 5 files differ, exit 1. - String control (the first character of the first import specifier flipped in each file): exactly 1 differing `StringLiteral` per file, exit 1. All 48 changed lines (24 out, 24 in) are `//` or `*` comment lines. **Emitted `dist`.** `pnpm --filter @objectstack/plugin-hono-server build` at the head, then at base (the base blobs of the 5 touched files restored in place under a trap-armed restore; an on-disk probe read `objectstack-ai#9934` 1 and `commit 79c46da` 0 in `adapter.ts` before that build; afterwards every touched blob equals its HEAD blob, `git diff HEAD` is empty and the status is clean), with the same dependency builds: - `index.js` and `index.mjs` differ, in one line each: the `adapter.ts:308` comment, `refusal text (objectstack-ai#9934)` at base and `refusal text (commit 79c46da)` at head. `index.d.ts`, `index.d.mts` and both `.map` files are equal. No docblock of this diff reaches the declaration files. - The same parser comparison over the two differing files reads identical tokens (10,818 in `index.js`, 10,521 in `index.mjs`), so the whole `dist` delta is comment text. Its code control (a code line appended) reads COUNT/TOKENS DIFFER in each. - Code-mutation control (`scripts/ablation-replace.mjs`, wrap mode, anchor `message: 'No response from handler' }` hit 1 to 0, planted marker 0 to 1, blob `6a0c10f76282` to `d5223196afeb`; `scripts/ablation-dist-preflight.mjs` found the marker in `index.js` and `index.mjs`): `index.js`, `index.mjs` and both `.map` files differ from the head build. The blob was restored to HEAD `6a0c10f76282` with `git diff HEAD` empty, `dist` was rebuilt, its six sha256 values equal the first head build, and the preflight in `--absent` mode reads the marker absent from all 6 files with a clean tree. A raw scan of the 6 changed files for ASCII control bytes finds none, and `check:nul-bytes` exits 0. ## Changeset **`patch` for `@objectstack/plugin-hono-server`** (`.changeset/plugin-hono-server-provenance-anchors.md`), in PR objectstack-ai#20632's form. The package's `files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the build above emits different `index.js` / `index.mjs` at base and head, so this diff publishes. `check-changeset-no-major`, `check-empty-changeset`, `check-adr-0087-registration` and `check-changeset-fixed` all exit 0. ## Gates (head `03e5f4c0fd`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its official wording, verbatim (printed by every run; the command line differs per run and is listed in the verdicts below): > **Declared narrowing — verification ran UNLOCKED.** `scripts/pm/os-verify-lock.sh` > could not take the shared verify lock on this host: no usable `flock`. The shared > verify lock is declared Linux-only (`flock` is util-linux, and a stock macOS does > not ship it), so the command below was run directly, without the lock — > a declared narrowing, not a silent one. No serialization guarantee held for this > run, nor for any sibling agent in this container while it ran. Its verdict line from each run (the closure build and the three `dist` builds at `feaf0c9b73`, whose `packages/plugins/plugin-hono-server` is byte-identical to this head; the first whole-workspace build, tests and typecheck at `91ce7e5e8f`; the second whole-workspace build, tests and typecheck at this head after the merge; the scratch-script paths shortened to `SCRATCH`): ```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 27s · declare it in the PR body · pnpm --workspace-concurrency=2 --filter '@objectstack/plugin-hono-server...' 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 3s · declare it in the PR body · bash SCRATCH/base-build.sh SCRATCH 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 3s · declare it in the PR body · node scripts/ablation-replace.mjs --file packages/plugins/plugin-hono-server/src/adapter.ts --anchor "message: 'No response from handler' }" --replacement "message: 'No response from handler ABLMARK20594S10' }" -- bash SCRATCH/mut-inner.sh SCRATCH 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 3s · declare it in the PR body · pnpm --filter @objectstack/plugin-hono-server 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 12s · declare it in the PR body · pnpm --filter @objectstack/plugin-hono-server exec vitest run --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 17s · declare it in the PR body · pnpm --filter @objectstack/plugin-hono-server typecheck 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 118s (1m58s) · declare it in the PR body · pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=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 118s (1m58s) · declare it in the PR body · pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=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 11s · declare it in the PR body · pnpm --filter @objectstack/plugin-hono-server exec vitest run --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 16s · declare it in the PR body · pnpm --filter @objectstack/plugin-hono-server typecheck ``` - **Build:** `@objectstack/plugin-hono-server` with its closure (7 of 81 workspace projects), then the whole workspace, `turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2`, 71 of 71 tasks, before and again after the merge. The tree was clean after each, and the package's six `dist` files after each whole build equal the first head build by sha256. - **Tests:** `vitest run --maxWorkers=2`: 27 files, 324 tests passed (every `*.test.ts` under `src/`), at this head and at `91ce7e5e8f`. - **Typecheck:** `pnpm --filter @objectstack/plugin-hono-server typecheck` exits 0 at this head and at `91ce7e5e8f` (`tsc --noEmit`, `tsc --noEmit -p tsconfig.typecheck.json`, and `check:test-typecheck` OK with 0 files / 0 errors / 0 pinned signatures). `--listFiles`: `tsconfig.json` and `tsconfig.test.json` each compile 33 `src/` files including all 27 tests and all 5 touched files. - **Spec artifacts:** `origin/main` brought a `packages/spec` change, so `pnpm --filter @objectstack/spec check:generated` ran after the rebuild: "All 15 generated artifacts are up to date" (exit 0). - **Lint:** the repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at this head (2026-09-30T00:25:09Z to 00:25:36Z), and at `91ce7e5e8f`. - **Citation judging:** after merging `origin/main` (`fbec216e2d`), `node scripts/check-issue-citations.mjs --base origin/main` reports "no issue citations added against fbec216 (2 file(s) read)" (exit 0). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 63 families, the same list at `91ce7e5e8f` and at this head. All 63 exit 0 at this head in one pass, and `--ran` with the exit-coded record reads "63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them: `check:issue-citations`, `check:doc-authoring`, `check:nul-bytes`, `check:published-files`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:type-check-debt`, `check-adr-0087-registration`, `check-empty-changeset`. - **Artifact rosters:** 36 of the 39 non-self-test roster rows exit 0 at this head, including the four the derivation marks as keeping their roster under one of this diff's paths (`check-changeset-fixed`, `check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`). The other three need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 self-test-only rows grade their checkers' fixtures and cannot judge this diff. ## Hypotheses (measured first) - **H0 holds.** At base `f927864ea0` the filtered census answers 5 sites on 5 lines, 4 numbers, 2 files, as on the seat's `0be898499f`. The whole-repo count is 1,105. - **H1 holds.** After the rewrite, the filtered census answers 0 for `packages/plugins/plugin-hono-server`. No site was left for an open PR (the file lists of all open PRs were read at 2026-09-29T23:48:36Z, 6 PRs, and again at 2026-09-30T00:15:14Z, 9 PRs: only the Version Packages PR objectstack-ai#20639 touches the package, in `CHANGELOG.md` and `package.json`) or for an unfound anchor. - **H2 holds on the token reading, not on the `dist` reading.** The parser leaf-token diff of all 5 touched files is empty with its controls firing. The emitted `dist` differs in one comment line of `index.js` and of `index.mjs`, token-identical with a code control. That is why the changeset ships. ## Acceptance notes - **Strings, the form-D stage.** One dead number remains in a string literal in `packages/plugins/plugin-hono-server/src`: `objectstack-ai#16721` at the end of the group-F `describe` title of `ui-plugin-auto-discovery.pin.test.ts` (`:635`, a test title, no assertion text). It stays on the card for its form-D stage; no string moved here. The supplementary scan's second test-string hit, `:111` (`'.os-pin{color:#123456}'`), is a CSS hex colour in a fixture, not a citation: the whole-file projection reads it as a six-digit number, while the census blanks strings and defers test files. - **Outside `src/**`, a later stage of the card:** `objectstack.config.ts:19` (`objectstack-ai#11332`) and `:26` (`objectstack-ai#10724`), `tsconfig.test.json:3` and `:61` (`objectstack-ai#13176`), `tsconfig.typecheck.json:12` (`objectstack-ai#11332` and `objectstack-ai#10724`; `objectstack-ai#4914` in the same group answers 200). The other citations in the package outside `src/**` (`CHANGELOG.md` excluded) answer 200: `tsconfig.test.json` (`objectstack-ai#14062`, `objectstack-ai#5286`, `objectstack-ai#5449`, `objectstack-ai#12542`), `tsconfig.typecheck.json` (`objectstack-ai#13284`, `objectstack-ai#5475`, `objectstack-ai#10756`), `vitest.config.ts` (`objectstack-ai#10374`, `objectstack-ai#9457`, `objectstack-ai#7378`; `objectstack-ai#8129` resolves as a pull request). `README.md` carries none. - **An open question now lives only in this file.** `hono-plugin.ts:521` and `:523` still carry the `&& plugin.staticPath` conjunct and the `plugin.slug || plugin.name.split('/').pop()` derivation that, since `51ae73123`, neither published kernel's `use()` lets an input reach. The pin file says so and leaves the call to `hono-plugin.ts`; the tracker note it pointed at is gone, so this file's text (and commit `3c48234b3`'s message) are the record. Unreachable defensive code, not a defect: noted, not filed. - **Card-word residue, cited nowhere.** `handler-throw-declared-envelope.test.ts` still says "before this card" (`:85`) and "the card" (`:19`, `:32`) around its rewritten lines. They cite no dead number, so they were left, as the landed stages left theirs. - **The moving `origin/main`.** The branch merged `origin/main` once (`03e5f4c0fd`, merging `fbec216e2d`: the ADR-0087 migration chain moves to `@objectstack/spec/migrations`). `packages/spec` is in this package's dependency closure, so the workspace was rebuilt and the package's tests, typecheck and every gate above were rerun at the merge head; nothing in `packages/plugins/plugin-hono-server` changed. ## Deviations - **Three derived gates first read NOT MEASURED.** `check:dual-build-cjs-loads`, `check:lean-entry-closure` and `check:type-check-debt` exited 3 (PREREQUISITE NOT MET: built output absent) in the first pass, before the whole-workspace build. Rerun after it, each exits 0, and all 63 exit 0 in the single pass at this head. - **The first `check:generated` run was void.** This host's global `pnpm` is a v11 front end that rejects the `-s` each sub-gate passes, so all 15 rows read "unexpected argument '-s'" (exit 1, nothing measured). Rerun with the real pnpm 10.31 binary first on `PATH`, it reads all 15 up to date (exit 0). - **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 harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. 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>
…kages/create-objectstack/src to the commits that decided them (objectstack-ai#20748) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 11 of the `domain:cli` lane of the dead-citation sweep: `packages/create-objectstack/src`. Every comment site there that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), the commit in this repository's history that decided what the line describes, and keeps saying in its own words what that commit decided. PR objectstack-ai#20533 is the method, and stages 1 to 10 of this card (PR objectstack-ai#20624, PR objectstack-ai#20632, PR objectstack-ai#20656, PR objectstack-ai#20673, PR objectstack-ai#20689, PR objectstack-ai#20703, PR objectstack-ai#20713, PR objectstack-ai#20723, PR objectstack-ai#20735, PR objectstack-ai#20741) are the precedents. The card stays open for the lane's remaining packages, so this PR says `Part of`. That is **25 sites on 25 lines in 10 files, covering 9 numbers**, rewritten to **8 distinct commits**: - the census's **3 sites**: `src/banner.ts` 2, `src/index.ts` 1 (2 numbers); - **22 test-file comment sites** in 8 test files (the census defers `*.test.ts`; stages 1 to 10 took test comments too): `starter-comments-self-contained.test.ts` 9, `scaffold-e2e-boot-probe.test.ts` 3, `banner-version.test.ts` 2, `blank-readme-validate-disclosure.test.ts` 2, `scaffold-next-steps-pm.test.ts` 2, `template-consistency.test.ts` 2, `scaffold-skills-single-copy.test.ts` 1, `template-ci-workflow.test.ts` 1. Only comments changed: **25 lines out, 25 in**, every one of them a site (no companion line), and every touched file keeps its line count (147 / 67 / 58 / 617 / 910 / 261 / 357 / 328 / 221 / 745), so no line citation into these files moves. **No citation number is added**: the added lines carry no tracker number at all, and no PR number stands on an added line. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records any of these 9 decisions (a grep for the 9 numbers there reads 0 hits; the control number `objectstack-ai#7329` reads 2 in the same tree), so every anchor is a commit. **No changeset; `skip-changeset`.** The rewritten comments do not reach the published `dist` (measured below), as in stages 5 and 7 (PR objectstack-ai#20689, PR objectstack-ai#20713). **Scaffold output is untouched.** No site sits inside a template literal or in a file the scaffolder copies: `src/templates/**` carries zero tracker citations in either projection, and all 25 sites are `//` or JSDoc comment prose outside any string. A real scaffold run at base and at head emits a byte-identical project (below). ## Census: `packages/create-objectstack`, before and after **Instrument.** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged, run under `with-fleet.sh --read` for the token. The count is its `allocated-but-absent` findings under `packages/create-objectstack/`. Both runs enumerated the whole board. | reading | tree | board | whole-repo `allocated-but-absent` | package sites | lines | numbers | files | |---|---|---|---|---|---|---|---| | before | base `01e78dceef`, run 2026-09-30T01:14:08Z to 01:19:48Z | enumerated, 186 pages, frontier objectstack-ai#20742, 18,569 numbers | 1,077 | **3** | 3 | 2 | 2 | | after | `4ed638093d`, run 01:30:22Z to 01:35:31Z | enumerated, 186 pages, frontier objectstack-ai#20745, 18,572 numbers | 1,074 | **0** | 0 | 0 | 0 | The whole-repo drop of 3 is exactly these sites: a site-by-site diff of the two JSON outputs has 3 findings gone (`banner.ts:10`, `banner.ts:17`, `index.ts:441`) and none added. The other three tallies (`resolves` 33,014, `resolves-as-pull-request` 1,984, `cross-repo-unjudged` 995) are equal in both runs. `packages/create-objectstack` is byte-identical at `4ed638093d` and at the head (the one merge brought no file under it). **Supplementary scan (test files, strings and files outside `src/` included).** The gate's exported `extractCitations` and `classifyCitation` over all 53 tracked files of the package (`CHANGELOG.md` excluded), comment-prose and whole-file projections, with the board from the gate's own `probeBoard`: 77 citations and 33 dead before, 52 and 8 after. Under `src/`: comments 3 dead to 0, test comments 23 to 1, test strings 7 unchanged; `src/templates/**` 0 citations of any kind. Outside `src/`, one citation (`vitest.config.ts:24`, `objectstack-ai#10374`) answers 200. Its before list of `src/` comment sites equals the census's. The 8 left are 7 test strings and 1 test comment with no deciding commit (see "The site left" and Acceptance notes). ## Per-number table `git blame` at the base ties each line to the commit that wrote it, and each anchor was read in its message, changeset or diff, not only its subject. | number | sites (base line) | anchor: what it decided | |---|---|---| | `objectstack-ai#10325` | `banner.ts:10`; `banner-version.test.ts:3` | `cec9d239d`: the startup banner reads the real version from `package.json` through the new `renderVersionBanner()`, and sizes the box from the version's plain length, widening and never truncating, instead of the hardcoded `v6.x`. Both lines blame to it; its message carries the closing trailer for this number. New anchor. | | `objectstack-ai#10322` | `banner.ts:17`; `index.ts:441`; `banner-version.test.ts:17`; `blank-readme-validate-disclosure.test.ts:3`, `:50`; `scaffold-next-steps-pm.test.ts:3`, `:7` | `8d21f7a76`: detect the package manager once, up front, and name it in the install line, the install-failure remedy and every "Next steps" line (labels padded to the longer of the two instead of hand-kerned for `npm`), and name `validate` in the blank README's "Getting started". Its message carries the closing trailer for this number. `index.ts:441` and the two test headers blame to it; `banner.ts:17` and `banner-version.test.ts:17` blame to `cec9d239d`, whose message calls this "the sibling bug fixed one function away in the same file"; `scaffold-next-steps-pm.test.ts:7` blames to `c6c7feccd`, a re-wrap that keeps the sentence. New anchor. | | `objectstack-ai#19424` | `scaffold-e2e-boot-probe.test.ts:397`, `:679`, `:816` | `c27e16059`: the boot-probe neighbour announces its own listener (or its bind error), asks the kernel for its port with `listen(0)`, and the harness names five distinct outcomes instead of one "never came up"; the controls block pins each. All three lines blame to it; its message carries the closing trailer for this number. New anchor. | | `objectstack-ai#16331` | `scaffold-skills-single-copy.test.ts:3` | `fd75728bc`: install the skills bundle for one agent (`--skill '*' --agent claude-code -y`) so a scaffolded project's first commit stages it once, with no symlinks. The line blames to it, and its diff is what added the number; its message names none. New anchor. | | `objectstack-ai#10990` | `starter-comments-self-contained.test.ts:41`, `:283` | `21756b325`: converge the shipped template files on the ruled canonical docs origin and pin that convergence as assertion 4 over `shippedFiles()`. Both lines blame to it; its message carries the closing trailer for this number. New anchor for this number. | | `objectstack-ai#11022` | `starter-comments-self-contained.test.ts:50`, `:91`, `:122`, `:221` | `21756b325`: rewrite the blank README's two monorepo-only references, add the fifth `MONOREPO_ONLY` pattern (the framework's own name next to a "repo" word), retire the self-retiring `EXCLUDED` entry and add the README's two RATIONALE facts. All four lines blame to it. Stage 3 (PR objectstack-ai#20656) gave this number the same anchor. | | `objectstack-ai#15150` | `starter-comments-self-contained.test.ts:72`, `:133`, `:141` | `cc986c913`: the sixth `MONOREPO_ONLY` pattern, for a reference written as a relative path that climbs out of the project, anchored on bare `../` rather than on a depth judgement. All three lines blame to it; its diff is what added the number (8 times, across both scaffolders' pins), its message names none. New anchor. | | `objectstack-ai#16330` | `template-ci-workflow.test.ts:3`; `template-consistency.test.ts:376` | `4998efa71`: ship `.github/workflows/ci.yml` in the blank template (the template's first dot-directory) so a scaffolded project has gates from its first push. Both lines blame to it; its diff added the number, its message names none. New anchor. | | `objectstack-ai#10326` | `template-consistency.test.ts:498` | `675ab574e`: declare the two benign peer skews a clean first install reported as scoped pnpm `allowedVersions` inside the scaffold. The line blames to it. Stage 3 (PR objectstack-ai#20656) gave this number the same anchor. | **Anchor checks.** Every cited sha matches exactly one object (`git rev-parse --disambiguate`, count 1 for each of the 8), is a commit, has one parent, and is an ancestor of `main` (`merge-base --is-ancestor` against `01e78dceef`, exit 0 for all 8). The checkout is not shallow. The control leg `2aca1bc4c0` (the parent of the oldest anchor `675ab574e`, 2026-08-20) exits 0 against the base, and the negative control (the base as an ancestor of `675ab574e`) exits 1. Two anchors reuse the landed stages' (`21756b325`, `675ab574e`); six are new. **Numbers.** All 9 dropped numbers answer 404 by REST (probed 2026-09-30T01:11:14Z and again at 01:50:21Z). The one number kept on a line beside the changed ones, `objectstack-ai#9779` (`scaffold-e2e-boot-probe.test.ts:673`), answers 200. The anchor commits' own PR numbers are not cited: three of them (objectstack-ai#11030, objectstack-ai#11013, objectstack-ai#11191) answer 404 as well, which is the reason the ruling cites commits. ## The site left **No deciding commit (1 site, a test comment, so not in the census):** `template-consistency.test.ts:153` (`objectstack-ai#11048`): "admitting them is a support decision (objectstack-ai#11048), not a value to drift here". The number names an open support decision (whether to admit pnpm 10.0 to 10.4). The only commit naming it, `568de194e`, files it unassigned; no later commit decides it, and the floor is still pnpm 10.15 or later at the base. Stage 3 (PR objectstack-ai#20656) left the sibling site `packages/cli/src/commands/init.ts:267` for the same reason. ## Mechanical guard: no code token moves, and nothing emitted moves **H2 holds on both readings: the parser-token diff is empty, and the emitted `dist` and the scaffolded project are byte-identical.** **Token guard.** It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, `getChildren` walk, JSDoc nodes excluded) of the 10 touched files at base `01e78dceef` and at `4ed638093d`. Controls mutate the head text in memory only. - Real run: 16,198 base tokens, 0 files differing, exit 0. - Comment-insertion control: 0 differing, exit 0. - Code-insertion control: all 10 files differ, exit 1. - String control (the first character of the first import specifier flipped in each file): all 10 files differ, first differing kind `StringLiteral`, exit 1. All 50 changed lines (25 out, 25 in) are `//` or `*` comment lines. **Emitted `dist`.** `pnpm --filter create-objectstack build` at base (before any edit) and at `4ed638093d`, after the same dependency build. All 24 `dist` files (`index.js`, `chunk-ZIUW7UEA.js`, `created-summary.js`, `created-summary.d.ts` and the 20 copied template files) have equal sha256 at base and head, and `diff -r` is empty. None of the dead numbers appears in the base `dist` at all: tsup drops these comments. - Code-mutation control (`scripts/ablation-replace.mjs`, wrap mode, anchor `Dependency installation failed.` hit 1 to 0, planted marker 0 to 1, blob `b68538942c96` to `860de8778f10`; `scripts/ablation-dist-preflight.mjs` found the marker in `dist/index.js`): `index.js` differs from the head build. The blob was restored to HEAD `b68538942c96` with `git diff HEAD` empty, `dist` was rebuilt, the preflight in `--absent` mode reads the marker absent from all 24 files with a clean tree, and the 24 sha256 values equal the first head build. - The whole-workspace builds (below) left `create-objectstack`'s `dist` equal to the same 24 values. **Scaffold output.** `node packages/create-objectstack/bin/create-objectstack.js demo-app --skip-install --skip-skills`, run in an empty directory from the base build and again from the head build: both emit the same 21 files with equal sha256, `diff -r` is empty, and the printed output differs only in the absolute target directory line. A raw scan of the 10 changed files for ASCII control bytes finds none (a positive probe on a scratch file with one such byte reads 1), and `check:nul-bytes` exits 0. ## Changeset **None; `skip-changeset`.** The package's `files[]` is `dist`, `README.md` and `CHANGELOG.md`; the build above emits a byte-identical `dist` at base and head, and the code-mutation control proves that build does move when code moves. The two other shipped files are untouched, so this diff publishes nothing. ## Gates (head `a84b73af13`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its official wording, verbatim (printed by every run; the command line differs per run and is listed in the verdicts below): > **Declared narrowing — verification ran UNLOCKED.** `scripts/pm/os-verify-lock.sh` > could not take the shared verify lock on this host: no usable `flock`. The shared > verify lock is declared Linux-only (`flock` is util-linux, and a stock macOS does > not ship it), so the command below was run directly, without the lock — > a declared narrowing, not a silent one. No serialization guarantee held for this > run, nor for any sibling agent in this container while it ran. Its verdict line from each run (the closure build and the base build at `01e78dceef`; the head build, the first whole-workspace build, the tests, the boot-probe file and the typecheck at `4ed638093d`; the second whole-workspace build, tests and typecheck at this head after the merge): ```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 22s · declare it in the PR body · pnpm --workspace-concurrency=2 --filter 'create-objectstack^...' 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 2s · declare it in the PR body · pnpm --filter create-objectstack 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 1s · declare it in the PR body · pnpm --filter create-objectstack 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 134s (2m14s) · declare it in the PR body · pnpm exec turbo run build --filter=./packages/* --filter=./packages/*/* --concurrency=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 create-objectstack exec vitest run --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 2s · declare it in the PR body · pnpm --filter create-objectstack exec vitest run --maxWorkers=2 src/scaffold-e2e-boot-probe.test.ts 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 2s · declare it in the PR body · pnpm --filter create-objectstack typecheck 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 35s · declare it in the PR body · pnpm exec turbo run build --filter=./packages/* --filter=./packages/*/* --concurrency=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 7s · declare it in the PR body · pnpm --filter create-objectstack exec vitest run --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 2s · declare it in the PR body · pnpm --filter create-objectstack typecheck ``` - **Build:** `create-objectstack`'s dependency closure (`@objectstack/spec`, its only workspace dependency), then the package, then the whole workspace, `turbo run build --filter=./packages/* --filter=./packages/*/* --concurrency=2`, 71 of 71 tasks, before and again after the merge. The tree was clean after each. - **Tests:** `vitest run --maxWorkers=2`: 16 files, 247 tests: 233 passed and 14 skipped, at this head and at `4ed638093d`. The 14 skipped are the whole of `scaffold-e2e-boot-probe.test.ts` (run alone: 1 file skipped, 14 tests skipped), which its own `RUNNABLE` gate (`process.platform === 'linux'`, plus `bash`, `curl`, `openssl`) skips on this macOS host. **NOT MEASURED locally: `scaffold-e2e-boot-probe.test.ts`, reason: Linux-only by its own gate; CI runs it.** Its diff is 3 comment lines with identical parser tokens. - **Typecheck:** `pnpm --filter create-objectstack typecheck` (`tsc --noEmit`) exits 0 at this head and at `4ed638093d`. `--listFiles` reaches 26 `src/` files outside `src/templates/`, including all 16 tests and all 10 touched files. - **Spec artifacts:** not run. Neither `origin/main`'s one incoming commit nor this diff touches `packages/spec`. - **Lint:** the repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at this head (2026-09-30T02:00:09Z to 02:00:43Z), and at `4ed638093d` (01:49:31Z to 01:50:04Z). - **Citation judging:** after merging `origin/main` (`697845d19f`), `node scripts/check-issue-citations.mjs --base origin/main` reports "no issue citations added against 697845d (2 file(s) read)" (exit 0). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 52 families, the same list at `4ed638093d` and at this head. All 52 exit 0 at this head in one pass, and `--ran` with the exit-coded record reads "52 derived, 52 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them: `check:issue-citations`, `check:doc-authoring`, `check:nul-bytes`, `check:published-files`, `check:cross-package-test-inputs`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:type-check-debt`, `check-changeset-no-major`. - **Artifact rosters:** 36 of the 39 non-self-test roster rows exit 0 at this head, among them `check:scaffold-emission-policy` and the three the derivation marks as keeping their roster under one of this diff's paths (`check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`). The other three need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 self-test-only rows grade their checkers' fixtures and cannot judge this diff. ## Hypotheses (measured first) - **H0 holds.** At base `01e78dceef` the filtered census answers 3 sites on 3 lines, 2 numbers, 2 files, as on the seat's `0be898499f`. The whole-repo count is 1,077. - **H1 holds.** After the rewrite, the filtered census answers 0 for `packages/create-objectstack`. No census site was left for an open PR (the file lists of all open PRs were read at 2026-09-30T01:21:44Z and again at 01:52:53Z, 8 PRs each time: only the Version Packages PR objectstack-ai#20639 touches the package, in `CHANGELOG.md` and `package.json`) or for an unfound anchor. The one site left for an unfound anchor is a test comment, outside the census. - **H2 holds.** The parser leaf-token diff of all 10 touched files is empty with its controls firing, and, independently, the emitted `dist` and the scaffolded project are byte-identical at base and head, with a code-mutation control that changes `dist`. ## Acceptance notes - **Strings, the form-D stage.** Seven dead numbers remain in string literals, all test titles in `src/`: `banner-version.test.ts:66` and `:96` (`objectstack-ai#10325`), `blank-readme-validate-disclosure.test.ts:25` (`objectstack-ai#10322`), `scaffold-e2e-boot-probe.test.ts:829` (`objectstack-ai#19424`), `scaffold-next-steps-pm.test.ts:173` and `:197` (`objectstack-ai#10322`), `template-consistency.test.ts:503` (`objectstack-ai#10326`). They stay on the card for its form-D stage; no string moved here. None is an assertion text or scaffold output. - **Outside `src/**`:** nothing dead. The one citation there, `vitest.config.ts:24` (`objectstack-ai#10374`), answers 200; `README.md` and `bin/` carry none. - **Live but misdirected numbers, a different class.** Two numbers in this package answer 200, but as unrelated pull requests. `objectstack-ai#4902` (`index.ts:165`, `:239`; `rewrite-identity.ts:36`; `runtime-image.ts:140`; `rewrite-identity.test.ts:3`, and the test title at `:123`) was written by `8d41998b0`, whose own message names `objectstack-ai#4926` (the remote-template object-name rewrite being silently skipped), and `f2f09e4e3` repeated it at `runtime-image.ts:140`; `objectstack-ai#4902` itself is an unrelated `init-service` guard PR. `objectstack-ai#3120` (`template-copy.ts:20`; `template-consistency.test.ts:259`) was written by `3b6ef8a32` (the scaffolded `.gitignore`), and `objectstack-ai#3120` is an unrelated approvals-docs PR. The census reads both as `resolves-as-pull-request`, a reading and not a finding, and this card is about 404s, so neither moved here. Noted, not filed. - **Card-word residue, cited nowhere.** Some rewritten test headers still say "the card" or "per triage" nearby (`banner-version.test.ts:13`, `blank-readme-validate-disclosure.test.ts:3`). They cite no dead number, so they were left, as the landed stages left theirs. - **The moving `origin/main`.** The branch merged `origin/main` once (`a84b73af13`, merging `697845d19f`: PR objectstack-ai#20742, the `service-package` citation re-anchoring). Nothing under `packages/create-objectstack` or `packages/spec` changed, so the package's tests, typecheck, every derived gate, the roster rows and lint were rerun at the merge head and all read as before. ## Deviations - **Three derived gates first read NOT MEASURED.** `check:dual-build-cjs-loads`, `check:lean-entry-closure` and `check:type-check-debt` exited 3 (PREREQUISITE NOT MET: built output absent) in the first pass, before the whole-workspace build. Rerun after it, each exits 0, and all 52 exit 0 in the single pass at this head. - **The first code-mutation attempt was void.** Its replacement text contained the anchor, so the anchor count could not fall; `ablation-replace.mjs` refused it (anchor 1 to 1, exit 1) and restored the blob to HEAD before anything was built. The second attempt, with a replacement that does not contain the anchor, is the one reported above. - **The two builds inside the code-mutation control** (the mutate leg and the restore leg) ran directly, not through `os-verify-lock.sh`. On this host that wrapper runs unlocked anyway, so nothing was serialized either way. - **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 harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. 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>
…ugins/plugin-dev/src to the commits that decided them (objectstack-ai#20767) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 12 of the `domain:cli` lane of the dead-citation sweep: `packages/plugins/plugin-dev/src`. Every comment site there that cited a tracker number answering 404 now cites, in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), the commit in this repository's history that decided what the line describes, and keeps saying in its own words what that commit decided. PR objectstack-ai#20533 is the method, and stages 1 to 11 of this card (PR objectstack-ai#20624, PR objectstack-ai#20632, PR objectstack-ai#20656, PR objectstack-ai#20673, PR objectstack-ai#20689, PR objectstack-ai#20703, PR objectstack-ai#20713, PR objectstack-ai#20723, PR objectstack-ai#20735, PR objectstack-ai#20741, PR objectstack-ai#20748) are the precedents. The card stays open for the lane's remaining packages, so this PR says `Part of`. That is **6 sites on 6 lines in 3 files, covering 2 numbers**, rewritten to **2 distinct commits**: - the census's **3 sites**, all in `src/dev-plugin.ts` (`:1063`, `:1078`, `:1097`); - **3 test-file comment sites** (the census defers `*.test.ts`; stages 1 to 11 took test comments too): `dev-plugin.test.ts:90` and `:127`, `dev-plugin-security-enforcement-warning.test.ts:53`. Only comments changed: **6 lines out, 6 in**, every one of them a site (no companion line), and every touched file keeps its line count (1159 / 317 / 199), so no line citation into these files moves. **No citation number is added**: the only tracker number on an added line is `objectstack-ai#3900` at `dev-plugin.ts:1063`, which the removed line already carried and which answers 200; no PR number stands on an added line. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records either decision (a grep there for the 2 numbers, their PR number objectstack-ai#10092 and the 2 shas reads 0 hits; the control number `7329` reads 1 file in the same tree), so both anchors are commits. ADR-0115 records the older decision the warning comes from (an empty security slot gets one loud boot-log line), not the move these lines describe. **A `patch` changeset** for `@objectstack/plugin-dev` rides along (`.changeset/plugin-dev-provenance-anchors.md`, in PR objectstack-ai#20632's form), because the two rewritten docblock lines reach the published `dist` (measured below), as stage 6 (PR objectstack-ai#20703) measured for its package. ## Census: `packages/plugins/plugin-dev`, before and after **Instrument.** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged, run under `with-fleet.sh --read` for the token. The count is its `allocated-but-absent` findings under `packages/plugins/plugin-dev/`. Both runs enumerated the whole board. | reading | tree | board | whole-repo `allocated-but-absent` | package sites | lines | numbers | files | |---|---|---|---|---|---|---|---| | before | base `33e4a5609c`, run 2026-09-30T02:45:30Z to 02:51:51Z | enumerated, 186 pages, frontier objectstack-ai#20757, 18,584 numbers | 1,061 | **3** | 3 | 2 | 1 | | after | head `a237b10ee7`, run 03:07:39Z to 03:14:14Z | enumerated, 186 pages, frontier objectstack-ai#20765, 18,592 numbers | 1,058 | **0** | 0 | 0 | 0 | The whole-repo drop of 3 is exactly these sites: a site-by-site diff of the two JSON outputs has 3 findings gone (`dev-plugin.ts:1063`, `:1078`, `:1097`) and none added. The other three tallies (`resolves` 33,038, `resolves-as-pull-request` 1,984, `cross-repo-unjudged` 995) are equal in both runs. **Supplementary scan (test files, strings and files outside `src/` included).** Every `#N` token (two to six digits) in the package's 19 tracked files, `CHANGELOG.md` excluded, was probed by REST: 39 distinct numbers at base, of which 2 answer 404 in `src/` (`objectstack-ai#10035`, `objectstack-ai#10036`) and 1 outside it (`objectstack-ai#13176`, in `tsconfig.test.json`); `objectstack-ai#1020` is `cloud#1020`, cross-repo. Dead occurrences at base: 6 in `src/` comments (3 source, 3 test), 1 in a test string, 2 in `tsconfig.test.json`. After: 0 in comments, the test string and the two `tsconfig.test.json` lines unchanged (see Acceptance notes). A grep for the two numbers with no word-boundary operator, beside a control of the same shape (`objectstack-ai#3900` reads 6 lines of `dev-plugin.ts`), finds only those three lines left. ## Per-number table `git blame` at the base ties every one of the 6 lines to `7552e0337`, the commit that wrote them, and each anchor was read in its message and its diff, not only its subject. | number | sites (base line) | anchor: what it decided | |---|---|---| | `objectstack-ai#10036` | `dev-plugin.ts:1063`, `:1078`; `dev-plugin.test.ts:90`, `:127`; `dev-plugin-security-enforcement-warning.test.ts:53` | `7552e0337`: the "RBAC/RLS/masking are NOT enforced" warning stops probing the three `SecurityPlugin.init()` internals (`security.permissions`, `security.rls`, `security.fieldMasker`, which the spec contract names implementation internals) and asks the published `security` service instead, and asks it from `DevPlugin.start()`, after the child-start loop and beside the boot banner, since asking from `init()` would find it absent on every stack; the internal handles keep one use, telling "never loaded" apart from "loaded, then failed to start". Both halves of its squash message carry this number. Its own PR number (objectstack-ai#10092) answers 404 as well. | | `objectstack-ai#10035` | `dev-plugin.ts:1097` | `c1731d023`: `plugin-hono-server`'s `/auth/me/permissions` and `/me/apps` delegate permission-set resolution to the `security` service, and their degraded branches key on the published `security` service instead of `security.permissions` (its docblock "What absent now means, precisely"). The site's sentence says the same presence signal misled that endpoint and was cured "by this same move"; `objectstack-ai#10035` is that commit's own PR number, carried in its subject. | **How the lines read now.** `:1063` keeps `objectstack-ai#3900` and says `commit 7552e03 moved this check here from init()`; the `:1078` heading and the test-comment brackets name `commit 7552e03` where the number stood, with the decision spelled out in the surrounding prose they already carried; `:127` reads `(the two told apart since commit 7552e03)`; `:1097` reads `commit c1731d0 by this same move`. **Anchor checks.** Both cited shas match exactly one object (`git rev-parse --disambiguate`, count 1 each), are commits, have one parent, and are ancestors of `main` (`merge-base --is-ancestor` against `33e4a5609c`, exit 0 for both). The checkout is not shallow. Control legs: `44738f7af6` (the parent of `c1731d023`) exits 0 against the base; the negative control (the base as an ancestor of `7552e0337`) exits 1. **Numbers.** `objectstack-ai#10035`, `objectstack-ai#10036` and `objectstack-ai#10092` answer 404 by REST (probed 2026-09-30T02:43:04Z and again at 03:14:40Z). `objectstack-ai#3900`, kept on `:1063`, answers 200. ## Mechanical guard: no code token moves **H2 holds on the token reading; the emitted `dist` is NOT byte-identical, and the difference is exactly the two docblock lines.** **Token guard.** It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, `getChildren` walk, JSDoc nodes excluded) of the 3 touched files at base `33e4a5609c` and at `37eaf1647f` (the comment commit). Controls mutate the head text in memory only. - Real run: 6,653 base tokens, 0 files differing. - Comment-insertion control: 0 differing. - Code-insertion control: all 3 files differ. - String control (the first character of the first import specifier flipped in each file): all 3 files differ, first differing kind `StringLiteral`. - The script's own verdict: exit 0 (real 0 and every control as expected). All 12 changed lines in `src/` (6 out, 6 in) are `//` or `*` comment lines. **Emitted `dist`.** `pnpm --filter @objectstack/plugin-dev build` at base (before any edit, after its dependency closure) and at `37eaf1647f`. Of the 6 `dist` files, `index.js.map` and `index.mjs.map` have equal sha256; `index.js`, `index.mjs`, `index.d.ts` and `index.d.mts` differ, and `diff -r` shows exactly two changed lines in each: the `:1078` heading and the `:1097` line of the `warnIfNothingIsEnforcingSecurity` docblock. The `//` comment at `:1063` does not ship. So the published tarball carried both dead numbers, and now carries the commits. - Code-mutation control (`scripts/ablation-replace.mjs`, wrap mode, anchor `ctx.logger.info(' Discovery: /.well-known/objectstack');` hit 1 to 0, planted marker 0 to 1, blob `708af69f9b2a` to `b0b387f53d6a`; `scripts/ablation-dist-preflight.mjs` found the marker in `dist/index.js` and `dist/index.mjs`): `index.js`, `index.mjs` and both source maps differ from the head build. The blob was restored to HEAD `708af69f9b2a` with `git diff HEAD` empty, `dist` was rebuilt, the preflight in `--absent` mode reads the marker absent from all 6 files with a clean tree, and the 6 sha256 values equal the head build. - The whole-workspace build (below) left `plugin-dev`'s `dist` equal to the same 6 values. A raw scan of the 4 changed files for ASCII control bytes finds none (a positive probe on a scratch file with one such byte reads 1), and `check:nul-bytes` exits 0. ## Changeset **`patch` for `@objectstack/plugin-dev`.** The package publishes (`files` is `dist`, `README.md`, `CHANGELOG.md`), and the measurement above shows the rewritten docblock reaching four `dist` files. The changeset states comments only, with no behaviour change. `check-empty-changeset`, `check-changeset-no-major`, `check-adr-0087-registration` (1 non-breaking changeset seen) and `check-changeset-fixed` all exit 0. ## Gates (head `a237b10ee7`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its official wording, verbatim (printed by every run; the command line differs per run and is listed in the verdicts below): > **Declared narrowing — verification ran UNLOCKED.** `scripts/pm/os-verify-lock.sh` > could not take the shared verify lock on this host: no usable `flock`. The shared > verify lock is declared Linux-only (`flock` is util-linux, and a stock macOS does > not ship it), so the command below was run directly, without the lock — > a declared narrowing, not a silent one. No serialization guarantee held for this > run, nor for any sibling agent in this container while it ran. Its verdict line from each run (the closure build at base `33e4a5609c`; the head build at `37eaf1647f`; the whole-workspace build, the tests and the typecheck 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 65s (1m05s) · declare it in the PR body · pnpm --workspace-concurrency=2 --filter '@objectstack/plugin-dev...' 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 3s · declare it in the PR body · pnpm --filter @objectstack/plugin-dev 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 97s (1m37s) · declare it in the PR body · pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=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 7s · declare it in the PR body · pnpm --filter @objectstack/plugin-dev exec vitest run --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/plugin-dev typecheck ``` - **Build:** `plugin-dev` with its dependency closure (36 packages, the filter spelled with the package included), then the package, then the whole workspace, `turbo run build --filter=./packages/* --filter=./packages/*/* --concurrency=2`, 71 of 71 tasks. The tree was clean after each. - **Tests:** `vitest run --maxWorkers=2`: 9 files, 86 tests, all passed. - **Typecheck:** `pnpm --filter @objectstack/plugin-dev typecheck` (`tsc --noEmit`, then `check:test-typecheck` over `tsconfig.test.json`) exits 0. `--listFiles` under both configs reaches all 12 `src/` files, including the 9 tests and the 3 touched files. - **Spec artifacts:** not run. `origin/main` did not move while this branch was open (still `33e4a5609c`; the merge was a no-op), and this diff does not touch `packages/spec`. - **Lint:** the repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at this head (2026-09-30T03:07:02Z to 03:07:32Z). - **Citation judging:** after merging `origin/main` (already up to date at `33e4a5609c`), `node scripts/check-issue-citations.mjs --base origin/main` judges 1 added citation (`objectstack-ai#3900`), which resolves (exit 0). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 62 families from the 4 changed paths. All 62 exit 0 in one pass at this head, and `--ran` with the exit-coded record reads "62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them: `check:issue-citations`, `check:doc-authoring`, `check:nul-bytes`, `check:published-files`, `check:cross-package-test-inputs`, `check:dts-closure`, `check:dual-build-cjs-loads`, `check:type-check-debt`, `check-empty-changeset`, `check-adr-0087-registration`. - **Artifact rosters:** 36 of the 39 non-self-test roster rows exit 0 at this head, among them `check-changeset-fixed` and the three others the derivation marks as keeping their roster under one of this diff's paths (`check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`). The other three need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 self-test-only rows grade their checkers' fixtures and cannot judge this diff. ## Hypotheses (measured first) - **H0 holds.** At base `33e4a5609c` the filtered census answers 3 sites on 3 lines, 2 numbers, 1 file, as on the seat's `0be898499f`. The whole-repo count is 1,061. - **H1 holds.** After the rewrite, the filtered census answers 0 for `packages/plugins/plugin-dev`. No site was left for an open PR (the file lists of all 8 open PRs were read at 2026-09-30T02:45:10Z: only the Version Packages PR objectstack-ai#20639 touches the package, in `CHANGELOG.md` and `package.json`) or for an unfound anchor. - **H2 holds, by the token reading, not the `dist` reading.** The parser leaf-token diff of all 3 touched files is empty with its controls firing. The emitted `dist` is not byte-identical, and it is not meant to be: its only difference is the two docblock lines, which is why the changeset ships. ## Acceptance notes - **Strings, the form-D stage.** One dead number remains in a string literal: the `describe` title at `dev-plugin-security-enforcement-warning.test.ts:121` (`objectstack-ai#10036`). It stays on the card for its form-D stage; no string moved here. It is not assertion text. The same title is quoted in three recorded CI-log fixtures under `scripts/fixtures/merge-queue-triage/`; those are captured logs read by `check-merge-queue-triage-outcome.mjs`, so a later rename of the title does not need them edited. - **Outside `src/**`:** `tsconfig.test.json:3` and `:56` cite `objectstack-ai#13176`, which answers 404. The same number sits in the `tsconfig.test.json` of 13 `packages/plugins/*` packages (17 `tsconfig*.json` files under `packages/` in all), outside the census's declared surface; stage 10 (PR objectstack-ai#20741) recorded its own copy for a later stage of this card. Every other citation in the package outside `src/` answers 200 (`vitest.config.ts`, `README.md`, `tsconfig.json`, `package.json`); `CHANGELOG.md` is release-owned and was not read as a site. - **`origin/main` did not move.** It read `33e4a5609c` at worktree creation and at every later fetch, so every run above is against the same base and nothing needed rerunning after the merge. ## Deviations - **The two builds inside the code-mutation control** (the mutate leg and the restore leg) ran directly, not through `os-verify-lock.sh`. On this host that wrapper runs unlocked anyway, so nothing was serialized either way. - **The dependency-closure build** used the filter `'@objectstack/plugin-dev...'` (package plus its dependencies) rather than the closure-only `^...` spelling; it built the same closure and the package in one run. - **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 harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. --- _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>
Part of #20594
Clause-②: no
What changed
This is stage 9 of the
domain:clilane of the dead-citation sweep:packages/cloud-connection/src. Every comment site there 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 keeps saying in its own words what that commit decided. PR #20533 is the method, and stages 1 to 8 of this card (PR #20624, PR #20632, PR #20656, PR #20673, PR #20689, PR #20703, PR #20713, PR #20723) are the precedents. The card stays open for the lane's remaining packages, so this PR saysPart of.That is 10 sites on 10 lines in 3 files, covering 3 numbers, rewritten to 3 distinct commits:
src/marketplace-install-local-plugin.ts(3 numbers);*.test.ts; stages 1 to 8 took test comments too).Only comments changed: 10 lines out, 10 in, and every touched file keeps its line count (1,969 / 377 / 308), so no line citation into these files moves. No citation number is added: over the 10 line pairs, added-minus-removed numbers is empty, and no PR number stands on an added line. No ADR or ruling-record file in
docs/adr/orscripts/adr-anchors/records any of these 3 decisions (a grep for the 3 numbers there reads 0 hits, with a control number from the same tree,#7329, reading 1), so every anchor is a commit.A
patchchangeset for@objectstack/cloud-connectionrides along, because the rewritten docblocks reachdist(measured below). That is stage 6's case (PR #20703), not stages 5 and 7's.Census:
packages/cloud-connection, before and afterInstrument. The gate's own
node scripts/check-issue-citations.mjs --census --json, read-only and unchanged, run underwith-fleet.sh --readfor the token. The count is itsallocated-but-absentfindings underpackages/cloud-connection/. Both runs enumerated the whole board.allocated-but-absentpackages/cloud-connectionsitesb291fcdae9, run 2026-09-29T22:34:12Z to 22:38:18Z4a1f38a4e6, run 22:44:08Z to 22:47:58ZThe whole-repo drop of 5 is exactly these sites: a site-by-site diff of the two JSON outputs has 5 findings gone, all in
packages/cloud-connection/src/marketplace-install-local-plugin.ts, and none added. The other three tallies (resolves32,994,resolves-as-pull-request1,984,cross-repo-unjudged995) are equal in both runs.packages/cloud-connection/srcis byte-identical at4a1f38a4e6and at the head.Supplementary scan (test files included). The gate's exported
extractCitationsandclassifyCitationover all 44.tsfiles undersrc/, with the board from the gate's ownprobeBoard: 301 citations and 14 dead before (src comments 5, test comments 5, src strings 1, test strings 3), 291 and 4 after (0, 0, 1, 3). Its before list of src comment sites is identical to the census's. The 4 left are strings, the form-D stage (see Acceptance notes).Per-site table
git blameat the base ties each line to the commit that wrote it, and each anchor was read in its message, changeset or diff, not only its subject.#9011marketplace-install-local-plugin.ts:35,:1001,:1821;marketplace-install-local-capability-enumeration.test.ts:50,:303;marketplace-install-local-list-posture.test.ts:4,:30201074e551: the install-local listing requires an authenticated principal (anonymous gets 401) and servesinstalledBy/storageDironly to amanage_metadataholder, the maintainer's 2026-08-16 "Option 3" that:1008still names; it also extracts the onerefuseUnauthenticated401 envelope that:1821describes. All seven lines blame to it. The PR that landed it (PR #9256, which answers 200) names #9011 on its first line.list-posture.test.ts:302now reads "The wire shape before commit 01074e5" for "The pre-(number) wire shape".#8919marketplace-install-local-plugin.ts:98;marketplace-install-local-capability-enumeration.test.ts:40b5378550e: gates the/metapublish and rollback promotion verbs onmanage_metadataand addsmeta-write-door-capability-enumeration.test.ts, the enumeration pin:40names as its precedent. Both lines blame toe0695b582, the commit that gated the four mutating install-local doors for #8976 (which answers 200), whose message cites this gate as the precedent. Stages 2 and 5 gave the number this anchor. The PR that landedb5378550eanswers 404 too.#13279marketplace-install-local-plugin.ts:18136a180e42d: a failed permission-store read raisesAuthzStoreUnavailableErrorinstead of resolving as an unauthenticated or capability-less principal, and each fail-closed transportcatchre-raises it. The line blames to it; PR #13475 names #13279. Stages 1, 2 and 4 gave the number this anchor.Anchor checks. Every cited sha matches exactly one object (
git rev-parse --disambiguate, count 1 for each of the 3), is a commit, has one parent, and is an ancestor ofmain(merge-base --is-ancestoragainst36d043be17, exit 0 for all 3). The checkout is not shallow. The control leg818fcafda(2026-08-16, the parent of the oldest anchorb5378550eof 2026-08-16) exits 0, and the negative control, this branch's own16a88d69b2, exits 1. Two anchors reuse the landed stages' (b5378550e,6a180e42d), so each number carries one anchor across the tree; one is new (01074e551).Numbers. All 3 dropped numbers answer 404 by REST (probed 2026-09-29T22:40:35Z). The numbers kept near the changed lines (
#8976,#15353) answer 200. Three slash-joined groups stand inpackages/cloud-connection/src, whose later halves the citation grammar does not read (#6603/#7020,#4127/#4251twice); every half answers 200, so none is dead.Mechanical guard: no code token moves
H2 holds on the comment-stripped reading; the emitted
distis NOT byte-identical, because the docblocks ship.Token guard. It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, JSDoc nodes excluded) of the 3 touched files at base
b291fcdae9and at4a1f38a4e6. Controls mutate the head text in memory only.'Authentication required.'to'Authentication requireD.'inrefuseUnauthenticated): exactly 1 differingStringLiteral, at token 7,973 ofmarketplace-install-local-plugin.ts(exit 1).Emitted
dist.pnpm --filter @objectstack/cloud-connection buildat the head, then at base (the base tree ofpackages/cloud-connection/srcrestored in place under a trap-armed restore; an on-disk probe read[#13279]1 andcommit 6a180e42d0 before that build; afterwards every touched blob equals its HEAD blob andgit diff HEADis empty), with the same dependency builds:index.cjs,index.js,index.d.tsandindex.d.ctsdiffer;index.cjs.mapandindex.js.mapare equal.distfiles reads 0 differing tokens (19,465 / 18,741 / 16,868 / 16,868), so the wholedistdelta is comment text. Its code control (a code line appended after a newline) reads COUNT DIFFERS in each.dist: "commit 01074e5" appears 2 times inindex.jsandindex.cjsand 3 times in each declaration file, where the base build carries#9011in the same places.scripts/ablation-replace.mjs, anchor'Authentication required.'hit 1 to 0, planted marker 0 to 1, blob2ef0f0ae8bacto77c3cef6324b;scripts/ablation-dist-preflight.mjsfound the marker indist):index.cjs,index.jsand both.mapfiles differ from the head build. The blob was restored to HEAD2ef0f0ae8bacwithgit diff HEADempty,distwas rebuilt, its six sha256 values equal the first head build, and the preflight in--absentmode reads the marker absent from all 6 files with a clean tree.A raw scan of the 4 changed files for control bytes finds none (a positive probe on a scratch file matched).
Changeset
patchfor@objectstack/cloud-connection(.changeset/cloud-connection-provenance-anchors.md), in PR #20632's form.@objectstack/cloud-connection'sfiles[]isdist,README.mdandCHANGELOG.md, and the build above emits differentindex.js/index.cjs/index.d.ts/index.d.ctsat base and head, so this diff publishes.check-changeset-no-major,check-empty-changeset,check-adr-0087-registrationandcheck-changeset-fixedall exit 0.Gates (head
16a88d69b2)This host has no
flock, soos-verify-lock.shran in its declared unlocked mode. Its disclosure, verbatim, from each run (the closure build at4a1f38a4e6, whosepackages/cloud-connectionand dependency closure are byte-identical to this head; the whole-workspace build, the tests and the typecheck at this head; the threedistbuilds at4a1f38a4e6, whosepackages/cloud-connection/srcis byte-identical to this head):@objectstack/cloud-connectionwith its closure (33 of 81 workspace projects), then the whole workspace,turbo run build --filter='./packages/*' --filter='./packages/*/*', 71 of 71 tasks, after the merge. The tree was clean after both, and the package's sixdistfiles after the whole build equal the first head build by sha256.vitest run: 30 files, 397 tests passed (every*.test.tsundersrc/), at this head and before the merge.@objectstack/cloud-connectionhas notypecheckscript; it is aDEBTentry inscripts/check-type-check-coverage.mjs(13 errors: 11 TS2493, 2 config-tier).tsc --noEmit -p tsconfig.jsonexits 2 with exactly those 13 (11 TS2493, 2 TS2550), all in three test files this PR does not touch (cloud-connection-plugin.test.ts4,connection-credential-store.test.ts7,marketplace-install-local-bundle.test.ts2).--listFilescompiles all three touched files and all 30 test files.check:type-check-debtandcheck:type-check-coverageexit 0, and thedistbuild's DTS step, this package's type gate, succeeds.pnpm lint(eslint . --no-inline-config) exits 0 at this head (2026-09-29T23:01:12Z to 23:01:39Z).origin/main(36d043be17),node scripts/check-issue-citations.mjs --base origin/mainreports "no issue citations added against 36d043b (1 file(s) read)" (exit 0); pinned--base 36d043be17reads the same.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 61 families. All 61 exit 0, and--ranwith the exit-coded record reads "61 derived, 61 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them:check:issue-citations,check:doc-authoring,check:nul-bytes,check:published-files,check:type-check-debt,check-adr-0087-registration,check-empty-changeset.check-changeset-fixed,check:authz-resolver,check:error-code-casing,check:filter-alias-parity). The other three need a pull request's context; they are run against this PR once it exists and reported on the card. The 18 self-test-only rows grade their checkers' fixtures and cannot judge this diff.Hypotheses (measured first)
b291fcdae9the filtered census answers 5 sites on 5 lines, 3 numbers, all insrc/marketplace-install-local-plugin.ts, as on the seat's0be898499f. The whole-repo count is 1,153.packages/cloud-connection. No site was left for an open PR (the file lists of all 10 open PRs were read at 2026-09-29T22:41:18Z: only the Version Packages PR chore: version packages #20639 touchespackages/cloud-connection, inCHANGELOG.mdandpackage.json) or for an unfound anchor.distreading. The parser leaf-token diff of all 3 touched files is empty with its controls firing. The emitteddistdiffers, and the difference is comment text only (token-identicaldistwith a code control). That is why the changeset ships.Acceptance notes
packages/cloud-connection/src:#9011in the threedescribetitles ofmarketplace-install-local-list-posture.test.ts(:206,:247,:287, no assertion text), and#9011in thenotestring of theGET /api/v1/marketplace/install-localrow ofcloud-connection-route-ledger.ts(:215), a runtime string already recorded inscripts/doc-authoring-prose-id.baseline.json. They stay on the card for its form-D stage; no string moved here.src/**, a later stage of the card:packages/cloud-connection/vitest.config.ts:64cites#16917(404). The other citations inpackages/cloud-connectionoutsidesrc/**(CHANGELOG.mdexcluded) answer 200:README.md:108(#10805,#12681) andvitest.config.ts(#10374,#11480,#7668/#7778,#7955,#10374/#13522).marketplace-install-local-capability-enumeration.test.ts:48,marketplace-install-local-list-posture.test.ts:12). They cite no number, so they were left, as the landed stages left theirs.origin/main. The branch mergedorigin/mainonce (16a88d69b2, merging36d043be17:service-automationand two changesets, nothing inpackages/cloud-connectionor its dependency closure).Deviations
Claude-SessionplusCo-authored-by: Claude), and the pre-push trailer check passed on every push. The harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. The merge commit carries git's default message.Generated by Claude Code