Install
npx skillscat add atrium-hermes/atrium-lighthouse/heartbeat Install via the SkillsCat registry.
${var} — Area to focus on. If empty, runs all checks.
If ${var} is set, focus checks on that specific area.
Read memory/MEMORY.md and the last 2 days of memory/logs/ for context.
Checks (in priority order)
P0 — Failed & stuck skills (check first)
Read memory/cron-state.json. This file tracks every scheduled skill's state and quality metrics:
{
"skill-name": {
"last_dispatch": "2026-04-06T12:00:00Z",
"last_status": "dispatched|success|failed",
"last_success": "2026-04-06T12:05:00Z",
"last_failed": "2026-04-05T12:03:00Z",
"total_runs": 10,
"total_successes": 8,
"total_failures": 2,
"consecutive_failures": 0,
"success_rate": 0.80,
"last_quality_score": 4,
"last_error": "error signature text"
}
}Flag these conditions:
- Failed skills: any entry with
last_status: "failed". Report the skill name and when it failed. - Stuck skills: any entry with
last_status: "dispatched"wherelast_dispatchis >45 minutes ago. The skill was dispatched but never reported back — likely hung or crashed before the state update step ran. - API degradation: any skill with
consecutive_failures >= 3. This likely indicates an external API is down or rate-limiting. Report the skill, failure count, andlast_error. If multiple skills share similar error signatures, flag the shared dependency. - Chronic failures: any skill with
success_rate < 0.5(andtotal_runs >= 5). The skill is failing more than it succeeds. - Self-check: if heartbeat's own entry shows
last_successis >36 hours ago (or missing), note that heartbeat itself may be unreliable.
P1 — Stalled PRs & urgent issues
- Any open PRs stalled > 24h? (use
gh pr list) - Any GitHub issues labeled urgent? (use
gh issue list)
P2 — Flagged memory items
- Anything flagged in memory/MEMORY.md that needs follow-up?
P3 — Missing scheduled skills
Read aeon.yml for enabled skills with schedules. Cross-reference with memory/cron-state.json:
- If an enabled skill has no entry at all in the state file, it has never been dispatched by the scheduler.
- If a skill's
last_successis >2x its schedule interval old (e.g., a daily skill hasn't succeeded in >48h), flag it.
Do NOT use gh run list for this — the state file is authoritative.
Dedup & notification
Before sending any notification, grep memory/logs/ for the same item. If it appears in the last 48h of logs, skip it. Never notify about the same item twice.
Batch all findings into a single notification, grouped by priority tier:
🔴 FAILED: skill-a (failed 2h ago), skill-b (stuck 1h ago)
🟡 STALLED: PR #42 open 3 days
🔵 MEMORY: follow-up on X flagged 2 days agoPublic status page
After the priority checks (even when everything is green — this step always runs), regenerate docs/status.md so the public GitHub Pages site reflects current fleet health.
Data sources
memory/cron-state.json— per-skill run state (authoritative)memory/issues/INDEX.md— open issue tableaeon.yml— enabled skill list with schedules- Latest
articles/token-report-*.md(most recent by filename date) — optional; powers the Token Pulse section. Skipped silently when no file exists.
Overall status
Compute one of three overall states from the same signals used above:
🔴 DEGRADED— any P0 flag fired (failed skill, stuck skill, consecutive_failures ≥ 3, chronic failures with success_rate < 0.5, heartbeat self-check >36h stale)🟡 WATCH— any P1/P2/P3 flag fired (stalled PRs, urgent issues, flagged memory items, skills >2x their schedule interval old) or any open issue with severitycriticalorhigh🟢 OK— no flags at all
Format
Write docs/status.md with Jekyll frontmatter so it renders as a gallery page:
---
layout: default
title: "Status"
permalink: /status/
---
# Agent Status
**Overall:** 🟢 OK
**Updated:** 2026-04-24 19:06 UTC
**Open issues:** 0
**Next scheduled run:** heartbeat at 20:00 UTC
Auto-generated by the `heartbeat` skill on every run (3× daily at 08:00 / 14:00 / 20:00 UTC). If the Updated timestamp is more than ~8h stale, the agent is not running.
## Token pulse
| Token | Price | 24h | Liquidity | Volume (24h) | FDV |
|-------|-------|-----|-----------|--------------|-----|
| AEON | $0.0000032626 | -11.16% | $223.4K | $41.3K | $326.3K |
_Source: `articles/token-report-2026-04-28.md` · verdict: SLIDING_
## Skill health (last 7 days)
| Skill | Last run | Status | Success rate | Consecutive failures |
|-------|----------|--------|-------------:|---------------------:|
| token-report | 2026-04-24 12:30 UTC | ✅ success | 100% | 0 |
| fetch-tweets | 2026-04-24 06:53 UTC | ✅ success | 95% | 0 |
| … | … | … | … | … |
## Open issues
_(if INDEX.md has any open rows, render them here; otherwise: "No open issues.")_
| ID | Title | Severity | Category | Detected |
|----|-------|----------|----------|----------|
| ISS-001 | … | medium | rate-limit | 2026-04-22 |
---
*Fork this repo and your copy inherits this page automatically — [how it works](/memory/).*Rules
- Include all enabled skills from
aeon.yml(not only those with recent runs). For skills with no entry in cron-state.json, show—for timestamp andnot yet runin status. - Sort the skill table by last-run timestamp descending (most recent first); skills that have never run sink to the bottom.
- Format timestamps as
YYYY-MM-DD HH:MM UTC(strip seconds and theZ). - Success rate shows
total_successes / total_runs × 100rounded to whole percent; display—whentotal_runs == 0. - Status column icons:
✅ success,❌ failed,⏳ dispatched(if last_dispatch within 45min),🕸 stuck(if last_dispatch > 45min and last_status still dispatched),—(never run). - For the
Next scheduled run:line, pick the enabled skill with the soonest upcoming cron time relative to now. - Dedup state: re-running heartbeat overwrites
docs/status.mdwholesale each time — do not append. - Never expose values from
.env, secrets, or anything outside cron-state.json + issues/INDEX.md + aeon.yml + articles/token-report-*.md. This file is public.
Token pulse rules
- Pick the latest
articles/token-report-*.mdby filename date (sort descending, take the first match). - Staleness: if the picked file's date is older than 24h relative to the heartbeat run timestamp, render
_No recent token data (latest report YYYY-MM-DD)._in place of the table — do not lift stale figures into the table. - No file at all: omit the
## Token pulsesection entirely. The status page must still render cleanly with no token row. - Token symbol: read from
memory/MEMORY.md"Tracked Token" table (first row,Tokencolumn). If the table is missing, render the heading as## Token pulsewith the symbol column blank. - Field extraction (regex, tolerant of both old
Value | 24h Changeand newNow | 24h Δtable layouts):- Price: first
| Price |row → first$value in the row → strip whitespace. - 24h: same Price row → first
±?\d+(\.\d+)?%token in the row (typically the second cell). Render as written, preserving sign. If absent, render—. - Liquidity: first
| Liquidity |row → first$value. - Volume (24h): first row whose first cell matches
Volume\b.*24hor24h Volume→ first$value. - FDV: first
| FDV |row → first$value. - For any field whose row or
$value cannot be located, render—for that cell only — do not skip the section.
- Price: first
- Verdict line: if the source article contains a
**Verdict:** LABELline, append· verdict: LABELto the source line. If no Verdict line is present (older format), omit the suffix. - Source link: the trailing
_Source: ..._line names the exact article file used so a reader can verify the numbers.
The file lands on main through the workflow's auto-commit step — no explicit git commands needed in this skill.
Output
If nothing needs attention, log "HEARTBEAT_OK" (plus the overall status page verdict, e.g. HEARTBEAT_OK · STATUS_PAGE=OK) and end your response.
If something needs attention:
- Send a single concise notification via
./notify(grouped by priority as above) - Log the findings and actions taken to memory/logs/${today}.md
- Log one line with the status-page verdict, e.g.
STATUS_PAGE=DEGRADED — wrote docs/status.md