# Discovery notes — post-review-backlog plan Single source of truth for project context. Specialists: read this first, do NOT re-grep what is here. Search further only for what your domain needs that is not covered. ## Tech stack - Monorepo, pnpm workspaces: `apps/server` (BooChat — Fastify + postgres, native inference, read-only tools), `apps/web` (React + Vite SPA), `apps/coder` (BooCoder — host systemd service, write tools + external-agent dispatch, port 9502), `apps/booterm` (PTY/tmux). TypeScript strict, NodeNext (`.js` import suffixes) on server + coder. - Tests: vitest (pinned ^3). server `pnpm -C apps/server test`; coder `pnpm -C apps/coder test` (`globals:false` — import describe/it/expect). Include glob `src/**/__tests__/**/*.test.ts`. No web test harness, no linters. DB-integration tests opt-in via `DATABASE_URL` + `describe.runIf`. - Deploy: apps/coder → `sudo systemctl restart boocoder`; apps/web|server → `docker compose up --build -d boocode`. - Postgres 16, DB `boochat`. Two schema files: `apps/server/src/schema.sql` (sessions/chats/messages/ message_parts) + `apps/coder/src/schema.sql` (agent_sessions, worktrees, pending_changes, available_agents, checkpoints, claude_session_entries, tasks extension). ## ADRs / coding standards found - No `docs/adr/` directory. Architectural decisions live in `boocode_roadmap.md` (Decisions log) + per-app `CLAUDE.md` files (auto-loaded when editing that subtree) + `openspec/changes/archived/`. - Coding standards: `docs/coding-standards/` (canonical), surfaced via `.claude/rules/coding-standards/` path-scoped index files. Not loaded automatically; open on demand. - Cross-cutting conventions in root `CLAUDE.md` "Conventions" section (WS-frame parity, sentinels, JSONB via `sql.json`, event dedup discipline, deploy-by-surface). ## Code touch points (per scope-brief item) - **F1 task-cancel:** `apps/coder/src/services/dispatcher.ts` (private `ac=new AbortController()` at ~316/655/991/1248; `inflight=Map` at :56 — no per-task AbortController registry); `apps/coder/src/routes/tasks.ts:110-148` (cancel route — inference.cancel + DB only); `routes/messages.ts:388` (session stop); backends honor `ctx.signal`: `pty-dispatch.ts:159` (child.kill), `backends/warm-acp.ts:318` (session/cancel), `backends/opencode-server.ts:775` (session.abort), `backends/claude-sdk.ts:209` (interrupt). Frontend `apps/web/src/components/panes/CoderPane.tsx:987` handleStop; `api/client.ts:395` cancelTask. - **F2 parser prune:** `apps/server/src/services/inference/tool-call-parser.ts` (exports extractToolCallBlocks, stripToolMarkup, parseXmlToolCall, parseInvokeToolCall, isPlaceholderArgValue, XML_/INVOKE_ consts). Live consumers: `stream-phase.ts:263-284` (extractToolCallBlocks, text-delta fallback path), `:285-294` (structured tool-call path — authoritative today), `tool-phase.ts:122` + `error-handler.ts:25,106` (stripToolMarkup). llama-swap native `--jinja` parsing confirmed ON (external host `:8401`). - **F3 xml logging:** `tool-call-parser.ts:65` console.debug; one call site in `stream-phase.ts` executeStreamPhase. - **F4 notify-hook:** agent config paths `~/.claude/settings.json`, `~/.qwen/settings.json`, `~/.config/goose/`; existing readers `claude-command-discovery.ts:84`, `qwen-settings.ts`, `provider-registry.ts`. Existing normalize helper `apps/coder/src/services/normalize-agent-status.ts` (`normalizeAgentEvent`). Existing status publish wired at dispatcher turn boundaries (v2.7.6); `index.ts:86` references #10. `permission-waiter.ts:47` has a `PermissionHooks` registry. - **F5 compaction surfacing:** `apps/coder/src/services/backends/opencode-server.ts` SSE arm handling (~215-311 region); WS frame parity → server `ws-frames.ts` + web `apps/web/src/api/types.ts` (`WsFrame`). - **F6 resilience:** `apps/server/src/services/inference/stream-phase.ts:261` (`for await ... result.fullStream`), abort check at :333, usage at :343. Frontend 60s `discard_stale` watchdog is the only stall guard today. - **F7 session-history MCP tool:** `apps/coder/src/services/mcp-server.ts` (existing BooCoder MCP tools); read path `messages_with_parts` view. - **F8 diff-line UX:** diff UI component NOT located by `git ls-files apps/web | grep -i diff` (returned empty) — UX specialist must locate the actual diff/changes panel component (BOOCODER.md calls it "DiffPanel"; may be named differently or nested). Routes through dispatcher + AgentComposerBar. - **F9 retire :9502:** `apps/coder/web/` package + static serve in `apps/coder/src/index.ts` + coder build scripts/Dockerfile. KEEP WS + REST routes. ## Recent activity / precedent - HEAD `e5ce01a` (v2.7.11). v2.7.x line (relicense, write-edit-robustness, sampling-streamjson-tokens, mistake-tracker-ledger, claude-sdk-sessionstore, agent-status-normalize, UI batches) all shipped 2026-06-01. - Pure-helper + TDD precedent for extraction: `backends/turn-guard.ts`, `backends/lifecycle-decisions.ts`, `mistake-tracker.ts` (pure module + unit test, then wire). F1/F2/F6 should follow it. - Parallel-disjoint-file agent precedent: v2.7.0/v2.7.1/v2.7.3 each built by 3 parallel agents over disjoint files — relevant to decomposition/sequencing. ## Enumerated gaps (searched, not found) - No `feature-specification.md` — `scope-brief.md` is the ground-truth stand-in. - No `docs/adr/`. - Diff UI component filename not found via naive grep (F8) — needs UX specialist location. - llama-swap config is NOT in-repo (external host `:8401`); native-jinja state confirmed by live probe only. - F8 (diff-line UX) and F4 (notify-hook) are the two items most likely to need their own plan-a-feature; they have no behavioral spec beyond the review-doc pattern description.