Repository navigation
docs(plugin-dev): re-anchor the dead tracker citations in packages/plugins/plugin-dev/src to the commits that decided them - #20767
Conversation
…ugins/plugin-dev/src to the commits that decided them Six comment lines in three files cited two tracker numbers that no longer resolve. Each now cites the commit in this repository's history that decided what the line describes (ruling C+D, form C): - the security-enforcement warning asks the published `security` service, and asks it in start(): commit 7552e03 (dev-plugin.ts x2, and three test-file comments); - plugin-hono-server's current-user endpoints key on the same published service instead of the init()-registered internals: commit c1731d0 (dev-plugin.ts x1). Comments only; every touched 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>
…rovenance comments The two rewritten docblock lines reach dist (index.js, index.mjs, index.d.ts, index.d.mts), so the package ships different bytes and takes a patch changeset, in the form the earlier stages of this sweep used. 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): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
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 8452a32c8a492e655d182c9e620969aa637efa1f && git checkout 8452a32c8a492e655d182c9e620969aa637efa1f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a51920f5fb1059ae6e8c7b1a96aa785f1da5d248 a237b10ee73b097d836b08da5af92e1bae1872f1 && git checkout -B drift-repro a51920f5fb1059ae6e8c7b1a96aa785f1da5d248 && git merge --no-ff a237b10ee73b097d836b08da5af92e1bae1872f1
node scripts/docs-audit/affected-docs.mjs --json a51920f5fb1059ae6e8c7b1a96aa785f1da5d248
|
Contract reviewServed-tier: Inputs read: card #20594 body and all 49 comments (the dev report Seat correction on adoption: the reviewer wrote that ① Derived judgmentsDiff: 4 files, +17/-6. Three files under Site by site, each judged against the cited commit's own message and diff:
Anchor choice.
Changeset (
Left in the package, and right to leave: Check-runs on the head:
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
…es outside src to the commits that decided them (objectstack-ai#20883) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 14 of the `domain:cli` lane's dead-citation sweep. It covers the lane packages' tracked files outside `src/**`, the card's one remaining stage (claim `5911994187`): `README.md`, `tsconfig*.json`, `vitest.config.*`, `tsup.config.*` and each package's `test/**`. The census at the stage's base `660a9b247e` counts **270 dead comment sites** on that surface. That is over the claim's 40-site line, so this stage takes the largest package, **`packages/cli`**. Every other package is listed below with its count. In `packages/cli`, every comment site on that surface that cited a tracker number answering 404 now cites a commit instead. Following ruling C+D's form C (comment `5749154545` on objectstack-ai#19123), it is the commit in this repository's history that decided what the line describes. Stages 1 to 13 of this card are the precedents; the latest are PR objectstack-ai#20767 and PR objectstack-ai#20842. - **154 sites on 149 lines in 56 files**, covering **51 numbers**, now cite **50 distinct commits**. The 56 files are `vitest.config.ts`, `tsconfig.test.json` and 54 files under `test/**`: 50 test files, `helpers/serve-process.ts` and 3 fixtures. - **Comments only.** 150 lines out and 150 in, and every file keeps its line count. - One of the 150 is a companion line: `generate-skill.e2e.test.ts:35`, "both pass" becomes "both passed". - Its anchor, commit `3c418c498`, rewrote the two `@example` blocks the sentence is about. A present tense beside that citation would contradict it. - **5 sites have no deciding commit** and are left as they were (see "The sites left"). - **No tracker number is added.** The 12 numbers still on changed lines were already on the removed lines, and all 12 answer 200: objectstack-ai#5286, objectstack-ai#5728, objectstack-ai#10678, objectstack-ai#11391, objectstack-ai#11643, objectstack-ai#11772, objectstack-ai#12047, objectstack-ai#13158, objectstack-ai#14554, objectstack-ai#16483, objectstack-ai#16888 (kept as a convenience link beside its commit) and objectstack-ai#17978. - **No ADR or ruling record carries any of these decisions.** A grep of `docs/adr` and `scripts/adr-anchors` finds 0 hits for the 54 numbers and 0 for the 50 shas. The control `7329` finds 1 file in the same tree. So every anchor is a commit. - Where an earlier stage gave a number an anchor and the line here describes the same decision, the same anchor is reused. That covers 33 of the 51 numbers (for `objectstack-ai#13504`, the tier half only), read by pairing the landed stages' removed and added lines. The other 18 anchors are new. ## Census, per package **Instrument.** The card's gate does not read these files. Its declared surface is `packages/**/src/**`, and `surfaceFor` answers null for all 56 touched paths; the control `packages/cli/src/commands/init.ts` answers `package-docblocks`. So the census is taken by hand, with the gate's own grammar: - **Files:** every tracked file of the 19 lane packages outside `src/**`, `CHANGELOG.md` excluded. That is 534 files. - **Extraction:** `extractCitations` from `scripts/check-issue-citations.mjs`, whole-file. Its comment-prose projection decides comment versus string. - **Numbers kept:** only those naming this repository. - **Probe:** each distinct number is probed by REST, `GET /repos/objectstack-ai/objectstack/issues/N`. **Probes:** - **Before**, at base `660a9b247e`, 2026-09-30T13:15:23Z to 13:16:12Z: 889 numbers. 794 answer 200 and 95 answer 404. - **After**, at head `fda0702246`, 15:00:12Z to 15:01:16Z: 864 numbers. 794 answer 200, 69 answer 404, and one answered 502. That one was objectstack-ai#11267; re-probed twice at 15:01:23Z, it answers 404. - No number present in both probes changed its answer. - Citation sites went from 3,634 to 3,480, a drop of exactly the 154 rewritten sites. Dead sites per package. "Comment" is this stage's surface. "String" means a string, a `describe`/`it` title or a message on the same file list; those belong to objectstack-ai#20752 (form D) and are untouched. "Off-list" means files outside the claim's file list; they are untouched and listed below. | package | comment, before → after | string (unchanged) | off-list (unchanged) | |---|---|---|---| | `cli` | **159 → 5** | 42 | 41 | | `qa/dogfood` | 94 → 94 | 28 | 0 | | `plugin-hono-server` | 4 → 4 | 0 | 2 | | `plugin-dev` | 2 → 2 | 0 | 0 | | `client` | 2 → 2 | 0 | 1 | | `qa/vitest-filter-preflight` | 2 → 2 | 0 | 1 | | `cloud-connection` | 1 → 1 | 0 | 0 | | `mcp` | 1 → 1 | 0 | 1 | | `qa/downstream-contract` | 1 → 1 | 0 | 0 | | `rest` | 1 → 1 | 0 | 7 | | `runtime` | 1 → 1 | 0 | 1 | | `types` | 1 → 1 | 0 | 0 | | `verify` | 1 → 1 | 0 | 0 | | `qa/http-conformance` | 0 → 0 | 0 | 1 | | `observability`, `client-react`, `create-objectstack`, `adapters/hono`, `qa/refd-timer-testkit` | 0 → 0 | 0 | 0 | | **total** | **270 → 116** | 70 | 55 | - **`tsconfig*.json` string values: none.** Every dead site in a `tsconfig*.json` sits in a `//` comment, and these files are JSONC. - **Taken here:** cli's `tsconfig.test.json:1`. - **Still dead:** `verify/tsconfig.test.json:1` (objectstack-ai#15145), `plugin-dev/tsconfig.test.json:3` and `:56`, and `plugin-hono-server/tsconfig.test.json:3` and `:61` (objectstack-ai#13176), `plugin-hono-server/tsconfig.typecheck.json:12` (objectstack-ai#11332, objectstack-ai#10724), and `client/tsconfig.json:8` (objectstack-ai#12181). - **No `README.md`** in any lane package cites a dead number. ## Per-number anchors `sites` counts the rewritten sites for each number. Each anchor was checked by blame, and in its message or its diff. The "what it decided" column is what the lines describe. | number | sites | anchor | what it decided | |---|---|---|---| | `objectstack-ai#6217` | 4 | `2b641ddd4` | `--json` reserves stdout for the payload across the `bootSchemaStack` family (its message closes the card) | | `objectstack-ai#10152` | 1 | `ad492e7fd` | wrote the measured suite-cost section this heading opens (a later commit's message pairs the card with this PR) | | `objectstack-ai#10323` | 1 | `5a616d558` | `create-objectstack` derives "Created files" from the finished project | | `objectstack-ai#10324` | 3 | `ecd06f613` | self-contained starter comments, and creates `starter-comments-self-contained.test.ts` | | `objectstack-ai#10326` | 1 | `675ab574e` | the two benign peer skews declared inside the scaffold (stage 3's anchor) | | `objectstack-ai#10359` | 4 | `15b63e85a` | retires `os g agent` (stage 3's anchor) | | `objectstack-ai#10366` | 1 | `bbe643c08` | gates plugin-auth's localhost trusted-origin substitution to non-production (the plugin-auth stage's anchor) | | `objectstack-ai#10498`, `objectstack-ai#10499` | 1, 4 | `6d441e41f` | its squash carries both: the measured pnpm boundary, and the gate between the two scaffold paths | | `objectstack-ai#10504` | 5 | `ff5733e03` | `UI: 0 Apps` instead of a dropped row; records the triage ruling | | `objectstack-ai#10557` | 2 | `818e02700` | init's "Created files" summary after install, and the `create-objectstack` alias | | `objectstack-ai#10763` | 1 | `c2b97c2a1` | `os package publish` prints the server's reason (stage 3's anchor) | | `objectstack-ai#10917` | 7 | `7940de5e0` | retires the `@capabilities` hook-body directive | | `objectstack-ai#10926` | 1 | `d173125fb` | the ruling commit stage 3 and the spec stages used for this number | | `objectstack-ai#10931` | 2 | `afe1c4e0a` | declares the four `@better-auth/utils` peer skews | | `objectstack-ai#10943` | 1 | `46d34ab7c` | `fallbackImport` becomes a caller-supplied parameter | | `objectstack-ai#10952` | 6 | `0d4bd93e7` | every summary section prints its zero state | | `objectstack-ai#10953` | 2 | `be7262e72` | the four structural advisories in `os validate --json` | | `objectstack-ai#11022` | 2 | `21756b325` | adds the fifth `MONOREPO_ONLY` pattern | | `objectstack-ai#11025` | 3 | `1c3a46f87` | `os g skill` writes `NAME.skill.ts` | | `objectstack-ai#11026` | 2 | `3c418c498` | rewrites `skill.zod.ts`'s two `@example` blocks off `triggerPhrases`; its changeset names the number | | `objectstack-ai#11071` | 7 | `50fb191dc` | derives every `os generate` filename from the registry (its message closes the card, and measures the loader) | | `objectstack-ai#11157` | 4 | `a4cb7817f` | `serve` hands the host importer its own base | | `objectstack-ai#11172` | 2 | `05181e8cc` | keeps the `Runtime:` row and stops counting an unrendered metric | | `objectstack-ai#11174` | 1 | `ab23c67ab` | `os validate --json --strict` exits 1 | | `objectstack-ai#11267` | 19 | `1ddda1d00` | introduces `childEnv()`, the measurement table and `serve-process-child-env.e2e.test.ts`; its message names the card twice | | `objectstack-ai#11268` | 4 | `918988ad3` | the PR itself; its squash changes `turbo.json` to `@objectstack/cli#test` `dependsOn: ["build"]` | | `objectstack-ai#11671` | 1 | `09b4f4e4e` | the source-hashes provenance companion (every earlier stage's anchor) | | `objectstack-ai#12125`, `objectstack-ai#12285` | 7, 1 | `79cf692b0` | carries `conversions` on every failure exit. `objectstack-ai#12285` is this commit's own PR. Its message withholds the fold question, which is what 3 of the lines say | | `objectstack-ai#12297` | 3 | `9fd45a952` | `os lint` surfaces conversion notices (stage 3's anchor) | | `objectstack-ai#12964` | 4 | `e6fd1caf7` | names the missing build output; its changeset names the number, and it holds both halves | | `objectstack-ai#13109` | 2 | `8b236c826` | matches i18n-extract's walk to `translatePage`'s | | `objectstack-ai#13112` | 1 | `e7191ce71` | per-condition `types` targets in the dual-build packages; its changeset names the number | | `objectstack-ai#13193` | 1 | `faff497fd` | `os serve` writes the state file before it announces the port | | `objectstack-ai#13218` | 1 | `c45d8e6b4` | exports the addressed-component walk; its changeset says "ruled 2026-08-30" | | `objectstack-ai#13504` | 4 | `55519d503` | the measurement half: attributes the `import` term per file (`vitest.config.ts:82`, `:261`, `:263`, `:359`) | | `objectstack-ai#13504` | 5 | `44813ba57` | the tier half: the named `unit` / `integration` split and the partition pin (`:496`, `:541`, `:677`, `:831` and `vitest-tiers-partition.test.ts:5`; the qa stage's anchor) | | `objectstack-ai#13651` | 1 | `ada3834ad` | the silent hook-body downgrade becomes a lint verdict (stage 3's anchor) | | `objectstack-ai#14336` | 2 | `79c71d29d` | object / view / action / app scaffolds `os validate` accepts | | `objectstack-ai#14710` | 2 | `95fdf627b` | wires the test layer into `check:test-typecheck` | | `objectstack-ai#14715` | 1 | `accb9231c` | the PR itself; keeps the exit-2 assertion for the never-read reader | | `objectstack-ai#14811` | 1 | `8ad872ba3` | sweeps every `os explain` catalog entry; its diff adds this heading | | `objectstack-ai#14817` | 2 | `5529a374e` | puts the three platform record pages under an i18n gate; its message records the harm | | `objectstack-ai#14824` | 6 | `cf6b67164` | `os create` emits a project that installs outside the monorepo (stage 3's anchor) | | `objectstack-ai#14858` | 5 | `0c5e97368` | a closed stderr read end exits 2 | | `objectstack-ai#15150` | 5 | `cc986c913` | the sixth `MONOREPO_ONLY` pattern (the create-objectstack stage's anchor) | | `objectstack-ai#16330` | 2 | `4998efa71` | the blank template's CI workflow, with `lint` (the create-objectstack stage's anchor) | | `objectstack-ai#16350` | 2 | `68aee4c99` | `os init` writes a `lint` script; its diff adds the pin that cites the number (PR objectstack-ai#16888 kept beside it) | | `objectstack-ai#16721` | 1 | `51ae73123` | `LiteKernel.use()` enforces the plugin contract (the plugin-hono-server stage's anchor) | | `objectstack-ai#17080` | 1 | `8b4890343` | the per-release `spec-changes.json` section (its message closes the card) | | `objectstack-ai#17853` | 2 | `08f5f0e5a` | a vitest filter that selects nothing says so (the qa stage's anchor) | **Anchor checks:** - **Each sha is unambiguous:** it matches exactly one object (`git rev-parse --disambiguate`, count 1 for each of the 50). - **Each is a plain commit** with one parent. - **Each is on the base:** `merge-base --is-ancestor` against `660a9b247e` exits 0 for all 50. - **The history is complete:** the checkout is not shallow. - **Control legs:** the parent of the oldest anchor, `8e13ca8764` (the parent of `2b641ddd4`, 2026-08-08), exits 0. The negative control, the base as an ancestor of `2b641ddd4`, exits 1. **Wordings to check, each true of its commit:** - **A defect named by its number now says so:** "The defect commit 79cf692 fixed — ...". - **A card's words stay the card's.** Where a line quotes what a card said or asked, it now says "commit X's card". That is `vitest.config.ts:263`, `:359` and `:541`, and `published-subpath-hook-body.pin.test.ts:28`. - **The objectstack-ai#12125 fold question:** "the same question commit 79cf692 left open", "commit 79cf692 explicitly withheld an answer". The commit's message reads: "`warnings` and `conversions` are deliberately NOT folded: whether they should become one field is a live question the ruling did not address." - **Ruling dates:** `platform-page-i18n-parity.test.ts:163` keeps its ruling date as "(the 2026-08-30 ruling)". - **Headings with a dash rule** keep their width by trimming the rule. The exception is `commands.test.ts:181`, which keeps a 2-character rule and grows by 6. ## The sites left **No deciding commit (5 sites).** The claim says to list them, not guess. - **`vitest.config.ts:221` (objectstack-ai#10149):** "the outer fan-out ... is a property of the shard, decided in `ci.yml`". - Only two commits name the number. `cc21aad8ed` is a measurement that says "Part of" and leaves the decision to the maintainer. `d18bc32770` cites the card's recorded reasoning. - Neither decides it, and the commit that wrote the line (`ad492e7fd`) only cites it. - **`test/init.test.ts:189` (objectstack-ai#11048):** "Admitting that band is a support decision". - It names an open decision (pnpm 10.0 to 10.4), and the floor is still pnpm 10.15 or later at the base. - Stage 3 and the create-objectstack stage left the sibling sites for the same reason. - **`published-entry-stderr-error-listener.test.ts:11` and `:150`, and `published-subpath-hook-body.pin.test.ts:35` (objectstack-ai#14874):** "npm packs a `bin` target regardless of `files`". - No commit message names the number. The commits that add it (`95d5cbb31`, `b3ef687c0`) only cite it. - `5023630b1`'s changeset records the same measurement but names no number, so the link is not proven. ## Not in this stage - **The other lane packages**, 116 dead comment sites in total: see the census table. - **String sites (70, form D, objectstack-ai#20752, not moved):** - **`cli`, 42 sites in 24 test files.** Examples: `describe('objectstack-ai#12125 — ...')` in `build-json-failure-conversions.e2e.test.ts:300`, `:459` and `:557`, and `describe('[objectstack-ai#11025] ...')` in `generate-skill.e2e.test.ts:203`. - **`qa/dogfood`, 28 sites in 13 test files**, including `authz-conformance.matrix.ts:429` (3 numbers in one string). - **Off-list files (55 sites):** - **`cli`:** `bin/run-dev.js` 6 and `bin/run.js` 4 (comments; `bin/run.js` ships). `scripts/check-app-nav-i18n.mjs` has 13 comment and 14 string sites. `vitest-tiers.ts` has 2 and `vitest-tiers.fixtures.ts` 1 (comments). `test-typecheck-debt.json` has 1 (string). - **`plugin-hono-server`:** `objectstack.config.ts` 2. - **`test-typecheck-debt.json` strings:** `rest` 7, and 1 each in `runtime`, `mcp`, `client` and `qa/http-conformance`. - **`qa/vitest-filter-preflight`:** `package.json` 1 (the description string). ## Mechanical guard: no code token moves The check compares the TypeScript parser's leaf tokens of the 56 changed files at base `660a9b247e` against head `fda0702246`. It walks with `getChildren`, excludes JSDoc nodes, and treats comments as trivia. `tsconfig.test.json` is compared by its parsed JSONC value. Controls mutate the head text in memory only. | run | result | exit | |---|---|---| | real diff | 86,550 base tokens, **0 files differing** | 0 | | comment-insertion control | 0 differing | 0 | | code-insertion control | 56 of 56 differ | 1 | | string control (one character flipped in each file's first real `StringLiteral`) | 56 of 56 differ (55 first at a `StringLiteral`, plus the JSON value) | 1 | A raw scan of the 56 changed files for control bytes finds none. Its positive control, a scratch file holding a U+0001 byte, matches 1. ## Changeset: none (`skip-changeset`) `@objectstack/cli`'s published set is `files: ["dist", "README.md", "CHANGELOG.md"]`, plus the `bin` target npm packs regardless of `files`. No touched path is in it: - `dist` is built from `tsconfig.build.json` (`rootDir: "src"`, `include: ["src"]`). - `bin/` is not touched. Measured on the built package at head, 3 phrases the change adds occur in 0 files of `dist`: - "commit 55519d5's card" - "the two templates commit cf6b671 repaired" - "commit 1ddda1d" The positive control, a `src` docblock phrase ("already drifted once (closed by commit 6d441e4)"), occurs in `dist/commands/init.js`. ## Tests (head `fda0702246`, `os-verify-lock` with `OS_VERIFY_LOCK_SLOT=issue-20594-outsidesrc`) - **Closure build.** `pnpm --workspace-concurrency=2 --filter '@objectstack/cli...' build` → VERDICT command-exit 0. - **Unit tier.** `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2` → VERDICT 0, Test Files 237 passed (237), Tests 3370 passed (3370). The unit tier holds 23 of the 50 touched test files. - **Queue integration tier.** The one touched file ran by name: `--project integration test/published-entry-stderr-error-listener.test.ts` → 1 file, 6 tests passed. - **Nightly tier.** The other 26 touched test files ran by name under `OS_TEST_TIERS=nightly`, in 4 runs: 9 files / 87 tests, 6 / 74, 6 / 22 and 5 / 22, each VERDICT 0 and all passed. - **Coverage.** Every touched test file ran. - **Typecheck.** `pnpm --filter @objectstack/cli typecheck` → VERDICT 0. - It runs `tsc --noEmit` and then `check:test-typecheck`, which reports "3 file(s) / 28 error(s) / 6 pinned signature(s) held in test-typecheck-debt.json". That is the ledger as it stands at the base, unchanged. - **Whole workspace.** `pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2` → VERDICT 0, 71/71 tasks. This was needed by the two gates that read built output. - **Reverse verification: none.** A comment-only change has no behaviour to invert. The token guard's controls are the sensitivity proof. ## Gates (head `fda0702246`) - **Derivation.** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derives 49 families. - All 49 ran, and every recorded exit code is 0. - Three needed a second run, each for a reason outside the diff: - `check:dual-build-cjs-loads` refused with exit 3 (PREREQUISITE NOT MET, no `dist` for 9 packages). After the whole-workspace build it exits 0. - `check:query-options-erasure` hit my 300 s cap on a contended box. Rerun, it exits 0 in 363 s ("ratchet holds ... none new"). - `check:type-check-debt` refused with exit 3 (no built `objectql`). After the build it exits 0 ("none above its recorded number"). - **Reconciliation.** `--ran`: 49 derived, 49 run, 0 NOT-MEASURED, 0 UNRUN. - **Issue citations, diff mode.** `node scripts/check-issue-citations.mjs` → 0 citations added. - **Lint.** `pnpm lint` (`eslint . --no-inline-config`, repo-wide) → exit 0, 2026-09-30T14:56:17Z to 15:00:01Z, at `fda0702246`. ## Acceptance notes - **`origin/main` moved 14 commits past the base (to `9905e61ca2`), and the branch was not merged forward.** - Of the files those commits touch, 0 are among this PR's 56. - The derived family set on `9905e61ca2` with this diff applied (a throwaway detached worktree, since removed) is the same 49 commands. - The merge-ref CI and the queue cover the joint tree. - **Five nearby wordings still read as before, because they are not sites:** - `print-metadata-stats-zero-row.test.ts:101` says "That card" and `:184` "that card's head". Both now follow a commit citation and mean the card behind it. - The `it` title at `generate-skill.e2e.test.ts:269` says both spec `@example` blocks "still pass" `triggerPhrases`. That is stale since `3c418c498`, but it is a test string and belongs to form D. - **The objectstack-ai#14874 wording repeats in `bin/run.js:225` and three `scripts/check-changeset-no-major.mjs` sites.** Both are outside this surface; `scripts/**` is objectstack-ai#15809's lane. --- _Generated by [Claude Code](https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB)_ Co-authored-by: Claude <noreply@anthropic.com>
Part of #20594
Clause-②: no
What changed
This is stage 12 of the
domain:clilane 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 #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 11 of this card (PR #20624, PR #20632, PR #20656, PR #20673, PR #20689, PR #20703, PR #20713, PR #20723, PR #20735, PR #20741, PR #20748) are the precedents. The card stays open for the lane's remaining packages, so this PR saysPart of.That is 6 sites on 6 lines in 3 files, covering 2 numbers, rewritten to 2 distinct commits:
src/dev-plugin.ts(:1063,:1078,:1097);*.test.ts; stages 1 to 11 took test comments too):dev-plugin.test.ts:90and: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
#3900atdev-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 indocs/adr/orscripts/adr-anchors/records either decision (a grep there for the 2 numbers, their PR number #10092 and the 2 shas reads 0 hits; the control number7329reads 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
patchchangeset for@objectstack/plugin-devrides along (.changeset/plugin-dev-provenance-anchors.md, in PR #20632's form), because the two rewritten docblock lines reach the publisheddist(measured below), as stage 6 (PR #20703) measured for its package.Census:
packages/plugins/plugin-dev, 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/plugins/plugin-dev/. Both runs enumerated the whole board.allocated-but-absent33e4a5609c, run 2026-09-30T02:45:30Z to 02:51:51Za237b10ee7, run 03:07:39Z to 03:14:14ZThe 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 (resolves33,038,resolves-as-pull-request1,984,cross-repo-unjudged995) are equal in both runs.Supplementary scan (test files, strings and files outside
src/included). Every#Ntoken (two to six digits) in the package's 19 tracked files,CHANGELOG.mdexcluded, was probed by REST: 39 distinct numbers at base, of which 2 answer 404 insrc/(#10035,#10036) and 1 outside it (#13176, intsconfig.test.json);#1020iscloud#1020, cross-repo. Dead occurrences at base: 6 insrc/comments (3 source, 3 test), 1 in a test string, 2 intsconfig.test.json. After: 0 in comments, the test string and the twotsconfig.test.jsonlines unchanged (see Acceptance notes). A grep for the two numbers with no word-boundary operator, beside a control of the same shape (#3900reads 6 lines ofdev-plugin.ts), finds only those three lines left.Per-number table
git blameat the base ties every one of the 6 lines to7552e0337, the commit that wrote them, and each anchor was read in its message and its diff, not only its subject.#10036dev-plugin.ts:1063,:1078;dev-plugin.test.ts:90,:127;dev-plugin-security-enforcement-warning.test.ts:537552e0337: the "RBAC/RLS/masking are NOT enforced" warning stops probing the threeSecurityPlugin.init()internals (security.permissions,security.rls,security.fieldMasker, which the spec contract names implementation internals) and asks the publishedsecurityservice instead, and asks it fromDevPlugin.start(), after the child-start loop and beside the boot banner, since asking frominit()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 (#10092) answers 404 as well.#10035dev-plugin.ts:1097c1731d023:plugin-hono-server's/auth/me/permissionsand/me/appsdelegate permission-set resolution to thesecurityservice, and their degraded branches key on the publishedsecurityservice instead ofsecurity.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";#10035is that commit's own PR number, carried in its subject.How the lines read now.
:1063keeps#3900and sayscommit 7552e0337 moved this check here from init(); the:1078heading and the test-comment brackets namecommit 7552e0337where the number stood, with the decision spelled out in the surrounding prose they already carried;:127reads(the two told apart since commit 7552e0337);:1097readscommit c1731d023 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 ofmain(merge-base --is-ancestoragainst33e4a5609c, exit 0 for both). The checkout is not shallow. Control legs:44738f7af6(the parent ofc1731d023) exits 0 against the base; the negative control (the base as an ancestor of7552e0337) exits 1.Numbers.
#10035,#10036and#10092answer 404 by REST (probed 2026-09-30T02:43:04Z and again at 03:14:40Z).#3900, kept on:1063, answers 200.Mechanical guard: no code token moves
H2 holds on the token reading; the emitted
distis 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,
getChildrenwalk, JSDoc nodes excluded) of the 3 touched files at base33e4a5609cand at37eaf1647f(the comment commit). Controls mutate the head text in memory only.StringLiteral.All 12 changed lines in
src/(6 out, 6 in) are//or*comment lines.Emitted
dist.pnpm --filter @objectstack/plugin-dev buildat base (before any edit, after its dependency closure) and at37eaf1647f. Of the 6distfiles,index.js.mapandindex.mjs.maphave equal sha256;index.js,index.mjs,index.d.tsandindex.d.mtsdiffer, anddiff -rshows exactly two changed lines in each: the:1078heading and the:1097line of thewarnIfNothingIsEnforcingSecuritydocblock. The//comment at:1063does not ship. So the published tarball carried both dead numbers, and now carries the commits.scripts/ablation-replace.mjs, wrap mode, anchorctx.logger.info(' Discovery: /.well-known/objectstack');hit 1 to 0, planted marker 0 to 1, blob708af69f9b2atob0b387f53d6a;scripts/ablation-dist-preflight.mjsfound the marker indist/index.jsanddist/index.mjs):index.js,index.mjsand both source maps differ from the head build. The blob was restored to HEAD708af69f9b2awithgit diff HEADempty,distwas rebuilt, the preflight in--absentmode reads the marker absent from all 6 files with a clean tree, and the 6 sha256 values equal the head build.plugin-dev'sdistequal 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-bytesexits 0.Changeset
patchfor@objectstack/plugin-dev. The package publishes (filesisdist,README.md,CHANGELOG.md), and the measurement above shows the rewritten docblock reaching fourdistfiles. 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) andcheck-changeset-fixedall exit 0.Gates (head
a237b10ee7)This host has no
flock, soos-verify-lock.shran 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):Its verdict line from each run (the closure build at base
33e4a5609c; the head build at37eaf1647f; the whole-workspace build, the tests and the typecheck at this head):plugin-devwith 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.vitest run --maxWorkers=2: 9 files, 86 tests, all passed.pnpm --filter @objectstack/plugin-dev typecheck(tsc --noEmit, thencheck:test-typecheckovertsconfig.test.json) exits 0.--listFilesunder both configs reaches all 12src/files, including the 9 tests and the 3 touched files.origin/maindid not move while this branch was open (still33e4a5609c; the merge was a no-op), and this diff does not touchpackages/spec.pnpm lint(eslint . --no-inline-config) exits 0 at this head (2026-09-30T03:07:02Z to 03:07:32Z).origin/main(already up to date at33e4a5609c),node scripts/check-issue-citations.mjs --base origin/mainjudges 1 added citation (#3900), which resolves (exit 0).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 62 families from the 4 changed paths. All 62 exit 0 in one pass at this head, and--ranwith 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.check-changeset-fixedand 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)
33e4a5609cthe filtered census answers 3 sites on 3 lines, 2 numbers, 1 file, as on the seat's0be898499f. The whole-repo count is 1,061.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 chore: version packages #20639 touches the package, 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 emitteddistis 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
describetitle atdev-plugin-security-enforcement-warning.test.ts:121(#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 underscripts/fixtures/merge-queue-triage/; those are captured logs read bycheck-merge-queue-triage-outcome.mjs, so a later rename of the title does not need them edited.src/**:tsconfig.test.json:3and:56cite#13176, which answers 404. The same number sits in thetsconfig.test.jsonof 13packages/plugins/*packages (17tsconfig*.jsonfiles underpackages/in all), outside the census's declared surface; stage 10 (PR docs(plugin-hono-server): re-anchor the dead tracker citations in packages/plugins/plugin-hono-server/src to the commits that decided them #20741) recorded its own copy for a later stage of this card. Every other citation in the package outsidesrc/answers 200 (vitest.config.ts,README.md,tsconfig.json,package.json);CHANGELOG.mdis release-owned and was not read as a site.origin/maindid not move. It read33e4a5609cat worktree creation and at every later fetch, so every run above is against the same base and nothing needed rerunning after the merge.Deviations
os-verify-lock.sh. On this host that wrapper runs unlocked anyway, so nothing was serialized either way.'@objectstack/plugin-dev...'(package plus its dependencies) rather than the closure-only^...spelling; it built the same closure and the package in one run.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.Generated by Claude Code