Commit Graph

3 Commits

Author SHA1 Message Date
Levi Neuwirth b492426c69
test(sigint): assert the 45 inputs are DISTINCT, and stop claiming every stub carries the sentinel
Two closure gaps.

1. Both suites asserted only `cases.len() == 45`, so the exact
   45-entries-over-43-distinct-inputs regression could recur unnoticed
   --- the one where X3 collapsed into 1/E/empty and X4 into
   0/V/safe/bare, leaving two framing-specified cases silently
   unexercised. shared_cases() now asserts uniqueness over
   (status, stdout, stderr), inside the generator so no consumer can
   forget it. Verified by reverting both payloads to the sentinel: it
   fails naming X3.

2. Comments and ledger still said every stub emits the sentinel, which
   the explicit X3/X4 payloads had made false. They now say the
   BRANCH-DISCRIMINATING cases carry it while X3 and X4 deliberately
   carry their own --- X3 the canonical ignored wording with no token,
   X4 noise --- and that this is what makes them distinct inputs. The
   duplicated `self::`/`super::` explanation left over from the nesting
   fix is reduced to the correct one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
2026-08-20 14:22:12 +02:00
Levi Neuwirth fb8a904923
test(sigint): distinct X3/X4 vectors, nesting-safe paths, and the gate I should have run
Five findings. The first was red CI that my local gate could not have
caught.

1. `crate::common` cannot resolve when gpu_invocation_acceptance.rs is
   compiled as a nested module of gpu_initial_target_acceptance.rs,
   where `crate::` is the outer test crate. Now `super::common`, which
   resolves in both modes --- verified by compiling each target
   explicitly. Clippy's `(Some(1 | 2), true)` folding applied too.

   The reason this shipped: plain `./scripts/gate` omits sweep-crdt,
   the only stage that compiles the nested target under crdt, while
   04-lib-crdt builds the lib alone. This lane gates with `--protocol`,
   and the ledger now says so.

2. X3 and X4 had stopped being the cases the framing specifies:
   stub_script() gave every case the same sentinel stderr, so X3 lacked
   the canonical ignored text and X4 was byte-identical to
   0/V/safe/bare --- 45 entries, 43 distinct inputs. Case now carries an
   explicit stderr payload; X3 emits the canonical wording with no
   token, and both consumers assert they never repeat it.

3. The capture-creation-failure row asserted exit, wording and stage
   output but not residue. It now inspects the temporary root before
   its RAII drop and requires it empty.

4. The exact-token test covered safe and error but not ignored, despite
   the ledger claiming all three. The ignored arm now asserts its exact
   stdout, driven through a SIGINT-ignoring shell.

5. The ledger's claim that the status-2 mutation is caught only by the
   dedicated row is superseded --- the sentinel matrix catches it --- and
   the self-referential "this commit" is replaced by bc7d776.

Also records two PRE-EXISTING crdt-only failures found while gating
properly (m4_24_bare_string_glob_stays_relative and
m4_24_d3_fallback_base_is_the_smallest_attachment_dir): they reproduce
in isolation and fail identically at 72da24a, so they are not this
lane's, and no cause is claimed for them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
2026-08-20 11:50:34 +02:00
Levi Neuwirth 8802d6a1a2
test(sigint): share the conformance vectors and assert the exact branch
Four acceptance gaps, all upheld.

1. Neither suite distinguished a validated refusal from a boundary
   error. Both exit 2 (and both produce Err in Rust), so comparing exit
   codes or is_ok() let a validator that accepts EVERY status-2 pair
   pass the whole matrix --- the precise defect A6c exists to catch.
   Every stub now emits a sentinel on stderr, and an Outcome enum
   (Safe / ValidatedIgnored / ValidatedError / Boundary) is asserted
   branch-exact: a validated verdict must surface the sentinel, a
   boundary failure must withhold it. Verified: mutating the gate to
   accept any status 2 now fails the MATRIX, where before it only
   failed a dedicated row. Each helper arm's exact stdout token is
   asserted as well.

2. The 45-case set was duplicated in both suites and could drift while
   both still reported length 45. It now lives in
   tests/common/sigint_conformance.rs and both validators consume the
   same vectors.

3. A8 was incomplete --- nothing forced capture-directory creation to
   fail. A bounded row points TMPDIR at a missing directory so
   `mktemp -d` fails, asserting boundary error 2, no stage execution and
   no residue; mutating the failure branch to fall through makes it
   fail. Temporary directories are RAII throughout, replacing the
   keep()-plus-manual-cleanup shape.

4. The R-d comment still claimed a shared helper means the consumers
   "can never disagree" and described status-only behaviour. Both were
   withdrawn by revision 13; the comment now points at the shared matrix
   as what actually keeps them in step.

36 gate rows, 16 GPU rows, clippy clean, full gate green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
2026-08-20 09:15:47 +02:00