Commit Graph

5 Commits

Author SHA1 Message Date
408bdb6dd7 fix(kanban): recover and self-heal stuck agent runs
A run could get stranded at 'running' in the UI after a crash/disconnect/
restart, with no way to clear it. Root cause was a race: the SSE history
replay re-asserted a stale `running` status that beat the poll's settled
status, leaving the run showing "Running" + the settle error at once.

Server (runs.ts / runner.ts / index.ts):
- reconcile() on every read force-settles any 'running' run with no live
  runner, so the board self-heals on the next poll (≤3s) — no restart needed.
- forceSettle() emits a persisted `status` event so an open/reconnecting
  SSE stream replays the terminal state last, not a stale `running`.
- Startup orphan-reconciliation now also emits that event (was the gap that
  let the replay re-assert `running` after a server restart).
- Idle watchdog (10min): a silent pi is settled as 'failed' instead of
  hanging forever; SIGKILL escalation (20s) reaps wedged processes.
- stop() now recovers: active→abort, orphaned-but-running→force-stop
  (the Stop button clears wedged runs instead of 409'ing).
- start() catch force-settles 'failed' so a spawn failure never orphans a
  half-created 'running' row.

Client (useOrchestrator.ts):
- patchRun refuses to un-settle a terminal run, dropping stale replayed
  status as a belt-and-suspenders guard against any such race.
EOF && echo "" && git log --oneline -3
2026-06-17 18:53:44 -04:00
6531dc00df feat(kanban): resume runs' chat via Refine + isolate the event stream
Two intertwined changes that both touch the orchestrator hook + run console:

Isolate the agent event stream (perf):
- useRunStream owns the SSE stream + event log locally inside AgentRunBar, so a
  burst of streamed events re-renders only the console — never the board page or
  card modal (which was causing frame drops at run start).
- useOrchestrator is now a registry only; lifecycle events reflect back up via
  stable patchRun/reflectBevy reflectors (effect deps depend on those, not the
  whole object, avoiding a stream-teardown loop).

Session resume for Refine:
- Runs now persist their pi session (drop --no-session); each fresh run captures
  its session JSONL path into a new agent_runs.session_file column (additive,
  idempotent migration).
- Refine resumes the prior run's actual session (--session <path> → appends) in
  that run's own worktree (inherited, never owned), sending the operator's
  feedback as the next message in the same conversation with full prior context.
- owns_worktree guards remove()/cleanup so a refinement never destroys the
  owning run's worktree; bad refinement targets return 409.
- AgentRunBar shows Refine only for settled runs with a recorded session.
EOF && echo "" && git log --oneline -3
2026-06-17 18:34:05 -04:00
292005edbb perf(kanban): stop board cards re-rendering on every agent event
Memoize the board so streaming events from an active run no longer force
all 38 collapsed cards to re-render — only the open CardModal/AgentRunBar
re-renders, since its props stay referentially equal.

- KanbanCard: wrap in React.memo; take isRunning/bevyRunning primitives
  instead of the whole orchestrator object; onOpen now takes the card id.
- useOrchestrator: expose a memoized activeByCard map, recomputed only
  when runs/bevyRunning change (not on every streamed text/tool event).
- KanbanBoardPage: pass a stable openById callback + primitive props so
  memo bails; memoize StatCard; extract the static category legend to a
  memoized CategoryLegend component.

Also drops the per-card .filter().find() status scans each render.
2026-06-16 20:32:08 -04:00
72a41c2d76 feat(kanban): card detail modal and rich agent-run console
- RunEventList: grouped activity timeline. Assistant text becomes chat
  bubbles (auto-collapsing long messages); tool_start/tool_end pair into
  entries with spinners and expandable input/result blocks; bevy output
  rolls into a live console; relative timestamps on a left rail
- AgentRunBar: redesigned as a mission console. Live stats header (elapsed
  time, tool count, events), animated status banner with sweep/glow while
  running, clearer action bar. All controls preserved (run/steer/stop,
  diff/merge/bevy) so the human-only merge/complete safety model holds
- tailwind.css: vn-flow, vn-sweep, vn-dots, vn-spin keyframes
- CardModal: full card overlay (orchestrator, references, tags, comments)
- DiffModal: branch-diff review (commits, stat, capped patch)
- useOrchestrator: background polling + bevy status sync + ref-counted SSE
- KanbanCard: pulsing agent/bevy running badge on collapsed cards
2026-06-16 18:17:35 -04:00
a3c72bb878 feat(kanban): persist board, reference pages, and run agents
Replace the localStorage kanban with the backend-backed board, add typed clients
and a React hook with optimistic updates. Cards can reference static doc pages
and user-created custom pages (new "custom" reference type with purple chips).

Add the agentic orchestrator UI: a per-card panel to launch `pi` runs, watch a
live tool/thought stream over SSE, steer mid-run, and stop — while the board
stays fully interactive. The board page wires the orchestrator and custom-pages
stores into every card.
2026-06-16 15:44:29 -04:00