# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.10.1] - 2026-10-07 ### Contributor integration and reliability - OAuth retry diagnostics omit provider-controlled error fields; account replacement stops before retired Weixin receipts exceed their storage limit, preserving uncertain work for local review. - Resuming a session through a symlink to the same workspace no longer shows a false workspace-change warning. - Runtime clients can read one tool call's actual workspace changes and reviewed skill details (thanks @gaord, #6817 and #6869). In-flight snapshot pairs remain pending; missing objects and corrupt repository metadata are distinguished. - Search accepts valid preferred locales, and image dimensions describe the same bytes sent to the model (thanks @asto18089, #6860 and #6858). Automation deletion keeps its definition until cleanup succeeds, and compaction preserves its original summary anchor (#6864 and #6857). - Config/status/permission commands share portable contracts while the host retains mutation authority; queue workers acknowledge a scheduled retry for temporary first-claim contention and fail honestly on corruption (thanks @aboimpinto, #6832). - Indefinite questions, approvals and elevation waits survive the TUI watchdog. Answers get time to resume the current turn; settled requests disappear by identity. Thanks @7jrxt42BxFZo4iAnN4CX for #6872. - Configured approval expiry belongs to the held Engine request; hiding or covering its card cannot restart the deadline, and a late queued answer cannot approve an expired call. - Tool discovery keeps the highest-ranked matches when a result batch exceeds the existing cache bounds, preserving search order and the 16 KiB limit (adapted from @AdityaVG13's #6393). - Model-switch receipts now translate their session-only saving note in every complete locale pack; the three save commands remain directly usable (thanks @Lstarsky0, #6875). - Route-save receipts and `/workspace` replies are translated in every complete locale pack, the Operate descriptions in fourteen packs match the current English, pt-BR, es-419 and ca regain accents six strings had lost, and long CJK text can be shortened between Han and kana characters (thanks @Lstarsky0, #6884, #6885, #6886, #6888, #6887 and #6882). - Long sessions keep less in memory: superseded journal entries beyond a retained window move out of the live session into a per-session archive under `sessions/.journal-archive/` (kept until the session is deleted; `/branch` can still restore an archived entry), ended shell operations in the work graph are capped, and session metadata larger than the first read no longer forces a full-file read. Not yet addressed: usage fingerprints in session metadata still grow without a bound, snapshots are still cloned on the UI task, and resume still reads the session file twice (thanks @7jrxt42BxFZo4iAnN4CX, refs #6842). - Weixin bridge threads belong to the account and chat that created them: resuming or listing another chat's thread is refused. An explicit `/new` after an account replacement keeps the old account's private receipt and never replays its prompts automatically. Replies never reuse another bot account's Weixin context token, and `/threads` lists this chat's own older threads even when other chats have newer ones. - Windows messaging bridges retry a briefly locked record replacement (EPERM/EACCES/EBUSY) with bounded delays and never delete the previous record first. - The website and README installation guides are generated from one shared source, and the critical Simplified Chinese guides were re-reviewed against current English. - A Codewhale sign-in that expired, or an account service that is unreachable, no longer blocks turns on your own provider key. The turn uses your local settings and Codewhale says once how to restore account preferences. - `codewhale login` keeps a DeepSeek route you chose, or one with a local key, instead of switching it to the managed Codewhale provider. - The bundled `computer-use` plugin is 0.12.1, reconciled with canonical source `724f9c422db1a51880dc81154dae70816c475ed8` while retaining Core's embedding manifest and version contract. Its image renderer lock now carries Sharp 0.35.5. - The bundled first-party catalog pins marketplace revision `6512f1dfaa91ee287e9f81ebabaf4909e8a371a3` and lists all 19 reviewed plugins, up from 6. Every catalog plugin still installs disabled and untrusted until you review it. - Every committed npm lockfile is audited in CI, including build tooling. The VS Code extension packages with `@vscode/vsce` 4 on Node 22 while it still compiles and tests on its Node 20 runtime. The website keeps one reviewed, hash-verified depth guard for an unpatched `braces` advisory (GHSA-vfj7-8cjw-p6xm); its raw audit findings are retained, not hidden. - Pasting through Windows Terminal (Ctrl+Shift+V) no longer drops emoji and other characters outside the Basic Multilingual Plane. Release binaries and source builds carry a small patch to crossterm 0.29.0 in `patches/` (the change proposed upstream as crossterm-rs/crossterm#1073); a real Windows Terminal paste of 24 Unicode lines is now a release gate. - Experimental extension host: reviewed Native plugins can register avatar packs with `ctx.avatars.registerPack` (`/pet avatar [key]`, `/pet action|view `). `/plugin import dsh ` reviews a DeepSeek Harness bundle and now lists the Native host code it contains; `approve ` installs it disabled and untrusted. Trusted host plugins stay trusted across a restart, enabling a second host plugin activates it without `/plugin reload`, and the review no longer crashes the TUI. Codewhale v0.10.1 focuses on reliability and first-run behavior. Turns that stall now say so, approvals keep what you approved, plugin suggestions are quieter, and Fleet runs can be checked before they spend anything. Scripts that parse `--json` output should read the **Breaking for scripts** note below before upgrading. ### Added - `/plugin doctor` reports stale built-in records and snapshots, and `/plugin doctor --fix` retires them. A user plugin, a snapshot a running process names, and a snapshot inside the grace window are kept. The previous `state.json` is kept as `state.json.pre-gc`. - Reviewed plugins can declare named OpenAI-compatible OAuth routes. The host owns PKCE, refresh and credential storage, and checks the review at each request ([docs/PLUGIN_PROVIDERS.md](docs/PLUGIN_PROVIDERS.md), #6805). The provider capability advances plugin review policy to v5 (v6 with the extension host): older receipts require explicit review again. - OrcaRouter account sign-in uses PKCE and saves the same durable API key as manual setup; its live catalog keeps chat-capable rows and stated pricing and modality facts (#6867). - Experimental TypeScript extension host. New in this release and off by default: turn it on with `[features] extension_host = true`. A plugin that declares a `native` TypeScript or JavaScript entry (the Cordis / DeepSeek Harness plugin model) can contribute tools, slash commands, pre-execution policy hooks, additive prompt sections, reviewed skill roots and plugin-local JSON state. Its code runs in a separate Node process, never inside Codewhale (Bun is an opt-in through `[extension_host] runtime`), and every call goes through Codewhale's own gate: an extension tool is never treated as read-only, so it always meets the approval gate (Full Access, Bypass or a session grant for that reviewed plugin can satisfy it), a command runs only when you type it, and a plugin must be reviewed and enabled first. The host is sandboxed on macOS (Seatbelt) and on Linux with bubblewrap, with no direct network and no reads of the protected credential locations (Codewhale's secret stores and the Codewhale, Codex and DSH homes). A Native extension starts only after that sandbox is verified at launch: if bubblewrap is missing or its namespace probe fails, activation is refused with the concrete error. Codewhale's own pinned built-in host modules keep a diagnosed exception, and every effect still needs a Rust operation ticket. On Windows a Native extension starts only in a freshly created Less Privileged AppContainer whose only capability is `registryRead` (Winsock cannot start without it), after Codewhale checks its token and a real file and network probe; otherwise activation is refused. Other files you can read, such as project `.env` files, stay readable, and plugins sharing the host can interfere with each other, so enable only plugins you have reviewed ([docs/EXTENSIONS.md](docs/EXTENSIONS.md)). - Extension slash commands: a plugin registers one with `ctx.commands.register`. It runs only when you type it, and it can show text, or submit a prompt as your next message that then goes through the ordinary turn and its approvals; it cannot call the model or a tool itself. A command cannot take a built-in command's name or another plugin's, and a markdown command with the same name wins. A command has 30 seconds, and commands are TUI only: the Runtime API does not list or run them. - Native extension authoring now includes policy listeners through `ctx.on('tools/pre-execute', ...)`, prompt sections through `ctx.prompt.registerSection`, and persistent plugin-local state through `ctx.storage`. Listeners may deny, ask, revise input or annotate; Rust rechecks revised calls and owns every approval. Prompt sections cannot replace the system prompt, and state exposes no session history or secret API. These services share the experimental, off-by-default host's reviewed owner lifecycle and are withdrawn when their owner unloads or is revoked; saved state remains available when the plugin reloads. - Extension tool input is checked against the JSON Schema the tool registered, before an approval card appears and again before the call reaches the host. An invalid call comes back to the model as an error naming what to correct, and the host never sees it. A schema that cannot be compiled, or that refers outside itself with `$ref`, is refused when the tool registers. - An extension tool can call eligible core tools with `core/call` while the ordinary turn is running that extension tool. Rust supplies a temporary invocation ticket and still owns planning, hooks, permissions, approval and execution. The ticket is bound to the plugin owner, host process and live invocation, and expires when that invocation ends or is revoked. Commands, timers and plugin startup cannot use this path. Approval grants are scoped to the reviewed extension build; a grant to the model does not cover it. Shell and network calls require a person's prompt even with a remembered grant; a permission mode that cannot present that prompt refuses the call. MCP tools, Computer Use, other extensions, agent/workflow launches and permission-changing tools remain unavailable through this path. A cancelled invocation withdraws its pending approvals instead of deciding them for you. - Extension host identity is checked at startup: its reported trust tier and built-in module digests must match the process Rust launched. Built-in host code and third-party plugins have separate process and owner namespaces; the table pins the MCP protocol module and the execution harness. The optional Host MCP backend uses the official TypeScript SDK for framing, with Rust retaining credentials, network/process access, approval and exact operation tickets. All 30 existing recorded comparisons pass locally. The Rust backend stays the default until platform and rollout gates pass; its protocol adapters remain through the compatibility window. - A plugin can declare several `native` entries (`native.paths`, up to 64). They activate in order under one owner, so one disable, review change or crash takes all of them down. If one entry fails to activate, only that entry is withdrawn: entries that already activated stay registered, and the plugin fails only when no entry activates. - Plugin settings and context: `[plugins."".config]` in your own `config.toml` is passed to the plugin's `apply(ctx, config)` and checked against its exported `Config` schema; a project's `.codewhale/config.toml` cannot set it, a change applies at `/plugin reload`, and `/plugin show` lists the keys, never the values. Tools and commands also receive the workspace of the session that called them and a private data directory for the plugin under `~/.codewhale/extension-host/data/plugins/`; no home, credential or other workspace path is passed. - `codewhale --enable ` and `--disable ` work from the `codewhale` command; before, they were rejected. Put the flag before any subcommand. - The extension host bundle carries MIT-licensed code (Cordis, Schemastery and others). Its third-party licence notices are generated from what the bundle actually contains and written beside the bundle when it is unpacked, and `THIRD_PARTY_NOTICES.md` lists the packages. - 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. - `docs/features.toml` lists every user feature with its status, first release, docs page and owning code. A test fails when a `[features]` flag and its row disagree, or when a listed docs page or code path is missing. The configuration reference now lists the `verify_tool`, `vision_model` and `extension_host` flags, and `config.example.toml` lists `code_mode`. - A reusable GitHub Action runs PR reviews with a configurable model endpoint and a checksum-pinned Codewhale binary. It checks the PR's eligibility and exact revisions before inference; fork events receive no model key ([#6780](https://github.com/codewhale-hq/Codewhale/pull/6780)). - An optional, off-by-default shadow Decision Gate classifies the first request of a turn — tool need, answerability from context, intent — through the existing System One client and only logs a typed recommendation; it never changes routing or delays the model call. Configure it with `SUPERFAST_ENABLED` and `SUPERFAST_PROVIDER` (docs/CONFIGURATION.md) ([#6603](https://github.com/codewhale-hq/Codewhale/issues/6603), [#6604](https://github.com/codewhale-hq/Codewhale/pull/6604), thanks @Andrea-Bruno). - `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)). Supported settled local shell calls also send a versioned JSON document on stdin to foreground or background observers, with session/tool-call IDs, nullable exit status and output truncation flags. Existing environment fields stay available; unsupported execution paths send no document, and observer output cannot change the completed call ([#6582](https://github.com/codewhale-hq/Codewhale/issues/6582)). - Runtime API: turns now record what they produced. Each item and turn carries typed artifact references (path, kind, size, revision, and a restore point when file-revert would accept one) for files a tool wrote, spilled tool output, and media. - Once the post-turn snapshot settles, the turn also lists what changed in the workspace while it ran, including shell and sub-agent writes. It then publishes `turn.artifacts`. - `GET /v1/threads/{id}/turns/{turn_id}/artifacts` lists a turn's references, and `.../artifacts/{artifact_id}` reads one from the workspace, the post-turn snapshot or the session artifact directory. - Spills from unbound runtime threads were unreadable before; they are now readable. - The legacy `artifact_refs` field is now filled with the workspace files a tool call wrote, so Preview in current desktop builds shows them ([#6653](https://github.com/codewhale-hq/Codewhale/issues/6653)). - Runtime API: git stage, unstage, discard and commit accept optional `expect` preconditions (full HEAD id, an index token, per-file `rev`, or a whole-tree `revision`, all read from `GET /v1/git`). When the repository changed since the client read it, the write does nothing and answers 409 `git_state_changed` with the current state, so a Review sheet can no longer stage bytes, discard edits or commit an index the user never saw. Requests without `expect` behave as before. Path writes now use literal pathspecs, as the docs already said, and `files[].path` is workspace-relative in a subdirectory workspace. Guards cover executable mode, submodule HEAD and changes outside that workspace; oversized or budget-limited stat-only revisions cannot authorize a guarded write. Status stays best-effort: unreadable paths, symlinked ancestors, special files and broken nested repositories withhold only affected row tokens and the whole-tree revision. Normal Git filters and untracked settings apply, with directory inventories scoped to the rows or paths that need them. Untracked workspace files and renames leaving the workspace remain visible, and broken HEADs cannot satisfy an unborn-HEAD guard ([#6647](https://github.com/codewhale-hq/Codewhale/issues/6647)). - Runtime API: `POST /v1/threads/{id}/fork-at-turn` forks a thread at a named user turn, keeping that turn and every turn before it. The receipt matches `/undo` and returns the first dropped prompt so a client can put it back in the composer. Naming the turn replaces a client-computed depth, which could fork the wrong prefix. The fork leaves the workspace and any running turn untouched ([#6580](https://github.com/codewhale-hq/Codewhale/pull/6580), thanks @gaord). - Official model routing: `/router` (also `/model router`) sets up the Auto router with presets: Jev (TypeSafe's decision model, via OpenRouter or a TypeSafe key), your provider's fast tier, Off, or Custom. Jev and Fast each make one test call before you save, the Turn Inspector (Ctrl+Alt+O or `/turn inspect`) shows the router's choice, cost and latency, and a failing router is shown as failing ([#6525](https://github.com/codewhale-hq/Codewhale/issues/6525)). - ChatGPT sign-in uses Codewhale-owned protected credentials and a model roster fetched for the signed-in account. Account, workspace and issuer changes cannot reuse another roster; a missing or stale roster offers no models. Authentication failures and subscription limits do not silently fall back to a paid API route. - Code mode composes MCP and plugin tools and is on by default: `execute_tools` programs can call MCP tools, and each nested call passes the same approval gate as a direct call, pausing the program for approval when needed. Every nested call keeps its receipt, including calls that finish before a deadline, and `[features] code_mode = false` stops offering `execute_tools` up front (it stays reachable through tool search). `codewhale mcp list` and `codewhale doctor` warn when a user MCP server duplicates the built-in Computer Use bundle ([#6562](https://github.com/codewhale-hq/Codewhale/issues/6562), [#6509](https://github.com/codewhale-hq/Codewhale/issues/6509)). - Tsubasa is a bundled OpenAI-compatible provider row: base `https://api.tsubasa.sh/v1`, key `TSUBASA_API_KEY`, model `tsubasa-pro` (also `tsubasa-fast`). Its window is 32,768 tokens; set `providers.tsubasa.context_window` to match ([#6695](https://github.com/codewhale-hq/Codewhale/issues/6695), thanks @cenab). ### Changed - The pinned prompt header follows the turn at the top of the viewport, handing over to the previous prompt as you scroll, and clicking it jumps back to the message it names ([#6830](https://github.com/codewhale-hq/Codewhale/pull/6830), thanks @SparkofSpike). - On Windows, every PowerShell command the shell tool starts now passes `-ExecutionPolicy Bypass` for that process only, so a local `Restricted` or `AllSigned` policy no longer blocks multi-line commands. (`.ps1` script tools still start as `powershell -File` without the flag and remain subject to the local policy.) A policy set by Group Policy still wins and the command is refused with PowerShell's own message. Scripts that a command invokes run under the same process-scoped setting. To let the machine or user policy apply instead, start Codewhale with `CODEWHALE_POWERSHELL_EXECUTION_POLICY=inherit`: it then omits `-ExecutionPolicy`, so a `Restricted` or `AllSigned` policy refuses the multi-line commands that need a temporary script; any other value keeps the default. Not verified on a native Windows machine ([#6745](https://github.com/codewhale-hq/Codewhale/issues/6745)). - The website's not-found page now uses the Codwhale poster and typo joke, with English/Chinese recovery links to home and docs ([#6419](https://github.com/codewhale-hq/Codewhale/issues/6419), [#6420](https://github.com/codewhale-hq/Codewhale/pull/6420)). - Script tools can no longer approve themselves or replace built-in tools (founder decision D4). A `# approval: auto` line in a script under `~/.codewhale/tools` (or `[tools].plugin_dir`) is ignored: the tool follows the session's approval setting like a script with no `approval:` line, and the runtime log and `/plugin tools` name each script that still declares it. A `[tools.overrides]` entry of `type = "script"` or `type = "command"` keyed by a built-in tool name is refused, and the built-in stays active; a status line names the key once per session, and the runtime log records it. `type = "disabled"` still turns a built-in off, and script or command overrides under a new name still work. To keep a wrapper such as an audited shell, disable the built-in and give the wrapper its own name ([configuration](docs/CONFIGURATION.md#script-tools-and-overrides)). - Complete the session slash-command group’s shared command boundary, including `/structcopy`, so all seventeen commands can compile independently of the TUI. Host operations remain behind capability interfaces; command behavior and upstream tool-execution identity safeguards are preserved ([#6792](https://github.com/codewhale-hq/Codewhale/issues/6792), [#6145](https://github.com/codewhale-hq/Codewhale/issues/6145)). - The declared minimum Rust version is now 1.89. It said 1.88, which could not build Codewhale: a locked dependency (`serde-saphyr`) needs 1.89, the version CI's minimum-version job builds. The install guides and the npm wrapper's build-from-source hints now say 1.89 too. - A deferred tool's first call now runs when its arguments already carry every required field and no field the schema does not declare, instead of costing a retry turn. Malformed calls still get the schema, and approvals, deny lists and Plan mode apply first. Argument types are still checked by the tool itself. Sub-agents preload tools named in `allowed_tools` ([#6494](https://github.com/codewhale-hq/Codewhale/issues/6494), [#6437](https://github.com/codewhale-hq/Codewhale/pull/6437)). - Automatic Git status and review reads need Git 2.31 or newer, because they pin Git's runtime configuration overrides. With an older Git they refuse with "upgrade Git (2.31 or newer)". This covers the read-only Git tools (`git_status`, `git_diff`, `git_log`, `git_show`, `git_blame`, `verify`); Git writes you ask for keep their existing behavior ([docs/dependency-maintenance.md](docs/dependency-maintenance.md)). ### Fixed - A failure Codewhale can name is no longer labelled an internal fault. An HTTP 400/405/409/413/422 rejection, an out-of-credits 402, the context-budget stop and a turn's own step or wall-clock ceiling now carry an input or budget label, and a bare `ERROR` from a provider is reported as an unreadable error instead of a warning. Refs #6843. - A transient upstream failure reported as an error frame inside a successful response is retried within the stream retry budget. When the budget is spent the turn fails once with an error card instead of an amber warning that promised a retry. Refs #6795. - Diff lines and tool output wrap at grapheme boundaries, so emoji families, skin tones and variation selectors no longer split across lines ([#6829](https://github.com/codewhale-hq/Codewhale/pull/6829), thanks @Lstarsky0). - Twelve translated packs now translate the context inspector's making-room and anchors rows, the Ctrl+O hint and the `/turn inspect` and `/advisor` descriptions instead of showing English ([#6831](https://github.com/codewhale-hq/Codewhale/pull/6831), thanks @Lstarsky0). - Optional MCP servers can be found before they connect. `tool_search` matches the query against configured, enabled server names (or an `mcp__` prefix), connects up to eight matches within the existing boot wait, and returns their real tool schemas. Before, a lazily started server exposed no tools, so the model could never trigger its connection ([#6828](https://github.com/codewhale-hq/Codewhale/issues/6828)). Known limit: a query that names neither the server nor `mcp` does not wake it. `codewhale mcp connect`, `validate` and `tools` run their own connection and do not attach to a running session. - `/undo` and `/restore ` refuse while a turn is running in the workspace, instead of rewriting files under it. - `--resume ` after a crash recovers that session's interrupted turn from its crash checkpoint, as `--continue` does. - `/resume ` keeps an imported session on the current provider route instead of a default one. - When the stall watchdog recovers a turn, the Engine's turn is ended too, so the next message is accepted ([#6800](https://github.com/codewhale-hq/Codewhale/issues/6800)). - A turn you cancel, or one the stall watchdog recovers, releases input at once. A message still waiting to reach the engine is abandoned and its unsent text returns to the composer, instead of holding input for up to 60 seconds ([#6800](https://github.com/codewhale-hq/Codewhale/issues/6800)). - A transient upstream failure that a gateway reports as an error frame inside a successful response ("Provider returned an empty response") is retried under the stream retry budget when nothing had streamed; authentication and invalid-model frames still fail at once ([#6795](https://github.com/codewhale-hq/Codewhale/issues/6795)). - Long sessions no longer start every turn late. Once a workspace held more than 50 undo snapshots (around the sixteenth turn), each new snapshot rebuilt the whole snapshot history before the provider request, about 2.8 s per turn in a small workspace. Old snapshots are now dropped half a window at a time. - Resuming a crashed session from inside the TUI recovers its interrupted turn too. - Release builds compile on Rust 1.99. - TUI undo and retry rewind the Engine conversation and saved session before replacement inference. If the conversation or its settings change while undo is being prepared, it refuses without overwriting that newer state or changing the draft. Retained compaction summaries survive the rewind and cannot be selected as editable user prompts ([#6788](https://github.com/codewhale-hq/Codewhale/issues/6788)). - `/edit` replaces the exchange it revises through the same rollback: the old prompt and its answer leave the transcript, the model's context and the saved session before the edited prompt is sent. - When the rollback that `/edit` needs is refused, your revised text goes back to the composer with edit mode still on, instead of being dropped. Opening `/edit` while you are editing a queued follow-up returns that follow-up to the queue first. - A session can still be resumed by its id when a stray copy of its file sits in the sessions directory; before, the id was reported as ambiguous. - Agents follow the Permissions you choose while they run: switching to Full Access reaches an agent that is already working, instead of leaving it with the Auto-Review guardian that denied it. Tightening reaches it too. An agent's answer to an approval prompt is delivered while the main session is busy, and a forced delete inside the workspace is no longer treated as a catastrophic system delete. On Linux, Full Access switched on at runtime cannot lift the kernel no-new-privileges flag set at startup, so `sudo` and setuid helpers still fail; start with `sandbox_mode = "danger-full-access"` or `CODEWHALE_NO_NEW_PRIVS=0` if agents need them ([#6787](https://github.com/codewhale-hq/Codewhale/issues/6787)). - Stream limits and transport settings share a typed `[stream]` configuration table, including retry budgets, TCP keepalive and HTTP/2 keepalive. Explicit values take precedence over legacy `[tui]` aliases; omitted values preserve existing defaults and environment behavior. A configured HTTP/1 pin stays pinned during recovery. `/config stream_chunk_timeout_secs ... --save` updates the canonical setting so it survives reopening a configuration that already had a timeout. Transport changes apply when a client is built ([#6700](https://github.com/codewhale-hq/Codewhale/issues/6700)). - Switching providers keeps a model set only in the root `default_text_model` with the provider it belongs to. Switching away and back (`/provider` in the TUI, or the desktop app's model chip) used to land on the provider's catalog default such as `gpt-5.6`, and a pass-through provider switched to in between inherited the other provider's model, or a stale legacy root `model` that the root default had been shadowing ([#6693](https://github.com/codewhale-hq/Codewhale/pull/6693)). - A turn no longer stops after an hour of work. The cumulative per-turn wall clock is unlimited by default, like model steps; set `[tui].turn_wall_clock_secs` to cap it. - OpenRouter turns are priced again instead of always showing "rate unavailable". The model-list refresh no longer fails as a whole on one bad row: `~` "latest" aliases are dropped, routers that publish a `-1` variable price are listed without a rate, and other malformed rows are skipped and counted. Main interactive turns now honor a `[[custom_models]]` rate the same way background work does, a declaration without rates no longer hides the catalog price, and an explicit declared rate prices a vendor-pinned OpenRouter route ([#6690](https://github.com/codewhale-hq/Codewhale/issues/6690)). - `codewhale exec` can take prompts past the OS argument limit (~128 KiB on Linux, where larger prompts failed with `Argument list too long` before Codewhale started): `--prompt-file ` reads the prompt from a file, and `--prompt-file -` reads it from stdin; a positional `-` stays literal text ([#6688](https://github.com/codewhale-hq/Codewhale/issues/6688)). - Keep reasoning effort labels, including `xhigh` and `ultra`, visible beside short model names in the 80-column terminal footer. - First-run TUI startup keeps explicitly configured providers, models and endpoints (including environment overrides and a legacy top-level `base_url`), even with a missing key, instead of adopting a detected local Ollama model. The `default_text_model` line written into the generated first-launch config is not treated as a choice, so starting Ollama after the first launch is still detected. Usable configured routes skip the provider picker and record the provider step as configured, without claiming a successful check; missing-key recovery focuses the configured provider even on a fresh home. Switching from that recovery picker (or after Esc) to a provider that has its key clears the launch "needs a key" state, so the footer names the route instead of "model not connected" and a detected local Ollama can no longer take over the provider just chosen. Empty sessions no longer show a full context window from the startup prompt; a submitted first turn or reported usage still shows real pressure. - `/trust on|off` changes file-tool trust for this session. Add `--save` to persist workspace trust for project skills, commands, hooks, MCP servers, and project context. Skipped-skill notices stay out of conversation titles and user bubbles, and trust changes append a correction to the model's history. - Stored-secret cleanup skips busy Runtime stores and reports unreadable paths while continuing through other files. Configured storage roots may be symlinks; discovered symlinks are not followed. Cleanup also masks current configured credentials, and doctor's bounded scan reserves capacity for saved transcripts and checkpoints separately from Runtime receipts. - Hooks: `tool_call_after` and `on_error` now get a shell command's exit code in `DEEPSEEK_TOOL_EXIT_CODE` on Runtime API threads as well as in the TUI, and for a failing command as well as a passing one, so `exit_code` conditions match. The Runtime API path passed no exit code at all, and a command that exited nonzero, timed out, or was killed reached hooks with no exit code on either surface. The new `DEEPSEEK_TOOL_STATUS` says how the command ended (`completed`, `failed`, `timed_out`, `killed`) ([#6582](https://github.com/codewhale-hq/Codewhale/issues/6582)). - Scrolling a long transcript repaints the reasoning reveal hint in place instead of rebuilding the transcript tail. Wheel and scrollbar input use interactive frame pacing, collapsed tool groups reuse cached summaries, and height-only resizes keep wrapped history. Width changes still rewrap content, and other per-frame work still grows with session length ([#6652](https://github.com/codewhale-hq/Codewhale/issues/6652)). - A settled transcript frame reuses its existing render plan instead of rebuilding or moving unchanged history on every poll. New output, selection, resize and other real changes still invalidate the affected work ([#6652](https://github.com/codewhale-hq/Codewhale/issues/6652)). - Workflow progress rows and working, verification and translation indicators use the pinned Codewhale terminal component kit. Quiet and reduced-motion working/verification indicators hold its semantic current-work mark. Working and verification keep their existing delay and cadence, while translation uses the same earned marker and five-frame-per-second cadence. The Engine still supplies workflow state, clocks, localized text, custom themes and terminal adaptation. The composer, transcript viewports, dock tabs, posture/metrics rows, pending-input cards, approval band, Ocean background and the whale's Braille raster now also render through the pinned kit. - Calm transcript previews keep the latest three rows of live thought and a single duration header when it settles. Successful tool headers are quieter; failed generic and MCP calls keep a bounded head-and-tail excerpt, with full output available in details. Existing collapsed groups show their hidden count and reveal cue, and explicit thought expansion stays available. - Composer history preserves multiline entries and literal quoted text while retaining the old history file during migration. An oversized message stays in the composer if its paste file cannot be saved, with a localized notice; mouse placement and quoted file mentions handle multibyte text and spaces ([#6776](https://github.com/codewhale-hq/Codewhale/pull/6776)). - The notice for an oversized message that cannot be saved as a paste file is now a short line that fits the footer ("Not sent: over N characters; paste file not saved."), in every supported language. The full reason, including the write error, goes to the transcript once. - Model-facing guidance names callable tools and explains discovery before a deferred read. The stopship workflow's scout activates the deferred `grep_files` with one required `tool_search` call, then gathers bounded `grep_files` evidence from the current workflow source paths ([#6747](https://github.com/codewhale-hq/Codewhale/issues/6747)). - Simplified and Traditional Chinese permission, provider and session wording now follows the current behavior. Chinese guides correct hook receipts, trusted skills, MCP startup and Windows limitations, preserving the contributor translations and a shared glossary. - Unknown website locale segments, including dotted missing paths, return a real 404 with noindex metadata and no home-page canonical URL. The existing layout guards now have regression coverage across all registered locales ([#6786](https://github.com/codewhale-hq/Codewhale/pull/6786)). - The terminal caret no longer blinks at the hidden composer while a picker, settings screen or other view covers it; it returns when the view closes ([#6545](https://github.com/codewhale-hq/Codewhale/issues/6545)). - On Linux and macOS, a `background: true` shell's process group is now stopped when the TUI dies without cleaning up (SIGKILL, a crash, or the signal exit path). The shell and the processes it started used to keep running as orphans. Processes that move to their own process group or session, staged services you choose to keep, and `tty: true` background shells are not covered. Under the bwrap sandbox, the sandboxed command now also exits when bwrap does ([#6654](https://github.com/codewhale-hq/Codewhale/issues/6654)). - Idle task workers stop periodically reloading a settled, unchanged empty queue, and task listings reuse an unchanged store snapshot. New queue writes and local notifications still wake workers; recent or unreadable metadata and failed claims keep bounded retries. This reduces repeated disk work when several TUIs share a data directory without changing task ownership or cancellation ([#6573](https://github.com/codewhale-hq/Codewhale/issues/6573), [#6728](https://github.com/codewhale-hq/Codewhale/issues/6728)). - Idle task workers check the queue file's metadata about once a second instead of five times a second, and no longer reloads the store when nothing changed. An in-process notification still wakes a worker at once; a write by another Codewhale process that shares the data directory is noticed within about a second instead of about 200 ms. A worker with pending work, a retry deadline or a failed claim keeps the short interval ([#6728](https://github.com/codewhale-hq/Codewhale/issues/6728), [#6573](https://github.com/codewhale-hq/Codewhale/issues/6573)). - After five seconds without session activity, the UI loop polls every 250 ms instead of 48 ms and the automation-panel scan backs off to 15 seconds. After thirty quiet seconds, the Git probe runs one `git status` every 15 seconds instead of the full probe every two seconds, unless the Git panel is showing. User input and engine events restore the active cadence. This reduces idle work; it does not remove every cost that grows with session history ([#6728](https://github.com/codewhale-hq/Codewhale/issues/6728)). - When the task store is busy, the message now names the process that holds its lock and how long it has held it ("lock held by pid 1234 for 12s"), when that can be read. A repeated "Task claim unavailable" error is logged once per episode, then at debug level ([#6573](https://github.com/codewhale-hq/Codewhale/issues/6573)). - On Windows, Fleet can read a running worker's log while its writer holds the file open, and task-store contention can still read the lock-holder record. These paths previously failed because of whole-file sharing and locking. - File writes, including legacy `File` and `write_file` calls, stop if the original contents cannot be read; legacy writers also reject non-UTF-8 originals, keeping undo and diffs from recording an empty original file. - Resuming a session preserves user messages that quote a compaction marker. - Requirements allow-lists now check unset approval and sandbox defaults, accept equivalent approval aliases, and lock permission posture when sandbox modes are constrained so saved Full Access and YOLO cannot bypass them. - Logout completes xAI OAuth revocation and attempts every credential deletion before reporting remaining credentials with a non-zero exit status. - ChatGPT and xAI sign-in now show the account the selected route actually uses, and sign-in names the account it replaces. `/auth chatgpt` and `/auth xai-device` switch the running session; signing in from a separate shell requires restarting an already-open session. Subscription-limit errors name the account that made the request and explain how to switch, without printing credentials ([#6715](https://github.com/codewhale-hq/Codewhale/pull/6715)). - `doctor --fix` keeps temporary files modified within the last hour. - Provider streams stop with a clear error if an SSE line exceeds 8 MiB. - Recursive `rlm_query` turns inherit the parent's remaining deadline, bounded by the existing child budget, including asynchronous lock waits, startup, model requests and Python evaluation. Expired work is refused before dispatch; a timeout returns the last response with an incomplete-result error. Nested code and status receipts accompany the enclosing tool result on success or failure and survive its session save/reopen. In-flight receipts still need that result to be handed back before they become durable ([#6511](https://github.com/codewhale-hq/Codewhale/issues/6511)). - The TUI keeps redrawing while its terminal is unfocused. v0.10.0 held every frame on focus loss, so on Windows Terminal, macOS and other terminals a window sitting behind another one looked frozen until you clicked back into it. Frames are now held only on GTK/VTE terminals, which replay the damage themselves when they return. That hold was added for the MATE flicker in [#6311](https://github.com/codewhale-hq/Codewhale/issues/6311) ([#6651](https://github.com/codewhale-hq/Codewhale/issues/6651)). - TUI `/undo` now restores only the files the undone tool call or turn changed, and refuses, changing nothing, when one of them changed since. Before, it checked out the whole snapshot tree, which also reverted later edits to other files. It also finds restore points older than the newest 100 snapshots, and a forked session can undo the turns it inherited. It waits for a post-turn snapshot that is still being written, leaves a changed symlink or other non-regular path in place (and says so) instead of refusing the whole undo, and writes nothing to the snapshot store when it refuses outside trusted mode ([#6644](https://github.com/codewhale-hq/Codewhale/issues/6644)). - On a fixed model, each Ctrl+T press now moves to a different thinking tier. Ctrl+T and the `/model` picker could list tiers the route treats as the same one — DeepSeek's `medium` is `high`, and Z.ai GLM-5.2's `low` is `high` — so some presses changed nothing. They now share one list per route with one entry per effective tier. Under Auto model routing, Ctrl+T walks the picker's Auto list instead of a longer private one; the tier is still settled when the turn is routed, so two neighbouring choices can land on the same tier. DeepSeek now reports `minimal`, `xhigh` and `ultra` as the `low`, `high` and `max` it sends, in `/status`, receipts and `/effort`, and Kimi Code K3 no longer offers `off`, which it always ran as `low` ([#6650](https://github.com/codewhale-hq/Codewhale/issues/6650)). - A top-level `base_url` or `api_key` in `config.toml` now means one thing everywhere. Every reader used its own rule for which routes inherited it, which is how a DeepSeek endpoint became the Xiaomi MiMo route's and failed with DeepSeek's 401. Old files keep working: the keys are read as `[providers.deepseek]` (or the vendor whose official host they name), the next save moves them there with a one-time backup and a one-line note, and a value that disagrees with its table is left for `codewhale config migrate --prefer` to settle. `codewhale config doctor` shows what is in use ([#6394](https://github.com/codewhale-hq/Codewhale/issues/6394)). - Setting up a bundled OpenAI-compatible host from `/provider` now shows that host's key console, docs link and guidance on the setup form, the same way the built-in providers' key entry does; before, the descriptor file carried them and nothing read them. AICraft gains all three ([#6616](https://github.com/codewhale-hq/Codewhale/issues/6616), thanks @BX166). - Runtime API undo now restores the files of the turns it undoes, for every kind of thread. Before, a new thread's turns were not linked to their workspace snapshots, so `patch-undo` returned `201` and rewound the conversation but left the files changed, and `file-revert` refused. Each turn record now lists its snapshots in `workspace_snapshots`, the engine runs under the thread's own id across restarts, and a fork owns the turns it inherited. `patch-undo` restores only the files the undone turns changed, including every write in a turn, and leaves later edits by the user or another thread alone. Every tool call that may write is bounded by its own snapshots, so a file another thread or an editor changed while the turn ran is never reverted as the turn's, and a turn's restore points survive the snapshot count cap. When it cannot restore files (including a write to a gitignored path) it now refuses with `409` and an `error.code` instead of returning `201`. A nameless `PUT /v1/sessions` updates the document the thread is bound to ([#6621](https://github.com/codewhale-hq/Codewhale/issues/6621)). - A Runtime thread that is not bound to a saved session keeps one engine session id, its own thread id, across its first turn, eviction and restarts. Before, each engine spawn generated a new id, so the thread's tool-output spills, snapshot tags and shell jobs were scattered across a different `sessions//` per spawn ([#6659](https://github.com/codewhale-hq/Codewhale/issues/6659)). - Saved sessions no longer go orphaned, and existing orphans are repaired at launch. Deleting a session now sets aside the Runtime store it was actually bound to, and switching a conversation to another host's store sets aside the store it left, unless another session still uses that store or it holds work. Exporting a thread (`POST /v1/sessions`) updates the thread's own document instead of creating a new one each time. A thread whose document was appended to elsewhere keeps loading. A thread whose document was deleted or rewritten loads from its own turns instead of failing, and threads write their files under the session they belong to. Each launch and `codewhale serve` repairs the store in the background: a store holding threads with no session gets a "Recovered:" session for each thread, and unreadable documents, unused empty stores and old files no session names move to `sessions/.set-aside/` with a manifest. Nothing is deleted. `codewhale doctor` reports the last repair, and `codewhale doctor --repair-sessions [--dry-run]` runs one now. `PUT` and `DELETE /v1/sessions` refuse a session that another Codewhale process has open ([#6144](https://github.com/codewhale-hq/Codewhale/issues/6144)). - Runtime API: the thread event stream now ends with a typed `stream.end` frame (reason and resume cursor) whenever the server closes it, including on shutdown, so clients can tell a Runtime error from a dropped connection and resume from the right event. A replay worker crash no longer ends history early and skips events without a detectable gap, and the mobile page resumes from its last event instead of replaying from zero, with stream statuses in the configured UI language. Cross-origin clients can read the stream-end and replay-progress capability headers, and the SDK exports `isThreadStreamEnd` for TypeScript narrowing. - `codewhale exec --auto` no longer exits 141 with no output when a child it writes to, such as a stdio MCP server, closes its pipe early. Headless exec now ignores SIGPIPE while it runs, as the interactive TUI already did, and `exec ... | head` still ends quietly. One-shot `codewhale exec` no longer prints DeepSeek's raw `<||DSML|| calls>` tool-call markup as its answer: the markup is removed, and an answer that was only a tool call fails at once with the reason and a pointer to `--auto`, instead of asking the model again and blaming an incomplete provider response. - Resuming a session keeps its "Resumed:" confirmation on screen instead of replacing it with "Make room automatically: on" when nothing was switched. - Tool output is no longer cut off where you can't get it back. Search answers, test runs, git, verifier and web results reach the model whole up to one budget sized to the model's context window, and anything beyond it can be read back with `retrieve_tool_result`, including read-only tools executed alone or in parallel. Restored raw results use the active route's same inline budget; existing recovery receipts stay intact. Tiny budgets use a compact retrieval reference instead of a long artifact path and instructions; a complete reference is kept even when it alone exceeds the allowance. Native search now asks for answers up to 8,192 tokens (was 2,048–4,096) and waits long enough for them to arrive, and an answer the provider still cuts short is marked as cut ([#6508](https://github.com/codewhale-hq/Codewhale/issues/6508)). - The installation page is generated from `docs/INSTALL.md`, so the website and the guide can no longer disagree; broken anchors and unsafe links fail the build ([#6450](https://github.com/codewhale-hq/Codewhale/pull/6450)). - `codewhale config set` refuses a value of the wrong type for a known setting (a word for an on/off switch, text for a number, a choice outside the list) instead of saving it ([#6568](https://github.com/codewhale-hq/Codewhale/pull/6568), thanks @dajiaohuang). - Receipts: `/receipts`, `codewhale receipts [ID|--last] [--format md|json]`, and `GET /v1/threads/{id}/receipt` (plus a per-turn form) list what a session did, one line per action: files changed with line counts, commands with exit codes, web and MCP calls, agents, approvals and who gave them, and failures. They also count what ran without asking and name the posture each turn ran under, read from the turn's own record. A call Codewhale blocked before it started (Auto-Review or guardian, a tool policy, a refused sandbox escalation, invalid input, a missing tool) is listed as blocked, with the reason, and is not counted as run or as ran without asking. Only Codewhale's own refusal text counts: an MCP server, a fetched page, or a program cannot make a call that ran read as blocked. A terminal session's receipt also lists the files a command changed in each turn, from the workspace snapshots taken before and after it (not ignored files or anything outside the workspace), with control characters in paths escaped so a file name cannot forge a receipt line. All three read the records Codewhale already keeps and say what those records do not hold ([docs/RECEIPTS.md](docs/RECEIPTS.md)). `audit.log` is not that record: it logs security events, and it logs an approval only when one is requested, which under Full Access is almost never. - Approvals now record who decided: you, a session rule, or the posture. An automatic approval used to be saved exactly like one you gave, and an app approval that expired was saved as your denial. `GET /v1/approvals` now returns `decided_by`. - Network audit lines now go to the same `audit.log` as every other audit event (`$CODEWHALE_HOME` included), and test runs no longer append to your real one. - In the terminal UI, Auto-Review verdicts now reach `audit.log`, as `/permissions` said they did; before, they were written only when `CODEWHALE_TOOL_AUDIT_LOG` was set. Headless `exec` and Runtime API sessions do not write them yet. - A turn that stops producing output now reports itself: the turn loop records its phase and last progress, and an overdue phase surfaces instead of hanging silently until the stream idle timeout. A delegated agent's final result is never dropped when the host is busy, so a finished child no longer leaves a ghost Running row behind ([#6184](https://github.com/codewhale-hq/Codewhale/issues/6184)). - Git commands run by tools never stop to ask for a password, passphrase or host-key confirmation inside the terminal, and `git_fetch` has a timeout ([#6184](https://github.com/codewhale-hq/Codewhale/issues/6184)). - A provider response that ends cleanly with no text and no tool call is retried before the turn fails, and the failure names how many retries ran ([#6310](https://github.com/codewhale-hq/Codewhale/issues/6310)). - The context meter, the point where Codewhale makes room, preflight, `/context` and turn receipts show one pressure number instead of disagreeing ([#6407](https://github.com/codewhale-hq/Codewhale/pull/6407)). - When Codewhale makes room, the note it leaves for the next turn is written in its own words, under fixed headings: the objective, the user's corrections, permissions and limits, changed files, what is still running and the checks left. A message that quotes the note's opening words now stays in the conversation instead of being dropped. If the summary request itself is too large, older history is dropped but the previous note is kept, and making room stops rather than write a new note without it. - Continuing a conversation that is already open no longer adds a second thread, and a fork keeps its own session file, so autosave on one side no longer leaves the other unloadable ([#6406](https://github.com/codewhale-hq/Codewhale/pull/6406), thanks @gaord). - Upgrading Codewhale no longer turns off the built-in Computer Use. Each build writes the built-in bundle to its own directory, so an upgrade used to present it as never reviewed and disabled. Now the review and enablement carry to the new build when its capabilities are unchanged. Changed capabilities show `capabilities-changed` and wait for review, and a revoked trust never carries ([#6303](https://github.com/codewhale-hq/Codewhale/issues/6303)). - "Allow for this conversation" records a grant for that tool and argument class instead of switching the whole thread to Full Access, so the call you just approved is no longer failed by a Permissions change. An approval also survives a Permissions change that only widens what is allowed, grants end when a thread is archived or deleted, and `web.run` open grants are scoped by host. Full Access covers MCP tools that declare themselves destructive in every host, including `codewhale exec` ([#3866](https://github.com/codewhale-hq/Codewhale/issues/3866)). - `web.run` retries a refused page once with a browser user agent, and one site's failure no longer fails the whole call or drops its search results. - Web search no longer stops when DuckDuckGo cannot be reached. After a connection error, timeout or non-2xx answer, the search tries Bing before giving up, and the result says it used Bing. A DuckDuckGo that hangs no longer uses up the whole time budget: when Bing may follow, DuckDuckGo gets 60% of it and Bing the rest. This also covers the DuckDuckGo step after a configured API provider. A custom `search_base_url` still has no public fallback and keeps the full budget. Bing sees the query only after DuckDuckGo has failed or returned nothing it could read ([#6746](https://github.com/codewhale-hq/Codewhale/issues/6746)). - Hooks treat `bash`, `Bash` and `exec_shell` as one tool in `tool_name` conditions, so the documented example fires. - macOS no longer reports Codewhale's ordinary heap as GPU (IOAccelerator) memory. - Code highlighting uses less memory, and long transcripts, the pager and the session picker do less work on the event loop; session previews load in the background ([#6014](https://github.com/codewhale-hq/Codewhale/issues/6014)). - The composer's send cue follows the draft, not a paste in progress ([#6397](https://github.com/codewhale-hq/Codewhale/issues/6397)). - Voice status is localized, ASCII-mode markers are distinct, and the cursor honours `NO_COLOR` ([#5846](https://github.com/codewhale-hq/Codewhale/issues/5846)). - `/cache`, `/stash`, `/config`, session prune, `metrics --since` and the `lane start`/`lane stop --json` flags handle their edge cases. - Plain `codewhale exec` (no `--auto`) runs one Engine turn with the same system prompt as every other run, so `--json` no longer changes the model's instructions. It offers no tools unless a flag grants them (`--auto`, `--yolo`, `--allowed-tools`, or resuming a session): `--max-turns`, `--disallowed-tools`, `--append-system-prompt`, `--sandbox` and `--output-format stream-json` no longer turn a chat call into a tool-using agent, and tool-only flags passed without a grant print a warning. A reply cut off at the provider's output limit is continued instead of failing the run, for at most 8 model steps unless `--max-turns` sets another limit. Breaking for scripts: the `--json` one-shot receipt no longer has `stop_reason`, adds the agent receipt's fields (`prompt`, `tools`, `outcomes`, `status`, `termination_reason`, `error_category`), and leaves out `usage` when the turn never settled ([#6510](https://github.com/codewhale-hq/Codewhale/issues/6510)). - `codewhale review` of a plain diff uses the same review prompt as `review --pr` and prints the structured review as Markdown, or the model's prose when it ignores the JSON format ([#6510](https://github.com/codewhale-hq/Codewhale/issues/6510)). - A recursive `rlm_query` that runs out of rounds returns its last answer marked `[rlm_query incomplete: …]` instead of an empty string, its model calls appear in the parent turn's record, and its history is no longer trimmed ([#6511](https://github.com/codewhale-hq/Codewhale/issues/6511)). - Starting without a network connection no longer drops images you attach to a model that accepts them. The offline model list lagged behind providers and listed Claude and others as text-only; it can now only say a model takes images, never that it refuses them, and a provider that does refuse gets one resend without the image and a message saying so ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)). - Model prices that a flat rate would get wrong now show as unknown after the model list refreshes online, as they already did offline: DeepSeek (priced by time of day, or from Codewhale's reviewed table on hosted providers), Grok and MiniMax M3 (rates rise on long prompts), Xiaomi MiMo (pay-as-you-go and Token Plan keys look the same), GLM-5.3 and the Alibaba Model Studio plans (quota or credits, not per-token) and StepFun. DeepSeek's output limit stays at its published 384K instead of the refreshed 393,216, and the reasoning controls Codewhale records for Grok, MiniMax, Qwen 3.8 Max, Muse Spark and Step 3.5 (defaults, always-on thinking, extra effort tiers) survive the refresh. Committed corrections now fail at load if their provider or model is missing from the bundled seed; partial live refreshes may still omit those rows ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)). - The offline model list is now generated from Models.dev instead of edited by hand, so a fresh install without network sees the same limits, image support and reasoning controls as an online one. Claude, GPT-5.5, Kimi and several OpenRouter models now show image input offline, and a model whose catalog row offers an on/off switch next to its effort tiers keeps Off in `/effort` and Ctrl+T instead of rounding it up ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396), [#6612](https://github.com/codewhale-hq/Codewhale/pull/6612)). - Cost estimates for GPT-5.6 and GPT-5.6 Sol use OpenAI's current rates of $4 input, $0.40 cached input and $20 output per million tokens. They were still at the older $5, $0.50 and $30 ([#6396](https://github.com/codewhale-hq/Codewhale/issues/6396)). - `codewhale integrations dsh` now reads current DeepSeek Harness prerelease versions such as `0.1.7-alpha.2` as semver. They were reported as `offline` and refused; they now show as `stale-version` (launchable once connected, clearly unverified). Only `0.1.0-rc.6` is still the verified version, and text that is not a version is still `offline`. - Rule and chain-segment source labels in the project instructions the model receives (`` and the scoped-instructions comments) are repo-relative instead of absolute. Moving or recasing a checkout no longer changes the pinned system prompt prefix or adds a spurious context update ([#6739](https://github.com/codewhale-hq/Codewhale/pull/6739), thanks @asto18089). ### Security - On Windows, a broad Node kill (`Stop-Process -Name node`, `Get-Process node | Stop-Process`, `taskkill /IM node.exe`, and wrapped, aliased or nested-shell forms) is held by a built-in safety floor: it is refused in Full Access, Auto-Review and Never, and asks in other modes. With the npm launcher such a command ended this and every other npm-launched Codewhale session without cleanup. Stopping a server by PID or port still works, and the Windows installer and archives have no Node launcher ([#6827](https://github.com/codewhale-hq/Codewhale/issues/6827), thanks @jayanthvee). - `code_execution` and `js_execution` now start their Python and Node interpreters through the same permission-aware launcher as other commands, so the session's execution policy applies to them. Before, an approved call ran the interpreter directly, and its working directory was the only boundary ([#6820](https://github.com/codewhale-hq/Codewhale/pull/6820), thanks @Guan0923). - A saved task without an `auto_approve` field is no longer treated as auto-approved. Updates accept HTTPS URLs only from the release-host allow-list, and the npm release-asset check bounds every request. - Workspace profile and skill discovery, pasted-image and screenshot writes, configuration redaction receipts and legacy configuration migration reject linked paths where they could redirect access outside their intended roots. Additional `.codewhale` writers use the existing confined filesystem helpers. The VS Code file opener checks the file's real path, and PowerShell temporary scripts receive unpredictable names and owner-only permissions. - Update development tooling to Undici 7.29.1 or newer for [GHSA-w293-vg96-wgc3](https://github.com/advisories/GHSA-w293-vg96-wgc3), brace-expansion 1.1.21/5.0.12 for [GHSA-q2hr-2g5m-vwhr](https://github.com/advisories/GHSA-q2hr-2g5m-vwhr), and the VS Code extension's markdown-it to 14.3.2 for [GHSA-253c-mchw-3w2r](https://github.com/advisories/GHSA-253c-mchw-3w2r). - Harden local runtime browser sessions, fleet SSH trust, agent continuation ownership, task gate approval, plugin tool registration, bridge action tokens, and release metadata credential forwarding. Browser sessions recover across reloads and new tabs, and stream tickets retry after transient failures. Fleet SSH known-host checks support OpenSSH 7.x and later. SSH host configs using `host_key_fingerprint` must migrate to `known_hosts` with verified host keys; the unsupported fingerprint field is now refused when an SSH worker starts, before any connection is made, instead of being silently ignored. - Harden workspace instruction, note, and anchor file access with shared no-follow reads and writes. Compaction loads pinned anchors only from trusted workspaces. Validate registry skill names before selecting cache paths. - Tighten approval, execution and endpoint boundaries. Computer control consent and script calls need an exact decision a person gave on that call's own approval card. Automatic Git status and review reads go through the sanitized review command and stay pinned to the checked Git executable. Config backups, config dumps, MCP listings and notification payloads share one sensitive-key vocabulary; structured exports now also redact keys ending in `key`. Python a child model writes during a recursive `rlm` call is admitted round by round like an inline `repl` block, and Python kernels are discarded when permissions narrow. Gate commands and the cargo test runner start inside the session's shell sandbox. Mutable session artifacts are written and read through pinned session-relative paths. The stdio bridge's Runtime child chooses and reports its own loopback port. - Chat bridges (Feishu, Telegram, WeCom, Weixin) accept an approval decision only from the person who started that turn, for the Runtime's current pending approval. After upgrading, approvals for turns that were already running are decided from the TUI, and WeCom `/allow` no longer takes `remember`. - More file and network paths are confined. A task or automation created by a session without full shell access no longer inherits the host's shell default. The commit planner, oversized-paste backup and project harness notes do not read or write through links that leave the workspace. On Unix, audit and approval logs are created owner-only and are not opened through a link; Windows is unchanged. Lane ids must be plain names. A session file is refused when it records a different session id than its name. The updater does not follow a redirect from HTTPS to plain HTTP and stops reading a response larger than 512 MB. - Nothing is written through a `.codewhale` that is a link. The workflow run journal no longer creates `.codewhale/` or its ledger when it is opened, only when the first record is written, and reads and appends through the same confined helpers as other state. The sub-agent coordination lock refuses a linked `.codewhale` or `state` directory before it creates anything. - On Unix, the runtime log is created owner-only and is not opened through a link; an existing log from an earlier version is tightened. The `.reconcile.lock` and `current.json.lock` lock files are created owner-only too. - Inline ```` ```repl ```` blocks in a reply now follow the same rules as the `code_execution` tool. They never run in Plan mode or when `code_execution` is not on the turn's tool surface, and they are admitted like a `code_execution` call with the same code: before-tool hooks, disallowed-tool rules, Auto-Review (including its reviewer) and repository law all apply, then the same approval under the session's permission posture (a blocked, denied or unanswerable call skips them with a visible note). Only a fence that opens its own line counts, here and in the `rlm` tool's child rounds, so a reply that mentions a fence in prose runs nothing. An `rlm(...)` call from a fence gets a one-shot child answer rather than a child that runs its own code. The docs no longer describe the REPL kernel as sandboxed. - `codewhale serve --mcp` now exposes only read-only tools by default (`file_read`, `search`). Tools that write files or run commands are neither listed nor run unless the operator sets `require_approval = false` in the MCP server config; a client's own `approved` flag no longer counts as approval. At startup the server names on stderr each configured tool it withholds and the setting that allows it. - A `Bash` entry in the disallowed tools now also blocks `start_mcp_server` and `start_registry_mcp_server`, which launch local processes. - An MCP tool call whose connection closes before it answers is no longer sent again on a new connection, since the server may already have run it. The same holds for a server error reply that mentions an expired or invalid session. The call reports an unknown outcome and the next call reconnects. Only a call the HTTP transport turned away for a stale session, before the server handled it, is still retried once. - Durable tasks and scheduled automations created by the agent no longer carry more authority than the session that created them: requested `auto_approve`, `trust_mode` and `allow_shell` are capped at what that session holds, a task's workspace and an automation's directories must be reachable from the session, and a task's turn runs under the posture pinned when it was created instead of re-deriving one from the legacy bit or a legacy mode alias. - The approval card for creating a task or creating/updating an automation now lists the requested trust mode, shell, auto-approve, mode and workspace as labeled lines. - "Approve for session" on a shell command now covers only a simple, known command family (`git status` still covers `git status -s`). Compound, wrapper, interpreter, unrecognised and option-configured commands are granted as the exact command, and interact/wait calls on a running shell as the exact call. - Workflow plan approval flags shell, network and file-write capability for the `Bash`, `Web` and `File` tool families regardless of letter case. - An agent session can no longer update, resume or run an automation whose stored `auto_approve`, `trust_mode` or `allow_shell` is more than the session holds, unless the same update lowers those fields. - The approval summary every Runtime client receives for task and automation create/update now names the requested trust mode, shell, auto-approve, mode and workspace, from the same fields the TUI card shows. - A shell session grant keeps its command family only when every option is a known value-free option such as `--release` or `--porcelain`; other options, in any spelling, grant the exact command. Families whose arguments are what runs or is installed (`go run`, `deno run`, `cargo run`, `make`, `git bisect`, `git submodule`, package installs) grant the exact command. - Workflow plan approval recognises tool names in any quote style and with a pattern suffix (`'Web'`, `` `File` ``, `Web(*)`), and flags `rlm`, Git and GitHub, computer and browser control, and task/automation tools with the capabilities they carry. - Model-run code no longer inherits provider credentials or other secrets from Codewhale's environment. Python `code_execution` (and every other Python runner), `gate_run` task gates, custom and completion verifier gates, persistent `terminal` sessions, and `run_tests` now start from the same scrubbed child environment as `exec_shell`; variables a gate declares are still passed through. `gate_run` also runs `/bin/sh -c` instead of a login shell, so profile files cannot re-export what was removed. - A `workflow` start with `verify: true` now needs approval even for a read-only plan, because the completion gates run workspace build and test scripts. - Git commands no longer hand provider credentials to programs that a workspace's git config can start (`core.fsmonitor`, hooks, filters) when they run through Codewhale's shared git helper: those start from the scrubbed environment plus the ssh agent, global config location and author identity. Sub-agent worktree provisioning and delivery do not use it yet. The read-only `git_status`, `git_diff`, history and `verify` tools also disable the workspace's fsmonitor, hooks and clean/process filters. - Language servers started for post-edit diagnostics, and every Python and Node command constructor, start from the scrubbed child environment. - Proxy URLs passed to model-run children (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `FTP_PROXY`, `CARGO_HTTP_PROXY`) keep their host and port but lose any `user:password@` part. - Behaviour change: the scrubbed child environment now keeps non-secret build configuration — `CARGO_*` (except registry and token-like keys), `RUSTFLAGS`, `RUST_LOG`, `RUST_BACKTRACE`, `VIRTUAL_ENV`, `JAVA_HOME`, Go paths, `NVM_*`/`NODE_OPTIONS` and CA-bundle variables — so `run_tests` and gates keep the user's target dir, job limit and toolchain. Connection strings such as `DATABASE_URL` are still dropped; set them in the project's own config, or wrap the command in a script that sets them, when a build needs them. - Deny rules in the permission settings now hold for these ways of hiding a command word until the shell runs it: a variable (`$v`), a substitution, a glob or brace list, escaped ANSI-C quoting, or a shell reading its script from a pipe, here-string or process substitution. Rules in a separate `execpolicy.toml` file are applied when the command runs, so there such a command is refused at run time rather than before an approval prompt. While any deny rule is configured in the permission settings, such a command is refused instead of being checked against text the shell will rewrite (an approval-always policy asks instead). This also applies to common forms such as `source "$HOME/.cargo/env"`, `eval "$(pyenv init -)"` and `$PYTHON -m pytest`; name the command directly to run it. The same holds when the text does not parse cleanly (an unterminated quote, substitution or heredoc, a `case` inside `$( … )`) or when a parse budget runs out. Commands after `if`, `then`, `while`, `do`, `!` and similar words, `function f { … }` bodies, and `find -exec` payloads are now checked like any other command. - Wrapper commands are unwrapped by their real option grammar, so `chroot DIR cmd`, `sudo --user NAME cmd` and `timeout -s SIG N cmd` expose `cmd` (and any `-c` payload) to deny rules. Options missing from a wrapper's table are read both with and without a value, BSD and macOS options are covered (`env -P`, `xargs -J`, `chroot -u`), and more wrappers are recognized (`caffeinate`, `arch`, `sandbox-exec`, `nsenter`, `unshare`, `runuser`, `flock`, `watch`, `wsl`, `noglob`, `nocorrect`), including `.exe` spellings. Code passed as a string to `trap`, `su -c`, `flock -c`, `script -c`, `watch`, `cmd /c` and PowerShell `-Command` is checked as a command line. - `(( … ))` arithmetic no longer reads `<<` as a heredoc that hides the lines after it, and an `xargs` or `find -exec` replacement string used as the command or as shell code (`xargs -I{} sh -c {}`) counts as known only at run time. - `task_shell_start` and task gate commands are now checked against shell deny and ask rules, like any other shell command. - An "approve for session" grant for a shell command covers only flag variants of that command as written; a command with options before the subcommand, a chain, or nested code matches only an identical repeat. - The read-only shell surface for sub-agents rejects a word that starts with an unquoted `*`, whose matches could be read as options; quote the pattern or give it a path prefix (`src/*.rs`). - A trusted or allow prefix such as `git status` no longer covers options placed before the subcommand (`git -c key=value status`, `git --exec-path=… status`), nor a command that runs nested code or whose command word is resolved at run time. Such commands ask instead. Typed deny rules also match a path-qualified command word (`/bin/rm`). - Commands containing parentheses are no longer auto-approved as parallel read-only commands, since some shells treat them as glob qualifiers or command substitution. - Sub-agent worktrees stay under the per-repo `.codewhale-worktrees//` root: an absolute `worktree_path` is now held to the same containment as a relative one, with symlinks resolved before the check. Any start that asks for a worktree keeps the approval card, even for a read-only role. A `worktree_base` starting with `-` is refused, and `git worktree add` now receives its path and base after `--`. - Fleet and reasoning-router names must be plain file names (optionally `origin/name`); a name with path separators or `..` is refused before any file is looked up, through one shared check in the workflow crate. - `pandoc_convert` and `image_ocr` apply the same read deny-list and credential-store checks as `read`, through one shared helper, and pandoc always runs with `--sandbox`. This needs pandoc 2.15 or newer; an older pandoc gets an upgrade message instead of a conversion. - Computer Use: screenshot and zoom output paths must be `.png`/`.jpg`/`.jpeg` files inside the recordings directory, and zoom always crops the last captured raster instead of a caller-named source file. - Skill registry sync refuses an index key that is not a single path-safe name before it is used as a cache directory, the same check an installed skill name already gets. - A project's `.codewhale/config.toml` can no longer set `notes_path`; it is ignored with the other user-only keys. The `note` tool and `/note` refuse a notes file that is a symlink or whose directory resolves outside the workspace, and a note is flushed to disk before the tool reports success. - Diffs and shows that read repository content (`codewhale review`, the `git_diff`/`git_show` tools, verification, delivery, task attempt records, `@diff` and the runtime API diff routes) share one flag set: no external diff, no textconv, and submodules compared by commit only, so a submodule's configured filters and diff drivers never run. Reads of the working tree (`git_diff`, `git_show`, `git_blame`, commit planning, verification, task attempt records, `@diff`/`@git`) also run through the hardened review command, so the repository's clean filters do not run either. `git_blame` and read-only shell `git blame` skip textconv, and read-only shell `git` reads neutralize the repository's clean filters. - `git_fetch` refuses refspecs that would write a local branch or tag: a `src:dst` destination must be under `refs/remotes/`, and the two-word `tag ` form is rejected. - Opening a URL on Windows goes through the URL protocol handler instead of `cmd /C start`, so characters in the URL are not interpreted by the shell. - Skill downloads and the skills registry index are read through a streaming size cap shared with the MCP HTTP transport, instead of buffering the whole body before checking its size. - Durable runtime thread, turn and item ids carry a full UUID instead of 32 random bits, so two records can no longer collide and overwrite each other. ### Removed - Flags, settings and tool parameters that did nothing are gone ([#6516](https://github.com/codewhale-hq/Codewhale/issues/6516)). `--output-mode` is hidden. It is still accepted, prints a warning, and is ignored. - The dispatcher no longer exports `DEEPSEEK_*` copies of its `CODEWHALE_*` variables. A `DEEPSEEK_*` variable you set yourself is still read. - `lane start` and `workflow run --runtime vm|ci` are rejected before a lane is created. Older lane records for those runtimes still load. - The control socket's `relaunch` verb is removed; it always returned an error. - The `speech` tool drops `stream`. `stream=true` used to fail; it is now ignored, a complete audio file is written, and the result no longer carries `"stream": false`. The `finance` tool drops `market`, and a call that still passes it has it ignored. - `[context].enabled`, the seam-manager keys and `tui.terminal_probe_timeout_ms` no longer load; old configs that carry them still start. The `[workshop]` docs now describe bounded spillover instead of a synthesis sub-agent. - About 2,650 lines of workflow code that nothing ran are deleted: the replay executor, the review-repair loop and experimental search. The `replay_diverged` status they produced goes with them. The isolated Runtime Chat prompt and the legacy YOLO alias list each have one owner now ([#6517](https://github.com/codewhale-hq/Codewhale/issues/6517)). ### Experience - Typing a first message with no model connected leaves a line in the transcript that says the message was not sent and opens the provider picker. - First run picks a chat-capable Ollama model instead of the alphabetically first tag, and says plainly when no model is available yet. - `codewhale doctor` leads and ends with one verdict and the next step, and gives the update command for how you actually installed Codewhale. Command-line usage and errors say `codewhale`. - The approval card leads with a plain summary of the action, such as "Run `cargo test`", and shows workspace-relative paths. The footer labels its values. - `/status` warns when the session's pinned model is no longer in its provider's live model list ([#6035](https://github.com/codewhale-hq/Codewhale/issues/6035)). - Error messages give one true sentence and one next step. The TUI's English copy says agent, Fleet, Permissions and Work consistently, help lists one summary per row, provider rows without a key say "needs key", `/setup` says what it sets up, and the pet tank rests when it is offline. - ACP clients can see the Permissions setting the server started with, including Full Access and how to turn it on, but cannot select it ([#6310](https://github.com/codewhale-hq/Codewhale/issues/6310)). - `GET /v1/commands` tells clients each command's argument shape, so they do not re-derive composer behaviour from the usage string ([#6230](https://github.com/codewhale-hq/Codewhale/issues/6230)). ### Fleet and agents - `codewhale fleet run --check` runs every validation a real run would and stops there: nothing is created, launched or spent. - A queued agent says why it is waiting, for example when launches are throttled after provider rate limits, and when it stops waiting ([#6277](https://github.com/codewhale-hq/Codewhale/issues/6277)). - Read-only agents can run chained inspection commands (a leading `cd`, `&&`, `;`, `echo` separators, `2>/dev/null`), and a refused command now names the rule it broke and what to do instead. Durable Fleet workers accept the same read-only commands as in-session agents. An agent's time budget starts when it launches, and a queued agent that never gets a slot says it never started ([#6015](https://github.com/codewhale-hq/Codewhale/issues/6015)). - Stopping an agent that writes files keeps and names the work it had changed, as a budget stop already did ([#5529](https://github.com/codewhale-hq/Codewhale/issues/5529)). - `workflow(fleet:)` runs Fleets saved from the Fleet UI, and finds workspace Fleets under `.codewhale/fleets`. - The runtime API can stop a delegated agent run from the desktop. - A finished agent's answer is no longer cut off. Its row and its completion notification show the first sentence of its result instead of a `## Summary` heading or its last tool, and opening the agent shows the whole result, or the full reason it stopped, even when no transcript was captured. Each agent also has one name: a workflow task's label or its dispatch name appears on the rows, the notification and the runtime API alike, never its internal id ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)). - The mobile page shows the thread's agents: a strip naming each one, its state, and what it is doing or what it found, rebuilt when the page reconnects. Sub-agent prompt caching now counts toward the session, including cache-write-only reports. PRICE and `/cache` show the parent, agents and combined hit rates, each labelled and weighted by all input tokens, including cache writes, and the footer `cache N%` still means this conversation's own requests ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)). - The dock's GIT, FILES and NOTES views are real. GIT shows the branch and where it stands against its upstream, the changes (with their paths one Enter away), linked worktrees and the last five commits, and it keeps updating during a turn while it is open. It says "not a git repository" only when that is true, reports failed status probes in the view and composer instead of claiming a clean tree, counts every unmerged path as a conflict, and only says there are more changed paths when the list is capped. FILES lists the files this session edited, including writes without diff receipts, and the files it read, with every unique path retained beyond the activity summary's twelve-path preview. FILES and its badge refresh from the current session even before TASKS opens. Edits with receipts show their size and open their diff. NOTES lists your `/note` notes. The git badge, the Git view and the model's git line now share one `git status --porcelain=v2` call, so there are fewer git processes than before ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)). - Background work tells you when it ends, even between refreshes. Batched shell notices cover explicitly backgrounded or detached commands; foreground results and old completions from before this TUI session stay quiet. Switching sessions does not repeat a completion notice. Batched notices count completed, failed and stopped work separately; shell commands, task prompts and errors stay in the app, away from lock-screen notifications. A running dev server no longer holds the notice back. Failed, killed and timed-out shells retain their outcomes, and the last eight finished shells stay listed per session. Finished tasks no longer look live or reopen the dock. Background labels follow the UI language, long agent previews keep their full-result pointer, and the quiet indicator uses the engine's clock and limit without marking an active tool as quiet ([#6565](https://github.com/codewhale-hq/Codewhale/issues/6565)). ### Plugins - Codewhale no longer appends plugin recommendations to your messages to the model. Suggestions appear in one place, follow one switch and one budget, and never advertise built-in plugins, generic words or plugins for another operating system. - `/plugin dismissals` lists the plugins suggestions skip, and `/plugin dismissals reset []` brings them back. - Tools from reviewed plugins that declare themselves read-only no longer ask for approval on every call. - The bundled Computer Use plugin is 0.12.0, the published upstream release `8435692` ([#6303](https://github.com/codewhale-hq/Codewhale/issues/6303), [#5856](https://github.com/codewhale-hq/Codewhale/issues/5856)). On macOS the agent uses its own pointer and never drives your cursor. `app_script` refuses shell escapes. Clicks on irreversible actions such as pay, send or delete need confirmation. Consent decisions cannot ride inside `run_actions` or trajectory replay, and trajectories redact secure fields. Also new: a shared-computer control lease that pauses agent input while a person drives, and a browser attach mode for a shared Chromium. The vendored README no longer claims delegated agents share the Computer Use session; they never receive its tools. - The bundled first-party catalog pins marketplace revision `ae3dd2255a9a266365c6125a084f511eb26bc04d`. It lists Computer Use 0.12.0 and adds Codewhale for Chrome (Chromewhale) 0.3.0 as a developer preview: you load its Chrome extension unpacked, and like every catalog plugin it installs disabled and untrusted until you review it. ### Release reliability - Upload the complete release into a private draft, verify every asset's size and SHA-256 digest, then publish. An interrupted retry cannot reuse stale same-size bytes. CNB and GHCR version tags follow canonical publication. - Ubuntu Lighthouse bootstrap requires trusted SSH source CIDRs or an explicit public-SSH opt-in before changing the host; malformed IPv6 and broad default networks are refused. ### CI - State-touching command and session tests seal `HOME`, `USERPROFILE` and `CODEWHALE_HOME` onto temporary directories. Unsealed session, snapshot, artifact, composer-history, audit and built-in-plugin storage resolves into an isolated test root; unrelated worker threads cannot borrow another test's home seal. A child-process sentinel checks that known command-dispatch and session cases leave their ambient home unchanged. - Fork pull requests stay under the macOS runner limit and the Actions cache stays under its cap. - Release candidates and releases share one parity gate, and a release tag without a release-candidate receipt is refused. - Budget ratchets block same-repository pull requests unless the pull request updates the budget with a receipt. - A CodeQL advanced-setup workflow is ready for when the repository switches from default setup. ### Contributors - **[@AdityaVG13](https://github.com/AdityaVG13)** — supplied the discovery-cache priority correction adapted from [#6393](https://github.com/codewhale-hq/Codewhale/pull/6393), keeping highest-ranked tools through cache overflow. Its broader echo and fork-inheritance draft remains open. - **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — reported indefinite questions cancelled by the TUI watchdog and supplied the timer evidence ([#6872](https://github.com/codewhale-hq/Codewhale/issues/6872)). - **[@hodeswildsmith455-boop](https://github.com/hodeswildsmith455-boop)** — added OrcaRouter account sign-in with PKCE and its live chat catalog ([#6867](https://github.com/codewhale-hq/Codewhale/pull/6867)). - **[@LIghtJUNction](https://github.com/LIghtJUNction)** — added reviewed plugin-provided AI routes with host-owned OAuth PKCE credentials and request-time authority checks ([#6805](https://github.com/codewhale-hq/Codewhale/pull/6805)). Contributors and issue reporters are credited below, including @cenab's provider report. - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@aiapienthusiast](https://github.com/aiapienthusiast)** — added Cheaper Inference to the bundled provider catalog ([#6761](https://github.com/codewhale-hq/Codewhale/pull/6761)). - **[@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)). - **[@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)). Translated the session-only note after model switches across the complete TUI locale packs ([#6875](https://github.com/codewhale-hq/Codewhale/pull/6875)). Translated the route-save receipts ([#6884](https://github.com/codewhale-hq/Codewhale/pull/6884)) and `/workspace` replies ([#6885](https://github.com/codewhale-hq/Codewhale/pull/6885)), brought the Operate descriptions in fourteen packs up to date ([#6886](https://github.com/codewhale-hq/Codewhale/pull/6886)), restored lost accents in pt-BR, es-419 and ca ([#6888](https://github.com/codewhale-hq/Codewhale/pull/6888)), let `semantic_truncate` cut between Han and kana ([#6887](https://github.com/codewhale-hq/Codewhale/pull/6887)), and removed the unused session-only route-save choice ([#6882](https://github.com/codewhale-hq/Codewhale/pull/6882)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). ## [0.10.0] - 2026-09-22 Codewhale v0.10.0 brings a redesigned terminal workbench, clearer settings, and more reliable session and runtime behavior. It supersedes the unpublished v0.9.14 candidate. ### Contributors - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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). - **[@asto18089](https://github.com/asto18089)** — co-authored the rate-limit-adaptive launch scheduling work ([#6055](https://github.com/codewhale-hq/Codewhale/pull/6055)). - **[@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). - **[@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). - **[@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). - **[@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)). - **[@yetuge](https://github.com/yetuge)** — dropped the retired `token_budget` field from the subagent documentation ([#6335](https://github.com/codewhale-hq/Codewhale/pull/6335)). - **[@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. ### Security - Children never inherit desktop or computer-control tools. Desktop control is the most machine-wide capability in the catalog, and a verifier child inherited it by default: on 2026-09-17 one opened the host Terminal and typed a blocked shell command into the user's live session. A family classifier now removes those tools when a child's registry is built, so they are neither eager nor searchable, and `execute_full` refuses the family at dispatch for every child role — visibility is a grant, and hiding is not the only defense (#6296). - Runtimes can be held to an organization's plugin allowlist. A managed policy document (`managed-policy.json` beside `state.json`, or `CODEWHALE_MANAGED_POLICY_PATH`) lists the plugin ids a Runtime may run, with an `allow_unlisted` flag and a schema version checked exactly like `PluginStateFile`. Enforcement sits inside `apply_state`, so a plugin enabled before the policy arrived — or hand-edited to `enabled: true` — never comes back enabled, and `enable()` re-reads the document so a policy landing after discovery refuses with a reason that names it. A malformed document fails closed rather than degrading to unenforced. With no policy present, behaviour is bit-for-bit what it was. This is the enforcement primitive only; the authority that decides the allowlist is still local, so it binds a cooperating Runtime, not a hostile one. - Approving an `apply_patch` "for the session" is now scoped to the file you approved. The grouping key that scopes a session grant was built by a second, weaker patch parser that read only `+++ b/` headers and the `replace` array: it saw no target at all for the documented `apply_patch{path, patch}` override, for `--no-prefix` diffs, or for delete-only diffs, and collapsed every one of them to a single shared key. One approval therefore pre-approved every later patch of that shape, to any file, with no card and no notice. The key now comes from the same resolver the executor and the permission path already use, and an input that cannot be resolved gets its own key rather than a shared one (#6247). ### Added - The statusline's performance readings survive compact mode and are separately configurable. Measured TTFT and average output rate are kept when space allows, shedding help text and secondary counts first; the existing metrics and statusline settings gain individual toggles with a migration that preserves a legacy single setting, and the picker takes mouse selection and scrolling. - Tasks can be given their own run name. `NewTaskRequest`, `TaskRecord` and `TaskSummary` carry an optional `name`, stored as given and omitted when absent, so queues still fall back to prompt-derived titles; a run started by an automation inherits the automation's name. The `tasks` tool's schema extends backward-compatibly and legacy records decode through serde defaults (APPS-153). - The offline catalog seeds Xiaomi's MiMo 2.6 family — `xiaomi/mimo-v2.6-pro` and `xiaomi/mimo-v2.6-flash` — so a first boot without network no longer shows the 2.5 generation. `DEFAULT_XIAOMI_MIMO_MODEL` stays on `mimo-v2.5-pro`, and the rows carry no price because the published rates cover only `sk-` keys. - Native memory is a reviewed store, not a model-writable file. `codewhale-memory` backs the TUI with SQLite as the authority instead of Markdown, and the `remember` tool now only *proposes* candidates — a model can no longer write an active memory. `/memory` and the Runtime API commit through `remember_reviewed`, and a Context Lens surface (`/v1/memory/lens`, `/lens/actions`, `/events`) shows what was kept and why. - Code mode (Experimental, default off): `execute_tools` runs a JavaScript program against a QuickJS host surface so a model can express several tool calls as one program. Nested calls must be read-only and auto-approved; the tool is hidden in Plan and refused under worker authority. Enable with `[features] code_mode`. - Two new built-in providers: **ZenMux** (`ZENMUX_API_KEY`) and **CSDN 星图** (`CSDN_API_KEY`, Coding Plan quota billing), each with its own key slot, bootstrap model and catalog rows. - The Runtime API gained the surface a native client actually needs: jobs with stdin, kill and cursor reads; context, secrets, git, diagnostics, targets, LSP and voice routes; `GET /v1/commands` for the slash-command catalog; `GET /v1/workspace/instructions`; account-wide `GET /v1/approvals`; plan and to-do inventory; `/v1/settings/schema`, with `POST /v1/config` now persisting every declared `settings.toml` key rather than a curated allowlist; PTY byte replay, resize and exit; and tool images as session artifacts. - Codewhale holds the host's idle-sleep assertion while a turn is in flight (`caffeinate -i` on macOS, `systemd-inhibit` on Linux), so an unattended machine no longer sleeps mid-run. You will see one child process per turn. - Skills are reachable in one call. The pinned `## Skills` index told the model to call `load_skill`, but the tool was deferred behind `tool_search`, so it was never in the tool array that instruction was printed beside: using a skill cost a discovery hop, a `name="list"` round trip, and a `change:tool_surface` re-pin of the whole cached prefix. `load_skill` is now eager for the parent and for children — +244B of pinned catalog, measured, against a re-prefill avoided every time a skill is used — and it takes a `query` that searches names and descriptions, so a truncated index no longer forces pulling the whole catalogue to find one skill. The usage line now says to load the matching skill by name before starting the work. - A fast lane the router cannot serve now says so. `provider_router_candidates` answers `cheap: None` for any pair its tables do not know, and a `Faster`/`Auto` child on such a pair used to run at the parent's model and price with no receipt and no way to tell "single tier by design" from misconfiguration. The fallback stays — the router must not invent a model — but the spawn receipt now carries a `fallback_note` naming the unserved lane, the same field the pinned-provider fallback already uses. `Inherit` and served lanes stay quiet: this reports a fallback, it does not nag. - The runtime API tells a replayed submission apart from a new admission: `POST /v1/threads/{id}/turns` answers `200` with `idempotent_replay: true` when the operation key was already used, and `201` for a fresh admission, so a client that retries after a dropped response can no longer create a second turn. The flag is absent on a fresh admission, so responses existing clients already parse are unchanged (#76). - Event streams resume where they left off: journal frames carry their durable `seq` as the SSE event `id:`, `Last-Event-ID` is honoured as the cursor when no explicit `since_seq` is asked for, and `RuntimeCapabilities` advertises `event_stream_resume` so a client can gate its reconnect controls on the capability instead of discovering it from a missing id (#76). - TTFT and average output rate stay visible in the compact working footer when space allows. `/statusline` now controls them separately; existing `session_metrics` settings still work. - StepFun’s current coding catalog includes Step 5 Preview, Step 3.7 Flash, Step 3.5 Flash and its 2603 version, with published reasoning controls and PAYG rates. Existing Step Plan routing remains subscription-based. - `read` responses now always report the file's byte size, line count, and whether output was truncated, and truncation footers name the total size alongside the continuation offset — so paging through a large file is deliberate instead of a surprise (#6283). - File edits are parse-gated before the write lands: Rust goes through `syn::parse_file` for a grammar-exact `line:column`, and `.toml` / `.json` through the parsers already vendored. An edit is refused only when the file parsed *before* and would not parse *after* — repairing an already-broken file is the commonest reason to edit source at all, so pre-existing breakage and new files fail open. The check precedes the write, so a rejection leaves the file untouched and `apply_patch` cannot half-apply (#6204, #6206, #6151). - Rust files that were already `rustfmt`-clean are re-normalized after an edit, so the next patch's anchors still match. Hand-formatted files are never rewritten, and every failure path skips and lets the edit land (#6205, #6151). - Native clients can finish provider setup without dropping to the CLI: `DELETE /v1/providers/{id}/key` clears a Codewhale-owned credential through the same shared owner as `codewhale auth clear`, and `GET /v1/providers` now carries `credentialSource` / `credentialWritable` (plus a reason) so a client disables its control with a truthful explanation instead of letting a write fail late. A credential Codewhale does not own — a literal key in a config file, or an active external consent — refuses both verbs with `409` rather than appearing to succeed against a source that still wins at request time (#6179). - The interactive approval card can be bounded: `[approval] timeout_seconds` resolves an unanswered card to **deny** when the window elapses — the same fail-closed decision the external approval path takes — and the transcript says the bound denied the call, not the operator. Omitted or `0` keeps today's unbounded wait, so nothing changes unless you opt in (#6101). - Transcript drag selection copies Markdown source by default: every cell the selection touches serializes through the same canonical path `Ctrl-Y` and `/copy` use, joined with blank lines, and the toast names the copied cell count. A selection that does not cover every touched cell end to end copies the exact rendered fragment instead: rounding a pinpoint selection out to whole cells meant copying an entire model message (#6228). `tui.selection_copy_markdown = false` keeps the rendered-text payload (#6156). - The Runtime API serves the workspace files a native client browses and edits: `GET /v1/workspace/files` lists one directory, `GET /v1/workspace/files/read` returns a bounded byte window with a whole-file SHA-256 revision, and `PUT /v1/workspace/files` writes atomically through the confined opener with revision-checked overwrites (409 on drift). `.git` is never served and symlinks are never followed. A saved session's oversized tool outputs are served as artifacts at `GET /v1/sessions/{id}/artifacts` and `GET /v1/sessions/{id}/artifacts/{artifact_id}`. (#6163) - A session that ended mid-turn is no longer invisible to the model. The newest workspace-scoped session still holding a crash-recovery checkpoint is surfaced as a one-line `## Prior Session` notice in the session-pinned prompt prefix — metadata reads only, excluding the live session and any session this process instance created. Clean sessions get no block, so their prefix bytes are unchanged. Two bounded read-only tools, `session_search` and `session_get`, give the model workspace-scoped recall over the same store (one-line summaries and an 8-message tail, labeled untrusted user data, read on the blocking pool). Resuming stays the user's decision: the hint tells the model to offer a continuation, never to silently take one (#5715). - `codewhale exec --hooks` opts a headless run into the same `HookExecutor` the TUI builds — global config, reviewed plugin snapshots, and trusted project `hooks.toml`. Headless runs previously fired no hooks at all. `tool_call_before` can still deny and `shell_env` still applies; a hook `ask` resolves fail-closed without a terminal. Fleet worker subprocesses never opt in, and `permissions.toml` typed rules are unchanged (#6099). - `codewhale doctor` flags fleet and profile model pins that the provider's own roster no longer offers. A pin is reported only when a *fresh* cached live roster for that exact route exists and omits it — stale, failed, or absent rosters prove nothing and are counted as `unverifiable` rather than raising a false warning. Each row names the route and every owner of the pin; the pin is surfaced, never rewritten (#6035). - Background-capable clients can enumerate owned work and watch TUI-visible conditions: `GET /v1/threads/running` lists threads with queued or in-progress turns in one call (one turns scan grouped by thread), and `GET /v1/threads/{id}/notices` serves active `subagent-terminal`, `elevation-needed`, and `model-notify` notices with thread/turn identity, cleared by ack or — for elevation — when the tool call completes (#6180, #3757). - Sub-agent launches adapt to provider throttling: a `DynamicGate` replaces the fixed semaphore so launch capacity adjusts at runtime, and a `RateLimitGovernor` halves capacity on 429 pressure, pauses admissions past the threshold, and recovers additively; 429 retries honor `Retry-After` with jittered backoff, and quota exhaustion keeps the failure path (#6055). - Turns record the mode they ran in, so mixed-mode sessions stay legible after the fact (#6321). - Shell spawning refuses NUL bytes in command and cwd before spawn, and sub-agent runs fall back loudly past credentialless profile provider pins instead of misrouting silently (#5529, #6318, #6320). - Children land past a per-step context bound instead of burning quadratically, and status rows surface live declared-vs-observed writes (#6189, #6194). - Queued Agent Mail can be cancelled before delivery, and the TUI suspend/resume handshake restores on stop and rebuilds on continue (#6176, #6169). - MCP connections are supervised: dead servers are probed and reconnected with transitions reported, and a failed reconnect keeps the last-good catalog instead of dropping tools (#6187, #6142). - Web search autodetects Tavily from `TAVILY_API_KEY` (Firecrawl stays the default), fleet refusals name the alternative, and verification runs on a bounded Git fetch plus a `merge_tree` verify surface (#6298, #6296). - Fleet authority projects through one `ChildGrant`, and ModelScope joins the built-in providers (#5633, #6299). - Child tool results are capped at capture time, and run tests/verifiers accept a bounded cwd (#6282, #6294, #6296). ### Changed - SearXNG results rank by the score the instance returns rather than by arrival order. Integers, floats and numeric strings are accepted; anything else, including NaN and infinity, becomes 0.0, and rows are stable-sorted descending before the result cap, so equal scores keep instance order. The docs now spell out the self-hosting requirement: the separate process must expose `search.formats: [json]` — an HTML-only instance answers 403 — and bind to loopback or a policy-allowed host, with no default instance discovered. - The bundled skills move to a new generation. social-media and health leave the shipped pack (phone-export workflows rather than everyday skills), feedback moves to `docs/skills/` beside contributor onboarding, and the exact earlier body is retained so only unmodified shipped skills upgrade — a skill you have edited is left in place. Google OAuth scopes and client setup, Photos exports, forgetting limits, Spotify playback and plugin reload guidance were corrected in the same pass. - `auto` is a declared default, not a guess about your wording. Reasoning effort no longer maps request vocabulary to tiers (debug/error to Max, search to Low) and Auto routing no longer infers cheap-versus-big from phrasing: both resolve the configured default, with `[auto] cost_saving` as the explicit opt-in. The same prompt now costs the same thing twice. - A workflow's shared token budget is opt-in. `[workflow] default_token_budget` applied a silent 120,000-token cap across a run and all of its children, and a fan-out died at the limit with no hand-back; the default is now 0, meaning no shared cap. - The shipped `deepseek-flash` route speaks the Responses endpoint, and `xhigh` effort maps to `high` per the vendor's own table. - Streamed text is paced at a steady rate rather than inheriting the provider's SSE chunking, so output reveals at a readable beat instead of in bursts. - Broadening shell access for a conversation now requires an idle conversation and rejects a stale-workspace check before it commits. Engines advertise a `thread_shell_consent` capability, so an older Engine reads as unsupported to a native consent client instead of silently accepting. - One base prompt now serves every host. `HEADLESS_BASE_PROMPT` was a second hand-maintained rendering of the same constitution — the drift pattern this repo forbids by convention — so headless runs compose the same `BASE_PROMPT` plus language and output layers that interactive runs do, skipping only host chrome (execution profile, authority recap). Headless and interactive can no longer disagree about what the agent is. - `BASE_PROMPT` gains a **Bearing** article, which changes how the agent talks to you: the user is a peer who gets honesty rather than deference, a blocking gate is named plainly instead of dressed up as refusal, bad code is called bad, a crude request is carried out without a lecture, and an apology appears only when there is something to apologize for — not as punctuation. It also states that the request is the whole mandate, so the scope law opens with what is yours to do before it reaches the edge. Every pinned kernel invariant survives verbatim. - The ocean reads as animals rather than a mechanism. The school used to translate as one rigid body — bob phase and tail pose were staggered per fish, but horizontal position was locked to an exact wedge offset — so each fish now eases a dot fore and aft of its slot on its own slow period, and the formation breathes while it travels. Bubble emission and the per-animal periods are hash-jittered instead of sharing one clock. Amplitude stays an order of magnitude under the crossing speed, so no fish travels against the school and `facing == velocity` still holds by construction. The species list is unchanged. - Extensions keeps the exact-content plugin review on the panel: confirming a bundle's digest re-reads the inventory, so the row you just reviewed reports its new trust state and offers Enable instead of leaving you in the transcript with a stale "not reviewed" row. - Underwater motion ticks at the cadence the frame limiter actually draws (the atmosphere interval while only the water moves, the authored 80 ms ocean cadence inside the interactive cap while a turn streams), and the event loop wakes exactly for the next tick instead of on the next idle poll. Idle water no longer requests frames it cannot draw or quantizes its cadence to the poll interval; reduced motion, Ghostty, tmux and the six-second idle settle are unchanged. - The launcher keeps the Codewhale mark while balancing its layout above the composer. A single cursor identifies the selected action; MCP faults retain their warning color even in compact terminals. Recent-session counts now read correctly for a single message. - Model and provider settings use quieter selection surfaces, one focused cursor, clearer missing-key warnings, compact output limits, and less repetitive credential detail. Plugin actions use plain labels. - The terminal opens on **Shoreline**, the same palette the GPUI client already uses: warm charcoal field `#211F23`, a raised plate for panels and the composer, one blue for action and selection `#90B9FF`, and the whale's ivory `#F2ECE5` for body text, with 4.5:1 floors on every muted step. The old saturated navy gradient is not gone — it is a named `underwater` theme, and after review it is once again what a fresh 0.10.0 install opens on (`DEFAULT_TUI_THEME`); Shoreline is one `/theme` away. Existing installs keep whatever theme they have saved (#6222). - Menu navigation is starting to mean the same thing everywhere. `menu_style` already single-sourced how a selected row *looks*; what a key *does* was still reinvented per surface — `h`/`l` in the provider picker against `Left`/`Right` in the model picker one screen later, `Home`/`End` in one of seven pickers, and no paging at all in Fleet's detail view. `list_nav`, which already owned the wrap arithmetic, now owns the vocabulary too: one vertical axis, one horizontal axis, and two entry points so a picker with a live filter never has a letter stolen out of its query. Fleet's detail view adopts it first and gains PageUp/PageDown and Home/End in both its lists (#6290). - Reviewed plugin bundles are no longer re-hashed four times per MCP dispatch. `verify_plugin_authority` walks and hashes both the reviewed source and the runtime snapshot, and four separate authority checks ran per `tools/call` — eight tree walks. Three of them sat one statement after a `validate_before_use` on the same source, so `is_ready` re-verified what had just been verified; readiness and authority are now separate, and only the callers with no preceding check still pay for both. The tool catalog is built once per turn instead of twice, which also removes a case where the two assemblies could disagree if authority drifted between them. The digest is deliberately **not** cached on `(path, mtime, len)`: the reviewed tree is user-writable and `utimensat(2)` lets a same-uid process restore an mtime after an equal-length rewrite, so a stat-keyed cache would serve a pre-tamper digest (#6209). - A sub-agent's completion is read from the manager once instead of polled. The workflow pump re-read it up to fifty times, sleeping 20ms between attempts, waiting for a terminal status that was already committed — every publisher commits the status inside the same `&mut self` call that wakes the pump, so the write guard spans both and the first read always sees it. A child the manager had no record of cost a full second of head-of-line blocking before failing; it now fails immediately, and says what actually happened instead of claiming the child "did not report a terminal status within 1s" (#6211). - MCP protocol negotiation: every surface advertised the original 2024-11-05 revision and the stdio client required an exact match, so newer servers could not connect. The server and both clients now advertise 2025-06-18 and negotiate over the supported set (2025-06-18, 2025-03-26, 2024-11-05) — the server echoes the client's revision when it is supported and answers with the latest otherwise, the stdio client accepts any supported revision, and streamable HTTP sends the required `MCP-Protocol-Version` header on every post-initialize request (#6280, first half). - Configured MCP servers now connect lazily instead of all at session boot. The pool owns a `connecting` set marked at spawn and cleared on resolution or abort, so "connecting" is no longer inferred as enabled-minus-connected. The boot pass scopes to the eager set — `required` servers plus those covered by `tools.always_load` / `allowed_tools` — and a turn naming an unstarted server spawns its connects alongside, under the existing five-second deadline. A configured-but-unstarted server now reads as configured on every surface (session-boot rows, Extensions tab, launch card), never as connecting. `docs/MCP.md` documents the lifecycle (#6033). - The launch card's MCP problems row runs its own remedy. It already printed `/mcp login ` or `/mcp`; it now joins the shared paint/click/keyboard ordering, so Up/Down lands on it and Enter or a click types the printed command into the composer for you to send. Typing beats copying: no clipboard dependency over SSH, and you see the command before a second Enter runs it (#6085). - Computer Use is the only computer-use product in Extensions and `/mcp recommendations`. Cua is no longer suggested as a parallel desktop-control MCP; enable the first-party `computer-use` plugin instead. The bundled plugin is 0.11.2 — macOS beta, with the Windows and Linux backends experimental and source-only. It carries the per-app consent ledger, background-by-default control, and a focus lease that refuses rather than stealing the foreground, alongside `get_app_state`, `focus`/`get_value` and `stop_computer_control`. Shared-desktop pointer gestures stay gated, and arbitrary background dragging remains unavailable. - The bundled first-party catalog pins marketplace revision `d8640b17f27542e7122c76368724196f92a0af61`, so installing Computer Use from the Extensions listing fetches the same 0.11.2 source the binary already carries. - Materializing is not enabling: the built-in bundle is written under `$CODEWHALE_HOME/builtin-plugins` on first run but stays `NeverReviewed`, so Computer Use is never switched on without an explicit capability review. ### Removed - The host no longer parses prose into goals. Ten phrasings and a clause allow-list ("make it your /goal to …") were turned into durable goals before the provider call; prose now reaches the model, which calls `create_goal` when a goal is useful. The deterministic path — a leading `/goals ` — is unchanged. ### Fixed - A thinking fold is an absolute choice again. The stored bit was relative to the display preference (`folded ^ !(verbose || thinking_default_expanded)`), so every recorded choice flipped meaning the moment a preference changed: turning `thinking_default_expanded` on closed a block the reader had explicitly expanded (#5847). An explicit tri-state intent now records Expanded or Collapsed outright, and the absence of an entry means untouched, so the preference baseline decides that cell's default. Space still toggles, and an untouched cell still follows `verbose || thinking_default_expanded`. - A terminal byte-stream cursor past the head is clamped instead of echoed back. `read_since` returned a future cursor as `next_cursor`, so a client that continued from it skipped every byte the stream produced before reaching that position — permanently. The start position now clamps to `total`: a future cursor reads nothing, is not a gap, and hands back the head. - Language-server startup is bounded and a failed transport now terminates. The client waits for successful initialization before sending notifications, drains stderr without buffering it, bounds request queueing and replies, caps protocol frames, and fails pending requests when the child transport dies. - Input no longer freezes for the rest of a turn when the engine's 32-slot op mailbox is full. The remaining input-path sends no longer await: droppable ops whose rejection is reported and retryable use `try_send` (CancelSubAgent, PreviewOutboundRequest, bang shell input, PurgeContext, and the single-op settings updates), ops that must land once the UI changed reserve first, and `ChangeMode` publishes its live authority even on a full channel. Must-deliver ordered transitions still await, and say why at `EngineHandle::send` (#6150). - The pet's whale is one body again. The same authored point set is checked in three copies plus four fixtures, and the Rust and TypeScript cores disagreed on particle positions from frame 0 while agreeing on every channel and constant — so the v1 fixtures had never matched what Rust produced and the conformance job had never passed. The bodies and the fixtures are reconciled and that check now runs green. - The context meter and the auto-compact gate share one honest estimator. The status bar inflated `ctx %` by about half and disagreed with the gate, so "ctx 82%" could sit beside a `/compact` that refused to run; displayed percentages now read materially lower because they are correct (#6297). - A steer the engine never accepted is queued for the next turn instead of being shown as held and then silently dropped with no turn and no answer (#6297). - Every `reqwest` client routes through `codewhale_release::tls`. A bare `Client::builder()` panics under rustls with no installed provider; 17 call sites were swept. - The bundled OpenAI-compatible hosts have their `/provider` rows back. Retiring the `ProviderSetupTemplate` layer moved SenseNova, Baseten, Groq, Cerebras, DashScope and Command Code into `provider_descriptors.json` and then wired that file to nothing, so six vendors silently lost their picker rows; AICraft never had one. Each descriptor is a row again, built through the same named-custom-provider builder a configured host uses, so endpoint, bootstrap model and "missing ``" reporting all come from one place. A descriptor whose id or alias already names a `[providers.*]` entry is dropped, so a configured row stays the only one. These rows are an invitation, not a route: they are not `is_configured`, and only the form's submit writes anything (#6289). - A StepFun Step Plan subscription reaches its own catalog. A subscriber's `base_url` is `https://api.stepfun.ai/step_plan/v1`, but only the pay-as-you-go `/v1` host was recognised as official, so the Step Plan host read as a custom endpoint, the catalog was withheld, and the picker showed `0 bundled` and a guessed context window for a route whose console advertises `step-5-preview` at 1M context. The model was in the seed the whole time. All four StepFun hosts — global (.ai) and China (.com), each with a `/v1` and a `/step_plan/v1` surface — are now recognised; a host StepFun does not own stays custom and keyless, since this predicate also scopes credentials. - The send cue stopped strobing while you type. `[↵]` flickered between dim `[·]` and bold blue once per character at an ordinary typing pace. The cue was not lying — Enter really does insert a newline during the ~120 ms paste-safety window, which every keystroke re-armed — but that window only exists for terminals that deliver a paste as a burst of ordinary keystrokes. Ghostty, iTerm2, WezTerm, Windows Terminal and Terminal.app now skip the heuristic from the first keystroke instead of waiting for proof by paste. - Shift+Tab sets the permission posture in Plan. Tab cycles the mode and Shift+Tab cycles Ask/Auto-Review/Full Access, but Plan refused the second one outright, so the key silently did nothing there and the two axes read as welded together. Plan's read-only guarantee comes from the mode, not the posture — `authority` maps `(Plan, _, Bypass)` to `SandboxPolicy::ReadOnly` and `tool_catalog` gates every write tool on `mode != Plan` — so the cycle now moves the durable Act/Operate baseline while Plan's live policy stays `Suggest`, and a toast says the posture lands when the mode leaves Plan. - A steer delivered mid-turn now clears its pending card. The transcript showed the message and the model answered it, while the "sending into this turn" card still listed it as pending: `turn_loop` commits a steer trimmed, but the UI handed the engine the untrimmed text and kept that same copy for matching, so a composer newline made the two differ by whitespace alone and the steer was never promoted to a transcript cell. The text is trimmed once at the source that feeds both, so they are the same string by construction; the match stays an exact `==`. - A Xiaomi MiMo key no longer fails verification with another vendor's 401. The legacy top-level `base_url` is a DeepSeek field, and a route without an endpoint of its own inherited it — so a config carrying `base_url = "https://api.deepseek.com"` made that host the MiMo route's endpoint. The custom-endpoint guard correctly withheld the MiMo credential from a host the route does not own, and the setup wizard's probe, which bypassed the guard, sent the key as `api-key:` — a header DeepSeek ignores. The result was `HTTP 401 Unauthorized: Authentication Fails (governor)`, DeepSeek's *unauthenticated* 401, shown to someone who believed they were testing their own key. Every layer that reads the root now inherits it only when the URL belongs to that provider's own official endpoint family; DeepSeek, which owns the field, is unchanged, and any other host is still expressible on `[providers.xiaomi_mimo] base_url`. Key verification failures now also name the endpoint that was probed, so a wrong endpoint reads as a wrong endpoint instead of a bad key. - The Extensions panel can act on the rows it shows. Every plugin now carries its on/off switch — Space, or `e` — including one that has never been reviewed: `/plugin enable` already routes an unreviewed bundle into the exact-capability review and only flips the switch once you confirm the digest, so withholding the control bought no safety and left the shipped `computer-use` bundle reading `disabled` with nothing that could enable it. - The panel stopped saying "untrusted". A bundle that is waiting on its capability review now reads `needs review` — `off · needs review` when the switch is off too — and its detail line says what Codewhale is withholding and which key ends the wait, instead of restating an internal pair of booleans. Enter's verb on that row is `review`, not `inspect`. - MCP servers say where they live, and mutations write there. Each row is labelled `global`, `project`, or `plugin: `. Enabling, disabling or removing a workspace-scoped server previously edited the user's global file and failed with "MCP server '' not found" on a row the panel had just offered; the write now lands in the file that declares the server, and a plugin-contributed server says it is switched off by disabling its plugin. - The permanent "Plugins · Problems: N" footer chip is gone. It could not be acted on from the footer, and its count and the Plugins tab disagreed by construction — the chip counted bundles waiting on a review while the tab's Problems group lists only registry-level diagnostics, so the rows behind the number were never the rows you found. A bundle waiting on a review is a row with an action, and `/plugins` states it per bundle next to the key that resolves it. - The Extensions marketplace no longer advertises what it cannot install. Browser Use and the sandbox runtime were pinned rows whose only possible action was `unavailable`; they are removed, along with the browser-driver and sandbox-runtime component vocabulary that existed solely to describe them. - Configuration parsing keeps the parsed base config boxed, so loading a profile no longer carries the full `Config` by value through the deserializer and overflows a default 2 MiB test-thread stack; the runtime-store binding test that also overflowed is split into phases and pinned to that budget so CI's larger stack cannot mask a regression ([#6362](https://github.com/codewhale-hq/Codewhale/issues/6362)). - Stopping a turn revokes its pending approvals. A late approval cannot resume the cancelled action or save an automatic approval for later turns. - Expanding and collapsing selected reasoning now matches its rendered state when verbose mode and the default-expansion preference are both enabled. - Branch navigation preserves sibling histories, stable entry IDs and timestamps through autosave, resume and forks, and synchronizes the selected branch into the live engine. Thanks to @7jrxt42BxFZo4iAnN4CX for the report (#6367). - Compaction now writes local diagnostic records for completed passes and automatic refusals. `codewhale metrics` reports them with summarizer token usage; text-mode exec retains its session after attempting compaction. Historical artifacts are not backfilled. Thanks to @7jrxt42BxFZo4iAnN4CX for identifying the missing producer (#6368). - The opening workbench retains the canonical Codewhale mark in a responsive header while keeping recent-session titles full-width and actions clickable. - `serve --acp` no longer ignores the approval posture. The ACP adapter hardcoded `ApprovalMode::Suggest`, so `--yolo` (and any configured `approval_policy`) never reached admission: every mutating tool parked behind a permission request no unattended client answers, and sessions executed zero tools. Posture now derives from server config — `--yolo` pre-approves prompts and flows into the sandbox policy — while hard blocks (safety floor, repo law, reviewer consult) and the Plan read-only guardrail stay intact (#6337). - Plain agent spawns could not resolve. `built_in_members()` seeded both `general` and `worker`, and the role parse boundary migrates `worker` to `general`, so both canonicalized to the same role — and `role:general`, the selector the roster advertises for the default posture, matched two members and raised `Ambiguous` every time, permanently. The duplicate built-in is gone. The legacy name still resolves: `general`, `member:general`, `role:general` and `default` all land on the `worker` posture through the identity selector rather than through a second member, which is what allowed the duplicate to be removed (#6244). - Clicking a `path:line` in tool output no longer spawns `$EDITOR` detached while the TUI still owns the terminal, and no longer spawns one editor per matching line. The launch goes through the single terminal-handoff path, and a click is one request to open one file (#6235). - A write-scope contention refusal now names a remedy that works. The `agent` tool's description claimed `release` was "the remediation a write-scope contention refusal names"; the refusal did not name it, and pointing back at it would have been worse, because `release` only clears claims whose owner is no longer running while a contention refusal names a live one. The refusal itself now says to wait for that owner to settle or cancel it (#6272). - The session picker no longer refuses a saved session whose Runtime store exists but holds nothing. A force-quit leaves the store on disk, ownerless and empty, and the switch path refused it because recovery only covered a *missing* store. A switch now also adopts a store that is provably empty (every work directory, plus the event sequence that remembers pruned appends) *and* provably unheld (the process-owner lock, which a live manager holds from open to close), with no automation pinned to its execution scope — and the save gate treats that shape as abandonable too, so the repaired binding persists. The first fix was reverted on a race (emptiness without liveness); this reland checks the lock first (#6207). - Double-tap Enter now sends every queued follow-up into the running turn, oldest first. The second Enter used to steer only the most recent message and leave older ones queued; a failed steer restores the failed message plus everything unattempted in original order, so nothing is lost or reordered. - Only the most recently sent prompt carries the elevated-surface background now; every older prompt renders on the bare ground. The fill used to sit behind every user row (striping), then behind none; newest-only keeps the eye on the turn in play. Sending a new prompt moves the highlight and un-highlights its predecessor. - Diff rows tint whole: added/deleted line numbers now share the row's green / red background instead of sitting bare next to a painted body. Context rows stay on the bare ground. - MCP connections are supervised now: a background task notices a dead server within one sweep, reconnects on the existing backoff ladder, and reports each transition, so Extensions rows flip with liveness instead of parking on stale-ready or a silent [reconnect]. Five consecutive failures park the server with a notice naming `/mcp retry`; an explicit retry or a fresh connection resumes watching. Tool calls also retry once across a dead pipe/socket (not just stale sessions), and a reconnect that fails reports both errors instead of swallowing the original (#6187; `list_changed` catalog refresh stays open). - A steer the engine never delivered is no longer reported as sent. The runtime API persisted the steer item as already-`Completed` and emitted `turn.steered` + `item.completed` the moment the text entered the engine's mailbox — before the engine decided anything. The engine discards a steer whose turn has moved on, and an interrupted or failed turn drops whatever it had queued, so a GUI could show "Guidance sent", clear the composer, and lose the user's words. The engine now returns a verdict for every steer on every exit path, the item settles `completed` or `canceled` to match, a dropped steer emits `turn.steer_dropped` and answers `409` so a client can resend, and `steer_count` counts steers the model actually received (#6276). - `` suggestions stop nagging: a plugin id is now injected at most once per engine lifetime, and a plugin whose name a loaded skill already covers is never suggested — the local skill owns the domain, so the nudge was noise. Dismissals still apply, and the fragment stays append-only on the user turn (#6274). - A canceled automation run now settles with a transcript receipt that names the cancellation (by request, cancel timeout, or shutdown) instead of vanishing from the live band silently. The receipt wears attention ink and never lights the failure demand; the run record keeps the cancellation reason as its error detail. (#6162) - A failed workflow run no longer settles silently: its terminal failure raises a sticky error toast naming the cause (dispatch, schema, or script errors), alongside the existing panel state (#5528). - MCP OAuth re-login now forces the provider's consent screen: logout only clears the local token, so without a prompt the provider silently re-granted the same account/workspace and a re-login could never change it. `/mcp logout` and `codewhale mcp logout` also say plainly that they clear local credentials only (#6040). - Session retention no longer deletes transcripts once the store reaches the cap: the oldest active session is archived — still openable from the picker's archived view — instead of being unlinked, and archived records sit outside the cap until they are pruned (#6136). - Empty auto-created "New Session" stubs are capped separately (the ten newest are kept) and can no longer occupy a real transcript's slot in the session cap (#6137). - A failed resume or session load is now a durable transcript error instead of a status line the next footer update replaces, so a resume that cannot restore its target no longer looks like a silent new session (#6138). - Compaction no longer retains a tool result whose tool call was summarized away: an older turn that mixes text with a tool result keeps its text and drops the orphaned result blocks, which providers reject outright (#6119). - Automation runs that need a tool approval no longer die as silent idle-timeout cancels: a pending approval suspends the idle watchdog for its decision window, and an unanswered window settles the run Failed with the recorded reason instead of a silent Canceled (#6118). - `/mcp` no longer freezes the console while a turn is running: the panel opens immediately from the last known MCP snapshot with a receipt naming the wait, and live-pool mutations say their refresh is deferred instead of parking the UI event loop behind the running turn (#6159). - MCP OAuth login no longer fails with "Authorization server response missing required issuer" against servers that implement RFC 9207, such as Cloudflare's `mcp.cloudflare.com`. The local callback listener now keeps the `iss` parameter from the redirect and hands it to the token exchange so the callback binds to the discovered issuer; servers that do not send `iss` keep working unchanged. (#6157) ## [0.9.13] - 2026-09-13 Codewhale v0.9.13 addresses integrity issues in 0.9.12: multiline paste is one paste again, truncated tool arguments can no longer execute, strict ACP clients connect again, concurrent instances stop destroying each other's queued text, and the Computer Use bundle includes plugin 0.3.1 with an accessibility-first pointer that no longer steals focus. DeepSeek V4.1 Flash (`deepseek-flash`) is the default DeepSeek model, reasoning-capable routes keep reasoning out of the answer even when a model id carries no version number, and `/mcp reload` no longer freezes the interface while servers reconnect. The Codewhale pet arrives with `/pet`: a full-screen habitat that shows what the Engine is doing and reveals the answer when it is done. ### Added - `/pet` turns the terminal over to the Codewhale pet. `/pet on` (or bare `/pet`) gives the habitat the whole content viewport now and on every accepted turn, reveals the actual answer or error when the turn completes, and Escape returns to the composer without cancelling anything. `/pet off` closes the view and stops automatic entry while the durable companion keeps the pet alive; `/pet appearance|window|source|sound|export|status` address the shared companion. The pet no longer lives in the workbar: the Watch panel and `/workbar watch …` are gone (#6109, #6110). - Codewhale Computer Use 0.3.1 ships as its own notarized Mac app. Download the disk image from [codewhale.net/computer-use](https://codewhale.net/computer-use) or the [v0.3.1 release](https://github.com/Hmbown/codewhale-cu-plugin/releases/tag/v0.3.1) (`Codewhale-Computer-Use-0.3.1-macos-universal.dmg`, drag into Applications; the ZIP stays for the in-app updater). The bundled plugin and the first-party marketplace pin the same 0.3.1 sources, so the app, the `computer-use` plugin and `/mcp` see one implementation. ### Fixed - The website's Computer Use download page resolves its state without the GitHub API (using `GITHUB_TOKEN` only when bound), and every page regenerates on the Worker again: the Open Graph image route read brand SVGs at import time, which the Workers runtime cannot do, so codewhale.net had been serving its build-time snapshot. - Operate can run structured workflows directly, with named phases, model assignments from Fleet, prerequisite results and shared budgets. Independent steps run together; dependent work waits for its required results and gates. Detached runs return their outcome to the owning conversation, and headless sessions stay alive between phases until the final handback is consumed. - Computer Use 0.3.1: mouse actions no longer steal focus or reclaim the foreground when the user switches apps mid-action; background typing, scrolling and selection use semantic input, and screenshots stay scoped to the targeted app. The bundled plugin and the first-party marketplace pin carry the same 0.3.1 sources. A registered macOS helper stays in charge of input through its Pause and Stop controls; an unavailable registered helper produces an error instead of silently bypassing those controls. - The Fleet editor uses the standard model picker to manage sub-agent model and thinking assignments. Enter edits the selected row without changing the running session's model. Unconfigured providers are refused, failed saves retain the previous assignment, and a changed or removed team file must be reopened before a pick can overwrite it. - The provider catalog includes Baseten and the other compatible-provider templates as selectable rows, opening their existing prefilled setup forms. DeepSeek routes with clock-based pricing show the current peak or off-peak tier beside session cost, with translated labels. - Extensions, teams, workflows and automations support mouse-wheel scrolling. Plugin and MCP rows have keyboard enable/disable controls and two-step removal; MCP OAuth can retry with narrower scopes after a scope rejection. - Healthy sub-agents continue after an ordinary parent reply. Headless runs keep the existing Engine alive for child results within the run deadline. Explicit cancellation remains authoritative when result queues are full or a completion starts a followup turn. - Sub-agent followup supports multiple targets and all parked children, keeps old IDs connected to their current continuation, and saves continuation identity before starting work. Repeated followup does not fork duplicates. - Sub-agents validate declared output files and distinguish real edit claims from file citations and unrelated workspace changes. Disjoint file claims can run together; overlapping writers receive the actual conflict and remedies. Explicit read-only shell analysis requires an enforcing native sandbox and refuses execution when that protection is unavailable. - Delegation depth stays absolute through saved profiles, nested workers and continuations. Per-call token, step and time limits narrow inherited limits; continuation retains ancestor usage and deadlines. Workers reserve room for one tools-disabled partial report inside those limits, then run the declared- output checks. Missing usage or unavailable reporting room produces an explicit fallback; partial work is never marked complete. - Agent rosters and detail pages have bounded output, visible continuation and descendant relationships, and usable handles for full diagnostic evidence. Completion receipts include measured worker and descendant token usage, count each continuation once, and distinguish unreported usage from zero. - Localization and native helper builds resolve the active checkout when the build script runs, so a shared Cargo target keeps working after a worktree moves or is removed. - Selecting a saved agent profile that is malformed, unreadable or duplicated now fails before any child request, including when its name matches a built-in role; the parent's default route is never substituted silently. `agent(action: "roster")` lists affected profile identities and paths, Fleet run creation performs the same check, and `docs/SUBAGENTS.md` documents the valid personal profile format with `[permissions]` (#6117, thanks @Gabriel-Degret). - Interactive startup no longer mistakes worker scheduling delays for an unresponsive terminal. Terminal ownership checks and shutdown cleanup remain enforced (#5929). - Interrupted conversations whose saved runtime store is missing recover into a fresh scope without restoring old tasks or approvals. Stale session saves cannot resurrect the broken binding (#6102). - Permission checks distinguish literal heredoc data from executable commands, including substitutions and shell stdin (#6098). - Automatic compaction runs quietly from live context pressure, preserving the current task and recent tool exchanges while keeping the system/tool prefix stable. Original history and the handoff are saved before context replacement; failed or canceled compaction retains the conversation (#5620, #6047). - Custom and gateway providers can override context limits for each exact model, so switching models also switches the meter and compaction budget (#6108). - Plugin suggestions explain their matching term and remember explicit dismissals across restarts. Generic words and repository-host domains no longer trigger unrelated installation prompts (#6031). - Plugin trust and automation deletion have keyboard and mouse confirmation controls bound to the exact reviewed content; users can still copy the command and changed content requires a fresh review (#6039). - The model-facing MCP start tool can reconnect an existing configured name after login without changing its credential key or restarting healthy siblings (#6030). A decreasing token-expiry countdown no longer makes a revoked credential look like a new login from another session. - Gemini setup uses the official endpoint's supported reasoning-effort field, avoiding the rejected top-level Google thinking object. Gemini 2.5 and 3 keep their supported effort ranges; signed tool history still survives reasoning changes and restart (#6018, thanks @vmakarov-uk). - Missed automation occurrences coalesce without overlapping a running job; restart reconciles durable receipts without replaying accepted work. Damaged neighboring records are isolated while preserving their original bytes. - The bundled first-party marketplace lists the actual plugin bundles and uses the existing install, review, trust and update paths. A read-only connection check verifies catalog and skill mirrors on changes and weekly. Already present bundles lead to their local review and management controls; catalog installs refuse name collisions before downloading, without overwriting or granting trust. - Windows deny checks preserve native path separators while retaining the conservative POSIX scan for shell wrappers and substitutions. - The config example agrees with the telemetry disclosure: usage analytics are optional and enabled by default; local diagnostics do not require telemetry (#6011). - Sub-agents enforce the session's typed shell and file deny rules, including Full Access, delegated edits, and policy updates after a child starts (#6097). - Live permission edits reach running engine clones atomically. Deny rules support token wildcards and Windows command spellings while keeping POSIX arguments literal (#6054, thanks @h3c-hexin and @asto18089). - Tool-result images use the existing typed inline path and are fully decoded under size and allocation limits before admission or provider projection. Invalid images keep a visible omission receipt alongside the text result (adapted from #6053, thanks @h3c-hexin and @asto18089). - A lone `y`, `Y`, or `r` remains composer input after selecting transcript text. Clicking the composer releases transcript and dock focus. - The Agents register updates from live worker events while the parent is busy, including when the register opened before the workers spawned. - Ghostty no longer shows a second graphical whale over the launch mark. The selected model stays visible before the first message; unused session metrics stay quiet. Scheduled counts open `/automation` directly. - Marketplace installation accepts compatible Claude plugin bundles and roots their relative sources outside `.claude-plugin`; unsupported components fail explicitly. Native trust and enablement review still applies. - Config table and nested reads work consistently and redact credentials. Unsupported dotted writes fail without changing the file, and `config doctor` no longer labels runtime settings as never applied (#6083). - Esc during a worker fanout keeps the parent stopped when cancelled workers finish. Their receipts remain available for the next explicit user turn. - Undo preserves messages even when older state lacks a timestamp. Session journal entries retain their append-time stamps when saved again. - Extension actions refresh in place, and inspection output uses the text pager. The empty launch shell hides unused metrics and keeps recovery hints readable when several MCP servers need attention. - The large-output router defaults to bounded spillover; adaptive routing remains opt-in through `CODEWHALE_ADAPTIVE_OUTPUT_ROUTING=1`. - Direct composer paste (`Ctrl-V`) preserves rich clipboard headings, lists, links, tables and code as Markdown, with plain-text fallback. Whole-answer copy preserves authored Markdown without terminal wrapping; settings fields still paste literal text. - The embedded Computer Use bundle includes the marketplace's JPEG capture and bounded-payload fixes, so new built-in installations receive them too. - A provider's missing-`thought_signature` HTTP 400 now explains how to recover: use the built-in Google provider and start a new session, or verify the gateway's signature handling. Working gateways are not blocked by a broader preflight check (#6048, #6081, thanks @nightt5879). - Chinese documentation links resolve to the contributor guide and Windows screenshots from their translated paths (#6080, thanks @c020627). - GLM-5.3 reasoning controls follow the forced-thinking contract on Z.ai and BigModel routes, including low effort when a prior configuration requested thinking off (#6051, thanks @h3c-hexin and @asto18089). - Finance calls respect the session network policy, and model-facing shell, verifier, notification and Fleet guidance matches executable contracts (#6052, thanks @h3c-hexin and @asto18089). - The sandbox-elevation prompt shows every option, `Abort` included. The card was a fixed 22 rows centred on the frame; inside its border and padding that left at most 18 usable rows against 20 to 23 rows of content, with no scroll rail and no truncation hint. The safe exit — the one choice that grants nothing — was painted past the bottom edge at every terminal size. The card is measured from its content now and reserves the option rows before the denial detail, which is what shortens; below roughly 60x24 the per-option descriptions shed and every choice keeps its row. Option hitboxes were also counted in unwrapped source lines, so a description that wrapped put every hitbox below it out of step and a click committed a different choice than the one under the pointer. - `d` in the Hotbar setup modal asks before it clears every slot. It persisted `hotbar = []` on the first keystroke, in a view that takes bare letters as its filter — the destructive key and the search key were the same press. It arms a confirmation that owns every key until answered, and the prompt takes the intro's place in the header so it cannot be the line that falls off a five-row budget. - Failure red means failure again. The metrics line painted the context reading in the error colour from 80 %, while the posture bar one row above called the identical threshold Attention; the workflow panel painted a `Waiting` row like a crashed one, though its own `is_running` counts Waiting as healthy; and the work surface spent `error_fg` on to-dos that were merely waiting, blocked or stale, and on the routine approach to auto-compaction. `WorkTone` has a real `Failure` variant now, and a guard test holds the reservation across every selectable theme rather than the default alone. - The command palette runs the row you highlighted. `refilter` clamped the selection index but never re-anchored it, and every keystroke re-sorts the list, so refining a query could move the highlight to an unrelated entry that Enter then ran. Long labels also overran their column and pushed the description off the card, because the padding never truncated and the capacity was measured against the popup rather than the content area. - The work surface's first `Down` reaches the first row. Nothing is selected when the dock opens, and that resolved to "row 0 is selected", so the first press moved to row 1 and row 0 could not be reached by pressing Down at all. - Auto-compact could not fire mid-turn. The gate read `max(last billed prompt, /4 estimate of the whole list)`, so as soon as the estimator undercounted the full list below the last bill, every tool result appended after that prompt was invisible to it, and a long turn could exhaust the context window with nothing compacted. It now reads live tokens — the billed prompt plus the growth since it, watermarked when the parent usage is recorded — and is still evaluated at the pre-request boundary after tools complete, never mid-tool-call. - Esc or Ctrl+C during a compaction that is serving an in-flight turn now stops the turn. It previously cancelled only the compaction pass, so the turn resumed against the context that had just failed to shrink. A manual `/compact` with no request in flight still cancels only the pass. - The `request_user_input` dialog is a bottom-anchored sheet instead of a centered 22-row overlay. It leaves the transcript visible above it, grows with its content, and scrolls internally so the highlighted option and the custom response being typed stay on screen at 141x38 and 80x24. Left arrow or `h` goes back to the previous question; Esc still cancels the whole request. PageUp/PageDown, Home/End and modified arrows now review the transcript while the sheet stays open; the mouse wheel scrolls the surface under the pointer. Wheel browsing preserves the answer, and option navigation or typing restores the focused content to view. The transcript viewport ends above question and approval prompts, so End keeps the newest rows visible. Documented in GUIDE.md and KEYBINDINGS.md (#6045). - `/mcp reload` no longer freezes the interface. The reload was awaiting the whole reconnect batch on the TUI event loop; it now joins the same supervised background pass the session boot uses, the status chip counts the batch down live, and the finished receipt arrives as an event. With 23 configured servers (11 live, 10 awaiting auth, 2 failing) the first echoed keystroke after a reload lands in ~5 s instead of ~42 s (#5974). - The posture bar no longer states the same duration twice on a first turn (#6041). - Reasoning-capable models whose id carries no version substring (`deepseek-flash`) keep `reasoning_content` in the thinking block instead of the answer text. The gate only ever matched the literal `deepseek-v4` version string, so it now consults the model catalog as well; the older literal arms remain for the V4 aliases they were written for (#6044). - `codewhale model resolve` accepts a provider's declared default even when its registry row is missing — `deepseek-flash` failed resolution against the provider that declares it as default — and a test now resolves every provider's `DEFAULT_*_MODEL` for its own provider (#6043). - A configured `default_text_model` is honored when a new thread's route is resolved. That path consulted only the provider's catalog default, so a config naming one model silently created threads on another, and the unset default disagreed with the shipped one; the active provider's configured default now wins, matching `provider_default_model`, and both unset defaults name `deepseek-flash` (#6043). - Markdown `_italic_` requires both delimiters to be flanking per CommonMark, so math subscripts no longer italicize the prose between them (`[t_, b_p]. Actually — hold on, do we even tile all the way from t_?` rendered 60 characters italic) (#6042). - An MCP server configured for OAuth that answers 401 before its first login now points at `/mcp login ` in the failure hint instead of a bearer token that does not exist (#6030). - Cancelling a foreground shell wait stops its owned process group even when the tool future is dropped. Explicitly backgrounded jobs retain their ownership. Interrupted tool receipts distinguish work that started from calls skipped before execution, and returned tool failures remain errors in the next model request. - Saved Fleet model identifiers retain exact spelling through selection, role pins, and roster changes, so changing one saved model does not modify another identifier that differs only in letter case. - Chat wrapping reserves its scrollbar gutter consistently, keeping long identifiers readable when the viewport changes. - The Engine keeps large send-message futures off the event loop's stack, preventing stack exhaustion when a restored session starts a provider turn. - New, imported, and live session titles skip runtime handoffs and use the first real user prompt. Explicitly renamed titles retain priority (#6012, thanks @SparkofSpike). - UI dispatch acceptance now precedes Engine execution, so a delayed acceptance callback cannot overwrite a turn that has already started or completed. Cancelling before acceptance preserves the prompt and leaves the next dispatch usable. - Bottom-chrome effort is omitted when the route cannot prove an effective tier; `/status` retains the full explanation. Cost remains visible when known, and `cost: unknown` remains on metered routes lacking a reading (#5950). - Pasting multiline text is one paste again. 0.9.12 gated the paste-burst heuristic off whenever bracketed paste was *requested*, but a terminal can accept `EnableBracketedPaste` and still deliver a paste as individual keystrokes — on those terminals (observed on Windows 11) every pasted line was submitted as its own message. The heuristic is again armed whenever `tui.paste_burst_detection` is on, and the existing `bracketed_paste_seen` guard still disarms it for the rest of the session once a real `Event::Paste` arrives, so fast typing on terminals with working bracketed paste is unaffected (#5981, thanks @nsfoxer). - `serve --acp` no longer breaks strict JetBrains clients: the `initialize` response advertised `sessionCapabilities.list` as a boolean and carried an undefined nested `load` capability; it now sends `{"list": {}}` with no `load` key, per the ACP schema (#5969, reported by @Lujc0523). - Concurrent Codewhale instances no longer destroy each other's queued, unsent text. The offline input queue was one global file that boot cleared on session-id mismatch, so a second instance deleted the first's parked messages. Queues are now keyed per session (mirroring per-session checkpoints), an existing global file is adopted by its owning session rather than discarded, and the adoption race between two instances of the same session tolerates the loser's cleanup. - A tool call truncated at the provider's output limit can no longer be repaired into valid JSON and executed: repairs that had to synthesize structure (append or discard closers) are routed to the existing malformed-arguments path so the model is asked to re-issue — including when the stream is cut before the closing content-block event (#5986). - `codewhale metrics` reads Codewhale's own receipts again: the deepseek-home fallback resolved `$HOME/.deepseek` unconditionally, so the rollup reported all zeros from a directory nothing has written since 2024. The Codewhale audit log is primary, with a checked legacy fallback. - The goal-continuation loop's promised stall bound actually bounds stalls now, and undeclared fleet role names fail closed to read-only `explore` in both fleet drivers instead of resolving to write-capable customs in one and not the other. - `allow_insecure_http = true` under a `[providers.]` table works again. 0.9.12 tightened plain-HTTP base URL handling in a way that silently dropped the per-provider key, leaving the process-wide env var as the only opt-in — LAN llama.cpp and internal-gateway users had to export `CODEWHALE_ALLOW_INSECURE_HTTP=1` to connect at all. The key is honored again (parsed, settable and unsettable through `codewhale config set providers..allow_insecure_http`, and listed in the custom-provider field hint), it stays distinct from `insecure_skip_tls_verify`, and the refusal message now leads with the config key. Loopback hosts remain auto-allowed and telemetry endpoint validation deliberately still consults neither switch (#5991, thanks @Gabriel-Degret). - A Fleet task that selects a roster member with `worker.agent_profile` now runs with that member's posture. The launch-time resolver only consulted the resolved member when the legacy `worker.role` label was absent, so a task labelled `manager` that selected `member:reviewer` ran as a write-capable manager instead of a reviewer and was never leased. The member's canonical slot now wins whenever one resolved; the label remains the posture only when no member resolved at all. To keep the fix from widening authority in the mirror case (a read-only label on a write-capable member), a spec whose `worker.role` names a different posture than the selected member's role is rejected at run creation with a message naming both postures; casing and legacy aliases of the member's own role are still accepted (#5945, thanks @gaord). - A queued message keeps one transcript entry from queue through steer to dispatch. It no longer reads as delivered while it is still pending, and the second Enter the strip prompts for no longer paints a duplicate bubble. - The Tasks rail panel no longer swallows the first keystroke of typed input: bare `y`/`Y` yank only when the work surface holds keyboard focus, so a message that starts with "yes" stays intact (#2000). - `wait` results reach the parent intact. The parent-context summarizer projected every `agent` tool result through the sub-agent snapshot renderer, which replaced a wait envelope's `settled`, `still_running`, `timed_out`, `waited_ms`, and `note` with `unknown (agent) status=unknown`. Only snapshot-shaped results are summarized now. - A sub-agent's final summary uses the same adaptive tool-result budget as every other tool result (`tool_result_max_bytes`, 12k floor, 2 MiB ceiling) instead of a hardcoded 12k/4k/4k copy that cut a 12,001-character report to 8,000. - The metrics line no longer carries a permanent `/help` hint. The route still appears until its binding has been used and then retires with the other footer hints, so the row stays quiet once help is learned. - `request_user_input`'s description names when asking is the right move (ambiguous scope, an irreversible or expensive choice, a missing preference) and when it is not, so the model stops guessing at discoverable facts. - `config.example.toml` states the real search default (keyless Firecrawl, not DuckDuckGo) and the preferred `CODEWHALE_SEARCH_*` environment names. - Startup type-ahead is preserved whole, and a slash command interrupted by startup keystrokes is no longer re-read as prose and sent to the model (#5925). - The model picker renders a large catalog without lag and supports per-column sort and mouse selection (#5975). - Session metrics report effective request throughput from provider receipts instead of a live estimate divided by the whole turn, and cost stays honest when a route has no price reading (#5976, #5977). - An offline-queue submit delivered as late raw keystrokes no longer wedges the composer behind stacked session notices (#5999). - Fleet setup with a model filter that matches nothing renders a hint instead of panicking (#5953), and shortlist enrollment plus authoritative role pins are honored on dispatch (#5915). - A mid-turn MCP catalog refresh keeps the tool pool deferred and the active set narrow (#5939). - Computer Use on macOS verifies application activation before sending keystrokes and guards input by the frontmost app (#5927). - Onboarding tests isolate `CODEWHALE_HOME`, so a fixture provider can no longer leak into the real setup state (#5932). - Snapshot availability is retained with one warning per session, and a diverged engine session id is a visible notice rather than a log line (#5930). ### Changed - How long Codewhale waits for a human is configurable. `[tools] user_input_timeout_seconds` governs the wait for an approval decision or a `request_user_input` answer; it was a hardcoded 300 seconds, which silently cancelled the work of anyone who stepped away mid-task. An explicit `0` waits indefinitely, the value is clamped to 24 hours, and omitting the key keeps the previous 300-second default. Documented in `docs/CONFIGURATION.md` ([#6003](https://github.com/codewhale-hq/Codewhale/issues/6003)). - `docs/PROVIDERS.md` lists every beginner setup template, not the four it happened to mention when the page was written. Baseten, Groq, Cerebras and Command Code have shipped as supported OpenAI-compatible hosts for a while and appeared nowhere in the provider documentation, which reads from outside exactly like not supporting them. The page now carries the full table — host, default model and key env for each — and states the rule it follows: a plain Chat Completions backend is a template row, while `ProviderKind` is reserved for distinct wires. A test now fails if a shipped template is missing from that page. - Reasoning capability for the Kimi coding routes and the qwen3.x Model Studio deep-thinking ids is catalog data now rather than hardcoded match arms, and `model_reasoning_capability` reports a model nothing knows about as unknown instead of silently not reasoning-capable. `model_supports_reasoning` keeps its `bool` shape for existing callers, where unknown still reads as false. The ids that have no cited source yet keep their literal arms (#6032). - The website uses Shannon Sans with versioned local font assets and retained serif, monospace, and language fallbacks. Terminal fonts are unchanged. - `codewhale metrics` reports recorded model requests and stream recovery separately from provider-reported token usage, with coverage for missing and duplicate receipts. Status messages and cumulative snapshots do not add requests or count tokens again. - Runtime turn receipts retain the Engine's terminal model-request, stream-retry, and resume counters separately from displayed status and provider-reported usage. These counters do not count HTTP retries inside a provider client or establish provider billing. - Initial tool definitions no longer repeat shell interpreter guidance and agent lifecycle/scope instructions in multiple description fields. Parameter schemas, approval rules and dispatch behavior are preserved. This reduces prompt schema size; it does not establish a provider billing regression. - The built-in Computer Use plugin bundle is refreshed to the standalone plugin's 0.2.1 runtime (vendored from `Hmbown/codewhale-cu-plugin` at `724ad258`): the native macOS accessibility backend with an a11y-first pointer strategy (covered points are refused, previews are drawn), the permission-owning desktop-app socket transport, remote computers over ssh and HarmonyOS HDC with contained temp handling, truthful win32 PowerShell failure reporting, and the shared allow-listed request handler for the app socket and ssh agent. The bundle retains the hardening port from [standalone plugin PR #12](https://github.com/Hmbown/codewhale-cu-plugin/pull/12). Single left clicks on macOS element targets now revalidate and press the observed element directly, without substituting a point hit-test or raw-pointer fallback. Explicit event clicks retain the app-ownership guard; a sent press still requires visual verification. Background mode permits application-bound keys and accessibility actions while refusing shared-pointer gestures; it does not provide an isolated desktop. The embed list gained the five new runtime files, and a consistency test now pins the embed list to the vendored tree so the bundle cannot rot silently again. Because the bundle's content hash changes, Computer Use deactivates and asks for a fresh review after upgrading — that is the designed fail-closed path for a desktop-driving plugin. The current macOS source candidate also embeds the compiled native helper, so its bundled server can run directly without a separate Computer Use app or a compiler on the user's machine. Accessibility and Screen Recording permissions belong to the hosting app or terminal and remain user-controlled. The CLI's Computer Use server requires Node.js 20 or newer. These are source candidate changes; they do not establish published-package or platform qualification. See the [included plugin guide](crates/tui/plugins/computer-use/README.md) for platform requirements and limitations. - `/statusline` drives the bottom chrome again. Since the 0.9.12 shell redesign the posture bar and the metrics line were built independently of `tui.status_items`, so every toggle in the picker except the balance fetch was decoration. Each remaining item now shows or hides exactly one thing: `model`, `context_percent`, `cost`, `balance`, `cache`, `tokens` and `session_metrics` are metrics-line segments, and `mode` is the posture bar's plan/act/operate chip. The `status`, `agents`, `reasoning_replay`, `prefix_stability`, `git_branch`, `last_tool_elapsed` and `rate_limit` items drove nothing and are retired; an existing `config.toml` still loads and those keys are ignored (#5950, #5962). - The context reading is back on screen at every fullness. 0.9.12 painted `ctx NN%` only from 50% up, which left most of a session with no context signal at all; it now paints from 0% and keeps its warning colour from 80% up (#5950). - A child agent parked because its parent's turn ended is shown as `parked` in the Agents panel, the sidebar and Agent Details, with `resume_from` / `cancel` as the recovery, instead of wearing the same "waiting for input" label as a child that asked a question. Parked work sorts below live and answerable work and no longer inflates the `blocked` chip; the receipts roster and the wire `state` gain `parked` (#5906, #5921). - `codewhale account keys set|remove|list` no longer carry a hardcoded eight-provider list. Provider ids come from the control plane's public catalog (`GET /api/model-providers`), are validated locally against `^[a-z0-9][a-z0-9-]{0,63}$` before they reach a URL path, and `list` shows every catalog provider with its label and stored-key state. `--from-local` maps a catalog row onto the local runtime provider through the catalog's own `runtimeProvider` field, so a newly supported provider needs no CLI release. - `/mcp` lists the servers that need a login first, as their own `Needs login` group above `Needs attention`, and opens with the cursor already on the first such row so the Enter the screen advertises runs `/mcp login ` straight away; translated in all 15 packs. A snapshot test pins the footer shape the chip landed with (`MCP · N connected · N ◆ auth required · N failed`) so an expired login never regresses into the failed count (#5926). ### Fixed - Five of the load-flaky tests tracked in #5929 no longer depend on shared state or live local daemons. Background-hook capture tests wait for the capture file to hold bytes instead of merely existing (the shell's `>` redirection creates the file empty before `cat` writes, which read as `valid JSON: EOF` under load); the session-picker acceptance test drives the real picker over a private store instead of a process-global `CODEWHALE_HOME` redirect that concurrent tests could observe mid-flight; the DeepSeek-Anthropic translate test holds the test env barrier so its request-time and assertion-time `max_tokens` reads cannot straddle another test's `CODEWHALE_MAX_OUTPUT_TOKENS` override; the unit-test binary no longer probes a real local Ollama daemon (`127.0.0.1:11434`) from the fire-and-forget provider catalog refresh, whose merged tags could flip another test's live-snapshot assertions; and the tmux clipboard test's attach/OSC 52 wait bounds tolerate a fully loaded machine (3s -> 30s) without changing what they verify (#5929). - The posture bar states how long the session has been working and how long the current turn has run, distinguishing actively working from waiting on a tool, a sub-agent or the operator; the 0.9.12 shell had dropped the overall working-time indicator from the place a glancing user checks (#5914). - A background runtime turn whose own store record could not be read, parsed or written (`Failed to read turn …`, `Failed to read item …`) was only a log line. The runtime now publishes a `runtime.store_failure` event naming the file, the root cause and the next action (move the file aside, or check free space and permissions); the TUI shows it as a warning toast and a transcript line, the task timeline records it, and the runtime API streams it. A turn whose own record is unreadable or unwritable is reported as terminal, so its task fails at once instead of idling out (#5931). - An MCP token refresh that fails to parse the provider's answer keeps the endpoint's receipt — status line, content type, and a 200-byte excerpt with every credential-shaped value (`access_token`, `refresh_token`, `client_secret`, `id_token`, bearer schemes) masked before the cut — instead of rmcp's bare `Failed to parse server response`, so a provider outage answering an HTML 502 reads differently from a parser defect, and the login remedy stays named (#5926; remedy wording landed in #5959). ### Added - `POST /v1/threads/{id}/file-revert` restores exactly one file from the exact `tool:`/`pre-turn:` snapshot the client selected, checking the reviewed file hash before and after the mandatory safety snapshot. Literal file names, regular files only, thread trust and active-turn admission are enforced, and `patch-undo` no longer forks a conversation whose file rollback failed (#6111, thanks @gaord; engine half of HengQuWorld/CodeWhale-VSCode#3). - Authenticated Runtime API workspace file suggestions reuse TUI `@file` matching and discovery, with bounded queries/results and workspace-contained relative paths only (`GET /v1/workspace/files/search`, #6095, #6120, thanks @wuisabel-gif; reported by @LmeSzinc). Shared discovery now honors disabled symlink following for AI-tool directory scan roots too. - Serply is available as an opt-in `[search]` provider for the Web tool (`provider = "serply"`, key from `[search] api_key` or `SERPLY_API_KEY`). Preflight fails closed without a key; Firecrawl remains the default and existing configurations are unchanged (#6100, thanks @googio). - Linux terminals: finishing a transcript or composer mouse selection copies the text to the PRIMARY selection without touching the regular clipboard, and middle-click inside the composer pastes PRIMARY at the pointer without submitting. Native X11 and Wayland data control are used through one bounded background worker; SSH sessions without a forwarded display keep their terminal's own selection behavior (#6116, thanks @dmt4). - `codewhale sessions export ` saves a `.tar.xz` archive with the durable record, portable session container, manifest and artifacts. Prefix exports preserve unfinished tool calls; confined reads reject linked artifact roots, and existing outputs require `--force`. Archives retain unredacted content; `/load` opens the extracted record without installing extracted artifacts (#6056, thanks @h3c-hexin and @asto18089). - `deepseek-flash` (DeepSeek V4.1 Flash: 1M-token context, reasoning and tool calls) joins the catalog as DeepSeek's declared default, and the offline catalog seed matches it; the DeepSeek Pro listing no longer overstates the published price (#6025). - DeepSeek's September 11 reversal is reflected in provider notices and cost estimates: V4 Pro remains available after September 14 at Pro rates. Explicit Pro selections remain unchanged; Flash remains the default (#6025, thanks @ronohara). - Native plugin authoring guides now cover English and Chinese. The explicit offline converter supports selected portable Skills and static Streamable HTTP MCP declarations from OpenCode and DSH. Unsupported executable hooks, automatic OAuth and policy-bearing configurations are refused; generated bundles still require native installation, review and trust. Legacy SSE fallback is not reproduced (#5827, requested by @giancarlocp). - Signed cloud model facts can refresh provider capabilities and prices while preserving verified cached data when a refresh fails. A dispatched request keeps its selected price snapshot so later catalog updates cannot change its recorded cost (#5752). - Saved sessions preserve exact provider routes. Auxiliary model calls settle their usage once against the route and price snapshot that executed them, including recovery, rather than resolving a new price at completion (#5726, #5848). - `[tui].posture_bar` and `[tui].metrics_line` accept `full`, `compact`, or `hidden`, also available through `/config`. Compact preserves the existing rows' essential fields; hidden returns their space to the transcript (#5973). - Optional model-bound tool-output redaction opt-out, with two explicit startup confirmations and a receipt bound to the readable config contents and modification time. Unconfirmed requests keep masking enabled; routing and stored goal summaries remain redacted (#5982, thanks @SparkofSpike). - The `rusty-alloc` cargo feature on `codewhale-tui` and `codewhale-cli` opts the binaries into the `rusty_alloc` global allocator (the mimalloc v2.4.5 architecture remade in pure Rust — no C compiler or build script on that path) instead of the default mimalloc. It is off by default and the default build is unchanged; build with `cargo build -p codewhale-tui --features rusty-alloc` (#5872). - The `/theme` picker now discovers valid user-authored `custom:` overlays, previews their colors, highlights the active overlay, and preserves it when the picker is opened and committed without navigation (#5901). - Compaction has two standing knobs next to `[context]` in config.toml: `[compaction] summary_instructions` (appended to the summarizer prompt on every manual and automatic pass; `/compact ` still composes after it) and `[compaction] retained_user_message_tokens` (default 20 000, clamped 2 000..=200 000) for the verbatim user-message budget. Both are absent by default and absent means the pre-existing behavior. The `/compact` receipt names the effective budget and whether operator instructions applied (#5956). - `[tools] user_input_max_questions` (default 6, 1..=10) and `[tools] user_input_max_options` (default 4, 2..=10) replace the hard-coded `request_user_input` limits; the validator, the tool schema and its description read one value, spawned children inherit the parent's ceilings, and a rejected payload names the ceiling it hit and the key to raise (#5949). - The slash menu shows a command's usage line and its subcommands as soon as a space is typed after the verb, filtered by what follows, so Tab completes `/workspace wor` to `/workspace worktrees`; `/help` states the focused command's usage in its detail slot (#5952). - The three `/fleet` views (roster, live workers, saved teams) are one back-navigable stack: `Esc` in workers or saved teams returns to the roster with its cursor intact and still closes the window at the root or on direct entry; the `Esc` footer hint says `back` or `close` accordingly (#5954). - `/fleet` presents its prioritized core (`members`, `setup`, `teams`, `workers`, `help`); every other verb stays dispatchable and is documented under explicit groups in `/fleet help`. The roster no longer shows the untouched built-in `general` alias next to `worker` (#5888). - `codewhale` provider: account-backed model access over the provider keys a customer connected to their Codewhale account. One base URL (`https://api.codewhale.net/v1`, overridable with `CODEWHALE_API_BASE`; HTTPS required except on loopback), one `cwc_key_…` account API key with the `models:infer` scope (`CODEWHALE_API_KEY`), and a per-model wire chosen from the account's authenticated `GET /v1/models`: ids are `provider/model` and each row states `chat-completions` (`/v1/chat/completions`) or `anthropic-messages` (`/v1/messages`). Both protocols authenticate with `Authorization: Bearer`, never `x-api-key`. The key is read from `CODEWHALE_API_KEY`, the `codewhale` secret-store slot, or `[providers.codewhale] api_key` / `api_key_env`, and a missing key fails before any request instead of dispatching unauthenticated. If the catalog cannot be fetched the route falls back to three bootstrap ids and says so. - `codewhale account api-keys create --scope` now accepts `models:infer` alongside `account:read` and `agent:run`, and an omitted `--scope` sends all three explicitly. `--use` saves the new secret as this machine's local `codewhale` provider credential in the same secret store `codewhale auth` uses; nothing is uploaded. - `Git` grows a `commit_plan` action: a propose-only planner that splits the working tree into ordered atomic commits (#3999). It groups whole files — lock files ride with their manifest, tests ride with the source they name — orders the groups so a commit that defines a symbol lands before the commit that uses it, and refuses the whole plan when that dependency graph has a cycle. It reads `git diff HEAD` plus the untracked-file list and writes nothing: no `git add -N`, no `git apply --cached`, no `git commit`, so staging and committing stay with the ordinary `git add` / `git commit` shell path where the approval gate already applies. Thanks [@goransh-walia](https://github.com/goransh-walia) for the original implementation (PR #5870, fixes #3999). ### Contributors - **[@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)). - **[@googio](https://github.com/googio)** — added the Serply web-search provider ([#6100](https://github.com/codewhale-hq/Codewhale/pull/6100)). - **[@dmt4](https://github.com/dmt4)** — requested Linux copy-on-select and middle-click paste ([#6116](https://github.com/codewhale-hq/Codewhale/issues/6116)). - **[@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)). - @nightt5879 — Gemini signature recovery guidance and transport regressions (#6081). - @c020627 — Chinese documentation link repairs (#6080). - @h3c-hexin and @asto18089 — GLM-5.3 reasoning controls and tool-gating/documentation fixes (#6051, #6052). - @Hmbown — dependency updates (#6057) and the Gemini signature recovery report (#6048). - **[@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)). - **[@goransh-walia](https://github.com/goransh-walia)** — contributed the propose-only commit-planning rework ([#5870](https://github.com/codewhale-hq/Codewhale/pull/5870)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@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)). - **[@Nefelibata1024](https://github.com/Nefelibata1024)** — confirmed the multiline-paste regression's impact ([#5981](https://github.com/codewhale-hq/Codewhale/issues/5981)). - **[@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)). - **[@Lujc0523](https://github.com/Lujc0523)** — reported the ACP initialize schema violation affecting strict IDE clients ([#5969](https://github.com/codewhale-hq/Codewhale/issues/5969)). - **[@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)). - **[@giancarlocp](https://github.com/giancarlocp)** — requested a plugin authoring guide and OpenCode plugin conversion ([#5827](https://github.com/codewhale-hq/Codewhale/discussions/5827)). - **[@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)). ### Notes - **DeepSeek V4 Pro continues after September 14.** The vendor reversed its earlier retirement notice. Codewhale preserves Pro selections and Pro pricing; `deepseek-flash` remains the default for new direct DeepSeek configurations. - Upgrading from 0.9.12 with Computer Use trusted and enabled: the bundle's content hash changes with the 0.2.1 refresh, so the plugin deactivates and asks for a fresh review — that is the designed fail-closed path for a desktop-driving plugin. Re-trust it from the Plugins page. - The multiline-paste fix restores v9.11 behavior on terminals that accept `EnableBracketedPaste` but deliver pastes as keystrokes (reported on Windows 11 / PowerShell). Verified at the input-contract level and in CI; a manual paste check on a real Windows terminal is still welcome — please comment on #5981 with your terminal if anything still misbehaves. ## [0.9.12] - 2026-09-03 Codewhale v0.9.12 puts computer use in the binary, opens two new routes — Alibaba Model Studio through the data-driven provider table and Concentrate as an opt-in BYOK Responses gateway — and adds cloud dispatch plus a config-gated per-session control socket. The shell is the other half of the release: a new launch card, the work surface docked under the composer, one focus owner for Tab, tool cells that carry their own state, and `fleet` as the public word for the live collective. The complete item-level change record is retained below the categorized release highlights. ### Added - Computer use ships with the binary. The `computer-use` plugin — 38 tools across macOS, Windows, Linux and HarmonyOS, accessibility-first observation with pixel fallback, screenshots, zoom, screen recording, and registered remote computers over ssh and hdc — is embedded in Codewhale and written to `$CODEWHALE_HOME/builtin-plugins` on first run, so every install channel carries it. It lists as `builtin · not-reviewed` and stays disabled until you review and enable it: shipping it is not consenting to it. The stdlib-Python computer-use server it replaces is gone. - Alibaba Model Studio joins the data-driven provider table as an `openai-compatible` descriptor: international compatible-mode endpoint, `DASHSCOPE_API_KEY` credential, live `/v1/models` discovery. Qwen 3.8 Flash and Qwen 3.8 Max arrive through the catalog authority — never a hard-coded id. - Concentrate: first-class opt-in BYOK Responses gateway with live models discovery and typed SSE streaming (#5725). - Cloud dispatch: remote runner offloads coding agent tasks to isolated cloud sandboxes with machine token auth and structured job tracking (#5701, #5712). - Per-session control socket: config-gated `[control_socket]` table binds `//control.sock` per running session, exposing message, interrupt, relaunch, and status JSON-RPC verbs (#5533, #5831). ### Changed - **Anonymous usage counting is on by default.** The 0.9.11 release asked first; 0.9.12 counts the same aggregate version/platform, session, feature and error totals unless you turn it off, and says so once at first launch (policy notice version 5, schema 3, `notice_version` replacing `consent_version`). Every recorded opt-out stays off: a durable `telemetry = false`, a decline recorded under the old opt-in notice, unreadable privacy state, and the `CODEWHALE_TELEMETRY=0` / `--telemetry false` kill switches. Showing the disclosure records only that it was shown, never an acceptance. `codewhale config set telemetry false` turns it off and wipes queued counts; `codewhale config set telemetry true` deliberately re-enables it. Nothing new is collected: no conversations, code, prompts, files, names, model content, credentials, or IP. - The launch screen is our own card take: a thin top line `⑂ branch path`; a centred bordered card with the whale mark, `Codewhale` + version, one announcement line only when it is true (the no-model warning, or MCP news), and the menu New worktree / Resume session / Changelog / Quit with their real chords right-aligned. Enter runs the highlighted entry, Up/Down move it, and typing goes straight to the composer. The card dissolves on the first keystroke or command (≤240 ms, instant under reduced motion) (#5826, #5801, #5815, #5286). - The work surface sits under the composer by default, keeping history readable and leaving the stage unencumbered (#5809). - Skills command shapes: FEAT-022 command shapes and retained-host validation (#5825, #5829). - After the card dissolves, the working screen shows `⑂ branch path` with `⋮ MCP n/m` on the right, the transcript starts with the `◆ session_start` receipt (naming the configured session-start hooks), and the composer's bottom rule carries `model (effort) · permission` — the route's one launch reading. The posture bar and metrics line appear only once a session exists. - Vocabulary: `fleet` is the public term and `Pod` is retired from copy — roster, setup, detail, worker-runtime and managed-API messages now say Fleet (`/fleet` canonical, `/pod` alias). The workflow wire accepts the canonical role spellings (general/explore/planner/reviewer/implement/ test/advisor) with the pre-rename ones kept as load-time aliases, and serializes canonical names. - The Operate mode-picker hint is shortened to fit 80 columns. - The footer always shows the permission posture; when only one chip fits, the permission chip outranks the mode word (#5796). - Local Ollama: the header names a model only when the local catalog can serve it, and says `unknown` until it knows. The startup mark, web and app icon carry the new side-view prompt-eye whale (#5795). - One focus owner: Tab and Shift+Tab work regardless of what is in the composer; Alt shortcuts survive mid-draft; Ctrl+Tab no longer cycles the mode by accident (#5798). - Tool cells carry their own state: a running, failed or warned tool reads as such in the transcript itself, with per-entry rail dots and family-coloured glyphs (#5799). - Web: docs hub with task search, shared empty/loading/error states, an offline-to-back-online banner, `/changelog` in every locale, and real 404s with correct metadata (#5743). - Web: the app's colours come from one file generated from the TUI whale palette; re-typing a colour by hand fails web CI (#5797). - Web: a one-way ceiling on `isZh` branching outside the i18n spine — the count may only go down (#5805). - An internal agent handoff doc was removed from the public tree and `.playwright-mcp/` is now ignored (#5800). - First run paints the composer immediately: the Welcome/language/provider/ trust gates no longer precede the first keystroke. Missing-key and workspace-trust recovery stay for returning users; language and provider remain in `/setup`. - The canonical whale-tile mark propagates beyond web to the exact-raster surfaces that can carry it (#5738). - Dead-code sweep: delete proven-unreferenced helpers (unused builders, wrappers, and leftover identifiers) and drop stale `#[allow(dead_code)]` where the item is production-called or test-exercised. No runtime behavior change (#5791, #5587). - Remote-control recovery gives every fresh pre-dispatch attempt a new lease generation while preserving that generation across its typed start (#5605). - Public roster language is Pod. `/pod` is the customer surface; fleet remains the internal wire, storage, and migration name (#5776). - Compaction replacement history keeps a bounded last user round (assistant + tool results) instead of dropping them behind a summary. `/context` names the compaction path and `/anchor` survival. Failed compact still does not replace live history (#4394). - Provider catalogs: compatible hosts (Baseten, Groq, Cerebras, SenseNova, Command Code) no longer compile a frozen model roster. Descriptors name the wire, URL, and env; live `GET /v1/models` and a Codewhale-owned catalog layer are the offering list. Command Code is a catalog/descriptor row, not a `ProviderKind`. Catalog presence is not an availability, entitlement, or provider-acceptance claim (#5783). - Provider selection no longer probes or adopts an external CLI credential on ordinary picker use. Reuse requires an explicit "Use external CLI credentials" choice, exact-path confirmation, and Codewhale-owned revoke (#5772). - TUI: startup no longer presents an approximate ASCII or block-glyph whale as the product mark. It keeps the direct Tideline prompt while exact-raster surfaces remain responsible for the canonical asset. - TUI: the active-session composer paints the same three-cell `[↑]` send target as Startup and clicks it through the existing Enter submit dispatcher (#5771). Compact/quiet composers still omit the control. - TUI/CLI: Pod is the public roster surface. User-facing Fleet wording moves to Pod; durable receipt keys stay compatible (#5776). ### Contributors - **hexin ([@h3c-hexin](https://github.com/h3c-hexin))** — provider-native web search across four routes (#5682, #5683, #5685, #5687), authoritative edit-last-turn boundaries (#5621), Kimi Code k3-256k (#5622), post-compaction input-token reporting (#5623), and preserving the scheduled model selection in automations (#5650). - **秋月凉梦 ([@qiuYliangM](https://github.com/qiuYliangM))** — co-authored the edit-last-turn boundary fix (#5621), Kimi Code k3-256k support (#5622), and post-compaction input-token reporting (#5623). - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — live session token totals (#5624), persisted context-pressure warnings (#5629), discoverable Fleet roster editing (#5604), the capability-gated cursor accent (#5599), and `/copy` for the latest completed response (#5692). - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** — Windows verbatim-path operands preserved through POSIX word splitting (#5610), the plugins group moved onto the command shapes (#5657), FEAT-022 skills command shapes with retained-host validation (#5825), and FEAT-020 plugin command shapes re-landed on main (#5865). - **Alex Musichen ([@musichen](https://github.com/musichen))** — a stable DeepSeek heading in the configured-view model picker, keeping every official catalog model for the active provider visible (#5689). - **[@gaord](https://github.com/gaord)** — the `GET /v1/fleet/profiles` runtime API endpoint, reusing the FleetManager validation path (#5688). - **Sh1Zuku ([@SparkofSpike](https://github.com/SparkofSpike))** — corrected English documentation inaccuracies and the first zh_hans translations for the Tier-2 docs (#5613). - **[@M-Maciej](https://github.com/M-Maciej)** — goal continuation cadence (#5591) and the per-session control socket (#5533, #5831). - **Serephus ([@serephus](https://github.com/serephus))** — nixpkgs update (#5669). - **[@whp233](https://github.com/whp233)** — `wire = responses|anthropic` for openai-compatible custom routes and opencode-zen muse-spark (#5716, landed as #5719). - **Gabriel Degret ([@Gabriel-Degret](https://github.com/Gabriel-Degret))** — found the reasoning-only retry gap and built the first fix; landed as the `[reasoning_only]` retry ceiling with a request-scoped nudge (#5867). - **[@huangxianzhan](https://github.com/huangxianzhan)** — the `x-opencode-session` header for OpenCode Go and Zen gateways (#5868). - **[@zhuowp](https://github.com/zhuowp)** — task origin preserved in job snapshots (#5869). - **AdityaG ([@AdityaVG13](https://github.com/AdityaVG13))** — a ten-commit performance pass: a zero-copy LaTeX fast path for streaming render, single-pass token accounting on the per-turn pressure paths, memoized provider resolution in the catalog cutline, parsing the bundled and on-disk models.dev catalogs once per process (interactive boot -70%), adaptive poll cadence for foreground shell completion, and worker caps across the read-only diagnostic family. - **Nightt ([@nightt5879](https://github.com/nightt5879))** — isolated remote recovery lease generations (#5790). - **[@yiheng-kkk](https://github.com/yiheng-kkk)** — replaced stale todo transcript snapshots so a rewritten todo list renders its current tasks (#5871, #5873). - **[@Lfanxing](https://github.com/Lfanxing)** — Moonshot routes now degrade incompatible tool definitions per request instead of failing the turn. - **WissssleyL ([@Lstarsky0](https://github.com/Lstarsky0))** — moved `docs/subagents` and `docs/mcp` onto the dictionary spine (#5337), with the metaTitle probe that keeps them there. Reports and reproductions that shaped this release: - **[@slowly247](https://github.com/slowly247)** — reported the Ollama input budget collapsing to 1,024 tokens on 32K local models (#5820). - **[@ronohara](https://github.com/ronohara)** — reported the engine stopping after recoverable network errors, with the reproduction that pinned the discarded approval (#5769), and surfaced DeepSeek's model-service notices and the subsequent reversal retaining V4 Pro (#6025). - **[@Lujc0523](https://github.com/Lujc0523)** — asked for ACP session configuration of mode and model (#5863). - **[@senka9h](https://github.com/senka9h)** — reported that `serve --acp` lacked `session/list` and `session/load` (#5864). ### Added - Native ChatGPT sign-in for the `openai-codex` route: `codewhale auth chatgpt` opens a browser PKCE flow and stores refreshable tokens in Codewhale-owned credentials — no Codex CLI install required. `/auth chatgpt-revoke` clears them off the event loop (#5784, #5778). - MCP servers and plugins can be connected self-serve from the session: a unified auth flow with rotation-safe token handling, a spoken authorization URL, and catalog refresh when stored credentials stop working (#5747). - `/operate` reads match the landed CWC `OperateRecord` contract: fetching an absent record returns a truthful not-found view instead of a fabricated operation, and an empty evidence path is rejected rather than resolving to the workspace directory (#5703). - TUI: scheduled automations project into the top strip (`⏱ N scheduled · M running`, compact `⏱ N·M`) with typed `HistoryCell::Automation` receipts when a run this session watched settle. `/automation` acknowledges failures. The merged footer does not carry the work fact (#5748). - The app-server can listen on a unix domain socket and advertise a `daemon/attach` handshake, so a local client can attach to an already-running engine instead of spawning its own. The socket is created with owner-only permissions and stale sockets are reclaimed on start. Non-unix hosts return a typed unsupported-platform refusal; the Windows named-pipe endpoint is named but not yet implemented (#5749). - The engine's internal `Op`/`Event` types and the wire protocol's `Op`/ `EventMsg` now carry a compile-enforced twin for every variant: adding an engine variant without a protocol counterpart fails the build instead of drifting silently. Internal durability work — no user-visible surface change yet (#5751). - Machine tokens: with `CODEWHALE_API_KEY` set, the CLI authenticates as the Codewhale account with no local session file and no browser — the CI authentication path, with a typed token shape and redaction (#5721). - Compaction publishes a structured survival contract for session-tree journal entry types (`crates/tui/src/compaction/SURVIVAL_CONTRACT.md`) and fails closed when the last user round, tool results, `/anchor` text, or checkpoint receipt would vanish (#4394, #5782). - Internal: `codewhale-config` gains `RouteAuthoritySnapshot`, one immutable authority that owns a compiled provider catalog together with the route resolver projected from it, so a picker, a readiness view, and an execution path can no longer resolve against different catalog snapshots without a type-level signal. Resolution still goes through the sole resolver; the returned receipt distinguishes an exact catalog row, a custom-endpoint route whose provider facts are deliberately not reused, and an allowed pass-through route with no catalog row. All state is secret-free. No call site changed and no user-visible behaviour changed yet (#5766). - Computer session records now count only time a provider actually accepted the session as active, at per-second granularity. Idle, queued, stopped, and teardown time are excluded, and a session whose allocation does not match a standard profile is refused rather than recorded approximately. Covered by hermetic fixtures; no live provider call and no deploy (#5781). - Website: the public site moves to the Tideline deep-ocean design language (dark by default with an opt-in light documentation sheet, palette grounded in the TUI's WHALE_* tokens) and the new whale brand mark across the favicon, app icons, web manifest, nav wordmark, and social card (#5573). - Add `codewhale dispatch` / `/dispatch` so a local session can propose a Codewhale cloud agent against an explicit `github`, `cnb`, or `gitee` remote. Confirmation is required; missing credentials fail closed; cloud jobs share the existing `/jobs` surface as `kind=cloud`. See [DAYTONA_CLOUD_DISPATCH.md](docs/DAYTONA_CLOUD_DISPATCH.md). - `/login` reports the Codewhale account session and provider-key next steps. The internal cloud-agent credential is not user surface: there is no `auth set-slot`/`auth clear-slot` command, no hint, and no completion entry for it — signing in with `codewhale login` is the only door. - Add the Tideline component family from the ratatui translation spec (#5698's screens, riding the #5699 work-strip layout): hero startup surface with quick actions and option strip, notifications inbox, merged footer band, pod ledger, receipt stream, theme list with motion toggles, live preview, settings rail, and the left rail — each a standalone render module pinned by 28 new byte-exact golden buffers. Frame wiring follows the Tideline acceptance gate; `NO_COLOR` is now honored by palette depth detection. - Route Contract Phase 1: `RouteResolver` is the runtime path for `resolve_runtime_options`; `codewhale providers export --json` ships the owned descriptor catalog; CLI `--provider` accepts any catalog route id (the closed `ProviderArg` enum is deleted). Catalog layers are bundled → models.dev → provider `/v1/models` → config.toml → user, with policy DENY last and never overridden. - Add provider-native web search for documented Xiaomi MiMo 2.5 Pro and 2.5 chat routes while keeping neighboring models and custom gateways fail-closed. - Add structured provider-native web search for exact Z.AI global and Zhipu China general API routes, using each site's documented search engine value. Existing `open.bigmodel.cn` configurations now share Z.AI's official model namespace and credential scope; unknown model IDs still pass through. - Add provider-native web search for documented Qwen models on ModelStudio Token Plan's Responses Harness, without enabling Coding Plan or Anthropic routes. - Added `/copy` to place the latest completed assistant response on the clipboard without copying tools, system messages, hidden reasoning, or active partial output (#5668). - Add provider-native web search for documented DeepSeek V4 routes through the Responses API, with fail-closed capability gating for compatible custom endpoints. - Add provider-native search for exact Moonshot K3 Formula, legacy K2.6 built-in search, and Kimi Code membership `/search` routes. Treat the exact Moonshot China endpoint as a first-party direct route. - Z.ai `GLM-5.3-Flash` and OpenRouter `z-ai/glm-5.3-flash` are first-class picker rows (`/model GLM-5.3-Flash`). Flash is the faster/explore sibling of `GLM-5.3`; the Z.ai default stays `GLM-5.3`. List price is $0.15/$0.50 per 1M (durable; the 50% promo through 2026-09-09 is not the catalog row). - Baseten, Groq, and Cerebras are bundled OpenAI-compatible setup templates (`[providers.] kind = "openai-compatible"`), not new `ProviderKind` variants. `/provider` fills URL, model, and env from one catalog row. - MCP manager copy now names the server, the failure, and one recovery command (`The X MCP server requires OAuth reauthentication. Run /mcp login X`). - Settings Advanced exposes clickable MCP Connect, Reconnect, and Diagnose actions, while Extensions and Problems route recovery through the existing `/mcp login`, `/mcp reload`, `/mcp validate`, and `/plugin validate` commands (#5643, #5655). - Plugin prompt matching (#5579): sending a task can toast the next review step when the prompt strongly matches an installed-but-idle plugin or a marketplace catalog you added (for example a Supabase prompt suggesting `/plugin trust supabase`). A live composer CTA offers the same review command while you type, matching turns append a bounded `` user block, and `request_plugin_install` surfaces review without installing. `/plugin suggest` now ranks manifest keywords and catalog candidates, never auto-installs, and on-disk plugin changes also nudge `/plugin reload` between turns. - Added `/import-claude` (#5557): reads `~/.claude.json` and `~/.claude/settings.json` read-only and renders an explicit, reviewable migration plan plus a written report. MCP servers route through the existing `/mcp import --approve` consent flow, allowlisted env keys become an unapplied portable bundle for `codewhale config import`, and permissions/hooks map to manual follow-ups; secret-shaped values are named but never echoed or imported. - Added the managed Chat relay: account-owned Chat commands now execute on the native runtime thread engine through a new `runtime_chat_relay` module instead of a second execution path. Each Chat thread is a dedicated, isolated runtime thread with an empty model-visible tool allowlist, a chat-only system prompt, and no workspace, memory, skill, credential, or local-path context; the active interactive TUI thread is never reused. The relay keeps one durable state file per scope behind a session-wide owner lock, binds a saved session permanently to its first remote target, replays exact duplicate commands from retained results instead of starting a second inference turn, terminalizes orphaned reservations on restart, and rejects (never queues into) a busy local Work turn with an immediate retryable result. Stop commands require the exact run and turn identity, and a worker aborts on any account or target mismatch during token refresh. - Added a verified Omarchy/AUR packaging path: `packaging/aur` now carries a `PKGBUILD` template, `.SRCINFO` renderer and tests, release-candidate render step, and docs; the live AUR compatibility alias `codewhale-tui -> codewhale` is preserved, AUR dependencies match the live package, and the self-updater refuses to fight an Omarchy/package-manager installation. - Added a Fleet run-wide cost/token usage ceiling (R6, #5567): an accumulator plus admission gate and alert bound a whole run's spend across workers. - Added the real provider cache hit rate to `/context` (C3, DSH #3): the token-weighted provider-reported rate from the same telemetry `/cache` aggregates, plus an honest "no cache telemetry yet" state when nothing is recorded. - Added per-step cost movement: `TurnUsage` receipts are priced as they land so the live cost surface moves during long agentic turns instead of only at `TurnComplete` (#5578), and the footer now honestly shows `cost: unknown` when nothing can be priced instead of hiding the line. - Added the underwater session surface: the ambient water reads session state from across the room, its animation shape follows live agent activity, and attention tints are steady (no breathing) with a distinct reading treatment and no mid-water seam on tall windows. - Added `@path:START-END` ranged line mentions (#5550, picker half to follow), a predictable last-copy backup file for clipboard exports with the path named when the clipboard fails (#5555), `wait` on multiple background shell tasks with `until=any|all` (#5549, named-kill half to follow), and composer double-click word / triple-click line selection. - Added workflow parallel-`schema` slot partial success (#5583): a slot that produces a schema-valid partial result no longer fails the whole parallel branch. - Added plugin load-failure startup hints (#5579) and OpenRouter app attribution headers on outbound requests. - Added `codewhale doctor --fix` (with `--yes` for non-interactive consent): the doctor now computes a concrete repair plan — delete stale `.tmp*` leftovers from interrupted atomic writes, tighten secret-store file permissions to `0600`, disable structurally broken (Error-status) MCP entries through the atomic MCP save path, and scaffold missing user-global `skills`/`tools`/`plugins` directories — shows it, and applies it only after explicit consent. Every action is narrowly scoped and idempotent; JSON and context-JSON modes stay read-only and conflict with `--fix` (#5552, v1). - Added `/context` reporting of the real provider prompt-cache hit rate (C3) alongside token pressure. ### Changed - Provider-native web search now applies domain constraints before accepting an attempt, discards generated answers when returned citations violate those constraints, and preserves the caller's configured/local timeout as an independent fallback budget (#5681). - Idle session metrics omit zero facts (`0 turns`, `LLM 0s`) until the runtime has evidence. Working chrome says `in the current` instead of a generic `working`. - Deleted nine uncompiled `runtime_contract/` staging files. Live contracts remain `model.rs` and `termination.rs`. - The first #5587 dead-code sweep converts audited test-only helpers to `#[cfg(test)]`, keeping production builds free of test-only APIs without changing runtime behavior. - `/plugin reload` is now discoverable when on-disk plugin bundles change: the next send and `/plugin list` nudge once with `Run /plugin reload to apply` instead of silently keeping the stale catalog (#5579). Trust is unchanged; this does not auto-reload. - Context-pressure warnings and critical alerts now remain visible in sticky UI status until compaction or explicit dismissal, instead of disappearing into scrolling turn metadata (#5620). - The Runtime thread store defaults to a per-session root (`$CODEWHALE_HOME/sessions//runtime`) so multiple Codewhale processes on one machine no longer share one owner lock (#5630). The exclusive lock is unchanged; `CODEWHALE_RUNTIME_DIR` still selects a shared root when that is intended. - Session token totals now include display-only per-model-call deltas while a turn is running, including input/output and cache-class counters; the authoritative `TurnComplete` totals still reconcile exactly once (#5581). - Transcript focus now exposes per-block actions: `y` copies content, `Y` copies the rendered metadata view, Enter opens a fullscreen block pager, and `r` opens raw detail; the existing Tasks rail shortcuts remain unchanged (#5551). - Provider neutrality (#5588): model resolution of omitted/aliased models is now provider-relative, OpenAI-native defaults no longer route through another provider's table, CLI credentials stay provider-scoped, and NVIDIA credentials no longer leak into the DeepSeek keychain. Neutrality test matrices exercise several providers instead of standing in with one. - The workflow engine module was decomposed out of its 3k-line mega-file into `journal`, `usage`, and `report` modules plus a module directory (#5586 slices 1a/B/C/D), a semantic-free move verified by normalized-content hash. - Compaction refusals are now always named (#5577): silent holds under context pressure are gone, the context meter honors the same provider-billed prompt the trigger uses (T1), and prune outcomes are projected without cloning the transcript. - Step budgets now end honestly: an ~80% soft landing nudges the model to write its final report, and exhaustion grants exactly one bounded report-on-exhaustion turn instead of dying silently (A1/A2). - Contributor credit: recognized agent contributors (e.g. `Codewhale Agent`) may now carry `Co-authored-by` trailers; unknown bot/tool trailers are still rejected by the credit gate. ### Fixed - Read-only Fleet workers no longer send `"action": {"enum": null}` in their projected `bash` schema. The read-only projection probed the action enum with a mutating index, which auto-vivified the key on schemas that have no action property, and strict OpenAI-compatible validators then rejected the whole request (`null is not of type "array"`). The probe is non-mutating now, in both the read-only projection and the `Run` arm next to it, and a regression test walks the whole projected catalog for nulls (#5944, thanks @gaord). - Fast typing no longer corrupts the composer. The paste-burst heuristic ran on every session until a real bracketed paste arrived, holding, buffering, retro-grabbing, and absorbing Enter on timing guesses; it is now fallback-only (gated off when the terminal provides bracketed paste), the retro-grab is deleted, and Enter on held command text flushes and submits. - Ctrl+C works on the pre-session launch menu and speaks everywhere: the first press arms the two-second exit window with a visible localized "Press Ctrl+C again to quit" hint (previously silent), the second exits. The worktree name input keeps Ctrl+C as cancel-input. - Fresh interactive sessions no longer leave a phantom one-message duplicate behind. The TUI claimed one session id (Runtime store lock, turn-start crash checkpoint) while the engine minted a second one; the first `SessionUpdated` re-keyed the App, the completion commit cleared only the engine id's checkpoint, and `codewhale --continue` later "recovered" the orphaned checkpoint as a duplicate session instead of the real one. The engine now adopts the host-owned id at spawn (`EngineConfig::session_id`) and `/clear` mints the next id in the App like `/new`. A non-TTY `--continue` no longer promotes and consumes the crash checkpoint before failing the terminal check, and the root `codewhale --resume ` / `--session-id ` flags documented in the operations runbook now parse instead of being swallowed as a prompt. - Website: `/signin`, `/signup`, and `/auth/callback` are locale-aware public routes instead of localized 404s. Sign-in and create-account send the person to the CWC app; OAuth callbacks hop to `app.codewhale.net` with the query intact; `/login` and `/register` are aliases. Local CLI use is not presented as requiring an account (#5767). - The sandbox read deny-list matches a rule's resolved path as well as its literal spelling. On macOS `/etc` and `/var` are symlinks into `/private`, so a read of `/private/etc/sudoers` walked around the `/etc/sudoers` rule, and a rule written against a symlinked directory never fired for the real path that `canonicalize` and the process cwd hand back. - Background shells are first-class work-strip rows (`▾ Shells N`) you can open, watch, and cancel by the `shell_*` id on the row. `/jobs cancel all` cancels running shells; it no longer looks up a task named `all`. The composer hourglass crumb no longer stands in for a shell surface. - `codewhale logout` and `/logout` now clear the Codewhale account session and the Daytona secret slot, not only provider API keys. The TUI crate's leftover `login --api-key` path no longer claims to save a key. - Account sessions no longer read the macOS Keychain. Unsigned or rebuilt `codewhale` binaries were a new Keychain ACL principal every time, so `codewhale web` and the TUI popped a password dialog on start. Sessions now use `~/.codewhale/secrets/secrets.json` (mode 0600), the same store as provider keys. Extracted from the Keychain-retirement half of #5632. - Hardened the dispatcher-side config parse the same way: `ConfigStore` loads and project-config parsing now deserialize `ConfigToml` on a dedicated 16 MiB-stack thread (the guided-setup save path could overflow a 2 MiB worker stack the same way the TUI's `ConfigFile` parse did), and the #5585 setup-confirm toast test runs its runtime on an equally sized thread instead of overflowing the default libtest stack. - Fixed detached interactive agents reporting worker usage after the parent turn ends with the usage missing from the session/live `/cost` total (#5597): interactive turns acquire an owner-scoped runtime usage lease, late usage enters the session cost pool without reopening the sealed mailbox, and worker/session/reload accounting share one hashed response identity so retried deliveries stay exactly-once. - Fixed the sub-agent fiasco class: in-workspace absolute `git -C` no longer trips the read-only child shell gate with a coherent bounded gate (#5595), turn end parks turn-owned children resumably instead of silently cancelling them (#5596), stale write-claims are released by liveness with coordinate release (#5562), and the verifier role description matches its real surface (#5562). - Fixed workflow responseSchema failure handling (#5583): bounded repair with typed receipts (kind + attempt), raw-output receipts persisted as artifacts that survive reload, and failures surfaced instead of null success (#5528). Degraded owner snapshots no longer project as ordinary Completed runs (#5582), typed task error kinds enable fail-fast parallel/pipeline (R9), and `/workflow confirm` finds the draft despite interleaved messages. - Fixed the DeepSeek session that never auto-compacted at 842k/1M (#5577): the exact `billed_842k_on_a_1m_window_compacts_despite_a_small_estimate` regression pins the trigger. - Fixed sandbox escapes and authority gaps: workspace-write tools resolve hard-linked files before writing (S2, #5569), an opt-in read deny-list bounds full-disk reads in any posture (S1, #5568), and session grants match the command family instead of widening the whole tool (R2). - Fixed provider-transport robustness: non-streaming HTTP requests are bounded by a read timeout (R4), and Chat-Completions mid-stream error frames surface instead of hanging (R3). MCP OAuth expiry now reacts to 401/403 with a named recovery path and login hint instead of looking like a broken server (T4, #5572). - Fixed Fleet lifecycle gaps: detached workers are reaped when their manager dies (R7) and the per-task wall-clock timeout is enforced (R5); the local Fleet host compiles on non-Unix targets; detached schema repair stays within the runtime budget. - Fixed prompt-cache correctness: the tool catalog is fingerprinted in provider wire order (C1), prefix changes between requests are always declared (C5) — including the newly named mid-turn `change:tool_surface` reasons for deferred-tool admission, tool-search activation, and runtime MCP tool arrival — and a reasoning-only response stopped at the output limit now fails the turn honestly instead of re-issuing a request that can only reproduce the stop. - Fixed docs/public-surface drift: REBRAND.md no longer presents `api.deepseeki.com` as a China fallback (#5564), and the web facts/tool counts match the repository. - Heavy pull requests now run the real Linux workspace nextest, doctest, and lockfile lanes directly on GitHub Actions instead of reporting a green placeholder while waiting for a branch-specific CNB mirror (#5547). - Fleet roster members in a selected Fleet now expose a visible edit affordance and a direct `m` model-picker shortcut, while the coordinator row remains read-only (#5604, covers #5589). - The context inspector now attributes bounded tool-schema cost to the built-in catalog and each discovered MCP server without changing prompt assembly or cache behavior (#5553). - The goal-continuation quiet period (`[goal] continuation_delay_seconds`, added in #5508) now applies on every dispatch path. Previously the within-turn dispatch hook fired the next continuation prompt immediately whenever a model step ended with the goal still active, so CLI-resumed and host-managed sessions never observed the configured delay (measured end-to-start gaps of ~9 s with a 300 s delay configured). The wait now runs unconditionally inside `goal_continuation_message_if_needed`, remains cancellable, and pause/clear/terminal `update_goal` calls still cancel a pending pass (#5534). - Two unit tests no longer depend on process-global environment state that sibling tests mutate concurrently. `route_budget::tests::v4_trigger_uses_window_percent_when_it_fits_spendable_input` asserted no-override output-budget values while reading `CODEWHALE_MAX_OUTPUT_TOKENS` / `DEEPSEEK_MAX_OUTPUT_TOKENS` without holding `lock_test_env()`, so a concurrent writer could flip the value mid-assertion (the order-dependent full-suite flake). `prompts::tests::system_prompt_prefix_never_leaks_private_content` read the real home via `HOME`/`USERPROFILE`, so a machine with `~/.codewhale/instructions.md` leaked its absolute path into the prompt and failed the no-private-paths assertion unless a sibling's temporary `HOME` guard happened to be live. Both tests now hold the env barrier and pin the variables (the route-budget test removes the overrides; the prompts test points `HOME`/`USERPROFILE` at a scratch dir). Assertions unchanged. - TUI sessions now apply a subtle OSC 12 cursor accent only on explicitly supported terminals and restore the terminal default through normal, panic, and signal cleanup paths (#5554). ## [0.9.11] - 2026-08-22 Codewhale v0.9.11 tightens the long-running agent loop, makes workflow failures visible instead of successful-looking, adds an experimental vision-capable DeepSeek route, and prepares reproducible Codewhale-versus-Pi evaluation without publishing a result before a real run. The complete item-level change record is retained below the categorized release highlights. ### Added - Added first-party `deepseek-v4-flash-vision-exp` discovery and selection for DeepSeek, including the `flash-vision` alias, bundled offline metadata, registry and picker entries, and image-input capability on the chat route. Context and output limits inherit from V4 Flash until DeepSeek publishes distinct values; pricing remains unknown rather than guessed. - Added a provider-controlled Codewhale-versus-Pi parity harness with three hermetic coding tasks, route and reasoning-effort receipts, doctor/dry-run modes, and bounded result artifacts. The repository ships the harness, not a benchmark verdict; comparable real runs remain an acceptance gate. - Added portable, secret-free config export/import with a reviewable plan, explicit headless consent, backup and rollback, and idempotent re-import. - Added bounded multi-file diagnostics through the existing model-facing `lsp` tool without increasing the tool-catalog count. Thanks to **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** for PR #5524. - Added portable presentation, media-attachment, and operation-digest facets to the command contract, then moved all seven utility handlers onto the contract-backed dispatch path. Thanks to **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** for PR #5525. ### Changed - Sub-agent, Fleet-worker, workflow-task, and thread-runtime model turns no longer inherit a hidden role-based step ceiling. An omitted or zero `max_steps` is unbounded; a positive user/config value remains an explicit cap and is still clamped to the runtime safety ceiling. Wall-clock, provider, heartbeat, cancellation, and admission safeguards are unchanged. - `/rc` now mirrors one shared session rather than transferring terminal ownership: local and web prompts remain available while idle, approvals use first-decision-wins semantics, and transport/integrity failures remain fail-closed. - The terminal status rows around the composer are now two stable bands: `provider · model · thinking level` is the persistent identity row below the composer in every phase, and a separate activity row above the composer carries the live phase, notices, and cost/metrics. Sending a prompt no longer relocates the route identity above the composer, and neither row ever duplicates it. - The embedded local Web client now uses the current CWC Ocean hierarchy and readable control sizing, follows the shared Enter/Shift+Enter composer grammar, and chooses a provider plus model per new thread without mutating Runtime defaults. Exact image-input capability is labelled honestly; a vision-capable route does not imply that browser attachments exist. - The runtime now has one authoritative model-turn loop. The placeholder `crates/core` engine tree is gone, while the active TUI loop and its extracted tool-call stages retain existing policy, hook, cancellation, and budget behavior. Thanks to **Sun Zhenyuan ([@bistack](https://github.com/bistack))** for PR #5523. ### Fixed - Chat Completions streams now require terminal proof from `[DONE]` or a non-empty `finish_reason`. Protocol-only frames no longer count as answer content or time-to-first-token, and a provider continuation that ends after tool results with no answer or tool call fails durably instead of producing a false `Completed` receipt. - A selected v2 Fleet now drives one bounded, deterministic Agent roster across terminal and runtime surfaces. Fleet operator/member/explicit-route precedence, resolved member identity, and exact `vision` requirement admission now fail visibly instead of silently falling back, first-matching, or rerouting. - A workflow whose `task()` dispatch was rejected no longer loses that failure inside a `parallel()` null slot or presents a successful-looking run. Rejected dispatches now fail the run, persist as typed bounded receipts with an exact count, and appear in transcript, activity detail, and workflow-panel views. - Provider readiness, credential-source explanations, focused-agent scrolling, compact `/status` and `/help` rendering, shell/web output bounds, MCP lifecycle reporting, and narrow-terminal onboarding received the detailed fixes recorded below. - Portable config import/export now preserves typed tables, arrays, numbers, booleans, and datetimes without stringifying them, while refusing machine-bound trust overlays, credential readers, automatically executable hooks/LSP definitions, local-path authority, machine-local network proxy routes, cookies, redaction placeholders, and nested or camel/dotted credential keys. Project and global bundle operations now load and validate the document for their actual scope in both directions, including a workspace whose document still lives under the legacy app directory. - `codewhale login` now means Codewhale account sign-in (the same browser device flow as `codewhale account login`, with `--no-open` and `--timeout-seconds`); provider API keys are configured exclusively through `codewhale auth set --provider `, and the hidden legacy `--api-key`/`--provider` flags redirect loudly instead of silently writing a key. - Account sessions prefer the OS credential manager and now fall back automatically to the private `0600` Codewhale secrets file on headless hosts, SSH boxes, and containers; the `CODEWHALE_CLOUD_ALLOW_FILE_SESSION_STORE` opt-in is deprecated and ignored. - `/update` gained a `Ctrl+Shift+U` install chord (catalogued in `docs/KEYBINDINGS.md`, localized in all 15 packs) and a startup hint that names the previous and current version on the first launch of a newer build, pointing at `/change`. - Fleet product-model copy pass: the TUI, docs, and locale packs now use Fleet / Member / Role / Model / Access / Saved consistently so a user can say "scout", "DeepSeek V4 Flash", or the member name and mean the same thing. - A reasoning model that returns only hidden reasoning and a clean stop (no answer, no tool call) is now re-requested automatically up to twice before the turn fails, instead of dead-ending with "the provider response was incomplete." The retry reuses the cached prefix so it is cheap; an output-length stop (`length`/`max_tokens`) is never retried, and a persistently answerless model still fails honestly after the bound. - Model-bound tool results now use a credential-shaped redaction policy: only values that look like secrets (known prefixes, JWTs, bearer tokens, PEM private-key blocks, long opaque strings) are masked before a `read` or shell result reaches the model, so code such as `password: credentials?.password` or `"password-validator": "^5.3.0"` stays byte-exact for edits and read-back. Exact configured credential values are still always replaced, and logs/previews/exports keep the broad key-based scrubber. (#5546, reported by @ronohara) - Terminal input shutdown no longer waits forever on a wedged TTY read, Windows launch receipts can atomically replace an existing record, and the complete `/status` report now follows the active locale without rewriting exact custom-provider identities that contain brace-like text. - Localized READMEs again match the English install and third-party-notice surface, including shell-completion guidance in all 18 translations. ### Security - Unified OAuth device-code polling now validates verification URLs before opening them, redacts token-bearing types, honors server slowdown intervals, and keeps credential save/logout mutations serialized. - Project instructions, rules-directory traversal, secret-shaped config data, URL fingerprints, and shell network authority now retain the explicit bounds and fail-closed behavior described in the detailed record. ### Contributors - **Sun Zhenyuan ([@bistack](https://github.com/bistack))** — tool-call stage extraction with the existing execution and policy contracts preserved (#5523). - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — bounded multi-file `read_lints` support (#5524), plus independently reviewed completion-routing overlap in #5530. - **Lstarsky0 ([@Lstarsky0](https://github.com/Lstarsky0))** — maintainer review hardening for truthful per-file states and truncation metadata in #5524. - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** — portable presentation/media/digest facets and the seven utility-handler migrations (#5525). - **RepentStar ([@RepentStar](https://github.com/RepentStar))** — reported and reproduced the stale completion-generator path and missing `codew` registration fixed for #5526. ### Detailed change record The notes below are preserved in full so the categorized highlights do not erase behavior, migration, security, compatibility, or verification details. - Provider completion is now evidence-based. A Chat Completions stream reaches `MessageStop` only after `[DONE]` or a non-empty `finish_reason`; raw EOF without either is a typed failure. Message-start, ping, usage/terminal deltas, block-stop, and message-stop frames do not count as productive content or mint time-to-first-token. After tool results, a terminal provider step with no answer or tool call now emits a durable failed turn and never fabricates an empty assistant message. - A selected v2 Fleet is the single effective Agent roster across terminal, Runtime threads, direct Workflow, Fleet execution, doctor, and setup/readiness; legacy profile layers are consulted only when no Fleet is selected, and invalid selections fail visibly with bounded, redacted errors. Member references resolve exact id first and otherwise require a unique display name, role, pinned model, offline model name, or provider/model route; `agent action=roster` exposes that same bounded roster. The Fleet operator supplies fresh-root and inherited-member routing unless an explicit launch route or member pin wins, the resolved member is shown separately from the requested alias, and `requires = ["vision"]` is admitted only on an exact route with verified offline `image_input` support—never by silent rerouting or custom-proxy inference. Fleet selection remains an explicit user/folder contract independent of legacy project-profile loading. - **Breaking (app-server):** `/prompt`, `prompt/request` and `prompt/run` now execute a real model turn instead of reporting success for work they never did. `Runtime::handle_prompt` called no model: it resolved config, ran a local `ModelRegistry` lookup, emitted three canned hook events (`ResponseDelta` was literally the string `model-selected`), and returned HTTP 200 with `output` set to a stringified JSON echo of the caller's own routing metadata — the prompt included. Worse, when a `thread_id` was supplied it appended a real user row, flipped the thread to `Running`, and then wrote that echo into durable history as an **assistant message** plus a `prompt_response` checkpoint. Nothing marked the row synthetic and nothing ever moved the thread out of `Running`. All three endpoints now route through the same `RuntimeBridge` that stdio `thread/message` has always used, so `output` is the model's streamed text, `model` is what the runtime reports for the thread that ran the turn, and `events` are the real streaming frames. `Runtime::handle_prompt` and its synthetic history write are gone. - **Breaking (app-server):** a failed prompt is now a typed failure rather than a success-shaped body. `POST /prompt` returns `{"error":{"code":...,"message":...}}` with `400` (invalid request), `404` (thread not found), `503` (`runtime_unavailable`) or `500`, instead of HTTP 500 carrying a `PromptResponse` with the error text stuffed into `output` where model text belongs. The stdio surface gained JSON-RPC `-32005` `runtime_unavailable` for "the turn engine could not be reached, so nothing ran" — distinct from `-32603`, and retryable. There is no configuration in which a prompt silently echoes instead of running. - **Breaking (app-server):** `POST /thread` with a `Message` body runs the turn. It previously replied `status: "accepted"` with a `ResponseDelta("queued")` frame while starting no worker and calling no bridge — the stdio path for the same request has always done real work, so the two transports disagreed about what `accepted` meant. HTTP now replies `status: "completed"` once the turn reaches a terminal state, with the streamed frames in `events` and the turn id in `data`. `Runtime::handle_thread` no longer accepts `ThreadRequest::Message` at all: it owns thread bookkeeping, not the turn engine, and returns an error naming `POST /v1/threads/{id}/turns` rather than a canned acceptance. - **Breaking (app-server):** `AppRequest::SubmitUserInput` now refuses explicitly (`ok: false`, `error: "user_input_reply_unsupported"`) instead of returning `resolved: true` and filing the answers in a map that had no reader anywhere in the crate — every answer submitted was silently discarded. It cannot be made to work on this transport: while a turn streams, the stdio loop executes only `thread/interrupt` and queues everything else, so an answer sent there would wait on the very turn waiting for it. The refusal names the surface that does accept it, `POST /v1/user-input/{thread_id}/{request_id}` on the runtime API. The client-visible refusal is whitespace-clean, and the `/tool` path that mints the `UserInputRequest` is unchanged and still genuine. - Split the coordination ledger out of `tools/subagent/coord.rs` into `tools/subagent/coord/ledger.rs`. The file held two unrelated things: the model-facing `agents/*` tool wrappers, and the durable decision/claim/ contention records those wrappers happen to write — records whose consumers are mostly *not* in the tool layer (`tui::coordination_detail`, `tui::work_surface`, `tui::ui::tests`, `core::engine::tests` all name these types). At 3.8k lines, reading either one started by scrolling past the other. A pure move with a glob re-export from `coord`, so every `crate::tools::subagent::coord::{…}` path still resolves and no consumer file was edited; the only content change the move required is one constant going from private to `pub(super)` because its caller stayed behind. `coord.rs` is now 2.3k lines and `ledger.rs` 1.6k. - `agent` is now the only sub-agent tool the model can see. `AGENTS.md` has said "the model-facing sub-agent surface is `agent` only" since the lifecycle tools were removed, but six more were reachable: `agents/list`, `agents/message`, `agents/followup`, `agents/interrupt`, `agents/coordinate`, and `agents/wait` all defaulted to model-visible, so they shipped in the catalog and `tool_search` could load any of them — and the `agent` description told the model they existed. They now declare `model_visible() -> false`, the same shape `rlm` and `exec_shell` use: still registered, still executable by name so a persisted transcript replays against the same implementation, never advertised and never returned by either `tool_search` matcher. Five of the six were already duplicates of an `agent` action. The sixth was not: `agents/coordinate action=claim` was the *only* way to widen a write claim, and write enforcement fails closed, so hiding it would have left a refusal ("expand it first with…") pointing at a tool the model could no longer call. `agent` gains one action, `claim`, taking the write scope vocabulary `action=start` already uses (`write_roots`, plus parse-accepted `exact_files` and `coordination_contracts`). It keeps `agents/coordinate`'s `Auto` approval — gating it deadlocks autonomous fan-in — and it can only widen the caller's own scope; peer contention still fails. A scopeless claim is refused rather than reported as granted, because `expand_write_claim` returns the unchanged claim with `Ok` when every list is empty. Collapsing six tools into one action set also collapses the gating: `agent` is deliberately exempt from both name-keyed gates (`posture_permits_tool` short-circuits it so delegation depth governs spawning, and `execution_envelope` classifies it `Bounded` so a read-only member can fan out read-only work), so a capability folded into it inherits no gate. `claim` is therefore gated per action, reproducing the envelope check that kept `agents/coordinate` off a read-only role's catalog — in the catalog and again at dispatch, since catalog shaping is not an authority boundary. The other actions keep exactly the visibility they had. - One placement table now decides which wire channel a message role belongs in, and unrepresentable role/dialect pairs are refused at the outbound seam (`DeepSeekClient::prepare_outbound_request`) instead of at the provider. Chat Completions and OpenAI Responses used to drop an unfamiliar role silently, Anthropic Messages forwarded `message.role` verbatim and took an opaque provider 400 for it, and Google cloud-code was alone in failing closed. Positioned `system` and `developer` history — including compaction and branch summaries — is carried natively by Chat Completions and Responses and projected, in place, onto Anthropic's user channel. It is neither hoisted nor dropped. Genuinely unknown roles keep the previous dialect-specific fail-closed/omit behavior, now decided in one table. The dead `"tool"` arm in the Responses adapter is gone — nothing constructs that role. - Message roles are a closed `Role` enum (`crates/core/src/role.rs`) instead of a free-form `String` on `Message`. Four wire adapters each decided independently what an unfamiliar role meant, and a typo in a role string was a silent transcript edit rather than a compile error. `Role` keeps an `Unrecognized(String)` variant and serializes via `as_str()`, so a saved session's bytes are unchanged, a transcript written by a newer build still loads here, and `assistant_interrupted` stays a distinct session item — no session schema bump and no migration ladder. - Portable config bundles: `codewhale config export --portable` writes a deterministic, secret-free bundle (credential and machine-specific keys dropped), and `codewhale config import ` applies one with a strict versioned envelope, a printed added/changed/skipped/conflicting/ rejected plan, consent gating (`--yes` required headless), a timestamped backup with rollback, and idempotent re-import. Credential-shaped entries are rejected by key name and value shape — rejections name the field, never the value. Remote imports revalidate the HTTPS-or-loopback-HTTP policy on every same-scheme redirect hop, and duplicate keys across applicable section labels fail before any backup or write instead of silently resolving by section order. Structured TOML values round-trip with their original types and exact named-provider identity; recursive sanitization covers arrays/tables and camel-case, dotted, cookie, and access-key spellings while retaining ordinary token-count metrics. Machine-bound project trust, credential-source consent, automatic hook/LSP execution, and local-path authority are non-portable and fail before mutation. A missing target is created transactionally and removed again on rollback, and project/global scope validation rejects the wrong document before import or export. Imported tables deep-merge portable fields into the target, so omitted machine-local provider credentials, endpoints, and executable definitions remain intact instead of being erased by a sanitized bundle. - `/rc` is now a shared-session mirror instead of a terminal takeover. Attaching the web app no longer locks the local composer or hides approvals: both surfaces can prompt while idle (one turn runs at a time), approval cards stay visible in the terminal and are shared with the web with first-decision-wins semantics (the losing side is told, a web decision dismisses the local card), and structured questions are answered locally instead of cancelled. Fail-closed behavior survives — the post-failure reconnect lockout, integrity-gated `/rc stop`, and the fail-closed shared-approval channel on transport loss are unchanged. The takeover vocabulary ("web owns prompts and approvals") is gone from every surface. - Auto-mode provider readiness no longer reports "key saved · not checked" forever. Readiness checks are recorded against the concrete model the router ran, but auto-mode reads resolved against the literal `auto` identity, which never matched any recorded check — so the setup receipt, model picker, and fleet setup view showed an eternal unchecked badge even after hundreds of successful turns. The read now falls back to the most recent check on the same route (provider + endpoint + auth class); concrete-model reads keep exact per-model scoping. - The focused sub-agent transcript now scrolls like the main transcript. The frame renderer sampled the ocean column through a `ChatWidget` whose constructor consumed `pending_scroll_delta` — every PageUp/PageDown and wheel event was swallowed by an invisible widget before the focused pane could read it. The delta is now parked across the sample; the pane pins on user scroll-up, follows new child activity at tail, and jump-to-bottom releases the pin. - Every Codex OAuth Responses request carried `max_output_tokens`, a parameter that endpoint rejects outright ("Unsupported parameter: max_output_tokens"), so every gpt-5.6-sol turn — including every sub-agent on that route — failed at the first request. Codex Responses bodies now ship without a client-side output cap; the backend applies its own. Every other Responses route keeps the central cap on the wire, exactly as before. - The model-facing `lsp` tool now supports a bounded `read_lints` operation for multi-file, workspace-relative LSP diagnostics without adding another tool catalog entry (#4070). - HTTP 400 classification no longer calls an unsupported-parameter error a context-window overflow. Responses shape errors such as "Unsupported parameter: max_output_tokens" name a token-shaped field, which the generic keyword rules read as prompt-size exhaustion and pointed users at compaction that could never help. Such responses now classify as invalid requests. - xAI device login validated nothing about the URL it opened. The `verification_uri` from the device-code response went straight to `webbrowser::open` with no parse, no scheme check and no credential check, so a spoofed or compromised issuer could hand the platform's "open this" call a `file:` path, a custom application scheme (`vscode://`, `slack://`), or a credential-bearing URL. The shared primitive now refuses anything that is not a web page before the URI is printed or opened. **Behaviour change:** a non-loopback plain-`http:` verification URI now aborts login where it previously opened; `http:` on a loopback host is still allowed, because local runtimes legitimately use it. - The xAI OAuth types no longer print bearer material through `Debug`. Five types holding tokens (`GrokAuthEntry`, `TokenResponse`, `DeviceCodeResponse`, `DeviceCodeGrant` and the poll outcome) either redact or no longer derive `Debug` at all, so a token has no printable path through a `{:?}` on any surrounding struct. The shared `DevicePollOutcome` derives nothing, which the compiler enforces. - **Behaviour change:** an `interval` of `0` from the authorization server now falls back to RFC 8628's five-second default rather than a one-second floor, in both the xAI and account device flows. - OAuth device-code login is now one implementation. xAI/Grok device login and Codewhale account login each carried their own hand-rolled RFC 8628 polling loop with nothing shared between them; both now call a single primitive (`codewhale-config`'s `device_code`), ported from pi. Three fixes come with it. `slow_down` now honours a server-supplied `interval` instead of always adding five seconds, which is what stops polling from running early forever under WSL and VM clock drift. Timing out after a `slow_down` now says so and names clock drift, rather than reading as a plain timeout. And the xAI verification URI is validated before it is handed to the browser opener — Codewhale previously opened whatever the device-code response said, so a spoofed or compromised issuer could point the platform "open this" call at a `file:` path or a custom application scheme. It must now be `https:`, or `http:` on a loopback host for self-hosted issuers. Stored credential files are unchanged and existing logins keep working. MCP OAuth is untouched: it delegates to `rmcp`/`oauth2` and was never hand-rolled. - Shell output truncation now stays inside its own budget. A truncated shell result keeps a 6 KB head, a 24 KB tail, and any high-signal lines rescued from the omitted middle — but that rescued block was bounded only by a line count. One rustc `error:` line carrying a long inferred type or a minified bundler frame is routinely hundreds of kilobytes, so a "30 KB" result could arrive at 430 KB with the omitted line pasted back in whole. Each rescued line is now clipped and the block has a 4 KiB ceiling; the signal survives, the payload does not. - Fetched web pages in non-Latin scripts no longer arrive half-read. Page text was reflowed against a column budget measured in bytes, so Cyrillic and Greek wrapped at roughly half the intended width and CJK at two thirds — and since the page view is delivered by line count, the surplus lines pushed real content off the end of the window. A Russian or Japanese URL returned a fraction of the text an English one did, for the same call. Wrapping now measures display width. - The `bash` tool no longer tells the model it has no default timeout when it does. An omitted timeout has always been bounded at 120 seconds and the command killed there, but the tool description and its `timeout` field both claimed otherwise — steering the model away from the one parameter that would have saved a longer build. Both now name the real bound. - MCP servers no longer restart because an unrelated setting was saved. The lazy config reload re-reads every watched source whenever one of their mtimes moves and keeps the live connections only when the content hash matches — but the hash was taken over `serde_json` bytes produced straight from the config's `HashMap`s, and two `HashMap`s with identical contents do not iterate in the same order. Any touch of any watched file therefore hashed differently, tore down every connection, and SIGTERMed and respawned every stdio child. Keys are now sorted before hashing. - An MCP server marked `required` now still tells you *why* it failed to start. `connect_all` appended a generic "required MCP server failed to initialize" entry after the real per-server error, and the snapshot folds those pairs into a map keyed by server name — so the contentless entry replaced the diagnosis and /mcp showed the marker instead of "No such file or directory". The marker is now only synthesized when nothing else reported a cause. - A crashed stdio MCP server is now rebuilt instead of being handed back dead. A failed transport *read* disconnected the connection; a failed *write* did not, so after the child exited the connection stayed `Ready`, the pool reused it on every later tool call, and /mcp kept listing the server as connected. - An MCP response carrying neither `result` nor `error` is now an error rather than an empty success. It previously reached the model as a successful tool call with a `null` payload, indistinguishable from a tool that did nothing. An explicit `"result": null` is still a valid empty success. - Stdio MCP server requests are answered while the client is idle instead of blocking behind the zero-capacity response rendezvous until an unrelated client call. `ping` receives its prompt empty result, unsupported methods receive JSON-RPC `-32601`, and the reader keeps only a weak stdin handle so dropping the client still delivers graceful EOF. - `base_url_fingerprint` is a persisted-key change for two input shapes. The digest is serde-serialized into `ProviderCatalogCache` and `LiveOffering`, pricing defect receipts, and `TurnRecord.routed_usage_source_ids` — it is not an in-memory-only cache label. Empty or whitespace-only values (and scheme-less query-only strings that strip to an empty authority) now hash the invalid-or-secret-bearing sentinel instead of SHA-256 of the empty string. Scheme-less URLs that contain `@` now strip `userinfo` before hashing, matching the scheme-bearing branch, so a typed `user:pass@host/v1` no longer embeds the password in a stored digest. `routed_usage_source_fingerprint` feeds arbitrary scheme-less source ids into the same function, so a turn rehydrated from an older build can fail to dedupe one routed-usage row. Recovery is a cache miss and a re-fetch, not corruption. Empty input was not restored to the old digest: an empty authority is not a usable endpoint, and mapping it to the same sentinel the scheme branch already uses for an empty host keeps invalid inputs from minting a unique cache scope. - Diagnostic lines that mention token *counts* are no longer swallowed by secret redaction. A stream error such as `max tokens = 8192 but budget = 4096` was matching the `token` hint as a substring of the English word `tokens`, and the spaced-assignment pass then dropped the rest of the line, leaving `max tokens = [redacted]`. Token counts are not credentials; the hint now matches a credential identifier (`token`, `api_token`) rather than an English word, so the numbers survive while `token = Bearer …` is still redacted. - Dashboard thread search no longer loads every thread's transcript to decide whether the row matches. `GET /v1/threads/summary?search=` walked the full thread list and called `get_thread_detail` on each row before matching, and that detail read is itself a whole-store walk of every turn JSON and every item JSON. A non-matching keystroke was therefore O(threads × (all_turns + all_items)) file reads — on the order of 10^8 JSON parses at a few thousand threads. Search now matches `id`, title, and model from the thread record (and, when the title is unset, the single latest-turn file that supplies the displayed title) and loads detail only for matches, so preview stays a display field rather than a search key. Session summary already refused to search last-message text for the same reason. - Silent `#[allow(dead_code)]` suppressions on the modules AGENTS.md warns auditors not to delete — prompt zones, context budget, the route seam — and on the next-largest holders (palette tokens, hotbar actions, core events) are now `#[expect(dead_code)]`, or gone where the lint was already stale. A suppression that stops matching the lint fails the `-Dwarnings` gate instead of sitting quiet. The same gate is recorded in `[workspace.lints]` so member crates inherit it from the manifest rather than only from CI `RUSTFLAGS`. - "missing key" now says where it looked. The provider picker reported credential readiness as the bare strings `missing key` / `key:not-set`, which named no source at all — so a home whose secret store held a working DeepSeek key could show `DeepSeek missing key` in the picker while a real turn from that same home completed, and nothing on screen said which layer disagreed. Every row now resolves through one sourced resolver and states the place its credential came from ("OPENROUTER_API_KEY", `secret store "deepseek"`, `[providers.x] api_key`, "xAI OAuth", a consented external CLI file); a row without a credential lists the places that were probed, in precedence order, and the command that fixes the first of them. Where a durable slot is deliberately *not* read — an inactive provider whose config table carries no api-key marker — the row says so rather than implying an empty slot. - Provider credential precedence is now stated once, in a doc comment beside the single resolver that enforces it, instead of being implied by a 150-line cascade of provider special cases. No precedence decision changed: `has_api_key_for` is now a wrapper over that resolver, and a test asserts the two agree for every provider. - Credential saves and logouts no longer interleave. Both took a snapshot of the durable slot, wrote it, mutated the config document, and rolled back on failure, with no lock held across the sequence — so a save racing a logout on the same slot could leave the secret store and the config file disagreeing. Both now hold that provider's credential write lock for the whole read-modify-write. Design ported from pi-mono (MIT, Copyright (c) 2025 Mario Zechner); see `docs/THIRD_PARTY_NOTICES.md`. - Enumerating stored credentials no longer fails closed on one bad slot. Listing used to propagate a backend read error, so a single unreadable secret-store entry made `/provider` and logout treat every other stored credential as missing. Enumeration now skips the unreadable slot and continues, matching the probe loop it replaced. - The first screen of first run no longer cuts its own headline. The welcome and ready titles, and the provider-step heading, were emitted as single unwrapped lines while the sentence beneath them wrapped, so at 40 columns German read "Codewhale arbeitet mit dir in diesem O", Russian lost its final stop, and Japanese lost "します。". Headings are prose and now wrap like it, in every shipped locale. - The workspace-trust screen no longer cuts its own question in half on a small terminal. The question, the prompt-injection risk hint, and the trust-effect hint were each pushed as one unwrapped line, so at 40 columns the screen read "Should Codewhale work with the instruc" — severed mid-word with nothing marking the cut, while the workspace path directly beneath it wrapped correctly. Asking someone to grant filesystem trust while the question itself is truncated is the worst place in the product for that to happen. All three now wrap through the same helper the rest of onboarding uses, which also means they wrap correctly in Japanese and Chinese. Verified across all fifteen shipped locales at 40, 60, 80 and 120 columns. - `codewhale completions ` generated a script for the wrong program. The subcommand forwarded to the in-tree `codewhale-tui` binary, which rendered completions from *its own* clap tree under *its own* name, so the output ended in `complete -F _codewhale__tui ... codewhale-tui` (bash), `#compdef codewhale-tui` (zsh), and `Register-ArgumentCompleter -Native -CommandName 'codewhale-tui'` (PowerShell). Sourcing it registered nothing for `codewhale` or `codew` — the two commands current installers expose — so tab completion appeared to do nothing. The forwarded tree was also stale against the real CLI: it offered `pr`, `scorecard`, and `session-diagnostics`, which `codewhale` does not have, and omitted `run`, `rc`, `config`, `model`, `thread`, `lane`, `workflow`, `web`, `account`, `app-server`, `mcp-server`, `metrics`, `update`, `cloud`, `completion`, and `lane-log-proxy`, which it does. Completions are now rendered in-process from the CLI's own command tree, and `completions` is an alias of the existing `completion` subcommand rather than a second, divergent path. Regenerate any script you installed from an earlier release. Reported by **RepentStar** (#5526); part of the `deepseek-tui`-era identifier retirement in #5443. - Completion scripts now fire for the `codew` shorthand as well as `codewhale`. Releases publish `codew` as a byte-identical copy of the `codewhale` binary, so a script bound to only one of the two names was half installed for anyone who types the short one. Each shell gets its own idiomatic hook rather than a second copy of the script: bash re-binds the generated function, zsh widens the `#compdef` tag line to `#compdef codewhale codew`, fish adds `complete -c codew -w codewhale`, PowerShell registers `-CommandName 'codewhale','codew'`, and Elvish aliases the completer with `set edit:completion:arg-completer[codew] = $edit:completion:arg-completer[codewhale]`. - Documented shell completions. `docs/INSTALL.md` § 8 now gives the generate and install commands for bash, zsh, fish, PowerShell, and Elvish, with a note to regenerate after upgrading and to delete scripts produced by v0.9.10 or earlier. There was previously no completion documentation anywhere in the repository, which is how #5526 was reported as three problems instead of one. - `/status` was 31 rows. On an 80x24 terminal the transcript viewport is 18, so typing `/status` landed you on the *tail* of the report: the version, route, directory, mode and sandbox rows had already scrolled past, and what stayed on screen was five `not reported` rows and a `$0.0000`. The report is 18 rows on a fresh session — `Window override:` is present unless the value is already configured. That is the viewport's height, so once `/status` itself occupies a history cell the title row still scrolls off; it does not fit that terminal whole. Provider, model and reasoning effort are one `Route:` lockup, the way the header rail already writes them. Mode and its permissions are one statement of posture. `Rate limits:` is gone — it was a `push_row` of a string literal and could never say anything but "not available from provider telemetry". The per-turn token ledger is gone too, because `/tokens` is that ledger's whole subject and `/status` was printing six rows of it at the same weight as the sandbox policy; the two facts that lived nowhere else, the cumulative in/out split and the cumulative cache totals, survive on one `Session tokens:` row. `Footer items:` no longer prints ten internal config keys across the full width — `/statusline` owns them, and the report now points there in the same row that points at `/tokens`. Two blank gutters do the grouping; the `===================` rule under the title is gone. - The `/status` window-override key has its own labelled row. It used to be parenthesised onto the end of the provenance row, which pushed `context_window in config.toml` past the right edge at 80 columns and wrapped the sentence. `Window source:` states the provenance and `Window override:` names the exact key — and the override row is omitted entirely when the value is already configured, rather than advising you to set what you have set. - `/help` no longer truncates anything. Every label and description used to run through a `truncate_to_width` that appended `…`, which in a two-hundred-row list promises text no keystroke can reveal and lands mid-token: `(aliases: /qin…` left the parenthesis hanging open. Descriptions now shed whole fields — the alias parenthetical first, then trailing clauses at their own joints, and only where there is no joint at all, the sentence's short form on a whole word with no mark, keeping the head noun of a simple verb + modifier + noun phrase rather than the adjectives that qualified it. The focused row's description is restated under the filter at the panel's full width, *only when the row itself could not hold it*, so a wide terminal does not say the same sentence twice. At 60 columns that restatement is itself shed — the `/advisor` detail stops before `session` — so the detail is longer than the row, not a copy of the original sentence. - The `/help` label column is measured instead of assumed. It was a flat 28 columns at every terminal size, so at 60 columns twenty blank cells sat between `/advisor` and a description cut down to 21. Each group now sizes its column to the labels it actually holds, which nearly doubles the description column on a narrow terminal, and the label — the string you have to type — reads one step brighter than the description that qualifies it. - `/help` stopped spending rows on itself. The match count moved onto the filter row it describes, the blank spacer under it is gone, and the footer no longer repeats `type to filter` while the filter box says `Type to filter` two lines above — at 60 columns that duplicate was what pushed the footer onto a second row. A group header also stopped printing `▸ ▾`: the selection cursor and the collapsed chevron are the same glyph, and a focused collapsed group was showing it twice for two different facts. Help now opens focused on the first entry rather than the header above it. - The bottom status rail is no longer one run-on sentence. At 120 columns it read `▌· idle · Ollama · deepseek-v4-flash · max · Anonymous usage counts are on. … ⌥V:output · /context:context · fn+F1:keys` — live state, route identity, a telemetry consent notice, and keyboard hints all strung together by the same middle dot in the same ink, so nothing was grouped and the eye had nothing to skim by. At 80 columns it simply stopped mid-notice, and at 60 the row overflowed and was clipped by the terminal mid-word. The rail now divides its groups with a blank gutter instead of another dot (the dot is kept for peers *inside* a group), the model name reads one step brighter than the qualifiers that narrow it, and `Esc to interrupt` reads in the same hint weight as the right-hand chords rather than in the separator weight. - Nothing on the status rail is ever truncated now. A notice sheds whole sentences to fit, and if one sentence is still too long it sheds at the inner joints — a colon, a semicolon — with the trailing mark cut so the phrase that survives does not itself advertise that more was coming. Route identity sheds the provider, then the reasoning effort, rather than rendering `deepseek-v4-flash-prev…`; a clipped model name is worse than no model name because routes share prefixes. Clauses rejoin without a Latin space after a full-width stop, so the Japanese receipt reads as Japanese. - A notice now stands the standing facts down instead of queueing behind them. Route identity and the ledger chips are still there in ten seconds; the notice is not, so it takes the row and the key hints yield last. This is what makes the telemetry receipt readable at 80 columns, where it used to be simultaneously always present and never legible. - The status rail no longer advertises `/context:context`. It was spending eighteen columns of a 24-row screen to name a slash command that announces itself the moment you type `/`; the rail advertises chords you cannot discover any other way. The rail now reads the same at 80 columns as at 200. - The idle screen no longer has an absolute path stretched across it. The workspace caption between the wordmark and "What do you want to accomplish?" was composed at full length and then truncated to the lane width, which made the centering inset `(width - caption.width()) / 2` evaluate to zero — so a line that was written to be centered rendered flush-left and full-bleed, cutting the centered whale/wordmark/prompt composition in half. The clipping also destroyed the information it was supposed to carry: at 80 columns the line read `/private/tmp/claude-501/-Volumes-.../34267917-11f4-4d15-911a-…`, which tells the reader nothing about where they are. The caption now sheds detail instead of being cut — MCP count first, then branch, then leading path components — so it always fits with room to center, and the folder you are standing in is the last thing to go. Elisions land on a path separator rather than mid-directory. - Removed the placeholder engine tree in `crates/core/src/engine/`. Its `Engine::run` accepted `Op::SendMessage`, appended to a journal, and emitted `TurnComplete { status: "completed" }` without ever contacting a model, and `TurnExecutor` was a struct with a field-copy constructor and a `step < max_steps` comparison. Nothing in the workspace referenced any of it — the only mention of `codewhale_core::engine` anywhere was a doc comment inside the tree itself — but its comments ("the real turn loop is wired here in the next slice") were what `docs/ARCHITECTURE.md` leaned on to claim that `crates/core` owns the agent loop. There is now exactly one turn loop in the workspace, `Engine::run_turn`, and a guard test fails if a second one appears. `docs/ARCHITECTURE.md` and `AGENTS.md` now say where it actually lives. - First-run onboarding no longer silently truncates its explanation in languages that do not put spaces between words. `wrap_words` split on whitespace, so a Japanese sentence arrived as a single token, the line-break check (which only fires once a line is non-empty) never triggered, and the over-wide line was clipped by the terminal. At 80 columns the provider screen read "Hosted providers need a key, but loca" and stopped — losing exactly the half that tells the reader local runtimes need no key, on the screen where they choose a provider. Space-less scripts now break by display width on grapheme clusters, and a line may not begin with closing punctuation (`。`, `、`, `」`, `)` and friends). Wrapping for languages that do use spaces is unchanged. - Project instructions are bounded by one budget and no longer treat other agents' files as law by default. Previously `.claude/instructions.md` and `CLAUDE.md` sat at ranks 2 and 3 of the canonical instruction list — *above* Codewhale's own `.codewhale/instructions.md` — `.claude/rules/` was an auto-discovered rules directory, and `.cursorrules`, `.cursor/rules`, `.clinerules`, `.windsurf/rules`, `.gemini`, `.github/copilot-instructions.md` and `.github/muse-instructions.md` were all imported into the system prompt with no opt-in. Dropping a `CLAUDE.md` written for a different tool into a repository silently made it standing authority here, which is an injection surface rather than a convenience. Codewhale now reads `AGENTS.md`, the cross-agent `.agents/AGENTS.md`, and its own instruction files by default; every other agent's format is opt-in by name through `project_instruction_imports` (env `CODEWHALE_PROJECT_INSTRUCTION_IMPORTS`), imported files rank *below* Codewhale's own, and a workspace that contains an un-imported format says so in a warning naming the exact setting. - Separately, a symlinked candidate rules directory — `.cursor/rules`, `.windsurf/rules`, or `.gemini` pointing outside the workspace — was traversed and its contents imported as instruction authority, because the directory check followed the link while only the files inside it were checked. The two instruction loaders now apply the same no-follow rule that `.codewhale/rules/` already had. - The three separate ceilings on standing instructions (200 KiB for the root->workspace chain, 500 KiB for the rules block, 40 KiB for imported fragments, and a global layer that was merged in after the chain budget had already closed and so counted against nothing) are replaced by a single 48 KiB aggregate budget covering all of them together. Instructions claim it before rules, and are trimmed from the broadest scope inward so the nearest-scope file is the last thing dropped rather than the first thing stranded. Truncation still leaves an explicit marker. - Editing the workspace no longer grants the shell outbound network access. `workspace-write` sandboxes are created network-restricted; `curl`, package installs, and `git fetch` inside a sandboxed shell are denied by the OS sandbox unless network is granted explicitly. This closes a real gap rather than tightening a working boundary: the elevation added in #273 was justified by the application-level `NetworkPolicy` remaining "the only outbound boundary", but that policy governs `fetch_url`, `web_search`, and MCP HTTP and never constrained shell subprocesses, so workspace-write turns had unrestricted egress with nothing enforcing anything. Network now comes from one of three explicit places: the new `sandbox_network_access` config key (also `CODEWHALE_SANDBOX_NETWORK_ACCESS`), a `danger-full-access` posture, or the existing post-denial elevation prompt that grants network for a single call. Yolo and `--yolo`/Bypass are unchanged — they resolve to `danger-full-access`, which applies no sandbox at all. `external-sandbox` reports the network it was actually granted instead of hardcoding `true`, and `/status` reads the flag instead of printing "network on" for every workspace-write policy. Platforms with no sandbox backend (default Linux without bubblewrap, and Windows) still enforce nothing, and both `/status` and `doctor` continue to say so. - The nightly Windows ARM64 artifact build works again. Every nightly from 2026-08-16 failed while compiling `codewhale-tui`, deterministically on the same codegen unit across all three build attempts, with `thread 'optimize module codewhale_tui...-cgu.13' has overflowed its stack`. The trigger is stack depth in the LLVM worker threads that run per-codegen-unit optimization, not the workflow's `lto=off` override: holding the crate and every flag fixed and varying only `RUST_MIN_STACK` on aarch64 shows 1 MiB crashes rustc while 2 MiB and 4 MiB succeed. Unix std defaults to 2 MiB and passed; the Windows ARM64 runner sat under the requirement. Nightly now sets `RUST_MIN_STACK` explicitly for every target, because the requirement follows from the size of `crates/tui` rather than from the platform. The redundant `codegen-units` override is gone -- `[profile.release]` already sets 16, so restating it never changed anything. Shipped binaries were never affected; `release-artifacts.yml` builds `--profile dist` with fat LTO and `codegen-units = 1`. - Test debt: the transcript history-cell suite has been rebuilt. It was 123 tests across 3,964 lines, and about a third of it pinned the current skin rather than any behavior -- `assert_eq!(spans[1], "⣤")` for the reduced-motion marker, `title_span.style.fg == theme.tool_title_color`, `visible[1] == "▏ done: scan repo"`, four separate tests each asserting one shape of fenced code never takes the transcript rail, and one test whose only assertion was `!text.is_empty()` under a name promising it checked the rendered tool id. Assertions like those break on every legitimate visual change and catch nothing a reader of the transcript would notice, which is the liability `d64b9429b` named. The replacement is 40 tests, each named for the property it protects and asserting the property instead of the token: reduced motion is checked by rendering the same running card at two different elapsed times and requiring the frames to match -- which also catches an animation leak the glyph constant missed -- and a frozen marker must stay visible rather than landing on the spinner's invisible blank (U+2800). Severity colors are checked by requiring warning not to read as error rather than by naming a palette entry. A streaming assistant glyph must actually pulse when motion is allowed, checked against `pulse_brightness` rather than by sleeping on the 2s sine. Each of the invariants claimed was verified to fail the new suite when deliberately broken in the renderer. ## [0.9.10] - 2026-08-19 - 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. - `registry_sync` no longer ships the full MCP Registry catalog into the conversation. It takes a required query, scores the local snapshot host-side, and returns at most eight matches; the complete catalog stays on disk, and the compaction and spillover exemptions that let a multi-hundred- kilobyte dump reach the model unchanged are gone. - Providers that mirror the outgoing `(reasoning omitted)` replay placeholder back as a reasoning delta no longer have that echo ingested as real thinking: the exact transport placeholder is dropped on arrival, so live sessions stop showing a stream of placeholder reasoning blocks and saved transcripts stay free of them. - Mid-stream connection drops during an interactive turn no longer persist a synthetic `[runtime]` user message. Retry state is a typed engine-internal descriptor; a thinking-only drop re-issues the request without claiming a partial reply was preserved, the retry budget is enforced in mechanism, and recovery produces exactly one authoritative final answer. Codewhale v0.9.10 is a retention, identity, and product-clarity release: the shell and transcript can no longer retain unbounded tool output in memory or on disk, mid-turn history inserts no longer strand in-flight tool rows, every agent that ran this session is visible from `/agents list`, the PTY acceptance lane has a stall watchdog and bounded CI steps, approval outcomes are durable and fail closed (cyq1017, #5360), and three $HOME disk leaks are reclaimed. Extension surfaces now name their real state and act only through the reviewed install and trust flows, and sub-agent, shell, task, and workflow state is owned by the session that created it (#5518). Test threads get an 8 MiB stack so the lib suite can no longer abort under load. ### Fixed - First run starts on the welcome screen again. A missing key no longer skips Welcome and auto-opens the local-provider list: Enter walks to the calm provider explanation, then Enter opens the picker so a first API key can be set. Returning missing-key recovery still opens the picker on launch. - A foreground `bash` command that named no timeout is bounded again. The model-facing `bash` tool left an omitted `timeout_ms` at the internal ceiling (~24.8 days) instead of the 120 s default its own schema advertises, so a CLI that blocked on an interactive prompt or a hung network call held the turn open indefinitely — one report sat on a single unauthenticated CLI call for over two hours with the tool row simply counting seconds. The advertised default now applies, which arms the existing recovery: the process is killed and the model is told to rerun with `background=true` and poll with `action="wait"`. An explicit `timeout_ms` is still honored for genuinely long foreground work, and background and interactive runs keep their own lifetimes. - The Extensions (`/plugin`) Marketplace is no longer a read-only list. Every recommendation and stored candidate names its truthful state and primary action — Add, Enable, Configured, or Unavailable — and Enter or a mouse click runs that action through the existing reviewed `/mcp add recommended`, `/mcp enable`, and `/plugin` install/trust controllers, so no second trust path exists. Browser Use and Sandbox Runtime stay honestly Unavailable with their real setup routing instead of implying an install Codewhale cannot perform. - The Extensions MCP tab now renders one honest inventory: the header count and the visible rows derive from the same configured-server set, so `MCP (6)` can no longer sit above two rendered rows. Disabled servers stay visible and labeled disabled instead of silently disappearing, and configured servers absent from the live snapshot list as not-yet-inspected with their own explicit reload affordance through the MCP command controller. - Installed plugin rows now act on their real state: Enter opens an active bundle (`/plugin show`), offers Enable for a trusted-but-disabled bundle, or routes an untrusted bundle to the existing trust review — through the same confirmation and persistence controllers as the slash commands. - Sub-agent handoffs and rosters, background shell jobs, durable tasks, delayed continuations, and workflow controls are now scoped to the session that owns them. Records carry immutable root-session ownership, stale completion-channel payloads are rejected before deduplication, background work drains and reports only to its owning session, and legacy ownerless jobs fail closed (#5518 failure class reported by @hxfhd; the report's exact JavaScript provenance was not claimed as reproduced). - The resolved route envelope now reaches every outbound model call: all wire dialects and auxiliary calls clamp at the shared transport seam under one wire/reservation budget, provider input limits are honored, and switching models on the same protocol no longer inherits the previous model's limits (#5516, #5518). - First-run continuity: the chosen onboarding provider persists across restarts, a missing first-run config no longer interrupts the flow, and the automatic working-agreement checkpoint renders as a standalone setup handoff instead of regressing the onboarding rail to the full wizard's 4/10 progress. - Explicitly worded natural-language `/goal` declarations now create a durable goal in the provider-neutral engine before model dispatch, while ordinary tasks and quoted transcripts stay out of goal mode and prose acknowledgement alone can no longer stand in for goal creation. - `/model` now keeps the current Z.ai default (`GLM-5.3`) visible when an older installation has an explicit `GLM-5.2` route saved. The saved 5.2 route remains exact; choosing 5.3 sends and remembers the distinct 5.3 ID. - The constitution checkpoint now leads with the bundled balanced agreement; the default path writes no custom constitution. The startup launch surface distinguishes read-only Chat from folder-bound, approval-gated Work. - Tabby and other IME bridges no longer observe a stale visible caret while a frame diff is being painted; Codewhale hides the cursor during the diff, restores the canonical composer cell, and only then reveals it again (BrathonBai, #5023). - Pre-header HTTP/2/SSE transport failures get one bounded HTTP/1.1 retry; authentication, provider-semantic, response-body, and already-pinned HTTP/1 failures remain fail-closed (demian-welt, #4683). - MCP `tools/call` images now travel as bounded typed content instead of leaking base64 through model-visible JSON. Direct and parallel calls share the same MIME, size, validation, and one-image boundary (PR #5515 by @cacdcaecawae). - Linux npm installs and updates race GitHub Releases against the CNB mirror at the checksum-manifest layer, then download from the first verified source without making users wait through a doomed slow-source timeout. - `CODEWHALE_PREFER_BWRAP` now applies the documented Linux sandbox override, and Codewhale-era names own build metadata, hook session/tool-call IDs, and sandbox child markers. The corresponding `DEEPSEEK_*` names remain as 0.9.x compatibility aliases (#5443). - Windows default launch prefers Windows Terminal: zip archives ship `codewhale.bat` (CRLF, `wt.exe` then the exe), `install.bat` copies that launcher, and the NSIS Start Menu shortcut opens it instead of the raw binary (#1854). - `fix(tui): make the header status mark honour its setting` — `status_indicator` did nothing for three of its four documented values. The header hardcoded a leading `cw` span *and* asked for a second mark beside the effort chip, then filtered the second one against the literal `"cw"`; because `cw`, the legacy `whale` opt-in, and every unknown value all normalize onto that same mark, the filter discarded them and left `off` with nothing to turn off. `cw`, `whale`, `off`, and a typo all rendered byte-identical headers. There is one mark now and the setting owns it: `cw`/`whale` draw the typographic mark, `dots` draws the activity frames, `off` removes it (thejayjetson, #5512). - `fix(tui): rebase active-cell tool bindings on every mid-turn history insert` — `/rename` mid-turn left the running tool row spinning forever (#5478). - `fix(tui): bound what the shell and transcript retain from tool output` — a 1.1 MB Bash call kept over a megabyte resident for up to an hour; raw streams now cap at 16 MiB in flight and release delivered output, and retained tool outputs cap at 64 KiB per record / 8 MiB per transcript (#5472). - `fix(tui): reclaim the three $HOME disk leaks` — orphaned session dirs, the unbounded audit.log, and stranded writer temp files. - `fix(tui): persist approval outcomes before execution` (cyq1017) — approval receipts are committed to a session-owned log before execution proceeds; unpersistable evidence blocks the tool; resume reconstructs closed and interrupted approvals (#5360). - `test(tui): break the LazyLock/env-barrier deadlock in the test harness`. - `ci: give test threads the 8 MiB stack they need` — the lib suite aborted with SIGABRT under load on the default 2 MiB stack. - YOLO entry points honor a locked approval policy: `--yolo`, `/mode yolo`, `/zidong`, and Alt+Y can no longer set Full Access + trust + shell when config or managed requirements own the posture. - Terminal PTY tools fail closed without a sandbox backend under a narrowed filesystem posture, and otherwise start `$SHELL -i` through `SandboxManager::prepare` like `bash`. - Skill update refuses to replace a directory that has no `.installed-from` marker — same ownership gate plugins already used. - `cp`/`mv` are workspace-safe only when every path operand stays inside the workspace — Auto-Review no longer auto-allows `cp /etc/passwd .`. - Main CI no longer shares one concurrency group per branch: each SHA gets a verdict instead of a cancelled pending run. A hermetic Safety gate job runs authorization tests in under 15 minutes (test bankruptcy restructuring — no tests deleted). - Config-fixture tests no longer honor `lock_test_env` as a license to read a populated `~/.codewhale/config.toml`; they need an `EnvVarGuard` like settings already did. Safety-gate and CNB workspace tests pin a hermetic `CODEWHALE_HOME`. `exec_persistent_service` is serialized in nextest and inside the cargo-test binary instead of dropped (#5355). - Short CLI no longer waits up to three seconds for a telemetry POST on exit; `session_end` is recorded and the buffer ships on the next interactive session. - Bare `/` now opens a deliberately small starter set: `/help`, `/setup`, `/model`, `/settings`, `/resume`, and `/rc`. The full command inventory remains searchable through `/help`, the command palette, and direct prefix typing, without front-loading the entire control surface (#5442, #5439). - First run now asks only for decisions needed to become usable, keeps the offline route explicit, and leaves optional provider, tools, policy, and appearance work in the progressive `/setup` repair guide. The idle aquarium asks one task-oriented question instead of advertising a tutorial or command billboard, and the localized telemetry choice appears after the workspace is ready without blocking the composer. - Provider, active model, and reasoning effort moved out of the crowded header into a quiet, width-aware footer identity. Compact layouts keep model and effort before provider detail and shed whole low-priority groups instead of clipping the composer or control hints. - The model picker no longer re-parses `~/.codewhale/config.toml` once per provider when deciding who has a saved key. ### Added - `/workflows` opens a live run dashboard over this workspace's durable workflow journal: every retained run with status, phases, child roster, progress, and host-side cancel — observation only, it never launches a run. - Repository instructions now assemble from the actual containing checkout: applicable `AGENTS.md` files resolve repository-root to current-directory in order under one aggregate budget, a linked worktree is its own root, and scope is never inferred from path mentions or whichever branch is named `main`. - `/goal` is a codex-style control plane: setting an objective dispatches it to the engine, which owns the goal and starts the first goal turn itself — the objective is never echoed back as the user's own message, pause/resume are real control ops, and the hunt-era vocabulary and trophy cards are gone. - `/extensions` and `/plugins` open one localized inventory for Hooks, Plugins, local Marketplace catalogs, Skills, and MCP. Reviewed suggestions include Playwright, Chrome DevTools, Cua Computer Use, Browser Use, and the sandbox runtime without granting trust or installing anything on open. - Turn Inspector now opens the newest turn and pages across complete recorded user, reasoning, tool/subagent, and assistant output with page-scoped search, copy, and export (sky-sun-moon, #1682). - Background tasks have bounded incremental persistence, durable terminal reasons, truthful timeout/cancellation receipts, restart recovery, and interruptible continuous-goal delays (#5497, #5508). - `/title` once again controls the terminal window title independently from `/rename`, survives session save/load, and sanitizes control, bidi, and zero-width characters (PR #5509 by @SparkofSpike). - MCP snapshots preserve whether capabilities were advertised by the server, discovered through the bounded legacy fallback, or not observed (#4170). - `codewhale auth status --diagnostic` reports canonical paths, isolation source, backend class, and value-free provider-source presence without opening credential stores or creating/migrating state (#2369). - `codewhale doctor --probe-search` performs an explicit credential-free, policy-checked transport probe for the selected search provider; ordinary doctor and JSON output remain offline (#5442). - The safe deferred `read_media` tool is available to supported read-only roles, and history receipts distinguish localized tool execution outcomes without exposing raw payloads (#5102). - **npm Linux x64 first-party source selection.** The wrapper concurrently fetches the GitHub Releases and CNB checksum manifests for the exact package version, locks the first source whose HTTP response and manifest validate, and downloads binaries only from that source. Explicit `CODEWHALE_RELEASE_BASE_URL` / `CODEWHALE_USE_CNB_MIRROR=1` still skip the race; other targets stay on GitHub. - `/workflow ` and `/workflow run ` now produce a bounded, tool-less proposal for review. Only `/workflow confirm` can launch that reviewed draft; status, cancel, settings, and the `/workflows` dashboard stay host-owned and do not spend a model turn (#5439). - `feat(tui): add cancellable cadence to continuous goals` (M-Maciej) — `[goal] continuation_delay_seconds` gives coordinator goals a visible quiet period between successful turns while reusing the existing coalesced goal continuation token; Esc, Ctrl+C, pause/done/blocked/clear cancel before the next provider request, and failures never continue (#5508). - `feat(tui): add command context adapters and migration gate (FEAT-015)` (aboimpinto) — TUI-owned capability facets, a dual-path dispatch seam, and source-aware CI enforcement so a command slice cannot claim to be migrated while it still accepts concrete `App`. Zero production commands migrate in this slice (#5316). - `feat(web): move docs/hooks and docs/troubleshooting onto the dictionary spine` (Lstarsky0) — both pages now read copy from the locale dictionaries instead of inline bilingual literals (#5337). - `feat(web): move docs/constitution and docs/runtime-api onto the dictionary spine` (Lstarsky0) — both pages now read copy from the locale dictionaries instead of inline bilingual literals; another incremental phase of #5337, not completion of the full epic (#5517). - `docs(i18n): complete Tier 1 of Chinese docs localization` (SparkofSpike) — Chinese and Indonesian docs move to `docs/zh_hans/` and `docs/id/`, with redirect stubs at the old paths for one release cycle (#5482). - `feat(tui): show repository context in git chrome` (wuisabel-gif) — the TUI header now identifies the active repository or linked worktree before the branch and dirty marker, so operators can see where the agent is working without opening the worktree manager (#5437). - `feat(tui): formalize the status-bar color grammar` — seven semantic families live in `docs/design/STATUS_BAR_COLOR_GRAMMAR.md` and `palette::grammar`; header and phase-strip ink resolve through named `ChromeInk` slots so chrome cannot invent an eighth meaning or spend Failure red on a dirty worktree or selected mode. The footer's session metrics strip resolves through the same inks, and the red reservation is checked against every selectable theme, not just the whale default; typed footer toasts resolve through the grammar too. Repo/worktree chrome stays metadata and still renders when Git names a location but not a ref (#5437). - `feat(tui): first slice of the agents roster` — every agent that ran this session, receipts-only, via `/agents list` and the sidebar fan-out rows (#5479 spec items 1 and 5). - `ci: bound PTY acceptance and add a stall watchdog to the harness` — QA_PTY_STALL_TIMEOUT_SECS aborts a wedged PTY run with a diagnostic; the isolated PTY step is capped at 15 minutes; Windows NSIS provisioning gets a bounded retry (#5496). - `chore(scripts): dev-cache warns before it fills a disk` (#5465 class). ### Contributors - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) — restored `/title` as an independent, persistent terminal-window title in PR #5509, in addition to the Tier 1 Chinese and Indonesian documentation work below. - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) — extracted the turn-loop stream processor in PR #5514 while preserving retry, cancellation, usage, TTFT, steering, and partial-response behavior. - [OctoBored](https://github.com/OctoBored) (`@OctoBored`) — supplied the working no-token Star History mirror used across the localized README set after the canonical chart endpoint began returning a restricted placeholder (#5510). - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) — added provider-neutral typed MCP image forwarding in PR #5515; the harvested version also makes malformed image fields produce a visible omission receipt. - [DingYong4223](https://github.com/DingYong4223) (`@DingYong4223`) — reported the narrow-terminal completion truncation closed by the bounded hover reveal (#998). Thanks also to @AiurArtanis and @formp3 for identifying the affected completion surfaces. - [sky-sun-moon](https://github.com/sky-sun-moon) (`@sky-sun-moon`) — reported the missing full per-turn input, reasoning, tool, and assistant pages that shaped Turn Inspector navigation (#1682). - [cy2311](https://github.com/cy2311) (`@cy2311`) — reported the Windows launch path that now ships and installs a Windows Terminal-aware batch launcher (#1854). - [demian-welt](https://github.com/demian-welt) (`@demian-welt`) — provided the reproducible pre-header SSE transport failure behind the bounded HTTP/1.1 retry (#4683). - [BrathonBai](https://github.com/BrathonBai) (`@BrathonBai`) — reported the Tabby/CJK IME candidate-window jump that led to the hide-diff-position-show cursor transaction (#5023). - M-Maciej (@M-Maciej) — the real-world organization-coordinator use case and 5–30 minute cadence requirement behind cancellable cross-turn goal delays (#5508). - cyq1017 (@cyq1017) — approval outcomes are persisted before execution can proceed: receipts commit to a session-owned log first, unpersistable evidence blocks the tool, stale decisions are rejected, and resume reconstructs closed and interrupted approvals (#5491, closes #5360). - aboimpinto (@aboimpinto) — the TUI-owned dependency-injection and migration infrastructure that makes slash-command extraction safe: seven capability facets, a dual-path dispatch seam, and source-aware CI enforcement so a command slice cannot claim migration while it still accepts concrete `App` (#5506, EPIC-005/FEAT-015 under #5316, which they also filed). - wuisabel-gif (@wuisabel-gif) — the TUI header now names the active repository or linked worktree before the branch and dirty marker, derived from Git's common directory and capped by shell density tier (#5511, the repo/worktree slice of #5437). - SparkofSpike (@SparkofSpike) — Tier 1 of the Chinese docs localization: Chinese and Indonesian documentation moves to `docs/zh_hans/` and `docs/id/` with redirect stubs held at the old paths for one release cycle (#5507, epic #5482, which they also filed). - Lstarsky0 (@Lstarsky0) — `docs/hooks` and `docs/troubleshooting` move onto the dictionary spine, retiring their inline bilingual literals in favor of locale dictionaries with token-aware code spans (#5504, closes #5337, which they also filed). - Lstarsky0 (@Lstarsky0) — `docs/constitution` and `docs/runtime-api` follow the same dictionary spine: 28 inline `isZh` branches become typed English and Chinese dictionaries held to key and token parity, while the other sixteen locales keep the English fallback (#5517, a further phase of #5337). - @thejayjetson — the header status-indicator report that pinned the regression to a specific setting, with every value, theme, and `fancy_animations` combination already ruled out (#5512). - hxfhd (@hxfhd) — reported the deterministic cross-session contamination class behind this release's session-ownership boundary, plus route budgeting evidence (#5518). - sfdzhmr (@sfdzhmr) — reported the route budgeting root causes that exact route-limit propagation now closes (#5516). ## [0.9.9] - 2026-08-18 Codewhale v0.9.9 is a truth-and-resilience release: the shell tool can no longer wedge a session when the host runs out of disk or descriptors, unverified context windows and output ceilings are labeled honestly at every surface, DeepSeek V4 is priced on the published peak/off-peak tiers, SSE UTF-8 fails closed in every dialect, Fleet shadowing is visible, bwrap gets container essentials and extra roots, the `dsh` skin rides the bundle profile, the `agent` tool schema is down to 12 fields, and README/website locales grow to 18 and 8. ### Fixed - The lowercase `bash` tool no longer wedges when its complete-output spill file cannot be created: a full temp volume or exhausted descriptor table used to fail *every* call — `echo ok` included — with the harness-internal "Failed to create streaming shell output" and never recover until the host was cleaned up. The spill is now best-effort (the bounded tail is still returned and the truncation notice says why the full-output path is missing), and any remaining spawn/stream failure names the exhausted resource — disk, file descriptors, memory — and says the next call is safe to retry (#5465; the wedge that took out the owner's own 0.9.9 session). - A concrete route/offering output limit now outranks the conservative 8,192-token compatibility guess for an uncatalogued model. Routes that publish no output limit remain fail-closed, documented model ceilings stay authoritative, and a route limit can never raise the requested cap (#5460). - Context-window honesty at every surface (#5239, #5441): the `model-name hint` and `fallback` rungs of the context-window ladder are guesses, and every surface that renders one now says so — the status line, `/status`, `/config`, the context-pressure message, the model picker chips, and the auto-router inventory. Unverified windows still drive real budgets (compaction trigger, context meter, output reservation); they just stop reading as capabilities anyone checked. A window parsed from an `_Nk` model-name suffix (`qwen3-32b-256k` → 256K) is now its own `model-name hint` rung below `catalog`, because it is optimistic rather than conservative — a catalog or provider-reported value beats it. The `[providers.] context_window` override remains the hard fix and renders as `configured` with no marker. - Output-ceiling honesty (#5440): an Anthropic-family model the catalog does not describe keeps the 64K Messages floor as its clamp and the ChatGPT/ Codex OAuth route keeps its 4K policy, but `OutputCeilingSource` gained an `unverified` rung for both, so exec-stream receipts and the model picker label them `unverified`/"assumed floor" instead of `documented`. Clamp values are unchanged. - Telemetry default-on is visible (#5441): `codewhale doctor`'s runtime-posture section gained a `telemetry=on (default)`-style row with the source that decided it (cli | env | config | default), and `codewhale config get telemetry` reports the resolved consent with its source instead of `key not found` on a machine whose batches ship. Truth change only; resolution and behavior are untouched. - Fleet: a scout's read-only shell carve-out (#5428) is now honored by both the posture gate and the execution envelope, so `git log`, `find | head`, `npm view` and the other bounded read-only commands run in-place instead of being refused as "Executes" (#5426). Delegation still never widens authority: the role-isolation test and docs/SUBAGENTS.md pin that a child cannot exceed its parent's posture (#5426, #5435). - `/rename` and `/title` now apply mid-first-turn: the session file does not exist until the first autosave, so the rename fell through with NotFound; the shared path now prefers the per-session checkpoint and rebuilds from App state, with a PTY regression test through the live event loop (#5430). - `integrations dsh plan` no longer refuses DeepSeek's default Responses-dialect route (`deepseek-v4-flash`); Responses and Anthropic-Messages routes are carried through pi-ai `openai-responses` / `anthropic-messages` instead of being approximated or refused; only credentialed base URLs are still refused, with an error that names provider and model (#5434). - Session cost no longer sits at `unverified_live_pricing` when live pricing cannot be verified (control-plane 503, Models.dev capabilities-only overlays): provider-docs bundled fallback rates for the DeepSeek V4 family on Fireworks / OpenCode Zen restore a usable figure, live per-provider rows still win, and `kimi-k3` stays unpriced until a published rate exists (#5241; harvested from #5402). - Release assets: `release.yml` asset-freshness checks compare against the release job's own `started_at`, so job-level reruns of the npm step are no longer poisoned by earlier uploads (#5429). - macOS CI: the `agent_focus_pty` auto-review receipt test waited on a worker that had already completed and raced the rail's focus; it now holds the child's wrap-up and waits for a settled live row (refs #5056, #5403). - DeepSeek V4 pricing follows the published peak/off-peak tiers (peak 01:00–04:00 and 06:00–10:00 UTC; off-peak is half of peak) for `deepseek-v4-flash` and `deepseek-v4-pro` in USD and CNY, resolved from each turn's recorded time; the stale single-tier rows understated cost up to ~4×. Because every direct DeepSeek first-party rate is now time-windowed, the scorecard fails closed (`missing_recorded_time`) on an undated DeepSeek turn instead of guessing a tier (#5470; #5241 follow-up, verified against api-docs.deepseek.com on 2026-08-17). - SSE UTF-8 split across HTTP/2 DATA frames now fails closed in every streaming dialect: a shared strict decoder, tail flush, and `decode_failed` propagation (`InvalidSseUtf8`) replace the per-dialect approximations, with byte-chunk decoder tests (#5374; supersedes draft #5404). - CI: `release_four_read_only_fleet_roles_launch_with_canonical_prompts` answered Fleet children with SSE while they call the blocking JSON path; the parse failure was retried and double-counted the worker on slow macOS runners (#5471; refs #5056). - Context: every web tool surface (`Web`, `web_search`, `web.run`, `fetch_url`) now uses the noisy-result soft limit, so large fetches are compacted like shell output instead of consuming the ordinary hard limit (#5474, thanks @h3c-hexin). - Routing: a lowercase saved selector such as `glm-5.2` resolves against the owning Z.ai / DeepSeek catalog row (case-fold fallback, only when exactly one provider-owned wire id matches) instead of being classified as another provider's bare model (#5475, thanks @h3c-hexin; diagnosis by @asto18089 in Pinvou/CodeWhale#14). - Model catalog brought current as of 2026-08-17 against the official pricing pages: gpt-5.6-terra / gpt-5.6-luna rates, `claude-sonnet-5` keeps $2/$10 (the announced September increase was withdrawn), `claude-opus-5` added, `kimi-k3` and `kimi-k2.7-code-highspeed`, `MiniMax-M2.7-highspeed`, Mistral first-party rows, xAI `grok-4.5` / `grok-4.3` with long-context tiers, Gemini and Qwen limits, and RedNote's `dots3-note` preview as an OpenRouter row (no first-party API exists yet) — every number carries its source and a pinned test (#5485). - Website: copy on codewhale.net rewritten in plain declarative sentences — one idea per sentence, numbers from the generated facts, no self-narration — with a voice sheet at docs/design/WEB_VOICE.md (#5483). - CI: the release workflows no longer restore npm/cargo caches after checking out a caller-supplied SHA — the CodeQL cache-poisoning Highs #88–#107 are closed with a contract test over the workflow files (#5463). - Compact TUI rows below 60 columns no longer reserve a hidden session-metrics strip, so narrow terminals reclaim the row instead of clipping the transcript (#5486). - Ghostty's truecolor underwater field now uses a dedicated synchronized 60 FPS lane instead of the legacy 30 FPS compatibility cap, with continuous caustic fades replacing visibly stepped color changes. - Live reasoning's advertised `Space:expand` action now runs before the composer's first-character paste-burst hold, while spaces in an active paste remain payload. The newest reasoning preview also spends only genuinely free viewport rows before truncating instead of stopping at the fixed 10/12-row fallback on roomy terminals. - Strict `cargo doc` builds no longer fail on bare URLs in rustdoc comments; the remaining links are explicit Markdown targets (#5489). ### Changed - The model-facing `agent` tool advertises exactly 12 fields — `action`, `prompt`, `type`, `profile`, `name`, `agent_id`, `message`, `until`, `detached`, `worktree`, `write_roots`, `resume_from` — down from 33 (#5324, refs #5123). Budgets (`max_steps`, `wall_time_secs`, `max_depth`), routing overrides (`model`, `model_strength`, `thinking`), worktree-path knobs, the deliberate/spawn-contract fields and the wait/status/interrupt extras moved off the advertised schema. Every removed field stays parse-accepted and honored unchanged (same contract as `token_budget`), so saved transcripts, ACP/MCP clients and Fleet configs replay as-is; the #5426/#5435 containment clamps are untouched. Child budgets now resolve from role defaults (60/120 turns, 1800 s wall time, unchanged clamps) and new `[subagents]` keys `default_max_steps` / `default_wall_time_secs`. Because the tool catalog is part of the session-pinned prompt prefix (docs/CACHE.md), upgrading re-fills the KV prefix once per session. - TUI prose — user messages, assistant answers, and reasoning/thinking — now wraps at the full content width on wide terminals, matching tool/status cells, instead of stopping at a 105-column rail that left a dead right margin on ultrawide displays (#5436). - Configured skill prompts are stable across session roots and operating systems: only custom configured roots hide their physical path, ordinary workspace/global skills keep a discoverable privacy-safe path, warning replacements are boundary-aware (including non-UTF-8 Unix paths), and Windows separators render as `/`. The skills prompt is also 50 bytes leaner without raising a runtime-contract ceiling (#5492, #5473). - Auto-router classifier requests accept `[auto.router] timeout_secs`, while preserving the existing default when the key is absent (#5494). - Every `ci.yml` job now has an explicit 10–90 minute timeout appropriate to its workload, bounding stale assigned runners instead of inheriting GitHub's six-hour default (#5495). - The docs shell and shared web components now route localized copy through the typed dictionary spine; these are two incremental phases of #5337, not completion of the full epic (#5488, #5490). - Dependency: rusqlite 0.40.2 (#5391). - Documentation: stale A/B/C-tier references, provider defaults, module descriptions, and line anchors now match the current code (#5481). ### Added - `[transcript] prose_measure` (positive integer, optional): caps prose wrap at N columns for owners who want a bounded reading measure on ultrawide terminals. `0` or absent keeps the full width; negative or non-integer values are rejected with a clear config error. Tool, diff, and status cells never inherit the cap (#5436). - Localization: README translations for Français, Deutsch, 繁體中文, हिन्दी, Türkçe, Italiano, Polski, العربية and Català join the existing nine (#5451); codewhale.net routes fr, de, ca, hi, tr, it, pl and ar (with `dir="rtl"` plumbing) as partial locales (#5453). - Docs: README Integrations section (incl. the DeepSeek Harness `dsh` plugin path, docs/INTEGRATIONS_DSH.md) localized across all READMEs; RFC keeping the deterministic-first auto-review hybrid (#5427); Claude Code parity reference for agents/workflows/plugins/skills (docs/design/CLAUDE_CODE_PARITY.md); config.example.toml / SUBAGENTS.md / TOOL_LIFECYCLE.md brought back in line with the code (#5447). - `dsh` integration: the Codewhale palette is applied through the bundle profile via dsh's documented `overrideTokens` (on by default; `codewhale integrations dsh update --skin false` turns it off), replacing the 0.9.8 exported-CSS skin that dsh's inline body variables overrode (docs/design/DSH_BUNDLE_SKIN.md, docs/INTEGRATIONS_DSH.md) (#5469). - `dsh` integration: an ambient ocean scene behind the DSH web UI — slow whale silhouettes, a school of `><>` glyph fish, bubbles — drawn on a canvas under a translucent veil of the Codewhale palette, plus an explicit responsive `WHALE BROTHERS / CODEWHALE × DEEPSEEK HARNESS` lockup; light and dark, ~30 fps capped, paused when hidden, a static frame under `prefers-reduced-motion`; on by default with the skin, `codewhale integrations dsh update --ocean false` turns it off (#5484). - Fleet: agent shadowing is visible — a roster-row badge, a Layers block in agent detail, and a `doctor` "Fleet roster layers" section (JSON `operate_fleet.roster.multi_layer`), in all 15 TUI locales. Layer collapse and `[fleet.profiles]` migration stay for 0.9.10 (#5098). - Sandbox: bwrap containers get the `--dev/--proc/--tmpfs` essentials plus configurable extra roots (`bwrap_ro_roots` / `bwrap_dev_roots`) so toolchains that live outside the workspace stay reachable read-only (#5410). - Tests: `crates/tui/tests/README.md` states the keyless assembled-journey rule and maps the Auto-Review guardian acceptance items to the engine journeys that exercise them (#5361). - OrcaRouter's default endpoint is classified as an aggregator billing surface, so pricing and session-cost reporting use the correct billing posture instead of treating it as a first-party provider (#5493). - Dependencies: ratatui 0.30.2, thiserror 2.0.20. ### Removed - `dsh` integration: the exported-CSS skin file and its "skin export" status line (superseded by the bundle-applied `overrideTokens` skin, #5469). ### Contributors - hexin (@h3c-hexin) — a concrete route/offering output limit outranks the 8,192-token compatibility guess for an uncatalogued model (#5461, closes #5460); web tool results use the noisy soft limit (#5474); owned direct model casing resolves safely (#5475); and configured-skill prompts stay stable across ephemeral roots and operating systems (#5492, #5473). - Gabriel-Degret (@Gabriel-Degret) — configurable auto-router classifier timeout (#5494; first contribution). - @asto18089 — diagnosed the Z.ai `glm-5.2` casing collision and wrote the first provider-scoped fix in Pinvou/CodeWhale#14 (carried upstream in #5475). - Reports and reproductions that shaped this release: @hardy922 (context- window honesty, #5239), @redstar (bwrap extra roots, #5410), @all-lopezg (SSE UTF-8 garbling on DeepSeek Flash, #5374), @alitvak69 (unverified live pricing, #5241), and @wuisabel-gif (the macOS filtered-suite hang investigation on #5056). ## [0.9.8] - 2026-08-16 Codewhale v0.9.8 ships the remaining assigned finish. Remaining web settings polish moves to v0.9.9. Prefab third-party templates that have a published OpenAI-compatible host ship here (#5350). ### Fixed - `sudo` (and `su`/setuid helpers) work again for wheel-group administrators who want Codewhale to be able to escalate: the Linux startup hardening's irreversible `PR_SET_NO_NEW_PRIVS` flag — inherited by every child process — is now skippable with `CODEWHALE_NO_NEW_PRIVS=0` (#5413). The flag stays on by default; the no-ptrace and no-core-dump measures are never skipped. - Abort-class process deaths no longer poison the terminal (#5424). A stack overflow, allocation failure, or double panic skips the panic hook and every cleanup guard, which is how a v0.9.7 user's mid-turn exit left mouse capture leaking SGR sequences into their shell. An async-signal-safe handler now restores the terminal modes and appends a one-line cause marker to `~/.codewhale/crashes/last-fatal-signal.log` before re-raising, keeping the honest 128+signal wait status. A SIGKILL (OOM killer) remains uninterceptable by design. ### Changed - Prompt-cache prefix is pinned for the session. The tool loop no longer recomposes the system prompt from disk on every model step, so an agent writing a file no longer busts the provider KV prefix cache mid-turn. The system prompt and tool catalog are re-composed only on a declared header change (`/model`, mode, goal, session resume), which re-pins under a logged reason; an undeclared change is reported as drift and the original pin is kept instead of silently becoming the new baseline. Workspace, AGENTS.md, skills, memory, and goal drift now reaches the model as one bounded `` user message at the next user turn — a history append, not a header rewrite. `/cache stats` shows the pin reason, the last-miss reason, the undeclared-drift count, and the context-update count. See [docs/CACHE.md](docs/CACHE.md). - Plugin compatibility is now per-component. A reviewed, trusted, enabled bundle that mixes Skills or MCP with unsupported commands, agents, hooks, LSP, native, filesystem-roots, or lifecycle-mutation declarations keeps the supported adapters active and reports the rest as inactive (`full` / `partial` / `unsupported`). All-unsupported bundles still cannot be enabled. The capability hash is now v2 and binds this build's activation policy, so older v1 receipts and any later adapter-enablement change fail closed as needs-review. Skills and each MCP transport re-request their own capability at the consumption boundary. ### Added - Opt-in multiline composer mode (`composer_multiline_mode = true`) makes Enter insert a newline and Shift+Enter send. Alt+Enter, Ctrl+J, and supported Ctrl+Enter/Cmd+Enter behavior stays unchanged (#5345, @AiurArtanis). - `/plugin marketplace add|list|show|remove|install` completes the federated marketplace journey (#5311). `add` reads one LOCAL catalog document in the real published schemas (Kimi, Claude, Codex, or Codewhale native) — no network, regular files only — and persists it beside the plugin state with the same hardened, fail-closed store. `list`/`show` render every candidate with per-entry diagnostics, display-only tiers, and honest install plans that say when Codewhale cannot fetch a source; `install` routes through the existing reviewed installer, so installed bundles still enter disabled and untrusted. Foreign auto-install policy (Codex `INSTALLED_BY_DEFAULT`) is visibly ignored; nothing is auto-installed, auto-trusted, or granted vendor trust. - `/rc` attach now includes an observed `owner/name` git remote when the folder has a GitHub, CNB, or Gitee origin, so CWC can label the paired session. Paths stay off the wire. Reconnect after both this client and CWC #202 land to backfill existing empty rows. - The local Runtime web client keeps the thread rail clipped so **New thread** cannot paint over the session fact chips. Chips wrap instead of sliding under the rail. - Z.ai `GLM-5.3` is live on the Coding Plan and is now the default direct Z.ai model: `DEFAULT_ZAI_MODEL` resolves to `GLM-5.3` in both `codewhale-tui` and `codewhale-config`, and it is the first `/model` row after `/provider zai`. Explicit `GLM-5.2` selections (`model = "GLM-5.2"` and its `glm-5.2` aliases) keep their own id — only the default moved. Limits and reasoning options still inherit from `GLM-5.2` until Z.ai publishes distinct 5.3 numbers. No USD price is claimed. A live call can still 429 with entitlement code 1311 on accounts that are not provisioned for 5.3. - The TUI transcript renders Markdown blockquotes (`>` lines) with a quote rail — nested quotes, inline bold/code/links, wrapped continuation rows, and selection copy that keeps the quote text and skips the rail chrome. - Sub-agent details show the resolved model, fleet role, and type. Labels use the session/role name instead of a generic Agent N (#5371, #5287). - Documented catalogue output ceilings (including DeepSeek V4's 384K maximum) remain authoritative bounds, while ordinary requests start at a safe 64K cap and explicit overrides can raise it within the resolved route window. A clean output-limit stop continues the turn instead of killing it (#5373, #5516, #5518). Thanks @sfdzhmr and @hxfhd for the route evidence. - Ollama Cloud is a first-class hosted provider (`/provider ollama-cloud`) on the official OpenAI-compatible `https://ollama.com/v1` route. Local Ollama stays keyless. The exact released `ollama` + Cloud URL tuple keeps a bounded compatibility path across saved sessions, Fleet, and nested subagents; neighboring remotes stay custom and fail closed against inherited official credentials. - Homebrew ships a `codewhale` formula. `brew tap Hmbown/deepseek-tui && brew install codewhale` is the install path; `brew upgrade codewhale` updates it. The legacy `deepseek-tui` formula remains a deprecated alias for one overlap release. - `/title [name|off]` sets a per-session tab/window title, shown as `[title] …` in front of the terminal window title (`Codewhale` / `reasoning…` / `using tool…` / `done`). The `title` config key supplies the default (`/config title … --save` persists it); multi-window workflows can tell parallel sessions apart at a glance. `/title` is independent of `/rename`, which keeps naming the session in the picker and composer. Control, bidi, and zero-width format characters are stripped from both the saved session name and the window title, so the picker, the Runtime API, `codewhale sessions`, and the OSC 0 tab title all carry the same escape-free text (#5419, #5430). - Eden AI is a named OpenAI-compatible Chat Completions provider (`edenai`, aliases `eden-ai` / `eden_ai`) with `EDENAI_API_KEY`, global and EU base-URL overrides, a live provider-scoped model catalog, and `deepseek/deepseek-v4-pro` as the verified default. Generic reasoning fields stay omitted because Eden AI routes multiple upstream model families (#5422, Kai Nacke). - Children (sub-agents and Fleet workers) inherit the session's permission posture faithfully: Auto-Review's deterministic floor and model guardian decide a worker's held calls (fail closed when unavailable, never a prompt); under Ask a held call is raised in the parent's approval UI and the worker waits visibly; Full Access still fails closed on the safety floor. Each prompt-less decision is a one-line note in that worker's transcript (focus mode) and an audit-log record. - Worker role defaults keep what the role does not intend to withhold: every built-in role keeps network reads; `planner` may run read-only shell probes; `custom` inherits the parent's write/network/shell posture and is narrowed only by its explicit tool list or the spawning call. Read-only roles (`scout`, `reviewer`, `planner`, `verifier`, `consultant`) still never write the workspace. The focused worker's header states its effective posture from the runtime snapshot. - `/workflow status`, `/workflow cancel [run_id]`, `/workflow settings`, and `/workflow help` are answered by Codewhale itself from the run journal and live run state — no model turn — and `/workflow run ` launches a checked-in workflow as-is. `/config workflow` and `/config goal` explain the effective tables. The workflow tool now honors the session `[workflow]` table (`automatic`, `auto_start_read_only`, `require_approval_for_writes`, limits) instead of product defaults. - Goal mode enters as readily as DeepSeek Harness: the agent may create the session goal when a direct request describes a verifiable multi-turn end state, and Codewhale shows a one-line `Goal set` receipt with how to pause or clear it. Bare `/goal` shows plain progress (and how to continue when no turn is running), prints usage on an empty session instead of asking the model, and `/goal help|status` are reserved words. - Whale Teams in the terminal: the six Signal Cut whale identities (Scout, Patch, Harbor, Echo, Keel, Lantern) appear as species badges on `/fleet` roster rows and worker rows, with an identity portrait in the roster detail pane and a six-state word (Resting, Thinking, Working, Waiting for you, Blocked, Offline) derived only from the child's real runtime status. Colors come from the theme tokens, every glyph has an ASCII fallback, and the working wake animates only under full motion. See `docs/design/WHALE_TEAMS_TUI.md`. - A session metrics strip on the phase row (`4 turns · 108 steps │ LLM 11m46s · Tool call 1m52s │ TTFT avg 1.5s · 120 tok/s │ Cache hit 99% │ Input 9.3M`), on by default as the `session_metrics` footer item (`/statusline`, `[tui].status_items`). Every value comes from engine receipts — turn starts, per-model-call usage with stream time, time-to-first-token and whole-call time, tool start/complete edges, and provider-reported cache and input tokens. Cells without evidence are omitted, never estimated. `/status` prints the untrimmed line; the phase row sheds its lowest-value groups to fit the columns it actually has. - Auto-Review decisions nobody was prompted for are now visible in the transcript as one-line notes: model-guardian allow/deny verdicts with their risk tier and stated reason, guardian failures (denied, fail closed), deterministic policy blocks, and holds Auto-Review denied without pausing. The audit log keeps the full record. `/permissions` ends with the active posture, what it decides on its own versus never, and the audit-log path. The footer's `Esc to interrupt` hint is localized. See `docs/design/AUTO_MODE_PARITY.md` for the Claude Code / Kimi Code parity ledger and follow-ups. - `codewhale integrations dsh status|plan|connect|update|launch|disable|enable|remove` connects an existing official DeepSeek Harness (`dsh` 0.1.0-rc.6, verified) through Codewhale using only its documented seams: a `--patch` overlay that pins the exact Codewhale provider/model/endpoint identity (native `deepseek-official` route, or a hand-declared `openai-completions` route named `codewhale-` for OpenAI-compatible providers), the Codewhale permission posture exported as `DSH_PERMISSION_MODE`, and an append-only receipt. Codewhale writes only under `$CODEWHALE_HOME/integrations/dsh/`, never copies API keys or edits DSH files, never broadens permissions (`--allow-full-access` only mirrors an existing Codewhale full-access posture), and reports not-installed / offline / incompatible / detected / connected / stale-config / stale-version / disabled honestly. Anthropic Messages and OpenAI Responses routes are refused as not carriable. The documented DSH plugin path is an explicit opt-in: `install-bundle` materializes a Codewhale bundle package (`codewhale-dsh-bundle`, MIT notice retained) and installs it with `dsh plugin --profile codewhale add ` into a dedicated `codewhale` profile (pnpm required, reported truthfully when missing; `web`/`headless` untouched), so `dsh --profile codewhale` alone carries the identity; `update` regenerates the bundle patch and `remove-bundle` reverses it, leaving the DSH-owned profile directory in place. `/setup tools` and `codewhale doctor` show the read-only detection state; `doctor` also lists the DSH read-only credential consent alongside Codex and Grok. The optional `--skin` export writes a Codewhale token stylesheet generated from the TUI palette (Blue Stage dark/light, ombre water column, mode/permission/state colors, reduced-motion fallbacks); DSH exposes no custom-theme API, so the sheet is labeled an unsupported overlay and is never injected. See `docs/INTEGRATIONS_DSH.md`. ### Fixed - Selecting the `google` provider kind resolved to the `antigravity` TUI identity (and vice versa): the agy provider entry was inserted at different positions in the config-level enum and the TUI's discriminant-indexed lookup table. The table now matches the enum, so provider pickers, sorted display, and kind round-trips are correct. - The provider picker's key-entry stage accepted typed input and pastes for OAuth-only providers after `antigravity` declared OAuth acquisition; those gates now key off the OAuth acquisition class instead of a hard-coded provider identity. - The webhook hook sink no longer panics when its HTTP client fails to build; it falls back to a default client (#5381, EvanProgramming). - Session-index JSONL writes are serialized behind a process-wide mutex so concurrent state stores cannot drop an append during compaction (#5382, EvanProgramming; complements the cross-process file lock). - A billed `max_tokens` stop followed by a transport error fails the turn instead of continuing into a second request. A clean output-limit stop still continues. Mid-size context windows keep the ordinary 65K internal reservation so compaction does not collapse to the 1K headroom floor when the catalogue documents a matching output ceiling. - Thinking cycle, `/effort`, and Settings now walk each model's real ladder instead of the DeepSeek off/high/max shortcut. Grok 4.6 is auto/low/medium/high/xhigh (cannot disable); Grok 4.5 is auto/low/medium/high; first-party DeepSeek keeps a documented `low` tier. `/effort` persists and receipts through the same path as Ctrl+T. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) is a separate provider: consent-gated read-only import of the official CLI's login, then a text-only cloud-code stream (`/v1internal:streamGenerateContent`). Tools, images, and unknown SSE shapes fail closed. Gemini 3.7 Flash is not advertised until a live turn succeeds on this wire. The website 44-count still excludes Antigravity. - DeepSeek Flash SSE on macOS no longer turns mid-character HTTP/2 flushes into U+FFFD replacement characters (#5374). Invalid UTF-8 fails the line instead of using lossy decode. - `[workshop] read_result_max_bytes` and `tool_result_max_bytes` raise the model-visible read/tool-result floor; they never lower the compile-time defaults and cap at 2MiB (#5367). - Fireworks and OpenCode Zen DeepSeek V4 Flash/Pro keep a bundled family rate when the live control plane is down, so session cost is not stuck on `unverified_live_pricing` (#5241). `kimi-k3` stays unpriced until a published rate exists. - Provider setup ships a typed beginner template catalog (#5350). OpenCode Zen/Go stay first-class key-only rows with their documented hosts and curated models. SenseNova fills a named OpenAI-compatible table on the published `https://token.sensenova.cn/v1` host (`S` or `/provider setup sensenova`). Agnes is listed as unpublished because this repository has no published URL. `/provider` `P` and Settings → beginner templates open the list; `T` tests `/models` and refreshes status without treating 2xx as model-ready. `/model` names a failed Models.dev refresh as `refresh failed; catalog available` instead of `cache failed`. - Privileged release workflows no longer restore rust-cache, sccache, or npm caches after checking out a caller-supplied SHA (CodeQL cache-poisoning #88–#106). Catalog drift no longer prints raw bundled/upstream blobs (#107). - Cancelling a turn now cancels its foreground child agents with it. - Empty compaction no longer wipes conversation history. - Wide terminals and tmux panes fill the full available width again for the transcript and composer (#5322). The brief v0.9 session-shell side gutter is gone so expanding a pane rematerializes layout the same way shrinking does. - The agent tool schema rejects empty calls. - The local web client keeps recovered stream gaps closed, user questions answerable, manual bootstrap access intact, and streamed prose quiet for assistive tech. - Website zh-Hans copy now says 宪章, matching the TUI pack (#5397, Lstarsky0). - Public website provider facts include Google Gemini and Ollama Cloud (44 runnable routes). Antigravity stays credential-plane-only. Harvested from #5398 (Lstarsky0) with that correction. - The website models page carries a truthful read-only settings preview built from repository facts; it never implies the site can change local configuration (#5370, #5411, mvanhorn). - The canonical `ultra` reasoning effort now maps to each provider's maximum tier alongside the legacy `ultracode` alias, instead of being silently dropped (#5303, #5409, buiducnhat). - Session titles truncate by character count, not byte offset, so multi-byte titles (CJK, emoji) cut at the intended width and word boundary instead of past the limit (#5415). - Wide terminals and tmux panes fill the full available width again for the transcript and composer (#5322). The brief v0.9 session-shell side gutter is gone so expanding a pane rematerializes layout the same way shrinking does. - The background verifier test drives the current libtest executable instead of the rustup `rustc` shim, so the TUI suite no longer depends on `$HOME` or holds the process-wide test environment lock across an async wait (#5056, #5423, Isabel Wu). ### Removed - The source-structure budget ratchet (CI step, checker, baseline JSON). It measured line counts, not quality: every legitimate feature required a hand-edited ceiling and the accompanying "review" was self-review, so it bought ceremony, not protection. Behavior-measuring gates (dead-code, runtime-contract, persistence-backlog) stay enforced. - DeepSeek can reuse a key already stored by official DeepSeek Harness (`dsh`) after `codewhale auth external-consent --provider deepseek --mode read-only`. Codewhale reads only `DEEPSEEK_API_KEY` from the exact granted `$DSH_HOME/.credentials.yaml` and never writes or refreshes that file. - The TUI markdown parser now honors CommonMark fence-length rules: a ```` opener is not closed by a shorter ``` line, so `>` content inside a longer fence stays literal code instead of escaping into a quote. - Sub-agents finalize when the parent session id changes, so a closed session cannot block new children as a live owner (#5372). - Child spawn-route receipts stay live and usage is deduped by response (#5366). - Doctor keeps persisted setup readiness across first-run / update checkpoints (#5340). - Approval default selection is applied and explained; agents are told when approvals are disabled (#5293). - A `/models` 2xx probe is a connection check, not model readiness. - Site layout uses one container, the ticker no longer implies false provider readiness, and install links stay in the active locale. ### Contributors - EvanProgramming (@EvanProgramming) — webhook client panic fallback (#5381); session-index JSONL mutex (#5382). - Lstarsky0 (@Lstarsky0) — session peek hides internal runtime events (#5376); thinking-ladder test re-pin (#5378); provider-count follow-ups (#5383/#5384); macOS agy fixture canonicalization (#5392); zh-Hans 宪章 terminology (#5397); regenerated website facts harvested and corrected from #5398. - Matt Van Horn (@mvanhorn) — read-only models settings preview on the website (#5411, fixes #5370). - Nhat Bui (@buiducnhat) — canonical `ultra` reasoning effort mapped across provider effort tables (#5409); session titles truncated by character count, not byte offset (#5415). - Sh1Zuku (@SparkofSpike) — `/title` and the session name in the terminal tab/window title, plus the mid-turn title deadlock fix (#5419). - Kai Nacke (@redstar) — Eden AI provider registration, aliases, `EDENAI_API_KEY`, and the global/EU endpoints (#5422). - Isabel Wu (@wuisabel-gif) — background verifier test isolated from rustup and `$HOME` (#5423, slice of #5056). ## [0.9.7] - 2026-08-12 Codewhale v0.9.7 keeps the catalog ordinary. Grok 4.6 lands as a normal catalog row instead of a provider-shaped pile of special cases, OrcaRouter joins as a named provider, and a panic-safety advisory in `lru` is cleared by lifting the pin that caused it rather than living around it. ### Added - Grok 4.6 is the direct xAI default, with the `grok` alias moving onto it and `grok-4.5` still explicitly selectable. Its 500K context, text/image input, tool and structured-output support, `low`/`medium`/`high`/`xhigh` reasoning efforts (default `high`), and server-side web search all come from the Models.dev-shaped catalog rather than model-specific code. `reasoning_effort` reaches the wire only on the exact first-party `https://api.x.ai/v1` route, and the usage-aware 200K-token pricing boundary is scoped to direct xAI so aggregator routes reusing the model slug cannot inherit xAI billing. - OrcaRouter is a first-class named provider: `ORCAROUTER_API_KEY`, default base URL `https://api.orcarouter.ai/v1`, `deepseek/deepseek-v4-pro` default, `orcarouter/auto` routing, CLI `--provider` selector, and TUI picker entries (#5321). ### Changed - Reasoning-effort normalization and the model picker read a model's published `reasoning_options` list from the catalog instead of collapsing every route to the historic Low/Medium ladder. Any catalog row that publishes an effort list keeps its own vocabulary. - Docs record DeepSeek's live `DeepSeek-V4-Pro-0813` backend label while the callable API ID stays `deepseek-v4-pro`. No aliases are remapped and no `deepseek-v4-pro[1m]` selector is sent. ### Fixed - Auto-Review once again executes proven read/build/test shell commands and bounded workspace writes without opening an approval modal. Explicit policy blocks, unknown tools, publish operations, secret actions, MCP mutations, and shell commands requiring approval still fail closed (#5323; reported by USTHzhanglu and root-caused by Lstarsky0). - Copying a user or assistant message takes its canonical content instead of reserialized transcript lines, keeping role glyphs, continuation rails, and visual wrapping out of the clipboard while preserving authored Unicode, Markdown, and hard line breaks. Tool and Thinking cells stay on the existing full-transcript path (#5319). - `load_session` no longer runs crash recovery on every read. Snapshot reads go through a side-effect-free `load_session_snapshot` and recovery is explicit via `recover_session_for_resume`, so an embedding host inspecting a durable session while a tool is still running no longer gets a spurious crash repair (#5320). ### Security - `lru` moves to 0.18 to clear RUSTSEC-2026-0253, where `LruCache::pop()` was not panic-safe and could leave dangling list pointers. The `ratatui-core` `=0.1.0` pin that transitively forced `lru` ^0.16 is lifted, so `ColorCompatBackend` now answers `get_cursor_position()` from tracked cursor state — the upstream-recommended workaround for the startup CPR race (ratatui/ratatui#2483, ratatui/ratatui#2640) that the pin originally worked around. `ratatui` itself stays pinned at `=0.30.0`, so the API surface is unchanged. ### Known issues - The integration test `exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero` is a confirmed flake under parallel load ("service pid file never appeared"). It passes in isolation and is unrelated to any v0.9.7 change. ### Contributors - XhesicaFrost (@XhesicaFrost) — canonical message copy (#5319). - h3c-hexin (@h3c-hexin) — session snapshot and crash-recovery split (#5320). - XiaoHuo888-hue (@XiaoHuo888-hue) — OrcaRouter provider registration (#5321). - USTHzhanglu (@USTHzhanglu) — Auto-Review regression report and Windows evidence (#5323). - Lstarsky0 (@Lstarsky0) — Auto-Review regression root-cause analysis (#5323). ## [0.9.6] - 2026-08-11 Codewhale v0.9.6 is a subtractive release: fewer runtime guards, one stable prompt, truthful provider endings, and a smaller compaction path that preserves the provider cache. The changes were grounded by matched Terminal-Bench 2.1 runs against Pi 0.8.41 and by dogfooding repeated manual compaction. ### Added - `web_search` defaults to Firecrawl Cloud without an API key; keyless requests are headerless and quota-bounded, while an optional user key raises limits. - Green web builds on `main` now emit an actionable manual-deploy reminder, so site changes cannot quietly appear shipped while Cloudflare still serves an older revision. - Mistral AI is a first-class provider route, including Codestral models, first-party reasoning support, authentication, picker entries, and aliases. - Headless `Bash` can transfer explicitly requested persistent Unix services out of an exec run, with ownership and cleanup receipts. - `/remote-env` opens hosted Work from the current GitHub or CNB branch tip and states exactly which unpushed, dirty, ignored, secret, and session state stays local. - Linux ARM64 release and nightly assets are static musl builds with native launch checks. - Maintainers can report observed daily active installs from the same anonymous, aggregate telemetry dataset; no additional client data is collected. - Fleet-dispatched members under a read-only evidence (no-network) ceiling now keep the `Web` tool's read-only `search` and `fetch` actions — parity with an ordinary scout — while every reaching surface (`web.run`, `fetch_url`, `github`, MCP) stays denied and the sentinel-backed capability envelope remains the fail-closed backstop. - `/fleet setup` can show an optional, deterministic, unratified role-to-model advisory built only from configured ready routes. Accept, edit, and reject all remain inside the existing human-reviewed profile save boundary; the advisory never launches a Fleet or writes a second configuration. - `/update` checks for a newer Codewhale release and installs it from inside the TUI, while `tui_help` gives agents the same command and key map users see. - Markdown file paths render as OSC 8 links where the terminal supports them, and every agent row can open that agent's transcript directly. - ACP editor sessions can execute multi-round file, search, Git, patch, and explicitly enabled shell tool calls through the shared Runtime registry. Shell access requires both the client's terminal capability and Codewhale's headless shell opt-in, and cancellation stops an in-flight tool before the turn returns (#5225 by @rafaelcavalheri). - Lowercase `read` returns bounded typed PNG, JPEG, GIF, and WebP results to image-capable Chat, Responses, Anthropic, and ACP routes. Text-only routes receive an explicit omission receipt; image bytes never spill into ordinary transcript, export, compaction, or relay text. ### Changed - Anonymous usage counting is on by default for fresh installs and disclosed in a native first-run Codewhale modal with an immediate opt-out. Prior declines remain off. Codewhale does not collect conversations, code, prompts, files, repo or branch names, credentials, model content, or per-turn activity timelines. - Wide terminals use a responsive, full-screen ocean canvas with modest gutters: prose keeps a readable measure while tools, diffs, work surfaces, the composer, and status chrome can use the available width. Turn and major activity seams breathe without padding every call inside a tool group. - Root CLI help describes product actions directly instead of exposing internal TUI/runtime layers. - `Bash action="wait"` now blocks by default when a wait is requested; callers can still ask for a nonblocking snapshot, and persistent service ownership remains explicit. - Compaction is one cache-stable summary request followed by one committed replacement summary and a bounded recent-message tail. Older saved sessions still restore. - Ask, Work, Auto-Review, and Full Access share one stable base prompt. Modes continue to differ through permissions and the live tool catalog; the former Act label is now Work throughout the product and shipped locales. - Full Access now auto-approves non-bypassable tools consistently, and the default choice shown on ordinary approval cards is configurable. - Model, context-window, dispatch-name, and nested-agent spawn receipts report the route and limits actually used rather than silently substituting a guessed identity. - Child-agent launches mint one immutable route receipt before admission and preserve it through status, interruption, completion, resume, Work Graph, and ledger projections, so provider/model attribution cannot drift (#5305). - Goal runs no longer stop because of internal continuation, repeated-gap, or unanswered-question guards. Explicit user limits and terminal goal states remain authoritative. - Account-owned `/rc` remote control now keeps exclusive ownership and a crash-recoverable delivery journal until the server acknowledges terminal, approval, failure, and snapshot state. - `todo_write` is an optional progress surface rather than required model ceremony. - New turns use one small, stable toolbox: `read`, `write`, `edit`, `bash`, `agent`, `todo_write`, and `tool_search`. The optional progress tool stays visible as familiar working memory; specialized native, Web, MCP, plugin, memory, task, and verification tools are policy-filtered and searchable; activated schemas stay in a bounded per-conversation cache. Every sub-agent keeps its own search and cache, including policy-allowed Web research, while forked context and parent activations remain warm starts rather than allowlists. - The direct file and shell schemas follow Pi's deliberately small contract: bounded complete-line reads, hash-free writes, unambiguous multi-edit with BOM/CRLF preservation and conservative fuzzy matching, and one foreground `bash` command with a bounded chronological output tail. Modes change execution authority, not those primitive names. - Codewhale no longer re-states the To-do list to the model. The model learns what is on the list from the tool result its own `todo_write` call returned, which is ordinary conversation history — the same way Pi's To-do works. The transient `` block that used to ride the tail of every parent turn-loop and sub-agent step request is gone, along with the stable system prefix being disturbed by list changes. A snapshot is still shown once, where a person asked for it: the `` block a newly forked sub-agent is handed, `/relay` handoff instructions, and the agent card. The complete To-do stays visible in the UI. A structural test asserts real outbound provider request bodies do not carry the list. - Scout and Reviewer name the read-only investigator roles. Both expose exactly one shell entry point — canonical lowercase `bash`, bounded by the strict read-only classifier — and the legacy `Bash` alias stays denied in the catalog and at dispatch. Previously a case-insensitive name match let a call spelled `Bash` execute through that carve-out, returning raw shell to a read-only role. ### Fixed - Sending more context while a lowercase `bash` command is running now moves the command to `/jobs` and returns a successful running receipt instead of falsely reporting `Command exited with code -1`; the process keeps running and its completion still arrives through the normal runtime event. - First-run usage disclosure now opens as a native Codewhale modal instead of a shell questionnaire before application startup. Telemetry remains unarmed until the native choice is made, and an in-memory Disable choice governs the current session even when its preference cannot be saved. - `/compact` completion, failure, queued, duplicate, and mailbox outcomes are durable transcript receipts instead of short-lived toasts. A stray terminal event can no longer leave every later compaction stuck as already running. - Compaction now follows Codex's simple transcript shape: recent user context followed by one ordinary history checkpoint. It never appends the summary, the To-do list, or volatile shell/worker state to the standing system prompt; reloads migrate the persisted carrier back into exactly one history item. - Automatic compaction uses a percentage of the real context window, clamped to the route's spendable ceiling. Pressure comes from the current parent-route prompt, not cumulative billing or child-model usage. - Compaction, review, verify, routing, setup, Fleet, MCP, RLM, vision, translation, and sub-agent calls inherit the resolved route's normal output, sampling, and reasoning policy. Small internal-task token caps no longer truncate thinking routes or special-case individual providers. - Incomplete provider responses fail truthfully across ordinary turns and every internal model consumer. Partial text stays interrupted, pending tool calls do not execute, and billed usage is retained. - Transport-only `(reasoning omitted)` placeholders no longer enter new transcripts and are filtered from restored sessions. Reasoning expand/collapse actions stay attached to the exact rendered cell, including after replacement, restore, filtering, and resize (#5291). - Step-budget exhaustion is a typed failure and cannot release a pending persistent service. Cancellation after terminal usage still charges the turn. - Deferred tools now preserve a completed result when a provider reuses its tool-call ID on the retry turn, preventing successful plugin calls from entering a repeated execution loop. - Website setup, provider, diagnostics, Fleet, and single-runtime claims now match the source candidate. - Opening the sub-agent register no longer hides the to-do list: the Agents panel shows the full register and the durable checklist together, and the register header is a two-way door that returns to Tasks on a second click. - The ⌥V / Alt+V details chord opens the selected work-surface row's own inspector instead of the transcript's nearest tool cell, so a selected to-do row shows its own content rather than the latest reasoning. - The first-run usage disclosure now asks a clear question — "Help improve Codewhale?" — with unambiguous "Yes, keep anonymous counts" / "No, turn off tracking" choices in every shipped locale, and states the persistent opt-out command. Consent semantics are unchanged: telemetry stays unarmed until a choice is made. - macOS screencapture screenshots referenced in a message are copied to a stable attachments directory the moment the message is received, and the reference is rewritten to the stable path, so the image still exists when the agent reads it. Only files under a screencapture "Temporary Items" directory are touched; copies are idempotent and a failed copy keeps the original reference. - Manual `/compact` during an active turn now queues even when the engine's bounded op mailbox is saturated. The request defers client-side, retries as mailbox slots free, and cannot latch as already running after it settles. - Interactive `/load`, startup `--resume`, and `/resume` picker paths preserve the persisted provider, endpoint, and model identity; picker resume also leaves a durable transcript receipt. - Relative `mcp_config_path` values no longer depend on the launch directory or silently load an empty server pool: Codewhale warns and falls back to the user-global MCP configuration. Explicit absolute paths remain authoritative. - Alibaba Model Studio `qwen3.8-max` and `qwen3.8-max-preview` still stream their current reasoning, but no longer replay historical `reasoning_content` that those routes do not accept. Historical reasoning replay is now gated by the exact provider/API/model contract, so unknown `*-thinking` lookalikes fail closed while documented Qwen, Kimi, DeepSeek, Mistral, Anthropic, and Responses continuity rules remain intact. - Compatibility File/patch calls retain optional content-hash guards when a caller supplies them. The new direct `write` and `edit` schemas do not expose hash or prior-read ceremony. - Shell previews hold back incomplete UTF-8 sequences instead of emitting replacement characters, and compaction receipts report token deltas. - Nested agents may narrow but can never widen their inherited depth budget (#5317 by @ousamabenyounes). - Container publication now assembles AMD64 and ARM64 images in parallel on native runners from the already-verified static release binaries, then publishes and checks one multi-architecture manifest. It no longer rebuilds both targets through the single long-running QEMU job that lost its runner. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - The no-progress guard, repeated-read guard, and injected tool-error strategy coaching. Productive polling, repeated inspection, and model-owned recovery are no longer interrupted by runtime heuristics. - Never-wired decision-card, keybinding, hover, shell-execution, engine-op, and release-script paths were deleted so the supported runtime has one route for each behavior. ### Contributors - Xavier Pestel (@xavierpestel-ai) — Mistral AI provider route (#5295). - Ben Younes (@ousamabenyounes) — inherited nested-agent depth cap (#5317). - Rafael Cavalheri (@rafaelcavalheri) — ACP agentic tool turns (#5225). ## [0.9.5] - 2026-08-08 Codewhale v0.9.5 consolidates the terminal application into one compiled runtime while preserving the familiar `codewhale` and `codew` commands. It also expands the managed Runtime API, makes session and Fleet work easier to inspect and resume, and removes the hidden local continuation backstop that could end productive work without a final assistant response. ### Added - **`model = "auto"` for prompt-based tier selection**: When set, the dispatcher analyses the user's prompt before delegating to the TUI and selects `deepseek-v4-pro` for complex tasks or `deepseek-v4-flash` for simple tasks (PR #5257). - Runtime API controls for persistent goals, bounded memory inspection, MCP server and skill lifecycle management, and durable Fleet receipt evidence. - Append-only session-tree history with `/tree`, `/branch`, `/fork`, and `/resume`, plus `/rc` remote control and managed login. - A unified Fleet roster for built-in dispatch postures and a pinned indicator that keeps active background work visible above the composer. - Incremental MCP registry refreshes that return the local snapshot immediately and update it in the background. - Scout and Reviewer agents can use a bounded direct-command evidence shell for read-only workspace, Git, and GitHub inspection, and can keep private working notes in their own To-do while the durable transcript retains their evidence. ### Changed - `codewhale-cli` now contains the terminal runtime directly. Release installers expose byte-identical `codewhale` and `codew` commands without a separate TUI executable. v0.9.5 introduced deprecated `codewhale-tui-*` release filenames as byte-identical compatibility copies; later releases retain those filenames while installed v0.9.4 clients remain supported upgrade sources. - Startup release checks cache successful lookups for one hour. The updater downloads and verifies the primary runtime once, then refreshes any existing `codew` or legacy `codewhale-tui` command paths from the same bytes. - Headless `codewhale exec` runs and verifier benchmark rollouts no longer impose a 100-step default. `--max-turns` remains available as an explicit opt-in ceiling; Fleet workers retain their separately configured budget. - Goal token and time budgets are telemetry rather than default stop conditions, and automatic goal continuation is unlimited unless the user explicitly configures a continuation ceiling. - Command-palette and slash-completion shadowing now share one alias-aware discovery contract. - The website install guidance, localized product copy, navigation controls, social metadata, and Cloudflare build pipeline now describe and deploy the same one-runtime release contract. ### Fixed - The hidden 20-step no-user-input backstop no longer ends productive turns. Tool results, queued steering, child completions, REPL feedback, and goal continuations can all reach the next provider step and a final assistant response; explicit user-configured limits and genuine stuck-loop guards remain. - Complete error details are directly inspectable after a failure instead of leaving the terminal with a clipped, unrecoverable error fragment. - A newly minted OAuth credential is adopted in the same provider-selection flow instead of requiring a second picker trip. - Fresh session titles can replace a stale cached `New Session` placeholder, unknown model context limits fail loudly, and release/source-install fallbacks no longer request binaries removed by the single-runtime conversion. ### Contributors - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) fixed stale cached session titles that could pin the `New Session` placeholder. - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) built the shared alias-aware command discovery contract and acceptance coverage. - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) contributed the background incremental MCP Registry refresh. - [SKY ZHAO](https://github.com/skyzhao1223) (`@skyzhao1223`) contributed prompt-based `model = "auto"` routing in PR #5257. ## [0.9.4] - 2026-08-07 Codewhale v0.9.4 ships the release-train harness work: the familiar Fleet roster/setup face with a clear operator-leader and user/folder scope, a work strip that keeps actionable agents instead of a permanent archive, waiting policy that forbids polling without freezing independent work, calmer tool output and session recovery, account/Workflow-search/ automation/handoff surfaces, a shorter translation-ready website, and release-blocker fixes across permissions, DeepSeek Responses, SQLite, File edits, terminal width, and Windows installation. ### Added - Memory maintenance: `remember` gains `revise` and `retire` beside the default `append`. Both name the exact note they target and both require the evidence for the change. Append-only memory decays — a correction sits behind the note it contradicts and both keep reaching the model — so the model can now keep its own durable notes true instead of only adding to them. - An audit trail for durable state the model writes about you. Every in-place memory edit is journalled to `memory/JOURNAL.md`, and every continual-harness `refine` / `remove` to a `JOURNAL.md` beside its state, each with before, after, and evidence. Harness removal previously left no record at all even though the entry leaves state entirely, so the journal is now the only place its content survives. - A first-run tip that says so: the first time Codewhale saves something durable it points at `/memory`, translated into all fifteen complete locale packs. This state shaped later sessions and nothing ever mentioned it existed. - Sub-agent checkpoint resume: `agents/followup` resumes an `interrupted_continuable` child from its checkpoint into a fresh agent loop — new agent id, original prompt plus the prior conversation tail — when a runtime is attached, and otherwise keeps queue-only semantics with the `continuation_handle` returned; a second followup on the same interrupted id returns the existing resumed target instead of spawning a duplicate (PR #5242). - MCP Registry discovery with Registry-first tool selection: `registry_sync` surfaces the eligible local stdio catalog as a complete model-side candidate set, connect-failure messages classify early-exit and usage-help output and point recovery at the next Registry candidate, and a bundled `mcp-discovery` skill documents the flow (PR #5238). - Progressive fresh-context disclosure: fresh sessions ship a minimal constitutional kernel — ground truth, user intent and scope, truthful completion, guarantees in mechanism, and precedence — with procedural playbooks disclosed on demand, an opt-in project context pack (`project_context_pack_enabled`) counted in context reports, and `load_skill` catalogue discovery via `name="list"`; the measured fresh-context budget drops by roughly 40% (PR #5077). - Named Fleet store v2: one self-contained TOML Fleet per configuration (`schema = "fleet"`), with scope-explicit selection (user-global default vs folder override), migration receipts from legacy role profiles, and atomic saves that refuse to clobber a different Fleet on the same slug. - Scout replaces the user-facing "faster" control: catalog-verified fast siblings only, never a guessed model name; pinned Scout survives operator changes. - Truthful model-picker rows: vision/tools/limits chips only when the catalog knows, with provider → family → exact model grouping. - **Opt-in product telemetry, off by default.** A first-run notice asks once, on a terminal, with declining pre-selected — Enter declines. Nothing is collected unless both `telemetry = true` and a recorded "Enable" answer are present, so a `telemetry = true` written before this release stays inert: the key has been settable and inert for a long time, and setting it was never consent. An enabled session sends its batches to the first-party ingest endpoint, `https://telemetry.codewhale.net/v1/telemetry`, which is the shipped default for `telemetry_endpoint`. That is a Cloudflare Worker whose complete source is in this repository under `telemetry-ingest/`; it writes to Workers Analytics Engine, whose row is exactly `_sample_interval`, `blob1`–`blob20`, `dataset`, `double1`–`double20`, `index1`, and `timestamp` — **there is no IP, country, or geo column**, so storing one is structurally impossible rather than merely disabled. The handler reads two request headers, never touches the request's geo properties, logs nothing, and validates against a closed field set that rejects an entire batch carrying any unpublished key. Cloudflare's retention for that data is a fixed three months. Setting `telemetry_endpoint = ""` instead writes each batch to `$CODEWHALE_HOME/telemetry/dryrun.jsonl` and constructs no HTTP client at all, so you can read exactly what would have been sent. Turning it off is an answer, not a flag: it deletes the random install id, truncates every buffered event, and leaves a permanent tombstone that a session already running re-checks before it appends and before it sends. A failed wipe fails closed. `CODEWHALE_TELEMETRY=0` is a hard floor that beats `--telemetry true` and the config key, and a value the parser cannot read also resolves to off. Fleet workers are hard-off. A repo-local `.codewhale/config.toml` can set neither key. Never collected: prompts, completions, tool arguments, diffs, file contents, filenames, paths, git remotes, repo or branch names, memory entries, chat history, credentials (not even a boolean asserting one exists), model ids, custom provider table names, MCP server names, error or panic message bodies, per-event timestamps, keystrokes, clipboard, screenshots, or location. The full schema is [`docs/TELEMETRY.md`](docs/TELEMETRY.md), and a test parses the field names out of that file and asserts set equality with the structs the serializer uses. This supersedes the roadmap's previous "no Codewhale product telemetry" entry, which moves from "Ruled out" to an opt-in framing. What stays ruled out: always-on or silent telemetry, per-keystroke or per-tool-call phone-home, and any third-party ad or analytics SDK in the runtime binary. - Registered `GLM-5.3` (direct Z.ai) and `z-ai/glm-5.3` (OpenRouter) as selectable GLM routes, with their aliases (`glm-5.3`, `glm-5-3`, `zai-glm-5.3`, `zai-glm-5-3`). Z.ai had **not released GLM-5.3 as of 2026-08-03** — the ids are registered so they resolve to the Z.ai/OpenRouter routes instead of being rewritten to another vendor's model, and they will fail upstream until Z.ai ships the model. Metadata (context, output, reasoning controls) is inherited wholesale from `GLM-5.2` pending official Z.ai release metadata; pricing is intentionally absent, and `GLM-5.2` remains the default Z.ai model. No third-party gateway roster gained the model: OpenCode Zen, OpenCode Go, Alibaba Model Studio, and TelecomJS publish no glm-5.3 entry, so Codewhale advertises none. - Managed Codewhale account commands (`account login`, `status`, `logout`, and `keys`) with browser device flow, profile- and origin-scoped secure sessions, refresh/revocation, redacted BYOK-vault management, and a token-free Runtime account receipt. Provider authentication remains separate, and `cloud` remains a compatibility alias. - `/automation` operator controls to list, inspect, pause, resume, delete, and run durable automations. Creation remains on the approval-gated model-visible `automation` tool. - A provider-neutral `WorkflowSearchSpec` authoring and freeze boundary, plus structured 2–16-candidate experimental search in the best-of-N Workflow starter. It freezes baseline, route, evidence, evaluator, gate, score, budget, and review policy before admission; it validates gate/scoring commands but does not execute or certify them itself. - The bundled generation-9 `handoff` skill for compact, decision-ready continuation across sessions. - Expanded terminal LaTeX rendering for aligned and matrix environments, cases, arrays, text/font/accent commands, brackets, symbols, and command-aware scripts (PR #4981). - Exact 40-character build provenance and secure account-session capability receipts on `/v1/runtime/info`; unknown source provenance continues to fail closed. - Acceptance-level Gherkin coverage locking the existing user-command precedence, alias shadowing, fallback, and invalid-command error contract (PR #4992). - Agent Plugins v1.0.0: consume, publish, and slugify packaged sub-agent briefs, with an install/update/uninstall on-ramp in the TUI (PR #5182). A plugin bundles a prompt, posture, and routing as one shareable artifact; on-disk migration of the older `plugin.toml` scaffold is deliberately out of scope for this train. - `send_later`: a model-callable one-shot delayed continuation tool, so the model can schedule a single future nudge without an operator-approved durable automation (PR #5138). - `/advisor`: an opt-in background advisor watcher for live turns (PR #5139). - Notification quiet mode with per-category switches and action-first copy (PR #5066). - Automation scheduling forms — one-shot `ONCE`, five-field cron, and honest watcher modes — created through the approval-gated `automation` tool (PR #5183). - Sub-agent `resume_from` continuation chains (PR #5142), child-result diff-tainting when a claimed diff is not visible to git, per-turn usage receipts on the exec stream-json stream, and spawn receipts that report the model each sub-agent actually ran on. - Transport resilience: sub-agent exec transport retries with a 600 s default (PR #5210), SSE header stalls retryable instead of fatal, and headless turn resume after mid-stream network drops with an `EX_TEMPFAIL` exit. - Session durability and control: a deterministic compaction continuation contract (PR #5064), persisting interrupted output (PR #5206), stop-word cancellation (PR #5207), token-counter refresh (PR #5204), deny-by-default approval cards (PR #5090), and the Operate completion gate (PR #5067). - zh-Hant promoted to a full shipped locale with complete `en.json` parity (PR #5143). - A persistent update-available chip in the header, with the startup update check throttled and naming the right command. - RLM static intent extraction for code blocks (`rlm_block_intent.rs`) landed as groundwork for a future code-mode approval flow; it is not yet wired into the turn pipeline and ships dormant by design. ### Changed - `/fleet` is the familiar roster/setup face again. The operator row is the Fleet leader (session model); the header names the selected saved Fleet and whether it is user-global or folder-scoped. Named-Fleet switching lives under `/fleet fleets` (Enter selects in the row's own scope). Session route changes stay temporary until `/fleet save`, `/fleet save-as`, or `/model save-default`. - Waiting-for-subagents directions forbid peek/status polling and sleep-as-wait, but allow independent work that does not depend on a child's result — the parent no longer freezes mid-turn with useful non-conflicting work available. - `workflow run` no longer requires `--fleet`; a saved Fleet is an optional pin layer over roles + the session route. - Homepage and getting-started copy is shorter and scannable across locales, with dictionary key and `{brand}` token parity preserved. - Tool results now render as ordinary bounded previews with real expansion; storage, retention-ledger, and internal evidence language no longer leak into normal transcripts. - Prose wrapping, goal state, modal questions, composer-tail behavior, and ambient motion now follow one deterministic interface contract across narrow terminals and fast streams. - Scout and reviewer Fleet roles gain network access and the bounded verification surface for real reconnaissance while retaining the no-write, no-raw-shell security floor. - Workflow runs may describe up to 1,000 tasks while admitting at most 16 live tasks at once through the host concurrency gate. Tournament ordering now supports explicit score-first selection while retaining its cost-first default. - Runtime permission compatibility inputs resolve to one live `permission_posture`. Auto-Review can proceed without approval or structured question modals, unresolved holds fail closed, and a call planned under stale authority is retried after a posture change (PR #5025). - Duplicate and drifting per-turn metadata has been removed in favor of runtime-owned authority, and large inline account and skill tests now live in owned test seams. - Pinned Ratatui to 0.30.0 and ratatui-core to 0.1.0. ratatui-core 0.1.1+ makes `Terminal::clear()` issue a blocking cursor-position report that raced the TUI input loop and could kill first launch; both pins are load-bearing, because 0.30.0 declares `ratatui-core ^0.1` and would otherwise resolve forward on its own (PR #5192 by @bistack; upstream ratatui/ratatui#2640). - Updated globset to 0.4.19, clap-complete to 4.6.8, futures-util to 0.3.33, libc to 0.2.189, actions/stale to 11.0.0, and docker/login-action to 4.5.2. The locked graph also includes the event-listener 5.4.2 fix for RUSTSEC-2026-0221. - The progress surface now speaks plainly everywhere: the last user-visible "Work update is pending" notices say "To-do list", the tool constructor and the docs name `todo_write` as the single canonical progress tool, and `work_update`, `TodoWrite`, and `todo` stay registered as hidden compatibility aliases so saved transcripts keep replaying. - Sub-agent and `agents/wait` waits stay short by default and by cap: blocking waits default to 30 s and refuse to block past 120 s, because a blocked wait deafens the session to typed input and settled children already report back as `` sentinels. - `Bash` `action=wait` honors `timeout_secs` (seconds) and bare `timeout` (milliseconds) alongside canonical `timeout_ms`, and `block` as an alias for `wait`, so a habit formed on other wait tools gets the duration it asked for instead of silently falling back to the 30 s default; the result metadata reports the real `wait_timeout_ms` applied. ### Fixed - The memory journal is no longer indexed as memory. It is Markdown in the memory tree, so the source walk collected it and every retired note re-entered the searchable set under its `before:` line — putting the exact facts a revision had just removed back into the prompt. - `memory_path` pointed at an already-native store no longer derives a second store nested inside it, which silently wrote somewhere other than the file the user named. - `muse` and `muse-spark` resolved to `muse-spark-1.1` in the agent registry while config had defaulted to `muse-spark-1.2`, so the CLI and app-server routed those aliases somewhere the configured default never pointed. The registry now carries 1.2 and the contributor variant. - An explicit `type=builder` (or its `implementer` alias) plus `write_authority=read_only` now fails closed at spawn instead of launching a labeled write role that silently had only read-only tools and then self-BLOCKED after burning a turn (#5123). The check is deliberately narrow, because two neighbouring combinations are legitimate and stay legal: - `type=worker` + `read_only` — worker is the unnamed default (it renders as `general`) and takes its capability from authority, not from its name, so a read-only worker is an ordinary general-purpose child. Worker, scout, reviewer, and verifier remain the four canonical read-only Fleet roles. - any `role` + `read_only` — `role` is an identity for roster resolution, not a capability claim, so an acceptance Workflow can still resolve `implementer` to its saved profile while scoping that child to verification. Callers that spelled a read-only narrowing as `type: "implementer"` should move it to `role: "implementer"`. - User-global credentials survive an explicit workspace `CODEWHALE_CONFIG_PATH` that selects a route with no local key — readiness probes the user-global provider table before concluding a key is missing. - Sub-agent token figures on the work bar accumulate input+output (the same total the worker budget uses) instead of completion tokens alone; elapsed time still freezes when the child settles. - Live work-bar rows for sub-agents show how many to-dos they still have left (`N left`) when the child's own list has unsettled items — never a fabricated zero when no list exists. - Surfaces no longer claim an OS sandbox on platforms that cannot enforce one. The policy resolver takes no platform input, so on default Linux (bubblewrap is opt-in) and on all Windows the header chip read `files: workspace` and `/status` read `sandbox workspace-write` while nothing was restricted. Both now resolve the real backend and say `(unenforced)`. - `tool_category` hook conditions matched only retired tool names, so a `category = "shell"` **deny** hook — the security control `docs/HOOKS.md` documents — silently never fired. Categories now use the registered names, and multi-action tools classify by action. - A `Retry-After` header of `-5`, `nan`, or `1e300` crashed the request task (`Duration::from_secs_f64` panics on a negative). Parsing is now guarded and bounded to one hour. - Bearer tokens no longer leak into operator-visible receipts. `Authorization: Bearer ` split into two tokens and the JWT matched no redaction rule; prefix matching was also case-sensitive, so `SK-live-…` survived. - `prune_older_than` destroyed the NEWEST rollback snapshots and kept the old ones — on every boot, for any workspace with snapshots spanning the retention window. Both prune paths now share one orphan-chain rebuild and preserve each survivor's real timestamp. - An absolute or relative command path no longer defeats every execpolicy deny rule (`/bin/rm -rf /` did not match a `rm -rf /` rule), and a typed `Allow` rule no longer auto-approves a chained suffix such as `git log ; curl … | sh`. - Wrong types on `File` read range params and `Bash` stdin/cwd/task_id are now errors instead of silent defaults — a `start_line:"1200"` string used to return the head of the file, and a non-string `stdin` ran the command with no stdin and reported success. - Multibyte tool ids no longer panic the context inspector, wide (CJK) text no longer overflows the decision card, and a hostname like `127.evil.example.com` is no longer treated as loopback. - Refusals name calls the model can actually make (`rlm action='open'` rather than a retired `rlm_open`; `Bash` rather than `exec_shell`). - Sub-agent dispatch no longer aborts the process. The Tokio runtime was built by `#[tokio::main]`, leaving every worker thread on the 2 MiB default while only the owner thread received the explicit 16 MiB stack — and the engine runs on a worker. A debug-build `agent` dispatch exceeded that stack and raised SIGABRT, which is not a panic and so could not be caught; the process died mid-spawn with no child request ever issued. Release builds were unaffected. - Fleet profiles that pin a provider no longer leak a bare model id onto the session route. `model_overrides` exported each role's model while dropping its provider, so a scout pinned to another provider's model was dispatched against the active client and denied at the wire — visible as an instant auth failure on the first sub-agent of a fan-out. - The rail's Pinned panel no longer spends four rows saying "No active work". An empty panel now collapses like the Tasks panel always has, and the settings migration no longer folds the default `sidebar_focus = "auto"` into a pinned always-on strip, which had silently handed that panel to every user who had a settings file at all. (An *empty* panel collapses; a panel holding settled to-dos or finished workers is not empty — see the standing-register entry below.) - The work bar keeps settled to-dos and an honest Subagents header, while completed/cancelled workers collapse out of the Top strip so fan-outs do not permanently eat the transcript. Failed or interrupted workers stay visible (they still need attention). Settled agents remain reachable through the Agents panel and catalog. To-do rows say their state in words (pending / in progress / completed / cancelled), and sub-agent rows carry type, objective, elapsed, and input+output tokens. Every work row is a door in every rail panel and placement: click and Enter open the row's world (work inspector / agent details — finished agents included) instead of doing nothing. A click after the detail pager closed itself reopens the detail rather than being swallowed by a stale toggle. - The rail strip yields its rows to the transcript when the terminal cannot seat both, so the idle ocean survives at 24 rows instead of being evicted. - `code_execution` and `js_execution` no longer describe themselves to the model as sandboxed. Both are ordinary local subprocesses with no seccomp, jail, or container (PR #5221 by @h3c-hexin and @asto18089). - Model Studio reasoning controls now fail closed on the host rather than on the provider enum, so a custom `base_url` no longer receives Alibaba-specific `enable_thinking` fields, and `qwen3.8-max` is no longer sent a thinking switch it does not accept (PR #5233 by @Inference1, closing #5203). - `config.example.toml` no longer claims Shift+Tab cycles the reasoning tier. Shift+Tab cycles the permission posture; Ctrl+T cycles reasoning (found by @vFONGv, PR #5229). - Alibaba Model Studio reasoning controls are now route- and model-scoped instead of provider-wide (#5203, harvested from #5233 by [@Inference1](https://github.com/Inference1)). Codewhale sends `enable_thinking` / `preserve_thinking` / `reasoning_effort` only when the configured `base_url` is a verified Alibaba Chat Completions host, so pointing a `modelstudio-*` provider ID at a custom gateway no longer injects DashScope's dialect into it. `qwen3.8-max` and `qwen3.8-max-preview` are thinking-only and no longer receive an `enable_thinking: false` they cannot honor; `preserve_thinking` is sent for the models documented to accept it, so their reasoning trace survives into the next turn; and `deepseek-v4*` / `glm-5.x` map the reasoning tier onto the documented `high` / `max` ladder. - xAI device login now recovers from a config that points at a missing Codewhale-owned credential generation instead of failing every attempt with a generic activation error, and finalize failures report the full error chain (#5032). - API keys saved to the secret store no longer read as unconfigured for providers that are not currently active; a configured Kimi/Moonshot key survives provider switches and restarts without re-entry (#5033). - Switching to the Codex provider with no saved model now lands on the live roster's flagship model instead of a stale static default (#5034). - Worktree-isolated Fleet builders no longer contend on the per-workspace delegated-coordination lock, and a failed lock acquisition is retried on use instead of being memoized for the life of the process (#5036). - Fleet dispatch now rebinds the child client when the resolved profile model requires a different wire protocol (DeepSeek flash on Responses), instead of failing deterministically on the worker's first request (#5042). - DeepSeek Responses now sends `reasoning.effort: "none"` for the Off tier, shows a truthful notice instead of silently discarding server-side `web_search_call` items, and parses cache-hit, cache-miss, cache-write, and pricing telemetry while retaining the OpenAI-style nested fallback. - File edits now explain no-op and missing-search failures, reject newly unbalanced C/C++ preprocessor replacements, handle the reported CRLF/non-ASCII cases, and safely relocate stale unified-diff hunks only when whole-file context is unique (PRs #5008 and #5030). - Circled digits, enclosed alphanumerics, and keycap graphemes use consistent two-column measurement in Codewhale, Ratatui, and CJK terminals, preventing missing-character and phantom-space corruption (PR #5001). - SQLite connections install their busy timeout before locking setup and avoid rewriting persistent WAL mode on every open, removing the concurrent-open release-gate failure. - The Windows installer preserves long current-user `PATH` values, their registry type, and unrelated entries across install and uninstall (PR #5006). - Provider configuration no longer contains user-reachable panic paths when metadata or prior credential state is missing. - Resuming a session restores composer text only from a same-session persisted draft; submitted prompts and internal background-runtime envelopes remain in history instead of appearing in the composer (PR #5029). - Shared CI now handles bot-authored issue-link checks, provisions cargo-deny's toolchain, and fetches the locked test graph before offline runtime-budget validation. - Re-quote each linker argument in the Windows OpenHarmony clang launcher so a spaced SDK path (e.g. the default `D:\DevEco Studio\...` install) keeps its `--sysroot` intact through the final Rust link, and extend the no-SDK release guard to keep the re-quoting contract (PR #5095). - The shell tool reports the real elapsed wait time in its result content instead of echoing the requested timeout (PR #5240). - Transcript wheel scrolling under iTerm2: xterm alternate-scroll (DECSET 1007) now stays off while mouse capture is active, so wheel events arrive as mouse events instead of being converted into arrow keys (#5223, PR #5234). - A stalled model stream no longer ends the turn as `Completed` over a frozen reasoning block: a mid-stream chunk-timeout now counts toward the stream-error budget, so a stall with nothing streamed retries the request transparently, and a stall that exhausts the retry budget fails the turn with the real reason instead of reporting success. - A finished background shell task now wakes the engine even when no goal is active: the idle loop starts an ordinary runtime turn so the completion reaches the model immediately instead of sitting unclaimed until the user types (a dead provider route claims the completion once and reports where the output lives instead of re-arming the same error every tick). - Sub-agent final reports that exceed the summary budget are now spilled to a session artifact, and the truncation footer names the `retrieve_tool_result` ref for the elided middle instead of telling the model the bytes are unrecoverable; write failures degrade to the honest no-ref footer. - An interactive mid-stream network drop after partial output no longer fails the turn: the partial reply is preserved as a committed assistant message, a runtime continuation message is appended, and the request is re-issued bounded by the stream-retry budget. - Large pasted input is no longer sent to the model twice as inline text and as a backup `.md` paste file; the submitted message now carries only the `@`-mention so the model reads the file once. - A builder sub-agent can run ordinary shell writes again. Write claims outlive the agents that register them, so a workspace accumulated one per builder that ever ran — six completed agents left four standing claims in testing — and the shared-checkout gate counted those long-finished children as live contenders. Every later builder was refused `Bash` writes with "cannot prove a bounded file target" and pushed toward worktree isolation, which puts the work in a checkout the operator never looks at. The gate now asks the question it meant to ask: is another *running* child writing in this shared checkout. Concurrent writers are still gated; a lone builder writes in the workspace you are actually watching. - Ctrl-C during the first moments of startup no longer kills Codewhale outright. The terminating-signal handlers were registered inside the task that waits on them, and a spawned task does not run until the scheduler first polls it, so a SIGINT arriving in that window hit the default disposition — the process died with no exit code, no terminal restore, and no session record. The handlers are now installed synchronously, before the telemetry notice and before arming, so the window is closed. - The documented tool list on the docs site named `update_plan` and `work_update` as coordination tools. Neither is callable by the model — `update_plan` replays older Plan artifacts and `work_update` is a hidden compatibility alias — so the page listed two tools a reader cannot use and omitted `todo_write`, the one they can. ### Security - Bumped `nanoid` past GHSA-2v37-7h3g-55p8 (a custom generator given size zero could loop indefinitely), restoring a zero-advisory `npm audit` for the website. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - The default model-facing SlopLedger implementation, its storage-oriented transcript language, and the `/debt`, `/cleanup`, `/slop`, and `/canzha` command surface. ### Contributors - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) contributed LaTeX rendering in PR #4981, completed circled-digit/keycap width handling in PR #5001, and delivered actionable File-edit recovery in PR #5008; for this train he resumed interrupted sub-agents from checkpoints in PR #5242, surfaced real shell wait elapsed time in PR #5240, and kept alternate-scroll off while mouse capture is active in PR #5234. - [XhesicaFrost](https://github.com/XhesicaFrost) (`@XhesicaFrost`) fixed long Windows user-PATH preservation in PR #5006. - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) added the user-command dispatch acceptance contract in PR #4992. - [DracheTek](https://github.com/DracheTek) (`@DracheTek`) provided the multilingual, CRLF-heavy File-edit failure report in issue #5003. - [An Ziwu](https://github.com/MuRongMoQing) (`@MuRongMoQing`) reported the Windows PATH-overwrite defect in issue #4685. - [shenjackyuanjie](https://github.com/shenjackyuanjie) (`@shenjackyuanjie`) fixed the Windows OpenHarmony linker re-quoting for spaced SDK paths in PR #5095. - [bistack](https://github.com/bistack) (`@bistack`) contributed MCP Registry discovery with Registry-first tool selection in PR #5238. - [vFONGv](https://github.com/vFONGv) (`@vFONGv`) wrote the zh-CN Windows beginner guide with screenshots in PR #5229, harvested after its base branch was accidentally deleted during maintainer cleanup. - [mky](https://github.com/mky) (`@mky`) fixed the FreeBSD build (PR #5254, `rquickjs` `bindgen` on FreeBSD). - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) contributed embedder-owned sub-agent state roots (PR #5252). ## [0.9.3] - 2026-07-31 This is the Codewhale v0.9.3 source candidate. It is not a published release until the matching tag, packages, checksums, and release assets exist. DeepSeek V4 Flash is now a first-class Codewhale route, and the agent-facing tool surface has been reduced to the canonical action tools that current models actually need. This release also hardens credential, authorization, durability, compaction, and macOS File Provider boundaries while deleting stale runtime and dependency surface. ### Added - Native `deepseek-v4-flash` support over DeepSeek's Responses API, including stateless reasoning-item replay, semantic SSE terminal events, structured function calls and outputs, `apply_patch`, and model-aware wire-format selection. Exact current Flash IDs use Responses; future direct `deepseek-vN-*` model IDs inherit that route conservatively, while custom DeepSeek-compatible endpoints retain Chat Completions unless configured otherwise. - A pipe-only `codewhale auth print-api-key` handoff for explicitly selected providers. It shares Codewhale's home-scoped credential authority, refuses terminal output, and prevents sentinel placeholders from becoming live credentials. - Per-turn `max_tool_calls` enforcement at the engine admission gate, plus a named-file write scope with a separate read seam. The runtime now rejects over-budget calls before execution and keeps the operator's write boundary explicit (#4415). - Runtime-contract, source-structure, and persistence-backlog ratchets that name drift instead of allowing large ownership surfaces to grow silently (#3921, #4785). ### Changed - Model-visible built-ins now use the canonical `Bash`, `File`, and `Run` action schemas. `apply_patch` remains available as the one direct custom edit tool supported by DeepSeek Responses. The bundled stop-ship workflow, Fleet fixtures, shell shortcut, and engine tests use the same canonical vocabulary. - Canonical `File { action: "write" }` requests now pass through the same semantic repo-law checks as the former write path. Approval, Full Access, and workflow execution cannot bypass the repository safety floor by choosing the canonical schema. - Codewhale home resolution is shared across the CLI, TUI, state, and secret stores. `doctor` is offline by default, distinguishes credential source from availability, and reports one consistent path snapshot. - Durable runtime event writes are serialized across simultaneous processes, blocking history waits move off async workers, and provider quota exhaustion remains typed and retryable through compaction (#4522). - Skill discovery caches the merged catalog behind watched-mtime validation; large skill, engine, subagent, UI, and ambient-ocean test blocks now live in owned test seams. - Reasoning summaries stay in the user's language, complete jellyfish silhouettes relocate around transcript text, and cached ocean frames include their palette identity (#4807). - The authorization-order contract now documents and tests how modes, hooks, permission rules, safety floors, repo law, approvals, and sandboxing compose (PR #4980). ### Fixed - macOS sandbox extensions cover CloudStorage/File Provider workspaces without broadening unrelated paths; thanks @Watcher24 for the #4085 report and reproduction. - Foreground shell state detaches before steering, so an interrupted command cannot keep owning the composer (PR #4979). - MCP application-level failures and malformed error envelopes fail closed instead of looking like successful tool output. - Optional PDF failures are truthful and PDF classification no longer misses supported inputs. - Bracketed-paste contents are redacted from traces, and credential diagnostics never treat placeholder sentinels as usable keys. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - The legacy callable aliases `exec_shell`, `run_shell_command`, `read_file`, `write_file`, `list_dir`, `grep_files`, `file_search`, and the duplicate Work/RLM registrations. Historical transcript and policy semantics remain readable, but new model turns receive only the canonical action surface. - The bundled PDF parser dependency chain, replacing it with the smaller optional extraction boundary tracked by #4382. ### Contributors - [Turisla](https://github.com/greyfreedom) (`@greyfreedom`) documented and locked the authorization-order contract in PR #4980. - [Nightt](https://github.com/nightt5879) (`@nightt5879`) fixed foreground shell detachment before steering in PR #4979. - [Watcher24](https://github.com/Watcher24) (`@Watcher24`) provided the macOS File Provider report and reproduction for #4085. - [Fred Leitz](https://github.com/fleitz) (`@fleitz`) retains required source-candidate credit for the canonical `Bash` workspace fix from PR #4673 and issue #4674. ## [0.9.2] - 2026-07-29 This is the Codewhale v0.9.2 source candidate. It is not a published release until the matching tag, packages, checksums, and release assets exist. ### Changed — behavior - **Legacy `model = auto` no longer elects a network classifier on its own.** Holding a DeepSeek API key used to silently select `deepseek-v4-flash` as the classifier for every Auto turn — a per-turn cost on a route nobody asked for, and one provider privileged over the rest. Auto now stays local and free unless an explicit `[auto.router]` block names a provider and model. **If you relied on the implicit default**, restore it explicitly: ```toml [auto.router] provider = "deepseek" model = "deepseek-v4-flash" ``` `[auto.router]` remains legacy `model = auto` configuration. It is unrelated to a Fleet's Adaptive Reasoning Router, which is a saved service referenced by name from a Fleet file and decides only how hard an already-frozen route thinks. Landed since v0.9.1, not yet released. A cluster of defects found by a read-through audit of the policy engine, the MCP proxy, the session index, and the app-server bridge — several of them cases where the wrong outcome was reached silently, behind a response or a log line that looked fine. The release also adds opt-in session, reasoning, localization, and inspectability surfaces; existing defaults remain stable unless an entry below explicitly says otherwise. ### Added - `/permissions` now lists the active user permission-rule source, each rule's effective matcher and global/repository scope, and whether that scope applies in the current workspace. `/permissions remove ` previews deletion and requires a snapshot-bound confirmation token, so a concurrent edit cannot move a different rule under the confirmed index. Appends and removals share one adjacent lock, preserve unrelated TOML formatting and comments, atomically replace `permissions.toml`, and reload the live user ruleset without clearing session-only approvals. `/config ask-rules` remains a compatibility entry; rule creation, glob/directory rules, and deny persistence remain out of scope (#1186, PR #4960 by @greyfreedom). - `/preview-request` (aliases `/dryrun` and `/preview_request`) is a human-only, provider-free inspection of the next primary turn. Production dispatch and preview share one prepared-request seam across Chat Completions, Anthropic Messages, and OpenAI Responses, so the manifest reads the final wire model, reasoning controls, tool choice, tool schemas, and body hash from the same value production sends. Route, tool, or body facts that require Auto's provider classifier, an MCP connection, mutable hooks, compaction, or queued runtime injections remain typed unavailable. The manifest reports exact primary role/lane identity, upstream route-source provenance, requested and effective reasoning, canonical JSON sizes, conservative offline estimates, and provider-reported usage as unavailable because no request ran. It never adds a model-visible tool, sends a provider call, or prints prompt, message, credential, endpoint-path, or workspace-path content. The explicit `/preview-request base-prompt` mode prints only the exact effective base prompt; effective system text remains protected behind its final hash. The exact body includes the same authoritative transient Work/To-do tail used by production, including graph-backed state newer than the legacy projection. Preflight preserves production's separately framed base-plus-Work estimate, and fails closed when the authoritative projection is unavailable. An exhausted active goal token budget also produces a typed unavailable result before any outbound request is built. (#1004, #3928; dry-run concept harvested from PR #1099 by @GTC2080 / TaoMu.) - Slash commands, hotbar actions, and CLI entrypoints for the same Lane/Fleet lifecycle operation now share one typed control-plane contract (`codewhale-lane::control`): a stable `.` id, read-vs-write authority, persistence scope, exact-identity target selection, retryability, lifecycle outcome, and one bounded, sanitized receipt. `docs/COMMAND_CONTROL_PLANE.md` documents it (#1888). - `/lane [list|status|interrupt|restart|resume]` — durable Lane control from the composer, backed by the same executor `codewhale lane …` calls. `codewhale lane interrupt|restart|resume` are the matching CLI verbs; `lane stop` stays as a compatibility spelling of `lane interrupt`. Appending `@` to a lane id fences a write to the exact durable generation you observed, so a concurrent transition is rejected as a conflict rather than acted on (#1888). - `codewhale fleet list` and `/fleet [list|status|interrupt|resume]` — durable Fleet run inspection and control from either surface, through shared DTOs that carry the exact provider, provider-table id, model, effective reasoning tier, and route source when the ledger records them, and a typed `not_recorded` / `not_applicable` / `redacted` reason when it does not. Requested-vs-effective reasoning is never back-filled: the ledger persists the effective tier only, so the requested tier reports `not_recorded` (#4022). - The bundled skill pack now ships a `help` skill (catalog generation 7). It is `invocation: explicit-only`, so it never enters the model's ambient catalogue and costs no prompt budget. Its body is a routing card that points at the surfaces this build actually exposes — `/help` and `/help `, `/skills` and `/skills inspect`, `/config`, `doctor`, and the `docs/` tree when the workspace is a Codewhale checkout — and explicitly forbids pasting a command list or settings table into context (#4698). - `crates/tui/assets/skills-catalog-matrix.json`: an authored, provider-free expectation matrix covering every bundled skill (tier, invocation, aliases, ambient-catalogue eligibility, shadowed aliases). Contract tests in `crates/tui/src/skills/catalog_matrix.rs` assert a bijection between the fixture and the shipped bundle, so the starter pack cannot change without an explicit fixture update. The matrix covers positive eligibility and explicit load, non-activation negatives, alias resolution, explicit-only exclusion, alias-vs-canonical collision precedence, and prompt-budget invariants (no duplicate catalogue entries, no aliases as extra entries, and the shipped pack fitting inside the 12 000-char budget with no omitted-skills line). These are deterministic registry/catalog/resolver assertions and make no claim about semantic model routing (#4698). - Locale-routing coverage for the complete bundled catalog across every shipped locale (`en`, `ja`, `zh-Hans`, `zh-Hant`, `pt-BR`, `es-419`, `vi`, `ko`). No bundled skill ships a localized routing description and none was invented; the tested contract is deterministic fallback to the canonical English description, with the rendered catalogue byte-identical across locales. Exact-tag match, primary-subtag fallback, and English fallback are covered against a synthetic authored fixture, and the parity test fails if a bundled skill ever gains localized metadata without source-backed coverage (#4698). - `docs/LIVE_SMOKE.md`: copy-pasteable, opt-in live-smoke instructions for Kimi K3 and a second provider/model (DeepSeek). The runs are manual only — nothing in CI, tests, or skills invokes them. They use `env -i` plus a throwaway `CODEWHALE_HOME`; `HOME` is left unset rather than repurposed, and ambient provider variables are not forwarded. The operator names the credential variable explicitly, and the isolated child reads its value with echo off, restores the prior terminal state on exit or interruption, and never persists the value or puts it in a command argument. The page states the expected route/model/reasoning/tool receipt fields while treating provider errors as unclassified until provider configuration, authentication/entitlement, and harness behavior have been corroborated independently (#4698). - Approval cards can now remember eligible safe shell and file-write approvals as exact `allow` rules scoped to the current repository. Remembered shell commands use complete-command matching, validated file and patch paths remain workspace-relative, and dangerous, critical, or repo-law-held requests stay ineligible and continue to require review. - `tui.header_items` (array of strings, optional, default `[]`): an opt-in header chip showing cumulative session token usage as input / cache-hit / output. Set `header_items = ["tokens"]` under `[tui]` to enable it. The chip is the only elidable element of the header — the git label, context meter, and version stamp keep their space, and narrow terminals drop the chip rather than the baseline chrome. Unknown entries are warned about and skipped so configs written by newer builds stay loadable by older ones (#4520 requested by @eugenicum; PR #4610 by @XhesicaFrost, harvested with co-authorship). - `thinking_default_expanded` lets reasoning blocks start open while keeping Space as the per-block toggle. The setting is persisted, available through native and runtime configuration, and documented for SSH/tmux accessibility (issue #4925 and PR #4928 by @M-Maciej). - The transcript renders a conservative subset of LaTeX math as readable Unicode without rewriting fenced/inline code, ordinary currency, escaped dollars, or unknown commands. The contribution from PR #4973 by @SparkofSpike was hardened and landed through PR #4974; reported by @antarikshraya in #4957. - Session control now includes a sessions rail, shared archive projection, picker archive controls, and opt-in interactive auto-resume with explicit handoff behavior. The work closes the remaining session-browsing direction from #2934; thanks @cy2311 for the original report. - The bundled contributor-onboarding skill can sync contribution context, select the appropriate gate, and prepare a digest without inflating the ambient skill catalog. It follows the contributor-navigation request in #4227 by @JayBeest. - Bahasa Indonesia now has a complete repository documentation suite and a registered website dictionary alongside the shipped TUI locale (PRs #4962 and #4972 by @atmosuwiryo, closing #4789). - Reasoning content can keep its rail, italics, cursor, and expansion controls while disabling only the warm background highlight. The independent setting is persisted and localized (#4089; reported by @elijahchan2019). - StepFun setup now asks whether a key belongs to PAYG or Step Plan, keeps the two endpoint/billing routes distinct, and localizes the choice across the complete packs (#4526; reported by @whp233). - OpenCode Zen is a separate model-aware API-key provider. Its curated catalog selects Responses, Anthropic Messages, or Chat Completions per model; unsupported Gemini and unknown models fail closed, and missing Zen credentials never fall through to ChatGPT/Codex OAuth guidance. The implementation from closed PR #4467 by @snail-vs (snailoniu) is preserved in the candidate. - Markdown exports correlate prompts with stable workspace restore-point ids and say when correlation is unavailable or ambiguous, completing the remaining restoration/export direction from #2494 by @wywsoor. ### Fixed - Permission setup now consistently presents the product postures Ask, Auto-Review, and Full Access instead of leaking the internal `never` token. The same resolved sandbox policy now drives execution and UI receipts: Plan stays read-only, Ask and Auto-Review stay workspace-scoped, and Full Access is actually unsandboxed unless a stricter effective configuration wins. - Fleet setup no longer stalls when a user explicitly selects a configured Codex or Grok external-consent route. The selected route is activated and validated before saving, roster roles open directly on their Model step, Review saves on the first Enter, and new profiles default to the personal profile directory that the roster loads on the next session. - Provider credential dialogs now share one wrapping, secret-safe API-key surface across every non-OAuth provider. A key already present in durable storage is reported as configured without rendering it, typing or pasting is clearly framed as replacement, narrow help text remains visible, and Codex and Grok OAuth flows remain token-free in this modal. - Ctrl+O again opens the complete recorded reasoning detail for the selected, active, or latest reasoning block. The whole-turn Turn Inspector moved to Ctrl+Alt+O and `/turn inspect`, removing the shortcut collision while keeping raw leaf detail and post-flush reasoning discoverable. - Failed child agents now deliver a distinct high-priority failure receipt to their owning parent with a sanitized failure class, elapsed work, and a full transcript handle. Parent-to-child message, follow-up, and interrupt tools now use one hierarchy-checked mailbox path, and persisted nested completion envelopes remain safely restorable across instruction-text revisions. - Background-shell completion events now carry only bounded tails plus a retrievable exact-evidence handle. Terminal foreground Bash results are acknowledged at the direct tool-result boundary and are no longer emitted a second time as background completion artifacts. - Providerless Fleet and child-agent fixed-model routes now reject only high-confidence foreign-provider model ids before creating a worktree, while explicit provider/model pairs, custom and local endpoints, unknown ids, and aggregator wire-id resolution retain their intended behavior. - Manual compaction now preserves and reports the supplied provider failure class instead of replacing it with an opaque generic error. This does not infer quota exhaustion when the recorded failure does not prove it. - The ambient jellyfish keep complete, readable silhouettes while animating, and the website favicon now uses the Signal Current desktop tile instead of the legacy whale mark. - ACP JSON-RPC responses preserve numeric request ids for avante.nvim while retaining the negotiated string-id exception for Zed (PR #4929 by @atmosuwiryo). - Restored shell cells whose job no longer exists stop displaying live spinners and settle into a truthful stale/no-output state across transcript, phase strip, and sidebar (PR #4937 by @LI-Jialu, closing #4547). - Interrupted checkpoints and timed recovery snapshots remain checkpoints instead of being promoted into orphan session files, preventing duplicate `/resume` entries (PR #4963 by @SparkofSpike). - Every shipped locale is admitted by the typed settings schema and native chooser, with complete/partial status kept independent and tested (PR #4856 by @nightt5879, closing #4786). Context-menu hover hit-testing also accounts for its title row (PR #4897 by @XhesicaFrost; reported by @SparkofSpike in #4803). - OSC 52 and SSH/tmux clipboard transport run on one bounded background worker rather than blocking input and rendering on the TUI loop; late transport failures still surface through the status path (PR #4896 by @nightt5879, closing #4159). - Non-streaming model calls receive a generation-length response budget rather than the SSE header-open timeout, while actual SSE opens share the bounded cross-provider transport seam. The equivalent fix direction came from closed PR #4743 by @vibecoding-skills. - Resumed sessions diagnose a deleted inherited workspace before shell launch instead of failing as an opaque Windows process error (report #4100 by @redjade75723). DeepSeek native tool-call wrapper tokens are also scrubbed from visible streaming and completed output as a grounded fail-soft follow-up to report #3880 by @hardy922; that report's exact emitted marker remained unconfirmed. - Auto model routing now preserves the user's requested reasoning effort through startup, provider/model changes, session restore, the picker, Ctrl+T, and Hotbar actions. The tier is normalized only after the concrete provider route is known instead of being silently replaced by Auto (#4941, PR #4961 by @nightt5879). - Auto-compaction now defaults on for every known model context window, including Kimi K3's 1,048,576-token routes. Persisting only an `auto_compact_threshold` or `auto_compact_threshold_percent` now counts as opt-in intent, while an explicit `auto_compact = false` remains authoritative. `/config` reports the effective state, percentage, and computed token trigger. - Per-provider `context_window` overrides are now documented and visible in `/config`, provider setup help, diagnostics, and the example configuration. The effective override consistently drives preflight budgeting, the context meter, and compaction; this lets a user cap a 1M Kimi route to 256K when their Coding Plan tier has the smaller window. - Agent Details now projects status, model, elapsed time, and step counts from the same row snapshot as the primary agents list, eliminating contradictory worker state between the two surfaces. - Composer submission and its hints now share one state machine. Portable terminals use Enter to queue during a running turn and Enter again to steer; Ctrl/Cmd+Enter is accepted only when an enhanced terminal reports it and is no longer advertised as universally available. - `edit_file` now matches LF-only model search text against CRLF files, preserves the file's line-ending style for replacement text, and still rejects newline-normalized duplicate matches as non-unique (#4764). Implemented in PR #4942 by @nightt5879; reported and root-caused by @LmeSzinc. - `/fleet status` read the current TUI session's sub-agents while `codewhale fleet status` read the durable `.codewhale/fleet.jsonl` ledger — two different things wearing one name, so a run started by `codewhale fleet run` never appeared in the TUI. `/fleet status` now reads the durable ledger through the same code path as the CLI; the session view keeps its own name as `/fleet workers` (`/subagents` and `n` still work). When a workspace has no ledger, both surfaces report a typed `no_fleet_ledger` reason instead of an empty-looking "all clear", and neither creates the ledger as a side effect of reading it (#4022). - `codewhale fleet status` (and `list`/`interrupt`/`resume`) created `.codewhale/fleet.jsonl` as a side effect of opening the manager, then reported `no_fleet_ledger` for the file it had just made — so the second invocation showed an empty Fleet where none existed. The CLI now refuses those verbs before the manager is constructed, matching `/fleet` (#4022). - `fleet resume ` accepted any string. An id absent from the ledger reconciled nothing but still wrote a run-status record keyed by whatever was typed, and reported `no_change`. Unknown ids are now refused as `not_found` before any durable write (#4022). - `lane interrupt` reported `transitioned` even when it changed nothing — another process's stop looked like our own. The Runtime backend now reports whether *this* call performed the transition, and a no-op is `no_change`. The `@` fence is also evaluated inside the registry's per-Lane lock rather than before it, so a stale fence refuses without running Runtime teardown instead of racing between the check and the stop (#1888). - `/lane` no longer runs Runtime teardown on the TUI composer thread. Reads on the slash surface skip reconciliation (which probes tmux and takes a lock) and say so on the receipt instead of implying freshness; `lane interrupt` is CLI-only until that work runs off-thread, and reports `surface_not_supported` naming `codewhale lane interrupt` (#4022). - The hotbar is no longer modelled as a third control surface. A slot binds a slash command and fires it with no argument, so it runs *as* the slash surface; the contract now declares which verb a bare press actually reaches (`hotbar_bare_dispatch`, true only for `lane.list`) instead of advertising target-taking verbs as hotbar-reachable (#1888). - `codewhale lane list --json` and `lane status --json` keep emitting the `LaneRecord` shape they always have — the receipt did not replace it. The human `lane status` output also regained `branch`, `session`, `socket`, `attach`, and `log`, which the first cut of the shared DTO had dropped (#1888). - No surface advertises a backend it does not have. `lane restart` and `lane resume` have no implementation — a Lane is re-created by `codewhale lane start`, and a stopped Lane's Runtime session is gone — so all three surfaces refuse them with `backend_not_implemented` and say why. `fleet restart` drives the manager loop to completion, which only the CLI runs, so `/fleet restart` reports `surface_not_supported` and names the CLI command rather than quietly doing a smaller thing (#1888). - Deny rules in `permissions.toml` no longer miss a command because of an intervening flag: deny matching is token-based with flag-skipping and backtracking, so a `git push` rule still catches `git -c foo=bar push`. Path matching folds case only on platforms whose filesystems are case-insensitive, and the default approval branch no longer proposes the working directory as a network host. - MCP tool calls run once. A failed call is no longer retried as if it were a failed lookup, qualified-name resolution collects every match and reports an ambiguity instead of taking whichever the hash map yielded first, and registering a server whose name collides with an existing one after sanitization is now an error rather than a silent overwrite. The equivalent call-once fix direction came from closed PR #4756 by @adity982. - The session index survives a torn line: an unparseable entry is skipped rather than aborting the whole read, appends carry their data through to disk, and appends and compaction share a lock so a compaction can no longer race an append into a lost record. - `Edit` counts as a write tool for workflow elevation, and the TUI's write/shell classification now delegates to one shared allowlist rather than keeping a second copy that could drift. - A rejected `app/config/set` stays a no-op. Previously an invalid value still tore down the cached runtime bridge, killing the child runtime and orphaning every other in-flight stdio thread behind a response that correctly reported failure. - A malformed project `config.toml` is no longer indistinguishable from having no project config. Because a project config may only *tighten* approval and sandbox policy, silently discarding a broken one dropped a repository's restrictions back to the looser user defaults; the setup wizard now says so, naming the file but never quoting its contents. - An expired lane worktree no longer leaves its branch behind, which made reusing the same lane name fail with "branch already exists". A branch still carrying unmerged commits is kept — a TTL lapsing is not consent to delete someone's work. - An in-flight `thread/message` turn can be stopped. The stdio loop keeps reading while a turn streams, so the new `thread/interrupt` request (and `shutdown`) can reach a runaway turn instead of waiting on the very turn they were meant to stop. - Precedence is stated only in the constitution's "Whose word wins" section. Memory hygiene no longer ships an inverted Tier list that put the constitution above the user's current request; approval, compaction, and personality overlays describe behavior without rank vocabulary; and the authority recap points at the single source rather than restating a second ladder. - `` carries facts (mode, posture, model, workspace), not mode doctrine or permission-question essays re-asserted every user message. - The project context pack (pretty-printed workspace tree) is off by default and opt-in via `[context] project_pack = true`. Language law is compressed while keeping the English-constitution / user-language-reply contract. - Modal lists and config pickers wrap selection at both ends (Down past the last row returns to the top). Home-directory resolution prefers `HOME`/`USERPROFILE` via `effective_home_dir` across remaining call sites so Windows tests that fake the home env vars match production paths. The equivalent home-directory sweep came from closed PR #4760 by @EvanProgramming. ### Changed - Prefix-cache tool catalog entries store only the SHA-256 digest, not the joined catalog string. Unused plan-transition validation helpers are removed. - Settings sections now hold only what they claim (#4751). Fleet keeps Fleet/member concerns; `/goal` moved to a **Session** section and Workflow orchestration to its own **Workflow** section. The inert DeepSeek-only `default_model` fallback moved out of Model settings into an explicit **Legacy** section — exact-Fleet users switch Fleets, not fallback models; the config field is retained because the runtime still reads it. This is presentation only: the persisted keys (`goal_command`, `workflow`, `default_model`), their values, scopes, and runtime behavior are unchanged. - Auto model routing is scoped to the active provider. The classifier inventory no longer discloses other providers' runnable routes (or the fact that their credentials exist), a classifier reply naming another provider is refused, the local heuristic no longer falls back to a different provider when the active one is unusable, and the implicit DeepSeek-flash classifier is skipped for non-DeepSeek sessions. Auto receipts and the model picker hint report the active-provider-only scope instead of "runnable providers". Cross-provider Auto is available only through the persisted `[auto] cross_provider = true` opt-in (an explicit `[auto.router]` route remains its own opt-in for the classifier call). Same-provider strong/fast selection and `[auto] cost_saving` are unchanged. - The QA pseudo-terminal acceptance harness now parses frames with `rio-vt` behind its existing neutral frame/color surface, retaining the assertions while removing the `vt100` dependency (PR #4931 by @raphamorim). - Anthropic Messages and OpenAI Responses stream opening now share the `client/stream_entry.rs` seam already used by Chat Completions: one bounded response-header wait, shared dual/HTTP-1.1 policy selection, at most one HTTP/1.1 fallback on a classified HTTP/2 header stall, and common idle-timeout diagnostics. Wire-specific authentication, headers, endpoints, decoding, and rate-limit behavior remain at each adapter edge. The timeout-placement diagnosis and fix direction came from closed PR #4743 by @vibecoding-skills. ### Security - Release containers now publish an SBOM attestation and pin maximum-mode provenance explicitly so supply-chain metadata cannot silently weaken with a builder-default change (PR #4958 by @kobihikri). ### Contributors Thank you to the contributors whose code, reports, and reviews shaped v0.9.2: - [@greyfreedom](https://github.com/greyfreedom) — exact repository-scoped allow grants and cross-platform path semantics (PR #4761), plus safe permission-rule listing and snapshot-bound removal (PR #4960). - [@nightt5879](https://github.com/nightt5879) — off-event-loop clipboard writes (PR #4896), complete locale exposure in settings (PR #4856), CRLF-safe edits (PR #4942), and reasoning-effort preservation across automatic model routing (PR #4961). - [@XhesicaFrost](https://github.com/XhesicaFrost) — the configurable session-token header (PR #4610) and context-menu hover alignment (PR #4897). - [@cyq1017](https://github.com/cyq1017) — the hooks configuration/executor split from PR #4087. - [@snail-vs](https://github.com/snail-vs) (snailoniu) — OpenCode Zen's model-aware routes, authentication, documentation, and test isolation from closed PR #4467, whose contributor commits are preserved in the candidate. - [@SparkofSpike](https://github.com/SparkofSpike) — the zh-Hans translation quality review harvested from PR #4908, duplicate-session fix in PR #4963, LaTeX implementation from PR #4973 landed through #4974, and the context-menu reproduction in #4803. - [@GTC2080](https://github.com/GTC2080) — the request-preview concept from PR #1099. - [@h3c-hexin](https://github.com/h3c-hexin) — non-UTF-8 `fetch_url` decoding direction from PR #4909. - [@fleitz](https://github.com/fleitz) — required source-candidate credit for the canonical `Bash` no-`cwd` workspace fix and regression in PR #4673 (issue #4674). - [@LmeSzinc](https://github.com/LmeSzinc) — the Windows CRLF `edit_file` reproduction, root-cause analysis, and affected-code anchors in issue #4764. - [@atmosuwiryo](https://github.com/atmosuwiryo) — ACP numeric-id compatibility (PR #4929) and the Indonesian documentation and website locale (PRs #4962 and #4972). - [@M-Maciej](https://github.com/M-Maciej) — the expanded-by-default reasoning setting and its original report (PR #4928, issue #4925). - [@raphamorim](https://github.com/raphamorim) — migration of the QA PTY frame parser to `rio-vt` (PR #4931). - [@LI-Jialu](https://github.com/LI-Jialu) — truthful finalization of restored stale shell cells (PR #4937). - [@kobihikri](https://github.com/kobihikri) — release-container SBOM and explicit provenance mode (PR #4958). - [@EvanProgramming](https://github.com/EvanProgramming), [@adity982](https://github.com/adity982), and [@vibecoding-skills](https://github.com/vibecoding-skills) — equivalent fix direction for the effective-home sweep (#4760), MCP call-once behavior (#4756), and streaming/non-streaming timeout split (#4743). - [@antarikshraya](https://github.com/antarikshraya) — the LaTeX transcript rendering report in #4957. - [@eugenicum](https://github.com/eugenicum) — the token-header request and output-presentation measurements in #4520 and #4468. - [@whp233](https://github.com/whp233) — the StepFun/OpenCode subscription-route request in #4526. - [@redjade75723](https://github.com/redjade75723), [@hardy922](https://github.com/hardy922), [@JayBeest](https://github.com/JayBeest), [@elijahchan2019](https://github.com/elijahchan2019), [@cy2311](https://github.com/cy2311), and [@wywsoor](https://github.com/wywsoor) — reports and product direction behind the stale-workspace diagnosis (#4100), native-tool-token filtering (#3880), contributor onboarding (#4227), optional reasoning highlight (#4089), session control (#2934), and export/restore correlation (#2494). ## [0.9.1] - 2026-07-24 ### Dogfood follow-ups (2026-07-24) ### Added - `/compact [focus]`: the manual compaction command now accepts an optional focus argument that is injected into the summary prompt, and the compaction summary itself becomes a structured nine-section successor briefing (primary intent, key concepts, files and code, errors and fixes, problem solving, user messages, pending tasks, current work, next step) that carries earlier compaction summaries forward and explicitly forbids tool use — replacing the free-form "under N words" instruction. Codewhale's pin/working-set and V4 prefix-cache-aligned machinery are unchanged. - Saved workflows become slash commands: `*.workflow.js` files under `/.codewhale/workflows/` and `~/.codewhale/workflows/` are discovered as `/name` commands that accept custom arguments (forwarded to the run's `args`), launch through the `workflow` tool in the background, and report their run id. Hand-written `.md` commands with the same name always win. The workflow tool's `source_path` now also accepts the user-global `~/.codewhale/workflows/` store, and every settled run leaves a durable synthesized report under `.codewhale/reports/.md` (status, goal, gates, progress, result, verification). ### Fixed - Disambiguate the two Kimi K3 model-picker rows, which read as an unexplained duplicate: bare `k3` is now labeled "Kimi Code plan route" with its default 262K window annotated as the plan-tier floor (raisable via the provider `context_window` setting for plans that include 1M), and `kimi-k3` is labeled "Moonshot direct route" with its 1M window. Both remain distinct, valid routes for the same underlying model. - Close the model-facing `agent` tool role schema: the `type` property now publishes the canonical JSON Schema enum `["worker", "scout", "planner", "reviewer", "builder", "verifier", "custom"]` instead of describing the accepted values in prose. Legacy aliases are no longer advertised to models; they remain accepted only at replay/deserialization boundaries. Provider schema sanitizers (Chat Completions, strict mode, Anthropic Messages / OpenAI Responses, Moonshot/Kimi) are pinned by test to preserve the closed enum. ### Changed - Rework the ambient idle ocean: the water now holds exactly one loose wedge school of fish, jellyfish, bubbles, and the rare whale cameo — seaweed and bio-dust are removed. Fish swim on a wrap-around path and always face the way they move (direction can only change while the school is off-screen); the lead fish carries an eye (`>`). Jellyfish become a pulsing bell with a lagging swaying tentacle. All ambient marks now glow via background→ink color lerp: a travelling sin² wave through the school, a floor-bounded pulse for jellyfish, and occasional raised-cosine glints on bubbles, with deliberately non-matching periods so nothing strobes in sync. - Rename the internal delegated-worker role type from `SubAgentType` to `FleetRole` with canonical variants (`Worker`, `Scout`, `Planner`, `Reviewer`, `Builder`, `Verifier`, `Custom`) matching the public Fleet vocabulary one-to-one. Wire behavior is unchanged: serialization emits canonical Fleet values only, and persisted `agent_type` fields plus documented legacy spellings (`general`, `explore`, `plan`, `review`, `implementer`, …) continue to load at deserialization/parse boundaries; unknown role tokens still fail closed with the canonical vocabulary in the error. The Codewhale v0.9.1 source candidate includes a first-class local web client over the Runtime API, first-class OpenCode Go and TelecomJS TokenHub providers and restored xAI device login, calendar-correct hourly automations, a buildable OpenHarmony workflow-js target, and hardening for Auto routing, remote-terminal clipboard transport, restart recovery, and a coherent TUI, Work, evidence, and public release surface. ### Added - Add `codewhale web [--port 7878]`, a first-class loopback-only browser client over the canonical Runtime API. The dependency-free embedded shell supports thread lifecycle, snapshot-then-SSE transcripts, turn start/steer/ interrupt, approvals, and user questions, including pending-request recovery across tab reloads, while leaving unsupported managed, files, PTY, model-selection, and Fleet controls absent. Browser auth uses a short-lived one-time loopback capability exchanged for an opaque, bounded, process-local HttpOnly, SameSite=Strict session cookie with a same-origin mutation guard; Runtime tokens never enter URLs, HTML, browser storage, logs, or browser-launch arguments (#4423). - Add OpenCode Go as a first-class, subscription-backed Chat Completions provider with `[providers.opencode_go]`, `OPENCODE_GO_API_KEY`, and the eight models currently documented on its `/v1/chat/completions` endpoint. Models served only through OpenCode Go's Anthropic `/messages` endpoint remain out of this narrow route until Codewhale supports per-model wire selection (#1481 by @seanthefuturegorilla; implementation harvested from PR #773 by @zhangweiii and PR #1050 by @sternelee). - Add TelecomJS TokenHub as a first-class Chat Completions provider with `[providers.telecomjs]`, `TELECOMJS_API_KEY`, and a key-scoped live `/v1/models` refresh. Models.dev and provider-specific catalogs remain in separate source partitions so either refresh order preserves both; refreshes do not delete the other source's rows, matching model ids from unrelated providers do not fabricate metadata, and chat requests omit unsupported reasoning fields (PR #4370 by @baendlorel; harvested with co-authorship). - Prepare native Windows ARM64 `codewhale`, `codew`, and `codewhale-tui` binaries, npm selection, updater support, and standard/portable release archives. Build and smoke them on GitHub's native Windows 11 ARM runner, and move Linux ARM64 release builds to the native Ubuntu ARM runner to remove the slower multi-arch cross-link setup (#4267 by @w1w218). - `load_skill` tool now supports listing: omit `name` or pass `"list"` to see all available skills without loading one (#4651). - Add a unified `/skills` manager with one precedence-aware root catalog, bounded duplicate/shadow/conflict auditing, package provenance, and validated install, update, remove, and trust mutations (PR #4679 by @SamhandsomeLee). - Add a safe Agent Details view and bounded, structured `current_activity` to the single Work projection, sourced from worker events instead of renderer string inference. Rows stay compact, exact evidence is opt-in, and raw child output never enters the parent transcript (#2889 and #4636; design direction by @aboimpinto, preserved from #2694). - Make exact results and delegated coordination durable: non-inline tool output becomes immutable session-owned evidence behind bounded receipts; File mutations add configurable success-only diffs; and decisions and write contention survive restart with typed neutral-fan-in records (#4619, #4636, #4647). - Runtime API provider registry and atomic provider-switch endpoints (`GET /v1/providers`, `GET /v1/providers/{id}/models`, `POST /v1/providers/{id}/switch`) so the web GUI renders a dynamic provider/model picker without the setConfig+reload clobber (#4658). - Typed filter (`/`) in the Fleet setup wizard's Model step: substring match over provider id, display label, and model id keeps OpenRouter-scale catalogs navigable (#4639). - `[auto.router]` config: explicit provider/model/thinking for the Auto mode classifier route; unset keeps the DeepSeek flash default, and missing credentials fall back to the local heuristic. ### Changed - Keep the top activity bar literal and actionable: active To-dos appear first, followed by Sub-agents, while generic operations and coordination stay in the detail surface. Completed-only bars auto-hide, and top/side layouts can be resized by dragging their divider and retain the chosen size (#4700, #4702). - Use each theme's semantic colors for composer mode and permission rails, and show a larger inline reasoning preview with clearer local/full expansion affordances (#4699, #4701). - Simplify the model-facing runtime around stable action tools (`File`, `Git`, `Run`, deferred `Web`, and durable task and automation families), with legacy spellings hidden for replay. Fresh sessions no longer reserve a Work surface before real work exists (PR #4675). - Give the terminal shell one deliberate visual language: cool Plan → Act → Operate and warm Ask → Auto-Review → Full Access ramps match between header and split composer edges; transcript rhythm groups related activity; a refined whale keeps the empty state calm; and one-cell live motion with truthful labels distinguishes reasoning, reading, tool use, and verification without exposing private reasoning text. Reduced-motion and animation-off settings freeze it, while ASCII-safe terminals retain the signal (#4676, #4677). - Unified shell tool: the model now sees a single `Bash` tool with an `action` parameter (run/wait/interact/cancel). Legacy `exec_shell*` names remain as hidden compat aliases for transcript replay, and the tool-search catalog keeps `Bash` active by default (#4625). - Tool output inline preview increased from 6 to 12 lines (4 head + 4 tail) before the fold indicator; full pager (`v` key) unchanged (#4603). - Mode changes (`/mode agent|plan|operate`) now persist to `settings.toml` and restore across sessions (#4628). - Billing provenance: every outgoing API request carries an `x-codewhale-provenance` header with client version and provider (#4324). - The `/model` picker's typed search now ranks results: provider-name matches first (drill-down), then exact id, then id-prefix, then the active provider's rows (#4639). - System prompt text consolidated into a single `prompts/text.rs` module (byte-exact constants replacing 17 layered files); composition order, constitution-first binding, and locale/personality variants unchanged. - Ask, Auto-Review, Full Access, and Never resolve through one permission contract: `resolve_tool_permission` in the engine and `resolve_approval_request_disposition` in the UI share one truth table for session grants/denials, non-bypassable policy holds, and modal prompts (#4412). - Collapsed multi-struct tool families into single action-dispatched tools (`AutomationTool`, `TasksTool`, `GithubTool`, `RlmTool`) while keeping legacy tool names as hidden compatibility aliases for transcript replay. - Operate-mode children default to leaf depth (`max_depth=0`) unless the caller explicitly grants a deeper budget (#4598). ### Fixed - Restore `uwu` theme config round-tripping and keep header permission colors and authored idle-whale geometry aligned with the selected theme (#4696). - Default canonical `Bash` runs with no explicit `cwd` to the active `ToolContext.workspace`, including an isolated sub-agent worktree, instead of falling through to the shared shell manager's parent workspace. The regression test detects the selected workspace through marker files so it remains meaningful across PowerShell path spellings (#4674, PR #4673 by @fleitz). - Generate QuickJS bindings for `aarch64-unknown-linux-ohos` with the native SDK's libclang and sysroot, carry the OHOS target and sysroot through final linking, and keep unsupported persistent PTY dependencies out of the target while retaining non-PTY `exec_shell` support (#4470 by @shenjackyuanjie; original bindgen approach in #4384 by @shenyongqing). - Honor `[auto] cost_saving = true` in provider-aware heuristic and classifier routing, using only validated same-provider fast siblings and deriving fallback candidates from their actual provider so Auto cannot invent a cross-provider model. Providers without a known fast sibling stay on the active model (#4486; partial #4405). - Make terminal-client clipboard behavior truthful over SSH: use OSC 52 outside tmux, stock `tmux load-buffer -w` inside tmux, and bracketed paste for client-to-remote text. Graphical text and image access now requires credible forwarding or an explicit override, transport failures no longer claim success, and help distinguishes terminal text paste from graphical image attachment (#4484). - Keep a fresh TUI Work surface from rendering prior-session worker snapshots or durable-task terminal receipts whose creation or completion predates the current app start. Active durable tasks remain visible, and shared history stays available through `/tasks` and archived agent views (#4488; partial #4416). - Make doctor and setup output distinguish static configuration, command availability, MCP protocol readiness, and backend health instead of presenting configured routes as live-healthy. Ordinary doctor runs no longer wake loopback/self-hosted providers unless `--probe-local` is explicitly requested (#4485; partial #4406). - Serialize test-only configuration-path readers with temporary environment redirects so the Windows provider-persistence matrix cannot observe another test's transient `CODEWHALE_HOME` or config path (#4483, closing #4463). - Restore direct Moonshot `kimi-k3` to its documented 1,048,576-token context window and 131,072-token output limit instead of treating the live model as an unknown legacy 128K route. The existing Kimi Code tiered `k3` route and credential reuse remain unchanged (#4481). - Keep read-before-edit snapshots in the engine session so a file read remains valid across turns and context compaction, while a new session still starts with an empty tracker (#4475 by @Angel-Hair). - Make `apply_patch` expose the canonical `replace` operation while continuing to accept deprecated `changes` payloads through one validation path. Mixed patch, replace, and compatibility modes now fail before any write (#4476 by @Angel-Hair). - Show the prompt-cache hit rate in the phase strip when the Cache status item is enabled, using overflow-safe rounded integer math and leaving compact or disabled status layouts unchanged (#4474 by @dmitri-0). - Preserve Solarized Light's canonical Base3 (`#fdf6e3`) shell background instead of tinting it green-grey through the default underwater Ombre treatment, while retaining foreground ambient life (#4457 by @AiurArtanis; PR #4471 by @nightt5879). - Register `/slop` and `/canzha` as compatibility aliases of `/debt`, while keeping user-command ownership truthful across dispatch, help, slash completion, alias copy, and typo suggestions (PR #4680 by @nightt5879). - Fail closed on legacy Kimi CLI credential imports: remove Codewhale's hard-coded first-party-client impersonation and refresh request, never auto-enable or rewrite imported credentials, and label the compatibility route as a read-only imported token. An explicitly configured, still-valid access token remains usable until expiry; missing, malformed, and expired imports recover through the supported Kimi Code API-key route while first-class OAuth awaits Codewhale's own vendor registration (#4417, partially addressed). - Restore xAI/Grok device-code OAuth login against the live xAI OIDC contract: discovery with issuer/endpoint validation and documented fallbacks, user-principal scope set, RFC 8628 `slow_down` backoff capped at code expiry, bounded, sanitized error reporting for denial, expiry, and malformed responses, and a shared blocking-worker boundary for both CLI and TUI login so reqwest's blocking client never creates or drops its private runtime inside Codewhale's Tokio runtime (#4410). - Anchor `FREQ=HOURLY` automations with `BYHOUR`/`BYMINUTE` to persisted local-calendar slots so intervals keep their wall-clock phase across DST, restart, resume, RRULE updates, duplicate-slot recovery, and post-run advancement. Nonexistent clock slots are skipped and ambiguous slots run at their first occurrence (#4381 by @h3c-hexin). - Give content-watch drafts canonical identities: the link and semantic-drift watchers now write and dedup through one canonical draft-storage key with deterministic hash-suffixed IDs, validate and bound model drift output before any KV writes, and show truthful admin draft labels, so unchanged findings dedup and changed findings re-draft instead of colliding (#4453). - Make model-policy JSON repair consider object and array payloads in source order, matching nested delimiters across quoted strings and escapes and returning the earliest balanced candidate that parses, instead of letting an unmatched opening delimiter or object-first preference corrupt array payloads (#4430). - Convert persisted sub-agent completion and still-running control events into concise, non-authoritative resume checkpoints, keeping their raw runtime envelopes, sentinels, and retry instructions out of restored model and TUI conversation state (#4409). - Deliver failed, stopped, and stale sub-agent outcomes exactly once to the awaiting parent, lifecycle mailbox, and TUI before closing their runtime state. Restart now reconciles orphaned queued/model/tool-wait worker records to interrupted while preserving checkpoints, and cancelled workers no longer read as completed in the TUI (#4408). - Give host applications a cancellation boundary for MCP OAuth login so a stalled or abandoned provider login no longer hangs the calling session (#4380). - Avoid blocked reader joins after Windows process kills so terminated shell sessions cannot hang their readers (#4383). - Give stdin-less observer hooks immediate EOF and contain timed-out hook process trees so descendants and pipe readers cannot leak after the parent shell exits (#4489 by @luismateusvargas). - Preserve the full unsigned Windows PTY process status instead of collapsing every high-bit exception or NTSTATUS to `2147483647`, including decimal and hexadecimal diagnostic metadata for device retests (#4100 by @redjade75723). - Keep the Hotbar Setup action list synchronized with keyboard focus when the selection moves beyond the visible rows, including Down past `/export` (#4418). - Route Windows OpenHarmony Cargo links through the repository's target-aware clang launcher so the final Rust link keeps its target, sysroot, and MUSL flags, and extend the no-SDK release guard to protect that contract. This completes [@shenjackyuanjie](https://github.com/shenjackyuanjie)'s PR #4470 setup alongside [@shenyongqing](https://github.com/shenyongqing)'s original bindgen approach in PR #4384. - Reconcile the website roadmap with reality: the retired share-link direction is now an explicit non-goal, Workrooms is the considered direction, and the local web client appears as underway, in English and Chinese (#3418). - System-prompt skills block and skill-load warnings no longer embed absolute home/workspace paths; entries render workspace-relative or `~/…` so the byte-stable prompt prefix never leaks private paths. A new invariant test guards absolute paths, API keys, and workspace paths in the prefix (#4632). - Mode/permission baseline unit tests no longer read the developer's live `settings.toml`; they isolate config I/O to a temp directory (#4628). - Enter no longer freezes the composer on send: dispatch splits into a sync prepare phase (instant history + spinner) and a spawned async phase (auto-route, preflight, engine send), with submits gated while a dispatch is in flight (#4605). - Self-hosted routes keep explicit per-model output limits for unknown wire aliases instead of the generic 4K fallback (#4655 by @h3c-hexin; PR #4656). - Chat Completions idle-timeout errors now include received-byte and timing telemetry, distinguishing prefill stalls from mid-stream stalls with truncated tool-call arguments (#4657 by @h3c-hexin). - `set_config` provider writes now keep the in-memory route in step, so a following model write lands in the new provider's table instead of clobbering the previous provider's root default_text_model (#4658 by @gaord, with a follow-up route-sync fix). ### Security - Restrict cross-origin Runtime API browser preflights to the documented authentication and content headers, explicitly allowing `Authorization` instead of relying on a wildcard (#4454). ### Contributors Thank you to the contributors whose code, reports, and reviews shaped v0.9.1: - [@h3c-hexin](https://github.com/h3c-hexin) — calendar-anchored hourly automation recurrence (PR #4381), the MCP OAuth cancellation report (#4380), explicit limits for unknown local models (PR #4656 / #4655), and idle-timeout progress telemetry (PR #4657). - [@gaord](https://github.com/gaord) — Runtime API provider registry and atomic provider-switch endpoints (PR #4658). - [@SamhandsomeLee](https://github.com/SamhandsomeLee) — the unified `/skills` root catalog, audit/provenance model, validated mutations, manager UI, and acceptance coverage (PR #4679), plus Enter-send lag diagnosis and fix direction for #4605 (PR #4654; landed via the release-lane async-dispatch split). - [@aboimpinto](https://github.com/aboimpinto) — the Layer 5.1 user-command registry boundary from PR #3278; the exact authored evidence commit from PR #4046, preserved intact in the integration graph; and the #2870 follow-up audit whose metadata and malformed-sibling gaps shaped the final corrections. Paulo also provided the structured, redacted Agent Details and `current_activity` direction preserved from #2694/#2889 and the real-PTY lifecycle acceptance direction from #2886. - [@baendlorel](https://github.com/baendlorel) — TelecomJS TokenHub provider support and key-scoped live-catalog direction from PR #4370, harvested into the current provider architecture with co-authorship preserved. - [@zhangweiii](https://github.com/zhangweiii) and [@sternelee](https://github.com/sternelee) — the original first-class OpenCode Go implementations (PRs #773 and #1050), harvested into the current provider architecture. - [@seanthefuturegorilla](https://github.com/seanthefuturegorilla) — the canonical OpenCode Go/Zen provider request and acceptance direction (#1481). - [@nightt5879](https://github.com/nightt5879) — `/debt` compatibility aliases with dispatch-consistent user-command shadowing across discovery surfaces (PR #4680), plus the Solarized Light background preservation fix (PR #4471). - [@AiurArtanis](https://github.com/AiurArtanis) — the Solarized Light regression report and reproduction (#4457). - [@shenjackyuanjie](https://github.com/shenjackyuanjie) — the HarmonyOS workflow-js bindgen, portable-pty gating, and SDK environment work (PR #4470). - [@shenyongqing](https://github.com/shenyongqing) — the original HarmonyOS bindgen approach (PR #4384), carried into the landed implementation. - [@luismateusvargas](https://github.com/luismateusvargas) — the Windows hook process-leak reproduction, process-tree analysis, and EOF fix direction (#4489). - [@redjade75723](https://github.com/redjade75723) — the persistent Windows PTY report that exposed lossy high-bit process-status handling (#4100). - [@w1w218](https://github.com/w1w218) — the Windows ARM64 release request and real-device motivation (#4267). - [@stream2stream](https://github.com/stream2stream) — the legacy-session recovery report that led to the read-only doctor diagnostic (#4032, #4539). - [@Angel-Hair](https://github.com/Angel-Hair) — session-owned read-before-edit tracking and the explicit, backwards-compatible `apply_patch` replacement contract (PRs #4475 and #4476). - [@dmitri-0](https://github.com/dmitri-0) — configurable cache-hit visibility in the phase strip (PR #4474). - [@fleitz](https://github.com/fleitz) — the canonical `Bash` no-`cwd` workspace fix and regression test that keep isolated sub-agent commands in their own worktree (PR #4673, closing #4674). - [@SparkofSpike](https://github.com/SparkofSpike) — the Windows Ctrl+O reproduction that exposed pre-pager result truncation and conflicting composer shortcut routing (#4482), and the exact Vim-space regression reproduction verifying the v0.9.1 input path already contains the needed global binding (PR #4477). ### Security - Harden the public community-site boundary: scheduled review drafts now use one canonical freshness namespace, admin discard is restricted to validated draft objects, public feed requests cannot spend the server-held GitHub token, and maintainer login bodies are type- and size-bounded before parsing. ## [0.9.0] - 2026-07-16 Codewhale v0.9.0 replaces the default terminal shell with the underwater interaction system, makes Operate message-first, and hardens the Fleet, Workflow, routing, accounting, and release surfaces that support day-to-day agent work. The release also expands localization and gives the public site a quieter, docs-first community foundation. Its provider work replaces the old hand-maintained picker boundary with live ProviderLake discovery and adds the largest curated model-and-pricing expansion in the project so far. ### Fixed — final integration - Redact configured, environment, file-backed, and bare active credentials from every tool result before it crosses any model-provider wire protocol; retrieved spillover content is sanitized again at that boundary. The `read_file` tool also refuses CodeWhale configuration, backup, and credential-store paths, preventing routine tool use from exposing those local files. - Keep immediate TUI submit failures inside the shell: custom-provider route preflight and closed-mailbox errors now restore the exact composer draft and selected skill for retry, with a sticky visible error instead of exiting. - Anchor automatic compaction thresholds to the route's spendable input budget after output reservation and safety headroom, so large-output and tight self-hosted routes compact before provider context rejection. The TUI pre-send gate and warning copy now use the same token threshold as the engine. Preserve the 262K Kimi route's usable input budget and use the documented 32K default generation budget instead of mirroring the context window as output (#4293 by @SamhandsomeLee, #4368 by @bruce6135, and #4378 by @mvanhorn). - Fail closed instead of reporting base-rate dollar estimates for direct OpenAI GPT-5.4/5.4 Pro, GPT-5.5 (including dated snapshots), and GPT-5.6 Sol/Terra/Luna requests above 272K input tokens. Exact tiered accounting remains deferred to the generalized pricing schema; smaller 5.4 variants, GPT-5.5 Pro, Codex subscription, and foreign-provider routes are unchanged (#4317). - Retire `deepseek-chat` and `deepseek-reasoner` before they reach DeepSeek's first-party OpenAI or Anthropic wire APIs, migrating both to the documented `deepseek-v4-flash` replacement while preserving legacy non-thinking / thinking intent when no explicit reasoning tier is set. Aggregator, Wanjie Ark, self-hosted, and custom endpoint model ids remain provider-owned (#4320). - Make Operate a message-first multitask surface: ordinary prompts work without a Workflow, direct parent tools follow the same approval, sandbox, shell, ask-rule, and repository protections as Act, and follow-ups can queue while work is active. Bounded background workers remain preferred for independent, parallel, isolated, or long-running work; child handoffs cannot inherit standing Full Access, and each dispatch produces one durable completion receipt. - Let personal Fleet profiles in `CODEWHALE_HOME/agents` travel across repositories while project profiles in `.codewhale/agents` override them. Saving refreshes the live roster, and the UI now says explicitly that profile availability does not expand workspace, trust, or filesystem authority. - Move file-mention discovery onto one bounded, generation-safe background worker so a slow filesystem read cannot freeze composer input. Exact paths resolve on send; fuzzy matches stay in the completion popup instead of silently attaching an arbitrary same-name file (#4365 by @WavesMan, with the initial bounded-walk approach from #4367 by @LeoLin990405). - Keep the opt-in `remember` tool in the model-visible first-turn catalog so durable preference capture works without requiring a model to discover a tool it cannot yet know exists (#4373 by @Angel-Hair and #4377 by @mvanhorn). - Make `review` handle a staged snapshot relative to a base ref by comparing the branch merge-base tree with the index. This preserves committed and staged branch work, excludes unstaged edits, and avoids the invalid `git diff --cached ...HEAD` form. - Honor each MCP server's advertised discovery capabilities before calling optional tools, resources, templates, or prompts; keep optional probes independently bounded and fail-soft (#4308 by @nsfoxer). - Make offline `scorecard` pricing provider-aware: `turn_end` records carry the effective route and a non-secret billing surface, runtime exports and supported aliases ingest cleanly, legacy/unknown routes remain explicitly unpriced, and route-scoped cache and recorded-time pricing replace model-only guesses. Historical runtime aggregates use each turn's recorded time; costless catalog routes fail closed while exact provider-owned hand-price rows remain available. StepFun PAYG and Step Plan usage now stay distinct without persisting raw endpoint URLs, so subscription quota is never reported as token spend (#4335). Completion-only shell, manual-compaction, and purge events remain visible to `turn_end` observers as explicitly non-model lifecycle records. This builds on the scorecard introduced by @findshan in #3388. - Preserve named custom-provider identity across TUI sessions, `exec --resume`, runtime threads, exports, cache and Workflow receipts. Restores resolve the saved provider against live configuration before creating a client, never infer a provider from the model ID, and fail closed when the named route was removed, invalid, or ambiguous (#4334). - Bind credentials to the endpoint that owns them. Environment-selected custom hosts can no longer inherit saved provider keys, keyring entries, OAuth, or ambient provider variables; only an explicitly source-marked CLI key may follow an explicit CLI endpoint override. `auth_mode = "none"` also strips credential-shaped custom headers consistently in the TUI and app server, while keyless loopback routes remain usable as local runtimes. - Make hosted runtime threads deterministic and provider-exact: serialize thread, turn, and event mutation; keep cancellation ownership with the host; preserve the selected provider through every durable turn; terminalize exceptional streams once; and prevent the runtime manager from silently dispatching unclaimed goal continuations or child turns. - Treat required user confirmation as a real goal blocker instead of a failed goal, and explain how to recover when a previously cached approval is denied. Cached-denial recovery is also committed as a settled transcript receipt, so tool completion or a later status update cannot erase it from scrollback or accessibility output. The notice now describes matching, process-scoped denials truthfully across all shipped locales; approval audits honor `CODEWHALE_HOME`, and expired status toasts cannot remain trapped behind a persistent entry. Both states remain visible and actionable instead of looking like unexplained model or tool failure (#4374 and #4375 by @Angel-Hair, with the final hardening in #4385 by @nightt5879). - Make Fleet launch and teardown deterministic: route flags are placed before `exec`, workers are contained in owned Unix sessions or Windows Job Objects, and cancellation reaps surviving descendants with bounded escalation before manager state settles. Fence progress, terminal status, verification receipts, and evidence by durable attempt generation so a stale process can never complete or overwrite a restarted attempt; terminal state and receipt now commit atomically, stale-heartbeat decisions use a full lease CAS, exhausted-retry alerts are exactly once, and crash-truncated ledger tails are quarantined before the next append. Standalone CLI and Runtime API restart controls now drive the replacement attempt through a real executor to its terminal receipt, while per-run manager ownership prevents concurrent controllers from launching the same attempt twice. - Keep the stopship Workflow fixture bounded to measured 24k-per-turn role budgets and a 360k aggregate. Authored child step and wall-time limits now reach the live runtime, including launch-queue wait; promoted evidence stays intact between roles, tool-free handoff consumers omit tool fields on the provider wire, and a terminal `BLOCK` fails the Workflow instead of producing a successful Lane receipt. Free-form descriptions no longer fabricate write, shell, or network risk; unknown structured risk remains fail-closed. - Keep repository trust affirmative and explicit: only `1`/`Y` are advertised as acceptance keys, while Enter remains non-affirmative and explains the required choice. - Replace literal legal and doctrinal metaphors in Simplified Chinese setup and `/constitution` copy with direct collaboration terminology reviewed by a native speaker (#4369 by @hmr-BH). - Keep the transcript reviewable while an inline approval card is active: Page Up/Down, modified arrows, Home/End, and the mouse wheel now move through the visible evidence without changing or dismissing the pending decision (#4371 by @amuthantamil). - Match generated worker names to the active UI language while preserving explicit user names, and tighten the 89x50 shell rhythm across Fleet rows, choice dialogs, transcript boundaries, and the idle composer. - Put docs content and search before the full index on small screens, reduce mobile dead space, and keep the public community copy focused on issues, pull requests, and international contributors. ### Changed — the underwater shell - Replace the default TUI shell with the underwater interaction system: one renderer owns the header, top work strip, transcript ledger, composer, and footer, with explicit compact/normal/wide tiers and no legacy sidebar or dashboard in the default path. The legacy composition survives only behind the internal `classic` treatment. - Add a distinct pre-session launch screen — new session, new worktree (with inline naming and real lane provisioning), scoped resume count, changelog, quit — with reliable non-colliding keys and row/keyboard parity. - Render turns as a ledger: user message, short narration, settled tool receipts, and exactly one live row. Fast tool bursts land directly as batch receipts (no spinner churn), completed receipts stay inspectable, failures hold a coral receipt with stderr one `v` away, and one shared tool rail replaces nested card borders. - Make completion a one-shot exhale: `working -> finishing -> done` in the footer only, with no transcript repaint, no lingering loop, and no stale cancel action in the completed state. - Rebuild the secondary rooms on one hairline grammar — config, setup, sessions, help, context, theme, model/route, Fleet, file attach — each with a title hairline, row objects with focus/selection/mouse parity, one panel-owned scroll rail, and wrapped action footers. - Make `/model` a model-first atomic route picker across configured providers: provider and model switch together on apply, and every row prints the resolved model. `/theme` gains a live preview with truthful Esc revert across all 12 shipped themes. - Add a live context inspector (Alt+C) backed by the current route: exact system/messages/free token buckets, a proportional map, drill-down into the detail pager, and no frozen session while it is open. - Project Workflow runs as an in-stream run map: a collapsed one-line card that unfolds into per-lane rows with role, resolved model, worktree, elapsed track, and per-member running/waiting/failed/cancelled/done states, plus gates and a debrief built only from real run data. Child transcripts never flood the parent shell. - Unify Fleet into roster/setup/workers rooms: the operator is pinned first with the live session route, members show resolved route truth (inherit / fast lane / pinned), and the workers tab is a control surface with row-local open/stop and real lifecycle counts. - Distinguish repository-law approvals from ordinary approvals: the constitution prompt names its authority, source, matched rule, and target, and Full Access never bypasses it. Ordinary approvals render as a still coral band above the visible transcript. - Keep streaming honest and cheap: provider-unit deltas replace per-grapheme queueing, the transcript is top-anchored so appended lines stop shifting settled rows, ambient animation stops during real work, and ordinary completion no longer triggers full-screen clears (verified by render-diff logs: suffix updates of tens of cells while streaming, zero periodic full repaints). - Give every underwater treatment ambient life: ombre breathes its water column while flat and Terminal-owned keep the idle fish and bubble (foreground-only for Terminal), a typed treatment setting replaces string comparisons, reduced motion freezes life legibly, `fancy_animations = false` stills the chrome, and typing scatters the fish immediately. Fish keep a one-cell gap from occupied text; the whale remains the single brand mark and returns to stillness between caustic sweeps. - Bring the whale mark to life with a soft diagonal caustic sweep, then let it genuinely rest. Active markers now share a smoother 8 Hz clock after the existing earned-motion delay, while reduced motion, hidden/off-screen views, modal ownership, and compact-terminal redraw budgets remain authoritative. The motion is adapted from the Apache-2.0 Grok Build interaction language, not copied as a global pulse or high-frequency receipt cascade. - Keep compact terminals operable: `/config` and `/resume` collapse secondary chrome before sacrificing their selectable rows at 40x12 and 60x16, bodies budget for the footer's real wrapped height, and the selection stays visible through resizes. - Route footer notices through the classified toast system so informational acknowledgements (for example "Auto-compaction enabled") expire instead of becoming permanent idle chrome, while warnings and errors hold as sticky notices until their window passes. - Complete the `CODEWHALE_ASCII_SAFE=1` decorative tier: the whale mark, context meter, braille state markers (mapped by dot density so the working bubble still reads as a rising fill), bubbles, rails, and role/lane glyphs all narrow to semantic ASCII while user, model, and CJK text passes through untouched. Verified by whole-surface rendered-buffer sweeps. - Repair the Help catalog to match handler truth (`Alt+G`, `Alt+Shift+G`, `Alt+[`, `Alt+]`, `Alt+L`, `Alt+?`), and give theme, Help, model, and config rows direct mouse paths with the same activation as Enter. ### Changed — integrated runtime and TUI - Make worker delegation route-aware and identity-safe: workers receive a small role-scoped system prompt instead of stale parent/model boilerplate, faster routes resolve through the configured provider, and opening a worker shows its complete available transcript. Remove `token_budget` from the ordinary model-facing Agent schema so agents do not micromanage ad-hoc launches; explicit legacy calls remain readable for compatibility. - Mature `/config` interaction for enumerated and boolean settings with pickers/toggles, mouse-wheel scrolling, stable focus, and configured-provider selection. Startup mode is now only Agent or Plan; legacy `operate`/`yolo` settings migrate to Agent with permission posture represented separately. - Show where effective permission policy comes from and keep profile, environment, project, managed, and requirements-controlled posture read-only in the in-session editor. Runtime presets edit only proven user-owned root settings and no longer persist temporary environment overlays. - Restore the original four-line whale mark and make ambient ocean motion coherent across the full scroll surface: one continuous ombre, eased fish that face their direction of travel, fish in otherwise blank scrollback, and explicit reduced-motion and animation controls. - Keep model reasoning in the transcript rather than the Tasks strip, retain the live header status indicator, separate worker and success colors, and use the same rail grammar for both work-strip and transcript scrollbars. - Present the default Z.AI Coding Plan route, including child routes, as subscription quota instead of estimated per-token dollars. No undocumented account endpoint is called by this change. ### Added - Thinking Machines Lab's Inkling through Together using the exact wire model `thinkingmachines/inkling`, with `inkling` and `together-inkling` aliases and exact `none` / `minimal` / `low` / `medium` / `high` / `max` reasoning values. Codewhale does not invent a context window, price, or offline picker claim while the provider's public catalog metadata remains inconsistent. - Expand the verified offline catalog with Claude Sonnet 5, Claude Fable 5, GPT-5.3 Codex, and Qwen3.7 Plus, including time-aware Sonnet 5 introductory pricing and explicit cache rates. Refresh stale GLM-5.1, Kimi K2.6, Trinity, Qwen3.6, Nemotron, Anthropic, GLM-5.2, Kimi K2.7 Code, GLM-5 Turbo, and GPT-5 Codex price or limit rows; keep Xiaomi MiMo explicitly unpriced where the provider's token plan and pay-as-you-go surfaces cannot be distinguished. - MiniMax Messages provider support for MiniMax-M3 and MiniMax-M2.7, with OpenAI-compatible and Messages routes, regional endpoint guidance, request coverage, catalog limits, and tier-aware pricing (PR #4354 by @octo-patch). - Dynamic MCP server infrastructure and an approval-gated tool that lets the model start a configured MCP server from chat context. Harvested from #3869 and #3866 by @bistack with authorship preserved. - Parent `--disallowed-tools` restrictions now flow into sub-agents and Fleet workers by default, including deny-wins, wildcard, catalog-filtering, and multi-generation inheritance coverage. Harvested from #4096 by @JayBeest (#4042). - Korean (ko) UI locale with full key parity and onboarding/setup wiring (PR #4347 by @moduvoice). - Localize the entire underwater layer: 104 new UI strings — launch menu, phase words, mode/permission chips, footer hints, session picker, context inspector, route and theme pickers, Fleet roster, workflow status, sidebar work strip, repository-law approval copy, and file-attach titles — wired through MessageIds and translated into ja, zh-Hans, es-419, pt-BR, vi, and ko. Every complete pack now holds exact raw key parity with English (856 keys), enforced by new tests that the old English-fallback gate could not perform. The permission chip maps from typed state, so localization can never silently collapse it. Machine-authored translations follow each pack's existing terminology and are flagged for native review. - Anthropic adapter: sanitize top-level `oneOf`/`anyOf`/`allOf` in tool input schemas so affected tools no longer fail the whole request with HTTP 400 (PR #4346 by @qinlinwang). - Anthropic pricing: bill cache-write tokens at published rates (PR #4348 by @knqiufan, #4318). - NetBSD: generate QuickJS bindings at build time so `codewhale-workflow-js` compiles (PR #4349 by @ci4ic4). - Real-PTY release gates for six-worker fan-out liveness with Esc cancel, multi-terminal route isolation, queued steering via terminal-safe Ctrl+G (with Ctrl+S retained where the terminal forwards it), the one-shot completion footer, and per-theme ANSI output for every shipped palette. ### Fixed - Make release publication complete and source-anchored: every build checks out the resolved tag commit, tag movement is rejected before GHCR, GitHub Release, Homebrew, Cargo, or npm writes, and registry helpers require a clean checkout exactly matching the remote tag. Manual recovery runs are exact-tag-only and execute the same parity gate as automatic tag pushes. - Publish a coherent distribution set: both checksum manifests now contain usable public basenames and cover the full 29-asset matrix; GHCR, Homebrew, GitHub archives, and the Linux x64 CNB mirror carry `codewhale`, `codew`, and `codewhale-tui`. The CNB shortcut now fails clearly outside Linux/OpenHarmony x64 instead of promising assets that the mirror does not build. - Preserve task text when a skill is invoked through dollar, unified-slash, or explicit skill syntax, while keeping bare skill invocations and management subcommands intact (PR #4372 by @nightt5879, co-authored by @CCChisato; #3915). - Honor MCP server discovery capabilities: require advertised or legacy `tools/list`, keep optional resource/template/prompt probes independently bounded and fail-soft, and format descriptions Unicode-safely (#4308, harvested with co-authorship from @nsfoxer). - Age-evict terminal sub-agent worker records from the state ledger so long-lived, high-fan-out sessions do not keep rewriting multi-megabyte terminal history (#4217; root-cause and fix direction from @yekern). - Resolve the sub-agent completion/cancellation race with one terminal-state claim: cancellation suppresses late mailbox/parent/UI delivery, while a completed result remains publicly running until its notification is safely delivered. - Keep Workflow panel controls from stealing ordinary composer letters. Enter, Delete, Up/Down, and Esc own panel actions; typed characters return focus to the composer and start the message normally. - Preserve the composer prompt gutter from the first typed character through wrapping, scrolling, cursor placement, and mouse hit-testing so the `>` does not disappear or make input appear to jump. - Emit terminal-native OSC 8 metadata for rendered URLs without placing escape payload bytes in the measured text, keeping long links visible, selectable, and clickable in supporting terminals. - Keep headless structured output terminal-clean: `codewhale exec` engines no longer emit interactive terminal-title/taskbar OSC sequences, so `--output-format stream-json` stdout stays parseable, escape-free JSONL. Interactive TUI sessions keep their terminal chrome. - Localization honesty: the parity gate was blinded by its own English fallback — two keybinding rows (`KbCyclePermissions`, `KbCycleThinking`) were missing from all five "complete" packs and now ship translated; the Operate-mode copy that drifted in English was retranslated in every pack (including zh-Hant's slice); three MessageIds absent from ALL_MESSAGE_IDS are visible to tests again; and the `/config` theme/locale hints and the invalid-locale error derive from the shipped registries instead of stale hand lists that advertised 4 of 12 themes and 4 of 8 locales. - The setup wizard's constitution step no longer claims a "55-line core" in any language (the bundled core is larger today); the guided draft says "the bundled core stays active" instead. - In-app selection copy is rail-clean and now regression-tested: copied transcript text excludes the `▎ ╎ │ ●` decorations via cache metadata (#4208 — thanks @eugenicum for the report and code-aware fix direction; terminal-native selection with mouse capture off remains a product decision on the proposed `rail_style` option). ### Docs - Stamp every 0.9-era roadmap document with an explicit status (current, historical, superseded, principle-only, or future RFC), correct trackers that recorded unshipped work as done, and describe what remains after v0.9.0 in `docs/AGENT_RUNTIME.md`. - Add `docs/rfcs/UNIFIED_PROVIDER_LOGIN.md`: one `codewhale auth login` surface for Anthropic, OpenAI Codex, and xAI, with the Anthropic adapter gated on verifying flow permissions before any constants are adopted. - Refresh `docs/ACCESSIBILITY.md` for treatment-independent ambient life and the completed ASCII tier. ### Changed — runtime foundations - Make the advertised Android/Termux release target buildable by generating QuickJS bindings against the Android NDK instead of expecting an upstream pre-generated `aarch64-linux-android` binding file, and give Android CLI/TUI HTTP clients a preconfigured rustls root store (Mozilla WebPKI roots) so standalone Termux processes stop panicking inside `rustls-platform-verifier`'s JVM expectations (#4236, #4242). - Rebalance the bundled Constitution after the v0.8.67 prompt ablation: keep the procedural policy tail in mode-specific layers, while restoring concise behavioral guidance for momentum, causal investigation, constraint-first decisions, mechanism-backed guarantees, and clean continuity. - Wire live catalog cache into provider/model pickers without dropping stale or prior rows after TTL expiry / refresh failure (#4139). Remove the dead `OFFERING_SEEDS` hand table so the bundled Models.dev catalog is the sole seed source; pickers show a compact `stale` / `cache failed` chrome chip when the Models.dev layer is past TTL or last refresh failed. - Make `work_update` the sole model-facing To-do / Work progress tool (#4132). `checklist_*` and `todo_*` remain registered as hidden compat aliases for transcript replay; `update_plan` stays Strategy metadata/context/route, not a second checklist. Mode/approval prompts nudge the single surface. - Demote the bundled Models.dev snapshot to an offline/stale fallback after live catalog refresh (#4188). ProviderLake precedence is live Models.dev > bundled seed > legacy hardcoded completion names; pickers, inventory, and subagent validation stay catalog-backed, and Codewhale-only providers keep defaults when Models.dev has no rows. ### Added - Wire xAI device-code OAuth into `codewhale auth xai-device`, the TUI `/auth xai-device` command, and guided provider setup, with comment-preserving auth-mode persistence and loopback exchange coverage (#4257). - Add GPT-5.6 Sol, Terra, and Luna to the OpenAI API route, including their 1.05M context metadata, 128K output limits, pricing, and `max` reasoning effort. Add Meta Model API as a first-class OpenAI-compatible provider for Muse Spark 1.1 with 1M context, tool/reasoning metadata, provider aliases, and both `META_MODEL_API_KEY` and Meta's `MODEL_API_KEY` credential names. - Catalog automation: `scripts/catalog_models_dev.py` refreshes secret-free Models.dev / OpenRouter listings and validates the offline seed snapshot (`snapshot --check`) without ever persisting API keys (#4117). - `/model` picker cycles six catalog views with `A` (Configured → Catalog → Recent → Coding → Cheap → Long context) and richer row metadata from the live/bundled catalog (context, max output, tools, reasoning, price/M, freshness). Discoverability views do not auto-apply a surprising route (#4115). - Workflow runs are now durable: every run appends to a `.codewhale/workflow-runs.jsonl` journal and hydrates on startup, so `workflow status` survives restarts; runs left `running` by a dead process are recovered as failed (#4011). The transcript renders workflow tool output as a run card (status, goal, children, progress, verification) instead of a generic one-liner (#4038), and `workflow` accepts a `verify` flag that runs post-completion verification gates and fails the run when gates fail (#4013). - Hotbar sources for MCP tools and skills: MCP tool slots prefill the composer (execution stays behind the normal tool-approval flow) and skill slots activate through the existing `$skill` alias (#2068, #2069). - Mode & permission surface: Tab cycles Plan → Act → Operate; Shift+Tab cycles the Agent permission posture (Ask / Auto-Review / Full Access) with a footer permission chip; Ctrl+T cycles reasoning effort and Ctrl+Shift+T opens the live transcript overlay. Operate is the orchestration mode (delegate, wait, inspect, dispatch) and raises sub-agent fan-out while focusing the Agents sidebar. - Provider lake facade: the provider/model pickers, hotbar, and model inventory now enumerate configured providers' models from the bundled catalog (with an `A` toggle to browse the full catalog), replacing the hardcoded per-provider model table (#3830 follow-up). - Added Cursor-integrated-terminal dogfood evidence for the published v0.8.67 release, covering installed binary provenance, release/publication checks, headless runtime smoke, setup QA, and remaining manual visual TUI checks. - README and README.zh-CN now point users to the community-maintained CodeWhale for VS Code GUI frontend while clarifying that this repository's `extensions/vscode/` scaffold remains the read-only Phase 0 viewer (#4035). ### Fixed - Sub-agent waiting no longer peek→sleep polls: `agent(action="wait")` joins children, unchanged peeks are throttled (~30s) with an anti-polling nudge, and mode prompts teach the join primitive (#4097). Harvested from PR #4098 by [@Mr-Moon121](https://github.com/Mr-Moon121) (Jeffrey Luna). - `/provider` picker remembers catalog/configured view and highlighted row across reopen, matching `/model` picker memory. - Mode picker roster is exactly Act / Plan / Operate (no Multitask, no numeric `4`/`5` gaps). Legacy `yolo`/`4` remain invisible one-way permission shorthand for Act + Bypass. - Fleet setup is a role/profile roster editor, not a provider-scoped model picker: the Model step lists routes from every configured provider (not only the active one), a picked route's provider is persisted explicitly in the saved profile TOML (`provider = "..."`, never inferred from the model id), and the loader/route resolver read that field back out verbatim. The draft-preview save keypress no longer competes with a separate pager's `g`/`G` scroll bindings — the exact TOML preview now renders inline on the same Review step that saves it (#4093). - `codewhale fleet run` and interactive in-process Fleet launches now honor a profile-pinned provider/model route instead of merely recording it on the receipt. Headless workers receive the non-secret `--provider` and `--model` pair; TUI workers resolve the same explicit route in process. Credentials still come from the worker's environment, provider is never inferred from a model id, and unpinned workers continue to inherit the run route (#4093, #4193). - The Fleet setup `m` model-assisted redraft no longer drops a picked cross-provider route: the provider/model the operator chose are re-pinned onto the drafted profile (a model draft is always `provider: None`), so saving it keeps the explicit route instead of persisting an ambiguous, provider-scoped profile (#4093). - Saving a Fleet profile now fails with a clear message when it pins a provider that has no configured credentials, using the same configured-provider check the model picker uses (#4093). - Workflow correctness: completion polling fails closed instead of fabricating success when a sub-agent reports no terminal status; cancel interrupts the JS VM (cancel handle + abort) and blocks further spawns; and `budget.spent()` reports real manager-scope usage instead of always 0. - Sub-agent spawns validate the model↔provider pair before dispatch: inherited/faster routes remap foreign models to the provider's catalog default, and explicit pins fail fast with a diagnostic instead of an upstream model-not-found error. - TUI stability: engine event drains break every 8–16 events / 8 ms to keep input live (#1830, #2317, #1198); the terminal input pump restarts after stall recovery on macOS/Linux too; the startup raw-mode probe no longer leaks raw mode on timeout; recovery snapshots persist every 45 s during long turns and the offline queue persists on every push (#1830); queue/steer paths surface toasts while streaming (#2317, #1338); and modal submit errors re-open the modal instead of being swallowed (#1198). - Core/state: paused jobs persist as paused across restarts; unarchive updates the in-memory cache; tool dispatch has a timeout; MCP notifications no longer receive responses; corrupted checkpoints surface errors instead of loading empty state; the session index compacts instead of growing unbounded; and recording thread-goal usage no longer self-deadlocks the state store. - Runtime compaction summaries are now persisted into `/v1` thread records so engine reloads and restarts preserve compacted context. Contributed by MXAntian (@MXAntian) (#4091). - The TUI leaves xterm alternate-scroll mode off when mouse capture is disabled, preserving native terminal text selection in light-theme/no-mouse-capture sessions. Contributed by Nightt (@nightt5879) (#4088, #4026). - The public `/api/github/feed` endpoint is now forced dynamic on Cloudflare so it returns live GitHub activity instead of a build-time empty feed. ### Security - Require bearer authentication for `/v1/chat/completions`, compare tokens in constant time, return accurate 4xx/5xx statuses, bound request bodies and SSE frames, redact secrets from stdio `config get`, and reliably reap the runtime child during shutdown. - Keep trust precedence and secret persistence fail-closed: user ExecPolicy rules outrank agent-layer rules, chained commands cannot propose unsafe trusted-prefix amendments, and config and secret writes are atomic with filesystem synchronization on every supported platform. ### Changed - Tool-hang watchdog trimmed from 15 minutes to 10 (#1862); approval modal footer hints use a higher-contrast tier (#3380); status/mode copy is disclosed once across header, footer, cards, and sidebar instead of repeated per layer. - Removed the unused `tui::whale_routes` taxonomy module and its tests. Contributed by Darrell Thomas (@DarrellThomas) (#4041, #3852). ### Deprecated - YOLO mode: `--yolo`, `default_mode = "yolo"`, and the hotbar YOLO action now map to Act + Full Access permissions via a compatibility shim and show a one-shot deprecation notice. Removal is deferred beyond v0.9.0 so this release does not break existing scripts without a dedicated cutover. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - Remove the deprecated `deepseek` and `deepseek-tui` binary shims in this breaking release. `codewhale`, `codew`, and `codewhale-tui` are the supported entry points; existing DeepSeek provider support and legacy config/session migration remain intact. ### Known issues - Android/Termux arm64 remains a preview in v0.9.0. The target, asset wiring, updater selection, dependency graph, and source-build path have automated or static coverage, but shell/PTY/config/TUI startup and runtime behavior remain unverified on a real device (#4236, #4242). Do not use a GNU/Linux arm64 archive in Termux. ### Contributors Thank you to the international community whose code, reports, reviews, and reproductions shaped v0.9.0: - [@amuthantamil](https://github.com/amuthantamil), [@bistack](https://github.com/bistack), [@bruce6135](https://github.com/bruce6135), [@CCChisato](https://github.com/CCChisato), [@ci4ic4](https://github.com/ci4ic4), [@cyq1017](https://github.com/cyq1017), and [@DarrellThomas](https://github.com/DarrellThomas). - [@eugenicum](https://github.com/eugenicum), [@findshan](https://github.com/findshan), [@gaord](https://github.com/gaord), [@hmr-BH](https://github.com/hmr-BH), [@hongqitai](https://github.com/hongqitai), and [@idling11](https://github.com/idling11). - [@JayBeest](https://github.com/JayBeest), [@knqiufan](https://github.com/knqiufan), [@LeoLin990405](https://github.com/LeoLin990405), [@moduvoice](https://github.com/moduvoice), [@mvanhorn](https://github.com/mvanhorn), [@Mr-Moon121](https://github.com/Mr-Moon121), and [@MXAntian](https://github.com/MXAntian). - [@Angel-Hair](https://github.com/Angel-Hair), [@nightt5879](https://github.com/nightt5879), [@nsfoxer](https://github.com/nsfoxer), [@octo-patch](https://github.com/octo-patch), [@qinlinwang](https://github.com/qinlinwang), [@SamhandsomeLee](https://github.com/SamhandsomeLee), and [@taixinguo](https://github.com/taixinguo). - [@WavesMan](https://github.com/WavesMan), [@wuisabel-gif](https://github.com/wuisabel-gif), and [@yekern](https://github.com/yekern). ## [0.8.68] - 2026-07-10 ### Changed - Make the advertised Android/Termux release target buildable by generating QuickJS bindings against the Android NDK instead of expecting an upstream pre-generated `aarch64-linux-android` binding file, and give Android CLI/TUI HTTP clients a preconfigured rustls root store (Mozilla WebPKI roots) so standalone Termux processes stop panicking inside `rustls-platform-verifier`'s JVM expectations (#4236, #4242). - Rebalance the bundled Constitution after the v0.8.67 prompt ablation: keep the procedural policy tail in mode-specific layers, while restoring concise behavioral guidance for momentum, causal investigation, constraint-first decisions, mechanism-backed guarantees, and clean continuity. - Wire live catalog cache into provider/model pickers without dropping stale or prior rows after TTL expiry / refresh failure (#4139). Remove the dead `OFFERING_SEEDS` hand table so the bundled Models.dev catalog is the sole seed source; pickers show a compact `stale` / `cache failed` chrome chip when the Models.dev layer is past TTL or last refresh failed. - Make `work_update` the sole model-facing To-do / Work progress tool (#4132). `checklist_*` and `todo_*` remain registered as hidden compat aliases for transcript replay; `update_plan` stays Strategy metadata/context/route, not a second checklist. Mode/approval prompts nudge the single surface. - Demote the bundled Models.dev snapshot to an offline/stale fallback after live catalog refresh (#4188). ProviderLake precedence is live Models.dev > bundled seed > legacy hardcoded completion names; pickers, inventory, and subagent validation stay catalog-backed, and CodeWhale-only providers keep defaults when Models.dev has no rows. ### Added - Wire xAI device-code OAuth into `codewhale auth xai-device`, the TUI `/auth xai-device` command, and guided provider setup, with comment-preserving auth-mode persistence and loopback exchange coverage (#4257). - Add GPT-5.6 Sol, Terra, and Luna to the OpenAI API route, including their 1.05M context metadata, 128K output limits, pricing, and `max` reasoning effort. Add Meta Model API as a first-class OpenAI-compatible provider for Muse Spark 1.1 with 1M context, tool/reasoning metadata, provider aliases, and both `META_MODEL_API_KEY` and Meta's `MODEL_API_KEY` credential names. - Catalog automation: `scripts/catalog_models_dev.py` refreshes secret-free Models.dev / OpenRouter listings and validates the offline seed snapshot (`snapshot --check`) without ever persisting API keys (#4117). - `/model` picker cycles six catalog views with `A` (Configured → Catalog → Recent → Coding → Cheap → Long context) and richer row metadata from the live/bundled catalog (context, max output, tools, reasoning, price/M, freshness). Discoverability views do not auto-apply a surprising route (#4115). - Workflow runs are now durable: every run appends to a `.codewhale/workflow-runs.jsonl` journal and hydrates on startup, so `workflow status` survives restarts; runs left `running` by a dead process are recovered as failed (#4011). The transcript renders workflow tool output as a run card (status, goal, children, progress, verification) instead of a generic one-liner (#4038), and `workflow` accepts a `verify` flag that runs post-completion verification gates and fails the run when gates fail (#4013). - Hotbar sources for MCP tools and skills: MCP tool slots prefill the composer (execution stays behind the normal tool-approval flow) and skill slots activate through the existing `$skill` alias (#2068, #2069). - Mode & permission surface: Tab cycles Plan → Act → Operate; Shift+Tab cycles the Agent permission posture (Ask / Auto-Review / Full Access) with a footer permission chip; Ctrl+T cycles reasoning effort and Ctrl+Shift+T opens the live transcript overlay. Operate is the orchestration mode (delegate, wait, inspect, dispatch) and raises sub-agent fan-out while focusing the Agents sidebar. - Provider lake facade: the provider/model pickers, hotbar, and model inventory now enumerate configured providers' models from the bundled catalog (with an `A` toggle to browse the full catalog), replacing the hardcoded per-provider model table (#3830 follow-up). - Added Cursor-integrated-terminal dogfood evidence for the published v0.8.67 release, covering installed binary provenance, release/publication checks, headless runtime smoke, setup QA, and remaining manual visual TUI checks. - README and README.zh-CN now point users to the community-maintained CodeWhale for VS Code GUI frontend while clarifying that this repository's `extensions/vscode/` scaffold remains the read-only Phase 0 viewer (#4035). ### Fixed - Sub-agent waiting no longer peek→sleep polls: `agent(action="wait")` joins children, unchanged peeks are throttled (~30s) with an anti-polling nudge, and mode prompts teach the join primitive (#4097). Harvested from PR #4098 by [@Mr-Moon121](https://github.com/Mr-Moon121) (Jeffrey Luna). - `/provider` picker remembers catalog/configured view and highlighted row across reopen, matching `/model` picker memory. - Mode picker roster is exactly Act / Plan / Operate (no Multitask, no numeric `4`/`5` gaps). Legacy `yolo`/`4` remain invisible one-way permission shorthand for Act + Bypass. - Fleet setup is a role/profile roster editor, not a provider-scoped model picker: the Model step lists routes from every configured provider (not only the active one), a picked route's provider is persisted explicitly in the saved profile TOML (`provider = "..."`, never inferred from the model id), and the loader/route resolver read that field back out verbatim. The draft-preview ratify keypress no longer competes with a separate pager's `g`/`G` scroll bindings — the exact TOML preview now renders inline on the same Review step that ratifies it (#4093). - The headless `codewhale fleet run` CLI now launches workers on their profile-pinned route, not just records it on the receipt: `codewhale exec` gains a non-secret `--provider` flag, and a worker whose profile pins provider B is dispatched with `--provider B --model ` even when the parent session is on provider A (credentials still resolve from the worker's own environment; provider is never inferred from the model id). Workers with no profile-bound provider are unchanged — no `--provider`, run-level model. The interactive TUI spawns roster members in-process and does not yet honor the pinned provider (it uses the session provider); that remainder is tracked in #4193 (#4093). - The Fleet setup `m` model-assisted redraft no longer drops a picked cross-provider route: the provider/model the operator chose are re-pinned onto the drafted profile (a model draft is always `provider: None`), so ratifying it keeps the explicit route instead of persisting an ambiguous, provider-scoped profile (#4093). - Ratifying a Fleet profile now fails with a clear message when it pins a provider that has no configured credentials, using the same configured-provider check the model picker uses (#4093). - Workflow correctness: completion polling fails closed instead of fabricating success when a sub-agent reports no terminal status; cancel interrupts the JS VM (cancel handle + abort) and blocks further spawns; and `budget.spent()` reports real manager-scope usage instead of always 0. - Sub-agent spawns validate the model↔provider pair before dispatch: inherited/faster routes remap foreign models to the provider's catalog default, and explicit pins fail fast with a diagnostic instead of an upstream model-not-found error. - TUI stability: engine event drains break every 8–16 events / 8 ms to keep input live (#1830, #2317, #1198); the terminal input pump restarts after stall recovery on macOS/Linux too; the startup raw-mode probe no longer leaks raw mode on timeout; recovery snapshots persist every 45 s during long turns and the offline queue persists on every push (#1830); queue/steer paths surface toasts while streaming (#2317, #1338); and modal submit errors re-open the modal instead of being swallowed (#1198). - app-server hardening: `/v1/chat/completions` requires the bearer token; errors return real 4xx/5xx statuses; request bodies and SSE frames are size-limited; stdio `config get` redacts secrets and stdio shutdown reaps the runtime child; graceful shutdown on SIGTERM/Ctrl+C; constant-time token comparison; dropping the runtime bridge no longer blocks the runtime. - Policy/config/secrets: user-layer ExecPolicy rules outrank agent-layer rules; chained commands no longer propose trusted-prefix amendments; config and secrets writes are atomic (with fsync) on all platforms; empty provider chains no longer panic. - Core/state: paused jobs persist as paused across restarts; unarchive updates the in-memory cache; tool dispatch has a timeout; MCP notifications no longer receive responses; corrupted checkpoints surface errors instead of loading empty state; the session index compacts instead of growing unbounded; and recording thread-goal usage no longer self-deadlocks the state store. - Runtime compaction summaries are now persisted into `/v1` thread records so engine reloads and restarts preserve compacted context. Contributed by MXAntian (@MXAntian) (#4091). - The TUI leaves xterm alternate-scroll mode off when mouse capture is disabled, preserving native terminal text selection in light-theme/no-mouse-capture sessions. Contributed by Nightt (@nightt5879) (#4088, #4026). - The public `/api/github/feed` endpoint is now forced dynamic on Cloudflare so it returns live GitHub activity instead of a build-time empty feed. ### Changed - Tool-hang watchdog trimmed from 15 minutes to 10 (#1862); approval modal footer hints use a higher-contrast tier (#3380); status/mode copy is disclosed once across header, footer, cards, and sidebar instead of repeated per layer. - Removed the unused `tui::whale_routes` taxonomy module and its tests. Contributed by Darrell Thomas (@DarrellThomas) (#4041, #3852). ### Deprecated - YOLO mode: `--yolo`, `default_mode = "yolo"`, and the hotbar YOLO action now map to Act + Full Access permissions via a compatibility shim and show a one-shot deprecation notice; removal is planned for 0.9.0. ## [0.8.67] - 2026-07-06 ### Added - The model you select in `/model` is now the operator: fleet workers whose task spec and roster profile pin no model inherit the active session route instead of a hardcoded `auto` sentinel, matching the pinned operator row in `/fleet roster`. Task-level and profile model overrides still win, and route receipts record which source applied (`task.model`, `agent_profile.model`, or `run.model`). - Added the `/workflow` command (aliases `/workflows`, `/wf`) as the user opt-in to workflow orchestration. Bare `/workflow` orchestrates the current work — the model synthesizes the objective from the conversation context; `/workflow ` narrows the run; `/workflow status [run_id]` and `/workflow cancel ` relay typed run receipts without starting new runs. - Bare `/goal` with no active goal now declares a goal from the conversation context via `create_goal` instead of printing usage; with an active goal it remains the status readout, and explicit `/goal ` is unchanged. - Added the constitution-first setup wizard: a unified `/setup` shell with resume, back navigation, and skip-retry state; provider/model readiness cards with a custom-provider form and provider-picker detail layout; a runtime posture card with preset application and project-override warnings; a setup verification report; and transactional setup persistence with secret redaction and rollback (#3402, #3403, #3404, #3405, #3406, #3410, #3411). - Added a structured user-global constitution with a deterministic renderer, prompt-block injection, guided principle authoring with preview and preset save, and a `/constitution` manager command as the primary constitution management surface, with file state shown in setup and actions surfaced in diagnostics (#3793, #3806, #3811). - Added model-assisted constitution and fleet-profile drafting behind an explicit ratify gate, with untrusted-draft provenance recorded so model-authored text is never applied silently. Updating users keep their existing constitution unchanged, and a localized constitution checkpoint is required after update (#3794). - Added the Hotbar route editor v1 with route-switch slot actions and support for custom model routes, plus a configured-provider route manager for `/provider` and `/model` with a missing-auth handoff into provider key entry (#2066, #3830, #3831). - Added auto-discovery of `.codewhale/rules/` and `.claude/rules/` directories as project context, with a total byte-budget cap on the assembled rules block. Contributed by maple (@yekern). - Exposed `context_input_budget_for_route` from the engine so external integrations can reuse route budget math. Contributed by hexin (@h3c-hexin). - Added GUI config persistence to the runtime API. Contributed by @gaord. - Added a website localization matrix with a locale registry and drift checks. Harvested from #3763 by @idling11 (#3090). - Added `doctor` detection of half-applied setup state, and startup milestone tracing for boot-performance diagnosis. - Added a v0.8.67 computer-use dogfood prompt that covers the Cursor-terminal QA flow, headless gates, setup, sub-agent completion, Fleet, Workflow, model pricing, and release evidence collection. - Fleet: local worker memory usage is now reported, including retained memory while a task is in Running status. Contributed by @cyq1017 (#3901). - Website: community hub, constitution thesis page and constitution-centered homepage, models page generated from the provider registry, docs dark mode and full SEO metadata/sitemap coverage, terminal player for real constitution traces, and a live star badge and version. - Added Meituan LongCat as a first-class OpenAI-compatible provider (`longcat`, with `long-cat`, `meituan-longcat`, and `meituan` aliases), `LONGCAT_API_KEY` discovery, the `LongCat-2.0` default model, provider picker wiring, model completions, provider docs, and web provider facts. - Fleet: added per-provider setup cards (Persistence, Constitution, Hotbar, Tools/MCP, Remote Runtime) with a unified setup catalog and provider-specific credential links. Provider setup progress is persisted transactionally with rollback guards, Codex OAuth is kept out of provider key storage, and a headless QA contract verifies setup readiness across providers. - Fleet: added Fleet starter profiles with role-aware loadouts (scout→Fast, manager→Inherit, etc.), `/fleet setup` profile-authoring wizard, Fleet effective-permission recording, and route intent-source tracking. - Fleet: added 'operator' as a built-in Fleet roster member — the preferred helm Fleet slot for workflow coordination. Operator plans, routes, reviews outputs, and calls other Fleet slots as needed. This is a roster role, not a separate app mode. The full Operation/Operate-mode architecture is deferred to 0.9.0. - Workflow: declarative workflows now run through the production driver, the workflow tool is wired to sub-agent dispatch, public Workflow surfaces are renamed, and typed workflow-run and status receipts are emitted for debugging and verification. - Added provider-agnostic Fleet rosters and loadouts: provider-specific subagent limits, launch concurrency, and admission caps are derived from config without hardcoding any single provider. - Added Workflow runtime foundations: the internal JS authoring/runtime crates compile and replay example workflows. 0.8.67 ships the `/workflow` opt-in, production-driver dispatch path, sub-agent task handoff, and typed run/status receipts; richer authoring UX and the full TUI run view remain tracked for v0.8.68 (#2974, #4038). ### Changed - Clarified the Fleet coordination hierarchy and made roles carry real doctrine: the **operator** (the session's `/model` selection) runs the operation and assigns managers to workflows; a **manager** is the middle manager of exactly one workflow. The built-in **reviewer** is now explicitly adversarial (assume the change is broken, try to refute it), and the review sub-agent intro adopts the same framing. Built-in `manager`/`operator`/ `reviewer` roster members now ship role `instructions` that flow into worker prompts on both the Fleet task-spec and agent/workflow `profile:` spawn paths; custom profiles override them via the same `instructions` field. - Removed the decorative Fleet vocabulary that never routed differently: the `tool-heavy` slot and the `strong`/`balanced`/`deep-reasoning`/`code`/ `review`/`tool-heavy` loadout tiers. `inherit` (the operator's route) and `fast` (the provider's faster class) remain; retired names in existing configs keep parsing (as custom labels) with identical auto routing, and the `/fleet setup` model-class step now offers only the real choices. - Raised the default subagent concurrency for high-throughput fanout: `max_subagents` default 20 → 64 (config ceiling 128) and the queued+running admission cap 200 → 1024. Users on metered plans who want the old behavior can set `max_subagents = 20` in config.toml. - Renamed the internal `whaleflow` subsystem to `workflow` across the workspace: the `codewhale-whaleflow`/`codewhale-whaleflow-js` crates become `codewhale-workflow`/`codewhale-workflow-js`, Rust identifiers and JS bridge symbols are renamed, the `CODEWHALE_WHALEFLOW_JS_*` environment variables become `CODEWHALE_WORKFLOW_JS_*`, and the authoring/RFC docs move to `WORKFLOW_AUTHORING.md` and `WORKFLOW_EXTERNAL_MEMORY.md`. Historical changelog and retro-ledger entries keep the old name as a record. - Documented the Homebrew rollout strategy and added a distribution-channel check to the release checklist. Harvested from #3760 by @idling11 (#3489). - Paused Linux RISC-V prebuilt release and nightly artifacts because `rquickjs-sys` 0.12.0 does not ship `riscv64gc-unknown-linux-gnu` bindings; installers, docs, and update paths now treat RISC-V as unsupported until upstream bindings or a bindgen-enabled build lands. - Made the approval prompt calm, compact, and honest, and centered the first-run follow-up on the constitution; first-run onboarding now hands off into the setup wizard, and the language picker offers every shipped locale (#3929). - Startup performance: boot janitors and store scans no longer block the first frame, `@mention` completion no longer re-walks the workspace per keystroke, and idle offline-queue clones and duplicate tool-output hashing were eliminated. - Clarified the misleading "Ctrl+B backgrounds this command" shell wording (#3859) and the hotbar help shortcuts. Docs contribution by Chanhyo Jung (@roian6). - Documented the enforced repo-law invariants, the constitution flow, and the `/fleet setup` profile-authoring wizard; aligned `permissions.toml` action docs. Docs contribution by @greyfreedom. - Bumped web dependencies: wrangler 4.103.0 → 4.107.0, mermaid 11.15.0 → 11.16.0, vitest 4.1.8 → 4.1.9 (@dependabot). - Backfilled v0.8.67 regression coverage across sub-agent completion, budget exhaustion, delegate ordering, provider onboarding, setup scroll, model catalog pricing, Fleet routing, and Workflow gates (#4076). - Split the large TUI debug command group and palette/theme internals into smaller modules without changing user-visible behavior (#4078, #4081). ### Fixed - Fixed the goal sidebar elapsed timer so completed and blocked goals freeze their "completed in {elapsed}" readout instead of ticking forever. Goal state now records a `finished_at` instant that both sidebar render paths and the engine snapshot clamp elapsed against; `/goal resume` clears the freeze and the timer ticks again. - Fixed paused goals silently un-freezing their sidebar timer: usage keeps accruing while paused, and the next goal snapshot used to clear the frozen instant. Paused goals now stay frozen until an explicit resume. - Fixed durable `/goal` progress accounting so usage and continuation updates release the shared SQLite connection before re-reading the updated goal, unblocking resumed goal loops and full workspace release tests. - Fixed a scheduled-automation race where deleting an automation while its run was being enqueued left the already-created task running untracked; the run record is now persisted unconditionally. - Removed `panic = "abort"` from the release profile: it disabled unwinding and broke the panic supervision that keeps one failing tool call from taking down the whole session. The `lto`/`strip`/`codegen-units` size and speed tuning is unchanged. - Fixed session save/load to persist and restore the active model provider across restarts. Previously sessions created under one provider (e.g. DeepSeek) would silently load under a different active provider. Provider, subagent limits, fallback chain, context window, and reasoning effort are now restored from saved session metadata, with `"deepseek"` as the default for legacy sessions. - Raised the streamed model-response idle timeout and matched the TUI stall watchdog to the configured stream budget so long reasoning pauses are not recovered as stalled turns (#2487, #3998). - Fixed Codex OAuth/sub-agent release diagnostics so `auth list` reports an active Codex OAuth file, Responses API child requests encode inherited tool names safely, rate-limited child requests checkpoint as resumable provider interruptions, and failure records surface the real Responses API error (#3884). - Fixed fresh launch/setup testing with an explicit `CODEWHALE_HOME` so config, settings, theme prefs, and doctor legacy-state diagnostics do not inherit unrelated ambient `~/.deepseek` files (#4001, #4002). - Sub-agent state now persists to `.codewhale/` instead of the lingering pre-rebrand `.deepseek/` path (#3864). Contributed by Stime (@yekern). - `/plugin enable|disable` now persists across restarts (#3918), and the plugin command is hidden from the root slash menu and kept canonical after the scanner merge. Contributed by Nightt (@nightt5879). - `/config ask-rules` now shows ask rule actions with improved diagnostics, with file-rule action precedence under test. Contributed by @greyfreedom. - Fleet/sub-agents: enforced an absolute recursion-depth ceiling and widened task-id entropy, gave each atomic state write a unique temp path, kept sub-agent tool catalogs in parent parity (#3836), and made the Agents sidebar reconcile sub-agent completion and cancellation live (#3837). - Fixed apply_patch mangling newlines, defaulted fuzz to 3, and made writes atomic; fixed compaction to preserve pins on emergency compaction, harden the summary fallback, and count image tokens; corrected backtrack boundary, checkpoint clear ordering, prune guard, and durable rename. - Fixed the SSE client to flush the final frame, join multi-line data fields, and stop corrupting multibyte UTF-8 split across network reads. - Kept review-only turns read-only, aliased `auto` mode to the agent policy, showed the mode-derived safety policy in status (contributed by @cyq1017), and stopped the durable-review floor from holding routine YOLO work (#3883). - Fixed self-update to prefer exact binary release assets. Contributed by @LI-Jialu. - UI polish: stopped constitution and fleet-profile model drafts from freezing the event loop, scoped the context-menu backdrop to the popup rect, stacked model-picker panes on narrow modals, unified display-width helpers on one contract (#3924), removed misleading success toasts, issue-number leaks, and dead-end empty states, and repaired the onboarding trust and api-key keys. - Fixed the onboarding Trust step so plain Enter no longer silently grants workspace trust; users must choose the explicit trust or exit keys. - Fixed same-root skill-name collisions being silently shadowed; duplicate normalized skill names now warn while keeping discovery deterministic (#3919). - Normalized discovered skill names, removed unenforced trust copy, and surfaced the gated constitution override in prompts. - Fixed a parallel `subagent::` suite flake where one test's process-wide `Retry-After` pause could strand unrelated budget-capped workers for the full stale window; requests now re-poll the global pause in bounded slices and the rate-limit test clears the window on drop. - Sub-agent and Fleet reliability now fail empty, step-limited, and budget-exhausted children with explicit diagnostics instead of silent `Completed (no output)` success; budget exhaustion preserves partial output, `worktree: true` discovers one-level nested repos from harness directories, and completion-before-start delegate events recover into named rows instead of ellipsis-only identities (#4050, #4051, #4052, #4053). - Goal-mode writing and research tasks can complete with `verification.status = "not_applicable"` without triggering continuation loops (#4054). - First-run onboarding routes API keys through the selected provider, setup wizard bodies scroll with PageUp/PageDown, shipped locale packs are back to `en.json` parity with zh-Hant explicitly partial, stable feature flags stay out of Experimental, and model/provider rows include current LongCat and sourced-pricing hints (#4056, #4057, #4058, #4062, #4063). - Running tool rows animate while a lone foreground tool is active, and workflow receipts render run/status/failure cards instead of one-line or null-success output (#4059). - Model-facing turn metadata now includes a compact git workspace snapshot and escalates context pressure at the same thresholds as the TUI, helping agents narrow scope or compact before truncation (#4071, #4073). - Successful child sub-agent completions inline the child's `EVIDENCE` block before the completion sentinel, so parents can cite child findings without re-running tools (#4072). - Deferred tools hydrate and execute in the same batch when the original arguments are valid, and `[tools].always_load` now keeps configured MCP tools active instead of forcing the first-call retry. Thanks @SparkofSpike for the hot-path MCP report (#4074, #4027). - New commit-range co-author checks reject bot/tool trailers on newly pushed commits; historical release-range cleanup remains a separate maintenance concern (#4075). - Fixed fuzzy `edit_file` matching so matches that begin with multibyte UTF-8 characters, including CJK text, advance on character boundaries instead of panicking. Contributed by Nightt (@nightt5879), reported by Taixin Guo (@taixinguo) (#3971, #4045). - Fixed Unix dispatcher/TUI output under early-closing pipes such as `codewhale doctor | head` by restoring the default `SIGPIPE` handler before printing and propagating signal exits quietly. Contributed by @aznikline, reported by @BrathonBai (#4030, #4043). - Suppressed dead_code warnings in the unused plugin registry module and fixed formatting across the command-group files. Contributed by Paulo Aboim Pinto (@aboimpinto). - Pointed the website Community nav link at the community hub. ### Security - MCP client hardening: closed an SSE-endpoint SSRF, bounded the HTTP response body via Content-Length instead of a streaming read, bounded stdio line reads to prevent OOM denial of service, fixed a dead timeout, and removed an unbounded buffer. - Made execpolicy deny/trust rules segment-aware, closing a command-chaining bypass. - Closed repo-law and safety-floor bypasses found by adversarial review: protected invariants are now enforced as mechanism, the destroyer gap in the safety floor is closed, a catalog-present tool with no execution path now fails closed, `web_run` open/click is classified as destructive, and the allow-list gained wildcard and case handling. - Refused symlinked rules directories to prevent workspace escape via discovered rules. Contributed by maple (@yekern). - Bounded Fleet sub-agent worker output so fanout cannot exhaust TUI memory (#3882), and preserved event headroom for progress. Contributed in part by @cyq1017. - Added an untrusted constitution-draft gate with authoring provenance so model-drafted constitutions require explicit human ratification. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - Removed unused model-registry helpers. Harvested from #3872 by @cyq1017. - Removed unused request-tuning metadata. Harvested from #3871 by @cyq1017. - Removed dead fleet task helpers (#3894 by @cyq1017), the unused approval-cache container (#3845) and localization QA metadata (both by @nightt5879), the dormant tab collaboration subsystem (#3838), the legacy flash auto-router (#3839), the stale project_doc loader (#3840), ignored mock LLM placeholders (#3841), dead model-catalog helpers (#3842), the unused execpolicy amend module, and dead MCP/client retry helpers. - Retired the deprecated `WHALE.md` context fallback (#3798). ## [0.8.66] - 2026-06-29 ### Added - Added `codewhale doctor` / `codewhale doctor --json` legacy-state diagnostics that compare known `~/.deepseek` state paths with their `~/.codewhale` counterparts and flag unmigrated or dual-root data (#3727). - Added Sakana AI Fugu as a first-class OpenAI-compatible provider with `sakana`/`fugu` aliases, `FUGU_API_KEY` / `SAKANA_API_KEY` discovery, provider-picker wiring, model completions, and provider docs. Harvested from #3748 by @lerugray. - Added WhaleFlow-to-Fleet launch-shape validation: the default Fleet workflow contract allows up to 100 total agents and 5 recursive rings, requires bounded loops/expands before launch, and preserves per-slot model selection. - Added a read-only `/config ask-rules` view for the resolved `permissions.toml` path, file status, rule count, and configured tool/command/path ask rules. Merged from #3569 by @greyfreedom. - Added provider-level `context_window` overrides so OpenAI-compatible gateways and self-hosted providers can budget against their real model context window (#3545). - Added the native `codew` shim to release archives, Windows installer inputs, local release-asset preparation, and checksum verification so manual installs receive the same short command that Cargo installs build. - Added OpenModel as a first-class Anthropic Messages provider, with config, CLI, provider picker, docs, and registry coverage. Harvested from #3585 by @noaft. - Added WeCom Bridge deployment and security documentation, with shipped runtime/bridge commands and approval-timeout environment guidance. Harvested from #3640 by @pkeging. - Added a token/cache/cost `scorecard` command for offline release gating, baseline regression checks, and per-turn cost visibility (#3388). Stream-JSON exec metadata now also reports conservative `input_analysis` and `visible_final_answer_chars`, so benchmark harnesses can measure transcript growth and final-answer bloat without guessing (#2956, #2957). - Added a release evidence ledger for v0.8.66 and opened the external ACP registry submission for CodeWhale after validating the published `codewhale@0.8.65` ACP auth handshake against the upstream registry checker (#3192). - Added a typed `[verifier]` config table for the verifier-preview lane, with `enabled` and the shipped `verdict_policy = "hunt"` mapping documented and validated (#2093). - Added Hotbar `Alt+1`–`Alt+8` quick-slot switching with decision-card key disambiguation, plus an introductory card that explains and can dismiss the Hotbar (#3796, #3788). - Release/docs hygiene: guarded public install/version snippets and the npm `codewhaleBinaryVersion` pointer against drift, made `check-docs`/`check-facts` fail on stale snippets or unmapped providers, and stopped `sync-changelog` from dropping a release when only `[Unreleased]` exists (#3767, #3768, #3769, #3770, #3771, #3772). ### Changed - Deferred Auto mode from the user-facing mode picker, cycle, hotbar, `/mode` command, and runtime-thread mode overrides until it has a distinct prompt and auto-review behavior; existing `auto` mode text now folds back to Agent instead of selecting a hollow mode, and approval modal copy no longer implies the current mode is YOLO (#3730, #3733). - Clarified the Fleet setup surface and docs so Fleet is treated as the durable sub-agent configuration layer while WhaleFlow is the agent-authored orchestration plan that selects and monitors Fleet slots. - Slimmed the default Constitution prompt while keeping its required structural anchors under regression coverage, reducing the static prompt footprint for cache-sensitive turns (#2953). - Made the approval prompt inline and bottom-anchored instead of a full-screen takeover, so context and controls stay visible while a tool awaits a decision (#3799). - The Hotbar is now hidden by default until explicit setup opt-in (#3807); the interactive Agent shell also defaults to approval-gated on with a shared baseline (#3756). - Mode authority now resolves approval prompts through a single authority source instead of per-surface checks (#3795). ### Fixed - Surfaced legacy state relocation with a user-visible migration notice whenever `~/.deepseek/` is moved or copied into `~/.codewhale/`, so upgraded users know their data was preserved and where the canonical state now lives (#3726). - Restored legacy `.deepseek/sessions` visibility for upgraded installs where an empty `~/.codewhale/sessions` directory already existed, by copying missing legacy session entries into the primary CodeWhale session store without overwriting newer data (#3724). - Calmed approval risk classification for read-only shell commands such as `codewhale --version`, `codewhale --help`, and `git status --porcelain` so the modal no longer labels proven read-only shell as destructive (#3730). - Added provider/model route columns to `/cache` turn telemetry so DeepSeek cache-hit regressions can be correlated with Auto route changes (#3738). - Fixed runtime API approval handling so workspace trust no longer auto-resolves ordinary tool approvals; trust now only participates in full-access retry decisions while YOLO/auto-approve remains the approval bypass (#3736). - Fixed modal surfaces so the shared view stack paints an opaque backdrop before any overlay, while Plan/request-input popup interiors stay opaque and the Plan confirmation footer keeps action choices visible on narrow terminals (#3732). - Added a turn-loop Plan-mode guard for file-writing tools and write-capable MCP tools so Plan's "no writes" promise is enforced before approval or execution, not only by the sandbox/catalog layer (#3734). - Preserved the durable review safety floor for publish-like shell actions in YOLO mode, so `cargo publish`, `npm publish`, and tag/release pushes force approval instead of silently auto-approving (#3735). - Fixed Ctrl+O external-editor freezes where CodeWhale's terminal input pump could keep reading keys while Vim/editor owned the terminal, especially in Windows mintty/cygwin shells. Thanks @buko for the precise repro (#3657). - Hardened the OHOS dependency drift check against transient Cargo registry EOFs by retrying the dependency graph probe before failing CI. - Updated the `/links` provider fallback to the current CodeWhale docs URL and added a Baidu Qianfan docs link. Harvested from #3621 by @noaft. - Hardened `CODEWHALE_TOOL_SURFACE=shell-only` for benchmark/exec runs: the shell-only surface hides native tools from the model-visible catalog, and unknown `CODEWHALE_TOOL_SURFACE` values now warn instead of silently falling back to the full tool surface (#2954). - Sub-agent fanout and lock hot paths: preserved event-channel headroom for progress events (#3783, thanks @cyq1017), let independent sub-agent starts join a single parallel dispatch batch instead of serializing (#3801), rendered the sub-agent sidebar/ListSubAgents from a read-only snapshot with bounded cleanup (#3803), used nonblocking best-effort sends for ListSubAgents refresh while still awaiting critical events (#3802), moved sub-agent state persistence disk I/O off the manager write lock (#3805), and used `try_lock` for shell-manager refresh in async UI paths (#3804). - Provenance: runtime continuations and `SubAgentHandoff` now inherit standing YOLO authority, while `MemoryRecall`, `ImportedTranscript`, and `AssistantGenerated` inputs remain guarded (#3817). - Approval honesty: labeled session-scoped approvals accurately instead of "always", and surfaced approval decisions in tool results (#3766). ## [0.8.65] - 2026-06-24 ### Added - **Provider/model/route resolution (EPIC #2608).** Canonical provider, model, offering, and route types with a single `RouteResolver` that produces a resolved `ReadyRouteCandidate` (endpoint, wire protocol, model id, context limit, price) for every switch (#3458, #3084, #3384). The executing client is now constructed from the resolved candidate rather than re-derived from config (#3384). A committed, network-free Models.dev-shaped catalog gives models real context windows and pricing, with a secret-free live cache (#3497, #3498, #3385). Offering pricing with provenance is projected onto candidates (#3501, #3085), and route limits feed a route-aware context-budget service (#3508, #3523, #3086). - **Fleet execution substrate (EPIC #3154).** Fleet profile types and config (#3469), durable manager resume, workspace agent-profile loading resolved into the worker runtime (#3367), loadout intent carried in task specs (#3512), and receipts that persist the resolved route for inspection (#3154, #3166). Worker status is folded into the unified `/fleet` surface and exposed through the Runtime API. - **Provider surfaces.** A `/provider` readiness dashboard with reasoning readiness, an experimental/supported maturity marker, and an "open models for this provider" action (#3083, #2984, #3485); cross-provider `/model` search with scroll and provider type-ahead (#3484, #3075); inline `` reasoning-stream routing with per-provider overrides (#3222); usage telemetry normalized into canonical token classes including Responses cache-miss and reasoning tokens (#2961, #3509); and remote MCP OAuth login with bearer/header auth precedence (#3527). - **More providers and routes.** User-defined OpenAI-compatible custom providers via `[providers.]` (#1519); a DeepSeek Anthropic-compatible route (#2963, #3449); a Qianfan route (#3425); Zhipu folded into Z.ai with equal-treatment model normalization (#3539); DashScope/Together fixtures. - **Localized mode picker and composer indicators.** The `/mode` picker prompt, mode names, and hints, plus the composer's Vim mode indicator, now render in all seven shipped locales (model-facing mode labels stay English). Harvested from #2239 by @gordonlu. - **Website and automation.** A runtime/integrations page, provenance and mirror-trust copy, a fact-drift CI gate, a published install script, and a weekly community digest archive on codewhale.net (#3419, #3421, #3415, #3482, #3420); per-automation mode/shell/trust/approval settings (#3467). - **Model reference browser.** A read-only `/modeldb` command (aliases `model-reference`, `modelref`) opens a pager over the bundled catalog — every model's factual context window, max output, modality, and price, grouped by provider/kind. Labels only: it never selects, routes, or tiers a model (#3205, #2300). - **Transcript presets.** A `/config preset [--save]` mechanism with a first `calm` preset — calm mode, calm tool collapse, comfortable spacing, and low motion — presentation-only and evidence-preserving (#3478). - **Model capability profiles.** A typed `model_profile` module separates intrinsic model facts from resolved provider-route capability, so compact routes defer heavier nonessential tools while standard/full routes keep the eager tool surface (#3451, #3365). - **Live provider catalog refresh.** A secret-free `/models` live-fetch layer (401/403/404/429 mapped to typed outcomes) feeds the catalog cache; the API key authorizes the request but is never persisted into the delta or cache (#3385). ### Changed - **Config modularization (#3311).** `ProviderKind` (#3505), harness posture (#3507), and provider default seeds (#3503) moved into dedicated modules, and the `config.rs` monolith split into clean leaf modules (paths, search, model/base-URL constants, sub-agent limits) behind a `pub use` facade. `AppMode` helpers were centralized (#3510), and mode-vs-permission policy is now derived through a single `base_policy_for_mode` resolver instead of scattered mutation (#3386, advisory review-intent behavior preserved). - **Leaner tool surface.** Dropped `task_shell_*` from the active set and folded `tool_search_*` (#3463); ablated the in-turn loop_guard and encoded reasoning dispositions (#3462); added the Orchestration disposition to the constitution. - **Routing.** Provider/model switches and the capability-aware fallback chain resolve through `RouteResolver`; reasoning effort is normalized for the *resolved* provider; the fallback chain now skips providers that lack auth (#2574); and context window and memory-pressure come from the resolved route (#3086). - **UX.** Approval modal gained a group divider and selected-row caret (#3515); picker scroll/type-ahead and selection contrast hardened (#3500); the README was rewritten as an architecture end-cap (#3087); and repo agent guidance was de-hardcoded to live truth. - **Fleet identity and defaults.** Fleet workers now enter with an explicit "summoned Fleet member" operating contract, setup/profile prompts keep the default model behavior as same-route inheritance, and generated worker instructions avoid leaking recursive topology that only the orchestrator needs. - **Legacy swarm cleanup.** Removed the obsolete `/swarm` core command/menu registration so `/fleet` is the product surface, while `/subagents` remains a compatibility shortcut to worker status. - **Running-state animation.** Tool cards and background-task rows now share one faster braille spinner cadence, so Bash/background work reads consistently alive across the transcript and sidebar. - **Restored contributor credit.** Threaded machine-readable credit (`docs/CONTRIBUTORS.md` + `.github/AUTHOR_MAP`) for earlier merged work that shipped without it, including the `/jobs cancel-all` action and the npm retry-timeout hint (#1538) by @jieshu666, and the community ACP adapter reference by @rockeverm3m. ### Fixed - **Release hygiene.** The strict `cargo clippy --workspace --all-targets --locked -- -D warnings` gate passes; `npm run build` no longer dirties the generated web facts; the site sets `metadataBase`; the community digest page parses each record independently and localizes its chrome; and `cargo audit` is clean with the starlark-transitive unmaintained advisories documented. - **Routing and mode correctness.** Ordinary prompt text is no longer interpreted as a mode switch (#3387, #3491); model candidates are scoped to the active provider; Together-owned DeepSeek routes are accepted (#3426); insecure `http://` custom endpoints raise an advisory warning (#1519); and the Fleet setup planner's role/model selection now drives the generated profile. - **Runtime stability.** MCP connection drops are explicit (#3524), HTTP API calls reuse a shared MCP pool (#3532), and per-agent sub-agent mailbox telemetry is throttled to cut UI lag (#3454). - **YOLO background-shell approvals.** A background shell command no longer pops an approval modal in YOLO mode. `classify_risk` marks all shell commands destructive, so the auto-review safety floor held every *background* shell for review, and the `ForcePrompt` site never checked `auto_approve` — only background commands surfaced it, since foreground shells take the `Interactive` origin and skip that branch. - **Bash approval modal fit.** The shell approval modal now labels Bash commands directly, avoids repeating command/workdir in the impact summary, wraps long commands, and switches to compact controls on short terminals so the decision keys stay visible. - **Custom-provider picker rows.** Concrete `[providers.]` entries now appear in the provider picker (id, endpoint, auth readiness, wire protocol, current model) instead of only the generic placeholder; auth readiness honors per-entry key/env/metadata/no-auth/loopback. - **Passive MCP tool discovery.** Runtime API-owned stdio MCP processes are no longer spawned from passive `/v1/apps/mcp/tools` requests; live discovery remains available through `?connect=true`. `doctor` now warns on relative-path stdio MCP commands without `cwd`. ## [0.8.64] - 2026-06-22 ### Added - **Seamless auto-compaction defaults.** Known large-context routes now keep automatic compaction on by default while carrying summaries forward through the stable prompt path, reducing surprise context loss without changing explicit opt-out behavior. - **Runtime web automation readiness.** Local app automation gains a loopback-only dev-server readiness primitive so agents can wait for TCP and optional HTTP health checks before browser verification. Harvested from #3376 by @cyq1017. - **Model and integration polish.** `/model pro` and `/model flash` shortcuts now resolve to the current DeepSeek V4 routes while preserving existing model IDs. Harvested from #3350 by @KUK4. The WeCom bridge landed with maintainer follow-up hardening for state permissions and chat-facing error reporting, from #3370 by @pkeging. ### Fixed - **Security and trust-boundary hardening.** Project-local config can no longer loosen user-owned shell or instruction-file policy, file edits now require a fresh read of the target file, git history inputs reject option-shaped or control-character revisions, interactive execution surfaces require approval, and local tool paths are narrowed through workspace/root validation. - **Runtime and diagnostics redaction.** Generated runtime/app-server tokens, raw session lineage identifiers, provider registry drift values, review receipt internals, and webhook URLs are no longer echoed into human-facing logs or diagnostics. - **Network and alert safety.** Provider TLS verification bypass requests now fail closed, fleet alert webhooks require HTTPS, fetch URL hostnames are resolved before requests, and runtime mobile auth no longer relies on token-bearing URLs. - **Path-state hardening.** Config sibling files, project MCP cwd values, runtime thread store files, sub-agent state, project-local state roots, and app-server sidecar config paths now resolve through checked roots before reads/writes. - **Release CI repair.** Nightly cross-target builds install Rust targets explicitly and retry transient cargo failures; auto-tag runs are serialized and treat an already-created remote tag as a no-op. Safe slices harvested from #3374 by @donglovejava. - **Provider wait and sidebar regressions.** Provider-wait footers suppress noisy countdowns until useful while keeping timeout warnings visible, harvested from #3375 by @idling11. The pinned sidebar can render at a narrower 64-column boundary, harvested from #3371 by @donglovejava. - **Delegated server cleanup.** Delegated `serve` / `app-server` children gain OS-level parent-death cleanup on supported platforms, completing the #3259 follow-up from #3378 and #3317 by @wuisabel-gif. - **ACP and sandbox correctness.** ACP sessions preserve multi-turn conversation history across prompt turns, harvested from #3372 by @xulongzhe. Worktree Git metadata writes are allowed through sandbox policy without broad trust-mode escalation, from #3356 by @cyq1017 and the #3355 report by @linletian. ### Changed - **Community and dependency harvests.** The release train carries focused community-credit slices from #3379 by @greyfreedom, #3348 by @nightt5879, #3346 by @hongqitai, #3345/#3333 by @cyq1017, and Dependabot updates for `windows`, `toml`, `tokio`, `lru`, `similar`, and web tooling security locks. - **Public release surface cleanup.** Benchmark-specific materials were kept out of the public release repo; benchmark source fragments belong in the separate `codewhale-bench` lane. ## [0.8.63] - 2026-06-19 ### Added - **Sub-agent fanout safeguards (#3318, #3319).** High-fanout Workflow runs can now queue and drain more agents than the instantaneous concurrency cap by default, with `[subagents] max_admitted` available to tune that bounded admission population. Distinct `agent` calls are no longer capped by the per-turn loop guard before runtime launch concurrency and provider rate-limit backoff can apply. `[subagents] token_budget` applies a shared aggregate token ceiling to a root `agent` run and its descendants. - **Per-worker sub-agent token enforcement (#3321).** A `token_budget` / `max_tokens` set on an individual `agent` call now bounds that single worker mid-run: once its accumulated model tokens exceed the cap it stops cleanly with a `budget_exhausted` status instead of running to `max_steps`. This complements the scope-level admission gate (#3319) — the per-worker cap stops one runaway worker, the scope cap bounds total fan-out — without double-counting. Harvested from #3321 by @donglovejava. - **Provider-specific sub-agent fanout config.** `[subagents.providers.]` profiles now override `enabled`, `max_concurrent`, `max_admitted`, `launch_concurrency`, `max_depth`, token budget, API timeout, and heartbeat timeout for the active provider. Use broad direct-API profiles such as `[subagents.providers.deepseek]` and tighter subscription profiles such as `[subagents.providers.glm]`; `/config subagents status` shows both global and active-provider resolved values. - **Sub-agent control and isolation.** The single `agent` tool now exposes status, peek, and cancel actions for running children, and accepts `worktree: true` to create an isolated git worktree/branch for parallel edit lanes instead of requiring callers to hand-roll a `cwd`. ### Fixed - **Mode and tool catalog correctness.** Core action tools remain discoverable in the model-facing catalog/tool search, and a consistency self-check flags registered handlers that drift out of the advertised catalog. Review-looking prompts in explicit Agent/YOLO mode now keep the requested mode and tools, with only an advisory review hint. - **Sub-agent orchestration recovery.** Child agents now retry transient provider header/SSE timeouts before failing, and parent runs synthesize missed child completions from terminal child state so orchestration cannot hang on a lost completion event. - **DeepSeek thinking tool calls.** DeepSeek chat-completions requests now omit explicit `tool_choice` whenever reasoning/thinking is enabled, avoiding provider rejections while leaving no-thinking routes unchanged. - **Task sidebar shortcuts and attribution.** Ctrl-K stays palette/emacs-kill, while Ctrl-X is scoped to Tasks-sidebar background shell cancellation. Shell jobs launched by sub-agents now render with their child-agent owner in the Tasks sidebar and transcript. - **Long-turn recovery and context economy.** Repeated read-only search loop blocks now return guidance instead of fatal tool failures, Python build failures that are missing `setuptools` include an install/retry hint, long foreground shell timeouts steer models toward background execution, and noisy shell/test/web outputs are compacted earlier for large-context routes. - **Config display redaction.** `codew config get/list` now recursively masks token-, secret-, password-, credential-, and authorization-like keys inside unknown `extras` tables and redacts sensitive HTTP header values before printing config output. - **Queued follow-up hints and force-steer keys.** The pending-input preview now advertises `Ctrl+S send now` whenever queued follow-ups exist, and Ctrl/Cmd+Enter force-steering also accepts the common Ctrl+J terminal encoding while a turn is running. - **Sidebar default visibility restored (#3328).** New and upgraded sessions now use a pinned composed sidebar by default when the terminal is wide enough, so live Agents and Tasks surface without opting back into idle auto-collapse. Older settings files that captured the v0.8.62 auto-collapse default now migrate to `pinned` unless `/sidebar auto --save` records an explicit opt-in. `/sidebar` now reports when width or auto-collapse suppresses rendering instead of saying the sidebar is visible. Reported by @dxfq. - **JavaScript execution proxy env handling (#3273, #3331).** `js_execution` now enables Node's environment-proxy mode when proxy variables are present, mirrors lowercase proxy variables for the child process, and backfills `HTTP_PROXY` / `HTTPS_PROXY` from `ALL_PROXY`. Reported by @lordwedggie and harvested from #3331 by @cyq1017. - **Legacy app-server non-loopback auth hardening (#3258).** Bare `codewhale app-server --host 0.0.0.0` now fails fast unless an explicit `--auth-token` or `CODEWHALE_APP_SERVER_TOKEN` is supplied, keeping generated one-time `cwapp_*` tokens loopback-only. - **Legacy `.deepseek` state write-path migration (#3240).** State subdirectories (`sessions`, `slop_ledger`, `trophies`, `catalog`) are now always written under `~/.codewhale/`, and the first write of a subdir relocates any pre-existing `~/.deepseek/` contents into the primary location so the legacy tree stops growing while old data is preserved. The read resolver still finds legacy data for backfill until each subdir migrates. Reported by @Final527; onboarding marker slice from #3302 by @nightt5879. - **State subdir validation on Windows (#3240).** State path hardening now rejects rooted/prefixed subdir strings such as `/etc` before resolving or migrating state directories, keeping the `.codewhale` write resolver inside its state root across platforms. ## [0.8.62] - 2026-06-17 ### Changed - **GLM-5.2 is now the default direct Z.AI model.** `DEFAULT_ZAI_MODEL` resolves to `GLM-5.2` in both `codewhale-tui` and `codewhale-config`; the `glm-5.1` alias still resolves to `GLM-5.1` (the defaulting was decoupled from the alias arm so it no longer tracks the default). Docs and `config.example.toml` no longer describe GLM-5.2 as an opt-in preview. - **GLM-5-Turbo registered as a real model** and wired as the faster/explore sub-agent sibling for the GLM family: a `GLM-5.2` parent routes faster/explore children to `GLM-5-Turbo` (direct Z.ai) and `z-ai/glm-5-turbo` (OpenRouter), instead of down to GLM-5.1. GLM-5.1 and GLM-5-Turbo themselves have no cheaper tier and keep children on the parent. - **`type: "explore"` sub-agents default to `model_strength: "faster"`.** Bounded read-only lookup/search/status work now uses the cheaper same-family sibling automatically, unless an explicit `model` or `model_strength: "same"` is supplied. Non-explore roles keep the conservative `same` default. - **GPT-5.5 / OpenAI Codex faster route stays on GPT-5.5** with reasoning resolved to `low` (the Codex Responses API has no true `off`, so the resolved effort is now honest `low` rather than `off` silently rewritten). No DeepSeek/GLM fallback is fabricated when no cheaper same-provider sibling exists. DeepSeek Pro→Flash routing and its no-thinking faster lane are unchanged. - **Base prompt / delegate skill guidance** updated to encourage parallel read-only exploration (2-4 `type: "explore"` sub-agents) for broad repo, version, branch, release, and API-surface investigations, while keeping architecture, integration, and final verification in the parent. The delegate skill examples now use provider-neutral `model_strength` instead of hardcoded DeepSeek model ids. - **Agent synthesis guardrails.** The base constitution now frames tools around sufficient evidence rather than open-ended persistence: extra reads, searches, and delegation must target a missing fact, and agents should answer with limits instead of broadening searches indefinitely. The runtime loop guard now blocks duplicate read-only/delegated calls earlier and caps repeated broad lookup/delegation loops in a single turn with a synthesis-forcing tool error. Guard metadata distinguishes exact duplicates (`identical_tool_call`) from no-progress loops (`no_progress_tool_loop`). - **Sub-agent handoff and visibility.** Direct sub-agent completions are drained before the next parent model request, so finished children can wake the main model promptly instead of waiting for an empty-tool-use branch or idle engine path. Nested sub-agents now report completions to their immediate parent inbox; the main model still receives only direct-child completions, avoiding grandchild floods while preserving nested evidence flow. Sub-agent output guidance now requires child-agent provenance when a sub-agent relies on a child report: cite the child `agent_id` and the child's EVIDENCE line(s), and do not present child findings as directly verified facts. The sidebar orders sub-agents as a parent/child tree and annotates nested rows with parent and depth information in hover text. - **Sub-agent summary provenance (#2652).** A sub-agent's free-text result is now explicitly treated as an unverified self-report rather than confirmed evidence. The completion sentinel carries `summary_kind: complete | truncated` so the parent model can branch on whether it saw the full report or a clipped excerpt. Short summaries (≤ 12,000 chars) get a soft "re-verify material claims" suffix; longer ones are head+tail truncated with an honest marker stating the elided middle is not retrievable via `retrieve_tool_result`. Every summary therefore carries exactly one boundary marker, never both. - **Provider metadata centralization.** Provider env vars, config keys, aliases, and auth hints are now resolved through the shared `ProviderMetadata` registry across `codewhale-config`, `codewhale-tui`, and `codewhale-cli`, reducing drift between the provider picker, `codewhale auth`, `doctor --json`, and setup hints. ### Added - **Agent clarification questions (#3102).** Agents now have a first-class `request_user_input` tool to ask the user structured clarifying questions through a modal UI surface instead of only emitting a chat message and hoping the user notices. Mirrors the approval/secret-request flow the harness already used for permissions. The tool accepts 1-3 questions, each with a header, an id, 2-4 selectable options (label + description), and `allow_free_text` / `multi_select` flags (both default to `false` for back-compat). Input is validated up front with actionable errors. Wired across all layers: the `request_user_input` tool, engine handling (`turn_loop` → `approval`), an interactive TUI modal (`UserInputView`) with full keyboard navigation, and the runtime protocol (`EventFrame::UserInputRequest` + `AppRequest::SubmitUserInput`) so headless / app-server clients can answer programmatically. Parity tests cover the wire round-trip and the omitted-flags default. - **Transcript hyperlinks — out-of-band OSC 8 (#3029).** Clickable file / file:line / URL links now reach the terminal through a column-drift-safe path. Link payloads are embedded in-band by the markdown renderer, then extracted out of the ratatui buffer cells and re-emitted out-of-band by `ColorCompatBackend` — so the `ESC` bytes never occupy display columns or corrupt selection. Supporting terminals get live hyperlinks; others see the label text unchanged. Clipboard/selection extraction strips residual codes as defense-in-depth. - **CodeWhale-only skill discovery gate (#3296).** New `[skills].scan_codewhale_only = true` limits session-time skill discovery to CodeWhale-owned roots (`/.codewhale/skills`, `~/.codewhale/skills`, and any explicit `skills_dir`) while ignoring cross-tool directories such as `.claude/skills`, `.opencode/skills`, `.cursor/skills`, and `~/.agents/skills`. The default remains the broad compatibility scan. - **Permission/ask runtime rules (#3295).** Sibling `permissions.toml` ask-only rules are now loaded by the TUI engine and applied to `exec_shell` before Auto/session approval shortcuts. Matching ask rules force an approval prompt in otherwise auto-approved flows and are rejected under `approval_mode = "never"`. - **Runtime API no-auth documentation.** `docs/RUNTIME_API.md` now documents `codewhale app-server --insecure-no-auth` for loopback-only testing and warns against combining it with `--mobile` on `0.0.0.0`. ### Fixed - **TUI polish.** The empty-startup welcome block is centered by the actual rendered text width, fixing the off-center layout left over from the old sidebar-oriented welcome composition. Streaming HTTP body read errors now explain whether CodeWhale can retry before output, or is surfacing a warning after partial output to avoid replaying and duplicating streamed text. - **Config comment preservation.** Rewriting `config.toml`, `settings.toml`, or `tui.toml` now merges user comments and formatting back into the serialized document; if comment merge fails, the write falls back to plain serialized output rather than failing. - **Snapshot gate respected for per-tool snapshots (#3292).** Per-tool snapshots now check `[snapshots].enabled` before writing, matching the existing session-level gate. - **Poppler `pdftotext` detection (#1667).** The dependency resolver now probes `pdftotext -v` instead of `--version`, because Poppler treats `--version` as an input filename. Fixes detection on systems where only Poppler is installed. - **Plan confirmation checklist visibility.** The Plan-mode confirmation modal now shows the active checklist under the plan details, so users can review the concrete `checklist_write` work breakdown before accepting or revising a plan. ### Retroactive credits A credit-reconciliation pass found shipped community fixes that were never recorded in this changelog. Crediting them now, with the version they shipped in: - Global `~/.deepseek/AGENTS.md` fallback loading — thanks @manaskarra (fix) and @xfy6238 (report) (#1157, v0.8.27) - CRLF SSE event parsing for MCP — thanks @reidliu41 (fix) and @djairjr (report) (#1309, v0.8.29) - Reduce-motion default on VTE/flicker terminals — thanks @Geallier (report) (#1470, v0.8.34) - `portable-pty` 0.9 upgrade for LoongArch64 — thanks @quentin-lian (fix) and @k0tran (report) (#1531, #1992, v0.8.46) - `DEEPSEEK_ALLOW_INSECURE_HTTP` guard for LAN vLLM — thanks @F1LT3R (report) (#1656, v0.8.47) - Hidden `reasoning_content` kept in English regardless of locale — thanks @cmyyy (report) (#1842, v0.8.47) - `ExternalTool` abstraction layer — thanks @aboimpinto (#1794, #2294, v0.8.48) - Ephemeral generated project context — thanks @Final527 (report) (#3058, v0.8.59) ## [0.8.61] - 2026-06-15 This release lands the **runtime control plane** for multi-agent work: the TUI stays responsive while sub-agents run, sub-agents converge toward fleet-style durable workers with per-role model routing, and provider/model routes are isolated per session. It also folds in several community contributions. ### Added - **WhaleFlow runtime foundations** — worker runtime profiles (role / permissions / shell / tools / model-route, with non-escalating child derivation), a cross-provider model registry with offline catalog hydration, and provider-readiness / context-budget / provider-adapter / resource-telemetry services. (#3217, #3071, #3072, #3073) - **Per-role, heterogeneous-model sub-agent routing** — sub-agents can be assigned a model and provider per role (e.g. scout vs. synthesis; verifiers route to a fast model). (#2027, #1768) - **Durable goal mode** — cross-turn goal progress with token/time accounting and a verifier-as-judge gate before a goal may complete. (#3215, #891, #1976, #2058, #2029) - Parent-visible worker interaction contract — a recommended action per worker. (#3226) - Maintainer GitHub workflow skills; ACP registry submission prepared. (#3192) - OpenAI-compatible `/v1/chat/completions` endpoint on the legacy app-server HTTP transport, provider-neutral, with model registry resolution and configured-credential forwarding. ### Changed - **Sub-agents converge toward fleet-style durable workers** — real worker lifecycle states are projected to the sidebar instead of a hardcoded "running", and a sub-agent returns a structured needs-input checkpoint instead of parking. (#3226, #3096, #3154) - The per-turn runtime tag exposes capability posture instead of human-facing mode labels. (#3213) - Independent shell and verifier work defaults to background jobs with nonblocking waits and a completion notification; blocking now requires an explicit wait. (#3212) - Sub-agent launches now expose explicit `model_strength` and `thinking` controls to the model instead of hidden child-model auto-routing; `explore` work is documented as a good fit for faster models and `thinking: "off"`. - Plan mode is strictly read-only (no shell tools), consistent with its runtime posture. - `/swarm` is gated behind the durable worker substrate. (#3218) - Legacy `deepseek` install/update path resolves to `codewhale`. (#2960, #2924, #2917) ### Fixed - **TUI freeze when multiple sub-agents spawn (launch blocker)** — the terminal input pump runs off the render thread, AgentProgress events are coalesced, and sub-agents no longer park on input with no orchestrator to answer; a six-worker stress test guards input/render/cancel liveness. (#3216, #3096) - Idle sub-agent completion notifications now resume the parent turn instead of waiting for a later user message; thanks @giovanni-paolilla for the deadlock report (#3266). - **Provider/model route isolation** — provider and model state is session-local, and a mismatched provider+model tuple is rejected at the route boundary. (#3227) - Route-effective context-window metadata, over-limit preflight, and bounded recovery from `context_length_exceeded` instead of re-looping. (#3204) - Synchronous tools (`file_search`, `grep_files`, `list_dir`) are cancellable and no longer hold a turn open against cancellation. (#1791) - MCP stdio proxy startup prompts no longer strand YOLO / non-interactive runs. (#2475) - Stalled / failed background-shell recovery; configurable sub-agent API timeout. (#1737, #1786, #1806) - Composer: reliable queued steering + Ctrl+S send (#3203, #3224); footer busy/idle indicator (#2982); CJK word-wrap (#963); clickable sidebar stop targets (#3028); live token throughput (#3190); auto-expiring terminal sub-agent cards (#3078). - Linux glibc preflight in the installer/update path with a clear error. (#3207, #1067) - Self-update retries transient GitHub metadata/asset failures and falls back from the GitHub REST API to the public `releases/latest` redirect before constructing release asset URLs. (#3232) - Provider picker lists providers in neutral alphabetical order instead of hard-coding DeepSeek first; the active provider stays pre-selected. (#3076) - Work sidebar no longer shows stale `phase now:` / `phase next:` strategy rows once the checklist is 100% complete. - Plan mode no longer shortcuts investigation for requests that name a repository, URL, version, release, build state, bug, PR, issue, API surface, or local code path. - Oversized pasted text stays editable in the composer, with a file backup appended at submit time for model access; thanks @idling11 (#3267, closes #3263). - Bare digit keys `1`-`8` now insert text instead of firing hotbar slots; use `Alt+digit` for hotbar actions. Thanks @wjq2026 for the report and @DieMoe233 for the paste-path note (#3243). - Kimi/Moonshot tool schemas normalize empty function parameters to a root object schema; thanks @jghwwnq for the provider repro (#3265). - Novita defaults to its OpenAI-compatible `/openai/v1` endpoint so chat completions no longer 404 out of the box; thanks @buko for the report and endpoint verification (#3255). - Dependency security: `ws` pinned to 8.21.0 across npm packages to close remote memory-exhaustion DoS (dependabot). ### Community contributions - Non-DeepSeek model pricing — thanks @mvanhorn (#3201) - Telegram polling transport — thanks @cyq1017 (#3195) - Mobile event history — thanks @RobertEmprechtinger (#3220) - Runtime-API session save — thanks @gaord (#3199) - Whale-accent rename — thanks @nightt5879 (#3197) - `DEEPSEEK_BASE_URL` / `MODEL` honored in `exec` — thanks @hongchen1993 (#3221) - VS Code read-only API documentation — thanks @cyq1017 (#3013) - Atomic ask-only permission rule persistence — thanks @greyfreedom (#3233) - DeepInfra provider support and release-surface follow-through — thanks @idling11 (#3235, closes #3231) and @nightt5879 (#3236) - Editable oversized paste composer flow — thanks @idling11 (#3267, closes #3263) - WeChat bridge (`integrations/weixin-bridge` via Feishu + Tencent OpenClaw) — thanks @VincentCorleone (#3206) - Config robustness: atomic permission-rule save, one-time config `.bak` backup before the first changed write, `CODEWHALE_HOME` as primary config home, and accepting the dispatcher-written config shape (camelCase aliases + `[features.enabled]` table) so legacy/dual-written configs parse cleanly - Dependency/CI bumps: docker login/qemu actions, softprops gh-release, download-artifact, vitest, @opennextjs/cloudflare, form-data, js-yaml, dompurify, ws ## [0.8.60] - 2026-06-13 ### Added - **Agent Fleet real-run cutover (#3154/#3096).** `codewhale fleet run` now launches durable workers through the headless `codewhale exec --output-format stream-json` path instead of the local simulation interpreter, with terminal worker events freeing leases so queued fleet tasks continue running. - **Read-only shell parallelism (#2983).** The engine can now run conservative read-only shell calls in parallel, including strict `bash`/`sh`/`zsh -c` wrappers for whitelisted commands, while writes, stdin, background TTY work, redirects, pipes, command substitution, and follow-mode tails stay serial. - **Declarative JS/TS WhaleFlow authoring (#3097).** WhaleFlow now accepts a compile-only `workflow({...})` JavaScript/TypeScript authoring form that lowers into the existing `WorkflowSpec` validator without executing user JavaScript. - **Slash-menu Ctrl+P/Ctrl+N navigation (#3196).** The slash command menu now supports Ctrl+P/Ctrl+N movement without letting the global file picker steal focus while the menu is open. Thanks @1Git2Clone for the PR. - **New models and first-party provider routes.** This release adds **GLM-5.2** (selectable on the Z.ai Coding Plan and over OpenRouter as `z-ai/glm-5.2`, alongside the existing GLM-5.1 default), a first-party **Z.ai** provider route, a first-party **StepFun / StepFlash** route (`step-3.7-flash`), and a first-party **MiniMax** route defaulting to `MiniMax-M3` with the M2.7/M2.5/M2.1 family selectable (#3187/#3191). ### Changed - **README and contributor credits.** The README now has a shorter public overview and moves the full contributor ledger to `docs/CONTRIBUTORS.md`, preserving public thanks for [DeepSeek](https://github.com/deepseek-ai), [DataWhale](https://github.com/datawhalechina), [OpenWarp](https://github.com/zerx-lab/warp), and [Open Design](https://github.com/nexu-io/open-design). - **Fleet-backed sub-agent direction.** Runtime docs now state the intended cutover clearly: "sub-agent" is role/UX vocabulary, while durable detached work should converge on the fleet-backed worker lifecycle with retries, receipts, and ledgered inspection. ### Fixed - **Sub-agent eval no longer blocks by default.** `agent_eval` now returns the current projection immediately and delivers follow-up input without waiting for a running child to finish its provider call. Pass `block:true` for an intentional terminal wait. - **Z.ai GLM thinking traces.** Direct Z.ai requests now use the documented `thinking` shape, preserve and replay `reasoning_content`, classify GLM reasoning streams as thinking output, and accept `ultracode` as a max-effort alias. - **Claude skill archive compatibility (#2743).** `/skill install` keeps portable Claude-style skill folders supported while rejecting multi-skill Claude plugin archives clearly instead of silently installing only one skill and dropping plugin semantics. Thanks @AiurArtanis for the ecosystem request. ## [0.8.59] - 2026-06-12 ### Added - **Moonshot Kimi K2.7 Code model.** The Moonshot/Kimi provider now defaults to `kimi-k2.7-code`, recognizes `kimi`/`kimi-k2` aliases for that model, keeps explicit `kimi-k2.6` selectable, and adds the OpenRouter `moonshotai/kimi-k2.7-code` registry row. - **Concise verbosity mode (#3052).** CLI noninteractive launches now default to concise prompt/output discipline unless overridden by config, env, or `--verbosity`, while interactive TUI launches remain normal by default. Thanks @cyq1017 for the PR. - **Ephemeral generated project context (#3058).** Opening CodeWhale in a directory with no instruction files now keeps the bounded generated project overview in memory instead of creating `.codewhale/instructions.md`. - **ACP registry auth metadata (#1447).** The ACP stdio adapter now advertises terminal authentication setup in `initialize.authMethods`, matching the registry's validation requirement. - **Sidebar context menus (#3065).** Right-clicking the sidebar no longer shows `Paste`; clickable sidebar rows now offer their row command as the first context action. - **Sidebar hover popovers (#3088).** Streaming turns now keep sidebar hover popovers responsive while continuing to throttle transcript/body mouse motion. - **Dark-theme selection contrast (#3074, thanks @drpars).** Session, config, help, context-menu, and approval selections now use the muted selection background instead of the bright accent color. - **Cursor-style activity metadata rows (#3146).** Dense successful tool-run summaries now render as a single muted `Explored ...` / `Updated metadata` row, include short command-family labels for successful generic verifier groups, and keep keyboard/mouse expansion and detail inspection intact. - **Provider-wait observability (#3095).** Footer stall reasons now name the active provider/model route, idle seconds vs stream budget, and whether a fanout plan is still at `0 running` or dispatch is pending. Structured provider-wait incidents log once per turn from the main tick loop (not on every footer redraw). - **Interactive fanout launch gate (#3095).** Direct sub-agent children queue behind a configurable semaphore (`[subagents] interactive_max_launch`, default 4) with a visible `queued: waiting for an interactive fanout slot` reason before their first model step. - **Goal lifecycle controls.** `/goal` is now the primary command surface for session goals, with `pause`, `resume`, `complete`, `blocked`, and `clear` controls while `/hunt` remains a compatibility alias. - **Persistent thread-goal API.** App-server clients can now set, get, and clear durable thread goals through `thread/goal/set`, `thread/goal/get`, and `thread/goal/clear`, backed by the state store with Codex-style status and token/time accounting fields. - **Command-boundary ownership layers (#2888/#3055).** Built-in slash command metadata now lives in `commands/registry.rs`, slash parsing in `commands/parse.rs`, and handlers under group-owned command areas, preserving the existing dispatch surface while reducing future `commands/mod.rs` churn. - **Approval-rule source metadata (#1186/#2971).** Runtime API `approval.required` events now include optional `matched_rule` metadata when an execution-policy rule caused the prompt. Thanks @greyfreedom for the PR and @Ram9199 for the audit-semantics discussion. - **Localized tool-family labels (#2901).** Tool activity labels for read, patch, run, find, delegate, fanout, RLM, verify, think, and generic tool work now route through the shipped locale tables. Thanks @gordonlu for the PR. - **Localized config section labels (#2918).** The interactive config view now localizes section and session/saved scope labels while preserving English search terms. Thanks @gordonlu for the PR. - **Localized config editor labels (#2919).** The config editor modal now localizes edit labels, default/unavailable placeholders, and effective currency hints. Thanks @gordonlu for the PR. - **Hotbar number-key dispatch (#3056).** Bare `1`-`8` now trigger bound hotbar slots only when the composer is empty, while `Alt+1`-`Alt+8` trigger slots regardless of composer text and overlays keep key ownership. Thanks @reidliu41 for the PR. - **Voice dictation commands (#3051).** `/voice`, `/voice-send`, and `/voice-control` now record through `sox`/`rec`/`arecord`, transcribe via the active provider's chat-completions API, and insert transcripts at the composer cursor. The `voice.toggle` hotbar action dispatches the real voice command, with help and status text localized across all seven shipped locales. Thanks @huqiantao for the PR. - **Thread rewind and snapshot restore API (#2808).** GUI clients can now call `POST /v1/threads/{id}/undo`, `/patch-undo`, and `/retry` to fork, roll back, or rerun recent thread turns, plus `POST /v1/snapshots/{id}/restore` to restore a workspace snapshot by id. Thanks @bengao168 for the PR. - **Active provider fallback chain (#2773).** Configured `fallback_providers` now build an ordered primary-plus-fallback route that the TUI can report, advance through, and reset with `/provider fallback reset`, including footer visibility for fallback state. Thanks @idling11 for the PR. - **Provider metadata registry (#3005).** Built-in provider ids, display names, defaults, env vars, config keys, aliases, and wire formats now live in a shared metadata registry, with the provider drift check covering the registry contract. Thanks @sximelon for the PR. - **Hugging Face provider route (#2879).** Hugging Face Inference Providers now have first-class config, env, docs, and registry coverage for the OpenAI-compatible router, including `huggingface`/`hugging-face`/ `hugging_face`/`hf` aliases and `HUGGINGFACE_*`/`HF_*` env fallbacks. Thanks @mvanhorn for the PR. ### Fixed - **SSE data lines without spaces (#3152).** Chat Completions, Responses, and Anthropic stream readers now accept both `data: {...}` and `data:{...}` SSE frames, matching the spec and preventing providers that omit the optional space from streaming empty output. Thanks @wgeeker for the PR. - **Runtime thread detail N+1 reads (#3141).** `get_thread_detail` now scans persisted turn items once and groups them by turn instead of reading the items directory once per turn, preserving item order while keeping large thread detail loads responsive. - **Project-local hook trust boundary (#3140).** `.codewhale/hooks.toml` is now loaded only after the workspace is trusted in user-owned config, matching the project-local MCP trust model while preserving the documented shell-command hook contract. - **Skill registry sync latency (#3139).** `/skills sync` now syncs registry entries with bounded ordered concurrency, so network latency no longer stacks one skill at a time while output order stays deterministic. - **SiliconFlow China provider config (#2893/#2895).** `siliconflow-CN` now reads its own `[providers.siliconflow_cn]` / `[providers.siliconflow-CN]` table and falls back to `[providers.siliconflow]` only for unset `api_key`/`base_url`/`model` fields. Thanks @Artenx for the report and @idling11 for the PR. - **Self-update download timeout (#3006).** `codewhale update` now applies a five-minute HTTP client timeout so blocked or very slow GitHub release downloads fail instead of hanging indefinitely. Thanks @New2Niu for the PR. - **Legacy `deepseek` update migration (#2960/#3013/#3053).** Running `deepseek update` or `deepseek-tui update` from a pre-rebrand install now returns copy-pasteable npm, Cargo, Homebrew, and manual-binary migration steps instead of trying to spawn a missing `codewhale` binary. README and rebrand docs now cover the same upgrade path. Thanks @jazzi and @tiangangQiu for the reports, @cyq1017 for the update-path PR, and @angus-guo for the README PR. - **Short `codew` shim delegation.** The `codew` convenience binary now prefers the sibling `codewhale` dispatcher installed next to it before falling back to `PATH`, preventing fresh local builds or installs from accidentally invoking an older global dispatcher. - **Constitution trust wording (#2950/#3008).** The base prompt now explains that "begins with an A" means a baseline of trust, not a literal output formatting rule. Thanks @cyq1017 for the PR. - **TUI provider-source recovery (#3007/#3011).** Unsupported interactive providers now report whether the value came from `--provider`, environment, or config. Config-sourced unsupported providers fall back to DeepSeek without forwarding stale keyring secrets. Thanks @cyq1017 for the PR. - **Exec auto-model handoff (#3148).** `codewhale exec --model auto` now survives the CLI/TUI boundary by honoring the CodeWhale model env alias and legacy DeepSeek model handoff before falling back to provider defaults. Thanks @hongchen1993 for the PR. - **macOS shortcut modifiers (#2938/#2943).** Ctrl-like shortcuts that are reported as `SUPER` by macOS terminals now work for backgrounding tasks and sidebar-focus chords without rewriting clipboard shortcuts. Thanks @idling11 for the PR. - **TUI mouse-report leak (#3063/#3067).** Strip raw SGR mouse coordinate tails from the composer even when `use_mouse_capture` is false, covering orphaned terminal reporting state after crashes or focus races. - **Interrupted sub-agent lifecycle (#3080).** API-timeout interruptions now emit `MailboxMessage::Interrupted`, render terminal interrupted cards, and reconcile stale running fanout counts from manager snapshots. - **OpenAI Codex stream diagnostics and active tool collapse (#3146).** The Responses bridge now reports nested `response.failed` / `response.incomplete` errors instead of `unknown`, and dense successful in-flight tool bursts collapse into the same calm activity metadata row as committed history. - **OpenAI Codex reasoning tiers.** Switching from DeepSeek to `openai-codex` now normalizes stale reasoning state into Responses-compatible `low`/`medium`/`high`/`xhigh` tiers. Startup, `/config`, and the model picker now display Codex labels instead of leaking DeepSeek `off`/`max` names, while Codex still reports as a Responses payload provider. The Responses request builder also clamps legacy `minimal` input to `low` and has regression coverage that Codex requests use `reasoning.effort`, not DeepSeek `thinking` fields. - **OpenAI Codex context metadata (#3070).** The `gpt-5.5` default and CodeWhale aliases now use OpenAI's documented 1,050,000-token context window and 128,000 max-output metadata for context pressure, prompts, and doctor capability output. - **OpenAI Codex effective context budgeting.** The public OpenAI API metadata for `gpt-5.5` remains 1,050,000 tokens, but the `openai-codex` OAuth route now budgets prompts against the 400K Codex-family effective window so preflight compaction runs before the backend returns `context_length_exceeded`. - **OpenRouter Nemotron 3 Ultra preset.** The OpenRouter preset and model registry now emit `nvidia/nemotron-3-ultra-550b-a55b` while keeping the old Ultra aliases compatible. - **OpenRouter auth after MiMo switches (#3064).** Switching from Xiaomi MiMo to OpenRouter now has regression coverage for preflight key failures and Bearer auth header isolation before any request can be dispatched. - **Responses strict-tool schema compatibility (#3062/#3017/#1883).** Responses function tools now preserve per-tool strict-mode compatibility, keep optional strict-schema fields nullable, and append deterministic constraint notes when root composition groups must be flattened for Responses. - **Runtime prompt autonomous loop guard (#3061).** Runtime policy reference now explicitly forbids initiating new work when `` is the only new turn content and no tool/sub-agent handoff is pending. - **Goal runtime status sync.** Goal token budgets and active/paused/complete status now sync into the engine alongside the objective, and model-visible `update_goal` can only mark goals complete or blocked. ### Contributors - Devin session work on #3080/#3095 (PRs #3103, #3104, #3106) — Hunter Bown (maintainer integration/cherry-pick on `codex/v0.8.59-release-ready`). - Nightt (@nightt5879) for the Responses strict-tool schema hardening in PR #3062. - yekern (@yekern) for the #3061 runtime-prompt loop safety report and repro that shaped the dispatch guard. - Paulo Aboim Pinto (@aboimpinto) for the staged command-boundary design and Layer 3 registry/parser extraction in PR #2888, plus the #2851/#2791/#2870 architecture stream that guided the grouped command areas in #3055. ## [0.8.58] - 2026-06-11 ### Added - **Native Anthropic provider.** A dedicated Messages API adapter (`/v1/messages` with `x-api-key` auth) replaces OpenAI-dialect shims for Claude models: adaptive thinking with `output_config.effort` shaping, prompt-cache breakpoints (capped at 4, earliest dropped), signed-thinking replay via `signature_delta`, normalized cache-hit/miss usage telemetry, and SSE error envelopes. `claude-opus-4-8`, `claude-sonnet-4-6`, and `claude-haiku-4-5` join the model registry; configure with `ANTHROPIC_API_KEY` (#3014). - **Hooks v2.** `tool_call_before` hooks can now return a JSON decision — `{"decision": "allow"|"deny"|"ask", "reason", "updatedInput", "additionalContext"}` — with deny > ask > allow precedence across multiple hooks, last-writer-wins input rewriting, and concatenated context. Exit code 2 remains a legacy hard deny. Hooks support glob matchers and project-local `.codewhale/hooks.toml` (#3026). - **Clickable sidebar.** Background-job rows show/cancel on click, the Ctrl+K hint row runs `/jobs cancel-all`, and agent rows open `/subagents`; row actions are built in the same pass as the rendered lines so a click can never target the wrong job (#3028). - OSC 8 out-of-band hyperlink infrastructure with per-region open/close sequences that survive partial redraws (#3029). - `codewhale exec` gains `--allowed-tools`, `--disallowed-tools` (deny wins), `--max-turns`, and `--append-system-prompt` (#3027). - Constitution prompt source: YAML source-of-truth plus Python renderer for the system prompt, with the active prompt now served from `constitution.md` (#3015, renderer reconciliation still tracked). - Agent-task issue template, labels, and runner protocol (#3021); remote smoke-test droplet loop hardening — gh CLI, swapfile, agent sessions (#3022). ### Changed - **Sub-agent routing is provider-aware.** DeepSeek ids are no longer hardcoded into model validation; routing works from per-provider big/cheap candidates, the network router is skipped when a provider has no cheap tier, and spawn-time model requests are validated against the active provider (#3018). - Model-specific facts in the system prompt (context window, sub-agent pricing, thinking notes, architecture characteristics) are now templated per-model instead of hardcoded DeepSeek V4 claims, in both `base.md` and `constitution.md` (#3025). - Provider capability lookups for Moonshot/OpenAI/Atlascloud resolve from per-model registry rows (bare and vendor-prefixed ids) instead of hardcoded 64K-era floors (#3023). - Reasoning-effort now reaches Atlascloud (DeepSeek dialect), Moonshot (`thinking` enable/disable), and Ollama (`think` param) (#3024); Moonshot/ Kimi models joined the reasoning-content provider and model gates (#3016). - Transcript polish: compact tool-call cells without boilerplate (#3031), internal turn/agent ids hidden behind stable labels (#3030), and Ctrl+B now backgrounds the running foreground shell directly instead of opening a menu (#3032). - The Tasks sidebar separates "Model reasoning" from "Background commands", and `auth list` reports the same active-credential source as `auth status` for openai-codex. ### Fixed - **TUI freeze under sub-agent load.** Rapid `AgentProgress` events saturated the render loop and starved terminal input; progress-driven repaints are now throttled to one per 100ms (#3033). - **Hooks on Windows.** Hook commands were passed to `cmd /C` through CRT-style argument quoting, which injected literal `\"` sequences that cmd.exe never unescapes — JSON decisions could not parse. Commands now reach cmd.exe verbatim via `raw_arg`. - Codex Responses: assistant tool results are converted to `function_call_output` items (multi-turn tool calling previously broke), tool schemas are sanitized for the Responses API, and `maximum` effort maps to `xhigh` (#3019, #3017 — both partially; retry/backoff and per-tool strict mode remain open). - Better tool-denial and provider error messages harvested from PR #2933 (#3020). ## [0.8.57] - 2026-06-10 ### Added - **Turns now survive system sleep.** When the host suspends mid-stream, the connection used to die on wake with `Stream read error: error decoding response body` and the turn was lost (#2990). The engine now stamps stream progress with both monotonic and wall-clock time; a large divergence on a stream error identifies a sleep/wake cycle, and the request is silently re-issued (up to the existing 3-retry budget) instead of failing the turn. - **One-command release prep.** `./scripts/release/prepare-release.sh X.Y.Z` bumps the workspace version, every internal crate dependency pin, the npm wrapper, and the README install-tag examples, refreshes `Cargo.lock`, regenerates the embedded TUI changelog slice and web facts, and runs `check-versions.sh` — the v0.8.56 release needed nine follow-up commits for exactly these sync points. - `.github/CODEOWNERS` and `.github/dependabot.yml` (weekly cargo + github-actions updates, monthly npm for `web/`). ### Changed - **The changelog went on a diet.** Root `CHANGELOG.md` now carries recent releases (v0.8.40+); older entries moved to `docs/CHANGELOG_ARCHIVE.md`. `crates/tui/CHANGELOG.md` — embedded into every binary for `/change` — is a generated 15-release slice (`scripts/sync-changelog.sh`), no longer a 357 KB manual byte-for-byte copy (~300 KB smaller binaries). - GitHub Release bodies are generated from the tagged version's changelog section (`scripts/release/generate-release-body.sh`) instead of a hardcoded workflow blob with a hand-pasted contributor list. - `check-versions.sh` now also gates `web/lib/facts.generated.ts` and the README install-tag examples; the CNB mirror pipeline validates the pushed tag against `Cargo.toml` before generating release notes. - Docs reorganized: internal design notes moved under `docs/rfcs/`; stale internal docs (old audits, handoffs, region-specific VM notes) removed. - Agent-facing polish: the system prompt environment block reports `codewhale_version` (was `deepseek_version`), the legacy `.deepseek/instructions.md` path is no longer advertised in the prompt (still honored for back-compat), and oversized instruction files are truncated with an explicit `[…truncated: N bytes omitted]` marker instead of a bare ellipsis. ### Fixed - **Docker images build again.** The release `docker` job failed for v0.8.56 because the Dockerfile still copied the pre-rebrand `deepseek` / `deepseek-tui` binaries; they are now symlinks to the codewhale binaries inside the image, so legacy container entrypoints keep working. - `.devcontainer/devcontainer.json` used the pre-rebrand container name, mount path, and `deepseek` remote user. - Stale `--bin deepseek` examples, `DeepSeek-TUI` strings in `/change` output, and pre-rebrand doc comments. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - Unused dependencies: `tracing-appender` and `zeroize` (TUI crate), `rustls` (release crate); the orphaned `vendor/schemaui-0.12.0` lockfile leftover and a machine-specific one-off `scripts/verify_task.sh`. ## [0.8.56] - 2026-06-09 ### Added - **Status picker localization.** The status picker surface (7 MessageIds) is now localized across all supported locales (#2896, @gordonlu). - **Approval dialog localization.** The approval dialog surface is now localized across 7 locales: English, Simplified Chinese, Japanese, Vietnamese, Portuguese, Spanish, and French (#2891, @gordonlu). - **Volcengine provider in TUI dispatcher.** The `codewhale` / `codewhale-tui` CLI dispatcher now allows the Volcengine provider, so users can launch directly into a Volcengine-backed session (#2923, @hongchen1993). - **Dispatcher API-key preference.** When a provider-specific API key is supplied via the CLI dispatcher, it is now preferred over the saved root key, fixing a regression where saved keys masked explicit CLI keys (#2928, @hongchen1993). - **Qwen 3.6 Plus model support.** Added complete Qwen 3.6 Plus model resolution with dedicated version-bump tests (#2930, @idling11). - **Oversized paste spill.** Pastes larger than ~10 KB are now written to `.codewhale/pastes/` instead of being truncated or dropped, preserving the full content for the session (#2920, @sximelon). - **Cross-session prompt cache.** Added a disk-backed cross-session prompt base-section cache so post-mode-flip and post-restart turns reuse the byte-stable prefix without rebuilding it from scratch. ### Fixed - **Background shell routing.** Shell commands expected to take >5 seconds are now automatically guided to background tasks instead of blocking the agent loop, with the task panel syncing immediately on cancel (#2947, #2941, @cyq1017, @idling11). - **`allow_shell` error naming.** Shell-tool refusal errors now explicitly name `allow_shell = false` as the reason and suggest `/config allow_shell true` as the escape hatch (#2905, @cyq1017). - **Prefix-cache stability across mode flips.** `allow_shell` is now decoupled from the static system-prompt prefix, so mode changes (Plan ↔ Agent ↔ YOLO) no longer rebuild the byte-stable message[0] and invalidate the DeepSeek prefix cache (#2949, @LeoAlex0). - **`visibility="internal"` explained.** The Runtime Policy Reference section of the system prompt now explains the `visibility="internal"` attribute so models stop narrating their current mode between steps (#2951, @LeoAlex0). - **Bocha web search response handling.** Updated response parsing for the Bocha search backend after an upstream API change (#2946, @h3c-hexin). - **PDF read hang.** Full-PDF reads now use `extract_text_by_pages` to avoid a hang on large or complex PDFs (#2898, @idling11). - **9 critical bugs.** Fixed bugs across tools, client, and commands: stale `ContentBlockStop` cleanup, missing `#[test]` attribute, trailing-space restoration on English `ApprovalField` labels, and several correctness/stability issues (#2880, @HUQIANTAO). ### Changed - **CNB shim cleanup.** Removed deprecated `deepseek` shim references from the CNB mirror path. - **Style.** Applied `cargo fmt` to `crates/tools/src/file.rs`. ## [0.8.55] - 2026-06-08 ### Added - **Together AI provider.** Added Together AI as a first-class provider (`[providers.together]`, `TOGETHER_API_KEY`/`TOGETHER_BASE_URL`/`TOGETHER_MODEL`) with default models `deepseek-ai/DeepSeek-V4-Pro` and `deepseek-ai/DeepSeek-V4-Flash`, TUI provider-picker/auth/capability support, and CLI `auth list`/`auth status` coverage. - **Model catalog updates.** Added Qwen 3.7 Max (`qwen/qwen3.7-max`), MiniMax 2.7 (`minimax/minimax-m2.7`), and NVIDIA Nemotron 3 Ultra (`nvidia/nemotron-3-ultra`) on OpenRouter. - **OpenAI Codex (ChatGPT) provider — experimental.** Added an `openai-codex` provider that reuses an existing ChatGPT/Codex CLI OAuth login. The access token is read and refreshed from `~/.codex/auth.json` (no API key is stored), and requests use the OpenAI Responses API at `/codex/responses` with the `chatgpt-account-id` header and `responses=experimental` beta opt-in. Env overrides: `OPENAI_CODEX_ACCESS_TOKEN`/`CODEX_ACCESS_TOKEN`, `OPENAI_CODEX_BASE_URL`/`CODEX_BASE_URL`, `OPENAI_CODEX_MODEL`/`CODEX_MODEL`, `OPENAI_CODEX_ACCOUNT_ID`/`CODEX_ACCOUNT_ID`, `OPENAI_CODEX_AUTH_FILE`, `CODEX_HOME`. Default model `gpt-5.5`. The live Responses round-trip has not been exercised against the production backend in CI; treat as preview. ## [0.8.54] - 2026-06-08 ### Added - Added `/restore list [N]` so users can inspect more side-git rollback snapshots with UTC timestamps before choosing a restore point. Plain `/restore` now shows the 20 most recent snapshots, numeric restore targets can reach beyond that default listing up to a bounded index, and list requests above the visible cap fail explicitly instead of silently truncating. - Added HarmonyOS/OpenHarmony support scaffolding: environment-driven `OHOS_NATIVE_SDK` setup scripts and compiler wrappers, platform docs, explicit Rustls ring-provider installation for the no-provider TLS build, and OHOS fallbacks for unsupported keyring, clipboard, sandbox, browser-open, TTY, execpolicy Starlark parsing, and self-update surfaces. - Added `scripts/release/check-ohos-deps.sh` and wired it into CI/release preflight so the OpenHarmony target graph fails if unsupported `nix`, `portable-pty`, `starlark`, `arboard`, or `keyring` dependencies re-enter. - Added `.github/AUTHOR_MAP` and a CI co-author credit check so harvested commits use GitHub-mappable numeric noreply identities instead of `.local`, placeholder, bot/tool, or raw third-party emails. - Added a `turn_end` observer hook that fires after post-turn TUI state and token totals are updated. Hooks receive structured JSON with status, usage, totals, duration, tool count, and queued-message count on stdin; stdout is ignored and failures are warn-only (#1364, #2578). - Added provider-scoped `insecure_skip_tls_verify` for private OpenAI-compatible gateways that cannot use a trusted CA bundle. The setting is disabled by default, applies only to the active LLM provider HTTP client, and is surfaced by `codewhale doctor`; `SSL_CERT_FILE` remains the preferred path for corporate or private CA roots. Thanks @wavezhang for the original #1893 direction. - Added a default-disabled hard-compaction planner that can identify the summarizable middle of a long conversation while preserving the recent tail, existing tool-call/result pair guarantees, and working-set pinning. This harvests the safe planning layer from #2522 without enabling hard compaction or adding a message-rewrite execution path yet. Thanks @HUQIANTAO for the proposal. - Added rich PlanArtifact support to `update_plan`: Plan mode can now carry grounded objectives, context, sources, critical files, constraints, verification, risks, and handoff notes through the transcript card, Plan confirmation prompt, `/relay`, fork-state, and saved-session replay. - Added the first `codewhale-whaleflow` foundation crate with typed workflow config/IR validation and deterministic phase ordering tests. This preserves the WhaleFlow direction from #2482/#2486 without exposing a runtime `workflow_run` tool until cancellation, replay, and worktree semantics are release-safe. The foundation now includes explicit `WorkflowSpec`, `WorkflowNode`, branch/leaf/policy metadata structs, plus serializable branch, leaf, and control-node result records toward the #2668 TraceStore contract. It also adds a crate-local mock executor skeleton for Sequence, BranchSet, Leaf, Reduce, LoopUntil, Cond, Expand, BranchTournament, and ParetoFrontier control flow so #2669 can progress without spawning agents, applying worktrees, or exposing a `workflow_run` runtime tool yet. A first Starlark authoring layer now compiles fail-closed model-authored workflow files into that typed IR, with `rlm_cache_change.star` and `issue_fix_tournament.star` examples plus a one-pass repair for common `ctx.*` authoring aliases (#2670). Leaf, branch, and workflow execution results now carry deterministic token and cost telemetry fields that the mock executor can aggregate without live provider calls or runtime sub-agent fanout (#2486). The mock executor now carries crate-local cancellation and budget-exhaustion status markers so the branch/leaf runtime contract can be tested before live workflow execution is exposed (#2669). A crate-only replay executor now evaluates workflows from recorded leaf/control records, computes stable SHA-256 leaf input hashes, and marks missing records as `replay_diverged` instead of calling models again (#2673); the runtime replay command and live-provider replay fallback remain deferred. The crate also now has a model-agnostic role/capability registry with mock provider plumbing and fail-closed JSON repair parsing, so WhaleFlow can choose capable models for roles without hardcoding provider-specific runtime paths (#2672). The `rlm_cache_change.star` dogfood workflow now exercises candidate branches, LoopUntil verification, tournament selection, teacher review, and mock execution in CI-oriented crate tests (#2679). Leaf, branch, and workflow results now also carry separate ARMH/shared-memo and provider prompt-cache telemetry counters, with mock aggregation tests, so #2671 can progress without wiring live RLM calls or billing-affecting provider behavior yet. The Starlark and typed-IR gates now also reject unknown leaf dependencies, reducer inputs, and teacher-review candidates before mock execution or replay, keeping generated workflows fail-closed while runtime/worktree semantics stay deferred. TeacherReview now has serializable GEPA-style candidate artifacts for notes, workflow recipes, skills, regression tests, cache policy, branch heuristics, and Starlark authoring prompt patches, plus an offline helper that proposes candidates from recorded execution traces without promoting them or training model weights (#2674). StudentReplay results can now be stored on teacher candidates, and a deterministic PromotionGate compares baseline-vs-candidate replay deltas, required tests, policy violations, staleness, and cost constraints before marking a candidate promotable (#2675). The external-memory cutline now documents that Aleph-style memory stays optional, explicit, visible, and clear/export-capable for v0.9.0 rather than becoming a hidden default context substrate (#2677). A dedicated v0.9.0 release acceptance matrix now tracks provider, runtime, UI, WhaleFlow, Model Lab, remote-workbench, docs, rollback, and credit gates that must be checked or explicitly deferred before tagging (#2729). HarnessProfile docs now pin the v0.9.0 order: posture/schema/resolver/seed profiles/status display must precede evidence stores, promotion gates, or any automatic Harness Creator, with DeepSeek, MiMo, Arcee, and generic/HF/local posture expectations called out separately (#2728). Hugging Face / Model Lab and `codebase_search` release gates now explicitly ship only the provider/MCP/docs/design foundation in v0.9; native Hub search, model passports, Spaces/Jobs workflows, eval/export surfaces, and runtime `codebase_search` registration remain deferred (#2705, #2680, #2727). Remote workbench acceptance is also marked docs/setup-only for v0.9 so release notes do not imply a shipped VM or Telegram bridge runtime (#2724). Release-facing HarnessProfile docs now match the current implementation: v0.9 ships the typed schema/config foundation and defers runtime resolver, telemetry, seed-profile selection, and status-display behavior until later verified slices. `config.example.toml` includes a commented dormant harness-profile example, and README links point at the real acceptance matrix and HarnessProfile cutline docs. The release acceptance matrix now records evidence for already-landed gates: provider-registry drift checks, provider-scoped TLS skip verify, read-only GUI runtime/restore-point surfaces, VS Code Agent View branch visibility, WhaleFlow mock/runtime foundations, explicit external-memory boundaries, and docs alignment. Live workflow execution, provider calls, TraceStore writes, and mutation-oriented GUI endpoints remain deferred until their atomicity and replay contracts are tested. The `rlm_cache_change.star` dogfood workflow can now be replayed from recorded mock leaf/control records, and missing dogfood records produce `ReplayDiverged` instead of falling back to live execution (#2679). The UI/workflow UX rows now also distinguish shipped transcript tool-run collapse, sidebar detail popovers, and PlanArtifact review/handoff evidence from the deferred first-look/home redesign, and record focused slash-picker readability smoke coverage for visibility, selection, skill insertion, Esc priority, and stable composer height (#2692, #2694, #2691, #2713). Thanks @AdityaVG13 for the WhaleFlow draft and cost-tracking direction. - Added a state-store v2 schema migration for WhaleFlow trace tables covering workflow, branch, leaf, control-node, and teacher-candidate runs. The migration creates persistence shape only; workflow execution and replay remain deferred until the runtime semantics are safe (#2668). - Added an official VS Code extension Phase 0 scaffold with terminal launch, local runtime attach checks, status bar state, and a read-only Agent View preview backed by recent runtime thread summaries, plus a read-only `GET /v1/snapshots` endpoint for GUI clients to inspect side-git restore points. The extension now renders those restore points read-only in its Agent View, and thread summaries include read-only workspace, branch, current Git head, and dirty-state metadata so the VS Code Agent View can show when a thread or agent lane is on another branch or has changed worktree state. Agent View and restore-point data now auto-refresh on a configurable read-only interval so branch/workspace/status changes become visible without a manual refresh. Agent View refreshes keep thread branch/workspace rows independent from restore-point loading, so a snapshot-listing failure no longer clears already-available thread metadata. This answers the VS Code GUI lane without exposing chat webviews, inline edits, or retry/undo/restore runtime mutation endpoints yet (#461, #462, #480, #1217, #2341, #1584, #2327, #2580, #2808). Thanks @AiurArtanis for the Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI runtime API direction, @douglarek, @caeserchen, and @nightt5879 for the branch visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan, @mangdehuang, @VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the GUI/VS Code demand and validation trail. - Added inline live-output refresh for background shell Exec cards keyed by the exact shell task id, so long-running commands can show bounded stdout/stderr tails without consuming deltas or matching by command text. Thanks @donglovejava for the live shell-output direction in #2048. - Added a static prompt composer override for embedders that need to replace the byte-stable base/personality prompt segment while leaving mode metadata, approval policy, tool taxonomy, Context Management, and the Compaction Relay under CodeWhale's runtime prompt assembly. This refines the embedder prompt customization path from #2786 without weakening prompt-continuity safeguards. Thanks @h3c-hexin. - Added `POST /v1/sessions` for runtime clients to save a completed thread as a managed session. The endpoint preserves thread title/model/mode/workspace metadata, maps missing threads to 404, and returns 409 instead of snapshotting queued or active turns. - Added cost-estimate pricing for the Xiaomi MiMo primary chat models, which were previously unpriced: `mimo-v2.5-pro` / `xiaomi/mimo-v2.5-pro` reuse the DeepSeek V4-Pro rate table and `mimo-v2.5` / `xiaomi/mimo-v2.5` reuse the DeepSeek V4-Flash rates. Existing DeepSeek pricing is unchanged (#2731, #2750). - Added a metadata-only `codewhale-config` provider registry with canonical lookup, alias-aware resolution, provider defaults, config-table keys, and API-key env candidates. Runtime routing remains unchanged and fallback providers stay dormant; this harvests the safe provider-trait foundation from #2479 toward #2075. Thanks @sximelon. - Added optional `[search].base_url` / `CODEWHALE_SEARCH_BASE_URL` support for DuckDuckGo-compatible private search endpoints, while keeping `DEEPSEEK_SEARCH_BASE_URL` as a legacy alias. Custom endpoints are gated by their configured host, do not fall back to public Bing, and report the custom host as the result source for diagnostics (#2436, #2510). - Added `completion_sound = "file"` with `[notifications].sound_file` so Windows users can play a custom WAV file for turn-completion sounds without changing the global Windows sound scheme (#2484, #2512). - Added `[tui].stream_chunk_timeout_secs` and `/config stream_chunk_timeout_secs` so slow local or OpenAI-compatible model servers can extend the SSE idle timeout without mutating process environment. The legacy `DEEPSEEK_STREAM_IDLE_TIMEOUT_SECS` env var remains a fallback (#2365, #2507). - Added dormant `fallback_providers = [...]` config parsing plus a provider-chain helper for future fallback routing. This preserves the requested contract without enabling silent runtime provider switches yet (#2574, #2777). Thanks @hsdbeebou for the request and @idling11 for the data-model draft. - Added `/hf` with `/huggingface` alias for Hugging Face MCP status/setup helpers and `/hf concepts` provider/MCP/Hub guidance. The helper points users to Hugging Face's settings-generated MCP configuration and intentionally does not include Hub search, direct Hugging Face HTTP requests, or upload behavior (#2709, #2782). Thanks @idling11 for the original Hugging Face MCP draft. - Added an in-process response cache for deterministic non-streaming, tool-free chat requests. The cache is keyed by provider, base URL, path suffix, API-key fingerprint, and final wire body, and zeroes usage on hits so local spend counters are not double-counted (#2501). Thanks @HUQIANTAO for the response-cache proposal and canonical-body key update. - Added `/sidebar` so users can toggle, show, hide, and optionally persist the TUI sidebar from the command line instead of relying on copy-hostile sidebar state during long transcript work (#2766, #2788). Thanks @mo-vic for the detailed report and @aboimpinto for the fix. - Added a pausable custom slash-command MVP: commands with `pausable: true` can pause before further tool execution, preserve the paused command while separate messages are handled, and resume only on explicit continue/resume wording. Harvested from #2732 with thanks to @aboimpinto. - Added Sofya (`provider = "sofya"`) as a search-tool backend with `SOFYA_API_KEY` fallback, while keeping Sofya scoped to web search rather than model-provider routing (#2790). Thanks @yusufgurdogan for the implementation. - Added Xiaomi MiMo `mode` / `XIAOMI_MIMO_MODE` / `MIMO_MODE` selection for Token Plan region endpoints and pay-as-you-go routing, plus dedicated Token Plan env keys for `tp-*` subscriptions (#2621, #2627). Thanks @springeye for the request and @xyuai for the implementation. - Added the first TUI hotbar action registry foundation so future UI controls can dispatch typed app actions instead of growing another command match surface (#2866). Thanks @reidliu41 for the implementation. - Added the narrow multi-tab core and persistence foundation, including tab manager snapshots, delegation/group restore counters, mention parsing, cross-tab events, and corruption-tolerant persisted state, while leaving the broader collaboration UI wiring to follow-up work (#2864). Thanks @ljm3790865 for the tab-core implementation and #2753 direction. - The VS Code Agent View now renders the runtime thread summary's Git `head` and dirty-worktree flag alongside branch metadata, keeping branch switches visible without adding retry/undo/restore mutation endpoints yet (#2580, #2862). Thanks @AiurArtanis and @nasus9527 for the IDE/agent-view requests and @gaord for the runtime metadata direction. ### Changed - Removed the deprecated `deepseek` and `deepseek-tui` binary shims from the v0.9.0 Cargo crates and GitHub release artifact matrix. The canonical `codewhale`, `codew`, and `codewhale-tui` entry points remain, the private deprecated `npm/deepseek-tui` notice package stays unpublished, and DeepSeek provider/model/env/config compatibility remains first-class. - Command-adjacent config persistence and auto model routing now live in neutral TUI modules instead of command-owned files, reducing command-boundary coupling while preserving current `/config`, `/model`, UI, runtime, and sub-agent behavior (#2871). Thanks @aboimpinto for landing this first staged command-boundary layer from the broader #2851/#2791 design direction. - `/config` now reports the canonical `~/.codewhale/settings.toml` path for TUI settings while still reading legacy DeepSeek-branded settings fallbacks and migrating them into the CodeWhale home on load. - Provider switches now roll back transactionally when the first request to a newly selected provider fails authentication: CodeWhale restores the previous provider/model, model-ID passthrough, onboarding/API-key state, runtime config, persisted provider selection, and engine handle so users can return to DeepSeek after a failed Moonshot/Kimi switch (#2754, #2755). Thanks @Dr3259 for the Windows repro and @cyq1017 for the draft fix. - `PATCH /v1/threads/{id}` can now update a thread's persisted workspace for GUI/runtime clients. Workspace changes reject active turns and evict idle cached engines so the next turn starts in the new workspace. - Split `web_run` session/page cache state so cached page reads use shared page handles and do not serialize through the mutation path. The harvest also adds panic-safe state write-back and serializes cache-mutating unit tests so the global web cache remains stable under normal Cargo test parallelism. - Appended volatile `` blocks after user text in outgoing user message content arrays so provider prefix caches can keep matching the stable user-input prefix across date, route, and working-set changes. - Projected mode, approval, and tool-taxonomy prompt metadata per request instead of mutating stored system prompts, keeping provider prefix-cache inputs byte-stable while preserving mode-specific instructions (#2687). Thanks @LeoAlex0 for the implementation. - Softened contribution intake automation: external issues now receive a warm triage note and are never auto-closed by the contribution gate, while the PR gate copy makes clear that dry-run observations are about maintainer safety, not contributor quality. - Added a PR gate marker guard so reopened unapproved PRs do not get duplicate intake comments, and clarified that PR reopening should happen after allowlist approval is merged. - Ollama `/model` completions no longer show hosted DeepSeek API model IDs. The picker preserves the current or saved local Ollama tag, and users can still fetch installed model IDs through `/models` instead of relying on a stale static default (#2742). Thanks @reidliu41 for the focused report and draft fix. - MCP runtime API tool listings and approval summaries no longer split underscored MCP server names at the first `_`. Tool-call routing already used the longest registered server name; the list endpoint now reuses that parser, and approval cards show the full MCP target route instead of a guessed server segment (#2744). Thanks @lioryx, @cyq1017, and @puneetdixit200 for the report and matching fixes. - Documented the agent and sub-agent stewardship ethos so future automation preserves human issue intake, careful PR review, and contributor credit. - Moved the TUI Starlark execpolicy parser and PTY support behind non-OHOS target dependencies so published OpenHarmony builds no longer pull `nix` 0.28 through `rustyline` or `portable-pty`. - Explicit `skills_dir` configuration is now unioned with workspace skill discovery instead of being shadowed by workspace-local skills, and configured skills take precedence over global defaults when prompt space is constrained. - Tool-agent sub-agent routing now inherits the parent session model, or an explicit tool-agent override, instead of hard-coding `deepseek-v4-flash`; the fast lane still disables thinking through provider-aware request shaping. - Dense successful read/search/list tool runs now collapse into a single expandable transcript row by default, while running, failed, shell, patch, review, diff, and other risky tool cells remain visible. The setting `tool_collapse = "compact" | "expanded" | "calm"` controls the behavior. - Pending-input preview rows now label delivery mode explicitly as steer pending, rejected steer, or queued follow-up, with wrapped continuation rows aligned under the label so busy-turn input state is easier to read (#2054). - Editing a queued follow-up is now an explicit pending-input state. Pressing `Esc` while editing a queued follow-up restores the original queued message instead of cancelling the active turn or silently dropping the queued work (#2054). - Approval prompts now render prominent command, directory, file, path, or target rows before falling back to raw JSON params. Shell approvals preserve long command tails, split common shell chains for review, and show compact `printf > file` previews while keeping intent summaries visible (#1991, #2269). - Sidebar hover details now use row-level metadata for truncated Work, Tasks, and Agents rows. Mouse hover opens a bordered, wrapping popover with the full underlying row text, long turn/agent ids, and current sub-agent progress instead of repeating the already-ellipsized sidebar label (#2694, #2734). - Sub-agents now preserve checkpoint metadata around long model calls. A per-step API timeout marks the child as interrupted with a continuable checkpoint instead of ending as a null failed result, and `agent_eval` can explicitly continue a live checkpointed interrupted child while normal completed/failed/cancelled follow-up behavior stays unchanged (#2029). - Durable task recovery no longer requeues tasks that were `running` when the previous CodeWhale process exited. On restart those records are marked failed with a recovery note, and any running tool-call summaries are marked failed too, so stale shell/task state cannot silently become live work again (#1786). - Auto-generated project instructions now reuse the bounded Project Context Pack data instead of running an unbounded summary/tree scan when no `.codewhale/instructions.md` file exists. The fallback keeps later top-level folders visible in noisy large workspaces while the dynamic `` marker remains controlled by its own setting (#697, #1827). - Project context loading now uses a bounded process-local content-signature cache for repeated hot-path loads. The cache covers workspace/parent instructions, global AGENTS/WHALE fallbacks, repo constitution files, generated-context targets, trust markers, and trust config paths, and it stores post-load signatures so auto-generated context deletion/regeneration stays correct (#2636). - Configuration docs now show the provider-local `path_suffix` escape hatch for OpenAI-compatible gateways that accept `/chat/completions` but reject `/v1/chat/completions`, while making clear that model listing and DeepSeek beta routes keep their built-in paths (#1874). - The config crate now carries the v0.9 HarnessPosture data model: `HarnessPosture`, `HarnessProfile`, and typed posture/compaction/tool/safety enums. The schema rejects misspelled posture names or unknown profile keys instead of silently falling back to `custom`; a pure resolver can match provider/model routes for tests and future status plumbing, while runtime provider/model posture selection remains a follow-up (#2693, #2741, #2728). ### Fixed - **MiMo default tests.** Guarded Xiaomi MiMo default-model tests against ambient CI provider environment variables. - Stream/body decode failures such as `Stream read error: error decoding response body` are now classified as recoverable network interruptions instead of generic internal errors, keeping the transcript and triage metadata aligned with the existing stream retry path (#2847). Thanks @qamranmushtaq-collab for the Windows/npx DeepSeek report. - The TUI footer, `/status`, `/mcp` manager, and command-palette MCP entries now count trusted workspace-local `.codewhale/mcp.json` servers together with the global MCP config, matching `codewhale mcp list` for merged global + project setups (#2787). Thanks @yekern for the detailed reproduction. - AltGr key chords in the composer no longer get swallowed by sidebar shortcuts on AZERTY and other international layouts, so characters such as `@`, `#`, `$`, `!`, and `%` can be entered normally (#2863, #2867). Thanks @ousamabenyounes for the fix and report. - Sub-agent shell completions now refresh the workspace branch/status chip immediately, and `/subagents` plus the Agents sidebar show each sub-agent's current workspace branch when it is running in a child worktree. - Authentication failures now include redacted request context such as provider, base URL authority, model, key source, key type, and key fingerprint, making stale provider, endpoint, or API-key state diagnosable without exposing the secret (#2665, #2792). Thanks @mvanhorn for the implementation. - Browser-opening actions now compile on non-desktop targets by delegating the unsupported-platform error to the shared URL opener instead of hiding the TUI wrapper behind a narrower macOS/Linux/Windows cfg. Thanks @ci4ic4 for the NetBSD/pkgsrc packaging report and fix (#2789). - MCP tool routing now preserves server names that contain underscores. `parse_prefixed_name` matches the qualified `mcp__` name against the set of registered server names and prefers the longest match, so tools on a server like `my_db` are reachable and an overlapping `my` / `my_db` pair routes correctly. Falls back to the legacy first-underscore split when no registered server matches (#2744). - Schema-hydrated deferred tools no longer render as a completed run. The first use of a deferred tool returns a schema-hydration result instead of executing; the transcript and sidebar now show "tool loaded — retry required" via a dedicated hydrated status, so it is no longer indistinguishable from a real successful execution. A hydrated row also ranks with active work rather than completed successes (#2648). - `codewhale sessions` now shows `codewhale resume ` in the footer instead of the invalid dispatcher command `codewhale --resume ` (#2758, #2760). - TUI HTTP clients now install the Rustls ring crypto provider before building `reqwest` clients, covering engine, runtime API, tool, MCP, config, and skill download paths. This keeps the no-provider TLS build from panicking during tests or embedded startup paths that do not enter through the main binary. - Prompt byte-stability tests now pin their temporary home and skills environment under the shared test-env lock so global skill directories cannot perturb deterministic prompt bytes during parallel test runs. ### Community Thanks to **@sximelon** for reporting and fixing the saved-session resume footer hint (#2758, #2760), **@cyq1017** for the custom DuckDuckGo-compatible search endpoint, custom completion sound file support, restore-listing implementation, and pending-input delivery-mode label work (#2510, #2512, #2513, #2532, #2054), **@Artenx** for the private-search endpoint report (#2436), **@LHqweasd** for the Windows custom notification sound request (#2484), **@wywsoor** for the broader macOS/iTerm rollback UX report (#2494), **@HUQIANTAO** for the `web_run` lock-splitting work (#2502), turn-metadata prefix-cache stability work (#2517), and project-context cache direction (#2636), **@xyuai** for canonical CodeWhale settings-path migration work (#2730), **@gaord** for the runtime thread workspace update and completed-thread save APIs (#2640, #2639), **@shenjackyuanjie** for the HarmonyOS/OpenHarmony port and MatePad Edge validation trail (#2634), **@ousamabenyounes** for the AZERTY AltGr composer shortcut fix (#2863, #2867), **@reidliu41** for the hotbar action-registry foundation (#2866), and **@ljm3790865** for the multi-tab core/persistence foundation and broader collaboration direction (#2864, #2753), **@aboimpinto** for the direct command-support boundary cleanup in #2871 and the broader #2851/#2791 command-layer design direction, **@idling11** for the PlanArtifact direction in Plan mode (#2733), the dense tool-call transcript collapse/sidebar detail direction (#2738, #2734, #2692, #2694), and the HarnessPosture config model for provider/model posture (#2741, #2693), and **@h3c-hexin** for the tool-agent model inheritance and configured `skills_dir` fixes (#2736, #2737), **@AresNing** for the turn-end observer hook work (#2578), and **@tdccccc** for the approval key-detail and shell-preview work (#1991, #2269). Thanks also to **@qiyuanlicn** for the checkpoint/resume report that shaped the sub-agent recovery slice (#2029), **@bevis-wong** for the long-running shell/task liveness report (#1786), **@shuxiangxuebiancheng** for the third-party OpenAI-compatible path report (#1874), **@hongqitai** and **@cyq1017** for the follow-up path-suffix PR review trail (#2508, #2506), **@NASLXTO** and **@wuxixing** for the large-workspace startup reports (#697, #1827), and **@linzhiqin2003** and **@merchloubna70-dot** for earlier context-cap and startup-diagnosis work that shaped this bounded fallback. Thanks also to **@cyq1017** for the MCP underscore-server-name fix and Xiaomi MiMo pricing (#2747, #2744, #2750, #2731) and **@puneetdixit200** for independently diagnosing and fixing the same MCP underscore issue (#2746, #2744), **@mvanhorn** for the hydrated deferred-tool render fix (#2757, #2648), and **@xyuai** for the Xiaomi MiMo Token Plan region documentation (#2756, #2735). Additional thanks to **@Implementist** for Plan prompt scrolling, wrapping, and display-width fixes, **@jrcjrcc** for the Windows sub-agent completion render-width fix, and **@punkcanyang** for the original `/init` implementation harvested through #2771/#2745. ## [0.8.53] - 2026-06-03 ### Added - **Hugging Face Inference Providers.** Added `huggingface` as a native provider route (`/provider huggingface`). Supports `HUGGINGFACE_API_KEY` or `HF_TOKEN` for auth, `HUGGINGFACE_BASE_URL` and `HUGGINGFACE_MODEL` for overrides, and `deepseek-ai/DeepSeek-V4-Pro` / `deepseek-ai/DeepSeek-V4-Flash` as default models. Org-prefixed model IDs pass through. ### Fixed - **Agent-mode shell error copy.** The missing-tool error for shell tools now directs users to `allow_shell = true` instead of nudging toward YOLO mode. `/config` surfaces `allow_shell` in the Permissions section. - **Provider description.** `/provider` command description is now neutral instead of recommending specific providers. ### Community Thanks to **@xyuai** for provider persistence, `/logout` scope clarification, provider picker key replacement, and MiMo auth cleanup work (#2714, #2715, #2717, #2718), and **@RefuseOdd** for configurable `path_suffix` support on OpenAI-compatible endpoints (#2558). ## [0.8.52] - 2026-06-03 ### Added - **SiliconFlow China region provider.** Added the `siliconflow-CN` provider variant for the China regional endpoint, sharing the existing `[providers.siliconflow]` credentials and `SILICONFLOW_API_KEY` slot instead of creating a second credential namespace; the provider picker and registry docs now expose the regional route explicitly (#2588, #2615). - **Multimodal `/attach` image forwarding.** Attached images are now sent as OpenAI-compatible `image_url` content blocks so multimodal providers can actually see image attachments (#2584, #2587, #2607). - **Sub-agent lifecycle hooks and runtime metadata.** Sub-agent spawn/complete hook events, mode-change runtime messages, mode metadata on turns, localized context-inspector strings, and drag-to-resize sidebar width are included in this release slice. ### Fixed - **Sub-agents now auto-cancel after stale heartbeats.** Running sub-agents track manager-visible progress and are auto-cancelled after the configurable `[subagents] heartbeat_timeout_secs` window (default 300s), releasing their concurrency slot and unblocking parent turns that would otherwise wait forever (#2603, #2614, #2620). - **Work panel state survives transient lock misses.** The sidebar caches the last successful Work summary so checklist and strategy progress no longer disappear into "Work state updating..." while the engine briefly owns the shared todo/plan locks (#2606, #2616). - **SiliconFlow-CN no longer breaks main.** Filled the missing CLI provider exhaustiveness arms and removed the duplicate/unreachable TUI config arms left by the #2615 landing; direct auth now stores the China-region variant in the shared SiliconFlow provider table (#2616, #2618, #2619). - **v0.8.51 image-attach closure corrected.** The `/attach` multimodal fix landed after the v0.8.51 tag, so this release is the first version that actually contains it for users installing from the published release line (#2584, #2607). - **Legacy SSE MCP reconnects are retryable again.** Closed or reset `POST /messages` requests on stale legacy SSE sessions now trigger the same reconnect-and-retry path as closed SSE streams, removing a release-gate flake and matching the intended recovery behavior (#2597). - **Cache-hit cost accounting uses one telemetry source.** Mixed DeepSeek `prompt_cache_hit_tokens` and OpenAI-style `cached_tokens` usage payloads no longer infer cache misses from the wrong hit count, avoiding inflated TUI cost estimates on cached DeepSeek turns (#2567, #2609). - **Cygwin/MSYS2 config paths honor exported `$HOME`.** CodeWhale and legacy DeepSeek config roots now prefer a non-empty `$HOME` before falling back to the platform home resolver, while `CODEWHALE_HOME` remains the strongest explicit override (#2369, #2610). ### Community Thanks to **@xyuai** (#2587), **@IcedOranges** (#2584), **@BH8GCJ** (#2588), **@shenjackyuanjie** (#2618, #2619), **@idling11** (#2606, #2616), **@AresNing** (#2578), **@caiyilian** (#2567), **@buko** (#2369), **@gordonlu**, **@encyc**, and **@simuusang** (#2603, #2620) for reports, patches, retesting, and release-stabilization signals that shaped this pass. ## [0.8.51] - 2026-06-02 ### Added - **Arcee AI as a direct provider.** New `[providers.arcee]` config block and `ARCEE_API_KEY` / `ARCEE_BASE_URL` / `ARCEE_MODEL` environment variables, wired through CLI auth (`codewhale auth set --provider arcee`), the TUI provider picker, and the model registry. The default direct-API model is `trinity-large-thinking` (reasoning-capable, 262K context and 262K max output); `trinity-large-preview` (262K context, non-reasoning) and `trinity-mini` (128K context) are also selectable. OpenRouter's `arcee-ai/trinity-large-thinking` route remains separate. - **Arcee Cloudflare-WAF compatibility.** The opening turn to the Arcee gateway uses a benign read-only tool surface (`read_file`, `list_dir`, `file_search`, `grep_files`, `git_status`, `git_diff`, `checklist_write`, `update_plan`) and splits example payloads such as `python -c …` out of the system prompt, so the WAF does not reject the first request; the full tool catalog stays reachable through tool-search. `trinity-large-thinking`'s `reasoning_content` is recognized and replayed on tool-call turns. - **Expanded model catalog.** Added context-window, max-output, and reasoning-capability metadata for additional model IDs, including `qwen/qwen3.6-flash`, `qwen/qwen3.6-plus`, `qwen/qwen3.6-max-preview`, and Xiaomi MiMo v2.5 chat/ASR/TTS variants; `trinity-large-preview`'s context window was corrected to 262K. - **Provider-aware model picker.** The picker groups models by provider, shows per-model hints, and remembers a saved model per provider. ### Changed - **Auto-compaction is now percentage- and model-aware.** The per-model threshold helper is `compaction_threshold_for_model_at_percent(model, percent)` (replacing the effort-based variant), and the default `auto_compact_threshold_percent` is 80%. Auto-compaction defaults on for models with a context window of 256K or smaller and stays opt-in for 1M-token models (e.g. DeepSeek V4) to protect prefix-cache economics, unless the user has explicitly set `auto_compact`. - **Clearer provider/gateway errors.** HTTP error bodies are sanitized before display — HTML interstitials and Cloudflare "Access Denied" pages collapse to a one-line reason (with the ray/error ID) instead of dumping raw markup into the transcript — and 403s are split into authentication vs. authorization (gateway/WAF block) categories. - The invalid-model error now names the active provider and lists Arcee among the options. - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - **The session "cycle" / checkpoint-restart system.** Removed the `/cycles`, `/cycle `, and `/recall` commands, the `recall_archive` tool, the cycle-handoff briefing prompt, the sidebar "cycles" lines, and the `cycle_manager` engine plumbing (`EngineConfig.cycle`, `Event::CycleAdvanced`, seam-manager cycle thresholds and flash briefings). Long sessions no longer auto-reset their context at a fixed token boundary — reclaim budget with `/compact` or model-aware auto-compaction instead. Existing on-disk cycle archives are left untouched but are no longer read or written. ### Fixed - Assistant turns no longer leave an orphaned role glyph (the stray "blue dot") when a turn streams only whitespace between reasoning and a tool call. - Scrolling the mouse wheel over the right-hand sidebar no longer leaks into the transcript scroll. - The sidebar hover tooltip now appears only for truncated lines, sits below the cursor, and uses a neutral surface color instead of the warning-orange highlight that overlapped neighbouring rows. - Corrected the README's description of the Constitution (Article VII is the hierarchy itself; Article II's truth duty overrides even a user request) to match `prompts/base.md`. - Repaired release-blocking unit and integration tests left failing by the cycle-removal and compaction-threshold refactors (relay instruction, model-reject message, compaction budget, mock-LLM threshold helper). - Fixed DEC private-mode CSI fragment leakage into composer text after terminal resets, restoring clean prompt editing (#2592). - The engine now recovers from turn-level panics instead of killing the main event loop, keeping the session alive through transient failures (#2583, #1269). - Deeply nested files are now discoverable via @-mention and Ctrl+P file picker; the default walk depth was relaxed to handle monorepo layouts (#2488). - Command-palette selection stays visible when scrolling through long lists instead of scrolling off-screen (#2590). - exec_shell child processes now inherit .NET/NuGet and Windows app-data environment variables, fixing toolchain resolution on Windows (#1857). - A warning is emitted when shell/sandbox config keys are nested under unknown top-level sections instead of being silently ignored (#2589). - Diff-render now preserves leading whitespace in patch content lines, fixing an extra-space regression in PR previews (#2591). Thanks @zlh124. - Model selection from the /model command now persists per-provider across restarts, with a warning when persistence fails. ### Community Thanks to **@zlh124** (#2591) and **@reidliu41** (#2601) for the fixes harvested into this release. Thanks also to **@idling11** (#2602), **@gordonlu** (#2585), **@cyq1017** (#2593), **@xyuai** (#2587, #2584), and **@IcedOranges** (#2584) for reports, drafts, and investigations that shaped this release cycle. ## [0.8.50] - 2026-06-02 ### Added - Added a Windows NSIS installer release artifact and classroom/lab deployment checklist, harvested from #2045 for #1987. The release workflow now builds `CodeWhaleSetup.exe` from the canonical Windows binaries, and the installer adds/removes only the exact current-user PATH entry. - Added deterministic session timestamps in session listings, receipt-export boundary docs, and current-model turn metadata for routed/auto sessions. - Added exact AtlasCloud provider-hinted model ID pass-through for explicit `vendor/model-id` selections, harvested from #2569 without freezing a brittle provider catalog. - Added Xiaomi MiMo speech/TTS support with a `codewhale speech` CLI command, `tts` tool alias, and config wiring for voice-design and voice-clone models, harvested from #2560. - Added a three-zone immutable prefix diagnostic layer (FrozenPrefix Phase 2) that logs cache-prefix drift at debug level without blocking requests, harvested from #2514. - Added a Cache Guard CI integration test suite simulating prefix-cache behaviour across nine scenarios, gated behind `CODEWHALE_CACHE_GUARD=1`, harvested from #2503. - Added a plan-mode byte-stability invariant test verifying that the tool catalog head remains byte-identical across mode toggles, harvested from #2519. - Localized all 15 `/queue` command messages across 7 shipped locales, harvested from #2568. - Added localized `FanoutCounts` MessageId for i18n of the aggregate worker stats line in fanout cards, harvested from #2566. - Added contribution gate CI workflows (PR gate, issue gate, contributor approval) with a dry-run mode, harvested from #2565. ### Changed - Hardened theme repainting and sidebar color use so theme switches do not leave stale Whale-dark panel colors behind. - Made legacy config migration visible when CodeWhale copies old DeepSeek-era config into the CodeWhale config path. ### Fixed - Fixed `/context` to use the effective routed model for context-window budgeting, so DeepSeek V4 routes report the 1M-token window and legacy DeepSeek routes keep the 128K fallback. - Fixed npm wrapper version output so `--version` prefers the installed binary version instead of stale package metadata when both are available. - Fixed multiline composer arrow navigation so holding Up/Down at the first or last line no longer replaces the current draft with prompt history. - Fixed foreground `exec_shell` output collection so timeout and inherited-pipe cleanup cannot wedge later tool calls behind the global tool lock. - Clarified the English DeepSeek account-balance footer chip from `bal` to `balance` so it is less likely to be mistaken for session spend. - Fixed truncated subagent tool calls and repeated truncated subagent responses so they return model-visible errors instead of silently failing. - Moved Paste to the first position in the right-click context menu so users copying text from the output area can paste with a single left-click instead of navigating past cell-specific actions. ### Community Thanks to **@ZhulongNT** (#2045), **@cyq1017** (#2521, #2536, #2537, #2559, #2562, #2563, #2564), **@HUQIANTAO** (#2527, #2519, #2503), **@lucaszhu-hue** (#2569), **@idling11** (#2573), **@encyc** (#2514), **@xyuai** (#2560), **@gordonlu** (#2568, #2566), and **@nightt5879** (#2565) for the work harvested into this release pass. Thanks also to issue reporters and verification helpers including **@New2Niu** (#2561), **@buko** (#2533, #2369), **@wywsoor** (#2494), **@ctxyao** (#2556), **@Dr3259** (#2380), **@caiyilian** (#2567), and **@chinaqy110** (#2571) for reports and acceptance details that shaped these fixes, plus the WeChat/Chinese UX reports relayed during the final triage pass. ## [0.8.49] - 2026-06-01 ### Added - Added the missing `[providers.moonshot]` example block for Moonshot/Kimi, documented `completion_sound`, and refreshed the tool-surface docs for the current registry, including `finance`, `web.run`, git history tools, memory, OCR, and other registered tools. ### Changed - Hardened prefix-cache fingerprints to hash API-visible tool schema details, not just tool names, so schema and description drift invalidates cached prefixes before it can confuse model calls (#2264). - Kept `finance` registered independently from web-search tools and prevented duplicate web/patch tool registration in agent and YOLO modes. ### Fixed - Fixed the DeepSeek V4-Pro cost estimate after the 2026-05-31 pricing cutoff: the post-promotion official rate remains one quarter of the original price, so CodeWhale no longer shows roughly 4x too much after June 1 (#2489). - Fixed Kimi/Moonshot tool schema normalization by moving parent `type` fields into `anyOf`/`oneOf` items, with regression coverage for nested schema shapes that could otherwise still fail Kimi validation (#2438). - Fixed raw ANSI/SGR fragments leaking into footer, shell-label, and sidebar activity text during active tool execution (#2481). - Fixed `[tui]` config parsing when `status_items` is omitted, restoring the documented default footer order for older and hand-written configs (#2483). - Fixed a shell env-scrubbing test so it does not depend on the user's default shell understanding POSIX parameter expansion. - Removed stale `qwen/qwen3.7-max` references left in `config.example.toml` after the v0.8.48 preset removal. ### Community Thanks to **@idling11** (#2480, #2485), **@reidliu41** (#2493), **@hongqitai** (#2495), and **@encyc** (#2477) for the fixes and reliability work harvested into this release. Thanks also to reporters and verification helpers whose issues shaped the release: **@A-Corner** (#2438), **@taiwan988** (#2483), **@AiurArtanis** (#2489), and **@Hmbown** (#2481). ## [0.8.48] - 2026-05-31 ### Added - **Recent large OpenRouter model presets.** Added completions, aliases, routing metadata, and docs for Arcee Trinity Large Thinking, MiniMax M3, Xiaomi MiMo v2.5, Qwen 3.6 open-weight models, Kimi K2.6, GLM 5.1, Tencent Hy3, Gemma 4, and Nemotron (#2461). - **Provider and web-search expansion.** Added Xiaomi MiMo provider support, SiliconFlow, AtlasCloud static models, Volcengine Ark search, Baidu AI Search, provider-picker coverage, and richer custom-provider docs (#2246, #1868, #2421, #2429, #2371, #2394, #2287). - **Workflow and tool ergonomics.** Added the external-tool abstraction, pluggable TUI tool registry, custom slash-command allowed-tools enforcement, opt-in Unix socket hook sink, message-submit transform hooks, tool-cache introspection, and cache warmup-key tracking (#2294, #2420, #2326, #2430, #2434, #2423, #2424). - **TUI workflow features.** Added `/purge`, `/hunt`, thinking fold/unfold, terminal-transparent/Solarized Light/Claude themes, footer branch display, macOS notifications, intent summaries before approval prompts, and the mobile runtime smoke/QR workflow (#2387, #2306, #2385, #2276, #2270, #2267, #2347, #2260, #2389, #2403). - **Platform and localization coverage.** Added RISC-V prebuilt-binary support, Vietnamese localization, Java/Vue language-server defaults, runtime event envelopes, task migration/env isolation fixes, and state-message parent IDs for future forks (#2383, #2358, #2367, #2252, #2272, #2308). - Google Gemini is its own backend (`/provider google`) on the official OpenAI-compatible route with thought-signature capture/replay and fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins as a separate credential-plane provider: consent-gated read-only import of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH` precedence; requests fail closed until the cloud-code wire protocol is implemented. ### Removed - **Qwen 3.7 Max OpenRouter preset.** Removed from the model registry, docs, and examples. Qwen 3.7 Max is a hosted model, not open-source; the preset will return when an open-weight Qwen 3.7 release ships. ### Changed - **Release hardening.** CI now runs clippy/docs checks, web frontend lint and type checks, provider-registry drift checks, broader crate docs, and a large unit-test pass across core, MCP, TUI core, app-server, and web helpers (#2443, #2444, #2274, #2446-#2460, #2440, #2441, #2450, #2448, #2454). - **Prompt, context, and model routing behavior.** Stabilized project-context pack ordering, exposed the auto route in turn metadata, allowed embedders to override or inline constitutional instructions, moved volatile environment context below the prompt boundary, and used the effective model for compaction budgeting (#2418, #2410, #2356, #2311, #2314, #2437). - **Execution policy foundation.** Added typed ask-rule groundwork and kept `task_shell_start` gated behind `allow_shell`, preparing the permission UI path without broadening default shell access (#2404, #2384). ### Fixed - **Windows and shell reliability.** Suppressed alt-screen logging on Windows, added the Windows batch launcher path, kept task shell tools eagerly loaded, loaded exec-shell companion tools consistently, covered controlling-terminal behavior, and improved shell tool availability errors (#2259, #2295, #1861, #2271, #2331, #2414, #2412). - **Session and transcript durability.** Fixed hidden-worktree discovery saturation, stalled in-progress turn recovery, session persistence truncation, cached-transcript user-message highlighting, large tool-output receipting, session-detail block serialization, and deterministic composer history flushing (#2273, #2329, #2283, #2395, #2386, #2297, #2265, #2375). - **Provider and UI polish.** Accepted custom model IDs in `/model` for non-DeepSeek providers, fixed Feishu per-chat model switching, localized context-menu labels, updated terminal tab naming, kept picker selections visible, allowed slash-space composer messages, and improved PDF text cleanup (#2280, #2149, #2320, #2319, #2324, #2316, #2266). - **Security and dependency hygiene.** Bumped `tar` and `qs`, trusted fake-IP placeholder ranges only when explicitly configured, decoded Bing result URL entities, fixed legacy MCP SSE connections, and replaced manual tool error display code with `thiserror` derives (#2364, #2425, #2355, #2245, #2301, #2442). ### Community Thanks to contributors whose PRs landed or were harvested in this release: **@cy2311** (#1861), **@LING71671** (#1902, #2287, #2292), **@axobase001** (#1968, #2296, #2297, #2298), **@dzyuan** (#1993), **@mvanhorn** (#2107, #2236), **@malsony** (#2129), **@gaord** (#2133, #2265, #2285), **@yuanchenglu** (#2149), **@idling11** (#2161, #2266, #2306), **@h3c-hexin** (#2245, #2311, #2313, #2314, #2354, #2355, #2356), **@AdityaVG13** (#2246), **@Sskift** (#2248), **@cyq1017** (#2252, #2332, #2375), **@HUQIANTAO** (#2257, #2267, #2283, #2384, #2385, #2389, #2403, #2440-#2458, #2460), **@New2Niu** (#2260), **@AiurArtanis** (#2270), **@Lee-take** (#2272), **@nightt5879** (#2274, #2344, #2347, #2373), **@AresNing** (#2278, #2318/#2434), **@AccMoment** (#2281), **@reidliu41** (#2291, #2316, #2324, #2357, #2366, #2386, #2431), **@aboimpinto** (#2290, #2294, #2295, #2326, #2433), **@zhuangbiaowei** (#2301), **@donglovejava** (#2302, #2329, #2330, #2331), **@hongqitai** (#2308, #2432), **@zlh124** (#2319, #2320, #2325), **@encyc** (#2336, #2338), **@Implementist** (#2426/#2429, #2439), **@lihuan215** (#2333/#2430), **@LeoAlex0** (#2388, #2395), **@jimmyzhuu** (#2371), **@rockyzhang** (#2383), **@mo-vic** (#2387), **@hufanexplore** (#2367), **@hoclaptrinh33** (#2358), and **@BryonGo** (#2437). Thanks also to reporters and verification helpers whose issues, patches, screenshots, logs, or retest requests shaped this release: **@buko** (#2359, #2360, #2369, #2469), **@yyyCode**, **@gaslebinh-glitch**, **@Dr3259**, **@lpeng1711694086-lang**, **@VerrPower**, **@yan-zay**, **@jretz**, **@Neo-millunnium**, **@caeserchen**, **@T-Phuong-Nguyen**, **@zhyuzhyu**, **@0gl20shk0sbt36**, **@hatakes**, **@goodvecn-dev**, **@bevis-wong**, **@PurplePulse**, and **@nbiish**. ## [0.8.47] - 2026-05-26 ### Added - **Closed-loop verification gate, runtime goal tools, DuckDuckGo default web search, Xiaomi MiMo, global AGENTS.md fallback, `/new`, composer selection, transcript copy cleanup, CNB mirror support, and Docker toolbox docs** shipped in the published v0.8.47 release. ### Changed - **DeepSeek-first release framing, project-context logging, state-root migration, CodeWhale README paths, and reasoning-locale behavior** were finalized for the v0.8.47 release. ### Fixed - **Provider picker scrolling, auto model restore, cache-inspect hashing, insecure LAN provider guard, large tool-output compaction, queued-message ordering, shell/Yolo startup handling, Windows alt-screen logging, and tooltip contrast** were fixed in the v0.8.47 release. ### Community Thanks to contributors credited in the v0.8.47 GitHub Release, including **@Fire-dtx**, **@imkingjh999**, **@harvey2011888**, **@victorcheng2333**, **@IIzzaya**, **@PurplePulse**, **@cyq1017**, **@knqiufan**, **@Colorful-glassblock**, **@hongqitai**, **@EmiyaKiritsugu3**, **@aboimpinto**, **@HUQIANTAO**, **@mvanhorn**, **@LING71671**, and **@reidliu41**. ## [0.8.46] - 2026-05-26 ### Added - **`CODEWHALE_*` env aliases.** `CODEWHALE_PROVIDER`, `CODEWHALE_MODEL`, and `CODEWHALE_BASE_URL` are public product-scoped aliases that take precedence over the legacy `DEEPSEEK_*` forms. The `DEEPSEEK_*` names remain accepted for back-compat. - **Platform archive bundles.** Release artifacts now ship as per-platform archives (`tar.gz` for Linux/macOS, `.zip` for Windows) containing both `codewhale` and `codewhale-tui` binaries plus an install script. No more downloading two loose files and guessing which ones to pick (#2193). - **Windows portable archive.** `codewhale-windows-x64-portable.zip` ships the two binaries without an install script for USB-stick distribution (#2193). - **Web install download tile.** The website install page now shows a platform-aware download tile with arch detection, SHA256 checksum display, and China mirror links, instead of burying the download behind the Cargo instructions (#2192). - **Whale dark palette refresh.** Better contrast and layer separation across the TUI color scheme (#2197). - **Auto-collapse finished sub-agents.** Completed sub-agent sessions now collapse automatically in the sidebar, reducing noise during long sessions (#2195). - **Shell-running status chip.** A `⏳ shell running` chip appears in the TUI footer while background shell tasks are active (#2194). - **Sandbox process hardening (Linux).** `PR_SET_DUMPABLE=0`, `NO_NEW_PRIVS`, and `RLIMIT_CORE=0` are applied at shell startup to harden child processes against inspection and privilege escalation (#2183). - **CONTRIBUTING.md cross-links.** Issue and PR templates are now cross-linked from CONTRIBUTING.md to improve contributor onboarding (#2203). ### Changed - **DeepSeek-first focus.** v0.8.46 refocuses on delivering the highest-quality experience on DeepSeek first. Additional first-class provider paths are planned for v0.9.0 after the core DeepSeek workflow is solid. ### Fixed - **Model name casing preserved.** `normalize_model_name_for_provider` no longer lowercases user-set model names such as `DeepSeek-V4-Flash`, preventing API lookup failures on case-sensitive backends (#2109). - **Esc in model picker applies selection.** Dismissing the model picker with Esc now applies the last-highlighted choice instead of reverting (#2196). - **Web install downloads both binaries.** The `install-binary.tsx` snippet now fetches both `codewhale` and `codewhale-tui`, fixing the `MISSING_COMPANION_BINARY` trap on fresh npm installs (#2191). - **`grep_files` skips large directories.** The pure-Rust search tool now skips known-large directories (`.git`, `node_modules`, `target`) before walking, preventing hangs on deep or slow filesystems. - **Version-update hint uses semver.** The update notification in the footer now compares versions semantically instead of lexicographically, so `0.8.10 > 0.8.9` is recognized correctly. - **CVE-2026-8723 in feishu-bridge.** Bumped `qs` to `>=6.15.2` in the Feishu bridge integration (#2198). ### Community Thanks to new contributors whose PRs landed in this release: **@donglovejava** (#2154, #2163, #2166, #2167, #2168), **@encyc** (#2152), **@saieswar237** (#2178), **@sximelon** (#2174), **@nanookclaw** (#2135), **@Sskift** (#2119), **@xin1104** (#2105), **@mrluanma** (#2059), **@Lellansin** (#2055), **@zhuangbiaowei** (#2145), **@aboimpinto** (#1872), and continuing contributors **@reidliu41**, **@cyq1017**, **@idling11**, **@h3c-hexin**, **@wdw8276**, **@zlh124**, and **@jeoor**. ## [0.8.45] - 2026-05-25 ### Added - **RLM session objects.** `rlm_open` can now load `session://` refs, exposing the active prompt, history, and session data as symbolic objects inside RLM REPLs (#2047). - **Command palette voice input.** The command palette can launch a configured speech-to-text helper and show footer status while transcription runs (#2047). - **Moonshot/Kimi provider.** Moonshot/Kimi is now a first-class provider, including API-key auth, model completion, CLI auth, secret-store integration, and optional Kimi CLI credential reuse. - **Deterministic whale-species sub-agent names.** Sub-agents now get stable, human-readable whale-species nicknames (e.g. "Beluga", "Orca") while preserving the raw agent ID in the popup (#2035, #2016). - **`/balance` command scaffold.** Registered the `/balance` slash command as a placeholder for future provider billing queries (#2035, #2019). - **Readable `/restore` snapshot labels.** Snapshot labels now include the originating user prompt so restore listings are easier to identify. Thanks @idling11 (#2111). - **Sidebar hover tooltips.** Truncated Work and Tasks sidebar lines now expose their full text on hover. Thanks @idling11 (#2110). ### Changed - **AGENTS.md is now maintainer-local.** The project instructions file no longer ships as a tracked repo file; it lives in maintainer-local ignored state (#2047). ### Fixed - **Sub-agent completion handoff compatibility.** Completion handoffs now use a chat-template-safe role and emit before terminal updates, fixing strict OpenAI-compatible/self-hosted backends and preserving transcript ordering. Thanks @h3c-hexin and @cyq1017 (#2057, #2120). - **Self-hosted context budgeting.** Sub-500K self-hosted model windows now keep a usable input budget instead of disabling preflight compaction after output reservation underflow. Thanks @h3c-hexin (#2060). - **Goal prompts start actionable.** Goal-start prompts now open in an actionable state instead of requiring an extra nudge. Thanks @cyq1017 (#2097). - **Composer session title display.** The composer chrome shows the current session title again and avoids grayscale luma overflow in debug builds. Thanks @wdw8276 (#2108). - **Approval prompts use a one-step confirmation flow.** Enter now commits the selected approval option directly, destructive warnings remain visible, and abort cancels the active turn instead of only denying the current tool call. Thanks @reidliu41 (#2143). - **Model picker selection survives Esc.** Dismissing the model picker with Esc no longer loses the highlighted selection. Thanks @reidliu41 (#2056). - **Moonshot/Kimi sessions launch from the dispatcher.** The `codewhale` wrapper now includes Moonshot/Kimi in the TUI provider allowlist, so `codewhale --provider moonshot --model kimi-k2.6` reaches the TUI instead of stopping after config resolution. - **Slash recovery no longer restores command tails in the composer.** Resuming a session or recovering from a crash no longer leaves stale slash-command text (e.g. `/sessions`) in the composer input (#2047, #2032). - **Remembered tool approvals now update the live active turn.** When the "remember" checkbox is set on an approval dialog, the active turn's auto-approve flag flips immediately instead of waiting for the next turn. Thanks @gaord (#2047, #2041). - **YAML block scalars in SKILL.md frontmatter.** Multi-line descriptions using `>` or `|` indicators are now parsed correctly — folded block scalars join non-empty lines with spaces, literal scalars preserve newlines, and all three chomping modes (strip/clip/keep) are supported. Thanks @zlh124 (#1908, #1907). - **User messages highlighted in the transcript.** User-authored messages now render with a full-row background in the live TUI transcript, making it easier to scan prior turns. Assistant and system messages are unaffected. Thanks @reidliu41 (#1995, #1672). - **Cancellable `list_dir` and `file_search`.** Long directory walks and file searches now respond to user cancel/stop requests with a 30-second fallback timeout, preventing the TUI from hanging on deep or slow filesystems (#2035). ### Community - **README contributor acknowledgements resynced.** The Thanks list now includes the latest contributor rows for @donglovejava, @encyc, @saieswar237, @sximelon, @nanookclaw, @Sskift, @xin1104, @mrluanma, @Lellansin, and @zhuangbiaowei, while preserving the existing @jeoor acknowledgement in the consolidated list. ## [0.8.44] - 2026-05-24 ### Added - **`codew` convenience alias.** `codew` is a short-form command that silently forwards to `codewhale`. Six fewer keystrokes, same binary. Ships with the Rust `codewhale-cli` crate and the npm `codewhale` package (#2013). - **Session picker inline rename.** Press `r` in the session picker (Ctrl+R) to rename the selected session inline. Type the new title, Enter to confirm, Esc to cancel (#1600). - **Plan detail display.** The \"Plan Confirmation\" modal now shows the plan explanation and step list from `update_plan` so you can review what was proposed before accepting (#834). - **Agent team UX.** Delegate cards in the transcript now show human-readable roles (scout, builder, reviewer, verifier, executor) and the completion summary instead of raw `agent_xxx` IDs (#1981). - **`--continue` / `-c` CLI flag.** `codewhale --continue` resumes your most recent interactive session for the current workspace. ### Changed - **App state migrates to `~/.codewhale/`.** New installs write product-owned state (config, sessions, tasks, skills, logs, etc.) under `~/.codewhale/`. `~/.deepseek/` continues to work as a compatibility fallback — no data loss, no forced migration. `CODEWHALE_HOME` and `CODEWHALE_CONFIG_PATH` env vars are now supported alongside existing `DEEPSEEK_*` vars (#2011). - **Project config overlay prefers `.codewhale/config.toml`** before `.deepseek/config.toml`. Both are read; the CodeWhale root takes precedence. - **Doctor reports active state root** and whether legacy `~/.deepseek/` state is also present. - **README contributor acknowledgements are current for this release.** Thanks @jeoor, @LING71671, and @ousamabenyounes for the fixes and reports now reflected in the public credits. - **Harvested-contribution credit audit completed.** The README Thanks list now includes previously missed community helpers whose code, reports, or review notes were already credited in older changelog entries but not in the public contributor surface: @mvanhorn, @krisclarkdev, @tdccccc, @LittleBlacky, @AnaheimEX, @THatch26, @alvin1, @knqiufan, @IIzzaya, @duanchao-lab, @imkingjh999, @eng2007, @chennest, @kunpeng-ai-lab, @asdfg314284230, @maker316, @lalala-233, @muyuliyan, @czf0718, @MeAiRobot, @tiger-dog, @MMMarcinho, @lucaszhu-hue, @sandofree, @zhuangbiaowei, @NorethSea, @Jianfengwu2024, @Fire-dtx, @oooyuy92, @qinxianyuzou, @tyouter, @xulongzhe, @YaYII, @47Cid, and @JafarAkhondali. - **Harvest guidance now requires GitHub-visible attribution.** Maintainer harvests should preserve the original commit author where possible or add `Co-authored-by` trailers from the original PR commits, in addition to the existing `Harvested from PR #N by @handle` trailer and changelog credit. - **Enter now steers when busy-waiting.** When the model is busy but not actively streaming (waiting on tool results, sub-agents, or shell commands), pressing Enter tries to steer your message into the current turn instead of silently queueing it. During active streaming, Enter still queues to avoid interrupting in-flight reasoning (#2009). ### Fixed - **`/save` no longer creates repo-local `session_*.json`.** Default saves now go to the managed sessions directory instead of the current workspace. Explicit `/save path/to/file.json` exports still work as before (#2010). - **Boot-time session prune** caps managed sessions at 50 on every startup, preventing unbounded growth of `~/.codewhale/sessions/`. - **Checkpoint path resolution** no longer hardcodes `~/.deepseek/` — uses the resolved session directory instead. - **Plain startup no longer auto-opens the session picker.** `codewhale` and `codew` start in a fresh composer again even when saved sessions exist. Use `/sessions`, Ctrl+R, `--resume`, or `--continue` when you want to resume. - **Work sidebar now refreshes immediately** after `checklist_write`, `checklist_update`, and `update_plan` tool calls, matching the existing `todo_write` behavior instead of relying on the 2.5s periodic poll (#1787). ## [0.8.43] - 2026-05-24 ### Fixed - **`grep_files` now respects the cancellation token.** Long-running file searches cancel promptly instead of running to completion after the user aborts (#1839). Thanks @LING71671. - **npm installer stream-pause race condition fixed.** The install script now pauses HTTP response streams immediately, preventing early data loss that caused "Invalid checksum manifest line" errors (#1860). Thanks @jeoor. - **Ctrl+Z restores the last cleared composer draft.** Pressing Ctrl+Z in an empty composer recovers the text that was last cleared with Ctrl+U or Ctrl+S, matching the muscle memory users expect from other editors (#1911). Thanks @LING71671. - **Clipboard works on non-wlroots Wayland compositors.** The Linux clipboard path now tries `wl-copy` before `arboard`, fixing silent copy failures on niri, River, cosmic-comp, and GNOME mutter (#1938). Thanks @ousamabenyounes. ### Added - **`/goal` remains the persistent objective surface.** Use `/goal ` to set a goal and `/goal done` to mark it complete. Goal status appears in the Work sidebar with elapsed time, but it does not change Plan / Agent / YOLO mode or approval behavior. A tabbed Ralph-style Goal loop is deferred to v0.8.44 (#2007). - **Post-turn receipts cite evidence for every completed turn.** When a turn finishes, a receipt line shows in the transcript tail with a summary of tool calls, file changes, and evidence that supports the agent's claims. Tool evidence is collected per-turn and flushed on new dispatch. - **Stall reason classification.** When a turn has been running for more than 30 seconds, the footer now appends a classified reason: "waiting for model", "tools executing", "sub-agents working", "compacting context", or "waiting — no recent activity". - **Decision card widget for structured user input.** When Brother Whale needs a choice, it surfaces a bordered card with numbered options, keyboard navigation (1-9 / j/k / arrows), and Enter/Esc to confirm or cancel. - **Tasks sidebar now shows fuller turn IDs and supports copy-to-clipboard.** Turn ID prefixes are widened from 12 to 16 characters for disambiguation, background job status is presented as "X running, Y completed" instead of ambiguous "X active (Y running)", and `y` / `Y` yank affordances copy the current turn ID or full status line to the system clipboard (#1975). ### Changed - **Contributor count and acknowledgement surfaces refreshed.** The website fallback contributor count now reflects 98 live GitHub contributors (up from the stale 91). All three README translations (English, 中文, 日本語) now include 30+ previously unlisted contributors whose PRs were merged since April 2026. - **README and web surface rebrand refinements.** Crate descriptions, npm package text, and website copy now consistently position CodeWhale as open-model-first and provider-spanning, with DeepSeek V4 as the first-class path. - **New contributor names added to README acknowledgements.** Thanks to @Apeiron0w0, @aqilaziz, @ChaceLyee2101, @ComeFromTheMars, @CrepuscularIRIS, @dst1213, @eltociear, @fuleinist, @greyfreedom, @h3c-hexin, @heloanc, @hxy91819, @J3y0r, @JiarenWang, @jinpengxuan, @KhalidAlnujaidi, @laoye2020, @lbcheng888, @linzhiqin2003, @Liu-Vince, @lixiasky-back, @pengyou200902, @punkcanyang, @Rene-Kuhm, @SamhandsomeLee, @sockerch, @sternelee, @Wenjunyun123, @whtis, and @wuwuzhijing for the translations, typo fixes, docs polish, and small UX improvements that landed across the 0.8.42 → 0.8.43 cycle. ### Security - **Thinking blocks can be collapsed/expanded via keyboard.** Space on an empty composer toggles the focused thinking cell between collapsed and expanded, complementing the existing mouse right-click context menu (#1972). - **Sub-agent completion events no longer delayed to the next turn.** The turn loop now drains late-arriving sub-agent completions at the final checkpoint before breaking, so child-agent sentinels surface immediately instead of appearing in the following turn (#1961). - **`codewhale doctor` now referenced correctly in SSE timeout errors.** The error message shown when SSE streams fail to connect now points users to `codewhale doctor` (not the legacy `deepseek doctor`). ## [0.8.42] - 2026-05-24 ### Changed - **CodeWhale now ships with the Brother Whale agent identity prompt.** The built-in system prompt frames the agent as trusted, calm, careful, and responsible, and adds the coordination principle that great intelligence creates spaces where future intelligences can work together. - **CodeWhale positioning is clarified as DeepSeek-first and open-model oriented.** README, rebrand notes, crate metadata, and npm package text now describe CodeWhale as an agentic terminal for open source and open-weight coding models while preserving the official DeepSeek provider as first-class. - **Model auto-routing is documented separately from TUI modes.** README and modes docs now reserve "mode" for Plan / Agent / YOLO, describe `--model auto` as model/thinking routing, and name the fast `deepseek-v4-flash` thinking-off seam as Fin. - **Rebrand shim docs now match the v0.8.x transition window.** The npm and migration notes no longer imply the legacy `deepseek-tui` package/shims expired immediately after v0.8.41. ### Fixed - **User-authored messages render as literal plain text.** Leading whitespace, whitespace-only lines, repeated spaces, and Markdown-looking `#` / `-` text now survive in transcript history, while assistant messages still render Markdown normally. - **English turns stay English after localized context.** The Brother Whale identity and base language rules no longer inject native-script examples into the English prompt path, and the prompt now calls out localized READMEs, issue text, file contents, and tool results as data rather than language signals. - **Stream decode failures no longer leave the turn visually stuck.** The UI now marks an active turn failed and flushes live cells as soon as the engine emits a stream error, so the sidebar/footer recover without requiring Ctrl+C (#1960). - **RLM contexts now expose `_ctx`.** Persistent RLM REPLs bind `_ctx` as a compatibility alias for the loaded source alongside `_context` and `content`, and the prompt/docs call out the exact names (#1962). - **`handle_read` is easier to recover from.** The tool keeps accepting full `var_handle` objects directly, adds `introspect: true` for size/projection hints, and validation failures now include copy-pasteable examples (#1963). - **The help picker keeps the selected row visible while scrolling.** `/help` now budgets against the real modal body height, wraps Up/Down navigation, and uses a stronger selected-row highlight (#1964). - **Unicode `git_status` paths stay readable.** Chinese and other non-ASCII repository paths now survive status parsing and display cleanly (#1936, #1953). - **Project-local and configured skills appear in the slash menu.** Workspace skills and configured skill directories now feed the command picker instead of only the bundled set (#1955, #1956). - **Repeated Tab mode switching no longer stacks composer-obscuring toasts.** The mode-switch notification now deduplicates instead of accumulating rows over the composer (#1926, #1957). - **Local tool UX surfaces are clearer.** `github_close_pr` now has the same guarded closure workflow as issue close, `handle_read` redirects artifact refs to `retrieve_tool_result`, Plan handoffs use plainer wording, and shell rows/sidebar tasks show the actual running command instead of placeholder labels. ### Thanks Thanks to **cyq ([@cyq1017](https://github.com/cyq1017))** for the Unicode `git_status`, local/configured skill discovery, and mode-switch toast fixes in #1953, #1956, and #1957. Thanks to **Reid ([@reidliu41](https://github.com/reidliu41))** for the help picker scrolling and selection fix in #1964. ## [0.8.41] - 2026-05-23 ### Changed - **Project renamed to codewhale.** The canonical CLI dispatcher is now `codewhale` (was `deepseek`) and the TUI runtime is `codewhale-tui` (was `deepseek-tui`). The 14 workspace crates are renamed from `deepseek-*` / `deepseek-tui-*` to `codewhale-*` / `codewhale-tui-*`. The npm wrapper package is now `codewhale` (was `deepseek-tui`). See [docs/REBRAND.md](docs/REBRAND.md) for migration notes. - **DeepSeek provider integration is unchanged.** `DEEPSEEK_*` env vars, model IDs (`deepseek-v4-pro`, `deepseek-v4-flash`, the legacy `deepseek-chat` / `deepseek-reasoner` aliases), the `https://api.deepseek.com` host, and the `~/.deepseek/` config directory are all preserved. ### Deprecated - The `deepseek` and `deepseek-tui` binary names continue to ship as tiny shims that print a one-line warning and forward argv to the renamed binaries. They will be removed in v0.9.0. - The `deepseek-tui` npm package continues to publish for one release cycle as a no-`bin` deprecation shim whose postinstall directs users to `npm install -g codewhale`. It will be removed in v0.9.0. ### Fixed - **Windows CI spillover tests are isolated.** Tool-result deduplication tests now use a temporary spillover root guarded by the existing global spillover mutex, removing the shared-state race that made Windows CI fail unrelated PRs (#1943). - **Terminated sub-agents keep `agent_eval` recoverable.** Evaluating a completed child session now returns the available transcript result instead of losing the final output (#1738, #1928). - **Bare `@/` completions no longer freeze the TUI.** File-mention completion skips bare separator and dot tokens so Windows/WSL2 workspaces do not trigger an eager 4096-entry filesystem walk on the UI thread (#1921, #1929). - **Enter paths avoid synchronous UI-thread waits.** Composer history writes, offline queue persistence, feedback URL launching, and clipboard fallback helpers now run off the hot Enter path where appropriate (#1927, #1931, #1940, #1941, #1944). - **tmux and screen sessions stop idling as terminal activity.** Terminal multiplexers now force low-motion behavior and pin the fallback footer label so passive animations do not trip activity monitors (#1925, #1942). - **Composer sanitization catches OSC 8 and Kitty fragments.** The input sanitizer now strips common hyperlink and keyboard-protocol fragments that leaked into drafts while preserving ordinary prose (#1915, #1933). - **The Work sidebar hides stale completed tasks.** Terminal task records older than the current session and outside the recent-completion window no longer crowd active Work sidebar rows (#1913, #1930). - **V4 Pro pricing docs reflect permanent rates.** The English, Simplified Chinese, and Japanese READMEs now describe the V4 Pro pricing change as permanent instead of temporary (#1923, #1932). ### Thanks Thanks to **OpenWarp ([@zerx-lab](https://github.com/zerx-lab))** for prioritizing codewhale support and collaborating on terminal-agent UX. Thanks to **[@leo119](https://github.com/leo119)** for the update-command documentation lineage now preserved through the rename. ## [0.8.40] - 2026-05-21 ### Added - **Configurable sub-agent per-step API timeout.** A new `[subagents] api_timeout_secs` setting in `~/.deepseek/config.toml` controls how long each sub-agent step will wait on a DeepSeek `create_message` response before falling back. The value is clamped to `1..=1800`; `0` or unset preserves the legacy 120-second default, so existing installs see no behavior change. Long-thinking children (e.g. heavy plan or review work behind `agent_open`) can extend the timeout without recompiling (#1806, #1808). - **Delegated file-write permissions for write-capable sub-agent roles.** `implementer` and `custom` sub-agents may now run `Suggest`-level write tools (`write_file`, `edit_file`, `apply_patch`) without the parent runtime being auto-approved. Read-only stances (`explore`, `plan`, `review`, `verifier`) and the default `general` role still bounce approval-gated tools so they can't quietly mutate the workspace, and `Required`-level tools (shell, etc.) still need parent auto-approve regardless of role. Pick `implementer` (or pass an explicit `custom` allowlist) when the delegated task needs to land file changes (#1828, #1833). - **Experimental Fin fast-lane tool agents.** `tool_agent` opens a durable child session on DeepSeek V4 Flash with thinking forced off for simple tool-bound work such as OCR, file/search lookups, fetches, and command probes. It uses the existing `agent_eval` / `agent_close` lifecycle and mailbox token-usage stream, so sub-agent cost accounting stays on the same path as normal `agent_open` sessions. ### Fixed - **WSL2 and headless Linux startup no longer blocks on clipboard init.** The TUI now defers clipboard initialization so machines without an X server can reach the first frame instead of hanging on a blank screen (#1773, #1772). - **Windows alt-screen output stays clean when `RUST_LOG` is set.** Runtime tracing is routed away from the interactive buffer so logs no longer leak into the TUI display (#1774, #1776). - **OpenAI-compatible custom model names are preserved.** Non-DeepSeek providers now pass explicit model names through instead of rewriting them to a DeepSeek default (#1714, #1740). - **Wanjie Ark is a first-class provider.** `--provider wanjie-ark`, the TUI provider picker, `deepseek auth`, doctor, and config files now target Wanjie's OpenAI-compatible MaaS endpoint with pass-through model IDs and Wanjie-specific env vars. - **DeepSeek reasoning replay works through OpenAI-compatible endpoints.** DeepSeek models selected under the generic `openai` provider now replay prior `reasoning_content` consistently and classify streamed reasoning the same way the replay path does (#1694, #1739, #1743). - **Thinking-only turns no longer disappear.** If a clean turn ends with thinking but no final answer text, the UI now surfaces a clear status instead of silently ending the turn (#1727, #1742). - **Windows `cmd /C` preserves quoted shell arguments.** Commands such as `git commit -m "feat: complete sub-pages"` now round-trip through the Windows shell wrapper without losing the quoted message (#1691, #1744). - **Home/End are line-local inside multiline composer drafts.** The keys now jump to the current input line boundary before falling back to transcript navigation (#1748, #1749). - **Ctrl+C restores the canceled prompt reliably.** Canceling a streaming turn puts the submitted prompt back in the composer and suppresses late stream events from drawing stale output (#1757, #1764). - **Compaction recovers from cache-aligned summary context overflow.** When a cache-preserving summary request itself exceeds the provider context window, compaction retries with the bounded formatted summary path instead of failing with a 400 "compression command failed" style error. - **Terminal sub-agent sessions expose full transcript handles.** Completed and canceled child agents now store the full child message transcript behind `transcript_handle`, so the parent can inspect details with `handle_read` instead of relying only on a lossy summary (#1738). - **Forked saved sessions now keep visible lineage.** `deepseek fork` records the parent session id and fork-time message count in additive metadata, and session listings mark forked paths with their source id. This gives users a bounded branchable-conversation workflow while the larger visual tree browser stays scoped for a future release. - **Repeated shell wait rows collapse in the Tasks sidebar.** Multiple live `task_shell_wait` polls for the same background job now render as one row with an explicit collapsed-wait count, reducing the stuck-task appearance tracked for v0.8.40 (#1737). - **Leaked mouse scroll reports no longer erase composer draft suffixes.** If a terminal delivers raw SGR mouse bytes into the input stream, the sanitizer now strips only the mouse report and adjacent coordinate fragments instead of deleting legitimate draft text such as `commit -m` or numeric prompts (#1778). - **TUI runtime logs are separated per process and pruned on startup.** Each session now writes `~/.deepseek/logs/tui-YYYY-MM-DD-PID.log`, and startup removes stale TUI logs older than seven days by default. Set `DEEPSEEK_LOG_RETENTION_DAYS` to a positive day count to adjust retention (#1782, #1784). - **The offline eval harness preserves quoted Windows shell payloads.** Its `exec_shell` step now uses the same single-payload shape as the runtime shell path, with raw `cmd /C` arguments on Windows so quoted commands remain intact (#1779). - **The Feishu/Lark bridge recovers better after restarts.** It now reattaches to persisted active turns after the long-connection client starts, and text chunking no longer splits emoji or other multi-code-unit characters. - **RLM survives non-UTF-8 stdout.** `rlm_eval` now decodes REPL stdout lossily instead of treating a single invalid byte as a fatal crash, so binary-adjacent diagnostics can still return a bounded result (#1815, #1819). - **Small UI/review reliability fixes landed with the stability branch.** `/clear` now resets all displayed cost state, grayscale theme previews avoid luma overflow, `/theme` picker arrow navigation wraps at the list edges, and encoded JSON review output is parsed before display. - **New-file writes execute on the first Agent-mode call.** `write_file` now stays preloaded in Agent mode, so creating a file no longer stops at the deferred-tool schema hydration message before the normal approval/execution path (#1825, #1841). - **Saved sessions keep the selected model mode.** Changing from `auto` to a concrete model now updates existing session metadata, and resumed sessions recompute the `auto` flag from the saved model instead of falling back to the startup default. - **The `/model` picker persists thinking effort across restarts.** Selecting Pro/Flash plus `high`/`max`/`auto` now writes both `default_model` and `reasoning_effort` to `settings.toml`, and startup restores the saved effort before falling back to `config.toml`. - **The footer water strip is visible by default again.** `fancy_animations` now defaults to `true`, while `NO_ANIMATIONS`, SSH/Termius, VS Code, Ghostty, and legacy terminal overrides still disable the animated strip where it is known to flicker. - **Screenshots are readable without extra setup on macOS.** `image_ocr` now uses the native Vision framework on macOS when Tesseract is absent, and `read_file` routes screenshot/image reads through the same OCR path. Pasted clipboard screenshots saved under `~/.deepseek/clipboard-images` are trusted automatically for read-only tools. - **Auto-routing context no longer leaks hidden thinking.** The model/router context summary now excludes `ContentBlock::Thinking`, so prior internal reasoning is not reintroduced as if it were visible user or assistant text. ### Changed - **Slash-command autocomplete ranks exact alias matches first.** Typing `/q` now surfaces `/exit` (whose alias `q` is an exact match) above `/clear` (which only matches by the longer pinyin alias `qingping`). Within each rank tier the menu still falls back to alphabetical name order for deterministic display (#1811). - **CNB mirror preflight covers stability-release branches.** The CNB sync path now recognizes the v0.8.40 stability branch shape before release tags exist, making the Tencent Lighthouse/Lark deployment path easier to verify before publishing. ### Thanks Thanks to **jayzhu ([@zlh124](https://github.com/zlh124))** for the WSL2 startup report and clipboard-init fix in #1772/#1773. Thanks to **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** for the Windows alt-screen logging report and fix in #1774/#1776, and for the Home/End composer work in #1748/#1749, plus the per-process log filename follow-up in #1782/#1783. Thanks to **Zhongyue Lin ([@LeoLin990405](https://github.com/LeoLin990405))** for the provider model passthrough, reasoning replay, thinking-only turn, and Windows quoting fixes in #1740, #1743, #1742, and #1744. Thanks to **Nightt ([@nightt5879](https://github.com/nightt5879))** for the Ctrl+C prompt restore fix in #1764. Thanks to **Ling ([@LING71671](https://github.com/LING71671); commits as `www17 `)** for the configurable sub-agent API timeout in #1808 and the Agent-mode `write_file` preload fix in #1841, harvested with `1..=1800` clamping and a fail-fast guard so a stray `api_timeout_secs = 0` keeps the legacy 120-second default. Thanks to **[@knqiufan](https://github.com/knqiufan)** for the sub-agent file-write delegation work in #1833, harvested with structured approval- gate semantics (`Implementer` and `Custom` only, never `Required`-level tools) so write-capable children can actually land code without bypassing the `Required` approval class. Thanks to **[@IIzzaya](https://github.com/IIzzaya)** for the exact-alias-first slash-completion ordering idea in #1811, landed with a focused regression test. Thanks to **Bevis** and the community reports that surfaced the compaction failure mode addressed in this release. Thanks to **Reid ([@reidliu41](https://github.com/reidliu41))** for the grayscale theme overflow report and `/theme` picker edge-wrapping patch in #1814. --- Older releases (v0.8.39 and earlier) are archived in [docs/CHANGELOG_ARCHIVE.md](docs/CHANGELOG_ARCHIVE.md). [Unreleased]: https://github.com/codewhale-hq/CodeWhale/compare/v0.10.0...HEAD [0.10.1]: https://github.com/codewhale-hq/CodeWhale/compare/v0.10.0...v0.10.1 [0.10.0]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.13...v0.10.0 [0.9.13]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.12...v0.9.13 [0.9.12]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.11...v0.9.12 [0.9.11]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.10...v0.9.11 [0.9.10]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.9...v0.9.10 [0.9.9]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.8...v0.9.9 [0.9.8]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.7...v0.9.8 [0.9.7]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.6...v0.9.7 [0.9.6]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.5...v0.9.6 [0.9.5]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.4...v0.9.5 [0.9.4]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.3...v0.9.4 [0.9.3]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.2...v0.9.3 [0.9.2]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.1...v0.9.2 [0.9.1]: https://github.com/codewhale-hq/CodeWhale/compare/v0.9.0...v0.9.1 [0.8.68]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.67...v0.8.68 [0.8.67]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.66...v0.8.67 [0.8.66]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.65...v0.8.66 [0.8.65]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.64...v0.8.65 [0.8.64]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.63...v0.8.64 [0.8.63]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.62...v0.8.63 [0.8.62]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.61...v0.8.62 [0.8.61]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.60...v0.8.61 [0.8.60]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.59...v0.8.60 [0.8.59]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.58...v0.8.59 [0.8.58]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.57...v0.8.58 [0.8.57]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.56...v0.8.57 [0.8.56]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.55...v0.8.56 [0.8.55]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.54...v0.8.55 [0.8.54]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.53...v0.8.54 [0.8.53]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.52...v0.8.53 [0.8.52]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.51...v0.8.52 [0.8.51]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.50...v0.8.51 [0.8.50]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.49...v0.8.50 [0.8.49]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.48...v0.8.49 [0.8.48]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.47...v0.8.48 [0.8.47]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.46...v0.8.47 [0.8.46]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.45...v0.8.46 [0.8.45]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.44...v0.8.45 [0.8.44]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.43...v0.8.44 [0.8.43]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.42...v0.8.43 [0.8.42]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.41...v0.8.42 [0.8.41]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.40...v0.8.41 [0.8.40]: https://github.com/codewhale-hq/CodeWhale/compare/v0.8.39...v0.8.40