@@ -1095,9 +1095,56 @@ async function judgeFixture(src) {
10951095// as one that passed (#13798).
10961096const SELF_TEST_VERDICT = 'check-objectql-double-limit self-test reached its verdict' ;
10971097
1098+ // ── The self-test's own battery roster and floor (#13489) ──────────────────
1099+ //
1100+ // `failures.length === 0` used to be this self-test's ONLY success condition, so
1101+ // "every case held" and "the cases never ran" printed the same line. Closed the
1102+ // way PR #13487 validated on check-doc-authoring: what is pinned is the
1103+ // registered NAMES, not a number. The floor requires the OPENED set to equal the
1104+ // DECLARED set with each battery at or above its own count.
1105+ //
1106+ // This file declares ONE battery, opened at the top of the self-test body. It
1107+ // carries fewer than the two named section banners the sectioning criterion
1108+ // needs, and ⛔ a comment is NOT promoted to a section head — that is a
1109+ // judgement per comment this transplant does not make. The hoisted single
1110+ // battery is the shape PR #14896 and PR #15003 landed for exactly this case.
1111+ //
1112+ // ⛔ A pinned TOTAL is not the repair: a battery dropping from 9 cases to 3
1113+ // keeps a total "right" the moment a sibling grows.
1114+ //
1115+ // The count is a FLOOR, not an equality — adding cases is ordinary work and must
1116+ // not red. A battery BELOW its floor means cases stopped running; the remedy is
1117+ // to find what stopped registering.
1118+ const SELF_TEST_BATTERIES = Object . freeze ( {
1119+ 'check-objectql-double-limit self-test' : 47 ,
1120+ } ) ;
1121+
1122+ // DELETING an entry silences that battery's floor exactly as effectively as
1123+ // zeroing it, so the roster's own size is pinned too.
1124+ const SELF_TEST_BATTERY_FLOOR = 1 ;
1125+
1126+ // The key an assertion is filed under when no battery is open. It is not a
1127+ // declared battery, so it reds by the same set difference rather than silently
1128+ // inflating whichever battery happened to run last.
1129+ const UNATTRIBUTED_BATTERY = '(no battery open)' ;
1130+
10981131async function selfTest ( ) {
1132+ // The battery ledger this self-test's floor is evaluated against (#13489).
1133+ // `battery()` opens a battery; every assertion below is attributed to the one
1134+ // most recently opened, so a section that stops running stops registering and
1135+ // names ITSELF at the floor rather than going quiet.
1136+ const batterySeen = new Map ( ) ;
1137+ let openBattery = null ;
1138+ const battery = ( name ) => {
1139+ openBattery = name ;
1140+ } ;
1141+ const registerCase = ( ) => {
1142+ const b = openBattery ?? UNATTRIBUTED_BATTERY ;
1143+ batterySeen . set ( b , ( batterySeen . get ( b ) ?? 0 ) + 1 ) ;
1144+ } ;
1145+ battery ( 'check-objectql-double-limit self-test' ) ;
10991146 const failures = [ ] ;
1100- const expect = ( label , cond ) => { if ( ! cond ) failures . push ( label ) ; } ;
1147+ const expect = ( label , cond ) => { registerCase ( ) ; if ( ! cond ) failures . push ( label ) ; } ;
11011148 const one = async ( src ) => {
11021149 const { found, results } = await judgeFixture ( src ) ;
11031150 return { found, r : results [ 0 ] , n : found . length } ;
@@ -1242,6 +1289,50 @@ async function selfTest() {
12421289 + 'is under the same root and is NOT in the walk' ,
12431290 Boolean ( nonTestSibling ) && ! admitted . has ( nonTestSibling ) ) ;
12441291
1292+ // ── The floor: every declared battery RAN, and ran its cases (#13489) ────
1293+ //
1294+ // Evaluated after every battery has had its chance and BEFORE the verdict, so
1295+ // the success line below can only be printed by a run in which the set of
1296+ // batteries that registered assertions EQUALS the set declared. A set
1297+ // difference names WHICH battery stopped; a count says only that something did.
1298+ const floorFailure = ( message ) => { failures . push ( message ) ; } ;
1299+ const declaredBatteries = Object . keys ( SELF_TEST_BATTERIES ) ;
1300+ let floorBreached = false ;
1301+ if ( declaredBatteries . length < SELF_TEST_BATTERY_FLOOR ) {
1302+ floorBreached = true ;
1303+ floorFailure (
1304+ `SELF_TEST_BATTERIES declares ${ declaredBatteries . length } batteries, below the pinned `
1305+ + `${ SELF_TEST_BATTERY_FLOOR } — a battery deleted from the roster takes its own floor with it.` ,
1306+ ) ;
1307+ }
1308+ for ( const [ name , count ] of batterySeen ) {
1309+ if ( declaredBatteries . includes ( name ) ) continue ;
1310+ floorBreached = true ;
1311+ floorFailure (
1312+ `self-test battery "${ name } " registered ${ count } case(s) but is not declared in `
1313+ + 'SELF_TEST_BATTERIES — an assertion attributed to no declared battery is one nothing floors.' ,
1314+ ) ;
1315+ }
1316+ for ( const name of declaredBatteries ) {
1317+ const count = batterySeen . get ( name ) ?? 0 ;
1318+ if ( count >= SELF_TEST_BATTERIES [ name ] ) continue ;
1319+ floorBreached = true ;
1320+ floorFailure (
1321+ count === 0
1322+ ? `self-test battery "${ name } " DID NOT RUN — 0 cases registered, ${ SELF_TEST_BATTERIES [ name ] } pinned. `
1323+ + 'The verdict below would have claimed those cases hold.'
1324+ : `self-test battery "${ name } " registered ${ count } case(s), below its pinned floor of `
1325+ + `${ SELF_TEST_BATTERIES [ name ] } — cases that used to run no longer do.` ,
1326+ ) ;
1327+ }
1328+ if ( floorBreached ) {
1329+ floorFailure (
1330+ 'A battery at or below its floor means cases STOPPED RUNNING — the battery is the bug, not the '
1331+ + 'number. Find what stopped registering (an early return, a deleted block, a guard that now '
1332+ + 'skips) and restore it.' ,
1333+ ) ;
1334+ }
1335+
12451336 if ( failures . length > 0 ) {
12461337 console . error ( `x check-objectql-double-limit --self-test (${ failures . length } failure(s)):\n` ) ;
12471338 for ( const f of failures ) console . error ( ` - ${ f } ` ) ;
0 commit comments