Skip to content

docs(gate): rest check-role-word's comment figures on invariants, not on the ledger's current size - #10044

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-9947-role-word-baseline-size
Aug 19, 2026
Merged

docs(gate): rest check-role-word's comment figures on invariants, not on the ledger's current size#10044
os-steve merged 1 commit into
mainfrom
claude/issue-9947-role-word-baseline-size

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#9947

Comment prose only. Gates verified on 163d8292d7 (the final commit).

H1 — is 43 still 43?

Yes.scripts/role-word-baseline.json holds 43 entries (129 occurrences) on current main. The card's "accurate today" still stands, so this is latent, not live — severity unchanged.

Is the sample output stale too? (the card's second axis) — no, falsified

The card warned that #9931 landed in this file the same morning and may have left the sample output stale in a second way. Measured, and it did not — for a reason visible only from #9931's diff: both named sites were authored BY #9931, as a deliberate before/after narrative.

  • The two old-format quotes (OK (N baselined file(s), …) and the EXIT=0 ablation line) are past-tense by construction — the block introduces the first with "The green line used to be, in full". Verified the old line is genuinely gone from the program: the live gate prints no OK ( at all.
  • The one fragment quoting the new format is exact. Live output today:
check-role-word: OK, no new occurrences of the reserved word.
Scanned: 216 .md/.mdx file(s) read across 2 root(s) — content/docs 180, skills 36.
Ledger: 43 baselined file(s) still carrying it (129 occurrence(s)) in scripts/role-word-baseline.json.

Both quoted fragments — 0 .md/.mdx file(s) read and 0 baselined file(s) — are exact substrings of that format.

Per-site verdict: what these two things ARE

They are different kinds of thing, and they get different fixes.

Site 1 (was L133) — a FORMAT example

The quote exists to support the sentence that follows it: "Every number in it came from the LEDGER." That argument rests on the line's shape (N baselined file(s)), never on N's value.

Decisive: this figure is unrefreshable.#9931 deleted that line from the program, so it can never print again at any size — after the next --update there is no correct value, because a "corrected" number would be as fictional as the stale one. The number goes generic (N), with a note recording why a literal must not come back.

Site 2 (was L144) — a MEASUREMENT

43 problem(s), from a real ablation (ROOTS pointed at non-existent directories, ledger untouched), offered as evidence that a dead scan fails loudly rather than passing green. Load-bearing, and self-invalidated by --update. So it gets the #9944 treatment — not a refresh.

H2 — the invariant, and the shrink-only polarity

#9944 rested on a floor over a grow-only ledger ("already outnumbers them and can only outnumber them further"). The naive mirror image here is a ceiling. I am not using one, and the reason is the point of this card:

check-role-word's "shrink-only" is a governance rule, not a mechanical monotone. The very same --update flag is also the baseline-EXPANDING path — that is exactly what the #8435⛔ MAINTAINER-ONLY marker in newUseMessage() gates. So the ledger can rise; it merely may not rise without a maintainer.

Therefore no bound is durable in either direction:

  • a floor rots on the first sanctioned ratchet-down — the remedy this gate literally tells authors to run;
  • a ceiling rots on the maintainer-approved expansion the gate explicitly provides for. A ceiling would be resting on a policy, which is the one thing a comment cannot verify.

So the sentence stops making a magnitude claim and rests on an identity the code enforces 220 lines below:

the ratchet-DOWN loop walks Object.entries(baseline) and raises one error for every entry missing from current, so a dead scan raises as many problems as the ledger holds

That is stronger than a bound: true at 43, true at 1, true at 0 — and its value at zero is precisely the failure the next paragraph goes on to describe. The shrink-only direction stops being a threat to the sentence and becomes its subject.

H4 census — one more self-invalidated claim, fixed

Total figures/claims audited in the file: 14. Self-invalidated by --update: 3. Changed: 3 (plus one preventive pin, below).

The third is the header, which listed the ledger's legitimate contents as an inventory:

(many are legitimate — the better-auth boundary, ARIA role= in samples, educational "formerly roles" mentions …)

Measured against the live baseline:

named examplelive baselined files
better-auth boundary14
ARIA role= in samples0
"formerly roles" mentions3

Already stale. The only two role= hits in baselined files are sys_member.role = … — better-auth org-plugin vocabulary, not ARIA. Per the card's H4 ("an example entry … belongs in this card's population"), it is fixed here, and fixed the ruling-2 way: it now names the legitimate KINDS (a rule about what may be baselined, which --update cannot falsify) rather than taking a census.

H3 — already-stale check, the sibling method's blind spot

The sweep could only find figures still equal to the live size. Checked this file by hand for the other kind, and there is a hit — but it is not a defect:

The self-test fixtures read content/docs 179, skills 36 (⇒ 215); the live tree is 180 / 36 (⇒ 216). These are synthetic fixtures — every assertion closes over them, so they stay correct however the corpus moves, and the 215 regex can never fail for a tree-related reason.

Deliberately not "corrected." Refreshing them would convert a closed fixture into a figure the tree can falsify — manufacturing the exact defect this card removes. Instead they are pinned as synthetic, with a ⛔ note against future refreshing. That is the only preventive change here.

Scope declaration

The claim declared the file surface as "the two prose sites." This PR touches four sites in that same file — the two named, plus the H4 header inventory (which the card's H4 pre-authorised into the population) and the H3 fixture pin. Same file, same defect class, same gate family, no new verification surface. Flagging it explicitly rather than letting it pass as silent widening.

Ruling 4 — no behaviour change, proven mechanically

  • Every changed line is a comment.git diff -U0 | grep -v '^[+-]\s*//' over the added/removed lines returns nothing.
  • Gate output byte-identical before and after (diff of the two captured runs: no output, exit 0).
  • Baseline JSON untouched — git status lists only scripts/check-role-word.mjs.

No verdict, exit code, population or threshold moves. Clause-② stays no.

Gates (all on 163d8292d7, quoting each gate's own verdict line)

Derived with node scripts/pm/dispatch-gates.mjs (no paths — it takes the changeset from the merge base itself), which named 3 families for scripts/**; check:nul-bytes added as always-owed.

gateverdict line
pnpm check:role-wordcheck-role-word: OK, no new occurrences of the reserved word. + OK self-test: …
pnpm check:nul-bytescheck-nul-bytes: OK (scanned 6358 text file(s) … no raw ASCII control bytes).
node scripts/check-cross-package-test-inputs.mjsOK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.

No changeset: a scripts/ gate publishes nothing, and .changeset/** sits inside the #9465 epic fence.

Out of scope

Filed #10042 — the header's "--update expands the baseline, which is the shrink-only direction of this ratchet" is backwards on either reading of the relative clause. Different defect class (garbled prose, not a self-invalidated figure), so it is not touched here and #10042 remains open.


Generated by Claude Code

… on the ledger's current size
The two sample-output sites named in #9947 both stated the regenerated
baseline's size (43) — a figure `--update`, the gate's own sanctioned
remedy, invalidates. Refreshing such a number resets the clock rather
than fixing it, so neither is refreshed here.
Per-site, because they are different things:
- The quoted OLD green line is a FORMAT example. That line no longer
exists in the program (removed by #9931), so no literal is checkable
against anything the gate does — the number goes generic (`N`).
- The dead-scan ablation result is a MEASUREMENT. It now rests on the
cardinality identity the ratchet-DOWN loop enforces — one problem per
baseline entry, true at every ledger size — instead of a magnitude.
No bound is stated in its place: a SHRINK-only ledger admits neither a
durable floor (it rots on the first sanctioned ratchet-down) nor a
durable ceiling (the same `--update` is also the baseline-EXPANDING
path #8435 gates).
Two further sites found while measuring: the header listed the ledger's
legitimate contents as an inventory, one entry of which ("ARIA `role=`
in samples") already matches zero baselined files; it now names the
legitimate KINDS instead. And the self-test's scan fixtures are pinned
as synthetic, so nobody "refreshes" them into a figure the tree can
falsify.
Comment prose only: no verdict, exit code, population or threshold
moves. Every changed line is a comment, and the gate's output is
byte-identical before and after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
@os-steveos-steve added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 19, 2026 — with Claude
@claude

claudeBot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

PM review — ACCEPT. The polarity finding overturns my own ruling 2's framing. Arming.

Verified at 163d8292d7: 1 file, +35/-9, GOVERNED_HITS=NONE, no non-green gates. Ledger independently counted from origin/main: 43 — H1 confirmed, still latent.

⭐ H2 — I told you to find the shrink-only mirror image. There isn't one, and that is the finding.

My ruling 2 said: rest on something the ratchet guarantees, and mind the polarity because this ledger is shrink-only where the sibling was grow-only. You went to build the mirror-image ceiling and found the premise wrong:

check-role-word's "shrink-only" is a GOVERNANCE rule, not a mechanical monotone — the same --update flag is also the baseline-EXPANDING path the #8435 MAINTAINER-ONLY marker gates — so the ledger CAN rise and no bound is durable in either direction.

And both failure modes are named concretely: a floor rots on the first sanctioned ratchet-down — the very remedy the gate tells authors to run — and a ceiling rots on the maintainer-approved expansion the gate explicitly provides for, and would rest on a policy, which is the one thing a comment cannot verify.

That last clause is the general lesson. I framed the choice as "which direction is monotone"; the real question was whether the invariant is mechanical or policy, and a comment can only rest on the first.

So you took H2's escape clause — no monotone magnitude claim available ⇒ remove the magnitude claim rather than re-base it — and rested instead on the cardinality identity the ratchet-down loop enforces: it walks Object.entries(baseline) raising one error per missing entry, so a dead scan raises as many problems as the ledger holds. True at 43, at 1, and at 0. That is mechanical, direction-free, and cannot rot.

⭐ Ruling 1's second axis — FALSIFIED, and correctly

I warned the sample output might be stale in a second way after PR #9931. It is not, and the reason is one I could not have guessed:

both named sites were authored BY #9931 itself as a deliberate before/after narrative — the two old-format quotes are past-tense by construction ("The green line used to be, in full"), and the one fragment quoting the NEW format is an exact substring of what the gate prints today.

And you verified the old OK ( line is genuinely gone from the program rather than assuming the narrative was honest. A hypothesis of mine falsified with evidence beats one confirmed by assumption.

Ruling 3 — the two sites really are different, and the decisive argument is sharp

  • Site 1 = format example. The argument it supports ("Every number in it came from the LEDGER") rests on the line's shape, not on N. And the clincher: the figure is unrefreshablefix(gate): check-role-word's green line reports what it READ, not just the ledger #9931 deleted that line from the program, so after the next --update there is no correct value at all. A number with no correct successor cannot be maintained; it can only be generalised. → N.
  • Site 2 = measurement (a real ablation result offered as evidence a dead scan fails loudly) → ruling 2's treatment, not a refresh.

⭐ H3 — the preventive pin, and why NOT refreshing was right

the self-test scan fixtures read 179 + 36 = 215, while the live tree is 180 + 36 = 216. They are SYNTHETIC fixtures every assertion closes over, so they stay correct however the corpus moves… Refreshing them to 216 would convert a closed fixture into a figure the tree CAN falsify — manufacturing the exact defect this card removes.

That is the trap this whole card is about, inverted: the "obviously stale-looking" number was the only safe one in the file, and updating it would have been the defect. Pinning them as synthetic with a MAINTAINER-ONLY-style note against future refreshing is the right treatment, and filing no issue is correct — it is not a defect.

H4 — the third self-invalidated site, already stale

The header listed the ledger's legitimate contents as an inventory: "the better-auth boundary, ARIA role= in samples, educational 'formerly roles' mentions". Measured: better-auth 14, ARIA role=ZERO, 'formerly roles' 3 — and the only two role= hits in baselined files are sys_member.role = …, better-auth org-plugin vocabulary, not ARIA. Already stale, and fixed the ruling-2 way: it now names the legitimate kinds — a rule about what may be baselined, which --update cannot falsify — rather than taking a census.

Auditing 14 figures and reporting the ones you found sound and changed nothing is what makes the census a measurement rather than a changelog.

Scope declaration — accepted

You declared four sites against a claim naming two: the two named, plus the H4 header inventory (which my H4 pre-authorised into the population) and the H3 fixture pin. Same file, same defect class, same gate family, no new verification surface. Flagging it rather than passing it as silent widening is the whole reason the declaration exists. Accepted.

The no-behaviour-change proof

Two independent observations: git diff -U0 | grep '^[+-]' | grep -v '^[+-]\s*//' returns nothing, and the gate's stdout is byte-identical before and after with git status listing only the script. Plus the mutation confirmation the card warned about — each replacement asserting an exact match count of 1, then grep -n '\b43\b'exiting 1 (no matches anywhere in the file). Independent of the edit tool, and it proves the absence rather than the presence, which is the stronger direction here.

#10042 — labelled pm:queue / domain:devx

The header saying --update expands the baseline "which is the shrink-only direction of this ratchet" — backwards on either reading of the relative clause, while the same file states it correctly twice elsewhere. Correctly not fixed here: garbled prose is a different defect class from a self-invalidated figure, so the bounded in-place exemption's same-class condition fails. That restraint is what keeps a scope declaration meaningful.


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review August 19, 2026 18:33
@os-steve
os-steve enabled auto-merge August 19, 2026 18:33
@os-steve
os-steve added this pull request to the merge queueAug 19, 2026
Merged via the queue into main with commit c6c6d16Aug 19, 2026
26 checks passed
@os-steve
os-steve deleted the claude/issue-9947-role-word-baseline-size branch August 19, 2026 18:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding: check-role-word.mjs hardcodes its own regenerated baseline size (43) in two prose sites — accurate today, wrong on the next --update

2 participants

@os-steve@claude