How the Away-Mode (/afk) Sub‑Supervisor Functions in Firstmate
The away‑mode sub‑supervisor is a presence‑gated bash daemon that temporarily replaces the standard fm-watch.sh watcher to buffer captain‑relevant escalations while the user is away, flushing periodic digests and shutting down gracefully upon detecting a non‑injection message.
Firstmate’s /afk command triggers a sophisticated sub‑supervisor architecture designed to minimize token consumption while preventing information loss. Implemented entirely in portable bash within the kunchenguid/firstmate repository, this system combines three tightly‑coupled components—bin/fm-afk-start.sh, bin/fm-supervise-daemon.sh, and bin/fm-operational-input.sh—to create a durable, state‑driven presence gate. The implementation relies on atomic flag files and lock‑based singleton guarantees to ensure only one daemon instance operates at any given time.
Entering Away‑Mode via fm-afk-start.sh
When the captain invokes /afk, the entry point script bin/fm-afk-start.sh performs atomic state initialization. It writes the durable flag file state/.afk using the helper fm_afk_flag_write, clears any stale escalation artifacts via fm_afk_clear_stale_artifacts, and handles the daemon launch sequence.
The script distinguishes between foreground‑capable environments and background‑only backends. In standard configurations, it executes fm-supervise-daemon.sh directly via exec, replacing the shell process. For backends lacking native foreground tracking, it delegates to a detached terminal wrapper.
# bin/fm-afk-start.sh – atomic flag write and daemon exec
fm_afk_flag_write "$FM_AFK_STATE" || {
echo "afk: failed to write away-mode flag" >&2;
return 1;
}
...
exec "$FM_AFK_DAEMON"
Upon launch, the daemon acquires an exclusive lock at state/.supervise-daemon.lock, ensuring singleton enforcement across the Firstmate session.
Presence Gating in fm-supervise-daemon.sh
The daemon implements presence gating through the afk_active helper function. Every operational loop begins with this check, which simply tests for the existence of state/.afk:
# bin/fm-supervise-daemon.sh – presence validation
afk_active() { [ -e "$1/$AFK_FLAG_NAME" ]; }
If the captain removes the flag (implicitly, by sending a non‑injection message), the daemon detects the absence during its next iteration and initiates graceful shutdown, flushing any pending escalation buffers before exiting. This state‑driven approach eliminates the need for process signals or complex IPC mechanisms.
Wake Classification and Escalation Buffering
While active, the daemon reuses the shared classification library bin/fm-classify-lib.sh to evaluate every durable wake event. The classifier returns structured strings in the format <action>|<distilled>, distinguishing between routine self‑handle events and escalate events requiring captain attention.
Classification examples include:
- Self‑handle: Heartbeat signals and routine status updates that require no intervention
- Escalate: Terminal states like
done,needs‑decision, orblocked
When an event requires escalation, the daemon appends it to state/.subsuper-escalations via escalate_add. Rather than injecting immediately, the implementation batches items and periodically flushes a single‑line digest via escalate_flush, significantly reducing supervisor pane noise.
The Housekeeping Loop
The daemon runs a perpetual housekeeping cycle configured by FM_HOUSEKEEPING_TICK, performing several maintenance operations:
| Job | Function | Purpose |
|---|---|---|
| Batch Flush | escalate_flush |
Injects digests when buffered items exceed FM_ESCALATE_BATCH_SECS |
| Max‑Defer Escape | Retry logic | Retries injection after FM_MAX_DEFER_SECS; raises wedge alarm on failure |
| Stale Re‑check | stale_window_is_busy |
Verifies idle panes marked in state/.subsuper-stale-* files older than FM_STALE_ESCALATE_SECS |
| Pause Re‑surface | Pause validation | Re‑checks external pauses in state/.subsuper-paused-* files older than FM_PAUSE_RESURFACE_SECS |
| Heartbeat Scan | scan_captain_relevant_statuses |
Greps all *.status files every FM_HEARTBEAT_SCAN_SECS for missed relevant lines |
This comprehensive sweep ensures no captain‑relevant event remains undetected, even when the primary wake classifier misses edge cases during high‑frequency updates.
Exiting Away‑Mode
Return detection occurs in bin/fm-operational-input.sh through the should_exit_afk function. The logic defines away‑mode exit conditions as any message that:
- Does not start with the internal injection marker (
FM_INJECT_MARKor the Unicode prefixU+2063 FIRSTMATE_OP) - Is not the
/afkcommand itself
should_exit_afk() {
afk_active "$state" || return 1
message_is_injection "$msg" && return 1
case "$msg" in /afk*) return 1 ;; esac
return 0
}
When these conditions are met, the primary Firstmate instance invokes afk_exit, which removes state/.afk. The daemon detects the missing flag during its next afk_active check and terminates, yielding control back to the standard fm-watch.sh watcher.
Wedge Alarm Handling
To prevent silent failure when the supervisor pane becomes unresponsive, the daemon implements wedge detection. If escalate_flush repeatedly fails to inject digests beyond FM_MAX_DEFER_SECS, the system writes a durable marker to state/.subsuper-inject-wedged and invokes inject_wedge_alarm:
inject_wedge_alarm() {
# ... marker creation ...
wedge_alarm_notify "away-mode escalations WEDGED …" "$marker";
}
This fallback mechanism fires OS‑level or Herdr notifications, guaranteeing that critical escalations reach the captain even when the primary injection pathway is compromised.
Summary
- Atomic Entry:
fm-afk-start.shwritesstate/.afkand execs the daemon with singleton locking viastate/.supervise-daemon.lock. - Presence Gating: The daemon uses
afk_activeto monitorstate/.afk, shutting down gracefully when the flag disappears. - Smart Buffering: Captain‑relevant wakes are classified via
fm-classify-lib.shand batched instate/.subsuper-escalationsbefore digest injection. - Continuous Maintenance: The
housekeepingloop performs stale‑window re‑checks, pause re‑surfaces, and heartbeat scans on configurable intervals. - Reliable Exit: Normal messages trigger
should_exit_afk, causing flag removal and daemon termination. - Failure Safety: Wedge alarms via
inject_wedge_alarmensure no escalations are lost during supervisor pane outages.
Frequently Asked Questions
What triggers the away‑mode sub‑supervisor to start?
The /afk command triggers bin/fm-afk-start.sh, which atomically writes the state/.afk flag file and executes bin/fm-supervise-daemon.sh. The daemon acquires an exclusive lock at state/.supervise-daemon.lock to prevent duplicate instances.
How does the daemon know when to shut down?
The daemon polls for the existence of state/.afk using the afk_active function. When the captain sends any message lacking the internal injection prefix (FM_INJECT_MARK or U+2063 FIRSTMATE_OP), the primary Firstmate process removes the flag file. The daemon detects this absence during its next housekeeping tick and exits gracefully after flushing buffers.
What happens if the supervisor pane freezes while the daemon is running?
If the daemon cannot inject escalation digests for longer than FM_MAX_DEFER_SECS, it writes a marker to state/.subsuper-inject-wedged and calls inject_wedge_alarm. This fires alternative notifications (OS‑level or Herdr) to alert the captain that away‑mode escalations are wedged, ensuring no events are silently dropped.
How are events classified during away‑mode?
The daemon imports bin/fm-classify-lib.sh to evaluate wakes. Each event returns an action string like escalate|<distilled> or self-handle. Escalations are buffered in state/.subsuper-escalations and flushed as single‑line digests, while routine heartbeats are suppressed to conserve tokens.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →