Summary
A Claude-primary Firstmate home can remain silently unsupervised indefinitely when an actionable watcher close successfully rewakes the session but that handling turn ends in an API error.
Claude runs StopFailure instead of Stop for API-error turn ends.
Firstmate's primary supervision guard and auto-arm are registered only under Stop, and the Claude continuity design starts the successor at the next Stop after handling.
No next Stop means no rearm, no guard, and no alarm.
This happened with three tasks in flight and remained invisible for 3h52m until the captain returned.
Observed
Installed harness:
Final pre-gap watcher lifecycle:
arm_pid=41542 watcher_pid=41556 origin=started
started_at=1787546697 ended_at=1787547749
exit_code=0 signal=none reason=actionable-signal
beacon_age=49 successor=none
Delivery ledger:
watcher_pid=41556
signal: deckhand-crawler-v1.status deckhand-crawler-v1.turn-ended alienware-ml.status
The Claude transcript then shows:
2026-08-24T05:02:29.597Z Stop hook feedback enqueued
2026-08-24T05:02:29.604Z feedback dequeued
2026-08-24T05:02:29.618Z synthetic handling turn created
2026-08-24T05:05:53.707Z API Error: 529 Overloaded (isApiErrorMessage=true)
There is no stop_hook_summary after the API error.
No further transcript event occurs until the captain returns.
Morning drain:
1787547749 102/103/104 signal ...
WATCHER DOWN - SUPERVISION IS OFF
3 task(s) in flight, but no watcher has a fresh beacon
(last beat: 13980s ago, grace 300s).
The next ordinary Stop immediately starts another watcher at 1787561825, which rules out a poisoned lock, bad eligibility, or persistent home misconfiguration.
Mechanism
- The watcher is intentionally one-shot and exits 0 after an actionable reason.
- Claude ordering intentionally does not start a successor before notification;
docs/watcher-continuity.md assigns that to the next Stop after handling.
fm-claude-stop-autoarm.sh exits 2 and successfully creates the handling turn.
- The handling turn ends through Claude's
StopFailure event because the API returns 529.
- Tracked
.claude/settings.json registers supervision only for Stop.
- Therefore no guard or successor arm runs.
- With no watcher there is no wake; with no wake there is no turn; with no normal turn end there is no Stop.
Claude's hook reference says StopFailure runs instead of Stop on API errors and that its output/exit code do not control continuation, so copying the current exit-2 Stop handler is not sufficient.
Not the retained SIGTERM artifacts
Two older .claude-autoarm-output.* files contain Terminated: 15, but their watcher PIDs map exactly to lifecycle rows with reason=arm-interrupted during explicit Claude session restarts.
The final overnight cycle is exit_code=0 signal=none reason=actionable-signal.
Impact
Durable queue custody prevents data loss, but blocked work is neither retried nor reported until a human supplies another turn.
A transient vendor overload can therefore disable all supervision for an unbounded unattended interval.
Suggested fix
Register a dedicated primary StopFailure supervision handler.
At minimum it must, without another model turn, publish a typed degraded episode and emit one rate-limited pane-independent active alert through the existing wedge-alarm channels.
Acceptance criterion: within FM_GUARD_GRACE after an eligible StopFailure, either a live identity-matched watcher with an independently viable owner exists or the captain receives the active alert.
Do not reuse the current Stop exit-2 protocol without isolated live verification because Claude documents StopFailure output and exit status as ignored.
Add a live isolated regression that induces an API-error handling turn and sends no later user message.
Workaround
There is no reliable normal-mode unattended workaround in the current Claude-primary design.
Keeping the optional away daemon active could provide an independent owner only when its injection target is valid, but that is a different operating mode and should not be required to uphold normal Stop-owned continuity.
Summary
A Claude-primary Firstmate home can remain silently unsupervised indefinitely when an actionable watcher close successfully rewakes the session but that handling turn ends in an API error.
Claude runs
StopFailureinstead ofStopfor API-error turn ends.Firstmate's primary supervision guard and auto-arm are registered only under
Stop, and the Claude continuity design starts the successor at the next Stop after handling.No next Stop means no rearm, no guard, and no alarm.
This happened with three tasks in flight and remained invisible for 3h52m until the captain returned.
Observed
Installed harness:
Final pre-gap watcher lifecycle:
Delivery ledger:
The Claude transcript then shows:
There is no
stop_hook_summaryafter the API error.No further transcript event occurs until the captain returns.
Morning drain:
The next ordinary Stop immediately starts another watcher at
1787561825, which rules out a poisoned lock, bad eligibility, or persistent home misconfiguration.Mechanism
docs/watcher-continuity.mdassigns that to the next Stop after handling.fm-claude-stop-autoarm.shexits 2 and successfully creates the handling turn.StopFailureevent because the API returns 529..claude/settings.jsonregisters supervision only forStop.Claude's hook reference says
StopFailureruns instead ofStopon API errors and that its output/exit code do not control continuation, so copying the current exit-2 Stop handler is not sufficient.Not the retained SIGTERM artifacts
Two older
.claude-autoarm-output.*files containTerminated: 15, but their watcher PIDs map exactly to lifecycle rows withreason=arm-interruptedduring explicit Claude session restarts.The final overnight cycle is
exit_code=0 signal=none reason=actionable-signal.Impact
Durable queue custody prevents data loss, but blocked work is neither retried nor reported until a human supplies another turn.
A transient vendor overload can therefore disable all supervision for an unbounded unattended interval.
Suggested fix
Register a dedicated primary
StopFailuresupervision handler.At minimum it must, without another model turn, publish a typed degraded episode and emit one rate-limited pane-independent active alert through the existing wedge-alarm channels.
Acceptance criterion: within
FM_GUARD_GRACEafter an eligibleStopFailure, either a live identity-matched watcher with an independently viable owner exists or the captain receives the active alert.Do not reuse the current Stop exit-2 protocol without isolated live verification because Claude documents
StopFailureoutput and exit status as ignored.Add a live isolated regression that induces an API-error handling turn and sends no later user message.
Workaround
There is no reliable normal-mode unattended workaround in the current Claude-primary design.
Keeping the optional away daemon active could provide an independent owner only when its injection target is valid, but that is a different operating mode and should not be required to uphold normal Stop-owned continuity.