Skip to content

Commit 8b54e9d

Browse files
claude[bot]claude
andauthored
test(scripts): batch 9 pilot (class-3) — floor check-turbo-task-graph at its verdict site (#15309)
* test(scripts): batch 9 pilot — floor check-turbo-task-graph at its verdict site (class-3) `failures.length === 0` inside `runSelfTest()` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line. This is the class-3 pilot: the registering body has no verdict site. `selfTest()` registers through a block-bodied `t(label, ok)` (49 sites, 0 named banners) and returns its failures; a separate `runSelfTest()` decides and prints. So the floor CHECK moves to the verdict site — inside `runSelfTest()`, immediately before the green line, on the `--self-test`-only path — while the `SELF_TEST_BATTERIES` roster, the sink's `registerCase()` and the ledger stay module-level as in every landed recipe. Only the check's location moves; attribution and scope are untouched, no assertion condition is touched, and the `SELF_TEST_VERDICT` handshake is kept exactly as landed. The floor is deliberately NOT placed before `selfTest()`'s own `return`: an early return above that line would skip it — the defect the #13798 handshake exists to catch — coupling hole 1 to hole 2 after the card ruled them orthogonal. Floor 49, measured rather than transcribed: the roster was probed with an unreachable pin (9999) and the floor's own report named the registered count. Behaviour is unchanged — normal mode and `--self-test` stdout and stderr are byte-identical against the pin, exit 0 both sides. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk * style(scripts): blank line before the verdict-site floor block Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 3a4373f commit 8b54e9d

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

‎scripts/check-turbo-task-graph.mjs‎

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,132 @@ function main() {
619619
);
620620
}
621621

622+
// ── The self-test's own battery roster and floor (#13489) ──────────────────
623+
//
624+
// `failures.length === 0` used to be this self-test's ONLY success condition, so
625+
// "every case held" and "the cases never ran" printed the same line. Closed the
626+
// way PR #13487 validated on check-doc-authoring: what is pinned is the
627+
// registered NAMES, not a number. The floor requires the OPENED set to equal the
628+
// DECLARED set with each battery at or above its own count.
629+
//
630+
// This file declares ONE battery, opened at the top of `selfTest()`'s body. It
631+
// carries ZERO named section banners — fewer than the two the sectioning
632+
// criterion needs — and ⛔ a comment is NOT promoted to a section head: that is
633+
// a judgement per comment this transplant does not make. The hoisted single
634+
// battery is the shape PRs #14896, #15003 and #15217 landed for this case.
635+
//
636+
// ── Why the LEDGER is module-level and the CHECK sits at the verdict site ──
637+
//
638+
// This gate splits its self-test in two: `selfTest()` REGISTERS and returns its
639+
// failures, and `runSelfTest()` DECIDES — it prints the `OK:` line or exits 1.
640+
// There is no verdict site inside the registering body, so the floor is
641+
// evaluated where the green line already is (inside `runSelfTest()`, reached
642+
// only from the `--self-test` branch of the dispatch, so it can never fire on a
643+
// production run). The ledger it reads therefore has to outlive `selfTest()`'s
644+
// frame — hence a module-scope `batterySeen` rather than the local map the
645+
// single-body recipe closes over. Roster, sink and ledger are module-level in
646+
// the landed recipes already; only the CHECK's location moves, and attribution
647+
// and scope are untouched.
648+
//
649+
// ⛔ The floor is NOT placed at the end of `selfTest()` before its `return`: an
650+
// early return anywhere above that line would skip the check entirely — the
651+
// exact defect the #13798 verdict handshake exists to catch — coupling hole 1
652+
// to hole 2 after the card ruled them orthogonal. Evaluated at the verdict site,
653+
// the same early return lands as a count BELOW the floor and reds.
654+
//
655+
// ⛔ A pinned TOTAL is not the repair: a battery dropping from 9 cases to 3
656+
// keeps a total "right" the moment a sibling grows.
657+
//
658+
// The count is a FLOOR, not an equality — adding cases is ordinary work and must
659+
// not red. A battery BELOW its floor means cases stopped running; the remedy is
660+
// to find what stopped registering.
661+
const SELF_TEST_BATTERIES = Object.freeze({
662+
'check-turbo-task-graph self-test': 49,
663+
});
664+
665+
// DELETING an entry silences that battery's floor exactly as effectively as
666+
// zeroing it, so the roster's own size is pinned too.
667+
const SELF_TEST_BATTERY_FLOOR = 1;
668+
669+
// The key an assertion is filed under when no battery is open. It is not a
670+
// declared battery, so it reds by the same set difference rather than silently
671+
// inflating whichever battery happened to run last.
672+
const UNATTRIBUTED_BATTERY = '(no battery open)';
673+
674+
// The battery ledger, read by `batteryFloorFailures()` below from the OTHER
675+
// function. `battery()` opens a battery; every assertion registered after that
676+
// line is attributed to the one most recently opened, so a section that stops
677+
// running stops registering and names ITSELF at the floor rather than going
678+
// quiet.
679+
//
680+
// ⚠️ Named for the roster's role, deliberately NOT with a self-test spelling:
681+
// `check:pm-dispatch-gates` anchors on a top-level declaration whose NAME spells
682+
// self-test and every such name owes a row in its COMPOUND_ANCHOR_LEDGER. This
683+
// machinery holds no fixtures to mask and reads no path literal, so the accurate
684+
// name is the one that says `battery`.
685+
const batterySeen = new Map();
686+
let openBattery = null;
687+
688+
/** Open a battery. Every assertion registered after this line is attributed to it. */
689+
function battery(name) {
690+
openBattery = name;
691+
}
692+
693+
/** Called by `selfTest()`'s own assertion sink, once per assertion. */
694+
function registerCase() {
695+
const name = openBattery ?? UNATTRIBUTED_BATTERY;
696+
batterySeen.set(name, (batterySeen.get(name) ?? 0) + 1);
697+
}
698+
699+
/**
700+
* The floor: every declared battery RAN, and ran its cases (#13489).
701+
*
702+
* Guards the registrations made by **`selfTest()`** — the body whose assertion
703+
* sink `t()` routes through `registerCase()`. It is called from `runSelfTest()`
704+
* immediately before the success line, so that line can only be printed by a run
705+
* in which the set of batteries that registered assertions EQUALS the set
706+
* declared, each at or above its own count. A set difference says WHICH battery
707+
* stopped; a count says only that something did.
708+
*
709+
* @returns {string[]} floor breaches; empty means the floor held
710+
*/
711+
function batteryFloorFailures() {
712+
const declared = Object.keys(SELF_TEST_BATTERIES);
713+
const problems = [];
714+
if (declared.length < SELF_TEST_BATTERY_FLOOR) {
715+
problems.push(
716+
`SELF_TEST_BATTERIES declares ${declared.length} batteries, below the pinned `
717+
+ `${SELF_TEST_BATTERY_FLOOR} — a battery deleted from the roster takes its own floor with it.`,
718+
);
719+
}
720+
for (const [name, count] of batterySeen) {
721+
if (declared.includes(name)) continue;
722+
problems.push(
723+
`self-test battery "${name}" registered ${count} case(s) but is not declared in `
724+
+ 'SELF_TEST_BATTERIES — an assertion attributed to no declared battery is one nothing floors.',
725+
);
726+
}
727+
for (const name of declared) {
728+
const count = batterySeen.get(name) ?? 0;
729+
if (count >= SELF_TEST_BATTERIES[name]) continue;
730+
problems.push(
731+
count === 0
732+
? `self-test battery "${name}" DID NOT RUN — 0 cases registered, ${SELF_TEST_BATTERIES[name]} pinned. `
733+
+ 'The verdict below would have claimed those cases hold.'
734+
: `self-test battery "${name}" registered ${count} case(s), below its pinned floor of `
735+
+ `${SELF_TEST_BATTERIES[name]} — cases that used to run no longer do.`,
736+
);
737+
}
738+
if (problems.length) {
739+
problems.push(
740+
'A battery at or below its floor means cases STOPPED RUNNING — the battery is the bug, not the '
741+
+ 'number. Find what stopped registering (an early return, a deleted block, a guard that now '
742+
+ 'skips) and restore it.',
743+
);
744+
}
745+
return problems;
746+
}
747+
622748
/**
623749
* The instrument for a gate whose defect class is its MATCHING RULE: a clean
624750
* tree cannot tell a working rule from one that stopped matching, because both
@@ -628,8 +754,12 @@ function main() {
628754
* @returns {string[]} failure descriptions; empty means OK
629755
*/
630756
export function selfTest() {
757+
// The single hoisted battery this body's assertions are attributed to. The
758+
// floor that reads them is evaluated at the verdict site in `runSelfTest()`.
759+
battery('check-turbo-task-graph self-test');
631760
const failures = [];
632761
const t = (label, ok) => {
762+
registerCase();
633763
if (!ok) failures.push(label);
634764
};
635765

@@ -896,6 +1026,22 @@ function runSelfTest() {
8961026
for (const f of failures) console.error(` - ${f}`);
8971027
process.exit(1);
8981028
}
1029+
1030+
// ── The assertion floor, at the verdict site ───────────────────────
1031+
// `selfTest()` registers but does not decide, so the floor over ITS
1032+
// registrations is evaluated here, after every battery has had its chance and
1033+
// immediately before the success line — the only place a run that registered
1034+
// nothing can still be stopped from reporting that every case held.
1035+
const floorBreaches = batteryFloorFailures();
1036+
if (floorBreaches.length) {
1037+
console.error(
1038+
`FAIL: check-turbo-task-graph --self-test — the assertion floor over selfTest()'s `
1039+
+ `registrations was breached (${floorBreaches.length} problem(s)); every case that DID run passed.`,
1040+
);
1041+
for (const b of floorBreaches) console.error(` - ${b}`);
1042+
process.exit(1);
1043+
}
1044+
8991045
console.log('OK: check-turbo-task-graph --self-test — all cases passed.');
9001046

9011047
return SELF_TEST_VERDICT;

0 commit comments

Comments
 (0)