---
name: stopped-local-ssh-does-not-stop-its-remote-command
description: "TaskStop on a local ssh leaves the remote bash alive (no tty); relaunching the same chain then runs two full batteries concurrently in one pool and one output dir, forging load reds and a two-summary nextest.raw"
metadata: 
  node_type: memory
  type: project
  originSessionId: 6c1b8106-fa83-4fff-8e19-385f80067f8b
  modified: 2026-09-06T19:17:58.476Z
---

2026-09-06 18:24Z-18:50Z, kitsubito, W0 head 0b9554b3 (todlando's rig, my triage). He launched a
background `ssh kitsubito 'wait-for-old-driver → reset → driver → smoke'`, saw it would outlive
the local 10-min ssh cap, TaskStop'ped it, and relaunched the same chain detached with
`setsid nohup`. The stopped ssh's REMOTE bash did not die (no tty; it was sleeping in its wait
loop) — both chains woke when the old driver exited and ran TWO full `cargo nextest` suites over
ONE target dir and ONE `nextest.raw` (both opened `wb`, interleaved: one `Starting 2776 tests`
header, two `Summary` lines 1123 s / 1137 s, different fail sets and test numbering), two
smokes, one docs port. Load avg 15.3, `DOCS_SERVER_BIND_FAIL: 5474 in use`, and three
"load" reds (resident_service precondition ×2, ring_blocks, resume_no_control_steal) — every one
of them manufactured by the rig. The FIRST map I received named "load, exe-hash ready path" as
the mechanism and cited the 1-failed summary only; the second summary was 60 lines further down.

**Why:** a live-lane pool share (releases#103 class) reached through a process-lifetime gap
rather than through a path; nothing in the pool guard sees two nextests of the SAME lane. And
the driver's log grep (`sort -u | head -8`) showed one Summary, so the driver's own report
hid the second run.

Pairing CORRECTED by hertz 19:17Z: both summaries were 2776-test runs = both at HEAD (the
earlier gate-am2 run was 2771 tests, green, and the chain provably waited for it). HEAD-vs-HEAD,
never old-vs-new — a guard aimed at "old battery vs new battery" would not have caught it.

**How to apply:** (1) never trust a nextest.raw with two `Summary` lines — `grep -c Summary`
before reading any FAIL line; two = void, not red. (2) A stopped local ssh is not a stopped
remote: kill by REMOTE pid, or make the remote side idempotent. (3) The lock guards the POOL,
so it lives at the WORKTREE level (one fixed path per worktree, taken by every driver
invocation regardless of output dir) — a lock on `$OUT` lets a relaunch with a different
outdir share target/ and the port uncontended (hertz, same day; ruled). (4) When a red arrives
with a named LOAD mechanism, ask what ELSE was on the box before accepting — self-inflicted
load is a rig defect wearing a ledger row's name. See [[open-the-subindex-before-running-a-gate]]
and the pool rules in AGENTS.md.

**AMENDMENT (hertz, 2026-09-06, measured on the rig itself) — the lockfile fix in (2) is
scoped WRONG, and following it as written walks back into this.** `w0-head-chain.sh` (mtime
12:14:50, i.e. added AFTER the 11:50 collision; gate-head/ has no `.lock`, gate-head2/ does)
guards with `exec 9>"$OUT/.lock"; flock -n 9`. But `$OUT` is an ARGUMENT — `OUTDIR="${3:-.spt/gate-head}"` —
so it locks the OUTPUT DIR, while the thing actually shared is the worktree: one `target/`, one
port 5474, one checkout the chain `git reset --hard`s. Two chains launched with different
outdirs (exactly the gate-head vs gate-head2 shape) each take an UNCONTENDED lock and collide
anyway, silently, with no REFUSED line to read afterwards. The lock must sit on the POOL
(worktree/target), not on `$OUT`; the file's own point (3) is the right instinct and (2) as
written contradicts it. A guard whose scope is narrower than the resource is worse than none:
it prints reassurance.

**Also measured, against the pairing that was first suspected:** the concurrent pair was
HEAD-vs-HEAD, never old-battery-vs-new. The am2 battery was 2771 tests / 0 failed / 1049.333 s;
BOTH summaries in the poisoned `nextest.raw` are 2776-test runs. The test COUNT is the cheap sha
discriminator when two runs share a file — use it before reasoning about which drivers collided,
because the serialization that was supposed to prevent this DID work (`old-driver-gone capped=0`,
and the chain logged am2's summary before resetting). The guard that failed was not the one
everybody looked at first.

**NARROWING (todlando, 2026-09-10, on my own misuse of point (1) the same minute I wrote it).**
I handed a gate reporting contract that said "two Summary lines = VOID leg". That is WRONG as a
general rule and todlando refused it correctly: golden's Windows `test` job runs Phase A and
Phase B, and each phase legitimately emits its OWN `Summary` — so the EXPECTED count in that
job's log is TWO, and a bare `grep -c Summary` of 2 there is health, not poison. The original
measurement (2026-09-06) was ONE intended execution writing ONE `nextest.raw`, where the second
Summary was a second concurrent battery. The discriminator was never the count; it was
SURPLUS-OVER-EXPECTED.

**How to apply (supersedes point (1) as written; mapping basis REFINED same day by deployah then
todlando):** count the Summary lines, state how many executions the job is SUPPOSED to have, then
map each Summary to its phase by the log's PHASE/EXECUTION BOUNDARY — the structural position in
the log is the authoritative map. Population (test count, duration, fail set) CORROBORATES that
map; it is not the map. deployah's worked example, golden arm 2: Windows 3381 and 238, Linux 3360
and 223 — four Summary lines across two legs, four distinct populations, each mapped to a phase,
so neither leg was void. todlando's guard on top: distinct executions can legitimately carry EQUAL
populations, so equal populations are a DUPLICATION WARNING to investigate, never proof of
contamination — and unequal ones are not proof of soundness either if the boundary map does not
close. Surplus beyond the mapping = VOID; a mapping that closes is a clean leg. Never carry a count threshold from one rig's log shape
into another's — a banked number is a measurement of the log it was taken from, and reciting it at
a differently-shaped log is the [[a-detector-must-pass-a-control-built-from-what-motivated-it]]
failure wearing a different hat. See also
[[an-identical-treatment-controls-the-input-not-the-effect]].
