hyperhive/docs/terminal-rendering.md

5.2 KiB

Per-agent terminal: row taxonomy + inconsistencies

Snapshot of how the per-agent web UI's live pane renders each event kind today, written up so the next coherence pass has a reference to work from. Source of truth lives in hive-ag3nt/assets/app.js (renderStream, fmtToolUse, renderRichToolUse, renderToolResult, renderTaskEvent) + hive-fr0nt/assets/terminal.css (the shared .live .<class> styling).

Row taxonomy

CSS class Prefix glyph Color Triggered by Source
.turn-start ◆ TURN ← <from> amber, bold, top-margin, amber left rule LiveEvent::TurnStart harness wake
.turn-body (inline under turn-start) fg dimmed 85% same the wake-prompt body
.turn-end-ok ✓ turn ok green, green left rule LiveEvent::TurnEnd { ok: true } harness
.turn-end-fail ✗ turn fail — note red, red left rule LiveEvent::TurnEnd { ok: false } harness
.text none fg/white, indented claude assistant.content[].text stream-json
.thinking · or · thinking … muted, italic claude assistant.content[].thinking stream-json
.tool-use → Name args… cyan assistant.content[].tool_use stream-json
.tool-use <details> → Name path · +N cyan, body is diff rich tool_use (Write/Edit) renderRichToolUse
.tool-use <details> → send → to · headline cyan, body is text mcp__hyperhive__send renderRichToolUse
.tool-result ← <txt> muted short user.content[].tool_result (≤120c) stream-json
.tool-result-block <details> ▸ ← Nl · headline muted, body is text long tool_result (>120c) stream-json
.tool-use ⌁ task <id> started · <desc> [type] cyan claude Task-tool subagent event renderTaskEvent
.turn-end-ok / .turn-end-fail / .tool-result ⌁ task <id> ✓/✗/◌ <status> · <desc> · → <output_file> green / red / muted claude Task-tool result renderTaskEvent
.note · <text> muted LiveEvent::Note (harness chatter, /cancel /compact /new-session, stderr lines, etc.) harness
.sys · {json…} muted anything renderStream doesn't recognise catch-all
.result (defined, never emitted today) green
Banner shimmer mauve turn in flight (ref-counted) setBannerActive

Where the inconsistencies live

  1. Glyph vocabulary drifts:

    • tool_use uses
    • tool_result uses
    • thinking uses ·
    • notes use ·
    • turn-end ok/fail use ✓ / ✗
    • turn-start uses
    • task events use
    • The · glyph is overloaded across thinking, notes, sys.
  2. What gets a <details> block vs a flat row is per-tool ad-hoc: Write/Edit always expand, send always expands, every other tool_use is flat regardless of input size. tool_result is flat if ≤120 chars otherwise <details>.

  3. Stderr handling: claude's stderr lines come through as LiveEvent::Note with text: "stderr: <line>" — they render as muted · stderr: …, identical styling to harness notes about /compact / /model. No red-tinted "this is an error" affordance for stderr.

  4. Catch-all .sys rows are visually identical to .note rows — both muted, both · prefix. They look like normal notes despite usually being "an event renderStream couldn't classify". Unmatched stream shapes (rate limit warnings under odd type/subtype combos, future claude additions, etc.) silently fall through.

  5. .tool-use ranges from one-liner (Read foo.md) to multi-page collapsed diff — same color, same prefix glyph, very different visual weight. A small marker on the collapsed <details> summary would help (the is present in .tool-result-block summaries but absent in tool-use <details> summaries).

  6. Cancel/compact/new-session notes are styled the same as autonomous harness chatter; nothing flags them as "operator initiated."

Suggested coherence pass

Pick one scheme and audit all renderers to match. A concrete proposal:

  • cyan: outbound action (tool_use, send)
  • muted: inbound result (tool_result)
  • amber: turn framing (turn_start)
  • ✓ / ✗: success / failure, green / red (turn_end, task_notification)
  • mauve: subagent / background event (task_*)
  • · muted: ambient note, italic for thinking
  • ! orange: caught error (stderr lines, .sys catch-all that landed something the renderer didn't recognise)

Plus: every tool_use <details> summary gets so collapsed content is visually announced. Operator-initiated notes get a distinct prefix (op· or similar) so they're easier to spot in the scrollback.

The .sys catch-all should escalate visually — a louder "unrecognised event" rendering surfaces silently-dropped event shapes for future fix-up rather than hiding them in the muted note stream.

Dashboard side (not covered here)

The main dashboard's message-flow pane is a different beast: broker messages render as .msgrow grid lines (ts / arrow / from / → / to / body) with separate styling. The current file focuses only on the per-agent terminal.