Skip to content

docs(spec): re-anchor the dead tracker citations in migrations/entries to the commits that decided them (stage 10) - #20750

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-20234-migrations-citations
Sep 30, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-20234-migrations-citations

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20234

Clause-②: no

Stage 10 of the dead-citation sweep: the migration registry's hand-written entries. Every tracker number in packages/spec/src/migrations/entries/** that no longer exists on the board now cites the commit that decided it, in ruling C+D form C (ruling 5749154545 on #19123). Where the number alone carried the meaning, the line now says what was decided. That is 131 sites over 21 numbers. All of them are comments; the entries' string literals carry no dead number. migrations/registry.ts moves only by gen:migration-registry. No entry id, literal, order, conversionIds or code token moves, and no live citation is removed.

Boundary

  • In: all of entries/**. The gate's census reads 117 sites there, under the claim's ~120 slicing threshold, so there is no slice. My raw walk finds 14 more comment sites that the census does not count (see Census below), which gives 131 in total. They are the same dead card on the line after a counted site, plus one README line, so they are rewritten with it.
  • Regenerated only: migrations/registry.ts, 128 lines. spec-changes.json and docs/protocol-upgrade-guide.md do not move, because entry comments are never projected into them. Both check: scripts pass with no regeneration.
  • Out, per the claim: registry.ts's hand-written parts. They still hold 13 dead sites, listed under Acceptance notes. The six 18.*-unit-in-key.ts entries that PR chore(objectui): bump the console pin to db11afd4967c (carries objectui#11119, the objectui#11105 fix) #20706 edits carry no dead site, and I did not touch them. I did not touch conversions/ or other lanes' sites.

The anchors (one per number, reused from earlier stages where they anchored the same number)

number sites anchor what the rewritten line says it decided
#13135 26 (13 are re-charter #13135) commit 9e0ba21 retires the paper metadata-customization protocol; re-charter of #12057, which stays
#8495 23 commit 4bfe1a5 (PR #8666 kept) the precedent: the first 17.x-line narrowing registered under protocol 18 (its own second commit says so)
#8715 16 commit 2c86fe3 the ApiKeySchema retirement; its message names the "route 3" kit (no carrier key, no tombstone, no D2)
#14691 11 commit b3a63d3 retires the ten inert RestServerConfig keys
#10724 11 commit be21955 retires the nine dead contributes members
#14369 10 commit a3d5724 the liveness census that recorded the 15 dead rows
#10485 6 commit 35ad101 retires the themes carrier and ThemeSchema
#11846 5 commit 0c2334f retires preview mode; its own text carries the ruling record (#12428 kept)
#14676 5 commit 13c48c2 retires connector.errorMapping
#11332 3 commit dce5cd4 retires the manifest's three dead containers
#6361 2 commit 90bbf25 retires the notification-list cursor on both halves
#10627 2 commit be21955 that commit records the controlled monorepo census
#14365 2 commit f60ab90 the open z.partialRecord proposal that commit's changeset recorded; the retirement leaves no record to reshape
#14526 2 commit db16b94 the landing of the client envelope convergence (anchor block, and the README's measured case)
#6363 1 commit 17d0954 "ruled jointly with the unreadCount fix"
#6239 1 commit f549a0d the ViewProtocol retirement sweep
#10726 1 commit bc56e18 retires contributes.routes (Option B)
#10812 1 commit be21955 "the cloud census", whose 2026-08-24 reading @5b5925a that commit's message records
#9041 1 commit d491625 the url-branch refinement (#9147, live, stays)
#14996 1 commit db16b94 the ADR-0087 registration, which landed in the same squash (its body: "Registration requested on #14996")
#14312 1 commit e944fdb the oauth.* binding, which left applications.delete out as a behaviour change (PR #15445 kept)

Two lines change without a number, so the sentence still reads: patterns' follow-on line and the oauth anchor block's continuation line. In total 133 lines are removed and 133 added in 86 files, and every file is balanced.

Verification record (final head 1ee5841c09; base fbec216e2d)

Census (the gate's own check-issue-citations.mjs --census --json, board enumerated, 186 pages):

subtree base (00:21Z, frontier #20740) head (01:18Z, frontier #20743)
entries/retired-keys 73 0
entries/retired-defs 40 0
entries/semantic 4 0
registry.ts, generated regions 114 0
registry.ts, hand-written parts 2 2
chain.ts, types.ts, index.ts, spec-changes.ts, tests 0 0
migrations/ 233 2
packages/spec/src 235 4

Residue (scratch walker over the TypeScript parser, per file, base vs head, 86 .ts files):

  • The file with every comment range cut out, everything else byte for byte, is IDENTICAL.
  • The leaf-token stream is IDENTICAL: 38,417 tokens, aggregate 67c1f6db944e93ed.
  • Controls mutate the head text in memory only, 259 of 259 as expected:
    • Expected identical: a comment insertion in every file.
    • Expected to differ: a string-literal edit, a template-literal edit, a regex-literal edit (where the file has one) and an appended declaration.

Regeneration (gen:migration-registry):

  • check:migration-registry exits 1 before and 0 after.
  • The registry diff is 128 lines out and 128 in. As (old, new) pairs they equal the entry diff's pairs, re-indented by four spaces.
  • 0 changed lines fall outside the generated regions.
  • 5 entry pairs are deliberately not carried: the README line, and the semantic "Anchors" header lines, which sit above a blank line and so are not in the carried comment run.
  • check:spec-changes and check:upgrade-guide exit 0 with no regeneration.

Build and tests (under os-verify-lock):

  • Build: turbo run build over ./packages/* and ./packages/*/*, 71 of 71, at 845e90fea4 and again at 1ee5841c09.
  • check:generated: all 15 artifacts up to date, at both heads.
  • spec local project: 576 files, 16,991 passed and 1 todo, at both heads.
  • spec repo project: 41 of its 45 files, 666 passed, at both heads.
  • spec typecheck: exit 0; 53 files / 251 errors / 138 pinned signatures held.

