0065 — The Supervisor does not replace a Driver the idle reaper closed while it waits on a person
- Status: Accepted 2026-10-17. Built in the same PR (ADR-0004: recorded at decision time).
- Date: 2026-10-17
- Deciders: Gera. He saw a session running that he didn't know about, asked why Drivers keep restarting and whether account swaps were the cause, and approved option A ("ok") once the evidence came back.
- Systems: the agentflow Supervisor (
supervisor/src/index.tsrespawn branch,supervisor/src/expiredhold.ts); local-bin'ssession-cap expire(the idle reaper, launchdco.propflow.session-expire); the block ledger and the answer bridge (supervisor/src/answers.ts).
The problem
Two rungs of the supervision ladder (ADR-0003) were undoing each other.
session-cap expireruns every 30 minutes and closes any session idle 48 h with nobody attached. It deliberately overrides anawaiting-humanhold. Its log line says so: "stale holds ignored: awaiting-human task untouched 50h".- The Supervisor saw a dead Driver on an open task and booted a successor. The successor idled on the same unanswered question, and two days later the reaper closed it again.
Measured over 2026-10-03 to 10-17, there were 25 Supervisor DEAD lines. 14 were this cycle. The other 11 came from one tmux server death on 10-11. None followed an account swap: of 1,390 in-place swaps, none was followed by the session ending within 10 minutes. appfolio-sync-reads, find-vercel-cuts, aws-spending-surge-investigation and company-line-emergency-page each respawned on 10-12, were closed on 10-14, respawned, and were closed again on 10-16. Every cycle left Gera a session he hadn't started and produced nothing.
The decision
The reaper keeps its rule. The Supervisor holds the respawn when all four of these are true:
- the task is
awaiting-human; - the reaper's own log has an
EXPIREDline naming this Driver's full sid; - the dead Driver has at least one open block, i.e. a question a person can see;
- none of those blocks has an answer bridged onto it.
The hold releases itself. When Gera answers, the answer bridge writes the answer onto the dead Driver's ledger row, and the next sweep respawns a Driver to act on it. A person moving the task off awaiting-human releases it the same way. A held task spends none of its 24 h respawn budget.
Options not taken
- B: the reaper respects the
awaiting-humanhold. It is simpler and keeps the Driver warm. It was rejected because idle Drivers waiting on a person would pile up indefinitely on a host where session count is already the pressure. The reaper's override was a deliberate choice in local-bin, and this ADR does not reverse it. - Hold on any
awaiting-humandeath. Rejected. A crash or a tmux death is still a death to repair (condition 2). A Driver with no open question would never be released (condition 3).
Consequences
- A Driver closed this way is gone until its question is answered. The question stays on the Decisions tab the whole time, because the ledger row is untouched, and the task timeline gets one
reportevent saying why. - If the reaper's log line format changes, condition 2 stops matching and the old respawn behaviour returns. That fails safe: it brings back the churn, never a silent stall.