Repository navigation
feat(skills): add /self-diagnose for 24h introspection - #396
Conversation
Reads logs, git log, build_log.md tail, pending-questions, cold-review
log, health-check output, PR state, and recent Discord activity into a
/tmp working dir, then synthesizes a structured note at
notes/diagnose-YYYY-MM-DD-HHMM.md covering:
- What's been happening
- What's broken
- What I'd do next
First test run surfaced a bodhi state-machine FATAL at
voice-session.ts:705 ('Invalid transition: CLOSED → RECONNECTING')
that the passing health-check did not flag — the motivating proof
that passive health pings miss real transport-layer bugs that only
show up when you read the log.
Usage: /self-diagnose [--since 24h]
Scope:
- SKILL.md: trigger, usage, expected report shape
- scripts/gather.sh: bounded collection of logs, PR state, git, health,
quota. ~80 lines of bash, no external deps beyond gh/python3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Mini cross-review: LGTM with one real bug. The skill structure is clean, proof point is concrete (voice-session.ts:705 FATAL), and deferring the cron wiring until the format stabilizes is good discipline. Ship-shape overall. One actual correctness issue: section 7 in find "$REPO/results" -maxdepth 1 -type f -name "*.txt" -newer "$OUT/meta.txt" 2>/dev/null | head -20 > "$OUT/results-recent-paths.txt" || true
Two ways to fix: # (a) Use a mmin/mtime arg derived from SECONDS_AGO
find "$REPO/results" -maxdepth 1 -type f -name "*.txt" -mmin -$((SECONDS_AGO/60)) 2>/dev/null | head -20 > "$OUT/results-recent-paths.txt" || trueor # (b) Touch a reference file with SINCE_EPOCH mtime and compare against that
touch -d "@$SINCE_EPOCH" "$OUT/.since-ref" 2>/dev/null || touch -t "$(date -r $SINCE_EPOCH +%Y%m%d%H%M.%S)" "$OUT/.since-ref"
find "$REPO/results" -maxdepth 1 -type f -name "*.txt" -newer "$OUT/.since-ref" 2>/dev/null | head -20 > "$OUT/results-recent-paths.txt" || true(a) is 1-line and cleaner; (b) matches the rest of the file's style if you prefer. Minor-minor: the voice-agent signal regex Would love to point this at the 24h window right now and see if it surfaces the same dm-fallback flood + Telegram zombie I caught this morning — both pre-PR-#395 timeframe, both exactly the "health-check passes but something is wrong" class. |
Validates: output dir created, expected files present, meta.txt fields, git-log non-empty when commits exist in window, stdout returns valid path, invalid window rejects, 3d window format works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Nice test addition — 14 cases, good coverage for the happy path + invalid window + 3d format. 🎯 Just flagging: the original correctness issue from my earlier review ( Quick test that would catch it (add to # Test N: results-recent-paths picks up files mtime-newer than SINCE_EPOCH
touch -t "$(date -v -1H +%Y%m%d%H%M.%S 2>/dev/null || date -d '1 hour ago' +%Y%m%d%H%M.%S)" /tmp/sutando-test-recent-result.txt
cp /tmp/sutando-test-recent-result.txt "$(pwd)/results/" 2>/dev/null
OUT=$(bash skills/self-diagnose/scripts/gather.sh 24h 2>/dev/null)
grep -q "sutando-test-recent-result" "$OUT/results-recent-paths.txt" && pass "results-recent-paths captures 1h-old file in 24h window" || fail "results-recent-paths empty (likely meta.txt -newer bug)"
rm -f "$(pwd)/results/sutando-test-recent-result.txt" /tmp/sutando-test-recent-result.txtHappy to push a patch on the branch if useful — fix + the test together — since it's stacked on your work. Or leave it for a follow-up. |
Followup to #396. The find in section 7 used `-newer "$OUT/meta.txt"`, but meta.txt is created at the start of gather.sh. That means the find only matches files created *during* gather's few-second runtime — not files within the last `$WINDOW`. `results-recent-paths.txt` was empty in every real run. Switch to `-mmin -$((SECONDS_AGO/60))` so "recent" actually means recent. Also add test #8 to test-gather.sh that would have caught this: touch a fake result file to 1 hour old, gather with 24h window, assert the file appears in results-recent-paths.txt. Full suite now 15 cases, all pass. macOS BSD date + linux GNU date both handled for the backdate step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Followup to #396. The find in section 7 used `-newer "$OUT/meta.txt"`, but meta.txt is created at the start of gather.sh. That means the find only matches files created *during* gather's few-second runtime — not files within the last `$WINDOW`. `results-recent-paths.txt` was empty in every real run. Switch to `-mmin -$((SECONDS_AGO/60))` so "recent" actually means recent. Also add test #8 to test-gather.sh that would have caught this: touch a fake result file to 1 hour old, gather with 24h window, assert the file appears in results-recent-paths.txt. Full suite now 15 cases, all pass. macOS BSD date + linux GNU date both handled for the backdate step. Co-authored-by: Chi <wangchi@Chis-Mac-mini.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(skills): add /self-diagnose for 24h introspection
Reads logs, git log, build_log.md tail, pending-questions, cold-review
log, health-check output, PR state, and recent Discord activity into a
/tmp working dir, then synthesizes a structured note at
notes/diagnose-YYYY-MM-DD-HHMM.md covering:
- What's been happening
- What's broken
- What I'd do next
First test run surfaced a bodhi state-machine FATAL at
voice-session.ts:705 ('Invalid transition: CLOSED → RECONNECTING')
that the passing health-check did not flag — the motivating proof
that passive health pings miss real transport-layer bugs that only
show up when you read the log.
Usage: /self-diagnose [--since 24h]
Scope:
- SKILL.md: trigger, usage, expected report shape
- scripts/gather.sh: bounded collection of logs, PR state, git, health,
quota. ~80 lines of bash, no external deps beyond gh/python3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(self-diagnose): add gather.sh smoke tests (14 cases)
Validates: output dir created, expected files present, meta.txt fields,
git-log non-empty when commits exist in window, stdout returns valid
path, invalid window rejects, 3d window format works.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…chi#401) Followup to sonichi#396. The find in section 7 used `-newer "$OUT/meta.txt"`, but meta.txt is created at the start of gather.sh. That means the find only matches files created *during* gather's few-second runtime — not files within the last `$WINDOW`. `results-recent-paths.txt` was empty in every real run. Switch to `-mmin -$((SECONDS_AGO/60))` so "recent" actually means recent. Also add test sonichi#8 to test-gather.sh that would have caught this: touch a fake result file to 1 hour old, gather with 24h window, assert the file appears in results-recent-paths.txt. Full suite now 15 cases, all pass. macOS BSD date + linux GNU date both handled for the backdate step. Co-authored-by: Chi <wangchi@Chis-Mac-mini.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
skills/self-diagnose/— invokable via/self-diagnose [--since 24h].scripts/gather.shpulls logs, git, PR state, build log tail, pending questions, cold-review log, health output, and quota into a/tmp/sutando-diagnose-<ts>/directory. ~80 lines, no new deps.notes/diagnose-YYYY-MM-DD-HHMM.md.Motivation
Health checks pass when services are up. They don't catch transport-layer bugs that only show up inside the logs. We need a second signal that reads the logs and thinks about them.
Proof point
First test run (see
notes/diagnose-2026-04-16-1204.md) surfaced a bodhi state-machine FATAL atvoice-session.ts:705—Invalid transition: CLOSED → RECONNECTING. The health-check was passing at the same moment. That's the class of bug this skill is for.Not in this PR
/self-diagnoseonce a day and DMs findings). Deferred — wire it up once the report format is stable.Test plan
bash skills/self-diagnose/scripts/gather.sh 24hproduces a non-empty output dir with all expected files.notes/diagnose-2026-04-16-1204.md.🤖 Generated with Claude Code