Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 41 additions & 11 deletions scripts/check-durability-degradation-log-level.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4201,11 +4201,21 @@ function reportDepthCost() {
// fixtures pin both directions: it must FLAG the #4420 shape and must NOT flag
// the shapes that are legitimately `warn`.

// Set by `selfTest()` only after its verdict is printed, and read at the
// dispatch: a `return` that leaves the function above that line prints nothing
// and still exits 0 — a self-test that never finished, reported as one that
// passed (#13798). The self-test's own exit code stays load-bearing, so the
// handshake is a flag rather than a returned sentinel.
// Set by `selfTest()` at BOTH its verdict sites — the green line and the red
// one — and read at the dispatch AFTER both batteries have run. What it asserts
// is "ran to the end", pass or fail: a `return` that leaves the function above
// both verdict lines prints nothing and still exits 0 — a self-test that never
// finished, reported as one that passed (#13798). The self-test's own exit code
// stays load-bearing, so the handshake is a flag rather than a returned sentinel.
//
// ⛔ Not the sibling gates' shape, deliberately (#14962). Those set the flag on
// the success path alone, which is sound THERE because their failure path calls
// `process.exit(1)` inside the self-test, so the flag is never consulted on a
// red. Here the failure path `return`s and the dispatch keeps running, so a
// success-only flag reads a genuine red as "never reached its verdict" — a false
// diagnostic that sends a maintainer hunting for a truncated run that did not
// happen, and, when the flag was read between the two calls, stopped the second
// battery from running at all.
let selfTestReachedVerdict = false;

// ── The two self-tests' battery roster and floors (#13489, batch 10c) ────────
Expand Down Expand Up @@ -5526,6 +5536,12 @@ function selfTest() {
);
if (failures > 0) {
console.error(`\n✗ self-test (log-level rule): ${failures} failure(s) (cases and floor)\n`);
// A printed red verdict IS a reached verdict (#14962). The handshake
// asserts "ran to the end", pass or FAIL; the returned 1 keeps carrying
// the verdict, so the dispatch still exits 1. Set HERE, adjacent to the
// line it certifies, rather than once before the branch: the flag can
// then only be true if one of the two verdict lines was really printed.
selfTestReachedVerdict = true;
return 1;
}
console.log(`\n✓ self-test (log-level rule): ${cases.length} case(s) passed\n`);
Expand All @@ -5543,7 +5559,9 @@ function selfTest() {
// three instances, in both directions, or the fourth recurrence lands green.
// The dispatch calls TWO self-test entries and combines their statuses, so each
// one needs its own handshake: a `return` above either verdict prints nothing and
// leaves `undefined`, which the `||` below reads as a pass (#13798).
// leaves `undefined`, which the `||` below reads as a pass (#13798). Set at both
// of this battery's verdict sites, green and red, for the reason spelled out at
// `selfTestReachedVerdict` (#14962).
let readSeamsReachedVerdict = false;

function selfTestReadSeams() {
Expand Down Expand Up @@ -6793,6 +6811,9 @@ function selfTestReadSeams() {
);
if (failures > 0) {
console.error(`\n✗ self-test (read-seam invention rule): ${failures} failure(s) (cases and floor)\n`);
// Its own handshake, same reading as `selfTest`'s red path (#14962): a
// printed red verdict is a reached verdict, and the returned 1 carries it.
readSeamsReachedVerdict = true;
return 1;
}
console.log(
Expand All @@ -6805,26 +6826,35 @@ function selfTestReadSeams() {

const args = process.argv.slice(2);
if (args.includes('--self-test')) {
// Both rules' fixtures always run — a red one must not hide the other.
// Both rules' fixtures always run — a red one must not hide the other. That
// is why BOTH batteries run BEFORE either handshake is read (#14962): reading
// the first handshake between the two calls exited the process on a red
// battery 1, so battery 2 never ran — the very thing this comment forbids —
// and it did so under a message saying no verdict had been reached, while the
// red verdict line sat directly above it in the same output.
const logLevelStatus = selfTest();
const readSeamStatus = selfTestReadSeams();
// Read AFTER both have reported. An early `return` from either one still
// trips its own named diagnostic here; a genuine red does not, because a
// printed verdict sets the flag.
let handshakeMissing = false;
if (!selfTestReachedVerdict) {
console.error(
'\n✗ check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,\n'
+ 'so no success line was printed. Exiting 0 here would report a self-test\n'
+ 'that never finished as a self-test that passed.\n',
);
process.exit(1);
handshakeMissing = true;
}
const readSeamStatus = selfTestReadSeams();
if (!readSeamsReachedVerdict) {
console.error(
'\n✗ check-durability-degradation-log-level self-test: selfTestReadSeams() returned without\n'
+ 'reaching its verdict, so no success line was printed. Exiting 0 here would report a\n'
+ 'self-test that never finished as a self-test that passed.\n',
);
process.exit(1);
handshakeMissing = true;
}
process.exit(logLevelStatus || readSeamStatus ? 1 : 0);
process.exit(handshakeMissing || logLevelStatus || readSeamStatus ? 1 : 0);
} else if (args.includes('--depth-cost')) {
// A diagnostic, deliberately not part of any verdict — see `reportDepthCost`.
process.exit(reportDepthCost());
Expand Down
Loading