---
name: gate-int-tests-with-nextest-not-bare-cargo-test
description: "Gate spt int suites with `cargo nextest` (or --test-threads=1), NEVER bare `cargo test` on Windows — process-global SPT_HOME/env set_var races under parallel threads = FALSE flakes"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 77a745a3-d838-40e7-9522-5dca2858907d
  modified: 2026-08-03T13:54:33.571Z
---

When re-gating an spt int suite, run it the way CI does — **`cargo nextest run`** (process-per-test) — or the documented fallback **`cargo test ... -- --test-threads=1`**. NEVER a bare `cargo test --test <suite>` on Windows for the broker/PTY suites.

**Why:** suites like `inject_control_wedge` (and siblings: `attach`, `broker`, `dispatch`, `daemon_e2e`, etc. — the ci.yml:127/129 `-E` list) share ONE process-global `SPT_HOME` set via `std::env::set_var` in their init, and each spins a REAL broker + PTY child. Under bare `cargo test` (N tests as parallel THREADS in one process) the `set_var` mutation RACES + concurrent test-binaries' env vars (`XLATE_FIXTURE_MODE`, `SPT_INJECT_COMMIT_DEADLINE_MS`) cross-contaminate → a test's fixture binary reads the WRONG mode/deadline → FALSE failures (e.g. g2 "delivered2=true" because a concurrent test removed its fault deadline). The runner contract is documented at `inject_control_wedge.rs:28-40` ("Do NOT run a bare `cargo test` on Windows"). CI = `cargo nextest run` (ci.yml:127/129), process-per-test → no race.

**RE-CONFIRMED 2026-08-03 (#117 lane), with two more members and one new sub-class.** `endpoint_teardown_authority_e2e`'s two tests collide with EACH OTHER inside ONE binary: both copy a psyche fixture into `perch::spt_home()/srcs/dummyharness/` (the file's own line ~399) — a MACHINE-GLOBAL path, not the test's temp home — so in parallel one holds the exe and the other gets Windows `os error 32` "used by another process". ⭐⭐ **The signature of this class is that WHICH test fails ALTERNATES between runs**, and the second test's failure is a downstream PRECONDITION panic that names nothing about contention. `--test-threads=1` ⇒ 2 passed, and 182s becomes 14s — the parallel run was mostly blocked, so a wall-clock collapse is itself corroboration. Two other rig artifacts from the same suite run, both env/rig and neither code: `cargo test -p spt` does not build `mock-adapter --bin mock-session` (the IR-21 class, second member), and `attach_wedge_e2e` fails on INHERITED identity env because the daemon-stop refusal fires on it.

⭐⭐ **The refusal names ONE inherited var at a time**: clearing `OWL_SESSION_ID` made it name `SPT_ENDPOINT_ID` next, so clearing one and re-running reads as "still broken" and invites the wrong verdict. Clear the whole set (`OWL_SESSION_ID SPT_ENDPOINT_ID SPT_AGENT_ID SPT_SESSION_ID`) — as a LIVE spt agent your own session always carries them, so every bare int run inherits them.

**How to apply:** before declaring a gate held/failed on an int suite, confirm the runner. If bare `cargo test` "flakes," that is almost certainly the env-race, NOT a code defect — re-run via nextest before attributing a mechanism. The discipline of re-running the real commit (don't trust the executor's green report) is RIGHT; the COMMAND must be the test's documented runner. **Lesson paid for 2026-06-23:** doyle bare-cargo-tested v0.14.3's inject_control_wedge, got a g2 "parallel flake," wrongly attributed it to a "fault-transient optimistic-ack drop," and held the gate — todlando refuted it with the module doc + ci.yml; nextest was 10/10. Burned ~8 gate cycles. Kin [[behavior-change-grep-tests-not-comments]] (green-units≠green-int) and [[no-machinewide-killon-shared-runner]] (the box is shared — load amplifies bare-parallel races further).
