PYR0D-355: Reimplement the away-mode watchdog (idle-with-work wake, stall and dead-supervisor alarms) #43

Merged
john merged 14 commits from fm/fm-afk-watchdog-reimplement into main 2026-10-02 15:29:23 +00:00
Owner

Story: PYR0D-355 - Away mode: reimplement our own watchdog (idle-with-work and dead-supervisor alarms)

What was wrong

On 2026-10-01 away mode did no work for 4h21m. One of the two causes was that nothing gave firstmate a turn when the fleet went idle with ready work queued. The fork's earlier private watchdog had caught the same shape on 09-29, but it was lost in the upstream rebuild.

What changed

  • New bin/fm-afk-watchdog.sh, started with the away daemon (fm-afk-start.sh / fm-afk-launch.sh). It runs only while an away record exists.
  • Idle-with-work wake: when no ordinary task is working and fm-tasks-axi.sh ready is non-empty, it wakes firstmate once per idle period through the durable wake queue, carrying the away words' read-back.
  • Stall alarm: it pages only when work is waiting and nothing is working.
  • Dead-supervisor alarm: it pages through the wedge-alarm channels when supervision stops beating.
  • It stands down where the upstream supervision host runs. It checks that through the shared fm_supervision_host_enabled gate, never by whether the config file exists.

Decisions made in review (firstmate)

  • Any ordinary task whose verdict is working, from any source (pane, run-step), counts as busy and healthy. A busy fleet never pages.
  • Secondmates are neutral: they neither vouch for the fleet nor count against it.
  • Done or terminal tasks are not stalled, and the stall check is skipped under a quiet record, so a finished fleet is never paged.
  • The interrupting page is rate-limited to WATCHDOG_REPEAT_SECS on its own marker, while the durable wake retries every poll.
  • The upstream half of "lets have both" is PYR0D-356 (PR 42, merged), so this PR stays fork-local.

How it was checked

tests/fm-afk-watchdog.test.sh covers the idle wake, the stall alarm (busy pane, run-step, secondmate, quiet and done cases), alarm rate limits, and the host gate (absent file on a Claude primary, and "off"). It also went through the no-mistakes pipeline.

Follow-ups

  • Retire the stopgap custom check state/away-idle-nudge.check.sh (home-private) once this merges.
  • A live overnight trial on a real away session.
**Story:** PYR0D-355 - Away mode: reimplement our own watchdog (idle-with-work and dead-supervisor alarms) ## What was wrong On 2026-10-01 away mode did no work for 4h21m. One of the two causes was that nothing gave firstmate a turn when the fleet went idle with ready work queued. The fork's earlier private watchdog had caught the same shape on 09-29, but it was lost in the upstream rebuild. ## What changed - New `bin/fm-afk-watchdog.sh`, started with the away daemon (`fm-afk-start.sh` / `fm-afk-launch.sh`). It runs only while an away record exists. - **Idle-with-work wake:** when no ordinary task is working and `fm-tasks-axi.sh ready` is non-empty, it wakes firstmate once per idle period through the durable wake queue, carrying the away words' read-back. - **Stall alarm:** it pages only when work is waiting and nothing is working. - **Dead-supervisor alarm:** it pages through the wedge-alarm channels when supervision stops beating. - It stands down where the upstream supervision host runs. It checks that through the shared `fm_supervision_host_enabled` gate, never by whether the config file exists. ## Decisions made in review (firstmate) - Any ordinary task whose verdict is `working`, from any source (pane, run-step), counts as busy and healthy. A busy fleet never pages. - Secondmates are neutral: they neither vouch for the fleet nor count against it. - Done or terminal tasks are not stalled, and the stall check is skipped under a quiet record, so a finished fleet is never paged. - The interrupting page is rate-limited to WATCHDOG_REPEAT_SECS on its own marker, while the durable wake retries every poll. - The upstream half of "lets have both" is PYR0D-356 (PR 42, merged), so this PR stays fork-local. ## How it was checked `tests/fm-afk-watchdog.test.sh` covers the idle wake, the stall alarm (busy pane, run-step, secondmate, quiet and done cases), alarm rate limits, and the host gate (absent file on a Claude primary, and "off"). It also went through the no-mistakes pipeline. ## Follow-ups - Retire the stopgap custom check `state/away-idle-nudge.check.sh` (home-private) once this merges. - A live overnight trial on a real away session.
john added 11 commits 2026-10-02 11:31:14 +00:00
A fork-local, independent watchdog (bin/fm-afk-watchdog.sh) runs beside every away
record on the daemon, supervision-host and Pi postures. It appends one durable
check: afk-idle wake per idle period, carrying the away record's read-back, when no
ordinary task is working and the ready queue is non-empty. It alarms a dead daemon,
a dead watcher (host path: a stale beat only) and a stalled fleet once per failure
class, resets its markers on a new away entry, and exits when the record is gone.
Away entry and the daemon entry start it; a singleton lock makes extra starts safe.
# Conflicts:
#	docs/scripts.md
# Conflicts:
#	.agents/skills/afk/SKILL.md
no-mistakes(review): Count working verdicts from any source as busy
Some checks failed
CI / Test coverage guard (pull_request) Successful in 31s
CI / Behavior portable parallel 2 (pull_request) Successful in 15m25s
CI / Behavior portable parallel 1 (pull_request) Successful in 17m23s
CI / Lint 1 (pull_request) Successful in 22m25s
CI / Lint 2 (pull_request) Successful in 26m47s
CI / Behavior portable serial 5 (pull_request) Has been cancelled
CI / Behavior portable serial 6 (pull_request) Has been cancelled
CI / Behavior portable serial 7 (pull_request) Has been cancelled
CI / Behavior portable serial 8 (pull_request) Has been cancelled
CI / Behavior portable serial 9 (pull_request) Has been cancelled
CI / Behavior tests (Herdr) (pull_request) Has been cancelled
CI / Repo invariants (pull_request) Has been cancelled
CI / Behavior portable serial 2 (pull_request) Has been cancelled
CI / Behavior portable serial 1 (pull_request) Has been cancelled
CI / Behavior portable serial 3 (pull_request) Has been cancelled
CI / Behavior portable serial 4 (pull_request) Has been cancelled
b416f45c7a
no-mistakes(review): Treat inconclusive crew-state unknowns as unknown; key episodes on entered_epoch
Some checks failed
CI / Test coverage guard (pull_request) Successful in 29s
CI / Behavior portable parallel 2 (pull_request) Successful in 15m0s
CI / Behavior portable parallel 1 (pull_request) Successful in 17m28s
CI / Lint 2 (pull_request) Successful in 24m35s
CI / Lint 1 (pull_request) Successful in 25m22s
CI / Behavior portable serial 2 (pull_request) Successful in 16m58s
CI / Behavior portable serial 1 (pull_request) Failing after 20m43s
CI / Behavior portable serial 4 (pull_request) Successful in 14m59s
CI / Behavior portable serial 3 (pull_request) Successful in 17m10s
CI / Behavior portable serial 6 (pull_request) Successful in 16m31s
CI / Behavior portable serial 7 (pull_request) Successful in 16m5s
CI / Behavior portable serial 8 (pull_request) Successful in 16m56s
CI / Repo invariants (pull_request) Successful in 10s
CI / Behavior portable serial 5 (pull_request) Successful in 26m47s
CI / Behavior tests (Herdr) (pull_request) Has been cancelled
CI / Behavior portable serial 9 (pull_request) Has been cancelled
cb92bf608a
Rename the watchdog launch seam so it no longer trips the gate guard's stock-layout rule
All checks were successful
CI / Test coverage guard (pull_request) Successful in 32s
CI / Behavior portable parallel 2 (pull_request) Successful in 15m15s
CI / Behavior portable parallel 1 (pull_request) Successful in 17m34s
CI / Lint 1 (pull_request) Successful in 24m15s
CI / Lint 2 (pull_request) Successful in 25m38s
CI / Behavior portable serial 2 (pull_request) Successful in 17m3s
CI / Behavior portable serial 1 (pull_request) Successful in 20m58s
CI / Behavior portable serial 4 (pull_request) Successful in 15m12s
CI / Behavior portable serial 3 (pull_request) Successful in 17m18s
CI / Behavior portable serial 6 (pull_request) Successful in 16m31s
CI / Behavior portable serial 7 (pull_request) Successful in 16m8s
CI / Behavior portable serial 8 (pull_request) Successful in 17m3s
CI / Repo invariants (pull_request) Successful in 9s
CI / Behavior portable serial 5 (pull_request) Successful in 26m53s
CI / Behavior tests (Herdr) (pull_request) Successful in 13m59s
CI / Behavior portable serial 9 (pull_request) Successful in 24m29s
b833a1c1d9
john merged commit c1ada66ade into main 2026-10-02 15:29:23 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
john/firstmate!43
No description provided.