| 1 | # Codewhale Runtime Simplification Design |
| 2 | |
| 3 | **Status:** Pre-implementation design record for the v0.9.1 cutover, kept for its |
| 4 | "Rejected alternatives" provenance. It is **not** current runtime documentation |
| 5 | and it shipped differently in two ways: |
| 6 | |
| 7 | - Goal 3 below ("keeping every legacy tool name registered but hidden") was |
| 8 | reversed. The per-action file/git/run/web and `exec_shell*` names were |
| 9 | **removed**, not hidden — `crates/tui/src/tools/registry.rs:2066-2088` and |
| 10 | `:2290-2304` assert they must stay unregistered. Only `apply_patch` and the |
| 11 | `task_*` / `github_*` / `automation_*` / `rlm_*` / `checklist_*` families |
| 12 | survive as hidden aliases. |
| 13 | - The default-active policy is nine names, not ten. `update_plan` and `Web` are |
| 14 | not in `DEFAULT_ACTIVE_NATIVE_TOOLS` |
| 15 | (`crates/tui/src/core/engine/tool_catalog.rs:44-58`). |
| 16 | |
| 17 | For the current contract see [`TOOL_SURFACE.md`](TOOL_SURFACE.md). |
| 18 | |
| 19 | ## Goal |
| 20 | |
| 21 | Make the model-facing runtime smaller, calmer, and easier for models to use by: |
| 22 | |
| 23 | 1. Collapsing the long tail of single-purpose file, git, run, and web tools into |
| 24 | a few canonical action-based tools. |
| 25 | 2. Shrinking the system prompt to durable behavioral invariants and per-turn |
| 26 | permission deltas. |
| 27 | 3. Keeping every legacy tool name registered but hidden so old transcripts, |
| 28 | saved sessions, and recorded automation replay without migration. |
| 29 | |
| 30 | ## Target model-facing surface (default active) |
| 31 | |
| 32 | | Tool | Actions / Niche | |
| 33 | |---|---| |
| 34 | | `Bash` | `run`, `wait`, `interact`, `cancel` (existing) | |
| 35 | | `File` | `read`, `list`, `search_name`, `search_content`, `write`, `edit`, `patch` | |
| 36 | | `Git` | `status`, `diff`, `log`, `show`, `blame` | |
| 37 | | `Run` | `tests`, `verifiers` | |
| 38 | | `Web` | `search`, `fetch`, `wait` (deferred unless network is enabled; hidden aliases for legacy names) | |
| 39 | | `tasks` | durable task family (existing action-based surface) | |
| 40 | | `github` | durable GitHub family (existing; deferred by default) | |
| 41 | | `automation` | durable automation family (existing; deferred by default) | |
| 42 | | `rlm` | durable RLM family (existing; deferred by default) | |
| 43 | | `agent` | sub-agent dispatch | |
| 44 | | `remember` | opt-in durable user-memory capture; eager whenever registered | |
| 45 | | `work_update` | progress / plan-of-work updates | |
| 46 | | `update_plan` | plan artifact updates | |
| 47 | | `tool_search` | on-demand discovery of deferred tools | |
| 48 | |
| 49 | Default-active policy: **10 names** (vs. ~18 before the simplification), with |
| 50 | `remember` registered only for built-in-memory users and the durable families |
| 51 | and `Web` discoverable via `tool_search` when needed. `tool_search` itself is a |
| 52 | synthetic always-active catalog entry. |
| 53 | |
| 54 | ## Rejected alternatives |
| 55 | |
| 56 | - **Keep every tool but defer the rare ones.** This only changes what is |
| 57 | advertised, not how many distinct schemas the model must learn. It also |
| 58 | leaves duplicated guidance in the prompt. |
| 59 | - **Route search and git through `Bash`.** `grep_files`, `file_search`, and the |
| 60 | git tools return structured, workspace-aware output and respect sandbox, |
| 61 | `.gitignore`, and network policy. Shell would force the model to re-parse |
| 62 | free-form text and lose those guarantees, so dedicated tools win. |
| 63 | - **One mega `File` tool plus a separate `Edit` tool.** A single `File` tool is |
| 64 | only slightly larger than a read/edit pair and keeps the boundary the model |
| 65 | already understands (`read` is cheap, `edit` requires prior read). Splitting |
| 66 | would re-introduce a two-tool alias for the same underlying operations. |
| 67 | - **Delete legacy tools.** Saved transcripts and replay tests rely on the old |
| 68 | names. Removing them would require a config migration and break reproducibility. |
| 69 | Hidden aliases avoid both. |
| 70 | |
| 71 | ## Compatibility |
| 72 | |
| 73 | - Legacy names (`read_file`, `write_file`, `edit_file`, `list_dir`, `file_search`, |
| 74 | `grep_files`, `apply_patch`, `git_status`, `git_diff`, `git_log`, `git_show`, |
| 75 | `git_blame`, `run_tests`, `run_verifiers`, `web_search`, `fetch_url`, |
| 76 | `wait_for_dev_server`) stay registered with `model_visible = false`. |
| 77 | - The engine resolves calls by name, so old transcripts replay without changes. |
| 78 | - `DEFAULT_ACTIVE_NATIVE_TOOLS` is updated to list the new canonical names only; |
| 79 | hidden legacy tools are ignored by catalog construction. |
| 80 | |
| 81 | ## Prompt simplification |
| 82 | |
| 83 | - Replace the tool-calling recipe sections in `AGENT_MODE` and |
| 84 | `SUBAGENT_OUTPUT_FORMAT` with short references to the canonical tools. |
| 85 | - Reduce mode deltas to permission statements (Act = write requires approval, |
| 86 | Plan = no writes or shell, Full Access = auto-approved, Operate = coordinate from |
| 87 | ordinary messages). |
| 88 | - Keep the `BASE_PROMPT` behavioral invariants, `LANGUAGE_PROMPT`, and |
| 89 | `OUTPUT_PROMPT` intact. |
| 90 | - Move detailed templates (`COMPACT_TEMPLATE`, sub-agent brief format, planning |
| 91 | artifact template) out of the stable prefix and into tool schemas or |
| 92 | conditional blocks. |
| 93 | |
| 94 | ## Validation |
| 95 | |
| 96 | - Provider-free: `scripts/measure-runtime-contract.py` reports active tool count |
| 97 | and prompt bytes before and after. |
| 98 | - Behavior-preserving: targeted unit tests for `File`, `Git`, `Run`, and `Web` |
| 99 | dispatch against legacy inputs. |
| 100 | - Regression: `cargo fmt`, `cargo clippy --workspace --all-targets --locked`, |
| 101 | `cargo test -p codewhale-tui --bin codewhale-tui --locked`, and |
| 102 | `cargo test --workspace`. |
| 103 | |
| 104 | ### v0.9.1 receipt |
| 105 | |
| 106 | The source contract and provider-free metric now exercise the complete policy, |
| 107 | including opt-in `remember`: |
| 108 | |
| 109 | | Contract | Before | After | |
| 110 | |---|---:|---:| |
| 111 | | Default active tools | 18 | 10 | |
| 112 | | Agent-mode instruction bytes | 4,064 | 663 | |
| 113 | | Full system-prompt bytes | 15,842 | 15,368 | |
| 114 | |
| 115 | The final active names are `Bash`, `File`, `Git`, `Run`, `agent`, `remember`, |
| 116 | `tasks`, `update_plan`, `work_update`, and `tool_search`. `remember` is present |
| 117 | only when built-in memory is enabled; it is eager whenever registered. `File` |
| 118 | advertises only read actions in Plan mode, and its `patch` action appears only |
| 119 | when the existing apply-patch feature is enabled. Hidden aliases remain |
| 120 | executable for transcript replay but are absent from the model catalog. |
| 121 |