docs(changelog): v2.6.7-interrupt-guard + reconcile roadmap/review/openspec
CHANGELOG entry for v2.6.7. Plus the session's doc reconciliation: roadmap shipped record synced through v2.6.7 (v2.3 lifecycle marked shipped, relicense AGPL->MIT batch, fork-sweep lift items, claude-agent-sdk SessionStore, ACP package fix); boocode_code_review_v2 (two fork sweeps, relicense decision = 3 AGPL files, jinja gate green); openspec v2-3 reconciled to shipped (v2.5.4-v2.5.13); openspec v2-6 Phase 0/1 + P1.5 shipped, F.1 done, remaining-phase plan + lift sources. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ Last updated: 2026-05-31
|
||||
BooCode is a **3-app monorepo** at `/opt/boocode/` (locked 2026-05-22):
|
||||
|
||||
- **BooChat** (`apps/server` + `apps/web`, port `9500`, `code.indifferentketchup.com`) — read-only chat with file-inspection tools. Backend in `apps/server`, SPA in `apps/web`. Database `boochat` (renamed from `boocode` at v2.0).
|
||||
- **BooCoder** (`apps/coder`, port `9502`, `coder.indifferentketchup.com`) — write tools + external-CLI dispatch. **Shipped v2.0.0–v2.6.4.** Host systemd service (not Docker since v2.1.0). In-process inference (with `pending_changes` table) AND Paseo-style ACP dispatch for five providers (opencode, goose, claude, qwen + native boocode; cursor + copilot retired at v2.5.3) with PTY fallback where ACP is unavailable. Provider lifecycle is config-backed (`data/coder-providers.json`, enable/disable, two-tier probe — shipped v2.5.4–v2.5.13). opencode now runs as a **warm HTTP server** with persistent per-chat sessions (v2.6 Phase 1); goose/qwen/claude still dispatch one-shot.
|
||||
- **BooCoder** (`apps/coder`, port `9502`, `coder.indifferentketchup.com`) — write tools + external-CLI dispatch. **Shipped v2.0.0–v2.6.6** (repo tag line; v2.6.5–v2.6.6 were BooChat workspace UX + docs). Host systemd service (not Docker since v2.1.0). In-process inference (with `pending_changes` table) AND Paseo-style ACP dispatch for five providers (opencode, goose, claude, qwen + native boocode; cursor + copilot retired at v2.5.3) with PTY fallback where ACP is unavailable. Provider lifecycle is config-backed (`data/coder-providers.json`, enable/disable, two-tier probe — shipped v2.5.4–v2.5.13). opencode now runs as a **warm HTTP server** with persistent per-chat sessions (v2.6 Phase 1); goose/qwen/claude still dispatch one-shot.
|
||||
- **BooTerm** (`apps/booterm`, port `9501`) — PTY/tmux/xterm.js. **Live since May 2026.** bookworm-slim + node-pty + tmux + xterm.js. Tmux session per pane (`bc-<uuid>`), SSH-out works (openssh-client + gosu in the image). Shares Postgres database `boochat`.
|
||||
|
||||
Caddy → Authelia → Tailscale → `100.114.205.53` → 9500/9501/9502. Three apps, **one shared Postgres** (Docker service `boocode_db`, database name `boochat`).
|
||||
@@ -21,7 +21,7 @@ Caddy → Authelia → Tailscale → `100.114.205.53` → 9500/9501/9502. Three
|
||||
- **Mount strategy: blanket `/opt:rw`, permission gating at the write-tool layer.** Per-project scoping is policy, not mount. Path-guard correctness is the #1 test target for v2.0.
|
||||
- **External CLI agents (`opencode`/`claude`/`goose`/`pi`) live on the host, not in containers.** BooCoder shells out via local-exec PTY or ACP subprocess. Host install inherits Sam's existing `~/.opencode/`, `~/.claude/`, `~/.config/goose/` configs.
|
||||
- **Protocol roles locked (2026-05-22):** **BooChat = MCP client only** (read-only tool consumer, never enables write-capable MCP servers). **BooCoder = MCP client + MCP server + ACP client (host) + ACP agent (driveable)** — full matrix. BooCoder's ACP-client role replaces raw-PTY dispatch for ACP-capable agents (opencode `opencode acp`, goose `goose acp`); PTY fallback retained for claude/pi/smallcode.
|
||||
- **Paseo-equivalent dispatcher inside BooCode** (2026-05-22 pivot, **shipped v2.2**). Paseo (`getpaseo/paseo`) is AGPL-3.0 — incompatible with BooCode's MIT license and network-served deployment. BooCode reproduces the architecture using license-clean patterns only (`provider-snapshot.ts`, ACP merge/stream/persist, `AgentComposerBar`). Primary architectural template: `Dominic789654/agent-hub` (Apache-2.0). Critical context-management primitive: Roo Code Boomerang Tasks pattern. Observation pattern: Claude Code hooks (siropkin/budi reference).
|
||||
- **Paseo-equivalent dispatcher inside BooCode** (2026-05-22 pivot, **shipped v2.2**). Paseo (`getpaseo/paseo`) is AGPL-3.0 — incompatible with BooCode's **target** MIT license and network-served deployment (the tree is *currently* AGPL-3.0 via the v2.4 Unsloth-Studio lifts — see the **License-debt → relicense to MIT** batch; the Paseo pattern-only rule holds regardless). BooCode reproduces the architecture using license-clean patterns only (`provider-snapshot.ts`, ACP merge/stream/persist, `AgentComposerBar`). Primary architectural template: `Dominic789654/agent-hub` (Apache-2.0). Critical context-management primitive: Roo Code Boomerang Tasks pattern. Observation pattern: Claude Code hooks (siropkin/budi reference).
|
||||
|
||||
External code lifted from / referenced in: see `boocode_code_review.md` for full inventory.
|
||||
|
||||
@@ -348,7 +348,7 @@ Per-session Docker sandbox spawned by BooCoder on first write. Only project path
|
||||
|
||||
-----
|
||||
|
||||
## Shipped (v2.2.2–v2.6.4 — interactive ACP, provider lifecycle, persistent agent sessions)
|
||||
## Shipped (v2.2.2–v2.6.7 — interactive ACP, provider lifecycle, persistent agent sessions, workspace UX)
|
||||
|
||||
All tags `vMAJOR.MINOR.PATCH-slug`, monotonic per minor, assigned at ship time (planning slugs differ — see the numbering-discipline note below). `CHANGELOG.md` is the canonical per-tag record. **Note on numbering divergence:** the *planned-feature* "v2.3 — Provider lifecycle" actually shipped under the **v2.5.4–v2.5.13** tags; the *planned-feature* "v2.4 — BooCoder as ACP agent" remains **unshipped** even though v2.4.0/v2.4.1 *tags* shipped unrelated content (Unsloth lifts, sidecar routing). The patch-tag thread and the conceptual-milestone thread have diverged — read tags as the ship record, the `## v2.x` feature sections below as the milestone plan. The v2.3.0–v2.5.1 tags were never CHANGELOG-backfilled; summarized here from commit bodies.
|
||||
|
||||
@@ -356,7 +356,7 @@ All tags `vMAJOR.MINOR.PATCH-slug`, monotonic per minor, assigned at ship time (
|
||||
- `v2.3.0-sampling-params-ask-user` — per-agent sampling params (`top_p`/`top_k`/`min_p`/`presence_penalty`) in AGENTS.md frontmatter threaded through inference (null = omit, preserve provider default); `ask_user_input` interactive card wired into both BooCoder frontends (CoderPane + standalone coder SPA)
|
||||
- `v2.3.1-permission-questions` — enrich ACP `permission_requested` frame with `kind` (`tool`|`question`|`plan`|`elicitation`) + `input` + `description`; PermissionCard renders interactive radio/checkbox forms for AskUserQuestion; ACP `createElicitation` (experimental) JSON-Schema-driven forms
|
||||
- `v2.3.2-coder-answer-endpoint` — fix `ask_user_input` submit in CoderPane (register `answer_user_input` on the boocoder service; `apiPrefix` routes through `/api/coder/...` so the right inference runner picks up the answer)
|
||||
- `v2.4.0-unsloth-studio-lift` — port of Unsloth Studio modules: `tool-call-parser.ts` (replaces `xml-parser.ts`; balanced-brace JSON scanner, `hasToolSignal`/`stripToolMarkup`/`parseToolCallsFromText`, stripping at all 3 final-write sites) + `web/html-to-md.ts` (parse5 HTML→Markdown for `web_fetch`). **License flag:** Unsloth Studio is AGPL-3.0 — tension with the roadmap's MIT / no-AGPL-code-lift commitment; revisit before any network-served distribution
|
||||
- `v2.4.0-unsloth-studio-lift` — port of Unsloth Studio modules: `tool-call-parser.ts` (replaces `xml-parser.ts`; balanced-brace JSON scanner, `hasToolSignal`/`stripToolMarkup`/`parseToolCallsFromText`, stripping at all 3 final-write sites) + `web/html-to-md.ts` (parse5 HTML→Markdown for `web_fetch`). **License consequence (recorded 2026-05-31):** Unsloth Studio is AGPL-3.0-only — this lift (plus `llama-args-validator.ts` from `v2.4.1-sidecar-routing`) put the **whole BooCode tree under AGPL-3.0** (`LICENSE` + all five `package.json` are `AGPL-3.0-only`; three files carry the AGPL SPDX header). Scheduled for removal in the **License-debt → relicense to MIT** batch
|
||||
- `v2.4.1-sidecar-routing` — route per-agent `llama_extra_args` to `LLAMA_SIDECAR_URL` via `X-Agent-Flags` (boot guard if set but URL unset); `resolveRoute` + PrefixFingerprint `route` field. AGENTS.md tool-gap fix: 8 post-hoc tools (`request_read_access`, `view_truncated_output`, `ask_user_input`, `git_status`, …) added to every agent's whitelist
|
||||
- `v2.5.0-task-model` — lightweight task-model services (`TASK_MODEL_URL` dedicated llama-server, falls back to `LLAMA_SWAP_URL`+`FAST_MODEL`) for auto-naming/search-rewrite/tags/summaries; search-query rewriting on step 0 when web tools enabled; `sessions.tags` column
|
||||
- `v2.5.1-budget-100` — tool-call budgets raised 50/10/50 → **100/100/100** (read-only / non-read-only / no-agent); per-agent `max_tool_calls` still overrides. `.claude/worktrees/` added to `.codecontextignore`
|
||||
@@ -379,6 +379,9 @@ All tags `vMAJOR.MINOR.PATCH-slug`, monotonic per minor, assigned at ship time (
|
||||
- `v2.6.2-delete-guard-and-sse` — session-delete work-loss guard (server gates `DELETE /api/sessions/:id`: reads `session_worktrees`, calls BooCoder `/worktree-risk` which runs git on the host; dirty/unpushed/unmerged → 409 + per-worktree `RiskReport[]`, `force` bypasses, fail-closed; sidebar block dialog distinguishes at-risk from couldn't-verify, never auto-commits). **Per-session SSE (P1.5-a):** one `event.subscribe({directory})` per live opencode session, each with an `AbortController`, so sessions in different worktrees stream concurrently (was: second silently dropped); `sessionID` demux guard + zombie-loop fix
|
||||
- `v2.6.3-chatkey-and-skills` — re-key `agent_sessions` to **`(chat_id, agent)`** (P1.5-b: the tab/chat is the agent-context unit; two opencode tabs in one session = two contexts sharing one worktree); `tasks.chat_id` threaded end-to-end (`runOpenCodeServerTask` resolve-or-creates a chat for session-less creators); first-class `worktrees` table (one-per-session, survives session delete) supersedes the defanged `session_worktrees`; `agent_sessions.chat_id` CASCADEs from `chats`; stateful cross-chunk dcp-message-id stripper; `committing-changes` + `using-worktrees` judgment skills in `data/skills/boocode/` + parser-safe `data/AGENTS.md` preamble
|
||||
- `v2.6.4-agent-sessions-fk` — converge the live `agent_sessions.session_id` FK `CASCADE → SET NULL` (standalone `confdeltype`-guarded `DO` block, idempotent — the P1.5-b re-key gate skipped already-re-keyed DBs and left it diverged); CLAUDE.md doc-sync (per-session SSE, `(chat_id, agent)` re-key, `data/AGENTS.md` parsing + `data/skills/<vendor>/` conventions)
|
||||
- `v2.6.5-panes-tabs-composer` — **workspace UX batch (BooChat panes/tabs/composer + the persistence that backs it).** *Panes/tabs:* open a chat in a fresh pane (ChatTabBar "Open in new pane" + fork-beside-original via a new `open_chat_in_new_pane` event), per-pane `[+]` → New BooChat/BooTerm/BooCode menu, closing a chat pane relocates its tabs (in order) to the oldest chat/empty pane (reopen strips restored chatIds from every live pane first → no dup), stable session-scoped tab numbers (assigned on open, retired on close, never reused, map-keyed render), and the empty/landing pane became a real session history (open + separately-fetched archived chats). Removed the per-message "Open in pane" artifact button. *Persistence:* `sessions.workspace_panes` widened from bare `WorkspacePane[]` → a `WorkspaceState` envelope (`panes` + `tabNumbers`/`nextTabNumber` + `closedPaneStack`); PATCH validator zod-unions legacy-array-or-envelope and migrates on write; `session_workspace_updated` WS frame widened (web+server byte-identical, parity test green). *Composer:* morphing **Send → Stop → Queue** button keyed on `sending || activeTaskId` (folds in the standalone Stop pill, adds `cancelTask`); pasted chips trail the typed text so a leading slash stays first. *Tooling:* new read-only `read_tab_by_number` tool + an optional `ToolExecCtx` (`{ sql, sessionId }`) 4th arg on `ToolDef.execute`
|
||||
- `v2.6.6-claude-md` — docs-only CLAUDE.md session-learnings from the v2.6.5 batch: the `WorkspaceState` envelope migration, the `ToolExecCtx` plumb (`read_tab_by_number` as reference), the two-schema-files-one-DB ownership split + idempotent `confdeltype` FK-action-flip pattern, and React-StrictMode nested-`setState` idempotency
|
||||
- `v2.6.7-interrupt-guard` — **F.1 fix:** post-interrupt stale-terminal bug in the opencode warm-server backend (one-click reachable since `v2.6.5`'s Stop button). opencode emits one trailing `session.idle`/`session.error` for a cancelled turn (sessionID only, no turn id) that settled the *next* turn early as success. Pure per-session guard (`backends/turn-guard.ts` — arm-on-abort / swallow-one-orphan / self-heal-on-activity) wired into `opencode-server.ts`; 3 regression tests (TDD). First item of the v2.6 openspec "remaining" plan; Phase 1-UX / 2 / 3 still open
|
||||
|
||||
-----
|
||||
|
||||
@@ -431,15 +434,61 @@ All tags `vMAJOR.MINOR.PATCH-slug`, monotonic per minor, assigned at ship time (
|
||||
**Remaining (per openspec `v2-6-persistent-agent-sessions/tasks.md`):**
|
||||
|
||||
- **Phase 1 UX** — DiffPanel per-change agent attribution (`pending_changes.agent` badges), resumed/new-session chip on AgentComposerBar (`GET /api/sessions/:id/agent-sessions`), staging-boundary hint.
|
||||
- **Phase 2 — warm ACP backend (goose, qwen)** — persistent `SpawnedACPProcess` connection reused across turns (one `session/new`, many prompts); dispatcher routes goose/qwen to the warm backend; switch round-trip smoke (opencode → boocode → opencode resumes the same session).
|
||||
- **Phase 3 — lifecycle hardening** — idle TTL eviction per `(chat, agent)`, crash recovery, chat-close/archive worktree cleanup, orphan reaper + max-live-worktrees LRU cap, re-baseline diff after `apply_pending`, reconnect test.
|
||||
- **Phase 2 — warm ACP backend (goose, qwen)** — persistent `SpawnedACPProcess` connection reused across turns (one `session/new`, many prompts); dispatcher routes goose/qwen to the warm backend; switch round-trip smoke (opencode → boocode → opencode resumes the same session). **De-risked (v2 review, 2026-05-31):** `qwen --acp` is a real stdio multi-session agent (`Map<sessionId,Session>`, `loadSession`/`resume`, mid-session model/mode switch) — the old "qwen ACP was HTTP-only → use PTY" premise is **stale**, so wire qwen into the existing `acp-dispatch.ts` stack. Cross-check qwen's `@agentclientprotocol/sdk@^0.14` vs BooCode's `^0.22` handshake before relying on `unstable_resumeSession`. Separately, qwen's one-shot PTY fallback emits Claude-Code-compatible `stream-json` NDJSON (today sliced opaque in `dispatcher.ts`) — **one parser serves both qwen and claude** PTY fallbacks.
|
||||
- **Phase 3 — lifecycle hardening** — idle TTL eviction per `(chat, agent)`, crash recovery, chat-close/archive worktree cleanup, orphan reaper + max-live-worktrees LRU cap, re-baseline diff after `apply_pending`, reconnect test. **Primary reference (v2 review, 2026-05-31): `openchamber` (MIT, same warm-opencode-server architecture — code-liftable)** — health-monitor + crash auto-restart + busy-aware restart + port reclaim (`killProcessOnPort`/`waitForPortRelease`) + stall-detecting SSE reader; **supersedes the Paseo "re-derive"** (paseo's lazy restart-on-demand has no active supervision). Also confirms the deferred `OPENCODE_SERVER_PASSWORD` scheme = `Authorization: Basic base64("opencode:"+pw)`.
|
||||
|
||||
**Lift sources:** `getpaseo/paseo` (design only — OpenCode-as-HTTP-server pattern, `streamedPartKeys` reasoning dedup), `@opencode-ai/sdk` (v2 client), `/opt/forks/opencode`.
|
||||
**Lift sources:** `getpaseo/paseo` (design only — OpenCode-as-HTTP-server pattern, `streamedPartKeys` reasoning dedup), `@opencode-ai/sdk` (v2 client), `/opt/forks/opencode`; **`openchamber` (MIT — Phase 3 lifecycle hardening, code-liftable)**; **`QwenLM/qwen-code` (Apache-2.0 — `qwen --acp` reference + `stream-json` schema)**. See `boocode_code_review_v2.md` §5a/§5f for evidence.
|
||||
|
||||
**Dependencies:** v2.2 (ACP dispatch) + v2.3 provider lifecycle (registry/snapshot). Openspec: `openspec/changes/v2-6-persistent-agent-sessions/`.
|
||||
|
||||
-----
|
||||
|
||||
## License-debt — relicense AGPL-3.0 → MIT (planned)
|
||||
|
||||
**Status: planned, not started.** Recorded 2026-05-31 from the v2 external review (`boocode_code_review_v2.md` §5k) + a direct tree audit. **Decision (Sam, 2026-05-31): relicense the project back to MIT.**
|
||||
|
||||
**Current state (the problem):** the tree is **currently AGPL-3.0** — root `LICENSE` is GNU Affero GPL v3 and all five `package.json` declare `"license": "AGPL-3.0-only"`. Cause: the `v2.4.0`/`v2.4.1` Unsloth-Studio lifts pulled in AGPL-3.0-only code, which makes the whole network-served work AGPL-encumbered. This batch clears that so the MIT flip is valid; **nothing else AGPL remains once these files are gone.**
|
||||
|
||||
**The three AGPL-3.0-only files to clear** (each `SPDX-License-Identifier: AGPL-3.0-only`, ported from Unsloth Studio):
|
||||
1. `apps/server/src/services/inference/tool-call-parser.ts` (← `tool_call_parser.py`) — remove by routing tool-call parsing to **native llama-server** template parsing + a **clean-room `<invoke>`-only fallback** (no Unsloth provenance).
|
||||
2. `apps/server/src/services/web/html-to-md.ts` (← `_html_to_md.py`, used by `web_fetch`) — replace with a permissively-licensed library (`turndown` / `node-html-markdown`) or a clean-room walker.
|
||||
3. `apps/server/src/services/inference/llama-args-validator.ts` (← `llama_server_args.py`, the v2.4.1 sidecar flag-denylist) — clean-room rewrite from the llama-server README flag list (the denylist is facts, not copyrightable).
|
||||
|
||||
**Steps:**
|
||||
1. Confirm native llama-server tool-parsing on **live qwen3.6** (jinja gate already green — `--jinja` + qwen3.x template live; llama.cpp server-side template parser, v2 review §4a).
|
||||
2. Run native parsing **behind a flag for one release** (qwen3.6 was historically unreliable — validate before deleting).
|
||||
3. **Delete** the ~250 Unsloth-derived parser lines + clean-room the `<invoke>` fallback; replace `html-to-md.ts`; clean-room `llama-args-validator.ts`.
|
||||
4. **Flip the license:** root `LICENSE` AGPL→MIT, the five `package.json` `license` fields `AGPL-3.0-only`→`MIT`, remove the per-file AGPL SPDX headers, and update roadmap/README prose. After this, **no AGPL remains in the tree** and the "BooCode is MIT" claim becomes true.
|
||||
|
||||
**Source:** `boocode_code_review_v2.md` §1 #1, §5k. **Prerequisite for the license flip — this batch is the blocker, not optional.**
|
||||
|
||||
-----
|
||||
|
||||
## Write/edit robustness (planned)
|
||||
|
||||
**Status: planned, not started.** From the v2 review (`boocode_code_review_v2.md` §5b; `cline/cline`, Apache-2.0 — code-liftable). Two lifts that harden BooCoder's write surface where it's weakest for local quantized models:
|
||||
|
||||
1. **Fuzzy patch applier for `edit_file`.** BooCoder's `edit_file` is exact-match today (`apps/coder/src/services/pending_changes.ts` — `if (!content.includes(oldStr)) throw`; no whitespace/unicode tolerance, no multi-occurrence guard). Lift cline's tiered match ladder (exact → `trimEnd` → `trim` → Levenshtein ≥0.66) + unicode canonicalization (dashes, curly quotes, nbsp) + multi-occurrence guard; unmatched → warning, not throw. `apply-patch-parser.ts:347-431`.
|
||||
2. **`git stash create` + private-ref checkpoint.** A per-turn workspace snapshot that captures **all** state — including edits made by dispatched external agents (opencode/claude/qwen/goose), build artifacts, test side-effects — which BooCoder's current `rewind` cannot (it only reverse-applies BooCoder's own queued `pending_changes`). Snapshot stored under a private `refs/…/checkpoints/…` ref, restorable with conversation-trim in sync. `checkpoint-hooks.ts:177-253`.
|
||||
|
||||
**Source:** `boocode_code_review_v2.md` §1 #3–#4, §5b.
|
||||
|
||||
-----
|
||||
|
||||
## Claude provider — SDK transport + native session resume (planned)
|
||||
|
||||
**Status: planned, not started.** From the v2 review (`boocode_code_review_v2.md` §5h–§5i) + a direct read of the published SDK `.d.ts` (`@anthropic-ai/claude-agent-sdk@0.3.158`, reviewed 2026-05-31). Today BooCoder dispatches `claude` one-shot via PTY (`claude --output-format stream-json`) with no continuity. Plan:
|
||||
|
||||
1. **Adopt the Agent SDK** (`@anthropic-ai/claude-agent-sdk`) over the PTY path. `query({ prompt, options })` yields structured `SDKMessage`s — `SDKSystemMessage` (`subtype:'init'`, carries the session id + tool/skill/mcp lists), `SDKPartialAssistantMessage` (`type:'stream_event'` deltas), `SDKResultMessage` (turn end) — no stdout scraping. `happy` (`slopus/happy`) is the working existence-proof.
|
||||
2. **Native session resume via a pluggable `SessionStore`.** Implement `PostgresSessionStore implements SessionStore` (5 methods: `append`/`load`/`listSessions`/`delete`/`listSubkeys`) over BooCode's Postgres, keyed by `(chat_id, agent)`; drive turns with `query({ options: { sessionStore, resume } })` and the SDK materializes the stored session for the CLI subprocess. **This supersedes happy's SessionStart-hook + jsonl-watcher** — that was a workaround predating the feature (happy pins SDK `^0.2.96`; the `SessionStore` API is `0.3.x`). `importSessionToStore()` migrates an existing local session; `InMemorySessionStore` is the reference shape.
|
||||
3. **Permissions:** wire BooCoder's permission cards to the SDK's `canUseTool(toolName, input, opts) → Promise<PermissionResult>` callback (one chokepoint, supports `permissionMode`) instead of parsing PTY permission prompts.
|
||||
|
||||
**License posture (reference-only):** `@anthropic-ai/claude-agent-sdk` is under **Anthropic Commercial Terms** (`package.json` `license: "SEE LICENSE IN README.md"`), **not OSS** — acceptable as a runtime **dependency** (same posture as already shelling out to the `claude` CLI), but its source/examples (incl. GitHub `examples/session-stores/postgres`) are **reference-only — do not vendor**, especially mid AGPL→MIT cleanup (relicense batch). Readable references on disk: `/opt/forks/claude-agent-sdk-python` (MIT mirror) + `/opt/forks/claude-agent-sdk-typescript` (examples, commercial terms).
|
||||
|
||||
**Source:** `boocode_code_review_v2.md` §1 #9, §5h–§5i. Refines the v2.6 "claude stays one-shot PTY" assumption on the continuity dimension.
|
||||
|
||||
-----
|
||||
|
||||
## v2.1.0 — Provider picker + model discovery
|
||||
|
||||
**Shipped `v2.1.0-provider-picker`.** Provider registry with 5 providers (boocode, opencode, goose, claude, qwen). Model discovery via `LLAMA_SWAP_URL/upstream/<model>/props`. `/api/providers` route returns installed providers with models. v2.1 `ProviderPicker` UI **superseded by `AgentComposerBar` in v2.2.** Agent-probe startup probe discovers installed agents on host, their versions, ACP support, and models. Booterm SSH host configurable via `BOOTERM_SSH_HOST`/`BOOTERM_SSH_USER` env vars.
|
||||
@@ -474,7 +523,7 @@ All tags `vMAJOR.MINOR.PATCH-slug`, monotonic per minor, assigned at ship time (
|
||||
|-------------------------------|---------------------|-----------------------------|------------------------------------------------------------------------|----------------------|
|
||||
|`boochat` (was `boocode`) |`100.114.205.53:9500`|`/opt:/opt:ro` |Read-only chat + SPA host + MCP client |Live (renames at v2.0)|
|
||||
|`booterm` |`100.114.205.53:9501`|`/opt:/opt` |PTY/tmux terminal sessions |**Live (May 2026)** |
|
||||
|`boocoder` (host systemd) |`100.114.205.53:9502`|full host FS (policy-gated) |Write tools + ACP client + MCP client + MCP server + external-CLI dispatch + warm opencode server|**Shipped v2.0.0–v2.6.4** (systemd since v2.1.0) |
|
||||
|`boocoder` (host systemd) |`100.114.205.53:9502`|full host FS (policy-gated) |Write tools + ACP client + MCP client + MCP server + external-CLI dispatch + warm opencode server|**Shipped v2.0.0–v2.6.6** (systemd since v2.1.0) |
|
||||
|**`boochat`** (Docker service `boocode_db`)|`127.0.0.1:5500` |`boocode_pgdata` volume |Postgres 16-alpine (shared by all three) |**Live** (DB renamed from `boocode` at v2.0)|
|
||||
|`codecontext` |`:8080` (internal, Docker network) |`/opt:/opt:ro`|Go HTTP sidecar for code graph tools |**Live (v1.12.0)** |
|
||||
|
||||
@@ -563,7 +612,7 @@ Full inventory and rationale in `boocode_code_review.md`. Headline items below;
|
||||
|`Dominic789654/agent-hub` |Apache-2.0 |**Task DAG schema, dispatcher worker, project registry, human inbox** — primary architectural template for v2.0 dispatcher|v2.0 |
|
||||
|`getpaseo/paseo` |AGPL-3.0 (**design only, no code lift**)|Daemon+clients arch, CLI verb shape, –worktree flag, provider snapshot/dispatch, OpenCode-as-HTTP-server + reasoning dedup |**v2.2, v2.6 (shipped)** / v2.x |
|
||||
|**`@opencode-ai/sdk`** |**MIT** |**OpenCode warm HTTP server client (`opencode serve`, SSE `session.next.*`, multi-session)** |**v2.6.1 (shipped)** |
|
||||
|**`agentclientprotocol.com` spec + `@zed-industries/agent-client-protocol` SDK**|**Apache-2.0** |**ACP client (host) — replaces raw-PTY dispatch for opencode/goose (cursor retired v2.5.3)** |**v2.0 → v2.2** |
|
||||
|**`agentclientprotocol.com` spec + `@agentclientprotocol/sdk@^0.22.1`**|**Apache-2.0** |**ACP client (host) — replaces raw-PTY dispatch for opencode/goose (cursor retired v2.5.3)** |**v2.0 → v2.2** |
|
||||
|**anthropics/skills `mcp-builder`** |**MIT** |**MCP server build workflow + 10-question evaluation framework** |**v2.0 (BooCoder MCP server)** |
|
||||
|**`zed-industries/codex-acp`** |**Apache-2.0** |**ACP server-side reference for `boocoder acp`** |**v2.4** |
|
||||
|Roo Code: Boomerang Tasks |Apache-2.0 (pattern only) |Orchestrator capability restriction + down-pass/up-pass context discipline |v1.14 (AGENTS.md) → v2.0 (real delegation) |
|
||||
@@ -615,7 +664,7 @@ Full inventory and rationale in `boocode_code_review.md`. Headline items below;
|
||||
|
||||
### Strategic pivot: Paseo-equivalent dispatcher (2026-05-22, **shipped v2.2**)
|
||||
|
||||
Sam wanted BooCode to function like Paseo without using Paseo itself. **Paseo is AGPL-3.0** — incompatible with BooCode's MIT license and its network-served deployment at `code.indifferentketchup.com`. Solution: **reproduce the architecture in BooCode's existing Fastify + TS + PostgreSQL + React stack, using only license-clean patterns**.
|
||||
Sam wanted BooCode to function like Paseo without using Paseo itself. **Paseo is AGPL-3.0** — incompatible with BooCode's **target** MIT license and its network-served deployment at `code.indifferentketchup.com`. Solution: **reproduce the architecture in BooCode's existing Fastify + TS + PostgreSQL + React stack, using only license-clean patterns**. **Reality check (2026-05-31):** the no-AGPL-code-lift rule was later broken by the `v2.4.0`/`v2.4.1` Unsloth-Studio lifts, which put the whole tree under AGPL-3.0 (root `LICENSE` + all five `package.json` are `AGPL-3.0-only` today). The **License-debt → relicense to MIT** batch restores the MIT target.
|
||||
|
||||
- **Primary architectural template:** `Dominic789654/agent-hub` (Apache-2.0) — three-process model (board server + dispatcher + assistant terminal) and schema (tasks/projects/templates/pipelines/human_inbox).
|
||||
- **Critical context-management primitive:** Roo Code Boomerang Tasks pattern — orchestrator with intentional capability restriction, down-pass/up-pass context discipline, no implicit inheritance.
|
||||
@@ -645,17 +694,18 @@ The v1.13.x cleanup line shipped 21 batches over a single intense window in `vMA
|
||||
|
||||
### v2.2.2–v2.6 shipped (2026-05-26 → 2026-05-31)
|
||||
|
||||
Full per-tag detail in the **Shipped (v2.2.2–v2.6.4)** section above and in `CHANGELOG.md`. Threads:
|
||||
Full per-tag detail in the **Shipped (v2.2.2–v2.6.6)** section above and in `CHANGELOG.md`. Threads:
|
||||
|
||||
- **Interactive ACP** (`v2.2.2`–`v2.3.2`) ✅ — placeholder-XML reject; per-agent sampling params; `ask_user_input` cards in both BooCoder frontends; enriched `permission_requested` frame (question/plan/elicitation) with interactive PermissionCard; coder `answer_user_input` endpoint fix.
|
||||
- **Unsloth lift + sidecar + task model** (`v2.4.0`–`v2.5.1`) ✅ — Unsloth Studio `tool-call-parser.ts` (replaces `xml-parser.ts`) + parse5 HTML→Markdown (**AGPL-3.0 source — license flag vs the MIT commitment**); llama-sidecar per-agent-flags routing; dedicated task-model services; tool budgets → 100/100/100.
|
||||
- **Unsloth lift + sidecar + task model** (`v2.4.0`–`v2.5.1`) ✅ — Unsloth Studio `tool-call-parser.ts` (replaces `xml-parser.ts`) + parse5 `html-to-md.ts` + `llama-args-validator.ts` (**all three AGPL-3.0-only — this is what relicensed the whole tree to AGPL-3.0**); llama-sidecar per-agent-flags routing; dedicated task-model services; tool budgets → 100/100/100. **→ removal tracked in the License-debt → relicense to MIT batch.**
|
||||
- **Provider lifecycle = the planned "v2.3"** (`v2.5.3`–`v2.5.15`) ✅ — cursor/copilot retired; config-backed registry + snapshot lifecycle + two-tier probe (phases 1–5); empty-picker fix; claude model list; mobile composer; per-agent + claude/opencode slash-command discovery; ACP path-guard security fix.
|
||||
- **v2.6 persistent agent sessions** (`v2.6.0`–`v2.6.4`) ✅ Phase 0/1 + P1.5-a/b — foundations scaffold; opencode warm HTTP server with per-chat resumable sessions; session-delete work-loss guard; per-session SSE; `(chat_id, agent)` re-key + `worktrees` table; FK convergence.
|
||||
- **Workspace UX + composer** (`v2.6.5`–`v2.6.6`) ✅ — BooChat panes/tabs overhaul (open-in-new-pane, `[+]` New BooChat/BooTerm/BooCode menu, tab relocation, stable tab numbers, session-history landing pane); `workspace_panes` → `WorkspaceState` envelope; morphing Send→Stop→Queue composer + `cancelTask`; `read_tab_by_number` tool + `ToolExecCtx`; CLAUDE.md doc-sync. (This is the work the earlier draft listed as "uncommitted frontend UX" — now shipped.)
|
||||
|
||||
### In flight
|
||||
|
||||
- **License-debt → relicense AGPL-3.0 → MIT** — see the planned batch above; the tree is currently AGPL-3.0 and three Unsloth-derived files must be cleared before the MIT flip. Prerequisite, blocker-status.
|
||||
- **v2.6 persistent agent sessions — Phase 2/3** — warm ACP backend for goose/qwen (persistent process reused across turns) + lifecycle hardening (idle eviction, crash recovery, worktree cleanup/reaper, post-apply re-baseline) + the Phase-1 UX attribution work (DiffPanel agent badges, resumed/new-session chip). See openspec `v2-6-persistent-agent-sessions/tasks.md`.
|
||||
- **Frontend pane/composer UX (uncommitted working tree, 2026-05-31)** — CoderPane stop button (`api.coder.cancelTask` → `POST /api/coder/tasks/:id/cancel`; `generating = sending || activeTaskId` gates queue/stop); ChatTabBar `[+]` becomes a New BooChat / BooTerm / BooCode menu; "Open in new pane" tab context-menu + `open_chat_in_new_pane` SessionEvent + `useWorkspacePanes.openChatInNewPane` (detaches the chat so it lives in exactly one pane); MessageBubble simplification so fork lands beside the original. Not yet committed/tagged.
|
||||
|
||||
### Numbering and scope-revision discipline during v1.13.x (2026-05-23)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user