Two board-level additions:
Merge all reviewable agent branches into the main branch sequentially:
- worktrees.mergeBranches() merges candidates in order, advancing HEAD each
time; refuses if the main tree is dirty, and on the first conflict aborts
that merge (main left clean) and stops — prior merges stay, untried
branches reported as unattempted.
- runManager.mergeAll() picks candidates (settled runs that own their
worktree, branch present, not yet in HEAD; deduped, oldest-first) — so
refinement runs (which inherit a worktree) are correctly excluded.
- POST /runs/merge-all; ⬇ Merge all button in the board header opens a
results modal (per-branch ✓/⇢/⚠, conflict banner, inline git output).
Floating dock to view/open running agents (front-end only):
- RunningAgentsBar pins bottom-right (below the card modal), lists every
running run with live elapsed times, and opens that card's modal on click;
auto-hides when nothing runs, collapsible otherwise.
EOF && echo "" && git log --oneline -4
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
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
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.
- 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
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.
User-created dynamic doc pages live at /docs/custom/:slug, persisted in the new
backend. The editor offers "Beautify with AI", which regenerates the page as
structured HTML with Mermaid diagrams and replaces the raw markdown source (the
beautified version becomes the page's canonical content and survives edits).
Adds a DocHtml renderer that lazily renders Mermaid blocks, a purple design
token, sidebar/topbar entries for custom pages, and routing.
Introduce the @void-nav/api Hono + SQLite backend that powers the docs site:
a persisted implementation board (kanban), a custom documentation-pages store
with AI beautify, and an agentic orchestrator that runs `pi` agents per card.
The orchestrator spawns `pi --mode rpc` inside an isolated git worktree per run,
streams slim events over SSE, and lets the agent drive the board/docs via
token-gated internal endpoints (all SQLite writes stay in-process). Interrupted
runs are reconciled to "stopped" on boot.
Workspace wiring: root `dev:api`/`dev:web` scripts with `concurrently`, the
docs Vite `/api` proxy, and `.worktrees/` gitignore.
- Add MiniStarMap, NpcMarketPanel, ShipStatusPanel, useKeyboardShortcuts
- Add progress bars for approach/mining operations and cargo fill indicator
- Rewrite docs from spreadsheet-first to exploration-first open-world RPG
- Replace dev:db + dev:standalone with unified dev script (scripts/dev.sh)
- Add Vite chunk splitting for three.js and spacetimedb
- Fix displayName dependency in useSpacetimeConnection
- Remove stale usePlayerSession.ts
- Add AGENTS.md files across all packages