# 2026-08-04 — Chat interaction overhaul: inline progressive stream (Claude Code style) **Status:** Planned — not started. (Refocused from the earlier feature-heavy draft; backend features deferred — see "Deferred".) ## Goal Streamline agent interactions — thinking, plan, tool usage, responses — into **one linear progressive inline stream per turn** (the Claude Code / Cline / Roo pattern), instead of the current split where the transcript shows a collapsed trace and the real live activity lives in a separate rail timeline. The right rail becomes **graph-only** (and auto-zooms to fit all entities). ## Locked decisions (operator interview) | Decision | Choice | |---|---| | Live activity layout | **Inline stream (Claude Code)** — one progressive column per turn; rail keeps ONLY the Scope graph; Activity timeline tab removed | | Tool-call detail | **Per-tool progressive lines** — each tool its own compact live line (spinner → one-line result summary), expandable to raw | | Feature phases | **Defer** — edit/resubmit, @mentions, attachments are later phases; this plan is interaction-focused + graph auto-zoom | ## Diagnosis (grounded in current code) - The transcript (`ChatThread` → `AgentTrace`) collapses a whole turn's tool calls into one line ("Proposed plan" / "N tool calls"), raw-JSON detail on expand. Not progressive; you can't see what's happening without expanding. - The actual live plan + tool timeline lives in the **right rail** (`TaskContextPanel` → `UnifiedTimeline`): newest-first backbone + tool stubs. So "what is the agent doing" is in a **second place** — a cognitive split. - `UnifiedTimeline` is imported **only** by `TaskContextPanel` (grep confirms), so removing the Activity pane is self-contained. - The `activityLog` **store** stays required: it feeds inline labels (`toolActivityLabel`), live `run` output (`toolsWithLive`), and the mascot (`mascot/stimuli.ts`). Only the timeline *view* is removed. - Tool events already arrive separately (`tool_use` then `tool_result` in `chat.ts`), and the activity log already carries humanized labels + per-tool `stepSeq` attribution. So progressive per-tool lines + step grouping are a **presentation** change, not a data/model change. - `run` results are free-form text (e.g. `"run on lxc:caddy: ERROR exit status 1"`) → one-line result summaries are best-effort text parsing, no backend. ## Design ### D1 — One progressive inline stream per turn Replace `AgentTrace` (one collapsed blob per turn) with a new **`TurnTrace.svelte`** rendered inline for each assistant turn, top-to-bottom: 1. **Live plan checklist** (only on the most-recent/running turn — see D3). 2. **Tool lines grouped by plan step** (D2), then orphan tools (no step). 3. **Streamed text answer** (existing `markdown-body prose-chat`), with the blinking cursor while streaming (existing). 4. A compact **"Thinking" line** while `working` and before any output: reuses the existing `indicatorLabel` (running step → tool → "Agent is thinking…"). Fades once text/tools arrive; reappears between steps. ### D2 — Per-tool progressive lines (the Claude-Code signature) One `ToolLine.svelte` per tool call (replaces `ToolCallCard`'s row style): - Left: state icon — spinner while `tool_use`-only, ✓ on result, ✗ on error. - Label: existing `toolActivityLabel(tool)` (humanized action). - **One-line result summary** on completion — new `toolResultSummary(tool)` in `activity.ts` (see plumbing). E.g.: - `run` → `exit 0 · ` (parse "exit status N" / "ERROR") - `get_entity` → `host:hubris (healthy)`; `get_health_summary` → `healthy X · degraded Y · down Z` - `list_entities`/`list_lxcs` → `N entities`; `get_relations` → `N relations` - `search_knowledge` → `N results`; `upsert_knowledge` → `recorded document:…` - `update_plan_step` → `step `; `propose_plan` → `N steps` - default → first non-empty line of stringified result (≤80ch); `done` if empty - Live `run` output: while streaming, the line auto-expands a pinned-tail mini pane (reuse the `liveOutput` path from `toolsWithLive`). - Click → expand raw args/result (border-driven `
`, cyberspace-square).
- Border-driven, no rounded/shadow (per `border_driven_language`).

### D3 — Live plan checklist (TodoWrite-style)
On the **running/last** turn, render the current-generation `planSteps`
(already generation-aware via `workspace.ts`) as a checklist: pending = hollow,
running = spinner + highlight, done = ✓, failed = ✗, blocked = pause. Steps
check off live as `plan.step.*` events land. This is the unified timeline's
plan view, moved inline and scoped to the active turn. Past turns render only
their tool lines + text (the plan is session-level; the running turn carries
its current state, mirroring how TodoWrite re-displays state each turn). On a
terminal task state (`done`/`failed`), the checklist collapses to one line:
`Plan complete — N steps` / `Plan failed — step K`.

### D4 — Rail → graph only
`TaskContextPanel`: remove the Activity pane and the `UnifiedTimeline` import;
the panel becomes the Scope graph full-height (keep the collapsible "Scope"
header + the `nowTouching` strip). The graph is now the rail's entire job, so
auto-fit (D6) matters more. `activityLog*` stores remain imported only where
the inline stream/mascot need them.

### D5 — Cyberspace cohesion of the stream
Apply alongside the rewrite so the new inline view is on-system from day one:
- Transcript → **terminal log rows** (square, full-width, `YOU`/`NOMOS`
  role-tags, hairline `divide-y` separators; no bubbles, no soft shadow).
  Delete `.user-msg { box-shadow }`.
- Tool lines + expanded `
`: border-driven, square, opaque.
- Composer: opaque `bg-background`, square (remove `rounded-2xl`/`bg-card/50`).
- Rewrite the stale "Art Nouveau" `