Skip to content

docs(gates): record the #17242 re-census — the declined residual is a SPELLING population, not rot - #19733

Merged
os-warren merged 9 commits into
mainfrom
claude/issue-17242-spec-citation-corpus
Sep 23, 2026
Merged

os-warren merged 9 commits into
mainfrom
claude/issue-17242-spec-citation-corpus

Conversation

@os-warren

@os-warren os-warren commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #17242

Clause-②: no

#17242 asked for three things: re-derive the population, tense-classify it, and answer the ratchet question with numbers. All three are done. The measurement inverts the card's working assumption, so the diff is one record rather than a cleanup — there is nothing to repair.

1. Re-derived population, with the historical pins reproduced as a lit control

reading tree declined
the card's original pin 08e38c6377 183
the re-measure already on the card 6465cc0a7c 217
this round fa29803417 467, across 39 files

Before today's number was taken, the instrument reproduced CENSUS_17065 verbatim at its own sha: 1,317 files swept, 189 comment-prose line citations, 6 naming a tracked target, 183 declined, by shape 69 bare-filename / 62 directory-qualified / 52 continuation. Every figure matches the constant in the gate, so the instrument could have given another answer and did not.

The resolver changed, so the growth was re-measured with both

scripts/symbol-anchors.mjs was rewritten between the 217 reading and today (655 insertions, 40 deletions), which means 217 and 467 were not comparable on their face. This tree was therefore swept twice:

  • the old resolver over today's tree: 467
  • the current resolver over today's tree: 467

Identical, declined-by-shape included. Instrument drift on this axis is zero and the three readings are comparable: 183 → 217 → 467 is real population growth.

2. What the residual actually IS — the question the card filed as NOT MEASURED

The card recorded two gaps explicitly: the objectui cross-repo vs in-repo split, and how many would resolve under a spec-relative base. Both are measured here by binding every declined citation against the sibling objectui checkout and against this repo:

class count share
names a file that exists in the sibling objectui repo 409 87.6%
names a file that exists here, written package-relative 53 11.3%
binds in neither 5 1.1%

462 of 467 name a file that really exists. The two sibling trees agree row by row — every one of the 467 lands on the same verdict against the .objectui-sha pin 87af769e9a3ee28ace099fdd653d3ebd79fe82e2 and against objectui main 0cf2d6644bdb96a9a6784ef801ee6a60a5306bd8, measured on the objectstack tree cdd68cf15ed863468ce6eecdd5c0824b760ea22a. ⛔ A moving ref is not an anchor, so all three shas are carried as data in RECENSUS_17242, not as prose. ⚠️ Round 2 moved these cells from 408 / 55 / 4: the binding predicate is now written out in full in the gate's docblock, and under it the split is 409 / 53 / 5, with a declared sensitivity — relaxing it for directory-qualified tokens gives 410 / 53 / 4, one row. Continuations (191 of the 467) carry no path of their own and are attributed to the antecedent they inherit — 188 inherit a token that way and 3 inherit none, which is held in RECENSUS_17242.bindingVia. ⚠️ An earlier revision of this paragraph added 「for 34 of them that antecedent is named in prose」; no field and no case carries that 34, and a re-derivation under one natural definition gives 36 / 152. ⛔ Unheld, so it is withdrawn rather than restated — it was neither confirmed nor refuted.

⇒ this residual is a SPELLING population — abbreviated cross-repo and package-relative citations — not the stale-citation rot its headline number suggests.

3. Tense classification — the defect cell is EMPTY

A citation naming no tracked file is a defect only when the surrounding sentence is live-tense. The classifier asserts on the live / not-live axis and runs two controls first, refusing the population reading if either fails:

Over the whole residual: 300 live, 129 dated-measurement, 38 record. Crossed with binding, the defect cell — binds nowhere AND live-tense — contains 0 rows. The five that bind nowhere are enumerated as data in RECENSUS_17242.bindingInNeitherRepoRows, each with its coordinate, citation text, reason and tense: one retirement record naming a file in the cloud repo in prose; two continuations whose comment block names its file only AFTER the citation (a backward-only walk finds none); one whose block names no file at all — it declares from the read point rather than from objectui's mirror, which the row's own why says; and one whose token tail-matches in no tree. All five are correct as written.

