fix(#3339): consolidated helper silently overwrote an unrelated module-scope function

The runVerifiedPhaseComplete(args, tmpDir) consolidation in the prior
commit hoisted a `function` declaration into a bare (sloppy-mode) block.
Annex B legacy hoisting semantics mean a block-scoped function
declaration in sloppy mode also reassigns any enclosing var of the same
name the instant the block executes -- and this file already had an
unrelated module-scope runVerifiedPhaseComplete(args, tmpDir, env) at
line 54, used by ~50 other call sites throughout the file. The block ran
before any test() body did, so every one of those 50 call sites was
silently pointed at the consolidated helper's different phase-matching
logic (parseInt-based, loses dotted decimal sub-phase segments) instead
of the real one (normalizePhaseToken/phaseTokenFromDirName-based),
breaking multi-level decimal phases like 03.2.1.

Fixed by wrapping the consolidated helper in a strict-mode IIFE, which
disables Annex B hoisting and restores real block scoping.

Caught by a genuine gsd-test failure (2 unique failures, both throw-
class, both in phase-completion verification-gate behavior) -- root-
caused via diff against the pre-consolidation commit and a scoped local
node --test run confirming the fix, not asserted from a hunch.

No test() count changed. No production code touched.
This commit is contained in:
sim
2026-08-12 07:40:34 -04:00
parent c444051bef
commit 4036470ca0

View File

@@ -10495,7 +10495,18 @@ describe('#2572: phase complete warns when a SUMMARY claims files that never lan
// Outer scope shared by the two fold blocks below (deliberately NOT module-scope:
// this file already declares a distinct, 3-arg `runVerifiedPhaseComplete(args, tmpDir, env)`
// at line 54 used throughout the rest of the file; nesting here avoids shadowing it).
{
//
// IIFE, not a bare `{ }` block: this file has no top-level 'use strict', so a plain
// block is sloppy-mode and Annex B function-hoisting semantics apply — a `function`
// declared directly inside a bare block still leaks out and REASSIGNS the enclosing
// (module-scope) `runVerifiedPhaseComplete` var the moment this block runs, clobbering
// the real one at line 54 for every call site in the file (test() bodies are deferred
// and all run after this synchronous top-level code, so every caller ends up hitting
// this one). Wrapping in a strict-mode function expression suppresses Annex B leakage,
// matching how the two original un-consolidated copies were each scoped inside a
// strict-mode `describe(() => { 'use strict'; ... })` arrow function body.
(function () {
'use strict';
/**
* Write a passed-VERIFICATION marker for the phase, then run `phase complete N`.
* Mirrors phase.test.cjs's writePassedVerificationForPhase: a `<phase>-VERIFICATION.md`
@@ -10846,4 +10857,4 @@ describe('phase complete stage-3 sentinel filter (#2949)', () => {
});
});
}
}
})();