Skip to content

test(scripts): batch 8b — assertion floors for two b4-thunk and two recipe-A self-tests - #15307

Merged
baozhoutao merged 4 commits into
mainfrom
claude/issue-13799-batch8b-thunk-and-rows
Sep 4, 2026
Merged

test(scripts): batch 8b — assertion floors for two b4-thunk and two recipe-A self-tests#15307
baozhoutao merged 4 commits into
mainfrom
claude/issue-13799-batch8b-thunk-and-rows

Conversation

@claude

@claude claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Part of #13799

Batch 8b of the self-test assertion-floor card: two b4-thunk files and two recipe-A files, from the batch 8 census table (5538556734) as dispatched by its ACCEPT (5538595066) and the PM claim 5538595337. Base pin origin/main = 5b09356b7; every reading below was taken at head 9965c88d3. Exactly four files, skip-changeset, no deferrals.

Per file

file census row recipe roster floor measured on a run
scripts/measure-test-shard-timings.mjs 16 b4 thunk 1 hoisted battery, size pin 1 22 registered 22 case(s), below its pinned floor of 23
scripts/measure-position-name-fold-census.mjs 15 b4 thunk 1 hoisted battery, size pin 1 24 registered 24 case(s), below its pinned floor of 999
scripts/check-override-consistency.mjs 7 recipe A 17 row labels, floor 1 each, size pin 17 17 declares 17 batteries, below the pinned 999
scripts/pm/check-skill-line-ratchet.mjs 19 recipe A 155 row labels, floor 1 each, size pin 155 155 declares 155 batteries, below the pinned 999

A measured correction to census row 19

The row warned that the cases array "also spreads an IIFE-produced block — generated rows cannot take a literal roster key", and dispatched the file as "recipe A on the literal rows only, generated rows outside the roster".

Measured, that premise does not hold for this file. Each of the four ...(() => { ... })() spreads is a SCOPING device: it declares local fixture consts and then return [...]s an array of LITERAL [label, actual, expected] rows. No row label is a template string, none is computed, and no row is produced by a map / push / loop. Three independent readings agree on 155:

  • 155 labels extracted from source by indentation (21 at the array's top level, 134 inside the four IIFEs), all single-quoted literals, zero duplicates;
  • 155 literal row starts, and only 4 spreads, all top-level;
  • 155 cases pass. printed by the green line on a run of the unmodified base tree.

So all 155 rows are floored, with no residue — nothing here is the extra-call class of PR #15286, and partitioning the table would have been the lossy reading (the 7a Q1 precedent). The reasoning is recorded in place above the roster.

Where the floor lives in measure-position-name-fold-census

main() gates the PRODUCTION census on selfTest({ quiet: true }), so this file has two callers of one body. The floor is evaluated inside the !quiet branch: the quiet call prints no verdict and therefore makes no claim for a floor to guard, and evaluating it there would let a roster edit change what a census run outputs. Proven, not argued — leg D4 below.

One site stays outside the roster and says so in place: the catch arm of the AUDIT_CONTROLS loop ends in continue, which is illegal inside the thunk's arrow function, and rewriting that control flow is exactly what the verbatim rule forbids. Its sibling in the same loop body, if (!ac.expect(result)), is floored, so a loop that stops running still reds.

Line-level identity (thunk files)

Every removed line, stripped of leading whitespace, reappears among the added lines. No condition was inverted; the dropped-! hazard cannot arise.

file removed added removed-not-in-added
measure-test-shard-timings.mjs 38 191 0
measure-position-name-fold-census.mjs 52 193 0

Wrapped-site count == assertion-site count in both: 22 check(() => { wrappers over 22 if (...) throw ... sites; 13 wrappers over the 13 if (...) problems.push(...) statement-sites carrying 14 of the 15 push sites (one if/else if carries two), the 15th being the declared catch-arm exclusion.

The two recipe-A files delete only sink lines: check-skill-line-ratchet deletes exactly one, its red-run verdict, reworded to the recipe's N failure(s) (cases and floor); check-override-consistency deletes four, converting its boolean passed into a failures counter so the same red line can carry a count. No assertion condition is touched in either, and both green lines are byte-identical to the base tree's.

Roster ⇄ table cross-check (recipe A)

Both lists printed and compared; symmetric difference empty in both directions, order identical, zero duplicate labels.

  • check-override-consistency: 17 roster keys vs 17 table labels.
  • check-skill-line-ratchet: 155 roster keys vs 155 table labels.

Ablation ledger — 15 legs

Every leg was run from the committed implementation. Each proves its mutation landed on disk (a grep count of the removed anchor AND of the injected text; a no-op mutation aborts the leg and discards the reading), and each restore is proven by HEAD-blob hash equality plus an empty git diff HEAD — an empty hash is read as failure, never as "nothing to compare". The mutators carry a trap ... EXIT INT TERM restore against an absolute REPO_ROOT.

leg file result
A1 row deleted ratchet names "over the ceiling -> red" DID NOT RUN, exit 1, 0 failing cases
A2 row renamed ratchet both halves: the undeclared registration and the missing declared name
A3 registerCase() removed ratchet all 155 DID NOT RUN, every case still green
A4 size pin unreachable ratchet declares 155 batteries, below the pinned 999
B1 row deleted override-consistency names the row, exit 1, 0 failing cases
B2 row renamed override-consistency both halves
B3 registerCase() removed override-consistency all 17 DID NOT RUN, every case still green
B4 size pin unreachable override-consistency declares 17 batteries, below the pinned 999
B5 duplicate label in the TABLE override-consistency names the colliding label, and the shadowed row as DID NOT RUN
C1 battery opener renamed shard-timings undeclared battery registered 22 + declared one DID NOT RUN
C2 registerCase() removed from the thunk shard-timings DID NOT RUN — 0 cases registered, 22 pinned, cases green
C3 roster size pin unreachable shard-timings declares 1 batteries, below the pinned 9
D1 battery opener renamed fold-census undeclared battery registered 24 + declared one DID NOT RUN
D2 registerCase() removed from the thunk fold-census DID NOT RUN — 0 cases registered, 24 pinned, cases green
D3 roster size pin unreachable fold-census declares 1 batteries, below the pinned 9
D4 floor made unreachable, PRODUCTION path run fold-census --self-test reds (exit 1) while the census run stays exit 0 and byte-identical to the base tree — the floor cannot reach production

These scripts are executed directly by path, not resolved through a package exports, so no dist/ rebuild leg applies; there is nothing between the edited source and the run.

Both modes vs an installed base worktree at the pin

A detached worktree at 5b09356b7, pnpm install exit 0. Every stream compared with cmp.

file mode base exit branch exit stdout stderr
fold-census normal 0 0 identical, 4225 B identical, 0 B
fold-census --json 0 0 identical, 6352 B identical, 0 B
fold-census --self-test 0 0 identical, 430 B identical
shard-timings normal (usage) 1 1 identical, 0 B identical, 75 B
shard-timings --self-test 0 0 identical, 41 B identical
override-consistency normal 0 0 identical, 1627 B identical, 0 B
override-consistency --self-test 0 0 identical, 1340 B identical
skill-line-ratchet normal (reads skills/**, .claude/**) 0 0 identical, 7917 B identical, 0 B
skill-line-ratchet --self-test 0 0 identical, 9288 B identical

18/18 streams identical. skills/** was never edited; the ratchet's normal mode is green on both trees.

The card's instrument

node scripts/measure-self-test-floor.mjs --json on both trees, 169 rows each:

  • NONE 34 → 30 — drops by exactly 4;
  • ROSTER 133 → 137; COUNT 2 → 2, unchanged;
  • the movers are exactly the four worklist files, symmetric difference against the worklist empty in both directions.

extractWatchHints (from scripts/pm/dispatch-gates.mjs) over all four files, base vs branch: byte-identical ×4 — the 172 new roster labels contribute zero hints, and check-skill-line-ratchet's own 28 hints are unmoved. check:watch-hint-literal green.

Gates (foreground; exit codes captured by redirect BEFORE any pipe)

  • Derived family: 28/28 green, from node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set: exactly the 4 files vs merge base 5b09356b7). check:pm-dispatch-gates under the shared verify lock, VERDICT command-exit 0 · held the lock 374s, 1381 cases pass.
  • Always-runs tail: check-self-test-workflow-commands.mjs and its --self-test, check:declared-population-live, check:ratchet-remedy-authority, check:watch-hint-literal, check:nul-bytes, check-self-test-wired.mjs and its --self-test — all exit 0. NOT MEASURED: pnpm check:self-test-wired exits 254 because no such package.json script exists (0 occurrences); the wired spelling is the direct node invocation, which is green.
  • Each edited script's own suite: all four run in normal mode AND --self-test; the only non-zero is measure-test-shard-timings.mjs normal mode, exit 1 = its usage line, identical to the base tree's.
  • Pin suite naming an edited script: packages/plugins/plugin-security/src/position-name-fold-warning.test.ts28/28 pass, after building the dependency closure under the verify lock.
  • Repo-wide pnpm lint exit 0, not narrowed.
  • Control-byte scan (grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]') clean on all four files and on every body posted.

Derivation carried a STALE TREE warning: origin/main has moved to ed217e697 (2 commits) since the dispatch pin, and 9 files changed across that range — all of them 7a/7b's landed files, disjoint from these four. The branch is deliberately left on its pin rather than rebased.

🤖 Generated with Claude Code

https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk


Generated by Claude Code

…tered battery

The 22 bare `if (...) throw ...` assertions in `selfTest()` are each wrapped
verbatim in the `check(() => { ... })` thunk PR #15198 landed: the condition is
carried in untouched, so no `!` can be dropped while the case still registers
and still passes. Zero named section banners, so one hoisted battery (the
PR #14896 / #15003 / #15217 shape), floored at the measured 22 with the roster's
own size pinned at 1. The floor throws, matching this file's own sink, and is
evaluated before the verdict so the success line can only be printed by a run
that actually ran its cases.

Part of #13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@github-actions github-actions Bot added the size/m label Sep 4, 2026
…a registered battery

The 13 `if (...) problems.push(...)` assertion sites in `selfTest()` are each
wrapped verbatim in the `check(() => { ... })` thunk PR #15198 landed. The sink
here is FAILURE-ONLY, so routing `problems.push` itself through `registerCase()`
would have inverted the floor rather than installing it: a green run would
register nothing and the battery would read DID NOT RUN. Zero named banners, so
one hoisted battery, floored at the 24 registrations measured on a run (four of
the thirteen sites sit inside loops: 9 + 4 + 4 + 2 + 5).

The floor lives inside the `!quiet` branch. `main()` gates the PRODUCTION census
on `selfTest({ quiet: true })`, which prints no verdict and so makes no claim for
a floor to guard; evaluating it there would let a roster edit change what a
census run outputs. Both production modes are byte-identical to the base tree.

One site stays outside the roster and says so in place: the `catch` arm of the
AUDIT_CONTROLS loop ends in `continue`, illegal inside the thunk's arrow
function, and rewriting that control flow is exactly what the verbatim rule
forbids. Its sibling in the same loop body is floored, so a loop that stops
running still reds.

Part of #13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…ble rows

Recipe A as the pilot PR #15271 settled it: each of the 17 row labels of the
literal `cases` table is a declared battery with a floor of 1, `registerCase(name)`
is the first statement of the driving loop body, and the roster is a LITERAL the
table is cross-checked against so a deleted or renamed row names ITSELF rather
than deleting its own floor. Roster size pinned at 17; duplicate labels are
refused from both sides. The three `// --- ... ---` comments inside the array are
grouping rules, not section heads.

The boolean `passed` becomes a `failures` counter so the red line can carry the
recipe's wording, `N failure(s) (cases and floor)`; no assertion condition is
touched and the green line is byte-identical to the base tree's.

Part of #13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…table rows

Recipe A per the pilot PR #15271: every row label is a declared battery with a
floor of 1, `registerCase(name)` is the first statement of the driving loop,
the roster is a LITERAL cross-checked against the table, size pinned at 155.
The only deleted line is the red-run verdict, reworded to the recipe's
`N failure(s) (cases and floor)`; the green line stays byte-identical.

The batch-8 census flagged this table's four `...(() => { ... })()` spreads as an
IIFE-produced block whose rows could not take a literal roster key. Measured, that
premise does not hold here: each IIFE is a SCOPING device that declares local
fixture consts and then returns an array of LITERAL [label, actual, expected]
rows. No label is a template string or computed, and no row comes from a
map/push/loop. Three independent readings agree on 155 -- labels extracted from
source, literal row starts, and the `cases.length` the green line prints on a run
-- so ALL 155 rows are floored with no residue, rather than the partition the row
anticipated.

Part of #13799

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@github-actions github-actions Bot added size/l and removed size/m labels Sep 4, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 4, 2026 10:31
@baozhoutao
baozhoutao enabled auto-merge September 4, 2026 10:31
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit a35dd34 Sep 4, 2026
36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13799-batch8b-thunk-and-rows branch September 4, 2026 11:02
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