⛔ Note record and dated-measurement are both correct historical prose; asserting the exact three-way label on a control would pin a sub-classification the rule never asked for, so the controls assert the live / not-live axis only.

4. ⛔ The trap, measured — repairing the PATH alone turns this gate RED

The obvious cleanup is to rewrite a package-relative citation to its repo-root spelling so it resolves. That makes the path tracked, which moves the citation out of the declined set and into the judged one, where a line number is exactly what this gate refuses.

One such repair was performed against a single citation in packages/spec/src/shared/union-author-message-pins.test.ts (api/protocol.zod.ts:2853 rewritten to its repo-root spelling), through scripts/ablation-replace.mjs so the mutation is proven on disk:

anchor   x1 -> x0
blob     d78fd346439f -> 1ac63738d490

The gate went from green to ❌ 1 finding(s), then was restored — blob == HEAD (d78fd346439f) and git diff HEAD empty.

⇒ the path is only half the repair; the citation must also leave anchor form. A round that "works the 467 down" by fixing spellings alone lands one finding per repair.

5. The ratchet question — a recommendation, not a decision

should the gate start judging untracked line anchors?

Recommendation: do not flip it, on these numbers:

  • the flip would red all 467 on day one, across 39 files — a migration, which is the disposition the corpus already ruled against;
  • of those 467, the number that are actual stale-citation defects is 0;
  • so the flip's false-positive rate on the axis it exists to police is 467/467;
  • and 409 of the 467 are unbindable by construction — they name the sibling repo, which a resolver living here cannot see. Its only remedy would be "stop writing that", which is the permanently-red verifier this repo retired.

The only judgeable half is the 53 in-repo abbreviations, and §4 shows that repairing them is a two-part change. If the residual is ever worked down, the in-repo 53 are the tractable set and each needs the anchor-form half too.

⛔ Adding a required gate is the maintainer's floor; this PR records the measurement and does not change the scope call. CENSUS_17065 is untouched and not restated.

Why the record lives in the gate header

The classification above cannot be re-derived by the gate: it needs a checkout of the sibling objectui repo, which the gate is deliberately not given — the same reason its cross-repo anchors are reported rather than judged. --list-unresolvable enumerates the residual. ⛔ And the stronger, truer statement: the binding harness and the tense classifier exist nowhere in this tree, so the three tense totals can be re-derived by nothing — not even a reader holding both checkouts. The binding split is re-runnable, because the predicate is written out. So it is kept as data beside the census it extends.

Verification

  • pnpm lint (repo-wide, eslint . --no-inline-config) — exit 0, dated at cdd68cf15e ⚠️ (the round-1 head; ⛔ not re-dated here — CI's Lint & Repo Gates is success at the current head)
  • all 31 gate families derived by scripts/pm/dispatch-gates.mjs for this change set — 31 run, 0 NOT-MEASURED, 0 UNRUN, each with its exit code recorded and reconciled via --ran
  • check-spec-docblock-symbol-anchors and its --self-test — exit 0; the residual arithmetic and the seven pinned day-one rows are unchanged
  • check-scripts-symbol-anchors — exit 0; this file is swept by that corpus. ⚠️ 3,653 → 3,654 was the round-1 delta; at head 988cf276bb the corpus reads 3,653 → 3,659 (it read 3,658 at round 3's head; round 4's prose added one resolving anchor), with declined unchanged at 14 throughout, so the added prose contributes resolving anchors and no new residue
  • six gates first reported exit 3 (PREREQUISITE NOT MET) on a fresh worktree with no node_modules; re-run after pnpm install, all exit 0. They are not reported as clean on the exit-3 reading.

Acceptance notes

  • No label written. The dispatch forbade label writes, so none were made. This PR publishes nothing — the changed path is a repo-root gate script, the root package is private, and none of the 70 packages carrying files[] has an entry escaping its own directory — so skip-changeset is the correct disposition and is owed from the seat.
  • The binding instrument's weakest leg is the prose-antecedent walk for continuations: on generic basenames it can attribute to the wrong repo (index.tsx in a docblock that is plainly about objectui binds to this repo's only file of that name). Every such case still names a file that exists, so it cannot create or hide a defect — it can only shift a row between the 409 and the 53. Noted, not filed.
  • The one citation binding in neither repo names a file in the cloud repo in prose, with a space rather than the grammar's cross-repo prefix. Verifying it needs a cloud checkout this container does not have, so its target is NOT MEASURED; its sentence is a retirement record either way, so it is not a defect on the tense axis. Noted, not filed.

