Repository navigation
docs(spec): four conversion summaries state their decision in words instead of a deleted tracker number (stage 9) - #20718
Conversation
…that cited deleted tracker numbers (stage 9) Ruling C+D form D: a conversion `summary` is author-shown (`os migrate meta`, spec-changes.json, the protocol upgrade guide), so it carries the lesson, not a number to look up. The four numbers removed answer 404 on the board; the lit reference in the submitLabel summary stays. No id, surface, verdict or code token moves. The comment clause at the withdrawn field-required-notnull-explicit entry said every docblock around retiredFromLoadPath misstates it; the flag's own docblock has stated the authoring-only reach since commit 29dd1a6, so the clause now says that. Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx Co-authored-by: Claude <noreply@anthropic.com>
…ide for the reworded mongo conversion summary Generated by gen:spec-changes and gen:upgrade-guide; only the one summary's copy moves (two JSON lines, one guide table row). Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx Co-authored-by: Claude <noreply@anthropic.com>
…nversion-summaries-form-d
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 137 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 0126aaf052db44fd67aade978d1de9ebe4fc3c86 && git checkout 0126aaf052db44fd67aade978d1de9ebe4fc3c86
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin dfc8547c4b4fd2e5e5780409b2b0a0e02a220f19 7ec0ef4c84bf4a4e0ca7e51c780da6d46cfa0708 && git checkout -B drift-repro dfc8547c4b4fd2e5e5780409b2b0a0e02a220f19 && git merge --no-ff 7ec0ef4c84bf4a4e0ca7e51c780da6d46cfa0708
node scripts/docs-audit/affected-docs.mjs --json dfc8547c4b4fd2e5e5780409b2b0a0e02a220f19
|
Contract reviewServed-tier: Read-only review of PR #20718 (card #20234, stage 9) against ruling C+D on #19123 ( ① Derived judgmentsDiff shape. Net diff against
The four
The Generated artifacts. Hypothesis 5 (neither gate counts a conversion Public surface and accept set. No export, schema, accept-set, reject-set or runtime behaviour changes; what changes is author-shown text ( ② Semver level
Clause-②: no — right; the PR body and the changeset each carry it as a standalone line. ③ Boundary flagsDev flags (the report's
Out-of-scope findings, judged:
Check-runs on the head (one read of 32 runs, 0 failed, taken after the newest run's
Implemented-by: VERDICT: PASS Generated by Claude Code |
…commits that decided them (objectstack-ai#20723) Part of objectstack-ai#20594 Clause-②: no ## What changed This is stage 8 of the `domain:cli` lane of the dead-citation sweep: `packages/qa`. `packages/qa` is a directory of five private workspace packages, not one package, so the surface is `packages/qa/*/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. Each line still says in its own words what that commit decided. PR objectstack-ai#20533 is the method, and stages 1 to 7 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) are the precedents. The card stays open for the lane's remaining packages, so this PR says `Part of`. That is **12 sites on 12 lines in 5 files, covering 6 numbers**, rewritten to **6 distinct commits**: - the census's **8 sites**: `downstream-contract/src/additional-domains.fixtures.ts` (2), `http-conformance/src/adapter.ts` (4) and `vitest-filter-preflight/src/index.ts` (2), 5 numbers; - **4 test-file comment sites** in 2 test files under `http-conformance/src/` (the census leaves `*.test.ts` out; stages 1 to 7 took test comments too). Only comments changed: **12 lines out, 12 in**, and every touched file keeps its line count, so no line citation into these files moves. **No citation number is added.** Over the 12 line pairs, added-minus-removed numbers is empty, and no PR number stands newly on any line. The two numbers still on changed lines (`objectstack-ai#17978`, `objectstack-ai#14554`) were already on them, and both answer 200. **Two numbers have an ADR beside them, and both ADRs stay.** - `objectstack-ai#6083`'s line already cited ADR-0122 phase 2. The ADR's own amendment records phase 2, so the line now reads "ADR-0122 phase 2, commit 53068c1", the same pair spec stage 1 wrote in `contracts/data-engine.ts`. - `objectstack-ai#10485`'s line cites ADR-0049, the enforce-or-remove principle it was retired under. No ADR records the theme retirement itself, so the commit is the anchor, and the ADR stays beside it, as in the landed stages. None of the other four numbers appears in `docs/adr/` or `scripts/adr-anchors/`. The grep reads 0 hits for them. The control, `objectstack-ai#5551`, reads 1 hit in ADR-0122. **No changeset, and `skip-changeset`.** None of the three touched packages publishes anything (see Changeset below). ## Census: `packages/qa`, 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/qa/`. Both runs enumerated the whole board. | reading | tree | board | whole-repo `allocated-but-absent` | `packages/qa` sites | lines | numbers | files | |---|---|---|---|---|---|---|---| | before | base `679f95ec5c`, run 2026-09-29T21:05:44Z to 21:09:44Z | enumerated, 186 pages, frontier objectstack-ai#20718, 18,545 numbers | 1,185 | **8** | 8 | 5 | 3 | | after | `30aae6a3e6`, run 21:18:38Z to 21:22:42Z | enumerated, 186 pages, frontier objectstack-ai#20720, 18,547 numbers | 1,177 | **0** | 0 | 0 | 0 | The whole-repo drop of 8 is exactly these sites. A site-by-site diff of the two JSON outputs has 8 findings gone, all under `packages/qa/*/src`, and none added. The other three tallies are equal in both runs: `resolves` 32,982, `resolves-as-pull-request` 1,984 and `cross-repo-unjudged` 995. `packages/qa/*/src` is byte-identical at `30aae6a3e6` and at the head; the two later commits are merges of `origin/main` that touch nothing in `packages/qa`. **Supplementary scan (test files and everything outside `src/` included).** The gate's exported `extractCitations` and `classifyCitation` ran over all 221 tracked files under `packages/qa` (`CHANGELOG.md` excluded), with the board from the gate's own `probeBoard`. The totals are 1,678 citations and 139 dead before, and 1,666 and 127 after. - Under `src/`, before: src comments 40 / 8 dead, test comments 42 / 4, src strings 1 / 0, test strings 9 / 0. - Under `src/`, after: src comments 32 / 0, test comments 38 / 0, strings unchanged. Nothing dead is left under any `src/`, strings included, so there is no form-D residue in this stage's surface. - Its before list of src comment sites is identical to the census's. - The 127 left are all outside `src/**` (see Acceptance notes). ## Per-site table `git blame` at the base ties each line to the commit that wrote it. Each anchor was read in its message, changeset or diff, not only its subject. Where the pull request that landed an anchor still answers, its body's first line names the dead number, and that is noted. | number | sites (base line) | anchor: what it decided | |---|---|---| | `objectstack-ai#6083` | `downstream-contract/src/additional-domains.fixtures.ts:11` | `53068c130`, ADR-0122 phase 2: the bare type name becomes the AUTHOR state (`z.input`) and the `XInput` synonyms retire. The same commit moved these frozen fixtures' annotations onto the bare names without touching a literal, which is what the paragraph says. The line blames to it, and its subject carries the number. The PR that landed it answers 404, and spec stage 1 gave the number this anchor. | | `objectstack-ai#10485` | `downstream-contract/src/additional-domains.fixtures.ts:133` | `35ad101bc`: retires the `themes` carrier key and `ThemeSchema` whole, under ADR-0049, and drops `DcTheme` from these fixtures. The line blames to it, and its subject carries the number. The spec, rest, runtime and cli stages gave the number this anchor. | | `objectstack-ai#6143` | `http-conformance/src/adapter.ts:32`, `:189`, `:257`, `:346`; `http-conformance/src/fallback-seam.conformance.test.ts:4`, `:27` | `12298c7d6`, which does two things: `NodeHttpServer` implements the optional `setFallbackHandler` out of its own router, as a field consulted in the route-miss branch, with the 405 answer extracted for its second call site; and the cross-adapter suite asserts the contract's four guarantees on both adapters. All six lines blame to it. PR objectstack-ai#6851, which landed it, names objectstack-ai#6143 on its first line. | | `objectstack-ai#6307` | `http-conformance/src/query-multiplicity.conformance.test.ts:76`, `:296` | `293476148`: refuses a repeated `?version=` on `GET` / `DELETE /packages/:id`, and adds `package-routes-query-multiplicity.test.ts`. Its changeset records the measured read: on `DELETE`, a repeated value skipped the full-uninstall branch, and the call still reported success. The lines blame to the later `68feaadd6` and `7cdbcbb30`, which cite this earlier work by number. PR objectstack-ai#6895, which landed the anchor, names objectstack-ai#6307 on its first line. The rest stage gave the number this anchor. | | `objectstack-ai#17853` | `vitest-filter-preflight/src/index.ts:5` | `08f5f0e5a`: a vitest file filter that selects nothing says so, even when the rest of the run selects something. This is the first implementation, in `packages/cli`. The line blames to `c667d8c80`, the shared port for all eight project-declaring packages; its number is `objectstack-ai#17978`, which answers 200 and stays. PR objectstack-ai#17965, which landed the anchor, names objectstack-ai#17853 on its first line. | | `objectstack-ai#13504` | `vitest-filter-preflight/src/index.ts:273` | `44813ba57`: splits `packages/cli`'s suite into the named `unit` and `integration` tiers, decided on behaviour, with the partition pin. That is half of the "tier walk" this sentence names, and its diff heads the new section with this number. `objectstack-ai#14554`, the derived-population half, answers 200 and stays. The only commit whose subject carries `objectstack-ai#13504` is `55519d503`, the comment-only measurement half: PR objectstack-ai#13872 says it lands only that half. So that commit is not the anchor for this sentence. The PR that landed `44813ba57` answers 404. | **Anchor checks.** Every cited sha matches exactly one object (`git rev-parse --disambiguate`, count 1 for each of the 6). Each is a commit with one parent, and each is an ancestor of `main` (`merge-base --is-ancestor` against `cbaf04c1fd`, exit 0 for all 6). The checkout is not shallow. The control leg `3cc8676e1` (2026-08-08, the parent of the oldest anchor `53068c130` of 2026-08-08) exits 0, and the negative control, this branch's own `06b8fbc2d3`, exits 1. Three anchors reuse the landed stages' (`53068c130`, `35ad101bc`, `293476148`), so each number carries one anchor across the tree. Three are new (`12298c7d6`, `08f5f0e5a`, `44813ba57`). **Numbers.** All 6 dropped numbers answer 404 by REST (probed 2026-09-29T21:16:49Z). The numbers kept on changed lines (`objectstack-ai#17978`, `objectstack-ai#14554`) answer 200. No slash-joined citation group stands in `packages/qa/*/src`. ## Mechanical guard: no code token moves **H2 holds on the parser-token reading.** The emitted-`dist` reading does not apply, because none of these packages has a build (see Changeset below). **Token guard.** It compares the TypeScript parser's leaf tokens (TypeScript 6.0.3, `getChildren` walked to the leaves, JSDoc nodes excluded) of the 5 touched files at base `679f95ec5c` and at `30aae6a3e6`. Controls mutate the head text in memory only. - Real run: 7,917 base tokens, 0 differing (exit 0). - Comment-insertion control: 0 differing (exit 0). - Code-insertion control: all 5 files differ at token 0 (exit 1). - String control (the first character of the `'vitest'` import specifier in `fallback-seam.conformance.test.ts` flipped): exactly 1 differing `StringLiteral`, at token 11 of that file (exit 1). Every one of the 24 changed lines is a `//` or `*` comment line. A raw scan of the 5 changed files for control bytes finds none (a positive probe on a scratch file matched). ## Changeset **None, and `skip-changeset`.** There is no `@objectstack/qa` package. The three touched packages are `@objectstack/downstream-contract`, `@objectstack/http-conformance` and `@objectstack/vitest-filter-preflight`. Each is `"private": true`, has no `build` script, no `files[]` and no `dist/`. `.changeset/config.json` versions private packages but never tags or publishes them. This diff therefore publishes nothing from any released package, so there is no `dist` to compare and no code-mutation control to run. The measurement is the packages' own manifests. ## Gates (head `06b8fbc2d3`) This host has no `flock`, so `os-verify-lock.sh` ran in its declared unlocked mode. Its disclosure, verbatim, from each run at this head, and from the closure build at `527d5dca06` (the first merge; `packages/qa` is byte-identical between the two): ```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 77s (1m17s) · declare it in the PR body · pnpm --workspace-concurrency=2 --filter '@objectstack/downstream-contract^...' --filter '@objectstack/http-conformance^...' --filter '@objectstack/vitest-filter-preflight^...' 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 11s · declare it in the PR body · pnpm 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 2s · declare it in the PR body · pnpm --filter @objectstack/downstream-contract 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 3s · declare it in the PR body · pnpm --filter @objectstack/downstream-contract typecheck os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 8s · declare it in the PR body · pnpm --filter @objectstack/http-conformance 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 4s · declare it in the PR body · pnpm --filter @objectstack/http-conformance typecheck os-verify-lock: VERDICT command-exit 0 · UNLOCKED (declared) · no usable `flock` on this host, so the shared verify lock was NEVER taken and NOTHING was serialized · ran 4s · declare it in the PR body · pnpm --filter @objectstack/vitest-filter-preflight 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 1s · declare it in the PR body · pnpm --filter @objectstack/vitest-filter-preflight typecheck ``` - **Build.** The three packages' dependency closure was built: 61 of 81 workspace projects, at `30aae6a3e6` and again at `527d5dca06`. Then the whole workspace was built with `turbo run build --filter='./packages/*' --filter='./packages/*/*'`: 71 of 71 tasks at this head, 66 of them cache hits. The tree was clean after each build. - **Tests (`vitest run`), at this head and at both earlier commits:** - `downstream-contract`: 3 files, 31 tests passed; - `http-conformance`: 8 files, 102 tests passed; - `vitest-filter-preflight`: 3 files, 111 tests passed. - These are every test file each package has. - **Typecheck.** All three `typecheck` scripts exit 0; `downstream-contract`'s is also one of CI's consumer-gate type-check lanes. `http-conformance`'s `check:test-typecheck` holds: 3 files, 27 errors, 10 pinned signatures. `tsc --listFiles` shows every touched file compiled: - `downstream-contract/tsconfig.json`: 11 files, 3 of them tests; - `http-conformance/tsconfig.test.json`: 11 files, all 8 tests, including both touched test files and `adapter.ts`; - `vitest-filter-preflight/tsconfig.json`: 6 files, 3 of them tests. - **Lint.** The repo-wide `pnpm lint` (`eslint . --no-inline-config`) exits 0 at this head (2026-09-29T21:48:59Z to 21:49:26Z), and at `527d5dca06` before the second merge. - **Citation judging.** `node scripts/check-issue-citations.mjs --base origin/main`, with `origin/main` at `cbaf04c1fd` and merged, judges 2 citations on the changed lines of 3 files (the kept `objectstack-ai#17978` and `objectstack-ai#14554`). Both resolve, and the run exits 0. The pinned merged base of the first merge (`--base 1ab9892`, at `527d5dca06`) gives the same 2 citations and also exits 0. - **Derived gates.** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 53 families, identical at `527d5dca06` and at this head. All 53 exit 0 at this head. `--ran` with the exit-coded record reads "53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN" (a derived zero). Among them: - `check:issue-citations`; - `check:doc-authoring` (808 pinned sites, no growth); - `check:nul-bytes` (9,342 text files, no raw control bytes); - `check:published-files`, `check:type-check-coverage` and `check:type-check-debt`. - **Artifact rosters.** 36 of the 39 non-self-test roster rows exit 0. These include 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 the results are 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 `679f95ec5c` the filtered census answers 8 sites on 8 lines, 5 numbers, in 3 files, as on the seat's `0be898499f`. The whole-repo count is 1,185. - **H1 holds.** After the rewrite, the filtered census answers 0 for `packages/qa`. No site was left for an open PR or for an unfound anchor. The file lists of all 12 open PRs were read at 2026-09-29T21:13:53Z: only the Version Packages PR objectstack-ai#20639 touches `packages/qa`, in `CHANGELOG.md` and `package.json`. - **H2 holds on the parser-token reading.** The comment-stripped (parser-token) diff of all 5 touched files is empty, and its controls fire. The `dist` reading is not available, because none of the packages has a build. ## Acceptance notes - **`packages/qa` outside `src/**`, a later stage of the card.** The census surface is `packages/**/src/**`, and `packages/qa/dogfood` has no `src/` at all. The supplementary scan counts 127 dead sites left in `packages/qa` outside `src/**`: - `dogfood/test/**` and `dogfood/vitest.config.ts`: 122 sites, 27 numbers, 28 files (94 comments, 28 strings); - `downstream-contract/test/contract.test.ts:46` (`objectstack-ai#10485`, a comment); - `vitest-filter-preflight/test/config-wiring-sweep.test.ts:6` and `test/filter-preflight.test.ts:5` (`objectstack-ai#17853`, comments); - `vitest-filter-preflight/package.json:6` (`objectstack-ai#17853`, in the package `description`); - `http-conformance/test-typecheck-debt.json:2` (`objectstack-ai#13470`, in the generated `_comment`, whose producer is `scripts/check-test-typecheck.mts`; that producer is objectstack-ai#20715's, and it is never fixed by hand). None of them is in this stage's surface, and none moved. - **ADR-0122's own status line and amendment heading** cite `objectstack-ai#6083` (404). `docs/adr/**` is a governed surface and one of the gate's deferred surfaces, so it is noted here, not touched. - **Card-word residue, cited nowhere.** `vitest-filter-preflight/src/index.ts:117` says "this card" about 150 lines from either rewritten line. It cites no number, so it was left, as the landed stages left theirs. - **The moving `origin/main`.** The branch merged `origin/main` twice. The first merge (`527d5dca06`) took `1ab98926b0` (a spec retirement, nothing in `packages/qa`). After it, the shared ref advanced to `cbaf04c1fd`, the plugin-approvals re-anchor (PR objectstack-ai#20717). Against that moved ref, `--base origin/main` then read the old plugin-approvals lines as this branch's additions: it judged 31 citations and exited 2, because the diff was two-dot. That run is not a measurement of this change. The pinned base answered exit 0. The second merge (`06b8fbc2d3`) took `cbaf04c1fd`, and every gate above was re-run on it. CI judges the merge ref. ## Deviations - **The dispatch's `packages/qa/src/**` and `@objectstack/qa`** do not exist as spelled. The surface was read as `packages/qa/*/src/**`, the census's own reading of `packages/**/src/**`. The changeset measurement was taken per touched package. - **Commit trailers** are AGENTS.md's model-free pair (`Claude-Session` plus `Co-authored-by: Claude`), and the pre-push trailer check passed on every push. The harness's attribution reminder asked for a model-named trailer and a different PR footer, and AGENTS.md overrides it. The two merge commits carry git's default message. --- _Generated by [Claude Code](https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289)_ Co-authored-by: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Part of #20234
Clause-②: no
Stage 9 of the dead-citation sweep. Four conversion
summaryliterals inpackages/spec/src/conversions/registry.tscited tracker numbers that no longer exist on the board. Asummaryis author-shown:os migrate metaprints it, andgen:spec-changes/gen:upgrade-guideproject it intopackages/spec/spec-changes.jsonanddocs/protocol-upgrade-guide.md. So each now takes ruling C+D form D: the decision in words, no number to look up. One stale comment clause at:2100is rewritten to be true (form C). No conversion id, surface, retirement state, transform or code token moves.What changes
datasource-driver-mongo-to-mongodb(#6345)translation-component-submit-label-removed#10926 —mapping-lookup-params-removed#10329,connector-error-mapping-removed#14676,The other number in the submitLabel literal, #9249, is live (200) and stays.
ADR-0049stays in the two literals that carried it.The comment at
:2100said the flag "does not mean what its name and every docblock around it say it means". That has been false since commit 29dd1a6, which rewrote the flag's own docblock to state its authoring-only reach. It now reads: "does not mean what its name says: its own docblock (RetiredConversionStateintypes.ts) has stated the authoring-only reach since commit 29dd1a6." Evidence:git log -S"its reach is the authoring surface" -- packages/spec/src/conversions/types.tsanswers 29dd1a6 only;rev-parse --disambiguatecount 1;merge-base --is-ancestorexit 0 against the base and against HEAD;GET /repos/objectstack-ai/objectstack/commits/29dd1a6ddanswers 200 with the full sha, and the 4-character control29ddanswers 422.Verification
Base
e4e5222b7b; head7ec0ef4c84(the base plus three commits, thenorigin/main5757463712merged throughscripts/pm/os-regen-merge.sh; that merge touched no path underpackages/specorscripts, and the post-merge regeneration produced no diff).Deadness. REST
GET issues/N, no redirects, with lit control #20234 and dead control #8710 at the start and end of each pass. At base, registry.ts has 109 string sites holding 79 distinct unqualified numbers of 100 or more: 75 answer 200 and 4 answer 404, exactly #6345, #10926, #10329, #14676. At head: 105 string sites, 75 numbers, all 200. Controls 4/4 and 4/4 each pass.The gate's census (
node scripts/check-issue-citations.mjs --census --json, board enumerated in full):Repo-wide allocated-but-absent goes 1222 to 1195. That moved with
main's merged commits, not with this diff.Hypothesis falsified: neither count moves, by construction. The citation gate reads source through the comment-prose projection, which blanks string literals, so these four sites were never in its census.
scripts/doc-authoring-prose-id.baseline.jsonexcludespackages/spec(PACKAGES_PROSE_EXCLUDED), andcheck:doc-authoring's spec leg sweeps message, strictObject, tombstone, describe and function-built positions, not a conversionsummary: it was green at base with all four numbers present. At head it prints "16827 customer-facing string(s) across 1186 spec sources clean" and "808 pinned site(s) across 229 file(s) ... no growth, no burn-down unrecorded".Residue. A scratch instrument over TypeScript 6.0.3 builds (a) the file with every comment token cut and everything else kept byte for byte and (b) the leaf-token stream, with the four
summaryinitializers masked by conversion id. Base vs head: IDENTICAL (residue sha256 prefix3352f29d13665120on both sides; 47,810 leaf tokens and 842 comment tokens cut on both). Controls mutate the head text in memory. A comment insertion stays IDENTICAL. Each of these DIFFERS: another summary literal edited, a template literal, a regex literal, an appended declaration, a masked conversion'sid, and itssurface(7/7). Unmasking the mongo summary alone DIFFERS (exit 1). The instrument evaluates each literal's value at base and at head: only the citation and the added clause differ. Line balance for registry.ts: +16/-11 (12,678 to 12,683 lines).Regeneration.
gen:spec-changesandgen:upgrade-guide, never by hand. Exactly 3 lines move, all #6345's copy:spec-changes.json:229 and :1121,docs/protocol-upgrade-guide.md:188. Word diff on each:used (#6345)becomesused, so the id that selects a driver and the id that selects its config contract are one string with no mapping between them.check:spec-changesandcheck:upgrade-guideexit 1 before regeneration and 0 after.Tests. Spec sources at
31a296909fare identical to head.os-verify-lock:turbo run build --concurrency=2over./packages/*and./packages/*/*, 71 of 71 (pre-merge and again at head).check:generated: all 15 generated artifacts are up to date.src/conversions src/migrations src/integration src/data, the translation and cron retirement files, the two step-18 merge scripts): 132 files, 4,732 passed.localproject: 575 files, 16,960 passed and 1 todo.repoproject: 40 of 44 files, 645 passed. The other four (build-schemas-check-mode,def-key-collisions,publish-smoke-boot-failure,publish-smoke-port-collision) hittimeout 560(exit 124). NOT MEASURED, left to CI. None reads summary text.pnpm --filter @objectstack/spec typecheck: exit 0.Gates at 7ec0ef4.
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderives 78, the same list as before the merge. All 78 exit 0,check:issue-citations,check:doc-authoring,check:generatedandcheck:upgrade-guideamong them.--ranreports 78 derived, 78 run, 0 NOT-MEASURED, 0 UNRUN. Also run:check:spec-changesandcheck:authorable-surface, both exit 0.Lint, a proven narrowing.
eslint --no-inline-config --format jsonon registry.ts: 1 file, 0 errors, 0 warnings.isPathIgnoredis false.eslint.config.mjs:327-328states that type-aware linting is never enabled, so a text edit cannot move an untouched file's verdict. The repo-widepnpm lintis CI's run.Changeset.
patch, with a standaloneClause-②: noline.files[]shipsdistandspec-changes.json. Each new phrase is in 6 dist files, and the four old citation spellings are in 0. Control: the unchangedrateLimitConfigsummary is in 6.Merge probes. From a bare
--sharedclone with no merge driver, deleted afterwards:merge-treeof this head with #20637's branch heada2abb8c78aexits 0, and with #20662's head3fcedfb564exits 0.Acceptance notes
docs/protocol-upgrade-guide.md:68still carries cli/runtime: explicit driver(--database-driver/OS_DATABASE_DRIVER)在 CLI 与 standalone stack 之间仍有三处分叉(#6265 后续) #6345. It is the protocol-17 step rationale, generated frompackages/spec/src/migrations/registry.ts:343, so it moves with themigrations/stage (233 comment sites there per the census). Stage 8's record calls it hand-written, but it is generated.service-datasourceandmetadata-coresites of the same numbers (dead tracker citations in thedomain:clipackages (689 sites, 166 numbers, 95 files): the ruling C+D stage for this lane (from #20556) #20594 / dead tracker citations in thedomain:enginepackages (645 sites, 160 numbers, 104 files): the ruling C+D stage for this lane (from #20556) #20595's lanes), the test-file sites, and the liveness JSON notes stage 8 listed.check:doc-authoringreaches a conversionsummary, so a number that dies later in one goes unflagged. Noted, not filed: it is a gate's coverage boundary, not a defect class, and no new gate is proposed.#4911inconnector-rate-limit-config-removed, and ADR-0049 candidate:element:formdeclares a full form contract with no renderer registration found in objectstack/objectui #9249 kept here). Form D says anything an author is shown carries no number, which would reach them too. This stage removes dead citations only, as its claim requires. Whether live numbers in summaries become a later stage is the seat's call.Generated by Claude Code