v2.0 proposal: BooCoder — write tools, pending changes, ACP dispatch, MCP server
Comprehensive roadmap for the v2.0 major version bump. Covers: - Schema: pending_changes, tasks, available_agents tables + human_inbox view - Path A: native write tools (edit_file, create_file, delete_file) queuing through pending_changes before /apply flushes to disk - Path B: external agent dispatch via ACP (opencode, goose) or PTY fallback (claude, pi) with per-task git worktrees and automatic diff-on-completion - BooCoder MCP server: 6 tools exposing task primitives over stdio - Code lifts: agent-hub (Apache-2.0, task DAG), plandex (MIT, diff UX), ACP SDK (Apache-2.0, subprocess protocol), Paseo (AGPL, design-only) - Sub-versions: v2.0.0 (Path A), v2.0.1 (Path B), v2.0.2 (MCP server), v2.0.3 (CLI + polish) - Estimate: ~2200 LoC total All v1.x dependencies shipped (v1.13 parts, v1.14 outer loop, v1.15 MCP client, v1.16 codesight). v2.0 is unblocked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
274
openspec/changes/v2.0-boocoder/proposal.md
Normal file
274
openspec/changes/v2.0-boocoder/proposal.md
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
# v2.0 — BooCoder
|
||||||
|
|
||||||
|
Major version bump. New app `apps/coder/` inside the existing monorepo. Lands together with the `boocode_db` → `boochat_db` DB rename and the per-app subdomain split (`code.indifferentketchup.com` → BooChat, `coder.indifferentketchup.com` → BooCoder).
|
||||||
|
|
||||||
|
## What BooCoder is
|
||||||
|
|
||||||
|
A write-capable coding agent surface. Two execution paths, same UI:
|
||||||
|
|
||||||
|
- **Path A (native):** BooCode's own inference loop with write tools (`edit_file`, `create_file`, `delete_file`). Edits queue in `pending_changes` — nothing touches disk until user approves via `/apply`.
|
||||||
|
- **Path B (dispatch):** Shells out to external CLI agents (`opencode`, `goose`, `claude`, `pi`) via ACP (preferred) or raw PTY (fallback). One git worktree per dispatch. Captures events into the same parts taxonomy.
|
||||||
|
|
||||||
|
Both paths feed the same task DAG, same project registry, same pending-changes queue, same UI.
|
||||||
|
|
||||||
|
## Why now
|
||||||
|
|
||||||
|
v1.x proved the read-only loop works end-to-end: inference, tool dispatch, streaming, compaction, MCP client, outer loop, step caps, artifact rendering. The infrastructure is stable. The jump from "read-only chat" to "write-capable agent orchestrator" is the remaining gap between BooCode and having a real development environment.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Three protocol roles (locked 2026-05-22)
|
||||||
|
|
||||||
|
1. **MCP client (write-capable allowed).** Inherits v1.15 client. Write-capable MCP servers (e.g. `@modelcontextprotocol/server-filesystem`) route writes through `pending_changes`. Per-task allow/deny means dispatched tasks can have a different MCP roster.
|
||||||
|
2. **MCP server (BooCoder's own primitives).** Exposes `boocoder.create_task`, `boocoder.list_pending_changes`, `boocoder.apply`, `boocoder.reject`, `boocoder.dispatch_external_agent`, `boocoder.list_worktrees` as MCP tools. Stdio transport for local consumers (Sam's `opencode` in Termius); HTTP deferred until OAuth + secret storage.
|
||||||
|
3. **ACP client (host).** Spawns `opencode acp` and `goose acp` as JSON-RPC stdio subprocesses. Maps ACP events (file operations, tool calls, terminal output) to BooCode's parts taxonomy. MCP servers configured in BooCoder are auto-forwarded to the dispatched agent (per goose docs — `context_servers` is the field).
|
||||||
|
|
||||||
|
### Container layout (post-v2.0)
|
||||||
|
|
||||||
|
| Container | Port | Mount | Purpose |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `boochat` (was `boocode`) | `100.114.205.53:9500` | `/opt:/opt:ro` | Read-only chat + MCP client |
|
||||||
|
| `booterm` | `100.114.205.53:9501` | `/opt:/opt:rw` | PTY/tmux terminal |
|
||||||
|
| `boocoder` | `100.114.205.53:9502` | `/opt:/opt:rw` (policy-gated) | Write tools + ACP host + MCP client + MCP server |
|
||||||
|
| `boochat_db` (was `boocode_db`) | `127.0.0.1:5500` | `boocode_pgdata` | Shared Postgres 16 |
|
||||||
|
| `codecontext` | internal `:8080` | `/opt:/opt:ro` | Analysis sidecar (shared) |
|
||||||
|
|
||||||
|
### Caddy routing
|
||||||
|
|
||||||
|
```
|
||||||
|
code.indifferentketchup.com → boochat:9500
|
||||||
|
coder.indifferentketchup.com → boocoder:9502
|
||||||
|
term.indifferentketchup.com → booterm:9501 (or routed under code.*/term/)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schema (new tables)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Pending changes: queued writes before /apply
|
||||||
|
CREATE TABLE IF NOT EXISTS pending_changes (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
session_id UUID NOT NULL REFERENCES sessions(id),
|
||||||
|
task_id UUID REFERENCES tasks(id),
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
operation TEXT NOT NULL CHECK (operation IN ('create', 'edit', 'delete')),
|
||||||
|
diff TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'applied', 'rejected', 'reverted')),
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tasks: the dispatch DAG
|
||||||
|
CREATE TABLE IF NOT EXISTS tasks (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
project_id UUID NOT NULL REFERENCES projects(id),
|
||||||
|
parent_task_id UUID REFERENCES tasks(id),
|
||||||
|
state TEXT NOT NULL DEFAULT 'pending'
|
||||||
|
CHECK (state IN ('pending', 'running', 'completed', 'failed', 'blocked', 'cancelled')),
|
||||||
|
input TEXT NOT NULL,
|
||||||
|
output_summary TEXT,
|
||||||
|
agent TEXT,
|
||||||
|
model TEXT,
|
||||||
|
execution_path TEXT CHECK (execution_path IN ('native', 'acp', 'pty')),
|
||||||
|
worktree_path TEXT,
|
||||||
|
cost_tokens INTEGER,
|
||||||
|
started_at TIMESTAMPTZ,
|
||||||
|
ended_at TIMESTAMPTZ,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Available agents: probed at startup
|
||||||
|
CREATE TABLE IF NOT EXISTS available_agents (
|
||||||
|
name TEXT PRIMARY KEY,
|
||||||
|
install_path TEXT,
|
||||||
|
version TEXT,
|
||||||
|
supports_acp BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
supports_mcp_client BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
last_probed_at TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Human inbox: tasks needing attention
|
||||||
|
CREATE VIEW human_inbox AS
|
||||||
|
SELECT * FROM tasks WHERE state IN ('blocked', 'failed');
|
||||||
|
```
|
||||||
|
|
||||||
|
`task_templates` and `pipelines` deferred to v2.1 — overhead for single-user. The core is `tasks` + `pending_changes` + `available_agents`.
|
||||||
|
|
||||||
|
## Path A — Native write tools
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `edit_file` | Apply a diff to an existing file. Input: `{file_path, old_string, new_string}`. Queues in `pending_changes` with `operation='edit'`. |
|
||||||
|
| `create_file` | Create a new file. Input: `{file_path, content}`. Queues as `operation='create'`. |
|
||||||
|
| `delete_file` | Delete a file. Input: `{file_path}`. Queues as `operation='delete'`. |
|
||||||
|
| `apply_pending` | Flush all pending changes for the current session to disk. Path-guarded. |
|
||||||
|
| `rewind` | Revert a specific applied change or all changes since a checkpoint. |
|
||||||
|
|
||||||
|
### Path guard for writes
|
||||||
|
|
||||||
|
Same `pathGuard()` function from BooChat, but with a write-path variant:
|
||||||
|
- `resolveWritePath(projectRoot, requested)` — uses `resolve()` (not `realpath()`, since the file may not exist yet for creates), then verifies the result starts with `projectRoot + sep`.
|
||||||
|
- Deny list: everything in `secret_guard.ts` (`.env`, `*.pem`, etc.) — can't write to those either.
|
||||||
|
- Defense-in-depth: the `pending_changes` queue means even a path-guard bypass only queues; it doesn't hit disk until `/apply` (which re-validates).
|
||||||
|
|
||||||
|
### Diff format
|
||||||
|
|
||||||
|
Standard unified diff (what `git diff` produces). The `edit_file` tool takes `old_string` / `new_string` (same as Claude Code's edit tool — the model is trained on this shape). Server computes the unified diff for storage in `pending_changes.diff`.
|
||||||
|
|
||||||
|
### UI: per-pane diff viewer
|
||||||
|
|
||||||
|
Frontend pane type `pending_changes` in BooCoder's workspace. Shows:
|
||||||
|
- List of queued changes with file path + operation
|
||||||
|
- Per-change diff view (syntax-highlighted, side-by-side or unified)
|
||||||
|
- Approve / Reject per change, or Approve All / Reject All
|
||||||
|
|
||||||
|
## Path B — External agent dispatch
|
||||||
|
|
||||||
|
### dispatch_external_agent tool
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
agent: 'opencode' | 'claude' | 'goose' | 'pi',
|
||||||
|
model: string, // e.g. 'claude-opus-4-7'
|
||||||
|
task: string, // natural-language task description
|
||||||
|
worktree?: string, // optional — auto-creates if not specified
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transport selection
|
||||||
|
|
||||||
|
Dispatcher checks `available_agents.supports_acp` at runtime:
|
||||||
|
- **ACP** (preferred): `opencode acp`, `goose acp` — JSON-RPC stdio. Native session lifecycle, file-operation events, terminal events, permission prompts.
|
||||||
|
- **PTY** (fallback): `claude`, `pi`, `smallcode` — raw terminal capture via `node-pty`. Captures stdout/stderr/exit-code into PostgreSQL. Less structured than ACP.
|
||||||
|
|
||||||
|
### Worktree management
|
||||||
|
|
||||||
|
Each dispatched task gets its own git worktree:
|
||||||
|
```bash
|
||||||
|
git worktree add /tmp/booworktrees/<task-id> -b task-<task-id> HEAD
|
||||||
|
```
|
||||||
|
|
||||||
|
On completion: diff the worktree against HEAD, queue the diff into `pending_changes` for the same task, clean up the worktree. User approves/rejects the diff the same way as Path A.
|
||||||
|
|
||||||
|
### ACP event mapping
|
||||||
|
|
||||||
|
ACP events → BooCode parts taxonomy:
|
||||||
|
- `file_operation` → `tool_call` part (name: `acp_edit_file`) + `tool_result` part
|
||||||
|
- `tool_call` → `tool_call` part (preserves name)
|
||||||
|
- `terminal_output` → routes into BooTerm pane
|
||||||
|
- `permission_request` → pause inference (same mechanism as `ask_user_input`)
|
||||||
|
- `session_end` → task state → `completed` or `failed`
|
||||||
|
|
||||||
|
### MCP server auto-forward
|
||||||
|
|
||||||
|
Per goose docs, `context_servers` field in the ACP session config auto-forwards BooCoder's configured MCP servers to the dispatched agent. One MCP config drives every agent.
|
||||||
|
|
||||||
|
## Dispatcher worker
|
||||||
|
|
||||||
|
Background process (or in-process `setInterval` for v2.0 simplicity) that:
|
||||||
|
1. Queries `tasks` WHERE `state = 'pending'` ORDER BY `created_at`
|
||||||
|
2. For each ready task (no unmet dependencies):
|
||||||
|
- Mark `state = 'running'`
|
||||||
|
- Resolve execution path (Path A if no agent specified, Path B if agent specified)
|
||||||
|
- Path A: run the inference loop with write tools enabled
|
||||||
|
- Path B: spawn ACP/PTY subprocess, stream events into parts
|
||||||
|
- On completion: mark `state = 'completed'` or `'failed'`
|
||||||
|
- Queue output diff into `pending_changes`
|
||||||
|
3. On failure: mark `state = 'failed'`, surface in `human_inbox` view
|
||||||
|
|
||||||
|
## BooCoder MCP server
|
||||||
|
|
||||||
|
Exposes BooCoder's primitives as MCP tools so external agents (Sam's opencode in Termius) can drive the task queue:
|
||||||
|
|
||||||
|
| MCP Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `boocoder.create_task` | Create a new task in the queue |
|
||||||
|
| `boocoder.list_pending_changes` | List queued changes awaiting approval |
|
||||||
|
| `boocoder.apply` | Apply a specific pending change |
|
||||||
|
| `boocoder.reject` | Reject a pending change |
|
||||||
|
| `boocoder.dispatch_external_agent` | Dispatch a task to an external agent |
|
||||||
|
| `boocoder.list_worktrees` | List active git worktrees |
|
||||||
|
|
||||||
|
Stdio transport for local consumers. HTTP transport deferred until OAuth + secret storage.
|
||||||
|
|
||||||
|
**Eval requirement:** run through `anthropics/skills mcp-builder` 10-question evaluation framework before shipping.
|
||||||
|
|
||||||
|
## Code lifts
|
||||||
|
|
||||||
|
### Primary architectural template
|
||||||
|
|
||||||
|
**`Dominic789654/agent-hub`** (Apache-2.0) — task DAG schema, dispatcher worker, project registry, human inbox. Three-process model (board server + dispatcher + assistant terminal). BooCode adapts this into a single-process Fastify app (v2.0.0) with the dispatcher as an in-process worker.
|
||||||
|
|
||||||
|
### Pending-changes UX
|
||||||
|
|
||||||
|
**`plandex-ai/plandex`** (MIT) — diff/apply/rewind vocabulary. The `pending_changes` queue concept, per-file diff view, approve/reject UI pattern. No code lifted — schema and UX design only.
|
||||||
|
|
||||||
|
### ACP client
|
||||||
|
|
||||||
|
**`agentclientprotocol.com` spec + `@zed-industries/agent-client-protocol` SDK** (Apache-2.0) — local-subprocess ACP via stdio JSON-RPC. The SDK handles framing; BooCode maps events to its parts taxonomy.
|
||||||
|
|
||||||
|
**`goose` docs** (`goose-docs.ai/docs/guides/acp-clients/`) — `context_servers` auto-forward pattern. Critical: one MCP config drives every dispatched agent.
|
||||||
|
|
||||||
|
### MCP server
|
||||||
|
|
||||||
|
**`anthropics/skills/mcp-builder`** (MIT) — 4-phase build workflow + 10-question evaluation framework for validating the MCP server before shipping.
|
||||||
|
|
||||||
|
### Dispatcher pattern
|
||||||
|
|
||||||
|
**Paseo (`getpaseo/paseo`)** — AGPL-3.0, **design only, no code lift**. Daemon+clients architecture, `--worktree` flag, CLI verb shape (`run/ls/attach/send`). BooCode reproduces the architecture using only license-clean patterns.
|
||||||
|
|
||||||
|
**Roo Code Boomerang Tasks** — orchestrator with intentional capability restriction. Down-pass/up-pass context discipline (`new_task` message, `attempt_completion` result, no implicit inheritance). Explicit precedence override clause.
|
||||||
|
|
||||||
|
### Write-tool security
|
||||||
|
|
||||||
|
**opencode `permission/evaluate.ts`** — wildcard permission ruleset (already lifted in v1.15). Extended in v2.0 to gate write tools.
|
||||||
|
|
||||||
|
**`covibes/zeroshot`** — blind-validation invariant. Verify gate runs in a separate agent context that only sees the diff and acceptance criteria, not the producing conversation. v2.0+ optional batch.
|
||||||
|
|
||||||
|
## Sub-versions
|
||||||
|
|
||||||
|
| Version | Scope |
|
||||||
|
|---|---|
|
||||||
|
| **v2.0.0** | Schema + Path A (native write tools + pending-changes queue + diff UI) + basic dispatcher |
|
||||||
|
| **v2.0.1** | Path B (ACP client for opencode/goose + PTY fallback for claude/pi + worktree management) |
|
||||||
|
| **v2.0.2** | BooCoder MCP server (stdio transport, `boocoder.*` tools, eval framework) |
|
||||||
|
| **v2.0.3** | Polish: `boocode` CLI (`run/ls/attach/send`), human_inbox UI, cost tracking |
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- v1.13 ✅ (parts table — the event taxonomy for everything)
|
||||||
|
- v1.14 ✅ (outer loop + step boundaries for future revert snapshots)
|
||||||
|
- v1.14.x-mcp ✅ (MCP client PoC — proves the protocol)
|
||||||
|
- v1.15 ✅ (full MCP client + tool globs — write-capable MCP servers route through pending_changes)
|
||||||
|
- v1.16 ✅ (codesight merge — codecontext now has blast-radius for impact analysis)
|
||||||
|
|
||||||
|
All dependencies shipped. v2.0 is unblocked.
|
||||||
|
|
||||||
|
## Estimate
|
||||||
|
|
||||||
|
- v2.0.0: ~800 LoC (schema + write tools + pending-changes service + diff pane + dispatcher skeleton)
|
||||||
|
- v2.0.1: ~600 LoC (ACP client + PTY dispatch + worktree management + event mapping)
|
||||||
|
- v2.0.2: ~400 LoC (MCP server + 6 tool handlers + stdio transport + eval)
|
||||||
|
- v2.0.3: ~400 LoC (CLI client + inbox UI + cost aggregation)
|
||||||
|
- **Total: ~2200 LoC** across 4 sub-versions
|
||||||
|
|
||||||
|
## Hard rules
|
||||||
|
|
||||||
|
- BooChat stays read-only. BooCoder is the only surface with write tools.
|
||||||
|
- Path-guard correctness is the #1 test target. Fuzz against every traversal pattern.
|
||||||
|
- Pending-changes queue gates ALL writes (native + MCP). Nothing touches disk without user approval (or explicit auto-apply flag per task).
|
||||||
|
- One shared database. Cross-surface joins are valuable (task → chat → terminal debugging session).
|
||||||
|
- External CLI agents on the host, not in containers. BooCoder shells out via local-exec.
|
||||||
|
- No OAuth in v2.0. MCP server is stdio-only until secret storage lands.
|
||||||
|
- DB rename `boocode_db` → `boochat_db` lands with v2.0.0 (one-time migration).
|
||||||
|
|
||||||
|
## Repos to clone before starting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/forks
|
||||||
|
git clone https://github.com/Dominic789654/agent-hub.git # Apache-2.0, task DAG reference
|
||||||
|
git clone https://github.com/plandex-ai/plandex.git # MIT, pending-changes UX
|
||||||
|
git clone https://github.com/anomalyco/opencode.git # MIT, permission evaluate.ts + MCP client reference
|
||||||
|
```
|
||||||
|
|
||||||
|
ACP SDK is an npm package (`@zed-industries/agent-client-protocol`), installed at implementation time. Paseo is design-only (AGPL, no code lift).
|
||||||
130
openspec/changes/v2.0-boocoder/tasks.md
Normal file
130
openspec/changes/v2.0-boocoder/tasks.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# v2.0 — BooCoder task breakdown
|
||||||
|
|
||||||
|
## Phase 0 — Prep (before any code)
|
||||||
|
|
||||||
|
- [ ] Clone lift sources: `agent-hub`, `plandex`, `opencode` to `/opt/forks/`
|
||||||
|
- [ ] Read agent-hub's schema + dispatcher pattern (Apache-2.0)
|
||||||
|
- [ ] Read plandex's pending-changes + diff/apply/rewind flow (MIT)
|
||||||
|
- [ ] Read opencode's `permission/evaluate.ts` for write-gate patterns (MIT)
|
||||||
|
- [ ] Install ACP SDK: `pnpm add @zed-industries/agent-client-protocol`
|
||||||
|
- [ ] Verify `opencode acp` and `goose acp` are available on the host
|
||||||
|
- [ ] Write `openspec/changes/v2.0-boocoder/design.md` with finalized decisions
|
||||||
|
|
||||||
|
## v2.0.0 — Schema + Path A (native write tools + pending-changes + diff UI)
|
||||||
|
|
||||||
|
### Infra
|
||||||
|
|
||||||
|
- [ ] Create `apps/coder/` directory skeleton (Fastify server, mirroring `apps/server/` structure)
|
||||||
|
- [ ] Create `apps/coder/Dockerfile` (Node 20 bookworm-slim, `/opt:/opt:rw` mount)
|
||||||
|
- [ ] Add `boocoder` service to `docker-compose.yml` (port 9502, boocode_net)
|
||||||
|
- [ ] Add Caddy route: `coder.indifferentketchup.com` → boocoder:9502
|
||||||
|
- [ ] DB rename: `boocode_db` → `boochat_db` (one-time ALTER DATABASE + docker-compose volume rename)
|
||||||
|
- [ ] Schema migration: CREATE TABLE `pending_changes`, `tasks`, `available_agents`; CREATE VIEW `human_inbox`
|
||||||
|
- [ ] Container guidance: `BOOCODER.md` (bind-mounted at `/app/BOOCODER.md`)
|
||||||
|
|
||||||
|
### Write tools
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/services/write_guard.ts` — `resolveWritePath(projectRoot, filePath)` (resolve + prefix-check, no realpath since file may not exist)
|
||||||
|
- [ ] `apps/coder/src/services/pending_changes.ts` — queue, apply, reject, revert operations
|
||||||
|
- [ ] Tool: `edit_file` — takes `{file_path, old_string, new_string}`, computes unified diff, queues in `pending_changes`
|
||||||
|
- [ ] Tool: `create_file` — takes `{file_path, content}`, queues as `operation='create'`
|
||||||
|
- [ ] Tool: `delete_file` — takes `{file_path}`, queues as `operation='delete'`
|
||||||
|
- [ ] Tool: `apply_pending` — flushes pending changes to disk (re-validates write_guard before each write)
|
||||||
|
- [ ] Tool: `rewind` — reverts applied changes by inverse-diff
|
||||||
|
|
||||||
|
### Inference loop
|
||||||
|
|
||||||
|
- [ ] Port the v1.14 outer loop from `apps/server/` into `apps/coder/` (or share via workspace package)
|
||||||
|
- [ ] Register write tools in the coder's tool registry (alongside all read tools from BooChat)
|
||||||
|
- [ ] Permission gate: write tools require `pending_changes` queue (can't bypass to direct disk write)
|
||||||
|
|
||||||
|
### Frontend (diff pane)
|
||||||
|
|
||||||
|
- [ ] Create `apps/coder/web/` SPA (React + Vite, same stack as BooChat's `apps/web/`)
|
||||||
|
- [ ] Diff pane component: shows pending changes with syntax-highlighted diffs
|
||||||
|
- [ ] Approve / Reject per change, Approve All / Reject All buttons
|
||||||
|
- [ ] Workspace splitter integration (chat pane + diff pane side by side)
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
- [ ] `pnpm -C apps/coder build` clean
|
||||||
|
- [ ] Write path-guard fuzz tests (traversal patterns, symlinks, non-existent paths, `.env` deny)
|
||||||
|
- [ ] `docker compose up --build -d` — boocoder container starts, healthcheck passes
|
||||||
|
- [ ] Smoke: send a chat requesting a file edit → see it queued in diff pane → approve → file written
|
||||||
|
|
||||||
|
## v2.0.1 — Path B (ACP dispatch + PTY fallback + worktrees)
|
||||||
|
|
||||||
|
### ACP client
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/services/acp-client.ts` — spawn `opencode acp` / `goose acp` via `@zed-industries/agent-client-protocol` StdioTransport
|
||||||
|
- [ ] Event mapping: ACP `file_operation` → `tool_call` part, `terminal_output` → BooTerm route, `permission_request` → pause
|
||||||
|
- [ ] Session lifecycle: start, mid-session model switch, end
|
||||||
|
- [ ] MCP auto-forward: pass BooCoder's `context_servers` config to the ACP session
|
||||||
|
|
||||||
|
### PTY fallback
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/services/pty-dispatch.ts` — spawn `claude` / `pi` / `smallcode` via `node-pty`
|
||||||
|
- [ ] Capture stdout/stderr/exit-code into parts (less structured than ACP)
|
||||||
|
- [ ] Worktree setup: `git worktree add /tmp/booworktrees/<task-id> -b task-<task-id> HEAD`
|
||||||
|
- [ ] On completion: diff worktree vs HEAD → queue into `pending_changes`
|
||||||
|
|
||||||
|
### Dispatcher
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/services/dispatcher.ts` — polls `tasks` WHERE `state='pending'`, picks by priority + creation order
|
||||||
|
- [ ] Transport selection: check `available_agents.supports_acp` at dispatch time
|
||||||
|
- [ ] On failure: mark `state='failed'`, surface in `human_inbox`
|
||||||
|
- [ ] On completion: mark `state='completed'`, queue diff if Path B
|
||||||
|
|
||||||
|
### Agent probing
|
||||||
|
|
||||||
|
- [ ] Startup probe: `which opencode && opencode --version`, `which goose`, `which claude`, `which pi`
|
||||||
|
- [ ] Populate `available_agents` table with version + ACP support
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
- [ ] Smoke: dispatch a task to `opencode` via ACP → task completes → diff queued
|
||||||
|
- [ ] Smoke: dispatch to `claude` via PTY fallback → captures output → diff from worktree
|
||||||
|
- [ ] Worktree cleanup after task completion
|
||||||
|
|
||||||
|
## v2.0.2 — BooCoder MCP server
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/services/mcp-server.ts` — register 6 tools as MCP tool handlers
|
||||||
|
- [ ] Stdio transport (use `@modelcontextprotocol/sdk` server-side, same SDK as client)
|
||||||
|
- [ ] Tools: `boocoder.create_task`, `boocoder.list_pending_changes`, `boocoder.apply`, `boocoder.reject`, `boocoder.dispatch_external_agent`, `boocoder.list_worktrees`
|
||||||
|
- [ ] Each tool maps to a DB operation or service call
|
||||||
|
|
||||||
|
### Eval
|
||||||
|
|
||||||
|
- [ ] Write 10-question eval per `anthropics/skills/mcp-builder` framework
|
||||||
|
- [ ] Run eval against the MCP server — all 10 must pass before shipping
|
||||||
|
- [ ] Document eval results in openspec
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
- [ ] From a terminal: `echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | boocoder --mcp` → returns 6 tools
|
||||||
|
- [ ] From opencode: configure BooCoder as an MCP server in `~/.opencode/config.json`, verify tool calls work
|
||||||
|
|
||||||
|
## v2.0.3 — Polish
|
||||||
|
|
||||||
|
### CLI client
|
||||||
|
|
||||||
|
- [ ] `apps/coder/src/cli.ts` — thin WebSocket/HTTP client against BooCoder API
|
||||||
|
- [ ] Verbs: `boocode run <task>`, `boocode ls`, `boocode attach <id>`, `boocode send <id> <message>`
|
||||||
|
- [ ] Mirrors Paseo's UX, license-clean implementation
|
||||||
|
|
||||||
|
### Human inbox UI
|
||||||
|
|
||||||
|
- [ ] Frontend route showing tasks in `blocked`/`failed` state
|
||||||
|
- [ ] Per-task: view output, retry, cancel, reassign to different agent
|
||||||
|
|
||||||
|
### Cost tracking
|
||||||
|
|
||||||
|
- [ ] `tasks.cost_tokens` populated from inference usage
|
||||||
|
- [ ] Summary view: per-project, per-agent, per-day token spend
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
- [ ] `boocode run "add a health endpoint"` from terminal → task appears in UI → completes → diff in pane
|
||||||
|
- [ ] `boocode ls` shows running/completed/failed tasks
|
||||||
Reference in New Issue
Block a user