diff --git a/.gitignore b/.gitignore index 4e091b581..a5955ebad 100644 --- a/.gitignore +++ b/.gitignore @@ -86,21 +86,16 @@ npm/*/bin/downloads/ apps/ # Claude Code runtime artifacts -.claude/settings.json -.claude/scheduled_tasks.lock -.claude/worktrees/ .worktrees/ .ace-tool/ -# Local-only Claude / ralph notes -.claude/*.local.md -.claude/*.local.json - -# Maintainer handoff + codemap notes are working-state, not user-facing -# artifacts. They've leaked into the public repo via .claude/ in the past -# (HANDOFF_v0.8.28, CODEMAP_v0.8.25) — those files now live under -# .private/handoffs/ instead. Block the patterns here so a future accidental -# add doesn't silently land on main. +# NOTE: the blanket `.claude/` rule further down already ignores everything +# under .claude/ — `git check-ignore -v` attributes every path below to that +# line, not to these. The handoff/codemap patterns are kept as defense in depth: +# those notes are working state, not user-facing artifacts, and they leaked into +# the public repo through .claude/ before (HANDOFF_v0.8.28, CODEMAP_v0.8.25). +# They live under .private/handoffs/ now. If anyone ever narrows the blanket +# rule to track part of .claude/, these must keep holding. .claude/HANDOFF_* .claude/CODEMAP_* .claude/handoff_* diff --git a/config.example.toml b/config.example.toml index 812eaff7b..03d29ede3 100644 --- a/config.example.toml +++ b/config.example.toml @@ -892,21 +892,26 @@ max_subagents = 10 # optional (1-20) # Off by default. Enable with `[advisor] enabled = true` or toggle per-session # with `/advisor on` / `/advisor off`. # -# Options: +# Options (the full set — `AdvisorConfigToml` in crates/config/src/lib.rs): # enabled — master switch (default: false) -# max_tool_pairs — number of recent tool call/result pairs to read -# (default: 8, max: 32) +# max_tool_calls — number of recent tool call/result pairs to read +# (default: 10, clamped to 1–50) # rate_limit_secs — minimum seconds between successive advisor notes -# (default: 60) -# dedup_window_secs — notes with identical text within this window are -# suppressed (default: 300) -# system_prompt — override the default advisor system prompt +# (default: 60, clamped to 5–3600) +# dedup_window_secs — notes whose content hash matches the previous note +# within this window are dropped (default: 300) +# model — model override for the advisory call; when absent the +# advisor reuses the session's current model +# +# Unknown keys under [advisor] are silently ignored, not rejected — a typo +# leaves the default in place with no error. # # [advisor] # enabled = false -# max_tool_pairs = 8 +# max_tool_calls = 10 # rate_limit_secs = 60 # dedup_window_secs = 300 +# model = "deepseek-v4-flash" # ───────────────────────────────────────────────────────────────────────────────── # Skills (#140) @@ -1430,8 +1435,9 @@ default_text_model = "deepseek-ai/deepseek-v4-pro" # instructions = "Run cargo fmt --check and cargo clippy; never apply fixes." # # [fleet.profiles.ci-linter.permissions] -# allow_tools = ["exec_shell"] -# deny_tools = [] +# allow_shell = true # the only three keys are allow_shell, trust, +# trust = false # and approval_required (FleetProfilePermissions +# approval_required = true # in crates/config/src/lib.rs) # # [fleet.profiles.pr-reviewer] # slot = "reviewer" diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 7ee6868a8..90def9a35 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -2031,12 +2031,6 @@ iTerm2, WezTerm, Ghostty, and kitty are matched first and use their own notification protocols, and `method = "osc9"` / `"bel"` / `"off"` opt out of the `osascript` path explicitly. -### Parsed but currently unused (reserved for future versions) - -These keys are accepted by the config loader but not currently used by the interactive TUI or built-in tools: - -- `tools_file` - ## Tool Catalog Codewhale loads a small core native tool catalog by default and leaves less diff --git a/docs/RUNTIME_SIMPLIFICATION_DESIGN.md b/docs/RUNTIME_SIMPLIFICATION_DESIGN.md index 2852a89cd..a5c587fa8 100644 --- a/docs/RUNTIME_SIMPLIFICATION_DESIGN.md +++ b/docs/RUNTIME_SIMPLIFICATION_DESIGN.md @@ -1,5 +1,21 @@ # Codewhale Runtime Simplification Design +**Status:** Pre-implementation design record for the v0.9.1 cutover, kept for its +"Rejected alternatives" provenance. It is **not** current runtime documentation +and it shipped differently in two ways: + +- Goal 3 below ("keeping every legacy tool name registered but hidden") was + reversed. The per-action file/git/run/web and `exec_shell*` names were + **removed**, not hidden — `crates/tui/src/tools/registry.rs:2066-2088` and + `:2290-2304` assert they must stay unregistered. Only `apply_patch` and the + `task_*` / `github_*` / `automation_*` / `rlm_*` / `checklist_*` families + survive as hidden aliases. +- The default-active policy is nine names, not ten. `update_plan` and `Web` are + not in `DEFAULT_ACTIVE_NATIVE_TOOLS` + (`crates/tui/src/core/engine/tool_catalog.rs:44-58`). + +For the current contract see [`TOOL_SURFACE.md`](TOOL_SURFACE.md). + ## Goal Make the model-facing runtime smaller, calmer, and easier for models to use by: diff --git a/docs/SUBAGENTS.md b/docs/SUBAGENTS.md index 1b17fc77d..393281750 100644 --- a/docs/SUBAGENTS.md +++ b/docs/SUBAGENTS.md @@ -260,7 +260,8 @@ the next turn. Up to **64** sub-agents run concurrently by default (`DEFAULT_MAX_SUBAGENTS`), configurable via `[subagents].max_concurrent` in `~/.codewhale/config.toml` up to the hard ceiling of **128** (`MAX_SUBAGENTS`). The session admits a bounded -queue of up to **200** running plus queued sub-agents by default, so a turn can +queue of up to **1024** running plus queued sub-agents by default +(`MAX_SUBAGENT_ADMISSION`, `crates/tui/src/config/subagent_limits.rs:21`), so a turn can request broad fan-out and let the manager drain it without creating an unbounded population. @@ -537,14 +538,18 @@ scouts and reviewers should be precise here. ## Memory and the `remember` tool (#489) -Sub-agents inherit the parent's memory file when memory is enabled +Sub-agents share the parent's native memory store when memory is enabled (`[memory] enabled = true` or `DEEPSEEK_MEMORY=on`). They can -append durable notes via the `remember` tool — handy for an +append durable notes via the `remember` tool — handy for a scout that discovers a project convention worth carrying across sessions, or a verifier that learns "this test is flaky". -Memory writes are scoped to the user's own `memory.md` file; they -don't go through the standard write-approval flow. +`remember` takes a `scope` of `global` or `workspace` +(`crates/tui/src/tools/remember.rs:79-108`) and writes through +`NativeMemoryStore` to `~/.codewhale/memory/global/MEMORY.md` or +`~/.codewhale/memory/workspaces//MEMORY.md`. Writes do not go through the +standard write-approval flow. The legacy single-file `memory.md` path was +removed in v0.9.4 (remember.rs:165); see `docs/MEMORY.md` for the full layout. ## Implementation notes diff --git a/docs/TOOL_SURFACE.md b/docs/TOOL_SURFACE.md index b2826ceb9..415b5aad5 100644 --- a/docs/TOOL_SURFACE.md +++ b/docs/TOOL_SURFACE.md @@ -15,7 +15,7 @@ Implementation sources: ## Default-active contract -The default-active policy contains exactly these ten names: +The default-active policy contains exactly these nine names: 1. `Bash` 2. `File` @@ -24,15 +24,23 @@ The default-active policy contains exactly these ten names: 5. `agent` 6. `remember` 7. `tasks` -8. `update_plan` -9. `work_update` -10. `tool_search` +8. `work_update` +9. `tool_search` + +The first eight are `DEFAULT_ACTIVE_NATIVE_TOOLS` in +`crates/tui/src/core/engine/tool_catalog.rs`. `tool_search` is synthetic rather +than registry-backed and is always active. `remember` is registered only when the user enables the built-in memory path; once present, it stays eager so a model can capture a durable preference without -first discovering the tool. A memory-disabled or Moraine-fallback runtime omits -that registration and therefore exposes nine of the ten policy names. -`tool_search` is synthetic rather than registry-backed and is always active. +first discovering the tool. A memory-disabled runtime omits that registration and +therefore exposes eight of the nine policy names. + +`update_plan` is **not** default-active. It is registered +(`crates/tui/src/tools/plan.rs:401`) but reachable only through `tool_search`, so +it does not appear in the first-turn catalog. Plan mode narrows the active set +further: `Bash` and `Run` drop out, leaving `File`, `Git`, `agent`, `tasks`, +`work_update`, and `tool_search`. The surface is action-based. A model calls one stable tool name and selects the operation through its `action` field instead of choosing among many synonymous @@ -65,7 +73,7 @@ by the former spellings remain in force. | `agent` | Dispatch one focused sub-agent run and return an id, compact receipt, and transcript handle. | | `remember` | Append one terse durable preference or convention when the user has enabled built-in memory. | | `tasks` | Create, list, read, cancel, gate, and inspect durable task work through one action family. | -| `update_plan` | Publish optional high-level strategy, phases, constraints, verification, and handoff context. | +| `update_plan` | Publish optional high-level strategy, phases, constraints, verification, and handoff context. Reachable through `tool_search` only — see the default-active contract above. | | `work_update` | Replace the concrete To-do / Work progress projection for the active thread or durable task. | | `tool_search` | Discover and load a deferred tool only when the current turn needs it. | @@ -135,22 +143,40 @@ Modes and permission postures are separate controls: See `docs/MODES.md` for the full mode and posture contract. +## Removed spellings + +The per-action single-purpose names below are **not registered**. They were +deleted, not hidden: a call to any of them fails with `tool '' is not +registered`, because `resolve` has deliberately no fuzzy step +(`crates/tui/src/tools/registry.rs:313-316` — "a hallucinated name must fail, +never dispatch"). There is no replay path for them; a transcript that calls one +will not re-execute. + +| Removed spelling | Use instead | +|---|---| +| `exec_shell`, `exec_shell_wait`, `exec_wait`, `exec_shell_interact`, `exec_interact`, `exec_shell_cancel` | `Bash`: `run`, `wait`, `interact`, `cancel` | +| `read_file`, `list_dir`, `grep_files`, `file_search`, `write_file`, `edit_file` | `File`: `read`, `list`, `search_content`, `search_name`, `write`, `edit` | +| `git_status`, `git_diff`, `git_log`, `git_show`, `git_blame` | `Git`: matching action | +| `run_tests`, `run_verifiers` | `Run`: `tests`, `verifiers` | +| `web_search`, `fetch_url`, `wait_for_dev_server` | `Web`: `search`, `fetch`, `wait` | + +Enforced by `shell_surface_contains_only_the_canonical_bash_tool` +(registry.rs:2290, `"{alias} must be removed"`) and the retired-name loop at +registry.rs:2066-2088 (`"{retired} must stay removed"` / +`"{retired} must not be advertised"`). + ## Replay-only aliases -Legacy single-purpose names stay registered so saved transcripts, sessions, and +These legacy names *are* still registered so saved transcripts, sessions, and recorded automation replay without migration. They are hidden from the model catalog and from `tool_search`; new prompts and docs must use the canonical action tools. | Replay-only spellings | Canonical action | |---|---| -| `exec_shell`, `exec_shell_wait`, `exec_wait`, `exec_shell_interact`, `exec_interact`, `exec_shell_cancel` | `Bash`: `run`, `wait`, `interact`, `cancel` | -| `read_file`, `list_dir`, `grep_files`, `file_search`, `write_file`, `edit_file`, `apply_patch` | `File`: `read`, `list`, `search_content`, `search_name`, `write`, `edit`, `patch` | -| `git_status`, `git_diff`, `git_log`, `git_show`, `git_blame` | `Git`: matching action | -| `run_tests`, `run_verifiers` | `Run`: `tests`, `verifiers` | -| `web_search`, `fetch_url`, `wait_for_dev_server` | `Web`: `search`, `fetch`, `wait` | -| `task_*` | `tasks`: matching action | -| `github_*` | `github`: matching action | +| `apply_patch` | `File`: `patch` (also DeepSeek Responses' one custom tool) | +| `task_create`, `task_list`, `task_read` | `tasks`: matching action | +| `github_issue_context`, `github_pr_context`, `github_comment` | `github`: matching action | | `automation_*` | `automation`: matching action | | `rlm_open`, `rlm_eval`, `rlm_configure`, `rlm_close` | `rlm`: `open`, `eval`, `configure`, `close` | | `checklist_*`, `todo_*` | `work_update` | @@ -263,13 +289,18 @@ catalog and alias visibility at the exact candidate SHA: ```bash python3 scripts/measure-runtime-contract.py -cargo test -p codewhale-tui --bin codewhale-tui --locked canonical_runtime_tools_hide_legacy_aliases -cargo test -p codewhale-tui --bin codewhale-tui --locked shell_alias_tools_hidden_from_model_catalog -cargo test -p codewhale-tui --bin codewhale-tui --locked runtime_task_families_expose_canonical_tools_with_hidden_aliases +cargo test -p codewhale-tui --bin codewhale-tui --locked shell_surface_contains_only_the_canonical_bash_tool +cargo test -p codewhale-tui --bin codewhale-tui --locked runtime_task_families_expose_only_canonical_tools +cargo test --locked -p codewhale-tui --bin codewhale-tui print_mode_tool_catalog_metrics -- --ignored --nocapture ``` +Check the test names against the source before trusting a green run: `cargo test` +exits 0 with "0 passed; N filtered out" when a filter matches nothing, so a +misspelled filter is indistinguishable from a pass. (Three filters printed here +before v0.9.4 named tests that did not exist.) + The provider-free full-policy receipt enables built-in memory and must report the -ten default-active names listed above. A memory-disabled receipt truthfully omits -`remember`. A separate repository-wide tool count may include deferred, dynamic, +nine default-active names listed above. A memory-disabled receipt truthfully omits +`remember` and reports eight. A separate repository-wide tool count may include deferred, dynamic, feature-gated, and replay-only registrations; it is not the number of tools placed in the first-turn model catalog. diff --git a/docs/TTC_DESIGN.md b/docs/TTC_DESIGN.md index 2d8abdd8d..f2db6b366 100644 --- a/docs/TTC_DESIGN.md +++ b/docs/TTC_DESIGN.md @@ -1,6 +1,8 @@ # Test-Time Compute (TTC) in CodeWhale — design -Status: **approved direction** (maintainer greenlit). Synthesized from three independent reviews — the verify-tool implementation contributor, GLM 5.2, and an internal analysis — which all converged. This doc is the spec; implementation is deferred beyond v0.9.0 and is split so nothing here blocks the current release. +Status: **landed in part.** Capability (A), the `verify` tool, shipped and is default-on as of v0.9.4 — `crates/tui/src/tools/verify.rs`, feature key `verify_tool` (`crates/tui/src/features.rs:262`), registered at `crates/tui/src/tools/registry.rs:1040-1041` with `verify_tool_enabled` defaulting to `true` (registry.rs:546-561). Capability (B) (sub-agent reasoning-effort escalation) and the #3982/#4013 triggers remain deferred. Treat the (A) sections below as a design record of what shipped, not as a plan; the deferred-work notes at the end still stand for (B). + +Synthesized from three independent reviews — the verify-tool implementation contributor, GLM 5.2, and an internal analysis — which all converged. ## What TTC means here @@ -27,7 +29,7 @@ Then three *distinct* entry points share that engine but **keep their own invoca **Why a tool, not a critic sub-agent:** a `verify` tool is *structurally isomorphic to the existing `review` tool* — same `ToolSpec` trait, same `ToolRegistryBuilder` path, same `Feature` gate, same `MessageRequest` reasoning normalization. It inherits every existing guarantee for almost no new surface. A critic *sub-agent* would be a **second runtime with a second policy surface** (spawn-depth, allowlist, sub-agent tier resolution) — the textbook bolted-on smell. (A sub-agent critic that autonomously explores may return as an opt-in follow-up *behind the same tool contract* once #4193's spawn work has settled — but it is NOT the default.) -**Interface:** registered via `ToolRegistryBuilder::with_verify(critic)`, gated by a `Feature` flag. Input: `claim` (required) + optional `requirement`, `scope` (`diff|staged|none`), `base`, `files[]`, `focus`. It snapshots evidence deterministically (diff by scope — **including uncommitted working-tree changes when a base is given**, per PR #4199 fix — plus named files), builds ONE `MessageRequest` at `ReasoningEffort::Max` with **tools disabled**, and returns the structured verdict as a tool result. +**Interface:** registered via `ToolRegistryBuilder::with_verify_tool(client, model)` (registry.rs:886 — the design said `with_verify(critic)`; the shipped signature takes an optional client and a model name), gated by a `Feature` flag. Input: `claim` (required) + optional `requirement`, `scope` (`diff|staged|none`), `base`, `files[]`, `focus`. It snapshots evidence deterministically (diff by scope — **including uncommitted working-tree changes when a base is given**, per PR #4199 fix — plus named files), builds ONE `MessageRequest` at `ReasoningEffort::Max` with **tools disabled**, and returns the structured verdict as a tool result. **Where it plugs in:** the standard tool loop. No new control plane. The model invokes it like `read`/`edit`/`review`. diff --git a/docs/architecture/command-dispatch.md b/docs/architecture/command-dispatch.md index ef1ec0412..580da9084 100644 --- a/docs/architecture/command-dispatch.md +++ b/docs/architecture/command-dispatch.md @@ -130,11 +130,11 @@ count, allowed tools, pause state, todos, and plan state. | `user_commands.rs` lower layer | The registry owns runtime behavior, while this module remains the shared filesystem and parser layer. | | `#[cfg(test)]` helpers in `user_commands.rs` | Deferred test migration compatibility while registry-specific tests are added. | -## EPIC-002 Completion Status (Phase 8 complete; ready for PR) +## EPIC-002 Completion Status (closed) EPIC-002 (Command Single Responsibility Extraction) extracted commands for -all 9 command groups through Layer 4.x sublayers. Layer 4.2 (FEAT-008) is -complete with final validation evidence recorded. +all 9 command groups through Layer 4.x sublayers. Layer 4.2 (FEAT-008) landed as +PR #3706 (merged) and issue #2870 closed on 2026-08-01. | Layer | FEAT | Title | Status | |---|---|---|---| @@ -142,8 +142,6 @@ complete with final validation evidence recorded. | 4.1 | FEAT-007 | Project, Memory, Skills, Utility, and Plugins Extraction | Complete | | 4.2 | FEAT-008 | Registry Cleanup, Documentation, and Full Validation | Complete | -### Current Evidence (Draft — subject to final verification) - ## Replay Status (EPIC-001) FEAT-001's group-owned built-in command direction is represented on `main` by diff --git a/docs/architecture/provider-model-settings-v091.md b/docs/architecture/provider-model-settings-v091.md index 97ce98b14..48feb3392 100644 --- a/docs/architecture/provider-model-settings-v091.md +++ b/docs/architecture/provider-model-settings-v091.md @@ -9,7 +9,8 @@ setup and adding a model are deliberately separate operations. 1. **Configured, enabled, current, saved, and default are distinct.** A provider is configured when `config::provider_is_configured` finds the active route, usable auth/external consent, or meaningful explicit provider configuration - (`crates/tui/src/config.rs:8625-8669`). An enabled model is a + (`provider_is_configured` in `crates/tui/src/config.rs`; grep the symbol + rather than trusting a line number). An enabled model is a `(provider identity, model id)` entry in `Settings::enabled_models`; the current model is `App::{api_provider,model,auto_model}`; a saved provider-specific preference is `Settings::provider_models`; and the startup diff --git a/docs/skills/README.md b/docs/skills/README.md index 9b00bb491..398c9bc4a 100644 --- a/docs/skills/README.md +++ b/docs/skills/README.md @@ -2,7 +2,8 @@ GitHub-stewardship and release-QA workflows for maintaining Codewhale, codified as `SKILL.md` skills (same format Claude Code and Codewhale both load). They encode the -workflows used to assemble the v0.8.61 release. +issue-triage, PR-harvest, credit, and release-QA workflows the maintainers run each +release. For end-user Skills Manager behavior (ownership, audit, import, trust), see [../SKILLS.md](../SKILLS.md). @@ -13,5 +14,5 @@ To activate: `/skills`, or bundle into `crates/tui/assets/skills/` + register in `crates/tui/src/skills/system.rs` to ship it. -Skills: gh-file-issue, gh-compile-issues, gh-assign-issues, gh-plan-issues, gh-find-prs, +Skills: gh-file-issue, gh-compile-issues, gh-assign-issues, gh-find-prs, gh-treasure-hunt, gh-close-issues, gh-credit-harvest, codew-release-qa-sweep.