Skip to content

fix(bin): make supervision recovery owner-aware and durable - #5

Merged
tiago-peixoto merged 9 commits into
mainfrom
fm/firstmate-stop-guard-starves-autoarm-fork
Aug 15, 2026
Merged

tiago-peixoto merged 9 commits into
mainfrom
fm/firstmate-stop-guard-starves-autoarm-fork

Conversation

@tiago-peixoto

Copy link
Copy Markdown
Owner

Intent

Fix the Claude primary-session supervision failure observed on 2026-08-14, where work was in flight, no watcher was live, and the turn-end guard could repeat forever while the Stop auto-arm did not claim recovery.
First add a durable, bounded, self-trimming, best-effort state trace that records every auto-arm entry and selected pre-claim gate without changing hook output, status, or failure behavior.
Reproduce only in a throwaway home with real Claude, let the evidence choose among sibling starvation, the foreign live session-lock owner gate, and discarded asyncRewake, and deliberately seek falsification: no entry on the blocked Stop would falsify the identity-gate diagnosis, while an owner claim without delivered Stop feedback would support discarded rewake.
The evidence showed the hook ran and took gate-live-session-owner, while lock-owner asyncRewake worked, so preserve the identity gate and its prevention of two sessions arming one home; do not weaken the guard, arm from the read-only session, reorder hooks, or teach the falsified short-circuit mechanism.
Align the guard with session ownership so the read-only competing session can finish and the lock-owning session remains the sole mutable supervision owner and restores supervision on its next Stop.
Add a portable real-process regression and an env-gated real-Claude live guard, and prove both RED against unfixed code and green after the fix.
After two genuinely identical guard blocks, terminate the exchange in exactly one captain-facing question, reset the identical-block count when evidence changes, and suppress repeated escalation.
Update the authoritative continuity, turn-end, operating-protocol, volatile-state, and dated verification records, including exact commands and output; keep the private learning corrected to the proven mechanism.
Require bin/fm-lint.sh and documentation checks to pass.

What Changed

  • Added a bounded, best-effort auto-arm entry trace that identifies every pre-claim gate without changing hook output or failure behavior.
  • Preserved the foreign live-owner identity boundary and aligned the Claude guard with it, so a read-only competing session cannot enter an impossible recovery loop while the lock-owning session remains the only mutable arm owner.
  • Made the second genuinely identical no-claim observation own exactly one captain question, fingerprinted actual task and process-source identities, refreshed evidence at the accounting boundary, and kept queued wake delivery supervised through source retirement.
  • Added portable real-process and credentialed Claude regressions, including exact RED counterfactuals and green outcomes in the maintained verification record.

Causal Evidence

  • The blocked competing Stop wrote event=entry followed by event=gate-live-session-owner; an absent entry would have falsified the identity-gate diagnosis and supported sibling starvation.
  • The lock-owning Stop reached event=claimed, recorded outcome=rewake, and delivered real Stop hook feedback; a claim without that delivery would have supported the discarded-asyncRewake candidate.
  • Claude's current hooks reference says matching hooks run in parallel, so hook order and sibling short-circuiting are not the repair mechanism.

Risk Assessment

⚠️ Medium: this changes safety-critical turn-end ownership and the shared supervision-needed boundary, but keeps the identity gate intact and covers task replacement, process-source retirement, pending queued delivery, repeated-block termination, and real two-session Claude behavior.

Testing

  • bin/fm-lint.sh
  • bin/fm-doc-audience-check.sh
  • bin/fm-test-run.sh tests/fm-claude-stop-autoarm.test.sh tests/fm-turnend-guard.test.sh tests/fm-supervision-instructions.test.sh tests/fm-guard-stale-banner.test.sh
  • FM_CLAUDE_LIVE_E2E=1 tests/fm-claude-stop-autoarm-live-e2e.test.sh
  • Unfixed portable counterfactual: failed at the foreign-live-owner trap with expected exit 0 and actual exit 2.
  • Unfixed real-Claude counterfactual: failed with read-only Claude session was trapped by the blind-turn guard.

Pipeline

Updates from git push no-mistakes

The no-mistakes run completed intent, review, targeted test, document, lint, and push validation.
Its original CI monitor was stopped only because GitHub opened the first PR against the fork parent instead of this repository; this replacement PR carries the same six validated supervision commits on a clean origin/main base.

…rd-starves-autoarm-fork

# Conflicts:
#	AGENTS.md
#	bin/fm-claude-stop-autoarm.sh
#	bin/fm-guard.sh
#	bin/fm-turnend-guard.sh
#	bin/fm-wake-lib.sh
#	docs/architecture.md
#	docs/turnend-guard.md
#	docs/verification/supervision.md
#	tests/fm-turnend-guard.test.sh
@tiago-peixoto
tiago-peixoto merged commit 2def68d into main Aug 15, 2026
13 checks passed
@tiago-peixoto
tiago-peixoto deleted the fm/firstmate-stop-guard-starves-autoarm-fork branch September 5, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant