| name | hyvemind-diagnose |
| description | One-call diagnosis of any Hyvemind entity (session, task, swarm, hivemind review, nurse decision) from an opaque ID. Use when given a UUID / task number / hmr-id and asked "what's going on with this agent/session/swarm" or "why isn't X showing up". |
Hyvemind Entity Diagnosis
Step 1 (usually the ONLY step): run the bundler
One tool call gets the entire context — entity-type resolution (full or partial IDs), known-failure-pattern scan, session metadata (harness backend, model, tool set, agent role, workflow prompt, duration, who stopped it), OpenCode server-side ground truth, condensed timeline, all WARN/ERRORs, nurse signals + decisions, captured submit_* tool args, and linked entities:
python3 .claude/skills/hyvemind-diagnose/diagnose.py <ID>
<ID> can be a session UUID (full or short prefix), a task number (306 or task-306), a swarm UUID, a review id (hmr-…), or a nurse decision_id.
--full disables truncation caps; --type session|task|swarm|review|decision skips auto-detection.
- Every truncated section prints the exact file path holding the rest — read that path directly instead of re-running broader commands.
Step 2: read the bundle top-down — each section answers one question
| Section | Question it answers |
|---|
DETECTED FAILURE PATTERNS | Does this match a known failure signature? Start here. |
TOOL SCHEMA PARITY | (fires on any did not call submit_X hit) Does the on-disk OpenCode echo-tool schema use the same field names the Rust consumers parse? The model follows the tool schema; the frontend/Rust parses the canonical field name (canonical schemas live in the Rust handlers + the echo-tool generator app/src-tauri/src/harness/opencode/tools.rs). A drifted name = silent capture miss = "did not call the tool" even though it did. |
SESSION METADATA | Which harness (opencode; old logs may say pi), which model (UI id + resolved provider id), tool set, agent role (first sentence of the system prompt), workflow (prompt preview), turn count, start/stop times, whether stop_chat cut the turn short, which watchdog was polling (watchdog_caller). |
OPENCODE SERVER LOG | Server-side ground truth when the Hyvemind transcript is gone: llm dispatch (provider/model OpenCode actually used), step-loop cadence, per-tool permission counts (proxy for what the agent did), Aborted process / session.error rows. |
REVIEW FLOW (task reports) | Which hmr- reviews the task ran, whether each has a review log (no log = aborted before the engine started, i.e. context-gather failed), and the exact flow error text from the task messages. |
SESSIONS REFERENCED BY THIS TASK | One line per session: harness, model, turns, STOPPED@ time, submit_calls count. |
DEBUG LOG | Hyvemind-side condensed timeline. Includes harness event: rows (tool start/end, extension tool calls with args preview, agent/turn lifecycle) for every backend. |
NURSE ACTIVITY | Did the Nurse see it, and why did/didn't it act. |
Step 3: interpretation rules learned from real incidents
| Symptom | Likely cause | Where the bundle shows it |
|---|
"did not call the submit_X tool" but the model is strong | Echo-tool schema field name drifted from canonical (e.g. review_prompt vs prompt) | TOOL SCHEMA PARITY — compare against the field names parsed by the Rust handlers / generated in tools.rs::tool_schema (parity is test-enforced in tools.rs). |
extension calls: NONE captured on an OpenCode session with a long turn | Same as above, OR the turn was aborted before the model reached the submit step | SESSION METADATA stopped_at vs duration_ms: stop long before natural end = aborted mid-work |
Review id exists in task but no ~/.hyvemind/reviews/{id}.jsonl | Review aborted in the context-gather phase, before the engine started | REVIEW FLOW flags it explicitly |
| Turn "completed" but no useful output | send_message complete fired only because stop_chat aborted the turn (timestamps identical) | SESSION METADATA + debug log L-rows |
Aborted process in OpenCode log | Hyvemind called abort (user stop, retry, review watchdog) — not a crash | Server-log ERROR row; ignore the scary wording |
| Plan never appears | Tool args nested under a wrapper key instead of flat top-level fields | harness event: extension tool call args preview in the debug log |
pi process crashed … {}.passthrough | Broken generated submit_*.ts crashes opencode serve at startup | ~/.config/opencode/tool/*.ts line 8 |
| "pi error" wording on OpenCode backend | Legacy PiRpcError::ProcessCrashed Display; the crash is the OpenCode server | Ignore the "pi" prefix |
| Session evicted unexpectedly | 10-min idle TTL | evicting idle pattern |
| Nurse saw it but did nothing | gated_* statuses in the decisions summary | Nurse section |
Expected submit_* arg shapes (canonical — what consumers parse)
Canonical source: the Rust handlers that parse each tool's args, mirrored by the OpenCode echo-tool schemas generated in app/src-tauri/src/harness/opencode/tools.rs::tool_schema (parity is test-enforced in tools.rs).
submit_plan → { plan_markdown }
submit_review_prompt → { prompt } (NOT review_prompt)
submit_context → { summary } (NOT context)
submit_features → { features: [{id, name, description, dependencies?, milestone?, fulfills?}], milestones?: [{id, name, features, assertions?}] }
submit_questions → { questions: [{id, kind, title, sub?, options?: [{id, label, hint?, recommended?}], placeholder?}] }
submit_handoff → { feature_id, salient_summary, what_was_implemented, verification, success_state }
submit_verdicts → { verdicts: [{reviewer_model, suggestion, verdict, severity?: int 1-5, best_find?: bool, co_reviewers?}] }
If the agent's final text says it called a tool but the UI shows nothing, compare the captured args (harness event: extension tool call row) against this table.
Data sources the bundler reads (for manual fallback)
| Surface | Path | Notes |
|---|
| Session debug log | ~/.hyvemind/debug/sessions/{ID}.jsonl | Needs HYVEMIND_DEBUG=1. Contains metadata rows + harness event: rows (all backends). |
| Session transcript (legacy) | ~/.hyvemind/chat-sessions/{ID}.jsonl | No longer written — only the removed Pi backend produced these. Old files may remain on disk for pre-migration sessions. OpenCode sessions live server-side — use the id map + server log. |
| OpenCode id map | ~/.hyvemind/opencode/sessions.json | Hyvemind UUID → ses_… + project directory. |
| OpenCode server logs | ~/.local/share/opencode/log/*.log | One file per opencode serve spawn; grep for the ses_ id. Logs lifecycle/permissions/errors but NOT tool names — tool names come from the Hyvemind harness event: rows. |
| OpenCode echo tools | ~/.config/opencode/tool/submit_*.ts + ~/.hyvemind/opencode/.opencode/tool/ | Regenerated on every server spawn by the running binary — stale until the app is rebuilt. |
| Task UI state | ~/.hyvemind/task-messages/task-{N}.json | Flow errors live in messages[].error, not .text. |
| Review logs | ~/.hyvemind/reviews/{id}.jsonl + {id}/output-*.txt | Absent entirely if the review aborted before the engine started. |
| Nurse | ~/.hyvemind/debug/nurse/ | Always-on, not gated on HYVEMIND_DEBUG. |
| Swarm | ~/.hyvemind/swarms/{ID}/progress_log.jsonl | Plus ~/.hyvemind/debug/swarms/{ID}/. |
Exhaustive per-entity recipes live in CLAUDE.md (§Investigating a Task / Session / Hivemind Review / Swarm / Nurse decision).
Frontend/backend code references
| What | File |
|---|
| Tool arg parsing (UI) | app/src/lib/taskReducer.ts (search the tool name) |
Review-flow capture (structured_review_prompt → parsed.prompt) | app/src/lib/taskRuntime.tsx (search reviewPromptFromTool) |
Structured event naming (submit_X → structured_X) | app/src-tauri/src/commands/chat.rs |
| Echo-tool generator + canonical-parity test | app/src-tauri/src/harness/opencode/tools.rs |
| Per-event diagnosis logging (all backends) | app/src-tauri/src/harness/session_runtime.rs::log_event_for_diagnosis |
| OpenCode SSE → event mapping | app/src-tauri/src/harness/opencode/event_map.rs |