0035 — An idle Driver has one waker, and a dead one has one reviver, chosen by a file

What was measured

A read-only audit of the mini on 2026-09-29 (05:40–06:30 UTC), four live Drivers: page-speed 1fdb267c, settings e40d61df, module-switch 74d91d18 and homepage 048857ea. All four are Driver-first: driverSid == workerSid, and the work runs in the Driver's own sub-agents (ADR-0025).

Four things can wake a Driver, and none of them covers a Driver-first Driver that went idle with its board short.

Waker Why it misses that Driver
Stop gate (drive-gate) It fails open on purpose. It releases after 25 minutes with nothing changed, after 180 minutes in total, or after 6 blocks in a row. Once it has released, nothing takes over.
nudge check-in (ADR-0030 row 4) watcher-doctor arms it, and has run as a system-domain LaunchDaemon since 2026-09-27 22:18. Every check-in it armed died before its first tick. nudge.log has 455 CHURN lines on 09-28. Three of the four Drivers had no live --_watch process, checked with ps.
Supervisor quiet-stop Rule 6 refuses whenever worker equals driver, which has been the default shape since 2026-09-12. Every live task's log says quiet-stop: no wake — worker and driver are the same session.
Temporal watcher It nudges only a Driver that is busy and stalled. An idle Driver it leaves alone.

A Driver that dies has two revivers, and they neither use the same test for death nor read each other.

The decision

  1. The Supervisor is the one waker for an idle Driver. For a Driver-first task, rule 6 no longer refuses. The Supervisor wakes the Driver when all of the following hold:

    • The task is neither terminal nor awaiting-human. awaiting-human means a person owes the next move.
    • The Driver is alive. This is read three ways; an undetermined reading does nothing.
    • The Driver has been quiet for at least 15 minutes, the Stop gate's own quiet window. Quiet means the Driver's transcript and every sub-agent transcript under its session stopped growing. A Driver waiting on its own sub-agents is working, not idle.
    • The backoff has run out. It grows 15 → 30 → 60 → 90 minutes while the task's authored state does not move, and resets when it does. "Authored state" is the same fingerprint the watcher uses: task.json, acceptance.json and events.jsonl.

    The wake text is the canonical Driver check-in, watcher-doctor --checkin-text <task>. There is one source for it, and it carries ADR-0033's rule that "nothing moved" is not an answer. The idle-streak audit is asked when the wake fires, not when it is armed. An unreadable board still wakes: a missed wake costs a quit, while an extra wake costs one turn.

    Why the Supervisor: it already sweeps every task file every 60 seconds. Coverage is triggered by the artifact (ADR-0030 principle 2), so nothing has to be armed per Driver, and there is no per-Driver process that can die. The check-in needed both an arm per Driver and a process per Driver, and both failed silently for two days.

  2. The nudge check-in stops being a Driver waker once decision 1 is deployed. watcher-doctor stops counting Drivers as expected lanes, a local-bin change that ships with the Supervisor deploy. nudge keeps all its non-Driver jobs, and its launcher bug is still owed for them. Until the deploy, the check-in stays as the interim waker. On 2026-09-29 it was armed by hand from a user shell for module-switch and homepage.

  3. The Temporal watcher keeps the one wake the Supervisor cannot give: busy and stalled, meaning a wedged turn. That is not an idle wake, and it is unchanged.

  4. Only one reviver acts for a task at a time, and a file decides which.

    • The watcher writes ~/.claude/jobs/tasks/<task>/watcher.json on every tick. It holds workflowId, runId, sid and tickAt, plus what that tick's probe saw (rosterOk, found). The probe activity writes it, so no new workflow command exists and running histories replay unchanged.
    • While tickAt is less than 10 minutes old, the watcher owns revival for a bounded grace. The Supervisor counts no dead readings toward a respawn and spawns nothing until it has itself seen the Driver dead for 15 minutes (WATCHER_REVIVE_GRACE_MS). Past that, revival comes back to it. See Amendment 2026-09-29.
    • When the file is stale or absent, the Supervisor owns revival, as it does today.
    • The Supervisor reads a file and never asks Temporal (ADR-0003).

    Why the watcher goes first: it resumes the same conversation, so the Driver keeps its board in context, which is the other failure Gera named. It also survives worker restarts, and it holds the item claims. The Supervisor's successor path remains for when the watcher itself is gone.

  5. Liveness is judged by session id. Names are labels. The watcher finds its roster row by sid first and by name second. A revive mints a new sid, and the watcher already re-captures it from the revive's output. A row counts as gone only when neither the sid nor the name matches. A live session is never revived just because it was renamed.

  6. Restart caps count a window, not a lifetime.

    • Neither reviver may revive a task more than 5 times in any rolling 24 hours.
    • The Supervisor keeps the times in task.json driverRespawnTimes. The watcher carries its own list across continue-as-new.
    • driverRespawns stays as a lifetime count, for display only.
    • A sixth death inside 24 hours still parks the task and escalates, as it does today.
  7. The watcher lives as long as its task is open. At its lifetime ceiling it continues-as-new instead of expiring, as long as the task is not terminal. Two exits stay:

    • The 2-day no-movement idle exit, which is how an abandoned task ends.
    • The nudge-ceiling FAILED exit.
  8. Temporal's terminal state is copied into the task by the task's only writer.

    • The watcher already appends a closed event to events.jsonl when it ends.
    • The Supervisor, which writes task.json through writeTask, copies {status, closedAt, reason} into task.json watcher and into STATE.md's health line.
    • "Watcher closed while the task is open" is a named health failure there, never "OK".
    • The copy never changes state. Only the finisher declares a task done (DESIGN §9c).

A revival counts only if the revived session drives

Live evidence from 2026-09-28/29 added three decisions. Each one makes a wake or a revival that arrives also one that acts.

  1. A kickoff or revival brief is delivered as the session's own prompt, never pasted into its pane.
    • Evidence: the Supervisor revived module-send-gate at 2026-09-28T02:10Z (tmux op-module-send-gate, claude --permission-mode auto) by pasting its brief. The model replied: "I read the task's files but haven't taken on the Driver role yet. Your message was entirely pasted text, with nothing you typed yourself… I want your go-ahead first."
    • Pasted content is treated as untrusted, so every revival or kickoff delivered by pane paste can produce a Driver that sits idle, which is a quit by construction.
    • The brief rides the claude CLI prompt argument on spawn and on --resume, the way ccswitch already restarts sessions (--resume <sid> "[restart…]").
    • Applies to the Supervisor's spawn and revive, and to local-bin's start-driver and driver-kickoff.
    • Mail to a session that is already driving (msg, quiet-stop wakes) is not a kickoff and is unchanged.
  2. A spawned session is never left on a first-run prompt. Evidence: a Claude Code first-run dialog ("Teach auto mode about your environment?") held the auto-mode op-module-send-gate session on a prompt, holding a message it never read. Every interactive prompt the fleet is known to meet at launch is pre-answered at spawn, by settings or flags. A spawn that lands on a prompt it cannot answer is a failed spawn and is logged as one, not as a Driver.
  3. A respawn-cap alarm offers an action, not only an acknowledgement.
    • The alarm was not lost. sess-propflow-ef's cap fired on 09-13, 09-14, 09-15 and 09-24 with architect=no-addressee. Each time it reached the decision ledger (reached: decision ledger sup-operator-respawn-cap-2 … -15), which escalate() does by design when no Architect session is live. Each row was resolved by a person.
    • The puller deliberately does not route sup-* rows to the decider: an alarm is not a question.
    • The defect is the row's options: "Acknowledged — close this alarm" and "Already handled — close it". Answering it executed nothing, so every time a person also had to un-park the task by hand (ADR-0013: answered is not executed).
    • With decision 6 the alarm fires only on five deaths inside 24 hours, not on five over a fortnight. When it does fire, its row offers revive once more (the Supervisor clears the window and respawns) or leave it parked. The Supervisor executes the answer on its next sweep.

Rejected

What this supersedes — precisely, and nothing more

Record Superseded What stands
ADR-0030 decision 4, row "Waking the Driver that owns it" The owner, nudge check-in armed by driver setup, becomes the Supervisor's Driver-first wake, which covers every task file with nothing to arm. The rest of the table, and principles 1–6. The check-in text is unchanged and remains the single source of what a wake says.
supervisor/src/quietstop.ts rule 6 (code, not an ADR) "The worker is never the driver" as a refusal. Rules 1–5 for tasks that do have a separate worker.

Consequences, and what happens to the four live Drivers

Nothing in a live task directory is written by this ADR or by either bundle's code before it is deployed.

Amendment 2026-09-29 — a fresh heartbeat buys a watcher 15 minutes, not ownership

What changed. Decision 4 read "while tickAt is fresh … the Supervisor spawns nothing". The Supervisor that shipped defers for a bounded grace instead. Receipt: supervisor/src/revival.ts decideDeadDriver, deployed at b3ebf76.

Why. Found in the review of #236 (§2): "the absence of action reads as ownership" is the shape a supervisor must not have. The review of agent-smith #670 (round 5) then found the concrete case.

What does not change.