Skip to content

feat: terminal orchestration system#16

Open
190km wants to merge 21 commits intocanaryfrom
feat/terminal-orchestration
Open

feat: terminal orchestration system#16
190km wants to merge 21 commits intocanaryfrom
feat/terminal-orchestration

Conversation

@190km
Copy link
Copy Markdown
Owner

@190km 190km commented Mar 24, 2026

Terminal Bus + APC protocol + inter-terminal communication. 2300+ lines.

190km and others added 21 commits March 25, 2026 00:13
Core orchestration system — 2310 lines of new code:

- src/bus/types.rs: TerminalHandle, TerminalStatus, TerminalRole,
  TerminalGroup, ContextEntry, BusEvent, EventFilter, TerminalInfo
- src/bus/mod.rs: TerminalBus with terminal registry, command injection,
  output reading, group management, shared context, event system
- src/bus/apc.rs: APC escape sequence parser and command dispatcher.
  Protocol: \x1b_VOID;{id};{method};{json}\x1b\ through the PTY pipe

Not yet wired into VoidApp or the PTY reader thread — this is the
foundation that the integration layer will build on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete integration of the orchestration bus:

- VoidApp owns Arc<Mutex<TerminalBus>>, threaded to all spawn/close sites
- Terminals register with the bus on spawn, deregister on close
- PTY reader thread intercepts APC sequences (\x1b_VOID;...\x1b\)
  before they reach the VTE parser, dispatches to bus, writes response
  back to PTY — enabling void-ctl communication through the pipe
- VOID_TERMINAL_ID env var set on spawned shells so processes know
  which terminal they're running in
- PtyHandle::create_bus_handle() creates TerminalHandle from Arc clones
- Handles partial APC sequences across read boundaries

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standalone binary that communicates with the Terminal Bus via APC
escape sequences through the PTY pipe. No sockets, no auth tokens.

Commands:
  list                    List all terminals
  send <id> <command>     Send command to terminal
  read <id> [--lines N]   Read terminal output
  wait-idle <id>          Wait for terminal to finish
  group create/join/leave Group management
  context set/get/list    Shared key-value store
  message send/list       Direct messaging
  spawn [--group G]       Spawn new terminals
  close <id>              Close a terminal

Usage: void-ctl is automatically available inside Void terminals
via VOID_TERMINAL_ID env var.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows conpty strips APC escape sequences, so APC-over-PTY doesn't
work. Added a local TCP server (127.0.0.1, random port) as fallback.

- src/bus/server.rs: TCP listener, accepts JSON-RPC over newline-delimited TCP
- VOID_BUS_PORT env var set on spawned terminals
- void-ctl rewritten to use TCP instead of stdin/stdout APC
- All commands work: list, send, read, group, context, message, spawn, close

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
list_terminals now only shows terminals in the same workspace as the
caller. Terminals from other workspaces are hidden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- void-ctl spawn: queues a terminal spawn for VoidApp to process
- void-ctl close <id>: queues a terminal close
- VoidApp polls pending_spawns/pending_closes each frame
- Suppress all dead_code warnings in bus module (methods used by void-ctl)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create src/bus/task.rs with Task struct, TaskStatus enum, TaskInfo
- Add task storage (HashMap + dependents index) to TerminalBus
- Implement task CRUD: create, update_status, assign, unassign, delete, list, get
- Add tick_tasks() for auto-unblock of blocked tasks when dependencies complete
- Add DAG cycle detection for task dependencies
- Add TaskNotFound and CycleDetected to BusError
- Add 8 task BusEvent variants (Created, StatusChanged, Assigned, etc.)
- Add task.* method dispatchers to APC handler (JSON-RPC)
- Add void-ctl task subcommand (create, list, update, assign, unassign, delete, get)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create src/orchestration/mod.rs with OrchestrationSession struct
- Create src/orchestration/prompt.rs with leader/worker prompt generation
- Create src/orchestration/template.rs with TOML template engine
- Create src/orchestration/worktree.rs with git worktree manager
- Add orchestration_enabled and orchestration fields to Workspace
- Add orchestration section to sidebar (toggle, team status, kanban/network controls)
- Add SidebarResponse variants: ToggleOrchestration, SpawnWorker, ToggleKanban, ToggleNetwork
- Implement toggle_orchestration() in VoidApp (group creation, role assignment, panel spawning)
- Add tick_tasks() and tick_statuses() to update loop
- Sync kanban/network panels from bus each frame

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create src/kanban/mod.rs — KanbanPanel with column rendering, task cards,
  status colors, drag/resize support, double-click to focus terminal
- Create src/network/mod.rs — NetworkPanel with force-directed layout,
  animated edge particles, node activity glow, event-driven updates
- Create src/canvas/edges.rs — CanvasEdgeOverlay with bezier curves,
  particle trails, and arrowheads between terminal panels
- Extend CanvasPanel enum with Kanban and Network variants
- Implement all match arms (id, title, position, size, color, z_index,
  focused, rect, is_alive, show, to_saved, drag/resize, etc.)
