Heartbeat Checklist
Purpose (read this first, every time)
The heartbeat exists to drive consistent incremental progress. That is the whole point. Every tick is an opportunity to nudge ongoing work forward — review an agent’s output, unblock a stalled task, file a follow-up, note a decision, advance a project by one step. Silence is fine when there is genuinely nothing to move; stasis is not. If days pass without any artifact, decision, or committed change, the heartbeat has failed its purpose even if every individual tick followed the rules.
Bias toward small, frequent motion over big infrequent pushes. A single reviewed PR, a single filed task, a single cleared blocker per heartbeat compounds. Ask on each tick: what is the smallest thing I can move forward right now?
0. MANDATORY First Action (do this before anything else)
Run this exact command and include the output in your reasoning:
/home/ben/.local/bin/ava-inbox count
If the count is > 0, you MUST:
/home/ben/.local/bin/ava-inbox view-unread— views the body of every unread message AND marks them all read in one shot- If any summary looks truncated/cut off (ends mid-sentence, missing verdict, “…” suffix, or clearly incomplete), READ THE AGENT LOGS DIRECTLY before composing the status message. See section 1.C.
- Compose a concise HIGH-LEVEL summary (see “Summary style” below)
send_messageto Ben with the summary
Note: view and view-unread auto-mark-read. You do NOT need a
separate mark-all-read step after reading. list / count /
unread-paths are read-only and do NOT mark anything.
Do NOT return AGENT_DONE while unread messages remain. Unread notifications with no send_message is a BUG in your heartbeat — treat it as failure and recover before exiting.
Note: the old ~/ava/pi-inbox.jsonl file is deprecated. Use the
ava-inbox script (wraps mu with Ava’s private MUHOME).
Summary style (CRITICAL)
When reporting agent activity to Ben, keep it HIGH-LEVEL. For each agent include only:
- What the agent did — one sentence, no file lists, no diff stats, no enumerated changes
- Your assessment — is it good, broken, blocked, needs review?
- Next steps / decisions needed — what, if anything, Ben needs to decide
Do NOT include: full diffs, file-by-file changes, acceptance criteria tables, test output, type signatures, or long code blocks. If Ben wants details he will ask.
Rule of thumb: each agent = 3-6 lines of prose max. If you’re writing bullet lists of implementation details, you’re doing it wrong.
1. Agent Notifications (ALWAYS check first)
Use BOTH channels below.
A) Ava inbox (preferred)
/home/ben/.local/bin/ava-inbox count # [read-only] how many unread
/home/ben/.local/bin/ava-inbox list # [read-only] list unread (date/from/subject)
/home/ben/.local/bin/ava-inbox view-unread # view bodies of ALL unread AND auto-mark-read
/home/ben/.local/bin/ava-inbox view <path> # view one message AND auto-mark it read
/home/ben/.local/bin/ava-inbox mark-all-read # escape hatch: mark read w/o viewing
agentd-notifyd.service watches agents and delivers an RFC822 message to
~/ava/inbox/new/ on agent completion or error. Headers carry structured
fields (X-Ava-Agent-Id, X-Ava-Status, X-Ava-Type); body is the
summary text.
Workflow:
- If
count> 0: runview-unread→ compose one concise HIGH-LEVEL summary →send_message. That’s it. The view step already marked everything read. - If you used plain
view <path>on individual messages, those are also already marked read. - Use
mark-all-readonly as an escape hatch (e.g. you learned about a message through some other channel and want to clear state without re-reading).
If count is 0: continue to B.
B) Poll agentd (fallback + safety net)
Always use the agentd CLI. Do NOT curl the HTTP daemon directly.
agentd list-runs
agentd ps
For details on a specific run:
agentd status <id> --json
If agentd itself fails (command not found, daemon down, errors), send_message Ben that agentd is unavailable.
If any agent is failed or unexpectedly stopped, then send_message Ben immediately.
If inbox was empty but an agent is newly completed with a useful summary, send one concise completion message (avoid repeats if already sent recently).
If all are running/idle and no new completions, do not message just for status.
C) Reading agent logs when summaries are truncated
When an inbox notification’s summary is cut off, use agentd logs to read the full session output. This works for both oneshot and persistent sessions and auto-resolves the mode:
agentd logs <agent-name>
For just the tail, pipe it:
agentd logs <agent-name> 2>&1 | tail -n 100
Use this to recover the real verdict/next-action before messaging Ben. Still keep the final message high-level per “Summary style”.
Real-time handling
If you handle a notification in real-time (during active chat, not a
heartbeat), use ava-inbox view <path> or ava-inbox view-unread —
both auto-mark-read, so there’s no separate cleanup step. If you
somehow learn about an inbox item without running view
(e.g. list-only, or through some out-of-band channel), run
ava-inbox mark-all-read manually before exiting, or the next
heartbeat will re-alert.
2. Active Agents
Check current state via the agentd CLI (not a static list in this file, and never via curl/HTTP):
agentd ps
agentd list-runs
For a suspicious agent, inspect details/logs:
agentd status <id> --json
agentd logs <id>
Only message Ben if:
- status is
failed, or - status is
stoppedunexpectedly, or - clear blocker is visible in logs (auth/key/path errors, repeated crashes).
3. Reminders
- None currently
Decision Tree
/home/ben/.local/bin/ava-inbox count> 0 → runview-unread(auto-marks read) → MUST send_message (high-level summary; read logs first if truncated)agentdCLI failed (command error, daemon down) → MUST send_message (agentd unavailable)- inbox empty but
agentdshows failed/stopped/blocker → MUST send_message - inbox empty but
agentdshows newly completed agent with useful summary → send_message once - a reminder is due → send_message
- otherwise no new actionable signal → do NOT send_message. Just return AGENT_DONE.
Rules
- ALWAYS use the
agentdCLI for inspecting agents. NEVER curlhttp://127.0.0.1:8400/...— the HTTP endpoint is deprecated for our purposes; prefer the CLI always. - If
/home/ben/.local/bin/ava-inbox count> 0 and you did not send_message this heartbeat, you have FAILED the heartbeat. Re-read unread messages and send the summary before exiting. viewandview-unreadauto-mark-read. Prefer those overlist+ manualmark-all-read. Only reach formark-all-readas an escape hatch when you learned about a message without runningview.- If an inbox summary is truncated, READ THE SESSION LOG (
agentd logs <id>) before messaging. Never report “summary was cut off” to Ben without first trying the log. - Keep status messages HIGH-LEVEL: what the agent did, your assessment, next steps. No file lists, no diff details, no acceptance tables. Ben will ask if he wants more.
- NEVER send “nothing to report” or “checked in” messages to Ben
- NEVER repeat information you already sent in the last few hours
- The ONLY reasons to message Ben on heartbeat are:
(a) new agent notifications from
ava-inbox, (b) agentd failed/stopped/blocker state, (c) agentd unavailable (CLI error / daemon down), (d) newly completed agent found via agentd fallback (with useful summary), (e) a due reminder - If none of those apply, stay silent
- Remember the purpose: consistent incremental progress. If work has been stalled across multiple heartbeats, that itself is a signal — consider nudging it forward or flagging the stall to Ben, even if no notification arrived
Done (don’t re-alert)
- Git cleanup (worktrees + branches) — completed Feb 16
- t-598-local merged into live — completed Feb 16
- projects.md updated — Feb 16
- t-488 newsreader reminder delivered — Feb 16 morning
- t-604 worktree gone, noted — Feb 16
- Idle subagents stopped — Feb 16 evening
- Root FS read-only issue — resolved, FS is writable as of Feb 17 (push fails are commit lint, not FS)
- Newsreader card-click fix — committed Feb 18
- t-643 created (newsreader full-text fetch) — Feb 18
- Rodney/Showboat discussion — install Rodney, steal Showboat pattern, build Telegram-browser bridge — Feb 18
- AI bottleneck report links fixed (37 bare URLs → markdown) — Feb 18
- t-647/648/649 created (fund model dashboard bugs) — Feb 18
- t-650/651/652/653 created (10-K deep dives: Arista, Cooling, SRAM, Broadcom) — Feb 18
- Fund model walkthrough delivered — Feb 18
- Fat loss protocol established — Mar 1 (carnivore OMAD Sun-Tue/Sat + 72h fast Wed-Fri, target 204 lbs / 15% BF by mid-May)
- Mar 30 meals backfilled to /var/health/meals.jsonl — Mar 31
- Parasail work skill created — Apr 3
- Intent fine-tuning review delivered — Apr 3
- Maildir inbox migration (ava-notify.ts → ~/ava/inbox via ava-inbox script) — Apr 7
- Review queue triage — cleared 127→0 items, 76 → Verified, 30 pipeline fake-dones → Open, 1 agent-claim mismatch flagged (t-758). NeedsHelp queue remains at 3 real blockers for Ben: t-265.8, t-162, t-627. Pipeline scheduler bug identified (treats “agent finished talking” as success; should check for git commit) — Apr 7
- agentd-notifyd.service → ava-inbox notification pipeline — Apr 15 (replaces pi ava-notify.ts; same ava-inbox script, new sender)