Conversation
A second mate's captain-facing outcomes - a needs-decision it holds and
publishes, a blocker, a failure - reach the main firstmate only while the
main's watcher is polling: the parent-channel line surfaces through the
watcher's ordinary status scan for a local mate, or through the
watcher-restarted remote-reply runner for a remote mate. When the watcher
wedged - its liveness beacon stale past grace while its own process kept the
lock - nothing surfaced at all, and the Claude Stop-hook auto-arm could not
recover it: arm mode refused a live-pid/stale-beacon holder ("inspect or stop
that watcher before re-arming"), and even a manual --restart's SIGTERM was
deferred by a watcher blocked in a foreground syscall. Recovery needed a manual
kill, so second-mate decisions sat unseen until the captain asked for a status.
Make the recovery script-owned, not model- or operator-dependent:
- The arm layer evicts a provably-wedged watcher - THIS home's own live watcher
whose beacon is stale past grace, the guard's own "watcher down" condition -
home-scoped, then arms a fresh cycle, so the Stop-hook auto-arm self-heals a
wedged watcher at the next turn boundary. Eviction signals only the pid
recorded in this home's lock and only after fm_watcher_lock_matches_pid proves
it is this home's own watcher: SIGTERM first, then SIGKILL only for a
still-wedged holder that defers its TERM trap; a healthy TERM-resistant peer is
left to be attached to, never force-killed. --restart shares the same stop.
- The watcher's terminal poll wait is now an interruptible sleep, so a
poll-blocked watcher honors SIGTERM at once instead of deferring it for the
whole poll interval - keeping the SIGKILL escalation for a genuine foreground
wedge.
- The synchronous remote-secondmate observe in the pending-reply tick, which
runs inside the watcher's poll cycle, is hard-bounded, so a hung remote observe
can no longer freeze the poll loop and let the beacon go stale.
Regression tests drive real processes and fail on today's code: arm evicting a
poll-blocked wedged watcher via SIGTERM and a frozen one via the bounded SIGKILL
escalation and re-arming, attaching to a healthy watcher without evicting it, a
poll-blocked watcher honoring SIGTERM promptly, and a stalled remote observe
bounded so the tick cannot freeze.
Confidence Score: 5/5The PR appears safe to merge. The previously reported unauthorized SIGKILL path is no longer reachable from ordinary arm mode, and no blocking failure remains. Reviews (2): Last reviewed commit: "no-mistakes(ci): Fixed the Greptile P1 f..." | Re-trigger Greptile |
…ming now stops safely after SIGTERM grace instead of escalating to SIGKILL. Destructive escalation is restricted to explicit --restart. Updated behavioral coverage and documentation. Verified with tests/fm-watch-arm.test.sh, repository ShellCheck fast lint, bash syntax checks, and git diff checks. The Require no-mistakes failure appears attestation-related rather than a code defect
Author
|
Closing this one - it is no longer needed on our side. Our fleet moved to current main, which already carries the related pane/endpoint fixes (#3785, #3823), and the incident that motivated this turned out to be a stuck herdr pane plus version skew rather than the specific watcher-wedge this targeted. Retiring to keep the queue clean; happy to reopen if the wedged-watcher recovery is wanted upstream. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
A decision raised by a second mate must reach the main firstmate (and thus the captain) automatically and promptly, without the captain having to ask for a status update. On 2026-09-06 a remote second mate raised an unsolicited needs-decision - a new decision its own worker surfaced mid-task, not a reply to any request the main was waiting on - and it never surfaced to the main firstmate, which was running on the claude harness with Claude Stop-hook supervision (no Pi supervision-branch). The decision sat published in the second mate's home for hours; the main was never woken, and the captain discovered it only by explicitly asking for a status update, at which point firstmate had to manually poll the mate. The captain reports this is a repeated pattern: they keep having to ask for status because second-mate decisions, blockers, and failures do not reliably reach the main between session starts. Make firstmate reliably and promptly wake the main firstmate when a second mate raises a captain-facing outcome - especially an unsolicited decision or blocker - by a mechanism owned by scripts, not one that depends on the model remembering to speak up or on the captain polling. It must hold for a claude main with Claude Stop-hook supervision, for both a remote and a local second mate.
What Changed
Risk Assessment
✅ Low: The changes provide bounded, home-scoped watcher recovery and fair remote observation while preserving documented lifecycle invariants and adding behavior-level regression coverage.
Testing
Inspected the change, ran the focused pending-reply and watcher-arm regressions, and manually exercised both local and real remote-delta second-mate decisions through plain Claude Stop-hook arm supervision; all checks succeeded, and the captured CLI transcript shows both decisions automatically waking firstmate and appearing in the captain-facing drain.
Evidence: End-to-end local and remote second-mate decision wake transcript
Source: End-to-end local and remote second-mate decision wake transcript
Evidence: Reproducible end-to-end evidence script
Source: Reproducible end-to-end evidence script
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
🔧 **Test** - 1 issue found → auto-fixed ✅
tests/fm-pending-reply.test.sh:1612- The shared-budget elapsed-time assertion failed once at 16s against a 15s threshold, then passed on an identical retry. This appears timing-sensitive under host load; functional call-count and fair-rotation checks succeeded on retry.tests/fm-pending-reply.test.sh | tee ~/.no-mistakes/evidence/01M1X2G06A39W7EAT9F3TJFHJW/pending-reply-targeted-tests.log(initial timing failure)tests/fm-pending-reply.test.sh | tee ~/.no-mistakes/evidence/01M1X2G06A39W7EAT9F3TJFHJW/pending-reply-targeted-tests-retry.logtests/fm-watch-arm.test.sh | tee ~/.no-mistakes/evidence/01M1X2G06A39W7EAT9F3TJFHJW/watch-arm-e2e-tests.logtests/fm-claude-stop-autoarm.test.sh | tee ~/.no-mistakes/evidence/01M1X2G06A39W7EAT9F3TJFHJW/claude-stop-autoarm-integration.log🔧 Fix: Remove flaky shared-budget wall-clock assertion
✅ Re-checked - no issues remain.
Inspectedgit diff 5592cb6e3a7a1a94b3289922ea814e47f6b21ef9..6b3166d00389bed7d7f61af6954d296b0d83192aand repository status.bash tests/fm-pending-reply.test.shbash tests/fm-watch-arm.test.shExecutedend-to-end-secondmate-wake.sh, starting plain Claude Stop-hook arms and publishing unsolicited local and remote second-mate decisions through the real status and remote-delta ingest paths; verified watcher exits, durable wake records, and captain-facing drain output.Confirmedgit status --shortremained clean and no test watcher processes remained.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.