--- name: muster description: Machine-wide loop muster — enumerate every registered loop with health, ownership, and staleness. Renamed from 'status' to avoid. allowed-tools: Bash, Read argument-hint: "[--json | --reclaim-candidates | ]" disable-model-invocation: false --- # autoloop: Muster (Fleet Roster) Enumerates all registered loops on the machine and reports health, dead-time ratio, staleness, and reclaim candidacy. Works as a table view for human inspection or JSONL for machine consumers. > **Self-Evolving Skill**: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues. ## Arguments - No arguments: show all loops as an ASCII table (default) - `--json`: emit JSONL (one loop per line) for machine consumers - `--reclaim-candidates`: filter table to only loops flagged for reclaim - ``: show single loop in detail (preserves Phase 8 behavior as fallback) ## Implementation ### Step 1: Load libraries ```bash PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" source "$PLUGIN_DIR/scripts/muster-lib.sh" || { echo "ERROR: Cannot load muster-lib.sh" >&2 exit 1 } ``` ### Step 2: Parse arguments ```bash case "${1:-}" in --json) enumerate_loops | cat # Raw JSONL output exit 0 ;; --reclaim-candidates) enumerate_loops | jq -r 'select(.reclaim_candidate == "yes") | @json' | format_muster_table exit 0 ;; "") # Default: show all loops as table enumerate_loops | format_muster_table exit 0 ;; *) # Fallback: treat as loop_id (single-loop detail from Phase 8) # This preserves backward compatibility loop_id="$1" enumerate_loops | jq -r "select(.loop_id == \"$loop_id\")" | jq . exit 0 ;; esac ``` ## Output Formats ### Table (default) ``` LOOP_ID SESSION STATUS LAST_WAKE DEAD STALE RECLAIM ———————————— ———————— ————————— —————————— —————— —————— ———— a1b2c3d4e5f6 session1 ACTIVE 2m ago 0.15 fresh no deadbeef1234 session2 STALE 1h ago 0.78 stale yes ``` **Columns:** | Column | Meaning | | --------- | --------------------------------------------------------------------------- | | LOOP_ID | 12-character hexadecimal loop identifier | | SESSION | First 8 characters of owner_session_id (session context) | | STATUS | ACTIVE (owner alive, fresh heartbeat) / STALE / DEAD | | LAST_WAKE | Relative time of last heartbeat (e.g., "2m ago", "—" if never) | | DEAD | Dead-time ratio (0.00–1.00): fraction of lifespan the loop was inactive | | STALE | Staleness flag: "fresh" (within 3× cadence), "stale" (>3×), "—" (no data) | | RECLAIM | "yes" if loop can be reclaimed (dead owner + old state dir), "no" otherwise | ### JSONL (--json) One JSON object per line, no top-level array. Fields: ```json { "loop_id": "a1b2c3d4e5f6", "session_id": "session1", "status": "ACTIVE", "last_wake_us": "1725000000000000", "last_wake_human": "2m ago", "dead_time_ratio": "0.15", "staleness_flag": "fresh", "reclaim_candidate": "no" } ``` ### Reclaim Candidates (--reclaim-candidates) Filters JSONL to `reclaim_candidate == "yes"` and formats as table. Use with `/autoloop:reclaim ` to clean up. ### Single Loop Detail () Shows a single loop's entry as formatted JSON (Phase 8 compatibility). ## Status Derivation - **ACTIVE**: owner_pid is alive AND staleness ≤ 3× expected_cadence - **STALE**: owner_pid alive but staleness > 3× expected_cadence (stuck/paused process) - **DEAD**: owner_pid dead OR staleness > 4× expected_cadence (no recovery possible) - **SATURATED** (Phase 11): contract marked done or stop event in revision-log ## Reclaim Candidacy (Phase 10 STAT-02) A loop is flagged "reclaim_candidate: yes" if: 1. Owner PID is dead AND state-dir mtime > 7 days, OR 2. Original Phase 4 predicate (owner dead OR heartbeat >3× cadence stale) Use `/autoloop:reclaim ` to manually clean up stale entries. ## Dead-Time Ratio Formula ``` dead_time_ratio = 1 - (heartbeat_count × cadence / lifespan) ``` - Approximates activity by counting heartbeat iterations - Clamped to [0.00, 1.00] - Helps identify chronically hung or underutilized loops ## Examples ```bash # Show all loops /autoloop:muster # Export to JSON for external processing. # --json emits JSONL (one object per line), so iterate with `jq 'select(...)'` # directly — NOT `jq '.[] | select(...)'` (the latter would try to iterate # inside each line and crash with "Cannot iterate over null"). /autoloop:muster --json | jq 'select(.status == "STALE")' # Find loops ready for cleanup /autoloop:muster --reclaim-candidates # Check single loop (backward compat) /autoloop:muster a1b2c3d4e5f6 ``` ## Troubleshooting | Symptom | Fix | | -------------------- | ---------------------------------------------------------------------- | | "No active loops" | No loops registered; run `/autoloop:start` to create one | | All loops DEAD | Likely system restart; loops recover on next iteration | | high dead_time_ratio | Loop may be saturated or paused; check reclaim eligibility | | JSONL parse error | Heartbeat file corrupted; check state_dir for malformed heartbeat.json | ## Anti-patterns - Do NOT modify the registry or state-dir while status is running - Do NOT use status to trigger cleanup (use explicit `/autoloop:reclaim` command) ## Post-Execution Reflection 0. **Locate yourself.** — Confirm this SKILL.md is the canonical file before any edit. 1. **What failed?** — Fix the instruction that caused it. 2. **What drifted?** — Update status derivation or output format if registry schema changed. 3. **Log it.** — Evolution-log entry.