Skip to content

test(ratchet): wire both hand-calibrated copies to the ceilings that produce them - #1334

Merged
os-trump merged 2 commits into
mainfrom
claude/issue-1321-wire-the-copies-to-ceilings
Aug 26, 2026
Merged

test(ratchet): wire both hand-calibrated copies to the ceilings that produce them#1334
os-trump merged 2 commits into
mainfrom
claude/issue-1321-wire-the-copies-to-ceilings

Conversation

@os-trump

Copy link
Copy Markdown
Collaborator

Fixes #1321

scripts/check-source-token-ratchet.mjs computes every figure it needs —
CEILINGS, BUFFER, anchor(), and the readings it prints. Two artefacts
restated those figures by hand with nothing comparing the copies to the
producer, so each sat in permanent tension with the ratchet it describes: a
shrink-only ceiling is meant to be tightened opportunistically, and every
legitimate tightening falsified a copy. Both copies now read the producer.

Half 1 — the fixtures are sized from the committed ceilings

test/source-token-ratchet.test.ts imports CEILINGS, BUFFER, anchor()
and fmt() from the gate it already runs in a sandbox.

The in-buffer case sizes its scope as Math.floor(ceiling / (1 + BUFFER))
the largest reading whose anchor() is that ceiling, which is what "inside
the buffer" means — fills to exactly that many tokens by subtracting what the
layer already holds and the wrapper the stripper keeps, and asserts headroom
relatively as ceiling - reading in the gate's own formatting. What the
case pins is unchanged and now stated as the property itself: under the
ceiling, and clear of the advisory's 2 × BUFFER trigger.

Floor, not round. The card suggested Math.round; the dispatch marked the
formula a suggestion and asked for what actually reproduces the case's intent.
Math.round does not. Rounding up makes reading × (1 + BUFFER) exceed the
ceiling, anchor() then carries it past the next 1k boundary and returns
ceiling + 1000, so the fixture is not the reading that ceiling was anchored
from:

ceiling  39000: round=37143 anchor=40000 WRONG | floor=37142 anchor=39000 ok
ceiling  40000: round=38095 anchor=40000 ok    | floor=38095 anchor=40000 ok
ceiling  41000: round=39048 anchor=42000 WRONG | floor=39047 anchor=41000 ok
ceiling  85000: round=80952 anchor=85000 ok    | floor=80952 anchor=85000 ok
ceiling 140000: round=133333 anchor=140000 ok  | floor=133333 anchor=140000 ok

The two agree at the committed 40,000, so the suite is green either way today
and only a re-anchoring exposes it — the same failure mode this card closes,
one level up. Caught by the reverse verification below, in 027bd73.

Half 2 — the docstring's worked table gets the pin it never had

A new describe parses the three rows out of the script source and asserts,
per row:

  • the printed ceiling is the committed constant, and equals anchor(reading)
  • the multiplier is the ruled buffer, not a number of its own (1 + BUFFER)
  • the product is Math.round(reading × (1 + BUFFER))
  • headroom is ceiling - reading and the percentage is its one-decimal form
  • exactly one row per committed ceiling, in the committed order
  • each row's date names the anchoring run its reading came from

Every assertion is internal to the row plus the committed constant. A row's
headroom is the headroom at anchor time — since #1320 the three rows do
not even come from one run, which is why the date column exists — so comparing
it against what the gate prints today would be wrong by design, and the pin
does not do it. (Live interaction reading today is 37,428; the row's is 37,424,
from the 2026-08-26 run. The pin is indifferent to that gap, correctly.)

Reverse verification — the acceptance criterion

Every mutation proved on disk by blob hash before any verdict was read
(anchor hit count 1, removed-text count 0, injected-text count 1, blob differs
from the HEAD blob); every restore via git checkout HEAD -- PATH and proved
by an empty git diff HEAD plus a disk blob equal to the HEAD blob. No leg
matched zero times, so no reading here is void.

Mutation A — move a ceiling constant (interaction layer 40000 to 39000,
blob ddf39cc to ac26097):

leg in-buffer fixture table pin
this PR's suite green — followed the constant automatically (18 passed) red, naming the row
pre-#1321 suite at a76b69f (control, same mutated tree) red did not exist
this PR:  AssertionError: *   interaction layer    37,424 × 1.05 =  39,295 -> ceil 1k ->  40,000  (headroom 2,576, 6.9%)  2026-08-26: expected 40000 to be 39000

control:  AssertionError: expected '  ✓ interaction layer ~38,095 tokens …' to contain 'headroom ~1,905'
          Received: "  ✓ interaction layer ~38,095 tokens (ceiling ~39,000; headroom ~905)."

The control leg is the card's thesis, reproduced on demand: the old literal
stays pinned at 38,095 tokens while the ceiling moves beneath it. The wired
fixture re-derived itself to 37,142 and stayed quiet and clean.

Mutation B — falsify one docstring row, three separate legs, each naming
its own row:

product  39,295 -> 39,999 : × derives the buffered product, the headroom and the percentage it prints
   *   interaction layer    37,424 × 1.05 =  39,999 -> … : expected 39999 to be 39295

headroom 4,644 -> 4,700   : × derives the buffered product, the headroom and the percentage it prints
   *   business semantics   80,356 × 1.05 =  84,374 -> … (headroom 4,700, 5.8%)  2026-08-17: expected 4700 to be 4644

date  2026-08-17 -> 08-26  : × dates every row with the anchoring run its reading came from
   *   authored total      133,302 × 1.05 = 139,967 -> … 2026-08-26: expected 133840 to be 133302

Gates

pnpm verify green on the final commit 027bd73:

✓ source hygiene clean
✓ source token ratchet clean          (0 re-anchor advisory lines)
  Test Files  141 passed (141)
        Tests  2990 passed | 1 skipped (2991)
os-verify-lock: VERDICT command-exit 0

The ratchet suite itself goes 15 tests to 19.

Two changes outside the dispatched file surface, declared

1. tsconfig.json gains allowJs: true (commented in place). tsc
resolves the relative .mjs either way, but without it there are no types for
the module and strict turns that into TS7016 at the import site — measured,
not assumed. Inferring the types from the producer is the point: the
alternative, a hand-written .d.mts beside the script, is one more
hand-maintained copy of exactly the kind this card deletes. checkJs stays
off, and no .js/.mjs file lives under src/ or e2e/ for the include
globs to newly sweep in.

2. A third hand-calibrated ceiling copy in the same file, folded in. Scan
that found it, on a76b69f:

$ grep -n "85_000\|86,005\|85,000\|40,010\|1,990" test/source-token-ratchet.test.ts
241:    const ceiling = 85_000; // business semantics, as committed in the gate
246:    expect(output).toContain('business semantics is ~86,005');
247:    expect(output).toContain('the ratchet ceiling is ~85,000');

The over-ceiling case restated CEILINGS.get('business semantics') as a literal
and quoted two absolute figures derived from it — the identical defect, in the
same case block, and it goes red on the next re-anchoring of business semantics
for exactly the same reason. It now sizes itself from the committed ceiling and
reads its over-by figures back off the measurement, and gains an assertion on
the over by ~N figure it previously ignored. Nothing it pinned was weakened.

Not done, deliberately

No ceiling value moved — not 40000, not 85000, not 140000. BUFFER is
untouched at 0.05; it is only newly exported, along with fmt.
scripts/check-source-hygiene.mjs is not touched. No existing assertion was
weakened, skipped or deleted. src/ metadata is unchanged, so the app bundle
is byte-identical and the ratchet's own readings do not move.

Sibling read-coupling with #1325 checked and irrelevant by construction: it
moves the interaction layer's live reading; everything here derives from the
constant, which is why Mutation A had to move the constant to have any
effect at all.

Generated by Claude Code


Generated by Claude Code

claude added 2 commits August 26, 2026 07:48
…ceilings

`scripts/check-source-token-ratchet.mjs` computes every figure it needs —
`CEILINGS`, `BUFFER`, `anchor()` and the readings it prints. Two artefacts
restated those figures by hand with nothing comparing the copies to the
producer, so each sat in permanent tension with the ratchet it describes: a
shrink-only ceiling is meant to be tightened opportunistically, and every
legitimate tightening falsified a copy.

The test fixtures now import `CEILINGS`, `BUFFER`, `anchor()` and `fmt()` from
the gate the suite already runs. The in-buffer case sizes its scope as
`ceiling / (1 + BUFFER)` — the reading whose `anchor()` is that ceiling, which
is what "inside the buffer" means — and asserts headroom relatively. The
over-ceiling case sizes itself from the committed ceiling and reads its over-by
figures back off the measurement. Both pin exactly what they pinned before.

The docstring's worked table gains the producer-side pin it never had: the rows
are parsed out of the script source and asserted per row against the committed
constant, `anchor(reading)`, `Math.round(reading * (1 + BUFFER))`, and the
headroom and percentage that row derives — plus one row per ceiling in order,
and each row's date naming the anchoring run its reading came from. Those
assertions are internal to the row and the constant: a row's headroom is the
headroom at anchor time, so comparing it against a live run would be wrong by
design and the pin does not do it.

`BUFFER` and `fmt` are newly exported; no value moved and no ceiling changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ED4cusQ7pxZ7d7TCLKrZb
The reverse verification for the previous commit caught this: with the ceiling
moved to 39,000 in a sandbox, `Math.round(ceiling / (1 + BUFFER))` gives 37,143,
whose `reading × 1.05` is 39,000.15 — over the ceiling, so `anchor()` rounds it
past the next 1k boundary and returns 40,000. The fixture was then NOT the
reading that ceiling was anchored from, which is the one thing the case is
about.

`Math.floor` is exact at every ceiling: the product lands at or just under the
ceiling and `anchor()` returns it. The two agree at the committed 40,000 (both
38,095) and disagree at 39,000 and 41,000, so today's suite is green either way
and only a re-anchoring would have exposed it — precisely the failure mode this
card exists to close, one level up.

The card suggested `Math.round`; the dispatch marked the formula a suggestion
and asked for what actually reproduces the case's intent. This is that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ED4cusQ7pxZ7d7TCLKrZb
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 26, 2026 7:59am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline configuration Build and app configuration files

Projects

None yet

2 participants