---
name: audit-live-watchers-before-rearming
description: "BINDING: enumerate and kill live background watchers before arming a replacement — a prior session's watcher survives /clear, its silence is ambiguous, and two watchers on one PR set means an unguarded merge"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: b1f660ea-fc30-43af-879d-11ea497501a6
  modified: 2026-07-27T14:27:52.583Z
---

Before arming any background watcher, **enumerate the ones already running** (`Get-CimInstance Win32_Process -Filter "Name='bash.exe'"`, match on the script path) and kill the ones your new watcher subsumes. Never arm a replacement on top of a live predecessor.

**Why:** three of my watchers survived a `/clear` into a new session on 2026-07-27 and were still polling. Two were structurally stale against rulings made *after* they were armed: `requeue-105.sh` merged with a bare `gh pr merge` (no `--match-head-commit`) — the exact stale-green mechanism that had already mis-merged #106 — and `sweep-watch.sh` v3 merged PRs *before* guarding the main run that was the sole verifier of an unverified fix. Arming a fourth would not have disarmed either; the oldest, dumbest watcher wins the race and merges.

Two traps that make this hard to see:

- **A watcher's silence is ambiguous, not dead.** Mine logged one line in 3 minutes because `say` only fires on state transitions — pending PRs log nothing. "Log stopped" and "process gone" look identical from the log. Read the process table, not the log tail. Sibling of [[verdict-from-exit-not-from-silence]].
- **Background work surviving a context reset is a documented feature** (the live-agent brief says so), so the default assumption must be ALIVE until the process table says otherwise — the opposite of the intuition that a new session starts clean.

**A watcher MUST emit a heartbeat, not just events.** This is the mechanism half of the rule, and I needed it because I rebuilt the exact flaw an hour after writing the paragraph above: my quiet-window detector logged only on state changes, so while the box stayed busy it printed nothing, and when it was killed its log was indistinguishable from a healthy watcher waiting. Log EVERY poll with the observed values (`poll: busy=false non-terminal=5 -- not quiet`), so a stale last-line timestamp is itself proof of death. A watcher whose silence is unfalsifiable cannot be trusted to be watching. Per [[rule-failed-its-author-needs-a-mechanism]] — the event-only log is what made the rule fail its author twice in one session.

**A `killed` task notification does NOT mean the process died.** The harness's background-task wrapper and the detached leaf script have independent lifetimes. Twice this session a watcher's wrapper reported `killed` while `Get-CimInstance Win32_Process` showed the leaf bash alive and still polling — one of them had been "dead" for 36 minutes and was in fact working the whole time. Both directions of the error are live: a wrapper can die under a healthy script (so you get no completion notification and must poll the log yourself), and a script can die under a healthy-looking wrapper. **`Get-CimInstance Win32_Process -Filter "Name='bash.exe'"` matched on the script path is the only oracle** — Git Bash's own `ps aux` does not reliably see these processes and returned 0 for a process PowerShell listed by pid. Consequence for design: when a watcher must WAKE you, do not rely on the harness notification — have the script signal over a channel that survives wrapper death (for me, `spt send <my own id>` onto my perch), and keep the log as the fallback.

**How to apply:** (1) list live watcher processes; (2) read each one's script before killing — it tells you what it was about to do, and that is often the finding of the hour; (3) kill leaf script + wrapper pids, confirm death via the task notifications; (4) only then arm. Corollary: **never patch a running watcher** — bash reads a script lazily by byte offset, so a live watcher gets replaced, never edited. And when a ruling changes mid-flight, killing and rewriting is the cheap move; a watcher whose ordering encodes a superseded ruling is a liability, not an asset. Related: [[main-baseline-procedure]], [[registry-mints-ride-build-prs]].