Generated by Claude Code

… SPELLING population, not rot

`check-spec-docblock-symbol-anchors` declines every line citation naming no
tracked file and enumerates them, but nothing said what those rows ARE. #17242
filed two questions as explicitly NOT MEASURED: the objectui cross-repo vs
in-repo split, and how many would resolve under a spec-relative base.

Both are measured here and kept as data, because this gate cannot re-derive
them — the classification needs a sibling objectui checkout the gate is
deliberately not given.

- the residual grew 183 -> 467; swept with BOTH the old and the current
  resolver over the same tree, which return the identical 467, so the growth
  is population and not instrument drift
- 463 of 467 name a file that really exists (408 in objectui, 55 here written
  package-relative); 4 bind in neither
- zero live-tense defects: the four that bind nowhere are one retirement
  record and three dated re-reads at a named objectui pin
- measured trap: repairing a package-relative citation's PATH alone makes it
  tracked and therefore JUDGED, turning this gate red — one repair was run
  against a single citation and restored

`CENSUS_17065` is untouched and not restated; the scope call is unchanged.

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

Copy link
Copy Markdown
Collaborator Author

skip-changeset applied by the seat — route 1, with the measurement it owes

domain:spec execution seat 2, session session_01UDXER3sdqfeVYpEWZs5mZx, 2026-09-22T15:17Z. Label write landed and read back: size/s, skip-changeset.

⭐ This is the seat's act by design, ⛔ not the round's omission. Check Changeset going red before the label exists is the expected shape of that division.

The measurement — route 1, 「releases nothing」, re-derived rather than recalled

This PR changes exactly one file: scripts/check-spec-docblock-symbol-anchors.mjs, at the repo root, and npm packs only from a package's own directory.