Gates: dispatch-gates --commands derives 82 gates, and the derivation is identical before and after the second merge. At 1ee5841c09 all 82 exit 0. --ran reconciles: 82 derived, 82 run, 0 NOT-MEASURED, a derived zero.

Lint (a proven narrowing):

  • eslint --no-inline-config --format json over the 86 touched .ts files: 86 files, 0 errors, 0 warnings.
  • isPathIgnored is false for all 86.
  • eslint.config.mjs:327-328 states that type-aware linting is never enabled, so a comment edit cannot move an untouched file's verdict.

Changeset: patch.

Merges: origin/main was merged twice through scripts/pm/os-regen-merge.sh. Neither merge left a regeneration to commit.

Acceptance notes


Generated by Claude Code

…s to the commits that decided them

Every dead tracker number in the hand-written migration entries (131 sites
over 21 numbers, all comments; one in entries/README.md) now cites the
commit that decided it, in ruling C+D form C, with the decision in words
where the number alone carried it. The anchors are the ones earlier stages
chose for the same numbers. Lit citations on the same lines stay.

Comment text only: no entry id, literal, order or code token moves.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
…ntries

gen:migration-registry output only. The 128 changed lines are the entry
comment lines the generator carries, re-indented; no line outside the
generated regions moves. spec-changes.json and the upgrade guide are
unchanged, because entry comments are never projected into them.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tooling labels Sep 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s). ⚠️ 86 changed file(s) yielded no anchor (packages/spec/src/migrations/entries/README.md, packages/spec/src/migrations/entries/retired-defs/17.api__CreateViewRequest.ts, packages/spec/src/migrations/entries/retired-defs/18.api__CrudEndpointPattern.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/kernel/cluster.mdx (via RETIRED_DEFS_BY_MAJOR (symbol, a top-level const object))
What this run could not see
  • 86 changed file(s) yielded no anchor (packages/spec/src/migrations/entries/README.md, packages/spec/src/migrations/entries/retired-defs/17.api__CreateViewRequest.ts, packages/spec/src/migrations/entries/retired-defs/18.api__CrudEndpointPattern.ts, …) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 137 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 97005aed04a069abc2d2fa82fd6c1594aebd7cd1 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 3d26556ab74c39abd96cd3056f0605693de27cd3 — the merge of head 1ee5841c092cdc7d2c446ab1e7cf933b940e3e25 into base 97005aed04a069abc2d2fa82fd6c1594aebd7cd1, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3d26556ab74c39abd96cd3056f0605693de27cd3 && git checkout 3d26556ab74c39abd96cd3056f0605693de27cd3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 97005aed04a069abc2d2fa82fd6c1594aebd7cd1 1ee5841c092cdc7d2c446ab1e7cf933b940e3e25 && git checkout -B drift-repro 97005aed04a069abc2d2fa82fd6c1594aebd7cd1 && git merge --no-ff 1ee5841c092cdc7d2c446ab1e7cf933b940e3e25

node scripts/docs-audit/affected-docs.mjs --json 97005aed04a069abc2d2fa82fd6c1594aebd7cd1

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 97005aed04a069abc2d2fa82fd6c1594aebd7cd1 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1ee5841c092cdc7d2c446ab1e7cf933b940e3e25
Local-runs: probe — one scratch script over the repo's git objects, tokenising the merge-base and head blobs of the 86 changed .ts files with a TypeScript scanner (comments and whitespace dropped) to settle comment-only; nothing built, tested or re-run.

Read: card #20234, body and all 41 comments (the C+D path decision 5856637615, the pointer 5858331362, stage 8's landing 5896689039, stage 9's ACCEPT 5899135835 and landing 5899597998, the stage-10 claim 5901544565, the dev report 5902687602); PR #20750, its body, its one comment, its 88-file list and the net diff against main at the merge base 01e78dceef; the 21 anchor commits by git show and git log; the check-runs on the head, read once.

① Derived judgments

The claim says no accept-set or public-surface move. Each judgment below is from the diff and the git objects, not the dev's prose.

② Semver level

  • patch is right, and its stated reason holds. The diff is comment text, but the comments ship: at this head packages/spec/tsup.config.ts lists src/migrations/index.ts as a bundle entry and package.json exports ./migrations to dist/migrations/index.mjs and index.js (the shared checkout's HEAD, two days older, has neither, which is why the dev's dist measurement is not reproducible there). That the bundler keeps // comments is verified on the published @objectstack/spec@17.5.0 tarball: its dist/index.mjs carries 9,901 comment lines, the old "PR feat(spec): refuse ${…} placeholder syntax in memory persistence.path / persistence.key at publish (#8495) #8666 precedent" phrase 23 times, and the RETIRED_KEYS_BY_MAJOR table with its entry comments. So the compiled @objectstack/spec/migrations entry carries these comments and the changeset's rationale sentence is true. No export, schema, prescription or projected text moves, so nothing above patch applies. Check Changeset is green.
  • Clause-②: no is right, in the PR body and as a standalone line in the changeset: no accept or reject moves, by the comment-only proof.

③ Boundary flags

Check-runs on the head, read once in the first CI wave (the newest concluded run at the read was Dogfood Regression Gate (2/3)), not re-read and not polled. 32 runs: 17 success, 3 skipped, 12 in progress, 0 failed. Green: Check Changeset, Check PR Size, Governed Surface Queue Guard, Spec property liveness, Type Check · source gates, Type Check · consumer gates, Type Check · debt ledger, the four claim, closing-keyword and single-writer guards, Check Documentation Links, Flag docs affected by code changes, Auto Label, filter, Dogfood Verify CLI, Dogfood Regression Gate (2/3). Roster skips: Build Docs, Console Pin Gate, Packed-tarball smoke (opt-in). NOT CONCLUDED at the read, so not presumed green: Lint & Repo Gates (the run carrying check:issue-citations, check:migration-registry, check:spec-changes, check:upgrade-guide, check:doc-authoring and check:generated, the gates closest to this diff), Type Check · workspace, Build Core, Test Core (all six shards), Dogfood Regression Gate (1/3 and 3/3), Temporal Conformance (live PG + MySQL). The derived families the concluded green runs answer: changeset shape and deadline, PR size, governed surface, liveness, the three type-check legs, card and branch parity. The rest is the seat's landing rule; nothing red was seen.

Implemented-by: claude/issue-20234-migrations-citations
Reviewed-by: session_014EJ1ED8X4MMrT18BhVx4tx

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 30, 2026 02:35
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 30, 2026
Merged via the queue into main with commit a51920f Sep 30, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20234-migrations-citations branch September 30, 2026 02:59
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…ned and URL-spelled citations, pinned in one spelling table (objectstack-ai#20989)

Fixes objectstack-ai#20636
Clause-②: no

The family closeout for the citation extractor in
`scripts/check-issue-citations.mjs`: every spelling a seat measured as
invisible to the diff gate and the census is now read, every exclusion
keeps only the shapes it was measured protecting, and the self-test
carries the one enumeration table the triage asked for (48 spellings,
each "extracted as" or "not a citation, because"). Landing site:
`scripts/check-issue-citations.mjs` only.
`scripts/check-doc-authoring.mjs` is untouched; H2 below says why.

## What changed

- **Hyphen after the number.** The lookahead no longer refuses a `-`, so
`objectstack-ai#13398-class`, `objectstack-ai#5347-A` and `ui#6206-B` read as citations of their
number. It still refuses a word character, so a hex colour stays out.
- **Slash before the `#`.** A `/` is now valid context before a bare
`#`. It stays refused only before a qualifier candidate, so a URL path
fragment such as `https://example.com/docs/page#12` never reads `page`
as prose. A `/` right after a digit is the exception, so
`objectstack-ai#3076/objectui#2614` still reads its own qualifier.
- **Slash-joined continuation.** In `#A/#B`, the second number takes the
chain head's reading: bare after a bare or prose head, the head's
repository after a qualified head, and an ordinal after an ordinal. Only
a joined `/` continues a chain. `objectui#1 / objectstack-ai#2` and `objectui#1 + objectstack-ai#2`
stay two separate readings.
- **URL spelling.** `https://github.com/OWNER/REPO/issues/N` and
`.../pull/N` are now citations, qualified by their own `OWNER/REPO`.
That puts `objectstack-ai/framework` in this repository and makes every
other repository's URL cross-repo, never a finding. Inside a markdown
link `[#N](URL)`, the citation counts once.
- **Head rows.** I retired `re-charter`, `clause` and `option` (named in
the thread), plus `acceptance` and the section mark (found by the same
measurement). Each protects 0 sites repo-wide at two or more digits and
hides board citations. The grammar's two-digit floor already keeps
one-digit ordinals out. I added a `](` row, the narrower guard the
hyphen exclusion leaves behind for markdown in-page heading anchors.
- **Self-test.**
  - A new `spellings` battery (56 cases) reads the table row by row.
- Every head row must excuse at least one table row, and every required
spelling (the card's list plus the thread's) must be present.
- The `live-corpus` battery gains three floors, one per new arm, each
counting only a number spelled once on its line.
  - The roster floor rises from 6 to 9 batteries.
  - Total: 114 cases in 8 batteries became 173 in 9.
- I edited the header in place and kept its line count, because
`scripts/pm/dispatch-gates.mjs`'s self-test pins
`scripts/check-issue-citations.mjs:204 local-env`. The marker is still
on line 204, and that pin passes (see Gates).

## H1: what each exclusion protected and hid

Measured on `3693a1b50` over the declared surfaces. Every arm was judged
against one enumerated board: 188 pages, frontier 20959,
2026-09-30T22:55Z. The instrument mirrors the gate's extractor and
matched it file for file on all 2,640 files (0 mismatches).

| exclusion | hid (sites, dead) | protected in the declared surfaces |
disposition |
|---|---|---|---|
| hyphen after the number | 58, 1 dead (8 cross-repo) | 0: no numeric
range, slug or hex-like token. Repo-wide: in-page heading anchors, 16
lines in `docs/design/**` and `skills/**`, plus one range,
`docs/audits/...md`, whose first number is a citation | dropped; the
`](` row keeps the anchor out |
| `/` before the `#` | 528, 10 dead: 523 `#A/#B` second numbers and 5
`TOKEN/#N` such as `ADR-0049/objectstack-ai#1888` | 0 paths and 0 URL fragments |
narrowed to the candidate arm; continuations read as their chain |
| head `re-charter` | 0 left on this tree (the 26 dead `re-charter
objectstack-ai#13135` were rewritten by PR objectstack-ai#20750) | 0; only the gate's own fixtures
used it | retired |
| head `clause` | 0 in the surfaces; 4 in deferred test files, all board
citations | 0 | retired |
| head `option` | 1 (`option objectstack-ai#14088`, live); 1 more under `scripts/**` |
0 | retired |
| head `acceptance` | 1 (`the silent acceptance objectstack-ai#6132 closed`, live) | 0
at two or more digits | retired (in-place, below) |
| head section mark | 0 in the surfaces; 4 in test files (`§6 objectstack-ai#11176's
decisions`) | 0 at two or more digits | retired (in-place, below) |
| heads kept | none measured hiding a citation | directive 203 (max 13),
`PD` 85 (max 13), batch 276 (69 distinct, 11 to 227), `OQ` 10, `PKCS` 1
| kept |

The 8 slash chains headed by another repository are not a case where the
two populations cannot be told apart. The 5 on objectui's public board
each name objectui's record, the issue and then the pull request that
fixed it, read one by one against both boards:

- `objectui#2715/objectstack-ai#2717`
- `objectstack-ai#2711/objectstack-ai#2722`
- `objectstack-ai#2725/objectstack-ai#2732`
- `objectstack-ai#2967/objectstack-ai#2904`
- `objectstack-ai#4648/objectstack-ai#4901`

This repository's records with the same numbers are unrelated. The other
3 (`cloud`, `hotcrm-heimao`) are boards one credential cannot read, so
they stay unjudged, as they were before.

## H2: where the URL spelling belongs

The extractor. At `3693a1b50`, 57 URL sites sit in the gate's
projection: 56 in package comments and 1 link on a release page. 4 of
them are dead. Only 2 URL sites in package sources are inside string
literals, both internal `note:` strings in
`packages/runtime/src/route-ledger.ts`.

`check:doc-authoring` asks a different question: may a runtime string
carry a tracker reference at all? It reads string literals, skills and
spec refusal messages. The two projections are disjoint, so adding the
URL to the extractor double-counts nothing there. Inside the extractor,
the one double-spelled site (`[objectstack-ai#15325](...objectstack-ai/issues/15325)` on
`v17/17-3.mdx`) counts once. `check-doc-authoring.mjs` is not touched.

## H3: open PRs' added lines

All 13 open PRs at 2026-09-30T23:2xZ: their heads were fetched into a
private ref namespace (deleted afterwards). For each, the BASE extractor
and this one were run over the lines it adds, against its merge base.
Result: 85 added-line citations under both extractors, 0 newly
extracted, 0 lost. No PR's verdict changes. Lines a PR does not add are
never judged, which is unchanged and pinned in the `diff-scope` battery.

## Census, before and after

The gate's own `--census --json`, once with the `3693a1b50` script and
once with this one, over the same tree:

| | judged | resolves | resolves as PR | cross-repo |
allocated-but-absent |
|---|---|---|---|---|---|
| before (frontier 20965) | 37,152 | 33,403 | 1,985 | 1,024 | 740 |
| after (frontier 20966) | 37,796 | 33,917 | 2,083 | 1,041 | 755 |

That is 644 more judged sites and 15 more dead ones, with 0 findings
lost. By arm: hyphen 1 dead, slash 10 dead, URL 4 dead.

Newly visible dead sites per lane. I rewrote none of them; they belong
to the lane cards:

- **objectstack-ai#20594 (`domain:cli`): 1.** `packages/rest/src/rest-server.ts:7456`,
objectstack-ai#11006.
- **objectstack-ai#20595 (`domain:engine`): 6.**
- `driver-sql`: `sql-driver.ts:3933` (URL, objectstack-ai#17590), `:12110` (objectstack-ai#10629),
`:16106` (objectstack-ai#17343).
  - `metadata`: `loaders/ambiguous-metadata-stem.ts:40` (objectstack-ai#14423).
- `metadata-protocol`: `migrations/partial-index-probe.ts:395` (objectstack-ai#16657).
  - `objectql`: `plugin.ts:1496` (objectstack-ai#10629).
- **objectstack-ai#20596 (`domain:services`): 0.**
- **objectstack-ai#20597 (`domain:spec`, `packages/lint`): 0.**
- **objectstack-ai#20234 (`packages/spec/src`): 7.**
  - `data/datasource.zod.ts:701` (objectstack-ai#9040).
  - `data/filter.zod.ts:1040` (URL, objectstack-ai#17590) and `:1042` (URL, objectstack-ai#17286).
  - `data/value-roundtrip-conformance.ts:100` (URL, objectstack-ai#12380).
  - `ui/component.zod.ts:593` and `:669` (objectstack-ai#6276), and `:3771` (objectstack-ai#9972).
- **Release pages (`domain:devx`, no lane card): 1.**
`content/docs/releases/v17/index.mdx:168` (objectstack-ai#6075).

This census was run on the PR head's tree, not after landing. A re-run
after landing reads the same corpus plus whatever `main` has gained by
then.

## In-place fixes beyond the three named rows

I retired the `acceptance` and section-mark rows here rather than filing
them. All four conditions hold:

1. They are the same defect class as `option` and `clause`: a head row
hiding a board citation.
2. The fix is mechanical, and the shape is pinned by the table.
3. The file is this claim's own surface (`NON_CITATION_HEADS`).
4. The same gate's self-test covers them, so no new verification surface
is added.

Evidence: `acceptance objectstack-ai#6132` (live) in
`packages/formula/src/cel-pushdown-limits.ts:82`, and the section-mark
sites in deferred test files. Neither row has any two-or-more-digit
ordinal anywhere in the repository.

## Gates (final head `25d96fcc0`)

I re-derived the list with `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack`, which gave 32 commands.
The same derivation on a throwaway tree at `origin/main` (`05be35259`)
with this diff applied gave an identical list. I ran all 32, plus `pnpm
check:doc-authoring` and the self-test, and every one exited 0.
Reconciliation verdict line:

`✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 32 run, 0
NOT-MEASURED (a DERIVED zero — all 32 recorded an exit code and none of
them is 3).`

Verdict lines worth quoting:

- `node scripts/check-issue-citations.mjs --self-test`: `✅ ... every
spelling enumerated ... (173 cases, 9 batteries)`. It also passes on
`origin/main` `05be35259` with this diff applied.
- `node scripts/check-issue-citations.mjs` (diff mode): `✅
check-issue-citations: no issue citations added against 3693a1b (0
file(s) read).` The script lives in the deferred `scripts/**` surface.
- `pnpm check:pm-dispatch-gates`: `✓ dispatch-gates self-test: 1976
cases pass.` (1237.9s). Its pin `scripts/check-issue-citations.mjs:204
local-env` holds.
- `pnpm check:doc-authoring`: `✓ doc authoring guard: ... hold the
baseline — 549 pinned site(s)`.
- `pnpm check:nul-bytes`: `check-nul-bytes: OK (scanned 9582 text
file(s) ...)`.
- `node scripts/check-scripts-symbol-anchors.mjs`: `✅ ... 3706 anchors
across 282 scripts resolve`.

## Ablations (one-shot, from committed `25d96fcc0`, via
`scripts/ablation-replace.mjs`)

Every leg was expected to go red, and every leg did. Each one restored
to blob `c732ce2e21c7` (equal to HEAD) with an empty `git diff HEAD`. No
permanent ablation file is left.

| mutation | first red |
|---|---|
| hyphen refused again after the number | `the live corpus must yield a
#N-word citation` |
| `/` refused again before the `#` | `the live corpus must yield a
slash-joined #A/#B second number` |
| URL arm disabled | `the live corpus must yield a URL-spelled citation`
|
| `option` head row restored | `spelling option #N in "the option objectstack-ai#14088
gave" must read objectstack-ai#14088; got nothing` |
| continuation disabled | `spelling repo#A/#B ... must read
objectstack-ai/objectui#2711, objectstack-ai/objectui#2722` |
| `](` row disabled | `a markdown link's in-page heading anchor is not a
citation` |
| link de-duplication disabled | `spelling [#N](URL) ... must read
objectstack-ai#15325` |

The first slash ablation, run before the floors were tightened, went red
in the table but left the live-corpus continuation floor green. A line
citing the same number twice let a plain citation stand in for the
slash-joined one. Commit `25d96fcc0` makes each new floor count only a
number spelled once on its line. The re-run above is red at that floor.

## Acceptance notes

- **URL spelling in runtime strings.** `check:doc-authoring` does not
read it. At `3693a1b50` the population is 2 internal route-ledger
`note:` strings (`packages/runtime/src/route-ledger.ts:459`, `:465`),
and no author-facing door shows them. Noted, not filed; carrier: none.
- **Range second numbers.** In a range such as `objectstack-ai#712-714`, the second
number carries no `#` and is not read. There is 1 site repo-wide, in
`docs/audits/**`, outside the declared surfaces. Pinned in the table
with its reason.
- **Dormant test-file citations.** The 8 test-file citations the retired
`clause` and section-mark rows hid are in the deferred test surface.
They become visible only when that surface is swept.
- **Line-number pin.** `dispatch-gates.mjs` pins this file's `local-env`
marker by line number (`:204`), so any future header growth above it has
to move that pin in the same PR.

No changeset: a root `scripts/` file publishes nothing (the root
`package.json` is private, and no package's `files` ships `scripts/`),
so this PR takes `skip-changeset`.

---
_Generated by [Claude
Code](https://claude.ai/code/session_017VaLJnYwhPsanVCe9dMCJU)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants