# Census — kill-by-REMEMBERED-pid, and whether identity is re-verified AT KILL TIME
hertz, 2026-09-07, at main ff4b405d. Read-only. Dispatch 2 of doyle's 08:15Z pair.

## The split that matters, stated first

**A kill through an OWNED handle cannot hit a reused pid.** `Child::kill()` (Rust) and
`child.kill()` (Node) act on the process OBJECT; Windows will not recycle a pid while any handle to
it remains open. Only a kill that starts from a bare `u32` is exposed. So the census is not "every
kill" — it is every kill that begins with a REMEMBERED NUMBER.

Owned-handle sites, listed once and then set aside as SAFE BY CONSTRUCTION: brainproc.rs :998,
:1015, :1055, :1071, :1081 · broker.rs :8400, :9681, :9740, :10121 · crc_swap.rs :573 ·
daemon.rs :1656 · livehost.rs :2396, :2398 · translation.rs :355 · spt-procident :577 ·
runtime.rs :992 · gitrun.rs :152 · proc.rs :643, :712, :889 · omp-spt.mjs :989, :997.

## Remembered-pid sites — the actual population

| site | guard at kill time | verdict |
|---|---|---|
| `spt-store/src/proc.rs:430` `kill_pid_tree` | pid==0 early-return only; no identity check. It is the MECHANISM, so the guard belongs in its callers | n/a — primitive |
| `spt-store/src/proc.rs:46` `kill_pid` | `OpenProcess`→`TerminateProcess` on the number | n/a — primitive |
| `spt-daemon/src/servicehost.rs:651` | **YES — the reference implementation.** `provably_gone` first, then `exe_path(pid)` compared to the parked image via `same_image`, with the comment "The pid is live. WHO is it? The image path decides — never the number", and a FRESH read taken after the kill | **GUARDED** |
| `spt-daemon/src/livehost.rs:1135` | **YES.** Kills only on a POSITIVE basename/cmdline match; a non-match emits `LEGACY_PSYCHE_SWEEP_DECLINE ... left running` | **GUARDED** |
| `spt-daemon/src/broker.rs:8102` (zombie reap, `Gate::AlreadyLive{spid}`) | **NO.** `spid` is a REMEMBERED pid from the session record. `zombie_verdict` consults `wrapper_alive` (`process_exists`/`is_process_alive` — liveness BY NUMBER), `adapter_labeled` (a property of the RECORD, not of the live process), `has_live_descendants`, and `past_grace`. **The live process's IMAGE is never read.** | **UNGUARDED** |
| `spt-daemon/src/broker.rs:9736` | pid read from a LIVE `h.session` handle the broker still holds, so the pid cannot be recycled underneath it | guarded by construction |
| `spt-daemon/src/servicehost.rs:3544`, `broker.rs:11860`, `:14719`, `:14795`, `:14970` | test-code teardown; pid likewise taken from a live session handle in the same scope | guarded by construction |
| `spt-daemon/src/daemon.rs:3472` `taskkill /PID <gc> /F /T` | `is_process_alive(gc)` only — liveness by number, no image check. Scoped (comment: "never machine-wide — shared runner") but not identity-checked | **UNGUARDED (narrow)** |
| `spt-daemon/src/daemon.rs:3525` | test; kills its own just-spawned `ping` by pid, microseconds after spawn | negligible |
| `spt-daemon/src/shellhost.rs:639` `taskkill /PID <pid> /T /F` | caller-supplied pid; no image check at this site | **UNGUARDED (inherits caller)** |

## The finding

**spt-core already contains the correct pattern, twice, and does not apply it at the one production
site that reaps a pid it remembered across time.** `servicehost.rs:651` even writes the rule down —
"WHO is it? The image path decides — never the number" — and `broker.rs:8102` decides by the number.
That is the shape of a fix: lift `servicehost`'s image comparison into the zombie path, or into
`kill_pid_tree` itself so no caller can forget it.

**Does it explain the 08:03:15Z death? Not on its own, and I will not stretch it to.** The daemon
had a live brain child, so `has_live_descendants` would be TRUE and `zombie_verdict` returns false —
the guard that would have saved it is accidental (descendants), not deliberate (identity). It
protects only while the brain is up.

## LIMIT — the adapter half is INCOMPLETE, stated rather than implied

The installed adapter dirs (`PACER`, `alchemy`, `claude-spt`, `mobile`, `omp-spt`) contain ONLY
`manifest.toml`/`record.toml` — no executable code. The one adapter source I could locate,
`adapters/_github/BigscreenVR-omp-spt/strings/omp-spt.mjs`, kills only owned child handles
(:989, :997). I could NOT locate the executable code for claude-spt, PACER, alchemy or mobile
(not under `~/.claude/plugins/marketplaces`, which holds caveman, claude-plugins-official, cplugs,
mempalace). **Four of five adapters are UNCENSUSED. Point me at their code and I will finish it.**

## ADAPTER HALF — COMPLETED 2026-09-07 08:35Z (doyle supplied the sibling-repo paths)

Read-only; sibling repos, not ours to edit.

| repo | termination sites | verdict |
|---|---|---|
| `spt-pacer-tool` (PACER) | **ZERO** | clean — nothing to guard |
| `spt-alchemy` | 1: `tests/spt_int.rs:47` `self.0.kill()` | owned handle — safe by construction |
| `spt-mobile` | 2: `host/src/follow.rs:70` `child.kill().await`, `rust/link-client/tests/host_link.rs:36` `self.0.kill()` | owned handles — safe by construction |
| `spt-claude-code` | 7 across 4 CI scripts — **the only adapter with remembered-pid and by-NAME kills** | see below |
| `omp-spt` | 2 owned handles (:989, :997) | done previously |

### spt-claude-code, site by site

- **`ci/psyche/live-relay-int.sh:78` — UNGUARDED, and the worst shape in this whole census.**
  ```sh
  for p in $(tasklist 2>/dev/null | grep -i claude-spt | awk '{print $2}'); do taskkill //PID "$p" //T //F; done
  ```
  This kills **every `claude-spt.exe` on the box**, tree-force, with **no run-scoping whatever** —
  on a shared runner that is every other agent's live adapter, not just this test's. The function's
  own comment says it out loud: "by marker pid then name."
- `ci/launcher/bind-int.sh:50` — **GUARDED.** `wmic process where "name='claude-spt.exe' and
  commandline like '%$ID%'"` — scoped to THIS run's unique id, with the comment "never wall-a's".
- `ci/subnet/multi-subnet-bringup-int.sh:117` — **GUARDED.** Same idiom, scoped by `$C3_ID`.
- `ci/idle-translate/wake-survival-int.sh:64` — **GUARDED.** `Where-Object {$_.CommandLine -match
  '$PROBE'}` before `Stop-Process`, scoped to the disposable probe id.
- `bind-int.sh:47`, `multi-subnet-bringup-int.sh:114`, `live-relay-int.sh:77` — kill a remembered
  `RUNPID` / marker pid with `//T //F` and no identity re-check. **Narrow**: the pid is captured
  moments earlier in the same run, so the reuse window is small — but it is the same class.

### The shape worth reporting

`spt-claude-code` contains the CORRECT pattern three times (`commandline like '%$ID%'`,
`-match '$PROBE'`) and the machine-wide one once, in the same repo, by the same hand — exactly as
spt-core carries `servicehost.rs:651`'s image check beside `broker.rs:8102`'s bare number. **The
knowledge is present; what is missing is a rule that makes the scoped form the only reachable one.**

### Does any of this explain the 08:03:15Z fleet-daemon death? NO — and stated so it is not misread.

Every claude-spt site enumerates `claude-spt.exe`. The fleet daemon is **`spt.exe`**, which matches
none of them. Further, the CI job on hfenduleam in that window was **spt-core's** `unit` job, not
spt-claude-code's CI at all. RESIDUAL I am not claiming, only recording: `//T` kills a TREE, so a
daemon that was a descendant of a killed `claude-spt.exe` would die with it — but daemons are
spawned detached precisely to escape their spawner's tree, so this requires the detach to have
failed, which nothing here shows.
