返回 CodeWhale
CHANGELOG.md
根目录 / crates / tui / CHANGELOG.md
1 # Changelog
2
3 All notable changes to this project will be documented in this file.
4
5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8 ## [Unreleased]
9
10 ## [0.10.1] - 2026-10-01
11
12 Codewhale v0.10.1 focuses on reliability and first-run behavior. Turns that
13 stall now say so, approvals keep what you approved, plugin suggestions are
14 quieter, and Fleet runs can be checked before they spend anything.
15 Scripts that parse `--json` output should read the **Breaking for scripts**
16 note below before upgrading.
17
18 ### Added
19
20 - Experimental TypeScript extension host. New in this release and off by
21 default: turn it on with `[features] extension_host = true`. A plugin that
22 declares a `native` TypeScript or JavaScript entry (the Cordis / DeepSeek
23 Harness plugin model) can contribute tools, slash commands, pre-execution
24 policy hooks, additive prompt sections, reviewed skill roots and plugin-local
25 JSON state. Its code runs in a separate
26 Node process, never inside Codewhale (Bun is an opt-in through
27 `[extension_host] runtime`), and every call goes through Codewhale's own gate:
28 an extension tool is never treated as read-only, so it always meets the
29 approval gate (Full Access, Bypass or a session grant for that reviewed plugin
30 can satisfy it), a command runs only when you type it, and a plugin must be
31 reviewed and enabled first. The host is sandboxed on macOS (Seatbelt) and on
32 Linux with bubblewrap, with no direct network and no reads of the protected
33 credential locations (Codewhale's secret stores and the Codewhale, Codex and
34 DSH homes). A Native extension starts only after that sandbox is verified at
35 launch: if bubblewrap is missing or its namespace probe fails, activation is
36 refused with the concrete error. Codewhale's own pinned built-in host modules
37 keep a diagnosed exception, and every effect still needs a Rust operation
38 ticket. On Windows a Native extension starts only in a freshly created Less
39 Privileged AppContainer whose only capability is `registryRead` (Winsock
40 cannot start without it), after Codewhale checks its token and a real file
41 and network probe; otherwise activation is refused.
42 Other files you
43 can read, such as project `.env` files, stay readable, and plugins sharing the
44 host can interfere with each other, so enable only plugins you have reviewed
45 ([docs/EXTENSIONS.md](docs/EXTENSIONS.md)).
46 - Extension slash commands: a plugin registers one with `ctx.commands.register`.
47 It runs only when you type it, and it can show text, or submit a prompt as
48 your next message that then goes through the ordinary turn and its approvals;
49 it cannot call the model or a tool itself. A command cannot take a built-in
50 command's name or another plugin's, and a markdown command with the same name
51 wins. A command has 30 seconds, and commands are TUI only: the Runtime API
52 does not list or run them.
53 - Native extension authoring now includes policy listeners through
54 `ctx.on('tools/pre-execute', ...)`, prompt sections through
55 `ctx.prompt.registerSection`, and persistent plugin-local state through
56 `ctx.storage`. Listeners may deny, ask, revise input or annotate; Rust
57 rechecks revised calls and owns every approval. Prompt sections cannot
58 replace the system prompt, and state exposes no session history or secret
59 API. These services share the experimental, off-by-default host's reviewed
60 owner lifecycle and are withdrawn when their owner unloads or is revoked;
61 saved state remains available when the plugin reloads.
62 - Extension tool input is checked against the JSON Schema the tool registered,
63 before an approval card appears and again before the call reaches the host. An
64 invalid call comes back to the model as an error naming what to correct, and
65 the host never sees it. A schema that cannot be compiled, or that refers
66 outside itself with `$ref`, is refused when the tool registers.
67 - An extension tool can call eligible core tools with `core/call` while the
68 ordinary turn is running that extension tool. Rust supplies a temporary
69 invocation ticket and still owns planning, hooks, permissions, approval and
70 execution. The ticket is bound to the plugin owner, host process and live
71 invocation, and expires when that invocation ends or is revoked. Commands,
72 timers and plugin startup cannot use this path. Approval grants are scoped
73 to the reviewed extension build; a grant to the model does not cover it.
74 Shell and network calls require a person's prompt even with a remembered
75 grant; a permission mode that cannot present that prompt refuses the call.
76 MCP tools, Computer Use, other extensions, agent/workflow launches and
77 permission-changing tools remain unavailable through this path. A cancelled
78 invocation withdraws its pending approvals instead of deciding them for you.
79 - Extension host identity is checked at startup: its reported trust tier and
80 built-in module digests must match the process Rust launched. Built-in host
81 code and third-party plugins have separate process and owner namespaces;
82 the table pins the MCP protocol module and the execution harness. The
83 optional Host MCP backend uses the official TypeScript SDK for framing,
84 with Rust retaining credentials, network/process access, approval and exact
85 operation tickets. All 30 existing recorded comparisons pass locally.
86 The Rust backend stays the default until platform and rollout gates pass;
87 its protocol adapters remain through the compatibility window.
88 - A plugin can declare several `native` entries (`native.paths`, up to 64). They
89 activate in order under one owner, so one disable, review change or crash
90 takes all of them down. If one entry fails to activate, only that entry is
91 withdrawn: entries that already activated stay registered, and the plugin
92 fails only when no entry activates.
93 - Plugin settings and context: `[plugins."<name>".config]` in your own
94 `config.toml` is passed to the plugin's `apply(ctx, config)` and checked
95 against its exported `Config` schema; a project's `.codewhale/config.toml`
96 cannot set it, a change applies at `/plugin reload`, and `/plugin show` lists
97 the keys, never the values. Tools and commands also receive the workspace of
98 the session that called them and a private data directory for the plugin under
99 `~/.codewhale/extension-host/data/plugins/`; no home, credential or other
100 workspace path is passed.
101 - `codewhale --enable <feature>` and `--disable <feature>` work from the
102 `codewhale` command; before, they were rejected. Put the flag before any
103 subcommand.
104 - The extension host bundle carries MIT-licensed code (Cordis, Schemastery and
105 others). Its third-party licence notices are generated from what the bundle
106 actually contains and written beside the bundle when it is unpacked, and
107 `THIRD_PARTY_NOTICES.md` lists the packages.
108 - Extension host runtime: Bun 1.4.0 or newer is an opt-in; Node stays the default. `[extension_host] runtime = "node" | "bun" | "auto"` chooses: unset means `node` (or `bun` when the table sets only a `bun` path), `bun` runs only Bun, and `auto` prefers a supported Bun and uses Node when none is found or the Bun host fails to start. An explicit choice never falls back, and restarts keep the runtime the session first started on; a runtime binary replaced mid-session is refused. A configured `node` or `bun` path is used as given and fails loudly rather than falling through to `PATH`, and a runtime found on `PATH` inside a `node_modules` directory or the working directory is skipped, not run. `codewhale doctor` and `/plugin` show which runtime runs the host, why, and how its memory is capped. Under Bun the host never auto-installs packages and ignores `.env` and `bunfig.toml` in its data directory. Extensions cannot run native code inside the host on either runtime: `bun:ffi`, `Bun.FFI`, `node:ffi`, the SQLite builtins, `process.dlopen`, `process.execve`, Worker threads and `ShadowRealm` are refused, and the host will not start if one of these restrictions does not hold. Known limit: that lockdown covers the native-code entry points found so far (Bun 1.4, Node 22 and 26); one a newer runtime adds is not covered until it is added. The 1 GiB memory cap uses `RLIMIT_DATA` on Linux, the Job Object on Windows and, for a Bun host, a kernel jetsam limit on macOS; a Node host on macOS is checked at each heartbeat. Bun is qualified on macOS only: the Rust host tests, the memory cap included, have not run a Bun host on Linux or Windows (CI runs them with Node, and the JS host suites under Bun 1.4.0 on Linux). `host/hello` reports the runtime and version that actually run.
109 - `docs/features.toml` lists every user feature with its status, first
110 release, docs page and owning code. A test fails when a `[features]` flag
111 and its row disagree, or when a listed docs page or code path is missing.
112 The configuration reference now lists the `verify_tool`, `vision_model` and
113 `extension_host` flags, and `config.example.toml` lists `code_mode`.
114 - A reusable GitHub Action runs PR reviews with a configurable model endpoint
115 and a checksum-pinned Codewhale binary. It checks the PR's eligibility and
116 exact revisions before inference; fork events receive no model key
117 ([#6780](https://github.com/codewhale-hq/Codewhale/pull/6780)).
118 - An optional, off-by-default shadow Decision Gate classifies the first request
119 of a turn — tool need, answerability from context, intent — through the
120 existing System One client and only logs a typed recommendation; it never
121 changes routing or delays the model call. Configure it with
122 `SUPERFAST_ENABLED` and `SUPERFAST_PROVIDER` (docs/CONFIGURATION.md)
123 ([#6603](https://github.com/codewhale-hq/Codewhale/issues/6603),
124 [#6604](https://github.com/codewhale-hq/Codewhale/pull/6604), thanks @Andrea-Bruno).
125 - `tool_call_after` hooks for shell tools receive `DEEPSEEK_TOOL_EXECUTION_RECEIPT`: the command that actually ran after admission, its working directory, how it ended, and bounded stdout/stderr previews, so a hook can record exactly what executed ([#6689](https://github.com/codewhale-hq/Codewhale/issues/6689), requested by [@wuisabel-gif](https://github.com/wuisabel-gif)).
126 Supported settled local shell calls also send a versioned JSON document on
127 stdin to foreground or background observers, with session/tool-call IDs,
128 nullable exit status and output truncation flags. Existing environment fields
129 stay available; unsupported execution paths send no document, and observer
130 output cannot change the completed call
131 ([#6582](https://github.com/codewhale-hq/Codewhale/issues/6582)).
132 - Runtime API: turns now record what they produced. Each item and turn
133 carries typed artifact references (path, kind, size, revision, and a
134 restore point when file-revert would accept one) for files a tool wrote,
135 spilled tool output, and media.
136 - Once the post-turn snapshot settles, the turn also lists what changed in
137 the workspace while it ran, including shell and sub-agent writes. It then
138 publishes `turn.artifacts`.
139 - `GET /v1/threads/{id}/turns/{turn_id}/artifacts` lists a turn's
140 references, and `.../artifacts/{artifact_id}` reads one from the
141 workspace, the post-turn snapshot or the session artifact directory.
142 - Spills from unbound runtime threads were unreadable before; they are now
143 readable.
144 - The legacy `artifact_refs` field is now filled with the workspace files a
145 tool call wrote, so Preview in current desktop builds shows them
146 ([#6653](https://github.com/codewhale-hq/Codewhale/issues/6653)).
147 - Runtime API: git stage, unstage, discard and commit accept optional
148 `expect` preconditions (full HEAD id, an index token, per-file `rev`, or a
149 whole-tree `revision`, all read from `GET /v1/git`). When the repository
150 changed since the client read it, the write does nothing and answers 409
151 `git_state_changed` with the current state, so a Review sheet can no
152 longer stage bytes, discard edits or commit an index the user never saw.
153 Requests without `expect` behave as before. Path writes now use literal
154 pathspecs, as the docs already said, and `files[].path` is
155 workspace-relative in a subdirectory workspace. Guards cover executable
156 mode, submodule HEAD and changes outside that workspace; oversized or
157 budget-limited stat-only revisions cannot authorize a guarded write.
158 Status stays best-effort: unreadable paths, symlinked ancestors, special
159 files and broken nested repositories withhold only affected row tokens
160 and the whole-tree revision. Normal Git filters and untracked settings
161 apply, with directory inventories scoped to the rows or paths that need
162 them. Untracked workspace files and renames leaving the workspace remain
163 visible, and broken HEADs cannot satisfy an unborn-HEAD guard
164 ([#6647](https://github.com/codewhale-hq/Codewhale/issues/6647)).
165 - Runtime API: `POST /v1/threads/{id}/fork-at-turn` forks a thread at a named
166 user turn, keeping that turn and every turn before it. The receipt matches
167 `/undo` and returns the first dropped prompt so a client can put it back in
168 the composer. Naming the turn replaces a client-computed depth, which could
169 fork the wrong prefix. The fork leaves the workspace and any running turn
170 untouched
171 ([#6580](https://github.com/codewhale-hq/Codewhale/pull/6580), thanks @gaord).
172 - Official model routing: `/router` (also `/model router`) sets up the Auto
173 router with presets: Jev (TypeSafe's decision model, via OpenRouter or a
174 TypeSafe key), your provider's fast tier, Off, or Custom. Jev and Fast each
175 make one test call before you save, the Turn Inspector (Ctrl+Alt+O or
176 `/turn inspect`) shows the router's choice, cost and latency, and a failing
177 router is shown as failing
178 ([#6525](https://github.com/codewhale-hq/Codewhale/issues/6525)).
179 - ChatGPT sign-in uses Codewhale-owned protected credentials and a model roster
180 fetched for the signed-in account. Account, workspace and issuer changes
181 cannot reuse another roster; a missing or stale roster offers no models.
182 Authentication failures and subscription limits do not silently fall back
183 to a paid API route.
184 - Code mode composes MCP and plugin tools and is on by default:
185 `execute_tools` programs can call MCP tools, and each nested call passes the
186 same approval gate as a direct call, pausing the program for approval when
187 needed. Every nested call keeps its receipt, including calls that finish
188 before a deadline, and `[features] code_mode = false` stops offering
189 `execute_tools` up front (it stays reachable through tool search).
190 `codewhale mcp list`
191 and `codewhale doctor` warn when a user MCP server duplicates the built-in
192 Computer Use bundle
193 ([#6562](https://github.com/codewhale-hq/Codewhale/issues/6562),
194 [#6509](https://github.com/codewhale-hq/Codewhale/issues/6509)).
195 - Tsubasa is a bundled OpenAI-compatible provider row: base
196 `https://api.tsubasa.sh/v1`, key `TSUBASA_API_KEY`, model `tsubasa-pro`
197 (also `tsubasa-fast`). Its window is 32,768 tokens; set
198 `providers.tsubasa.context_window` to match
199 ([#6695](https://github.com/codewhale-hq/Codewhale/issues/6695), thanks @cenab).
200
201 ### Changed
202
203 - The pinned prompt header follows the turn at the top of the viewport,
204 handing over to the previous prompt as you scroll, and clicking it jumps back
205 to the message it names
206 ([#6830](https://github.com/codewhale-hq/Codewhale/pull/6830), thanks @SparkofSpike).
207 - On Windows, every PowerShell command the shell tool starts now passes
208 `-ExecutionPolicy Bypass` for that process only, so a local `Restricted` or
209 `AllSigned` policy no longer blocks multi-line commands. (`.ps1` script tools
210 still start as `powershell -File` without the flag and remain subject to the
211 local policy.) A policy set by
212 Group Policy still wins and the command is refused with PowerShell's own
213 message. Scripts that a command invokes run under the same process-scoped
214 setting. To let the machine or user policy apply instead, start Codewhale
215 with `CODEWHALE_POWERSHELL_EXECUTION_POLICY=inherit`: it then omits
216 `-ExecutionPolicy`, so a `Restricted` or `AllSigned` policy refuses the
217 multi-line commands that need a temporary script; any other value keeps
218 the default. Not verified on a native Windows machine
219 ([#6745](https://github.com/codewhale-hq/Codewhale/issues/6745)).
220 - The website's not-found page now uses the Codwhale poster and typo joke,
221 with English/Chinese recovery links to home and docs
222 ([#6419](https://github.com/codewhale-hq/Codewhale/issues/6419),
223 [#6420](https://github.com/codewhale-hq/Codewhale/pull/6420)).
224 - Script tools can no longer approve themselves or replace built-in tools
225 (founder decision D4). A `# approval: auto` line in a script under
226 `~/.codewhale/tools` (or `[tools].plugin_dir`) is ignored: the tool follows
227 the session's approval setting like a script with no `approval:` line, and
228 the runtime log and `/plugin tools` name each script that still declares it.
229 A `[tools.overrides]` entry of `type = "script"` or `type = "command"` keyed
230 by a built-in tool name is refused, and the built-in stays active; a status
231 line names the key once per session, and the runtime log records it. `type = "disabled"` still turns a
232 built-in off, and script or command overrides under a new name still work.
233 To keep a wrapper such as an audited shell, disable the built-in and give
234 the wrapper its own name
235 ([configuration](docs/CONFIGURATION.md#script-tools-and-overrides)).
236 - Complete the session slash-command group’s shared command boundary, including
237 `/structcopy`, so all seventeen commands can compile independently of the TUI.
238 Host operations remain behind capability interfaces; command behavior and
239 upstream tool-execution identity safeguards are preserved
240 ([#6792](https://github.com/codewhale-hq/Codewhale/issues/6792),
241 [#6145](https://github.com/codewhale-hq/Codewhale/issues/6145)).
242 - The declared minimum Rust version is now 1.89. It said 1.88, which could not
243 build Codewhale: a locked dependency (`serde-saphyr`) needs 1.89, the version
244 CI's minimum-version job builds. The install guides and the npm wrapper's
245 build-from-source hints now say 1.89 too.
246 - A deferred tool's first call now runs when its arguments already carry every
247 required field and no field the schema does not declare, instead of costing a
248 retry turn. Malformed calls still get the schema, and approvals, deny lists
249 and Plan mode apply first. Argument types are still checked by the tool
250 itself. Sub-agents preload tools named in `allowed_tools`
251 ([#6494](https://github.com/codewhale-hq/Codewhale/issues/6494),
252 [#6437](https://github.com/codewhale-hq/Codewhale/pull/6437)).
253 - Automatic Git status and review reads need Git 2.31 or newer, because they pin
254 Git's runtime configuration overrides. With an older Git they refuse with
255 "upgrade Git (2.31 or newer)". This covers the read-only Git tools
256 (`git_status`, `git_diff`, `git_log`, `git_show`, `git_blame`, `verify`); Git
257 writes you ask for keep their existing behavior
258 ([docs/dependency-maintenance.md](docs/dependency-maintenance.md)).
259
260 ### Fixed
261
262 - Diff lines and tool output wrap at grapheme boundaries, so emoji families,
263 skin tones and variation selectors no longer split across lines
264 ([#6829](https://github.com/codewhale-hq/Codewhale/pull/6829), thanks @Lstarsky0).
265 - Twelve translated packs now translate the context inspector's making-room
266 and anchors rows, the Ctrl+O hint and the `/turn inspect` and `/advisor`
267 descriptions instead of showing English
268 ([#6831](https://github.com/codewhale-hq/Codewhale/pull/6831), thanks @Lstarsky0).
269 - Optional MCP servers can be found before they connect. `tool_search` matches
270 the query against configured, enabled server names (or an `mcp_<server>_`
271 prefix), connects up to eight matches within the existing boot wait, and
272 returns their real tool schemas. Before, a lazily started server exposed no
273 tools, so the model could never trigger its connection
274 ([#6828](https://github.com/codewhale-hq/Codewhale/issues/6828)). Known limit: a
275 query that names neither the server nor `mcp` does not wake it.
276 `codewhale mcp connect`, `validate` and `tools` run their own connection and
277 do not attach to a running session.
278 - `/undo` and `/restore <N>` refuse while a turn is running in the workspace,
279 instead of rewriting files under it.
280 - `--resume <id>` after a crash recovers that session's interrupted turn from
281 its crash checkpoint, as `--continue` does.
282 - `/resume <file>` keeps an imported session on the current provider route
283 instead of a default one.
284 - When the stall watchdog recovers a turn, the Engine's turn is ended too, so
285 the next message is accepted
286 ([#6800](https://github.com/codewhale-hq/Codewhale/issues/6800)).
287 - A turn you cancel, or one the stall watchdog recovers, releases input at once.
288 A message still waiting to reach the engine is abandoned and its unsent text
289 returns to the composer, instead of holding input for up to 60 seconds
290 ([#6800](https://github.com/codewhale-hq/Codewhale/issues/6800)).
291 - A transient upstream failure that a gateway reports as an error frame inside
292 a successful response ("Provider returned an empty response") is retried
293 under the stream retry budget when nothing had streamed; authentication and
294 invalid-model frames still fail at once
295 ([#6795](https://github.com/codewhale-hq/Codewhale/issues/6795)).
296 - Long sessions no longer start every turn late. Once a workspace held more
297 than 50 undo snapshots (around the sixteenth turn), each new snapshot rebuilt
298 the whole snapshot history before the provider request, about 2.8 s per turn
299 in a small workspace. Old snapshots are now dropped half a window at a time.
300 - Resuming a crashed session from inside the TUI recovers its interrupted
301 turn too.
302 - Release builds compile on Rust 1.99.
303 - TUI undo and retry rewind the Engine conversation and saved session before
304 replacement inference. If the conversation or its settings change while
305 undo is being prepared, it refuses without overwriting that newer state or
306 changing the draft. Retained compaction summaries survive the rewind and
307 cannot be selected as editable user prompts
308 ([#6788](https://github.com/codewhale-hq/Codewhale/issues/6788)).
309 - `/edit` replaces the exchange it revises through the same rollback: the old
310 prompt and its answer leave the transcript, the model's context and the
311 saved session before the edited prompt is sent.
312 - When the rollback that `/edit` needs is refused, your revised text goes back
313 to the composer with edit mode still on, instead of being dropped. Opening
314 `/edit` while you are editing a queued follow-up returns that follow-up to the
315 queue first.
316 - A session can still be resumed by its id when a stray copy of its file sits
317 in the sessions directory; before, the id was reported as ambiguous.
318 - Agents follow the Permissions you choose while they run: switching to
319 Full Access reaches an agent that is already working, instead of leaving
320 it with the Auto-Review guardian that denied it. Tightening reaches it too.
321 An agent's answer to an approval prompt is delivered while the main
322 session is busy, and a forced delete inside the workspace is no longer
323 treated as a catastrophic system delete. On Linux, Full Access switched on
324 at runtime cannot lift the kernel no-new-privileges flag set at startup,
325 so `sudo` and setuid helpers still fail; start with
326 `sandbox_mode = "danger-full-access"` or `CODEWHALE_NO_NEW_PRIVS=0` if
327 agents need them ([#6787](https://github.com/codewhale-hq/Codewhale/issues/6787)).
328 - Stream limits and transport settings share a typed `[stream]` configuration
329 table, including retry budgets, TCP keepalive and HTTP/2 keepalive. Explicit
330 values take precedence over legacy `[tui]` aliases; omitted values preserve
331 existing defaults and environment behavior. A configured HTTP/1 pin stays
332 pinned during recovery. `/config stream_chunk_timeout_secs ... --save`
333 updates the canonical setting so it survives reopening a configuration
334 that already had a timeout. Transport changes apply when a client is built
335 ([#6700](https://github.com/codewhale-hq/Codewhale/issues/6700)).
336 - Switching providers keeps a model set only in the root `default_text_model`
337 with the provider it belongs to. Switching away and back (`/provider` in the
338 TUI, or the desktop app's model chip) used to land on the provider's catalog
339 default such as `gpt-5.6`, and a pass-through provider switched to in between
340 inherited the other provider's model, or a stale legacy root `model` that the
341 root default had been shadowing
342 ([#6693](https://github.com/codewhale-hq/Codewhale/pull/6693)).
343 - A turn no longer stops after an hour of work. The cumulative per-turn wall
344 clock is unlimited by default, like model steps; set
345 `[tui].turn_wall_clock_secs` to cap it.
346 - OpenRouter turns are priced again instead of always showing "rate
347 unavailable". The model-list refresh no longer fails as a whole on one bad
348 row: `~` "latest" aliases are dropped, routers that publish a `-1`
349 variable price are listed without a rate, and other malformed rows are
350 skipped and counted. Main interactive turns now honor a `[[custom_models]]`
351 rate the same way background work does, a declaration without rates no
352 longer hides the catalog price, and an explicit declared rate prices a
353 vendor-pinned OpenRouter route
354 ([#6690](https://github.com/codewhale-hq/Codewhale/issues/6690)).
355 - `codewhale exec` can take prompts past the OS argument limit (~128 KiB on
356 Linux, where larger prompts failed with `Argument list too long` before
357 Codewhale started): `--prompt-file <PATH>` reads the prompt from a file, and
358 `--prompt-file -` reads it from stdin; a positional `-` stays literal text
359 ([#6688](https://github.com/codewhale-hq/Codewhale/issues/6688)).
360 - Keep reasoning effort labels, including `xhigh` and `ultra`, visible beside
361 short model names in the 80-column terminal footer.
362 - First-run TUI startup keeps explicitly configured providers, models and
363 endpoints (including environment overrides and a legacy top-level
364 `base_url`), even with a missing key, instead of adopting a detected local
365 Ollama model. The `default_text_model` line written into the generated
366 first-launch config is not treated as a choice, so starting Ollama after the
367 first launch is still detected. Usable configured routes skip the provider
368 picker and record the provider step as configured, without claiming a
369 successful check; missing-key recovery focuses the configured provider even
370 on a fresh home. Switching from that recovery picker (or after Esc) to a
371 provider that has its key clears the launch "needs a key" state, so the
372 footer names the route instead of "model not connected" and a detected local
373 Ollama can no longer take over the provider just chosen. Empty sessions no
374 longer show a full context window from the startup prompt; a submitted first
375 turn or reported usage still shows real pressure.
376 - `/trust on|off` changes file-tool trust for this session. Add `--save` to
377 persist workspace trust for project skills, commands, hooks, MCP servers,
378 and project context. Skipped-skill notices stay out of conversation titles
379 and user bubbles, and trust changes append a correction to the model's history.
380 - Stored-secret cleanup skips busy Runtime stores and reports unreadable paths
381 while continuing through other files. Configured storage roots may be symlinks;
382 discovered symlinks are not followed. Cleanup also masks current configured
383 credentials, and doctor's bounded scan reserves capacity for saved transcripts
384 and checkpoints separately from Runtime receipts.
385 - Hooks: `tool_call_after` and `on_error` now get a shell command's exit code
386 in `DEEPSEEK_TOOL_EXIT_CODE` on Runtime API threads as well as in the TUI,
387 and for a failing command as well as a passing one, so `exit_code`
388 conditions match. The Runtime API path passed no exit code at all, and a
389 command that exited nonzero, timed out, or was killed reached hooks with no
390 exit code on either surface. The new `DEEPSEEK_TOOL_STATUS` says how the
391 command ended (`completed`, `failed`, `timed_out`, `killed`)
392 ([#6582](https://github.com/codewhale-hq/Codewhale/issues/6582)).
393 - Scrolling a long transcript repaints the reasoning reveal hint in place
394 instead of rebuilding the transcript tail. Wheel and scrollbar input use
395 interactive frame pacing, collapsed tool groups reuse cached summaries, and
396 height-only resizes keep wrapped history. Width changes still rewrap content,
397 and other per-frame work still grows with session length
398 ([#6652](https://github.com/codewhale-hq/Codewhale/issues/6652)).
399 - A settled transcript frame reuses its existing render plan instead of
400 rebuilding or moving unchanged history on every poll. New output, selection,
401 resize and other real changes still invalidate the affected work
402 ([#6652](https://github.com/codewhale-hq/Codewhale/issues/6652)).
403 - Workflow progress rows and working, verification and translation indicators
404 use the pinned Codewhale terminal component kit. Quiet and reduced-motion
405 working/verification indicators hold its semantic current-work mark. Working
406 and verification keep their existing delay and cadence, while translation
407 uses the same earned marker and five-frame-per-second cadence. The Engine
408 still supplies workflow state, clocks, localized text, custom themes and
409 terminal adaptation. The composer, transcript viewports, dock tabs,
410 posture/metrics rows, pending-input cards, approval band, Ocean background
411 and the whale's Braille raster now also render through the pinned kit.
412 - Calm transcript previews keep the latest three rows of live thought and a
413 single duration header when it settles. Successful tool headers are quieter;
414 failed generic and MCP calls keep a bounded head-and-tail excerpt, with full
415 output available in details. Existing collapsed groups show their hidden
416 count and reveal cue, and explicit thought expansion stays available.
417 - Composer history preserves multiline entries and literal quoted text while
418 retaining the old history file during migration. An oversized message stays
419 in the composer if its paste file cannot be saved, with a localized notice;
420 mouse placement and quoted file mentions handle multibyte text and spaces
421 ([#6776](https://github.com/codewhale-hq/Codewhale/pull/6776)).
422 - The notice for an oversized message that cannot be saved as a paste file is
423 now a short line that fits the footer ("Not sent: over N characters; paste
424 file not saved."), in every supported language. The full reason, including the
425 write error, goes to the transcript once.
426 - Model-facing guidance names callable tools and explains discovery before a
427 deferred read. The stopship workflow's scout activates the deferred
428 `grep_files` with one required `tool_search` call, then gathers bounded
429 `grep_files` evidence from the current workflow source paths
430 ([#6747](https://github.com/codewhale-hq/Codewhale/issues/6747)).
431 - Simplified and Traditional Chinese permission, provider and session wording
432 now follows the current behavior. Chinese guides correct hook receipts,
433 trusted skills, MCP startup and Windows limitations, preserving the
434 contributor translations and a shared glossary.
435 - Unknown website locale segments, including dotted missing paths, return a
436 real 404 with noindex metadata and no home-page canonical URL. The existing
437 layout guards now have regression coverage across all registered locales
438 ([#6786](https://github.com/codewhale-hq/Codewhale/pull/6786)).
439 - The terminal caret no longer blinks at the hidden composer while a picker,
440 settings screen or other view covers it; it returns when the view closes
441 ([#6545](https://github.com/codewhale-hq/Codewhale/issues/6545)).
442 - On Linux and macOS, a `background: true` shell's process group is now
443 stopped when the TUI dies without cleaning up (SIGKILL, a crash, or the
444 signal exit path). The shell and the processes it started used to keep
445 running as orphans. Processes that move to their own process group or
446 session, staged services you choose to keep, and `tty: true` background
447 shells are not covered. Under the bwrap sandbox, the sandboxed command
448 now also exits when bwrap does
449 ([#6654](https://github.com/codewhale-hq/Codewhale/issues/6654)).
450 - Idle task workers stop periodically reloading a settled, unchanged empty
451 queue, and task listings reuse an unchanged store snapshot. New queue writes
452 and local notifications still wake workers; recent or unreadable metadata and
453 failed claims keep bounded retries. This reduces repeated disk work when
454 several TUIs share a data directory without changing task ownership or
455 cancellation ([#6573](https://github.com/codewhale-hq/Codewhale/issues/6573),
456 [#6728](https://github.com/codewhale-hq/Codewhale/issues/6728)).
457 - Idle task workers check the queue file's metadata about once a second instead
458 of five times a second, and no longer reloads the store when nothing changed.
459 An in-process notification still wakes a worker at once; a
460 write by another Codewhale process that shares the data directory is noticed
461 within about a second instead of about 200 ms. A worker with pending work, a
462 retry deadline or a failed claim keeps the short interval
463 ([#6728](https://github.com/codewhale-hq/Codewhale/issues/6728),
464 [#6573](https://github.com/codewhale-hq/Codewhale/issues/6573)).
465 - After five seconds without session activity, the UI loop polls every 250 ms
466 instead of 48 ms and the automation-panel scan backs off to 15 seconds. After
467 thirty quiet seconds, the Git probe runs one `git status` every 15 seconds
468 instead of the full probe every two seconds, unless the Git panel is showing.
469 User input and engine events restore the active cadence. This reduces idle
470 work; it does not remove every cost that grows with session history
471 ([#6728](https://github.com/codewhale-hq/Codewhale/issues/6728)).
472 - When the task store is busy, the message now names the process that holds its
473 lock and how long it has held it ("lock held by pid 1234 for 12s"), when that
474 can be read. A repeated "Task claim unavailable" error is logged once per
475 episode, then at debug level
476 ([#6573](https://github.com/codewhale-hq/Codewhale/issues/6573)).
477 - On Windows, Fleet can read a running worker's log while its writer holds the
478 file open, and task-store contention can still read the lock-holder record.
479 These paths previously failed because of whole-file sharing and locking.
480 - File writes, including legacy `File` and `write_file` calls, stop if the
481 original contents cannot be read; legacy writers also reject non-UTF-8
482 originals, keeping undo and diffs from recording an empty original file.
483 - Resuming a session preserves user messages that quote a compaction marker.
484 - Requirements allow-lists now check unset approval and sandbox defaults,
485 accept equivalent approval aliases, and lock permission posture when sandbox
486 modes are constrained so saved Full Access and YOLO cannot bypass them.
487 - Logout completes xAI OAuth revocation and attempts every credential deletion
488 before reporting remaining credentials with a non-zero exit status.
489 - ChatGPT and xAI sign-in now show the account the selected route actually
490 uses, and sign-in names the account it replaces. `/auth chatgpt` and
491 `/auth xai-device` switch the running session; signing in from a separate
492 shell requires restarting an already-open session. Subscription-limit errors
493 name the account that made the request and explain how to switch, without
494 printing credentials ([#6715](https://github.com/codewhale-hq/Codewhale/pull/6715)).
495 - `doctor --fix` keeps temporary files modified within the last hour.
496 - Provider streams stop with a clear error if an SSE line exceeds 8 MiB.
497 - Recursive `rlm_query` turns inherit the parent's remaining deadline,
498 bounded by the existing child budget, including asynchronous lock waits,
499 startup, model requests and Python evaluation. Expired work is refused before
500 dispatch; a timeout returns the last response with an incomplete-result error.
501 Nested code and status receipts accompany the enclosing tool result on success
502 or failure and survive its session save/reopen. In-flight receipts still need
503 that result to be handed back before they become durable
504 ([#6511](https://github.com/codewhale-hq/Codewhale/issues/6511)).
505 - The TUI keeps redrawing while its terminal is unfocused. v0.10.0 held
506 every frame on focus loss, so on Windows Terminal, macOS and other
507 terminals a window sitting behind another one looked frozen until you
508 clicked back into it. Frames are now held only on GTK/VTE terminals, which
509 replay the damage themselves when they return. That hold was added for the
510 MATE flicker in [#6311](https://github.com/codewhale-hq/Codewhale/issues/6311)
511 ([#6651](https://github.com/codewhale-hq/Codewhale/issues/6651)).
512 - TUI `/undo` now restores only the files the undone tool call or turn
513 changed, and refuses, changing nothing, when one of them changed since.
514 Before, it checked out the whole snapshot tree, which also reverted later
515 edits to other files. It also finds restore points older than the newest
516 100 snapshots, and a forked session can undo the turns it inherited. It
517 waits for a post-turn snapshot that is still being written, leaves a
518 changed symlink or other non-regular path in place (and says so) instead
519 of refusing the whole undo, and writes nothing to the snapshot store when
520 it refuses outside trusted mode
521 ([#6644](https://github.com/codewhale-hq/Codewhale/issues/6644)).
522 - On a fixed model, each Ctrl+T press now moves to a different thinking
523 tier. Ctrl+T and the `/model` picker could list tiers the route treats as
524 the same one — DeepSeek's `medium` is `high`, and Z.ai GLM-5.2's `low` is
525 `high` — so some presses changed nothing. They now share one list per
526 route with one entry per effective tier. Under Auto model routing, Ctrl+T
527 walks the picker's Auto list instead of a longer private one; the tier is
528 still settled when the turn is routed, so two neighbouring choices can
529 land on the same tier. DeepSeek now reports `minimal`, `xhigh` and `ultra`
530 as the `low`, `high` and `max` it sends, in `/status`, receipts and
531 `/effort`, and Kimi Code K3 no longer offers `off`, which it always ran as
532 `low` ([#6650](https://github.com/codewhale-hq/Codewhale/issues/6650)).
533 - A top-level `base_url` or `api_key` in `config.toml` now means one thing
534 everywhere. Every reader used its own rule for which routes inherited it,
535 which is how a DeepSeek endpoint became the Xiaomi MiMo route's and failed
536 with DeepSeek's 401. Old files keep working: the keys are read as
537 `[providers.deepseek]` (or the vendor whose official host they name), the
538 next save moves them there with a one-time backup and a one-line note, and
539 a value that disagrees with its table is left for `codewhale config migrate
540 --prefer` to settle. `codewhale config doctor` shows what is in use
541 ([#6394](https://github.com/codewhale-hq/Codewhale/issues/6394)).
542 - Setting up a bundled OpenAI-compatible host from `/provider` now shows
543 that host's key console, docs link and guidance on the setup form, the same
544 way the built-in providers' key entry does; before, the descriptor file
545 carried them and nothing read them. AICraft gains all three
546 ([#6616](https://github.com/codewhale-hq/Codewhale/issues/6616), thanks @BX166).
547 - Runtime API undo now restores the files of the turns it undoes, for every
548 kind of thread. Before, a new thread's turns were not linked to their
549 workspace snapshots, so `patch-undo` returned `201` and rewound the
550 conversation but left the files changed, and `file-revert` refused. Each
551 turn record now lists its snapshots in `workspace_snapshots`, the engine runs
552 under the thread's own id across restarts, and a fork owns the turns it
553 inherited. `patch-undo` restores only the files the undone turns changed,
554 including every write in a turn, and leaves later edits by the user or
555 another thread alone. Every tool call that may write is bounded by its own
556 snapshots, so a file another thread or an editor changed while the turn ran
557 is never reverted as the turn's, and a turn's restore points survive the
558 snapshot count cap. When it cannot restore files (including a write to a
559 gitignored path) it now refuses with `409` and an `error.code` instead of
560 returning `201`. A nameless `PUT /v1/sessions` updates the document the
561 thread is bound to
562 ([#6621](https://github.com/codewhale-hq/Codewhale/issues/6621)).
563 - A Runtime thread that is not bound to a saved session keeps one engine
564 session id, its own thread id, across its first turn, eviction and
565 restarts. Before, each engine spawn generated a new id, so the thread's
566 tool-output spills, snapshot tags and shell jobs were scattered across a
567 different `sessions/<id>/` per spawn
568 ([#6659](https://github.com/codewhale-hq/Codewhale/issues/6659)).
569 - Saved sessions no longer go orphaned, and existing orphans are repaired at
570 launch. Deleting a session now sets aside the Runtime store it was actually
571 bound to, and switching a conversation to another host's store sets aside the
572 store it left, unless another session still uses that store or it holds
573 work. Exporting a thread (`POST /v1/sessions`) updates the thread's own
574 document instead of creating a new one each time. A thread whose document was
575 appended to elsewhere keeps loading. A thread whose document was deleted or
576 rewritten loads from its own turns instead of failing, and threads write
577 their files under the session they belong to. Each launch and `codewhale
578 serve` repairs the store in the background: a store holding threads with no
579 session gets a "Recovered:" session for each thread, and unreadable
580 documents, unused empty stores and old files no session names move to
581 `sessions/.set-aside/` with a manifest. Nothing is deleted. `codewhale doctor`
582 reports the last repair, and `codewhale doctor --repair-sessions [--dry-run]`
583 runs one now. `PUT` and `DELETE /v1/sessions` refuse a session that another
584 Codewhale process has open
585 ([#6144](https://github.com/codewhale-hq/Codewhale/issues/6144)).
586 - Runtime API: the thread event stream now ends with a typed `stream.end`
587 frame (reason and resume cursor) whenever the server closes it, including
588 on shutdown, so clients can tell a Runtime error from a dropped connection
589 and resume from the right event. A replay worker crash no longer ends
590 history early and skips events without a detectable gap, and the mobile
591 page resumes from its last event instead of replaying from zero, with stream
592 statuses in the configured UI language. Cross-origin clients can read the
593 stream-end and replay-progress capability headers, and the SDK exports
594 `isThreadStreamEnd` for TypeScript narrowing.
595 - `codewhale exec --auto` no longer exits 141 with no output when a child
596 it writes to, such as a stdio MCP server, closes its pipe early. Headless
597 exec now ignores SIGPIPE while it runs, as the interactive TUI already did,
598 and `exec ... | head` still ends quietly. One-shot `codewhale exec` no
599 longer prints DeepSeek's raw `<||DSML|| calls>` tool-call markup as its
600 answer: the markup is removed, and an answer that was only a tool call
601 fails at once with the reason and a pointer to `--auto`, instead of asking
602 the model again and blaming an incomplete provider response.
603 - Resuming a session keeps its "Resumed:" confirmation on screen instead of
604 replacing it with "Make room automatically: on" when nothing was switched.
605 - Tool output is no longer cut off where you can't get it back. Search
606 answers, test runs, git, verifier and web results reach the model whole up
607 to one budget sized to the model's context window, and anything beyond it
608 can be read back with `retrieve_tool_result`, including read-only tools
609 executed alone or in parallel. Restored raw results use the
610 active route's same inline budget; existing recovery receipts stay intact.
611 Tiny budgets use a compact retrieval reference instead of a long artifact
612 path and instructions; a complete reference is kept even when it alone
613 exceeds the allowance.
614 Native search now asks for answers up to 8,192 tokens (was 2,048–4,096)
615 and waits long enough for
616 them to arrive, and an answer the provider still cuts short is marked as
617 cut ([#6508](https://github.com/codewhale-hq/Codewhale/issues/6508)).
618 - The installation page is generated from `docs/INSTALL.md`, so the website
619 and the guide can no longer disagree; broken anchors and unsafe links fail
620 the build ([#6450](https://github.com/codewhale-hq/Codewhale/pull/6450)).
621 - `codewhale config set` refuses a value of the wrong type for a known setting
622 (a word for an on/off switch, text for a number, a choice outside the list)
623 instead of saving it ([#6568](https://github.com/codewhale-hq/Codewhale/pull/6568),
624 thanks @dajiaohuang).
625 - Receipts: `/receipts`, `codewhale receipts [ID|--last] [--format md|json]`,
626 and `GET /v1/threads/{id}/receipt` (plus a per-turn form) list what a session
627 did, one line per action: files changed with line counts, commands with exit
628 codes, web and MCP calls, agents, approvals and who gave them, and failures.
629 They also count what ran without asking and name the posture each turn ran
630 under, read from the turn's own record. A call Codewhale blocked before it
631 started (Auto-Review or guardian, a tool policy, a refused sandbox
632 escalation, invalid input, a missing tool) is listed as blocked, with the
633 reason, and is not counted as run or as ran without asking. Only
634 Codewhale's own refusal text counts: an MCP server, a fetched page, or a
635 program cannot make a call that ran read as blocked. A terminal
636 session's receipt also lists the files a command changed in each turn,
637 from the workspace snapshots taken before and after it (not ignored files
638 or anything outside the workspace), with control characters in paths
639 escaped so a file name cannot forge a receipt line. All three read the
640 records Codewhale already keeps and say what those records do not hold
641 ([docs/RECEIPTS.md](docs/RECEIPTS.md)). `audit.log` is not that record: it
642 logs security events, and it logs an approval only when one is requested,
643 which under Full Access is almost never.
644 - Approvals now record who decided: you, a session rule, or the posture. An
645 automatic approval used to be saved exactly like one you gave, and an app
646 approval that expired was saved as your denial. `GET /v1/approvals` now
647 returns `decided_by`.
648 - Network audit lines now go to the same `audit.log` as every other audit
649 event (`$CODEWHALE_HOME` included), and test runs no longer append to your
650 real one.
651 - In the terminal UI, Auto-Review verdicts now reach `audit.log`, as
652 `/permissions` said they did; before, they were written only when
653 `CODEWHALE_TOOL_AUDIT_LOG` was set. Headless `exec` and Runtime API sessions
654 do not write them yet.
655 - A turn that stops producing output now reports itself: the turn loop records
656 its phase and last progress, and an overdue phase surfaces instead of
657 hanging silently until the stream idle timeout. A delegated agent's final result is
658 never dropped when the host is busy, so a finished child no longer leaves a
659 ghost Running row behind ([#6184](https://github.com/codewhale-hq/Codewhale/issues/6184)).
660 - Git commands run by tools never stop to ask for a password, passphrase or
661 host-key confirmation inside the terminal, and `git_fetch` has a timeout
662 ([#6184](https://github.com/codewhale-hq/Codewhale/issues/6184)).
663 - A provider response that ends cleanly with no text and no tool call is
664 retried before the turn fails, and the failure names how many retries ran
665 ([#6310](https://github.com/codewhale-hq/Codewhale/issues/6310)).
666 - The context meter, the point where Codewhale makes room, preflight,
667 `/context` and turn receipts show one pressure number instead of disagreeing
668 ([#6407](https://github.com/codewhale-hq/Codewhale/pull/6407)).
669 - When Codewhale makes room, the note it leaves for the next turn is written in
670 its own words, under fixed headings: the objective, the user's corrections,
671 permissions and limits, changed files, what is still running and the checks
672 left. A message that quotes the note's opening words now stays in the
673 conversation instead of being dropped. If the summary request itself is too
674 large, older history is dropped but the previous note is kept, and making
675 room stops rather than write a new note without it.
676 - Continuing a conversation that is already open no longer adds a second
677 thread, and a fork keeps its own session file, so autosave on one side no
678 longer leaves the other unloadable
679 ([#6406](https://github.com/codewhale-hq/Codewhale/pull/6406), thanks @gaord).
680 - Upgrading Codewhale no longer turns off the built-in Computer Use. Each build
681 writes the built-in bundle to its own directory, so an upgrade used to present
682 it as never reviewed and disabled. Now the review and enablement carry to the
683 new build when its capabilities are unchanged. Changed capabilities show
684 `capabilities-changed` and wait for review, and a revoked trust never carries
685 ([#6303](https://github.com/codewhale-hq/Codewhale/issues/6303)).
686 - "Allow for this conversation" records a grant for that tool and argument
687 class instead of switching the whole thread to Full Access, so the call you
688 just approved is no longer failed by a Permissions change. An approval
689 also survives a Permissions change that only widens what is allowed, grants
690 end when a thread is archived or deleted, and `web.run` open grants are
691 scoped by host. Full Access covers MCP tools that declare themselves destructive in
692 every host, including `codewhale exec`
693 ([#3866](https://github.com/codewhale-hq/Codewhale/issues/3866)).
694 - `web.run` retries a refused page once with a browser user agent, and one
695 site's failure no longer fails the whole call or drops its search results.
696 - Web search no longer stops when DuckDuckGo cannot be reached. After a
697 connection error, timeout or non-2xx answer, the search tries Bing before
698 giving up, and the result says it used Bing. A DuckDuckGo that hangs no longer
699 uses up the whole time budget: when Bing may follow, DuckDuckGo gets 60% of it
700 and Bing the rest. This also covers the DuckDuckGo step after a configured API
701 provider. A custom `search_base_url` still has no public fallback and keeps
702 the full budget. Bing sees the query only after DuckDuckGo has failed or
703 returned nothing it could read
704 ([#6746](https://github.com/codewhale-hq/Codewhale/issues/6746)).
705 - Hooks treat `bash`, `Bash` and `exec_shell` as one tool in `tool_name`
706 conditions, so the documented example fires.
707 - macOS no longer reports Codewhale's ordinary heap as GPU (IOAccelerator)
708 memory.
709 - Code highlighting uses less memory, and long transcripts, the pager and the
710 session picker do less work on the event loop; session previews load in the
711 background ([#6014](https://github.com/codewhale-hq/Codewhale/issues/6014)).
712 - The composer's send cue follows the draft, not a paste in progress
713 ([#6397](https://github.com/codewhale-hq/Codewhale/issues/6397)).
714 - Voice status is localized, ASCII-mode markers are distinct, and the cursor
715 honours `NO_COLOR` ([#5846](https://github.com/codewhale-hq/Codewhale/issues/5846)).
716 - `/cache`, `/stash`, `/config`, session prune, `metrics --since` and the
717 `lane start`/`lane stop --json` flags handle their edge cases.
718 - Plain `codewhale exec` (no `--auto`) runs one Engine turn with the same
719 system prompt as every other run, so `--json` no longer changes the model's
720 instructions. It offers no tools unless a flag grants them (`--auto`,
721 `--yolo`, `--allowed-tools`, or resuming a session): `--max-turns`,
722 `--disallowed-tools`, `--append-system-prompt`, `--sandbox` and
723 `--output-format stream-json` no longer turn a chat call into a tool-using
724 agent, and tool-only flags passed without a grant print a warning. A reply
725 cut off at the provider's output limit is continued instead of failing the
726 run, for at most 8 model steps unless `--max-turns` sets another limit.
727 Breaking for scripts: the `--json` one-shot receipt no longer has
728 `stop_reason`, adds the agent receipt's fields (`prompt`, `tools`,
729 `outcomes`, `status`, `termination_reason`, `error_category`), and leaves
730 out `usage` when the turn never settled
731 ([#6510](https://github.com/codewhale-hq/Codewhale/issues/6510)).
732 - `codewhale review` of a plain diff uses the same review prompt as
733 `review --pr` and prints the structured review as Markdown, or the model's
734 prose when it ignores the JSON format
735 ([#6510](https://github.com/codewhale-hq/Codewhale/issues/6510)).
736 - A recursive `rlm_query` that runs out of rounds returns its last answer
737 marked `[rlm_query incomplete: …]` instead of an empty string, its model
738 calls appear in the parent turn's record, and its history is no longer
739 trimmed ([#6511](https://github.com/codewhale-hq/Codewhale/issues/6511)).
740 - Starting without a network connection no longer drops images you attach to a
741 model that accepts them. The offline model list lagged behind providers and
742 listed Claude and others as text-only; it can now only say a model takes
743 images, never that it refuses them, and a provider that does refuse gets one
744 resend without the image and a message saying so
745 ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)).
746 - Model prices that a flat rate would get wrong now show as unknown after the
747 model list refreshes online, as they already did offline: DeepSeek (priced by
748 time of day, or from Codewhale's reviewed table on hosted providers), Grok and MiniMax M3 (rates rise on long prompts), Xiaomi MiMo
749 (pay-as-you-go and Token Plan keys look the same), GLM-5.3 and the Alibaba
750 Model Studio plans (quota or credits, not per-token) and StepFun. DeepSeek's output limit stays at its
751 published 384K instead of the refreshed 393,216, and the reasoning controls
752 Codewhale records for Grok, MiniMax, Qwen 3.8 Max, Muse Spark and Step 3.5
753 (defaults, always-on thinking, extra effort tiers) survive the refresh.
754 Committed corrections now fail at load if their provider or model is missing
755 from the bundled seed; partial live refreshes may still omit those rows
756 ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)).
757 - The offline model list is now generated from Models.dev instead of edited by
758 hand, so a fresh install without network sees the same limits, image
759 support and reasoning controls as an online one. Claude, GPT-5.5, Kimi and
760 several OpenRouter models now show image input offline, and a model whose
761 catalog row offers an on/off switch next to its effort tiers keeps Off in
762 `/effort` and Ctrl+T instead of rounding it up
763 ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396),
764 [#6612](https://github.com/codewhale-hq/Codewhale/pull/6612)).
765 - Cost estimates for GPT-5.6 and GPT-5.6 Sol use OpenAI's current rates of
766 $4 input, $0.40 cached input and $20 output per million tokens. They were
767 still at the older $5, $0.50 and $30
768 ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)).
769 - `codewhale integrations dsh` now reads current DeepSeek Harness prerelease
770 versions such as `0.1.7-alpha.2` as semver. They were reported as `offline`
771 and refused; they now show as `stale-version` (launchable once connected,
772 clearly unverified). Only `0.1.0-rc.6` is still the verified version, and text
773 that is not a version is still `offline`.
774 - Rule and chain-segment source labels in the project instructions the model
775 receives (`<project_rule source=...>` and the scoped-instructions comments)
776 are repo-relative instead of absolute. Moving or recasing a checkout no longer
777 changes the pinned system prompt prefix or adds a spurious context update
778 ([#6739](https://github.com/codewhale-hq/Codewhale/pull/6739), thanks @asto18089).
779
780 ### Security
781
782 - On Windows, a broad Node kill (`Stop-Process -Name node`,
783 `Get-Process node | Stop-Process`, `taskkill /IM node.exe`, and wrapped,
784 aliased or nested-shell forms) is held by a built-in safety floor: it is
785 refused in Full Access, Auto-Review and Never, and asks in other modes. With
786 the npm launcher such a command ended this and every other npm-launched
787 Codewhale session without cleanup. Stopping a server by PID or port still
788 works, and the Windows installer and archives have no Node launcher
789 ([#6827](https://github.com/codewhale-hq/Codewhale/issues/6827), thanks @jayanthvee).
790 - `code_execution` and `js_execution` now start their Python and Node
791 interpreters through the same permission-aware launcher as other commands, so
792 the session's execution policy applies to them. Before, an approved call ran
793 the interpreter directly, and its working directory was the only boundary
794 ([#6820](https://github.com/codewhale-hq/Codewhale/pull/6820), thanks @Guan0923).
795 - A saved task without an `auto_approve` field is no longer treated as
796 auto-approved. Updates accept HTTPS URLs only from the release-host
797 allow-list, and the npm release-asset check bounds every request.
798 - Workspace profile and skill discovery, pasted-image and screenshot writes,
799 configuration redaction receipts and legacy configuration migration reject
800 linked paths where they could redirect access outside their intended roots.
801 Additional `.codewhale` writers use the existing confined filesystem helpers.
802 The VS Code file opener checks the file's real path, and PowerShell temporary
803 scripts receive unpredictable names and owner-only permissions.
804 - Update development tooling to Undici 7.29.1 or newer for
805 [GHSA-w293-vg96-wgc3](https://github.com/advisories/GHSA-w293-vg96-wgc3),
806 brace-expansion 1.1.21/5.0.12 for
807 [GHSA-q2hr-2g5m-vwhr](https://github.com/advisories/GHSA-q2hr-2g5m-vwhr),
808 and the VS Code extension's markdown-it to 14.3.2 for
809 [GHSA-253c-mchw-3w2r](https://github.com/advisories/GHSA-253c-mchw-3w2r).
810 - Harden local runtime browser sessions, fleet SSH trust, agent continuation
811 ownership, task gate approval, plugin tool registration, bridge action tokens,
812 and release metadata credential forwarding. Browser sessions recover across
813 reloads and new tabs, and stream tickets retry after transient failures.
814 Fleet SSH known-host checks support OpenSSH 7.x and later. SSH host configs
815 using `host_key_fingerprint` must migrate to `known_hosts` with verified host
816 keys; the unsupported fingerprint field is now refused when an SSH worker
817 starts, before any connection is made, instead of being silently ignored.
818 - Harden workspace instruction, note, and anchor file access with shared
819 no-follow reads and writes. Compaction loads pinned anchors only from
820 trusted workspaces. Validate registry skill names before selecting cache paths.
821 - Tighten approval, execution and endpoint boundaries. Computer control
822 consent and script calls need an exact decision a person gave on that call's
823 own approval card. Automatic Git status and review reads go through the
824 sanitized review command and stay pinned to the checked Git executable.
825 Config backups, config dumps, MCP listings and notification payloads share
826 one sensitive-key vocabulary; structured exports now also redact keys ending
827 in `key`. Python a child model writes during a recursive `rlm` call is
828 admitted round by round like an inline `repl` block, and Python kernels are
829 discarded when permissions narrow. Gate commands and the cargo test runner
830 start inside the session's shell sandbox. Mutable session artifacts are
831 written and read through pinned session-relative paths. The stdio bridge's
832 Runtime child chooses and reports its own loopback port.
833 - Chat bridges (Feishu, Telegram, WeCom, Weixin) accept an approval decision
834 only from the person who started that turn, for the Runtime's current
835 pending approval. After upgrading, approvals for turns that were already
836 running are decided from the TUI, and WeCom `/allow` no longer takes
837 `remember`.
838 - More file and network paths are confined. A task or automation created by a
839 session without full shell access no longer inherits the host's shell default.
840 The commit planner, oversized-paste backup and project harness notes do not
841 read or write through links that leave the workspace. On Unix, audit and
842 approval logs are created owner-only and are not opened through a link;
843 Windows is unchanged. Lane ids must be plain names. A session file is refused
844 when it records a different session id than its name. The updater does not
845 follow a redirect from HTTPS to plain HTTP and stops reading a response larger
846 than 512 MB.
847 - Nothing is written through a `.codewhale` that is a link. The workflow run
848 journal no longer creates `.codewhale/` or its ledger when it is opened, only
849 when the first record is written, and reads and appends through the same
850 confined helpers as other state. The sub-agent coordination lock refuses a
851 linked `.codewhale` or `state` directory before it creates anything.
852 - On Unix, the runtime log is created owner-only and is not opened through a
853 link; an existing log from an earlier version is tightened. The
854 `.reconcile.lock` and `current.json.lock` lock files are created owner-only
855 too.
856 - Inline ```` ```repl ```` blocks in a reply now follow the same rules as the
857 `code_execution` tool. They never run in Plan mode or when
858 `code_execution` is not on the turn's tool surface, and they are admitted
859 like a `code_execution` call with the same code: before-tool hooks,
860 disallowed-tool rules, Auto-Review (including its reviewer) and repository
861 law all apply, then the same approval under the session's permission
862 posture (a blocked, denied or unanswerable call skips them with a visible
863 note). Only a fence that opens its own line counts, here and in the `rlm`
864 tool's child rounds, so a reply that mentions a fence in prose runs nothing.
865 An `rlm(...)` call from a fence gets a one-shot child answer rather than a
866 child that runs its own code. The docs no longer describe the REPL kernel
867 as sandboxed.
868 - `codewhale serve --mcp` now exposes only read-only tools by default
869 (`file_read`, `search`). Tools that write files or run commands are
870 neither listed nor run unless the operator sets `require_approval = false`
871 in the MCP server config; a client's own `approved` flag no longer counts
872 as approval. At startup the server names on stderr each configured tool it
873 withholds and the setting that allows it.
874 - A `Bash` entry in the disallowed tools now also blocks `start_mcp_server`
875 and `start_registry_mcp_server`, which launch local processes.
876 - An MCP tool call whose connection closes before it answers is no longer
877 sent again on a new connection, since the server may already have run it.
878 The same holds for a server error reply that mentions an expired or invalid
879 session. The call reports an unknown outcome and the next call reconnects.
880 Only a call the HTTP transport turned away for a stale session, before the
881 server handled it, is still retried once.
882 - Durable tasks and scheduled automations created by the agent no longer
883 carry more authority than the session that created them: requested
884 `auto_approve`, `trust_mode` and `allow_shell` are capped at what that
885 session holds, a task's workspace and an automation's directories must be
886 reachable from the session, and a task's turn runs under the posture pinned
887 when it was created instead of re-deriving one from the legacy bit or a
888 legacy mode alias.
889 - The approval card for creating a task or creating/updating an automation
890 now lists the requested trust mode, shell, auto-approve, mode and
891 workspace as labeled lines.
892 - "Approve for session" on a shell command now covers only a simple, known
893 command family (`git status` still covers `git status -s`). Compound,
894 wrapper, interpreter, unrecognised and option-configured commands are
895 granted as the exact command, and interact/wait calls on a running shell as
896 the exact call.
897 - Workflow plan approval flags shell, network and file-write capability for
898 the `Bash`, `Web` and `File` tool families regardless of letter case.
899 - An agent session can no longer update, resume or run an automation whose
900 stored `auto_approve`, `trust_mode` or `allow_shell` is more than the
901 session holds, unless the same update lowers those fields.
902 - The approval summary every Runtime client receives for task and
903 automation create/update now names the requested trust mode, shell,
904 auto-approve, mode and workspace, from the same fields the TUI card shows.
905 - A shell session grant keeps its command family only when every option is a
906 known value-free option such as `--release` or `--porcelain`; other options,
907 in any spelling, grant the exact command. Families whose arguments are what
908 runs or is installed (`go run`, `deno run`, `cargo run`, `make`,
909 `git bisect`, `git submodule`, package installs) grant the exact command.
910 - Workflow plan approval recognises tool names in any quote style and with a
911 pattern suffix (`'Web'`, `` `File` ``, `Web(*)`), and flags `rlm`, Git and
912 GitHub, computer and browser control, and task/automation tools with the
913 capabilities they carry.
914 - Model-run code no longer inherits provider credentials or other secrets
915 from Codewhale's environment. Python `code_execution` (and every other
916 Python runner), `gate_run` task gates, custom and completion verifier gates,
917 persistent `terminal` sessions, and `run_tests` now start from the same
918 scrubbed child environment as `exec_shell`; variables a gate declares are
919 still passed through. `gate_run` also runs `/bin/sh -c` instead of a login
920 shell, so profile files cannot re-export what was removed.
921 - A `workflow` start with `verify: true` now needs approval even for a
922 read-only plan, because the completion gates run workspace build and test
923 scripts.
924 - Git commands no longer hand provider credentials to programs that a
925 workspace's git config can start (`core.fsmonitor`, hooks, filters) when
926 they run through Codewhale's shared git helper: those start from the scrubbed
927 environment plus the ssh agent, global config location and author identity.
928 Sub-agent worktree provisioning and delivery do not use it yet. The read-only `git_status`,
929 `git_diff`, history and `verify` tools also disable the workspace's
930 fsmonitor, hooks and clean/process filters.
931 - Language servers started for post-edit diagnostics, and every Python and
932 Node command constructor, start from the scrubbed child environment.
933 - Proxy URLs passed to model-run children (`HTTP_PROXY`, `HTTPS_PROXY`,
934 `ALL_PROXY`, `FTP_PROXY`, `CARGO_HTTP_PROXY`) keep their host and port but
935 lose any `user:password@` part.
936 - Behaviour change: the scrubbed child environment now keeps non-secret build
937 configuration — `CARGO_*` (except registry and token-like keys),
938 `RUSTFLAGS`, `RUST_LOG`, `RUST_BACKTRACE`, `VIRTUAL_ENV`, `JAVA_HOME`, Go
939 paths, `NVM_*`/`NODE_OPTIONS` and CA-bundle variables — so `run_tests` and
940 gates keep the user's target dir, job limit and toolchain. Connection
941 strings such as `DATABASE_URL` are still dropped; set them in the project's
942 own config, or wrap the command in a script that sets them, when a build
943 needs them.
944 - Deny rules in the permission settings now hold for these ways of hiding a
945 command word until the shell runs it: a variable (`$v`), a substitution, a
946 glob or brace list, escaped ANSI-C quoting, or a shell reading its script
947 from a pipe, here-string or process
948 substitution. Rules in a separate `execpolicy.toml` file are applied when
949 the command runs, so there such a command is refused at run time rather than
950 before an approval prompt. While any deny rule is configured in the permission
951 settings, such a command is refused instead of being checked against text
952 the shell will rewrite (an
953 approval-always policy asks instead). This also applies to common forms such
954 as `source "$HOME/.cargo/env"`, `eval "$(pyenv init -)"` and `$PYTHON -m
955 pytest`; name the command directly to run it. The same holds when the text
956 does not parse cleanly (an unterminated quote, substitution or heredoc, a
957 `case` inside `$( … )`) or when a parse budget runs out. Commands after
958 `if`, `then`, `while`, `do`, `!` and similar words, `function f { … }`
959 bodies, and `find -exec` payloads are now checked like any other command.
960 - Wrapper commands are unwrapped by their real option grammar, so
961 `chroot DIR cmd`, `sudo --user NAME cmd` and `timeout -s SIG N cmd` expose
962 `cmd` (and any `-c` payload) to deny rules. Options missing from a wrapper's
963 table are read both with and without a value, BSD and macOS options are
964 covered (`env -P`, `xargs -J`, `chroot -u`), and more wrappers are recognized
965 (`caffeinate`, `arch`, `sandbox-exec`, `nsenter`, `unshare`, `runuser`,
966 `flock`, `watch`, `wsl`, `noglob`, `nocorrect`), including `.exe` spellings.
967 Code passed as a string to `trap`, `su -c`, `flock -c`, `script -c`,
968 `watch`, `cmd /c` and PowerShell `-Command` is checked as a command line.
969 - `(( … ))` arithmetic no longer reads `<<` as a heredoc that hides the lines
970 after it, and an `xargs` or `find -exec` replacement string used as the
971 command or as shell code (`xargs -I{} sh -c {}`) counts as known only at run
972 time.
973 - `task_shell_start` and task gate commands are now checked against shell deny
974 and ask rules, like any other shell command.
975 - An "approve for session" grant for a shell command covers only flag variants
976 of that command as written; a command with options before the subcommand,
977 a chain, or nested code matches only an identical repeat.
978 - The read-only shell surface for sub-agents rejects a word that starts with
979 an unquoted `*`, whose matches could be read as options; quote the pattern
980 or give it a path prefix (`src/*.rs`).
981 - A trusted or allow prefix such as `git status` no longer covers options
982 placed before the subcommand (`git -c key=value status`,
983 `git --exec-path=… status`), nor a command that runs nested code or whose
984 command word is resolved at run time. Such commands ask instead. Typed deny
985 rules also match a path-qualified command word (`/bin/rm`).
986 - Commands containing parentheses are no longer auto-approved as parallel
987 read-only commands, since some shells treat them as glob qualifiers or
988 command substitution.
989 - Sub-agent worktrees stay under the per-repo `.codewhale-worktrees/<repo>/`
990 root: an absolute `worktree_path` is now held to the same containment as a
991 relative one, with symlinks resolved before the check. Any start that asks
992 for a worktree keeps the approval card, even for a read-only role. A
993 `worktree_base` starting with `-` is refused, and `git worktree add` now
994 receives its path and base after `--`.
995 - Fleet and reasoning-router names must be plain file names (optionally
996 `origin/name`); a name with path separators or `..` is refused before any
997 file is looked up, through one shared check in the workflow crate.
998 - `pandoc_convert` and `image_ocr` apply the same read deny-list and
999 credential-store checks as `read`, through one shared helper, and pandoc
1000 always runs with `--sandbox`. This needs pandoc 2.15 or newer; an older
1001 pandoc gets an upgrade message instead of a conversion.
1002 - Computer Use: screenshot and zoom output paths must be `.png`/`.jpg`/`.jpeg`
1003 files inside the recordings directory, and zoom always crops the last
1004 captured raster instead of a caller-named source file.
1005 - Skill registry sync refuses an index key that is not a single path-safe
1006 name before it is used as a cache directory, the same check an installed
1007 skill name already gets.
1008 - A project's `.codewhale/config.toml` can no longer set `notes_path`; it is
1009 ignored with the other user-only keys. The `note` tool and `/note` refuse a
1010 notes file that is a symlink or whose directory resolves outside the
1011 workspace, and a note is flushed to disk before the tool reports success.
1012 - Diffs and shows that read repository content (`codewhale review`, the
1013 `git_diff`/`git_show` tools, verification, delivery, task attempt records,
1014 `@diff` and the runtime API diff routes) share one flag set: no external
1015 diff, no textconv, and submodules compared by commit only, so a submodule's
1016 configured filters and diff drivers never run. Reads of the working tree
1017 (`git_diff`, `git_show`, `git_blame`, commit planning, verification, task
1018 attempt records, `@diff`/`@git`) also run through the hardened review
1019 command, so the repository's clean filters do not run either. `git_blame`
1020 and read-only shell `git blame` skip textconv, and read-only shell `git`
1021 reads neutralize the repository's clean filters.
1022 - `git_fetch` refuses refspecs that would write a local branch or tag: a
1023 `src:dst` destination must be under `refs/remotes/`, and the two-word
1024 `tag <name>` form is rejected.
1025 - Opening a URL on Windows goes through the URL protocol handler instead of
1026 `cmd /C start`, so characters in the URL are not interpreted by the shell.
1027 - Skill downloads and the skills registry index are read through a streaming
1028 size cap shared with the MCP HTTP transport, instead of buffering the whole
1029 body before checking its size.
1030 - Durable runtime thread, turn and item ids carry a full UUID instead of 32
1031 random bits, so two records can no longer collide and overwrite each other.
1032
1033 ### Removed
1034
1035 - Flags, settings and tool parameters that did nothing are gone
1036 ([#6516](https://github.com/codewhale-hq/Codewhale/issues/6516)). `--output-mode`
1037 is hidden. It is still accepted, prints a warning, and is ignored.
1038 - The dispatcher no longer exports `DEEPSEEK_*` copies of its `CODEWHALE_*`
1039 variables. A `DEEPSEEK_*` variable you set yourself is still read.
1040 - `lane start` and `workflow run --runtime vm|ci` are rejected before a lane
1041 is created. Older lane records for those runtimes still load.
1042 - The control socket's `relaunch` verb is removed; it always returned an
1043 error.
1044 - The `speech` tool drops `stream`. `stream=true` used to fail; it is now
1045 ignored, a complete audio file is written, and the result no longer carries
1046 `"stream": false`. The `finance` tool drops `market`, and a call that still
1047 passes it has it ignored.
1048 - `[context].enabled`, the seam-manager keys and
1049 `tui.terminal_probe_timeout_ms` no longer load; old configs that carry
1050 them still start. The `[workshop]` docs now describe bounded spillover
1051 instead of a synthesis sub-agent.
1052 - About 2,650 lines of workflow code that nothing ran are deleted: the replay
1053 executor, the review-repair loop and experimental search. The
1054 `replay_diverged` status they produced goes with them. The isolated
1055 Runtime Chat prompt and the legacy YOLO alias list each have one owner now
1056 ([#6517](https://github.com/codewhale-hq/Codewhale/issues/6517)).
1057
1058 ### Experience
1059
1060 - Typing a first message with no model connected leaves a line in the
1061 transcript that says the message was not sent and opens the provider picker.
1062 - First run picks a chat-capable Ollama model instead of the alphabetically
1063 first tag, and says plainly when no model is available yet.
1064 - `codewhale doctor` leads and ends with one verdict and the next step, and
1065 gives the update command for how you actually installed Codewhale.
1066 Command-line usage and errors say `codewhale`.
1067 - The approval card leads with a plain summary of the action, such as
1068 "Run `cargo test`", and shows workspace-relative paths. The footer labels
1069 its values.
1070 - `/status` warns when the session's pinned model is no longer in its
1071 provider's live model list
1072 ([#6035](https://github.com/codewhale-hq/Codewhale/issues/6035)).
1073 - Error messages give one true sentence and one next step. The TUI's English
1074 copy says agent, Fleet, Permissions and Work consistently, help lists one
1075 summary per row, provider rows without a key say "needs key", `/setup` says
1076 what it sets up, and the pet tank rests when it is offline.
1077 - ACP clients can see the Permissions setting the server started with,
1078 including Full Access and how to turn it on, but cannot select it
1079 ([#6310](https://github.com/codewhale-hq/Codewhale/issues/6310)).
1080 - `GET /v1/commands` tells clients each command's argument shape, so they do
1081 not re-derive composer behaviour from the usage string
1082 ([#6230](https://github.com/codewhale-hq/Codewhale/issues/6230)).
1083
1084 ### Fleet and agents
1085
1086 - `codewhale fleet run <spec> --check` runs every validation a real run would
1087 and stops there: nothing is created, launched or spent.
1088 - A queued agent says why it is waiting, for example when launches are
1089 throttled after provider rate limits, and when it stops waiting
1090 ([#6277](https://github.com/codewhale-hq/Codewhale/issues/6277)).
1091 - Read-only agents can run chained inspection commands (a leading `cd`,
1092 `&&`, `;`, `echo` separators, `2>/dev/null`), and a refused command now
1093 names the rule it broke and what to do instead. Durable Fleet workers
1094 accept the same read-only commands as in-session agents. An agent's time
1095 budget starts when it launches, and a queued agent that never gets a slot
1096 says it never started
1097 ([#6015](https://github.com/codewhale-hq/Codewhale/issues/6015)).
1098 - Stopping an agent that writes files keeps and names the work it had
1099 changed, as a budget stop already did
1100 ([#5529](https://github.com/codewhale-hq/Codewhale/issues/5529)).
1101 - `workflow(fleet:)` runs Fleets saved from the Fleet UI, and finds
1102 workspace Fleets under `.codewhale/fleets`.
1103 - The runtime API can stop a delegated agent run from the desktop.
1104 - A finished agent's answer is no longer cut off. Its row and its completion
1105 notification show the first sentence of its result instead of a
1106 `## Summary` heading or its last tool, and opening the agent shows the whole
1107 result, or the full reason it stopped, even when no transcript was captured.
1108 Each agent also has one name: a workflow task's label or its dispatch name
1109 appears on the rows, the notification and the runtime API alike, never its
1110 internal id ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)).
1111 - The mobile page shows the thread's agents: a strip naming each one, its
1112 state, and what it is doing or what it found, rebuilt when the page
1113 reconnects. Sub-agent prompt caching now counts toward the session, including
1114 cache-write-only reports. PRICE and `/cache` show the parent, agents and
1115 combined hit rates, each labelled and weighted by all input tokens,
1116 including cache writes,
1117 and the footer `cache N%` still means this conversation's own requests
1118 ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)).
1119 - The dock's GIT, FILES and NOTES views are real. GIT shows the branch and
1120 where it stands against its upstream, the changes (with their paths one
1121 Enter away), linked worktrees and the last five commits, and it keeps
1122 updating during a turn while it is open. It says "not a git repository"
1123 only when that is true, reports failed status probes in the view and composer
1124 instead of claiming a clean tree, counts every unmerged path as a conflict, and only
1125 says there are more changed paths when the list is capped. FILES lists the
1126 files this session edited, including writes without diff receipts, and the
1127 files it read, with every unique path retained beyond the activity summary's
1128 twelve-path preview. FILES and its badge refresh from the current session
1129 even before TASKS opens. Edits with receipts show their size and open their diff.
1130 NOTES lists your `/note` notes. The git
1131 badge, the Git view and the model's git line now share one
1132 `git status --porcelain=v2` call, so there are fewer git processes than
1133 before ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)).
1134 - Background work tells you when it ends, even between refreshes. Batched
1135 shell notices cover explicitly backgrounded or detached commands; foreground
1136 results and old completions from before this TUI session stay quiet.
1137 Switching sessions does not repeat a completion notice. Batched
1138 notices count completed, failed and stopped work separately; shell commands,
1139 task prompts and errors stay in the app, away from lock-screen notifications.
1140 A running dev server no longer holds the notice back. Failed, killed and
1141 timed-out shells retain their outcomes, and the last eight finished shells
1142 stay listed per session. Finished tasks no longer look live or reopen the
1143 dock. Background labels follow the UI language, long agent previews keep
1144 their full-result pointer, and the quiet indicator uses the engine's clock
1145 and limit without marking an active tool as quiet
1146 ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)).
1147
1148 ### Plugins
1149
1150 - Codewhale no longer appends plugin recommendations to your messages to the
1151 model. Suggestions appear in one place, follow one switch and one budget,
1152 and never advertise built-in plugins, generic words or plugins for another
1153 operating system.
1154 - `/plugin dismissals` lists the plugins suggestions skip, and
1155 `/plugin dismissals reset [<name>]` brings them back.
1156 - Tools from reviewed plugins that declare themselves read-only no longer ask
1157 for approval on every call.
1158 - The bundled Computer Use plugin is 0.12.0, the published upstream release
1159 `8435692` ([#6303](https://github.com/codewhale-hq/Codewhale/issues/6303),
1160 [#5856](https://github.com/codewhale-hq/Codewhale/issues/5856)). On macOS the agent
1161 uses its own pointer and never drives your cursor. `app_script` refuses shell
1162 escapes. Clicks on irreversible actions such as
1163 pay, send or delete need confirmation. Consent decisions cannot ride inside
1164 `run_actions` or trajectory replay, and trajectories redact secure fields.
1165 Also new: a shared-computer control lease that pauses agent input while a
1166 person drives, and a browser attach mode for a shared Chromium. The vendored
1167 README no longer claims delegated agents share the Computer Use session; they
1168 never receive its tools.
1169 - The bundled first-party catalog pins marketplace revision
1170 `ae3dd2255a9a266365c6125a084f511eb26bc04d`. It lists Computer Use 0.12.0 and
1171 adds Codewhale for Chrome (Chromewhale) 0.3.0 as a developer preview: you
1172 load its Chrome extension unpacked, and like every catalog plugin it installs
1173 disabled and untrusted until you review it.
1174
1175 ### Release reliability
1176
1177 - Upload the complete release into a private draft, verify every asset's size
1178 and SHA-256 digest, then publish. An interrupted retry cannot reuse stale
1179 same-size bytes. CNB and GHCR version tags follow canonical publication.
1180 - Ubuntu Lighthouse bootstrap requires trusted SSH source CIDRs or an explicit
1181 public-SSH opt-in before changing the host; malformed IPv6 and broad default
1182 networks are refused.
1183
1184 ### CI
1185
1186 - State-touching command and session tests seal `HOME`, `USERPROFILE` and
1187 `CODEWHALE_HOME` onto temporary directories. Unsealed session, snapshot,
1188 artifact, composer-history, audit and built-in-plugin storage resolves into
1189 an isolated test root; unrelated worker threads cannot borrow another test's
1190 home seal. A child-process sentinel checks that known command-dispatch and
1191 session cases leave their ambient home unchanged.
1192 - Fork pull requests stay under the macOS runner limit and the Actions cache
1193 stays under its cap.
1194 - Release candidates and releases share one parity gate, and a release tag
1195 without a release-candidate receipt is refused.
1196 - Budget ratchets block same-repository pull requests unless the pull request
1197 updates the budget with a receipt.
1198 - A CodeQL advanced-setup workflow is ready for when the repository switches
1199 from default setup.
1200
1201 ### Contributors
1202
1203 Seventeen contributors and issue reporters are credited below, including
1204 @cenab's provider report.
1205
1206 - **[@Guan0923](https://github.com/Guan0923)** — accepted case-insensitive HTTP(S) schemes in `config doctor` without rewriting the configured URL ([#6819](https://github.com/codewhale-hq/Codewhale/pull/6819)), and routed the Python and JavaScript execution tools through the session's execution policy ([#6820](https://github.com/codewhale-hq/Codewhale/pull/6820)).
1207 - **[@harryvgiunta](https://github.com/harryvgiunta)** — added Yolo-Auto as a bundled OpenAI-compatible host, starting on the vendor's recommended `qwen3.8-flash` model ([#6408](https://github.com/codewhale-hq/Codewhale/pull/6408)).
1208 - **[@asto18089](https://github.com/asto18089)** — contributed the integrated runtime liveness, context, search, JavaScript execution, stopship scout and pet repairs, preserving their original contributor commits ([#6799](https://github.com/codewhale-hq/Codewhale/pull/6799)); made context rule and chain-segment source labels repository-relative ([#6739](https://github.com/codewhale-hq/Codewhale/pull/6739)).
1209 - **[@qiuYliangM](https://github.com/qiuYliangM)** — made provider-bound project instruction and constitution labels stable across directory moves and kept their absolute paths in operator reports ([#6799](https://github.com/codewhale-hq/Codewhale/pull/6799)).
1210 - **[@zhuowp](https://github.com/zhuowp)** — supplied the process-scoped PowerShell execution-policy repair adapted for Codewhale, preserving machine and user Group Policy precedence ([#6745](https://github.com/codewhale-hq/Codewhale/issues/6745)).
1211 - **[@Andrea-Bruno](https://github.com/Andrea-Bruno)** — designed the Superfast Decision Gate and contributed its off-by-default shadow classifier ([#6604](https://github.com/codewhale-hq/Codewhale/pull/6604), [#6603](https://github.com/codewhale-hq/Codewhale/issues/6603)).
1212 - **[@aiapienthusiast](https://github.com/aiapienthusiast)** — added Cheaper Inference to the bundled provider catalog ([#6761](https://github.com/codewhale-hq/Codewhale/pull/6761)).
1213 - **[@gaord](https://github.com/gaord)** — let a client fork a thread at a named turn ([#6580](https://github.com/codewhale-hq/Codewhale/pull/6580)), let undo roll back files for the turn it is undoing ([#6483](https://github.com/codewhale-hq/Codewhale/pull/6483)), stopped resume and fork from duplicating threads and sessions ([#6406](https://github.com/codewhale-hq/Codewhale/pull/6406)), exposed user-defined provider routes to native clients ([#6404](https://github.com/codewhale-hq/Codewhale/pull/6404)), and kept a fork going when a turn lost its tool call ([#6664](https://github.com/codewhale-hq/Codewhale/pull/6664)).
1214 - **[@Lstarsky0](https://github.com/Lstarsky0)** — moved the docs/work, legal, digest and FAQ pages onto the dictionary spine ([#6405](https://github.com/codewhale-hq/Codewhale/pull/6405), [#6417](https://github.com/codewhale-hq/Codewhale/pull/6417), [#6499](https://github.com/codewhale-hq/Codewhale/pull/6499), [#6574](https://github.com/codewhale-hq/Codewhale/pull/6574)), tightened the Chinese-branching ceiling to 18 ([#6403](https://github.com/codewhale-hq/Codewhale/pull/6403)), and made Fleet publish without a two-link window ([#6431](https://github.com/codewhale-hq/Codewhale/pull/6431)). Also moved the constitution page onto the dictionary spine and kept its install link in the selected locale ([#6733](https://github.com/codewhale-hq/Codewhale/pull/6733)), wrapped diff and tool output at grapheme boundaries ([#6829](https://github.com/codewhale-hq/Codewhale/pull/6829)), and translated the context inspector rows twelve packs still shipped in English ([#6831](https://github.com/codewhale-hq/Codewhale/pull/6831)).
1215 - **[@aboimpinto](https://github.com/aboimpinto)** — restored a green Linux full-workspace test gate without loosening any test, twice ([#6581](https://github.com/codewhale-hq/Codewhale/pull/6581), [#6666](https://github.com/codewhale-hq/Codewhale/pull/6666)). Completed the seventeen-command portable session group, including `/structcopy` ([#6793](https://github.com/codewhale-hq/Codewhale/pull/6793)).
1216 - **[@dajiaohuang](https://github.com/dajiaohuang)** — `codewhale config set` checks a known setting's value against its schema type before saving it ([#6568](https://github.com/codewhale-hq/Codewhale/pull/6568)).
1217 - **[@jayanthvee](https://github.com/jayanthvee)** — reported and diagnosed that killing the npm launcher's `node.exe` ends Windows sessions without cleanup, with reproductions and fix directions ([#6827](https://github.com/codewhale-hq/Codewhale/issues/6827)).
1218 - **[@cenab](https://github.com/cenab)** — requested the Tsubasa provider row and supplied its endpoint, key and model values ([#6695](https://github.com/codewhale-hq/Codewhale/issues/6695)).
1219 - **[@BX166](https://github.com/BX166)** — reported the AICraft provider row missing its key console, docs link and guidance, and supplied the values ([#6616](https://github.com/codewhale-hq/Codewhale/issues/6616)).
1220 - **[@Water-Run](https://github.com/Water-Run)** — ingested namespaced model-only catalog entries so models present only in the canonical `models` map reach the offering list ([#6400](https://github.com/codewhale-hq/Codewhale/pull/6400)), and retired the blanket dead-code allowance with its unused feature stages, tightening the budget to match ([#6402](https://github.com/codewhale-hq/Codewhale/pull/6402)).
1221 - **[@wuisabel-gif](https://github.com/wuisabel-gif)** — designed the `tool_call_after` execution-receipt contract and its tests on a reference branch, which landed re-implemented on the current hook seam ([#6689](https://github.com/codewhale-hq/Codewhale/issues/6689), [#6713](https://github.com/codewhale-hq/Codewhale/pull/6713)).
1222 - **[@SparkofSpike](https://github.com/SparkofSpike)** — let making room survive a provider request-body limit (HTTP 413) by shrinking, then replacing, inline images for that one summary pass ([#6642](https://github.com/codewhale-hq/Codewhale/pull/6642)). Translated seventeen Tier-2 guides and thirteen developer and internal docs into Simplified Chinese, and connected the localized documentation ([#6662](https://github.com/codewhale-hq/Codewhale/pull/6662), [#6663](https://github.com/codewhale-hq/Codewhale/pull/6663)); added regression coverage for rejecting unknown website locales before dictionary lookup ([#6786](https://github.com/codewhale-hq/Codewhale/pull/6786)); made the pinned prompt header follow the viewport's turn and jump on click ([#6830](https://github.com/codewhale-hq/Codewhale/pull/6830)).
1223
1224 ## [0.10.0] - 2026-09-22
1225
1226 Codewhale v0.10.0 brings a redesigned terminal workbench, clearer settings, and
1227 more reliable session and runtime behavior. It supersedes the unpublished
1228 v0.9.14 candidate.
1229
1230 ### Contributors
1231
1232 - **[@AdityaVG13](https://github.com/AdityaVG13)** — fixed composer wrapping, tab/caret placement, pasted and editor-returned draft history, painted-column transcript copying, explicit terminal foregrounds, headless user-input tool availability, and engine synchronization after importing foreign sessions ([#6369](https://github.com/codewhale-hq/Codewhale/pull/6369), [#6363](https://github.com/codewhale-hq/Codewhale/pull/6363), [#6365](https://github.com/codewhale-hq/Codewhale/pull/6365)).
1233 - **[@aboimpinto](https://github.com/aboimpinto)** — moved the TUI session-export slice onto shared command contracts (FEAT-025): a session-export contract facet with one shared sanitizer, `/export` routed through the facet, pinned with baseline-captured goldens and gates ([#6096](https://github.com/codewhale-hq/Codewhale/pull/6096)).
1234 - **[@BX166](https://github.com/BX166)** — contributed the AICraft provider template and its documentation ([#6171](https://github.com/codewhale-hq/Codewhale/pull/6171)). It was closed unmerged, but it is what surfaced the decision to stop special-casing named OpenAI-compatible hosts ([#6289](https://github.com/codewhale-hq/Codewhale/issues/6289)).
1235 - **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — reported the session-retention defects behind archive-past-the-cap and empty-session cap occupancy ([#6136](https://github.com/codewhale-hq/Codewhale/issues/6136), [#6137](https://github.com/codewhale-hq/Codewhale/issues/6137)), the resume-failure design behind durable transcript errors ([#6138](https://github.com/codewhale-hq/Codewhale/issues/6138)), and the gaps behind the opt-in approval timeout ([#6101](https://github.com/codewhale-hq/Codewhale/issues/6101)), `codewhale exec --hooks` ([#6099](https://github.com/codewhale-hq/Codewhale/issues/6099)), Markdown drag-copy ([#6156](https://github.com/codewhale-hq/Codewhale/issues/6156)), and the browsable, current-aware session picker ([#6014](https://github.com/codewhale-hq/Codewhale/issues/6014)); the goal token-budget hard stop ([#6013](https://github.com/codewhale-hq/Codewhale/issues/6013)) and the fleet no-progress guard shared with child workers ([#6015](https://github.com/codewhale-hq/Codewhale/issues/6015)) landed as first slices of two larger proposals, and the runtime-store session refusal ([#6207](https://github.com/codewhale-hq/Codewhale/issues/6207)).
1236 - **[@Lstarsky0](https://github.com/Lstarsky0)** — reported TUI tests reading machine state instead of hermetic fixtures; the `lock_test_env` remedy from that report shaped two more hermetic fixes, for the shared UI fixtures and the compaction budget test ([#5359](https://github.com/codewhale-hq/Codewhale/issues/5359)).
1237 - **[@Lujc0523](https://github.com/Lujc0523)** — reported `/hooks edit` splitting keystrokes between the editor and the composer, fixed by pausing the TUI input pump inside the editor handoff ([#6165](https://github.com/codewhale-hq/Codewhale/issues/6165)).
1238 - **[@Statter](https://github.com/Statter)** — reported the Gemini `/models` failure that now surfaces the provider's reason instead of an empty error ([#6173](https://github.com/codewhale-hq/Codewhale/issues/6173)).
1239 - **[@sequico](https://github.com/sequico)** — reported the ACP `session/new` ids that `session/load` could not resolve, fixed by minting resolvable session ids ([#6174](https://github.com/codewhale-hq/Codewhale/issues/6174)).
1240 - **[@bevis-wong](https://github.com/bevis-wong)** — reported the mid-run engine freeze behind the bounded turn-end foreground-child join, and the resume path that re-ran identical tool-call repair on every load instead of persisting it ([#6184](https://github.com/codewhale-hq/Codewhale/issues/6184), [#6185](https://github.com/codewhale-hq/Codewhale/issues/6185)).
1241 - **[@gaord](https://github.com/gaord)** — recorded the mode each turn ran in ([#6321](https://github.com/codewhale-hq/Codewhale/pull/6321), harvested), stated the approval posture a task thread starts on ([#6386](https://github.com/codewhale-hq/Codewhale/pull/6386)), and rebuilt the runtime-API thread summary in one store pass ([#6376](https://github.com/codewhale-hq/Codewhale/pull/6376)).
1242 - **[@zhuowp](https://github.com/zhuowp)** — preserved chat roles across compaction, protected user turns on recompaction, and kept the operate contract intact ([#6286](https://github.com/codewhale-hq/Codewhale/pull/6286)).
1243 - **[@h3c-hexin](https://github.com/h3c-hexin)** — rate-limit-adaptive subagent launch scheduling: the `DynamicGate` that replaces fixed spawn pacing under provider throttling ([#6055](https://github.com/codewhale-hq/Codewhale/pull/6055), harvested).
1244 - **[@asto18089](https://github.com/asto18089)** — co-authored the rate-limit-adaptive launch scheduling work ([#6055](https://github.com/codewhale-hq/Codewhale/pull/6055)).
1245 - **[@yrk111222](https://github.com/yrk111222)** — ModelScope provider support, landed through the shared `ChildGrant` fleet authority ([#6299](https://github.com/codewhale-hq/Codewhale/pull/6299), harvested).
1246 - **[@xiechimon](https://github.com/xiechimon)** — capped child tool results at capture time rather than at render ([#6294](https://github.com/codewhale-hq/Codewhale/pull/6294), harvested).
1247 - **[@VincentCorleone](https://github.com/VincentCorleone)** — defined and implemented the weixin-bridge Quick Start so a first run works from the README alone ([#6170](https://github.com/codewhale-hq/Codewhale/pull/6170), harvested).
1248 - **[@Serendo](https://github.com/Serendo)** — fixed the `/config` theme editor exiting the panel on an arrow key ([#6336](https://github.com/codewhale-hq/Codewhale/pull/6336)).
1249 - **[@yetuge](https://github.com/yetuge)** — dropped the retired `token_budget` field from the subagent documentation ([#6335](https://github.com/codewhale-hq/Codewhale/pull/6335)).
1250 - **[@Water-Run](https://github.com/Water-Run)** — translated the local browser client guide into Simplified Chinese ([#6401](https://github.com/codewhale-hq/Codewhale/pull/6401)). Water-Run's catalog and dead-code work (#6400, #6402) landed after the v0.10.0 tag and ships in v0.10.1.
1251 ### Security
1252 - Children never inherit desktop or computer-control tools. Desktop control is
1253 the most machine-wide capability in the catalog, and a verifier child
1254 inherited it by default: on 2026-09-17 one opened the host Terminal and typed
1255 a blocked shell command into the user's live session. A family classifier now
1256 removes those tools when a child's registry is built, so they are neither
1257 eager nor searchable, and `execute_full` refuses the family at dispatch for
1258 every child role — visibility is a grant, and hiding is not the only defense
1259 (#6296).
1260 - Runtimes can be held to an organization's plugin allowlist. A managed policy
1261 document (`managed-policy.json` beside `state.json`, or
1262 `CODEWHALE_MANAGED_POLICY_PATH`) lists the plugin ids a Runtime may run,
1263 with an `allow_unlisted` flag and a schema version checked exactly like
1264 `PluginStateFile`. Enforcement sits inside `apply_state`, so a plugin
1265 enabled before the policy arrived — or hand-edited to `enabled: true` —
1266 never comes back enabled, and `enable()` re-reads the document so a policy
1267 landing after discovery refuses with a reason that names it. A malformed
1268 document fails closed rather than degrading to unenforced. With no policy
1269 present, behaviour is bit-for-bit what it was. This is the enforcement
1270 primitive only; the authority that decides the allowlist is still local,
1271 so it binds a cooperating Runtime, not a hostile one.
1272
1273 - Approving an `apply_patch` "for the session" is now scoped to the file you
1274 approved. The grouping key that scopes a session grant was built by a second,
1275 weaker patch parser that read only `+++ b/` headers and the `replace` array:
1276 it saw no target at all for the documented `apply_patch{path, patch}`
1277 override, for `--no-prefix` diffs, or for delete-only diffs, and collapsed
1278 every one of them to a single shared key. One approval therefore pre-approved
1279 every later patch of that shape, to any file, with no card and no notice. The
1280 key now comes from the same resolver the executor and the permission path
1281 already use, and an input that cannot be resolved gets its own key rather
1282 than a shared one (#6247).
1283
1284 ### Added
1285 - The statusline's performance readings survive compact mode and are separately
1286 configurable. Measured TTFT and average output rate are kept when space
1287 allows, shedding help text and secondary counts first; the existing metrics
1288 and statusline settings gain individual toggles with a migration that
1289 preserves a legacy single setting, and the picker takes mouse selection and
1290 scrolling.
1291 - Tasks can be given their own run name. `NewTaskRequest`, `TaskRecord` and
1292 `TaskSummary` carry an optional `name`, stored as given and omitted when
1293 absent, so queues still fall back to prompt-derived titles; a run started by
1294 an automation inherits the automation's name. The `tasks` tool's schema
1295 extends backward-compatibly and legacy records decode through serde defaults
1296 (APPS-153).
1297 - The offline catalog seeds Xiaomi's MiMo 2.6 family — `xiaomi/mimo-v2.6-pro`
1298 and `xiaomi/mimo-v2.6-flash` — so a first boot without network no longer shows
1299 the 2.5 generation. `DEFAULT_XIAOMI_MIMO_MODEL` stays on `mimo-v2.5-pro`, and
1300 the rows carry no price because the published rates cover only `sk-` keys.
1301 - Native memory is a reviewed store, not a model-writable file. `codewhale-memory`
1302 backs the TUI with SQLite as the authority instead of Markdown, and the
1303 `remember` tool now only *proposes* candidates — a model can no longer write
1304 an active memory. `/memory` and the Runtime API commit through
1305 `remember_reviewed`, and a Context Lens surface (`/v1/memory/lens`,
1306 `/lens/actions`, `/events`) shows what was kept and why.
1307 - Code mode (Experimental, default off): `execute_tools` runs a JavaScript
1308 program against a QuickJS host surface so a model can express several tool
1309 calls as one program. Nested calls must be read-only and auto-approved; the
1310 tool is hidden in Plan and refused under worker authority. Enable with
1311 `[features] code_mode`.
1312 - Two new built-in providers: **ZenMux** (`ZENMUX_API_KEY`) and **CSDN 星图**
1313 (`CSDN_API_KEY`, Coding Plan quota billing), each with its own key slot,
1314 bootstrap model and catalog rows.
1315 - The Runtime API gained the surface a native client actually needs: jobs with
1316 stdin, kill and cursor reads; context, secrets, git, diagnostics, targets,
1317 LSP and voice routes; `GET /v1/commands` for the slash-command catalog;
1318 `GET /v1/workspace/instructions`; account-wide `GET /v1/approvals`; plan and
1319 to-do inventory; `/v1/settings/schema`, with `POST /v1/config` now persisting
1320 every declared `settings.toml` key rather than a curated allowlist; PTY byte
1321 replay, resize and exit; and tool images as session artifacts.
1322 - Codewhale holds the host's idle-sleep assertion while a turn is in flight
1323 (`caffeinate -i` on macOS, `systemd-inhibit` on Linux), so an unattended
1324 machine no longer sleeps mid-run. You will see one child process per turn.
1325 - Skills are reachable in one call. The pinned `## Skills` index told the model
1326 to call `load_skill`, but the tool was deferred behind `tool_search`, so it
1327 was never in the tool array that instruction was printed beside: using a
1328 skill cost a discovery hop, a `name="list"` round trip, and a
1329 `change:tool_surface` re-pin of the whole cached prefix. `load_skill` is now
1330 eager for the parent and for children — +244B of pinned catalog, measured,
1331 against a re-prefill avoided every time a skill is used — and it takes a
1332 `query` that searches names and descriptions, so a truncated index no longer
1333 forces pulling the whole catalogue to find one skill. The usage line now says
1334 to load the matching skill by name before starting the work.
1335 - A fast lane the router cannot serve now says so. `provider_router_candidates`
1336 answers `cheap: None` for any pair its tables do not know, and a
1337 `Faster`/`Auto` child on such a pair used to run at the parent's model and
1338 price with no receipt and no way to tell "single tier by design" from
1339 misconfiguration. The fallback stays — the router must not invent a model —
1340 but the spawn receipt now carries a `fallback_note` naming the unserved lane,
1341 the same field the pinned-provider fallback already uses. `Inherit` and
1342 served lanes stay quiet: this reports a fallback, it does not nag.
1343
1344 - The runtime API tells a replayed submission apart from a new admission:
1345 `POST /v1/threads/{id}/turns` answers `200` with `idempotent_replay: true`
1346 when the operation key was already used, and `201` for a fresh admission, so a
1347 client that retries after a dropped response can no longer create a second
1348 turn. The flag is absent on a fresh admission, so responses existing clients
1349 already parse are unchanged (#76).
1350 - Event streams resume where they left off: journal frames carry their durable
1351 `seq` as the SSE event `id:`, `Last-Event-ID` is honoured as the cursor when
1352 no explicit `since_seq` is asked for, and `RuntimeCapabilities` advertises
1353 `event_stream_resume` so a client can gate its reconnect controls on the
1354 capability instead of discovering it from a missing id (#76).
1355
1356 - TTFT and average output rate stay visible in the compact working footer when
1357 space allows. `/statusline` now controls them separately; existing
1358 `session_metrics` settings still work.
1359 - StepFun’s current coding catalog includes Step 5 Preview, Step 3.7 Flash,
1360 Step 3.5 Flash and its 2603 version, with published reasoning controls and
1361 PAYG rates. Existing Step Plan routing remains subscription-based.
1362
1363 - `read` responses now always report the file's byte size, line count, and
1364 whether output was truncated, and truncation footers name the total size
1365 alongside the continuation offset — so paging through a large file is
1366 deliberate instead of a surprise (#6283).
1367 - File edits are parse-gated before the write lands: Rust goes through
1368 `syn::parse_file` for a grammar-exact `line:column`, and `.toml` / `.json`
1369 through the parsers already vendored. An edit is refused only when the file
1370 parsed *before* and would not parse *after* — repairing an already-broken
1371 file is the commonest reason to edit source at all, so pre-existing breakage
1372 and new files fail open. The check precedes the write, so a rejection leaves
1373 the file untouched and `apply_patch` cannot half-apply (#6204, #6206, #6151).
1374 - Rust files that were already `rustfmt`-clean are re-normalized after an edit,
1375 so the next patch's anchors still match. Hand-formatted files are never
1376 rewritten, and every failure path skips and lets the edit land (#6205, #6151).
1377 - Native clients can finish provider setup without dropping to the CLI:
1378 `DELETE /v1/providers/{id}/key` clears a Codewhale-owned credential through
1379 the same shared owner as `codewhale auth clear`, and `GET /v1/providers`
1380 now carries `credentialSource` / `credentialWritable` (plus a reason) so a
1381 client disables its control with a truthful explanation instead of letting
1382 a write fail late. A credential Codewhale does not own — a literal key in a
1383 config file, or an active external consent — refuses both verbs with `409`
1384 rather than appearing to succeed against a source that still wins at
1385 request time (#6179).
1386 - The interactive approval card can be bounded: `[approval] timeout_seconds`
1387 resolves an unanswered card to **deny** when the window elapses — the same
1388 fail-closed decision the external approval path takes — and the transcript
1389 says the bound denied the call, not the operator. Omitted or `0` keeps
1390 today's unbounded wait, so nothing changes unless you opt in (#6101).
1391 - Transcript drag selection copies Markdown source by default: every cell the
1392 selection touches serializes through the same canonical path `Ctrl-Y` and
1393 `/copy` use, joined with blank lines, and the toast names the copied cell
1394 count. A selection that does not cover every touched cell end to end copies
1395 the exact rendered fragment instead: rounding a pinpoint selection out to
1396 whole cells meant copying an entire model message (#6228).
1397 `tui.selection_copy_markdown = false` keeps the rendered-text payload
1398 (#6156).
1399 - The Runtime API serves the workspace files a native client browses and edits:
1400 `GET /v1/workspace/files` lists one directory, `GET /v1/workspace/files/read`
1401 returns a bounded byte window with a whole-file SHA-256 revision, and
1402 `PUT /v1/workspace/files` writes atomically through the confined opener with
1403 revision-checked overwrites (409 on drift). `.git` is never served and
1404 symlinks are never followed. A saved session's oversized tool outputs are
1405 served as artifacts at `GET /v1/sessions/{id}/artifacts` and
1406 `GET /v1/sessions/{id}/artifacts/{artifact_id}`. (#6163)
1407 - A session that ended mid-turn is no longer invisible to the model. The newest
1408 workspace-scoped session still holding a crash-recovery checkpoint is
1409 surfaced as a one-line `## Prior Session` notice in the session-pinned prompt
1410 prefix — metadata reads only, excluding the live session and any session this
1411 process instance created. Clean sessions get no block, so their prefix bytes
1412 are unchanged. Two bounded read-only tools, `session_search` and
1413 `session_get`, give the model workspace-scoped recall over the same store
1414 (one-line summaries and an 8-message tail, labeled untrusted user data, read
1415 on the blocking pool). Resuming stays the user's decision: the hint tells the
1416 model to offer a continuation, never to silently take one (#5715).
1417 - `codewhale exec --hooks` opts a headless run into the same `HookExecutor` the
1418 TUI builds — global config, reviewed plugin snapshots, and trusted project
1419 `hooks.toml`. Headless runs previously fired no hooks at all. `tool_call_before`
1420 can still deny and `shell_env` still applies; a hook `ask` resolves
1421 fail-closed without a terminal. Fleet worker subprocesses never opt in, and
1422 `permissions.toml` typed rules are unchanged (#6099).
1423 - `codewhale doctor` flags fleet and profile model pins that the provider's own
1424 roster no longer offers. A pin is reported only when a *fresh* cached live
1425 roster for that exact route exists and omits it — stale, failed, or absent
1426 rosters prove nothing and are counted as `unverifiable` rather than raising a
1427 false warning. Each row names the route and every owner of the pin; the pin
1428 is surfaced, never rewritten (#6035).
1429 - Background-capable clients can enumerate owned work and watch TUI-visible
1430 conditions: `GET /v1/threads/running` lists threads with queued or
1431 in-progress turns in one call (one turns scan grouped by thread), and
1432 `GET /v1/threads/{id}/notices` serves active `subagent-terminal`,
1433 `elevation-needed`, and `model-notify` notices with thread/turn identity,
1434 cleared by ack or — for elevation — when the tool call completes (#6180,
1435 #3757).
1436 - Sub-agent launches adapt to provider throttling: a `DynamicGate` replaces
1437 the fixed semaphore so launch capacity adjusts at runtime, and a
1438 `RateLimitGovernor` halves capacity on 429 pressure, pauses admissions
1439 past the threshold, and recovers additively; 429 retries honor
1440 `Retry-After` with jittered backoff, and quota exhaustion keeps the
1441 failure path (#6055).
1442 - Turns record the mode they ran in, so mixed-mode sessions stay legible
1443 after the fact (#6321).
1444 - Shell spawning refuses NUL bytes in command and cwd before spawn, and
1445 sub-agent runs fall back loudly past credentialless profile provider
1446 pins instead of misrouting silently (#5529, #6318, #6320).
1447 - Children land past a per-step context bound instead of burning
1448 quadratically, and status rows surface live declared-vs-observed writes
1449 (#6189, #6194).
1450 - Queued Agent Mail can be cancelled before delivery, and the TUI
1451 suspend/resume handshake restores on stop and rebuilds on continue
1452 (#6176, #6169).
1453 - MCP connections are supervised: dead servers are probed and reconnected
1454 with transitions reported, and a failed reconnect keeps the last-good
1455 catalog instead of dropping tools (#6187, #6142).
1456 - Web search autodetects Tavily from `TAVILY_API_KEY` (Firecrawl stays the
1457 default), fleet refusals name the alternative, and verification runs on
1458 a bounded Git fetch plus a `merge_tree` verify surface (#6298, #6296).
1459 - Fleet authority projects through one `ChildGrant`, and ModelScope joins
1460 the built-in providers (#5633, #6299).
1461 - Child tool results are capped at capture time, and run
1462 tests/verifiers accept a bounded cwd (#6282, #6294, #6296).
1463
1464 ### Changed
1465 - SearXNG results rank by the score the instance returns rather than by arrival
1466 order. Integers, floats and numeric strings are accepted; anything else,
1467 including NaN and infinity, becomes 0.0, and rows are stable-sorted descending
1468 before the result cap, so equal scores keep instance order. The docs now spell
1469 out the self-hosting requirement: the separate process must expose
1470 `search.formats: [json]` — an HTML-only instance answers 403 — and bind to
1471 loopback or a policy-allowed host, with no default instance discovered.
1472 - The bundled skills move to a new generation. social-media and health leave the
1473 shipped pack (phone-export workflows rather than everyday skills), feedback
1474 moves to `docs/skills/` beside contributor onboarding, and the exact earlier
1475 body is retained so only unmodified shipped skills upgrade — a skill you have
1476 edited is left in place. Google OAuth scopes and client setup, Photos exports,
1477 forgetting limits, Spotify playback and plugin reload guidance were corrected
1478 in the same pass.
1479 - `auto` is a declared default, not a guess about your wording. Reasoning
1480 effort no longer maps request vocabulary to tiers (debug/error to Max, search
1481 to Low) and Auto routing no longer infers cheap-versus-big from phrasing:
1482 both resolve the configured default, with `[auto] cost_saving` as the
1483 explicit opt-in. The same prompt now costs the same thing twice.
1484 - A workflow's shared token budget is opt-in. `[workflow] default_token_budget`
1485 applied a silent 120,000-token cap across a run and all of its children, and
1486 a fan-out died at the limit with no hand-back; the default is now 0, meaning
1487 no shared cap.
1488 - The shipped `deepseek-flash` route speaks the Responses endpoint, and `xhigh`
1489 effort maps to `high` per the vendor's own table.
1490 - Streamed text is paced at a steady rate rather than inheriting the provider's
1491 SSE chunking, so output reveals at a readable beat instead of in bursts.
1492 - Broadening shell access for a conversation now requires an idle conversation
1493 and rejects a stale-workspace check before it commits. Engines advertise a
1494 `thread_shell_consent` capability, so an older Engine reads as unsupported to
1495 a native consent client instead of silently accepting.
1496 - One base prompt now serves every host. `HEADLESS_BASE_PROMPT` was a second
1497 hand-maintained rendering of the same constitution — the drift pattern this
1498 repo forbids by convention — so headless runs compose the same `BASE_PROMPT`
1499 plus language and output layers that interactive runs do, skipping only host
1500 chrome (execution profile, authority recap). Headless and interactive can no
1501 longer disagree about what the agent is.
1502 - `BASE_PROMPT` gains a **Bearing** article, which changes how the agent talks
1503 to you: the user is a peer who gets honesty rather than deference, a blocking
1504 gate is named plainly instead of dressed up as refusal, bad code is called
1505 bad, a crude request is carried out without a lecture, and an apology appears
1506 only when there is something to apologize for — not as punctuation. It also
1507 states that the request is the whole mandate, so the scope law opens with
1508 what is yours to do before it reaches the edge. Every pinned kernel invariant
1509 survives verbatim.
1510 - The ocean reads as animals rather than a mechanism. The school used to
1511 translate as one rigid body — bob phase and tail pose were staggered per
1512 fish, but horizontal position was locked to an exact wedge offset — so each
1513 fish now eases a dot fore and aft of its slot on its own slow period, and the
1514 formation breathes while it travels. Bubble emission and the per-animal
1515 periods are hash-jittered instead of sharing one clock. Amplitude stays an
1516 order of magnitude under the crossing speed, so no fish travels against the
1517 school and `facing == velocity` still holds by construction. The species list
1518 is unchanged.
1519
1520 - Extensions keeps the exact-content plugin review on the panel: confirming
1521 a bundle's digest re-reads the inventory, so the row you just reviewed
1522 reports its new trust state and offers Enable instead of leaving you in
1523 the transcript with a stale "not reviewed" row.
1524 - Underwater motion ticks at the cadence the frame limiter actually draws
1525 (the atmosphere interval while only the water moves, the authored 80 ms
1526 ocean cadence inside the interactive cap while a turn streams), and the
1527 event loop wakes exactly for the next tick instead of on the next idle
1528 poll. Idle water no longer requests frames it cannot draw or quantizes its
1529 cadence to the poll interval; reduced motion, Ghostty, tmux and the
1530 six-second idle settle are unchanged.
1531 - The launcher keeps the Codewhale mark while balancing its layout above the
1532 composer. A single cursor identifies the selected action; MCP faults retain
1533 their warning color even in compact terminals. Recent-session counts now
1534 read correctly for a single message.
1535 - Model and provider settings use quieter selection surfaces, one focused
1536 cursor, clearer missing-key warnings, compact output limits, and less
1537 repetitive credential detail. Plugin actions use plain labels.
1538
1539 - The terminal opens on **Shoreline**, the same palette the GPUI client already
1540 uses: warm charcoal field `#211F23`, a raised plate for panels and the
1541 composer, one blue for action and selection `#90B9FF`, and the whale's ivory
1542 `#F2ECE5` for body text, with 4.5:1 floors on every muted step. The old
1543 saturated navy gradient is not gone — it is a named `underwater` theme, and
1544 after review it is once again what a fresh 0.10.0 install opens on
1545 (`DEFAULT_TUI_THEME`); Shoreline is one `/theme` away. Existing installs keep
1546 whatever theme they have saved (#6222).
1547
1548 - Menu navigation is starting to mean the same thing everywhere. `menu_style`
1549 already single-sourced how a selected row *looks*; what a key *does* was still
1550 reinvented per surface — `h`/`l` in the provider picker against `Left`/`Right`
1551 in the model picker one screen later, `Home`/`End` in one of seven pickers, and
1552 no paging at all in Fleet's detail view. `list_nav`, which already owned the
1553 wrap arithmetic, now owns the vocabulary too: one vertical axis, one
1554 horizontal axis, and two entry points so a picker with a live filter never has
1555 a letter stolen out of its query. Fleet's detail view adopts it first and
1556 gains PageUp/PageDown and Home/End in both its lists (#6290).
1557
1558 - Reviewed plugin bundles are no longer re-hashed four times per MCP dispatch.
1559 `verify_plugin_authority` walks and hashes both the reviewed source and the
1560 runtime snapshot, and four separate authority checks ran per `tools/call` —
1561 eight tree walks. Three of them sat one statement after a
1562 `validate_before_use` on the same source, so `is_ready` re-verified what had
1563 just been verified; readiness and authority are now separate, and only the
1564 callers with no preceding check still pay for both. The tool catalog is built
1565 once per turn instead of twice, which also removes a case where the two
1566 assemblies could disagree if authority drifted between them. The digest is
1567 deliberately **not** cached on `(path, mtime, len)`: the reviewed tree is
1568 user-writable and `utimensat(2)` lets a same-uid process restore an mtime
1569 after an equal-length rewrite, so a stat-keyed cache would serve a pre-tamper
1570 digest (#6209).
1571 - A sub-agent's completion is read from the manager once instead of polled. The
1572 workflow pump re-read it up to fifty times, sleeping 20ms between attempts,
1573 waiting for a terminal status that was already committed — every publisher
1574 commits the status inside the same `&mut self` call that wakes the pump, so
1575 the write guard spans both and the first read always sees it. A child the
1576 manager had no record of cost a full second of head-of-line blocking before
1577 failing; it now fails immediately, and says what actually happened instead of
1578 claiming the child "did not report a terminal status within 1s" (#6211).
1579
1580 - MCP protocol negotiation: every surface advertised the original 2024-11-05
1581 revision and the stdio client required an exact match, so newer servers
1582 could not connect. The server and both clients now advertise 2025-06-18
1583 and negotiate over the supported set (2025-06-18, 2025-03-26, 2024-11-05)
1584 — the server echoes the client's revision when it is supported and answers
1585 with the latest otherwise, the stdio client accepts any supported revision,
1586 and streamable HTTP sends the required `MCP-Protocol-Version` header on
1587 every post-initialize request (#6280, first half).
1588 - Configured MCP servers now connect lazily instead of all at session boot. The
1589 pool owns a `connecting` set marked at spawn and cleared on resolution or
1590 abort, so "connecting" is no longer inferred as enabled-minus-connected. The
1591 boot pass scopes to the eager set — `required` servers plus those covered by
1592 `tools.always_load` / `allowed_tools` — and a turn naming an unstarted server
1593 spawns its connects alongside, under the existing five-second deadline. A
1594 configured-but-unstarted server now reads as configured on every surface
1595 (session-boot rows, Extensions tab, launch card), never as connecting.
1596 `docs/MCP.md` documents the lifecycle (#6033).
1597 - The launch card's MCP problems row runs its own remedy. It already printed
1598 `/mcp login <name>` or `/mcp`; it now joins the shared paint/click/keyboard
1599 ordering, so Up/Down lands on it and Enter or a click types the printed
1600 command into the composer for you to send. Typing beats copying: no clipboard
1601 dependency over SSH, and you see the command before a second Enter runs it
1602 (#6085).
1603
1604 - Computer Use is the only computer-use product in Extensions and
1605 `/mcp recommendations`. Cua is no longer suggested as a parallel
1606 desktop-control MCP; enable the first-party `computer-use` plugin
1607 instead. The bundled plugin is 0.11.2 — macOS beta, with the Windows and
1608 Linux backends experimental and source-only. It carries the per-app consent
1609 ledger, background-by-default control, and a focus lease that refuses rather
1610 than stealing the foreground, alongside `get_app_state`, `focus`/`get_value`
1611 and `stop_computer_control`. Shared-desktop pointer gestures stay gated, and
1612 arbitrary background dragging remains unavailable.
1613 - The bundled first-party catalog pins marketplace revision
1614 `d8640b17f27542e7122c76368724196f92a0af61`, so installing Computer Use from
1615 the Extensions listing fetches the same 0.11.2 source the binary already
1616 carries.
1617 - Materializing is not enabling: the built-in bundle is written under
1618 `$CODEWHALE_HOME/builtin-plugins` on first run but stays `NeverReviewed`,
1619 so Computer Use is never switched on without an explicit capability review.
1620
1621 ### Removed
1622
1623 - The host no longer parses prose into goals. Ten phrasings and a clause
1624 allow-list ("make it your /goal to …") were turned into durable goals before
1625 the provider call; prose now reaches the model, which calls `create_goal` when
1626 a goal is useful. The deterministic path — a leading `/goals <objective>` — is
1627 unchanged.
1628
1629 ### Fixed
1630 - A thinking fold is an absolute choice again. The stored bit was relative to the
1631 display preference (`folded ^ !(verbose || thinking_default_expanded)`), so
1632 every recorded choice flipped meaning the moment a preference changed: turning
1633 `thinking_default_expanded` on closed a block the reader had explicitly
1634 expanded (#5847). An explicit tri-state intent now records Expanded or
1635 Collapsed outright, and the absence of an entry means untouched, so the
1636 preference baseline decides that cell's default. Space still toggles, and an
1637 untouched cell still follows `verbose || thinking_default_expanded`.
1638 - A terminal byte-stream cursor past the head is clamped instead of echoed back.
1639 `read_since` returned a future cursor as `next_cursor`, so a client that
1640 continued from it skipped every byte the stream produced before reaching that
1641 position — permanently. The start position now clamps to `total`: a future
1642 cursor reads nothing, is not a gap, and hands back the head.
1643 - Language-server startup is bounded and a failed transport now terminates. The
1644 client waits for successful initialization before sending notifications,
1645 drains stderr without buffering it, bounds request queueing and replies, caps
1646 protocol frames, and fails pending requests when the child transport dies.
1647 - Input no longer freezes for the rest of a turn when the engine's 32-slot op
1648 mailbox is full. The remaining input-path sends no longer await: droppable ops
1649 whose rejection is reported and retryable use `try_send` (CancelSubAgent,
1650 PreviewOutboundRequest, bang shell input, PurgeContext, and the single-op
1651 settings updates), ops that must land once the UI changed reserve first, and
1652 `ChangeMode` publishes its live authority even on a full channel. Must-deliver
1653 ordered transitions still await, and say why at `EngineHandle::send` (#6150).
1654 - The pet's whale is one body again. The same authored point set is checked in
1655 three copies plus four fixtures, and the Rust and TypeScript cores disagreed
1656 on particle positions from frame 0 while agreeing on every channel and
1657 constant — so the v1 fixtures had never matched what Rust produced and the
1658 conformance job had never passed. The bodies and the fixtures are reconciled
1659 and that check now runs green.
1660 - The context meter and the auto-compact gate share one honest estimator. The
1661 status bar inflated `ctx %` by about half and disagreed with the gate, so
1662 "ctx 82%" could sit beside a `/compact` that refused to run; displayed
1663 percentages now read materially lower because they are correct (#6297).
1664 - A steer the engine never accepted is queued for the next turn instead of
1665 being shown as held and then silently dropped with no turn and no answer
1666 (#6297).
1667 - Every `reqwest` client routes through `codewhale_release::tls`. A bare
1668 `Client::builder()` panics under rustls with no installed provider; 17 call
1669 sites were swept.
1670 - The bundled OpenAI-compatible hosts have their `/provider` rows back.
1671 Retiring the `ProviderSetupTemplate` layer moved SenseNova, Baseten, Groq,
1672 Cerebras, DashScope and Command Code into `provider_descriptors.json` and
1673 then wired that file to nothing, so six vendors silently lost their picker
1674 rows; AICraft never had one. Each descriptor is a row again, built through
1675 the same named-custom-provider builder a configured host uses, so endpoint,
1676 bootstrap model and "missing `<ENV>`" reporting all come from one place. A
1677 descriptor whose id or alias already names a `[providers.*]` entry is
1678 dropped, so a configured row stays the only one. These rows are an
1679 invitation, not a route: they are not `is_configured`, and only the form's
1680 submit writes anything (#6289).
1681 - A StepFun Step Plan subscription reaches its own catalog. A subscriber's
1682 `base_url` is `https://api.stepfun.ai/step_plan/v1`, but only the
1683 pay-as-you-go `/v1` host was recognised as official, so the Step Plan host
1684 read as a custom endpoint, the catalog was withheld, and the picker showed
1685 `0 bundled` and a guessed context window for a route whose console
1686 advertises `step-5-preview` at 1M context. The model was in the seed the
1687 whole time. All four StepFun hosts — global (.ai) and China (.com), each
1688 with a `/v1` and a `/step_plan/v1` surface — are now recognised; a host
1689 StepFun does not own stays custom and keyless, since this predicate also
1690 scopes credentials.
1691 - The send cue stopped strobing while you type. `[↵]` flickered between dim
1692 `[·]` and bold blue once per character at an ordinary typing pace. The cue
1693 was not lying — Enter really does insert a newline during the ~120 ms
1694 paste-safety window, which every keystroke re-armed — but that window only
1695 exists for terminals that deliver a paste as a burst of ordinary keystrokes.
1696 Ghostty, iTerm2, WezTerm, Windows Terminal and Terminal.app now skip the
1697 heuristic from the first keystroke instead of waiting for proof by paste.
1698 - Shift+Tab sets the permission posture in Plan. Tab cycles the mode and
1699 Shift+Tab cycles Ask/Auto-Review/Full Access, but Plan refused the second
1700 one outright, so the key silently did nothing there and the two axes read as
1701 welded together. Plan's read-only guarantee comes from the mode, not the
1702 posture — `authority` maps `(Plan, _, Bypass)` to `SandboxPolicy::ReadOnly`
1703 and `tool_catalog` gates every write tool on `mode != Plan` — so the cycle
1704 now moves the durable Act/Operate baseline while Plan's live policy stays
1705 `Suggest`, and a toast says the posture lands when the mode leaves Plan.
1706 - A steer delivered mid-turn now clears its pending card. The transcript
1707 showed the message and the model answered it, while the "sending into this
1708 turn" card still listed it as pending: `turn_loop` commits a steer trimmed,
1709 but the UI handed the engine the untrimmed text and kept that same copy for
1710 matching, so a composer newline made the two differ by whitespace alone and
1711 the steer was never promoted to a transcript cell. The text is trimmed once
1712 at the source that feeds both, so they are the same string by construction;
1713 the match stays an exact `==`.
1714
1715 - A Xiaomi MiMo key no longer fails verification with another vendor's 401.
1716 The legacy top-level `base_url` is a DeepSeek field, and a route without an
1717 endpoint of its own inherited it — so a config carrying
1718 `base_url = "https://api.deepseek.com"` made that host the MiMo route's
1719 endpoint. The custom-endpoint guard correctly withheld the MiMo credential
1720 from a host the route does not own, and the setup wizard's probe, which
1721 bypassed the guard, sent the key as `api-key:` — a header DeepSeek ignores.
1722 The result was `HTTP 401 Unauthorized: Authentication Fails (governor)`,
1723 DeepSeek's *unauthenticated* 401, shown to someone who believed they were
1724 testing their own key. Every layer that reads the root now inherits it only
1725 when the URL belongs to that provider's own official endpoint family;
1726 DeepSeek, which owns the field, is unchanged, and any other host is still
1727 expressible on `[providers.xiaomi_mimo] base_url`. Key verification
1728 failures now also name the endpoint that was probed, so a wrong endpoint
1729 reads as a wrong endpoint instead of a bad key.
1730 - The Extensions panel can act on the rows it shows. Every plugin now carries
1731 its on/off switch — Space, or `e` — including one that has never been
1732 reviewed: `/plugin enable` already routes an unreviewed bundle into the
1733 exact-capability review and only flips the switch once you confirm the
1734 digest, so withholding the control bought no safety and left the shipped
1735 `computer-use` bundle reading `disabled` with nothing that could enable it.
1736 - The panel stopped saying "untrusted". A bundle that is waiting on its
1737 capability review now reads `needs review` — `off · needs review` when the
1738 switch is off too — and its detail line says what Codewhale is withholding
1739 and which key ends the wait, instead of restating an internal pair of
1740 booleans. Enter's verb on that row is `review`, not `inspect`.
1741 - MCP servers say where they live, and mutations write there. Each row is
1742 labelled `global`, `project`, or `plugin: <name>`. Enabling, disabling or
1743 removing a workspace-scoped server previously edited the user's global file
1744 and failed with "MCP server '<name>' not found" on a row the panel had just
1745 offered; the write now lands in the file that declares the server, and a
1746 plugin-contributed server says it is switched off by disabling its plugin.
1747 - The permanent "Plugins · Problems: N" footer chip is gone. It could not be
1748 acted on from the footer, and its count and the Plugins tab disagreed by
1749 construction — the chip counted bundles waiting on a review while the tab's
1750 Problems group lists only registry-level diagnostics, so the rows behind the
1751 number were never the rows you found. A bundle waiting on a review is a row
1752 with an action, and `/plugins` states it per bundle next to the key that
1753 resolves it.
1754 - The Extensions marketplace no longer advertises what it cannot install.
1755 Browser Use and the sandbox runtime were pinned rows whose only possible
1756 action was `unavailable`; they are removed, along with the browser-driver
1757 and sandbox-runtime component vocabulary that existed solely to describe
1758 them.
1759
1760 - Configuration parsing keeps the parsed base config boxed, so loading a
1761 profile no longer carries the full `Config` by value through the
1762 deserializer and overflows a default 2 MiB test-thread stack; the
1763 runtime-store binding test that also overflowed is split into phases and
1764 pinned to that budget so CI's larger stack cannot mask a regression
1765 ([#6362](https://github.com/codewhale-hq/Codewhale/issues/6362)).
1766 - Stopping a turn revokes its pending approvals. A late approval cannot resume
1767 the cancelled action or save an automatic approval for later turns.
1768 - Expanding and collapsing selected reasoning now matches its rendered state
1769 when verbose mode and the default-expansion preference are both enabled.
1770
1771 - Branch navigation preserves sibling histories, stable entry IDs and timestamps
1772 through autosave, resume and forks, and synchronizes the selected branch into
1773 the live engine. Thanks to @7jrxt42BxFZo4iAnN4CX for the report (#6367).
1774 - Compaction now writes local diagnostic records for completed passes and
1775 automatic refusals. `codewhale metrics` reports them with summarizer token
1776 usage; text-mode exec retains its session after attempting compaction.
1777 Historical artifacts are not backfilled. Thanks to @7jrxt42BxFZo4iAnN4CX
1778 for identifying the missing producer (#6368).
1779 - The opening workbench retains the canonical Codewhale mark in a responsive
1780 header while keeping recent-session titles full-width and actions clickable.
1781 - `serve --acp` no longer ignores the approval posture. The ACP adapter
1782 hardcoded `ApprovalMode::Suggest`, so `--yolo` (and any configured
1783 `approval_policy`) never reached admission: every mutating tool parked
1784 behind a permission request no unattended client answers, and sessions
1785 executed zero tools. Posture now derives from server config — `--yolo`
1786 pre-approves prompts and flows into the sandbox policy — while hard blocks
1787 (safety floor, repo law, reviewer consult) and the Plan read-only guardrail
1788 stay intact (#6337).
1789 - Plain agent spawns could not resolve. `built_in_members()` seeded both
1790 `general` and `worker`, and the role parse boundary migrates `worker` to
1791 `general`, so both canonicalized to the same role — and `role:general`, the
1792 selector the roster advertises for the default posture, matched two members
1793 and raised `Ambiguous` every time, permanently. The duplicate built-in is
1794 gone. The legacy name still resolves: `general`, `member:general`,
1795 `role:general` and `default` all land on the `worker` posture through the
1796 identity selector rather than through a second member, which is what allowed
1797 the duplicate to be removed (#6244).
1798 - Clicking a `path:line` in tool output no longer spawns `$EDITOR` detached
1799 while the TUI still owns the terminal, and no longer spawns one editor per
1800 matching line. The launch goes through the single terminal-handoff path, and
1801 a click is one request to open one file (#6235).
1802 - A write-scope contention refusal now names a remedy that works. The `agent`
1803 tool's description claimed `release` was "the remediation a write-scope
1804 contention refusal names"; the refusal did not name it, and pointing back at
1805 it would have been worse, because `release` only clears claims whose owner is
1806 no longer running while a contention refusal names a live one. The refusal
1807 itself now says to wait for that owner to settle or cancel it (#6272).
1808 - The session picker no longer refuses a saved session whose Runtime store
1809 exists but holds nothing. A force-quit leaves the store on disk, ownerless
1810 and empty, and the switch path refused it because recovery only covered a
1811 *missing* store. A switch now also adopts a store that is provably empty
1812 (every work directory, plus the event sequence that remembers pruned
1813 appends) *and* provably unheld (the process-owner lock, which a live
1814 manager holds from open to close), with no automation pinned to its
1815 execution scope — and the save gate treats that shape as abandonable too,
1816 so the repaired binding persists. The first fix was reverted on a race
1817 (emptiness without liveness); this reland checks the lock first (#6207).
1818 - Double-tap Enter now sends every queued follow-up into the running turn,
1819 oldest first. The second Enter used to steer only the most recent message
1820 and leave older ones queued; a failed steer restores the failed message
1821 plus everything unattempted in original order, so nothing is lost or
1822 reordered.
1823 - Only the most recently sent prompt carries the elevated-surface background
1824 now; every older prompt renders on the bare ground. The fill used to sit
1825 behind every user row (striping), then behind none; newest-only keeps the
1826 eye on the turn in play. Sending a new prompt moves the highlight and
1827 un-highlights its predecessor.
1828 - Diff rows tint whole: added/deleted line numbers now share the row's green
1829 / red background instead of sitting bare next to a painted body. Context
1830 rows stay on the bare ground.
1831 - MCP connections are supervised now: a background task notices a dead
1832 server within one sweep, reconnects on the existing backoff ladder, and
1833 reports each transition, so Extensions rows flip with liveness instead
1834 of parking on stale-ready or a silent [reconnect]. Five consecutive
1835 failures park the server with a notice naming `/mcp retry`; an explicit
1836 retry or a fresh connection resumes watching. Tool calls also retry
1837 once across a dead pipe/socket (not just stale sessions), and a
1838 reconnect that fails reports both errors instead of swallowing the
1839 original (#6187; `list_changed` catalog refresh stays open).
1840
1841 - A steer the engine never delivered is no longer reported as sent. The runtime
1842 API persisted the steer item as already-`Completed` and emitted
1843 `turn.steered` + `item.completed` the moment the text entered the engine's
1844 mailbox — before the engine decided anything. The engine discards a steer
1845 whose turn has moved on, and an interrupted or failed turn drops whatever it
1846 had queued, so a GUI could show "Guidance sent", clear the composer, and lose
1847 the user's words. The engine now returns a verdict for every steer on every
1848 exit path, the item settles `completed` or `canceled` to match, a dropped
1849 steer emits `turn.steer_dropped` and answers `409` so a client can resend,
1850 and `steer_count` counts steers the model actually received (#6276).
1851 - `<recommended_plugins>` suggestions stop nagging: a plugin id is now
1852 injected at most once per engine lifetime, and a plugin whose name a
1853 loaded skill already covers is never suggested — the local skill owns
1854 the domain, so the nudge was noise. Dismissals still apply, and the
1855 fragment stays append-only on the user turn (#6274).
1856 - A canceled automation run now settles with a transcript receipt that names
1857 the cancellation (by request, cancel timeout, or shutdown) instead of
1858 vanishing from the live band silently. The receipt wears attention ink and
1859 never lights the failure demand; the run record keeps the cancellation
1860 reason as its error detail. (#6162)
1861 - A failed workflow run no longer settles silently: its terminal failure
1862 raises a sticky error toast naming the cause (dispatch, schema, or script
1863 errors), alongside the existing panel state (#5528).
1864 - MCP OAuth re-login now forces the provider's consent screen: logout only
1865 clears the local token, so without a prompt the provider silently
1866 re-granted the same account/workspace and a re-login could never change
1867 it. `/mcp logout` and `codewhale mcp logout` also say plainly that they
1868 clear local credentials only (#6040).
1869 - Session retention no longer deletes transcripts once the store reaches the
1870 cap: the oldest active session is archived — still openable from the
1871 picker's archived view — instead of being unlinked, and archived records
1872 sit outside the cap until they are pruned (#6136).
1873 - Empty auto-created "New Session" stubs are capped separately (the ten
1874 newest are kept) and can no longer occupy a real transcript's slot in the
1875 session cap (#6137).
1876 - A failed resume or session load is now a durable transcript error instead
1877 of a status line the next footer update replaces, so a resume that cannot
1878 restore its target no longer looks like a silent new session (#6138).
1879 - Compaction no longer retains a tool result whose tool call was summarized
1880 away: an older turn that mixes text with a tool result keeps its text and
1881 drops the orphaned result blocks, which providers reject outright (#6119).
1882 - Automation runs that need a tool approval no longer die as silent
1883 idle-timeout cancels: a pending approval suspends the idle watchdog for its
1884 decision window, and an unanswered window settles the run Failed with the
1885 recorded reason instead of a silent Canceled (#6118).
1886 - `/mcp` no longer freezes the console while a turn is running: the panel
1887 opens immediately from the last known MCP snapshot with a receipt naming
1888 the wait, and live-pool mutations say their refresh is deferred instead of
1889 parking the UI event loop behind the running turn (#6159).
1890 - MCP OAuth login no longer fails with "Authorization server response missing
1891 required issuer" against servers that implement RFC 9207, such as
1892 Cloudflare's `mcp.cloudflare.com`. The local callback listener now keeps the
1893 `iss` parameter from the redirect and hands it to the token exchange so the
1894 callback binds to the discovered issuer; servers that do not send `iss`
1895 keep working unchanged. (#6157)
1896
1897 ## [0.9.13] - 2026-09-13
1898
1899 Codewhale v0.9.13 addresses integrity issues in 0.9.12:
1900 multiline paste is one paste again, truncated tool arguments can no longer execute, strict
1901 ACP clients connect again, concurrent instances stop destroying each
1902 other's queued text, and the Computer Use bundle includes plugin 0.3.1
1903 with an accessibility-first pointer that no longer steals focus. DeepSeek V4.1 Flash
1904 (`deepseek-flash`) is the default DeepSeek model, reasoning-capable routes
1905 keep reasoning out of the answer even when a model id carries no version
1906 number, and `/mcp reload` no longer freezes the interface while servers
1907 reconnect. The Codewhale pet arrives with `/pet`: a full-screen habitat that
1908 shows what the Engine is doing and reveals the answer when it is done.
1909
1910 ### Added
1911
1912 - `/pet` turns the terminal over to the Codewhale pet. `/pet on` (or bare
1913 `/pet`) gives the habitat the whole content viewport now and on every
1914 accepted turn, reveals the actual answer or error when the turn completes,
1915 and Escape returns to the composer without cancelling anything. `/pet off`
1916 closes the view and stops automatic entry while the durable companion keeps
1917 the pet alive; `/pet appearance|window|source|sound|export|status` address
1918 the shared companion. The pet no longer lives in the workbar: the Watch
1919 panel and `/workbar watch …` are gone (#6109, #6110).
1920 - Codewhale Computer Use 0.3.1 ships as its own notarized Mac app. Download
1921 the disk image from [codewhale.net/computer-use](https://codewhale.net/computer-use)
1922 or the [v0.3.1 release](https://github.com/Hmbown/codewhale-cu-plugin/releases/tag/v0.3.1)
1923 (`Codewhale-Computer-Use-0.3.1-macos-universal.dmg`, drag into
1924 Applications; the ZIP stays for the in-app updater). The bundled plugin and
1925 the first-party marketplace pin the same 0.3.1 sources, so the app, the
1926 `computer-use` plugin and `/mcp` see one implementation.
1927
1928 ### Fixed
1929
1930 - The website's Computer Use download page resolves its state without the
1931 GitHub API (using `GITHUB_TOKEN` only when bound), and every page regenerates
1932 on the Worker again: the Open Graph image route read brand SVGs at import
1933 time, which the Workers runtime cannot do, so codewhale.net had been serving
1934 its build-time snapshot.
1935 - Operate can run structured workflows directly, with named phases, model
1936 assignments from Fleet, prerequisite results and shared budgets. Independent
1937 steps run together; dependent work waits for its required results and gates.
1938 Detached runs return their outcome to the owning conversation, and headless
1939 sessions stay alive between phases until the final handback is consumed.
1940 - Computer Use 0.3.1: mouse actions no longer steal focus or reclaim the
1941 foreground when the user switches apps mid-action; background typing,
1942 scrolling and selection use semantic input, and screenshots stay scoped to
1943 the targeted app. The bundled plugin and the first-party marketplace pin
1944 carry the same 0.3.1 sources. A registered macOS helper stays in charge of
1945 input through its Pause and Stop controls; an unavailable registered helper
1946 produces an error instead of silently bypassing those controls.
1947 - The Fleet editor uses the standard model picker to manage sub-agent model
1948 and thinking assignments. Enter edits the selected row without changing the
1949 running session's model. Unconfigured providers are refused, failed saves
1950 retain the previous assignment, and a changed or removed team file must be
1951 reopened before a pick can overwrite it.
1952 - The provider catalog includes Baseten and the other compatible-provider
1953 templates as selectable rows, opening their existing prefilled setup forms.
1954 DeepSeek routes with clock-based pricing show the current peak or off-peak
1955 tier beside session cost, with translated labels.
1956 - Extensions, teams, workflows and automations support mouse-wheel scrolling.
1957 Plugin and MCP rows have keyboard enable/disable controls and two-step
1958 removal; MCP OAuth can retry with narrower scopes after a scope rejection.
1959 - Healthy sub-agents continue after an ordinary parent reply. Headless runs
1960 keep the existing Engine alive for child results within the run deadline.
1961 Explicit cancellation remains authoritative when result queues are full or
1962 a completion starts a followup turn.
1963 - Sub-agent followup supports multiple targets and all parked children, keeps
1964 old IDs connected to their current continuation, and saves continuation
1965 identity before starting work. Repeated followup does not fork duplicates.
1966 - Sub-agents validate declared output files and distinguish real edit claims
1967 from file citations and unrelated workspace changes. Disjoint file claims
1968 can run together; overlapping writers receive the actual conflict and remedies.
1969 Explicit read-only shell analysis requires an enforcing native sandbox and
1970 refuses execution when that protection is unavailable.
1971 - Delegation depth stays absolute through saved profiles, nested workers and
1972 continuations. Per-call token, step and time limits narrow inherited limits;
1973 continuation retains ancestor usage and deadlines. Workers reserve room for
1974 one tools-disabled partial report inside those limits, then run the declared-
1975 output checks. Missing usage or unavailable reporting room produces an
1976 explicit fallback; partial work is never marked complete.
1977 - Agent rosters and detail pages have bounded output, visible continuation and
1978 descendant relationships, and usable handles for full diagnostic evidence.
1979 Completion receipts include measured worker and descendant token usage,
1980 count each continuation once, and distinguish unreported usage from zero.
1981 - Localization and native helper builds resolve the active checkout when the
1982 build script runs, so a shared Cargo target keeps working after a worktree
1983 moves or is removed.
1984 - Selecting a saved agent profile that is malformed, unreadable or duplicated
1985 now fails before any child request, including when its name matches a
1986 built-in role; the parent's default route is never substituted silently.
1987 `agent(action: "roster")` lists affected profile identities and paths, Fleet
1988 run creation performs the same check, and `docs/SUBAGENTS.md` documents the
1989 valid personal profile format with `[permissions]` (#6117, thanks
1990 @Gabriel-Degret).
1991 - Interactive startup no longer mistakes worker scheduling delays for an
1992 unresponsive terminal. Terminal ownership checks and shutdown cleanup remain
1993 enforced (#5929).
1994 - Interrupted conversations whose saved runtime store is missing recover into a
1995 fresh scope without restoring old tasks or approvals. Stale session saves
1996 cannot resurrect the broken binding (#6102).
1997 - Permission checks distinguish literal heredoc data from executable commands,
1998 including substitutions and shell stdin (#6098).
1999 - Automatic compaction runs quietly from live context pressure, preserving the
2000 current task and recent tool exchanges while keeping the system/tool prefix
2001 stable. Original history and the handoff are saved before context replacement;
2002 failed or canceled compaction retains the conversation (#5620, #6047).
2003 - Custom and gateway providers can override context limits for each exact model,
2004 so switching models also switches the meter and compaction budget (#6108).
2005 - Plugin suggestions explain their matching term and remember explicit dismissals
2006 across restarts. Generic words and repository-host domains no longer trigger
2007 unrelated installation prompts (#6031).
2008 - Plugin trust and automation deletion have keyboard and mouse confirmation
2009 controls bound to the exact reviewed content; users can still copy the command
2010 and changed content requires a fresh review (#6039).
2011 - The model-facing MCP start tool can reconnect an existing configured name after
2012 login without changing its credential key or restarting healthy siblings (#6030).
2013 A decreasing token-expiry countdown no longer makes a revoked credential look
2014 like a new login from another session.
2015 - Gemini setup uses the official endpoint's supported reasoning-effort field,
2016 avoiding the rejected top-level Google thinking object. Gemini 2.5 and 3 keep
2017 their supported effort ranges; signed tool history still survives reasoning
2018 changes and restart (#6018, thanks @vmakarov-uk).
2019 - Missed automation occurrences coalesce without overlapping a running job;
2020 restart reconciles durable receipts without replaying accepted work. Damaged
2021 neighboring records are isolated while preserving their original bytes.
2022 - The bundled first-party marketplace lists the actual plugin bundles and uses
2023 the existing install, review, trust and update paths. A read-only connection
2024 check verifies catalog and skill mirrors on changes and weekly. Already present
2025 bundles lead to their local review and management controls; catalog installs
2026 refuse name collisions before downloading, without overwriting or granting trust.
2027 - Windows deny checks preserve native path separators while retaining the
2028 conservative POSIX scan for shell wrappers and substitutions.
2029 - The config example agrees with the telemetry disclosure: usage analytics are
2030 optional and enabled by default; local diagnostics do not require telemetry (#6011).
2031
2032 - Sub-agents enforce the session's typed shell and file deny rules, including
2033 Full Access, delegated edits, and policy updates after a child starts (#6097).
2034 - Live permission edits reach running engine clones atomically. Deny rules
2035 support token wildcards and Windows command spellings while keeping POSIX
2036 arguments literal (#6054, thanks @h3c-hexin and @asto18089).
2037 - Tool-result images use the existing typed inline path and are fully decoded
2038 under size and allocation limits before admission or provider projection.
2039 Invalid images keep a visible omission receipt alongside the text result
2040 (adapted from #6053, thanks @h3c-hexin and @asto18089).
2041
2042 - A lone `y`, `Y`, or `r` remains composer input after selecting transcript
2043 text. Clicking the composer releases transcript and dock focus.
2044 - The Agents register updates from live worker events while the parent is
2045 busy, including when the register opened before the workers spawned.
2046 - Ghostty no longer shows a second graphical whale over the launch mark.
2047 The selected model stays visible before the first message; unused session
2048 metrics stay quiet. Scheduled counts open `/automation` directly.
2049 - Marketplace installation accepts compatible Claude plugin bundles and roots
2050 their relative sources outside `.claude-plugin`; unsupported components fail
2051 explicitly. Native trust and enablement review still applies.
2052 - Config table and nested reads work consistently and redact credentials.
2053 Unsupported dotted writes fail without changing the file, and `config doctor`
2054 no longer labels runtime settings as never applied (#6083).
2055
2056 - Esc during a worker fanout keeps the parent stopped when cancelled workers
2057 finish. Their receipts remain available for the next explicit user turn.
2058 - Undo preserves messages even when older state lacks a timestamp. Session
2059 journal entries retain their append-time stamps when saved again.
2060 - Extension actions refresh in place, and inspection output uses the text
2061 pager. The empty launch shell hides unused metrics and keeps recovery hints
2062 readable when several MCP servers need attention.
2063 - The large-output router defaults to bounded spillover; adaptive routing
2064 remains opt-in through `CODEWHALE_ADAPTIVE_OUTPUT_ROUTING=1`.
2065 - Direct composer paste (`Ctrl-V`) preserves rich clipboard headings, lists,
2066 links, tables and code as Markdown, with plain-text fallback. Whole-answer
2067 copy preserves authored Markdown without terminal wrapping; settings fields
2068 still paste literal text.
2069 - The embedded Computer Use bundle includes the marketplace's JPEG capture
2070 and bounded-payload fixes, so new built-in installations receive them too.
2071 - A provider's missing-`thought_signature` HTTP 400 now explains how to recover:
2072 use the built-in Google provider and start a new session, or verify the
2073 gateway's signature handling. Working gateways are not blocked by a broader
2074 preflight check (#6048, #6081, thanks @nightt5879).
2075 - Chinese documentation links resolve to the contributor guide and Windows
2076 screenshots from their translated paths (#6080, thanks @c020627).
2077 - GLM-5.3 reasoning controls follow the forced-thinking contract on Z.ai and
2078 BigModel routes, including low effort when a prior configuration requested
2079 thinking off (#6051, thanks @h3c-hexin and @asto18089).
2080 - Finance calls respect the session network policy, and model-facing shell,
2081 verifier, notification and Fleet guidance matches executable contracts
2082 (#6052, thanks @h3c-hexin and @asto18089).
2083 - The sandbox-elevation prompt shows every option, `Abort` included. The card
2084 was a fixed 22 rows centred on the frame; inside its border and padding that
2085 left at most 18 usable rows against 20 to 23 rows of content, with no scroll
2086 rail and no truncation hint. The safe exit — the one choice that grants
2087 nothing — was painted past the bottom edge at every terminal size. The card
2088 is measured from its content now and reserves the option rows before the
2089 denial detail, which is what shortens; below roughly 60x24 the per-option
2090 descriptions shed and every choice keeps its row. Option hitboxes were also
2091 counted in unwrapped source lines, so a description that wrapped put every
2092 hitbox below it out of step and a click committed a different choice than the
2093 one under the pointer.
2094 - `d` in the Hotbar setup modal asks before it clears every slot. It persisted
2095 `hotbar = []` on the first keystroke, in a view that takes bare letters as its
2096 filter — the destructive key and the search key were the same press. It arms a
2097 confirmation that owns every key until answered, and the prompt takes the
2098 intro's place in the header so it cannot be the line that falls off a
2099 five-row budget.
2100 - Failure red means failure again. The metrics line painted the context reading
2101 in the error colour from 80 %, while the posture bar one row above called the
2102 identical threshold Attention; the workflow panel painted a `Waiting` row like
2103 a crashed one, though its own `is_running` counts Waiting as healthy; and the
2104 work surface spent `error_fg` on to-dos that were merely waiting, blocked or
2105 stale, and on the routine approach to auto-compaction. `WorkTone` has a real
2106 `Failure` variant now, and a guard test holds the reservation across every
2107 selectable theme rather than the default alone.
2108 - The command palette runs the row you highlighted. `refilter` clamped the
2109 selection index but never re-anchored it, and every keystroke re-sorts the
2110 list, so refining a query could move the highlight to an unrelated entry that
2111 Enter then ran. Long labels also overran their column and pushed the
2112 description off the card, because the padding never truncated and the capacity
2113 was measured against the popup rather than the content area.
2114 - The work surface's first `Down` reaches the first row. Nothing is selected
2115 when the dock opens, and that resolved to "row 0 is selected", so the first
2116 press moved to row 1 and row 0 could not be reached by pressing Down at all.
2117 - Auto-compact could not fire mid-turn. The gate read `max(last billed
2118 prompt, /4 estimate of the whole list)`, so as soon as the estimator
2119 undercounted the full list below the last bill, every tool result appended
2120 after that prompt was invisible to it, and a long turn could exhaust the
2121 context window with nothing compacted. It now reads live tokens — the
2122 billed prompt plus the growth since it, watermarked when the parent usage
2123 is recorded — and is still evaluated at the pre-request boundary after
2124 tools complete, never mid-tool-call.
2125 - Esc or Ctrl+C during a compaction that is serving an in-flight turn now
2126 stops the turn. It previously cancelled only the compaction pass, so the
2127 turn resumed against the context that had just failed to shrink. A manual
2128 `/compact` with no request in flight still cancels only the pass.
2129 - The `request_user_input` dialog is a bottom-anchored sheet instead of a
2130 centered 22-row overlay. It leaves the transcript visible above it, grows
2131 with its content, and scrolls internally so the highlighted option and the
2132 custom response being typed stay on screen at 141x38 and 80x24. Left arrow
2133 or `h` goes back to the previous question; Esc still cancels the whole
2134 request. PageUp/PageDown, Home/End and modified arrows now review the
2135 transcript while the sheet stays open; the mouse wheel scrolls the surface
2136 under the pointer. Wheel browsing preserves the answer, and option navigation
2137 or typing restores the focused content to view. The transcript viewport ends
2138 above question and approval prompts, so End keeps the newest rows visible.
2139 Documented in GUIDE.md and KEYBINDINGS.md (#6045).
2140 - `/mcp reload` no longer freezes the interface. The reload was awaiting the
2141 whole reconnect batch on the TUI event loop; it now joins the same
2142 supervised background pass the session boot uses, the status chip counts
2143 the batch down live, and the finished receipt arrives as an event. With
2144 23 configured servers (11 live, 10 awaiting auth, 2 failing) the first
2145 echoed keystroke after a reload lands in ~5 s instead of ~42 s (#5974).
2146 - The posture bar no longer states the same duration twice on a first turn
2147 (#6041).
2148 - Reasoning-capable models whose id carries no version substring
2149 (`deepseek-flash`) keep `reasoning_content` in the thinking block instead
2150 of the answer text. The gate only ever matched the literal `deepseek-v4`
2151 version string, so it now consults the model catalog as well; the older
2152 literal arms remain for the V4 aliases they were written for (#6044).
2153 - `codewhale model resolve` accepts a provider's declared default even when
2154 its registry row is missing — `deepseek-flash` failed resolution against
2155 the provider that declares it as default — and a test now resolves every
2156 provider's `DEFAULT_*_MODEL` for its own provider (#6043).
2157 - A configured `default_text_model` is honored when a new thread's route is
2158 resolved. That path consulted only the provider's catalog default, so a
2159 config naming one model silently created threads on another, and the
2160 unset default disagreed with the shipped one; the active provider's
2161 configured default now wins, matching `provider_default_model`, and both
2162 unset defaults name `deepseek-flash` (#6043).
2163 - Markdown `_italic_` requires both delimiters to be flanking per CommonMark,
2164 so math subscripts no longer italicize the prose between them
2165 (`[t_, b_p]. Actually — hold on, do we even tile all the way from t_?`
2166 rendered 60 characters italic) (#6042).
2167 - An MCP server configured for OAuth that answers 401 before its first login
2168 now points at `/mcp login <name>` in the failure hint instead of a bearer
2169 token that does not exist (#6030).
2170 - Cancelling a foreground shell wait stops its owned process group even when
2171 the tool future is dropped. Explicitly backgrounded jobs retain their
2172 ownership. Interrupted tool receipts distinguish work that started from
2173 calls skipped before execution, and returned tool failures remain errors in
2174 the next model request.
2175 - Saved Fleet model identifiers retain exact spelling through selection,
2176 role pins, and roster changes, so changing one saved model does not modify
2177 another identifier that differs only in letter case.
2178 - Chat wrapping reserves its scrollbar gutter consistently, keeping long
2179 identifiers readable when the viewport changes.
2180 - The Engine keeps large send-message futures off the event loop's stack,
2181 preventing stack exhaustion when a restored session starts a provider turn.
2182 - New, imported, and live session titles skip runtime handoffs and use the
2183 first real user prompt. Explicitly renamed titles retain priority
2184 (#6012, thanks @SparkofSpike).
2185 - UI dispatch acceptance now precedes Engine execution, so a delayed acceptance
2186 callback cannot overwrite a turn that has already started or completed.
2187 Cancelling before acceptance preserves the prompt and leaves the next
2188 dispatch usable.
2189 - Bottom-chrome effort is omitted when the route cannot prove an effective
2190 tier; `/status` retains the full explanation. Cost remains visible when
2191 known, and `cost: unknown` remains on metered routes lacking a reading (#5950).
2192
2193 - Pasting multiline text is one paste again. 0.9.12 gated the
2194 paste-burst heuristic off whenever bracketed paste was *requested*, but
2195 a terminal can accept `EnableBracketedPaste` and still deliver a paste
2196 as individual keystrokes — on those terminals (observed on Windows 11)
2197 every pasted line was submitted as its own message. The heuristic is
2198 again armed whenever `tui.paste_burst_detection` is on, and the
2199 existing `bracketed_paste_seen` guard still disarms it for the rest of
2200 the session once a real `Event::Paste` arrives, so fast typing on
2201 terminals with working bracketed paste is unaffected (#5981, thanks
2202 @nsfoxer).
2203 - `serve --acp` no longer breaks strict JetBrains clients: the
2204 `initialize` response advertised `sessionCapabilities.list` as a
2205 boolean and carried an undefined nested `load` capability; it now
2206 sends `{"list": {}}` with no `load` key, per the ACP schema (#5969,
2207 reported by @Lujc0523).
2208 - Concurrent Codewhale instances no longer destroy each other's queued,
2209 unsent text. The offline input queue was one global file that boot
2210 cleared on session-id mismatch, so a second instance deleted the
2211 first's parked messages. Queues are now keyed per session (mirroring
2212 per-session checkpoints), an existing global file is adopted by its
2213 owning session rather than discarded, and the adoption race between
2214 two instances of the same session tolerates the loser's cleanup.
2215 - A tool call truncated at the provider's output limit can no longer be
2216 repaired into valid JSON and executed: repairs that had to synthesize
2217 structure (append or discard closers) are routed to the existing
2218 malformed-arguments path so the model is asked to re-issue — including
2219 when the stream is cut before the closing content-block event (#5986).
2220 - `codewhale metrics` reads Codewhale's own receipts again: the
2221 deepseek-home fallback resolved `$HOME/.deepseek` unconditionally, so
2222 the rollup reported all zeros from a directory nothing has written
2223 since 2024. The Codewhale audit log is primary, with a checked legacy
2224 fallback.
2225 - The goal-continuation loop's promised stall bound actually bounds
2226 stalls now, and undeclared fleet role names fail closed to read-only
2227 `explore` in both fleet drivers instead of resolving to write-capable
2228 customs in one and not the other.
2229 - `allow_insecure_http = true` under a `[providers.<name>]` table works
2230 again. 0.9.12 tightened plain-HTTP base URL handling in a way that
2231 silently dropped the per-provider key, leaving the process-wide env
2232 var as the only opt-in — LAN llama.cpp and internal-gateway users
2233 had to export `CODEWHALE_ALLOW_INSECURE_HTTP=1` to connect at all.
2234 The key is honored again (parsed, settable and unsettable through
2235 `codewhale config set providers.<name>.allow_insecure_http`, and
2236 listed in the custom-provider field hint), it stays distinct from
2237 `insecure_skip_tls_verify`, and the refusal message now leads with
2238 the config key. Loopback hosts remain auto-allowed and telemetry
2239 endpoint validation deliberately still consults neither switch
2240 (#5991, thanks @Gabriel-Degret).
2241 - A Fleet task that selects a roster member with `worker.agent_profile` now
2242 runs with that member's posture. The launch-time resolver only consulted the
2243 resolved member when the legacy `worker.role` label was absent, so a task
2244 labelled `manager` that selected `member:reviewer` ran as a write-capable
2245 manager instead of a reviewer and was never leased. The member's canonical
2246 slot now wins whenever one resolved; the label remains the posture only when
2247 no member resolved at all. To keep the fix from widening authority in the
2248 mirror case (a read-only label on a write-capable member), a spec whose
2249 `worker.role` names a different posture than the selected member's role is
2250 rejected at run creation with a message naming both postures; casing and
2251 legacy aliases of the member's own role are still accepted (#5945, thanks
2252 @gaord).
2253 - A queued message keeps one transcript entry from queue through steer to
2254 dispatch. It no longer reads as delivered while it is still pending, and the
2255 second Enter the strip prompts for no longer paints a duplicate bubble.
2256 - The Tasks rail panel no longer swallows the first keystroke of typed input:
2257 bare `y`/`Y` yank only when the work surface holds keyboard focus, so a
2258 message that starts with "yes" stays intact (#2000).
2259 - `wait` results reach the parent intact. The parent-context summarizer
2260 projected every `agent` tool result through the sub-agent snapshot renderer,
2261 which replaced a wait envelope's `settled`, `still_running`, `timed_out`,
2262 `waited_ms`, and `note` with `unknown (agent) status=unknown`. Only
2263 snapshot-shaped results are summarized now.
2264 - A sub-agent's final summary uses the same adaptive tool-result budget as
2265 every other tool result (`tool_result_max_bytes`, 12k floor, 2 MiB ceiling)
2266 instead of a hardcoded 12k/4k/4k copy that cut a 12,001-character report to
2267 8,000.
2268 - The metrics line no longer carries a permanent `/help` hint. The route still
2269 appears until its binding has been used and then retires with the other
2270 footer hints, so the row stays quiet once help is learned.
2271 - `request_user_input`'s description names when asking is the right move
2272 (ambiguous scope, an irreversible or expensive choice, a missing preference)
2273 and when it is not, so the model stops guessing at discoverable facts.
2274 - `config.example.toml` states the real search default (keyless Firecrawl, not
2275 DuckDuckGo) and the preferred `CODEWHALE_SEARCH_*` environment names.
2276 - Startup type-ahead is preserved whole, and a slash command interrupted by
2277 startup keystrokes is no longer re-read as prose and sent to the model
2278 (#5925).
2279 - The model picker renders a large catalog without lag and supports per-column
2280 sort and mouse selection (#5975).
2281 - Session metrics report effective request throughput from provider receipts
2282 instead of a live estimate divided by the whole turn, and cost stays honest
2283 when a route has no price reading (#5976, #5977).
2284 - An offline-queue submit delivered as late raw keystrokes no longer wedges the
2285 composer behind stacked session notices (#5999).
2286 - Fleet setup with a model filter that matches nothing renders a hint instead
2287 of panicking (#5953), and shortlist enrollment plus authoritative role pins
2288 are honored on dispatch (#5915).
2289 - A mid-turn MCP catalog refresh keeps the tool pool deferred and the active
2290 set narrow (#5939).
2291 - Computer Use on macOS verifies application activation before sending
2292 keystrokes and guards input by the frontmost app (#5927).
2293 - Onboarding tests isolate `CODEWHALE_HOME`, so a fixture provider can no
2294 longer leak into the real setup state (#5932).
2295 - Snapshot availability is retained with one warning per session, and a
2296 diverged engine session id is a visible notice rather than a log line
2297 (#5930).
2298
2299 ### Changed
2300
2301 - How long Codewhale waits for a human is configurable. `[tools]
2302 user_input_timeout_seconds` governs the wait for an approval decision or a
2303 `request_user_input` answer; it was a hardcoded 300 seconds, which silently
2304 cancelled the work of anyone who stepped away mid-task. An explicit `0`
2305 waits indefinitely, the value is clamped to 24 hours, and omitting the key
2306 keeps the previous 300-second default. Documented in
2307 `docs/CONFIGURATION.md` ([#6003](https://github.com/codewhale-hq/Codewhale/issues/6003)).
2308 - `docs/PROVIDERS.md` lists every beginner setup template, not the four it
2309 happened to mention when the page was written. Baseten, Groq, Cerebras and
2310 Command Code have shipped as supported OpenAI-compatible hosts for a while
2311 and appeared nowhere in the provider documentation, which reads from outside
2312 exactly like not supporting them. The page now carries the full table —
2313 host, default model and key env for each — and states the rule it follows:
2314 a plain Chat Completions backend is a template row, while `ProviderKind` is
2315 reserved for distinct wires. A test now fails if a shipped template is
2316 missing from that page.
2317 - Reasoning capability for the Kimi coding routes and the qwen3.x Model Studio
2318 deep-thinking ids is catalog data now rather than hardcoded match arms, and
2319 `model_reasoning_capability` reports a model nothing knows about as unknown
2320 instead of silently not reasoning-capable. `model_supports_reasoning` keeps
2321 its `bool` shape for existing callers, where unknown still reads as false.
2322 The ids that have no cited source yet keep their literal arms (#6032).
2323 - The website uses Shannon Sans with versioned local font assets and retained
2324 serif, monospace, and language fallbacks. Terminal fonts are unchanged.
2325 - `codewhale metrics` reports recorded model requests and stream recovery
2326 separately from provider-reported token usage, with coverage for missing
2327 and duplicate receipts. Status messages and cumulative snapshots do not
2328 add requests or count tokens again.
2329 - Runtime turn receipts retain the Engine's terminal model-request, stream-retry,
2330 and resume counters separately from displayed status and provider-reported
2331 usage. These counters do not count HTTP retries inside a provider client or
2332 establish provider billing.
2333 - Initial tool definitions no longer repeat shell interpreter guidance and
2334 agent lifecycle/scope instructions in multiple description fields. Parameter
2335 schemas, approval rules and dispatch behavior are preserved. This reduces
2336 prompt schema size; it does not establish a provider billing regression.
2337
2338 - The built-in Computer Use plugin bundle is refreshed to the standalone
2339 plugin's 0.2.1 runtime (vendored from `Hmbown/codewhale-cu-plugin`
2340 at `724ad258`): the native macOS accessibility backend with an
2341 a11y-first pointer strategy (covered points are refused, previews are
2342 drawn), the permission-owning desktop-app socket transport, remote
2343 computers over ssh and HarmonyOS HDC with contained temp handling,
2344 truthful win32 PowerShell failure reporting, and the shared
2345 allow-listed request handler for the app socket and ssh agent.
2346 The bundle retains the hardening port from
2347 [standalone plugin PR #12](https://github.com/Hmbown/codewhale-cu-plugin/pull/12).
2348 Single left clicks on macOS element targets now revalidate and press
2349 the observed element directly, without substituting a point hit-test
2350 or raw-pointer fallback. Explicit event clicks retain the app-ownership
2351 guard; a sent press still requires visual verification. Background mode
2352 permits application-bound keys and accessibility actions while refusing
2353 shared-pointer gestures; it does not provide an isolated desktop. The
2354 embed list gained the five new runtime files, and a consistency test
2355 now pins the embed list to the vendored tree so the bundle cannot rot
2356 silently again. Because the bundle's content hash changes, Computer
2357 Use deactivates and asks for a fresh review after upgrading — that is
2358 the designed fail-closed path for a desktop-driving plugin. The
2359 current macOS source candidate also embeds the compiled native helper,
2360 so its bundled server can run directly without a separate Computer Use
2361 app or a compiler on the user's machine. Accessibility and Screen
2362 Recording permissions belong to the hosting app or terminal and remain
2363 user-controlled. The CLI's Computer Use server requires Node.js 20 or newer. These are source
2364 candidate changes; they do not establish published-package or platform
2365 qualification. See the [included plugin guide](crates/tui/plugins/computer-use/README.md)
2366 for platform requirements and limitations.
2367 - `/statusline` drives the bottom chrome again. Since the 0.9.12 shell
2368 redesign the posture bar and the metrics line were built independently of
2369 `tui.status_items`, so every toggle in the picker except the balance fetch
2370 was decoration. Each remaining item now shows or hides exactly one thing:
2371 `model`, `context_percent`, `cost`, `balance`, `cache`, `tokens` and
2372 `session_metrics` are metrics-line segments, and `mode` is the posture
2373 bar's plan/act/operate chip. The `status`, `agents`, `reasoning_replay`,
2374 `prefix_stability`, `git_branch`, `last_tool_elapsed` and `rate_limit`
2375 items drove nothing and are retired; an existing `config.toml` still loads
2376 and those keys are ignored (#5950, #5962).
2377 - The context reading is back on screen at every fullness. 0.9.12 painted
2378 `ctx NN%` only from 50% up, which left most of a session with no context
2379 signal at all; it now paints from 0% and keeps its warning colour from 80%
2380 up (#5950).
2381 - A child agent parked because its parent's turn ended is shown as `parked`
2382 in the Agents panel, the sidebar and Agent Details, with `resume_from` /
2383 `cancel` as the recovery, instead of wearing the same "waiting for input"
2384 label as a child that asked a question. Parked work sorts below live and
2385 answerable work and no longer inflates the `blocked` chip; the receipts
2386 roster and the wire `state` gain `parked` (#5906, #5921).
2387
2388 - `codewhale account keys set|remove|list` no longer carry a hardcoded
2389 eight-provider list. Provider ids come from the control plane's public
2390 catalog (`GET /api/model-providers`), are validated locally against
2391 `^[a-z0-9][a-z0-9-]{0,63}$` before they reach a URL path, and `list` shows
2392 every catalog provider with its label and stored-key state. `--from-local`
2393 maps a catalog row onto the local runtime provider through the catalog's own
2394 `runtimeProvider` field, so a newly supported provider needs no CLI release.
2395
2396 - `/mcp` lists the servers that need a login first, as their own
2397 `Needs login` group above `Needs attention`, and opens with the cursor
2398 already on the first such row so the Enter the screen advertises runs
2399 `/mcp login <server>` straight away; translated in all 15 packs. A
2400 snapshot test pins the footer shape the chip landed with (`MCP · N
2401 connected · N ◆ auth required · N failed`) so an expired login never
2402 regresses into the failed count (#5926).
2403
2404 ### Fixed
2405
2406 - Five of the load-flaky tests tracked in #5929 no longer depend on shared
2407 state or live local daemons. Background-hook capture tests wait for the
2408 capture file to hold bytes instead of merely existing (the shell's `>`
2409 redirection creates the file empty before `cat` writes, which read as
2410 `valid JSON: EOF` under load); the session-picker acceptance test drives
2411 the real picker over a private store instead of a process-global
2412 `CODEWHALE_HOME` redirect that concurrent tests could observe mid-flight;
2413 the DeepSeek-Anthropic translate test holds the test env barrier so its
2414 request-time and assertion-time `max_tokens` reads cannot straddle another
2415 test's `CODEWHALE_MAX_OUTPUT_TOKENS` override; the unit-test binary no
2416 longer probes a real local Ollama daemon (`127.0.0.1:11434`) from the
2417 fire-and-forget provider catalog refresh, whose merged tags could flip
2418 another test's live-snapshot assertions; and the tmux clipboard test's
2419 attach/OSC 52 wait bounds tolerate a fully loaded machine (3s -> 30s)
2420 without changing what they verify (#5929).
2421 - The posture bar states how long the session has been working and how long
2422 the current turn has run, distinguishing actively working from waiting on
2423 a tool, a sub-agent or the operator; the 0.9.12 shell had dropped the overall
2424 working-time indicator from the place a glancing user checks (#5914).
2425 - A background runtime turn whose own store record could not be read, parsed
2426 or written (`Failed to read turn …`, `Failed to read item …`) was only a log
2427 line. The runtime now publishes a `runtime.store_failure` event naming the
2428 file, the root cause and the next action (move the file aside, or check free
2429 space and permissions); the TUI shows it as a warning toast and a transcript
2430 line, the task timeline records it, and the runtime API streams it. A turn
2431 whose own record is unreadable or unwritable is reported as terminal, so its
2432 task fails at once instead of idling out (#5931).
2433
2434 - An MCP token refresh that fails to parse the provider's answer keeps the
2435 endpoint's receipt — status line, content type, and a 200-byte excerpt
2436 with every credential-shaped value (`access_token`, `refresh_token`,
2437 `client_secret`, `id_token`, bearer schemes) masked before the cut —
2438 instead of rmcp's bare `Failed to parse server response`, so a provider
2439 outage answering an HTML 502 reads differently from a parser defect, and
2440 the login remedy stays named (#5926; remedy wording landed in #5959).
2441
2442 ### Added
2443
2444 - `POST /v1/threads/{id}/file-revert` restores exactly one file from the
2445 exact `tool:`/`pre-turn:` snapshot the client selected, checking the
2446 reviewed file hash before and after the mandatory safety snapshot. Literal
2447 file names, regular files only, thread trust and active-turn admission are
2448 enforced, and `patch-undo` no longer forks a conversation whose file
2449 rollback failed (#6111, thanks @gaord; engine half of
2450 HengQuWorld/CodeWhale-VSCode#3).
2451 - Authenticated Runtime API workspace file suggestions reuse TUI `@file`
2452 matching and discovery, with bounded queries/results and workspace-contained
2453 relative paths only (`GET /v1/workspace/files/search`, #6095, #6120, thanks @wuisabel-gif; reported by @LmeSzinc). Shared discovery
2454 now honors disabled symlink following for AI-tool directory scan roots too.
2455 - Serply is available as an opt-in `[search]` provider for the Web tool
2456 (`provider = "serply"`, key from `[search] api_key` or `SERPLY_API_KEY`).
2457 Preflight fails closed without a key; Firecrawl remains the default and
2458 existing configurations are unchanged (#6100, thanks @googio).
2459 - Linux terminals: finishing a transcript or composer mouse selection copies
2460 the text to the PRIMARY selection without touching the regular clipboard, and
2461 middle-click inside the composer pastes PRIMARY at the pointer without
2462 submitting. Native X11 and Wayland data control are used through one bounded
2463 background worker; SSH sessions without a forwarded display keep their
2464 terminal's own selection behavior (#6116, thanks @dmt4).
2465 - `codewhale sessions export <id-or-unique-prefix>` saves a `.tar.xz` archive
2466 with the durable record, portable session container, manifest and artifacts.
2467 Prefix exports preserve unfinished tool calls; confined reads reject linked
2468 artifact roots, and existing outputs require `--force`. Archives retain
2469 unredacted content; `/load` opens the extracted record without installing
2470 extracted artifacts (#6056, thanks @h3c-hexin and @asto18089).
2471
2472 - `deepseek-flash` (DeepSeek V4.1 Flash: 1M-token context,
2473 reasoning and tool calls) joins the catalog as DeepSeek's declared default,
2474 and the offline catalog seed matches it; the DeepSeek Pro listing no longer
2475 overstates the published price (#6025).
2476 - DeepSeek's September 11 reversal is reflected in provider notices and cost
2477 estimates: V4 Pro remains available after September 14 at Pro rates. Explicit
2478 Pro selections remain unchanged; Flash remains the default (#6025, thanks @ronohara).
2479 - Native plugin authoring guides now cover English and Chinese. The explicit
2480 offline converter supports selected portable Skills and static Streamable
2481 HTTP MCP declarations from OpenCode and DSH. Unsupported executable hooks,
2482 automatic OAuth and policy-bearing configurations are refused; generated
2483 bundles still require native installation, review and trust. Legacy SSE
2484 fallback is not reproduced (#5827, requested by @giancarlocp).
2485
2486 - Signed cloud model facts can refresh provider capabilities and prices while
2487 preserving verified cached data when a refresh fails. A dispatched request
2488 keeps its selected price snapshot so later catalog updates cannot change its
2489 recorded cost (#5752).
2490 - Saved sessions preserve exact provider routes. Auxiliary model calls settle
2491 their usage once against the route and price snapshot that executed them,
2492 including recovery, rather than resolving a new price at completion
2493 (#5726, #5848).
2494 - `[tui].posture_bar` and `[tui].metrics_line` accept `full`, `compact`, or
2495 `hidden`, also available through `/config`. Compact preserves the existing
2496 rows' essential fields; hidden returns their space to the transcript (#5973).
2497 - Optional model-bound tool-output redaction opt-out, with two explicit startup
2498 confirmations and a receipt bound to the readable config contents and
2499 modification time. Unconfirmed requests keep masking enabled; routing and
2500 stored goal summaries remain redacted (#5982, thanks @SparkofSpike).
2501
2502 - The `rusty-alloc` cargo feature on `codewhale-tui` and `codewhale-cli`
2503 opts the binaries into the `rusty_alloc` global allocator (the mimalloc
2504 v2.4.5 architecture remade in pure Rust — no C compiler or build script
2505 on that path) instead of the default mimalloc. It is off by default and
2506 the default build is unchanged; build with
2507 `cargo build -p codewhale-tui --features rusty-alloc` (#5872).
2508 - The `/theme` picker now discovers valid user-authored `custom:<name>`
2509 overlays, previews their colors, highlights the active overlay, and preserves
2510 it when the picker is opened and committed without navigation (#5901).
2511 - Compaction has two standing knobs next to `[context]` in config.toml:
2512 `[compaction] summary_instructions` (appended to the summarizer prompt on
2513 every manual and automatic pass; `/compact <focus>` still composes after
2514 it) and `[compaction] retained_user_message_tokens` (default 20 000,
2515 clamped 2 000..=200 000) for the verbatim user-message budget. Both are
2516 absent by default and absent means the pre-existing behavior. The
2517 `/compact` receipt names the effective budget and whether operator
2518 instructions applied (#5956).
2519 - `[tools] user_input_max_questions` (default 6, 1..=10) and
2520 `[tools] user_input_max_options` (default 4, 2..=10) replace the hard-coded
2521 `request_user_input` limits; the validator, the tool schema and its
2522 description read one value, spawned children inherit the parent's ceilings,
2523 and a rejected payload names the ceiling it hit and the key to raise (#5949).
2524 - The slash menu shows a command's usage line and its subcommands as soon as
2525 a space is typed after the verb, filtered by what follows, so Tab completes
2526 `/workspace wor` to `/workspace worktrees`; `/help` states the focused
2527 command's usage in its detail slot (#5952).
2528 - The three `/fleet` views (roster, live workers, saved teams) are one
2529 back-navigable stack: `Esc` in workers or saved teams returns to the roster
2530 with its cursor intact and still closes the window at the root or on direct
2531 entry; the `Esc` footer hint says `back` or `close` accordingly (#5954).
2532 - `/fleet` presents its prioritized core (`members`, `setup`, `teams`,
2533 `workers`, `help`); every other verb stays dispatchable and is documented
2534 under explicit groups in `/fleet help`. The roster no longer shows the
2535 untouched built-in `general` alias next to `worker` (#5888).
2536 - `codewhale` provider: account-backed model access over the provider keys a
2537 customer connected to their Codewhale account. One base URL
2538 (`https://api.codewhale.net/v1`, overridable with `CODEWHALE_API_BASE`;
2539 HTTPS required except on loopback), one `cwc_key_…` account API key with the
2540 `models:infer` scope (`CODEWHALE_API_KEY`), and a per-model wire chosen from
2541 the account's authenticated `GET /v1/models`: ids are `provider/model` and
2542 each row states `chat-completions` (`/v1/chat/completions`) or
2543 `anthropic-messages` (`/v1/messages`). Both protocols authenticate with
2544 `Authorization: Bearer`, never `x-api-key`. The key is read from
2545 `CODEWHALE_API_KEY`, the `codewhale` secret-store slot, or
2546 `[providers.codewhale] api_key` / `api_key_env`, and a missing key fails
2547 before any request instead of dispatching unauthenticated. If the catalog
2548 cannot be fetched the route falls back to three bootstrap ids and says so.
2549 - `codewhale account api-keys create --scope` now accepts `models:infer`
2550 alongside `account:read` and `agent:run`, and an omitted `--scope` sends all
2551 three explicitly. `--use` saves the new secret as this machine's local
2552 `codewhale` provider credential in the same secret store `codewhale auth`
2553 uses; nothing is uploaded.
2554 - `Git` grows a `commit_plan` action: a propose-only planner that splits the
2555 working tree into ordered atomic commits (#3999). It groups whole files —
2556 lock files ride with their manifest, tests ride with the source they name —
2557 orders the groups so a commit that defines a symbol lands before the commit
2558 that uses it, and refuses the whole plan when that dependency graph has a
2559 cycle. It reads `git diff HEAD` plus the untracked-file list and writes
2560 nothing: no `git add -N`, no `git apply --cached`, no `git commit`, so
2561 staging and committing stay with the ordinary `git add` / `git commit` shell
2562 path where the approval gate already applies. Thanks
2563 [@goransh-walia](https://github.com/goransh-walia) for the original
2564 implementation (PR #5870, fixes #3999).
2565
2566 ### Contributors
2567
2568 - **[@LmeSzinc](https://github.com/LmeSzinc)** — requested Runtime API access to the TUI's fuzzy file search ([#6095](https://github.com/codewhale-hq/Codewhale/issues/6095)).
2569 - **[@googio](https://github.com/googio)** — added the Serply web-search provider ([#6100](https://github.com/codewhale-hq/Codewhale/pull/6100)).
2570 - **[@dmt4](https://github.com/dmt4)** — requested Linux copy-on-select and middle-click paste ([#6116](https://github.com/codewhale-hq/Codewhale/issues/6116)).
2571 - **[@Gabriel-Degret](https://github.com/Gabriel-Degret)** — reported that saved agent profiles were silently ignored when spawning sub-agents ([#6117](https://github.com/codewhale-hq/Codewhale/issues/6117)).
2572 - @nightt5879 — Gemini signature recovery guidance and transport regressions (#6081).
2573 - @c020627 — Chinese documentation link repairs (#6080).
2574 - @h3c-hexin and @asto18089 — GLM-5.3 reasoning controls and tool-gating/documentation fixes (#6051, #6052).
2575 - @Hmbown — dependency updates (#6057) and the Gemini signature recovery report (#6048).
2576 - **[@gaord](https://github.com/gaord)** — contributed the file-scoped restore endpoint and the trust-gated whole-tree rollback ([#6111](https://github.com/codewhale-hq/Codewhale/pull/6111)), Fleet schema inspection, role precedence and worker deliverable receipts, and linked the community VS Code frontend ([#5944](https://github.com/codewhale-hq/Codewhale/pull/5944), [#5945](https://github.com/codewhale-hq/Codewhale/pull/5945), [#5946](https://github.com/codewhale-hq/Codewhale/pull/5946), [#5992](https://github.com/codewhale-hq/Codewhale/pull/5992)).
2577 - **[@goransh-walia](https://github.com/goransh-walia)** — contributed the propose-only commit-planning rework ([#5870](https://github.com/codewhale-hq/Codewhale/pull/5870)).
2578 - **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — documented turn budgets and goal configuration, and reported gaps in command discovery, Fleet navigation, human waits, state hooks, history and provider routing ([#5996](https://github.com/codewhale-hq/Codewhale/pull/5996), [#5952](https://github.com/codewhale-hq/Codewhale/issues/5952), [#5954](https://github.com/codewhale-hq/Codewhale/issues/5954), [#6003](https://github.com/codewhale-hq/Codewhale/issues/6003), [#6004](https://github.com/codewhale-hq/Codewhale/issues/6004), [#6006](https://github.com/codewhale-hq/Codewhale/issues/6006), [#6007](https://github.com/codewhale-hq/Codewhale/issues/6007)).
2579 - **[@SparkofSpike](https://github.com/SparkofSpike)** — contributed two-stage consent for opting out of model-bound credential redaction ([#5982](https://github.com/codewhale-hq/Codewhale/pull/5982)).
2580 - **[@aboimpinto](https://github.com/aboimpinto)** — moved session lifecycle and session-control commands onto shared command contracts ([#5902](https://github.com/codewhale-hq/Codewhale/pull/5902), [#5951](https://github.com/codewhale-hq/Codewhale/pull/5951)).
2581 - **[@EvanProgramming](https://github.com/EvanProgramming)** — reported Windows input and CRLF-write defects, and contributed CRLF preservation and an injectable Windows input runner ([#5908](https://github.com/codewhale-hq/Codewhale/issues/5908), [#5909](https://github.com/codewhale-hq/Codewhale/issues/5909), [#5910](https://github.com/codewhale-hq/Codewhale/pull/5910), [#5911](https://github.com/codewhale-hq/Codewhale/pull/5911), [#5912](https://github.com/codewhale-hq/Codewhale/pull/5912)).
2582 - **[@wuisabel-gif](https://github.com/wuisabel-gif)** — exposed workspace file suggestions through the Runtime API ([#6120](https://github.com/codewhale-hq/Codewhale/pull/6120)) and added custom-theme discovery, preview and selection in the theme picker ([#5907](https://github.com/codewhale-hq/Codewhale/pull/5907)).
2583 - **[@zhuowp](https://github.com/zhuowp)** — matched model-visible shell guidance to the interpreter selected for execution ([#5900](https://github.com/codewhale-hq/Codewhale/pull/5900)).
2584 - **[@nsfoxer](https://github.com/nsfoxer)** — reported the multiline-paste regression and incomplete provider model lists ([#5981](https://github.com/codewhale-hq/Codewhale/issues/5981), [#6009](https://github.com/codewhale-hq/Codewhale/issues/6009)).
2585 - **[@Nefelibata1024](https://github.com/Nefelibata1024)** — confirmed the multiline-paste regression's impact ([#5981](https://github.com/codewhale-hq/Codewhale/issues/5981)).
2586 - **[@Gabriel-Degret](https://github.com/Gabriel-Degret)** — reported the loss of the allow_insecure_http provider setting ([#5991](https://github.com/codewhale-hq/Codewhale/issues/5991)).
2587 - **[@Lujc0523](https://github.com/Lujc0523)** — reported the ACP initialize schema violation affecting strict IDE clients ([#5969](https://github.com/codewhale-hq/Codewhale/issues/5969)).
2588 - **[@mo-vic](https://github.com/mo-vic)** — proposed storing evicted context on disk so it can be retrieved later ([#6008](https://github.com/codewhale-hq/Codewhale/issues/6008)).
2589 - **[@giancarlocp](https://github.com/giancarlocp)** — requested a plugin authoring guide and OpenCode plugin conversion ([#5827](https://github.com/codewhale-hq/Codewhale/discussions/5827)).
2590 - **[@hxfhd](https://github.com/hxfhd)** — supplied a Windows reproduction of a turn stopping before its stated next tool action ([#6010](https://github.com/codewhale-hq/Codewhale/discussions/6010)).
2591
2592 ### Notes
2593
2594 - **DeepSeek V4 Pro continues after September 14.** The vendor reversed its
2595 earlier retirement notice. Codewhale preserves Pro selections and Pro pricing;
2596 `deepseek-flash` remains the default for new direct DeepSeek configurations.
2597 - Upgrading from 0.9.12 with Computer Use trusted and enabled: the
2598 bundle's content hash changes with the 0.2.1 refresh, so the plugin
2599 deactivates and asks for a fresh review — that is the designed
2600 fail-closed path for a desktop-driving plugin. Re-trust it from the
2601 Plugins page.
2602 - The multiline-paste fix restores v9.11 behavior on terminals that
2603 accept `EnableBracketedPaste` but deliver pastes as keystrokes
2604 (reported on Windows 11 / PowerShell). Verified at the input-contract
2605 level and in CI; a manual paste check on a real Windows terminal is
2606 still welcome — please comment on #5981 with your terminal if anything
2607 still misbehaves.
2608
2609 ## [0.9.12] - 2026-09-03
2610
2611 Codewhale v0.9.12 puts computer use in the binary, opens two new routes —
2612 Alibaba Model Studio through the data-driven provider table and Concentrate
2613 as an opt-in BYOK Responses gateway — and adds cloud dispatch plus a
2614 config-gated per-session control socket. The shell is the other half of the
2615 release: a new launch card, the work surface docked under the composer, one
2616 focus owner for Tab, tool cells that carry their own state, and `fleet` as
2617 the public word for the live collective. The complete item-level change
2618 record is retained below the categorized release highlights.
2619
2620 ### Added
2621
2622 - Computer use ships with the binary. The `computer-use` plugin — 38 tools
2623 across macOS, Windows, Linux and HarmonyOS, accessibility-first observation
2624 with pixel fallback, screenshots, zoom, screen recording, and registered
2625 remote computers over ssh and hdc — is embedded in Codewhale and written to
2626 `$CODEWHALE_HOME/builtin-plugins` on first run, so every install channel
2627 carries it. It lists as `builtin · not-reviewed` and stays disabled until
2628 you review and enable it: shipping it is not consenting to it. The
2629 stdlib-Python computer-use server it replaces is gone.
2630 - Alibaba Model Studio joins the data-driven provider table as an
2631 `openai-compatible` descriptor: international compatible-mode endpoint,
2632 `DASHSCOPE_API_KEY` credential, live `/v1/models` discovery. Qwen 3.8
2633 Flash and Qwen 3.8 Max arrive through the catalog authority — never a
2634 hard-coded id.
2635 - Concentrate: first-class opt-in BYOK Responses gateway with live models
2636 discovery and typed SSE streaming (#5725).
2637 - Cloud dispatch: remote runner offloads coding agent tasks to isolated
2638 cloud sandboxes with machine token auth and structured job tracking
2639 (#5701, #5712).
2640 - Per-session control socket: config-gated `[control_socket]` table binds
2641 `<sessions-dir>/<session-id>/control.sock` per running session, exposing
2642 message, interrupt, relaunch, and status JSON-RPC verbs (#5533, #5831).
2643
2644 ### Changed
2645
2646 - **Anonymous usage counting is on by default.** The 0.9.11 release asked
2647 first; 0.9.12 counts the same aggregate version/platform, session, feature
2648 and error totals unless you turn it off, and says so once at first launch
2649 (policy notice version 5, schema 3, `notice_version` replacing
2650 `consent_version`). Every recorded opt-out stays off: a durable
2651 `telemetry = false`, a decline recorded under the old opt-in notice,
2652 unreadable privacy state, and the `CODEWHALE_TELEMETRY=0` / `--telemetry
2653 false` kill switches. Showing the disclosure records only that it was
2654 shown, never an acceptance. `codewhale config set telemetry false` turns
2655 it off and wipes queued counts; `codewhale config set telemetry true`
2656 deliberately re-enables it. Nothing new is collected: no conversations,
2657 code, prompts, files, names, model content, credentials, or IP.
2658
2659 - The launch screen is our own card take: a thin top line
2660 `⑂ branch path`; a centred bordered card with the whale mark,
2661 `Codewhale` + version, one announcement line only when it is true (the
2662 no-model warning, or MCP news), and the menu New worktree / Resume
2663 session / Changelog / Quit with their real chords right-aligned. Enter
2664 runs the highlighted entry, Up/Down move it, and typing goes straight to
2665 the composer. The card dissolves on the first keystroke or command
2666 (≤240 ms, instant under reduced motion) (#5826, #5801, #5815, #5286).
2667 - The work surface sits under the composer by default, keeping history
2668 readable and leaving the stage unencumbered (#5809).
2669 - Skills command shapes: FEAT-022 command shapes and retained-host
2670 validation (#5825, #5829).
2671 - After the card dissolves, the working screen shows `⑂ branch path` with
2672 `⋮ MCP n/m` on the right, the transcript starts with the
2673 `◆ session_start` receipt (naming the configured session-start hooks),
2674 and the composer's bottom rule carries `model (effort) · permission` —
2675 the route's one launch reading. The posture bar and metrics line appear
2676 only once a session exists.
2677 - Vocabulary: `fleet` is the public term and `Pod` is retired from copy —
2678 roster, setup, detail, worker-runtime and managed-API messages now say
2679 Fleet (`/fleet` canonical, `/pod` alias). The workflow wire accepts the
2680 canonical role spellings (general/explore/planner/reviewer/implement/
2681 test/advisor) with the pre-rename ones kept as load-time aliases, and
2682 serializes canonical names.
2683 - The Operate mode-picker hint is shortened to fit 80 columns.
2684
2685 - The footer always shows the permission posture; when only one chip
2686 fits, the permission chip outranks the mode word (#5796).
2687 - Local Ollama: the header names a model only when the local catalog can
2688 serve it, and says `unknown` until it knows. The startup mark, web and
2689 app icon carry the new side-view prompt-eye whale (#5795).
2690 - One focus owner: Tab and Shift+Tab work regardless of what is in the
2691 composer; Alt shortcuts survive mid-draft; Ctrl+Tab no longer cycles the
2692 mode by accident (#5798).
2693 - Tool cells carry their own state: a running, failed or warned tool
2694 reads as such in the transcript itself, with per-entry rail dots and
2695 family-coloured glyphs (#5799).
2696 - Web: docs hub with task search, shared empty/loading/error states, an
2697 offline-to-back-online banner, `/changelog` in every locale, and real
2698 404s with correct metadata (#5743).
2699 - Web: the app's colours come from one file generated from the TUI whale
2700 palette; re-typing a colour by hand fails web CI (#5797).
2701 - Web: a one-way ceiling on `isZh` branching outside the i18n spine —
2702 the count may only go down (#5805).
2703 - An internal agent handoff doc was removed from the public tree and
2704 `.playwright-mcp/` is now ignored (#5800).
2705 - First run paints the composer immediately: the Welcome/language/provider/
2706 trust gates no longer precede the first keystroke. Missing-key and
2707 workspace-trust recovery stay for returning users; language and provider
2708 remain in `/setup`.
2709 - The canonical whale-tile mark propagates beyond web to the exact-raster
2710 surfaces that can carry it (#5738).
2711 - Dead-code sweep: delete proven-unreferenced helpers (unused builders,
2712 wrappers, and leftover identifiers) and drop stale `#[allow(dead_code)]`
2713 where the item is production-called or test-exercised. No runtime behavior
2714 change (#5791, #5587).
2715 - Remote-control recovery gives every fresh pre-dispatch attempt a new lease
2716 generation while preserving that generation across its typed start (#5605).
2717
2718 - Public roster language is Pod. `/pod` is the customer surface; fleet remains
2719 the internal wire, storage, and migration name (#5776).
2720
2721 - Compaction replacement history keeps a bounded last user round (assistant +
2722 tool results) instead of dropping them behind a summary. `/context` names
2723 the compaction path and `/anchor` survival. Failed compact still does not
2724 replace live history (#4394).
2725 - Provider catalogs: compatible hosts (Baseten, Groq, Cerebras, SenseNova,
2726 Command Code) no longer compile a frozen model roster. Descriptors name the
2727 wire, URL, and env; live `GET /v1/models` and a Codewhale-owned catalog
2728 layer are the offering list. Command Code is a catalog/descriptor row, not
2729 a `ProviderKind`. Catalog presence is not an availability, entitlement, or
2730 provider-acceptance claim (#5783).
2731
2732 - Provider selection no longer probes or adopts an external CLI credential on
2733 ordinary picker use. Reuse requires an explicit "Use external CLI credentials"
2734 choice, exact-path confirmation, and Codewhale-owned revoke (#5772).
2735
2736 - TUI: startup no longer presents an approximate ASCII or block-glyph whale as
2737 the product mark. It keeps the direct Tideline prompt while exact-raster
2738 surfaces remain responsible for the canonical asset.
2739
2740 - TUI: the active-session composer paints the same three-cell `[↑]` send
2741 target as Startup and clicks it through the existing Enter submit
2742 dispatcher (#5771). Compact/quiet composers still omit the control.
2743
2744 - TUI/CLI: Pod is the public roster surface. User-facing Fleet wording
2745 moves to Pod; durable receipt keys stay compatible (#5776).
2746
2747 ### Contributors
2748
2749 - **hexin ([@h3c-hexin](https://github.com/h3c-hexin))** — provider-native web
2750 search across four routes (#5682, #5683, #5685, #5687), authoritative
2751 edit-last-turn boundaries (#5621), Kimi Code k3-256k (#5622),
2752 post-compaction input-token reporting (#5623), and preserving the scheduled
2753 model selection in automations (#5650).
2754 - **秋月凉梦 ([@qiuYliangM](https://github.com/qiuYliangM))** — co-authored the
2755 edit-last-turn boundary fix (#5621), Kimi Code k3-256k support (#5622), and
2756 post-compaction input-token reporting (#5623).
2757 - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — live
2758 session token totals (#5624), persisted context-pressure warnings (#5629),
2759 discoverable Fleet roster editing (#5604), the capability-gated cursor
2760 accent (#5599), and `/copy` for the latest completed response (#5692).
2761 - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** —
2762 Windows verbatim-path operands preserved through POSIX word splitting
2763 (#5610), the plugins group moved onto the command shapes (#5657), FEAT-022
2764 skills command shapes with retained-host validation (#5825), and FEAT-020
2765 plugin command shapes re-landed on main (#5865).
2766 - **Alex Musichen ([@musichen](https://github.com/musichen))** — a stable
2767 DeepSeek heading in the configured-view model picker, keeping every official
2768 catalog model for the active provider visible (#5689).
2769 - **[@gaord](https://github.com/gaord)** — the `GET /v1/fleet/profiles`
2770 runtime API endpoint, reusing the FleetManager validation path (#5688).
2771 - **Sh1Zuku ([@SparkofSpike](https://github.com/SparkofSpike))** — corrected
2772 English documentation inaccuracies and the first zh_hans translations for
2773 the Tier-2 docs (#5613).
2774 - **[@M-Maciej](https://github.com/M-Maciej)** — goal continuation cadence
2775 (#5591) and the per-session control socket (#5533, #5831).
2776 - **Serephus ([@serephus](https://github.com/serephus))** — nixpkgs update
2777 (#5669).
2778 - **[@whp233](https://github.com/whp233)** — `wire = responses|anthropic` for
2779 openai-compatible custom routes and opencode-zen muse-spark (#5716, landed
2780 as #5719).
2781 - **Gabriel Degret ([@Gabriel-Degret](https://github.com/Gabriel-Degret))** —
2782 found the reasoning-only retry gap and built the first fix; landed as the
2783 `[reasoning_only]` retry ceiling with a request-scoped nudge (#5867).
2784 - **[@huangxianzhan](https://github.com/huangxianzhan)** — the
2785 `x-opencode-session` header for OpenCode Go and Zen gateways (#5868).
2786 - **[@zhuowp](https://github.com/zhuowp)** — task origin preserved in job
2787 snapshots (#5869).
2788 - **AdityaG ([@AdityaVG13](https://github.com/AdityaVG13))** — a ten-commit
2789 performance pass: a zero-copy LaTeX fast path for streaming render,
2790 single-pass token accounting on the per-turn pressure paths, memoized
2791 provider resolution in the catalog cutline, parsing the bundled and
2792 on-disk models.dev catalogs once per process (interactive boot -70%),
2793 adaptive poll cadence for foreground shell completion, and worker caps
2794 across the read-only diagnostic family.
2795 - **Nightt ([@nightt5879](https://github.com/nightt5879))** — isolated remote
2796 recovery lease generations (#5790).
2797 - **[@yiheng-kkk](https://github.com/yiheng-kkk)** — replaced stale todo
2798 transcript snapshots so a rewritten todo list renders its current tasks
2799 (#5871, #5873).
2800 - **[@Lfanxing](https://github.com/Lfanxing)** — Moonshot routes now degrade
2801 incompatible tool definitions per request instead of failing the turn.
2802 - **WissssleyL ([@Lstarsky0](https://github.com/Lstarsky0))** — moved
2803 `docs/subagents` and `docs/mcp` onto the dictionary spine (#5337), with the
2804 metaTitle probe that keeps them there.
2805
2806 Reports and reproductions that shaped this release:
2807
2808 - **[@slowly247](https://github.com/slowly247)** — reported the Ollama input
2809 budget collapsing to 1,024 tokens on 32K local models (#5820).
2810 - **[@ronohara](https://github.com/ronohara)** — reported the engine stopping
2811 after recoverable network errors, with the reproduction that pinned the
2812 discarded approval (#5769), and surfaced DeepSeek's model-service notices and the subsequent reversal
2813 retaining V4 Pro (#6025).
2814 - **[@Lujc0523](https://github.com/Lujc0523)** — asked for ACP session
2815 configuration of mode and model (#5863).
2816 - **[@senka9h](https://github.com/senka9h)** — reported that `serve --acp`
2817 lacked `session/list` and `session/load` (#5864).
2818
2819 ### Added
2820
2821 - Native ChatGPT sign-in for the `openai-codex` route: `codewhale auth
2822 chatgpt` opens a browser PKCE flow and stores refreshable tokens in
2823 Codewhale-owned credentials — no Codex CLI install required.
2824 `/auth chatgpt-revoke` clears them off the event loop (#5784, #5778).
2825 - MCP servers and plugins can be connected self-serve from the session: a
2826 unified auth flow with rotation-safe token handling, a spoken authorization
2827 URL, and catalog refresh when stored credentials stop working (#5747).
2828 - `/operate` reads match the landed CWC `OperateRecord` contract: fetching an
2829 absent record returns a truthful not-found view instead of a fabricated
2830 operation, and an empty evidence path is rejected rather than resolving to
2831 the workspace directory (#5703).
2832 - TUI: scheduled automations project into the top strip
2833 (`⏱ N scheduled · M running`, compact `⏱ N·M`) with typed
2834 `HistoryCell::Automation` receipts when a run this session watched settle.
2835 `/automation` acknowledges failures. The merged footer does not carry the
2836 work fact (#5748).
2837 - The app-server can listen on a unix domain socket and advertise a
2838 `daemon/attach` handshake, so a local client can attach to an already-running
2839 engine instead of spawning its own. The socket is created with
2840 owner-only permissions and stale sockets are reclaimed on start. Non-unix
2841 hosts return a typed unsupported-platform refusal; the Windows named-pipe
2842 endpoint is named but not yet implemented (#5749).
2843 - The engine's internal `Op`/`Event` types and the wire protocol's `Op`/
2844 `EventMsg` now carry a compile-enforced twin for every variant: adding an
2845 engine variant without a protocol counterpart fails the build instead of
2846 drifting silently. Internal durability work — no user-visible surface
2847 change yet (#5751).
2848 - Machine tokens: with `CODEWHALE_API_KEY` set, the CLI authenticates as the
2849 Codewhale account with no local session file and no browser — the CI
2850 authentication path, with a typed token shape and redaction (#5721).
2851 - Compaction publishes a structured survival contract for session-tree
2852 journal entry types (`crates/tui/src/compaction/SURVIVAL_CONTRACT.md`) and
2853 fails closed when the last user round, tool results, `/anchor` text, or
2854 checkpoint receipt would vanish (#4394, #5782).
2855 - Internal: `codewhale-config` gains `RouteAuthoritySnapshot`, one immutable
2856 authority that owns a compiled provider catalog together with the route
2857 resolver projected from it, so a picker, a readiness view, and an execution
2858 path can no longer resolve against different catalog snapshots without a
2859 type-level signal. Resolution still goes through the sole resolver; the
2860 returned receipt distinguishes an exact catalog row, a custom-endpoint route
2861 whose provider facts are deliberately not reused, and an allowed
2862 pass-through route with no catalog row. All state is secret-free. No call
2863 site changed and no user-visible behaviour changed yet (#5766).
2864
2865 - Computer session records now count only time a provider actually accepted the
2866 session as active, at per-second granularity. Idle, queued, stopped, and
2867 teardown time are excluded, and a session whose allocation does not match a
2868 standard profile is refused rather than recorded approximately. Covered by
2869 hermetic fixtures; no live provider call and no deploy (#5781).
2870
2871 - Website: the public site moves to the Tideline deep-ocean design language
2872 (dark by default with an opt-in light documentation sheet, palette grounded
2873 in the TUI's WHALE_* tokens) and the new whale brand mark across the favicon,
2874 app icons, web manifest, nav wordmark, and social card (#5573).
2875
2876 - Add `codewhale dispatch` / `/dispatch` so a local session can propose a
2877 Codewhale cloud agent against an explicit `github`, `cnb`, or `gitee` remote.
2878 Confirmation is required; missing credentials fail closed; cloud jobs share
2879 the existing `/jobs` surface as `kind=cloud`. See
2880 [DAYTONA_CLOUD_DISPATCH.md](docs/DAYTONA_CLOUD_DISPATCH.md).
2881 - `/login` reports the Codewhale account session and provider-key next
2882 steps. The internal cloud-agent credential is not user surface: there is
2883 no `auth set-slot`/`auth clear-slot` command, no hint, and no completion
2884 entry for it — signing in with `codewhale login` is the only door.
2885 - Add the Tideline component family from the ratatui translation spec
2886 (#5698's screens, riding the #5699 work-strip layout): hero startup
2887 surface with quick actions and option strip, notifications inbox, merged
2888 footer band, pod ledger, receipt
2889 stream, theme list with motion toggles, live preview, settings rail,
2890 and the left rail — each a standalone render module pinned by 28 new
2891 byte-exact golden buffers. Frame wiring follows the Tideline acceptance
2892 gate; `NO_COLOR` is now honored by palette depth detection.
2893 - Route Contract Phase 1: `RouteResolver` is the runtime path for
2894 `resolve_runtime_options`; `codewhale providers export --json` ships the
2895 owned descriptor catalog; CLI `--provider` accepts any catalog route id
2896 (the closed `ProviderArg` enum is deleted). Catalog layers are
2897 bundled → models.dev → provider `/v1/models` → config.toml → user, with
2898 policy DENY last and never overridden.
2899 - Add provider-native web search for documented Xiaomi MiMo 2.5 Pro and 2.5
2900 chat routes while keeping neighboring models and custom gateways fail-closed.
2901 - Add structured provider-native web search for exact Z.AI global and Zhipu
2902 China general API routes, using each site's documented search engine value.
2903 Existing `open.bigmodel.cn` configurations now share Z.AI's official model
2904 namespace and credential scope; unknown model IDs still pass through.
2905 - Add provider-native web search for documented Qwen models on ModelStudio
2906 Token Plan's Responses Harness, without enabling Coding Plan or Anthropic
2907 routes.
2908 - Added `/copy` to place the latest completed assistant response on the
2909 clipboard without copying tools, system messages, hidden reasoning, or
2910 active partial output (#5668).
2911 - Add provider-native web search for documented DeepSeek V4 routes through the
2912 Responses API, with fail-closed capability gating for compatible custom
2913 endpoints.
2914 - Add provider-native search for exact Moonshot K3 Formula, legacy K2.6
2915 built-in search, and Kimi Code membership `/search` routes. Treat the exact
2916 Moonshot China endpoint as a first-party direct route.
2917 - Z.ai `GLM-5.3-Flash` and OpenRouter `z-ai/glm-5.3-flash` are first-class
2918 picker rows (`/model GLM-5.3-Flash`). Flash is the faster/explore sibling
2919 of `GLM-5.3`; the Z.ai default stays `GLM-5.3`. List price is $0.15/$0.50
2920 per 1M (durable; the 50% promo through 2026-09-09 is not the catalog row).
2921 - Baseten, Groq, and Cerebras are bundled OpenAI-compatible setup templates
2922 (`[providers.<id>] kind = "openai-compatible"`), not new `ProviderKind`
2923 variants. `/provider` fills URL, model, and env from one catalog row.
2924 - MCP manager copy now names the server, the failure, and one recovery
2925 command (`The X MCP server requires OAuth reauthentication. Run /mcp login X`).
2926 - Settings Advanced exposes clickable MCP Connect, Reconnect, and Diagnose
2927 actions, while Extensions and Problems route recovery through the existing
2928 `/mcp login`, `/mcp reload`, `/mcp validate`, and `/plugin validate` commands
2929 (#5643, #5655).
2930 - Plugin prompt matching (#5579): sending a task can toast the next review
2931 step when the prompt strongly matches an installed-but-idle plugin or a
2932 marketplace catalog you added (for example a Supabase prompt suggesting
2933 `/plugin trust supabase`). A live composer CTA offers the same review
2934 command while you type, matching turns append a bounded
2935 `<recommended_plugins>` user block, and `request_plugin_install` surfaces
2936 review without installing. `/plugin suggest` now ranks manifest keywords and
2937 catalog candidates, never auto-installs, and on-disk plugin changes also
2938 nudge `/plugin reload` between turns.
2939
2940
2941 - Added `/import-claude` (#5557): reads `~/.claude.json` and
2942 `~/.claude/settings.json` read-only and renders an explicit, reviewable
2943 migration plan plus a written report. MCP servers route through the
2944 existing `/mcp import <name> --approve` consent flow, allowlisted env keys
2945 become an unapplied portable bundle for `codewhale config import`, and
2946 permissions/hooks map to manual follow-ups; secret-shaped values are named
2947 but never echoed or imported.
2948 - Added the managed Chat relay: account-owned Chat commands now execute on the
2949 native runtime thread engine through a new `runtime_chat_relay` module
2950 instead of a second execution path. Each Chat thread is a dedicated,
2951 isolated runtime thread with an empty model-visible tool allowlist, a
2952 chat-only system prompt, and no workspace, memory, skill, credential, or
2953 local-path context; the active interactive TUI thread is never reused. The
2954 relay keeps one durable state file per scope behind a session-wide owner
2955 lock, binds a saved session permanently to its first remote target, replays
2956 exact duplicate commands from retained results instead of starting a second
2957 inference turn, terminalizes orphaned reservations on restart, and rejects
2958 (never queues into) a busy local Work turn with an immediate retryable
2959 result. Stop commands require the exact run and turn identity, and a worker
2960 aborts on any account or target mismatch during token refresh.
2961
2962 - Added a verified Omarchy/AUR packaging path: `packaging/aur` now carries a
2963 `PKGBUILD` template, `.SRCINFO` renderer and tests, release-candidate
2964 render step, and docs; the live AUR compatibility alias `codewhale-tui ->
2965 codewhale` is preserved, AUR dependencies match the live package, and the
2966 self-updater refuses to fight an Omarchy/package-manager installation.
2967 - Added a Fleet run-wide cost/token usage ceiling (R6, #5567): an accumulator
2968 plus admission gate and alert bound a whole run's spend across workers.
2969 - Added the real provider cache hit rate to `/context` (C3, DSH #3): the
2970 token-weighted provider-reported rate from the same telemetry `/cache`
2971 aggregates, plus an honest "no cache telemetry yet" state when nothing is
2972 recorded.
2973 - Added per-step cost movement: `TurnUsage` receipts are priced as they land
2974 so the live cost surface moves during long agentic turns instead of only at
2975 `TurnComplete` (#5578), and the footer now honestly shows `cost: unknown`
2976 when nothing can be priced instead of hiding the line.
2977 - Added the underwater session surface: the ambient water reads session state
2978 from across the room, its animation shape follows live agent activity, and
2979 attention tints are steady (no breathing) with a distinct reading treatment
2980 and no mid-water seam on tall windows.
2981 - Added `@path:START-END` ranged line mentions (#5550, picker half to follow),
2982 a predictable last-copy backup file for clipboard exports with the path
2983 named when the clipboard fails (#5555), `wait` on multiple background shell
2984 tasks with `until=any|all` (#5549, named-kill half to follow), and composer
2985 double-click word / triple-click line selection.
2986 - Added workflow parallel-`schema` slot partial success (#5583): a slot that
2987 produces a schema-valid partial result no longer fails the whole parallel
2988 branch.
2989 - Added plugin load-failure startup hints (#5579) and OpenRouter app
2990 attribution headers on outbound requests.
2991 - Added `codewhale doctor --fix` (with `--yes` for non-interactive consent):
2992 the doctor now computes a concrete repair plan — delete stale `.tmp*`
2993 leftovers from interrupted atomic writes, tighten secret-store file
2994 permissions to `0600`, disable structurally broken (Error-status) MCP
2995 entries through the atomic MCP save path, and scaffold missing user-global
2996 `skills`/`tools`/`plugins` directories — shows it, and applies it only after
2997 explicit consent. Every action is narrowly scoped and idempotent; JSON and
2998 context-JSON modes stay read-only and conflict with `--fix` (#5552, v1).
2999 - Added `/context` reporting of the real provider prompt-cache hit rate (C3)
3000 alongside token pressure.
3001
3002 ### Changed
3003
3004 - Provider-native web search now applies domain constraints before accepting an
3005 attempt, discards generated answers when returned citations violate those
3006 constraints, and preserves the caller's configured/local timeout as an
3007 independent fallback budget (#5681).
3008 - Idle session metrics omit zero facts (`0 turns`, `LLM 0s`) until the
3009 runtime has evidence. Working chrome says `in the current` instead of a
3010 generic `working`.
3011 - Deleted nine uncompiled `runtime_contract/` staging files. Live contracts
3012 remain `model.rs` and `termination.rs`.
3013
3014 - The first #5587 dead-code sweep converts audited test-only helpers to
3015 `#[cfg(test)]`, keeping production builds free of test-only APIs without
3016 changing runtime behavior.
3017 - `/plugin reload` is now discoverable when on-disk plugin bundles change: the
3018 next send and `/plugin list` nudge once with `Run /plugin reload to apply`
3019 instead of silently keeping the stale catalog (#5579). Trust is unchanged;
3020 this does not auto-reload.
3021 - Context-pressure warnings and critical alerts now remain visible in sticky UI
3022 status until compaction or explicit dismissal, instead of disappearing into
3023 scrolling turn metadata (#5620).
3024 - The Runtime thread store defaults to a per-session root
3025 (`$CODEWHALE_HOME/sessions/<id>/runtime`) so multiple Codewhale processes on
3026 one machine no longer share one owner lock (#5630). The exclusive lock is
3027 unchanged; `CODEWHALE_RUNTIME_DIR` still selects a shared root when that is
3028 intended.
3029 - Session token totals now include display-only per-model-call deltas while a
3030 turn is running, including input/output and cache-class counters; the
3031 authoritative `TurnComplete` totals still reconcile exactly once (#5581).
3032 - Transcript focus now exposes per-block actions: `y` copies content, `Y`
3033 copies the rendered metadata view, Enter opens a fullscreen block pager, and
3034 `r` opens raw detail; the existing Tasks rail shortcuts remain unchanged
3035 (#5551).
3036 - Provider neutrality (#5588): model resolution of omitted/aliased models is
3037 now provider-relative, OpenAI-native defaults no longer route through
3038 another provider's table, CLI credentials stay provider-scoped, and NVIDIA
3039 credentials no longer leak into the DeepSeek keychain. Neutrality test
3040 matrices exercise several providers instead of standing in with one.
3041 - The workflow engine module was decomposed out of its 3k-line mega-file into
3042 `journal`, `usage`, and `report` modules plus a module directory (#5586
3043 slices 1a/B/C/D), a semantic-free move verified by normalized-content hash.
3044 - Compaction refusals are now always named (#5577): silent holds under context
3045 pressure are gone, the context meter honors the same provider-billed prompt
3046 the trigger uses (T1), and prune outcomes are projected without cloning the
3047 transcript.
3048 - Step budgets now end honestly: an ~80% soft landing nudges the model to
3049 write its final report, and exhaustion grants exactly one bounded
3050 report-on-exhaustion turn instead of dying silently (A1/A2).
3051 - Contributor credit: recognized agent contributors (e.g. `Codewhale Agent`)
3052 may now carry `Co-authored-by` trailers; unknown bot/tool trailers are
3053 still rejected by the credit gate.
3054
3055 ### Fixed
3056
3057 - Read-only Fleet workers no longer send `"action": {"enum": null}` in their
3058 projected `bash` schema. The read-only projection probed the action enum
3059 with a mutating index, which auto-vivified the key on schemas that have no
3060 action property, and strict OpenAI-compatible validators then rejected the
3061 whole request (`null is not of type "array"`). The probe is non-mutating
3062 now, in both the read-only projection and the `Run` arm next to it, and a
3063 regression test walks the whole projected catalog for nulls
3064 (#5944, thanks @gaord).
3065 - Fast typing no longer corrupts the composer. The paste-burst heuristic ran
3066 on every session until a real bracketed paste arrived, holding, buffering,
3067 retro-grabbing, and absorbing Enter on timing guesses; it is now
3068 fallback-only (gated off when the terminal provides bracketed paste), the
3069 retro-grab is deleted, and Enter on held command text flushes and submits.
3070 - Ctrl+C works on the pre-session launch menu and speaks everywhere: the
3071 first press arms the two-second exit window with a visible localized
3072 "Press Ctrl+C again to quit" hint (previously silent), the second exits.
3073 The worktree name input keeps Ctrl+C as cancel-input.
3074 - Fresh interactive sessions no longer leave a phantom one-message duplicate
3075 behind. The TUI claimed one session id (Runtime store lock, turn-start crash
3076 checkpoint) while the engine minted a second one; the first `SessionUpdated`
3077 re-keyed the App, the completion commit cleared only the engine id's
3078 checkpoint, and `codewhale --continue` later "recovered" the orphaned
3079 checkpoint as a duplicate session instead of the real one. The engine now
3080 adopts the host-owned id at spawn (`EngineConfig::session_id`) and `/clear`
3081 mints the next id in the App like `/new`. A non-TTY `--continue` no longer
3082 promotes and consumes the crash checkpoint before failing the terminal
3083 check, and the root `codewhale --resume <id>` / `--session-id <id>` flags
3084 documented in the operations runbook now parse instead of being swallowed
3085 as a prompt.
3086 - Website: `/signin`, `/signup`, and `/auth/callback` are locale-aware public
3087 routes instead of localized 404s. Sign-in and create-account send the person
3088 to the CWC app; OAuth callbacks hop to `app.codewhale.net` with the query
3089 intact; `/login` and `/register` are aliases. Local CLI use is not presented
3090 as requiring an account (#5767).
3091 - The sandbox read deny-list matches a rule's resolved path as well as its
3092 literal spelling. On macOS `/etc` and `/var` are symlinks into `/private`,
3093 so a read of `/private/etc/sudoers` walked around the `/etc/sudoers` rule,
3094 and a rule written against a symlinked directory never fired for the real
3095 path that `canonicalize` and the process cwd hand back.
3096 - Background shells are first-class work-strip rows (`▾ Shells N`) you can
3097 open, watch, and cancel by the `shell_*` id on the row. `/jobs cancel all`
3098 cancels running shells; it no longer looks up a task named `all`. The
3099 composer hourglass crumb no longer stands in for a shell surface.
3100 - `codewhale logout` and `/logout` now clear the Codewhale account session
3101 and the Daytona secret slot, not only provider API keys. The TUI crate's
3102 leftover `login --api-key` path no longer claims to save a key.
3103 - Account sessions no longer read the macOS Keychain. Unsigned or rebuilt
3104 `codewhale` binaries were a new Keychain ACL principal every time, so
3105 `codewhale web` and the TUI popped a password dialog on start. Sessions
3106 now use `~/.codewhale/secrets/secrets.json` (mode 0600), the same store
3107 as provider keys. Extracted from the Keychain-retirement half of #5632.
3108 - Hardened the dispatcher-side config parse the same way: `ConfigStore`
3109 loads and project-config parsing now deserialize `ConfigToml` on a
3110 dedicated 16 MiB-stack thread (the guided-setup save path could overflow
3111 a 2 MiB worker stack the same way the TUI's `ConfigFile` parse did), and
3112 the #5585 setup-confirm toast test runs its runtime on an equally sized
3113 thread instead of overflowing the default libtest stack.
3114 - Fixed detached interactive agents reporting worker usage after the parent
3115 turn ends with the usage missing from the session/live `/cost` total
3116 (#5597): interactive turns acquire an owner-scoped runtime usage lease,
3117 late usage enters the session cost pool without reopening the sealed
3118 mailbox, and worker/session/reload accounting share one hashed response
3119 identity so retried deliveries stay exactly-once.
3120 - Fixed the sub-agent fiasco class: in-workspace absolute `git -C` no longer
3121 trips the read-only child shell gate with a coherent bounded gate (#5595),
3122 turn end parks turn-owned children resumably instead of silently cancelling
3123 them (#5596), stale write-claims are released by liveness with coordinate
3124 release (#5562), and the verifier role description matches its real
3125 surface (#5562).
3126 - Fixed workflow responseSchema failure handling (#5583): bounded repair with
3127 typed receipts (kind + attempt), raw-output receipts persisted as artifacts
3128 that survive reload, and failures surfaced instead of null success (#5528).
3129 Degraded owner snapshots no longer project as ordinary Completed runs
3130 (#5582), typed task error kinds enable fail-fast parallel/pipeline (R9), and
3131 `/workflow confirm` finds the draft despite interleaved messages.
3132 - Fixed the DeepSeek session that never auto-compacted at 842k/1M (#5577): the
3133 exact `billed_842k_on_a_1m_window_compacts_despite_a_small_estimate`
3134 regression pins the trigger.
3135 - Fixed sandbox escapes and authority gaps: workspace-write tools resolve
3136 hard-linked files before writing (S2, #5569), an opt-in read deny-list
3137 bounds full-disk reads in any posture (S1, #5568), and session grants match
3138 the command family instead of widening the whole tool (R2).
3139 - Fixed provider-transport robustness: non-streaming HTTP requests are bounded
3140 by a read timeout (R4), and Chat-Completions mid-stream error frames surface
3141 instead of hanging (R3). MCP OAuth expiry now reacts to 401/403 with a named
3142 recovery path and login hint instead of looking like a broken server (T4,
3143 #5572).
3144 - Fixed Fleet lifecycle gaps: detached workers are reaped when their manager
3145 dies (R7) and the per-task wall-clock timeout is enforced (R5); the local
3146 Fleet host compiles on non-Unix targets; detached schema repair stays within
3147 the runtime budget.
3148 - Fixed prompt-cache correctness: the tool catalog is fingerprinted in
3149 provider wire order (C1), prefix changes between requests are always
3150 declared (C5) — including the newly named mid-turn `change:tool_surface`
3151 reasons for deferred-tool admission, tool-search activation, and runtime MCP
3152 tool arrival — and a reasoning-only response stopped at the output limit now
3153 fails the turn honestly instead of re-issuing a request that can only
3154 reproduce the stop.
3155 - Fixed docs/public-surface drift: REBRAND.md no longer presents
3156 `api.deepseeki.com` as a China fallback (#5564), and the web facts/tool
3157 counts match the repository.
3158
3159 - Heavy pull requests now run the real Linux workspace nextest, doctest, and
3160 lockfile lanes directly on GitHub Actions instead of reporting a green
3161 placeholder while waiting for a branch-specific CNB mirror (#5547).
3162 - Fleet roster members in a selected Fleet now expose a visible edit affordance
3163 and a direct `m` model-picker shortcut, while the coordinator row remains
3164 read-only (#5604, covers #5589).
3165 - The context inspector now attributes bounded tool-schema cost to the built-in
3166 catalog and each discovered MCP server without changing prompt assembly or
3167 cache behavior (#5553).
3168 - The goal-continuation quiet period (`[goal] continuation_delay_seconds`,
3169 added in #5508) now applies on every dispatch path. Previously the
3170 within-turn dispatch hook fired the next continuation prompt immediately
3171 whenever a model step ended with the goal still active, so CLI-resumed and
3172 host-managed sessions never observed the configured delay (measured
3173 end-to-start gaps of ~9 s with a 300 s delay configured). The wait now
3174 runs unconditionally inside `goal_continuation_message_if_needed`,
3175 remains cancellable, and pause/clear/terminal `update_goal` calls still
3176 cancel a pending pass (#5534).
3177 - Two unit tests no longer depend on process-global environment state that
3178 sibling tests mutate concurrently.
3179 `route_budget::tests::v4_trigger_uses_window_percent_when_it_fits_spendable_input`
3180 asserted no-override output-budget values while reading
3181 `CODEWHALE_MAX_OUTPUT_TOKENS` / `DEEPSEEK_MAX_OUTPUT_TOKENS` without
3182 holding `lock_test_env()`, so a concurrent writer could flip the value
3183 mid-assertion (the order-dependent full-suite flake).
3184 `prompts::tests::system_prompt_prefix_never_leaks_private_content` read the
3185 real home via `HOME`/`USERPROFILE`, so a machine with
3186 `~/.codewhale/instructions.md` leaked its absolute path into the prompt and
3187 failed the no-private-paths assertion unless a sibling's temporary `HOME`
3188 guard happened to be live. Both tests now hold the env barrier and pin the
3189 variables (the route-budget test removes the overrides; the prompts test
3190 points `HOME`/`USERPROFILE` at a scratch dir). Assertions unchanged.
3191
3192 - TUI sessions now apply a subtle OSC 12 cursor accent only on explicitly
3193 supported terminals and restore the terminal default through normal, panic,
3194 and signal cleanup paths (#5554).
3195
3196 ## [0.9.11] - 2026-08-22
3197
3198 Codewhale v0.9.11 tightens the long-running agent loop, makes workflow
3199 failures visible instead of successful-looking, adds an experimental
3200 vision-capable DeepSeek route, and prepares reproducible Codewhale-versus-Pi
3201 evaluation without publishing a result before a real run. The complete
3202 item-level change record is retained below the categorized release highlights.
3203
3204 ### Added
3205
3206 - Added first-party `deepseek-v4-flash-vision-exp` discovery and selection for
3207 DeepSeek, including the `flash-vision` alias, bundled offline metadata,
3208 registry and picker entries, and image-input capability on the chat route.
3209 Context and output limits inherit from V4 Flash until DeepSeek publishes
3210 distinct values; pricing remains unknown rather than guessed.
3211 - Added a provider-controlled Codewhale-versus-Pi parity harness with three
3212 hermetic coding tasks, route and reasoning-effort receipts, doctor/dry-run
3213 modes, and bounded result artifacts. The repository ships the harness, not a
3214 benchmark verdict; comparable real runs remain an acceptance gate.
3215 - Added portable, secret-free config export/import with a reviewable plan,
3216 explicit headless consent, backup and rollback, and idempotent re-import.
3217 - Added bounded multi-file diagnostics through the existing model-facing `lsp`
3218 tool without increasing the tool-catalog count. Thanks to **Isabel Wu
3219 ([@wuisabel-gif](https://github.com/wuisabel-gif))** for PR #5524.
3220 - Added portable presentation, media-attachment, and operation-digest facets to
3221 the command contract, then moved all seven utility handlers onto the
3222 contract-backed dispatch path. Thanks to **Paulo Aboim Pinto
3223 ([@aboimpinto](https://github.com/aboimpinto))** for PR #5525.
3224
3225 ### Changed
3226
3227 - Sub-agent, Fleet-worker, workflow-task, and thread-runtime model turns no
3228 longer inherit a hidden role-based step ceiling. An omitted or zero
3229 `max_steps` is unbounded; a positive user/config value remains an explicit
3230 cap and is still clamped to the runtime safety ceiling. Wall-clock, provider,
3231 heartbeat, cancellation, and admission safeguards are unchanged.
3232 - `/rc` now mirrors one shared session rather than transferring terminal
3233 ownership: local and web prompts remain available while idle, approvals use
3234 first-decision-wins semantics, and transport/integrity failures remain
3235 fail-closed.
3236 - The terminal status rows around the composer are now two stable bands:
3237 `provider · model · thinking level` is the persistent identity row below
3238 the composer in every phase, and a separate activity row above the
3239 composer carries the live phase, notices, and cost/metrics. Sending a
3240 prompt no longer relocates the route identity above the composer, and
3241 neither row ever duplicates it.
3242 - The embedded local Web client now uses the current CWC Ocean hierarchy and
3243 readable control sizing, follows the shared Enter/Shift+Enter composer
3244 grammar, and chooses a provider plus model per new thread without mutating
3245 Runtime defaults. Exact image-input capability is labelled honestly; a
3246 vision-capable route does not imply that browser attachments exist.
3247 - The runtime now has one authoritative model-turn loop. The placeholder
3248 `crates/core` engine tree is gone, while the active TUI loop and its extracted
3249 tool-call stages retain existing policy, hook, cancellation, and budget
3250 behavior. Thanks to **Sun Zhenyuan
3251 ([@bistack](https://github.com/bistack))** for PR #5523.
3252
3253 ### Fixed
3254
3255 - Chat Completions streams now require terminal proof from `[DONE]` or a
3256 non-empty `finish_reason`. Protocol-only frames no longer count as answer
3257 content or time-to-first-token, and a provider continuation that ends after
3258 tool results with no answer or tool call fails durably instead of producing
3259 a false `Completed` receipt.
3260 - A selected v2 Fleet now drives one bounded, deterministic Agent roster across
3261 terminal and runtime surfaces. Fleet operator/member/explicit-route
3262 precedence, resolved member identity, and exact `vision` requirement
3263 admission now fail visibly instead of silently falling back, first-matching,
3264 or rerouting.
3265 - A workflow whose `task()` dispatch was rejected no longer loses that failure
3266 inside a `parallel()` null slot or presents a successful-looking run. Rejected
3267 dispatches now fail the run, persist as typed bounded receipts with an exact
3268 count, and appear in transcript, activity detail, and workflow-panel views.
3269 - Provider readiness, credential-source explanations, focused-agent scrolling,
3270 compact `/status` and `/help` rendering, shell/web output bounds, MCP
3271 lifecycle reporting, and narrow-terminal onboarding received the detailed
3272 fixes recorded below.
3273 - Portable config import/export now preserves typed tables, arrays, numbers,
3274 booleans, and datetimes without stringifying them, while refusing
3275 machine-bound trust overlays, credential readers, automatically executable
3276 hooks/LSP definitions, local-path authority, machine-local network proxy
3277 routes, cookies, redaction placeholders, and nested or camel/dotted
3278 credential keys. Project and global bundle operations now load and validate
3279 the document for their actual scope in both directions, including a
3280 workspace whose document still lives under the legacy app directory.
3281 - `codewhale login` now means Codewhale account sign-in (the same browser
3282 device flow as `codewhale account login`, with `--no-open` and
3283 `--timeout-seconds`); provider API keys are configured exclusively through
3284 `codewhale auth set --provider <provider>`, and the hidden legacy
3285 `--api-key`/`--provider` flags redirect loudly instead of silently writing
3286 a key.
3287 - Account sessions prefer the OS credential manager and now fall back
3288 automatically to the private `0600` Codewhale secrets file on headless
3289 hosts, SSH boxes, and containers; the `CODEWHALE_CLOUD_ALLOW_FILE_SESSION_STORE`
3290 opt-in is deprecated and ignored.
3291 - `/update` gained a `Ctrl+Shift+U` install chord (catalogued in
3292 `docs/KEYBINDINGS.md`, localized in all 15 packs) and a startup hint that
3293 names the previous and current version on the first launch of a newer
3294 build, pointing at `/change`.
3295 - Fleet product-model copy pass: the TUI, docs, and locale packs now use
3296 Fleet / Member / Role / Model / Access / Saved consistently so a user can
3297 say "scout", "DeepSeek V4 Flash", or the member name and mean the same
3298 thing.
3299 - A reasoning model that returns only hidden reasoning and a clean stop (no
3300 answer, no tool call) is now re-requested automatically up to twice before
3301 the turn fails, instead of dead-ending with "the provider response was
3302 incomplete." The retry reuses the cached prefix so it is cheap; an
3303 output-length stop (`length`/`max_tokens`) is never retried, and a
3304 persistently answerless model still fails honestly after the bound.
3305 - Model-bound tool results now use a credential-shaped redaction policy:
3306 only values that look like secrets (known prefixes, JWTs, bearer tokens,
3307 PEM private-key blocks, long opaque strings) are masked before a `read` or
3308 shell result reaches the model, so code such as `password:
3309 credentials?.password` or `"password-validator": "^5.3.0"` stays byte-exact
3310 for edits and read-back. Exact configured credential values are still always
3311 replaced, and logs/previews/exports keep the broad key-based scrubber. (#5546,
3312 reported by @ronohara)
3313 - Terminal input shutdown no longer waits forever on a wedged TTY read,
3314 Windows launch receipts can atomically replace an existing record, and the
3315 complete `/status` report now follows the active locale without rewriting
3316 exact custom-provider identities that contain brace-like text.
3317 - Localized READMEs again match the English install and third-party-notice
3318 surface, including shell-completion guidance in all 18 translations.
3319
3320 ### Security
3321
3322 - Unified OAuth device-code polling now validates verification URLs before
3323 opening them, redacts token-bearing types, honors server slowdown intervals,
3324 and keeps credential save/logout mutations serialized.
3325 - Project instructions, rules-directory traversal, secret-shaped config data,
3326 URL fingerprints, and shell network authority now retain the explicit bounds
3327 and fail-closed behavior described in the detailed record.
3328
3329 ### Contributors
3330
3331 - **Sun Zhenyuan ([@bistack](https://github.com/bistack))** — tool-call stage
3332 extraction with the existing execution and policy contracts preserved
3333 (#5523).
3334 - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — bounded
3335 multi-file `read_lints` support (#5524), plus independently reviewed
3336 completion-routing overlap in #5530.
3337 - **Lstarsky0 ([@Lstarsky0](https://github.com/Lstarsky0))** — maintainer review
3338 hardening for truthful per-file states and truncation metadata in #5524.
3339 - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** — portable
3340 presentation/media/digest facets and the seven utility-handler migrations
3341 (#5525).
3342 - **RepentStar ([@RepentStar](https://github.com/RepentStar))** — reported and
3343 reproduced the stale completion-generator path and missing `codew`
3344 registration fixed for #5526.
3345
3346 ### Detailed change record
3347
3348 The notes below are preserved in full so the categorized highlights do not
3349 erase behavior, migration, security, compatibility, or verification details.
3350
3351 - Provider completion is now evidence-based. A Chat Completions stream reaches
3352 `MessageStop` only after `[DONE]` or a non-empty `finish_reason`; raw EOF
3353 without either is a typed failure. Message-start, ping, usage/terminal
3354 deltas, block-stop, and message-stop frames do not count as productive
3355 content or mint time-to-first-token. After tool results, a terminal provider
3356 step with no answer or tool call now emits a durable failed turn and never
3357 fabricates an empty assistant message.
3358
3359 - A selected v2 Fleet is the single effective Agent roster across terminal,
3360 Runtime threads, direct Workflow, Fleet execution, doctor, and
3361 setup/readiness; legacy profile layers are consulted only when no Fleet is
3362 selected, and invalid selections fail visibly with bounded, redacted errors.
3363 Member references resolve exact id first and otherwise require a unique
3364 display name, role, pinned model, offline model name, or provider/model route;
3365 `agent action=roster` exposes that same bounded roster. The Fleet operator
3366 supplies fresh-root and inherited-member routing unless an explicit launch
3367 route or member pin wins, the resolved member is shown separately from the
3368 requested alias, and `requires = ["vision"]` is admitted only on an exact
3369 route with verified offline `image_input` support—never by silent rerouting
3370 or custom-proxy inference. Fleet selection remains an explicit user/folder
3371 contract independent of legacy project-profile loading.
3372
3373 - **Breaking (app-server):** `/prompt`, `prompt/request` and `prompt/run` now
3374 execute a real model turn instead of reporting success for work they never
3375 did. `Runtime::handle_prompt` called no model: it resolved config, ran a
3376 local `ModelRegistry` lookup, emitted three canned hook events
3377 (`ResponseDelta` was literally the string `model-selected`), and returned
3378 HTTP 200 with `output` set to a stringified JSON echo of the caller's own
3379 routing metadata — the prompt included. Worse, when a `thread_id` was
3380 supplied it appended a real user row, flipped the thread to `Running`, and
3381 then wrote that echo into durable history as an **assistant message** plus a
3382 `prompt_response` checkpoint. Nothing marked the row synthetic and nothing
3383 ever moved the thread out of `Running`. All three endpoints now route
3384 through the same `RuntimeBridge` that stdio `thread/message` has always
3385 used, so `output` is the model's streamed text, `model` is what the runtime
3386 reports for the thread that ran the turn, and `events` are the real
3387 streaming frames. `Runtime::handle_prompt` and its synthetic history write
3388 are gone.
3389
3390 - **Breaking (app-server):** a failed prompt is now a typed failure rather
3391 than a success-shaped body. `POST /prompt` returns
3392 `{"error":{"code":...,"message":...}}` with `400` (invalid request), `404`
3393 (thread not found), `503` (`runtime_unavailable`) or `500`, instead of HTTP
3394 500 carrying a `PromptResponse` with the error text stuffed into `output`
3395 where model text belongs. The stdio surface gained JSON-RPC `-32005`
3396 `runtime_unavailable` for "the turn engine could not be reached, so nothing
3397 ran" — distinct from `-32603`, and retryable. There is no configuration in
3398 which a prompt silently echoes instead of running.
3399
3400 - **Breaking (app-server):** `POST /thread` with a `Message` body runs the
3401 turn. It previously replied `status: "accepted"` with a
3402 `ResponseDelta("queued")` frame while starting no worker and calling no
3403 bridge — the stdio path for the same request has always done real work, so
3404 the two transports disagreed about what `accepted` meant. HTTP now replies
3405 `status: "completed"` once the turn reaches a terminal state, with the
3406 streamed frames in `events` and the turn id in `data`. `Runtime::handle_thread`
3407 no longer accepts `ThreadRequest::Message` at all: it owns thread
3408 bookkeeping, not the turn engine, and returns an error naming
3409 `POST /v1/threads/{id}/turns` rather than a canned acceptance.
3410
3411 - **Breaking (app-server):** `AppRequest::SubmitUserInput` now refuses
3412 explicitly (`ok: false`, `error: "user_input_reply_unsupported"`) instead of
3413 returning `resolved: true` and filing the answers in a map that had no
3414 reader anywhere in the crate — every answer submitted was silently
3415 discarded. It cannot be made to work on this transport: while a turn
3416 streams, the stdio loop executes only `thread/interrupt` and queues
3417 everything else, so an answer sent there would wait on the very turn
3418 waiting for it. The refusal names the surface that does accept it,
3419 `POST /v1/user-input/{thread_id}/{request_id}` on the runtime API. The
3420 client-visible refusal is whitespace-clean, and the `/tool` path that mints
3421 the `UserInputRequest` is unchanged and still genuine.
3422 - Split the coordination ledger out of `tools/subagent/coord.rs` into
3423 `tools/subagent/coord/ledger.rs`. The file held two unrelated things: the
3424 model-facing `agents/*` tool wrappers, and the durable decision/claim/
3425 contention records those wrappers happen to write — records whose consumers
3426 are mostly *not* in the tool layer (`tui::coordination_detail`,
3427 `tui::work_surface`, `tui::ui::tests`, `core::engine::tests` all name these
3428 types). At 3.8k lines, reading either one started by scrolling past the
3429 other. A pure move with a glob re-export from `coord`, so every
3430 `crate::tools::subagent::coord::{…}` path still resolves and no consumer file
3431 was edited; the only content change the move required is one constant going
3432 from private to `pub(super)` because its caller stayed behind. `coord.rs` is
3433 now 2.3k lines and `ledger.rs` 1.6k.
3434
3435 - `agent` is now the only sub-agent tool the model can see. `AGENTS.md` has
3436 said "the model-facing sub-agent surface is `agent` only" since the lifecycle
3437 tools were removed, but six more were reachable: `agents/list`,
3438 `agents/message`, `agents/followup`, `agents/interrupt`, `agents/coordinate`,
3439 and `agents/wait` all defaulted to model-visible, so they shipped in the
3440 catalog and `tool_search` could load any of them — and the `agent`
3441 description told the model they existed. They now declare
3442 `model_visible() -> false`, the same shape `rlm` and `exec_shell` use: still
3443 registered, still executable by name so a persisted transcript replays
3444 against the same implementation, never advertised and never returned by
3445 either `tool_search` matcher.
3446
3447 Five of the six were already duplicates of an `agent` action. The sixth was
3448 not: `agents/coordinate action=claim` was the *only* way to widen a write
3449 claim, and write enforcement fails closed, so hiding it would have left a
3450 refusal ("expand it first with…") pointing at a tool the model could no
3451 longer call. `agent` gains one action, `claim`, taking the write scope
3452 vocabulary `action=start` already uses (`write_roots`, plus parse-accepted
3453 `exact_files` and `coordination_contracts`). It keeps `agents/coordinate`'s
3454 `Auto` approval — gating it deadlocks autonomous fan-in — and it can only
3455 widen the caller's own scope; peer contention still fails. A scopeless claim
3456 is refused rather than reported as granted, because `expand_write_claim`
3457 returns the unchanged claim with `Ok` when every list is empty.
3458
3459 Collapsing six tools into one action set also collapses the gating: `agent`
3460 is deliberately exempt from both name-keyed gates (`posture_permits_tool`
3461 short-circuits it so delegation depth governs spawning, and
3462 `execution_envelope` classifies it `Bounded` so a read-only member can fan
3463 out read-only work), so a capability folded into it inherits no gate. `claim`
3464 is therefore gated per action, reproducing the envelope check that kept
3465 `agents/coordinate` off a read-only role's catalog — in the catalog and again
3466 at dispatch, since catalog shaping is not an authority boundary. The other
3467 actions keep exactly the visibility they had.
3468 - One placement table now decides which wire channel a message role belongs
3469 in, and unrepresentable role/dialect pairs are refused at the outbound seam
3470 (`DeepSeekClient::prepare_outbound_request`) instead of at the provider.
3471 Chat Completions and OpenAI Responses used to drop an unfamiliar role
3472 silently, Anthropic Messages forwarded `message.role` verbatim and took an
3473 opaque provider 400 for it, and Google cloud-code was alone in failing
3474 closed. Positioned `system` and `developer` history — including compaction
3475 and branch summaries — is carried natively by Chat Completions and Responses
3476 and projected, in place, onto Anthropic's user channel. It is neither
3477 hoisted nor dropped. Genuinely unknown roles keep the previous
3478 dialect-specific fail-closed/omit behavior, now decided in one table. The
3479 dead `"tool"` arm in the Responses adapter is gone — nothing constructs that
3480 role.
3481
3482 - Message roles are a closed `Role` enum (`crates/core/src/role.rs`) instead of
3483 a free-form `String` on `Message`. Four wire adapters each decided
3484 independently what an unfamiliar role meant, and a typo in a role string was
3485 a silent transcript edit rather than a compile error. `Role` keeps an
3486 `Unrecognized(String)` variant and serializes via `as_str()`, so a saved
3487 session's bytes are unchanged, a transcript written by a newer build still
3488 loads here, and `assistant_interrupted` stays a distinct session item — no
3489 session schema bump and no migration ladder.
3490
3491 - Portable config bundles: `codewhale config export --portable` writes a
3492 deterministic, secret-free bundle (credential and machine-specific keys
3493 dropped), and `codewhale config import <FILE|URL|->` applies one with a
3494 strict versioned envelope, a printed added/changed/skipped/conflicting/
3495 rejected plan, consent gating (`--yes` required headless), a timestamped
3496 backup with rollback, and idempotent re-import. Credential-shaped entries
3497 are rejected by key name and value shape — rejections name the field,
3498 never the value. Remote imports revalidate the HTTPS-or-loopback-HTTP policy
3499 on every same-scheme redirect hop, and duplicate keys across applicable
3500 section labels fail before any backup or write instead of silently resolving
3501 by section order. Structured TOML values round-trip with their original
3502 types and exact named-provider identity; recursive sanitization covers
3503 arrays/tables and camel-case, dotted, cookie, and access-key spellings while
3504 retaining ordinary token-count metrics. Machine-bound project trust,
3505 credential-source consent, automatic hook/LSP execution, and local-path
3506 authority are non-portable and fail before mutation. A missing target is
3507 created transactionally and removed again on rollback, and project/global
3508 scope validation rejects the wrong document before import or export.
3509 Imported tables deep-merge portable fields into the target, so omitted
3510 machine-local provider credentials, endpoints, and executable definitions
3511 remain intact instead of being erased by a sanitized bundle.
3512
3513 - `/rc` is now a shared-session mirror instead of a terminal takeover.
3514 Attaching the web app no longer locks the local composer or hides
3515 approvals: both surfaces can prompt while idle (one turn runs at a
3516 time), approval cards stay visible in the terminal and are shared with
3517 the web with first-decision-wins semantics (the losing side is told, a
3518 web decision dismisses the local card), and structured questions are
3519 answered locally instead of cancelled. Fail-closed behavior survives —
3520 the post-failure reconnect lockout, integrity-gated `/rc stop`, and the
3521 fail-closed shared-approval channel on transport loss are unchanged.
3522 The takeover vocabulary ("web owns prompts and approvals") is gone from
3523 every surface.
3524
3525 - Auto-mode provider readiness no longer reports "key saved · not checked"
3526 forever. Readiness checks are recorded against the concrete model the
3527 router ran, but auto-mode reads resolved against the literal `auto`
3528 identity, which never matched any recorded check — so the setup receipt,
3529 model picker, and fleet setup view showed an eternal unchecked badge
3530 even after hundreds of successful turns. The read now falls back to the
3531 most recent check on the same route (provider + endpoint + auth class);
3532 concrete-model reads keep exact per-model scoping.
3533
3534 - The focused sub-agent transcript now scrolls like the main transcript.
3535 The frame renderer sampled the ocean column through a `ChatWidget` whose
3536 constructor consumed `pending_scroll_delta` — every PageUp/PageDown and
3537 wheel event was swallowed by an invisible widget before the focused pane
3538 could read it. The delta is now parked across the sample; the pane pins
3539 on user scroll-up, follows new child activity at tail, and
3540 jump-to-bottom releases the pin.
3541
3542 - Every Codex OAuth Responses request carried `max_output_tokens`, a parameter
3543 that endpoint rejects outright ("Unsupported parameter: max_output_tokens"),
3544 so every gpt-5.6-sol turn — including every sub-agent on that route — failed
3545 at the first request. Codex Responses bodies now ship without a client-side
3546 output cap; the backend applies its own. Every other Responses route keeps
3547 the central cap on the wire, exactly as before.
3548
3549 - The model-facing `lsp` tool now supports a bounded `read_lints` operation
3550 for multi-file, workspace-relative LSP diagnostics without adding another
3551 tool catalog entry (#4070).
3552
3553 - HTTP 400 classification no longer calls an unsupported-parameter error a
3554 context-window overflow. Responses shape errors such as "Unsupported
3555 parameter: max_output_tokens" name a token-shaped field, which the generic
3556 keyword rules read as prompt-size exhaustion and pointed users at compaction
3557 that could never help. Such responses now classify as invalid requests.
3558
3559 - xAI device login validated nothing about the URL it opened. The
3560 `verification_uri` from the device-code response went straight to
3561 `webbrowser::open` with no parse, no scheme check and no credential check, so a
3562 spoofed or compromised issuer could hand the platform's "open this" call a
3563 `file:` path, a custom application scheme (`vscode://`, `slack://`), or a
3564 credential-bearing URL. The shared primitive now refuses anything that is not a
3565 web page before the URI is printed or opened. **Behaviour change:** a
3566 non-loopback plain-`http:` verification URI now aborts login where it
3567 previously opened; `http:` on a loopback host is still allowed, because local
3568 runtimes legitimately use it.
3569 - The xAI OAuth types no longer print bearer material through `Debug`. Five types
3570 holding tokens (`GrokAuthEntry`, `TokenResponse`, `DeviceCodeResponse`,
3571 `DeviceCodeGrant` and the poll outcome) either redact or no longer derive
3572 `Debug` at all, so a token has no printable path through a `{:?}` on any
3573 surrounding struct. The shared `DevicePollOutcome` derives nothing, which the
3574 compiler enforces.
3575 - **Behaviour change:** an `interval` of `0` from the authorization server now
3576 falls back to RFC 8628's five-second default rather than a one-second floor,
3577 in both the xAI and account device flows.
3578
3579 - OAuth device-code login is now one implementation. xAI/Grok device login and
3580 Codewhale account login each carried their own hand-rolled RFC 8628 polling
3581 loop with nothing shared between them; both now call a single primitive
3582 (`codewhale-config`'s `device_code`), ported from pi. Three fixes come with
3583 it. `slow_down` now honours a server-supplied `interval` instead of always
3584 adding five seconds, which is what stops polling from running early forever
3585 under WSL and VM clock drift. Timing out after a `slow_down` now says so and
3586 names clock drift, rather than reading as a plain timeout. And the xAI
3587 verification URI is validated before it is handed to the browser opener —
3588 Codewhale previously opened whatever the device-code response said, so a
3589 spoofed or compromised issuer could point the platform "open this" call at a
3590 `file:` path or a custom application scheme. It must now be `https:`, or
3591 `http:` on a loopback host for self-hosted issuers. Stored credential files
3592 are unchanged and existing logins keep working. MCP OAuth is untouched: it
3593 delegates to `rmcp`/`oauth2` and was never hand-rolled.
3594 - Shell output truncation now stays inside its own budget. A truncated shell
3595 result keeps a 6 KB head, a 24 KB tail, and any high-signal lines rescued
3596 from the omitted middle — but that rescued block was bounded only by a line
3597 count. One rustc `error:` line carrying a long inferred type or a minified
3598 bundler frame is routinely hundreds of kilobytes, so a "30 KB" result could
3599 arrive at 430 KB with the omitted line pasted back in whole. Each rescued
3600 line is now clipped and the block has a 4 KiB ceiling; the signal survives,
3601 the payload does not.
3602
3603 - Fetched web pages in non-Latin scripts no longer arrive half-read. Page text
3604 was reflowed against a column budget measured in bytes, so Cyrillic and Greek
3605 wrapped at roughly half the intended width and CJK at two thirds — and since
3606 the page view is delivered by line count, the surplus lines pushed real
3607 content off the end of the window. A Russian or Japanese URL returned a
3608 fraction of the text an English one did, for the same call. Wrapping now
3609 measures display width.
3610
3611 - The `bash` tool no longer tells the model it has no default timeout when it
3612 does. An omitted timeout has always been bounded at 120 seconds and the
3613 command killed there, but the tool description and its `timeout` field both
3614 claimed otherwise — steering the model away from the one parameter that
3615 would have saved a longer build. Both now name the real bound.
3616 - MCP servers no longer restart because an unrelated setting was saved. The
3617 lazy config reload re-reads every watched source whenever one of their
3618 mtimes moves and keeps the live connections only when the content hash
3619 matches — but the hash was taken over `serde_json` bytes produced straight
3620 from the config's `HashMap`s, and two `HashMap`s with identical contents do
3621 not iterate in the same order. Any touch of any watched file therefore hashed
3622 differently, tore down every connection, and SIGTERMed and respawned every
3623 stdio child. Keys are now sorted before hashing.
3624
3625 - An MCP server marked `required` now still tells you *why* it failed to start.
3626 `connect_all` appended a generic "required MCP server failed to initialize"
3627 entry after the real per-server error, and the snapshot folds those pairs into
3628 a map keyed by server name — so the contentless entry replaced the diagnosis
3629 and /mcp showed the marker instead of "No such file or directory". The marker
3630 is now only synthesized when nothing else reported a cause.
3631
3632 - A crashed stdio MCP server is now rebuilt instead of being handed back dead.
3633 A failed transport *read* disconnected the connection; a failed *write* did
3634 not, so after the child exited the connection stayed `Ready`, the pool reused
3635 it on every later tool call, and /mcp kept listing the server as connected.
3636
3637 - An MCP response carrying neither `result` nor `error` is now an error rather
3638 than an empty success. It previously reached the model as a successful tool
3639 call with a `null` payload, indistinguishable from a tool that did nothing.
3640 An explicit `"result": null` is still a valid empty success.
3641 - Stdio MCP server requests are answered while the client is idle instead of
3642 blocking behind the zero-capacity response rendezvous until an unrelated
3643 client call. `ping` receives its prompt empty result, unsupported methods
3644 receive JSON-RPC `-32601`, and the reader keeps only a weak stdin handle so
3645 dropping the client still delivers graceful EOF.
3646 - `base_url_fingerprint` is a persisted-key change for two input shapes.
3647 The digest is serde-serialized into `ProviderCatalogCache` and
3648 `LiveOffering`, pricing defect receipts, and
3649 `TurnRecord.routed_usage_source_ids` — it is not an in-memory-only cache
3650 label. Empty or whitespace-only values (and scheme-less query-only strings
3651 that strip to an empty authority) now hash the invalid-or-secret-bearing
3652 sentinel instead of SHA-256 of the empty string. Scheme-less URLs that
3653 contain `@` now strip `userinfo` before hashing, matching the
3654 scheme-bearing branch, so a typed `user:pass@host/v1` no longer embeds the
3655 password in a stored digest. `routed_usage_source_fingerprint` feeds
3656 arbitrary scheme-less source ids into the same function, so a turn
3657 rehydrated from an older build can fail to dedupe one routed-usage row.
3658 Recovery is a cache miss and a re-fetch, not corruption. Empty input was
3659 not restored to the old digest: an empty authority is not a usable
3660 endpoint, and mapping it to the same sentinel the scheme branch already
3661 uses for an empty host keeps invalid inputs from minting a unique cache
3662 scope.
3663
3664 - Diagnostic lines that mention token *counts* are no longer swallowed by
3665 secret redaction. A stream error such as `max tokens = 8192 but budget =
3666 4096` was matching the `token` hint as a substring of the English word
3667 `tokens`, and the spaced-assignment pass then dropped the rest of the
3668 line, leaving `max tokens = [redacted]`. Token counts are not credentials;
3669 the hint now matches a credential identifier (`token`, `api_token`) rather
3670 than an English word, so the numbers survive while `token = Bearer …` is
3671 still redacted.
3672 - Dashboard thread search no longer loads every thread's transcript to decide
3673 whether the row matches. `GET /v1/threads/summary?search=` walked the full
3674 thread list and called `get_thread_detail` on each row before matching, and
3675 that detail read is itself a whole-store walk of every turn JSON and every
3676 item JSON. A non-matching keystroke was therefore
3677 O(threads × (all_turns + all_items)) file reads — on the order of 10^8 JSON
3678 parses at a few thousand threads. Search now matches `id`, title, and model
3679 from the thread record (and, when the title is unset, the single latest-turn
3680 file that supplies the displayed title) and loads detail only for matches, so
3681 preview stays a display field rather than a search key. Session summary
3682 already refused to search last-message text for the same reason.
3683
3684 - Silent `#[allow(dead_code)]` suppressions on the modules AGENTS.md warns
3685 auditors not to delete — prompt zones, context budget, the route seam —
3686 and on the next-largest holders (palette tokens, hotbar actions, core
3687 events) are now `#[expect(dead_code)]`, or gone where the lint was already
3688 stale. A suppression that stops matching the lint fails the `-Dwarnings`
3689 gate instead of sitting quiet. The same gate is recorded in
3690 `[workspace.lints]` so member crates inherit it from the manifest rather
3691 than only from CI `RUSTFLAGS`.
3692 - "missing key" now says where it looked. The provider picker reported
3693 credential readiness as the bare strings `missing key` / `key:not-set`,
3694 which named no source at all — so a home whose secret store held a working
3695 DeepSeek key could show `DeepSeek missing key` in the picker while a real
3696 turn from that same home completed, and nothing on screen said which layer
3697 disagreed. Every row now resolves through one sourced resolver and states
3698 the place its credential came from ("OPENROUTER_API_KEY", `secret store
3699 "deepseek"`, `[providers.x] api_key`, "xAI OAuth", a consented external CLI
3700 file); a row without a credential lists the places that were probed, in
3701 precedence order, and the command that fixes the first of them. Where a
3702 durable slot is deliberately *not* read — an inactive provider whose config
3703 table carries no api-key marker — the row says so rather than implying an
3704 empty slot.
3705
3706 - Provider credential precedence is now stated once, in a doc comment beside
3707 the single resolver that enforces it, instead of being implied by a
3708 150-line cascade of provider special cases. No precedence decision changed:
3709 `has_api_key_for` is now a wrapper over that resolver, and a test asserts
3710 the two agree for every provider.
3711
3712 - Credential saves and logouts no longer interleave. Both took a snapshot of
3713 the durable slot, wrote it, mutated the config document, and rolled back on
3714 failure, with no lock held across the sequence — so a save racing a logout
3715 on the same slot could leave the secret store and the config file
3716 disagreeing. Both now hold that provider's credential write lock for the
3717 whole read-modify-write.
3718
3719 Design ported from pi-mono (MIT, Copyright (c) 2025 Mario Zechner); see
3720 `docs/THIRD_PARTY_NOTICES.md`.
3721
3722 - Enumerating stored credentials no longer fails closed on one bad slot.
3723 Listing used to propagate a backend read error, so a single unreadable
3724 secret-store entry made `/provider` and logout treat every other stored
3725 credential as missing. Enumeration now skips the unreadable slot and
3726 continues, matching the probe loop it replaced.
3727
3728 - The first screen of first run no longer cuts its own headline. The welcome
3729 and ready titles, and the provider-step heading, were emitted as single
3730 unwrapped lines while the sentence beneath them wrapped, so at 40 columns
3731 German read "Codewhale arbeitet mit dir in diesem O", Russian lost its final
3732 stop, and Japanese lost "します。". Headings are prose and now wrap like it,
3733 in every shipped locale.
3734
3735 - The workspace-trust screen no longer cuts its own question in half on a small
3736 terminal. The question, the prompt-injection risk hint, and the trust-effect
3737 hint were each pushed as one unwrapped line, so at 40 columns the screen read
3738 "Should Codewhale work with the instruc" — severed mid-word with nothing
3739 marking the cut, while the workspace path directly beneath it wrapped
3740 correctly. Asking someone to grant filesystem trust while the question itself
3741 is truncated is the worst place in the product for that to happen. All three
3742 now wrap through the same helper the rest of onboarding uses, which also
3743 means they wrap correctly in Japanese and Chinese. Verified across all
3744 fifteen shipped locales at 40, 60, 80 and 120 columns.
3745 - `codewhale completions <shell>` generated a script for the wrong program.
3746 The subcommand forwarded to the in-tree `codewhale-tui` binary, which
3747 rendered completions from *its own* clap tree under *its own* name, so the
3748 output ended in `complete -F _codewhale__tui ... codewhale-tui` (bash),
3749 `#compdef codewhale-tui` (zsh), and
3750 `Register-ArgumentCompleter -Native -CommandName 'codewhale-tui'`
3751 (PowerShell). Sourcing it registered nothing for `codewhale` or `codew` —
3752 the two commands current installers expose — so tab completion appeared to
3753 do nothing. The forwarded tree was also stale against the real CLI: it offered
3754 `pr`, `scorecard`, and `session-diagnostics`, which `codewhale` does not
3755 have, and omitted `run`, `rc`, `config`, `model`, `thread`, `lane`,
3756 `workflow`, `web`, `account`, `app-server`, `mcp-server`, `metrics`,
3757 `update`, `cloud`, `completion`, and `lane-log-proxy`, which it does.
3758 Completions are now rendered in-process from the CLI's own command tree,
3759 and `completions` is an alias of the existing
3760 `completion` subcommand rather than a second, divergent path. Regenerate any
3761 script you installed from an earlier release. Reported by **RepentStar**
3762 (#5526); part of the `deepseek-tui`-era identifier retirement in #5443.
3763
3764 - Completion scripts now fire for the `codew` shorthand as well as
3765 `codewhale`. Releases publish `codew` as a byte-identical copy of the
3766 `codewhale` binary, so a script bound to only one of the two names was half
3767 installed for anyone who types the short one. Each shell gets its own
3768 idiomatic hook rather than a second copy of the script: bash re-binds the
3769 generated function, zsh widens the `#compdef` tag line to
3770 `#compdef codewhale codew`, fish adds `complete -c codew -w codewhale`,
3771 PowerShell registers `-CommandName 'codewhale','codew'`, and Elvish aliases
3772 the completer with
3773 `set edit:completion:arg-completer[codew] = $edit:completion:arg-completer[codewhale]`.
3774
3775 - Documented shell completions. `docs/INSTALL.md` § 8 now gives the generate
3776 and install commands for bash, zsh, fish, PowerShell, and Elvish, with a
3777 note to regenerate after upgrading and to delete scripts produced by
3778 v0.9.10 or earlier. There was previously no completion documentation
3779 anywhere in the repository, which is how #5526 was reported as three
3780 problems instead of one.
3781 - `/status` was 31 rows. On an 80x24 terminal the transcript viewport is 18, so
3782 typing `/status` landed you on the *tail* of the report: the version, route,
3783 directory, mode and sandbox rows had already scrolled past, and what stayed on
3784 screen was five `not reported` rows and a `$0.0000`. The report is 18 rows on a
3785 fresh session — `Window override:` is present unless the value is already
3786 configured. That is the viewport's height, so once `/status` itself occupies a
3787 history cell the title row still scrolls off; it does not fit that terminal
3788 whole. Provider, model and reasoning effort are one `Route:` lockup, the way
3789 the header rail already writes them. Mode and its permissions are one statement
3790 of posture. `Rate limits:` is gone — it was a `push_row` of a string literal
3791 and could never say anything but "not available from provider telemetry". The
3792 per-turn token ledger is gone too, because `/tokens` is that ledger's whole
3793 subject and `/status` was printing six rows of it at the same weight as the
3794 sandbox policy; the two facts that lived nowhere else, the cumulative in/out
3795 split and the cumulative cache totals, survive on one `Session tokens:` row.
3796 `Footer items:` no longer prints ten internal config keys across the full
3797 width — `/statusline` owns them, and the report now points there in the same
3798 row that points at `/tokens`. Two blank gutters do the grouping; the
3799 `===================` rule under the title is gone.
3800
3801 - The `/status` window-override key has its own labelled row. It used to be
3802 parenthesised onto the end of the provenance row, which pushed
3803 `context_window in config.toml` past the right edge at 80 columns and wrapped
3804 the sentence. `Window source:` states the provenance and `Window override:`
3805 names the exact key — and the override row is omitted entirely when the value
3806 is already configured, rather than advising you to set what you have set.
3807
3808 - `/help` no longer truncates anything. Every label and description used to run
3809 through a `truncate_to_width` that appended `…`, which in a two-hundred-row
3810 list promises text no keystroke can reveal and lands mid-token:
3811 `(aliases: /qin…` left the parenthesis hanging open. Descriptions now shed
3812 whole fields — the alias parenthetical first, then trailing clauses at their
3813 own joints, and only where there is no joint at all, the sentence's short form
3814 on a whole word with no mark, keeping the head noun of a simple verb +
3815 modifier + noun phrase rather than the adjectives that qualified it. The
3816 focused row's description is restated under the filter at the panel's full
3817 width, *only when the row itself could not hold it*, so a wide terminal does
3818 not say the same sentence twice. At 60 columns that restatement is itself
3819 shed — the `/advisor` detail stops before `session` — so the detail is longer
3820 than the row, not a copy of the original sentence.
3821
3822 - The `/help` label column is measured instead of assumed. It was a flat 28
3823 columns at every terminal size, so at 60 columns twenty blank cells sat
3824 between `/advisor` and a description cut down to 21. Each group now sizes its
3825 column to the labels it actually holds, which nearly doubles the description
3826 column on a narrow terminal, and the label — the string you have to type —
3827 reads one step brighter than the description that qualifies it.
3828
3829 - `/help` stopped spending rows on itself. The match count moved onto the filter
3830 row it describes, the blank spacer under it is gone, and the footer no longer
3831 repeats `type to filter` while the filter box says `Type to filter` two lines
3832 above — at 60 columns that duplicate was what pushed the footer onto a second
3833 row. A group header also stopped printing `▸ ▾`: the selection cursor and the
3834 collapsed chevron are the same glyph, and a focused collapsed group was
3835 showing it twice for two different facts. Help now opens focused on the first
3836 entry rather than the header above it.
3837
3838 - The bottom status rail is no longer one run-on sentence. At 120 columns it
3839 read `▌· idle · Ollama · deepseek-v4-flash · max · Anonymous usage counts are
3840 on. … ⌥V:output · /context:context · fn+F1:keys` — live state, route
3841 identity, a telemetry consent notice, and keyboard hints all strung together
3842 by the same middle dot in the same ink, so nothing was grouped and the eye
3843 had nothing to skim by. At 80 columns it simply stopped mid-notice, and at 60
3844 the row overflowed and was clipped by the terminal mid-word. The rail now
3845 divides its groups with a blank gutter instead of another dot (the dot is
3846 kept for peers *inside* a group), the model name reads one step brighter than
3847 the qualifiers that narrow it, and `Esc to interrupt` reads in the same hint
3848 weight as the right-hand chords rather than in the separator weight.
3849
3850 - Nothing on the status rail is ever truncated now. A notice sheds whole
3851 sentences to fit, and if one sentence is still too long it sheds at the inner
3852 joints — a colon, a semicolon — with the trailing mark cut so the phrase that
3853 survives does not itself advertise that more was coming. Route identity sheds
3854 the provider, then the reasoning effort, rather than rendering
3855 `deepseek-v4-flash-prev…`; a clipped model name is worse than no model name
3856 because routes share prefixes. Clauses rejoin without a Latin space after a
3857 full-width stop, so the Japanese receipt reads as Japanese.
3858
3859 - A notice now stands the standing facts down instead of queueing behind them.
3860 Route identity and the ledger chips are still there in ten seconds; the
3861 notice is not, so it takes the row and the key hints yield last. This is what
3862 makes the telemetry receipt readable at 80 columns, where it used to be
3863 simultaneously always present and never legible.
3864
3865 - The status rail no longer advertises `/context:context`. It was spending
3866 eighteen columns of a 24-row screen to name a slash command that announces
3867 itself the moment you type `/`; the rail advertises chords you cannot
3868 discover any other way. The rail now reads the same at 80 columns as at 200.
3869
3870 - The idle screen no longer has an absolute path stretched across it. The
3871 workspace caption between the wordmark and "What do you want to accomplish?"
3872 was composed at full length and then truncated to the lane width, which made
3873 the centering inset `(width - caption.width()) / 2` evaluate to zero — so a
3874 line that was written to be centered rendered flush-left and full-bleed,
3875 cutting the centered whale/wordmark/prompt composition in half. The clipping
3876 also destroyed the information it was supposed to carry: at 80 columns the
3877 line read `/private/tmp/claude-501/-Volumes-.../34267917-11f4-4d15-911a-…`,
3878 which tells the reader nothing about where they are. The caption now sheds
3879 detail instead of being cut — MCP count first, then branch, then leading path
3880 components — so it always fits with room to center, and the folder you are
3881 standing in is the last thing to go. Elisions land on a path separator rather
3882 than mid-directory.
3883
3884 - Removed the placeholder engine tree in `crates/core/src/engine/`. Its
3885 `Engine::run` accepted `Op::SendMessage`, appended to a journal, and emitted
3886 `TurnComplete { status: "completed" }` without ever contacting a model, and
3887 `TurnExecutor` was a struct with a field-copy constructor and a
3888 `step < max_steps` comparison. Nothing in the workspace referenced any of it —
3889 the only mention of `codewhale_core::engine` anywhere was a doc comment inside
3890 the tree itself — but its comments ("the real turn loop is wired here in the
3891 next slice") were what `docs/ARCHITECTURE.md` leaned on to claim that
3892 `crates/core` owns the agent loop. There is now exactly one turn loop in the
3893 workspace, `Engine::run_turn`, and a guard test fails if a second one appears.
3894 `docs/ARCHITECTURE.md` and `AGENTS.md` now say where it actually lives.
3895
3896 - First-run onboarding no longer silently truncates its explanation in
3897 languages that do not put spaces between words. `wrap_words` split on
3898 whitespace, so a Japanese sentence arrived as a single token, the
3899 line-break check (which only fires once a line is non-empty) never
3900 triggered, and the over-wide line was clipped by the terminal. At 80
3901 columns the provider screen read
3902 "Hosted providers need a key, but loca" and stopped — losing exactly the
3903 half that tells the reader local runtimes need no key, on the screen where
3904 they choose a provider. Space-less scripts now break by display width on
3905 grapheme clusters, and a line may not begin with closing punctuation
3906 (`。`, `、`, `」`, `)` and friends). Wrapping for languages that do use
3907 spaces is unchanged.
3908
3909 - Project instructions are bounded by one budget and no longer treat other
3910 agents' files as law by default. Previously `.claude/instructions.md` and
3911 `CLAUDE.md` sat at ranks 2 and 3 of the canonical instruction list — *above*
3912 Codewhale's own `.codewhale/instructions.md` — `.claude/rules/` was an
3913 auto-discovered rules directory, and `.cursorrules`, `.cursor/rules`,
3914 `.clinerules`, `.windsurf/rules`, `.gemini`, `.github/copilot-instructions.md`
3915 and `.github/muse-instructions.md` were all imported into the system prompt
3916 with no opt-in. Dropping a `CLAUDE.md` written for a different tool into a
3917 repository silently made it standing authority here, which is an injection
3918 surface rather than a convenience. Codewhale now reads `AGENTS.md`, the
3919 cross-agent `.agents/AGENTS.md`, and its own instruction files by default;
3920 every other agent's format is opt-in by name through
3921 `project_instruction_imports` (env `CODEWHALE_PROJECT_INSTRUCTION_IMPORTS`),
3922 imported files rank *below* Codewhale's own, and a workspace that contains an
3923 un-imported format says so in a warning naming the exact setting.
3924 - Separately, a symlinked candidate rules directory — `.cursor/rules`,
3925 `.windsurf/rules`, or `.gemini` pointing outside the workspace — was
3926 traversed and its contents imported as instruction authority, because the
3927 directory check followed the link while only the files inside it were
3928 checked. The two instruction loaders now apply the same no-follow rule that
3929 `.codewhale/rules/` already had.
3930 - The three separate ceilings on standing instructions (200 KiB for the
3931 root->workspace chain, 500 KiB for the rules block, 40 KiB for imported
3932 fragments, and a global layer that was merged in after the chain budget had
3933 already closed and so counted against nothing) are replaced by a single
3934 48 KiB aggregate budget covering all of them together. Instructions claim it
3935 before rules, and are trimmed from the broadest scope inward so the
3936 nearest-scope file is the last thing dropped rather than the first thing
3937 stranded. Truncation still leaves an explicit marker.
3938
3939 - Editing the workspace no longer grants the shell outbound network access.
3940 `workspace-write` sandboxes are created network-restricted; `curl`, package
3941 installs, and `git fetch` inside a sandboxed shell are denied by the OS
3942 sandbox unless network is granted explicitly. This closes a real gap rather
3943 than tightening a working boundary: the elevation added in #273 was justified
3944 by the application-level `NetworkPolicy` remaining "the only outbound
3945 boundary", but that policy governs `fetch_url`, `web_search`, and MCP HTTP
3946 and never constrained shell subprocesses, so workspace-write turns had
3947 unrestricted egress with nothing enforcing anything. Network now comes from
3948 one of three explicit places: the new `sandbox_network_access` config key
3949 (also `CODEWHALE_SANDBOX_NETWORK_ACCESS`), a `danger-full-access` posture, or
3950 the existing post-denial elevation prompt that grants network for a single
3951 call. Yolo and `--yolo`/Bypass are unchanged — they resolve to
3952 `danger-full-access`, which applies no sandbox at all. `external-sandbox`
3953 reports the network it was actually granted instead of hardcoding `true`, and
3954 `/status` reads the flag instead of printing "network on" for every
3955 workspace-write policy. Platforms with no sandbox backend (default Linux
3956 without bubblewrap, and Windows) still enforce nothing, and both `/status`
3957 and `doctor` continue to say so.
3958
3959 - The nightly Windows ARM64 artifact build works again. Every nightly from
3960 2026-08-16 failed while compiling `codewhale-tui`, deterministically on the
3961 same codegen unit across all three build attempts, with
3962 `thread 'optimize module codewhale_tui...-cgu.13' has overflowed its stack`.
3963 The trigger is stack depth in the LLVM worker threads that run per-codegen-unit
3964 optimization, not the workflow's `lto=off` override: holding the crate and
3965 every flag fixed and varying only `RUST_MIN_STACK` on aarch64 shows 1 MiB
3966 crashes rustc while 2 MiB and 4 MiB succeed. Unix std defaults to 2 MiB and
3967 passed; the Windows ARM64 runner sat under the requirement. Nightly now sets
3968 `RUST_MIN_STACK` explicitly for every target, because the requirement follows
3969 from the size of `crates/tui` rather than from the platform. The redundant
3970 `codegen-units` override is gone -- `[profile.release]` already sets 16, so
3971 restating it never changed anything. Shipped binaries were never affected;
3972 `release-artifacts.yml` builds `--profile dist` with fat LTO and
3973 `codegen-units = 1`.
3974
3975 - Test debt: the transcript history-cell suite has been rebuilt. It was 123
3976 tests across 3,964 lines, and about a third of it pinned the current skin
3977 rather than any behavior -- `assert_eq!(spans[1], "⣤")` for the
3978 reduced-motion marker, `title_span.style.fg == theme.tool_title_color`,
3979 `visible[1] == "▏ done: scan repo"`, four separate tests each asserting one
3980 shape of fenced code never takes the transcript rail, and one test whose
3981 only assertion was `!text.is_empty()` under a name promising it checked the
3982 rendered tool id. Assertions like those break on every legitimate visual
3983 change and catch nothing a reader of the transcript would notice, which is
3984 the liability `d64b9429b` named. The replacement is 40 tests, each named
3985 for the property it protects and asserting the property instead of the
3986 token: reduced motion is checked by rendering the same running card at two
3987 different elapsed times and requiring the frames to match -- which also
3988 catches an animation leak the glyph constant missed -- and a frozen marker
3989 must stay visible rather than landing on the spinner's invisible blank
3990 (U+2800). Severity colors are checked by requiring warning not to read as
3991 error rather than by naming a palette entry. A streaming assistant glyph
3992 must actually pulse when motion is allowed, checked against
3993 `pulse_brightness` rather than by sleeping on the 2s sine. Each of the
3994 invariants claimed was verified to fail the new suite when deliberately
3995 broken in the renderer.
3996 ## [0.9.10] - 2026-08-19
3997
3998 - Show the full slash-command or `/model` completion row in a bounded, wrapping hover popover whenever narrow terminals truncate it, closing the remaining scoped gap from [#998](https://github.com/codewhale-hq/CodeWhale/issues/998). Thanks [@AiurArtanis](https://github.com/AiurArtanis) and [@formp3](https://github.com/formp3) for identifying the affected surfaces.
3999 - `registry_sync` no longer ships the full MCP Registry catalog into the
4000 conversation. It takes a required query, scores the local snapshot
4001 host-side, and returns at most eight matches; the complete catalog stays on
4002 disk, and the compaction and spillover exemptions that let a multi-hundred-
4003 kilobyte dump reach the model unchanged are gone.
4004 - Providers that mirror the outgoing `(reasoning omitted)` replay placeholder
4005 back as a reasoning delta no longer have that echo ingested as real
4006 thinking: the exact transport placeholder is dropped on arrival, so live
4007 sessions stop showing a stream of placeholder reasoning blocks and saved
4008 transcripts stay free of them.
4009 - Mid-stream connection drops during an interactive turn no longer persist a
4010 synthetic `[runtime]` user message. Retry state is a typed engine-internal
4011 descriptor; a thinking-only drop re-issues the request without claiming a
4012 partial reply was preserved, the retry budget is enforced in mechanism, and
4013 recovery produces exactly one authoritative final answer.
4014
4015 Codewhale v0.9.10 is a retention, identity, and product-clarity release: the shell and
4016 transcript can no longer retain unbounded tool output in memory or on disk,
4017 mid-turn history inserts no longer strand in-flight tool rows, every agent
4018 that ran this session is visible from `/agents list`, the PTY acceptance
4019 lane has a stall watchdog and bounded CI steps, approval outcomes are
4020 durable and fail closed (cyq1017, #5360), and three $HOME disk leaks are
4021 reclaimed. Extension surfaces now name their real state and act only
4022 through the reviewed install and trust flows, and sub-agent, shell, task,
4023 and workflow state is owned by the session that created it (#5518). Test
4024 threads get an 8 MiB stack so the lib suite can no longer
4025 abort under load.
4026
4027 ### Fixed
4028
4029 - First run starts on the welcome screen again. A missing key no longer
4030 skips Welcome and auto-opens the local-provider list: Enter walks to the
4031 calm provider explanation, then Enter opens the picker so a first API key
4032 can be set. Returning missing-key recovery still opens the picker on
4033 launch.
4034 - A foreground `bash` command that named no timeout is bounded again. The
4035 model-facing `bash` tool left an omitted `timeout_ms` at the internal
4036 ceiling (~24.8 days) instead of the 120 s default its own schema
4037 advertises, so a CLI that blocked on an interactive prompt or a hung
4038 network call held the turn open indefinitely — one report sat on a single
4039 unauthenticated CLI call for over two hours with the tool row simply
4040 counting seconds. The advertised default now applies, which arms the
4041 existing recovery: the process is killed and the model is told to rerun
4042 with `background=true` and poll with `action="wait"`. An explicit
4043 `timeout_ms` is still honored for genuinely long foreground work, and
4044 background and interactive runs keep their own lifetimes.
4045 - The Extensions (`/plugin`) Marketplace is no longer a read-only list.
4046 Every recommendation and stored candidate names its truthful state and
4047 primary action — Add, Enable, Configured, or Unavailable — and Enter or a
4048 mouse click runs that action through the existing reviewed `/mcp add
4049 recommended`, `/mcp enable`, and `/plugin` install/trust controllers, so
4050 no second trust path exists. Browser Use and Sandbox Runtime stay
4051 honestly Unavailable with their real setup routing instead of implying an
4052 install Codewhale cannot perform.
4053 - The Extensions MCP tab now renders one honest inventory: the header count
4054 and the visible rows derive from the same configured-server set, so
4055 `MCP (6)` can no longer sit above two rendered rows. Disabled servers
4056 stay visible and labeled disabled instead of silently disappearing, and
4057 configured servers absent from the live snapshot list as not-yet-inspected
4058 with their own explicit reload affordance through the MCP command
4059 controller.
4060 - Installed plugin rows now act on their real state: Enter opens an active
4061 bundle (`/plugin show`), offers Enable for a trusted-but-disabled bundle,
4062 or routes an untrusted bundle to the existing trust review — through the
4063 same confirmation and persistence controllers as the slash commands.
4064 - Sub-agent handoffs and rosters, background shell jobs, durable tasks,
4065 delayed continuations, and workflow controls are now scoped to the
4066 session that owns them. Records carry immutable root-session ownership,
4067 stale completion-channel payloads are rejected before deduplication,
4068 background work drains and reports only to its owning session, and
4069 legacy ownerless jobs fail closed (#5518 failure class reported by
4070 @hxfhd; the report's exact JavaScript provenance was not claimed as
4071 reproduced).
4072 - The resolved route envelope now reaches every outbound model call: all
4073 wire dialects and auxiliary calls clamp at the shared transport seam
4074 under one wire/reservation budget, provider input limits are honored, and
4075 switching models on the same protocol no longer inherits the previous
4076 model's limits (#5516, #5518).
4077 - First-run continuity: the chosen onboarding provider persists across
4078 restarts, a missing first-run config no longer interrupts the flow, and
4079 the automatic working-agreement checkpoint renders as a standalone setup
4080 handoff instead of regressing the onboarding rail to the full wizard's
4081 4/10 progress.
4082 - Explicitly worded natural-language `/goal` declarations now create a
4083 durable goal in the provider-neutral engine before model dispatch, while
4084 ordinary tasks and quoted transcripts stay out of goal mode and prose
4085 acknowledgement alone can no longer stand in for goal creation.
4086 - `/model` now keeps the current Z.ai default (`GLM-5.3`) visible when an
4087 older installation has an explicit `GLM-5.2` route saved. The saved 5.2
4088 route remains exact; choosing 5.3 sends and remembers the distinct 5.3 ID.
4089 - The constitution checkpoint now leads with the bundled balanced agreement;
4090 the default path writes no custom constitution. The startup launch surface
4091 distinguishes read-only Chat from folder-bound, approval-gated Work.
4092 - Tabby and other IME bridges no longer observe a stale visible caret while a
4093 frame diff is being painted; Codewhale hides the cursor during the diff,
4094 restores the canonical composer cell, and only then reveals it again
4095 (BrathonBai, #5023).
4096 - Pre-header HTTP/2/SSE transport failures get one bounded HTTP/1.1 retry;
4097 authentication, provider-semantic, response-body, and already-pinned HTTP/1
4098 failures remain fail-closed (demian-welt, #4683).
4099 - MCP `tools/call` images now travel as bounded typed content instead of
4100 leaking base64 through model-visible JSON. Direct and parallel calls share
4101 the same MIME, size, validation, and one-image boundary (PR #5515 by
4102 @cacdcaecawae).
4103 - Linux npm installs and updates race GitHub Releases against the CNB mirror
4104 at the checksum-manifest layer, then download from the first verified source
4105 without making users wait through a doomed slow-source timeout.
4106 - `CODEWHALE_PREFER_BWRAP` now applies the documented Linux sandbox override,
4107 and Codewhale-era names own build metadata, hook session/tool-call IDs, and
4108 sandbox child markers. The corresponding `DEEPSEEK_*` names remain as 0.9.x
4109 compatibility aliases (#5443).
4110 - Windows default launch prefers Windows Terminal: zip archives ship
4111 `codewhale.bat` (CRLF, `wt.exe` then the exe), `install.bat` copies that
4112 launcher, and the NSIS Start Menu shortcut opens it instead of the raw
4113 binary (#1854).
4114 - `fix(tui): make the header status mark honour its setting` — `status_indicator`
4115 did nothing for three of its four documented values. The header hardcoded a
4116 leading `cw` span *and* asked for a second mark beside the effort chip, then
4117 filtered the second one against the literal `"cw"`; because `cw`, the legacy
4118 `whale` opt-in, and every unknown value all normalize onto that same mark,
4119 the filter discarded them and left `off` with nothing to turn off. `cw`,
4120 `whale`, `off`, and a typo all rendered byte-identical headers. There is one
4121 mark now and the setting owns it: `cw`/`whale` draw the typographic mark,
4122 `dots` draws the activity frames, `off` removes it (thejayjetson, #5512).
4123 - `fix(tui): rebase active-cell tool bindings on every mid-turn history
4124 insert` — `/rename` mid-turn left the running tool row spinning forever
4125 (#5478).
4126 - `fix(tui): bound what the shell and transcript retain from tool output` —
4127 a 1.1 MB Bash call kept over a megabyte resident for up to an hour; raw
4128 streams now cap at 16 MiB in flight and release delivered output, and
4129 retained tool outputs cap at 64 KiB per record / 8 MiB per transcript
4130 (#5472).
4131 - `fix(tui): reclaim the three $HOME disk leaks` — orphaned session dirs,
4132 the unbounded audit.log, and stranded writer temp files.
4133 - `fix(tui): persist approval outcomes before execution` (cyq1017) —
4134 approval receipts are committed to a session-owned log before execution
4135 proceeds; unpersistable evidence blocks the tool; resume reconstructs
4136 closed and interrupted approvals (#5360).
4137 - `test(tui): break the LazyLock/env-barrier deadlock in the test harness`.
4138 - `ci: give test threads the 8 MiB stack they need` — the lib suite aborted
4139 with SIGABRT under load on the default 2 MiB stack.
4140 - YOLO entry points honor a locked approval policy: `--yolo`, `/mode yolo`,
4141 `/zidong`, and Alt+Y can no longer set Full Access + trust + shell when
4142 config or managed requirements own the posture.
4143 - Terminal PTY tools fail closed without a sandbox backend under a narrowed
4144 filesystem posture, and otherwise start `$SHELL -i` through
4145 `SandboxManager::prepare` like `bash`.
4146 - Skill update refuses to replace a directory that has no `.installed-from`
4147 marker — same ownership gate plugins already used.
4148 - `cp`/`mv` are workspace-safe only when every path operand stays inside
4149 the workspace — Auto-Review no longer auto-allows `cp /etc/passwd .`.
4150 - Main CI no longer shares one concurrency group per branch: each SHA
4151 gets a verdict instead of a cancelled pending run. A hermetic Safety
4152 gate job runs authorization tests in under 15 minutes (test bankruptcy
4153 restructuring — no tests deleted).
4154 - Config-fixture tests no longer honor `lock_test_env` as a license to
4155 read a populated `~/.codewhale/config.toml`; they need an `EnvVarGuard`
4156 like settings already did. Safety-gate and CNB workspace tests pin a
4157 hermetic `CODEWHALE_HOME`. `exec_persistent_service` is serialized in
4158 nextest and inside the cargo-test binary instead of dropped (#5355).
4159 - Short CLI no longer waits up to three seconds for a telemetry POST on
4160 exit; `session_end` is recorded and the buffer ships on the next
4161 interactive session.
4162 - Bare `/` now opens a deliberately small starter set: `/help`, `/setup`,
4163 `/model`, `/settings`, `/resume`, and `/rc`. The full command inventory
4164 remains searchable through `/help`, the command palette, and direct prefix
4165 typing, without front-loading the entire control surface (#5442, #5439).
4166 - First run now asks only for decisions needed to become usable, keeps the
4167 offline route explicit, and leaves optional provider, tools, policy, and
4168 appearance work in the progressive `/setup` repair guide. The idle aquarium
4169 asks one task-oriented question instead of advertising a tutorial or command
4170 billboard, and the localized telemetry choice appears after the workspace is
4171 ready without blocking the composer.
4172 - Provider, active model, and reasoning effort moved out of the crowded header
4173 into a quiet, width-aware footer identity. Compact layouts keep model and
4174 effort before provider detail and shed whole low-priority groups instead of
4175 clipping the composer or control hints.
4176 - The model picker no longer re-parses `~/.codewhale/config.toml` once per
4177 provider when deciding who has a saved key.
4178
4179 ### Added
4180
4181 - `/workflows` opens a live run dashboard over this workspace's durable
4182 workflow journal: every retained run with status, phases, child roster,
4183 progress, and host-side cancel — observation only, it never launches a run.
4184 - Repository instructions now assemble from the actual containing checkout:
4185 applicable `AGENTS.md` files resolve repository-root to current-directory in
4186 order under one aggregate budget, a linked worktree is its own root, and
4187 scope is never inferred from path mentions or whichever branch is named
4188 `main`.
4189 - `/goal` is a codex-style control plane: setting an objective dispatches it
4190 to the engine, which owns the goal and starts the first goal turn itself —
4191 the objective is never echoed back as the user's own message, pause/resume
4192 are real control ops, and the hunt-era vocabulary and trophy cards are
4193 gone.
4194 - `/extensions` and `/plugins` open one localized inventory for Hooks,
4195 Plugins, local Marketplace catalogs, Skills, and MCP. Reviewed suggestions
4196 include Playwright, Chrome DevTools, Cua Computer Use, Browser Use, and the
4197 sandbox runtime without granting trust or installing anything on open.
4198 - Turn Inspector now opens the newest turn and pages across complete recorded
4199 user, reasoning, tool/subagent, and assistant output with page-scoped search,
4200 copy, and export (sky-sun-moon, #1682).
4201 - Background tasks have bounded incremental persistence, durable terminal
4202 reasons, truthful timeout/cancellation receipts, restart recovery, and
4203 interruptible continuous-goal delays (#5497, #5508).
4204 - `/title` once again controls the terminal window title independently from
4205 `/rename`, survives session save/load, and sanitizes control, bidi, and
4206 zero-width characters (PR #5509 by @SparkofSpike).
4207 - MCP snapshots preserve whether capabilities were advertised by the server,
4208 discovered through the bounded legacy fallback, or not observed (#4170).
4209 - `codewhale auth status --diagnostic` reports canonical paths, isolation
4210 source, backend class, and value-free provider-source presence without
4211 opening credential stores or creating/migrating state (#2369).
4212 - `codewhale doctor --probe-search` performs an explicit credential-free,
4213 policy-checked transport probe for the selected search provider; ordinary
4214 doctor and JSON output remain offline (#5442).
4215 - The safe deferred `read_media` tool is available to supported read-only
4216 roles, and history receipts distinguish localized tool execution outcomes
4217 without exposing raw payloads (#5102).
4218 - **npm Linux x64 first-party source selection.** The wrapper concurrently
4219 fetches the GitHub Releases and CNB checksum manifests for the exact
4220 package version, locks the first source whose HTTP response and manifest
4221 validate, and downloads binaries only from that source. Explicit
4222 `CODEWHALE_RELEASE_BASE_URL` / `CODEWHALE_USE_CNB_MIRROR=1` still skip the
4223 race; other targets stay on GitHub.
4224 - `/workflow <objective>` and `/workflow run <path>` now produce a bounded,
4225 tool-less proposal for review. Only `/workflow confirm` can launch that
4226 reviewed draft; status, cancel, settings, and the `/workflows` dashboard stay
4227 host-owned and do not spend a model turn (#5439).
4228 - `feat(tui): add cancellable cadence to continuous goals` (M-Maciej) —
4229 `[goal] continuation_delay_seconds` gives coordinator goals a visible quiet
4230 period between successful turns while reusing the existing coalesced goal
4231 continuation token; Esc, Ctrl+C, pause/done/blocked/clear cancel before the
4232 next provider request, and failures never continue (#5508).
4233 - `feat(tui): add command context adapters and migration gate (FEAT-015)`
4234 (aboimpinto) — TUI-owned capability facets, a dual-path dispatch seam, and
4235 source-aware CI enforcement so a command slice cannot claim to be migrated
4236 while it still accepts concrete `App`. Zero production commands migrate in
4237 this slice (#5316).
4238 - `feat(web): move docs/hooks and docs/troubleshooting onto the dictionary
4239 spine` (Lstarsky0) — both pages now read copy from the locale dictionaries
4240 instead of inline bilingual literals (#5337).
4241 - `feat(web): move docs/constitution and docs/runtime-api onto the dictionary
4242 spine` (Lstarsky0) — both pages now read copy from the locale dictionaries
4243 instead of inline bilingual literals; another incremental phase of #5337,
4244 not completion of the full epic (#5517).
4245 - `docs(i18n): complete Tier 1 of Chinese docs localization` (SparkofSpike) —
4246 Chinese and Indonesian docs move to `docs/zh_hans/` and `docs/id/`, with
4247 redirect stubs at the old paths for one release cycle (#5482).
4248 - `feat(tui): show repository context in git chrome` (wuisabel-gif) — the TUI
4249 header now identifies the active repository or linked worktree before the
4250 branch and dirty marker, so operators can see where the agent is working
4251 without opening the worktree manager (#5437).
4252 - `feat(tui): formalize the status-bar color grammar` — seven semantic
4253 families live in `docs/design/STATUS_BAR_COLOR_GRAMMAR.md` and
4254 `palette::grammar`; header and phase-strip ink resolve through named
4255 `ChromeInk` slots so chrome cannot invent an eighth meaning or spend
4256 Failure red on a dirty worktree or selected mode. The footer's session
4257 metrics strip resolves through the same inks, and the red reservation is
4258 checked against every selectable theme, not just the whale default;
4259 typed footer toasts resolve through the grammar too.
4260 Repo/worktree chrome stays metadata and still renders when Git names a
4261 location but not a ref (#5437).
4262 - `feat(tui): first slice of the agents roster` — every agent that ran this
4263 session, receipts-only, via `/agents list` and the sidebar fan-out rows
4264 (#5479 spec items 1 and 5).
4265 - `ci: bound PTY acceptance and add a stall watchdog to the harness` —
4266 QA_PTY_STALL_TIMEOUT_SECS aborts a wedged PTY run with a diagnostic;
4267 the isolated PTY step is capped at 15 minutes; Windows NSIS provisioning
4268 gets a bounded retry (#5496).
4269 - `chore(scripts): dev-cache warns before it fills a disk` (#5465 class).
4270
4271 ### Contributors
4272
4273 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) — restored
4274 `/title` as an independent, persistent terminal-window title in PR #5509,
4275 in addition to the Tier 1 Chinese and Indonesian documentation work below.
4276 - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) — extracted the
4277 turn-loop stream processor in PR #5514 while preserving retry, cancellation,
4278 usage, TTFT, steering, and partial-response behavior.
4279 - [OctoBored](https://github.com/OctoBored) (`@OctoBored`) — supplied the
4280 working no-token Star History mirror used across the localized README set
4281 after the canonical chart endpoint began returning a restricted placeholder
4282 (#5510).
4283 - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) — added
4284 provider-neutral typed MCP image forwarding in PR #5515; the harvested
4285 version also makes malformed image fields produce a visible omission receipt.
4286 - [DingYong4223](https://github.com/DingYong4223) (`@DingYong4223`) — reported
4287 the narrow-terminal completion truncation closed by the bounded hover reveal
4288 (#998). Thanks also to @AiurArtanis and @formp3 for identifying the affected
4289 completion surfaces.
4290 - [sky-sun-moon](https://github.com/sky-sun-moon) (`@sky-sun-moon`) — reported
4291 the missing full per-turn input, reasoning, tool, and assistant pages that
4292 shaped Turn Inspector navigation (#1682).
4293 - [cy2311](https://github.com/cy2311) (`@cy2311`) — reported the Windows launch
4294 path that now ships and installs a Windows Terminal-aware batch launcher
4295 (#1854).
4296 - [demian-welt](https://github.com/demian-welt) (`@demian-welt`) — provided the
4297 reproducible pre-header SSE transport failure behind the bounded HTTP/1.1
4298 retry (#4683).
4299 - [BrathonBai](https://github.com/BrathonBai) (`@BrathonBai`) — reported the
4300 Tabby/CJK IME candidate-window jump that led to the hide-diff-position-show
4301 cursor transaction (#5023).
4302 - M-Maciej (@M-Maciej) — the real-world organization-coordinator use case and
4303 5–30 minute cadence requirement behind cancellable cross-turn goal delays
4304 (#5508).
4305 - cyq1017 (@cyq1017) — approval outcomes are persisted before execution can
4306 proceed: receipts commit to a session-owned log first, unpersistable
4307 evidence blocks the tool, stale decisions are rejected, and resume
4308 reconstructs closed and interrupted approvals (#5491, closes #5360).
4309 - aboimpinto (@aboimpinto) — the TUI-owned dependency-injection and migration
4310 infrastructure that makes slash-command extraction safe: seven capability
4311 facets, a dual-path dispatch seam, and source-aware CI enforcement so a
4312 command slice cannot claim migration while it still accepts concrete `App`
4313 (#5506, EPIC-005/FEAT-015 under #5316, which they also filed).
4314 - wuisabel-gif (@wuisabel-gif) — the TUI header now names the active
4315 repository or linked worktree before the branch and dirty marker, derived
4316 from Git's common directory and capped by shell density tier (#5511, the
4317 repo/worktree slice of #5437).
4318 - SparkofSpike (@SparkofSpike) — Tier 1 of the Chinese docs localization:
4319 Chinese and Indonesian documentation moves to `docs/zh_hans/` and
4320 `docs/id/` with redirect stubs held at the old paths for one release cycle
4321 (#5507, epic #5482, which they also filed).
4322 - Lstarsky0 (@Lstarsky0) — `docs/hooks` and `docs/troubleshooting` move onto
4323 the dictionary spine, retiring their inline bilingual literals in favor of
4324 locale dictionaries with token-aware code spans (#5504, closes #5337, which
4325 they also filed).
4326 - Lstarsky0 (@Lstarsky0) — `docs/constitution` and `docs/runtime-api` follow
4327 the same dictionary spine: 28 inline `isZh` branches become typed English
4328 and Chinese dictionaries held to key and token parity, while the other
4329 sixteen locales keep the English fallback (#5517, a further phase of #5337).
4330 - @thejayjetson — the header status-indicator report that pinned the
4331 regression to a specific setting, with every value, theme, and
4332 `fancy_animations` combination already ruled out (#5512).
4333 - hxfhd (@hxfhd) — reported the deterministic cross-session contamination
4334 class behind this release's session-ownership boundary, plus route
4335 budgeting evidence (#5518).
4336 - sfdzhmr (@sfdzhmr) — reported the route budgeting root causes that exact
4337 route-limit propagation now closes (#5516).
4338
4339 ## [0.9.9] - 2026-08-18
4340
4341 Codewhale v0.9.9 is a truth-and-resilience release: the shell tool can no
4342 longer wedge a session when the host runs out of disk or descriptors,
4343 unverified context windows and output ceilings are labeled honestly at every
4344 surface, DeepSeek V4 is priced on the published peak/off-peak tiers, SSE
4345 UTF-8 fails closed in every dialect, Fleet shadowing is visible, bwrap gets
4346 container essentials and extra roots, the `dsh` skin rides the bundle
4347 profile, the `agent` tool schema is down to 12 fields, and README/website
4348 locales grow to 18 and 8.
4349
4350 ### Fixed
4351
4352 - The lowercase `bash` tool no longer wedges when its complete-output spill
4353 file cannot be created: a full temp volume or exhausted descriptor table
4354 used to fail *every* call — `echo ok` included — with the harness-internal
4355 "Failed to create streaming shell output" and never recover until the
4356 host was cleaned up. The spill is now best-effort (the bounded tail is
4357 still returned and the truncation notice says why the full-output path is
4358 missing), and any remaining spawn/stream failure names the exhausted
4359 resource — disk, file descriptors, memory — and says the next call is safe
4360 to retry (#5465; the wedge that took out the owner's own 0.9.9 session).
4361 - A concrete route/offering output limit now outranks the conservative
4362 8,192-token compatibility guess for an uncatalogued model. Routes that
4363 publish no output limit remain fail-closed, documented model ceilings stay
4364 authoritative, and a route limit can never raise the requested cap (#5460).
4365 - Context-window honesty at every surface (#5239, #5441): the
4366 `model-name hint` and `fallback` rungs of the context-window ladder are
4367 guesses, and every surface that renders one now says so — the status line,
4368 `/status`, `/config`, the context-pressure message, the model picker chips,
4369 and the auto-router inventory. Unverified windows still drive real budgets
4370 (compaction trigger, context meter, output reservation); they just stop
4371 reading as capabilities anyone checked. A window parsed from an `_Nk`
4372 model-name suffix (`qwen3-32b-256k` → 256K) is now its own
4373 `model-name hint` rung below `catalog`, because it is optimistic rather
4374 than conservative — a catalog or provider-reported value beats it. The
4375 `[providers.<name>] context_window` override remains the hard fix and
4376 renders as `configured` with no marker.
4377 - Output-ceiling honesty (#5440): an Anthropic-family model the catalog does
4378 not describe keeps the 64K Messages floor as its clamp and the ChatGPT/
4379 Codex OAuth route keeps its 4K policy, but `OutputCeilingSource` gained an
4380 `unverified` rung for both, so exec-stream receipts and the model picker
4381 label them `unverified`/"assumed floor" instead of `documented`. Clamp
4382 values are unchanged.
4383 - Telemetry default-on is visible (#5441): `codewhale doctor`'s
4384 runtime-posture section gained a `telemetry=on (default)`-style row with
4385 the source that decided it (cli | env | config | default), and
4386 `codewhale config get telemetry` reports the resolved consent with its
4387 source instead of `key not found` on a machine whose batches ship. Truth
4388 change only; resolution and behavior are untouched.
4389 - Fleet: a scout's read-only shell carve-out (#5428) is now honored by both
4390 the posture gate and the execution envelope, so `git log`, `find | head`,
4391 `npm view` and the other bounded read-only commands run in-place instead
4392 of being refused as "Executes" (#5426). Delegation still never widens
4393 authority: the role-isolation test and docs/SUBAGENTS.md pin that a child
4394 cannot exceed its parent's posture (#5426, #5435).
4395 - `/rename` and `/title` now apply mid-first-turn: the session file does
4396 not exist until the first autosave, so the rename fell through with
4397 NotFound; the shared path now prefers the per-session checkpoint and
4398 rebuilds from App state, with a PTY regression test through the live
4399 event loop (#5430).
4400 - `integrations dsh plan` no longer refuses DeepSeek's default
4401 Responses-dialect route (`deepseek-v4-flash`); Responses and
4402 Anthropic-Messages routes are carried through pi-ai
4403 `openai-responses` / `anthropic-messages` instead of being approximated
4404 or refused; only credentialed base URLs are still refused, with an error
4405 that names provider and model (#5434).
4406 - Session cost no longer sits at `unverified_live_pricing` when live pricing
4407 cannot be verified (control-plane 503, Models.dev capabilities-only
4408 overlays): provider-docs bundled fallback rates for the DeepSeek V4
4409 family on Fireworks / OpenCode Zen restore a usable figure, live
4410 per-provider rows still win, and `kimi-k3` stays unpriced until a
4411 published rate exists (#5241; harvested from #5402).
4412 - Release assets: `release.yml` asset-freshness checks compare against the
4413 release job's own `started_at`, so job-level reruns of the npm step are no
4414 longer poisoned by earlier uploads (#5429).
4415 - macOS CI: the `agent_focus_pty` auto-review receipt test waited on a
4416 worker that had already completed and raced the rail's focus; it now holds
4417 the child's wrap-up and waits for a settled live row (refs #5056, #5403).
4418 - DeepSeek V4 pricing follows the published peak/off-peak tiers (peak
4419 01:00–04:00 and 06:00–10:00 UTC; off-peak is half of peak) for
4420 `deepseek-v4-flash` and `deepseek-v4-pro` in USD and CNY, resolved from
4421 each turn's recorded time; the stale single-tier rows understated cost up
4422 to ~4×. Because every direct DeepSeek first-party rate is now
4423 time-windowed, the scorecard fails closed (`missing_recorded_time`) on an
4424 undated DeepSeek turn instead of guessing a tier (#5470; #5241 follow-up,
4425 verified against api-docs.deepseek.com on 2026-08-17).
4426 - SSE UTF-8 split across HTTP/2 DATA frames now fails closed in every
4427 streaming dialect: a shared strict decoder, tail flush, and
4428 `decode_failed` propagation (`InvalidSseUtf8`) replace the per-dialect
4429 approximations, with byte-chunk decoder tests (#5374; supersedes draft
4430 #5404).
4431 - CI: `release_four_read_only_fleet_roles_launch_with_canonical_prompts`
4432 answered Fleet children with SSE while they call the blocking JSON path;
4433 the parse failure was retried and double-counted the worker on slow macOS
4434 runners (#5471; refs #5056).
4435 - Context: every web tool surface (`Web`, `web_search`, `web.run`,
4436 `fetch_url`) now uses the noisy-result soft limit, so large fetches are
4437 compacted like shell output instead of consuming the ordinary hard limit
4438 (#5474, thanks @h3c-hexin).
4439 - Routing: a lowercase saved selector such as `glm-5.2` resolves against the
4440 owning Z.ai / DeepSeek catalog row (case-fold fallback, only when exactly
4441 one provider-owned wire id matches) instead of being classified as another
4442 provider's bare model (#5475, thanks @h3c-hexin; diagnosis by @asto18089
4443 in Pinvou/CodeWhale#14).
4444 - Model catalog brought current as of 2026-08-17 against the official
4445 pricing pages: gpt-5.6-terra / gpt-5.6-luna rates, `claude-sonnet-5` keeps
4446 $2/$10 (the announced September increase was withdrawn), `claude-opus-5`
4447 added, `kimi-k3` and `kimi-k2.7-code-highspeed`, `MiniMax-M2.7-highspeed`,
4448 Mistral first-party rows, xAI `grok-4.5` / `grok-4.3` with long-context
4449 tiers, Gemini and Qwen limits, and RedNote's `dots3-note` preview as an
4450 OpenRouter row (no first-party API exists yet) — every number carries its
4451 source and a pinned test (#5485).
4452 - Website: copy on codewhale.net rewritten in plain declarative sentences —
4453 one idea per sentence, numbers from the generated facts, no self-narration
4454 — with a voice sheet at docs/design/WEB_VOICE.md (#5483).
4455 - CI: the release workflows no longer restore npm/cargo caches after
4456 checking out a caller-supplied SHA — the CodeQL cache-poisoning Highs
4457 #88–#107 are closed with a contract test over the workflow files (#5463).
4458 - Compact TUI rows below 60 columns no longer reserve a hidden session-metrics
4459 strip, so narrow terminals reclaim the row instead of clipping the
4460 transcript (#5486).
4461 - Ghostty's truecolor underwater field now uses a dedicated synchronized
4462 60 FPS lane instead of the legacy 30 FPS compatibility cap, with continuous
4463 caustic fades replacing visibly stepped color changes.
4464 - Live reasoning's advertised `Space:expand` action now runs before the
4465 composer's first-character paste-burst hold, while spaces in an active paste
4466 remain payload. The newest reasoning preview also spends only genuinely free
4467 viewport rows before truncating instead of stopping at the fixed 10/12-row
4468 fallback on roomy terminals.
4469 - Strict `cargo doc` builds no longer fail on bare URLs in rustdoc comments;
4470 the remaining links are explicit Markdown targets (#5489).
4471
4472 ### Changed
4473
4474
4475 - The model-facing `agent` tool advertises exactly 12 fields — `action`,
4476 `prompt`, `type`, `profile`, `name`, `agent_id`, `message`, `until`,
4477 `detached`, `worktree`, `write_roots`, `resume_from` — down from 33
4478 (#5324, refs #5123). Budgets (`max_steps`, `wall_time_secs`, `max_depth`),
4479 routing overrides (`model`, `model_strength`, `thinking`), worktree-path
4480 knobs, the deliberate/spawn-contract fields and the wait/status/interrupt
4481 extras moved off the advertised schema. Every removed field stays
4482 parse-accepted and honored unchanged (same contract as `token_budget`), so
4483 saved transcripts, ACP/MCP clients and Fleet configs replay as-is; the
4484 #5426/#5435 containment clamps are untouched. Child budgets now resolve
4485 from role defaults (60/120 turns, 1800 s wall time, unchanged clamps) and
4486 new `[subagents]` keys `default_max_steps` / `default_wall_time_secs`.
4487 Because the tool catalog is part of the session-pinned prompt prefix
4488 (docs/CACHE.md), upgrading re-fills the KV prefix once per session.
4489 - TUI prose — user messages, assistant answers, and reasoning/thinking —
4490 now wraps at the full content width on wide terminals, matching
4491 tool/status cells, instead of stopping at a 105-column rail that left a
4492 dead right margin on ultrawide displays (#5436).
4493 - Configured skill prompts are stable across session roots and operating
4494 systems: only custom configured roots hide their physical path, ordinary
4495 workspace/global skills keep a discoverable privacy-safe path, warning
4496 replacements are boundary-aware (including non-UTF-8 Unix paths), and
4497 Windows separators render as `/`. The skills prompt is also 50 bytes
4498 leaner without raising a runtime-contract ceiling (#5492, #5473).
4499 - Auto-router classifier requests accept `[auto.router] timeout_secs`, while
4500 preserving the existing default when the key is absent (#5494).
4501 - Every `ci.yml` job now has an explicit 10–90 minute timeout appropriate to
4502 its workload, bounding stale assigned runners instead of inheriting
4503 GitHub's six-hour default (#5495).
4504 - The docs shell and shared web components now route localized copy through
4505 the typed dictionary spine; these are two incremental phases of #5337,
4506 not completion of the full epic (#5488, #5490).
4507 - Dependency: rusqlite 0.40.2 (#5391).
4508 - Documentation: stale A/B/C-tier references, provider defaults, module
4509 descriptions, and line anchors now match the current code (#5481).
4510
4511 ### Added
4512
4513 - `[transcript] prose_measure` (positive integer, optional): caps prose
4514 wrap at N columns for owners who want a bounded reading measure on
4515 ultrawide terminals. `0` or absent keeps the full width; negative or
4516 non-integer values are rejected with a clear config error. Tool, diff,
4517 and status cells never inherit the cap (#5436).
4518 - Localization: README translations for Français, Deutsch, 繁體中文, हिन्दी,
4519 Türkçe, Italiano, Polski, العربية and Català join the existing nine
4520 (#5451); codewhale.net routes fr, de, ca, hi, tr, it, pl and ar (with
4521 `dir="rtl"` plumbing) as partial locales (#5453).
4522 - Docs: README Integrations section (incl. the DeepSeek Harness `dsh` plugin
4523 path, docs/INTEGRATIONS_DSH.md) localized across all READMEs; RFC keeping
4524 the deterministic-first auto-review hybrid (#5427); Claude Code parity
4525 reference for agents/workflows/plugins/skills
4526 (docs/design/CLAUDE_CODE_PARITY.md); config.example.toml / SUBAGENTS.md /
4527 TOOL_LIFECYCLE.md brought back in line with the code (#5447).
4528 - `dsh` integration: the Codewhale palette is applied through the bundle
4529 profile via dsh's documented `overrideTokens` (on by default;
4530 `codewhale integrations dsh update --skin false` turns it off), replacing
4531 the 0.9.8 exported-CSS skin that dsh's inline body variables overrode
4532 (docs/design/DSH_BUNDLE_SKIN.md, docs/INTEGRATIONS_DSH.md) (#5469).
4533 - `dsh` integration: an ambient ocean scene behind the DSH web UI — slow
4534 whale silhouettes, a school of `><>` glyph fish, bubbles — drawn on a
4535 canvas under a translucent veil of the Codewhale palette, plus an explicit
4536 responsive `WHALE BROTHERS / CODEWHALE × DEEPSEEK HARNESS` lockup; light
4537 and dark, ~30 fps capped, paused when hidden, a static frame under
4538 `prefers-reduced-motion`; on by default with the skin,
4539 `codewhale integrations dsh update --ocean false` turns it off (#5484).
4540 - Fleet: agent shadowing is visible — a roster-row badge, a Layers block in
4541 agent detail, and a `doctor` "Fleet roster layers" section (JSON
4542 `operate_fleet.roster.multi_layer`), in all 15 TUI locales. Layer collapse
4543 and `[fleet.profiles]` migration stay for 0.9.10 (#5098).
4544 - Sandbox: bwrap containers get the `--dev/--proc/--tmpfs` essentials plus
4545 configurable extra roots (`bwrap_ro_roots` / `bwrap_dev_roots`) so
4546 toolchains that live outside the workspace stay reachable read-only
4547 (#5410).
4548 - Tests: `crates/tui/tests/README.md` states the keyless assembled-journey
4549 rule and maps the Auto-Review guardian acceptance items to the engine
4550 journeys that exercise them (#5361).
4551 - OrcaRouter's default endpoint is classified as an aggregator billing
4552 surface, so pricing and session-cost reporting use the correct billing
4553 posture instead of treating it as a first-party provider (#5493).
4554 - Dependencies: ratatui 0.30.2, thiserror 2.0.20.
4555
4556 ### Removed
4557
4558 - `dsh` integration: the exported-CSS skin file and its "skin export" status
4559 line (superseded by the bundle-applied `overrideTokens` skin, #5469).
4560
4561 ### Contributors
4562
4563 - hexin (@h3c-hexin) — a concrete route/offering output limit outranks the
4564 8,192-token compatibility guess for an uncatalogued model (#5461, closes
4565 #5460); web tool results use the noisy soft limit (#5474); owned direct
4566 model casing resolves safely (#5475); and configured-skill prompts stay
4567 stable across ephemeral roots and operating systems (#5492, #5473).
4568 - Gabriel-Degret (@Gabriel-Degret) — configurable auto-router classifier
4569 timeout (#5494; first contribution).
4570 - @asto18089 — diagnosed the Z.ai `glm-5.2` casing collision and wrote the
4571 first provider-scoped fix in Pinvou/CodeWhale#14 (carried upstream in
4572 #5475).
4573 - Reports and reproductions that shaped this release: @hardy922 (context-
4574 window honesty, #5239), @redstar (bwrap extra roots, #5410), @all-lopezg
4575 (SSE UTF-8 garbling on DeepSeek Flash, #5374), @alitvak69 (unverified live
4576 pricing, #5241), and @wuisabel-gif (the macOS filtered-suite hang
4577 investigation on #5056).
4578
4579 ## [0.9.8] - 2026-08-16
4580
4581 Codewhale v0.9.8 ships the remaining assigned finish. Remaining web
4582 settings polish moves to v0.9.9. Prefab third-party templates that have
4583 a published OpenAI-compatible host ship here (#5350).
4584
4585 ### Fixed
4586
4587 - `sudo` (and `su`/setuid helpers) work again for wheel-group administrators
4588 who want Codewhale to be able to escalate: the Linux startup hardening's
4589 irreversible `PR_SET_NO_NEW_PRIVS` flag — inherited by every child process —
4590 is now skippable with `CODEWHALE_NO_NEW_PRIVS=0` (#5413). The flag stays on
4591 by default; the no-ptrace and no-core-dump measures are never skipped.
4592
4593 - Abort-class process deaths no longer poison the terminal (#5424). A
4594 stack overflow, allocation failure, or double panic skips the panic hook
4595 and every cleanup guard, which is how a v0.9.7 user's mid-turn exit left
4596 mouse capture leaking SGR sequences into their shell. An
4597 async-signal-safe handler now restores the terminal modes and appends a
4598 one-line cause marker to `~/.codewhale/crashes/last-fatal-signal.log`
4599 before re-raising, keeping the honest 128+signal wait status. A SIGKILL
4600 (OOM killer) remains uninterceptable by design.
4601
4602 ### Changed
4603
4604 - Prompt-cache prefix is pinned for the session. The tool loop no longer
4605 recomposes the system prompt from disk on every model step, so an agent
4606 writing a file no longer busts the provider KV prefix cache mid-turn. The
4607 system prompt and tool catalog are re-composed only on a declared header
4608 change (`/model`, mode, goal, session resume), which re-pins under a logged
4609 reason; an undeclared change is reported as drift and the original pin is
4610 kept instead of silently becoming the new baseline. Workspace, AGENTS.md,
4611 skills, memory, and goal drift now reaches the model as one bounded
4612 `<context_update>` user message at the next user turn — a history append,
4613 not a header rewrite. `/cache stats` shows the pin reason, the last-miss
4614 reason, the undeclared-drift count, and the context-update count. See
4615 [docs/CACHE.md](docs/CACHE.md).
4616
4617 - Plugin compatibility is now per-component. A reviewed, trusted, enabled
4618 bundle that mixes Skills or MCP with unsupported commands, agents, hooks,
4619 LSP, native, filesystem-roots, or lifecycle-mutation declarations keeps the
4620 supported adapters active and reports the rest as inactive (`full` /
4621 `partial` / `unsupported`). All-unsupported bundles still cannot be enabled.
4622 The capability hash is now v2 and binds this build's activation policy, so
4623 older v1 receipts and any later adapter-enablement change fail closed as
4624 needs-review. Skills and each MCP transport re-request their own capability
4625 at the consumption boundary.
4626
4627 ### Added
4628
4629 - Opt-in multiline composer mode (`composer_multiline_mode = true`) makes
4630 Enter insert a newline and Shift+Enter send. Alt+Enter, Ctrl+J, and supported
4631 Ctrl+Enter/Cmd+Enter behavior stays unchanged (#5345, @AiurArtanis).
4632
4633 - `/plugin marketplace add|list|show|remove|install` completes the
4634 federated marketplace journey (#5311). `add` reads one LOCAL catalog
4635 document in the real published schemas (Kimi, Claude, Codex, or
4636 Codewhale native) — no network, regular files only — and persists it
4637 beside the plugin state with the same hardened, fail-closed store.
4638 `list`/`show` render every candidate with per-entry diagnostics,
4639 display-only tiers, and honest install plans that say when Codewhale
4640 cannot fetch a source; `install` routes through the existing reviewed
4641 installer, so installed bundles still enter disabled and untrusted.
4642 Foreign auto-install policy (Codex `INSTALLED_BY_DEFAULT`) is visibly
4643 ignored; nothing is auto-installed, auto-trusted, or granted vendor
4644 trust.
4645
4646 - `/rc` attach now includes an observed `owner/name` git remote when the
4647 folder has a GitHub, CNB, or Gitee origin, so CWC can label the paired
4648 session. Paths stay off the wire. Reconnect after both this client and
4649 CWC #202 land to backfill existing empty rows.
4650
4651 - The local Runtime web client keeps the thread rail clipped so **New
4652 thread** cannot paint over the session fact chips. Chips wrap instead
4653 of sliding under the rail.
4654
4655 - Z.ai `GLM-5.3` is live on the Coding Plan and is now the default direct
4656 Z.ai model: `DEFAULT_ZAI_MODEL` resolves to `GLM-5.3` in both
4657 `codewhale-tui` and `codewhale-config`, and it is the first `/model` row
4658 after `/provider zai`. Explicit `GLM-5.2` selections (`model = "GLM-5.2"`
4659 and its `glm-5.2` aliases) keep their own id — only the default moved.
4660 Limits and reasoning options still inherit from `GLM-5.2` until Z.ai
4661 publishes distinct 5.3 numbers. No USD price is claimed. A live call
4662 can still 429 with entitlement code 1311 on accounts that are not
4663 provisioned for 5.3.
4664
4665 - The TUI transcript renders Markdown blockquotes (`>` lines) with a quote
4666 rail — nested quotes, inline bold/code/links, wrapped continuation rows, and
4667 selection copy that keeps the quote text and skips the rail chrome.
4668
4669 - Sub-agent details show the resolved model, fleet role, and type. Labels
4670 use the session/role name instead of a generic Agent N (#5371, #5287).
4671
4672 - Documented catalogue output ceilings (including DeepSeek V4's 384K maximum)
4673 remain authoritative bounds, while ordinary requests start at a safe 64K
4674 cap and explicit overrides can raise it within the resolved route window. A
4675 clean output-limit stop continues the turn instead of killing it (#5373,
4676 #5516, #5518). Thanks @sfdzhmr and @hxfhd for the route evidence.
4677
4678 - Ollama Cloud is a first-class hosted provider (`/provider ollama-cloud`)
4679 on the official OpenAI-compatible `https://ollama.com/v1` route. Local
4680 Ollama stays keyless. The exact released `ollama` + Cloud URL tuple keeps
4681 a bounded compatibility path across saved sessions, Fleet, and nested
4682 subagents; neighboring remotes stay custom and fail closed against
4683 inherited official credentials.
4684
4685 - Homebrew ships a `codewhale` formula. `brew tap Hmbown/deepseek-tui &&
4686 brew install codewhale` is the install path; `brew upgrade codewhale`
4687 updates it. The legacy `deepseek-tui` formula remains a deprecated alias
4688 for one overlap release.
4689
4690 - `/title [name|off]` sets a per-session tab/window title, shown as
4691 `[title] …` in front of the terminal window title (`Codewhale` /
4692 `reasoning…` / `using tool…` / `done`). The `title` config key supplies
4693 the default (`/config title … --save` persists it); multi-window
4694 workflows can tell parallel sessions apart at a glance. `/title` is
4695 independent of `/rename`, which keeps naming the session in the picker
4696 and composer. Control, bidi, and zero-width format characters are
4697 stripped from both the saved session name and the window title, so the
4698 picker, the Runtime API, `codewhale sessions`, and the OSC 0 tab title
4699 all carry the same escape-free text (#5419, #5430).
4700 - Eden AI is a named OpenAI-compatible Chat Completions provider (`edenai`,
4701 aliases `eden-ai` / `eden_ai`) with `EDENAI_API_KEY`, global and EU base-URL
4702 overrides, a live provider-scoped model catalog, and
4703 `deepseek/deepseek-v4-pro` as the verified default. Generic reasoning fields
4704 stay omitted because Eden AI routes multiple upstream model families
4705 (#5422, Kai Nacke).
4706 - Children (sub-agents and Fleet workers) inherit the session's permission
4707 posture faithfully: Auto-Review's deterministic floor and model guardian
4708 decide a worker's held calls (fail closed when unavailable, never a
4709 prompt); under Ask a held call is raised in the parent's approval UI and
4710 the worker waits visibly; Full Access still fails closed on the safety
4711 floor. Each prompt-less decision is a one-line note in that worker's
4712 transcript (focus mode) and an audit-log record.
4713 - Worker role defaults keep what the role does not intend to withhold:
4714 every built-in role keeps network reads; `planner` may run read-only
4715 shell probes; `custom` inherits the parent's write/network/shell posture
4716 and is narrowed only by its explicit tool list or the spawning call.
4717 Read-only roles (`scout`, `reviewer`, `planner`, `verifier`,
4718 `consultant`) still never write the workspace. The focused worker's
4719 header states its effective posture from the runtime snapshot.
4720 - `/workflow status`, `/workflow cancel [run_id]`, `/workflow settings`, and
4721 `/workflow help` are answered by Codewhale itself from the run journal and
4722 live run state — no model turn — and `/workflow run <path>` launches a
4723 checked-in workflow as-is. `/config workflow` and `/config goal` explain
4724 the effective tables. The workflow tool now honors the session `[workflow]`
4725 table (`automatic`, `auto_start_read_only`, `require_approval_for_writes`,
4726 limits) instead of product defaults.
4727 - Goal mode enters as readily as DeepSeek Harness: the agent may create the
4728 session goal when a direct request describes a verifiable multi-turn end
4729 state, and Codewhale shows a one-line `Goal set` receipt with how to pause
4730 or clear it. Bare `/goal` shows plain progress (and how to continue when no
4731 turn is running), prints usage on an empty session instead of asking the
4732 model, and `/goal help|status` are reserved words.
4733
4734 - Whale Teams in the terminal: the six Signal Cut whale identities (Scout,
4735 Patch, Harbor, Echo, Keel, Lantern) appear as species badges on `/fleet`
4736 roster rows and worker rows, with an identity portrait in the roster detail
4737 pane and a six-state word (Resting, Thinking, Working, Waiting for you,
4738 Blocked, Offline) derived only from the child's real runtime status. Colors
4739 come from the theme tokens, every glyph has an ASCII fallback, and the
4740 working wake animates only under full motion. See
4741 `docs/design/WHALE_TEAMS_TUI.md`.
4742 - A session metrics strip on the phase row (`4 turns · 108 steps │ LLM
4743 11m46s · Tool call 1m52s │ TTFT avg 1.5s · 120 tok/s │ Cache hit 99% │
4744 Input 9.3M`), on by default as the `session_metrics` footer item
4745 (`/statusline`, `[tui].status_items`). Every value comes from engine
4746 receipts — turn starts, per-model-call usage with stream time,
4747 time-to-first-token and whole-call time, tool start/complete edges, and
4748 provider-reported cache and input tokens. Cells without evidence are
4749 omitted, never estimated. `/status` prints the untrimmed line; the phase
4750 row sheds its lowest-value groups to fit the columns it actually has.
4751 - Auto-Review decisions nobody was prompted for are now visible in the
4752 transcript as one-line notes: model-guardian allow/deny verdicts with
4753 their risk tier and stated reason, guardian failures (denied, fail
4754 closed), deterministic policy blocks, and holds Auto-Review denied
4755 without pausing. The audit log keeps the full record. `/permissions`
4756 ends with the active posture, what it decides on its own versus never,
4757 and the audit-log path. The footer's `Esc to interrupt` hint is
4758 localized. See `docs/design/AUTO_MODE_PARITY.md` for the Claude Code /
4759 Kimi Code parity ledger and follow-ups.
4760 - `codewhale integrations dsh status|plan|connect|update|launch|disable|enable|remove`
4761 connects an existing official DeepSeek Harness (`dsh` 0.1.0-rc.6, verified)
4762 through Codewhale using only its documented seams: a `--patch` overlay that
4763 pins the exact Codewhale provider/model/endpoint identity (native
4764 `deepseek-official` route, or a hand-declared `openai-completions` route
4765 named `codewhale-<provider>` for OpenAI-compatible providers), the
4766 Codewhale permission posture exported as `DSH_PERMISSION_MODE`, and an
4767 append-only receipt. Codewhale writes only under
4768 `$CODEWHALE_HOME/integrations/dsh/`, never copies API keys or edits DSH
4769 files, never broadens permissions (`--allow-full-access` only mirrors an
4770 existing Codewhale full-access posture), and reports not-installed /
4771 offline / incompatible / detected / connected / stale-config /
4772 stale-version / disabled honestly. Anthropic Messages and OpenAI Responses
4773 routes are refused as not carriable. The documented DSH plugin path is an
4774 explicit opt-in: `install-bundle` materializes a Codewhale bundle package
4775 (`codewhale-dsh-bundle`, MIT notice retained) and installs it with
4776 `dsh plugin --profile codewhale add <path>` into a dedicated `codewhale`
4777 profile (pnpm required, reported truthfully when missing; `web`/`headless`
4778 untouched), so `dsh --profile codewhale` alone carries the identity;
4779 `update` regenerates the bundle patch and `remove-bundle` reverses it,
4780 leaving the DSH-owned profile directory in place. `/setup tools` and `codewhale doctor`
4781 show the read-only detection state; `doctor` also lists the DSH read-only
4782 credential consent alongside Codex and Grok. The optional `--skin` export
4783 writes a Codewhale token stylesheet generated from the TUI palette
4784 (Blue Stage dark/light, ombre water column, mode/permission/state colors,
4785 reduced-motion fallbacks); DSH exposes no custom-theme API, so the sheet is
4786 labeled an unsupported overlay and is never injected. See
4787 `docs/INTEGRATIONS_DSH.md`.
4788
4789 ### Fixed
4790
4791 - Selecting the `google` provider kind resolved to the `antigravity`
4792 TUI identity (and vice versa): the agy provider entry was inserted at
4793 different positions in the config-level enum and the TUI's
4794 discriminant-indexed lookup table. The table now matches the enum, so
4795 provider pickers, sorted display, and kind round-trips are correct.
4796
4797 - The provider picker's key-entry stage accepted typed input and pastes
4798 for OAuth-only providers after `antigravity` declared OAuth
4799 acquisition; those gates now key off the OAuth acquisition class
4800 instead of a hard-coded provider identity.
4801
4802 - The webhook hook sink no longer panics when its HTTP client fails to
4803 build; it falls back to a default client (#5381, EvanProgramming).
4804
4805 - Session-index JSONL writes are serialized behind a process-wide mutex
4806 so concurrent state stores cannot drop an append during compaction
4807 (#5382, EvanProgramming; complements the cross-process file lock).
4808
4809 - A billed `max_tokens` stop followed by a transport error fails the turn
4810 instead of continuing into a second request. A clean output-limit stop
4811 still continues. Mid-size context windows keep the ordinary 65K internal
4812 reservation so compaction does not collapse to the 1K headroom floor
4813 when the catalogue documents a matching output ceiling.
4814
4815 - Thinking cycle, `/effort`, and Settings now walk each model's real ladder
4816 instead of the DeepSeek off/high/max shortcut. Grok 4.6 is
4817 auto/low/medium/high/xhigh (cannot disable); Grok 4.5 is
4818 auto/low/medium/high; first-party DeepSeek keeps a documented `low` tier.
4819 `/effort` persists and receipts through the same path as Ctrl+T.
4820
4821 - Google Gemini is its own backend (`/provider google`) on the official
4822 OpenAI-compatible route with thought-signature capture/replay and
4823 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) is
4824 a separate provider: consent-gated read-only import of the official
4825 CLI's login, then a text-only cloud-code stream
4826 (`/v1internal:streamGenerateContent`). Tools, images, and unknown SSE
4827 shapes fail closed. Gemini 3.7 Flash is not advertised until a live
4828 turn succeeds on this wire. The website 44-count still excludes
4829 Antigravity.
4830
4831 - DeepSeek Flash SSE on macOS no longer turns mid-character HTTP/2
4832 flushes into U+FFFD replacement characters (#5374). Invalid UTF-8
4833 fails the line instead of using lossy decode.
4834
4835 - `[workshop] read_result_max_bytes` and `tool_result_max_bytes` raise
4836 the model-visible read/tool-result floor; they never lower the
4837 compile-time defaults and cap at 2MiB (#5367).
4838
4839 - Fireworks and OpenCode Zen DeepSeek V4 Flash/Pro keep a bundled
4840 family rate when the live control plane is down, so session cost is
4841 not stuck on `unverified_live_pricing` (#5241). `kimi-k3` stays
4842 unpriced until a published rate exists.
4843
4844 - Provider setup ships a typed beginner template catalog (#5350). OpenCode
4845 Zen/Go stay first-class key-only rows with their documented hosts and
4846 curated models. SenseNova fills a named OpenAI-compatible table on the
4847 published `https://token.sensenova.cn/v1` host (`S` or `/provider setup
4848 sensenova`). Agnes is listed as unpublished because this repository has
4849 no published URL. `/provider` `P` and Settings → beginner templates open
4850 the list; `T` tests `/models` and refreshes status without treating 2xx
4851 as model-ready. `/model` names a failed Models.dev refresh as
4852 `refresh failed; catalog available` instead of `cache failed`.
4853
4854 - Privileged release workflows no longer restore rust-cache, sccache,
4855 or npm caches after checking out a caller-supplied SHA (CodeQL
4856 cache-poisoning #88–#106). Catalog drift no longer prints raw
4857 bundled/upstream blobs (#107).
4858
4859 - Cancelling a turn now cancels its foreground child agents with it.
4860
4861 - Empty compaction no longer wipes conversation history.
4862
4863 - Wide terminals and tmux panes fill the full available width again for the
4864 transcript and composer (#5322). The brief v0.9 session-shell side gutter
4865 is gone so expanding a pane rematerializes layout the same way shrinking
4866 does.
4867
4868 - The agent tool schema rejects empty calls.
4869
4870 - The local web client keeps recovered stream gaps closed, user questions
4871 answerable, manual bootstrap access intact, and streamed prose quiet for
4872 assistive tech.
4873
4874 - Website zh-Hans copy now says 宪章, matching the TUI pack (#5397,
4875 Lstarsky0).
4876
4877 - Public website provider facts include Google Gemini and Ollama Cloud
4878 (44 runnable routes). Antigravity stays credential-plane-only.
4879 Harvested from #5398 (Lstarsky0) with that correction.
4880
4881 - The website models page carries a truthful read-only settings preview
4882 built from repository facts; it never implies the site can change local
4883 configuration (#5370, #5411, mvanhorn).
4884
4885 - The canonical `ultra` reasoning effort now maps to each provider's
4886 maximum tier alongside the legacy `ultracode` alias, instead of being
4887 silently dropped (#5303, #5409, buiducnhat).
4888
4889 - Session titles truncate by character count, not byte offset, so
4890 multi-byte titles (CJK, emoji) cut at the intended width and word
4891 boundary instead of past the limit (#5415).
4892 - Wide terminals and tmux panes fill the full available width again for the
4893 transcript and composer (#5322). The brief v0.9 session-shell side gutter is
4894 gone so expanding a pane rematerializes layout the same way shrinking does.
4895 - The background verifier test drives the current libtest executable
4896 instead of the rustup `rustc` shim, so the TUI suite no longer depends
4897 on `$HOME` or holds the process-wide test environment lock across an
4898 async wait (#5056, #5423, Isabel Wu).
4899
4900 ### Removed
4901
4902 - The source-structure budget ratchet (CI step, checker, baseline JSON).
4903 It measured line counts, not quality: every legitimate feature required
4904 a hand-edited ceiling and the accompanying "review" was self-review, so
4905 it bought ceremony, not protection. Behavior-measuring gates (dead-code,
4906 runtime-contract, persistence-backlog) stay enforced.
4907 - DeepSeek can reuse a key already stored by official DeepSeek Harness
4908 (`dsh`) after
4909 `codewhale auth external-consent --provider deepseek --mode read-only`.
4910 Codewhale reads only `DEEPSEEK_API_KEY` from the exact granted
4911 `$DSH_HOME/.credentials.yaml` and never writes or refreshes that file.
4912 - The TUI markdown parser now honors CommonMark fence-length rules: a ````
4913 opener is not closed by a shorter ``` line, so `>` content inside a longer
4914 fence stays literal code instead of escaping into a quote.
4915 - Sub-agents finalize when the parent session id changes, so a closed
4916 session cannot block new children as a live owner (#5372).
4917 - Child spawn-route receipts stay live and usage is deduped by response
4918 (#5366).
4919 - Doctor keeps persisted setup readiness across first-run / update
4920 checkpoints (#5340).
4921 - Approval default selection is applied and explained; agents are told
4922 when approvals are disabled (#5293).
4923 - A `/models` 2xx probe is a connection check, not model readiness.
4924 - Site layout uses one container, the ticker no longer implies false
4925 provider readiness, and install links stay in the active locale.
4926
4927 ### Contributors
4928
4929 - EvanProgramming (@EvanProgramming) — webhook client panic fallback
4930 (#5381); session-index JSONL mutex (#5382).
4931 - Lstarsky0 (@Lstarsky0) — session peek hides internal runtime events
4932 (#5376); thinking-ladder test re-pin (#5378); provider-count follow-ups
4933 (#5383/#5384); macOS agy fixture canonicalization (#5392); zh-Hans 宪章
4934 terminology (#5397); regenerated website facts harvested and corrected
4935 from #5398.
4936 - Matt Van Horn (@mvanhorn) — read-only models settings preview on the
4937 website (#5411, fixes #5370).
4938 - Nhat Bui (@buiducnhat) — canonical `ultra` reasoning effort mapped across
4939 provider effort tables (#5409); session titles truncated by character
4940 count, not byte offset (#5415).
4941 - Sh1Zuku (@SparkofSpike) — `/title` and the session name in the terminal
4942 tab/window title, plus the mid-turn title deadlock fix (#5419).
4943 - Kai Nacke (@redstar) — Eden AI provider registration, aliases,
4944 `EDENAI_API_KEY`, and the global/EU endpoints (#5422).
4945 - Isabel Wu (@wuisabel-gif) — background verifier test isolated from
4946 rustup and `$HOME` (#5423, slice of #5056).
4947
4948 ## [0.9.7] - 2026-08-12
4949
4950 Codewhale v0.9.7 keeps the catalog ordinary. Grok 4.6 lands as a normal catalog
4951 row instead of a provider-shaped pile of special cases, OrcaRouter joins as a
4952 named provider, and a panic-safety advisory in `lru` is cleared by lifting the
4953 pin that caused it rather than living around it.
4954
4955 ### Added
4956
4957 - Grok 4.6 is the direct xAI default, with the `grok` alias moving onto it and
4958 `grok-4.5` still explicitly selectable. Its 500K context, text/image input,
4959 tool and structured-output support, `low`/`medium`/`high`/`xhigh` reasoning
4960 efforts (default `high`), and server-side web search all come from the
4961 Models.dev-shaped catalog rather than model-specific code. `reasoning_effort`
4962 reaches the wire only on the exact first-party `https://api.x.ai/v1` route,
4963 and the usage-aware 200K-token pricing boundary is scoped to direct xAI so
4964 aggregator routes reusing the model slug cannot inherit xAI billing.
4965 - OrcaRouter is a first-class named provider: `ORCAROUTER_API_KEY`, default base
4966 URL `https://api.orcarouter.ai/v1`, `deepseek/deepseek-v4-pro` default,
4967 `orcarouter/auto` routing, CLI `--provider` selector, and TUI picker entries
4968 (#5321).
4969
4970 ### Changed
4971
4972 - Reasoning-effort normalization and the model picker read a model's published
4973 `reasoning_options` list from the catalog instead of collapsing every route to
4974 the historic Low/Medium ladder. Any catalog row that publishes an effort list
4975 keeps its own vocabulary.
4976 - Docs record DeepSeek's live `DeepSeek-V4-Pro-0813` backend label while the
4977 callable API ID stays `deepseek-v4-pro`. No aliases are remapped and no
4978 `deepseek-v4-pro[1m]` selector is sent.
4979
4980 ### Fixed
4981
4982 - Auto-Review once again executes proven read/build/test shell commands and
4983 bounded workspace writes without opening an approval modal. Explicit policy
4984 blocks, unknown tools, publish operations, secret actions, MCP mutations,
4985 and shell commands requiring approval still fail closed (#5323; reported by
4986 USTHzhanglu and root-caused by Lstarsky0).
4987 - Copying a user or assistant message takes its canonical content instead of
4988 reserialized transcript lines, keeping role glyphs, continuation rails, and
4989 visual wrapping out of the clipboard while preserving authored Unicode,
4990 Markdown, and hard line breaks. Tool and Thinking cells stay on the existing
4991 full-transcript path (#5319).
4992 - `load_session` no longer runs crash recovery on every read. Snapshot reads go
4993 through a side-effect-free `load_session_snapshot` and recovery is explicit
4994 via `recover_session_for_resume`, so an embedding host inspecting a durable
4995 session while a tool is still running no longer gets a spurious crash repair
4996 (#5320).
4997
4998 ### Security
4999
5000 - `lru` moves to 0.18 to clear RUSTSEC-2026-0253, where `LruCache::pop()` was
5001 not panic-safe and could leave dangling list pointers. The `ratatui-core`
5002 `=0.1.0` pin that transitively forced `lru` ^0.16 is lifted, so
5003 `ColorCompatBackend` now answers `get_cursor_position()` from tracked cursor
5004 state — the upstream-recommended workaround for the startup CPR race
5005 (ratatui/ratatui#2483, ratatui/ratatui#2640) that the pin originally worked
5006 around. `ratatui` itself stays pinned at `=0.30.0`, so the API surface is
5007 unchanged.
5008
5009 ### Known issues
5010
5011 - The integration test
5012 `exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero`
5013 is a confirmed flake under parallel load ("service pid file never appeared").
5014 It passes in isolation and is unrelated to any v0.9.7 change.
5015
5016 ### Contributors
5017
5018 - XhesicaFrost (@XhesicaFrost) — canonical message copy (#5319).
5019 - h3c-hexin (@h3c-hexin) — session snapshot and crash-recovery split (#5320).
5020 - XiaoHuo888-hue (@XiaoHuo888-hue) — OrcaRouter provider registration (#5321).
5021 - USTHzhanglu (@USTHzhanglu) — Auto-Review regression report and Windows
5022 evidence (#5323).
5023 - Lstarsky0 (@Lstarsky0) — Auto-Review regression root-cause analysis (#5323).
5024
5025 ## [0.9.6] - 2026-08-11
5026
5027 Codewhale v0.9.6 is a subtractive release: fewer runtime guards, one stable
5028 prompt, truthful provider endings, and a smaller compaction path that preserves
5029 the provider cache. The changes were grounded by matched Terminal-Bench 2.1
5030 runs against Pi 0.8.41 and by dogfooding repeated manual compaction.
5031
5032 ### Added
5033
5034 - `web_search` defaults to Firecrawl Cloud without an API key; keyless requests
5035 are headerless and quota-bounded, while an optional user key raises limits.
5036 - Green web builds on `main` now emit an actionable manual-deploy reminder, so
5037 site changes cannot quietly appear shipped while Cloudflare still serves an
5038 older revision.
5039 - Mistral AI is a first-class provider route, including Codestral models,
5040 first-party reasoning support, authentication, picker entries, and aliases.
5041 - Headless `Bash` can transfer explicitly requested persistent Unix services
5042 out of an exec run, with ownership and cleanup receipts.
5043 - `/remote-env` opens hosted Work from the current GitHub or CNB branch tip and
5044 states exactly which unpushed, dirty, ignored, secret, and session state stays
5045 local.
5046 - Linux ARM64 release and nightly assets are static musl builds with native
5047 launch checks.
5048 - Maintainers can report observed daily active installs from the same anonymous,
5049 aggregate telemetry dataset; no additional client data is collected.
5050 - Fleet-dispatched members under a read-only evidence (no-network) ceiling now
5051 keep the `Web` tool's read-only `search` and `fetch` actions — parity with an
5052 ordinary scout — while every reaching surface (`web.run`, `fetch_url`,
5053 `github`, MCP) stays denied and the sentinel-backed capability envelope
5054 remains the fail-closed backstop.
5055 - `/fleet setup` can show an optional, deterministic, unratified role-to-model
5056 advisory built only from configured ready routes. Accept, edit, and reject
5057 all remain inside the existing human-reviewed profile save boundary; the
5058 advisory never launches a Fleet or writes a second configuration.
5059 - `/update` checks for a newer Codewhale release and installs it from inside
5060 the TUI, while `tui_help` gives agents the same command and key map users see.
5061 - Markdown file paths render as OSC 8 links where the terminal supports them,
5062 and every agent row can open that agent's transcript directly.
5063 - ACP editor sessions can execute multi-round file, search, Git, patch, and
5064 explicitly enabled shell tool calls through the shared Runtime registry.
5065 Shell access requires both the client's terminal capability and Codewhale's
5066 headless shell opt-in, and cancellation stops an in-flight tool before the
5067 turn returns (#5225 by @rafaelcavalheri).
5068 - Lowercase `read` returns bounded typed PNG, JPEG, GIF, and WebP results to
5069 image-capable Chat, Responses, Anthropic, and ACP routes. Text-only routes
5070 receive an explicit omission receipt; image bytes never spill into ordinary
5071 transcript, export, compaction, or relay text.
5072
5073 ### Changed
5074
5075 - Anonymous usage counting is on by default for fresh installs and disclosed in
5076 a native first-run Codewhale modal with an immediate opt-out. Prior declines
5077 remain off. Codewhale does not collect conversations, code, prompts, files,
5078 repo or branch names, credentials, model content, or per-turn activity
5079 timelines.
5080 - Wide terminals use a responsive, full-screen ocean canvas with modest
5081 gutters: prose keeps a readable measure while tools, diffs, work surfaces,
5082 the composer, and status chrome can use the available width. Turn and major
5083 activity seams breathe without padding every call inside a tool group.
5084 - Root CLI help describes product actions directly instead of exposing internal
5085 TUI/runtime layers.
5086 - `Bash action="wait"` now blocks by default when a wait is requested; callers
5087 can still ask for a nonblocking snapshot, and persistent service ownership
5088 remains explicit.
5089 - Compaction is one cache-stable summary request followed by one committed
5090 replacement summary and a bounded recent-message tail. Older saved sessions
5091 still restore.
5092 - Ask, Work, Auto-Review, and Full Access share one stable base prompt. Modes
5093 continue to differ through permissions and the live tool catalog; the former
5094 Act label is now Work throughout the product and shipped locales.
5095 - Full Access now auto-approves non-bypassable tools consistently, and the
5096 default choice shown on ordinary approval cards is configurable.
5097 - Model, context-window, dispatch-name, and nested-agent spawn receipts report
5098 the route and limits actually used rather than silently substituting a
5099 guessed identity.
5100 - Child-agent launches mint one immutable route receipt before admission and
5101 preserve it through status, interruption, completion, resume, Work Graph,
5102 and ledger projections, so provider/model attribution cannot drift (#5305).
5103 - Goal runs no longer stop because of internal continuation, repeated-gap, or
5104 unanswered-question guards. Explicit user limits and terminal goal states
5105 remain authoritative.
5106 - Account-owned `/rc` remote control now keeps exclusive ownership and a
5107 crash-recoverable delivery journal until the server acknowledges terminal,
5108 approval, failure, and snapshot state.
5109 - `todo_write` is an optional progress surface rather than required model
5110 ceremony.
5111 - New turns use one small, stable toolbox: `read`, `write`, `edit`, `bash`,
5112 `agent`, `todo_write`, and `tool_search`. The optional progress tool stays
5113 visible as familiar working memory; specialized native, Web, MCP, plugin,
5114 memory, task, and verification tools are policy-filtered and searchable;
5115 activated schemas stay in a bounded per-conversation cache. Every sub-agent
5116 keeps its own search and cache, including policy-allowed Web research, while
5117 forked context and parent activations remain warm starts rather than allowlists.
5118 - The direct file and shell schemas follow Pi's deliberately small contract:
5119 bounded complete-line reads, hash-free writes, unambiguous multi-edit with
5120 BOM/CRLF preservation and conservative fuzzy matching, and one foreground
5121 `bash` command with a bounded chronological output tail. Modes change
5122 execution authority, not those primitive names.
5123 - Codewhale no longer re-states the To-do list to the model. The model learns
5124 what is on the list from the tool result its own `todo_write` call returned,
5125 which is ordinary conversation history — the same way Pi's To-do works. The
5126 transient `<codewhale:work_state>` block that used to ride the tail of every
5127 parent turn-loop and sub-agent step request is gone, along with the stable
5128 system prefix being disturbed by list changes. A snapshot is still shown once,
5129 where a person asked for it: the `<codewhale:fork_state>` block a newly forked
5130 sub-agent is handed, `/relay` handoff instructions, and the agent card. The
5131 complete To-do stays visible in the UI. A structural test asserts real
5132 outbound provider request bodies do not carry the list.
5133 - Scout and Reviewer name the read-only investigator roles. Both expose exactly
5134 one shell entry point — canonical lowercase `bash`, bounded by the strict
5135 read-only classifier — and the legacy `Bash` alias stays denied in the catalog
5136 and at dispatch. Previously a case-insensitive name match let a call spelled
5137 `Bash` execute through that carve-out, returning raw shell to a read-only role.
5138
5139 ### Fixed
5140
5141 - Sending more context while a lowercase `bash` command is running now moves
5142 the command to `/jobs` and returns a successful running receipt instead of
5143 falsely reporting `Command exited with code -1`; the process keeps running
5144 and its completion still arrives through the normal runtime event.
5145
5146 - First-run usage disclosure now opens as a native Codewhale modal instead of a
5147 shell questionnaire before application startup. Telemetry remains unarmed
5148 until the native choice is made, and an in-memory Disable choice governs the
5149 current session even when its preference cannot be saved.
5150 - `/compact` completion, failure, queued, duplicate, and mailbox outcomes are
5151 durable transcript receipts instead of short-lived toasts. A stray terminal
5152 event can no longer leave every later compaction stuck as already running.
5153 - Compaction now follows Codex's simple transcript shape: recent user context
5154 followed by one ordinary history checkpoint. It never appends the summary,
5155 the To-do list, or volatile shell/worker state to the standing system prompt;
5156 reloads migrate the persisted carrier back into exactly one history item.
5157 - Automatic compaction uses a percentage of the real context window, clamped to
5158 the route's spendable ceiling. Pressure comes from the current parent-route
5159 prompt, not cumulative billing or child-model usage.
5160 - Compaction, review, verify, routing, setup, Fleet, MCP, RLM, vision,
5161 translation, and sub-agent calls inherit the resolved route's normal output,
5162 sampling, and reasoning policy. Small internal-task token caps no longer
5163 truncate thinking routes or special-case individual providers.
5164 - Incomplete provider responses fail truthfully across ordinary turns and every
5165 internal model consumer. Partial text stays interrupted, pending tool calls do
5166 not execute, and billed usage is retained.
5167 - Transport-only `(reasoning omitted)` placeholders no longer enter new
5168 transcripts and are filtered from restored sessions. Reasoning expand/collapse
5169 actions stay attached to the exact rendered cell, including after replacement,
5170 restore, filtering, and resize (#5291).
5171 - Step-budget exhaustion is a typed failure and cannot release a pending
5172 persistent service. Cancellation after terminal usage still charges the turn.
5173 - Deferred tools now preserve a completed result when a provider reuses its
5174 tool-call ID on the retry turn, preventing successful plugin calls from
5175 entering a repeated execution loop.
5176 - Website setup, provider, diagnostics, Fleet, and single-runtime claims now
5177 match the source candidate.
5178 - Opening the sub-agent register no longer hides the to-do list: the Agents
5179 panel shows the full register and the durable checklist together, and the
5180 register header is a two-way door that returns to Tasks on a second click.
5181 - The ⌥V / Alt+V details chord opens the selected work-surface row's own
5182 inspector instead of the transcript's nearest tool cell, so a selected
5183 to-do row shows its own content rather than the latest reasoning.
5184 - The first-run usage disclosure now asks a clear question — "Help improve
5185 Codewhale?" — with unambiguous "Yes, keep anonymous counts" / "No, turn off
5186 tracking" choices in every shipped locale, and states the persistent opt-out
5187 command. Consent semantics are unchanged: telemetry stays unarmed until a
5188 choice is made.
5189 - macOS screencapture screenshots referenced in a message are copied to a
5190 stable attachments directory the moment the message is received, and the
5191 reference is rewritten to the stable path, so the image still exists when
5192 the agent reads it. Only files under a screencapture "Temporary Items"
5193 directory are touched; copies are idempotent and a failed copy keeps the
5194 original reference.
5195 - Manual `/compact` during an active turn now queues even when the engine's
5196 bounded op mailbox is saturated. The request defers client-side, retries as
5197 mailbox slots free, and cannot latch as already running after it settles.
5198 - Interactive `/load`, startup `--resume`, and `/resume` picker paths preserve
5199 the persisted provider, endpoint, and model identity; picker resume also
5200 leaves a durable transcript receipt.
5201 - Relative `mcp_config_path` values no longer depend on the launch directory or
5202 silently load an empty server pool: Codewhale warns and falls back to the
5203 user-global MCP configuration. Explicit absolute paths remain authoritative.
5204 - Alibaba Model Studio `qwen3.8-max` and `qwen3.8-max-preview` still stream
5205 their current reasoning, but no longer replay historical `reasoning_content`
5206 that those routes do not accept. Historical reasoning replay is now gated by
5207 the exact provider/API/model contract, so unknown `*-thinking` lookalikes
5208 fail closed while documented Qwen, Kimi, DeepSeek, Mistral, Anthropic, and
5209 Responses continuity rules remain intact.
5210 - Compatibility File/patch calls retain optional content-hash guards when a
5211 caller supplies them. The new direct `write` and `edit` schemas do not expose
5212 hash or prior-read ceremony.
5213 - Shell previews hold back incomplete UTF-8 sequences instead of emitting
5214 replacement characters, and compaction receipts report token deltas.
5215 - Nested agents may narrow but can never widen their inherited depth budget
5216 (#5317 by @ousamabenyounes).
5217 - Container publication now assembles AMD64 and ARM64 images in parallel on
5218 native runners from the already-verified static release binaries, then
5219 publishes and checks one multi-architecture manifest. It no longer rebuilds
5220 both targets through the single long-running QEMU job that lost its runner.
5221
5222 - Google Gemini is its own backend (`/provider google`) on the official
5223 OpenAI-compatible route with thought-signature capture/replay and
5224 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
5225 as a separate credential-plane provider: consent-gated read-only import
5226 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
5227 precedence; requests fail closed until the cloud-code wire protocol is
5228 implemented.
5229
5230 ### Removed
5231
5232 - The no-progress guard, repeated-read guard, and injected tool-error strategy
5233 coaching. Productive polling, repeated inspection, and model-owned recovery
5234 are no longer interrupted by runtime heuristics.
5235 - Never-wired decision-card, keybinding, hover, shell-execution, engine-op, and
5236 release-script paths were deleted so the supported runtime has one route for
5237 each behavior.
5238
5239 ### Contributors
5240
5241 - Xavier Pestel (@xavierpestel-ai) — Mistral AI provider route (#5295).
5242 - Ben Younes (@ousamabenyounes) — inherited nested-agent depth cap (#5317).
5243 - Rafael Cavalheri (@rafaelcavalheri) — ACP agentic tool turns (#5225).
5244
5245 ## [0.9.5] - 2026-08-08
5246
5247 Codewhale v0.9.5 consolidates the terminal application into one compiled
5248 runtime while preserving the familiar `codewhale` and `codew` commands. It
5249 also expands the managed Runtime API, makes session and Fleet work easier to
5250 inspect and resume, and removes the hidden local continuation backstop that
5251 could end productive work without a final assistant response.
5252
5253 ### Added
5254
5255 - **`model = "auto"` for prompt-based tier selection**: When set, the
5256 dispatcher analyses the user's prompt before delegating to the TUI and
5257 selects `deepseek-v4-pro` for complex tasks or `deepseek-v4-flash` for simple
5258 tasks (PR #5257).
5259 - Runtime API controls for persistent goals, bounded memory inspection, MCP
5260 server and skill lifecycle management, and durable Fleet receipt evidence.
5261 - Append-only session-tree history with `/tree`, `/branch`, `/fork`, and
5262 `/resume`, plus `/rc` remote control and managed login.
5263 - A unified Fleet roster for built-in dispatch postures and a pinned indicator
5264 that keeps active background work visible above the composer.
5265 - Incremental MCP registry refreshes that return the local snapshot immediately
5266 and update it in the background.
5267 - Scout and Reviewer agents can use a bounded direct-command evidence shell for
5268 read-only workspace, Git, and GitHub inspection, and can keep private working
5269 notes in their own To-do while the durable transcript retains their evidence.
5270
5271 ### Changed
5272
5273 - `codewhale-cli` now contains the terminal runtime directly. Release installers
5274 expose byte-identical `codewhale` and `codew` commands without a separate TUI
5275 executable. v0.9.5 introduced deprecated `codewhale-tui-*` release filenames
5276 as byte-identical compatibility copies; later releases retain those filenames
5277 while installed v0.9.4 clients remain supported upgrade sources.
5278 - Startup release checks cache successful lookups for one hour. The updater
5279 downloads and verifies the primary runtime once, then refreshes any existing
5280 `codew` or legacy `codewhale-tui` command paths from the same bytes.
5281 - Headless `codewhale exec` runs and verifier benchmark rollouts no longer
5282 impose a 100-step default. `--max-turns` remains available as an explicit
5283 opt-in ceiling; Fleet workers retain their separately configured budget.
5284 - Goal token and time budgets are telemetry rather than default stop
5285 conditions, and automatic goal continuation is unlimited unless the user
5286 explicitly configures a continuation ceiling.
5287 - Command-palette and slash-completion shadowing now share one alias-aware
5288 discovery contract.
5289 - The website install guidance, localized product copy, navigation controls,
5290 social metadata, and Cloudflare build pipeline now describe and deploy the
5291 same one-runtime release contract.
5292
5293 ### Fixed
5294
5295 - The hidden 20-step no-user-input backstop no longer ends productive turns.
5296 Tool results, queued steering, child completions, REPL feedback, and goal
5297 continuations can all reach the next provider step and a final assistant
5298 response; explicit user-configured limits and genuine stuck-loop guards remain.
5299 - Complete error details are directly inspectable after a failure instead of
5300 leaving the terminal with a clipped, unrecoverable error fragment.
5301 - A newly minted OAuth credential is adopted in the same provider-selection
5302 flow instead of requiring a second picker trip.
5303 - Fresh session titles can replace a stale cached `New Session` placeholder,
5304 unknown model context limits fail loudly, and release/source-install fallbacks
5305 no longer request binaries removed by the single-runtime conversion.
5306
5307 ### Contributors
5308
5309 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) fixed stale
5310 cached session titles that could pin the `New Session` placeholder.
5311 - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) built the
5312 shared alias-aware command discovery contract and acceptance coverage.
5313 - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) contributed the
5314 background incremental MCP Registry refresh.
5315 - [SKY ZHAO](https://github.com/skyzhao1223) (`@skyzhao1223`) contributed
5316 prompt-based `model = "auto"` routing in PR #5257.
5317
5318 ## [0.9.4] - 2026-08-07
5319 Codewhale v0.9.4 ships the release-train harness work: the familiar Fleet
5320 roster/setup face with a clear operator-leader and user/folder scope, a
5321 work strip that keeps actionable agents instead of a permanent archive,
5322 waiting policy that forbids polling without freezing independent work,
5323 calmer tool output and session recovery, account/Workflow-search/
5324 automation/handoff surfaces, a shorter translation-ready website, and
5325 release-blocker fixes across permissions, DeepSeek Responses, SQLite,
5326 File edits, terminal width, and Windows installation.
5327
5328 ### Added
5329
5330 - Memory maintenance: `remember` gains `revise` and `retire` beside the
5331 default `append`. Both name the exact note they target and both require
5332 the evidence for the change. Append-only memory decays — a correction
5333 sits behind the note it contradicts and both keep reaching the model —
5334 so the model can now keep its own durable notes true instead of only
5335 adding to them.
5336 - An audit trail for durable state the model writes about you. Every
5337 in-place memory edit is journalled to `memory/JOURNAL.md`, and every
5338 continual-harness `refine` / `remove` to a `JOURNAL.md` beside its state,
5339 each with before, after, and evidence. Harness removal previously left no
5340 record at all even though the entry leaves state entirely, so the journal
5341 is now the only place its content survives.
5342 - A first-run tip that says so: the first time Codewhale saves something
5343 durable it points at `/memory`, translated into all fifteen complete
5344 locale packs. This state shaped later sessions and nothing ever mentioned
5345 it existed.
5346
5347 - Sub-agent checkpoint resume: `agents/followup` resumes an
5348 `interrupted_continuable` child from its checkpoint into a fresh agent loop —
5349 new agent id, original prompt plus the prior conversation tail — when a
5350 runtime is attached, and otherwise keeps queue-only semantics with the
5351 `continuation_handle` returned; a second followup on the same interrupted id
5352 returns the existing resumed target instead of spawning a duplicate (PR #5242).
5353 - MCP Registry discovery with Registry-first tool selection: `registry_sync`
5354 surfaces the eligible local stdio catalog as a complete model-side candidate
5355 set, connect-failure messages classify early-exit and usage-help output and
5356 point recovery at the next Registry candidate, and a bundled `mcp-discovery`
5357 skill documents the flow (PR #5238).
5358 - Progressive fresh-context disclosure: fresh sessions ship a minimal
5359 constitutional kernel — ground truth, user intent and scope, truthful
5360 completion, guarantees in mechanism, and precedence — with procedural
5361 playbooks disclosed on demand, an opt-in project context pack
5362 (`project_context_pack_enabled`) counted in context reports, and `load_skill`
5363 catalogue discovery via `name="list"`; the measured fresh-context budget
5364 drops by roughly 40% (PR #5077).
5365 - Named Fleet store v2: one self-contained TOML Fleet per configuration
5366 (`schema = "fleet"`), with scope-explicit selection (user-global default vs
5367 folder override), migration receipts from legacy role profiles, and atomic
5368 saves that refuse to clobber a different Fleet on the same slug.
5369 - Scout replaces the user-facing "faster" control: catalog-verified fast
5370 siblings only, never a guessed model name; pinned Scout survives operator
5371 changes.
5372 - Truthful model-picker rows: vision/tools/limits chips only when the catalog
5373 knows, with provider → family → exact model grouping.
5374
5375 - **Opt-in product telemetry, off by default.** A first-run notice asks once, on
5376 a terminal, with declining pre-selected — Enter declines. Nothing is collected
5377 unless both `telemetry = true` and a recorded "Enable" answer are present, so
5378 a `telemetry = true` written before this release stays inert: the key has been
5379 settable and inert for a long time, and setting it was never consent.
5380
5381 An enabled session sends its batches to the first-party ingest endpoint,
5382 `https://telemetry.codewhale.net/v1/telemetry`, which is the shipped default
5383 for `telemetry_endpoint`. That is a Cloudflare Worker whose complete source is
5384 in this repository under `telemetry-ingest/`; it writes to Workers Analytics
5385 Engine, whose row is exactly `_sample_interval`, `blob1`–`blob20`, `dataset`,
5386 `double1`–`double20`, `index1`, and `timestamp` — **there is no IP, country,
5387 or geo column**, so storing one is structurally impossible rather than merely
5388 disabled. The handler reads two request headers, never touches the request's
5389 geo properties, logs nothing, and validates against a closed field set that
5390 rejects an entire batch carrying any unpublished key. Cloudflare's retention
5391 for that data is a fixed three months. Setting `telemetry_endpoint = ""`
5392 instead writes each batch to `$CODEWHALE_HOME/telemetry/dryrun.jsonl` and
5393 constructs no HTTP client at all, so you can read exactly what would have been
5394 sent.
5395
5396 Turning it off is an answer, not a flag: it deletes the random install id,
5397 truncates every buffered event, and leaves a permanent tombstone that a
5398 session already running re-checks before it appends and before it sends. A
5399 failed wipe fails closed. `CODEWHALE_TELEMETRY=0` is a hard floor that beats
5400 `--telemetry true` and the config key, and a value the parser cannot read
5401 also resolves to off. Fleet workers are hard-off. A repo-local
5402 `.codewhale/config.toml` can set neither key.
5403
5404 Never collected: prompts, completions, tool arguments, diffs, file contents,
5405 filenames, paths, git remotes, repo or branch names, memory entries, chat
5406 history, credentials (not even a boolean asserting one exists), model ids,
5407 custom provider table names, MCP server names, error or panic message bodies,
5408 per-event timestamps, keystrokes, clipboard, screenshots, or location. The
5409 full schema is [`docs/TELEMETRY.md`](docs/TELEMETRY.md), and a test parses the
5410 field names out of that file and asserts set equality with the structs the
5411 serializer uses.
5412
5413 This supersedes the roadmap's previous "no Codewhale product telemetry" entry,
5414 which moves from "Ruled out" to an opt-in framing. What stays ruled out:
5415 always-on or silent telemetry, per-keystroke or per-tool-call phone-home, and
5416 any third-party ad or analytics SDK in the runtime binary.
5417 - Registered `GLM-5.3` (direct Z.ai) and `z-ai/glm-5.3` (OpenRouter) as
5418 selectable GLM routes, with their aliases (`glm-5.3`, `glm-5-3`,
5419 `zai-glm-5.3`, `zai-glm-5-3`). Z.ai had **not released GLM-5.3 as of
5420 2026-08-03** — the ids are registered so they resolve to the Z.ai/OpenRouter
5421 routes instead of being rewritten to another vendor's model, and they will
5422 fail upstream until Z.ai ships the model. Metadata (context, output,
5423 reasoning controls) is inherited wholesale from `GLM-5.2` pending official
5424 Z.ai release metadata; pricing is intentionally absent, and `GLM-5.2` remains
5425 the default Z.ai model. No third-party gateway roster gained the model:
5426 OpenCode Zen, OpenCode Go, Alibaba Model Studio, and TelecomJS publish no
5427 glm-5.3 entry, so Codewhale advertises none.
5428
5429 - Managed Codewhale account commands (`account login`, `status`, `logout`, and
5430 `keys`) with browser device flow, profile- and origin-scoped secure sessions,
5431 refresh/revocation, redacted BYOK-vault management, and a token-free Runtime
5432 account receipt. Provider authentication remains separate, and `cloud`
5433 remains a compatibility alias.
5434 - `/automation` operator controls to list, inspect, pause, resume, delete, and
5435 run durable automations. Creation remains on the approval-gated
5436 model-visible `automation` tool.
5437 - A provider-neutral `WorkflowSearchSpec` authoring and freeze boundary, plus
5438 structured 2–16-candidate experimental search in the best-of-N Workflow
5439 starter. It freezes baseline, route, evidence, evaluator, gate, score, budget,
5440 and review policy before admission; it validates gate/scoring commands but
5441 does not execute or certify them itself.
5442 - The bundled generation-9 `handoff` skill for compact, decision-ready
5443 continuation across sessions.
5444 - Expanded terminal LaTeX rendering for aligned and matrix environments,
5445 cases, arrays, text/font/accent commands, brackets, symbols, and
5446 command-aware scripts (PR #4981).
5447 - Exact 40-character build provenance and secure account-session capability
5448 receipts on `/v1/runtime/info`; unknown source provenance continues to fail
5449 closed.
5450 - Acceptance-level Gherkin coverage locking the existing user-command
5451 precedence, alias shadowing, fallback, and invalid-command error contract
5452 (PR #4992).
5453 - Agent Plugins v1.0.0: consume, publish, and slugify packaged sub-agent
5454 briefs, with an install/update/uninstall on-ramp in the TUI (PR #5182). A
5455 plugin bundles a prompt, posture, and routing as one shareable artifact;
5456 on-disk migration of the older `plugin.toml` scaffold is deliberately out
5457 of scope for this train.
5458 - `send_later`: a model-callable one-shot delayed continuation tool, so the
5459 model can schedule a single future nudge without an operator-approved
5460 durable automation (PR #5138).
5461 - `/advisor`: an opt-in background advisor watcher for live turns (PR #5139).
5462 - Notification quiet mode with per-category switches and action-first copy
5463 (PR #5066).
5464 - Automation scheduling forms — one-shot `ONCE`, five-field cron, and honest
5465 watcher modes — created through the approval-gated `automation` tool
5466 (PR #5183).
5467 - Sub-agent `resume_from` continuation chains (PR #5142), child-result
5468 diff-tainting when a claimed diff is not visible to git, per-turn usage
5469 receipts on the exec stream-json stream, and spawn receipts that report
5470 the model each sub-agent actually ran on.
5471 - Transport resilience: sub-agent exec transport retries with a 600 s
5472 default (PR #5210), SSE header stalls retryable instead of fatal, and
5473 headless turn resume after mid-stream network drops with an `EX_TEMPFAIL`
5474 exit.
5475 - Session durability and control: a deterministic compaction continuation
5476 contract (PR #5064), persisting interrupted output (PR #5206), stop-word
5477 cancellation (PR #5207), token-counter refresh (PR #5204), deny-by-default
5478 approval cards (PR #5090), and the Operate completion gate (PR #5067).
5479 - zh-Hant promoted to a full shipped locale with complete `en.json` parity
5480 (PR #5143).
5481 - A persistent update-available chip in the header, with the startup update
5482 check throttled and naming the right command.
5483 - RLM static intent extraction for code blocks (`rlm_block_intent.rs`)
5484 landed as groundwork for a future code-mode approval flow; it is not yet
5485 wired into the turn pipeline and ships dormant by design.
5486
5487 ### Changed
5488
5489 - `/fleet` is the familiar roster/setup face again. The operator row is the
5490 Fleet leader (session model); the header names the selected saved Fleet and
5491 whether it is user-global or folder-scoped. Named-Fleet switching lives under
5492 `/fleet fleets` (Enter selects in the row's own scope). Session route changes
5493 stay temporary until `/fleet save`, `/fleet save-as`, or `/model save-default`.
5494 - Waiting-for-subagents directions forbid peek/status polling and sleep-as-wait,
5495 but allow independent work that does not depend on a child's result — the
5496 parent no longer freezes mid-turn with useful non-conflicting work available.
5497 - `workflow run` no longer requires `--fleet`; a saved Fleet is an optional pin
5498 layer over roles + the session route.
5499 - Homepage and getting-started copy is shorter and scannable across locales,
5500 with dictionary key and `{brand}` token parity preserved.
5501
5502 - Tool results now render as ordinary bounded previews with real expansion;
5503 storage, retention-ledger, and internal evidence language no longer leak into
5504 normal transcripts.
5505 - Prose wrapping, goal state, modal questions, composer-tail behavior, and
5506 ambient motion now follow one deterministic interface contract across narrow
5507 terminals and fast streams.
5508 - Scout and reviewer Fleet roles gain network access and the bounded
5509 verification surface for real reconnaissance while retaining the no-write,
5510 no-raw-shell security floor.
5511 - Workflow runs may describe up to 1,000 tasks while admitting at most 16 live
5512 tasks at once through the host concurrency gate. Tournament ordering now
5513 supports explicit score-first selection while retaining its cost-first
5514 default.
5515 - Runtime permission compatibility inputs resolve to one live
5516 `permission_posture`. Auto-Review can proceed without approval or structured
5517 question modals, unresolved holds fail closed, and a call planned under stale
5518 authority is retried after a posture change (PR #5025).
5519 - Duplicate and drifting per-turn metadata has been removed in favor of
5520 runtime-owned authority, and large inline account and skill tests now live in
5521 owned test seams.
5522 - Pinned Ratatui to 0.30.0 and ratatui-core to 0.1.0. ratatui-core 0.1.1+
5523 makes `Terminal::clear()` issue a blocking cursor-position report that
5524 raced the TUI input loop and could kill first launch; both pins are
5525 load-bearing, because 0.30.0 declares `ratatui-core ^0.1` and would
5526 otherwise resolve forward on its own (PR #5192 by @bistack; upstream
5527 ratatui/ratatui#2640).
5528 - Updated globset to 0.4.19, clap-complete to 4.6.8,
5529 futures-util to 0.3.33, libc to 0.2.189, actions/stale to 11.0.0, and
5530 docker/login-action to 4.5.2. The locked graph also includes the
5531 event-listener 5.4.2 fix for RUSTSEC-2026-0221.
5532 - The progress surface now speaks plainly everywhere: the last user-visible
5533 "Work update is pending" notices say "To-do list", the tool constructor and
5534 the docs name `todo_write` as the single canonical progress tool, and
5535 `work_update`, `TodoWrite`, and `todo` stay registered as hidden
5536 compatibility aliases so saved transcripts keep replaying.
5537 - Sub-agent and `agents/wait` waits stay short by default and by cap:
5538 blocking waits default to 30 s and refuse to block past 120 s, because a
5539 blocked wait deafens the session to typed input and settled children
5540 already report back as `<codewhale:subagent.done>` sentinels.
5541 - `Bash` `action=wait` honors `timeout_secs` (seconds) and bare `timeout`
5542 (milliseconds) alongside canonical `timeout_ms`, and `block` as an alias
5543 for `wait`, so a habit formed on other wait tools gets the duration it
5544 asked for instead of silently falling back to the 30 s default; the result
5545 metadata reports the real `wait_timeout_ms` applied.
5546
5547 ### Fixed
5548
5549 - The memory journal is no longer indexed as memory. It is Markdown in the
5550 memory tree, so the source walk collected it and every retired note
5551 re-entered the searchable set under its `before:` line — putting the
5552 exact facts a revision had just removed back into the prompt.
5553 - `memory_path` pointed at an already-native store no longer derives a
5554 second store nested inside it, which silently wrote somewhere other than
5555 the file the user named.
5556 - `muse` and `muse-spark` resolved to `muse-spark-1.1` in the agent
5557 registry while config had defaulted to `muse-spark-1.2`, so the CLI and
5558 app-server routed those aliases somewhere the configured default never
5559 pointed. The registry now carries 1.2 and the contributor variant.
5560
5561 - An explicit `type=builder` (or its `implementer` alias) plus
5562 `write_authority=read_only` now fails closed at spawn instead of launching a
5563 labeled write role that silently had only read-only tools and then self-BLOCKED
5564 after burning a turn (#5123). The check is deliberately narrow, because two
5565 neighbouring combinations are legitimate and stay legal:
5566 - `type=worker` + `read_only` — worker is the unnamed default (it renders as
5567 `general`) and takes its capability from authority, not from its name, so a
5568 read-only worker is an ordinary general-purpose child. Worker, scout,
5569 reviewer, and verifier remain the four canonical read-only Fleet roles.
5570 - any `role` + `read_only` — `role` is an identity for roster resolution, not
5571 a capability claim, so an acceptance Workflow can still resolve
5572 `implementer` to its saved profile while scoping that child to verification.
5573
5574 Callers that spelled a read-only narrowing as `type: "implementer"` should
5575 move it to `role: "implementer"`.
5576 - User-global credentials survive an explicit workspace `CODEWHALE_CONFIG_PATH`
5577 that selects a route with no local key — readiness probes the user-global
5578 provider table before concluding a key is missing.
5579 - Sub-agent token figures on the work bar accumulate input+output (the same
5580 total the worker budget uses) instead of completion tokens alone; elapsed
5581 time still freezes when the child settles.
5582 - Live work-bar rows for sub-agents show how many to-dos they still have
5583 left (`N left`) when the child's own list has unsettled items — never a
5584 fabricated zero when no list exists.
5585
5586 - Surfaces no longer claim an OS sandbox on platforms that cannot enforce one.
5587 The policy resolver takes no platform input, so on default Linux (bubblewrap
5588 is opt-in) and on all Windows the header chip read `files: workspace` and
5589 `/status` read `sandbox workspace-write` while nothing was restricted. Both
5590 now resolve the real backend and say `(unenforced)`.
5591 - `tool_category` hook conditions matched only retired tool names, so a
5592 `category = "shell"` **deny** hook — the security control `docs/HOOKS.md`
5593 documents — silently never fired. Categories now use the registered names,
5594 and multi-action tools classify by action.
5595 - A `Retry-After` header of `-5`, `nan`, or `1e300` crashed the request task
5596 (`Duration::from_secs_f64` panics on a negative). Parsing is now guarded and
5597 bounded to one hour.
5598 - Bearer tokens no longer leak into operator-visible receipts. `Authorization:
5599 Bearer <jwt>` split into two tokens and the JWT matched no redaction rule;
5600 prefix matching was also case-sensitive, so `SK-live-…` survived.
5601 - `prune_older_than` destroyed the NEWEST rollback snapshots and kept the old
5602 ones — on every boot, for any workspace with snapshots spanning the retention
5603 window. Both prune paths now share one orphan-chain rebuild and preserve each
5604 survivor's real timestamp.
5605 - An absolute or relative command path no longer defeats every execpolicy deny
5606 rule (`/bin/rm -rf /` did not match a `rm -rf /` rule), and a typed `Allow`
5607 rule no longer auto-approves a chained suffix such as `git log ; curl … | sh`.
5608 - Wrong types on `File` read range params and `Bash` stdin/cwd/task_id are now
5609 errors instead of silent defaults — a `start_line:"1200"` string used to
5610 return the head of the file, and a non-string `stdin` ran the command with no
5611 stdin and reported success.
5612 - Multibyte tool ids no longer panic the context inspector, wide (CJK) text no
5613 longer overflows the decision card, and a hostname like `127.evil.example.com`
5614 is no longer treated as loopback.
5615 - Refusals name calls the model can actually make (`rlm action='open'` rather
5616 than a retired `rlm_open`; `Bash` rather than `exec_shell`).
5617
5618 - Sub-agent dispatch no longer aborts the process. The Tokio runtime was built
5619 by `#[tokio::main]`, leaving every worker thread on the 2 MiB default while
5620 only the owner thread received the explicit 16 MiB stack — and the engine runs
5621 on a worker. A debug-build `agent` dispatch exceeded that stack and raised
5622 SIGABRT, which is not a panic and so could not be caught; the process died
5623 mid-spawn with no child request ever issued. Release builds were unaffected.
5624 - Fleet profiles that pin a provider no longer leak a bare model id onto the
5625 session route. `model_overrides` exported each role's model while dropping its
5626 provider, so a scout pinned to another provider's model was dispatched against
5627 the active client and denied at the wire — visible as an instant auth failure
5628 on the first sub-agent of a fan-out.
5629 - The rail's Pinned panel no longer spends four rows saying "No active work".
5630 An empty panel now collapses like the Tasks panel always has, and the settings
5631 migration no longer folds the default `sidebar_focus = "auto"` into a pinned
5632 always-on strip, which had silently handed that panel to every user who had a
5633 settings file at all. (An *empty* panel collapses; a panel holding settled
5634 to-dos or finished workers is not empty — see the standing-register entry
5635 below.)
5636 - The work bar keeps settled to-dos and an honest Subagents header, while
5637 completed/cancelled workers collapse out of the Top strip so fan-outs do not
5638 permanently eat the transcript. Failed or interrupted workers stay visible
5639 (they still need attention). Settled agents remain reachable through the
5640 Agents panel and catalog. To-do rows say their state in words (pending /
5641 in progress / completed / cancelled), and sub-agent rows carry type,
5642 objective, elapsed, and input+output tokens. Every work row is a door in
5643 every rail panel and placement: click and Enter open the row's world
5644 (work inspector / agent details — finished agents included) instead of
5645 doing nothing. A click after the detail pager closed itself reopens the
5646 detail rather than being swallowed by a stale toggle.
5647 - The rail strip yields its rows to the transcript when the terminal cannot
5648 seat both, so the idle ocean survives at 24 rows instead of being evicted.
5649 - `code_execution` and `js_execution` no longer describe themselves to the model
5650 as sandboxed. Both are ordinary local subprocesses with no seccomp, jail, or
5651 container (PR #5221 by @h3c-hexin and @asto18089).
5652 - Model Studio reasoning controls now fail closed on the host rather than on the
5653 provider enum, so a custom `base_url` no longer receives Alibaba-specific
5654 `enable_thinking` fields, and `qwen3.8-max` is no longer sent a thinking
5655 switch it does not accept (PR #5233 by @Inference1, closing #5203).
5656 - `config.example.toml` no longer claims Shift+Tab cycles the reasoning tier.
5657 Shift+Tab cycles the permission posture; Ctrl+T cycles reasoning
5658 (found by @vFONGv, PR #5229).
5659
5660 - Alibaba Model Studio reasoning controls are now route- and model-scoped
5661 instead of provider-wide (#5203, harvested from #5233 by
5662 [@Inference1](https://github.com/Inference1)). Codewhale sends
5663 `enable_thinking` / `preserve_thinking` / `reasoning_effort` only when the
5664 configured `base_url` is a verified Alibaba Chat Completions host, so
5665 pointing a `modelstudio-*` provider ID at a custom gateway no longer injects
5666 DashScope's dialect into it. `qwen3.8-max` and `qwen3.8-max-preview` are
5667 thinking-only and no longer receive an `enable_thinking: false` they cannot
5668 honor; `preserve_thinking` is sent for the models documented to accept it, so
5669 their reasoning trace survives into the next turn; and `deepseek-v4*` /
5670 `glm-5.x` map the reasoning tier onto the documented `high` / `max` ladder.
5671
5672 - xAI device login now recovers from a config that points at a missing
5673 Codewhale-owned credential generation instead of failing every attempt
5674 with a generic activation error, and finalize failures report the full
5675 error chain (#5032).
5676 - API keys saved to the secret store no longer read as unconfigured for
5677 providers that are not currently active; a configured Kimi/Moonshot key
5678 survives provider switches and restarts without re-entry (#5033).
5679 - Switching to the Codex provider with no saved model now lands on the live
5680 roster's flagship model instead of a stale static default (#5034).
5681 - Worktree-isolated Fleet builders no longer contend on the per-workspace
5682 delegated-coordination lock, and a failed lock acquisition is retried on
5683 use instead of being memoized for the life of the process (#5036).
5684 - Fleet dispatch now rebinds the child client when the resolved profile
5685 model requires a different wire protocol (DeepSeek flash on Responses),
5686 instead of failing deterministically on the worker's first request
5687 (#5042).
5688 - DeepSeek Responses now sends `reasoning.effort: "none"` for the Off tier,
5689 shows a truthful notice instead of silently discarding server-side
5690 `web_search_call` items, and parses cache-hit, cache-miss, cache-write, and
5691 pricing telemetry while retaining the OpenAI-style nested fallback.
5692 - File edits now explain no-op and missing-search failures, reject newly
5693 unbalanced C/C++ preprocessor replacements, handle the reported
5694 CRLF/non-ASCII cases, and safely relocate stale unified-diff hunks only when
5695 whole-file context is unique (PRs #5008 and #5030).
5696 - Circled digits, enclosed alphanumerics, and keycap graphemes use consistent
5697 two-column measurement in Codewhale, Ratatui, and CJK terminals, preventing
5698 missing-character and phantom-space corruption (PR #5001).
5699 - SQLite connections install their busy timeout before locking setup and avoid
5700 rewriting persistent WAL mode on every open, removing the concurrent-open
5701 release-gate failure.
5702 - The Windows installer preserves long current-user `PATH` values, their
5703 registry type, and unrelated entries across install and uninstall (PR #5006).
5704 - Provider configuration no longer contains user-reachable panic paths when
5705 metadata or prior credential state is missing.
5706 - Resuming a session restores composer text only from a same-session persisted
5707 draft; submitted prompts and internal background-runtime envelopes remain in
5708 history instead of appearing in the composer (PR #5029).
5709 - Shared CI now handles bot-authored issue-link checks, provisions cargo-deny's
5710 toolchain, and fetches the locked test graph before offline runtime-budget
5711 validation.
5712 - Re-quote each linker argument in the Windows OpenHarmony clang launcher so a
5713 spaced SDK path (e.g. the default `D:\DevEco Studio\...` install) keeps its
5714 `--sysroot` intact through the final Rust link, and extend the no-SDK release
5715 guard to keep the re-quoting contract (PR #5095).
5716
5717 - The shell tool reports the real elapsed wait time in its result content
5718 instead of echoing the requested timeout (PR #5240).
5719 - Transcript wheel scrolling under iTerm2: xterm alternate-scroll (DECSET
5720 1007) now stays off while mouse capture is active, so wheel events arrive as
5721 mouse events instead of being converted into arrow keys (#5223, PR #5234).
5722 - A stalled model stream no longer ends the turn as `Completed` over a
5723 frozen reasoning block: a mid-stream chunk-timeout now counts toward the
5724 stream-error budget, so a stall with nothing streamed retries the request
5725 transparently, and a stall that exhausts the retry budget fails the turn
5726 with the real reason instead of reporting success.
5727 - A finished background shell task now wakes the engine even when no goal is
5728 active: the idle loop starts an ordinary runtime turn so the completion
5729 reaches the model immediately instead of sitting unclaimed until the user
5730 types (a dead provider route claims the completion once and reports where
5731 the output lives instead of re-arming the same error every tick).
5732 - Sub-agent final reports that exceed the summary budget are now spilled to
5733 a session artifact, and the truncation footer names the
5734 `retrieve_tool_result` ref for the elided middle instead of telling the
5735 model the bytes are unrecoverable; write failures degrade to the honest
5736 no-ref footer.
5737 - An interactive mid-stream network drop after partial output no longer fails
5738 the turn: the partial reply is preserved as a committed assistant message,
5739 a runtime continuation message is appended, and the request is re-issued
5740 bounded by the stream-retry budget.
5741 - Large pasted input is no longer sent to the model twice as inline text and
5742 as a backup `.md` paste file; the submitted message now carries only the
5743 `@`-mention so the model reads the file once.
5744 - A builder sub-agent can run ordinary shell writes again. Write claims
5745 outlive the agents that register them, so a workspace accumulated one per
5746 builder that ever ran — six completed agents left four standing claims in
5747 testing — and the shared-checkout gate counted those long-finished children
5748 as live contenders. Every later builder was refused `Bash` writes with
5749 "cannot prove a bounded file target" and pushed toward worktree isolation,
5750 which puts the work in a checkout the operator never looks at. The gate now
5751 asks the question it meant to ask: is another *running* child writing in this
5752 shared checkout. Concurrent writers are still gated; a lone builder writes in
5753 the workspace you are actually watching.
5754 - Ctrl-C during the first moments of startup no longer kills Codewhale
5755 outright. The terminating-signal handlers were registered inside the task
5756 that waits on them, and a spawned task does not run until the scheduler
5757 first polls it, so a SIGINT arriving in that window hit the default
5758 disposition — the process died with no exit code, no terminal restore, and
5759 no session record. The handlers are now installed synchronously, before
5760 the telemetry notice and before arming, so the window is closed.
5761 - The documented tool list on the docs site named `update_plan` and
5762 `work_update` as coordination tools. Neither is callable by the model —
5763 `update_plan` replays older Plan artifacts and `work_update` is a hidden
5764 compatibility alias — so the page listed two tools a reader cannot use and
5765 omitted `todo_write`, the one they can.
5766
5767 ### Security
5768
5769 - Bumped `nanoid` past GHSA-2v37-7h3g-55p8 (a custom generator given size
5770 zero could loop indefinitely), restoring a zero-advisory `npm audit` for
5771 the website.
5772
5773 - Google Gemini is its own backend (`/provider google`) on the official
5774 OpenAI-compatible route with thought-signature capture/replay and
5775 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
5776 as a separate credential-plane provider: consent-gated read-only import
5777 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
5778 precedence; requests fail closed until the cloud-code wire protocol is
5779 implemented.
5780
5781 ### Removed
5782
5783 - The default model-facing SlopLedger implementation, its storage-oriented
5784 transcript language, and the `/debt`, `/cleanup`, `/slop`, and `/canzha`
5785 command surface.
5786
5787 ### Contributors
5788
5789 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) contributed
5790 LaTeX rendering in PR #4981, completed circled-digit/keycap width handling in
5791 PR #5001, and delivered actionable File-edit recovery in PR #5008; for this
5792 train he resumed interrupted sub-agents from checkpoints in PR #5242,
5793 surfaced real shell wait elapsed time in PR #5240, and kept alternate-scroll
5794 off while mouse capture is active in PR #5234.
5795 - [XhesicaFrost](https://github.com/XhesicaFrost) (`@XhesicaFrost`) fixed long
5796 Windows user-PATH preservation in PR #5006.
5797 - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) added the
5798 user-command dispatch acceptance contract in PR #4992.
5799 - [DracheTek](https://github.com/DracheTek) (`@DracheTek`) provided the
5800 multilingual, CRLF-heavy File-edit failure report in issue #5003.
5801 - [An Ziwu](https://github.com/MuRongMoQing) (`@MuRongMoQing`) reported the
5802 Windows PATH-overwrite defect in issue #4685.
5803 - [shenjackyuanjie](https://github.com/shenjackyuanjie) (`@shenjackyuanjie`)
5804 fixed the Windows OpenHarmony linker re-quoting for spaced SDK paths in
5805 PR #5095.
5806 - [bistack](https://github.com/bistack) (`@bistack`) contributed MCP Registry
5807 discovery with Registry-first tool selection in PR #5238.
5808 - [vFONGv](https://github.com/vFONGv) (`@vFONGv`) wrote the zh-CN Windows
5809 beginner guide with screenshots in PR #5229, harvested after its base branch
5810 was accidentally deleted during maintainer cleanup.
5811 - [mky](https://github.com/mky) (`@mky`) fixed the FreeBSD build (PR #5254, `rquickjs` `bindgen` on FreeBSD).
5812 - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) contributed embedder-owned sub-agent state roots (PR #5252).
5813
5814 ## [0.9.3] - 2026-07-31
5815
5816 This is the Codewhale v0.9.3 source candidate. It is not a published release
5817 until the matching tag, packages, checksums, and release assets exist.
5818
5819 DeepSeek V4 Flash is now a first-class Codewhale route, and the agent-facing
5820 tool surface has been reduced to the canonical action tools that current
5821 models actually need. This release also hardens credential, authorization,
5822 durability, compaction, and macOS File Provider boundaries while deleting
5823 stale runtime and dependency surface.
5824
5825 ### Added
5826
5827 - Native `deepseek-v4-flash` support over DeepSeek's Responses API, including
5828 stateless reasoning-item replay, semantic SSE terminal events, structured
5829 function calls and outputs, `apply_patch`, and model-aware wire-format
5830 selection. Exact current Flash IDs use Responses; future direct
5831 `deepseek-vN-*` model IDs inherit that route conservatively, while custom
5832 DeepSeek-compatible endpoints retain Chat Completions unless configured
5833 otherwise.
5834 - A pipe-only `codewhale auth print-api-key` handoff for explicitly selected
5835 providers. It shares Codewhale's home-scoped credential authority, refuses
5836 terminal output, and prevents sentinel placeholders from becoming live
5837 credentials.
5838 - Per-turn `max_tool_calls` enforcement at the engine admission gate, plus a
5839 named-file write scope with a separate read seam. The runtime now rejects
5840 over-budget calls before execution and keeps the operator's write boundary
5841 explicit (#4415).
5842 - Runtime-contract, source-structure, and persistence-backlog ratchets that
5843 name drift instead of allowing large ownership surfaces to grow silently
5844 (#3921, #4785).
5845
5846 ### Changed
5847
5848 - Model-visible built-ins now use the canonical `Bash`, `File`, and `Run`
5849 action schemas. `apply_patch` remains available as the one direct custom
5850 edit tool supported by DeepSeek Responses. The bundled stop-ship workflow,
5851 Fleet fixtures, shell shortcut, and engine tests use the same canonical
5852 vocabulary.
5853 - Canonical `File { action: "write" }` requests now pass through the same
5854 semantic repo-law checks as the former write path. Approval, Full Access,
5855 and workflow execution cannot bypass the repository safety floor by choosing
5856 the canonical schema.
5857 - Codewhale home resolution is shared across the CLI, TUI, state, and secret
5858 stores. `doctor` is offline by default, distinguishes credential source from
5859 availability, and reports one consistent path snapshot.
5860 - Durable runtime event writes are serialized across simultaneous processes,
5861 blocking history waits move off async workers, and provider quota exhaustion
5862 remains typed and retryable through compaction (#4522).
5863 - Skill discovery caches the merged catalog behind watched-mtime validation;
5864 large skill, engine, subagent, UI, and ambient-ocean test blocks now live in
5865 owned test seams.
5866 - Reasoning summaries stay in the user's language, complete jellyfish
5867 silhouettes relocate around transcript text, and cached ocean frames include
5868 their palette identity (#4807).
5869 - The authorization-order contract now documents and tests how modes, hooks,
5870 permission rules, safety floors, repo law, approvals, and sandboxing compose
5871 (PR #4980).
5872
5873 ### Fixed
5874
5875 - macOS sandbox extensions cover CloudStorage/File Provider workspaces without
5876 broadening unrelated paths; thanks @Watcher24 for the #4085 report and
5877 reproduction.
5878 - Foreground shell state detaches before steering, so an interrupted command
5879 cannot keep owning the composer (PR #4979).
5880 - MCP application-level failures and malformed error envelopes fail closed
5881 instead of looking like successful tool output.
5882 - Optional PDF failures are truthful and PDF classification no longer misses
5883 supported inputs.
5884 - Bracketed-paste contents are redacted from traces, and credential diagnostics
5885 never treat placeholder sentinels as usable keys.
5886
5887 - Google Gemini is its own backend (`/provider google`) on the official
5888 OpenAI-compatible route with thought-signature capture/replay and
5889 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
5890 as a separate credential-plane provider: consent-gated read-only import
5891 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
5892 precedence; requests fail closed until the cloud-code wire protocol is
5893 implemented.
5894
5895 ### Removed
5896
5897 - The legacy callable aliases `exec_shell`, `run_shell_command`, `read_file`,
5898 `write_file`, `list_dir`, `grep_files`, `file_search`, and the duplicate
5899 Work/RLM registrations. Historical transcript and policy semantics remain
5900 readable, but new model turns receive only the canonical action surface.
5901 - The bundled PDF parser dependency chain, replacing it with the smaller
5902 optional extraction boundary tracked by #4382.
5903
5904 ### Contributors
5905
5906 - [Turisla](https://github.com/greyfreedom) (`@greyfreedom`) documented and
5907 locked the authorization-order contract in PR #4980.
5908 - [Nightt](https://github.com/nightt5879) (`@nightt5879`) fixed foreground
5909 shell detachment before steering in PR #4979.
5910 - [Watcher24](https://github.com/Watcher24) (`@Watcher24`) provided the macOS
5911 File Provider report and reproduction for #4085.
5912 - [Fred Leitz](https://github.com/fleitz) (`@fleitz`) retains required
5913 source-candidate credit for the canonical `Bash` workspace fix from PR #4673
5914 and issue #4674.
5915
5916 ## [0.9.2] - 2026-07-29
5917
5918 This is the Codewhale v0.9.2 source candidate. It is not a published release
5919 until the matching tag, packages, checksums, and release assets exist.
5920
5921 ### Changed — behavior
5922
5923 - **Legacy `model = auto` no longer elects a network classifier on its own.**
5924 Holding a DeepSeek API key used to silently select `deepseek-v4-flash` as the
5925 classifier for every Auto turn — a per-turn cost on a route nobody asked for,
5926 and one provider privileged over the rest. Auto now stays local and free
5927 unless an explicit `[auto.router]` block names a provider and model.
5928
5929 **If you relied on the implicit default**, restore it explicitly:
5930
5931 ```toml
5932 [auto.router]
5933 provider = "deepseek"
5934 model = "deepseek-v4-flash"
5935 ```
5936
5937 `[auto.router]` remains legacy `model = auto` configuration. It is unrelated
5938 to a Fleet's Adaptive Reasoning Router, which is a saved service referenced by
5939 name from a Fleet file and decides only how hard an already-frozen route
5940 thinks.
5941
5942 Landed since v0.9.1, not yet released. A cluster of defects found by a
5943 read-through audit of the policy engine, the MCP proxy, the session index,
5944 and the app-server bridge — several of them cases where the wrong outcome
5945 was reached silently, behind a response or a log line that looked fine. The
5946 release also adds opt-in session, reasoning, localization, and inspectability
5947 surfaces; existing defaults remain stable unless an entry below explicitly
5948 says otherwise.
5949
5950 ### Added
5951
5952 - `/permissions` now lists the active user permission-rule source, each rule's
5953 effective matcher and global/repository scope, and whether that scope applies
5954 in the current workspace. `/permissions remove <number>` previews deletion
5955 and requires a snapshot-bound confirmation token, so a concurrent edit
5956 cannot move a different rule under the confirmed index. Appends and removals
5957 share one adjacent lock, preserve unrelated TOML formatting and comments,
5958 atomically replace `permissions.toml`, and reload the live user ruleset
5959 without clearing session-only approvals. `/config ask-rules` remains a
5960 compatibility entry; rule creation, glob/directory rules, and deny
5961 persistence remain out of scope (#1186, PR #4960 by @greyfreedom).
5962
5963 - `/preview-request` (aliases `/dryrun` and `/preview_request`) is a human-only,
5964 provider-free inspection of the next primary turn. Production dispatch and
5965 preview share one prepared-request seam across Chat Completions, Anthropic
5966 Messages, and OpenAI Responses, so the manifest reads the final wire model,
5967 reasoning controls, tool choice, tool schemas, and body hash from the same
5968 value production sends. Route, tool, or body facts that require Auto's
5969 provider classifier, an MCP connection, mutable hooks, compaction, or queued
5970 runtime injections remain typed unavailable. The manifest reports exact
5971 primary role/lane identity, upstream route-source provenance, requested and
5972 effective reasoning, canonical JSON sizes, conservative offline estimates,
5973 and provider-reported usage as unavailable because no request ran. It never
5974 adds a model-visible tool, sends a provider call, or prints prompt, message,
5975 credential, endpoint-path, or workspace-path content. The explicit
5976 `/preview-request base-prompt` mode prints only the exact effective base
5977 prompt; effective system text remains protected behind its final hash. The
5978 exact body includes the same authoritative transient Work/To-do tail used by
5979 production, including graph-backed state newer than the legacy projection.
5980 Preflight preserves production's separately framed base-plus-Work estimate,
5981 and fails closed when the authoritative projection is unavailable. An
5982 exhausted active goal token budget also produces a typed unavailable result
5983 before any outbound request is built.
5984 (#1004, #3928; dry-run concept harvested from PR #1099 by @GTC2080 / TaoMu.)
5985
5986 - Slash commands, hotbar actions, and CLI entrypoints for the same Lane/Fleet
5987 lifecycle operation now share one typed control-plane contract
5988 (`codewhale-lane::control`): a stable `<domain>.<verb>` id, read-vs-write
5989 authority, persistence scope, exact-identity target selection, retryability,
5990 lifecycle outcome, and one bounded, sanitized receipt. `docs/COMMAND_CONTROL_PLANE.md`
5991 documents it (#1888).
5992
5993 - `/lane [list|status|interrupt|restart|resume]` — durable Lane control from the
5994 composer, backed by the same executor `codewhale lane …` calls. `codewhale
5995 lane interrupt|restart|resume` are the matching CLI verbs; `lane stop` stays as
5996 a compatibility spelling of `lane interrupt`. Appending `@<lifecycle-seq>` to a
5997 lane id fences a write to the exact durable generation you observed, so a
5998 concurrent transition is rejected as a conflict rather than acted on (#1888).
5999
6000 - `codewhale fleet list` and `/fleet [list|status|interrupt|resume]` — durable
6001 Fleet run inspection and control from either surface, through shared DTOs that
6002 carry the exact provider, provider-table id, model, effective reasoning tier,
6003 and route source when the ledger records them, and a typed `not_recorded` /
6004 `not_applicable` / `redacted` reason when it does not. Requested-vs-effective
6005 reasoning is never back-filled: the ledger persists the effective tier only, so
6006 the requested tier reports `not_recorded` (#4022).
6007
6008 - The bundled skill pack now ships a `help` skill (catalog generation 7). It is
6009 `invocation: explicit-only`, so it never enters the model's ambient catalogue
6010 and costs no prompt budget. Its body is a routing card that points at the
6011 surfaces this build actually exposes — `/help` and `/help <command>`,
6012 `/skills` and `/skills inspect`, `/config`, `doctor`, and the `docs/` tree
6013 when the workspace is a Codewhale checkout — and explicitly forbids pasting a
6014 command list or settings table into context (#4698).
6015
6016 - `crates/tui/assets/skills-catalog-matrix.json`: an authored, provider-free
6017 expectation matrix covering every bundled skill (tier, invocation, aliases,
6018 ambient-catalogue eligibility, shadowed aliases). Contract tests in
6019 `crates/tui/src/skills/catalog_matrix.rs` assert a bijection between the
6020 fixture and the shipped bundle, so the starter pack cannot change without an
6021 explicit fixture update. The matrix covers positive eligibility and explicit
6022 load, non-activation negatives, alias resolution, explicit-only exclusion,
6023 alias-vs-canonical collision precedence, and prompt-budget invariants (no
6024 duplicate catalogue entries, no aliases as extra entries, and the shipped
6025 pack fitting inside the 12 000-char budget with no omitted-skills line). These
6026 are deterministic registry/catalog/resolver assertions and make no claim about
6027 semantic model routing (#4698).
6028
6029 - Locale-routing coverage for the complete bundled catalog across every shipped
6030 locale (`en`, `ja`, `zh-Hans`, `zh-Hant`, `pt-BR`, `es-419`, `vi`, `ko`). No
6031 bundled skill ships a localized routing description and none was invented;
6032 the tested contract is deterministic fallback to the canonical English
6033 description, with the rendered catalogue byte-identical across locales.
6034 Exact-tag match, primary-subtag fallback, and English fallback are covered
6035 against a synthetic authored fixture, and the parity test fails if a bundled
6036 skill ever gains localized metadata without source-backed coverage (#4698).
6037
6038 - `docs/LIVE_SMOKE.md`: copy-pasteable, opt-in live-smoke instructions for Kimi
6039 K3 and a second provider/model (DeepSeek). The runs are manual only — nothing
6040 in CI, tests, or skills invokes them. They use `env -i` plus a throwaway
6041 `CODEWHALE_HOME`; `HOME` is left unset rather than repurposed, and ambient
6042 provider variables are not forwarded. The operator names the credential
6043 variable explicitly, and the isolated child reads its value with echo off,
6044 restores the prior terminal state on exit or interruption, and never persists
6045 the value or puts it in a command argument. The page states the expected
6046 route/model/reasoning/tool receipt fields while treating provider errors as
6047 unclassified until provider configuration, authentication/entitlement, and
6048 harness behavior have been corroborated independently (#4698).
6049
6050 - Approval cards can now remember eligible safe shell and file-write approvals
6051 as exact `allow` rules scoped to the current repository. Remembered shell
6052 commands use complete-command matching, validated file and patch paths remain
6053 workspace-relative, and dangerous, critical, or repo-law-held requests stay
6054 ineligible and continue to require review.
6055
6056 - `tui.header_items` (array of strings, optional, default `[]`): an opt-in
6057 header chip showing cumulative session token usage as input / cache-hit /
6058 output. Set `header_items = ["tokens"]` under `[tui]` to enable it. The
6059 chip is the only elidable element of the header — the git label, context
6060 meter, and version stamp keep their space, and narrow terminals drop the
6061 chip rather than the baseline chrome. Unknown entries are warned about and
6062 skipped so configs written by newer builds stay loadable by older ones
6063 (#4520 requested by @eugenicum; PR #4610 by @XhesicaFrost, harvested with
6064 co-authorship).
6065
6066 - `thinking_default_expanded` lets reasoning blocks start open while keeping
6067 Space as the per-block toggle. The setting is persisted, available through
6068 native and runtime configuration, and documented for SSH/tmux accessibility
6069 (issue #4925 and PR #4928 by @M-Maciej).
6070
6071 - The transcript renders a conservative subset of LaTeX math as readable
6072 Unicode without rewriting fenced/inline code, ordinary currency, escaped
6073 dollars, or unknown commands. The contribution from PR #4973 by
6074 @SparkofSpike was hardened and landed through PR #4974; reported by
6075 @antarikshraya in #4957.
6076
6077 - Session control now includes a sessions rail, shared archive projection,
6078 picker archive controls, and opt-in interactive auto-resume with explicit
6079 handoff behavior. The work closes the remaining session-browsing direction
6080 from #2934; thanks @cy2311 for the original report.
6081
6082 - The bundled contributor-onboarding skill can sync contribution context,
6083 select the appropriate gate, and prepare a digest without inflating the
6084 ambient skill catalog. It follows the contributor-navigation request in
6085 #4227 by @JayBeest.
6086
6087 - Bahasa Indonesia now has a complete repository documentation suite and a
6088 registered website dictionary alongside the shipped TUI locale (PRs #4962
6089 and #4972 by @atmosuwiryo, closing #4789).
6090
6091 - Reasoning content can keep its rail, italics, cursor, and expansion controls
6092 while disabling only the warm background highlight. The independent setting
6093 is persisted and localized (#4089; reported by @elijahchan2019).
6094
6095 - StepFun setup now asks whether a key belongs to PAYG or Step Plan, keeps the
6096 two endpoint/billing routes distinct, and localizes the choice across the
6097 complete packs (#4526; reported by @whp233).
6098
6099 - OpenCode Zen is a separate model-aware API-key provider. Its curated catalog
6100 selects Responses, Anthropic Messages, or Chat Completions per model;
6101 unsupported Gemini and unknown models fail closed, and missing Zen
6102 credentials never fall through to ChatGPT/Codex OAuth guidance. The
6103 implementation from closed PR #4467 by @snail-vs (snailoniu) is preserved in
6104 the candidate.
6105
6106 - Markdown exports correlate prompts with stable workspace restore-point ids
6107 and say when correlation is unavailable or ambiguous, completing the
6108 remaining restoration/export direction from #2494 by @wywsoor.
6109
6110 ### Fixed
6111
6112 - Permission setup now consistently presents the product postures Ask,
6113 Auto-Review, and Full Access instead of leaking the internal `never` token.
6114 The same resolved sandbox policy now drives execution and UI receipts: Plan
6115 stays read-only, Ask and Auto-Review stay workspace-scoped, and Full Access
6116 is actually unsandboxed unless a stricter effective configuration wins.
6117
6118 - Fleet setup no longer stalls when a user explicitly selects a configured
6119 Codex or Grok external-consent route. The selected route is activated and
6120 validated before saving, roster roles open directly on their Model step,
6121 Review saves on the first Enter, and new profiles default to the personal
6122 profile directory that the roster loads on the next session.
6123
6124 - Provider credential dialogs now share one wrapping, secret-safe API-key
6125 surface across every non-OAuth provider. A key already present in durable
6126 storage is reported as configured without rendering it, typing or pasting is
6127 clearly framed as replacement, narrow help text remains visible, and Codex
6128 and Grok OAuth flows remain token-free in this modal.
6129
6130 - Ctrl+O again opens the complete recorded reasoning detail for the selected,
6131 active, or latest reasoning block. The whole-turn Turn Inspector moved to
6132 Ctrl+Alt+O and `/turn inspect`, removing the shortcut collision while keeping
6133 raw leaf detail and post-flush reasoning discoverable.
6134
6135 - Failed child agents now deliver a distinct high-priority failure receipt to
6136 their owning parent with a sanitized failure class, elapsed work, and a full
6137 transcript handle. Parent-to-child message, follow-up, and interrupt tools
6138 now use one hierarchy-checked mailbox path, and persisted nested completion
6139 envelopes remain safely restorable across instruction-text revisions.
6140
6141 - Background-shell completion events now carry only bounded tails plus a
6142 retrievable exact-evidence handle. Terminal foreground Bash results are
6143 acknowledged at the direct tool-result boundary and are no longer emitted a
6144 second time as background completion artifacts.
6145
6146 - Providerless Fleet and child-agent fixed-model routes now reject only
6147 high-confidence foreign-provider model ids before creating a worktree, while
6148 explicit provider/model pairs, custom and local endpoints, unknown ids, and
6149 aggregator wire-id resolution retain their intended behavior.
6150
6151 - Manual compaction now preserves and reports the supplied provider failure
6152 class instead of replacing it with an opaque generic error. This does not
6153 infer quota exhaustion when the recorded failure does not prove it.
6154
6155 - The ambient jellyfish keep complete, readable silhouettes while animating,
6156 and the website favicon now uses the Signal Current desktop tile instead of
6157 the legacy whale mark.
6158
6159 - ACP JSON-RPC responses preserve numeric request ids for avante.nvim while
6160 retaining the negotiated string-id exception for Zed (PR #4929 by
6161 @atmosuwiryo).
6162
6163 - Restored shell cells whose job no longer exists stop displaying live
6164 spinners and settle into a truthful stale/no-output state across transcript,
6165 phase strip, and sidebar (PR #4937 by @LI-Jialu, closing #4547).
6166
6167 - Interrupted checkpoints and timed recovery snapshots remain checkpoints
6168 instead of being promoted into orphan session files, preventing duplicate
6169 `/resume` entries (PR #4963 by @SparkofSpike).
6170
6171 - Every shipped locale is admitted by the typed settings schema and native
6172 chooser, with complete/partial status kept independent and tested (PR #4856
6173 by @nightt5879, closing #4786). Context-menu hover hit-testing also accounts
6174 for its title row (PR #4897 by @XhesicaFrost; reported by @SparkofSpike in
6175 #4803).
6176
6177 - OSC 52 and SSH/tmux clipboard transport run on one bounded background worker
6178 rather than blocking input and rendering on the TUI loop; late transport
6179 failures still surface through the status path (PR #4896 by @nightt5879,
6180 closing #4159).
6181
6182 - Non-streaming model calls receive a generation-length response budget rather
6183 than the SSE header-open timeout, while actual SSE opens share the bounded
6184 cross-provider transport seam. The equivalent fix direction came from
6185 closed PR #4743 by @vibecoding-skills.
6186
6187 - Resumed sessions diagnose a deleted inherited workspace before shell launch
6188 instead of failing as an opaque Windows process error (report #4100 by
6189 @redjade75723). DeepSeek native tool-call wrapper tokens are also scrubbed
6190 from visible streaming and completed output as a grounded fail-soft follow-up
6191 to report #3880 by @hardy922; that report's exact emitted marker remained
6192 unconfirmed.
6193
6194 - Auto model routing now preserves the user's requested reasoning effort
6195 through startup, provider/model changes, session restore, the picker,
6196 Ctrl+T, and Hotbar actions. The tier is normalized only after the concrete
6197 provider route is known instead of being silently replaced by Auto
6198 (#4941, PR #4961 by @nightt5879).
6199
6200 - Auto-compaction now defaults on for every known model context window,
6201 including Kimi K3's 1,048,576-token routes. Persisting only an
6202 `auto_compact_threshold` or `auto_compact_threshold_percent` now counts as
6203 opt-in intent, while an explicit `auto_compact = false` remains authoritative.
6204 `/config` reports the effective state, percentage, and computed token trigger.
6205
6206 - Per-provider `context_window` overrides are now documented and visible in
6207 `/config`, provider setup help, diagnostics, and the example configuration.
6208 The effective override consistently drives preflight budgeting, the context
6209 meter, and compaction; this lets a user cap a 1M Kimi route to 256K when their
6210 Coding Plan tier has the smaller window.
6211
6212 - Agent Details now projects status, model, elapsed time, and step counts from
6213 the same row snapshot as the primary agents list, eliminating contradictory
6214 worker state between the two surfaces.
6215
6216 - Composer submission and its hints now share one state machine. Portable
6217 terminals use Enter to queue during a running turn and Enter again to steer;
6218 Ctrl/Cmd+Enter is accepted only when an enhanced terminal reports it and is
6219 no longer advertised as universally available.
6220
6221 - `edit_file` now matches LF-only model search text against CRLF files,
6222 preserves the file's line-ending style for replacement text, and still
6223 rejects newline-normalized duplicate matches as non-unique (#4764).
6224 Implemented in PR #4942 by @nightt5879; reported and root-caused by
6225 @LmeSzinc.
6226
6227 - `/fleet status` read the current TUI session's sub-agents while `codewhale
6228 fleet status` read the durable `.codewhale/fleet.jsonl` ledger — two different
6229 things wearing one name, so a run started by `codewhale fleet run` never
6230 appeared in the TUI. `/fleet status` now reads the durable ledger through the
6231 same code path as the CLI; the session view keeps its own name as
6232 `/fleet workers` (`/subagents` and `n` still work). When a workspace has no
6233 ledger, both surfaces report a typed `no_fleet_ledger` reason instead of an
6234 empty-looking "all clear", and neither creates the ledger as a side effect of
6235 reading it (#4022).
6236
6237 - `codewhale fleet status` (and `list`/`interrupt`/`resume`) created
6238 `.codewhale/fleet.jsonl` as a side effect of opening the manager, then
6239 reported `no_fleet_ledger` for the file it had just made — so the second
6240 invocation showed an empty Fleet where none existed. The CLI now refuses
6241 those verbs before the manager is constructed, matching `/fleet` (#4022).
6242
6243 - `fleet resume <run-id>` accepted any string. An id absent from the ledger
6244 reconciled nothing but still wrote a run-status record keyed by whatever was
6245 typed, and reported `no_change`. Unknown ids are now refused as `not_found`
6246 before any durable write (#4022).
6247
6248 - `lane interrupt` reported `transitioned` even when it changed nothing —
6249 another process's stop looked like our own. The Runtime backend now reports
6250 whether *this* call performed the transition, and a no-op is `no_change`.
6251 The `@<lifecycle-seq>` fence is also evaluated inside the registry's per-Lane
6252 lock rather than before it, so a stale fence refuses without running Runtime
6253 teardown instead of racing between the check and the stop (#1888).
6254
6255 - `/lane` no longer runs Runtime teardown on the TUI composer thread. Reads on
6256 the slash surface skip reconciliation (which probes tmux and takes a lock)
6257 and say so on the receipt instead of implying freshness; `lane interrupt` is
6258 CLI-only until that work runs off-thread, and reports
6259 `surface_not_supported` naming `codewhale lane interrupt` (#4022).
6260
6261 - The hotbar is no longer modelled as a third control surface. A slot binds a
6262 slash command and fires it with no argument, so it runs *as* the slash
6263 surface; the contract now declares which verb a bare press actually reaches
6264 (`hotbar_bare_dispatch`, true only for `lane.list`) instead of advertising
6265 target-taking verbs as hotbar-reachable (#1888).
6266
6267 - `codewhale lane list --json` and `lane status --json` keep emitting the
6268 `LaneRecord` shape they always have — the receipt did not replace it. The
6269 human `lane status` output also regained `branch`, `session`, `socket`,
6270 `attach`, and `log`, which the first cut of the shared DTO had dropped
6271 (#1888).
6272
6273 - No surface advertises a backend it does not have. `lane restart` and
6274 `lane resume` have no implementation — a Lane is re-created by
6275 `codewhale lane start`, and a stopped Lane's Runtime session is gone — so all
6276 three surfaces refuse them with `backend_not_implemented` and say why.
6277 `fleet restart` drives the manager loop to completion, which only the CLI
6278 runs, so `/fleet restart` reports `surface_not_supported` and names the CLI
6279 command rather than quietly doing a smaller thing (#1888).
6280
6281 - Deny rules in `permissions.toml` no longer miss a command because of an
6282 intervening flag: deny matching is token-based with flag-skipping and
6283 backtracking, so a `git push` rule still catches
6284 `git -c foo=bar push`. Path matching folds case only on platforms whose
6285 filesystems are case-insensitive, and the default approval branch no
6286 longer proposes the working directory as a network host.
6287
6288 - MCP tool calls run once. A failed call is no longer retried as if it
6289 were a failed lookup, qualified-name resolution collects every match and
6290 reports an ambiguity instead of taking whichever the hash map yielded
6291 first, and registering a server whose name collides with an existing one
6292 after sanitization is now an error rather than a silent overwrite.
6293 The equivalent call-once fix direction came from closed PR #4756 by
6294 @adity982.
6295
6296 - The session index survives a torn line: an unparseable entry is skipped
6297 rather than aborting the whole read, appends carry their data through to
6298 disk, and appends and compaction share a lock so a compaction can no
6299 longer race an append into a lost record.
6300
6301 - `Edit` counts as a write tool for workflow elevation, and the TUI's
6302 write/shell classification now delegates to one shared allowlist rather
6303 than keeping a second copy that could drift.
6304
6305 - A rejected `app/config/set` stays a no-op. Previously an invalid value
6306 still tore down the cached runtime bridge, killing the child runtime and
6307 orphaning every other in-flight stdio thread behind a response that
6308 correctly reported failure.
6309
6310 - A malformed project `config.toml` is no longer indistinguishable from
6311 having no project config. Because a project config may only *tighten*
6312 approval and sandbox policy, silently discarding a broken one dropped a
6313 repository's restrictions back to the looser user defaults; the setup
6314 wizard now says so, naming the file but never quoting its contents.
6315
6316 - An expired lane worktree no longer leaves its branch behind, which made
6317 reusing the same lane name fail with "branch already exists". A branch
6318 still carrying unmerged commits is kept — a TTL lapsing is not consent
6319 to delete someone's work.
6320
6321 - An in-flight `thread/message` turn can be stopped. The stdio loop keeps
6322 reading while a turn streams, so the new `thread/interrupt` request (and
6323 `shutdown`) can reach a runaway turn instead of waiting on the very turn
6324 they were meant to stop.
6325
6326 - Precedence is stated only in the constitution's "Whose word wins" section.
6327 Memory hygiene no longer ships an inverted Tier list that put the
6328 constitution above the user's current request; approval, compaction, and
6329 personality overlays describe behavior without rank vocabulary; and the
6330 authority recap points at the single source rather than restating a second
6331 ladder.
6332
6333 - `<turn_meta>` carries facts (mode, posture, model, workspace), not mode
6334 doctrine or permission-question essays re-asserted every user message.
6335
6336 - The project context pack (pretty-printed workspace tree) is off by default
6337 and opt-in via `[context] project_pack = true`. Language law is compressed
6338 while keeping the English-constitution / user-language-reply contract.
6339
6340 - Modal lists and config pickers wrap selection at both ends (Down past the
6341 last row returns to the top). Home-directory resolution prefers
6342 `HOME`/`USERPROFILE` via `effective_home_dir` across remaining call sites so
6343 Windows tests that fake the home env vars match production paths. The
6344 equivalent home-directory sweep came from closed PR #4760 by
6345 @EvanProgramming.
6346
6347 ### Changed
6348
6349 - Prefix-cache tool catalog entries store only the SHA-256 digest, not the
6350 joined catalog string. Unused plan-transition validation helpers are removed.
6351
6352 - Settings sections now hold only what they claim (#4751). Fleet keeps
6353 Fleet/member concerns; `/goal` moved to a **Session** section and Workflow
6354 orchestration to its own **Workflow** section. The inert DeepSeek-only
6355 `default_model` fallback moved out of Model settings into an explicit
6356 **Legacy** section — exact-Fleet users switch Fleets, not fallback models;
6357 the config field is retained because the runtime still reads it. This is
6358 presentation only: the persisted keys (`goal_command`, `workflow`,
6359 `default_model`), their values, scopes, and runtime behavior are unchanged.
6360
6361 - Auto model routing is scoped to the active provider. The classifier
6362 inventory no longer discloses other providers' runnable routes (or the fact
6363 that their credentials exist), a classifier reply naming another provider is
6364 refused, the local heuristic no longer falls back to a different provider
6365 when the active one is unusable, and the implicit DeepSeek-flash classifier
6366 is skipped for non-DeepSeek sessions. Auto receipts and the model picker
6367 hint report the active-provider-only scope instead of "runnable providers".
6368 Cross-provider Auto is available only through the persisted `[auto]
6369 cross_provider = true` opt-in (an explicit `[auto.router]` route remains its
6370 own opt-in for the classifier call). Same-provider strong/fast selection and
6371 `[auto] cost_saving` are unchanged.
6372
6373 - The QA pseudo-terminal acceptance harness now parses frames with `rio-vt`
6374 behind its existing neutral frame/color surface, retaining the assertions
6375 while removing the `vt100` dependency (PR #4931 by @raphamorim).
6376
6377 - Anthropic Messages and OpenAI Responses stream opening now share the
6378 `client/stream_entry.rs` seam already used by Chat Completions: one bounded
6379 response-header wait, shared dual/HTTP-1.1 policy selection, at most one
6380 HTTP/1.1 fallback on a classified HTTP/2 header stall, and common idle-timeout
6381 diagnostics. Wire-specific authentication, headers, endpoints, decoding, and
6382 rate-limit behavior remain at each adapter edge. The timeout-placement
6383 diagnosis and fix direction came from closed PR #4743 by
6384 @vibecoding-skills.
6385
6386 ### Security
6387
6388 - Release containers now publish an SBOM attestation and pin maximum-mode
6389 provenance explicitly so supply-chain metadata cannot silently weaken with a
6390 builder-default change (PR #4958 by @kobihikri).
6391
6392 ### Contributors
6393
6394 Thank you to the contributors whose code, reports, and reviews shaped v0.9.2:
6395
6396 - [@greyfreedom](https://github.com/greyfreedom) — exact repository-scoped
6397 allow grants and cross-platform path semantics (PR #4761), plus safe
6398 permission-rule listing and snapshot-bound removal (PR #4960).
6399 - [@nightt5879](https://github.com/nightt5879) — off-event-loop clipboard
6400 writes (PR #4896), complete locale exposure in settings (PR #4856), CRLF-safe
6401 edits (PR #4942), and reasoning-effort preservation across automatic model
6402 routing (PR #4961).
6403 - [@XhesicaFrost](https://github.com/XhesicaFrost) — the configurable
6404 session-token header (PR #4610) and context-menu hover alignment (PR #4897).
6405 - [@cyq1017](https://github.com/cyq1017) — the hooks configuration/executor
6406 split from PR #4087.
6407 - [@snail-vs](https://github.com/snail-vs) (snailoniu) — OpenCode Zen's
6408 model-aware routes, authentication, documentation, and test isolation from
6409 closed PR #4467, whose contributor commits are preserved in the candidate.
6410 - [@SparkofSpike](https://github.com/SparkofSpike) — the zh-Hans translation
6411 quality review harvested from PR #4908, duplicate-session fix in PR #4963,
6412 LaTeX implementation from PR #4973 landed through #4974, and the context-menu
6413 reproduction in #4803.
6414 - [@GTC2080](https://github.com/GTC2080) — the request-preview concept from
6415 PR #1099.
6416 - [@h3c-hexin](https://github.com/h3c-hexin) — non-UTF-8 `fetch_url`
6417 decoding direction from PR #4909.
6418 - [@fleitz](https://github.com/fleitz) — required source-candidate credit for
6419 the canonical `Bash` no-`cwd` workspace fix and regression in PR #4673
6420 (issue #4674).
6421 - [@LmeSzinc](https://github.com/LmeSzinc) — the Windows CRLF `edit_file`
6422 reproduction, root-cause analysis, and affected-code anchors in issue #4764.
6423 - [@atmosuwiryo](https://github.com/atmosuwiryo) — ACP numeric-id compatibility
6424 (PR #4929) and the Indonesian documentation and website locale (PRs #4962
6425 and #4972).
6426 - [@M-Maciej](https://github.com/M-Maciej) — the expanded-by-default reasoning
6427 setting and its original report (PR #4928, issue #4925).
6428 - [@raphamorim](https://github.com/raphamorim) — migration of the QA PTY frame
6429 parser to `rio-vt` (PR #4931).
6430 - [@LI-Jialu](https://github.com/LI-Jialu) — truthful finalization of restored
6431 stale shell cells (PR #4937).
6432 - [@kobihikri](https://github.com/kobihikri) — release-container SBOM and
6433 explicit provenance mode (PR #4958).
6434 - [@EvanProgramming](https://github.com/EvanProgramming),
6435 [@adity982](https://github.com/adity982), and
6436 [@vibecoding-skills](https://github.com/vibecoding-skills) — equivalent fix
6437 direction for the effective-home sweep (#4760), MCP call-once behavior
6438 (#4756), and streaming/non-streaming timeout split (#4743).
6439 - [@antarikshraya](https://github.com/antarikshraya) — the LaTeX transcript
6440 rendering report in #4957.
6441 - [@eugenicum](https://github.com/eugenicum) — the token-header request and
6442 output-presentation measurements in #4520 and #4468.
6443 - [@whp233](https://github.com/whp233) — the StepFun/OpenCode subscription-route
6444 request in #4526.
6445 - [@redjade75723](https://github.com/redjade75723),
6446 [@hardy922](https://github.com/hardy922),
6447 [@JayBeest](https://github.com/JayBeest),
6448 [@elijahchan2019](https://github.com/elijahchan2019),
6449 [@cy2311](https://github.com/cy2311), and
6450 [@wywsoor](https://github.com/wywsoor) — reports and product direction behind
6451 the stale-workspace diagnosis (#4100), native-tool-token filtering (#3880),
6452 contributor onboarding (#4227), optional reasoning highlight (#4089),
6453 session control (#2934), and export/restore correlation (#2494).
6454
6455 ## [0.9.1] - 2026-07-24
6456
6457 ### Dogfood follow-ups (2026-07-24)
6458
6459 ### Added
6460
6461 - `/compact [focus]`: the manual compaction command now accepts an
6462 optional focus argument that is injected into the summary prompt, and
6463 the compaction summary itself becomes a structured nine-section
6464 successor briefing (primary intent, key concepts, files and code,
6465 errors and fixes, problem solving, user messages, pending tasks,
6466 current work, next step) that carries earlier compaction summaries
6467 forward and explicitly forbids tool use — replacing the free-form
6468 "under N words" instruction. Codewhale's pin/working-set and
6469 V4 prefix-cache-aligned machinery are unchanged.
6470
6471 - Saved workflows become slash commands: `*.workflow.js` files under
6472 `<workspace>/.codewhale/workflows/` and `~/.codewhale/workflows/` are
6473 discovered as `/name` commands that accept custom arguments (forwarded
6474 to the run's `args`), launch through the `workflow` tool in the
6475 background, and report their run id. Hand-written `.md` commands with
6476 the same name always win. The workflow tool's `source_path` now also
6477 accepts the user-global `~/.codewhale/workflows/` store, and every
6478 settled run leaves a durable synthesized report under
6479 `.codewhale/reports/<run_id>.md` (status, goal, gates, progress,
6480 result, verification).
6481
6482 ### Fixed
6483
6484 - Disambiguate the two Kimi K3 model-picker rows, which read as an
6485 unexplained duplicate: bare `k3` is now labeled "Kimi Code plan route"
6486 with its default 262K window annotated as the plan-tier floor (raisable
6487 via the provider `context_window` setting for plans that include 1M),
6488 and `kimi-k3` is labeled "Moonshot direct route" with its 1M window.
6489 Both remain distinct, valid routes for the same underlying model.
6490 - Close the model-facing `agent` tool role schema: the `type` property now
6491 publishes the canonical JSON Schema enum `["worker", "scout", "planner",
6492 "reviewer", "builder", "verifier", "custom"]` instead of describing the
6493 accepted values in prose. Legacy aliases are no longer advertised to
6494 models; they remain accepted only at replay/deserialization boundaries.
6495 Provider schema sanitizers (Chat Completions, strict mode, Anthropic
6496 Messages / OpenAI Responses, Moonshot/Kimi) are pinned by test to
6497 preserve the closed enum.
6498
6499 ### Changed
6500
6501 - Rework the ambient idle ocean: the water now holds exactly one loose
6502 wedge school of fish, jellyfish, bubbles, and the rare whale cameo —
6503 seaweed and bio-dust are removed. Fish swim on a wrap-around path and
6504 always face the way they move (direction can only change while the
6505 school is off-screen); the lead fish carries an eye (`><o>`).
6506 Jellyfish become a pulsing bell with a lagging swaying tentacle. All
6507 ambient marks now glow via background→ink color lerp: a travelling
6508 sin² wave through the school, a floor-bounded pulse for jellyfish,
6509 and occasional raised-cosine glints on bubbles, with deliberately
6510 non-matching periods so nothing strobes in sync.
6511
6512 - Rename the internal delegated-worker role type from `SubAgentType` to
6513 `FleetRole` with canonical variants (`Worker`, `Scout`, `Planner`,
6514 `Reviewer`, `Builder`, `Verifier`, `Custom`) matching the public Fleet
6515 vocabulary one-to-one. Wire behavior is unchanged: serialization emits
6516 canonical Fleet values only, and persisted `agent_type` fields plus
6517 documented legacy spellings (`general`, `explore`, `plan`, `review`,
6518 `implementer`, …) continue to load at deserialization/parse boundaries;
6519 unknown role tokens still fail closed with the canonical vocabulary in
6520 the error.
6521
6522
6523 The Codewhale v0.9.1 source candidate includes a first-class local web client over the Runtime API,
6524 first-class OpenCode Go and TelecomJS TokenHub providers and restored xAI device login,
6525 calendar-correct hourly automations, a buildable OpenHarmony workflow-js
6526 target, and hardening for Auto routing, remote-terminal clipboard transport,
6527 restart recovery, and a coherent TUI, Work, evidence, and public release
6528 surface.
6529
6530 ### Added
6531
6532 - Add `codewhale web [--port 7878]`, a first-class loopback-only browser
6533 client over the canonical Runtime API. The dependency-free embedded shell
6534 supports thread lifecycle, snapshot-then-SSE transcripts, turn start/steer/
6535 interrupt, approvals, and user questions, including pending-request recovery
6536 across tab reloads, while leaving unsupported managed,
6537 files, PTY, model-selection, and Fleet controls absent. Browser auth uses a
6538 short-lived one-time loopback capability exchanged for an opaque, bounded,
6539 process-local HttpOnly, SameSite=Strict session cookie with a same-origin
6540 mutation guard; Runtime tokens never enter URLs, HTML, browser storage, logs,
6541 or browser-launch arguments (#4423).
6542 - Add OpenCode Go as a first-class, subscription-backed Chat Completions
6543 provider with `[providers.opencode_go]`, `OPENCODE_GO_API_KEY`, and the eight
6544 models currently documented on its `/v1/chat/completions` endpoint. Models
6545 served only through OpenCode Go's Anthropic `/messages` endpoint remain out
6546 of this narrow route until Codewhale supports per-model wire selection
6547 (#1481 by @seanthefuturegorilla; implementation harvested from PR #773 by
6548 @zhangweiii and PR #1050 by @sternelee).
6549 - Add TelecomJS TokenHub as a first-class Chat Completions provider with
6550 `[providers.telecomjs]`, `TELECOMJS_API_KEY`, and a key-scoped live
6551 `/v1/models` refresh. Models.dev and provider-specific catalogs remain in
6552 separate source partitions so either refresh order preserves both; refreshes
6553 do not delete the other source's rows, matching model ids from unrelated
6554 providers do not fabricate metadata, and chat requests omit unsupported
6555 reasoning fields (PR #4370 by @baendlorel; harvested with co-authorship).
6556 - Prepare native Windows ARM64 `codewhale`, `codew`, and `codewhale-tui`
6557 binaries, npm selection, updater support, and standard/portable release
6558 archives. Build and smoke them on GitHub's native Windows 11 ARM runner,
6559 and move Linux ARM64 release builds to the native Ubuntu ARM runner to
6560 remove the slower multi-arch cross-link setup (#4267 by @w1w218).
6561 - `load_skill` tool now supports listing: omit `name` or pass `"list"` to
6562 see all available skills without loading one (#4651).
6563 - Add a unified `/skills` manager with one precedence-aware root catalog,
6564 bounded duplicate/shadow/conflict auditing, package provenance, and
6565 validated install, update, remove, and trust mutations (PR #4679 by
6566 @SamhandsomeLee).
6567 - Add a safe Agent Details view and bounded, structured `current_activity` to
6568 the single Work projection, sourced from worker events instead of renderer
6569 string inference. Rows stay compact, exact evidence is opt-in, and raw child
6570 output never enters the parent transcript (#2889 and #4636; design direction
6571 by @aboimpinto, preserved from #2694).
6572 - Make exact results and delegated coordination durable: non-inline tool output
6573 becomes immutable session-owned evidence behind bounded receipts; File
6574 mutations add configurable success-only diffs; and decisions and write
6575 contention survive restart with typed neutral-fan-in records (#4619, #4636,
6576 #4647).
6577 - Runtime API provider registry and atomic provider-switch endpoints
6578 (`GET /v1/providers`, `GET /v1/providers/{id}/models`,
6579 `POST /v1/providers/{id}/switch`) so the web GUI renders a dynamic
6580 provider/model picker without the setConfig+reload clobber (#4658).
6581 - Typed filter (`/`) in the Fleet setup wizard's Model step: substring
6582 match over provider id, display label, and model id keeps
6583 OpenRouter-scale catalogs navigable (#4639).
6584 - `[auto.router]` config: explicit provider/model/thinking for the Auto
6585 mode classifier route; unset keeps the DeepSeek flash default, and
6586 missing credentials fall back to the local heuristic.
6587
6588 ### Changed
6589
6590 - Keep the top activity bar literal and actionable: active To-dos appear first,
6591 followed by Sub-agents, while generic operations and coordination stay in
6592 the detail surface. Completed-only bars auto-hide, and top/side layouts can
6593 be resized by dragging their divider and retain the chosen size (#4700,
6594 #4702).
6595 - Use each theme's semantic colors for composer mode and permission rails, and
6596 show a larger inline reasoning preview with clearer local/full expansion
6597 affordances (#4699, #4701).
6598 - Simplify the model-facing runtime around stable action tools (`File`, `Git`,
6599 `Run`, deferred `Web`, and durable task and automation families), with legacy
6600 spellings hidden for replay. Fresh sessions no longer reserve a Work surface
6601 before real work exists (PR #4675).
6602 - Give the terminal shell one deliberate visual language: cool Plan → Act →
6603 Operate and warm Ask → Auto-Review → Full Access ramps match between header
6604 and split composer edges; transcript rhythm groups related activity; a
6605 refined whale keeps the empty state calm; and one-cell live motion with
6606 truthful labels distinguishes reasoning, reading, tool use, and verification
6607 without exposing private reasoning text. Reduced-motion and animation-off
6608 settings freeze it, while ASCII-safe terminals retain the signal (#4676,
6609 #4677).
6610 - Unified shell tool: the model now sees a single `Bash` tool with an `action`
6611 parameter (run/wait/interact/cancel). Legacy `exec_shell*` names remain as
6612 hidden compat aliases for transcript replay, and the tool-search catalog
6613 keeps `Bash` active by default (#4625).
6614 - Tool output inline preview increased from 6 to 12 lines (4 head + 4 tail)
6615 before the fold indicator; full pager (`v` key) unchanged (#4603).
6616 - Mode changes (`/mode agent|plan|operate`) now persist to `settings.toml`
6617 and restore across sessions (#4628).
6618 - Billing provenance: every outgoing API request carries an
6619 `x-codewhale-provenance` header with client version and provider (#4324).
6620 - The `/model` picker's typed search now ranks results: provider-name
6621 matches first (drill-down), then exact id, then id-prefix, then the
6622 active provider's rows (#4639).
6623 - System prompt text consolidated into a single `prompts/text.rs`
6624 module (byte-exact constants replacing 17 layered files);
6625 composition order, constitution-first binding, and locale/personality
6626 variants unchanged.
6627 - Ask, Auto-Review, Full Access, and Never resolve through one permission
6628 contract: `resolve_tool_permission` in the engine and
6629 `resolve_approval_request_disposition` in the UI share one truth table for
6630 session grants/denials, non-bypassable policy holds, and modal prompts
6631 (#4412).
6632 - Collapsed multi-struct tool families into single action-dispatched tools
6633 (`AutomationTool`, `TasksTool`, `GithubTool`, `RlmTool`) while keeping
6634 legacy tool names as hidden compatibility aliases for transcript replay.
6635 - Operate-mode children default to leaf depth (`max_depth=0`) unless the
6636 caller explicitly grants a deeper budget (#4598).
6637
6638 ### Fixed
6639
6640 - Restore `uwu` theme config round-tripping and keep header permission colors
6641 and authored idle-whale geometry aligned with the selected theme (#4696).
6642 - Default canonical `Bash` runs with no explicit `cwd` to the active
6643 `ToolContext.workspace`, including an isolated sub-agent worktree, instead of
6644 falling through to the shared shell manager's parent workspace. The regression
6645 test detects the selected workspace through marker files so it remains
6646 meaningful across PowerShell path spellings (#4674, PR #4673 by @fleitz).
6647 - Generate QuickJS bindings for `aarch64-unknown-linux-ohos` with the native
6648 SDK's libclang and sysroot, carry the OHOS target and sysroot through final
6649 linking, and keep unsupported persistent PTY dependencies out of the target
6650 while retaining non-PTY `exec_shell` support (#4470 by @shenjackyuanjie;
6651 original bindgen approach in #4384 by @shenyongqing).
6652 - Honor `[auto] cost_saving = true` in provider-aware heuristic and classifier
6653 routing, using only validated same-provider fast siblings and deriving
6654 fallback candidates from their actual provider so Auto cannot invent a
6655 cross-provider model. Providers without a known fast sibling stay on the
6656 active model (#4486; partial #4405).
6657 - Make terminal-client clipboard behavior truthful over SSH: use OSC 52
6658 outside tmux, stock `tmux load-buffer -w` inside tmux, and bracketed paste
6659 for client-to-remote text. Graphical text and image access now requires
6660 credible forwarding or an explicit override, transport failures no longer
6661 claim success, and help distinguishes terminal text paste from graphical
6662 image attachment (#4484).
6663 - Keep a fresh TUI Work surface from rendering prior-session worker snapshots
6664 or durable-task terminal receipts whose creation or completion predates the
6665 current app start. Active durable tasks remain visible, and shared history
6666 stays available through `/tasks` and archived agent views (#4488; partial
6667 #4416).
6668 - Make doctor and setup output distinguish static configuration, command
6669 availability, MCP protocol readiness, and backend health instead of
6670 presenting configured routes as live-healthy. Ordinary doctor runs no
6671 longer wake loopback/self-hosted providers unless `--probe-local` is
6672 explicitly requested (#4485; partial #4406).
6673 - Serialize test-only configuration-path readers with temporary environment
6674 redirects so the Windows provider-persistence matrix cannot observe another
6675 test's transient `CODEWHALE_HOME` or config path (#4483, closing #4463).
6676 - Restore direct Moonshot `kimi-k3` to its documented 1,048,576-token
6677 context window and 131,072-token output limit instead of treating the live
6678 model as an unknown legacy 128K route. The existing Kimi Code tiered `k3`
6679 route and credential reuse remain unchanged (#4481).
6680 - Keep read-before-edit snapshots in the engine session so a file read remains
6681 valid across turns and context compaction, while a new session still starts
6682 with an empty tracker (#4475 by @Angel-Hair).
6683 - Make `apply_patch` expose the canonical `replace` operation while continuing
6684 to accept deprecated `changes` payloads through one validation path. Mixed
6685 patch, replace, and compatibility modes now fail before any write (#4476 by
6686 @Angel-Hair).
6687 - Show the prompt-cache hit rate in the phase strip when the Cache status item
6688 is enabled, using overflow-safe rounded integer math and leaving compact or
6689 disabled status layouts unchanged (#4474 by @dmitri-0).
6690 - Preserve Solarized Light's canonical Base3 (`#fdf6e3`) shell background
6691 instead of tinting it green-grey through the default underwater Ombre
6692 treatment, while retaining foreground ambient life (#4457 by
6693 @AiurArtanis; PR #4471 by @nightt5879).
6694 - Register `/slop` and `/canzha` as compatibility aliases of `/debt`, while
6695 keeping user-command ownership truthful across dispatch, help, slash
6696 completion, alias copy, and typo suggestions (PR #4680 by @nightt5879).
6697 - Fail closed on legacy Kimi CLI credential imports: remove Codewhale's
6698 hard-coded first-party-client impersonation and refresh request, never
6699 auto-enable or rewrite imported credentials, and label the compatibility
6700 route as a read-only imported token. An explicitly configured, still-valid
6701 access token remains usable until expiry; missing, malformed, and expired
6702 imports recover through the supported Kimi Code API-key route while
6703 first-class OAuth awaits Codewhale's own vendor registration (#4417,
6704 partially addressed).
6705 - Restore xAI/Grok device-code OAuth login against the live xAI OIDC
6706 contract: discovery with issuer/endpoint validation and documented
6707 fallbacks, user-principal scope set, RFC 8628 `slow_down` backoff capped at
6708 code expiry, bounded, sanitized error reporting for denial, expiry, and
6709 malformed responses, and a shared blocking-worker boundary for both CLI and
6710 TUI login so reqwest's blocking client never creates or drops its private
6711 runtime inside Codewhale's Tokio runtime (#4410).
6712 - Anchor `FREQ=HOURLY` automations with `BYHOUR`/`BYMINUTE` to persisted
6713 local-calendar slots so intervals keep their wall-clock phase across DST,
6714 restart, resume, RRULE updates, duplicate-slot recovery, and post-run
6715 advancement. Nonexistent clock slots are skipped and ambiguous slots run at
6716 their first occurrence (#4381 by @h3c-hexin).
6717 - Give content-watch drafts canonical identities: the link and semantic-drift
6718 watchers now write and dedup through one canonical draft-storage key with
6719 deterministic hash-suffixed IDs, validate and bound model drift output
6720 before any KV writes, and show truthful admin draft labels, so unchanged
6721 findings dedup and changed findings re-draft instead of colliding (#4453).
6722 - Make model-policy JSON repair consider object and array payloads in source
6723 order, matching nested delimiters across quoted strings and escapes and
6724 returning the earliest balanced candidate that parses, instead of letting
6725 an unmatched opening delimiter or object-first preference corrupt array
6726 payloads (#4430).
6727 - Convert persisted sub-agent completion and still-running control events into
6728 concise, non-authoritative resume checkpoints, keeping their raw runtime
6729 envelopes, sentinels, and retry instructions out of restored model and TUI
6730 conversation state (#4409).
6731 - Deliver failed, stopped, and stale sub-agent outcomes exactly once to the
6732 awaiting parent, lifecycle mailbox, and TUI before closing their runtime
6733 state. Restart now reconciles orphaned queued/model/tool-wait worker records
6734 to interrupted while preserving checkpoints, and cancelled workers no
6735 longer read as completed in the TUI (#4408).
6736 - Give host applications a cancellation boundary for MCP OAuth login so a
6737 stalled or abandoned provider login no longer hangs the calling session
6738 (#4380).
6739 - Avoid blocked reader joins after Windows process kills so terminated shell
6740 sessions cannot hang their readers (#4383).
6741 - Give stdin-less observer hooks immediate EOF and contain timed-out hook
6742 process trees so descendants and pipe readers cannot leak after the parent
6743 shell exits (#4489 by @luismateusvargas).
6744 - Preserve the full unsigned Windows PTY process status instead of collapsing
6745 every high-bit exception or NTSTATUS to `2147483647`, including decimal and
6746 hexadecimal diagnostic metadata for device retests (#4100 by
6747 @redjade75723).
6748 - Keep the Hotbar Setup action list synchronized with keyboard focus when the
6749 selection moves beyond the visible rows, including Down past `/export`
6750 (#4418).
6751 - Route Windows OpenHarmony Cargo links through the repository's target-aware
6752 clang launcher so the final Rust link keeps its target, sysroot, and MUSL
6753 flags, and extend the no-SDK release guard to protect that contract. This
6754 completes [@shenjackyuanjie](https://github.com/shenjackyuanjie)'s PR #4470
6755 setup alongside [@shenyongqing](https://github.com/shenyongqing)'s original
6756 bindgen approach in PR #4384.
6757 - Reconcile the website roadmap with reality: the retired share-link
6758 direction is now an explicit non-goal, Workrooms is the considered
6759 direction, and the local web client appears as underway, in English and
6760 Chinese (#3418).
6761 - System-prompt skills block and skill-load warnings no longer embed absolute
6762 home/workspace paths; entries render workspace-relative or `~/…` so the
6763 byte-stable prompt prefix never leaks private paths. A new invariant test
6764 guards absolute paths, API keys, and workspace paths in the prefix (#4632).
6765 - Mode/permission baseline unit tests no longer read the developer's live
6766 `settings.toml`; they isolate config I/O to a temp directory (#4628).
6767 - Enter no longer freezes the composer on send: dispatch splits into a
6768 sync prepare phase (instant history + spinner) and a spawned async
6769 phase (auto-route, preflight, engine send), with submits gated while
6770 a dispatch is in flight (#4605).
6771 - Self-hosted routes keep explicit per-model output limits for unknown
6772 wire aliases instead of the generic 4K fallback (#4655 by @h3c-hexin;
6773 PR #4656).
6774 - Chat Completions idle-timeout errors now include received-byte and
6775 timing telemetry, distinguishing prefill stalls from mid-stream
6776 stalls with truncated tool-call arguments (#4657 by @h3c-hexin).
6777 - `set_config` provider writes now keep the in-memory route in step,
6778 so a following model write lands in the new provider's table instead
6779 of clobbering the previous provider's root default_text_model (#4658
6780 by @gaord, with a follow-up route-sync fix).
6781
6782 ### Security
6783
6784 - Restrict cross-origin Runtime API browser preflights to the documented
6785 authentication and content headers, explicitly allowing `Authorization`
6786 instead of relying on a wildcard (#4454).
6787
6788 ### Contributors
6789
6790 Thank you to the contributors whose code, reports, and reviews shaped v0.9.1:
6791
6792 - [@h3c-hexin](https://github.com/h3c-hexin) — calendar-anchored hourly
6793 automation recurrence (PR #4381), the MCP OAuth cancellation report
6794 (#4380), explicit limits for unknown local models (PR #4656 / #4655),
6795 and idle-timeout progress telemetry (PR #4657).
6796 - [@gaord](https://github.com/gaord) — Runtime API provider registry and
6797 atomic provider-switch endpoints (PR #4658).
6798 - [@SamhandsomeLee](https://github.com/SamhandsomeLee) — the unified `/skills`
6799 root catalog, audit/provenance model, validated mutations, manager UI, and
6800 acceptance coverage (PR #4679), plus Enter-send lag diagnosis and fix
6801 direction for #4605 (PR #4654; landed via the release-lane async-dispatch
6802 split).
6803 - [@aboimpinto](https://github.com/aboimpinto) — the Layer 5.1 user-command
6804 registry boundary from PR #3278; the exact authored evidence commit from PR
6805 #4046, preserved intact in the integration graph; and the #2870 follow-up
6806 audit whose metadata and malformed-sibling gaps shaped the final corrections.
6807 Paulo also provided the structured, redacted Agent Details and
6808 `current_activity` direction preserved from #2694/#2889 and the real-PTY
6809 lifecycle acceptance direction from #2886.
6810 - [@baendlorel](https://github.com/baendlorel) — TelecomJS TokenHub provider
6811 support and key-scoped live-catalog direction from PR #4370, harvested into
6812 the current provider architecture with co-authorship preserved.
6813 - [@zhangweiii](https://github.com/zhangweiii) and
6814 [@sternelee](https://github.com/sternelee) — the original first-class
6815 OpenCode Go implementations (PRs #773 and #1050), harvested into the
6816 current provider architecture.
6817 - [@seanthefuturegorilla](https://github.com/seanthefuturegorilla) — the
6818 canonical OpenCode Go/Zen provider request and acceptance direction
6819 (#1481).
6820 - [@nightt5879](https://github.com/nightt5879) — `/debt` compatibility aliases
6821 with dispatch-consistent user-command shadowing across discovery surfaces
6822 (PR #4680), plus the Solarized Light background preservation fix (PR #4471).
6823 - [@AiurArtanis](https://github.com/AiurArtanis) — the Solarized Light
6824 regression report and reproduction (#4457).
6825 - [@shenjackyuanjie](https://github.com/shenjackyuanjie) — the HarmonyOS
6826 workflow-js bindgen, portable-pty gating, and SDK environment work
6827 (PR #4470).
6828 - [@shenyongqing](https://github.com/shenyongqing) — the original HarmonyOS
6829 bindgen approach (PR #4384), carried into the landed implementation.
6830 - [@luismateusvargas](https://github.com/luismateusvargas) — the Windows hook
6831 process-leak reproduction, process-tree analysis, and EOF fix direction
6832 (#4489).
6833 - [@redjade75723](https://github.com/redjade75723) — the persistent Windows PTY
6834 report that exposed lossy high-bit process-status handling (#4100).
6835 - [@w1w218](https://github.com/w1w218) — the Windows ARM64 release request and
6836 real-device motivation (#4267).
6837 - [@stream2stream](https://github.com/stream2stream) — the legacy-session
6838 recovery report that led to the read-only doctor diagnostic (#4032, #4539).
6839 - [@Angel-Hair](https://github.com/Angel-Hair) — session-owned read-before-edit
6840 tracking and the explicit, backwards-compatible `apply_patch` replacement
6841 contract (PRs #4475 and #4476).
6842 - [@dmitri-0](https://github.com/dmitri-0) — configurable cache-hit visibility
6843 in the phase strip (PR #4474).
6844 - [@fleitz](https://github.com/fleitz) — the canonical `Bash` no-`cwd`
6845 workspace fix and regression test that keep isolated sub-agent commands in
6846 their own worktree (PR #4673, closing #4674).
6847 - [@SparkofSpike](https://github.com/SparkofSpike) — the Windows Ctrl+O
6848 reproduction that exposed pre-pager result truncation and conflicting composer
6849 shortcut routing (#4482), and the exact Vim-space regression reproduction
6850 verifying the v0.9.1 input path already contains the needed global binding
6851 (PR #4477).
6852
6853 ### Security
6854
6855 - Harden the public community-site boundary: scheduled review drafts now use
6856 one canonical freshness namespace, admin discard is restricted to validated
6857 draft objects, public feed requests cannot spend the server-held GitHub
6858 token, and maintainer login bodies are type- and size-bounded before parsing.
6859
6860 ---
6861
6862 Older releases: [CHANGELOG.md](https://github.com/codewhale-hq/CodeWhale/blob/main/CHANGELOG.md) and [docs/CHANGELOG_ARCHIVE.md](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/CHANGELOG_ARCHIVE.md).
6863
6863 lines MARKDOWN