---
name: ci-kill-scoping
description: "2026-09-07: ci/psyche/live-relay-int.sh cleanup killed EVERY claude-spt.exe on the shared runner (tasklist|grep|taskkill) = every peer agent's live adapter incl. perri's own. Fixed run-scoped; repo already had the idiom 3x. REQ-HAZARD-CI-KILL-SCOPING, commit 9c87372."
metadata:
  type: project
---

**Found by hertz during doyle's fleet kill-census** (a fleet daemon `spt.exe` died unexplained on
hfenduleam ~08:03Z 2026-09-07; census asked every DRI: "do you kill a remembered pid or a NAME
without re-verifying identity at kill time?"). hertz explicitly did NOT attribute the outage to us
(dead proc was spt.exe, matches none of our sites) — a real hazard found while hunting another.

**The bug:** `for p in $(tasklist 2>/dev/null | grep -i claude-spt | awk '{print $2}'); do taskkill
//PID "$p" //T //F; done` in live-relay-int.sh cleanup. On the shared runner EVERY live agent runs
`claude-spt.exe launch --id <agent>` — deployah, doyle, hertz, perri (me), … — so this tree-force
kills all of them, not just the test's disposable. Confirmed by dumping `wmic process where "name
like 'claude-spt%'" get commandline`: 10 agents' launch procs + their translate procs, none
carrying the test's `sptc-ci-liverelay-<RUN>` id.

**Fix (commit 9c87372, test-only, no release):** scope by this run's unique id in the command line —
`wmic process where "name like 'claude-spt%' and commandline like '%$ID%'"`. The image-name pin is
load-bearing: it stops wmic matching its OWN command line (which contains the `%$ID%` literal).
Three remembered-pid kills (`taskkill //PID "$RUNPID" //T //F`) gained a kill-time recheck
(`wmic process where "processid=$RUNPID" get name | grep -qiE 'claude'`) — a captured pid can be
OS-recycled between spawn and cleanup. Guard: `tests/ci-kill-scoping.sh` scans ci/+tests/ for the
class; REQ-HAZARD-CI-KILL-SCOPING; KNOWN-HAZARDS §10.1. Related: [[measuring-a-process-env-vs-shipping-a-probe]].

⭐ **The correct pattern was already in my own repo three times** (bind-int.sh:50, multi-subnet:117,
wake-survival:64) — the fix was applying line 50's idiom, not inventing one. When a peer flags a
hazard class, grep your repo for BOTH the offender AND the sites that already do it right; the right
ones are the spec.

⭐ **wmic self-match trap:** a cmdline-scoped `wmic process where "commandline like '%$ID%'"` with NO
name pin matches the wmic process's own command line (the `$ID` literal is in its argv). Always pin
an image name alongside the cmdline filter.

⭐ **Presence probe ≠ kill.** live-relay also greps `tasklist | grep -qi claude-spt` for an
online-count wait — that takes no life and is exempt. A guard test keyed on "name enumeration" must
require the enumeration to FEED a kill (taskkill/Stop-Process), or it flags the harmless probes. My
first guard version misfired here: it read the by-`processid=` identity-recheck as a name
enumeration, because "wmic process where" + "claude" both appeared — a name enumeration must match a
NAME predicate (`name=`/`name like`/`tasklist…claude`), never a `processid=` query.