- Kanban and Network panels return None from to_saved() (not persisted)
- Add edges module to canvas/mod.rs
- Add kanban, network, orchestration modules to main.rs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- templates/duo.toml — 1 leader + 1 worker pair programming
- templates/trio.toml — 1 leader + 2 workers small team
- templates/fullstack.toml — 1 architect + backend/frontend/QA workers
- templates/research.toml — 1 lead + 4 researchers + synthesizer
- templates/hedge-fund.toml — 1 PM + 5 analysts + risk manager

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add orchestration env vars to PTY spawn (VOID_TEAM_NAME, VOID_ROLE,
  VOID_GROUP_ID, VOID_ORCHESTRATION_PROTOCOL)
- Add orchestration commands to command palette (Toggle, Spawn Worker,
  Show Kanban, Show Network)
- Wire up edge overlay: subscribe to bus events, feed on_event() each
  frame, draw bezier curves + particles between terminal panels
- Handle orchestration commands in execute_command()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The panels were comparing screen-space clip rect with canvas-space
panel rect, which never intersected. The app already does proper
culling via viewport.is_visible() before calling show().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When orchestration is activated, each terminal now receives:
1. export VOID_TEAM_NAME/VOID_ROLE/VOID_GROUP_ID env vars
2. The full coordination prompt (leader or worker variant) echoed
   into the terminal so agents see void-ctl commands and their role

Also fixes kanban/network not visible on canvas (broken frustum cull
was comparing screen-space vs canvas-space coordinates).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite leader prompt with full CLI reference, worker list, workflow
  guide, context sharing instructions, and spawn commands
- Rewrite worker prompt with worker loop protocol (check tasks → work →
  report → check inbox → repeat), self-assign, blocker reporting
- Inject protocol via heredoc to /tmp file (clean, no escaping issues)
- Export VOID_ORCHESTRATION_PROTOCOL path so agents can read it
- Display protocol in terminal via cat so agents see it immediately
- Add void-ctl task wait (blocking poll with progress display)
- Fix void-ctl spawn to auto-join caller's group via VOID_TEAM_NAME env
- Fix app spawn handler to auto-join new terminals to requested group

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PendingSpawn now carries an optional `command` field
- void-ctl spawn defaults to launching "claude" when in a team
- void-ctl spawn accepts --command flag for other agents (codex, etc.)
- App spawn handler executes the command in the new terminal after spawn
- App spawn handler injects worker env vars + coordination prompt
- Leader prompt updated: explains void-ctl spawn auto-launches Claude,
  documents the full autonomous workflow (spawn → list → create tasks)
- void-ctl task wait: blocking poll with live progress display

The leader Claude can now do this autonomously:
  void-ctl spawn              → new terminal with Claude appears
  void-ctl list               → see worker ID
  void-ctl task create "..." --assign <ID>  → assign work
  void-ctl task wait --all    → wait for completion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The injection was using Unix-only commands (export, cat, mkdir -p,
heredocs, /tmp/) which fail on Windows CMD.

Now:
- Protocol files are written from Rust via std::fs::write (no shell)
- Protocol dir uses std::env::temp_dir() (cross-platform)
- Env vars use `set` on Windows, `export` on Unix
- File display uses `type` on Windows, `cat` on Unix
- Same fix applied to both initial activation and worker spawn

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of injecting shell commands (set/export/cat/type) which fail
when an agent like Claude is already running in the terminal, now:

1. Write protocol file to disk from Rust (cross-platform)
2. Inject the prompt TEXT directly into the PTY as raw bytes
3. The agent (Claude) reads it as user input, like ClawTeam's
   tmux paste-buffer approach
4. Send double-Enter to confirm submission

This means:
- If Claude is running → it reads the prompt as a user message
- If a shell is running → the text appears as pasted comments
- Works on Windows AND Unix
- No shell command escaping issues

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Click "Enable Orchestration" → everything happens automatically:
1. New leader terminal spawns
2. "claude" launches in it automatically
3. After 4s delay (CLI startup), the leader prompt is injected
4. Claude reads it as user input and starts orchestrating
5. When Claude does void-ctl spawn, new worker terminals auto-spawn
   with claude + worker prompt (also deferred 4s)

Uses deferred injection queue (pending_injections) to wait for the
agent CLI to be ready before pasting the prompt — same approach as
ClawTeam's _wait_for_cli_ready + tmux paste-buffer.

No manual terminal opening, no manual claude launching, no manual
prompt copying. One click → full swarm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Like ClawTeam: protocol goes into --append-system-prompt (invisible),
kick-off message goes into -p (first user message). User sees nothing
except Claude starting to work.

Leader launch: claude --dangerously-skip-permissions \
  --append-system-prompt "$(cat protocol.md)" \
  -p "You are the LEADER. Spawn workers and assign tasks."

Worker launch: claude --dangerously-skip-permissions \
  --append-system-prompt "$(cat protocol.md)" \
  -p "You are a WORKER. Check tasks and start working."

Windows uses PowerShell to read the file, Unix uses $() subshell.
Removed deferred injection system (no longer needed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oggles + PRD

Key fixes:
- Launch Claude in interactive TUI mode instead of one-shot -p mode
  (Claude stays running and accepts commands)
- Delayed prompt injection: wait 5s for Claude to boot, then inject
  leader/worker protocol as a typed message
- Kanban/Network visibility toggles now actually hide panels
- FocusTerminal from kanban cards and network nodes works (bring_to_front)
- void-ctl PATH: prepend exe directory so void-ctl is always reachable
- Add orchestration-prd.md (5120 lines — complete specification)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant