feat(bootstrap): surface fleet daemon health alerts at cold start#214
Open
e-jung wants to merge 4 commits into
Open
feat(bootstrap): surface fleet daemon health alerts at cold start#214e-jung wants to merge 4 commits into
e-jung wants to merge 4 commits into
Conversation
The bootstrap health gate (the cold-start counterpart of fm-guard.sh) was a local-only feature lost when local main was reset to origin/main. Re-apply it adapted to the current code structure: the gate runs last, after every mutating sweep, and surfaces one ALERT line per live fleet-health problem while keeping bootstrap exit 0 (warn, never block). Four checks, each degrading silently where its detection mechanism is unavailable so a non-Linux or stripped host skips the systemd-based paths: 1. afk on but the away-mode daemon dark (systemd is-active, pidfile fallback) 2. watcher beacon stale with tasks in flight (mirrors fm-guard.sh) 3. crash-looping no-mistakes daemon units (high NRestarts, threshold 50) 4. duplicate no-mistakes daemons serving one --root (stale-cache push risk) Add the portable _bootstrap_stat_mtime helper mirroring fm-guard.sh, run the gate even in detect-only mode since it mutates nothing, and document the new ALERT line type. fm-daemon-systemd.sh is optional: where absent its is-active fails and check (1) degrades to the pidfile path. Cover with three behavior tests: silent on a healthy fleet, afk-daemon-dark ALERT (plus silent nm degradation), and stale-watcher-beacon ALERT.
…art host-node test fragility
a8272fa to
e94de52
Compare
4 tasks
Owner
|
Thanks for the PR! It looks like this branch has a merge conflict with the base branch right now. When you get a chance, could you rebase onto (or merge in) the latest base branch, resolve the conflict, and push? Once GitHub shows the PR as mergeable again, it'll be picked back up for review. Noted for firstmate#214 at |
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
Re-apply the lost bootstrap fleet daemon health gate so cold-start bootstrap surfaces ALERT lines for afk-on-but-daemon-dark, stale watcher beacon with tasks in flight, crash-looping no-mistakes daemon units, and duplicate no-mistakes daemons on one root; warn never block, degrade silently where detection is unavailable.
What Changed
bin/fm-bootstrap.shthat runs at the end of every cold start and surfaces oneALERT:line per live fleet-health problem: afk-on-but-away-mode-daemon-dark, stale watcher beacon with tasks in flight, crash-loopingno-mistakesdaemon units (NRestarts ≥ 50), and duplicateno-mistakesdaemons serving one--root; each check degrades silently where its detection mechanism is unavailable (non-Linux or stripped host) and bootstrap stays exit 0.fm-daemon-systemd.shprimary command.ALERT:line type acrossAGENTS.md,docs/configuration.md, anddocs/scripts.md.Risk Assessment
✅ Low: The incremental change is a small, correct simplification: it removes dead guidance (a call to a non-existent script) and aligns the afk-dark ALERT with the actual pidfile-based liveness mechanism and recovery command, introducing no new behavior or risk.
Testing
Exercised the new bootstrap health gate both through its dedicated test suite (all pass) and through direct end-to-end drives of the real bin/fm-bootstrap.sh against realistic state/ setups, capturing the exact ALERT lines a captain would see at cold start for all four failure modes (afk-dark, stale watcher beacon, crash-looping nm unit, duplicate-root nm daemons) plus the silent-degradation, live-pidfile-no-false-alarm, detect-only, threshold-override, and exit-0-warn-never-block contracts; every behavior matches the user intent and the worktree is clean.
Evidence: Health-gate end-to-end transcript (all 4 ALERTs + silent degradation)
(0) HEALTHY fleet -> health gate emits nothing >>> ALERT lines: <none - correct, healthy fleet is silent> (1) AFK on but away-mode daemon DARK (dead pidfile) -> ALERT ALERT: afk is on but the away-mode daemon is not running - escalations are dark; re-enter /afk or run: nohup bin/fm-supervise-daemon.sh >/dev/null 2>&1 & >>> nm crash-loop ALERT leaked despite no systemd? no - silent degradation correct (2) WATCHER beacon stale (>300s) WITH a task in flight -> ALERT ALERT: watcher beacon is 1783052466s stale (grace 300s) with 1 task(s) in flight - supervision is off; re-arm: bin/fm-watch-arm.sh as a harness-tracked background task (3) no-mistakes daemon unit CRASH-LOOPING (NRestarts>=50) -> ALERT ALERT: no-mistakes daemon unit(s) crash-looping (high NRestarts): no-mistakes-daemon-acme.service(127) - investigate/reset: systemctl --user stop '<unit>' && systemctl --user reset-failed '<unit>' (4) MULTIPLE no-mistakes daemons serve one --root (stale-cache risk) -> ALERT ALERT: multiple no-mistakes daemons serve root '/srv/acme' (stale-cache push risk) - reconcile: keep the systemd-managed one, kill the stray nohup processes (5) STRIPPED host (no systemctl, no pgrep, healthy state) -> no spurious nm ALERT <no ALERT lines - detection degrades silently, correct>Evidence: Evidence script driving the real fm-bootstrap.sh health gate
Evidence: warn-never-block contract: bootstrap exits 0 while emitting an ALERT
Evidence: real pidfile mechanism: live PID $$ => no false afk-dark ALERT
Evidence: threshold override: NRestarts=40 silent at default 50, alerts at FM_NM_CRASH_THRESHOLD=40
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed ✅
bin/fm-bootstrap.sh:211- The afk-daemon-dark ALERT recommends the primary fixbin/fm-daemon-systemd.sh start, but that script does not exist anywhere in the repo (confirmed: onlybin/fm-supervise-daemon.shexists, and the afk skill itself starts the daemon withnohup bin/fm-supervise-daemon.sh &). Sincefm-daemon-systemd.shis absent, theis-activeprobe at line 208 always fails and the check always degrades to the pidfile path, so the message's primary command is dead guidance. The captain would run a non-existent command before reaching the working fallback in parentheses.bin/fm-bootstrap.sh:224- Check (2) only emits the stale-beacon ALERT when.last-watcher-beatEXISTS and is older than grace: the guard[ -e "$STATE/.last-watcher-beat" ]skips the whole block when the file is absent. This contradicts the check's own comment ('stale or missing with tasks in flight means supervision is off') andbin/fm-guard.sh, which treats a missing beacon asneverand banners on it. The dangerous cold-start state (tasks in flight, watcher never armed / beacon never written) therefore produces no ALERT here, the precise recovery gap this gate was meant to mirror.bin/fm-bootstrap.sh:264- Checks (3) and (4) depend on external contracts that cannot be verified from this repo: the systemd unit prefixno-mistakes-daemon-*(line 254) and the process cmdline shapeno-mistakes daemon run --root <path>with a space (not--root=) at line 264. The added tests only exercise the silent-degradation path (failing fake systemctl), never a positive ALERT, so a mismatched pattern/naming would leave both checks silently dead with no test catching it. This is by-design graceful degradation for a warn-never-block gate, but worth awareness given the patterns are unverified against the actual no-mistakes CLI.🔧 Fix: fix afk-dark alert to use real pidfile mechanism
✅ Re-checked - no issues remain.
🔧 **Test** - 1 issue found → auto-fixed ✅
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"🔧 Fix: fix herdr jq label-keyword conflict and session-start host-node test fragility
✅ Re-checked - no issues remain.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"bash tests/fm-bootstrap.test.sh(incl. the 3 new health-gate cases: silent-when-healthy, afk-daemon-dark, watcher-stale)bash tests/fm-tangle-guard.test.shbash tests/fm-session-start.test.sh(composes the real bootstrap)bash tests/fm-daemon.test.shbash tests/fm-fleet-sync.test.shmanual e2e via realbin/fm-bootstrap.sh: healthy fleet -> no ALERTmanual e2e:.afkset + dead pidfile (999999) -> afk-dark ALERT; confirmed nm checks stay silent without systemdmanual e2e: stale.last-watcher-beat(epoch 1) + one*.metain flight -> watcher-stale ALERTmanual e2e: fakesystemctlreporting NRestarts=127 -> crash-loop ALERT; NRestarts=40 silent at default 50manual e2e: fakepgrepreporting two daemons on same--root-> duplicate-root ALERTmanual e2e:FM_NM_CRASH_THRESHOLD=40flips NRestarts=40 from silent to ALERT (threshold override)manual e2e:.afkset + pidfile pointing at live PID ($$) -> no false afk-dark ALERT (real pidfile mechanism)manual e2e:FM_BOOTSTRAP_DETECT_ONLY=1still runs the health gate; bootstrap exit code verified 0 even when ALERTs present (warn-never-block)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.