Skip to content

feat(bootstrap): surface fleet daemon health alerts at cold start#214

Open
e-jung wants to merge 4 commits into
kunchenguid:mainfrom
e-jung:fm/fm-bootstrap-gate-q1
Open

feat(bootstrap): surface fleet daemon health alerts at cold start#214
e-jung wants to merge 4 commits into
kunchenguid:mainfrom
e-jung:fm/fm-bootstrap-gate-q1

Conversation

@e-jung

@e-jung e-jung commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

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

  • Adds a warn-never-block health gate to bin/fm-bootstrap.sh that runs at the end of every cold start and surfaces one ALERT: line per live fleet-health problem: afk-on-but-away-mode-daemon-dark, stale watcher beacon with tasks in flight, crash-looping no-mistakes daemon units (NRestarts ≥ 50), and duplicate no-mistakes daemons serving one --root; each check degrades silently where its detection mechanism is unavailable (non-Linux or stripped host) and bootstrap stays exit 0.
  • Fixes the afk-dark alert to use the real away-mode pidfile mechanism instead of the non-existent fm-daemon-systemd.sh primary command.
  • Fixes a herdr jq label-keyword conflict and session-start host-node test fragility, and documents the new ALERT: line type across AGENTS.md, docs/configuration.md, and docs/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>


========================================
(0) HEALTHY fleet -> health gate emits nothing
========================================
    | MISSING: tasks-axi (install: npm install -g tasks-axi)

>>> 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>

DONE.
Evidence: Evidence script driving the real fm-bootstrap.sh health gate
#!/usr/bin/env bash
# End-to-end evidence: exercise the REAL bin/fm-bootstrap.sh fleet daemon
# health gate across every documented scenario and capture the exact ALERT
# lines a captain would see at cold start. Uses the project's own test harness
# (tests/lib.sh) to build a fake-but-valid toolchain, then drives the real
# bootstrap script against realistic state/ setups.
set -u

ROOT="$(cd "$(dirname "$0")/../../.no-mistakes/worktrees/507cc8072d97/01KWJZFFSV9Y6B7J6475QNPAV8" 2>/dev/null && pwd || pwd)"
ROOT="$(cd "$(dirname "$0")" && pwd)"
# Resolve to the actual firstmate repo root hosting the change under test.
for cand in \
  "/home/ubuntu/.no-mistakes/worktrees/507cc8072d97/01KWJZFFSV9Y6B7J6475QNPAV8"; do
  [ -f "$cand/bin/fm-bootstrap.sh" ] && ROOT="$cand" && break
done

# shellcheck source=/dev/null
. "$ROOT/tests/lib.sh"

BASE_PATH=${FM_TEST_BASE_PATH:-/usr/bin:/bin:/usr/sbin:/sbin}
TMP_ROOT=$(fm_test_tmproot health-gate-demo)

build_toolchain() {
  local fakebin
  fakebin=$(fm_fakebin "$1")
  fm_fake_exit0 "$fakebin" tmux node gh-axi chrome-devtools-axi lavish-axi
  cat > "$fakebin/gh" <<'SH'
#!/usr/bin/env bash
exit 0
SH
  chmod +x "$fakebin/gh"
  cat > "$fakebin/treehouse" <<'SH'
#!/usr/bin/env bash
if [ "${1:-}" = get ] && [ "${2:-}" = --help ]; then
  printf '%s\n' 'Usage: treehouse get [--lease] [--lease-holder <holder>]'
fi
exit 0
SH
  chmod +x "$fakebin/treehouse"
  cat > "$fakebin/no-mistakes" <<'SH'
#!/usr/bin/env bash
if [ "${1:-}" = --version ]; then
  printf '%s\n' 'no-mistakes version v1.31.2 (fake) 2026-06-27T00:02:18Z'
fi
exit 0
SH
  chmod +x "$fakebin/no-mistakes"
  printf '%s\n' "$fakebin"
}

# A failing systemctl (no systemd --user) models a non-Linux / stripped host.
add_failing_systemctl() {
  local fakebin=$1
  printf '#!/usr/bin/env bash\nexit 1\n' > "$fakebin/systemctl"
  chmod +x "$fakebin/systemctl"
}

make_home() {
  mkdir -p "$1/home/state" "$1/home/projects"
}

run_bootstrap() {
  # Suppress the noisy tool-detection preamble by pinning every tool; only the
  # health-gate ALERT lines (and the harmless non-git "fatal" from fleet sync
  # against the empty fake home) reach the transcript.
  PATH="$1:$BASE_PATH" FM_HOME="$2/home" FM_ROOT_OVERRIDE="$2/home" \
    FM_FAKE_TREEHOUSE_LEASE_HELP=1 "$ROOT/bin/fm-bootstrap.sh" 2>/dev/null
}

header() { printf '\n========================================\n%s\n========================================\n' "$1"; }

# --- (0) healthy fleet: gate MUST be silent --------------------------------
header "(0) HEALTHY fleet -> health gate emits nothing"
c="$TMP_ROOT/healthy"; make_home "$c"
fb=$(build_toolchain "$c"); add_failing_systemctl "$fb"
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "$out" | sed 's/^/    | /'
printf '\n>>> ALERT lines: %s\n' "${alerts:-<none - correct, healthy fleet is silent>}"

# --- (1) afk on but daemon dark (dead pid) ---------------------------------
header "(1) AFK on but away-mode daemon DARK (dead pidfile) -> ALERT"
c="$TMP_ROOT/afk-dark"; make_home "$c"
fb=$(build_toolchain "$c"); add_failing_systemctl "$fb"
: > "$c/home/state/.afk"
echo 999999 > "$c/home/state/.supervise-daemon.pid"   # a PID nobody owns
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "$alerts" | sed 's/^/    | /'
printf '\n>>> nm crash-loop ALERT leaked despite no systemd? %s\n' \
  "$(printf '%s\n' "$out" | grep -q 'no-mistakes daemon unit' && echo YES-BAD || echo 'no - silent degradation correct')"

# --- (2) watcher beacon stale with work in flight --------------------------
header "(2) WATCHER beacon stale (>300s) WITH a task in flight -> ALERT"
c="$TMP_ROOT/stale-beacon"; make_home "$c"
fb=$(build_toolchain "$c"); add_failing_systemctl "$fb"
echo "window=firstmate:fm-demo" > "$c/home/state/demo.meta"
touch "$c/home/state/.last-watcher-beat"
touch -d @1 "$c/home/state/.last-watcher-beat"   # epoch 1 -> far past 300s grace
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "$alerts" | sed 's/^/    | /'

# --- (3) crash-looping no-mistakes daemon unit (high NRestarts) ------------
header "(3) no-mistakes daemon unit CRASH-LOOPING (NRestarts>=50) -> ALERT"
c="$TMP_ROOT/crash-loop"; make_home "$c"
fb=$(build_toolchain "$c")
# A fake systemctl that advertises a flapping nm unit with 127 restarts and a
# healthy show-environment (so the systemd --user gate stays open).
cat > "$fb/systemctl" <<'SH'
#!/usr/bin/env bash
# `systemctl --user show-environment` succeeds -> systemd --user is available.
if [ "${1:-}" = --user ] && [ "${2:-}" = show-environment ]; then exit 0; fi
# `systemctl --user show -p NRestarts --value <unit>` -> report 127 restarts.
if [ "${1:-}" = --user ] && [ "${2:-}" = show ]; then
  printf '%s\n' "127"; exit 0
fi
# `systemctl --user list-units ...` -> advertise one flapping nm unit.
if [ "${1:-}" = --user ] && [ "${2:-}" = list-units ]; then
  printf '%s\n' "no-mistakes-daemon-acme.service loaded active running nm daemon for acme"
fi
exit 0
SH
chmod +x "$fb/systemctl"
# Fake pgrep finds NO duplicate -> the dup check stays silent; isolates (3).
cat > "$fb/pgrep" <<'SH'
#!/usr/bin/env bash
exit 1
SH
chmod +x "$fb/pgrep"
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "$alerts" | sed 's/^/    | /'

# --- (4) duplicate no-mistakes daemons serving one --root ------------------
header "(4) MULTIPLE no-mistakes daemons serve one --root (stale-cache risk) -> ALERT"
c="$TMP_ROOT/dup-root"; make_home "$c"
fb=$(build_toolchain "$c")
cat > "$fb/systemctl" <<'SH'
#!/usr/bin/env bash
[ "${1:-}" = --user ] && [ "${2:-}" = show-environment ] && exit 0
[ "${1:-}" = --user ] && [ "${2:-}" = list-units ] && { printf '\n'; exit 0; }
exit 0
SH
chmod +x "$fb/systemctl"
# Fake pgrep reports two daemons serving the SAME root -> a duplicate.
cat > "$fb/pgrep" <<'SH'
#!/usr/bin/env bash
if [ "${1:-}" = -af ]; then
  printf '%s\n' "4112 no-mistakes daemon run --root /srv/acme"
  printf '%s\n' "4233 no-mistakes daemon run --root /srv/acme"
  exit 0
fi
exit 1
SH
chmod +x "$fb/pgrep"
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "$alerts" | sed 's/^/    | /'

# --- (5) silent degradation: no systemctl, no pgrep at all -----------------
header "(5) STRIPPED host (no systemctl, no pgrep, healthy state) -> no spurious nm ALERT"
c="$TMP_ROOT/stripped"; make_home "$c"
fb=$(build_toolchain "$c")
add_failing_systemctl "$fb"
out=$(run_bootstrap "$fb" "$c")
alerts=$(printf '%s\n' "$out" | grep '^ALERT:' || true)
printf '%s\n' "${alerts:-<no ALERT lines - detection degrades silently, correct>}" | sed 's/^/    | /'

printf '\nDONE.\n'
Evidence: warn-never-block contract: bootstrap exits 0 while emitting an ALERT
bootstrap exit code = 0
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 &
Evidence: real pidfile mechanism: live PID $$ => no false afk-dark ALERT
afk on, pidfile -> live PID $$ (3846685): bootstrap exit=0
(none - correct: live pidfile => no false afk-dark ALERT)
Evidence: threshold override: NRestarts=40 silent at default 50, alerts at FM_NM_CRASH_THRESHOLD=40
(B) NRestarts=40 at default threshold 50: <none>
(B) NRestarts=40 with FM_NM_CRASH_THRESHOLD=40: ALERT: no-mistakes daemon unit(s) crash-looping (high NRestarts): no-mistakes-daemon-x.service(40) - investigate/reset: systemctl --user stop '<unit>' && systemctl --user reset-failed '<unit>'
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (42m29s)

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 fix bin/fm-daemon-systemd.sh start, but that script does not exist anywhere in the repo (confirmed: only bin/fm-supervise-daemon.sh exists, and the afk skill itself starts the daemon with nohup bin/fm-supervise-daemon.sh &amp;). Since fm-daemon-systemd.sh is absent, the is-active probe 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-beat EXISTS and is older than grace: the guard [ -e &#34;$STATE/.last-watcher-beat&#34; ] 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') and bin/fm-guard.sh, which treats a missing beacon as never and 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 prefix no-mistakes-daemon-* (line 254) and the process cmdline shape no-mistakes daemon run --root &lt;path&gt; 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 ✅
  • 🚨 tests failed with exit code 1
  • 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.sh
  • bash tests/fm-session-start.test.sh (composes the real bootstrap)
  • bash tests/fm-daemon.test.sh
  • bash tests/fm-fleet-sync.test.sh
  • manual e2e via real bin/fm-bootstrap.sh: healthy fleet -> no ALERT
  • manual e2e: .afk set + dead pidfile (999999) -> afk-dark ALERT; confirmed nm checks stay silent without systemd
  • manual e2e: stale .last-watcher-beat (epoch 1) + one *.meta in flight -> watcher-stale ALERT
  • manual e2e: fake systemctl reporting NRestarts=127 -> crash-loop ALERT; NRestarts=40 silent at default 50
  • manual e2e: fake pgrep reporting two daemons on same --root -> duplicate-root ALERT
  • manual e2e: FM_NM_CRASH_THRESHOLD=40 flips NRestarts=40 from silent to ALERT (threshold override)
  • manual e2e: .afk set + pidfile pointing at live PID ($$) -> no false afk-dark ALERT (real pidfile mechanism)
  • manual e2e: FM_BOOTSTRAP_DETECT_ONLY=1 still 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.

e-jung added 4 commits July 3, 2026 05:11
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.
@kunchenguid

Copy link
Copy Markdown
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 e94de525.

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.

3 participants