@@ -233,9 +233,57 @@ function run(dir) {
233233// handshake is a flag rather than a returned sentinel.
234234let selfTestReachedVerdict = false ;
235235
236+ // ── The self-test's own battery roster and floor (#13489) ──────────────────
237+ //
238+ // `failures.length === 0` used to be this self-test's ONLY success condition, so
239+ // "every case held" and "the cases never ran" printed the same line. Closed the
240+ // way PR #13487 validated on check-doc-authoring: what is pinned is the
241+ // registered NAMES, not a number. The floor requires the OPENED set to equal the
242+ // DECLARED set with each battery at or above its own count.
243+ //
244+ // This file declares ONE battery, opened at the top of the self-test body. It
245+ // carries fewer than the two named section banners the sectioning criterion
246+ // needs, and ⛔ a comment is NOT promoted to a section head — that is a
247+ // judgement per comment this transplant does not make. The hoisted single
248+ // battery is the shape PR #14896 and PR #15003 landed for exactly this case.
249+ //
250+ // ⛔ A pinned TOTAL is not the repair: a battery dropping from 9 cases to 3
251+ // keeps a total "right" the moment a sibling grows.
252+ //
253+ // The count is a FLOOR, not an equality — adding cases is ordinary work and must
254+ // not red. A battery BELOW its floor means cases stopped running; the remedy is
255+ // to find what stopped registering.
256+ const SELF_TEST_BATTERIES = Object . freeze ( {
257+ 'check-dts-emitted self-test' : 8 ,
258+ } ) ;
259+
260+ // DELETING an entry silences that battery's floor exactly as effectively as
261+ // zeroing it, so the roster's own size is pinned too.
262+ const SELF_TEST_BATTERY_FLOOR = 1 ;
263+
264+ // The key an assertion is filed under when no battery is open. It is not a
265+ // declared battery, so it reds by the same set difference rather than silently
266+ // inflating whichever battery happened to run last.
267+ const UNATTRIBUTED_BATTERY = '(no battery open)' ;
268+
236269function selfTest ( ) {
270+ // The battery ledger this self-test's floor is evaluated against (#13489).
271+ // `battery()` opens a battery; every assertion below is attributed to the one
272+ // most recently opened, so a section that stops running stops registering and
273+ // names ITSELF at the floor rather than going quiet.
274+ const batterySeen = new Map ( ) ;
275+ let openBattery = null ;
276+ const battery = ( name ) => {
277+ openBattery = name ;
278+ } ;
279+ const registerCase = ( ) => {
280+ const b = openBattery ?? UNATTRIBUTED_BATTERY ;
281+ batterySeen . set ( b , ( batterySeen . get ( b ) ?? 0 ) + 1 ) ;
282+ } ;
283+ battery ( 'check-dts-emitted self-test' ) ;
237284 const failures = [ ] ;
238285 const eq = ( label , actual , expected ) => {
286+ registerCase ( ) ;
239287 const a = JSON . stringify ( actual ) ;
240288 const e = JSON . stringify ( expected ) ;
241289 if ( a !== e ) failures . push ( `${ label } \n expected ${ e } \n actual ${ a } ` ) ;
@@ -295,6 +343,50 @@ function selfTest() {
295343 [ 'empty:dist/index.d.ts' ] ,
296344 ) ;
297345
346+ // ── The floor: every declared battery RAN, and ran its cases (#13489) ────
347+ //
348+ // Evaluated after every battery has had its chance and BEFORE the verdict, so
349+ // the success line below can only be printed by a run in which the set of
350+ // batteries that registered assertions EQUALS the set declared. A set
351+ // difference names WHICH battery stopped; a count says only that something did.
352+ const floorFailure = ( message ) => { failures . push ( message ) ; } ;
353+ const declaredBatteries = Object . keys ( SELF_TEST_BATTERIES ) ;
354+ let floorBreached = false ;
355+ if ( declaredBatteries . length < SELF_TEST_BATTERY_FLOOR ) {
356+ floorBreached = true ;
357+ floorFailure (
358+ `SELF_TEST_BATTERIES declares ${ declaredBatteries . length } batteries, below the pinned `
359+ + `${ SELF_TEST_BATTERY_FLOOR } — a battery deleted from the roster takes its own floor with it.` ,
360+ ) ;
361+ }
362+ for ( const [ name , count ] of batterySeen ) {
363+ if ( declaredBatteries . includes ( name ) ) continue ;
364+ floorBreached = true ;
365+ floorFailure (
366+ `self-test battery "${ name } " registered ${ count } case(s) but is not declared in `
367+ + 'SELF_TEST_BATTERIES — an assertion attributed to no declared battery is one nothing floors.' ,
368+ ) ;
369+ }
370+ for ( const name of declaredBatteries ) {
371+ const count = batterySeen . get ( name ) ?? 0 ;
372+ if ( count >= SELF_TEST_BATTERIES [ name ] ) continue ;
373+ floorBreached = true ;
374+ floorFailure (
375+ count === 0
376+ ? `self-test battery "${ name } " DID NOT RUN — 0 cases registered, ${ SELF_TEST_BATTERIES [ name ] } pinned. `
377+ + 'The verdict below would have claimed those cases hold.'
378+ : `self-test battery "${ name } " registered ${ count } case(s), below its pinned floor of `
379+ + `${ SELF_TEST_BATTERIES [ name ] } — cases that used to run no longer do.` ,
380+ ) ;
381+ }
382+ if ( floorBreached ) {
383+ floorFailure (
384+ 'A battery at or below its floor means cases STOPPED RUNNING — the battery is the bug, not the '
385+ + 'number. Find what stopped registering (an early return, a deleted block, a guard that now '
386+ + 'skips) and restore it.' ,
387+ ) ;
388+ }
389+
298390 if ( failures . length > 0 ) {
299391 console . error ( `\nx check-dts-emitted self-test: ${ failures . length } failure(s)\n` ) ;
300392 for ( const f of failures ) console . error ( ` - ${ f } \n` ) ;
0 commit comments