main
md 172 lines 8.29 KB
Rendered Raw
1 # siGit Code parity roadmap: the three biggest wins
2
3 Status: draft v1 (2026-07-04). Owner: product/eng. Audience: internal (private repo).
4 Scope: **siGit Code**, the Rust CLI / ACP agent (see [product-overview.md](product-overview.md)).
5 This document records where siGit Code stands against Claude Code and specifies the
6 three features that close the most important gaps. Each spec below is written to be
7 implementable on its own branch off `development` in the `sigit` repo; the three are
8 independent of each other.
9
10 ---
11
12 ## 1. Where we stand
13
14 siGit Code already covers the core agent loop: file tools, shell, glob and search,
15 web fetch, todos, memory, Agent Skills, an MCP client (Streamable HTTP), project
16 instruction files (AGENTS.md / CLAUDE.md), a tool permission system with plan mode
17 (PR #20), commit co-author attribution (PR #21), ACP editor integration, a Unix TUI,
18 and local / cloud / BYO inference. Local inference is our differentiator; Claude
19 Code has no equivalent.
20
21 What Claude Code has that we lack is not one feature. It is the machinery that lets
22 an agent work for a long time:
23
24 | Capability | Claude Code | siGit Code today |
25 |---|---|---|
26 | Durable sessions (resume after restart) | yes | no, history lives in RAM |
27 | Context compaction | auto + manual | no, hard cap of 10 tool rounds |
28 | Subagents (delegate work to a fresh context) | yes | no |
29 | Background / long-running commands | yes | no, commands are killed at 120s |
30 | Web search | yes | fetch only |
31 | Custom slash commands | yes | built-ins only |
32 | Permission rule patterns (`Bash(git:*)`) | yes | mode + per-tool only |
33 | stdio MCP transport | yes | HTTP only |
34 | Headless mode for CI | yes | no |
35
36 The three specs below are the biggest wins, ordered by implementation cost from
37 smallest to largest. Everything else on the list is a fast follow.
38
39 ---
40
41 ## 2. Spec: background and long-running commands
42
43 **Branch:** `feature/background-commands` · **Touches:** `src/tools.rs` (self-contained)
44
45 ### Problem
46
47 `run_command` kills every child at the 120 second `COMMAND_TIMEOUT`. A cold
48 `cargo build`, a full test suite, a dev server, or a watch task cannot run at all.
49 This is the most visceral failure in daily use: the agent cannot even build the
50 projects it is asked to work on.
51
52 ### Design
53
54 - `run_command` gains an optional boolean argument `run_in_background`. When true,
55 the child is spawned, registered in a process-global task table
56 (`Mutex<HashMap<u64, BackgroundTask>>`, monotonically increasing ids, same
57 process-global pattern as `mcp.rs`), and the tool returns immediately with the
58 task id. A reader thread drains stdout/stderr into a capped buffer
59 (`COMMAND_OUTPUT_LIMIT` per task, oldest output dropped first).
60 - New tool `command_output` `{task_id}`: returns output accumulated since the last
61 poll plus the task status (running / exited with code).
62 - New tool `kill_command` `{task_id}`: terminates the child (SIGKILL on Unix,
63 `TerminateProcess` semantics via `Child::kill` everywhere) and reports the tail
64 of its output.
65 - Foreground behavior is unchanged, including the 120s timeout. Background tasks
66 have no timeout; all children die with the sigit process (document this).
67 - Tool descriptions must steer the model: run servers, builds, and anything that
68 may exceed two minutes in the background, then poll.
69 - When the permission system (PR #20) merges: `command_output` is read-only,
70 `kill_command` is mutating but only affects children the agent itself started.
71
72 ### Acceptance
73
74 - A background task outliving the 120s foreground timeout keeps running and its
75 output is retrievable via `command_output`.
76 - `kill_command` stops a running task; polling a finished task reports its exit code.
77 - Unit tests cover: spawn + poll + finish, kill, unknown task id, output capping.
78
79 ---
80
81 ## 3. Spec: subagent tool
82
83 **Branch:** `feature/subagent-tool` · **Touches:** `src/tools.rs`, `src/backend.rs`, both surfaces' startup
84
85 ### Problem
86
87 One conversation does everything, so every file read pollutes the main context
88 forever. With on-device models this is fatal: a 3B model's context fills after a
89 few searches. Delegating research to a throwaway context keeps the main thread
90 small.
91
92 ### Design
93
94 - New tool `task` `{description, prompt}`: runs a nested agent loop in a fresh
95 conversation and returns only its final text answer (capped, e.g. 8k chars).
96 - The subagent's toolset is read-only: `read_file`, `list_directory`,
97 `search_files`, `glob`, `read_website`. No `task` (no recursion), no mutating
98 tools, so no permission prompts fire mid-subagent.
99 - Architecture: `tools.rs` is backend-agnostic, so it cannot construct a backend.
100 At startup each surface registers a subagent factory in a process-global
101 (`OnceLock<Box<dyn Fn() -> Option<Arc<dyn InferenceBackend>>>>`): for
102 `OpenAiBackend` the factory builds a fresh backend with the same base_url / key /
103 model and a short subagent system prompt; for `LocalBackend` the factory returns
104 `None` for now (onde has a single shared history; a second concurrent context
105 needs onde support first) and the tool returns a clear "not available on-device
106 yet" result the model can react to.
107 - The nested loop reuses `send_message_with_tools` / `send_tool_results` and
108 `execute_tool`, with its own round cap (8).
109 - The `task` tool is only offered when the factory reports availability, the same
110 conditional-spec pattern the `skill` tool uses.
111
112 ### Acceptance
113
114 - On an OpenAI-compatible backend, `task` completes a research prompt using only
115 read-only tools and returns a text answer; the main conversation history gains
116 one tool result, not the subagent transcript.
117 - On-device, the tool either is not offered or returns the documented fallback.
118 - Unit tests cover the loop against a scripted backend (the
119 `tests/acp_permissions.rs` fake-endpoint harness pattern) and the toolset
120 restriction.
121
122 ---
123
124 ## 4. Spec: durable sessions and context compaction
125
126 **Branch:** `feature/session-persistence-compaction` · **Touches:** `src/backend.rs`, `src/main.rs`, `src/chat.rs`, new `src/session_store.rs`
127
128 ### Problem
129
130 History lives in RAM (`OpenAiBackend`'s message vec, onde's engine state). A
131 restart loses everything, ACP `session/load` cannot actually restore, and the hard
132 `MAX_TOOL_ROUNDS = 10` cap is the only defense against blowing the context window.
133 This is the single hardest ceiling on task size, and it hurts most on-device where
134 context windows are smallest.
135
136 ### Design
137
138 - **Persistence.** `InferenceBackend` gains `history_snapshot() -> Vec<serde_json::Value>`
139 and `restore_history(Vec<serde_json::Value>)`. `OpenAiBackend` serializes its
140 message vec as-is. `LocalBackend` flattens through onde's `history()` /
141 `push_history` (tool entries flatten to text in the MVP; acceptable loss).
142 A new `session_store` module writes one JSONL file per session under
143 `$SIGIT_CONFIG_DIR/sessions/<session-id>.jsonl` after every completed turn, and
144 loads it on demand.
145 - **Resume.** ACP `session/load` restores from the store when a file for that
146 session id exists. The TUI gets `/resume` to reload the most recent session.
147 `/clear` deletes the file along with the in-memory history.
148 - **Compaction.** A `compact_history()` path: estimate tokens (chars / 4), and when
149 the estimate crosses a per-model budget (default 24k tokens), ask the backend to
150 summarize the conversation, then rebuild history as system prompt + summary +
151 the last few turns. Exposed as `/compact`, and run automatically between tool
152 rounds when over budget. With compaction in place, raise `MAX_TOOL_ROUNDS` from
153 10 to 24.
154
155 ### Acceptance
156
157 - Kill sigit mid-conversation, restart, `session/load` (or `/resume`): the model
158 answers a follow-up that requires earlier context.
159 - A conversation pushed past the token budget compacts instead of erroring, and
160 the model still answers questions whose answers survived in the summary.
161 - Unit tests cover snapshot/restore round-trips for both backends, store
162 read/write, threshold triggering, and post-compaction history shape.
163
164 ---
165
166 ## 5. Sequencing
167
168 All three branch off `development` independently. Suggested land order: background
169 commands (smallest, immediately felt), subagent tool, then sessions and compaction
170 (largest). Fast follows after these: permission rule patterns on top of PR #20,
171 stdio MCP transport, web search, and a headless `sigit -p` mode for CI, which is
172 also what the [Cloud Agent](sigit-code-cloud-agent-plan.md) sandbox runner needs.