Skip to content

fix(bin): harden supervision recovery - #99

Merged
Amplify-Logic merged 7 commits into
mainfrom
fm/fm-upstream-supervision-recovery-s5
Aug 24, 2026
Merged

fix(bin): harden supervision recovery#99
Amplify-Logic merged 7 commits into
mainfrom
fm/fm-upstream-supervision-recovery-s5

Conversation

@Amplify-Logic

Copy link
Copy Markdown
Owner

Intent

Port three upstream supervision-recovery commits from kunchenguid/firstmate into this fork (Amplify-Logic/firstmate), adapting each to this fork's diverged code rather than cherry-picking: 88b2a94 (session-lock harness identity via path components/argv[0], contiguous-ancestry ownership, outermost-of-run lock pid, own-lock recognition in fm-lock.sh; attached watch-arm resolves unobservable closes against a PID+identity-bound delivery ledger instead of false FAILED; fork equivalents live in bin/fm-primary-scope-lib.sh and bin/fm-lock.sh, not upstream's fm-session-lock-lib.sh), 33a4287 (only its transferable core: pull guard uses the identity-matched live-watcher health predicate so a fresh leftover beacon never reads healthy; upstream's Claude Stop auto-arm subsystem is deliberately skipped because this fork never had it), and d0461e4 (model-aware supervision verdict fm_watcher_supervision_verdict with reason-keyed banner episodes; this fork maps every harness including claude to the persistent model). Captain-accepted adaptations during the port, all deliberate: supervision tests are hermetic by construction (tests/lib.sh drops inherited FM_HOME/FM_ROOT_OVERRIDE/FM_STATE_OVERRIDE and pins a temp hermetic home; teardown reaps ONLY path-scoped children - processes whose command path lies inside the worktree or registered fixture temp dirs - never by bare script name, after leaked test watchers stole the primary home's watch lock); new regression suite tests/fm-supervision-test-isolation.test.sh owns that guarantee; several existing fixtures were pinned to explicit fixture homes for the same reason; fork-surface.conf gained a supervision-recovery-port capability claiming the new suites and repaired the glasses capability's commit reference to the landed squash merge 9f158d3 (previously an unresolvable pre-squash sha that failed every run); a fourth upstream commit f9b9d43 (durable re-arm recovery) was deliberately DEFERRED by captain decision after its recovery-marker state machine could not be made green against tests/fm-watch-triage.test.sh - it must NOT appear in this diff. Each ported commit passes shellcheck (bin/fm-lint.sh) and the behavior suite; the branch carries one extra hygiene commit for the manifest repair. Do not treat the skipped autoarm subsystem, the persistent-model mapping for claude, or the deferred fourth commit as omissions.

What Changed

  • Correct session-lock ownership across version-named harness executables and nested process ancestry.
  • Resolve attached watcher shutdowns through a PID-and-identity-bound delivery ledger, avoiding false failures after delivered wakes.
  • Require an identity-matched live watcher for supervision health, with reason-keyed outage banners and hermetic regression coverage.

Risk Assessment

✅ Low: Captain, the follow-up correctly fixes both teardown scope defects, and the complete branch diff now conforms to the required port adaptations without introducing another substantiated material risk.

Testing

Port-specific real-process CLI scenarios, the full watcher-lock regression, and the retained watch-triage boundary all passed with reviewer-visible transcripts; one peer-startup test flaked only under the initial combined load and passed on a clean full-suite rerun. No visual artifact was applicable because the change affects shell supervision and CLI output rather than UI.

Evidence: Port acceptance CLI transcript
FM_TEST_BEGIN 2026-08-24T04:04:29Z tests/fm-session-lock-ancestry.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - session-lock: a version-named Claude Code session is identified from its install path and argv[0]
ok - session-lock: ordinary script paths under a harness directory are not harness processes
ok - session-lock: ownership stops at the first non-harness gap above the contiguous run
ok - session-lock: a live version-named session holding the lock is not mistaken for a stale owner
ok - session-lock e2e: a version-named session claims the home under its own pid
ok - session-lock e2e: a daemon-parented session recognizes its own lock and keeps its record
ok - session-lock e2e: a version-named session under a harness-named daemon keeps its own lock
FM_TEST_END 2026-08-24T04:04:32Z tests/fm-session-lock-ancestry.test.sh exit=0 duration_ms=3340 gate_skip=false
FM_TEST_BEGIN 2026-08-24T04:04:32Z tests/fm-watch-arm.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - watch-arm: an attached arm reports the wake its cycle delivered instead of a false failure
ok - watch-arm: a delivered wake consumed by the handling turn still closes the attached arm cleanly
ok - watch-arm: a cycle that delivered no wake of its own still fails loudly
FM_TEST_END 2026-08-24T04:05:02Z tests/fm-watch-arm.test.sh exit=0 duration_ms=30015 gate_skip=false
FM_TEST_BEGIN 2026-08-24T04:05:02Z tests/fm-guard-stale-banner.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - fm-guard stale banner: first stale call prints the full actionable banner
ok - fm-guard stale banner: repeated same-episode calls print a concise reminder only
ok - fm-guard stale banner: auto-arm fresh beacon without a live watcher is healthy
ok - fm-guard stale banner: auto-arm stale beacon alarms with the true reason
ok - fm-guard stale banner: auto-arm stale episode stays one episode across calls
ok - fm-guard stale banner: persistent no-watcher banner names the true reason
ok - fm-guard stale banner: a no-watcher episode survives a beacon mtime change
ok - fm-guard stale banner: a fresh beacon without a live watcher remains unhealthy
ok - fm-guard stale banner: healthy recovery rearms the next stale episode
ok - fm-guard stale banner: concurrent same-episode calls claim exactly one full banner
ok - fm-guard stale banner: deduplication is isolated per FM_HOME
ok - fm-guard stale banner: queued-wake warning remains independent
ok - fm-guard stale banner: read-only before writable does not consume full banner
ok - fm-guard stale banner: read-only during episode observes without mutating marker
ok - fm-guard stale banner: healthy read-only does not clear marker
ok - fm-guard stale banner: read-only never mutates stale-banner state files
FM_TEST_END 2026-08-24T04:05:08Z tests/fm-guard-stale-banner.test.sh exit=0 duration_ms=6227 gate_skip=false
FM_TEST_BEGIN 2026-08-24T04:05:08Z tests/fm-supervision-test-isolation.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - isolation: sourcing tests/lib.sh drops every inherited operational-home variable
ok - isolation: a watcher with no overrides binds only the hermetic fixture home
ok - isolation: a restart cannot see or stop a foreign home's watcher
ok - isolation: teardown reaps only path-scoped children and never touches anything else
FM_TEST_END 2026-08-24T04:05:30Z tests/fm-supervision-test-isolation.test.sh exit=0 duration_ms=21567 gate_skip=false
Evidence: Watcher-lock clean rerun
FM_TEST_BEGIN 2026-08-24T04:16:47Z tests/fm-watcher-lock.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - simultaneous watcher starts leave exactly one live process
ok - fm_pid_identity real ps fallback is locale-invariant
ok - fm_pid_identity is locale-invariant across LC_ALL/LC_TIME
ok - /proc process identity ignores simulated btime changes
ok - /proc process identity detects pid reuse
ok - MSYS /proc process identity regression skipped on non-Windows host
ok - non-Windows watcher startup defaults remain byte-identical and Windows-only budgets stay gated
ok - killed watcher stale lock is reclaimed
ok - live watcher lock with stale heartbeat is actionable
ok - guard banner leads when down with pending wakes (repair-after-drain) and stays silent when live and fresh
ok - concurrent fm_lock_try_acquire yields exactly one winner
ok - dead-pid stale lock is reclaimed by a single acquirer
ok - concurrent stale-lock steal yields exactly one winner
ok - live steal mutex is not reclaimed
ok - live-held lock is not stolen
ok - empty mid-acquire lock keeps a minimum grace
ok - late original claimant cannot claim a recreated lock
ok - paused mid-acquire claimant backs off to active stealer
ok - abandoned steal mutex is reclaimed flatly without nesting
ok - preseeded steal.steal chain does not recurse or deepen
ok - owner death during contended acquire is reclaimed
ok - live pid slot is not stolen even with mismatched leftover identity
ok - concurrent abandoned-steal reclaim yields one winner without nesting
ok - watch restart refuses to signal a reused pid
ok - watch restart reports a healthy peer without attaching to it
ok - watcher self-evicts when the lock pid no longer names it
ok - arm turns clean self-eviction without a successor into a typed failure
ok - arm attaches to a live fresh watcher and fails loudly when that cycle has no successor
ok - attached arm signals record a classified lifecycle entry
ok - arm starts+confirms a fresh watcher on a clean lock and self-heals a dead-pid lock (never healthy off a dead pid)
ok - arm cleans child watcher and temp output on HUP
ok - arm propagates an immediate watcher wake before confirmation
ok - arm attaches to a peer watcher after child stands down and surfaces a missing successor
watcher: lock held by live pid 87720 but heartbeat is stale for 840863884s (>300s); inspect or stop that watcher before re-arming.
ok - arm reports FAILED and exits non-zero when no fresh watcher can be confirmed
ok - watcher and arm startup reclaim abandoned lock owner staging dirs and keep the ones still in use
/Users/larsmusic/.no-mistakes/worktrees/f569cc43ac96/01M0RYNV6F3WH4TQPVPQA1WF2T/bin/fm-watch-arm.sh: line 510: 89106 Terminated: 15          "$WATCH" > "$child_out"
ok - arm extends its confirmation window for a running migration sweep and names it instead of blaming the beacon
ok - arm preserves a bounded confirmation interval after a long migration sweep finishes
ok - arm recovers from an interrupted migration sweep without a confirmation timeout
ok - cycle-exit ledger links a verified successor and remains size-capped
ok - SIGSTOP distinguishes live PID from stale beacon and termination records the exit class
FM_TEST_END 2026-08-24T04:19:19Z tests/fm-watcher-lock.test.sh exit=0 duration_ms=151447 gate_skip=false
FM_TEST_SUMMARY total=1 failed=0 skipped_gate=0 duration_ms=151506
FM_TEST_SUMMARY_FAMILY family=watcher-wake-lock count=1 duration_ms=151447 failed=0
FM_TEST_SLOWEST rank=1 script=tests/fm-watcher-lock.test.sh duration_ms=151447
Evidence: Watch-triage deferred-boundary transcript
FM_TEST_BEGIN 2026-08-24T04:11:12Z tests/fm-watch-triage.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - signal_reason_is_actionable: benign absorbed, captain verbs and coalesced batches surfaced
ok - stale_is_terminal: terminal status surfaces, non-terminal and no-status are benign
ok - scan_captain_relevant_statuses lists only captain-relevant statuses
ok - classifier primitives: keyed decisions and activity phases, captain relevance, window-to-task, and overrides
ok - crew_is_provably_working: only working+run-step/pane is provable; idle/finished/parked/failed/unknown surface
ok - status_is_paused: only the leading paused verb matches, and paused is not captain-relevant
ok - status_pause_reason_key normalizes identical blockers and keeps distinct reasons apart
ok - status_pause_is_captain_gated matches captain-named waits only
ok - pause_resurface_secs_for_line uses the longer captain cadence only for captain-gated waits
ok - crew_absorb_class: working/paused/none from one read; crew_is_paused and crew_is_provably_working agree
ok - signal_crew_provably_working: benign only when every referenced crew is provably working
ok - a no-verb signal whose crew is provably working is absorbed (no exit, no queue, suppressor advanced, beacon present)
ok - a bare turn-end whose crew is provably working (busy pane) is absorbed
ok - a bare turn-end whose crew is not provably working is surfaced (the swallowed-finish fix)
ok - a no-verb working: note whose crew is idle with no running pipeline is surfaced
ok - captain-relevant signal is surfaced (queue + exit) and marked surfaced
ok - a stale pane sitting on a terminal status is surfaced (queue + exit)
ok - a stale terminal-looking status is overridden and absorbed while a run is actively working, then wedge-escalated
ok - provably-working non-terminal stale is absorbed on first sight, then wedge-escalated past the threshold
ok - consecutive wedge escalations on the same pane accumulate and demand deep inspection at the threshold
ok - a pane becoming active again resets the consecutive wedge-escalation counter
ok - Herdr stale triage distinguishes busy agent, healthy finished-idle agent, and gone bare shell without wedging the finish
ok - a not-provably-working non-terminal stale is surfaced immediately (never left to wait out the timer)
ok - a declared pause is absorbed on first sight, then re-surfaced as a recheck past the threshold, never wedge-escalated
ok - declared pauses that share one blocker re-surface as a single grouped recheck
ok - metas sharing one backend window re-surface as a single deduped recheck
ok - a trigger absent from the due set is still throttled after the grouped wake is durable
ok - the shared pause-due record and fold group by blocker and expose the throttles for a post-report commit
ok - pause_due_fold keeps empty notes and the gated flag on their own fields
ok - pause_due_fold counts distinct windows while exposing every throttle marker
grep: /var/folders/1g/hctp3vpn27b1zrlsn4nsfg680000gn/T//fm-watch-triage-tests.na7kwm/live-captain-held/state/.wake-queue: No such file or directory
grep: /var/folders/1g/hctp3vpn27b1zrlsn4nsfg680000gn/T//fm-watch-triage-tests.na7kwm/live-captain-held/state/.wake-queue: No such file or directory
grep: /var/folders/1g/hctp3vpn27b1zrlsn4nsfg680000gn/T//fm-watch-triage-tests.na7kwm/live-captain-held/state/.wake-queue: No such file or directory
ok - declared-wait policies: paused: is bounded, captain-held absorbs silently when healthy and surfaces a dead agent once
grep: /var/folders/1g/hctp3vpn27b1zrlsn4nsfg680000gn/T//fm-watch-triage-tests.na7kwm/away-surfaced-captain-held/state/.wake-queue: No such file or directory
ok - a dead-agent captain-held hold already surfaced in away mode absorbs in normal mode
ok - a re-opened captain-held hold is not suppressed by a one-shot marker of either namespace
ok - a busy pane cannot strand either one-shot after its hold resolves
ok - captain-held quiet-state is stream-truth: resolved: closes a key, open siblings and non-hold supersession behave
ok - a hold's closing resolved: line does not mask a preceding declared pause
ok - post-colon keyed lines stay under the default key and a keyless resolved: closes them
ok - an invalid post-colon key folds under default instead of dropping the decision
ok - after resolve emits its closing line the stopped crew surfaces normally again
ok - a trailing resolved: line for one hold does not retire a sibling still-open hold
ok - a malformed hold line gets normal stale handling instead of a silent absorb
ok - a declared paused secondmate re-surfaces on the bounded normal-mode cadence
ok - a non-paused secondmate retains normal stale suppression
ok - a confidently dead secondmate under a captain-held transfer surfaces once, never wedge-aged
ok - a resumed secondmate clears pause and stale tracking before stale exemption
ok - unchanged stale hashes reclassify when a crew enters or leaves pause
ok - a declared pause is periodically rechecked against authoritative active-run state
ok - a paused status overridden by authoritative working preserves its wedge timer and escalates
ok - matching non-terminal stale suppressors repair missing or corrupt stale-since timers
ok - triage log capping handles wc byte counts with leading spaces
ok - a heartbeat with no captain-relevant change is absorbed and backs off the cadence
ok - heartbeat backstop fail-safe surfaces a captain-relevant status the per-wake path missed
ok - the liveness beacon stays fresh while the watcher absorbs benign wakes (fm-guard never false-alarms)
ok - with .afk present the watcher reverts to one-shot so the daemon owns triage (no double-triage)
ok - AFK changed paused panes hand off plain stale identities for daemon-owned pause triage
FM_TEST_END 2026-08-24T04:16:28Z tests/fm-watch-triage.test.sh exit=0 duration_ms=315504 gate_skip=false
FM_TEST_SUMMARY total=1 failed=0 skipped_gate=0 duration_ms=315565
FM_TEST_SUMMARY_FAMILY family=watcher-wake-lock count=1 duration_ms=315504 failed=0
FM_TEST_SLOWEST rank=1 script=tests/fm-watch-triage.test.sh duration_ms=315504
- Outcome: ⚠️ 1 warning across 1 run (15m51s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • 🚨 tests/lib.sh:150 - The required guarantee says teardown reaps processes “whose command path lies inside the worktree,” but this pattern quotes *, making it literal; it also only matches commands beginning with the worktree path, while interpreted scripts typically appear as bash /worktree/bin/.... Consequently tracked watchers can survive teardown. Match the worktree path anywhere as a path component.
  • 🚨 tests/lib.sh:152 - The required guarantee says teardown reaps children in “registered fixture temp dirs,” but 121 suites call fm_test_tmproot through command substitution. Those array mutations occur in a subshell and never reach FM_TEST_CLEANUP_DIRS, so the new scope gate cannot recognize their fixture directories and leaked processes remain alive. Convert callers to the parent-shell FM_TEST_LAST_TMPROOT pattern or redesign registration to persist across command substitution.

🔧 Fix: Fix path-scoped test process cleanup
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 warning
  • ⚠️ tests/fm-watcher-lock.test.sh:993 - The combined run intermittently failed the peer-startup synchronization scenario with “arm child did not stand down behind the peer watcher” and then did not terminate promptly. A clean isolated rerun of the complete watcher-lock suite passed, including that exact scenario, classifying this as a load-sensitive flaky test rather than a reproducible product failure.
  • Inspected git diff --stat ef164dd6617cc5abbf7f6d1cfefd01d73c64915e..ecb5899896d7f0945533f89ae5073cd845f29c2b and the changed-file list.
  • Ran bin/fm-test-run.sh tests/fm-session-lock-ancestry.test.sh tests/fm-watch-arm.test.sh tests/fm-guard-stale-banner.test.sh tests/fm-supervision-test-isolation.test.sh tests/fm-watcher-lock.test.sh tests/fm-watch-triage.test.sh; the four port-specific suites passed before a load-sensitive watcher-lock failure, after which the non-terminating combined run was interrupted.
  • Ran bin/fm-test-run.sh tests/fm-watch-triage.test.sh; the complete retained triage behavior passed.
  • Ran bin/fm-test-run.sh tests/fm-watcher-lock.test.sh; the complete isolated rerun passed, including the previously failing peer-startup scenario.
  • Searched the target diff with rg -n 'f9b9d43|recovery-marker|Claude Stop|autoarm' to verify no deferred recovery-marker implementation or Claude Stop subsystem was introduced; matches were limited to model support/tests and explanatory comments.
  • Checked git status --short after testing; the working tree remained clean.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…ash merge

The glasses-file-event-wake entry still named pre-squash branch commit
74d836d, which no longer resolves anywhere in this clone or on origin,
so the fork-surface check failed for every session. PR #97 landed as
9f158d3; record the same post-merge repair the bridge capability above
documents.

Upstream: none (fork-manifest hygiene, not a port)
…henguid#1545)

Port upstream 88b2a94 onto this fork's diverged supervision code, adapting
rather than overwriting.

Fault 1, session-lock identity and ownership. Upstream rewrote its
bin/fm-session-lock-lib.sh; this fork never had that file, so the same
semantics land in this fork's owners instead. bin/fm-primary-scope-lib.sh
gains whole-path-component and argv[0] harness evidence
(fm_harness_path_name, fm_harness_process_matches), a contiguous
verified-harness ancestry walk (fm_harness_ancestry_pids), membership
ownership (fm_harness_ancestry_contains), the outermost-of-run resolver
(fm_harness_ancestry_pid), and a relation whose ancestry answer is
membership rather than one chosen pid. bin/fm-lock.sh resolves
harness_pid through that shared owner and now recognizes a live lock held
inside this session's own ancestry as its own earlier acquisition,
keeping the recorded owner instead of refusing or rewriting it.

Fault 2, attached arms reporting delivered cycles as failures. The
watcher publishes each printed reason to state/.watch-deliveries.log
bound to its PID and process identity before releasing the singleton
(bin/fm-watch.sh wake + bin/fm-wake-lib.sh, which owns the ledger once
for watcher and arm), fm_watcher_healthy returns the matched identity,
and bin/fm-watch-arm.sh tracks cycle identity and resolves an
unobservable close against the delivery record: a matching record
reports the delivered wake and exits zero, only a cycle that delivered
nothing stays the typed nonzero failure. Covers started-child and
attached closes on every harness protocol.

Fork-preserving adaptations:
- FM_HARNESS_RE keeps this fork's verified set (no pi-signed); loose
  holder-liveness survives as a boundary-checked argv-token tier so
  profile launchers named codex-primary still read as live holders while
  ordinary ~/.claude/hooks paths do not.
- The ancestry walk keeps the fork's eight-parent budget, preserving
  documented parity with Pi's lockOwnership().
- docs/verification/supervision.md hunks skipped: this fork has no such
  file.
- Upstream's e2e drove bin/fm-claude-stop-autoarm.sh, absent here; the
  end-to-end layer targets this fork's real bin/fm-lock.sh in orphaned
  version-named, daemon-parented, and combined process trees instead.
- Hermeticity hardening for every supervision suite (incident-driven):
  tests/lib.sh drops inherited operational-home variables and pins a
  temp hermetic FM_HOME, teardown reaps only path-scoped children, and
  new tests/fm-supervision-test-isolation.test.sh proves a test watcher
  or --restart can never resolve or stop a real home.
- tests/fm-test-run.sh registers the three suites in watcher-wake-lock
  and serial shard 2; fixture homes pinned explicitly in the affected
  suites per the hermeticity contract.

Full bin/fm-test-run.sh --all passes at this tree (140 scripts, 0
failed); shellcheck clean via bin/fm-lint.sh on every touched script.

Upstream: 88b2a94
…unchenguid#1495)

Port the transferable core of upstream 33a4287: every supervision
consumer now decides alarm state with the same identity-matched
live-watcher and fresh-beacon predicate, so a dead or reused watcher pid
with a leftover beacon can no longer read as healthy.

bin/fm-guard.sh drops its beacon-fresh-only field and calls
fm_watcher_healthy (bin/fm-wake-lib.sh) - the predicate the arm wrapper
and turn-end guard already use. bin/fm-supervision-lib.sh's docstring
records that split: banner text from the status fields, decisions from
the shared predicate.

Skipped as inapplicable to this fork, which has no Claude Stop auto-arm
and no --claude guard mode:
- bin/fm-claude-stop-autoarm.sh failure episodes, bounded retries,
  one-time attended fail-open, and post-alarm suppression;
- lock role records (fm_lock_set_role/fm_lock_role) and
  fm_failure_episode_reset, whose only consumers are that subsystem;
- the Claude repair-line rewording, X-mode-as-need source, and
  procevent sources, which would misdocument this fork's different
  continuity model.

Regression coverage ports upstream's: a fresh beacon without a live
watcher stays an alarm; healthy-recovery cases record genuinely live
identity-matched holders instead of touching only the beacon; drain
liveness asserts the same; secondmate config-push fixtures pin live
watchers where they assert silent stderr. fork-surface.conf claims the
ported surface as the supervision-recovery-port capability.

Upstream: 33a4287
…unchenguid#1661)

Port the transferable core of upstream d0461e4: the pull guard's health
verdict becomes model-aware and its banner names the real failing
condition instead of always blaming the beacon.

bin/fm-wake-lib.sh gains fm_supervision_model and
fm_watcher_supervision_verdict. Under a between-turns arm-owner model
(FM_SUPERVISION_MODEL=autoarm) a fresh beacon with no live watcher is
healthy mid-turn and only a stale beacon alarms; under persistent models
a live identity-matched watcher with a fresh beacon is still required.
This fork maps every detected harness - Claude included - to the
persistent model, because its Claude continuity runs tracked background
arms rather than a Stop-hook auto-arm; the override keeps the model
branch exercised and upstream-shaped.

bin/fm-guard.sh consumes the verdict: the once-per-episode dedup keys on
the failing condition instead of the beacon mtime (which any beacon
touch used to churn into a fresh episode), and the banner now says
whether the home lacks a live watcher process or a genuinely fresh
beacon. The turn-end guard keeps the PID-strict predicate unchanged,
as does the arm layer.

Skipped as inapplicable: upstream's spawn-time FM_SUPERVISION_MODEL
injection for secondmates (this fork launches every harness under the
persistent default), the autoarm/claude-protocol doc rewrites, and the
procevent/X-mode need sources this fork's guard has never had.
docs/scripts.md rows for the guard and drain reflect the supervision-
health wording.

Upstream: d0461e4
@Amplify-Logic
Amplify-Logic merged commit 2ce90a4 into main Aug 24, 2026
12 of 13 checks passed
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