Add siGit Code parity roadmap: the three biggest wins

Records where siGit Code stands against Claude Code and specifies the three features that close the most important gaps: background commands, a subagent tool, and durable sessions with context compaction. Each spec is scoped to its own branch off development in the sigit repo, with design notes and acceptance criteria detailed enough to implement from.

Seto Elkahfi committed Jul 4, 2026 at 22:04 UTC 1710db46eb52b34b0824ed6149a9a170aa928991
1 file changed +172
docs/product/sigit-code-parity-roadmap.md
+172
new file mode 100644 index 0000000..0041e25 --- /dev/null +++ b/docs/product/sigit-code-parity-roadmap.md @@ -0,0 +1,172 @@ +# siGit Code parity roadmap: the three biggest wins + +Status: draft v1 (2026-07-04). Owner: product/eng. Audience: internal (private repo). +Scope: **siGit Code**, the Rust CLI / ACP agent (see [product-overview.md](product-overview.md)). +This document records where siGit Code stands against Claude Code and specifies the +three features that close the most important gaps. Each spec below is written to be +implementable on its own branch off `development` in the `sigit` repo; the three are +independent of each other. + +--- + +## 1. Where we stand + +siGit Code already covers the core agent loop: file tools, shell, glob and search, +web fetch, todos, memory, Agent Skills, an MCP client (Streamable HTTP), project +instruction files (AGENTS.md / CLAUDE.md), a tool permission system with plan mode +(PR #20), commit co-author attribution (PR #21), ACP editor integration, a Unix TUI, +and local / cloud / BYO inference. Local inference is our differentiator; Claude +Code has no equivalent. + +What Claude Code has that we lack is not one feature. It is the machinery that lets +an agent work for a long time: + +| Capability | Claude Code | siGit Code today | +|---|---|---| +| Durable sessions (resume after restart) | yes | no, history lives in RAM | +| Context compaction | auto + manual | no, hard cap of 10 tool rounds | +| Subagents (delegate work to a fresh context) | yes | no | +| Background / long-running commands | yes | no, commands are killed at 120s | +| Web search | yes | fetch only | +| Custom slash commands | yes | built-ins only | +| Permission rule patterns (`Bash(git:*)`) | yes | mode + per-tool only | +| stdio MCP transport | yes | HTTP only | +| Headless mode for CI | yes | no | + +The three specs below are the biggest wins, ordered by implementation cost from +smallest to largest. Everything else on the list is a fast follow. + +--- + +## 2. Spec: background and long-running commands + +**Branch:** `feature/background-commands` · **Touches:** `src/tools.rs` (self-contained) + +### Problem + +`run_command` kills every child at the 120 second `COMMAND_TIMEOUT`. A cold +`cargo build`, a full test suite, a dev server, or a watch task cannot run at all. +This is the most visceral failure in daily use: the agent cannot even build the +projects it is asked to work on. + +### Design + +- `run_command` gains an optional boolean argument `run_in_background`. When true, + the child is spawned, registered in a process-global task table + (`Mutex<HashMap<u64, BackgroundTask>>`, monotonically increasing ids, same + process-global pattern as `mcp.rs`), and the tool returns immediately with the + task id. A reader thread drains stdout/stderr into a capped buffer + (`COMMAND_OUTPUT_LIMIT` per task, oldest output dropped first). +- New tool `command_output` `{task_id}`: returns output accumulated since the last + poll plus the task status (running / exited with code). +- New tool `kill_command` `{task_id}`: terminates the child (SIGKILL on Unix, + `TerminateProcess` semantics via `Child::kill` everywhere) and reports the tail + of its output. +- Foreground behavior is unchanged, including the 120s timeout. Background tasks + have no timeout; all children die with the sigit process (document this). +- Tool descriptions must steer the model: run servers, builds, and anything that + may exceed two minutes in the background, then poll. +- When the permission system (PR #20) merges: `command_output` is read-only, + `kill_command` is mutating but only affects children the agent itself started. + +### Acceptance + +- A background task outliving the 120s foreground timeout keeps running and its + output is retrievable via `command_output`. +- `kill_command` stops a running task; polling a finished task reports its exit code. +- Unit tests cover: spawn + poll + finish, kill, unknown task id, output capping. + +--- + +## 3. Spec: subagent tool + +**Branch:** `feature/subagent-tool` · **Touches:** `src/tools.rs`, `src/backend.rs`, both surfaces' startup + +### Problem + +One conversation does everything, so every file read pollutes the main context +forever. With on-device models this is fatal: a 3B model's context fills after a +few searches. Delegating research to a throwaway context keeps the main thread +small. + +### Design + +- New tool `task` `{description, prompt}`: runs a nested agent loop in a fresh + conversation and returns only its final text answer (capped, e.g. 8k chars). +- The subagent's toolset is read-only: `read_file`, `list_directory`, + `search_files`, `glob`, `read_website`. No `task` (no recursion), no mutating + tools, so no permission prompts fire mid-subagent. +- Architecture: `tools.rs` is backend-agnostic, so it cannot construct a backend. + At startup each surface registers a subagent factory in a process-global + (`OnceLock<Box<dyn Fn() -> Option<Arc<dyn InferenceBackend>>>>`): for + `OpenAiBackend` the factory builds a fresh backend with the same base_url / key / + model and a short subagent system prompt; for `LocalBackend` the factory returns + `None` for now (onde has a single shared history; a second concurrent context + needs onde support first) and the tool returns a clear "not available on-device + yet" result the model can react to. +- The nested loop reuses `send_message_with_tools` / `send_tool_results` and + `execute_tool`, with its own round cap (8). +- The `task` tool is only offered when the factory reports availability, the same + conditional-spec pattern the `skill` tool uses. + +### Acceptance + +- On an OpenAI-compatible backend, `task` completes a research prompt using only + read-only tools and returns a text answer; the main conversation history gains + one tool result, not the subagent transcript. +- On-device, the tool either is not offered or returns the documented fallback. +- Unit tests cover the loop against a scripted backend (the + `tests/acp_permissions.rs` fake-endpoint harness pattern) and the toolset + restriction. + +--- + +## 4. Spec: durable sessions and context compaction + +**Branch:** `feature/session-persistence-compaction` · **Touches:** `src/backend.rs`, `src/main.rs`, `src/chat.rs`, new `src/session_store.rs` + +### Problem + +History lives in RAM (`OpenAiBackend`'s message vec, onde's engine state). A +restart loses everything, ACP `session/load` cannot actually restore, and the hard +`MAX_TOOL_ROUNDS = 10` cap is the only defense against blowing the context window. +This is the single hardest ceiling on task size, and it hurts most on-device where +context windows are smallest. + +### Design + +- **Persistence.** `InferenceBackend` gains `history_snapshot() -> Vec<serde_json::Value>` + and `restore_history(Vec<serde_json::Value>)`. `OpenAiBackend` serializes its + message vec as-is. `LocalBackend` flattens through onde's `history()` / + `push_history` (tool entries flatten to text in the MVP; acceptable loss). + A new `session_store` module writes one JSONL file per session under + `$SIGIT_CONFIG_DIR/sessions/<session-id>.jsonl` after every completed turn, and + loads it on demand. +- **Resume.** ACP `session/load` restores from the store when a file for that + session id exists. The TUI gets `/resume` to reload the most recent session. + `/clear` deletes the file along with the in-memory history. +- **Compaction.** A `compact_history()` path: estimate tokens (chars / 4), and when + the estimate crosses a per-model budget (default 24k tokens), ask the backend to + summarize the conversation, then rebuild history as system prompt + summary + + the last few turns. Exposed as `/compact`, and run automatically between tool + rounds when over budget. With compaction in place, raise `MAX_TOOL_ROUNDS` from + 10 to 24. + +### Acceptance + +- Kill sigit mid-conversation, restart, `session/load` (or `/resume`): the model + answers a follow-up that requires earlier context. +- A conversation pushed past the token budget compacts instead of erroring, and + the model still answers questions whose answers survived in the summary. +- Unit tests cover snapshot/restore round-trips for both backends, store + read/write, threshold triggering, and post-compaction history shape. + +--- + +## 5. Sequencing + +All three branch off `development` independently. Suggested land order: background +commands (smallest, immediately felt), subagent tool, then sessions and compaction +(largest). Fast follows after these: permission rule patterns on top of PR #20, +stdio MCP transport, web search, and a headless `sigit -p` mode for CI, which is +also what the [Cloud Agent](sigit-code-cloud-agent-plan.md) sandbox runner needs.