Skip to content

TUI architecture: SolidJS migration, worker isolation, shared component library, event streaming #217

@windoliver

Description

@windoliver

Summary

Cross-project TUI architecture decisions that affect Grove's boardroom UI. Canonical issue with full rationale: windoliver/koi#1484. This issue tracks Grove-specific implementation.

Sibling issues: windoliver/koi#1484, nexi-lab/nexus#3632

Execution Order

Grove's TUI is the most mature of the three (~40 views, full app shell, multi-panel boardroom). Migration is larger but the payoff is highest — streaming contribution feeds, agent terminals, and frontier updates all benefit from SolidJS reactivity.

16 issues in 5 waves.

Wave 0 — Prerequisites (fix what's broken)

Order Issue What Why first
0a #213 Fix correctness issues — conflicting keybinds, dead code, broken refresh, unreachable Plan panel Can't migrate broken code
0b #216 Panel UX polish — frontier grouping, detail scrolling, search fallback, running view errors Fix before restructuring

Wave 0 unblocks everything. Stabilize before transforming.

Wave 1 — Foundation (theme + welcome + product direction)

Order Issue What Depends on
1a #195 Persisted theme, keymap, and layout customization Wave 0
1b #191 Guided run as default, boardroom demoted to advanced Wave 0
1c #190 Redesign welcome flow for smarter startup and session resumption Wave 0
1d #177 Screen manager transition tests Wave 0 (document current behavior before changing it)

These are mostly independent — run 1a-1c in parallel, 1d anytime. Theme tokens (1a) must land before SolidJS migration. Product direction (1b, 1c) must settle before converting views — no point converting a view that's about to be redesigned.

Wave 2 — Architecture migration (the big one)

Order Issue What Depends on
2a #217 §1 SolidJS migration (@opentui/react@opentui/solid) Wave 1a (theme), Wave 1b (product shape settled)
2b #217 §5 Pin OpenTUI to 0.1.96 (match Koi) Do during 2a
2c #188 SSE event streaming replaces polling Do during 2a — SolidJS signals make reactive updates trivial

SolidJS conversion order (Grove-specific — by dependency, not alphabetical):

Phase 2a-i: Infrastructure (~2 days)

  1. theme.ts → SolidJS context provider
  2. hooks/use-keyboard.ts, hooks/use-navigation.ts → Solid primitives
  3. data/use-polled-data.ts → Solid createResource + SSE (TUI: reduce polling feel with event-driven live updates across core surfaces #188)
  4. providers/ → Solid context providers

Phase 2a-ii: App shell (~1 day)
5. tui-app.tsx → Solid entry
6. app.tsx (boardroom) → Solid
7. screens/screen-manager.tsx → Solid

Phase 2a-iii: Guided flow screens (~2 days)
8. screens/preset-select.tsx
9. screens/goal-input.tsx
10. screens/agent-detect.tsx, spawn-progress.tsx
11. screens/running-view.tsx
12. screens/complete-view.tsx

Phase 2a-iv: Boardroom panels (~3 days)
13. panels/panel-manager.tsx, panel-registry.ts
14. components/ (status bar, input bar, tab bar, command palette, help, tooltips, progress)
15. views/ — convert in dependency order: simple views first (welcome, dashboard), then complex (dag, frontier, detail, terminal, artifact-preview, trace)

Phase 2a-v: Remove React (~0.5 day)
16. Remove react, @opentui/react, @types/react
17. Switch @opentui-ui/dialog and @opentui-ui/toast to /solid entry points

Wave 3 — Features enabled by new architecture

Order Issue What Depends on
3a #212 OpenTUI native components — <code>, <diff>, <scrollbox>, <markdown> Wave 2 (Solid)
3b #192 Rich components and transitions Wave 2 (Solid + useTimeline)
3c #189 Plugin/extensibility surface for custom panels Wave 2 (Solid — plugin slots only in @opentui/solid)
3d #194 Command palette → universal action system Wave 2
3e #186 Leader-key presets and configurable keymaps Wave 1a (theme/keymap persistence) + Wave 2
3f #217 §4 Shared components from @koi/tui-base Wave 2 + 3d (palette is a shared component)

All independent of each other — run in parallel. This is where the SolidJS migration pays off: plugin slots (#189), useTimeline animations (#192), and reactive event streaming all require Solid.

Wave 4 — Advanced UX

Order Issue What Depends on
4a #193 Agent supervision as hero surface Wave 3a (native components for agent output)
4b #187 Redesign frontier as grouped navigable views Wave 3a (native <scrollbox>, <code>)
4c #184 Resume shows past session traces and contributions Wave 2c (SSE events), Wave 1c (welcome redesign)
4d #201 Session config screen — edit metrics, gates, mode Wave 1b (product direction), Wave 2
4e #217 §2 Worker thread isolation Wave 2c (SSE transport between threads)

Visual dependency graph

Wave 0:  #213 (fixes) ── #216 (polish)
           │
Wave 1:  #195 (theme) ║ #191 (guided default) ║ #190 (welcome) ║ #177 (tests)
           │                    │
Wave 2:  #217§1 (SolidJS) ─── #188 (SSE) ─── pin OpenTUI
           │
         ┌─┴──────┬──────┬──────┬──────┬──────┐
Wave 3:  #212     #192   #189   #194   #186   #217§4
         (native) (rich) (plug) (palette)(keys)(shared)
           │               │
Wave 4:  #193 ── #187     #184 ── #201 ── #217§2 (worker)
         (agent)  (frontier)(resume)(config)

Effort estimates

Wave Issues Estimated effort Risk
0 #213, #216 2-3 days Low — known fixes
1 #195, #191, #190, #177 3-4 days (parallel) Medium — product decisions
2 SolidJS + SSE + version pin 8-10 days High — 40+ views to convert
3 #212, #192, #189, #194, #186, shared lib 5-7 days (parallel) Low — building on stable base
4 #193, #187, #184, #201, worker 5-7 days Medium — new features

Total: ~23-31 days of focused work. Grove is the largest migration because it has the most views, but Waves 3 and 4 are heavily parallelizable.

Recommended cross-project sequence

Koi should go first (smallest, no app shell — build right from day one), then the pattern is proven for Grove and Nexus:

Koi Wave 1 (SolidJS shell) ──► Grove Wave 2 (migration) ──► Nexus Wave 2 (migration)
         │                              │                            │
         └── @koi/tui-base ────────────►└── consume shared ─────────►└── consume shared

What changes for Grove

1. Migrate from @opentui/react to @opentui/solid

Grove's TUI has ~40 views built on React 19 + @opentui/react ^0.1.87. SolidJS fine-grained reactivity eliminates reconciliation overhead — critical for the contribution feed, agent terminal output, and frontier updates.

Grove-specific migration notes:

  • Zustand stores map to SolidJS stores (both proxy-based, similar API)
  • @opentui-ui/dialog and @opentui-ui/toast both ship /react and /solid entry points
  • useKeyboard, useRenderer, useTerminalDimensions have identical APIs in both reconcilers
  • xterm terminal views need the Solid lifecycle equivalent (onMount/onCleanup vs useEffect)
  • The @opentui/solid plugin slot system enables TUI: add plugin/extensibility surface for custom panels and actions #189 (extensibility)

2. Worker thread isolation

Grove mixes TUI rendering with HTTP polling, contribution processing, and tmux/acpx management in one thread. Target: rendering in main thread, Grove server + agent coordination in worker.

Grove-specific RPC:

  • start(preset, goal) — launch session
  • subscribe() → SSE stream of contributions, claims, agent events
  • submitWork(contribution) — agent publishes work
  • claim(taskId) — claim a task
  • shutdown() — cleanup agents + Nexus

3. SSE event streaming (replaces polling)

Directly addresses #188. Grove server emits SSE for:

  • New contributions
  • Claim state changes
  • Agent status transitions
  • Frontier recomputation
  • Goal/topology changes

TUI consumes via 16ms batched event handler.

4. Shared component library

Grove independently built components that overlap with Koi and Nexus:

  • command-palette.tsx → shared CommandPalette
  • status-bar.tsx → shared StatusBar
  • table.tsx → shared or native OpenTUI
  • theme.ts → shared ThemeProvider with semantic tokens

Grove adds domain-specific views on top: DAG, frontier, claims, agent terminals, artifact preview, etc.

5. OpenTUI version bump

Currently ^0.1.87 — pin to 0.1.96 (match Koi). Gains: streaming markdown, improved diff rendering, plugin slot system, performance fixes.

Existing Grove issues this extends

Issue Wave Relation
#213 0 Prerequisite — fix before migrating
#216 0 Prerequisite — polish before restructuring
#195 1 Theme tokens before SolidJS conversion
#191 1 Product direction settles view set
#190 1 Welcome flow before conversion
#177 1 Tests document current behavior
#188 2 SSE replaces polling (core of §3)
#212 3 Native primitives (§5)
#192 3 Rich components + transitions
#189 3 Plugin slots (requires Solid)
#194 3 Command palette → shared component (§4)
#186 3 Keymaps
#193 4 Agent supervision hero surface
#187 4 Frontier redesign
#184 4 Resume with traces
#201 4 Session config screen

Acceptance criteria

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions