Skip to content

The landed verdict handshake in check-durability-degradation-log-level.mjs turns a GENUINE red into 'never reached its verdict', and stops the second battery from running at all #14962

Description

@claude

Found while working #13800 (verdict handshake, PR #14960), which probed this file and left it untouched. Filed unassigned. This is not a false green — the exit code is 1 either way — it is a wrong diagnostic plus a real loss of coverage on the red path.

The shape

scripts/check-durability-degradation-log-level.mjs runs TWO batteries. Its dispatch says, verbatim:

if (args.includes('--self-test')) {
    // Both rules' fixtures always run -- a red one must not hide the other.
    const logLevelStatus = selfTest();
    if (!selfTestReachedVerdict) { ...exit 1... }
    const readSeamStatus = selfTestReadSeams();

But selfTest() sets selfTestReachedVerdict = true only on its SUCCESS path; its failure path is console.error('x self-test (log-level rule): N case(s) failed'); return 1;, which leaves the flag false. So a genuine red trips the handshake guard.

Measured, not read

A mutated copy beside the original (the tracked file was never touched), forcing the first battery's failure branch and nothing else; mutation confirmed on disk before running:

EXIT: 1
did the SECOND battery (read-seam) run at all? false

x self-test (log-level rule): 0 case(s) failed

x check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,
so no success line was printed. Exiting 0 here would report a self-test
that never finished as a self-test that passed.

Two defects in one reading:

  1. The message is false. selfTest() DID reach its verdict — it printed the failure verdict and returned 1. A maintainer reading this hunts for a truncated run that did not happen.
  2. The second battery never ran, which is exactly what the comment one line above says must not happen. Before the handshake landed, a red log-level rule still let the read-seam rule report; now it does not.

Why it is not fixed in #14960

The repair is a decision, not a transplant: either the flag is set on both exit paths (handshake means "ran to the end", pass or fail) and the returned status keeps carrying the verdict, or the two batteries each get a handshake that is checked after BOTH have run. Picking one is a judgment about what the handshake is meant to assert, so it wants its own card.

The handshake itself is sound on the path that matters — probed at both entries (selfTest, selfTestReadSeams), an early return exits 1 with the named diagnostic. Only the interaction with a genuine red is wrong.

Same landed shape ships in scripts/check-dispatcher-error-vocabulary.mjs, but it is NOT affected: there the failure path calls process.exit(1) inside the self-test, so the flag is never consulted.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions