Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .tickets/_docs/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# KaitenCode Roadmap

> Authoritative "what's done / what's left" as of **2026-06-12**, verified against
> `main` HEAD. Supersedes the tier table in [STATUS.md](./STATUS.md) and the
> session-scoped [handoffs/REMAINING_WORK.md](./handoffs/REMAINING_WORK.md) (both
> kept for history). Released: **v1.0.0** (Linux `.deb` + AppImage, 2026-06-07).

Context: the goal is to **daily-drive KaitenCode as the primary surface for
agent-driven dev work** (in place of raw terminals). Priorities below are ranked
by that goal — interactive-mode reliability first, since it's the path that
replaces the terminal.

---

## ✅ Shipped & wired

- Source-of-truth refactor (Fronts 1–3): all surfaces (UI / HTTP API / MCP / chef)
funnel through shared `pipeline::*_service`; MCP routes through `/api/*`.
- Reliability cluster (PR #256): queue-stall, worktree leak, startup false-success,
over-spawn, sentinel scan — fixed before v1.
- Interactive mode (PR #257): real `claude`/`codex` TUI in per-task tmux, opt-in
setting + per-chat toggle.
- Terminal-harness B1–B4: create-UI options, interactive promotion, chef terminal,
CLI health check.
- Local HTTP API on by default (PR #258).
- Discord MVP (PR #260): task→thread + agent-output streaming (one-way).
- Trigger UX redesign phase 1 (PR #261): sentence-builder + recipes.
- Settings runtime tab (PR #262): backend `AppSettings` via System → Runtime.
- MCP: 25 tools; source attribution + recursion guard (migration 046);
mark_complete/dependencies route through `/api/*`.

---

## 🔴 Critical now (blocks comfortable daily-driving)

1. **Interactive readiness hard-kill.** Readiness is a 5s glyph-scrape that
*hard-kills* the tmux session on slow cold start / CLI UI change
(`chat/bridge.rs` ~2469/2610). Make it quiescence-based (adaptive), not a fixed
budget. → board task "Interactive: adaptive readiness".
2. **Interactive codex parity.** `--append-system-prompt` likely invalid for
interactive codex (would fail to start); `--resume` not wired (`spawn_interactive_cli`
warns + ignores `resume_id`). Verify against a real codex binary; drop/guard the
bad flag. Claude is solid. → board task "Interactive: codex parity".
3. **Two-claude footgun (env hygiene).** Stale `/usr/local/bin/claude` (2.1.138 npm
copy) can win in some PATHs. App now resolves absolute paths correctly, but
`rm /usr/local/bin/claude` removes the ambiguity. One-liner, do it.

## 🟡 Important (rough edges, not blockers)

4. **Interactive completion is panel-bound.** The "agent done" advisory only fires
while the panel is attached — no persisted flag / card badge. Needs a migration
+ badge so it survives panel close. → board task "Interactive: persist advisory".
5. **`effort_level` not wired into the trigger path.** It's a real DB field + has a
`thinking-selector.tsx` and works in the interactive chat panel, but no
`effort_level`→CLI plumbing in `pipeline/spawn.rs` (the headless `spawn_cli`
path). Either wire `--effort`/`-c model_reasoning_effort` into the trigger
command or document it as interactive-only.
6. **Checklist as per-workspace roadmap + MCP surface.** Checklist has zero
`/api/*` routes and zero MCP tools. Make it agent-readable/maintainable so it
can serve as the project roadmap. **Spec:** [specs/CHECKLIST_AS_ROADMAP.md](./specs/CHECKLIST_AS_ROADMAP.md).
Planned, deferred 2026-06-12.
7. **MCP UI-only gaps.** No MCP tool for `update_column`/`delete_column`/
`reorder_columns`, `update_script`/`delete_script`, per-task runtime-mode
override, or agent control (inject/interrupt/pause/restart/switch-model). Each
needs an `/api/*` route first. Add as needed (the checklist spec establishes the
route+tool pattern).

## ⚪ Inert / deferred (known, intentional)

- Custom keyboard shortcuts render but are inert (`shortcuts-tab.tsx:54`).
- Providers OpenRouter / Google AI / Ollama are "Coming soon" cards.
- Voice/Whisper built but gated out of the default build (`voice` Cargo feature).
- macOS release: matrix disabled pending Apple Developer ID + notarization secrets.
Windows unsupported by design (tmux/jq/sh).
- Discord: one-way only; reply-routing / `#chef` / bidirectional are later slices
(`.tickets/discord/`).
- MCP source-attribution Part 3 (spawned-by badge + human/agent filter); interactive/
managed spawn-path env threading (headless done).

---

## Needs testing (no automated coverage)

- Interactive codex round-trip (resume, append-system-prompt, sentinel) on a real
binary — gates item #2.
- Live CLI smoke test (throwaway-tmux round-trip) — designed in B4, not built.
- Discord thread streaming end-to-end.
- 5-agent-per-workspace concurrency under real load (queue promotion).

## Suggested order

`#1 readiness` → `#2 codex parity` (+ its testing) → `#3 rm stale claude` (free) →
`#4 persist advisory` → `#5 effort wiring` → `#6 checklist/roadmap MCP` → `#7 MCP gaps`.
2 changes: 1 addition & 1 deletion .tickets/_docs/STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Phase 6 🟡 — CliSessionManager removed, but AgentRunner + PtyManager still u

### MCP Server (kaitencode-mcp)

Standalone Rust binary (19 tools), shares Cargo workspace with Tauri app for WAL-compatible concurrent DB access. 17 unit tests.
Standalone Rust binary (25 tools), shares Cargo workspace with Tauri app for WAL-compatible concurrent DB access. 18+ unit tests.

### Database

Expand Down
114 changes: 114 additions & 0 deletions .tickets/_docs/specs/CHECKLIST_AS_ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Spec — Checklist as Per-Workspace Roadmap (+ MCP/HTTP surface)

> Status: **PLANNED, not started** (deferred 2026-06-12 — "more critical things first").
> Owner: TBD. Effort: ~1 day (routes + MCP tools + tests + rebuild).

## Goal

Repurpose the existing **checklist** feature as a high-level, per-workspace
**project roadmap** that both the human (UI) and agents (MCP) can read and
maintain. Today the checklist is a release-readiness widget with *no* agent
surface; this spec closes that gap without inventing a new feature.

## Why checklist (not pipeline templates)

They are genuinely different things (verified 2026-06-12):

| | Pipeline Template | **Checklist** |
|---|---|---|
| Scope | Global, stateless blueprint | **Already per-workspace** (1 per ws) |
| Captures | Column names/icons/triggers | Categories → items + state |
| Item state | — | `checked`, `notes`, `position`, `linked_task_id`, auto-detect |
| Agent surface | 3 MCP tools | **none** |

The checklist is already workspace-scoped, ordered, supports notes, can **link an
item to a board task** (`linked_task_id`), and can **auto-detect** completion from
repo state (file-exists / file-contains / file-absent / command-succeeds). That is
a near-perfect roadmap primitive — it just isn't reachable by agents.

## Current state (what exists)

- **DB** (`src-tauri/src/db/checklist.rs`): full CRUD already implemented as
`(conn, …)` functions — `insert_checklist`, `get_workspace_checklist`,
`insert_checklist_category`, `list_checklist_categories`,
`insert_checklist_item`, `list_checklist_items`, `update_checklist_item`
(toggle `checked`), `update_checklist_item_details`, `delete_checklist_item`,
`link_checklist_item_to_task`, `create_checklist_item_with_detect`, …
- **Tauri commands** (`src-tauri/src/commands/checklist.rs`): 15 commands wrapping
the above (used by the UI).
- **Tables** (migration `005_checklists.sql`, `019_checklist_autodetect.sql`):
`checklists(workspace_id)`, `checklist_categories(checklist_id, name, icon,
position)`, `checklist_items(category_id, text, checked, notes, position,
detect_type, detect_config, auto_detected, linked_task_id)`.

## Gap

- **Zero `/api/*` routes** for checklist. MCP mutation tools route through
`/api/*`, so nothing is reachable from MCP today.
- **Zero MCP tools.**
- One structural constraint: **exactly one checklist per workspace**
(`commands/checklist.rs:134`). Fine for a *single* roadmap per project; only a
blocker if we later want multiple named roadmaps per workspace.

## Design

Mirror the established `create_column` pattern exactly: an `/api/*` handler that
takes `AxumState<Arc<ApiState>>`, grabs a conn via `get_db!(api)`, calls the
`db::checklist::*` fn directly, then emits an event and returns `ok_response`.
Add a new event `checklist:changed { workspaceId }` (typed struct,
`#[serde(rename_all = "camelCase")]`) + a `useChecklistSync` hook so UI refreshes
live when an agent edits the roadmap.

### New HTTP routes (`src-tauri/src/api.rs`, registered in the `protected` router ~L893)

| Route | Calls | Notes |
|---|---|---|
| `GET /api/checklist?workspace_id=` | `get_workspace_checklist` + categories + items | read; returns full nested roadmap |
| `POST /api/checklist/ensure` | `insert_checklist` if absent | idempotent; create-on-first-use |
| `POST /api/checklist/category` | `insert_checklist_category` | add roadmap phase |
| `POST /api/checklist/item` | `insert_checklist_item` / `create_checklist_item_with_detect` | add milestone (optional auto-detect) |
| `POST /api/checklist/item/update` | `update_checklist_item` (toggle) + `update_checklist_item_details` (text/notes) + `link_checklist_item_to_task` | the workhorse |
| `POST /api/checklist/item/delete` | `delete_checklist_item` | |

All request structs `#[derive(Deserialize)]` snake_case (match existing API
convention — note: the API request structs are snake_case, e.g. `MoveTaskReq`
uses `id`/`target_column_id`, *not* camelCase).

### New MCP tools (`mcp-server/src/main.rs`)

| Tool | Route | Scope |
|---|---|---|
| `get_checklist` | `GET /api/checklist` | read-only — works without app |
| `checklist_update` | `POST /api/checklist/item/update` | toggle done / edit text / link task |
| `checklist_add_item` | `POST /api/checklist/item` | add milestone |
| `checklist_add_category` | `POST /api/checklist/category` | add phase |

Read-only `get_checklist` should also support the test-only direct-DB fallback
(like the other read tools); mutations require the running app (`/api/*`).

### Phasing

1. **P1 (minimal, unblocks roadmap):** `GET /api/checklist` + `POST
/api/checklist/item/update` → MCP `get_checklist` + `checklist_update`.
Agents can read the roadmap and tick milestones.
2. **P2 (agent-maintainable):** add category + item create/delete routes + tools.
Agents can build/restructure the roadmap.
3. **P3 (optional):** drop the 1-per-workspace constraint + add a `name` column to
`checklists` for multiple named roadmaps per workspace (migration after 047).
Only if multi-roadmap is wanted.

### Tests

- MCP: extend `mcp-server/src/main.rs` test module (currently 18 tests) with a
`test_checklist_update_*` round-trip against the test-DB fallback.
- API: a handler test if the api.rs test harness supports it; otherwise rely on
the MCP round-trip + a manual smoke test after rebuild.

## Open decisions (for whoever picks this up)

- **Single vs multiple roadmaps per workspace** — P3 above. Default: keep single
(zero schema change) until there's a concrete need.
- **Auto-detect as roadmap signal** — should `checklist_update` allow agents to
set `detect_config` so a milestone self-checks from repo state? Powerful for a
roadmap ("done when `cargo test` passes"), but lets agents wire shell commands.
Default: P2 read-only on detect; no agent-set detect until reviewed.
102 changes: 102 additions & 0 deletions .tickets/_docs/specs/CHEF_TOOL_BASED_CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Spec — Tool-based board context for the chef (orchestrator)

> Status: **IMPLEMENTED behind `KAITENCODE_CHEF_TOOLS=1`** (2026-06-13). Verified
> end-to-end: the chef calls `mcp__kaitencode__get_board` with the workspace id and
> answers from the live board. Default-off; falls back to the embedded board when
> the flag is off OR `kaitencode-mcp` can't be located.
>
> **Open follow-ups before promoting to default:**
> - **Bundle `kaitencode-mcp`** with the app (tauri `externalBin`/resources) — it
> isn't shipped today, so the feature only works where the binary is on PATH or a
> sibling of the exe (dev). Resolution: `commands/orchestrator/stream_cli.rs::locate_kaitencode_mcp`.
> - The chef still runs `ToolSearch` before the real tool call (a built-in of the
> installed claude, not removed by `--strict-mcp-config`) — harmless, just an extra step.
> - Writes still use the action-block protocol; only reads moved to the tool. Moving
> writes to MCP too (create_task/move_task) is a separate, larger step.
> - API chef (`stream_api.rs`) unchanged — this is CLI-only.

## Problem

Today the chef embeds the **entire board state in the prompt every turn**:
- `context::build_cli_system_prompt` puts a `[id] title - description(≤120c)`
snapshot of every task (across all columns) + the action-protocol prompts into
`--system-prompt`.
- `chef.rs::augment_message` historically *also* prepended that snapshot to the
user message (now gated to `--resume` turns only — the quick dedup).

Consequences:
- Prompt size scales with board size, not with what the turn needs.
- It feeds the argv/E2BIG ceiling (see the stdin fix — the `--system-prompt`
board is still on argv; a large enough board can still trip 128 KiB).
- Most turns ("rename task X", "what's in Review?") don't need the *whole* board.

## Goal

Stop embedding the board. Give the chef a **read tool** and let the model fetch
board state on demand — tiny prompts, scales to any board, removes the E2BIG
residual.

## Design

The chef CLI path spawns `claude -p`. Two ways to give it a read tool:

### Option A — MCP (preferred)
Wire the existing **`kaitencode-mcp`** server (already exposes `get_board`,
`get_task`, `get_workspaces`, …) into the chef's claude invocation via
`--mcp-config` (or `--mcp-server`). The model calls `get_board` when it needs
state.
- `kaitencode-mcp` is already spawned in some flows (see `bridge.rs:1586` env
threading) and shares the rusqlite build for WAL-safe concurrent reads, so
read tools work without the app for the DB, but mutations still route through
`/api/*`.
- **VERIFIED 2026-06-13 (spike):** `claude -p --mcp-config <json>
--allowedTools "mcp__kaitencode__get_workspaces,..." --output-format stream-json`
loads `kaitencode-mcp`, the model calls `mcp__kaitencode__get_workspaces`, the
tool_result (real DB data) comes back, and the answer is correct. The
tool_use/tool_result events appear in the stream-json (transcript already renders
tool calls). claude 2.1.177. → **Option A is GO.**
- Nuance: in the spike, claude had the *user's* global MCP servers loaded too, so
it went through `ToolSearch` (deferred-tool discovery) before the real call.
Chef should spawn with an **isolated** config (only kaitencode, via
`--strict-mcp-config` + `--mcp-config`) so there's no ToolSearch indirection and
the tool is directly available. Also pre-approve the read tools with
`--allowedTools` (no permission prompt in headless).
- Note: pass the prompt on **stdin** (the E2BIG fix already does) — a positional
prompt makes claude wait ~3s for stdin ("no stdin data received in 3s").

### Option B — extend the action protocol with a read action
Add a `get_board` "action" the model emits (like the existing `create_task`
blocks); the backend intercepts it, runs the read, and feeds the result back as a
follow-up turn. Reuses the existing `parse_cli_action_blocks` machinery — no MCP
dependency — but needs a multi-turn read/observe loop the chef doesn't have yet.

**Recommendation:** Option A if the `-p` + MCP spike works; otherwise B.

## Changes (Option A)

1. `build_cli_system_prompt`: drop the `Current tasks:` snapshot; replace with a
one-liner — "Call `get_board` to see the current board; call it again after you
change something." Keep columns list (cheap, stable) + the action protocol for
*writes*.
2. `chef.rs`: delete `augment_message` / `format_context_message` board injection
entirely (the quick-dedup branch goes away too).
3. Chef claude invocation (`runtime`/`session` pipe path for orchestrator): add
`--mcp-config` pointing at `kaitencode-mcp`. Likely a chef-only spawn flag so
per-task agents are unaffected.
4. Ensure the stream parser surfaces MCP tool-use/tool-result events into the
transcript (the agent transcript already renders tool calls — reuse).

## Verification

- Spike: `claude -p --mcp-config … "list tasks in Review"` headless → confirm a
`get_board` tool call + result in the `stream-json` output.
- Prompt size: a 200-task board should produce a *constant* small system prompt.
- Regression: chef can still create/move/rename tasks (writes unaffected).
- No E2BIG at any board size.

## Open questions

- Does `claude -p` support MCP headlessly in this version? (gates A)
- Read-staleness after a write: instruct the model to re-`get_board` after each
action (cheap) vs. auto-injecting a fresh snapshot post-write.
- Codex parity (codex chef MCP support is separate/unverified).
8 changes: 5 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,11 @@ mcp-server/

**App requirement:** Most mutation tools route through the Tauri app's HTTP API (port and bearer token discovered via `~/.kaitencode/api.port`) so triggers fire and `tasks:changed` events flow to the UI. If the app isn't running, those tools error out (production builds disable direct-DB fallback; only `cfg!(test)` allows it). Read-only tools work without the app.

**Known gaps (see `.tickets/_docs/MCP_DOGFOOD_REPORT.md`):**
- `mark_complete`, `add_dependency`, `remove_dependency` bypass the API and write the DB directly — no `tasks:changed` event, so the UI doesn't refresh in real-time.
- No recursion guard / source attribution on MCP-created tasks. See `.tickets/_docs/MCP_SELF_TASK_WORKFLOW.md` for a safe self-task pattern.
**Resolved (was a gap, now fixed):** `mark_complete`, `add_dependency`, `remove_dependency` now route through `/api/mark_complete` + `/api/set_dependencies` (emit `tasks:changed`); source attribution + recursion guard shipped (migration 046 — `created_by_task_id`/`created_by_agent_session_id`, `mcp_max_recursion_depth`). See `.tickets/_docs/MCP_SELF_TASK_WORKFLOW.md` for the self-task pattern.

**Remaining gaps:**
- **No checklist tools.** Checklist is Tauri-IPC-only (15 commands in `commands/checklist.rs`), with zero `/api/*` routes — so no MCP tool can reach it yet. Adding `checklist_update`/`get_checklist` requires a new `/api/*` route first.
- **UI-only ops without MCP coverage:** `update_column`/`delete_column`/`reorder_columns`, `update_script`/`delete_script`, per-task runtime-mode override, and agent control (`inject_message`/`interrupt`/`pause`/`restart`/`switch_model`) — each needs an `/api/*` route before an MCP tool.

## Type System

Expand Down
7 changes: 6 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ export default tseslint.config(
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
projectService: true,
// allowDefaultProject lets root config files (vite.config.ts) lint
// without being in tsconfig's include — otherwise the project service
// rejects them ("not found by the project service").
projectService: {
allowDefaultProject: ['*.config.ts'],
},
tsconfigRootDir: import.meta.dirname,
},
},
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"profile": "VITE_REACT_SCAN=1 vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"prepare": "husky",
Expand Down Expand Up @@ -67,6 +68,7 @@
"jsdom": "^28.1.0",
"lint-staged": "^15.5.2",
"prettier": "^3.5.3",
"react-scan": "^0.5.7",
"tailwindcss": "^4.0.0",
"typescript": "^5.7.3",
"typescript-eslint": "^8.24.1",
Expand Down
Loading
Loading