Skip to content

Commit 6cddfb7

Browse files
committed
tooling(scripts): assertion floor for check-docs-single-h1' self-test
`cases.filter((c) => !c.ok)` was this self-test's only success condition, so "every case held" and "the cases never ran" printed the same line (#13489). Class-1 sink repair, the PR #15156 shape: the concise-arrow `t` sink gains a block body that calls `registerCase()` before the unchanged `cases.push`. No assertion condition is inverted or rewritten. Class-2 roster, the PR #15217 shape: ONE battery hoisted to the top of the self-test body, floor at the measured 20, `SELF_TEST_BATTERIES` size pinned at 1. The file's single named section banner is NOT split on, and no comment was promoted to a section head. Case count before == after, measured by pinning the roster to an unreachable value and reading the breach line: 20 — which agrees with the count the existing verdict line prints. `--self-test` stdout and stderr are byte-identical to the base tree's, exit 0 on both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
1 parent 0d46da5 commit 6cddfb7

1 file changed

Lines changed: 103 additions & 1 deletion

File tree

scripts/check-docs-single-h1.mjs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,64 @@ function main(argv) {
378378
// handshake is a flag rather than a returned sentinel.
379379
let selfTestReachedVerdict = false;
380380

381+
// ── The self-test's own battery roster and floor (#13489) ──────────────────
382+
//
383+
// `cases.filter((c) => !c.ok)` used to be this self-test's ONLY success
384+
// condition, so "every case
385+
// held" and "the cases never ran" printed the same line. Closed the way
386+
// PR #13487 validated on check-doc-authoring: what is pinned is the registered
387+
// NAMES, not a number. The floor requires the OPENED set to equal the DECLARED
388+
// set with each battery at or above its own count.
389+
//
390+
// This file declares ONE battery, opened at the top of the self-test body. It
391+
// carries exactly ONE named section banner (`The carve-out machinery, driven by
392+
// a SYNTHETIC exclusion`), which is fewer than the two the sectioning criterion
393+
// needs, and ⛔ a single banner is NOT split on — sectioning on it would leave
394+
// every case above it in an unnamed remainder battery this transplant would
395+
// have to invent a name for. The hoisted single battery is the shape PR #14896,
396+
// PR #15003 and PR #15217 landed for exactly this case.
397+
//
398+
// ⛔ A pinned TOTAL is not the repair: a battery dropping from 9 cases to 3
399+
// keeps a total "right" the moment a sibling grows.
400+
//
401+
// The count is a FLOOR, not an equality — adding cases is ordinary work and must
402+
// not red. A battery BELOW its floor means cases stopped running; the remedy is
403+
// to find what stopped registering.
404+
const SELF_TEST_BATTERIES = Object.freeze({
405+
'check-docs-single-h1 self-test': 20,
406+
});
407+
408+
// DELETING an entry silences that battery's floor exactly as effectively as
409+
// zeroing it, so the roster's own size is pinned too.
410+
const SELF_TEST_BATTERY_FLOOR = 1;
411+
412+
// The key an assertion is filed under when no battery is open. It is not a
413+
// declared battery, so it reds by the same set difference rather than silently
414+
// inflating whichever battery happened to run last.
415+
const UNATTRIBUTED_BATTERY = '(no battery open)';
416+
381417
export function selfTest() {
418+
// The battery ledger this self-test's floor is evaluated against (#13489).
419+
// `battery()` opens a battery; every assertion below is attributed to the one
420+
// most recently opened, so a section that stops running stops registering and
421+
// names ITSELF at the floor rather than going quiet.
422+
const batterySeen = new Map();
423+
let openBattery = null;
424+
const battery = (name) => {
425+
openBattery = name;
426+
};
427+
const registerCase = () => {
428+
const b = openBattery ?? UNATTRIBUTED_BATTERY;
429+
batterySeen.set(b, (batterySeen.get(b) ?? 0) + 1);
430+
};
431+
battery('check-docs-single-h1 self-test');
382432
const cases = [];
383-
const t = (name, ok, detail) => cases.push({ name, ok: Boolean(ok), detail });
433+
// The concise arrow gains a BLOCK body so the case can be registered before
434+
// it is recorded; `cases.push` is unchanged, so no assertion is rewritten.
435+
const t = (name, ok, detail) => {
436+
registerCase();
437+
cases.push({ name, ok: Boolean(ok), detail });
438+
};
384439

385440
const dir = mkdtempSync(join(tmpdir(), 'docs-single-h1-'));
386441
try {
@@ -493,6 +548,53 @@ export function selfTest() {
493548
rmSync(dir, { recursive: true, force: true });
494549
}
495550

551+
// ── The floor: every declared battery RAN, and ran its cases (#13489) ────
552+
//
553+
// Evaluated after every battery has had its chance and BEFORE the verdict, so
554+
// the success line below can only be printed by a run in which the set of
555+
// batteries that registered assertions EQUALS the set declared. A set
556+
// difference names WHICH battery stopped; a count says only that something did.
557+
// This file's sink IS the `cases` ledger, so the floor speaks its idiom: a
558+
// breach is recorded as a failing case and reds through the existing verdict
559+
// below. It bypasses `t()` deliberately — a floor message is not a case.
560+
const floorFailure = (message) => { cases.push({ name: message, ok: false }); };
561+
const declaredBatteries = Object.keys(SELF_TEST_BATTERIES);
562+
let floorBreached = false;
563+
if (declaredBatteries.length < SELF_TEST_BATTERY_FLOOR) {
564+
floorBreached = true;
565+
floorFailure(
566+
`SELF_TEST_BATTERIES declares ${declaredBatteries.length} batteries, below the pinned `
567+
+ `${SELF_TEST_BATTERY_FLOOR} — a battery deleted from the roster takes its own floor with it.`,
568+
);
569+
}
570+
for (const [name, count] of batterySeen) {
571+
if (declaredBatteries.includes(name)) continue;
572+
floorBreached = true;
573+
floorFailure(
574+
`self-test battery "${name}" registered ${count} case(s) but is not declared in `
575+
+ 'SELF_TEST_BATTERIES — an assertion attributed to no declared battery is one nothing floors.',
576+
);
577+
}
578+
for (const name of declaredBatteries) {
579+
const count = batterySeen.get(name) ?? 0;
580+
if (count >= SELF_TEST_BATTERIES[name]) continue;
581+
floorBreached = true;
582+
floorFailure(
583+
count === 0
584+
? `self-test battery "${name}" DID NOT RUN — 0 cases registered, ${SELF_TEST_BATTERIES[name]} pinned. `
585+
+ 'The verdict below would have claimed those cases hold.'
586+
: `self-test battery "${name}" registered ${count} case(s), below its pinned floor of `
587+
+ `${SELF_TEST_BATTERIES[name]} — cases that used to run no longer do.`,
588+
);
589+
}
590+
if (floorBreached) {
591+
floorFailure(
592+
'A battery at or below its floor means cases STOPPED RUNNING — the battery is the bug, not the '
593+
+ 'number. Find what stopped registering (an early return, a deleted block, a guard that now '
594+
+ 'skips) and restore it.',
595+
);
596+
}
597+
496598
const failed = cases.filter((c) => !c.ok);
497599
for (const c of failed) console.error(` ✗ ${c.name}${c.detail ? ` — ${c.detail}` : ''}`);
498600
if (failed.length) {

0 commit comments

Comments
 (0)