reading at origin/main value
root package.json @objectstack/spec-monorepo, private: true ⇒ publishes nothing
package.json files under scripts/ 0 ⇒ the file is inside no package directory
manifests censused (packages/**, apps/**) 77, of which 70 declare files[]
escape hatches — a files[] entry beginning ../ or /, or naming scripts ZERO
lit control — packages/spec's files[] on the same reader 10 entries ⇒ the reader works, so the zero is a reading

⇒ nothing in this PR can reach a published tarball. Route 1, and skip-changeset is the true declaration — ⛔ not a convenience.

Ruling D checked, ⛔ not assumed: the skip-changeset label is never applied to a PR that edits an existing changeset. Measured on this file list: zero .changeset/ files touched. ⇒ the ruling does not bar it here.

The re-run, because the label alone does not clear the red

Check Changeset ran before the label existed, and a labeled event spawns a run whose jobs skip — so nothing in the event graph re-judges the earlier red on its own. The seat re-ran the failed job in this same act, which is where the job's live label re-read makes attempt 2 green.

⛔ Not a flake re-run and ⛔ not spent against that budget: the gate's input changed after it ran.

⚠️ This PR's round has not reported yet, so ⛔ nothing here grades its content. The seat has read only the file list and the changeset question.


Generated by Claude Code

…and pin the record

F1 — the cross-repo reading named "objectui's main" with no sha, and a moving
ref is not an anchor. Both sibling trees are data now, beside `measuredOn`: the
`.objectui-sha` pin and objectui's main at the sha actually read, alongside the
objectstack tree the sweep ran on. The two trees agree ROW BY ROW, not merely in
the totals.

F2 — the four-row "binds nowhere" cell was a sentence no reader could reconcile
with the tree. The binding predicate is written out now (token, antecedent walk,
resolution tiers, where it is basename-lenient, tie-break) and carried as data,
and the cell is ENUMERATED with each row's coordinate, citation text, reason and
hand-read tense. Re-measured under that stated predicate the split moves
408/55/4 to 409/53/5: it is stricter about directory-qualified tokens and walks
comment blocks rather than whole files. The declared sensitivity with the
directory fallback on is recorded beside it and moves exactly one row.

F3 — `RECENSUS_17242` occurred once in the whole tree, its own definition, while
`CENSUS_17065` thirty lines above is pinned five ways. A record nothing holds
drifts from the code in silence, which is the defect class this corpus exists
for. The self-test carries the re-census's arithmetic battery now, the sha
forms, the sensitivity's invariants and a five-case exactness loop per
enumerated row — 38 new cases, so the battery floor is raised from 64 to 102,
the count the gate itself registered under a probe. The pins are internal to the
record on purpose: the reading is frozen at the shas it names, so coupling a
cell to the live tree would turn a historical record into a ratchet that reds on
every unrelated spec docblock edit.

Also adopts the review's sharpening on reproducibility: the binding split is
re-runnable by any reader holding both checkouts, but the tense classifier
exists nowhere in this repository, so nothing can re-derive the three tense
totals — the record says that now, instead of "only an outside reading can".

Gate behaviour delta is zero: 3437 anchors, 467 declined, 7 day-one residual,
exit 0 before and after.

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

Round 2 shipped two sentences in this file that nothing held, and both were
wrong about the tree they describe.

1. The via split read "188 of the 467 rows are bound that way and the other
   279 carry their own path". The measured split is 276 own-path, 188
   continuations that inherit a token, and 3 that inherit none and bind
   nowhere -- and 279 also contradicted `declinedByShape` twenty lines above
   (467 - 191 continuations = 276). The sentence is corrected and the three
   cells now live in `RECENSUS_17242.bindingVia`, held by two arithmetics:
   they exhaust `declinedCitations`, and the two antecedent cells are exactly
   the `continuation` shape count. `antecedentNoToken` is additionally held
   against the enumerated rows it names, which now carry a closed `via`
   vocabulary and must agree with their own `token`.

2. The token grammar's comment and its self-test case both said the
   longest-first alternation is what stops a `tsx` citation being truncated to
   `ts`. It is not: the pattern ends in a negative lookahead, so a `ts` arm
   fails on a `tsx` extension and the engine backtracks into the `tsx` arm.
   Measured both ways round -- a shortest-arm-first alternation returns the
   IDENTICAL token, and removing the lookahead while keeping longest-first
   truncates nothing; only removing BOTH truncates. The comment now names the
   lookahead, and that one case is replaced by three that pin it: its presence
   at the end of the pattern, the untruncated token it produces, and the
   order-independence itself -- with a case that refuses to compare a pattern
   with itself.

Two smaller corrections of the same class:

- Case 8's "one pinned five ways" counted five `check()` calls where seven
  reference `CENSUS_17065`. A count of pins is itself an unheld number, so it
  is gone rather than merely corrected.
- The enumeration's comment claimed the self-test holds a row "by" its
  document and citation text. It required them to be CARRIED and keyed nothing
  by them. It now says what it does, and a new case makes the pair an identity
  by refusing two rows that share it.

And one pin taken rather than argued about: every pin on this record was
internal to it, which is exactly what cannot catch a sentence about a tree.
The one cheap FROZEN reality pin available is now taken -- the objectui commit
this repo was pinned to, read at `boundAgainstSha` -- and it is conditional on
that object still being reachable, which it reports out loud when it is not.

Battery floor 102 -> 120, read off a probe rather than derived.

Gate behaviour delta is zero: the gate's stdout and `--list-unresolvable` are
byte-identical at base and at head (sha256 match), and the self-test's success
line is unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…about a tree

The note added one commit ago read "a sentence about a tree that nothing
reading that tree holds -- which is what shipped here twice". Only one of the
two was about a tree: the via split. The other was about the token pattern's
own mechanism, and an internal pin did catch it -- it pinned the wrong
mechanism. Saying "twice" overstates what the reality pin below is for, which
is the same defect this round exists to remove.

Comment text only. The gate's stdout stays byte-identical to base, and the
self-test battery count is unchanged at 120.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…ors where it survives the merge

Two fail bases in `scripts/check-spec-docblock-symbol-anchors.mjs`, both of the
class this file exists about: a self-test message describing a mechanism the
code does not have.

1. The NOT-TAKEN notice stated as fact that the sha "is not an object in this
   clone". `readTextAtCommit` returned one `null` for FOUR causes -- git
   missing, cwd not a repository, the commit absent, and the path absent at a
   commit that is perfectly present -- and the code established none of them.
   Measured: with the pin file renamed, the self-test printed that sentence and
   exited 0 while `git cat-file -t` answered `commit` for the same sha, so a
   rename or a typo in the pin path switched the guard off and its own notice
   told the reader to expect the skip. The reader now establishes the cause
   before it is named: `git rev-parse --git-dir`, then
   `git cat-file -e <sha>^{commit}`, then the read. Only a MISSING COMMIT is NOT
   TAKEN; a present commit whose pin path cannot be read is a hard red, and so
   is a directory that is not a repository. The docblock lists all four.

2. The pin was read at `boundAgainstSha`, a commit ON this branch, so a squash
   drops it from main's history and the pin holds nothing for the entire
   post-merge life of the record -- exactly the one-cell-at-a-time drift the
   case-8 comment says these pins close. `measuredOn` is the anchor the record
   already carried: it is an ancestor of main, so under lint.yml's
   `fetch-depth: 0` checkout it resolves before and after the squash, and
   `.objectui-sha` reads the same `87af769e9a...` at both commits because the
   only file differing between them is this gate. It is now the PRIMARY pin;
   `boundAgainstSha` stays as a second, conditional one. The "one cheap FROZEN
   reality pin available" sentence was wrong rather than optimistic -- frozen
   does not pick an anchor, lifetime does -- and it is corrected in place.

State table, with a deliberately WRONG `objectuiPinSha` as the lit control in
every state:

  clone state                     before          after
  full clone carrying the branch  RED (exit 1)    RED (exit 1)
  depth-1 clone of head           dark (exit 0)   dark (exit 0), both anchors reported
  main-shaped, no branch objects  dark (exit 0)   RED (exit 1)

The third row is the post-merge state. A genuinely shallow clone stays the only
NOT-TAKEN state, which is what the cause split buys.

Two cases written and removed rather than shipped, both because they could not
fail:

- A case comparing the two pin reads to each other is only reachable once both
  have been asserted equal to the same string. Phantom; the loop already holds
  the byte-identity claim.
- A case for the token grammar's third leg ("removing the lookahead while
  keeping longest-first truncates nothing") is entailed by the two guard cases
  above it, which catch every mutation that would light it first. The docblock
  already says the battery pins the lookahead, not that leg, so it stays prose.

Battery floor 120 -> 124, read off a probe rather than derived.

Gate behaviour delta is zero: the gate's stdout and `--list-unresolvable` are
byte-identical at base and at head (sha256 match). The self-test's success line
is unchanged, and its stdout is byte-identical in a clone that carries the
branch; the added line appears only where an anchor is genuinely unreachable.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
@github-actions github-actions Bot added size/l and removed size/m labels Sep 23, 2026
Two sentences in the previous commit went stale inside it. Both said the
byte-identity of `.objectui-sha` at `measuredOn` and `boundAgainstSha` is held
by an "equivalence case", and that case was written and then removed in the
same round for being a phantom: it is only reachable once both reads have been
asserted equal to the same string, so it can never fail.

The claim itself is still held, by the loop rather than by a third case -- both
anchors must read `objectuiPinSha`, so the pin file cannot differ between them
without one of the two per-anchor cases reddening. The two sentences now say
that, which is the same defect class this round is about, one level up.

Comment-only. Gate stdout, `--list-unresolvable` and the self-test's output are
byte-identical at base and at this head; the registered case count is unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…git reports the clone shallow

`commit-absent` was a skip for both anchors, so a one-digit typo in
`measuredOn` switched the primary pin off in any clone. It is now a skip
only for `boundAgainstSha`, or for `measuredOn` when
`git rev-parse --is-shallow-repository` answers `true`; otherwise it fails
the existing case. The NOT TAKEN notice now says only that the sha names
no commit in this clone, and whether git reports the clone as shallow.

Comments that said the pin loop holds the record's "the only file
differing between the two commits is this gate" are narrowed to what the
loop does: where both anchors resolve, it requires `.objectui-sha` to read
`objectuiPinSha` at each, and it compares no other file.

Three loose sentences corrected: "FOUR ways" (one of the four is a spawn
failure, not a git exit), "Two of this record's shas are frozen", and
"two anchors that fail in opposite ways".

No case added or removed; the battery floor stays 124.

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

"Everything not `skipped` is a hard red" was false for a read that
succeeded; it now reads "Every failed read not `skipped`". The red
message's `no-repo` gloss now names the probe that failed rather than
one of the two conditions that make it fail.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
A mistyped pin file reds only where an anchor resolves; in a clone that
holds neither anchor both reads are skips. The red message's mistyped-
literal gloss now names `measuredOn`, the only anchor whose absence can
reach it.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
@os-warren
os-warren marked this pull request as ready for review September 23, 2026 02:51
@os-warren
os-warren enabled auto-merge September 23, 2026 02:51
@os-warren
os-warren added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit 4b23e4f Sep 23, 2026
40 checks passed
@os-warren
os-warren deleted the claude/issue-17242-spec-citation-corpus branch September 23, 2026 03:30
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…eason (objectstack-ai#19786)

Fixes objectstack-ai#17242
Clause-②: no

Round 6: one file, `scripts/check-spec-docblock-symbol-anchors.mjs`,
comments only.

## What was stale

The header section headed "`counts.symbol` is ZERO on this corpus", the
case-4 note and one sentence of the case-5 note said the spec tree holds
exactly one symbol-anchor-shaped span and that it does not resolve. They
gave that as the reason the live-corpus self-test does not assert
`symbol > 0`.

## Re-derived

Instrument: this gate's `CORPUS` and `scripts/symbol-anchors.mjs` at
`4b23e4fab5`, swept over a checkout of each tree.

| tree | anchors | symbol (declaration) | declined |
symbol-anchor-shaped spans | the `websocket.zod.ts` span |
|:--|--:|--:|--:|--:|:--|
| `08e38c6377` (census) | 2639 | 0 (0) | 183 | 1 | present, unresolved |
| `fa29803417` (re-census) | 3437 | 6 (6) | 467 | 7 | present,
unresolved |
| `4b23e4fab5` (base) | 3448 | 6 (6) | 502 | 7 | present, unresolved,
pinned |

Controls: each older tree's own instrument gives the same counts. The
gate at `fa29803417` prints 3437 / 6 (6) / 467. `08e38c6377` has no
gate, so its own `symbol-anchors.mjs` was run with the same corpus spec
and read 0 / 2639 / 183. The six resolving spans are 2 in
`data/analytics.zod.ts`, 3 in `kernel/functional-completeness.ts` and 1
in `ui/action-params.zod.ts`.

⇒ The text was true at the census tree and false at `fa29803417` and at
base.

## Change: deleted only

- The header section, from its heading to its last paragraph. The
`websocket.zod.ts` part was still true, and its `CENSUS_RESIDUAL` row
still carries the doc, the citation and the repair.
- The case-4 note.
- The case-5 sentence that called that loop the positive control for
"the ONE symbol-shaped span".

No reason replaces them. Claim audit: 0 sentences added or changed in
the file. The self-test still asserts `fileLevel` and does not assert
`symbol > 0`. The ratchet recommendation recorded by objectstack-ai#19733 is unchanged
and not restated here.

## Verification, at `d23edb4eef`

- Gate, `--list-unresolvable` and `--self-test`: exit 0 at base and
head, stdout byte-identical (`cmp` 0; sha256 `44a6a984…`, `af5d0039…`,
`1dcc0b91…`), stderr empty.
- Comment-only: the TypeScript printer's output with comments removed is
identical at base and head (sha256 `8865ec39…`). Lit control: a
one-character code mutation makes it differ. The self-test floor stays
124.
- `check-scripts-symbol-anchors` (sweeps this file): exit 0. Anchors
3694 → 3691 and file-level 3642 → 3639; symbol 52 and declined 14
unchanged. The −3 are the three code spans in the deleted text. Its
self-test exits 0.
- `dispatch-gates`: 31 derived, 31 run, all exit 0; `--ran` reads 0
NOT-MEASURED, 0 UNRUN. Outside that total: the 2 workflow-valued
families and the Test Core steps run in CI only. The 14
changeset-pending families do not apply (no changeset: a repo-root
script in the private root package).
- ESLint on the file: 0 errors, 0 warnings. Repo-wide lint is left to
CI.
- 0 control bytes and 0 model identifiers in the file and the commit
message. Lit control: a planted control byte and a planted model
identifier are both found.

## Acceptance notes

- No `symbol > 0` live control is proposed. Case 1 already asserts
`declaration >= 1` and `literal >= 1` through the same `CORPUS` on its
fixture. A live floor would add a constraint on authors and no new
detection. Noted, not filed; carrier: none.

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

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

size/l skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants