Repository navigation
docs(create-objectstack): re-anchor the dead tracker citations in packages/create-objectstack/src to the commits that decided them - #20748
Merged
objectstack-fleet[bot] merged 2 commits intoSep 30, 2026
Conversation
…kages/create-objectstack/src to the commits that decided them Stage 11 of the domain:cli lane of the dead-citation sweep. 25 comment sites that cited a tracker number answering 404 now cite, in ruling C+D's form C, the commit in this repository's history that decided what the line describes: cec9d23 (the banner reads its own version), 8d21f7a (Next steps names the detected package manager), c27e160 (the boot-probe neighbour reports why it did not come up), fd75728 (the skills bundle is installed for one agent), 21756b3 (scaffold docs converge on the canonical host), cc986c9 (the escaping-relative-path MONOREPO_ONLY pattern), 4998efa (the blank template's CI workflow) and 675ab57 (the two benign peer skews are declared). Comments only; every file keeps its line count; no tracker number is added. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude <noreply@anthropic.com>
…eate-objectstack-citations
Contributor
📓 Docs Drift Check
What this run could not see
Coarse fallback — 11 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
objectstack-fleet
Bot
deleted the
claude/issue-20594-create-objectstack-citations
branch
September 30, 2026 02:37
This was referenced Sep 30, 2026
Merged
os-warren
pushed a commit
that referenced
this pull request
Sep 30, 2026
The recogniser admits only its one exact shape and refuses a pull_request / push / merge_group term, a negation and every live mixed if:; the derivation refuses a shared, a listed and an untellable name; the measured #20748 head judges 0 with its raw-named canary and 4 with a genuinely unexpected skip beside it, both in-process and through the CLI on a payload file. Claude-Session: https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…ts that decided them (objectstack-ai#20757) Part of objectstack-ai#20596 Clause-②: no ## What changed This is the eleventh stage of the `domain:services` lane of the dead-citation sweep. It covers `packages/plugins/plugin-email/src/**` and nothing else. By the seat's census at the claim (`5902547086`), 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 10 (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`, PR objectstack-ai#20737 as `4dfff176b`, PR objectstack-ai#20742 as `697845d19`). That is **16 sites on 16 lines in 8 files, covering 4 numbers**: - 7 census sites (every census site this package has); - 9 sites in test comments, which the census defers. Three of them carry `objectstack-ai#13190`, a dead number that stands only in test files here, so the census never judged it; it was read on its own (404); - no site the gate's grammar cannot see (the package has none that is dead, see Acceptance notes). 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: **4 distinct shas**. No number in this package has an ADR or ruling record of its own (a grep of `docs/adr/` and `scripts/adr-anchors/` finds only ADR-0131 naming `objectstack-ai#11741`, as evidence in its D7, not as the record of that decision; nothing else under `docs/` names the four), 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 (16 lines out, 16 in, over 8 files), so no line citation into these files moves. Every one of the 16 changed lines carried a dead citation; there is no reflow line. No code token moves (see the guard below). **No citation number is added.** The added lines carry no tracker number at all. Over the whole diff, added minus removed is negative for the four dead numbers and zero for every other number, and no number is new to the diff. No PR number is the citation on an added line: the two `PR objectstack-ai#8675` spellings became that pull request's squash commit. 10 dead sites are left on purpose, all of them `describe` / `it` titles (see the list below). One more file: a `patch` changeset for `@objectstack/plugin-email`, because the rewritten prose ships (see Changeset below). ## Census: `plugin-email`, 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-email/`. Each run counts as a reading only because its board frontier equals the newest issue or pull-request number, read by a separate request just before and just after the run. | reading | tree | board | whole-repo `allocated-but-absent` | plugin-email sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `97005aed0`, run 2026-09-30T02:00:45Z to 02:04:02Z | enumerated, 186 pages, frontier objectstack-ai#20748 (newest objectstack-ai#20747 before, objectstack-ai#20748 after: a pull request opened at 02:03:20Z, inside the run) | 1,064 | **7** | 7 | 4 | 3 | | after | head `15a7d69a7`, run 02:11:19Z to 02:14:30Z | enumerated, 186 pages, frontier objectstack-ai#20753 (newest objectstack-ai#20753 before and after) | 1,057 | **0** | 0 | 0 | 0 | The before count matches the seat's census and A1 (7 sites: `objectstack-ai#13189` ×4, `objectstack-ai#11741` ×2, `objectstack-ai#8675` ×1). The before run's board moved during the run; its frontier equals the newest number at the run's end, which is A1's criterion (stage 7's precedent). The whole-repo drop is 7, exactly this diff's census sites. The `resolves` tally is 33,029 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 `15a7d69a7`; the head `23283d394` 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-email/src` (50 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,072 rows) and did not report it. The eleven numbers the census never saw, because they stand only in test files or as the second half of a slash pair here, were read one by one on the issues endpoint: `objectstack-ai#13190` answers 404; `objectstack-ai#5169`, `objectstack-ai#5286`, `objectstack-ai#10619`, `objectstack-ai#16506`, `objectstack-ai#20374`, `objectstack-ai#5197` answer 200 as issues, and `objectstack-ai#8348`, `objectstack-ai#5191`, `objectstack-ai#5211`, `objectstack-ai#5232` as pull requests. | reading | citations | dead | src comment | test comment | src string | test string | |---|---|---|---|---|---|---| | before, `97005aed0` | 360 | **26** | 7 | 9 | 0 | 10 | | after, `15a7d69a7` | 344 | **10** | 0 | 0 | 0 | 10 | Its src-comment column equals the census's 7, which is the control on the second instrument. The 323 live citations are the same in both readings, and the drop of 16 citations is exactly the rewritten sites. 11 extracted tokens are not tracker references at all and are not judged: the HTML entity `&objectstack-ai#39;` (6 sites in the template engine and its tests) and the fixture subjects `Invoice objectstack-ai#42` to `Invoice objectstack-ai#45` (5 sites). A third, raw reading (every `#` followed by 2 to 6 digits, whatever surrounds it) finds 371 occurrences and 26 dead before, 355 and 10 after. Beyond the gate's grammar it sees 11 tokens, none dead: the nine second numbers of the `#A/#B` lines (all live), the excused `Prime Directive objectstack-ai#12`, and the CSS colour `#2563eb`. ## 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 16 line and anchor pairs). | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#13189` | 13/4 | 8/5 | `33fbd3566` (PR objectstack-ai#13375): the SMTP port guard tests integrality (`Number.isInteger`), so a fractional port such as `587.5` is refused at construction, and the generated refusal sentence reads `(expected an integer 1-65535)`, the range still rendered from the constants. Its changeset headline names `objectstack-ai#13189`; its diff writes the integrality docblocks the rewritten lines sit in. New to the sweep | | `objectstack-ai#13190` | 5/1 | 3/2 | `56c5b1dbe` (PR objectstack-ai#13316): `smtpOptionsFromMailSettings` passes a present-but-unreadable `smtp_port` through to the guard instead of omitting it (which had silently fallen back to 587); absent and `''` still mean "not set", and no second refusal was added. Its changeset headline names `objectstack-ai#13190`; its diff writes the `objectstack-ai#13190` comment block itself. New to the sweep | | `objectstack-ai#11741` | 6/3 | 3/3 | `b706af987` (PR objectstack-ai#11839): `SendEmailInput` / `SendTemplateInput` gain an optional `organizationId`, which `plugin-email`'s writer stamps verbatim onto `sys_email.organization_id` (pass-through only, no resolution or fabrication), and `sendTemplate` forwards it as a producer of `send()`. Its message names `objectstack-ai#11741` as the card that commit closed; `git blame` puts all three rewritten lines in it. The `plugin-auth` stage's anchor for the same number | | `objectstack-ai#8675` | 2/2 | 2/0 | `c9f595083`: the squash commit of the pull request that was `objectstack-ai#8675` (its subject ends `(objectstack-ai#7987) (objectstack-ai#8675)`): `sys_account`'s OAuth token columns are declared `internal: true`. Its diff records the trap both lines describe: those columns are `required: false`, so inferring "key missing, therefore the strip ran" broke ordinary sign-in (16 red tests), which is why the readback carries the `absenceProvesStrip` discriminator. New to the sweep | Every cited sha matches exactly one commit (`git rev-parse --disambiguate`, count 1 for each of the 4), and every one is an ancestor of the base (`merge-base --is-ancestor`, exit 0 for all 4; control leg: stage 1's landing `422db788a` exit 0; the history is complete, `--is-shallow-repository` false, 15,155 commits). Each of the 4 numbers answers 404 on the issues endpoint, which serves pull requests too. Independently, the package's own shipped `CHANGELOG.md` pairs `b706af9`, `33fbd35` and `56c5b1d` with the same three decisions. ## Wordings to check - **Tag swaps in parentheses.** 「(objectstack-ai#13189)」 became 「(commit 33fbd35)」 at `transports/smtp-port-contract.ts:87` (a section heading), `:134` and `transports/smtp.ts:68`. - **Line openers.** 「objectstack-ai#11741 —」 became 「Commit b706af9 —」 at `email-service.ts:742` and `:1439`; 「objectstack-ai#13190 —」 became 「Commit 56c5b1d —」 at `transports/smtp.test.ts:221`; 「## objectstack-ai#13189 —」 became 「## Commit 33fbd35 —」 at `transports/smtp-port-contract.test.ts:34`. - **`email-service.test.ts:342`**, a section rule: 「── objectstack-ai#11741 —」 became 「── Commit b706af9 —」, and its trailing rule was shortened by 10 characters so the line keeps its width exactly. - **`internal-header-readback.ts:37`.** 「(PR objectstack-ai#8675 hit exactly this on `sys_account`'s optional」 became 「(Commit c9f5950 records exactly this on `sys_account`'s optional」: a commit does not "hit" a trap, it records one, and that commit's own diff is where the 16 red tests are recorded. - **`email-headers-internal.integration.test.ts:251`.** 「The regression PR objectstack-ai#8675 measured on a sibling card」 became 「The regression commit c9f5950 records from a sibling card」, the same reading. - **`transports/smtp-port-contract.test.ts:228`.** 「objectstack-ai#13189 is the card that SPENDS that」 became 「Commit 33fbd35 is the change that SPENDS that」, so the noun matches the anchor. - **`transports/smtp.ts:127`, `transports/smtp.test.ts:272`, `:276`, `:281`, `:283`.** The number became 「commit SHA」 in place (「until commit 33fbd35:」, 「The bucket commit 56c5b1d never had to name」, 「Commit 33fbd35 made the guard test」, 「Commit 56c5b1d's rule is that」, 「commit 33fbd35 changed which numbers」). ## The 10 sites left - **Test strings, 10 sites on 9 lines**, all `describe` / `it` titles, left as stages 1 to 10 left theirs: `email-service.test.ts:349` and `send-template.test.ts:63`, `:88` (`objectstack-ai#11741`); `transports/smtp-port-contract.test.ts:225`, `:309`, `:340` (`objectstack-ai#13189`); `transports/smtp.test.ts:230` (`objectstack-ai#13190`), `:271` (`objectstack-ai#13189`), `:293` (`objectstack-ai#13190` and `objectstack-ai#13189`). - No source string, operator log string, assertion message, quoted maintainer ruling or generated file in this package carries a dead number. - Outside `src`, the package's `CHANGELOG.md` names three of these numbers on 5 lines. It is release-owned and deliberately not edited here (see Acceptance notes). ## Mechanical guard: no code token moves The guard compares the TypeScript parser's leaf nodes (a `forEachChild` walk, so comments are trivia and JSDoc nodes are never visited), base `97005aed0` against head. String and template literals are therefore read in full. It ran over all 8 touched `.ts` files. - Real run: 7,035 base leaf tokens, **0 files with a token change** (exit 0). - Comment control in `email-service.ts` (「no resolution, no default, no fabrication」 to 「… no default and no fabrication」): 0 files changed, as expected (exit 0). - Positive control, a code token added in `transports/smtp.ts` (`isValidSmtpPort(port)` given `as number`): DIFFER, 587 to 588 leaf tokens (exit 1). - Positive control, one digit changed inside a kept test title (`transports/smtp.test.ts:293`, `objectstack-ai#13189` to `objectstack-ai#13188`): DIFFER (exit 1). Every mutation went through `scripts/ablation-replace.mjs` (wrap mode) under a shell trap that restores by absolute path, and each landed (anchor 1 to 0, blob changed). Each restore was proven byte-identical to the HEAD blob (`1e99bd5e2bcb`, `46c13267611b`, `da5314910bc4`), with `git diff HEAD` empty and a clean tree afterwards. ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/plugin-email` (`.changeset/20596-plugin-email-provenance-anchors.md`) is included. Its body is stage 10's, word for word, with the package name changed. Measured on the built package (A3): `files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the package is not private. After the build, `b706af987` appears twice in each of `dist/index.js` and `dist/index.mjs` (the two inline comments in `email-service.ts`, which the bundle keeps). `c9f595083` appears once in each of `dist/index.d.ts` and `dist/index.d.mts` (the `internal-header-readback.ts` docblock), and so does `33fbd3566` (the docblock on `SmtpTransportOptions.port`). `56c5b1dbe` reaches nothing (test files only). Positive controls, one unchanged line beside each shipped rewrite, land exactly where their neighbours do: 「context, so the input's organization is the one fact it may stamp:」 and 「caller's organization so the sys_email row it persists is stamped.」 once in each JS file; 「token columns: inheriting」 and the unchanged line just above the rewritten one in the `port` docblock once in each declaration file. A never-written negative phrase appears nowhere in `dist`. None of the 4 dead numbers is left in `dist`. ## Gates (head `23283d394`) - **Citation judging, as CI runs it:** `pnpm check:issue-citations` exits 0. `node scripts/check-issue-citations.mjs` exits 0: the diff-scoped run found no citation added against `97005aed0` (4 files read; test files are a deferred surface). - **Doc authoring:** `pnpm check:doc-authoring` exits 0. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `23283d394` derived 61 commands: all 55 derived at dispatch, plus `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 61 exit 0. `--ran`, fed each command with its exit code, reports 61 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. - **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-email test`: 31 files pass and 510 tests pass. `vitest list --filesOnly` names 31 files, all the tracked test files, the 4 touched ones included. - `pnpm --filter @objectstack/plugin-email typecheck` exits 0 (`tsc` on `tsconfig.json`, then `check:test-typecheck` on `tsconfig.test.json`: 0 files and 0 errors in its debt ledger). `tsc --listFiles` holds all 8 touched files in both programs, and the test program holds all 50 files under `src/`. - **Lint, as a proven narrowing:** eslint with inline config disabled, over the 8 touched `.ts` files, gives 8 files, 0 errors and 0 warnings. All 8 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 9 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` 9 lines, `option #N` none, at the base and at the head, which is the claim's 0 / 9 / 0. Every second number on the 9 slash lines answers 200 (`objectstack-ai#5197` ×2, `objectstack-ai#5191`, `objectstack-ai#5211`, `objectstack-ai#5232` ×2, `objectstack-ai#5177`, `objectstack-ai#4251`, `objectstack-ai#5094`), so nothing there needed rewriting. - **ADR-0131 names `objectstack-ai#11741`.** Its D7 cites `objectstack-ai#11741` as the writer fact that keeps `sys_email` tenant data. That is evidence inside a later record, not the record of what `objectstack-ai#11741` decided, so it is not this stage's anchor, and `docs/adr/**` is a governed Tier H surface outside this card's stages. It joins the ADR-tree residue the seat already carries (ADR-0131's `objectstack-ai#14484`, stage 2). - **`CHANGELOG.md` is left.** `packages/plugins/plugin-email/CHANGELOG.md` names `objectstack-ai#11741`, `objectstack-ai#13189`, `objectstack-ai#13190` and `objectstack-ai#8675` on 5 lines. It is release-owned (AGENTS.md, Documentation Guardrails), a deferred surface of the citation gate, and ⛔ not part of this stage. - **「This card」 phrases are left.** 20 comment lines in 8 files of this package speak of 「this card」, 「the card」 or 「the two cards」. They carry no number and neither instrument sees them. Inside the `objectstack-ai#13189` test block, they still have the kept `(objectstack-ai#13189)` title as their referent; the one rewritten line that said 「the card」 now says 「the change」 (above). The rest are unchanged, as in stages 8 to 10. - **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#13189` → `33fbd3566`; `objectstack-ai#13190` → `56c5b1dbe`; `objectstack-ai#8675` → `c9f595083`. `objectstack-ai#11741` → `b706af987` reuses the `plugin-auth` stage's anchor. - **Base.** The branch is on `main` at `97005aed0`. `main` has since moved two commits (`9c8f113c6`, `a6866da0c`). Their 14 files touch nothing under `plugin-email`, nor `scripts/check-issue-citations.mjs`, `.changeset/config.json` or the `doc-authoring-prose-id` baseline, and the three console-injection scripts they change are not among this diff's 61 derived families. 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>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…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>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…expected skips under their raw name (objectstack-ai#20835) Fixes objectstack-ai#20756 Clause-②: no ## What changed `scripts/pm/check-expected-skips.mjs` now **derives** a second half of its expected-skip roster from the workflows, next to the eleven listed rows. The listed rows are unchanged. The derived half admits a job if its job-level `if:` is a disjunction of `github.event_name == 'schedule'` / `github.event_name == 'workflow_dispatch'` terms **only**, optionally wrapped whole in one `${{ }}`. Such a job skips on every `pull_request`, `push` and `merge_group` run by construction. The row takes the check-run name GitHub reports for that skip: `name:` verbatim, else the job key. The judge (`--pr` / `--head` / `--check-runs-json`) and `--roster` both read the joined roster. There is no literal `Registry canary` entry. - **Recogniser, not evaluator.** `nonPrEventGate` is an allow-list of one comparison shape, `github.event_name == 'EVENT'`, joined by `||`. It returns null on anything else: `&&`, `!=`, parentheses, `inputs.*`, `needs.*`, `success()`, `matrix.*`, a label read, a case-folded or double-quoted literal, two `${{ }}` blocks, or an event outside the closed `NON_PR_EVENTS = ['schedule', 'workflow_dispatch']`. `push` and `merge_group` are refused on purpose. The header's boundary still holds: nothing here evaluates GitHub's expression language or `paths:` filters. - **The name rule (`skippedCheckRunName`).** GitHub evaluates a job-level `if:` before it expands the matrix, so a gated matrix job's skipped check-run keeps each `${{ matrix.* }}` literally. Only a bare matrix reference is admitted. A name holding any other expression, a matrix reference on a job with no `strategy.matrix`, or a non-string `name:` is refused, because its skipped spelling is unmeasured. Expanded names are deliberately **not** rostered: an expanded job ran, so its check-runs are never a gate skip. - **Refusals are the safe direction.** A candidate stays out of the roster, and so still answers exit 4, when any of these holds: - another job anywhere in the tree carries the same check-run name, so a skip of that other job would read expected; - the listed roster already carries the name (derive, don't list); - the name cannot be told; - its workflow cannot be read. The live self-test holds the refusal list at empty, so a job's author hears about a refusal before a landing seat does. ## Measured **Premise, confirmed.** The shape is on the real check-run: in the full `GET /commits/a84b73af13/check-runs` listing for PR objectstack-ai#20748 (42 runs), `Registry canary: ${{ matrix.template }}` is `skipped` in check suite 99276458880 (run 36658032070). It sits beside `Scaffold with repo dist` = success in the same suite. `.github/workflows/scaffold-e2e.yml` at `origin/main` `73155fed` declares the job as `name: 'Registry canary: ${{ matrix.template }}'` / `if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'`, with no `needs`. **What the predicate admits on this tree (39 workflow files, `73155fed`): 2 jobs, 0 refused.** | workflow › job | check-run name | `on:` | runs on a PR? | |---|---|---|---| | `scaffold-e2e.yml` › `registry-canary` | `Registry canary: ${{ matrix.template }}` | pull_request (paths), schedule, workflow_dispatch | never: skipped on every PR run | | `publish-smoke.yml` › `registry-canary` | `Registry canary (published latest)` | workflow_run (Release), schedule, workflow_dispatch | never: the workflow has no PR trigger | These job-level `if:`s read `github.event_name` and are **not** admitted, pinned live: - `release.yml` › `version-pr`: a `workflow_dispatch` term conjoined with `inputs.refresh_version_pr`. - `release.yml` › `release-integrity` / `stale-prompts` / `publish`: `push`, `inputs`, `needs` outputs. - `merged-branch-reaper.yml` › `reap`: `success()`, `!= 'pull_request'`, `inputs.dry_run`. - `publish-smoke.yml` › `resolve` and `scaffold-e2e.yml` › `scaffold-local`: `!= 'schedule'`. `scaffold-local` runs on every PR. **Live control** (`node scripts/pm/check-expected-skips.mjs --pr 20748`, read-only): - before (`73155fed`): `VERDICT check-expected-skips: ⛔ 1 skipped check-run(s) outside the roster (exit 4)`, naming `Registry canary: ${{ matrix.template }}`; - after (`3993387d`): `VERDICT check-expected-skips: OK — 8 skipped check-run(s), every one in the roster (exit 0)`. The canary is listed as `[scaffold-e2e.yml › registry-canary; derived]`. - A second, unrelated control (`--pr 20816`, after) still answers `OK — 3 skipped … (exit 0)`. ## Pins (`pnpm check:pm-expected-skips`, 99 → 154 cases) - **The card's pin.** The measured objectstack-ai#20748 listing is carried verbatim as `MEASURED_20748`. On disk through `--check-runs-json` it answers **exit 0**, with the canary tagged derived. In-process against the joined roster it is 0 as well. Against the listed half alone it still names the canary, which shows the derivation is what moved it. - **The control.** The same head plus a genuinely unexpected skip answers **exit 4**, naming only that skip: `Lint & Repo Gates` through the CLI, `TypeScript Type Check` in-process. The canary's PR-running sibling `Scaffold with repo dist`, when skipped, also answers 4. - **Narrowness.** `github.event_name == 'schedule' || github.event_name == 'pull_request'` is not admitted. The synthetic tree's job carrying that `if:` answers exit 4 when skipped. `push`, `merge_group`, negation, `inputs`, `needs`, `success()`, `matrix`, label, parenthesised, case-folded and double-quoted forms each have their own null case. So do both live mixed shapes (`version-pr`, `reap`). - **The derivation's refusals** are each driven on a synthetic tree: a shared name, a listed name, an untellable name, an unreadable file. **Ablation (committed first, restore proven).** At `3993387d`, `node scripts/ablation-replace.mjs` replaced the recogniser's first line with `return null;`. On disk: anchor x1 → x0, marker x0 → x1, blob `a999480b` → `0dc4f77f`. The self-test then went **red: 22 of 154 failed**. Among the red cases: - `measured objectstack-ai#20748: the raw-named skipped canary judges exit 0 … (got 4, want 0)`; - `cli: the measured objectstack-ai#20748 head on disk (raw-named skipped canary) → exit 0 (got 4, want 0)`. The control and narrowness cases stayed green, which is the expected direction. The restore was proven: blob after restore == blob at HEAD (`a999480b`), `git diff HEAD` empty, marker count 0, `git status --porcelain` empty. ## Gates `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` was run with no paths at `3993387d`. It derived the same 30 commands the dispatch named. **All 30 ran and all 30 answered exit 0**, including `pnpm check:pm-dispatch-gates` (`✓ dispatch-gates self-test: 1976 cases pass.`) and `pnpm check:pm-expected-skips` (154 cases). `--ran` reconciles: `30 derived famil(ies) accounted for — 30 run, 0 NOT-MEASURED`. Lint was narrowed to the one touched file and still counts as a measurement: - eslint's own config resolves for `scripts/pm/check-expected-skips.mjs`: `--print-config`, 2 rules, the file is not ignored; - `--no-inline-config --format json` reports 1 file, 0 errors, 0 warnings; - the config enables no type-aware linting (no `parserOptions.project`, no `projectService`), so this diff cannot move the verdict on any untouched file. `dispatch-gates.mjs` pins this file's `self-test-reads` declaration at line 131. Every edit here keeps that line in place: the one header sentence changed is rewritten in the same line count. `skip-changeset` basis: the diff is `scripts/pm/check-expected-skips.mjs` alone. It sits under the repo root, whose `package.json` is `private: true`. None of the 69 non-private `package.json` files in the tree has a directory that contains `scripts/pm/`, so the diff publishes nothing. The seat applies the label. ## Acceptance notes - **A residual exit 4 remains on PRs that edit `merged-branch-reaper.yml`.** That workflow's `pull_request` trigger is path-filtered to itself, and its `reap` job (`Delete the reapable branches`) skips on those runs by design. The narrow recogniser refuses its `if:` by construction (`success()` plus `inputs.dry_run`), as the dispatch required. It is noted here and not filed (carrier: none). - **Expanded matrix names are not rostered, although the dispatch's mechanism note mentioned them.** A job reports expanded names only once it has run, and a run is never a job-level skip. Adding them would widen the roster with names that cannot skip by design. - **This file's `--self-test` pins no battery floor.** It keeps its handshake (`selfTestReachedVerdict`-equivalent `SELF_TEST_VERDICT` record) but has no `SELF_TEST_BATTERIES` floor as AGENTS.md describes. That was true before this PR; the new cases join its existing sections. Noted, not changed (carrier: none). --- _Generated by [Claude Code](https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #20594
Clause-②: no
What changed
This is stage 11 of the
domain:clilane 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 #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 10 of this card (PR #20624, PR #20632, PR #20656, PR #20673, PR #20689, PR #20703, PR #20713, PR #20723, PR #20735, PR #20741) are the precedents. The card stays open for the lane's remaining packages, so this PR saysPart of.That is 25 sites on 25 lines in 10 files, covering 9 numbers, rewritten to 8 distinct commits:
src/banner.ts2,src/index.ts1 (2 numbers);*.test.ts; stages 1 to 10 took test comments too):starter-comments-self-contained.test.ts9,scaffold-e2e-boot-probe.test.ts3,banner-version.test.ts2,blank-readme-validate-disclosure.test.ts2,scaffold-next-steps-pm.test.ts2,template-consistency.test.ts2,scaffold-skills-single-copy.test.ts1,template-ci-workflow.test.ts1.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/orscripts/adr-anchors/records any of these 9 decisions (a grep for the 9 numbers there reads 0 hits; the control number#7329reads 2 in the same tree), so every anchor is a commit.No changeset;
skip-changeset. The rewritten comments do not reach the publisheddist(measured below), as in stages 5 and 7 (PR #20689, PR #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 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/create-objectstack/. Both runs enumerated the whole board.allocated-but-absent01e78dceef, run 2026-09-30T01:14:08Z to 01:19:48Z4ed638093d, run 01:30:22Z to 01:35:31ZThe 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 (resolves33,014,resolves-as-pull-request1,984,cross-repo-unjudged995) are equal in both runs.packages/create-objectstackis byte-identical at4ed638093dand at the head (the one merge brought no file under it).Supplementary scan (test files, strings and files outside
src/included). The gate's exportedextractCitationsandclassifyCitationover all 53 tracked files of the package (CHANGELOG.mdexcluded), comment-prose and whole-file projections, with the board from the gate's ownprobeBoard: 77 citations and 33 dead before, 52 and 8 after. Undersrc/: comments 3 dead to 0, test comments 23 to 1, test strings 7 unchanged;src/templates/**0 citations of any kind. Outsidesrc/, one citation (vitest.config.ts:24,#10374) answers 200. Its before list ofsrc/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 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.#10325banner.ts:10;banner-version.test.ts:3cec9d239d: the startup banner reads the real version frompackage.jsonthrough the newrenderVersionBanner(), and sizes the box from the version's plain length, widening and never truncating, instead of the hardcodedv6.x. Both lines blame to it; its message carries the closing trailer for this number. New anchor.#10322banner.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,:78d21f7a76: 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 fornpm), and namevalidatein the blank README's "Getting started". Its message carries the closing trailer for this number.index.ts:441and the two test headers blame to it;banner.ts:17andbanner-version.test.ts:17blame tocec9d239d, whose message calls this "the sibling bug fixed one function away in the same file";scaffold-next-steps-pm.test.ts:7blames toc6c7feccd, a re-wrap that keeps the sentence. New anchor.#19424scaffold-e2e-boot-probe.test.ts:397,:679,:816c27e16059: the boot-probe neighbour announces its own listener (or its bind error), asks the kernel for its port withlisten(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.#16331scaffold-skills-single-copy.test.ts:3fd75728bc: 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.#10990starter-comments-self-contained.test.ts:41,:28321756b325: converge the shipped template files on the ruled canonical docs origin and pin that convergence as assertion 4 overshippedFiles(). Both lines blame to it; its message carries the closing trailer for this number. New anchor for this number.#11022starter-comments-self-contained.test.ts:50,:91,:122,:22121756b325: rewrite the blank README's two monorepo-only references, add the fifthMONOREPO_ONLYpattern (the framework's own name next to a "repo" word), retire the self-retiringEXCLUDEDentry and add the README's two RATIONALE facts. All four lines blame to it. Stage 3 (PR #20656) gave this number the same anchor.#15150starter-comments-self-contained.test.ts:72,:133,:141cc986c913: the sixthMONOREPO_ONLYpattern, 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.#16330template-ci-workflow.test.ts:3;template-consistency.test.ts:3764998efa71: ship.github/workflows/ci.ymlin 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.#10326template-consistency.test.ts:498675ab574e: declare the two benign peer skews a clean first install reported as scoped pnpmallowedVersionsinside the scaffold. The line blames to it. Stage 3 (PR #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 ofmain(merge-base --is-ancestoragainst01e78dceef, exit 0 for all 8). The checkout is not shallow. The control leg2aca1bc4c0(the parent of the oldest anchor675ab574e, 2026-08-20) exits 0 against the base, and the negative control (the base as an ancestor of675ab574e) 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,
#9779(scaffold-e2e-boot-probe.test.ts:673), answers 200. The anchor commits' own PR numbers are not cited: three of them (#11030, #11013, #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(#11048): "admitting them is a support decision (#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 #20656) left the sibling sitepackages/cli/src/commands/init.ts:267for 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
distand the scaffolded project are byte-identical.Token guard. It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3,
getChildrenwalk, JSDoc nodes excluded) of the 10 touched files at base01e78dceefand at4ed638093d. Controls mutate the head text in memory only.StringLiteral, exit 1.All 50 changed lines (25 out, 25 in) are
//or*comment lines.Emitted
dist.pnpm --filter create-objectstack buildat base (before any edit) and at4ed638093d, after the same dependency build. All 24distfiles (index.js,chunk-ZIUW7UEA.js,created-summary.js,created-summary.d.tsand the 20 copied template files) have equal sha256 at base and head, anddiff -ris empty. None of the dead numbers appears in the basedistat all: tsup drops these comments.scripts/ablation-replace.mjs, wrap mode, anchorDependency installation failed.hit 1 to 0, planted marker 0 to 1, blobb68538942c96to860de8778f10;scripts/ablation-dist-preflight.mjsfound the marker indist/index.js):index.jsdiffers from the head build. The blob was restored to HEADb68538942c96withgit diff HEADempty,distwas rebuilt, the preflight in--absentmode reads the marker absent from all 24 files with a clean tree, and the 24 sha256 values equal the first head build.create-objectstack'sdistequal 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 -ris 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-bytesexits 0.Changeset
None;
skip-changeset. The package'sfiles[]isdist,README.mdandCHANGELOG.md; the build above emits a byte-identicaldistat 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, 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 and the base build at
01e78dceef; the head build, the first whole-workspace build, the tests, the boot-probe file and the typecheck at4ed638093d; the second whole-workspace build, tests and typecheck at this head after the merge):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.vitest run --maxWorkers=2: 16 files, 247 tests: 233 passed and 14 skipped, at this head and at4ed638093d. The 14 skipped are the whole ofscaffold-e2e-boot-probe.test.ts(run alone: 1 file skipped, 14 tests skipped), which its ownRUNNABLEgate (process.platform === 'linux', plusbash,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.pnpm --filter create-objectstack typecheck(tsc --noEmit) exits 0 at this head and at4ed638093d.--listFilesreaches 26src/files outsidesrc/templates/, including all 16 tests and all 10 touched files.origin/main's one incoming commit nor this diff touchespackages/spec.pnpm lint(eslint . --no-inline-config) exits 0 at this head (2026-09-30T02:00:09Z to 02:00:43Z), and at4ed638093d(01:49:31Z to 01:50:04Z).origin/main(697845d19f),node scripts/check-issue-citations.mjs --base origin/mainreports "no issue citations added against 697845d (2 file(s) read)" (exit 0).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 52 families, the same list at4ed638093dand at this head. All 52 exit 0 at this head in one pass, and--ranwith 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.check:scaffold-emission-policyand 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)
01e78dceefthe filtered census answers 3 sites on 3 lines, 2 numbers, 2 files, as on the seat's0be898499f. The whole-repo count is 1,077.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 chore: version packages #20639 touches the package, inCHANGELOG.mdandpackage.json) or for an unfound anchor. The one site left for an unfound anchor is a test comment, outside the census.distand the scaffolded project are byte-identical at base and head, with a code-mutation control that changesdist.Acceptance notes
src/:banner-version.test.ts:66and:96(#10325),blank-readme-validate-disclosure.test.ts:25(#10322),scaffold-e2e-boot-probe.test.ts:829(#19424),scaffold-next-steps-pm.test.ts:173and:197(#10322),template-consistency.test.ts:503(#10326). They stay on the card for its form-D stage; no string moved here. None is an assertion text or scaffold output.src/**: nothing dead. The one citation there,vitest.config.ts:24(#10374), answers 200;README.mdandbin/carry none.#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 by8d41998b0, whose own message names#4926(the remote-template object-name rewrite being silently skipped), andf2f09e4e3repeated it atruntime-image.ts:140;#4902itself is an unrelatedinit-serviceguard PR.#3120(template-copy.ts:20;template-consistency.test.ts:259) was written by3b6ef8a32(the scaffolded.gitignore), and#3120is an unrelated approvals-docs PR. The census reads both asresolves-as-pull-request, a reading and not a finding, and this card is about 404s, so neither moved here. Noted, not filed.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.origin/main. The branch mergedorigin/mainonce (a84b73af13, merging697845d19f: PR docs(service-package): re-anchor the dead tracker citations to the commits that decided them #20742, theservice-packagecitation re-anchoring). Nothing underpackages/create-objectstackorpackages/specchanged, 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
check:dual-build-cjs-loads,check:lean-entry-closureandcheck:type-check-debtexited 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.ablation-replace.mjsrefused 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.os-verify-lock.sh. On this host that wrapper runs unlocked anyway, so nothing was serialized either way.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