返回 CodeWhale
CHANGELOG.md
根目录 / crates / tui / CHANGELOG.md
1 # Changelog
2
3 All notable changes to this project will be documented in this file.
4
5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8 ## [Unreleased]
9
10 ## [0.10.0] - Unreleased candidate
11
12 The v0.10.0 source candidate brings a redesigned terminal workbench, clearer
13 settings, and more reliable session and runtime behavior. It supersedes the
14 unpublished v0.9.14 candidate. Nothing below is published until the matching
15 tag, packages, checksums and release assets exist.
16
17 ### Contributors
18
19 - **[@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/Hmbown/Codewhale/pull/6369), [#6363](https://github.com/Hmbown/Codewhale/pull/6363), [#6365](https://github.com/Hmbown/Codewhale/pull/6365)).
20 - **[@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/Hmbown/Codewhale/pull/6096)).
21 - **[@BX166](https://github.com/BX166)** — contributed the AICraft provider template and its documentation ([#6171](https://github.com/Hmbown/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/Hmbown/Codewhale/issues/6289)).
22 - **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — reported the session-retention defects behind archive-past-the-cap and empty-session cap occupancy ([#6136](https://github.com/Hmbown/Codewhale/issues/6136), [#6137](https://github.com/Hmbown/Codewhale/issues/6137)), the resume-failure design behind durable transcript errors ([#6138](https://github.com/Hmbown/Codewhale/issues/6138)), and the gaps behind the opt-in approval timeout ([#6101](https://github.com/Hmbown/Codewhale/issues/6101)), `codewhale exec --hooks` ([#6099](https://github.com/Hmbown/Codewhale/issues/6099)), Markdown drag-copy ([#6156](https://github.com/Hmbown/Codewhale/issues/6156)), and the browsable, current-aware session picker ([#6014](https://github.com/Hmbown/Codewhale/issues/6014)); the goal token-budget hard stop ([#6013](https://github.com/Hmbown/Codewhale/issues/6013)) and the fleet no-progress guard shared with child workers ([#6015](https://github.com/Hmbown/Codewhale/issues/6015)) landed as first slices of two larger proposals, and the runtime-store session refusal ([#6207](https://github.com/Hmbown/Codewhale/issues/6207)).
23 - **[@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/Hmbown/Codewhale/issues/5359)).
24 - **[@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/Hmbown/Codewhale/issues/6165)).
25 - **[@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/Hmbown/Codewhale/issues/6173)).
26 - **[@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/Hmbown/Codewhale/issues/6174)).
27 - **[@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/Hmbown/Codewhale/issues/6184), [#6185](https://github.com/Hmbown/Codewhale/issues/6185)).
28
29 ### Security
30
31 - Approving an `apply_patch` "for the session" is now scoped to the file you
32 approved. The grouping key that scopes a session grant was built by a second,
33 weaker patch parser that read only `+++ b/` headers and the `replace` array:
34 it saw no target at all for the documented `apply_patch{path, patch}`
35 override, for `--no-prefix` diffs, or for delete-only diffs, and collapsed
36 every one of them to a single shared key. One approval therefore pre-approved
37 every later patch of that shape, to any file, with no card and no notice. The
38 key now comes from the same resolver the executor and the permission path
39 already use, and an input that cannot be resolved gets its own key rather
40 than a shared one (#6247).
41
42 ### Added
43
44 - TTFT and average output rate stay visible in the compact working footer when
45 space allows. `/statusline` now controls them separately; existing
46 `session_metrics` settings still work.
47 - StepFun’s current coding catalog includes Step 5 Preview, Step 3.7 Flash,
48 Step 3.5 Flash and its 2603 version, with published reasoning controls and
49 PAYG rates. Existing Step Plan routing remains subscription-based.
50
51 - `read` responses now always report the file's byte size, line count, and
52 whether output was truncated, and truncation footers name the total size
53 alongside the continuation offset — so paging through a large file is
54 deliberate instead of a surprise (#6283).
55 - File edits are parse-gated before the write lands: Rust goes through
56 `syn::parse_file` for a grammar-exact `line:column`, and `.toml` / `.json`
57 through the parsers already vendored. An edit is refused only when the file
58 parsed *before* and would not parse *after* — repairing an already-broken
59 file is the commonest reason to edit source at all, so pre-existing breakage
60 and new files fail open. The check precedes the write, so a rejection leaves
61 the file untouched and `apply_patch` cannot half-apply (#6204, #6206, #6151).
62 - Rust files that were already `rustfmt`-clean are re-normalized after an edit,
63 so the next patch's anchors still match. Hand-formatted files are never
64 rewritten, and every failure path skips and lets the edit land (#6205, #6151).
65 - Native clients can finish provider setup without dropping to the CLI:
66 `DELETE /v1/providers/{id}/key` clears a Codewhale-owned credential through
67 the same shared owner as `codewhale auth clear`, and `GET /v1/providers`
68 now carries `credentialSource` / `credentialWritable` (plus a reason) so a
69 client disables its control with a truthful explanation instead of letting
70 a write fail late. A credential Codewhale does not own — a literal key in a
71 config file, or an active external consent — refuses both verbs with `409`
72 rather than appearing to succeed against a source that still wins at
73 request time (#6179).
74 - The interactive approval card can be bounded: `[approval] timeout_seconds`
75 resolves an unanswered card to **deny** when the window elapses — the same
76 fail-closed decision the external approval path takes — and the transcript
77 says the bound denied the call, not the operator. Omitted or `0` keeps
78 today's unbounded wait, so nothing changes unless you opt in (#6101).
79 - Transcript drag selection copies Markdown source by default: every cell the
80 selection touches serializes through the same canonical path `Ctrl-Y` and
81 `/copy` use, partial intersections round out to whole cells joined with
82 blank lines, and the toast names the copied cell count.
83 `tui.selection_copy_markdown = false` keeps the rendered-text payload
84 (#6156).
85 - The Runtime API serves the workspace files a native client browses and edits:
86 `GET /v1/workspace/files` lists one directory, `GET /v1/workspace/files/read`
87 returns a bounded byte window with a whole-file SHA-256 revision, and
88 `PUT /v1/workspace/files` writes atomically through the confined opener with
89 revision-checked overwrites (409 on drift). `.git` is never served and
90 symlinks are never followed. A saved session's oversized tool outputs are
91 served as artifacts at `GET /v1/sessions/{id}/artifacts` and
92 `GET /v1/sessions/{id}/artifacts/{artifact_id}`. (#6163)
93 - A session that ended mid-turn is no longer invisible to the model. The newest
94 workspace-scoped session still holding a crash-recovery checkpoint is
95 surfaced as a one-line `## Prior Session` notice in the session-pinned prompt
96 prefix — metadata reads only, excluding the live session and any session this
97 process instance created. Clean sessions get no block, so their prefix bytes
98 are unchanged. Two bounded read-only tools, `session_search` and
99 `session_get`, give the model workspace-scoped recall over the same store
100 (one-line summaries and an 8-message tail, labeled untrusted user data, read
101 on the blocking pool). Resuming stays the user's decision: the hint tells the
102 model to offer a continuation, never to silently take one (#5715).
103 - `codewhale exec --hooks` opts a headless run into the same `HookExecutor` the
104 TUI builds — global config, reviewed plugin snapshots, and trusted project
105 `hooks.toml`. Headless runs previously fired no hooks at all. `tool_call_before`
106 can still deny and `shell_env` still applies; a hook `ask` resolves
107 fail-closed without a terminal. Fleet worker subprocesses never opt in, and
108 `permissions.toml` typed rules are unchanged (#6099).
109 - `codewhale doctor` flags fleet and profile model pins that the provider's own
110 roster no longer offers. A pin is reported only when a *fresh* cached live
111 roster for that exact route exists and omits it — stale, failed, or absent
112 rosters prove nothing and are counted as `unverifiable` rather than raising a
113 false warning. Each row names the route and every owner of the pin; the pin
114 is surfaced, never rewritten (#6035).
115 - Background-capable clients can enumerate owned work and watch TUI-visible
116 conditions: `GET /v1/threads/running` lists threads with queued or
117 in-progress turns in one call (one turns scan grouped by thread), and
118 `GET /v1/threads/{id}/notices` serves active `subagent-terminal`,
119 `elevation-needed`, and `model-notify` notices with thread/turn identity,
120 cleared by ack or — for elevation — when the tool call completes (#6180,
121 #3757).
122 - Sub-agent launches adapt to provider throttling: a `DynamicGate` replaces
123 the fixed semaphore so launch capacity adjusts at runtime, and a
124 `RateLimitGovernor` halves capacity on 429 pressure, pauses admissions
125 past the threshold, and recovers additively; 429 retries honor
126 `Retry-After` with jittered backoff, and quota exhaustion keeps the
127 failure path (#6055).
128 - Turns record the mode they ran in, so mixed-mode sessions stay legible
129 after the fact (#6321).
130 - Shell spawning refuses NUL bytes in command and cwd before spawn, and
131 sub-agent runs fall back loudly past credentialless profile provider
132 pins instead of misrouting silently (#5529, #6318, #6320).
133 - Children land past a per-step context bound instead of burning
134 quadratically, and status rows surface live declared-vs-observed writes
135 (#6189, #6194).
136 - Queued Agent Mail can be cancelled before delivery, and the TUI
137 suspend/resume handshake restores on stop and rebuilds on continue
138 (#6176, #6169).
139 - MCP connections are supervised: dead servers are probed and reconnected
140 with transitions reported, and a failed reconnect keeps the last-good
141 catalog instead of dropping tools (#6187, #6142).
142 - Web search autodetects Tavily from `TAVILY_API_KEY` (Firecrawl stays the
143 default), fleet refusals name the alternative, and verification runs on
144 a bounded Git fetch plus a `merge_tree` verify surface (#6298, #6296).
145 - Fleet authority projects through one `ChildGrant`, and ModelScope joins
146 the built-in providers (#5633, #6299).
147 - Child tool results are capped at capture time, and run
148 tests/verifiers accept a bounded cwd (#6282, #6294, #6296).
149
150 ### Changed
151
152 - The launcher keeps the Codewhale mark while balancing its layout above the
153 composer. A single cursor identifies the selected action; MCP faults retain
154 their warning color even in compact terminals. Recent-session counts now
155 read correctly for a single message.
156 - Model and provider settings use quieter selection surfaces, one focused
157 cursor, clearer missing-key warnings, compact output limits, and less
158 repetitive credential detail. Plugin actions use plain labels.
159
160 - The terminal opens on **Shoreline**, the same palette the GPUI client already
161 uses: warm charcoal field `#211F23`, a raised plate for panels and the
162 composer, one blue for action and selection `#90B9FF`, and the whale's ivory
163 `#F2ECE5` for body text, with 4.5:1 floors on every muted step. The old
164 saturated navy gradient is not gone — `underwater` is a named theme now
165 rather than the ground the product opens on. Existing installs keep whatever
166 theme they have saved; `/theme` switches (#6222).
167
168 - Menu navigation is starting to mean the same thing everywhere. `menu_style`
169 already single-sourced how a selected row *looks*; what a key *does* was still
170 reinvented per surface — `h`/`l` in the provider picker against `Left`/`Right`
171 in the model picker one screen later, `Home`/`End` in one of seven pickers, and
172 no paging at all in Fleet's detail view. `list_nav`, which already owned the
173 wrap arithmetic, now owns the vocabulary too: one vertical axis, one
174 horizontal axis, and two entry points so a picker with a live filter never has
175 a letter stolen out of its query. Fleet's detail view adopts it first and
176 gains PageUp/PageDown and Home/End in both its lists (#6290).
177
178 - Reviewed plugin bundles are no longer re-hashed four times per MCP dispatch.
179 `verify_plugin_authority` walks and hashes both the reviewed source and the
180 runtime snapshot, and four separate authority checks ran per `tools/call` —
181 eight tree walks. Three of them sat one statement after a
182 `validate_before_use` on the same source, so `is_ready` re-verified what had
183 just been verified; readiness and authority are now separate, and only the
184 callers with no preceding check still pay for both. The tool catalog is built
185 once per turn instead of twice, which also removes a case where the two
186 assemblies could disagree if authority drifted between them. The digest is
187 deliberately **not** cached on `(path, mtime, len)`: the reviewed tree is
188 user-writable and `utimensat(2)` lets a same-uid process restore an mtime
189 after an equal-length rewrite, so a stat-keyed cache would serve a pre-tamper
190 digest (#6209).
191 - A sub-agent's completion is read from the manager once instead of polled. The
192 workflow pump re-read it up to fifty times, sleeping 20ms between attempts,
193 waiting for a terminal status that was already committed — every publisher
194 commits the status inside the same `&mut self` call that wakes the pump, so
195 the write guard spans both and the first read always sees it. A child the
196 manager had no record of cost a full second of head-of-line blocking before
197 failing; it now fails immediately, and says what actually happened instead of
198 claiming the child "did not report a terminal status within 1s" (#6211).
199
200 - MCP protocol negotiation: every surface advertised the original 2024-11-05
201 revision and the stdio client required an exact match, so newer servers
202 could not connect. The server and both clients now advertise 2025-06-18
203 and negotiate over the supported set (2025-06-18, 2025-03-26, 2024-11-05)
204 — the server echoes the client's revision when it is supported and answers
205 with the latest otherwise, the stdio client accepts any supported revision,
206 and streamable HTTP sends the required `MCP-Protocol-Version` header on
207 every post-initialize request (#6280, first half).
208 - Configured MCP servers now connect lazily instead of all at session boot. The
209 pool owns a `connecting` set marked at spawn and cleared on resolution or
210 abort, so "connecting" is no longer inferred as enabled-minus-connected. The
211 boot pass scopes to the eager set — `required` servers plus those covered by
212 `tools.always_load` / `allowed_tools` — and a turn naming an unstarted server
213 spawns its connects alongside, under the existing five-second deadline. A
214 configured-but-unstarted server now reads as configured on every surface
215 (session-boot rows, Extensions tab, launch card), never as connecting.
216 `docs/MCP.md` documents the lifecycle (#6033).
217 - The launch card's MCP problems row runs its own remedy. It already printed
218 `/mcp login <name>` or `/mcp`; it now joins the shared paint/click/keyboard
219 ordering, so Up/Down lands on it and Enter or a click types the printed
220 command into the composer for you to send. Typing beats copying: no clipboard
221 dependency over SSH, and you see the command before a second Enter runs it
222 (#6085).
223
224 - Computer Use is the only computer-use product in Extensions and
225 `/mcp recommendations`. Cua is no longer suggested as a parallel
226 desktop-control MCP; enable the first-party `computer-use` plugin
227 instead. The bundled plugin is 0.4.0: Return/Enter from `type`,
228 filtered and paginated `get_app_state`, `focus`/`get_value`, and
229 `strategy:"app"` window-scoped clicks. Shared-desktop pointer
230 gestures stay gated.
231 - The bundled first-party catalog pins marketplace revision `ca6be22`, so
232 installing Computer Use from the Extensions listing fetches the same 0.4.0
233 source and the published notarized 0.4.0 Mac app.
234
235 ### Fixed
236
237 - Stopping a turn revokes its pending approvals. A late approval cannot resume
238 the cancelled action or save an automatic approval for later turns.
239 - Expanding and collapsing selected reasoning now matches its rendered state
240 when verbose mode and the default-expansion preference are both enabled.
241
242 - Branch navigation preserves sibling histories, stable entry IDs and timestamps
243 through autosave, resume and forks, and synchronizes the selected branch into
244 the live engine. Thanks to @7jrxt42BxFZo4iAnN4CX for the report (#6367).
245 - Compaction now writes local diagnostic records for completed passes and
246 automatic refusals. `codewhale metrics` reports them with summarizer token
247 usage; text-mode exec retains its session after attempting compaction.
248 Historical artifacts are not backfilled. Thanks to @7jrxt42BxFZo4iAnN4CX
249 for identifying the missing producer (#6368).
250 - The opening workbench retains the canonical Codewhale mark in a responsive
251 header while keeping recent-session titles full-width and actions clickable.
252 - `serve --acp` no longer ignores the approval posture. The ACP adapter
253 hardcoded `ApprovalMode::Suggest`, so `--yolo` (and any configured
254 `approval_policy`) never reached admission: every mutating tool parked
255 behind a permission request no unattended client answers, and sessions
256 executed zero tools. Posture now derives from server config — `--yolo`
257 pre-approves prompts and flows into the sandbox policy — while hard blocks
258 (safety floor, repo law, reviewer consult) and the Plan read-only guardrail
259 stay intact (#6337).
260 - Plain agent spawns could not resolve. `built_in_members()` seeded both
261 `general` and `worker`, and the role parse boundary migrates `worker` to
262 `general`, so both canonicalized to the same role — and `role:general`, the
263 selector the roster advertises for the default posture, matched two members
264 and raised `Ambiguous` every time, permanently. The duplicate built-in is
265 gone. The legacy name still resolves: `general`, `member:general`,
266 `role:general` and `default` all land on the `worker` posture through the
267 identity selector rather than through a second member, which is what allowed
268 the duplicate to be removed (#6244).
269 - Clicking a `path:line` in tool output no longer spawns `$EDITOR` detached
270 while the TUI still owns the terminal, and no longer spawns one editor per
271 matching line. The launch goes through the single terminal-handoff path, and
272 a click is one request to open one file (#6235).
273 - A write-scope contention refusal now names a remedy that works. The `agent`
274 tool's description claimed `release` was "the remediation a write-scope
275 contention refusal names"; the refusal did not name it, and pointing back at
276 it would have been worse, because `release` only clears claims whose owner is
277 no longer running while a contention refusal names a live one. The refusal
278 itself now says to wait for that owner to settle or cancel it (#6272).
279 - The session picker no longer refuses a saved session whose Runtime store
280 exists but holds nothing. A force-quit leaves the store on disk, ownerless
281 and empty, and the switch path refused it because recovery only covered a
282 *missing* store. A switch now also adopts a store that is provably empty
283 (every work directory, plus the event sequence that remembers pruned
284 appends) *and* provably unheld (the process-owner lock, which a live
285 manager holds from open to close), with no automation pinned to its
286 execution scope — and the save gate treats that shape as abandonable too,
287 so the repaired binding persists. The first fix was reverted on a race
288 (emptiness without liveness); this reland checks the lock first (#6207).
289 - Double-tap Enter now sends every queued follow-up into the running turn,
290 oldest first. The second Enter used to steer only the most recent message
291 and leave older ones queued; a failed steer restores the failed message
292 plus everything unattempted in original order, so nothing is lost or
293 reordered.
294 - Only the most recently sent prompt carries the elevated-surface background
295 now; every older prompt renders on the bare ground. The fill used to sit
296 behind every user row (striping), then behind none; newest-only keeps the
297 eye on the turn in play. Sending a new prompt moves the highlight and
298 un-highlights its predecessor.
299 - Diff rows tint whole: added/deleted line numbers now share the row's green
300 / red background instead of sitting bare next to a painted body. Context
301 rows stay on the bare ground.
302 - MCP connections are supervised now: a background task notices a dead
303 server within one sweep, reconnects on the existing backoff ladder, and
304 reports each transition, so Extensions rows flip with liveness instead
305 of parking on stale-ready or a silent [reconnect]. Five consecutive
306 failures park the server with a notice naming `/mcp retry`; an explicit
307 retry or a fresh connection resumes watching. Tool calls also retry
308 once across a dead pipe/socket (not just stale sessions), and a
309 reconnect that fails reports both errors instead of swallowing the
310 original (#6187; `list_changed` catalog refresh stays open).
311
312 - A steer the engine never delivered is no longer reported as sent. The runtime
313 API persisted the steer item as already-`Completed` and emitted
314 `turn.steered` + `item.completed` the moment the text entered the engine's
315 mailbox — before the engine decided anything. The engine discards a steer
316 whose turn has moved on, and an interrupted or failed turn drops whatever it
317 had queued, so a GUI could show "Guidance sent", clear the composer, and lose
318 the user's words. The engine now returns a verdict for every steer on every
319 exit path, the item settles `completed` or `canceled` to match, a dropped
320 steer emits `turn.steer_dropped` and answers `409` so a client can resend,
321 and `steer_count` counts steers the model actually received (#6276).
322 - `<recommended_plugins>` suggestions stop nagging: a plugin id is now
323 injected at most once per engine lifetime, and a plugin whose name a
324 loaded skill already covers is never suggested — the local skill owns
325 the domain, so the nudge was noise. Dismissals still apply, and the
326 fragment stays append-only on the user turn (#6274).
327 - A canceled automation run now settles with a transcript receipt that names
328 the cancellation (by request, cancel timeout, or shutdown) instead of
329 vanishing from the live band silently. The receipt wears attention ink and
330 never lights the failure demand; the run record keeps the cancellation
331 reason as its error detail. (#6162)
332 - A failed workflow run no longer settles silently: its terminal failure
333 raises a sticky error toast naming the cause (dispatch, schema, or script
334 errors), alongside the existing panel state (#5528).
335 - MCP OAuth re-login now forces the provider's consent screen: logout only
336 clears the local token, so without a prompt the provider silently
337 re-granted the same account/workspace and a re-login could never change
338 it. `/mcp logout` and `codewhale mcp logout` also say plainly that they
339 clear local credentials only (#6040).
340 - Session retention no longer deletes transcripts once the store reaches the
341 cap: the oldest active session is archived — still openable from the
342 picker's archived view — instead of being unlinked, and archived records
343 sit outside the cap until they are pruned (#6136).
344 - Empty auto-created "New Session" stubs are capped separately (the ten
345 newest are kept) and can no longer occupy a real transcript's slot in the
346 session cap (#6137).
347 - A failed resume or session load is now a durable transcript error instead
348 of a status line the next footer update replaces, so a resume that cannot
349 restore its target no longer looks like a silent new session (#6138).
350 - Compaction no longer retains a tool result whose tool call was summarized
351 away: an older turn that mixes text with a tool result keeps its text and
352 drops the orphaned result blocks, which providers reject outright (#6119).
353 - Automation runs that need a tool approval no longer die as silent
354 idle-timeout cancels: a pending approval suspends the idle watchdog for its
355 decision window, and an unanswered window settles the run Failed with the
356 recorded reason instead of a silent Canceled (#6118).
357 - `/mcp` no longer freezes the console while a turn is running: the panel
358 opens immediately from the last known MCP snapshot with a receipt naming
359 the wait, and live-pool mutations say their refresh is deferred instead of
360 parking the UI event loop behind the running turn (#6159).
361 - MCP OAuth login no longer fails with "Authorization server response missing
362 required issuer" against servers that implement RFC 9207, such as
363 Cloudflare's `mcp.cloudflare.com`. The local callback listener now keeps the
364 `iss` parameter from the redirect and hands it to the token exchange so the
365 callback binds to the discovered issuer; servers that do not send `iss`
366 keep working unchanged. (#6157)
367
368 ## [0.9.13] - 2026-09-13
369
370 Codewhale v0.9.13 addresses integrity issues in 0.9.12:
371 multiline paste is one paste again, truncated tool arguments can no longer execute, strict
372 ACP clients connect again, concurrent instances stop destroying each
373 other's queued text, and the Computer Use bundle includes plugin 0.3.1
374 with an accessibility-first pointer that no longer steals focus. DeepSeek V4.1 Flash
375 (`deepseek-flash`) is the default DeepSeek model, reasoning-capable routes
376 keep reasoning out of the answer even when a model id carries no version
377 number, and `/mcp reload` no longer freezes the interface while servers
378 reconnect. The Codewhale pet arrives with `/pet`: a full-screen habitat that
379 shows what the Engine is doing and reveals the answer when it is done.
380
381 ### Added
382
383 - `/pet` turns the terminal over to the Codewhale pet. `/pet on` (or bare
384 `/pet`) gives the habitat the whole content viewport now and on every
385 accepted turn, reveals the actual answer or error when the turn completes,
386 and Escape returns to the composer without cancelling anything. `/pet off`
387 closes the view and stops automatic entry while the durable companion keeps
388 the pet alive; `/pet appearance|window|source|sound|export|status` address
389 the shared companion. The pet no longer lives in the workbar: the Watch
390 panel and `/workbar watch …` are gone (#6109, #6110).
391 - Codewhale Computer Use 0.3.1 ships as its own notarized Mac app. Download
392 the disk image from [codewhale.net/computer-use](https://codewhale.net/computer-use)
393 or the [v0.3.1 release](https://github.com/Hmbown/codewhale-cu-plugin/releases/tag/v0.3.1)
394 (`Codewhale-Computer-Use-0.3.1-macos-universal.dmg`, drag into
395 Applications; the ZIP stays for the in-app updater). The bundled plugin and
396 the first-party marketplace pin the same 0.3.1 sources, so the app, the
397 `computer-use` plugin and `/mcp` see one implementation.
398
399 ### Fixed
400
401 - The website's Computer Use download page resolves its state without the
402 GitHub API (using `GITHUB_TOKEN` only when bound), and every page regenerates
403 on the Worker again: the Open Graph image route read brand SVGs at import
404 time, which the Workers runtime cannot do, so codewhale.net had been serving
405 its build-time snapshot.
406 - Operate can run structured workflows directly, with named phases, model
407 assignments from Fleet, prerequisite results and shared budgets. Independent
408 steps run together; dependent work waits for its required results and gates.
409 Detached runs return their outcome to the owning conversation, and headless
410 sessions stay alive between phases until the final handback is consumed.
411 - Computer Use 0.3.1: mouse actions no longer steal focus or reclaim the
412 foreground when the user switches apps mid-action; background typing,
413 scrolling and selection use semantic input, and screenshots stay scoped to
414 the targeted app. The bundled plugin and the first-party marketplace pin
415 carry the same 0.3.1 sources. A registered macOS helper stays in charge of
416 input through its Pause and Stop controls; an unavailable registered helper
417 produces an error instead of silently bypassing those controls.
418 - The Fleet editor uses the standard model picker to manage sub-agent model
419 and thinking assignments. Enter edits the selected row without changing the
420 running session's model. Unconfigured providers are refused, failed saves
421 retain the previous assignment, and a changed or removed team file must be
422 reopened before a pick can overwrite it.
423 - The provider catalog includes Baseten and the other compatible-provider
424 templates as selectable rows, opening their existing prefilled setup forms.
425 DeepSeek routes with clock-based pricing show the current peak or off-peak
426 tier beside session cost, with translated labels.
427 - Extensions, teams, workflows and automations support mouse-wheel scrolling.
428 Plugin and MCP rows have keyboard enable/disable controls and two-step
429 removal; MCP OAuth can retry with narrower scopes after a scope rejection.
430 - Healthy sub-agents continue after an ordinary parent reply. Headless runs
431 keep the existing Engine alive for child results within the run deadline.
432 Explicit cancellation remains authoritative when result queues are full or
433 a completion starts a followup turn.
434 - Sub-agent followup supports multiple targets and all parked children, keeps
435 old IDs connected to their current continuation, and saves continuation
436 identity before starting work. Repeated followup does not fork duplicates.
437 - Sub-agents validate declared output files and distinguish real edit claims
438 from file citations and unrelated workspace changes. Disjoint file claims
439 can run together; overlapping writers receive the actual conflict and remedies.
440 Explicit read-only shell analysis requires an enforcing native sandbox and
441 refuses execution when that protection is unavailable.
442 - Delegation depth stays absolute through saved profiles, nested workers and
443 continuations. Per-call token, step and time limits narrow inherited limits;
444 continuation retains ancestor usage and deadlines. Workers reserve room for
445 one tools-disabled partial report inside those limits, then run the declared-
446 output checks. Missing usage or unavailable reporting room produces an
447 explicit fallback; partial work is never marked complete.
448 - Agent rosters and detail pages have bounded output, visible continuation and
449 descendant relationships, and usable handles for full diagnostic evidence.
450 Completion receipts include measured worker and descendant token usage,
451 count each continuation once, and distinguish unreported usage from zero.
452 - Localization and native helper builds resolve the active checkout when the
453 build script runs, so a shared Cargo target keeps working after a worktree
454 moves or is removed.
455 - Selecting a saved agent profile that is malformed, unreadable or duplicated
456 now fails before any child request, including when its name matches a
457 built-in role; the parent's default route is never substituted silently.
458 `agent(action: "roster")` lists affected profile identities and paths, Fleet
459 run creation performs the same check, and `docs/SUBAGENTS.md` documents the
460 valid personal profile format with `[permissions]` (#6117, thanks
461 @Gabriel-Degret).
462 - Interactive startup no longer mistakes worker scheduling delays for an
463 unresponsive terminal. Terminal ownership checks and shutdown cleanup remain
464 enforced (#5929).
465 - Interrupted conversations whose saved runtime store is missing recover into a
466 fresh scope without restoring old tasks or approvals. Stale session saves
467 cannot resurrect the broken binding (#6102).
468 - Permission checks distinguish literal heredoc data from executable commands,
469 including substitutions and shell stdin (#6098).
470 - Automatic compaction runs quietly from live context pressure, preserving the
471 current task and recent tool exchanges while keeping the system/tool prefix
472 stable. Original history and the handoff are saved before context replacement;
473 failed or canceled compaction retains the conversation (#5620, #6047).
474 - Custom and gateway providers can override context limits for each exact model,
475 so switching models also switches the meter and compaction budget (#6108).
476 - Plugin suggestions explain their matching term and remember explicit dismissals
477 across restarts. Generic words and repository-host domains no longer trigger
478 unrelated installation prompts (#6031).
479 - Plugin trust and automation deletion have keyboard and mouse confirmation
480 controls bound to the exact reviewed content; users can still copy the command
481 and changed content requires a fresh review (#6039).
482 - The model-facing MCP start tool can reconnect an existing configured name after
483 login without changing its credential key or restarting healthy siblings (#6030).
484 A decreasing token-expiry countdown no longer makes a revoked credential look
485 like a new login from another session.
486 - Gemini setup uses the official endpoint's supported reasoning-effort field,
487 avoiding the rejected top-level Google thinking object. Gemini 2.5 and 3 keep
488 their supported effort ranges; signed tool history still survives reasoning
489 changes and restart (#6018, thanks @vmakarov-uk).
490 - Missed automation occurrences coalesce without overlapping a running job;
491 restart reconciles durable receipts without replaying accepted work. Damaged
492 neighboring records are isolated while preserving their original bytes.
493 - The bundled first-party marketplace lists the actual plugin bundles and uses
494 the existing install, review, trust and update paths. A read-only connection
495 check verifies catalog and skill mirrors on changes and weekly. Already present
496 bundles lead to their local review and management controls; catalog installs
497 refuse name collisions before downloading, without overwriting or granting trust.
498 - Windows deny checks preserve native path separators while retaining the
499 conservative POSIX scan for shell wrappers and substitutions.
500 - The config example agrees with the telemetry disclosure: usage analytics are
501 optional and enabled by default; local diagnostics do not require telemetry (#6011).
502
503 - Sub-agents enforce the session's typed shell and file deny rules, including
504 Full Access, delegated edits, and policy updates after a child starts (#6097).
505 - Live permission edits reach running engine clones atomically. Deny rules
506 support token wildcards and Windows command spellings while keeping POSIX
507 arguments literal (#6054, thanks @h3c-hexin and @asto18089).
508 - Tool-result images use the existing typed inline path and are fully decoded
509 under size and allocation limits before admission or provider projection.
510 Invalid images keep a visible omission receipt alongside the text result
511 (adapted from #6053, thanks @h3c-hexin and @asto18089).
512
513 - A lone `y`, `Y`, or `r` remains composer input after selecting transcript
514 text. Clicking the composer releases transcript and dock focus.
515 - The Agents register updates from live worker events while the parent is
516 busy, including when the register opened before the workers spawned.
517 - Ghostty no longer shows a second graphical whale over the launch mark.
518 The selected model stays visible before the first message; unused session
519 metrics stay quiet. Scheduled counts open `/automation` directly.
520 - Marketplace installation accepts compatible Claude plugin bundles and roots
521 their relative sources outside `.claude-plugin`; unsupported components fail
522 explicitly. Native trust and enablement review still applies.
523 - Config table and nested reads work consistently and redact credentials.
524 Unsupported dotted writes fail without changing the file, and `config doctor`
525 no longer labels runtime settings as never applied (#6083).
526
527 - Esc during a worker fanout keeps the parent stopped when cancelled workers
528 finish. Their receipts remain available for the next explicit user turn.
529 - Undo preserves messages even when older state lacks a timestamp. Session
530 journal entries retain their append-time stamps when saved again.
531 - Extension actions refresh in place, and inspection output uses the text
532 pager. The empty launch shell hides unused metrics and keeps recovery hints
533 readable when several MCP servers need attention.
534 - The large-output router defaults to bounded spillover; adaptive routing
535 remains opt-in through `CODEWHALE_ADAPTIVE_OUTPUT_ROUTING=1`.
536 - Direct composer paste (`Ctrl-V`) preserves rich clipboard headings, lists,
537 links, tables and code as Markdown, with plain-text fallback. Whole-answer
538 copy preserves authored Markdown without terminal wrapping; settings fields
539 still paste literal text.
540 - The embedded Computer Use bundle includes the marketplace's JPEG capture
541 and bounded-payload fixes, so new built-in installations receive them too.
542 - A provider's missing-`thought_signature` HTTP 400 now explains how to recover:
543 use the built-in Google provider and start a new session, or verify the
544 gateway's signature handling. Working gateways are not blocked by a broader
545 preflight check (#6048, #6081, thanks @nightt5879).
546 - Chinese documentation links resolve to the contributor guide and Windows
547 screenshots from their translated paths (#6080, thanks @c020627).
548 - GLM-5.3 reasoning controls follow the forced-thinking contract on Z.ai and
549 BigModel routes, including low effort when a prior configuration requested
550 thinking off (#6051, thanks @h3c-hexin and @asto18089).
551 - Finance calls respect the session network policy, and model-facing shell,
552 verifier, notification and Fleet guidance matches executable contracts
553 (#6052, thanks @h3c-hexin and @asto18089).
554 - The sandbox-elevation prompt shows every option, `Abort` included. The card
555 was a fixed 22 rows centred on the frame; inside its border and padding that
556 left at most 18 usable rows against 20 to 23 rows of content, with no scroll
557 rail and no truncation hint. The safe exit — the one choice that grants
558 nothing — was painted past the bottom edge at every terminal size. The card
559 is measured from its content now and reserves the option rows before the
560 denial detail, which is what shortens; below roughly 60x24 the per-option
561 descriptions shed and every choice keeps its row. Option hitboxes were also
562 counted in unwrapped source lines, so a description that wrapped put every
563 hitbox below it out of step and a click committed a different choice than the
564 one under the pointer.
565 - `d` in the Hotbar setup modal asks before it clears every slot. It persisted
566 `hotbar = []` on the first keystroke, in a view that takes bare letters as its
567 filter — the destructive key and the search key were the same press. It arms a
568 confirmation that owns every key until answered, and the prompt takes the
569 intro's place in the header so it cannot be the line that falls off a
570 five-row budget.
571 - Failure red means failure again. The metrics line painted the context reading
572 in the error colour from 80 %, while the posture bar one row above called the
573 identical threshold Attention; the workflow panel painted a `Waiting` row like
574 a crashed one, though its own `is_running` counts Waiting as healthy; and the
575 work surface spent `error_fg` on to-dos that were merely waiting, blocked or
576 stale, and on the routine approach to auto-compaction. `WorkTone` has a real
577 `Failure` variant now, and a guard test holds the reservation across every
578 selectable theme rather than the default alone.
579 - The command palette runs the row you highlighted. `refilter` clamped the
580 selection index but never re-anchored it, and every keystroke re-sorts the
581 list, so refining a query could move the highlight to an unrelated entry that
582 Enter then ran. Long labels also overran their column and pushed the
583 description off the card, because the padding never truncated and the capacity
584 was measured against the popup rather than the content area.
585 - The work surface's first `Down` reaches the first row. Nothing is selected
586 when the dock opens, and that resolved to "row 0 is selected", so the first
587 press moved to row 1 and row 0 could not be reached by pressing Down at all.
588 - Auto-compact could not fire mid-turn. The gate read `max(last billed
589 prompt, /4 estimate of the whole list)`, so as soon as the estimator
590 undercounted the full list below the last bill, every tool result appended
591 after that prompt was invisible to it, and a long turn could exhaust the
592 context window with nothing compacted. It now reads live tokens — the
593 billed prompt plus the growth since it, watermarked when the parent usage
594 is recorded — and is still evaluated at the pre-request boundary after
595 tools complete, never mid-tool-call.
596 - Esc or Ctrl+C during a compaction that is serving an in-flight turn now
597 stops the turn. It previously cancelled only the compaction pass, so the
598 turn resumed against the context that had just failed to shrink. A manual
599 `/compact` with no request in flight still cancels only the pass.
600 - The `request_user_input` dialog is a bottom-anchored sheet instead of a
601 centered 22-row overlay. It leaves the transcript visible above it, grows
602 with its content, and scrolls internally so the highlighted option and the
603 custom response being typed stay on screen at 141x38 and 80x24. Left arrow
604 or `h` goes back to the previous question; Esc still cancels the whole
605 request. PageUp/PageDown, Home/End and modified arrows now review the
606 transcript while the sheet stays open; the mouse wheel scrolls the surface
607 under the pointer. Wheel browsing preserves the answer, and option navigation
608 or typing restores the focused content to view. The transcript viewport ends
609 above question and approval prompts, so End keeps the newest rows visible.
610 Documented in GUIDE.md and KEYBINDINGS.md (#6045).
611 - `/mcp reload` no longer freezes the interface. The reload was awaiting the
612 whole reconnect batch on the TUI event loop; it now joins the same
613 supervised background pass the session boot uses, the status chip counts
614 the batch down live, and the finished receipt arrives as an event. With
615 23 configured servers (11 live, 10 awaiting auth, 2 failing) the first
616 echoed keystroke after a reload lands in ~5 s instead of ~42 s (#5974).
617 - The posture bar no longer states the same duration twice on a first turn
618 (#6041).
619 - Reasoning-capable models whose id carries no version substring
620 (`deepseek-flash`) keep `reasoning_content` in the thinking block instead
621 of the answer text. The gate only ever matched the literal `deepseek-v4`
622 version string, so it now consults the model catalog as well; the older
623 literal arms remain for the V4 aliases they were written for (#6044).
624 - `codewhale model resolve` accepts a provider's declared default even when
625 its registry row is missing — `deepseek-flash` failed resolution against
626 the provider that declares it as default — and a test now resolves every
627 provider's `DEFAULT_*_MODEL` for its own provider (#6043).
628 - A configured `default_text_model` is honored when a new thread's route is
629 resolved. That path consulted only the provider's catalog default, so a
630 config naming one model silently created threads on another, and the
631 unset default disagreed with the shipped one; the active provider's
632 configured default now wins, matching `provider_default_model`, and both
633 unset defaults name `deepseek-flash` (#6043).
634 - Markdown `_italic_` requires both delimiters to be flanking per CommonMark,
635 so math subscripts no longer italicize the prose between them
636 (`[t_, b_p]. Actually — hold on, do we even tile all the way from t_?`
637 rendered 60 characters italic) (#6042).
638 - An MCP server configured for OAuth that answers 401 before its first login
639 now points at `/mcp login <name>` in the failure hint instead of a bearer
640 token that does not exist (#6030).
641 - Cancelling a foreground shell wait stops its owned process group even when
642 the tool future is dropped. Explicitly backgrounded jobs retain their
643 ownership. Interrupted tool receipts distinguish work that started from
644 calls skipped before execution, and returned tool failures remain errors in
645 the next model request.
646 - Saved Fleet model identifiers retain exact spelling through selection,
647 role pins, and roster changes, so changing one saved model does not modify
648 another identifier that differs only in letter case.
649 - Chat wrapping reserves its scrollbar gutter consistently, keeping long
650 identifiers readable when the viewport changes.
651 - The Engine keeps large send-message futures off the event loop's stack,
652 preventing stack exhaustion when a restored session starts a provider turn.
653 - New, imported, and live session titles skip runtime handoffs and use the
654 first real user prompt. Explicitly renamed titles retain priority
655 (#6012, thanks @SparkofSpike).
656 - UI dispatch acceptance now precedes Engine execution, so a delayed acceptance
657 callback cannot overwrite a turn that has already started or completed.
658 Cancelling before acceptance preserves the prompt and leaves the next
659 dispatch usable.
660 - Bottom-chrome effort is omitted when the route cannot prove an effective
661 tier; `/status` retains the full explanation. Cost remains visible when
662 known, and `cost: unknown` remains on metered routes lacking a reading (#5950).
663
664 - Pasting multiline text is one paste again. 0.9.12 gated the
665 paste-burst heuristic off whenever bracketed paste was *requested*, but
666 a terminal can accept `EnableBracketedPaste` and still deliver a paste
667 as individual keystrokes — on those terminals (observed on Windows 11)
668 every pasted line was submitted as its own message. The heuristic is
669 again armed whenever `tui.paste_burst_detection` is on, and the
670 existing `bracketed_paste_seen` guard still disarms it for the rest of
671 the session once a real `Event::Paste` arrives, so fast typing on
672 terminals with working bracketed paste is unaffected (#5981, thanks
673 @nsfoxer).
674 - `serve --acp` no longer breaks strict JetBrains clients: the
675 `initialize` response advertised `sessionCapabilities.list` as a
676 boolean and carried an undefined nested `load` capability; it now
677 sends `{"list": {}}` with no `load` key, per the ACP schema (#5969,
678 reported by @Lujc0523).
679 - Concurrent Codewhale instances no longer destroy each other's queued,
680 unsent text. The offline input queue was one global file that boot
681 cleared on session-id mismatch, so a second instance deleted the
682 first's parked messages. Queues are now keyed per session (mirroring
683 per-session checkpoints), an existing global file is adopted by its
684 owning session rather than discarded, and the adoption race between
685 two instances of the same session tolerates the loser's cleanup.
686 - A tool call truncated at the provider's output limit can no longer be
687 repaired into valid JSON and executed: repairs that had to synthesize
688 structure (append or discard closers) are routed to the existing
689 malformed-arguments path so the model is asked to re-issue — including
690 when the stream is cut before the closing content-block event (#5986).
691 - `codewhale metrics` reads Codewhale's own receipts again: the
692 deepseek-home fallback resolved `$HOME/.deepseek` unconditionally, so
693 the rollup reported all zeros from a directory nothing has written
694 since 2024. The Codewhale audit log is primary, with a checked legacy
695 fallback.
696 - The goal-continuation loop's promised stall bound actually bounds
697 stalls now, and undeclared fleet role names fail closed to read-only
698 `explore` in both fleet drivers instead of resolving to write-capable
699 customs in one and not the other.
700 - `allow_insecure_http = true` under a `[providers.<name>]` table works
701 again. 0.9.12 tightened plain-HTTP base URL handling in a way that
702 silently dropped the per-provider key, leaving the process-wide env
703 var as the only opt-in — LAN llama.cpp and internal-gateway users
704 had to export `CODEWHALE_ALLOW_INSECURE_HTTP=1` to connect at all.
705 The key is honored again (parsed, settable and unsettable through
706 `codewhale config set providers.<name>.allow_insecure_http`, and
707 listed in the custom-provider field hint), it stays distinct from
708 `insecure_skip_tls_verify`, and the refusal message now leads with
709 the config key. Loopback hosts remain auto-allowed and telemetry
710 endpoint validation deliberately still consults neither switch
711 (#5991, thanks @Gabriel-Degret).
712 - A Fleet task that selects a roster member with `worker.agent_profile` now
713 runs with that member's posture. The launch-time resolver only consulted the
714 resolved member when the legacy `worker.role` label was absent, so a task
715 labelled `manager` that selected `member:reviewer` ran as a write-capable
716 manager instead of a reviewer and was never leased. The member's canonical
717 slot now wins whenever one resolved; the label remains the posture only when
718 no member resolved at all. To keep the fix from widening authority in the
719 mirror case (a read-only label on a write-capable member), a spec whose
720 `worker.role` names a different posture than the selected member's role is
721 rejected at run creation with a message naming both postures; casing and
722 legacy aliases of the member's own role are still accepted (#5945, thanks
723 @gaord).
724 - A queued message keeps one transcript entry from queue through steer to
725 dispatch. It no longer reads as delivered while it is still pending, and the
726 second Enter the strip prompts for no longer paints a duplicate bubble.
727 - The Tasks rail panel no longer swallows the first keystroke of typed input:
728 bare `y`/`Y` yank only when the work surface holds keyboard focus, so a
729 message that starts with "yes" stays intact (#2000).
730 - `wait` results reach the parent intact. The parent-context summarizer
731 projected every `agent` tool result through the sub-agent snapshot renderer,
732 which replaced a wait envelope's `settled`, `still_running`, `timed_out`,
733 `waited_ms`, and `note` with `unknown (agent) status=unknown`. Only
734 snapshot-shaped results are summarized now.
735 - A sub-agent's final summary uses the same adaptive tool-result budget as
736 every other tool result (`tool_result_max_bytes`, 12k floor, 2 MiB ceiling)
737 instead of a hardcoded 12k/4k/4k copy that cut a 12,001-character report to
738 8,000.
739 - The metrics line no longer carries a permanent `/help` hint. The route still
740 appears until its binding has been used and then retires with the other
741 footer hints, so the row stays quiet once help is learned.
742 - `request_user_input`'s description names when asking is the right move
743 (ambiguous scope, an irreversible or expensive choice, a missing preference)
744 and when it is not, so the model stops guessing at discoverable facts.
745 - `config.example.toml` states the real search default (keyless Firecrawl, not
746 DuckDuckGo) and the preferred `CODEWHALE_SEARCH_*` environment names.
747 - Startup type-ahead is preserved whole, and a slash command interrupted by
748 startup keystrokes is no longer re-read as prose and sent to the model
749 (#5925).
750 - The model picker renders a large catalog without lag and supports per-column
751 sort and mouse selection (#5975).
752 - Session metrics report effective request throughput from provider receipts
753 instead of a live estimate divided by the whole turn, and cost stays honest
754 when a route has no price reading (#5976, #5977).
755 - An offline-queue submit delivered as late raw keystrokes no longer wedges the
756 composer behind stacked session notices (#5999).
757 - Fleet setup with a model filter that matches nothing renders a hint instead
758 of panicking (#5953), and shortlist enrollment plus authoritative role pins
759 are honored on dispatch (#5915).
760 - A mid-turn MCP catalog refresh keeps the tool pool deferred and the active
761 set narrow (#5939).
762 - Computer Use on macOS verifies application activation before sending
763 keystrokes and guards input by the frontmost app (#5927).
764 - Onboarding tests isolate `CODEWHALE_HOME`, so a fixture provider can no
765 longer leak into the real setup state (#5932).
766 - Snapshot availability is retained with one warning per session, and a
767 diverged engine session id is a visible notice rather than a log line
768 (#5930).
769
770 ### Changed
771
772 - How long Codewhale waits for a human is configurable. `[tools]
773 user_input_timeout_seconds` governs the wait for an approval decision or a
774 `request_user_input` answer; it was a hardcoded 300 seconds, which silently
775 cancelled the work of anyone who stepped away mid-task. An explicit `0`
776 waits indefinitely, the value is clamped to 24 hours, and omitting the key
777 keeps the previous 300-second default. Documented in
778 `docs/CONFIGURATION.md` ([#6003](https://github.com/Hmbown/Codewhale/issues/6003)).
779 - `docs/PROVIDERS.md` lists every beginner setup template, not the four it
780 happened to mention when the page was written. Baseten, Groq, Cerebras and
781 Command Code have shipped as supported OpenAI-compatible hosts for a while
782 and appeared nowhere in the provider documentation, which reads from outside
783 exactly like not supporting them. The page now carries the full table —
784 host, default model and key env for each — and states the rule it follows:
785 a plain Chat Completions backend is a template row, while `ProviderKind` is
786 reserved for distinct wires. A test now fails if a shipped template is
787 missing from that page.
788 - Reasoning capability for the Kimi coding routes and the qwen3.x Model Studio
789 deep-thinking ids is catalog data now rather than hardcoded match arms, and
790 `model_reasoning_capability` reports a model nothing knows about as unknown
791 instead of silently not reasoning-capable. `model_supports_reasoning` keeps
792 its `bool` shape for existing callers, where unknown still reads as false.
793 The ids that have no cited source yet keep their literal arms (#6032).
794 - The website uses Shannon Sans with versioned local font assets and retained
795 serif, monospace, and language fallbacks. Terminal fonts are unchanged.
796 - `codewhale metrics` reports recorded model requests and stream recovery
797 separately from provider-reported token usage, with coverage for missing
798 and duplicate receipts. Status messages and cumulative snapshots do not
799 add requests or count tokens again.
800 - Runtime turn receipts retain the Engine's terminal model-request, stream-retry,
801 and resume counters separately from displayed status and provider-reported
802 usage. These counters do not count HTTP retries inside a provider client or
803 establish provider billing.
804 - Initial tool definitions no longer repeat shell interpreter guidance and
805 agent lifecycle/scope instructions in multiple description fields. Parameter
806 schemas, approval rules and dispatch behavior are preserved. This reduces
807 prompt schema size; it does not establish a provider billing regression.
808
809 - The built-in Computer Use plugin bundle is refreshed to the standalone
810 plugin's 0.2.1 runtime (vendored from `Hmbown/codewhale-cu-plugin`
811 at `724ad258`): the native macOS accessibility backend with an
812 a11y-first pointer strategy (covered points are refused, previews are
813 drawn), the permission-owning desktop-app socket transport, remote
814 computers over ssh and HarmonyOS HDC with contained temp handling,
815 truthful win32 PowerShell failure reporting, and the shared
816 allow-listed request handler for the app socket and ssh agent.
817 The bundle retains the hardening port from
818 [standalone plugin PR #12](https://github.com/Hmbown/codewhale-cu-plugin/pull/12).
819 Single left clicks on macOS element targets now revalidate and press
820 the observed element directly, without substituting a point hit-test
821 or raw-pointer fallback. Explicit event clicks retain the app-ownership
822 guard; a sent press still requires visual verification. Background mode
823 permits application-bound keys and accessibility actions while refusing
824 shared-pointer gestures; it does not provide an isolated desktop. The
825 embed list gained the five new runtime files, and a consistency test
826 now pins the embed list to the vendored tree so the bundle cannot rot
827 silently again. Because the bundle's content hash changes, Computer
828 Use deactivates and asks for a fresh review after upgrading — that is
829 the designed fail-closed path for a desktop-driving plugin. The
830 current macOS source candidate also embeds the compiled native helper,
831 so its bundled server can run directly without a separate Computer Use
832 app or a compiler on the user's machine. Accessibility and Screen
833 Recording permissions belong to the hosting app or terminal and remain
834 user-controlled. The CLI's Computer Use server requires Node.js 20 or newer. These are source
835 candidate changes; they do not establish published-package or platform
836 qualification. See the [included plugin guide](crates/tui/plugins/computer-use/README.md)
837 for platform requirements and limitations.
838 - `/statusline` drives the bottom chrome again. Since the 0.9.12 shell
839 redesign the posture bar and the metrics line were built independently of
840 `tui.status_items`, so every toggle in the picker except the balance fetch
841 was decoration. Each remaining item now shows or hides exactly one thing:
842 `model`, `context_percent`, `cost`, `balance`, `cache`, `tokens` and
843 `session_metrics` are metrics-line segments, and `mode` is the posture
844 bar's plan/act/operate chip. The `status`, `agents`, `reasoning_replay`,
845 `prefix_stability`, `git_branch`, `last_tool_elapsed` and `rate_limit`
846 items drove nothing and are retired; an existing `config.toml` still loads
847 and those keys are ignored (#5950, #5962).
848 - The context reading is back on screen at every fullness. 0.9.12 painted
849 `ctx NN%` only from 50% up, which left most of a session with no context
850 signal at all; it now paints from 0% and keeps its warning colour from 80%
851 up (#5950).
852 - A child agent parked because its parent's turn ended is shown as `parked`
853 in the Agents panel, the sidebar and Agent Details, with `resume_from` /
854 `cancel` as the recovery, instead of wearing the same "waiting for input"
855 label as a child that asked a question. Parked work sorts below live and
856 answerable work and no longer inflates the `blocked` chip; the receipts
857 roster and the wire `state` gain `parked` (#5906, #5921).
858
859 - `codewhale account keys set|remove|list` no longer carry a hardcoded
860 eight-provider list. Provider ids come from the control plane's public
861 catalog (`GET /api/model-providers`), are validated locally against
862 `^[a-z0-9][a-z0-9-]{0,63}$` before they reach a URL path, and `list` shows
863 every catalog provider with its label and stored-key state. `--from-local`
864 maps a catalog row onto the local runtime provider through the catalog's own
865 `runtimeProvider` field, so a newly supported provider needs no CLI release.
866
867 - `/mcp` lists the servers that need a login first, as their own
868 `Needs login` group above `Needs attention`, and opens with the cursor
869 already on the first such row so the Enter the screen advertises runs
870 `/mcp login <server>` straight away; translated in all 15 packs. A
871 snapshot test pins the footer shape the chip landed with (`MCP · N
872 connected · N ◆ auth required · N failed`) so an expired login never
873 regresses into the failed count (#5926).
874
875 ### Fixed
876
877 - Five of the load-flaky tests tracked in #5929 no longer depend on shared
878 state or live local daemons. Background-hook capture tests wait for the
879 capture file to hold bytes instead of merely existing (the shell's `>`
880 redirection creates the file empty before `cat` writes, which read as
881 `valid JSON: EOF` under load); the session-picker acceptance test drives
882 the real picker over a private store instead of a process-global
883 `CODEWHALE_HOME` redirect that concurrent tests could observe mid-flight;
884 the DeepSeek-Anthropic translate test holds the test env barrier so its
885 request-time and assertion-time `max_tokens` reads cannot straddle another
886 test's `CODEWHALE_MAX_OUTPUT_TOKENS` override; the unit-test binary no
887 longer probes a real local Ollama daemon (`127.0.0.1:11434`) from the
888 fire-and-forget provider catalog refresh, whose merged tags could flip
889 another test's live-snapshot assertions; and the tmux clipboard test's
890 attach/OSC 52 wait bounds tolerate a fully loaded machine (3s -> 30s)
891 without changing what they verify (#5929).
892 - The posture bar states how long the session has been working and how long
893 the current turn has run, distinguishing actively working from waiting on
894 a tool, a sub-agent or the operator; the 0.9.12 shell had dropped the overall
895 working-time indicator from the place a glancing user checks (#5914).
896 - A background runtime turn whose own store record could not be read, parsed
897 or written (`Failed to read turn …`, `Failed to read item …`) was only a log
898 line. The runtime now publishes a `runtime.store_failure` event naming the
899 file, the root cause and the next action (move the file aside, or check free
900 space and permissions); the TUI shows it as a warning toast and a transcript
901 line, the task timeline records it, and the runtime API streams it. A turn
902 whose own record is unreadable or unwritable is reported as terminal, so its
903 task fails at once instead of idling out (#5931).
904
905 - An MCP token refresh that fails to parse the provider's answer keeps the
906 endpoint's receipt — status line, content type, and a 200-byte excerpt
907 with every credential-shaped value (`access_token`, `refresh_token`,
908 `client_secret`, `id_token`, bearer schemes) masked before the cut —
909 instead of rmcp's bare `Failed to parse server response`, so a provider
910 outage answering an HTML 502 reads differently from a parser defect, and
911 the login remedy stays named (#5926; remedy wording landed in #5959).
912
913 ### Added
914
915 - `POST /v1/threads/{id}/file-revert` restores exactly one file from the
916 exact `tool:`/`pre-turn:` snapshot the client selected, checking the
917 reviewed file hash before and after the mandatory safety snapshot. Literal
918 file names, regular files only, thread trust and active-turn admission are
919 enforced, and `patch-undo` no longer forks a conversation whose file
920 rollback failed (#6111, thanks @gaord; engine half of
921 HengQuWorld/CodeWhale-VSCode#3).
922 - Authenticated Runtime API workspace file suggestions reuse TUI `@file`
923 matching and discovery, with bounded queries/results and workspace-contained
924 relative paths only (`GET /v1/workspace/files/search`, #6095, #6120, thanks @wuisabel-gif; reported by @LmeSzinc). Shared discovery
925 now honors disabled symlink following for AI-tool directory scan roots too.
926 - Serply is available as an opt-in `[search]` provider for the Web tool
927 (`provider = "serply"`, key from `[search] api_key` or `SERPLY_API_KEY`).
928 Preflight fails closed without a key; Firecrawl remains the default and
929 existing configurations are unchanged (#6100, thanks @googio).
930 - Linux terminals: finishing a transcript or composer mouse selection copies
931 the text to the PRIMARY selection without touching the regular clipboard, and
932 middle-click inside the composer pastes PRIMARY at the pointer without
933 submitting. Native X11 and Wayland data control are used through one bounded
934 background worker; SSH sessions without a forwarded display keep their
935 terminal's own selection behavior (#6116, thanks @dmt4).
936 - `codewhale sessions export <id-or-unique-prefix>` saves a `.tar.xz` archive
937 with the durable record, portable session container, manifest and artifacts.
938 Prefix exports preserve unfinished tool calls; confined reads reject linked
939 artifact roots, and existing outputs require `--force`. Archives retain
940 unredacted content; `/load` opens the extracted record without installing
941 extracted artifacts (#6056, thanks @h3c-hexin and @asto18089).
942
943 - `deepseek-flash` (DeepSeek V4.1 Flash: 1M-token context,
944 reasoning and tool calls) joins the catalog as DeepSeek's declared default,
945 and the offline catalog seed matches it; the DeepSeek Pro listing no longer
946 overstates the published price (#6025).
947 - DeepSeek's September 11 reversal is reflected in provider notices and cost
948 estimates: V4 Pro remains available after September 14 at Pro rates. Explicit
949 Pro selections remain unchanged; Flash remains the default (#6025, thanks @ronohara).
950 - Native plugin authoring guides now cover English and Chinese. The explicit
951 offline converter supports selected portable Skills and static Streamable
952 HTTP MCP declarations from OpenCode and DSH. Unsupported executable hooks,
953 automatic OAuth and policy-bearing configurations are refused; generated
954 bundles still require native installation, review and trust. Legacy SSE
955 fallback is not reproduced (#5827, requested by @giancarlocp).
956
957 - Signed cloud model facts can refresh provider capabilities and prices while
958 preserving verified cached data when a refresh fails. A dispatched request
959 keeps its selected price snapshot so later catalog updates cannot change its
960 recorded cost (#5752).
961 - Saved sessions preserve exact provider routes. Auxiliary model calls settle
962 their usage once against the route and price snapshot that executed them,
963 including recovery, rather than resolving a new price at completion
964 (#5726, #5848).
965 - `[tui].posture_bar` and `[tui].metrics_line` accept `full`, `compact`, or
966 `hidden`, also available through `/config`. Compact preserves the existing
967 rows' essential fields; hidden returns their space to the transcript (#5973).
968 - Optional model-bound tool-output redaction opt-out, with two explicit startup
969 confirmations and a receipt bound to the readable config contents and
970 modification time. Unconfirmed requests keep masking enabled; routing and
971 stored goal summaries remain redacted (#5982, thanks @SparkofSpike).
972
973 - The `rusty-alloc` cargo feature on `codewhale-tui` and `codewhale-cli`
974 opts the binaries into the `rusty_alloc` global allocator (the mimalloc
975 v2.4.5 architecture remade in pure Rust — no C compiler or build script
976 on that path) instead of the default mimalloc. It is off by default and
977 the default build is unchanged; build with
978 `cargo build -p codewhale-tui --features rusty-alloc` (#5872).
979 - The `/theme` picker now discovers valid user-authored `custom:<name>`
980 overlays, previews their colors, highlights the active overlay, and preserves
981 it when the picker is opened and committed without navigation (#5901).
982 - Compaction has two standing knobs next to `[context]` in config.toml:
983 `[compaction] summary_instructions` (appended to the summarizer prompt on
984 every manual and automatic pass; `/compact <focus>` still composes after
985 it) and `[compaction] retained_user_message_tokens` (default 20 000,
986 clamped 2 000..=200 000) for the verbatim user-message budget. Both are
987 absent by default and absent means the pre-existing behavior. The
988 `/compact` receipt names the effective budget and whether operator
989 instructions applied (#5956).
990 - `[tools] user_input_max_questions` (default 6, 1..=10) and
991 `[tools] user_input_max_options` (default 4, 2..=10) replace the hard-coded
992 `request_user_input` limits; the validator, the tool schema and its
993 description read one value, spawned children inherit the parent's ceilings,
994 and a rejected payload names the ceiling it hit and the key to raise (#5949).
995 - The slash menu shows a command's usage line and its subcommands as soon as
996 a space is typed after the verb, filtered by what follows, so Tab completes
997 `/workspace wor` to `/workspace worktrees`; `/help` states the focused
998 command's usage in its detail slot (#5952).
999 - The three `/fleet` views (roster, live workers, saved teams) are one
1000 back-navigable stack: `Esc` in workers or saved teams returns to the roster
1001 with its cursor intact and still closes the window at the root or on direct
1002 entry; the `Esc` footer hint says `back` or `close` accordingly (#5954).
1003 - `/fleet` presents its prioritized core (`members`, `setup`, `teams`,
1004 `workers`, `help`); every other verb stays dispatchable and is documented
1005 under explicit groups in `/fleet help`. The roster no longer shows the
1006 untouched built-in `general` alias next to `worker` (#5888).
1007 - `codewhale` provider: account-backed model access over the provider keys a
1008 customer connected to their Codewhale account. One base URL
1009 (`https://api.codewhale.net/v1`, overridable with `CODEWHALE_API_BASE`;
1010 HTTPS required except on loopback), one `cwc_key_…` account API key with the
1011 `models:infer` scope (`CODEWHALE_API_KEY`), and a per-model wire chosen from
1012 the account's authenticated `GET /v1/models`: ids are `provider/model` and
1013 each row states `chat-completions` (`/v1/chat/completions`) or
1014 `anthropic-messages` (`/v1/messages`). Both protocols authenticate with
1015 `Authorization: Bearer`, never `x-api-key`. The key is read from
1016 `CODEWHALE_API_KEY`, the `codewhale` secret-store slot, or
1017 `[providers.codewhale] api_key` / `api_key_env`, and a missing key fails
1018 before any request instead of dispatching unauthenticated. If the catalog
1019 cannot be fetched the route falls back to three bootstrap ids and says so.
1020 - `codewhale account api-keys create --scope` now accepts `models:infer`
1021 alongside `account:read` and `agent:run`, and an omitted `--scope` sends all
1022 three explicitly. `--use` saves the new secret as this machine's local
1023 `codewhale` provider credential in the same secret store `codewhale auth`
1024 uses; nothing is uploaded.
1025 - `Git` grows a `commit_plan` action: a propose-only planner that splits the
1026 working tree into ordered atomic commits (#3999). It groups whole files —
1027 lock files ride with their manifest, tests ride with the source they name —
1028 orders the groups so a commit that defines a symbol lands before the commit
1029 that uses it, and refuses the whole plan when that dependency graph has a
1030 cycle. It reads `git diff HEAD` plus the untracked-file list and writes
1031 nothing: no `git add -N`, no `git apply --cached`, no `git commit`, so
1032 staging and committing stay with the ordinary `git add` / `git commit` shell
1033 path where the approval gate already applies. Thanks
1034 [@goransh-walia](https://github.com/goransh-walia) for the original
1035 implementation (PR #5870, fixes #3999).
1036
1037 ### Contributors
1038
1039 - **[@LmeSzinc](https://github.com/LmeSzinc)** — requested Runtime API access to the TUI's fuzzy file search ([#6095](https://github.com/Hmbown/Codewhale/issues/6095)).
1040 - **[@googio](https://github.com/googio)** — added the Serply web-search provider ([#6100](https://github.com/Hmbown/Codewhale/pull/6100)).
1041 - **[@dmt4](https://github.com/dmt4)** — requested Linux copy-on-select and middle-click paste ([#6116](https://github.com/Hmbown/Codewhale/issues/6116)).
1042 - **[@Gabriel-Degret](https://github.com/Gabriel-Degret)** — reported that saved agent profiles were silently ignored when spawning sub-agents ([#6117](https://github.com/Hmbown/Codewhale/issues/6117)).
1043 - @nightt5879 — Gemini signature recovery guidance and transport regressions (#6081).
1044 - @c020627 — Chinese documentation link repairs (#6080).
1045 - @h3c-hexin and @asto18089 — GLM-5.3 reasoning controls and tool-gating/documentation fixes (#6051, #6052).
1046 - @Hmbown — dependency updates (#6057) and the Gemini signature recovery report (#6048).
1047 - **[@gaord](https://github.com/gaord)** — contributed the file-scoped restore endpoint and the trust-gated whole-tree rollback ([#6111](https://github.com/Hmbown/Codewhale/pull/6111)), Fleet schema inspection, role precedence and worker deliverable receipts, and linked the community VS Code frontend ([#5944](https://github.com/Hmbown/Codewhale/pull/5944), [#5945](https://github.com/Hmbown/Codewhale/pull/5945), [#5946](https://github.com/Hmbown/Codewhale/pull/5946), [#5992](https://github.com/Hmbown/Codewhale/pull/5992)).
1048 - **[@goransh-walia](https://github.com/goransh-walia)** — contributed the propose-only commit-planning rework ([#5870](https://github.com/Hmbown/Codewhale/pull/5870)).
1049 - **[@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/Hmbown/Codewhale/pull/5996), [#5952](https://github.com/Hmbown/Codewhale/issues/5952), [#5954](https://github.com/Hmbown/Codewhale/issues/5954), [#6003](https://github.com/Hmbown/Codewhale/issues/6003), [#6004](https://github.com/Hmbown/Codewhale/issues/6004), [#6006](https://github.com/Hmbown/Codewhale/issues/6006), [#6007](https://github.com/Hmbown/Codewhale/issues/6007)).
1050 - **[@SparkofSpike](https://github.com/SparkofSpike)** — contributed two-stage consent for opting out of model-bound credential redaction ([#5982](https://github.com/Hmbown/Codewhale/pull/5982)).
1051 - **[@aboimpinto](https://github.com/aboimpinto)** — moved session lifecycle and session-control commands onto shared command contracts ([#5902](https://github.com/Hmbown/Codewhale/pull/5902), [#5951](https://github.com/Hmbown/Codewhale/pull/5951)).
1052 - **[@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/Hmbown/Codewhale/issues/5908), [#5909](https://github.com/Hmbown/Codewhale/issues/5909), [#5910](https://github.com/Hmbown/Codewhale/pull/5910), [#5911](https://github.com/Hmbown/Codewhale/pull/5911), [#5912](https://github.com/Hmbown/Codewhale/pull/5912)).
1053 - **[@wuisabel-gif](https://github.com/wuisabel-gif)** — exposed workspace file suggestions through the Runtime API ([#6120](https://github.com/Hmbown/Codewhale/pull/6120)) and added custom-theme discovery, preview and selection in the theme picker ([#5907](https://github.com/Hmbown/Codewhale/pull/5907)).
1054 - **[@zhuowp](https://github.com/zhuowp)** — matched model-visible shell guidance to the interpreter selected for execution ([#5900](https://github.com/Hmbown/Codewhale/pull/5900)).
1055 - **[@nsfoxer](https://github.com/nsfoxer)** — reported the multiline-paste regression and incomplete provider model lists ([#5981](https://github.com/Hmbown/Codewhale/issues/5981), [#6009](https://github.com/Hmbown/Codewhale/issues/6009)).
1056 - **[@Nefelibata1024](https://github.com/Nefelibata1024)** — confirmed the multiline-paste regression's impact ([#5981](https://github.com/Hmbown/Codewhale/issues/5981)).
1057 - **[@Gabriel-Degret](https://github.com/Gabriel-Degret)** — reported the loss of the allow_insecure_http provider setting ([#5991](https://github.com/Hmbown/Codewhale/issues/5991)).
1058 - **[@Lujc0523](https://github.com/Lujc0523)** — reported the ACP initialize schema violation affecting strict IDE clients ([#5969](https://github.com/Hmbown/Codewhale/issues/5969)).
1059 - **[@mo-vic](https://github.com/mo-vic)** — proposed storing evicted context on disk so it can be retrieved later ([#6008](https://github.com/Hmbown/Codewhale/issues/6008)).
1060 - **[@giancarlocp](https://github.com/giancarlocp)** — requested a plugin authoring guide and OpenCode plugin conversion ([#5827](https://github.com/Hmbown/Codewhale/discussions/5827)).
1061 - **[@hxfhd](https://github.com/hxfhd)** — supplied a Windows reproduction of a turn stopping before its stated next tool action ([#6010](https://github.com/Hmbown/Codewhale/discussions/6010)).
1062
1063 ### Notes
1064
1065 - **DeepSeek V4 Pro continues after September 14.** The vendor reversed its
1066 earlier retirement notice. Codewhale preserves Pro selections and Pro pricing;
1067 `deepseek-flash` remains the default for new direct DeepSeek configurations.
1068 - Upgrading from 0.9.12 with Computer Use trusted and enabled: the
1069 bundle's content hash changes with the 0.2.1 refresh, so the plugin
1070 deactivates and asks for a fresh review — that is the designed
1071 fail-closed path for a desktop-driving plugin. Re-trust it from the
1072 Plugins page.
1073 - The multiline-paste fix restores v9.11 behavior on terminals that
1074 accept `EnableBracketedPaste` but deliver pastes as keystrokes
1075 (reported on Windows 11 / PowerShell). Verified at the input-contract
1076 level and in CI; a manual paste check on a real Windows terminal is
1077 still welcome — please comment on #5981 with your terminal if anything
1078 still misbehaves.
1079
1080 ## [0.9.12] - 2026-09-03
1081
1082 Codewhale v0.9.12 puts computer use in the binary, opens two new routes —
1083 Alibaba Model Studio through the data-driven provider table and Concentrate
1084 as an opt-in BYOK Responses gateway — and adds cloud dispatch plus a
1085 config-gated per-session control socket. The shell is the other half of the
1086 release: a new launch card, the work surface docked under the composer, one
1087 focus owner for Tab, tool cells that carry their own state, and `fleet` as
1088 the public word for the live collective. The complete item-level change
1089 record is retained below the categorized release highlights.
1090
1091 ### Added
1092
1093 - Computer use ships with the binary. The `computer-use` plugin — 38 tools
1094 across macOS, Windows, Linux and HarmonyOS, accessibility-first observation
1095 with pixel fallback, screenshots, zoom, screen recording, and registered
1096 remote computers over ssh and hdc — is embedded in Codewhale and written to
1097 `$CODEWHALE_HOME/builtin-plugins` on first run, so every install channel
1098 carries it. It lists as `builtin · not-reviewed` and stays disabled until
1099 you review and enable it: shipping it is not consenting to it. The
1100 stdlib-Python computer-use server it replaces is gone.
1101 - Alibaba Model Studio joins the data-driven provider table as an
1102 `openai-compatible` descriptor: international compatible-mode endpoint,
1103 `DASHSCOPE_API_KEY` credential, live `/v1/models` discovery. Qwen 3.8
1104 Flash and Qwen 3.8 Max arrive through the catalog authority — never a
1105 hard-coded id.
1106 - Concentrate: first-class opt-in BYOK Responses gateway with live models
1107 discovery and typed SSE streaming (#5725).
1108 - Cloud dispatch: remote runner offloads coding agent tasks to isolated
1109 cloud sandboxes with machine token auth and structured job tracking
1110 (#5701, #5712).
1111 - Per-session control socket: config-gated `[control_socket]` table binds
1112 `<sessions-dir>/<session-id>/control.sock` per running session, exposing
1113 message, interrupt, relaunch, and status JSON-RPC verbs (#5533, #5831).
1114
1115 ### Changed
1116
1117 - **Anonymous usage counting is on by default.** The 0.9.11 release asked
1118 first; 0.9.12 counts the same aggregate version/platform, session, feature
1119 and error totals unless you turn it off, and says so once at first launch
1120 (policy notice version 5, schema 3, `notice_version` replacing
1121 `consent_version`). Every recorded opt-out stays off: a durable
1122 `telemetry = false`, a decline recorded under the old opt-in notice,
1123 unreadable privacy state, and the `CODEWHALE_TELEMETRY=0` / `--telemetry
1124 false` kill switches. Showing the disclosure records only that it was
1125 shown, never an acceptance. `codewhale config set telemetry false` turns
1126 it off and wipes queued counts; `codewhale config set telemetry true`
1127 deliberately re-enables it. Nothing new is collected: no conversations,
1128 code, prompts, files, names, model content, credentials, or IP.
1129
1130 - The launch screen is our own card take: a thin top line
1131 `⑂ branch path`; a centred bordered card with the whale mark,
1132 `Codewhale` + version, one announcement line only when it is true (the
1133 no-model warning, or MCP news), and the menu New worktree / Resume
1134 session / Changelog / Quit with their real chords right-aligned. Enter
1135 runs the highlighted entry, Up/Down move it, and typing goes straight to
1136 the composer. The card dissolves on the first keystroke or command
1137 (≤240 ms, instant under reduced motion) (#5826, #5801, #5815, #5286).
1138 - The work surface sits under the composer by default, keeping history
1139 readable and leaving the stage unencumbered (#5809).
1140 - Skills command shapes: FEAT-022 command shapes and retained-host
1141 validation (#5825, #5829).
1142 - After the card dissolves, the working screen shows `⑂ branch path` with
1143 `⋮ MCP n/m` on the right, the transcript starts with the
1144 `◆ session_start` receipt (naming the configured session-start hooks),
1145 and the composer's bottom rule carries `model (effort) · permission` —
1146 the route's one launch reading. The posture bar and metrics line appear
1147 only once a session exists.
1148 - Vocabulary: `fleet` is the public term and `Pod` is retired from copy —
1149 roster, setup, detail, worker-runtime and managed-API messages now say
1150 Fleet (`/fleet` canonical, `/pod` alias). The workflow wire accepts the
1151 canonical role spellings (general/explore/planner/reviewer/implement/
1152 test/advisor) with the pre-rename ones kept as load-time aliases, and
1153 serializes canonical names.
1154 - The Operate mode-picker hint is shortened to fit 80 columns.
1155
1156 - The footer always shows the permission posture; when only one chip
1157 fits, the permission chip outranks the mode word (#5796).
1158 - Local Ollama: the header names a model only when the local catalog can
1159 serve it, and says `unknown` until it knows. The startup mark, web and
1160 app icon carry the new side-view prompt-eye whale (#5795).
1161 - One focus owner: Tab and Shift+Tab work regardless of what is in the
1162 composer; Alt shortcuts survive mid-draft; Ctrl+Tab no longer cycles the
1163 mode by accident (#5798).
1164 - Tool cells carry their own state: a running, failed or warned tool
1165 reads as such in the transcript itself, with per-entry rail dots and
1166 family-coloured glyphs (#5799).
1167 - Web: docs hub with task search, shared empty/loading/error states, an
1168 offline-to-back-online banner, `/changelog` in every locale, and real
1169 404s with correct metadata (#5743).
1170 - Web: the app's colours come from one file generated from the TUI whale
1171 palette; re-typing a colour by hand fails web CI (#5797).
1172 - Web: a one-way ceiling on `isZh` branching outside the i18n spine —
1173 the count may only go down (#5805).
1174 - An internal agent handoff doc was removed from the public tree and
1175 `.playwright-mcp/` is now ignored (#5800).
1176 - First run paints the composer immediately: the Welcome/language/provider/
1177 trust gates no longer precede the first keystroke. Missing-key and
1178 workspace-trust recovery stay for returning users; language and provider
1179 remain in `/setup`.
1180 - The canonical whale-tile mark propagates beyond web to the exact-raster
1181 surfaces that can carry it (#5738).
1182 - Dead-code sweep: delete proven-unreferenced helpers (unused builders,
1183 wrappers, and leftover identifiers) and drop stale `#[allow(dead_code)]`
1184 where the item is production-called or test-exercised. No runtime behavior
1185 change (#5791, #5587).
1186 - Remote-control recovery gives every fresh pre-dispatch attempt a new lease
1187 generation while preserving that generation across its typed start (#5605).
1188
1189 - Public roster language is Pod. `/pod` is the customer surface; fleet remains
1190 the internal wire, storage, and migration name (#5776).
1191
1192 - Compaction replacement history keeps a bounded last user round (assistant +
1193 tool results) instead of dropping them behind a summary. `/context` names
1194 the compaction path and `/anchor` survival. Failed compact still does not
1195 replace live history (#4394).
1196 - Provider catalogs: compatible hosts (Baseten, Groq, Cerebras, SenseNova,
1197 Command Code) no longer compile a frozen model roster. Descriptors name the
1198 wire, URL, and env; live `GET /v1/models` and a Codewhale-owned catalog
1199 layer are the offering list. Command Code is a catalog/descriptor row, not
1200 a `ProviderKind`. Catalog presence is not an availability, entitlement, or
1201 provider-acceptance claim (#5783).
1202
1203 - Provider selection no longer probes or adopts an external CLI credential on
1204 ordinary picker use. Reuse requires an explicit "Use external CLI credentials"
1205 choice, exact-path confirmation, and Codewhale-owned revoke (#5772).
1206
1207 - TUI: startup no longer presents an approximate ASCII or block-glyph whale as
1208 the product mark. It keeps the direct Tideline prompt while exact-raster
1209 surfaces remain responsible for the canonical asset.
1210
1211 - TUI: the active-session composer paints the same three-cell `[↑]` send
1212 target as Startup and clicks it through the existing Enter submit
1213 dispatcher (#5771). Compact/quiet composers still omit the control.
1214
1215 - TUI/CLI: Pod is the public roster surface. User-facing Fleet wording
1216 moves to Pod; durable receipt keys stay compatible (#5776).
1217
1218 ### Contributors
1219
1220 - **hexin ([@h3c-hexin](https://github.com/h3c-hexin))** — provider-native web
1221 search across four routes (#5682, #5683, #5685, #5687), authoritative
1222 edit-last-turn boundaries (#5621), Kimi Code k3-256k (#5622),
1223 post-compaction input-token reporting (#5623), and preserving the scheduled
1224 model selection in automations (#5650).
1225 - **秋月凉梦 ([@qiuYliangM](https://github.com/qiuYliangM))** — co-authored the
1226 edit-last-turn boundary fix (#5621), Kimi Code k3-256k support (#5622), and
1227 post-compaction input-token reporting (#5623).
1228 - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — live
1229 session token totals (#5624), persisted context-pressure warnings (#5629),
1230 discoverable Fleet roster editing (#5604), the capability-gated cursor
1231 accent (#5599), and `/copy` for the latest completed response (#5692).
1232 - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** —
1233 Windows verbatim-path operands preserved through POSIX word splitting
1234 (#5610), the plugins group moved onto the command shapes (#5657), FEAT-022
1235 skills command shapes with retained-host validation (#5825), and FEAT-020
1236 plugin command shapes re-landed on main (#5865).
1237 - **Alex Musichen ([@musichen](https://github.com/musichen))** — a stable
1238 DeepSeek heading in the configured-view model picker, keeping every official
1239 catalog model for the active provider visible (#5689).
1240 - **[@gaord](https://github.com/gaord)** — the `GET /v1/fleet/profiles`
1241 runtime API endpoint, reusing the FleetManager validation path (#5688).
1242 - **Sh1Zuku ([@SparkofSpike](https://github.com/SparkofSpike))** — corrected
1243 English documentation inaccuracies and the first zh_hans translations for
1244 the Tier-2 docs (#5613).
1245 - **[@M-Maciej](https://github.com/M-Maciej)** — goal continuation cadence
1246 (#5591) and the per-session control socket (#5533, #5831).
1247 - **Serephus ([@serephus](https://github.com/serephus))** — nixpkgs update
1248 (#5669).
1249 - **[@whp233](https://github.com/whp233)** — `wire = responses|anthropic` for
1250 openai-compatible custom routes and opencode-zen muse-spark (#5716, landed
1251 as #5719).
1252 - **Gabriel Degret ([@Gabriel-Degret](https://github.com/Gabriel-Degret))** —
1253 found the reasoning-only retry gap and built the first fix; landed as the
1254 `[reasoning_only]` retry ceiling with a request-scoped nudge (#5867).
1255 - **[@huangxianzhan](https://github.com/huangxianzhan)** — the
1256 `x-opencode-session` header for OpenCode Go and Zen gateways (#5868).
1257 - **[@zhuowp](https://github.com/zhuowp)** — task origin preserved in job
1258 snapshots (#5869).
1259 - **AdityaG ([@AdityaVG13](https://github.com/AdityaVG13))** — a ten-commit
1260 performance pass: a zero-copy LaTeX fast path for streaming render,
1261 single-pass token accounting on the per-turn pressure paths, memoized
1262 provider resolution in the catalog cutline, parsing the bundled and
1263 on-disk models.dev catalogs once per process (interactive boot -70%),
1264 adaptive poll cadence for foreground shell completion, and worker caps
1265 across the read-only diagnostic family.
1266 - **Nightt ([@nightt5879](https://github.com/nightt5879))** — isolated remote
1267 recovery lease generations (#5790).
1268 - **[@yiheng-kkk](https://github.com/yiheng-kkk)** — replaced stale todo
1269 transcript snapshots so a rewritten todo list renders its current tasks
1270 (#5871, #5873).
1271 - **[@Lfanxing](https://github.com/Lfanxing)** — Moonshot routes now degrade
1272 incompatible tool definitions per request instead of failing the turn.
1273 - **WissssleyL ([@Lstarsky0](https://github.com/Lstarsky0))** — moved
1274 `docs/subagents` and `docs/mcp` onto the dictionary spine (#5337), with the
1275 metaTitle probe that keeps them there.
1276
1277 Reports and reproductions that shaped this release:
1278
1279 - **[@slowly247](https://github.com/slowly247)** — reported the Ollama input
1280 budget collapsing to 1,024 tokens on 32K local models (#5820).
1281 - **[@ronohara](https://github.com/ronohara)** — reported the engine stopping
1282 after recoverable network errors, with the reproduction that pinned the
1283 discarded approval (#5769), and surfaced DeepSeek's model-service notices and the subsequent reversal
1284 retaining V4 Pro (#6025).
1285 - **[@Lujc0523](https://github.com/Lujc0523)** — asked for ACP session
1286 configuration of mode and model (#5863).
1287 - **[@senka9h](https://github.com/senka9h)** — reported that `serve --acp`
1288 lacked `session/list` and `session/load` (#5864).
1289
1290 ### Added
1291
1292 - Native ChatGPT sign-in for the `openai-codex` route: `codewhale auth
1293 chatgpt` opens a browser PKCE flow and stores refreshable tokens in
1294 Codewhale-owned credentials — no Codex CLI install required.
1295 `/auth chatgpt-revoke` clears them off the event loop (#5784, #5778).
1296 - MCP servers and plugins can be connected self-serve from the session: a
1297 unified auth flow with rotation-safe token handling, a spoken authorization
1298 URL, and catalog refresh when stored credentials stop working (#5747).
1299 - `/operate` reads match the landed CWC `OperateRecord` contract: fetching an
1300 absent record returns a truthful not-found view instead of a fabricated
1301 operation, and an empty evidence path is rejected rather than resolving to
1302 the workspace directory (#5703).
1303 - TUI: scheduled automations project into the top strip
1304 (`⏱ N scheduled · M running`, compact `⏱ N·M`) with typed
1305 `HistoryCell::Automation` receipts when a run this session watched settle.
1306 `/automation` acknowledges failures. The merged footer does not carry the
1307 work fact (#5748).
1308 - The app-server can listen on a unix domain socket and advertise a
1309 `daemon/attach` handshake, so a local client can attach to an already-running
1310 engine instead of spawning its own. The socket is created with
1311 owner-only permissions and stale sockets are reclaimed on start. Non-unix
1312 hosts return a typed unsupported-platform refusal; the Windows named-pipe
1313 endpoint is named but not yet implemented (#5749).
1314 - The engine's internal `Op`/`Event` types and the wire protocol's `Op`/
1315 `EventMsg` now carry a compile-enforced twin for every variant: adding an
1316 engine variant without a protocol counterpart fails the build instead of
1317 drifting silently. Internal durability work — no user-visible surface
1318 change yet (#5751).
1319 - Machine tokens: with `CODEWHALE_API_KEY` set, the CLI authenticates as the
1320 Codewhale account with no local session file and no browser — the CI
1321 authentication path, with a typed token shape and redaction (#5721).
1322 - Compaction publishes a structured survival contract for session-tree
1323 journal entry types (`crates/tui/src/compaction/SURVIVAL_CONTRACT.md`) and
1324 fails closed when the last user round, tool results, `/anchor` text, or
1325 checkpoint receipt would vanish (#4394, #5782).
1326 - Internal: `codewhale-config` gains `RouteAuthoritySnapshot`, one immutable
1327 authority that owns a compiled provider catalog together with the route
1328 resolver projected from it, so a picker, a readiness view, and an execution
1329 path can no longer resolve against different catalog snapshots without a
1330 type-level signal. Resolution still goes through the sole resolver; the
1331 returned receipt distinguishes an exact catalog row, a custom-endpoint route
1332 whose provider facts are deliberately not reused, and an allowed
1333 pass-through route with no catalog row. All state is secret-free. No call
1334 site changed and no user-visible behaviour changed yet (#5766).
1335
1336 - Computer session records now count only time a provider actually accepted the
1337 session as active, at per-second granularity. Idle, queued, stopped, and
1338 teardown time are excluded, and a session whose allocation does not match a
1339 standard profile is refused rather than recorded approximately. Covered by
1340 hermetic fixtures; no live provider call and no deploy (#5781).
1341
1342 - Website: the public site moves to the Tideline deep-ocean design language
1343 (dark by default with an opt-in light documentation sheet, palette grounded
1344 in the TUI's WHALE_* tokens) and the new whale brand mark across the favicon,
1345 app icons, web manifest, nav wordmark, and social card (#5573).
1346
1347 - Add `codewhale dispatch` / `/dispatch` so a local session can propose a
1348 Codewhale cloud agent against an explicit `github`, `cnb`, or `gitee` remote.
1349 Confirmation is required; missing credentials fail closed; cloud jobs share
1350 the existing `/jobs` surface as `kind=cloud`. See
1351 [DAYTONA_CLOUD_DISPATCH.md](docs/DAYTONA_CLOUD_DISPATCH.md).
1352 - `/login` reports the Codewhale account session and provider-key next
1353 steps. The internal cloud-agent credential is not user surface: there is
1354 no `auth set-slot`/`auth clear-slot` command, no hint, and no completion
1355 entry for it — signing in with `codewhale login` is the only door.
1356 - Add the Tideline component family from the ratatui translation spec
1357 (#5698's screens, riding the #5699 work-strip layout): hero startup
1358 surface with quick actions and option strip, notifications inbox, merged
1359 footer band, pod ledger, receipt
1360 stream, theme list with motion toggles, live preview, settings rail,
1361 and the left rail — each a standalone render module pinned by 28 new
1362 byte-exact golden buffers. Frame wiring follows the Tideline acceptance
1363 gate; `NO_COLOR` is now honored by palette depth detection.
1364 - Route Contract Phase 1: `RouteResolver` is the runtime path for
1365 `resolve_runtime_options`; `codewhale providers export --json` ships the
1366 owned descriptor catalog; CLI `--provider` accepts any catalog route id
1367 (the closed `ProviderArg` enum is deleted). Catalog layers are
1368 bundled → models.dev → provider `/v1/models` → config.toml → user, with
1369 policy DENY last and never overridden.
1370 - Add provider-native web search for documented Xiaomi MiMo 2.5 Pro and 2.5
1371 chat routes while keeping neighboring models and custom gateways fail-closed.
1372 - Add structured provider-native web search for exact Z.AI global and Zhipu
1373 China general API routes, using each site's documented search engine value.
1374 Existing `open.bigmodel.cn` configurations now share Z.AI's official model
1375 namespace and credential scope; unknown model IDs still pass through.
1376 - Add provider-native web search for documented Qwen models on ModelStudio
1377 Token Plan's Responses Harness, without enabling Coding Plan or Anthropic
1378 routes.
1379 - Added `/copy` to place the latest completed assistant response on the
1380 clipboard without copying tools, system messages, hidden reasoning, or
1381 active partial output (#5668).
1382 - Add provider-native web search for documented DeepSeek V4 routes through the
1383 Responses API, with fail-closed capability gating for compatible custom
1384 endpoints.
1385 - Add provider-native search for exact Moonshot K3 Formula, legacy K2.6
1386 built-in search, and Kimi Code membership `/search` routes. Treat the exact
1387 Moonshot China endpoint as a first-party direct route.
1388 - Z.ai `GLM-5.3-Flash` and OpenRouter `z-ai/glm-5.3-flash` are first-class
1389 picker rows (`/model GLM-5.3-Flash`). Flash is the faster/explore sibling
1390 of `GLM-5.3`; the Z.ai default stays `GLM-5.3`. List price is $0.15/$0.50
1391 per 1M (durable; the 50% promo through 2026-09-09 is not the catalog row).
1392 - Baseten, Groq, and Cerebras are bundled OpenAI-compatible setup templates
1393 (`[providers.<id>] kind = "openai-compatible"`), not new `ProviderKind`
1394 variants. `/provider` fills URL, model, and env from one catalog row.
1395 - MCP manager copy now names the server, the failure, and one recovery
1396 command (`The X MCP server requires OAuth reauthentication. Run /mcp login X`).
1397 - Settings Advanced exposes clickable MCP Connect, Reconnect, and Diagnose
1398 actions, while Extensions and Problems route recovery through the existing
1399 `/mcp login`, `/mcp reload`, `/mcp validate`, and `/plugin validate` commands
1400 (#5643, #5655).
1401 - Plugin prompt matching (#5579): sending a task can toast the next review
1402 step when the prompt strongly matches an installed-but-idle plugin or a
1403 marketplace catalog you added (for example a Supabase prompt suggesting
1404 `/plugin trust supabase`). A live composer CTA offers the same review
1405 command while you type, matching turns append a bounded
1406 `<recommended_plugins>` user block, and `request_plugin_install` surfaces
1407 review without installing. `/plugin suggest` now ranks manifest keywords and
1408 catalog candidates, never auto-installs, and on-disk plugin changes also
1409 nudge `/plugin reload` between turns.
1410
1411
1412 - Added `/import-claude` (#5557): reads `~/.claude.json` and
1413 `~/.claude/settings.json` read-only and renders an explicit, reviewable
1414 migration plan plus a written report. MCP servers route through the
1415 existing `/mcp import <name> --approve` consent flow, allowlisted env keys
1416 become an unapplied portable bundle for `codewhale config import`, and
1417 permissions/hooks map to manual follow-ups; secret-shaped values are named
1418 but never echoed or imported.
1419 - Added the managed Chat relay: account-owned Chat commands now execute on the
1420 native runtime thread engine through a new `runtime_chat_relay` module
1421 instead of a second execution path. Each Chat thread is a dedicated,
1422 isolated runtime thread with an empty model-visible tool allowlist, a
1423 chat-only system prompt, and no workspace, memory, skill, credential, or
1424 local-path context; the active interactive TUI thread is never reused. The
1425 relay keeps one durable state file per scope behind a session-wide owner
1426 lock, binds a saved session permanently to its first remote target, replays
1427 exact duplicate commands from retained results instead of starting a second
1428 inference turn, terminalizes orphaned reservations on restart, and rejects
1429 (never queues into) a busy local Work turn with an immediate retryable
1430 result. Stop commands require the exact run and turn identity, and a worker
1431 aborts on any account or target mismatch during token refresh.
1432
1433 - Added a verified Omarchy/AUR packaging path: `packaging/aur` now carries a
1434 `PKGBUILD` template, `.SRCINFO` renderer and tests, release-candidate
1435 render step, and docs; the live AUR compatibility alias `codewhale-tui ->
1436 codewhale` is preserved, AUR dependencies match the live package, and the
1437 self-updater refuses to fight an Omarchy/package-manager installation.
1438 - Added a Fleet run-wide cost/token usage ceiling (R6, #5567): an accumulator
1439 plus admission gate and alert bound a whole run's spend across workers.
1440 - Added the real provider cache hit rate to `/context` (C3, DSH #3): the
1441 token-weighted provider-reported rate from the same telemetry `/cache`
1442 aggregates, plus an honest "no cache telemetry yet" state when nothing is
1443 recorded.
1444 - Added per-step cost movement: `TurnUsage` receipts are priced as they land
1445 so the live cost surface moves during long agentic turns instead of only at
1446 `TurnComplete` (#5578), and the footer now honestly shows `cost: unknown`
1447 when nothing can be priced instead of hiding the line.
1448 - Added the underwater session surface: the ambient water reads session state
1449 from across the room, its animation shape follows live agent activity, and
1450 attention tints are steady (no breathing) with a distinct reading treatment
1451 and no mid-water seam on tall windows.
1452 - Added `@path:START-END` ranged line mentions (#5550, picker half to follow),
1453 a predictable last-copy backup file for clipboard exports with the path
1454 named when the clipboard fails (#5555), `wait` on multiple background shell
1455 tasks with `until=any|all` (#5549, named-kill half to follow), and composer
1456 double-click word / triple-click line selection.
1457 - Added workflow parallel-`schema` slot partial success (#5583): a slot that
1458 produces a schema-valid partial result no longer fails the whole parallel
1459 branch.
1460 - Added plugin load-failure startup hints (#5579) and OpenRouter app
1461 attribution headers on outbound requests.
1462 - Added `codewhale doctor --fix` (with `--yes` for non-interactive consent):
1463 the doctor now computes a concrete repair plan — delete stale `.tmp*`
1464 leftovers from interrupted atomic writes, tighten secret-store file
1465 permissions to `0600`, disable structurally broken (Error-status) MCP
1466 entries through the atomic MCP save path, and scaffold missing user-global
1467 `skills`/`tools`/`plugins` directories — shows it, and applies it only after
1468 explicit consent. Every action is narrowly scoped and idempotent; JSON and
1469 context-JSON modes stay read-only and conflict with `--fix` (#5552, v1).
1470 - Added `/context` reporting of the real provider prompt-cache hit rate (C3)
1471 alongside token pressure.
1472
1473 ### Changed
1474
1475 - Provider-native web search now applies domain constraints before accepting an
1476 attempt, discards generated answers when returned citations violate those
1477 constraints, and preserves the caller's configured/local timeout as an
1478 independent fallback budget (#5681).
1479 - Idle session metrics omit zero facts (`0 turns`, `LLM 0s`) until the
1480 runtime has evidence. Working chrome says `in the current` instead of a
1481 generic `working`.
1482 - Deleted nine uncompiled `runtime_contract/` staging files. Live contracts
1483 remain `model.rs` and `termination.rs`.
1484
1485 - The first #5587 dead-code sweep converts audited test-only helpers to
1486 `#[cfg(test)]`, keeping production builds free of test-only APIs without
1487 changing runtime behavior.
1488 - `/plugin reload` is now discoverable when on-disk plugin bundles change: the
1489 next send and `/plugin list` nudge once with `Run /plugin reload to apply`
1490 instead of silently keeping the stale catalog (#5579). Trust is unchanged;
1491 this does not auto-reload.
1492 - Context-pressure warnings and critical alerts now remain visible in sticky UI
1493 status until compaction or explicit dismissal, instead of disappearing into
1494 scrolling turn metadata (#5620).
1495 - The Runtime thread store defaults to a per-session root
1496 (`$CODEWHALE_HOME/sessions/<id>/runtime`) so multiple Codewhale processes on
1497 one machine no longer share one owner lock (#5630). The exclusive lock is
1498 unchanged; `CODEWHALE_RUNTIME_DIR` still selects a shared root when that is
1499 intended.
1500 - Session token totals now include display-only per-model-call deltas while a
1501 turn is running, including input/output and cache-class counters; the
1502 authoritative `TurnComplete` totals still reconcile exactly once (#5581).
1503 - Transcript focus now exposes per-block actions: `y` copies content, `Y`
1504 copies the rendered metadata view, Enter opens a fullscreen block pager, and
1505 `r` opens raw detail; the existing Tasks rail shortcuts remain unchanged
1506 (#5551).
1507 - Provider neutrality (#5588): model resolution of omitted/aliased models is
1508 now provider-relative, OpenAI-native defaults no longer route through
1509 another provider's table, CLI credentials stay provider-scoped, and NVIDIA
1510 credentials no longer leak into the DeepSeek keychain. Neutrality test
1511 matrices exercise several providers instead of standing in with one.
1512 - The workflow engine module was decomposed out of its 3k-line mega-file into
1513 `journal`, `usage`, and `report` modules plus a module directory (#5586
1514 slices 1a/B/C/D), a semantic-free move verified by normalized-content hash.
1515 - Compaction refusals are now always named (#5577): silent holds under context
1516 pressure are gone, the context meter honors the same provider-billed prompt
1517 the trigger uses (T1), and prune outcomes are projected without cloning the
1518 transcript.
1519 - Step budgets now end honestly: an ~80% soft landing nudges the model to
1520 write its final report, and exhaustion grants exactly one bounded
1521 report-on-exhaustion turn instead of dying silently (A1/A2).
1522 - Contributor credit: recognized agent contributors (e.g. `Codewhale Agent`)
1523 may now carry `Co-authored-by` trailers; unknown bot/tool trailers are
1524 still rejected by the credit gate.
1525
1526 ### Fixed
1527
1528 - Read-only Fleet workers no longer send `"action": {"enum": null}` in their
1529 projected `bash` schema. The read-only projection probed the action enum
1530 with a mutating index, which auto-vivified the key on schemas that have no
1531 action property, and strict OpenAI-compatible validators then rejected the
1532 whole request (`null is not of type "array"`). The probe is non-mutating
1533 now, in both the read-only projection and the `Run` arm next to it, and a
1534 regression test walks the whole projected catalog for nulls
1535 (#5944, thanks @gaord).
1536 - Fast typing no longer corrupts the composer. The paste-burst heuristic ran
1537 on every session until a real bracketed paste arrived, holding, buffering,
1538 retro-grabbing, and absorbing Enter on timing guesses; it is now
1539 fallback-only (gated off when the terminal provides bracketed paste), the
1540 retro-grab is deleted, and Enter on held command text flushes and submits.
1541 - Ctrl+C works on the pre-session launch menu and speaks everywhere: the
1542 first press arms the two-second exit window with a visible localized
1543 "Press Ctrl+C again to quit" hint (previously silent), the second exits.
1544 The worktree name input keeps Ctrl+C as cancel-input.
1545 - Fresh interactive sessions no longer leave a phantom one-message duplicate
1546 behind. The TUI claimed one session id (Runtime store lock, turn-start crash
1547 checkpoint) while the engine minted a second one; the first `SessionUpdated`
1548 re-keyed the App, the completion commit cleared only the engine id's
1549 checkpoint, and `codewhale --continue` later "recovered" the orphaned
1550 checkpoint as a duplicate session instead of the real one. The engine now
1551 adopts the host-owned id at spawn (`EngineConfig::session_id`) and `/clear`
1552 mints the next id in the App like `/new`. A non-TTY `--continue` no longer
1553 promotes and consumes the crash checkpoint before failing the terminal
1554 check, and the root `codewhale --resume <id>` / `--session-id <id>` flags
1555 documented in the operations runbook now parse instead of being swallowed
1556 as a prompt.
1557 - Website: `/signin`, `/signup`, and `/auth/callback` are locale-aware public
1558 routes instead of localized 404s. Sign-in and create-account send the person
1559 to the CWC app; OAuth callbacks hop to `app.codewhale.net` with the query
1560 intact; `/login` and `/register` are aliases. Local CLI use is not presented
1561 as requiring an account (#5767).
1562 - The sandbox read deny-list matches a rule's resolved path as well as its
1563 literal spelling. On macOS `/etc` and `/var` are symlinks into `/private`,
1564 so a read of `/private/etc/sudoers` walked around the `/etc/sudoers` rule,
1565 and a rule written against a symlinked directory never fired for the real
1566 path that `canonicalize` and the process cwd hand back.
1567 - Background shells are first-class work-strip rows (`▾ Shells N`) you can
1568 open, watch, and cancel by the `shell_*` id on the row. `/jobs cancel all`
1569 cancels running shells; it no longer looks up a task named `all`. The
1570 composer hourglass crumb no longer stands in for a shell surface.
1571 - `codewhale logout` and `/logout` now clear the Codewhale account session
1572 and the Daytona secret slot, not only provider API keys. The TUI crate's
1573 leftover `login --api-key` path no longer claims to save a key.
1574 - Account sessions no longer read the macOS Keychain. Unsigned or rebuilt
1575 `codewhale` binaries were a new Keychain ACL principal every time, so
1576 `codewhale web` and the TUI popped a password dialog on start. Sessions
1577 now use `~/.codewhale/secrets/secrets.json` (mode 0600), the same store
1578 as provider keys. Extracted from the Keychain-retirement half of #5632.
1579 - Hardened the dispatcher-side config parse the same way: `ConfigStore`
1580 loads and project-config parsing now deserialize `ConfigToml` on a
1581 dedicated 16 MiB-stack thread (the guided-setup save path could overflow
1582 a 2 MiB worker stack the same way the TUI's `ConfigFile` parse did), and
1583 the #5585 setup-confirm toast test runs its runtime on an equally sized
1584 thread instead of overflowing the default libtest stack.
1585 - Fixed detached interactive agents reporting worker usage after the parent
1586 turn ends with the usage missing from the session/live `/cost` total
1587 (#5597): interactive turns acquire an owner-scoped runtime usage lease,
1588 late usage enters the session cost pool without reopening the sealed
1589 mailbox, and worker/session/reload accounting share one hashed response
1590 identity so retried deliveries stay exactly-once.
1591 - Fixed the sub-agent fiasco class: in-workspace absolute `git -C` no longer
1592 trips the read-only child shell gate with a coherent bounded gate (#5595),
1593 turn end parks turn-owned children resumably instead of silently cancelling
1594 them (#5596), stale write-claims are released by liveness with coordinate
1595 release (#5562), and the verifier role description matches its real
1596 surface (#5562).
1597 - Fixed workflow responseSchema failure handling (#5583): bounded repair with
1598 typed receipts (kind + attempt), raw-output receipts persisted as artifacts
1599 that survive reload, and failures surfaced instead of null success (#5528).
1600 Degraded owner snapshots no longer project as ordinary Completed runs
1601 (#5582), typed task error kinds enable fail-fast parallel/pipeline (R9), and
1602 `/workflow confirm` finds the draft despite interleaved messages.
1603 - Fixed the DeepSeek session that never auto-compacted at 842k/1M (#5577): the
1604 exact `billed_842k_on_a_1m_window_compacts_despite_a_small_estimate`
1605 regression pins the trigger.
1606 - Fixed sandbox escapes and authority gaps: workspace-write tools resolve
1607 hard-linked files before writing (S2, #5569), an opt-in read deny-list
1608 bounds full-disk reads in any posture (S1, #5568), and session grants match
1609 the command family instead of widening the whole tool (R2).
1610 - Fixed provider-transport robustness: non-streaming HTTP requests are bounded
1611 by a read timeout (R4), and Chat-Completions mid-stream error frames surface
1612 instead of hanging (R3). MCP OAuth expiry now reacts to 401/403 with a named
1613 recovery path and login hint instead of looking like a broken server (T4,
1614 #5572).
1615 - Fixed Fleet lifecycle gaps: detached workers are reaped when their manager
1616 dies (R7) and the per-task wall-clock timeout is enforced (R5); the local
1617 Fleet host compiles on non-Unix targets; detached schema repair stays within
1618 the runtime budget.
1619 - Fixed prompt-cache correctness: the tool catalog is fingerprinted in
1620 provider wire order (C1), prefix changes between requests are always
1621 declared (C5) — including the newly named mid-turn `change:tool_surface`
1622 reasons for deferred-tool admission, tool-search activation, and runtime MCP
1623 tool arrival — and a reasoning-only response stopped at the output limit now
1624 fails the turn honestly instead of re-issuing a request that can only
1625 reproduce the stop.
1626 - Fixed docs/public-surface drift: REBRAND.md no longer presents
1627 `api.deepseeki.com` as a China fallback (#5564), and the web facts/tool
1628 counts match the repository.
1629
1630 - Heavy pull requests now run the real Linux workspace nextest, doctest, and
1631 lockfile lanes directly on GitHub Actions instead of reporting a green
1632 placeholder while waiting for a branch-specific CNB mirror (#5547).
1633 - Fleet roster members in a selected Fleet now expose a visible edit affordance
1634 and a direct `m` model-picker shortcut, while the coordinator row remains
1635 read-only (#5604, covers #5589).
1636 - The context inspector now attributes bounded tool-schema cost to the built-in
1637 catalog and each discovered MCP server without changing prompt assembly or
1638 cache behavior (#5553).
1639 - The goal-continuation quiet period (`[goal] continuation_delay_seconds`,
1640 added in #5508) now applies on every dispatch path. Previously the
1641 within-turn dispatch hook fired the next continuation prompt immediately
1642 whenever a model step ended with the goal still active, so CLI-resumed and
1643 host-managed sessions never observed the configured delay (measured
1644 end-to-start gaps of ~9 s with a 300 s delay configured). The wait now
1645 runs unconditionally inside `goal_continuation_message_if_needed`,
1646 remains cancellable, and pause/clear/terminal `update_goal` calls still
1647 cancel a pending pass (#5534).
1648 - Two unit tests no longer depend on process-global environment state that
1649 sibling tests mutate concurrently.
1650 `route_budget::tests::v4_trigger_uses_window_percent_when_it_fits_spendable_input`
1651 asserted no-override output-budget values while reading
1652 `CODEWHALE_MAX_OUTPUT_TOKENS` / `DEEPSEEK_MAX_OUTPUT_TOKENS` without
1653 holding `lock_test_env()`, so a concurrent writer could flip the value
1654 mid-assertion (the order-dependent full-suite flake).
1655 `prompts::tests::system_prompt_prefix_never_leaks_private_content` read the
1656 real home via `HOME`/`USERPROFILE`, so a machine with
1657 `~/.codewhale/instructions.md` leaked its absolute path into the prompt and
1658 failed the no-private-paths assertion unless a sibling's temporary `HOME`
1659 guard happened to be live. Both tests now hold the env barrier and pin the
1660 variables (the route-budget test removes the overrides; the prompts test
1661 points `HOME`/`USERPROFILE` at a scratch dir). Assertions unchanged.
1662
1663 - TUI sessions now apply a subtle OSC 12 cursor accent only on explicitly
1664 supported terminals and restore the terminal default through normal, panic,
1665 and signal cleanup paths (#5554).
1666
1667 ## [0.9.11] - 2026-08-22
1668
1669 Codewhale v0.9.11 tightens the long-running agent loop, makes workflow
1670 failures visible instead of successful-looking, adds an experimental
1671 vision-capable DeepSeek route, and prepares reproducible Codewhale-versus-Pi
1672 evaluation without publishing a result before a real run. The complete
1673 item-level change record is retained below the categorized release highlights.
1674
1675 ### Added
1676
1677 - Added first-party `deepseek-v4-flash-vision-exp` discovery and selection for
1678 DeepSeek, including the `flash-vision` alias, bundled offline metadata,
1679 registry and picker entries, and image-input capability on the chat route.
1680 Context and output limits inherit from V4 Flash until DeepSeek publishes
1681 distinct values; pricing remains unknown rather than guessed.
1682 - Added a provider-controlled Codewhale-versus-Pi parity harness with three
1683 hermetic coding tasks, route and reasoning-effort receipts, doctor/dry-run
1684 modes, and bounded result artifacts. The repository ships the harness, not a
1685 benchmark verdict; comparable real runs remain an acceptance gate.
1686 - Added portable, secret-free config export/import with a reviewable plan,
1687 explicit headless consent, backup and rollback, and idempotent re-import.
1688 - Added bounded multi-file diagnostics through the existing model-facing `lsp`
1689 tool without increasing the tool-catalog count. Thanks to **Isabel Wu
1690 ([@wuisabel-gif](https://github.com/wuisabel-gif))** for PR #5524.
1691 - Added portable presentation, media-attachment, and operation-digest facets to
1692 the command contract, then moved all seven utility handlers onto the
1693 contract-backed dispatch path. Thanks to **Paulo Aboim Pinto
1694 ([@aboimpinto](https://github.com/aboimpinto))** for PR #5525.
1695
1696 ### Changed
1697
1698 - Sub-agent, Fleet-worker, workflow-task, and thread-runtime model turns no
1699 longer inherit a hidden role-based step ceiling. An omitted or zero
1700 `max_steps` is unbounded; a positive user/config value remains an explicit
1701 cap and is still clamped to the runtime safety ceiling. Wall-clock, provider,
1702 heartbeat, cancellation, and admission safeguards are unchanged.
1703 - `/rc` now mirrors one shared session rather than transferring terminal
1704 ownership: local and web prompts remain available while idle, approvals use
1705 first-decision-wins semantics, and transport/integrity failures remain
1706 fail-closed.
1707 - The terminal status rows around the composer are now two stable bands:
1708 `provider · model · thinking level` is the persistent identity row below
1709 the composer in every phase, and a separate activity row above the
1710 composer carries the live phase, notices, and cost/metrics. Sending a
1711 prompt no longer relocates the route identity above the composer, and
1712 neither row ever duplicates it.
1713 - The embedded local Web client now uses the current CWC Ocean hierarchy and
1714 readable control sizing, follows the shared Enter/Shift+Enter composer
1715 grammar, and chooses a provider plus model per new thread without mutating
1716 Runtime defaults. Exact image-input capability is labelled honestly; a
1717 vision-capable route does not imply that browser attachments exist.
1718 - The runtime now has one authoritative model-turn loop. The placeholder
1719 `crates/core` engine tree is gone, while the active TUI loop and its extracted
1720 tool-call stages retain existing policy, hook, cancellation, and budget
1721 behavior. Thanks to **Sun Zhenyuan
1722 ([@bistack](https://github.com/bistack))** for PR #5523.
1723
1724 ### Fixed
1725
1726 - Chat Completions streams now require terminal proof from `[DONE]` or a
1727 non-empty `finish_reason`. Protocol-only frames no longer count as answer
1728 content or time-to-first-token, and a provider continuation that ends after
1729 tool results with no answer or tool call fails durably instead of producing
1730 a false `Completed` receipt.
1731 - A selected v2 Fleet now drives one bounded, deterministic Agent roster across
1732 terminal and runtime surfaces. Fleet operator/member/explicit-route
1733 precedence, resolved member identity, and exact `vision` requirement
1734 admission now fail visibly instead of silently falling back, first-matching,
1735 or rerouting.
1736 - A workflow whose `task()` dispatch was rejected no longer loses that failure
1737 inside a `parallel()` null slot or presents a successful-looking run. Rejected
1738 dispatches now fail the run, persist as typed bounded receipts with an exact
1739 count, and appear in transcript, activity detail, and workflow-panel views.
1740 - Provider readiness, credential-source explanations, focused-agent scrolling,
1741 compact `/status` and `/help` rendering, shell/web output bounds, MCP
1742 lifecycle reporting, and narrow-terminal onboarding received the detailed
1743 fixes recorded below.
1744 - Portable config import/export now preserves typed tables, arrays, numbers,
1745 booleans, and datetimes without stringifying them, while refusing
1746 machine-bound trust overlays, credential readers, automatically executable
1747 hooks/LSP definitions, local-path authority, machine-local network proxy
1748 routes, cookies, redaction placeholders, and nested or camel/dotted
1749 credential keys. Project and global bundle operations now load and validate
1750 the document for their actual scope in both directions, including a
1751 workspace whose document still lives under the legacy app directory.
1752 - `codewhale login` now means Codewhale account sign-in (the same browser
1753 device flow as `codewhale account login`, with `--no-open` and
1754 `--timeout-seconds`); provider API keys are configured exclusively through
1755 `codewhale auth set --provider <provider>`, and the hidden legacy
1756 `--api-key`/`--provider` flags redirect loudly instead of silently writing
1757 a key.
1758 - Account sessions prefer the OS credential manager and now fall back
1759 automatically to the private `0600` Codewhale secrets file on headless
1760 hosts, SSH boxes, and containers; the `CODEWHALE_CLOUD_ALLOW_FILE_SESSION_STORE`
1761 opt-in is deprecated and ignored.
1762 - `/update` gained a `Ctrl+Shift+U` install chord (catalogued in
1763 `docs/KEYBINDINGS.md`, localized in all 15 packs) and a startup hint that
1764 names the previous and current version on the first launch of a newer
1765 build, pointing at `/change`.
1766 - Fleet product-model copy pass: the TUI, docs, and locale packs now use
1767 Fleet / Member / Role / Model / Access / Saved consistently so a user can
1768 say "scout", "DeepSeek V4 Flash", or the member name and mean the same
1769 thing.
1770 - A reasoning model that returns only hidden reasoning and a clean stop (no
1771 answer, no tool call) is now re-requested automatically up to twice before
1772 the turn fails, instead of dead-ending with "the provider response was
1773 incomplete." The retry reuses the cached prefix so it is cheap; an
1774 output-length stop (`length`/`max_tokens`) is never retried, and a
1775 persistently answerless model still fails honestly after the bound.
1776 - Model-bound tool results now use a credential-shaped redaction policy:
1777 only values that look like secrets (known prefixes, JWTs, bearer tokens,
1778 PEM private-key blocks, long opaque strings) are masked before a `read` or
1779 shell result reaches the model, so code such as `password:
1780 credentials?.password` or `"password-validator": "^5.3.0"` stays byte-exact
1781 for edits and read-back. Exact configured credential values are still always
1782 replaced, and logs/previews/exports keep the broad key-based scrubber. (#5546,
1783 reported by @ronohara)
1784 - Terminal input shutdown no longer waits forever on a wedged TTY read,
1785 Windows launch receipts can atomically replace an existing record, and the
1786 complete `/status` report now follows the active locale without rewriting
1787 exact custom-provider identities that contain brace-like text.
1788 - Localized READMEs again match the English install and third-party-notice
1789 surface, including shell-completion guidance in all 18 translations.
1790
1791 ### Security
1792
1793 - Unified OAuth device-code polling now validates verification URLs before
1794 opening them, redacts token-bearing types, honors server slowdown intervals,
1795 and keeps credential save/logout mutations serialized.
1796 - Project instructions, rules-directory traversal, secret-shaped config data,
1797 URL fingerprints, and shell network authority now retain the explicit bounds
1798 and fail-closed behavior described in the detailed record.
1799
1800 ### Contributors
1801
1802 - **Sun Zhenyuan ([@bistack](https://github.com/bistack))** — tool-call stage
1803 extraction with the existing execution and policy contracts preserved
1804 (#5523).
1805 - **Isabel Wu ([@wuisabel-gif](https://github.com/wuisabel-gif))** — bounded
1806 multi-file `read_lints` support (#5524), plus independently reviewed
1807 completion-routing overlap in #5530.
1808 - **Lstarsky0 ([@Lstarsky0](https://github.com/Lstarsky0))** — maintainer review
1809 hardening for truthful per-file states and truncation metadata in #5524.
1810 - **Paulo Aboim Pinto ([@aboimpinto](https://github.com/aboimpinto))** — portable
1811 presentation/media/digest facets and the seven utility-handler migrations
1812 (#5525).
1813 - **RepentStar ([@RepentStar](https://github.com/RepentStar))** — reported and
1814 reproduced the stale completion-generator path and missing `codew`
1815 registration fixed for #5526.
1816
1817 ### Detailed change record
1818
1819 The notes below are preserved in full so the categorized highlights do not
1820 erase behavior, migration, security, compatibility, or verification details.
1821
1822 - Provider completion is now evidence-based. A Chat Completions stream reaches
1823 `MessageStop` only after `[DONE]` or a non-empty `finish_reason`; raw EOF
1824 without either is a typed failure. Message-start, ping, usage/terminal
1825 deltas, block-stop, and message-stop frames do not count as productive
1826 content or mint time-to-first-token. After tool results, a terminal provider
1827 step with no answer or tool call now emits a durable failed turn and never
1828 fabricates an empty assistant message.
1829
1830 - A selected v2 Fleet is the single effective Agent roster across terminal,
1831 Runtime threads, direct Workflow, Fleet execution, doctor, and
1832 setup/readiness; legacy profile layers are consulted only when no Fleet is
1833 selected, and invalid selections fail visibly with bounded, redacted errors.
1834 Member references resolve exact id first and otherwise require a unique
1835 display name, role, pinned model, offline model name, or provider/model route;
1836 `agent action=roster` exposes that same bounded roster. The Fleet operator
1837 supplies fresh-root and inherited-member routing unless an explicit launch
1838 route or member pin wins, the resolved member is shown separately from the
1839 requested alias, and `requires = ["vision"]` is admitted only on an exact
1840 route with verified offline `image_input` support—never by silent rerouting
1841 or custom-proxy inference. Fleet selection remains an explicit user/folder
1842 contract independent of legacy project-profile loading.
1843
1844 - **Breaking (app-server):** `/prompt`, `prompt/request` and `prompt/run` now
1845 execute a real model turn instead of reporting success for work they never
1846 did. `Runtime::handle_prompt` called no model: it resolved config, ran a
1847 local `ModelRegistry` lookup, emitted three canned hook events
1848 (`ResponseDelta` was literally the string `model-selected`), and returned
1849 HTTP 200 with `output` set to a stringified JSON echo of the caller's own
1850 routing metadata — the prompt included. Worse, when a `thread_id` was
1851 supplied it appended a real user row, flipped the thread to `Running`, and
1852 then wrote that echo into durable history as an **assistant message** plus a
1853 `prompt_response` checkpoint. Nothing marked the row synthetic and nothing
1854 ever moved the thread out of `Running`. All three endpoints now route
1855 through the same `RuntimeBridge` that stdio `thread/message` has always
1856 used, so `output` is the model's streamed text, `model` is what the runtime
1857 reports for the thread that ran the turn, and `events` are the real
1858 streaming frames. `Runtime::handle_prompt` and its synthetic history write
1859 are gone.
1860
1861 - **Breaking (app-server):** a failed prompt is now a typed failure rather
1862 than a success-shaped body. `POST /prompt` returns
1863 `{"error":{"code":...,"message":...}}` with `400` (invalid request), `404`
1864 (thread not found), `503` (`runtime_unavailable`) or `500`, instead of HTTP
1865 500 carrying a `PromptResponse` with the error text stuffed into `output`
1866 where model text belongs. The stdio surface gained JSON-RPC `-32005`
1867 `runtime_unavailable` for "the turn engine could not be reached, so nothing
1868 ran" — distinct from `-32603`, and retryable. There is no configuration in
1869 which a prompt silently echoes instead of running.
1870
1871 - **Breaking (app-server):** `POST /thread` with a `Message` body runs the
1872 turn. It previously replied `status: "accepted"` with a
1873 `ResponseDelta("queued")` frame while starting no worker and calling no
1874 bridge — the stdio path for the same request has always done real work, so
1875 the two transports disagreed about what `accepted` meant. HTTP now replies
1876 `status: "completed"` once the turn reaches a terminal state, with the
1877 streamed frames in `events` and the turn id in `data`. `Runtime::handle_thread`
1878 no longer accepts `ThreadRequest::Message` at all: it owns thread
1879 bookkeeping, not the turn engine, and returns an error naming
1880 `POST /v1/threads/{id}/turns` rather than a canned acceptance.
1881
1882 - **Breaking (app-server):** `AppRequest::SubmitUserInput` now refuses
1883 explicitly (`ok: false`, `error: "user_input_reply_unsupported"`) instead of
1884 returning `resolved: true` and filing the answers in a map that had no
1885 reader anywhere in the crate — every answer submitted was silently
1886 discarded. It cannot be made to work on this transport: while a turn
1887 streams, the stdio loop executes only `thread/interrupt` and queues
1888 everything else, so an answer sent there would wait on the very turn
1889 waiting for it. The refusal names the surface that does accept it,
1890 `POST /v1/user-input/{thread_id}/{request_id}` on the runtime API. The
1891 client-visible refusal is whitespace-clean, and the `/tool` path that mints
1892 the `UserInputRequest` is unchanged and still genuine.
1893 - Split the coordination ledger out of `tools/subagent/coord.rs` into
1894 `tools/subagent/coord/ledger.rs`. The file held two unrelated things: the
1895 model-facing `agents/*` tool wrappers, and the durable decision/claim/
1896 contention records those wrappers happen to write — records whose consumers
1897 are mostly *not* in the tool layer (`tui::coordination_detail`,
1898 `tui::work_surface`, `tui::ui::tests`, `core::engine::tests` all name these
1899 types). At 3.8k lines, reading either one started by scrolling past the
1900 other. A pure move with a glob re-export from `coord`, so every
1901 `crate::tools::subagent::coord::{…}` path still resolves and no consumer file
1902 was edited; the only content change the move required is one constant going
1903 from private to `pub(super)` because its caller stayed behind. `coord.rs` is
1904 now 2.3k lines and `ledger.rs` 1.6k.
1905
1906 - `agent` is now the only sub-agent tool the model can see. `AGENTS.md` has
1907 said "the model-facing sub-agent surface is `agent` only" since the lifecycle
1908 tools were removed, but six more were reachable: `agents/list`,
1909 `agents/message`, `agents/followup`, `agents/interrupt`, `agents/coordinate`,
1910 and `agents/wait` all defaulted to model-visible, so they shipped in the
1911 catalog and `tool_search` could load any of them — and the `agent`
1912 description told the model they existed. They now declare
1913 `model_visible() -> false`, the same shape `rlm` and `exec_shell` use: still
1914 registered, still executable by name so a persisted transcript replays
1915 against the same implementation, never advertised and never returned by
1916 either `tool_search` matcher.
1917
1918 Five of the six were already duplicates of an `agent` action. The sixth was
1919 not: `agents/coordinate action=claim` was the *only* way to widen a write
1920 claim, and write enforcement fails closed, so hiding it would have left a
1921 refusal ("expand it first with…") pointing at a tool the model could no
1922 longer call. `agent` gains one action, `claim`, taking the write scope
1923 vocabulary `action=start` already uses (`write_roots`, plus parse-accepted
1924 `exact_files` and `coordination_contracts`). It keeps `agents/coordinate`'s
1925 `Auto` approval — gating it deadlocks autonomous fan-in — and it can only
1926 widen the caller's own scope; peer contention still fails. A scopeless claim
1927 is refused rather than reported as granted, because `expand_write_claim`
1928 returns the unchanged claim with `Ok` when every list is empty.
1929
1930 Collapsing six tools into one action set also collapses the gating: `agent`
1931 is deliberately exempt from both name-keyed gates (`posture_permits_tool`
1932 short-circuits it so delegation depth governs spawning, and
1933 `execution_envelope` classifies it `Bounded` so a read-only member can fan
1934 out read-only work), so a capability folded into it inherits no gate. `claim`
1935 is therefore gated per action, reproducing the envelope check that kept
1936 `agents/coordinate` off a read-only role's catalog — in the catalog and again
1937 at dispatch, since catalog shaping is not an authority boundary. The other
1938 actions keep exactly the visibility they had.
1939 - One placement table now decides which wire channel a message role belongs
1940 in, and unrepresentable role/dialect pairs are refused at the outbound seam
1941 (`DeepSeekClient::prepare_outbound_request`) instead of at the provider.
1942 Chat Completions and OpenAI Responses used to drop an unfamiliar role
1943 silently, Anthropic Messages forwarded `message.role` verbatim and took an
1944 opaque provider 400 for it, and Google cloud-code was alone in failing
1945 closed. Positioned `system` and `developer` history — including compaction
1946 and branch summaries — is carried natively by Chat Completions and Responses
1947 and projected, in place, onto Anthropic's user channel. It is neither
1948 hoisted nor dropped. Genuinely unknown roles keep the previous
1949 dialect-specific fail-closed/omit behavior, now decided in one table. The
1950 dead `"tool"` arm in the Responses adapter is gone — nothing constructs that
1951 role.
1952
1953 - Message roles are a closed `Role` enum (`crates/core/src/role.rs`) instead of
1954 a free-form `String` on `Message`. Four wire adapters each decided
1955 independently what an unfamiliar role meant, and a typo in a role string was
1956 a silent transcript edit rather than a compile error. `Role` keeps an
1957 `Unrecognized(String)` variant and serializes via `as_str()`, so a saved
1958 session's bytes are unchanged, a transcript written by a newer build still
1959 loads here, and `assistant_interrupted` stays a distinct session item — no
1960 session schema bump and no migration ladder.
1961
1962 - Portable config bundles: `codewhale config export --portable` writes a
1963 deterministic, secret-free bundle (credential and machine-specific keys
1964 dropped), and `codewhale config import <FILE|URL|->` applies one with a
1965 strict versioned envelope, a printed added/changed/skipped/conflicting/
1966 rejected plan, consent gating (`--yes` required headless), a timestamped
1967 backup with rollback, and idempotent re-import. Credential-shaped entries
1968 are rejected by key name and value shape — rejections name the field,
1969 never the value. Remote imports revalidate the HTTPS-or-loopback-HTTP policy
1970 on every same-scheme redirect hop, and duplicate keys across applicable
1971 section labels fail before any backup or write instead of silently resolving
1972 by section order. Structured TOML values round-trip with their original
1973 types and exact named-provider identity; recursive sanitization covers
1974 arrays/tables and camel-case, dotted, cookie, and access-key spellings while
1975 retaining ordinary token-count metrics. Machine-bound project trust,
1976 credential-source consent, automatic hook/LSP execution, and local-path
1977 authority are non-portable and fail before mutation. A missing target is
1978 created transactionally and removed again on rollback, and project/global
1979 scope validation rejects the wrong document before import or export.
1980 Imported tables deep-merge portable fields into the target, so omitted
1981 machine-local provider credentials, endpoints, and executable definitions
1982 remain intact instead of being erased by a sanitized bundle.
1983
1984 - `/rc` is now a shared-session mirror instead of a terminal takeover.
1985 Attaching the web app no longer locks the local composer or hides
1986 approvals: both surfaces can prompt while idle (one turn runs at a
1987 time), approval cards stay visible in the terminal and are shared with
1988 the web with first-decision-wins semantics (the losing side is told, a
1989 web decision dismisses the local card), and structured questions are
1990 answered locally instead of cancelled. Fail-closed behavior survives —
1991 the post-failure reconnect lockout, integrity-gated `/rc stop`, and the
1992 fail-closed shared-approval channel on transport loss are unchanged.
1993 The takeover vocabulary ("web owns prompts and approvals") is gone from
1994 every surface.
1995
1996 - Auto-mode provider readiness no longer reports "key saved · not checked"
1997 forever. Readiness checks are recorded against the concrete model the
1998 router ran, but auto-mode reads resolved against the literal `auto`
1999 identity, which never matched any recorded check — so the setup receipt,
2000 model picker, and fleet setup view showed an eternal unchecked badge
2001 even after hundreds of successful turns. The read now falls back to the
2002 most recent check on the same route (provider + endpoint + auth class);
2003 concrete-model reads keep exact per-model scoping.
2004
2005 - The focused sub-agent transcript now scrolls like the main transcript.
2006 The frame renderer sampled the ocean column through a `ChatWidget` whose
2007 constructor consumed `pending_scroll_delta` — every PageUp/PageDown and
2008 wheel event was swallowed by an invisible widget before the focused pane
2009 could read it. The delta is now parked across the sample; the pane pins
2010 on user scroll-up, follows new child activity at tail, and
2011 jump-to-bottom releases the pin.
2012
2013 - Every Codex OAuth Responses request carried `max_output_tokens`, a parameter
2014 that endpoint rejects outright ("Unsupported parameter: max_output_tokens"),
2015 so every gpt-5.6-sol turn — including every sub-agent on that route — failed
2016 at the first request. Codex Responses bodies now ship without a client-side
2017 output cap; the backend applies its own. Every other Responses route keeps
2018 the central cap on the wire, exactly as before.
2019
2020 - The model-facing `lsp` tool now supports a bounded `read_lints` operation
2021 for multi-file, workspace-relative LSP diagnostics without adding another
2022 tool catalog entry (#4070).
2023
2024 - HTTP 400 classification no longer calls an unsupported-parameter error a
2025 context-window overflow. Responses shape errors such as "Unsupported
2026 parameter: max_output_tokens" name a token-shaped field, which the generic
2027 keyword rules read as prompt-size exhaustion and pointed users at compaction
2028 that could never help. Such responses now classify as invalid requests.
2029
2030 - xAI device login validated nothing about the URL it opened. The
2031 `verification_uri` from the device-code response went straight to
2032 `webbrowser::open` with no parse, no scheme check and no credential check, so a
2033 spoofed or compromised issuer could hand the platform's "open this" call a
2034 `file:` path, a custom application scheme (`vscode://`, `slack://`), or a
2035 credential-bearing URL. The shared primitive now refuses anything that is not a
2036 web page before the URI is printed or opened. **Behaviour change:** a
2037 non-loopback plain-`http:` verification URI now aborts login where it
2038 previously opened; `http:` on a loopback host is still allowed, because local
2039 runtimes legitimately use it.
2040 - The xAI OAuth types no longer print bearer material through `Debug`. Five types
2041 holding tokens (`GrokAuthEntry`, `TokenResponse`, `DeviceCodeResponse`,
2042 `DeviceCodeGrant` and the poll outcome) either redact or no longer derive
2043 `Debug` at all, so a token has no printable path through a `{:?}` on any
2044 surrounding struct. The shared `DevicePollOutcome` derives nothing, which the
2045 compiler enforces.
2046 - **Behaviour change:** an `interval` of `0` from the authorization server now
2047 falls back to RFC 8628's five-second default rather than a one-second floor,
2048 in both the xAI and account device flows.
2049
2050 - OAuth device-code login is now one implementation. xAI/Grok device login and
2051 Codewhale account login each carried their own hand-rolled RFC 8628 polling
2052 loop with nothing shared between them; both now call a single primitive
2053 (`codewhale-config`'s `device_code`), ported from pi. Three fixes come with
2054 it. `slow_down` now honours a server-supplied `interval` instead of always
2055 adding five seconds, which is what stops polling from running early forever
2056 under WSL and VM clock drift. Timing out after a `slow_down` now says so and
2057 names clock drift, rather than reading as a plain timeout. And the xAI
2058 verification URI is validated before it is handed to the browser opener —
2059 Codewhale previously opened whatever the device-code response said, so a
2060 spoofed or compromised issuer could point the platform "open this" call at a
2061 `file:` path or a custom application scheme. It must now be `https:`, or
2062 `http:` on a loopback host for self-hosted issuers. Stored credential files
2063 are unchanged and existing logins keep working. MCP OAuth is untouched: it
2064 delegates to `rmcp`/`oauth2` and was never hand-rolled.
2065 - Shell output truncation now stays inside its own budget. A truncated shell
2066 result keeps a 6 KB head, a 24 KB tail, and any high-signal lines rescued
2067 from the omitted middle — but that rescued block was bounded only by a line
2068 count. One rustc `error:` line carrying a long inferred type or a minified
2069 bundler frame is routinely hundreds of kilobytes, so a "30 KB" result could
2070 arrive at 430 KB with the omitted line pasted back in whole. Each rescued
2071 line is now clipped and the block has a 4 KiB ceiling; the signal survives,
2072 the payload does not.
2073
2074 - Fetched web pages in non-Latin scripts no longer arrive half-read. Page text
2075 was reflowed against a column budget measured in bytes, so Cyrillic and Greek
2076 wrapped at roughly half the intended width and CJK at two thirds — and since
2077 the page view is delivered by line count, the surplus lines pushed real
2078 content off the end of the window. A Russian or Japanese URL returned a
2079 fraction of the text an English one did, for the same call. Wrapping now
2080 measures display width.
2081
2082 - The `bash` tool no longer tells the model it has no default timeout when it
2083 does. An omitted timeout has always been bounded at 120 seconds and the
2084 command killed there, but the tool description and its `timeout` field both
2085 claimed otherwise — steering the model away from the one parameter that
2086 would have saved a longer build. Both now name the real bound.
2087 - MCP servers no longer restart because an unrelated setting was saved. The
2088 lazy config reload re-reads every watched source whenever one of their
2089 mtimes moves and keeps the live connections only when the content hash
2090 matches — but the hash was taken over `serde_json` bytes produced straight
2091 from the config's `HashMap`s, and two `HashMap`s with identical contents do
2092 not iterate in the same order. Any touch of any watched file therefore hashed
2093 differently, tore down every connection, and SIGTERMed and respawned every
2094 stdio child. Keys are now sorted before hashing.
2095
2096 - An MCP server marked `required` now still tells you *why* it failed to start.
2097 `connect_all` appended a generic "required MCP server failed to initialize"
2098 entry after the real per-server error, and the snapshot folds those pairs into
2099 a map keyed by server name — so the contentless entry replaced the diagnosis
2100 and /mcp showed the marker instead of "No such file or directory". The marker
2101 is now only synthesized when nothing else reported a cause.
2102
2103 - A crashed stdio MCP server is now rebuilt instead of being handed back dead.
2104 A failed transport *read* disconnected the connection; a failed *write* did
2105 not, so after the child exited the connection stayed `Ready`, the pool reused
2106 it on every later tool call, and /mcp kept listing the server as connected.
2107
2108 - An MCP response carrying neither `result` nor `error` is now an error rather
2109 than an empty success. It previously reached the model as a successful tool
2110 call with a `null` payload, indistinguishable from a tool that did nothing.
2111 An explicit `"result": null` is still a valid empty success.
2112 - Stdio MCP server requests are answered while the client is idle instead of
2113 blocking behind the zero-capacity response rendezvous until an unrelated
2114 client call. `ping` receives its prompt empty result, unsupported methods
2115 receive JSON-RPC `-32601`, and the reader keeps only a weak stdin handle so
2116 dropping the client still delivers graceful EOF.
2117 - `base_url_fingerprint` is a persisted-key change for two input shapes.
2118 The digest is serde-serialized into `ProviderCatalogCache` and
2119 `LiveOffering`, pricing defect receipts, and
2120 `TurnRecord.routed_usage_source_ids` — it is not an in-memory-only cache
2121 label. Empty or whitespace-only values (and scheme-less query-only strings
2122 that strip to an empty authority) now hash the invalid-or-secret-bearing
2123 sentinel instead of SHA-256 of the empty string. Scheme-less URLs that
2124 contain `@` now strip `userinfo` before hashing, matching the
2125 scheme-bearing branch, so a typed `user:pass@host/v1` no longer embeds the
2126 password in a stored digest. `routed_usage_source_fingerprint` feeds
2127 arbitrary scheme-less source ids into the same function, so a turn
2128 rehydrated from an older build can fail to dedupe one routed-usage row.
2129 Recovery is a cache miss and a re-fetch, not corruption. Empty input was
2130 not restored to the old digest: an empty authority is not a usable
2131 endpoint, and mapping it to the same sentinel the scheme branch already
2132 uses for an empty host keeps invalid inputs from minting a unique cache
2133 scope.
2134
2135 - Diagnostic lines that mention token *counts* are no longer swallowed by
2136 secret redaction. A stream error such as `max tokens = 8192 but budget =
2137 4096` was matching the `token` hint as a substring of the English word
2138 `tokens`, and the spaced-assignment pass then dropped the rest of the
2139 line, leaving `max tokens = [redacted]`. Token counts are not credentials;
2140 the hint now matches a credential identifier (`token`, `api_token`) rather
2141 than an English word, so the numbers survive while `token = Bearer …` is
2142 still redacted.
2143 - Dashboard thread search no longer loads every thread's transcript to decide
2144 whether the row matches. `GET /v1/threads/summary?search=` walked the full
2145 thread list and called `get_thread_detail` on each row before matching, and
2146 that detail read is itself a whole-store walk of every turn JSON and every
2147 item JSON. A non-matching keystroke was therefore
2148 O(threads × (all_turns + all_items)) file reads — on the order of 10^8 JSON
2149 parses at a few thousand threads. Search now matches `id`, title, and model
2150 from the thread record (and, when the title is unset, the single latest-turn
2151 file that supplies the displayed title) and loads detail only for matches, so
2152 preview stays a display field rather than a search key. Session summary
2153 already refused to search last-message text for the same reason.
2154
2155 - Silent `#[allow(dead_code)]` suppressions on the modules AGENTS.md warns
2156 auditors not to delete — prompt zones, context budget, the route seam —
2157 and on the next-largest holders (palette tokens, hotbar actions, core
2158 events) are now `#[expect(dead_code)]`, or gone where the lint was already
2159 stale. A suppression that stops matching the lint fails the `-Dwarnings`
2160 gate instead of sitting quiet. The same gate is recorded in
2161 `[workspace.lints]` so member crates inherit it from the manifest rather
2162 than only from CI `RUSTFLAGS`.
2163 - "missing key" now says where it looked. The provider picker reported
2164 credential readiness as the bare strings `missing key` / `key:not-set`,
2165 which named no source at all — so a home whose secret store held a working
2166 DeepSeek key could show `DeepSeek missing key` in the picker while a real
2167 turn from that same home completed, and nothing on screen said which layer
2168 disagreed. Every row now resolves through one sourced resolver and states
2169 the place its credential came from ("OPENROUTER_API_KEY", `secret store
2170 "deepseek"`, `[providers.x] api_key`, "xAI OAuth", a consented external CLI
2171 file); a row without a credential lists the places that were probed, in
2172 precedence order, and the command that fixes the first of them. Where a
2173 durable slot is deliberately *not* read — an inactive provider whose config
2174 table carries no api-key marker — the row says so rather than implying an
2175 empty slot.
2176
2177 - Provider credential precedence is now stated once, in a doc comment beside
2178 the single resolver that enforces it, instead of being implied by a
2179 150-line cascade of provider special cases. No precedence decision changed:
2180 `has_api_key_for` is now a wrapper over that resolver, and a test asserts
2181 the two agree for every provider.
2182
2183 - Credential saves and logouts no longer interleave. Both took a snapshot of
2184 the durable slot, wrote it, mutated the config document, and rolled back on
2185 failure, with no lock held across the sequence — so a save racing a logout
2186 on the same slot could leave the secret store and the config file
2187 disagreeing. Both now hold that provider's credential write lock for the
2188 whole read-modify-write.
2189
2190 Design ported from pi-mono (MIT, Copyright (c) 2025 Mario Zechner); see
2191 `docs/THIRD_PARTY_NOTICES.md`.
2192
2193 - Enumerating stored credentials no longer fails closed on one bad slot.
2194 Listing used to propagate a backend read error, so a single unreadable
2195 secret-store entry made `/provider` and logout treat every other stored
2196 credential as missing. Enumeration now skips the unreadable slot and
2197 continues, matching the probe loop it replaced.
2198
2199 - The first screen of first run no longer cuts its own headline. The welcome
2200 and ready titles, and the provider-step heading, were emitted as single
2201 unwrapped lines while the sentence beneath them wrapped, so at 40 columns
2202 German read "Codewhale arbeitet mit dir in diesem O", Russian lost its final
2203 stop, and Japanese lost "します。". Headings are prose and now wrap like it,
2204 in every shipped locale.
2205
2206 - The workspace-trust screen no longer cuts its own question in half on a small
2207 terminal. The question, the prompt-injection risk hint, and the trust-effect
2208 hint were each pushed as one unwrapped line, so at 40 columns the screen read
2209 "Should Codewhale work with the instruc" — severed mid-word with nothing
2210 marking the cut, while the workspace path directly beneath it wrapped
2211 correctly. Asking someone to grant filesystem trust while the question itself
2212 is truncated is the worst place in the product for that to happen. All three
2213 now wrap through the same helper the rest of onboarding uses, which also
2214 means they wrap correctly in Japanese and Chinese. Verified across all
2215 fifteen shipped locales at 40, 60, 80 and 120 columns.
2216 - `codewhale completions <shell>` generated a script for the wrong program.
2217 The subcommand forwarded to the in-tree `codewhale-tui` binary, which
2218 rendered completions from *its own* clap tree under *its own* name, so the
2219 output ended in `complete -F _codewhale__tui ... codewhale-tui` (bash),
2220 `#compdef codewhale-tui` (zsh), and
2221 `Register-ArgumentCompleter -Native -CommandName 'codewhale-tui'`
2222 (PowerShell). Sourcing it registered nothing for `codewhale` or `codew` —
2223 the two commands current installers expose — so tab completion appeared to
2224 do nothing. The forwarded tree was also stale against the real CLI: it offered
2225 `pr`, `scorecard`, and `session-diagnostics`, which `codewhale` does not
2226 have, and omitted `run`, `rc`, `config`, `model`, `thread`, `lane`,
2227 `workflow`, `web`, `account`, `app-server`, `mcp-server`, `metrics`,
2228 `update`, `cloud`, `completion`, and `lane-log-proxy`, which it does.
2229 Completions are now rendered in-process from the CLI's own command tree,
2230 and `completions` is an alias of the existing
2231 `completion` subcommand rather than a second, divergent path. Regenerate any
2232 script you installed from an earlier release. Reported by **RepentStar**
2233 (#5526); part of the `deepseek-tui`-era identifier retirement in #5443.
2234
2235 - Completion scripts now fire for the `codew` shorthand as well as
2236 `codewhale`. Releases publish `codew` as a byte-identical copy of the
2237 `codewhale` binary, so a script bound to only one of the two names was half
2238 installed for anyone who types the short one. Each shell gets its own
2239 idiomatic hook rather than a second copy of the script: bash re-binds the
2240 generated function, zsh widens the `#compdef` tag line to
2241 `#compdef codewhale codew`, fish adds `complete -c codew -w codewhale`,
2242 PowerShell registers `-CommandName 'codewhale','codew'`, and Elvish aliases
2243 the completer with
2244 `set edit:completion:arg-completer[codew] = $edit:completion:arg-completer[codewhale]`.
2245
2246 - Documented shell completions. `docs/INSTALL.md` § 8 now gives the generate
2247 and install commands for bash, zsh, fish, PowerShell, and Elvish, with a
2248 note to regenerate after upgrading and to delete scripts produced by
2249 v0.9.10 or earlier. There was previously no completion documentation
2250 anywhere in the repository, which is how #5526 was reported as three
2251 problems instead of one.
2252 - `/status` was 31 rows. On an 80x24 terminal the transcript viewport is 18, so
2253 typing `/status` landed you on the *tail* of the report: the version, route,
2254 directory, mode and sandbox rows had already scrolled past, and what stayed on
2255 screen was five `not reported` rows and a `$0.0000`. The report is 18 rows on a
2256 fresh session — `Window override:` is present unless the value is already
2257 configured. That is the viewport's height, so once `/status` itself occupies a
2258 history cell the title row still scrolls off; it does not fit that terminal
2259 whole. Provider, model and reasoning effort are one `Route:` lockup, the way
2260 the header rail already writes them. Mode and its permissions are one statement
2261 of posture. `Rate limits:` is gone — it was a `push_row` of a string literal
2262 and could never say anything but "not available from provider telemetry". The
2263 per-turn token ledger is gone too, because `/tokens` is that ledger's whole
2264 subject and `/status` was printing six rows of it at the same weight as the
2265 sandbox policy; the two facts that lived nowhere else, the cumulative in/out
2266 split and the cumulative cache totals, survive on one `Session tokens:` row.
2267 `Footer items:` no longer prints ten internal config keys across the full
2268 width — `/statusline` owns them, and the report now points there in the same
2269 row that points at `/tokens`. Two blank gutters do the grouping; the
2270 `===================` rule under the title is gone.
2271
2272 - The `/status` window-override key has its own labelled row. It used to be
2273 parenthesised onto the end of the provenance row, which pushed
2274 `context_window in config.toml` past the right edge at 80 columns and wrapped
2275 the sentence. `Window source:` states the provenance and `Window override:`
2276 names the exact key — and the override row is omitted entirely when the value
2277 is already configured, rather than advising you to set what you have set.
2278
2279 - `/help` no longer truncates anything. Every label and description used to run
2280 through a `truncate_to_width` that appended `…`, which in a two-hundred-row
2281 list promises text no keystroke can reveal and lands mid-token:
2282 `(aliases: /qin…` left the parenthesis hanging open. Descriptions now shed
2283 whole fields — the alias parenthetical first, then trailing clauses at their
2284 own joints, and only where there is no joint at all, the sentence's short form
2285 on a whole word with no mark, keeping the head noun of a simple verb +
2286 modifier + noun phrase rather than the adjectives that qualified it. The
2287 focused row's description is restated under the filter at the panel's full
2288 width, *only when the row itself could not hold it*, so a wide terminal does
2289 not say the same sentence twice. At 60 columns that restatement is itself
2290 shed — the `/advisor` detail stops before `session` — so the detail is longer
2291 than the row, not a copy of the original sentence.
2292
2293 - The `/help` label column is measured instead of assumed. It was a flat 28
2294 columns at every terminal size, so at 60 columns twenty blank cells sat
2295 between `/advisor` and a description cut down to 21. Each group now sizes its
2296 column to the labels it actually holds, which nearly doubles the description
2297 column on a narrow terminal, and the label — the string you have to type —
2298 reads one step brighter than the description that qualifies it.
2299
2300 - `/help` stopped spending rows on itself. The match count moved onto the filter
2301 row it describes, the blank spacer under it is gone, and the footer no longer
2302 repeats `type to filter` while the filter box says `Type to filter` two lines
2303 above — at 60 columns that duplicate was what pushed the footer onto a second
2304 row. A group header also stopped printing `▸ ▾`: the selection cursor and the
2305 collapsed chevron are the same glyph, and a focused collapsed group was
2306 showing it twice for two different facts. Help now opens focused on the first
2307 entry rather than the header above it.
2308
2309 - The bottom status rail is no longer one run-on sentence. At 120 columns it
2310 read `▌· idle · Ollama · deepseek-v4-flash · max · Anonymous usage counts are
2311 on. … ⌥V:output · /context:context · fn+F1:keys` — live state, route
2312 identity, a telemetry consent notice, and keyboard hints all strung together
2313 by the same middle dot in the same ink, so nothing was grouped and the eye
2314 had nothing to skim by. At 80 columns it simply stopped mid-notice, and at 60
2315 the row overflowed and was clipped by the terminal mid-word. The rail now
2316 divides its groups with a blank gutter instead of another dot (the dot is
2317 kept for peers *inside* a group), the model name reads one step brighter than
2318 the qualifiers that narrow it, and `Esc to interrupt` reads in the same hint
2319 weight as the right-hand chords rather than in the separator weight.
2320
2321 - Nothing on the status rail is ever truncated now. A notice sheds whole
2322 sentences to fit, and if one sentence is still too long it sheds at the inner
2323 joints — a colon, a semicolon — with the trailing mark cut so the phrase that
2324 survives does not itself advertise that more was coming. Route identity sheds
2325 the provider, then the reasoning effort, rather than rendering
2326 `deepseek-v4-flash-prev…`; a clipped model name is worse than no model name
2327 because routes share prefixes. Clauses rejoin without a Latin space after a
2328 full-width stop, so the Japanese receipt reads as Japanese.
2329
2330 - A notice now stands the standing facts down instead of queueing behind them.
2331 Route identity and the ledger chips are still there in ten seconds; the
2332 notice is not, so it takes the row and the key hints yield last. This is what
2333 makes the telemetry receipt readable at 80 columns, where it used to be
2334 simultaneously always present and never legible.
2335
2336 - The status rail no longer advertises `/context:context`. It was spending
2337 eighteen columns of a 24-row screen to name a slash command that announces
2338 itself the moment you type `/`; the rail advertises chords you cannot
2339 discover any other way. The rail now reads the same at 80 columns as at 200.
2340
2341 - The idle screen no longer has an absolute path stretched across it. The
2342 workspace caption between the wordmark and "What do you want to accomplish?"
2343 was composed at full length and then truncated to the lane width, which made
2344 the centering inset `(width - caption.width()) / 2` evaluate to zero — so a
2345 line that was written to be centered rendered flush-left and full-bleed,
2346 cutting the centered whale/wordmark/prompt composition in half. The clipping
2347 also destroyed the information it was supposed to carry: at 80 columns the
2348 line read `/private/tmp/claude-501/-Volumes-.../34267917-11f4-4d15-911a-…`,
2349 which tells the reader nothing about where they are. The caption now sheds
2350 detail instead of being cut — MCP count first, then branch, then leading path
2351 components — so it always fits with room to center, and the folder you are
2352 standing in is the last thing to go. Elisions land on a path separator rather
2353 than mid-directory.
2354
2355 - Removed the placeholder engine tree in `crates/core/src/engine/`. Its
2356 `Engine::run` accepted `Op::SendMessage`, appended to a journal, and emitted
2357 `TurnComplete { status: "completed" }` without ever contacting a model, and
2358 `TurnExecutor` was a struct with a field-copy constructor and a
2359 `step < max_steps` comparison. Nothing in the workspace referenced any of it —
2360 the only mention of `codewhale_core::engine` anywhere was a doc comment inside
2361 the tree itself — but its comments ("the real turn loop is wired here in the
2362 next slice") were what `docs/ARCHITECTURE.md` leaned on to claim that
2363 `crates/core` owns the agent loop. There is now exactly one turn loop in the
2364 workspace, `Engine::run_turn`, and a guard test fails if a second one appears.
2365 `docs/ARCHITECTURE.md` and `AGENTS.md` now say where it actually lives.
2366
2367 - First-run onboarding no longer silently truncates its explanation in
2368 languages that do not put spaces between words. `wrap_words` split on
2369 whitespace, so a Japanese sentence arrived as a single token, the
2370 line-break check (which only fires once a line is non-empty) never
2371 triggered, and the over-wide line was clipped by the terminal. At 80
2372 columns the provider screen read
2373 "Hosted providers need a key, but loca" and stopped — losing exactly the
2374 half that tells the reader local runtimes need no key, on the screen where
2375 they choose a provider. Space-less scripts now break by display width on
2376 grapheme clusters, and a line may not begin with closing punctuation
2377 (`。`, `、`, `」`, `)` and friends). Wrapping for languages that do use
2378 spaces is unchanged.
2379
2380 - Project instructions are bounded by one budget and no longer treat other
2381 agents' files as law by default. Previously `.claude/instructions.md` and
2382 `CLAUDE.md` sat at ranks 2 and 3 of the canonical instruction list — *above*
2383 Codewhale's own `.codewhale/instructions.md` — `.claude/rules/` was an
2384 auto-discovered rules directory, and `.cursorrules`, `.cursor/rules`,
2385 `.clinerules`, `.windsurf/rules`, `.gemini`, `.github/copilot-instructions.md`
2386 and `.github/muse-instructions.md` were all imported into the system prompt
2387 with no opt-in. Dropping a `CLAUDE.md` written for a different tool into a
2388 repository silently made it standing authority here, which is an injection
2389 surface rather than a convenience. Codewhale now reads `AGENTS.md`, the
2390 cross-agent `.agents/AGENTS.md`, and its own instruction files by default;
2391 every other agent's format is opt-in by name through
2392 `project_instruction_imports` (env `CODEWHALE_PROJECT_INSTRUCTION_IMPORTS`),
2393 imported files rank *below* Codewhale's own, and a workspace that contains an
2394 un-imported format says so in a warning naming the exact setting.
2395 - Separately, a symlinked candidate rules directory — `.cursor/rules`,
2396 `.windsurf/rules`, or `.gemini` pointing outside the workspace — was
2397 traversed and its contents imported as instruction authority, because the
2398 directory check followed the link while only the files inside it were
2399 checked. The two instruction loaders now apply the same no-follow rule that
2400 `.codewhale/rules/` already had.
2401 - The three separate ceilings on standing instructions (200 KiB for the
2402 root->workspace chain, 500 KiB for the rules block, 40 KiB for imported
2403 fragments, and a global layer that was merged in after the chain budget had
2404 already closed and so counted against nothing) are replaced by a single
2405 48 KiB aggregate budget covering all of them together. Instructions claim it
2406 before rules, and are trimmed from the broadest scope inward so the
2407 nearest-scope file is the last thing dropped rather than the first thing
2408 stranded. Truncation still leaves an explicit marker.
2409
2410 - Editing the workspace no longer grants the shell outbound network access.
2411 `workspace-write` sandboxes are created network-restricted; `curl`, package
2412 installs, and `git fetch` inside a sandboxed shell are denied by the OS
2413 sandbox unless network is granted explicitly. This closes a real gap rather
2414 than tightening a working boundary: the elevation added in #273 was justified
2415 by the application-level `NetworkPolicy` remaining "the only outbound
2416 boundary", but that policy governs `fetch_url`, `web_search`, and MCP HTTP
2417 and never constrained shell subprocesses, so workspace-write turns had
2418 unrestricted egress with nothing enforcing anything. Network now comes from
2419 one of three explicit places: the new `sandbox_network_access` config key
2420 (also `CODEWHALE_SANDBOX_NETWORK_ACCESS`), a `danger-full-access` posture, or
2421 the existing post-denial elevation prompt that grants network for a single
2422 call. Yolo and `--yolo`/Bypass are unchanged — they resolve to
2423 `danger-full-access`, which applies no sandbox at all. `external-sandbox`
2424 reports the network it was actually granted instead of hardcoding `true`, and
2425 `/status` reads the flag instead of printing "network on" for every
2426 workspace-write policy. Platforms with no sandbox backend (default Linux
2427 without bubblewrap, and Windows) still enforce nothing, and both `/status`
2428 and `doctor` continue to say so.
2429
2430 - The nightly Windows ARM64 artifact build works again. Every nightly from
2431 2026-08-16 failed while compiling `codewhale-tui`, deterministically on the
2432 same codegen unit across all three build attempts, with
2433 `thread 'optimize module codewhale_tui...-cgu.13' has overflowed its stack`.
2434 The trigger is stack depth in the LLVM worker threads that run per-codegen-unit
2435 optimization, not the workflow's `lto=off` override: holding the crate and
2436 every flag fixed and varying only `RUST_MIN_STACK` on aarch64 shows 1 MiB
2437 crashes rustc while 2 MiB and 4 MiB succeed. Unix std defaults to 2 MiB and
2438 passed; the Windows ARM64 runner sat under the requirement. Nightly now sets
2439 `RUST_MIN_STACK` explicitly for every target, because the requirement follows
2440 from the size of `crates/tui` rather than from the platform. The redundant
2441 `codegen-units` override is gone -- `[profile.release]` already sets 16, so
2442 restating it never changed anything. Shipped binaries were never affected;
2443 `release-artifacts.yml` builds `--profile dist` with fat LTO and
2444 `codegen-units = 1`.
2445
2446 - Test debt: the transcript history-cell suite has been rebuilt. It was 123
2447 tests across 3,964 lines, and about a third of it pinned the current skin
2448 rather than any behavior -- `assert_eq!(spans[1], "⣤")` for the
2449 reduced-motion marker, `title_span.style.fg == theme.tool_title_color`,
2450 `visible[1] == "▏ done: scan repo"`, four separate tests each asserting one
2451 shape of fenced code never takes the transcript rail, and one test whose
2452 only assertion was `!text.is_empty()` under a name promising it checked the
2453 rendered tool id. Assertions like those break on every legitimate visual
2454 change and catch nothing a reader of the transcript would notice, which is
2455 the liability `d64b9429b` named. The replacement is 40 tests, each named
2456 for the property it protects and asserting the property instead of the
2457 token: reduced motion is checked by rendering the same running card at two
2458 different elapsed times and requiring the frames to match -- which also
2459 catches an animation leak the glyph constant missed -- and a frozen marker
2460 must stay visible rather than landing on the spinner's invisible blank
2461 (U+2800). Severity colors are checked by requiring warning not to read as
2462 error rather than by naming a palette entry. A streaming assistant glyph
2463 must actually pulse when motion is allowed, checked against
2464 `pulse_brightness` rather than by sleeping on the 2s sine. Each of the
2465 invariants claimed was verified to fail the new suite when deliberately
2466 broken in the renderer.
2467 ## [0.9.10] - 2026-08-19
2468
2469 - 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/Hmbown/CodeWhale/issues/998). Thanks [@AiurArtanis](https://github.com/AiurArtanis) and [@formp3](https://github.com/formp3) for identifying the affected surfaces.
2470 - `registry_sync` no longer ships the full MCP Registry catalog into the
2471 conversation. It takes a required query, scores the local snapshot
2472 host-side, and returns at most eight matches; the complete catalog stays on
2473 disk, and the compaction and spillover exemptions that let a multi-hundred-
2474 kilobyte dump reach the model unchanged are gone.
2475 - Providers that mirror the outgoing `(reasoning omitted)` replay placeholder
2476 back as a reasoning delta no longer have that echo ingested as real
2477 thinking: the exact transport placeholder is dropped on arrival, so live
2478 sessions stop showing a stream of placeholder reasoning blocks and saved
2479 transcripts stay free of them.
2480 - Mid-stream connection drops during an interactive turn no longer persist a
2481 synthetic `[runtime]` user message. Retry state is a typed engine-internal
2482 descriptor; a thinking-only drop re-issues the request without claiming a
2483 partial reply was preserved, the retry budget is enforced in mechanism, and
2484 recovery produces exactly one authoritative final answer.
2485
2486 Codewhale v0.9.10 is a retention, identity, and product-clarity release: the shell and
2487 transcript can no longer retain unbounded tool output in memory or on disk,
2488 mid-turn history inserts no longer strand in-flight tool rows, every agent
2489 that ran this session is visible from `/agents list`, the PTY acceptance
2490 lane has a stall watchdog and bounded CI steps, approval outcomes are
2491 durable and fail closed (cyq1017, #5360), and three $HOME disk leaks are
2492 reclaimed. Extension surfaces now name their real state and act only
2493 through the reviewed install and trust flows, and sub-agent, shell, task,
2494 and workflow state is owned by the session that created it (#5518). Test
2495 threads get an 8 MiB stack so the lib suite can no longer
2496 abort under load.
2497
2498 ### Fixed
2499
2500 - First run starts on the welcome screen again. A missing key no longer
2501 skips Welcome and auto-opens the local-provider list: Enter walks to the
2502 calm provider explanation, then Enter opens the picker so a first API key
2503 can be set. Returning missing-key recovery still opens the picker on
2504 launch.
2505 - A foreground `bash` command that named no timeout is bounded again. The
2506 model-facing `bash` tool left an omitted `timeout_ms` at the internal
2507 ceiling (~24.8 days) instead of the 120 s default its own schema
2508 advertises, so a CLI that blocked on an interactive prompt or a hung
2509 network call held the turn open indefinitely — one report sat on a single
2510 unauthenticated CLI call for over two hours with the tool row simply
2511 counting seconds. The advertised default now applies, which arms the
2512 existing recovery: the process is killed and the model is told to rerun
2513 with `background=true` and poll with `action="wait"`. An explicit
2514 `timeout_ms` is still honored for genuinely long foreground work, and
2515 background and interactive runs keep their own lifetimes.
2516 - The Extensions (`/plugin`) Marketplace is no longer a read-only list.
2517 Every recommendation and stored candidate names its truthful state and
2518 primary action — Add, Enable, Configured, or Unavailable — and Enter or a
2519 mouse click runs that action through the existing reviewed `/mcp add
2520 recommended`, `/mcp enable`, and `/plugin` install/trust controllers, so
2521 no second trust path exists. Browser Use and Sandbox Runtime stay
2522 honestly Unavailable with their real setup routing instead of implying an
2523 install Codewhale cannot perform.
2524 - The Extensions MCP tab now renders one honest inventory: the header count
2525 and the visible rows derive from the same configured-server set, so
2526 `MCP (6)` can no longer sit above two rendered rows. Disabled servers
2527 stay visible and labeled disabled instead of silently disappearing, and
2528 configured servers absent from the live snapshot list as not-yet-inspected
2529 with their own explicit reload affordance through the MCP command
2530 controller.
2531 - Installed plugin rows now act on their real state: Enter opens an active
2532 bundle (`/plugin show`), offers Enable for a trusted-but-disabled bundle,
2533 or routes an untrusted bundle to the existing trust review — through the
2534 same confirmation and persistence controllers as the slash commands.
2535 - Sub-agent handoffs and rosters, background shell jobs, durable tasks,
2536 delayed continuations, and workflow controls are now scoped to the
2537 session that owns them. Records carry immutable root-session ownership,
2538 stale completion-channel payloads are rejected before deduplication,
2539 background work drains and reports only to its owning session, and
2540 legacy ownerless jobs fail closed (#5518 failure class reported by
2541 @hxfhd; the report's exact JavaScript provenance was not claimed as
2542 reproduced).
2543 - The resolved route envelope now reaches every outbound model call: all
2544 wire dialects and auxiliary calls clamp at the shared transport seam
2545 under one wire/reservation budget, provider input limits are honored, and
2546 switching models on the same protocol no longer inherits the previous
2547 model's limits (#5516, #5518).
2548 - First-run continuity: the chosen onboarding provider persists across
2549 restarts, a missing first-run config no longer interrupts the flow, and
2550 the automatic working-agreement checkpoint renders as a standalone setup
2551 handoff instead of regressing the onboarding rail to the full wizard's
2552 4/10 progress.
2553 - Explicitly worded natural-language `/goal` declarations now create a
2554 durable goal in the provider-neutral engine before model dispatch, while
2555 ordinary tasks and quoted transcripts stay out of goal mode and prose
2556 acknowledgement alone can no longer stand in for goal creation.
2557 - `/model` now keeps the current Z.ai default (`GLM-5.3`) visible when an
2558 older installation has an explicit `GLM-5.2` route saved. The saved 5.2
2559 route remains exact; choosing 5.3 sends and remembers the distinct 5.3 ID.
2560 - The constitution checkpoint now leads with the bundled balanced agreement;
2561 the default path writes no custom constitution. The startup launch surface
2562 distinguishes read-only Chat from folder-bound, approval-gated Work.
2563 - Tabby and other IME bridges no longer observe a stale visible caret while a
2564 frame diff is being painted; Codewhale hides the cursor during the diff,
2565 restores the canonical composer cell, and only then reveals it again
2566 (BrathonBai, #5023).
2567 - Pre-header HTTP/2/SSE transport failures get one bounded HTTP/1.1 retry;
2568 authentication, provider-semantic, response-body, and already-pinned HTTP/1
2569 failures remain fail-closed (demian-welt, #4683).
2570 - MCP `tools/call` images now travel as bounded typed content instead of
2571 leaking base64 through model-visible JSON. Direct and parallel calls share
2572 the same MIME, size, validation, and one-image boundary (PR #5515 by
2573 @cacdcaecawae).
2574 - Linux npm installs and updates race GitHub Releases against the CNB mirror
2575 at the checksum-manifest layer, then download from the first verified source
2576 without making users wait through a doomed slow-source timeout.
2577 - `CODEWHALE_PREFER_BWRAP` now applies the documented Linux sandbox override,
2578 and Codewhale-era names own build metadata, hook session/tool-call IDs, and
2579 sandbox child markers. The corresponding `DEEPSEEK_*` names remain as 0.9.x
2580 compatibility aliases (#5443).
2581 - Windows default launch prefers Windows Terminal: zip archives ship
2582 `codewhale.bat` (CRLF, `wt.exe` then the exe), `install.bat` copies that
2583 launcher, and the NSIS Start Menu shortcut opens it instead of the raw
2584 binary (#1854).
2585 - `fix(tui): make the header status mark honour its setting` — `status_indicator`
2586 did nothing for three of its four documented values. The header hardcoded a
2587 leading `cw` span *and* asked for a second mark beside the effort chip, then
2588 filtered the second one against the literal `"cw"`; because `cw`, the legacy
2589 `whale` opt-in, and every unknown value all normalize onto that same mark,
2590 the filter discarded them and left `off` with nothing to turn off. `cw`,
2591 `whale`, `off`, and a typo all rendered byte-identical headers. There is one
2592 mark now and the setting owns it: `cw`/`whale` draw the typographic mark,
2593 `dots` draws the activity frames, `off` removes it (thejayjetson, #5512).
2594 - `fix(tui): rebase active-cell tool bindings on every mid-turn history
2595 insert` — `/rename` mid-turn left the running tool row spinning forever
2596 (#5478).
2597 - `fix(tui): bound what the shell and transcript retain from tool output` —
2598 a 1.1 MB Bash call kept over a megabyte resident for up to an hour; raw
2599 streams now cap at 16 MiB in flight and release delivered output, and
2600 retained tool outputs cap at 64 KiB per record / 8 MiB per transcript
2601 (#5472).
2602 - `fix(tui): reclaim the three $HOME disk leaks` — orphaned session dirs,
2603 the unbounded audit.log, and stranded writer temp files.
2604 - `fix(tui): persist approval outcomes before execution` (cyq1017) —
2605 approval receipts are committed to a session-owned log before execution
2606 proceeds; unpersistable evidence blocks the tool; resume reconstructs
2607 closed and interrupted approvals (#5360).
2608 - `test(tui): break the LazyLock/env-barrier deadlock in the test harness`.
2609 - `ci: give test threads the 8 MiB stack they need` — the lib suite aborted
2610 with SIGABRT under load on the default 2 MiB stack.
2611 - YOLO entry points honor a locked approval policy: `--yolo`, `/mode yolo`,
2612 `/zidong`, and Alt+Y can no longer set Full Access + trust + shell when
2613 config or managed requirements own the posture.
2614 - Terminal PTY tools fail closed without a sandbox backend under a narrowed
2615 filesystem posture, and otherwise start `$SHELL -i` through
2616 `SandboxManager::prepare` like `bash`.
2617 - Skill update refuses to replace a directory that has no `.installed-from`
2618 marker — same ownership gate plugins already used.
2619 - `cp`/`mv` are workspace-safe only when every path operand stays inside
2620 the workspace — Auto-Review no longer auto-allows `cp /etc/passwd .`.
2621 - Main CI no longer shares one concurrency group per branch: each SHA
2622 gets a verdict instead of a cancelled pending run. A hermetic Safety
2623 gate job runs authorization tests in under 15 minutes (test bankruptcy
2624 restructuring — no tests deleted).
2625 - Config-fixture tests no longer honor `lock_test_env` as a license to
2626 read a populated `~/.codewhale/config.toml`; they need an `EnvVarGuard`
2627 like settings already did. Safety-gate and CNB workspace tests pin a
2628 hermetic `CODEWHALE_HOME`. `exec_persistent_service` is serialized in
2629 nextest and inside the cargo-test binary instead of dropped (#5355).
2630 - Short CLI no longer waits up to three seconds for a telemetry POST on
2631 exit; `session_end` is recorded and the buffer ships on the next
2632 interactive session.
2633 - Bare `/` now opens a deliberately small starter set: `/help`, `/setup`,
2634 `/model`, `/settings`, `/resume`, and `/rc`. The full command inventory
2635 remains searchable through `/help`, the command palette, and direct prefix
2636 typing, without front-loading the entire control surface (#5442, #5439).
2637 - First run now asks only for decisions needed to become usable, keeps the
2638 offline route explicit, and leaves optional provider, tools, policy, and
2639 appearance work in the progressive `/setup` repair guide. The idle aquarium
2640 asks one task-oriented question instead of advertising a tutorial or command
2641 billboard, and the localized telemetry choice appears after the workspace is
2642 ready without blocking the composer.
2643 - Provider, active model, and reasoning effort moved out of the crowded header
2644 into a quiet, width-aware footer identity. Compact layouts keep model and
2645 effort before provider detail and shed whole low-priority groups instead of
2646 clipping the composer or control hints.
2647 - The model picker no longer re-parses `~/.codewhale/config.toml` once per
2648 provider when deciding who has a saved key.
2649
2650 ### Added
2651
2652 - `/workflows` opens a live run dashboard over this workspace's durable
2653 workflow journal: every retained run with status, phases, child roster,
2654 progress, and host-side cancel — observation only, it never launches a run.
2655 - Repository instructions now assemble from the actual containing checkout:
2656 applicable `AGENTS.md` files resolve repository-root to current-directory in
2657 order under one aggregate budget, a linked worktree is its own root, and
2658 scope is never inferred from path mentions or whichever branch is named
2659 `main`.
2660 - `/goal` is a codex-style control plane: setting an objective dispatches it
2661 to the engine, which owns the goal and starts the first goal turn itself —
2662 the objective is never echoed back as the user's own message, pause/resume
2663 are real control ops, and the hunt-era vocabulary and trophy cards are
2664 gone.
2665 - `/extensions` and `/plugins` open one localized inventory for Hooks,
2666 Plugins, local Marketplace catalogs, Skills, and MCP. Reviewed suggestions
2667 include Playwright, Chrome DevTools, Cua Computer Use, Browser Use, and the
2668 sandbox runtime without granting trust or installing anything on open.
2669 - Turn Inspector now opens the newest turn and pages across complete recorded
2670 user, reasoning, tool/subagent, and assistant output with page-scoped search,
2671 copy, and export (sky-sun-moon, #1682).
2672 - Background tasks have bounded incremental persistence, durable terminal
2673 reasons, truthful timeout/cancellation receipts, restart recovery, and
2674 interruptible continuous-goal delays (#5497, #5508).
2675 - `/title` once again controls the terminal window title independently from
2676 `/rename`, survives session save/load, and sanitizes control, bidi, and
2677 zero-width characters (PR #5509 by @SparkofSpike).
2678 - MCP snapshots preserve whether capabilities were advertised by the server,
2679 discovered through the bounded legacy fallback, or not observed (#4170).
2680 - `codewhale auth status --diagnostic` reports canonical paths, isolation
2681 source, backend class, and value-free provider-source presence without
2682 opening credential stores or creating/migrating state (#2369).
2683 - `codewhale doctor --probe-search` performs an explicit credential-free,
2684 policy-checked transport probe for the selected search provider; ordinary
2685 doctor and JSON output remain offline (#5442).
2686 - The safe deferred `read_media` tool is available to supported read-only
2687 roles, and history receipts distinguish localized tool execution outcomes
2688 without exposing raw payloads (#5102).
2689 - **npm Linux x64 first-party source selection.** The wrapper concurrently
2690 fetches the GitHub Releases and CNB checksum manifests for the exact
2691 package version, locks the first source whose HTTP response and manifest
2692 validate, and downloads binaries only from that source. Explicit
2693 `CODEWHALE_RELEASE_BASE_URL` / `CODEWHALE_USE_CNB_MIRROR=1` still skip the
2694 race; other targets stay on GitHub.
2695 - `/workflow <objective>` and `/workflow run <path>` now produce a bounded,
2696 tool-less proposal for review. Only `/workflow confirm` can launch that
2697 reviewed draft; status, cancel, settings, and the `/workflows` dashboard stay
2698 host-owned and do not spend a model turn (#5439).
2699 - `feat(tui): add cancellable cadence to continuous goals` (M-Maciej) —
2700 `[goal] continuation_delay_seconds` gives coordinator goals a visible quiet
2701 period between successful turns while reusing the existing coalesced goal
2702 continuation token; Esc, Ctrl+C, pause/done/blocked/clear cancel before the
2703 next provider request, and failures never continue (#5508).
2704 - `feat(tui): add command context adapters and migration gate (FEAT-015)`
2705 (aboimpinto) — TUI-owned capability facets, a dual-path dispatch seam, and
2706 source-aware CI enforcement so a command slice cannot claim to be migrated
2707 while it still accepts concrete `App`. Zero production commands migrate in
2708 this slice (#5316).
2709 - `feat(web): move docs/hooks and docs/troubleshooting onto the dictionary
2710 spine` (Lstarsky0) — both pages now read copy from the locale dictionaries
2711 instead of inline bilingual literals (#5337).
2712 - `feat(web): move docs/constitution and docs/runtime-api onto the dictionary
2713 spine` (Lstarsky0) — both pages now read copy from the locale dictionaries
2714 instead of inline bilingual literals; another incremental phase of #5337,
2715 not completion of the full epic (#5517).
2716 - `docs(i18n): complete Tier 1 of Chinese docs localization` (SparkofSpike) —
2717 Chinese and Indonesian docs move to `docs/zh_hans/` and `docs/id/`, with
2718 redirect stubs at the old paths for one release cycle (#5482).
2719 - `feat(tui): show repository context in git chrome` (wuisabel-gif) — the TUI
2720 header now identifies the active repository or linked worktree before the
2721 branch and dirty marker, so operators can see where the agent is working
2722 without opening the worktree manager (#5437).
2723 - `feat(tui): formalize the status-bar color grammar` — seven semantic
2724 families live in `docs/design/STATUS_BAR_COLOR_GRAMMAR.md` and
2725 `palette::grammar`; header and phase-strip ink resolve through named
2726 `ChromeInk` slots so chrome cannot invent an eighth meaning or spend
2727 Failure red on a dirty worktree or selected mode. The footer's session
2728 metrics strip resolves through the same inks, and the red reservation is
2729 checked against every selectable theme, not just the whale default;
2730 typed footer toasts resolve through the grammar too.
2731 Repo/worktree chrome stays metadata and still renders when Git names a
2732 location but not a ref (#5437).
2733 - `feat(tui): first slice of the agents roster` — every agent that ran this
2734 session, receipts-only, via `/agents list` and the sidebar fan-out rows
2735 (#5479 spec items 1 and 5).
2736 - `ci: bound PTY acceptance and add a stall watchdog to the harness` —
2737 QA_PTY_STALL_TIMEOUT_SECS aborts a wedged PTY run with a diagnostic;
2738 the isolated PTY step is capped at 15 minutes; Windows NSIS provisioning
2739 gets a bounded retry (#5496).
2740 - `chore(scripts): dev-cache warns before it fills a disk` (#5465 class).
2741
2742 ### Contributors
2743
2744 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) — restored
2745 `/title` as an independent, persistent terminal-window title in PR #5509,
2746 in addition to the Tier 1 Chinese and Indonesian documentation work below.
2747 - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) — extracted the
2748 turn-loop stream processor in PR #5514 while preserving retry, cancellation,
2749 usage, TTFT, steering, and partial-response behavior.
2750 - [OctoBored](https://github.com/OctoBored) (`@OctoBored`) — supplied the
2751 working no-token Star History mirror used across the localized README set
2752 after the canonical chart endpoint began returning a restricted placeholder
2753 (#5510).
2754 - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) — added
2755 provider-neutral typed MCP image forwarding in PR #5515; the harvested
2756 version also makes malformed image fields produce a visible omission receipt.
2757 - [DingYong4223](https://github.com/DingYong4223) (`@DingYong4223`) — reported
2758 the narrow-terminal completion truncation closed by the bounded hover reveal
2759 (#998). Thanks also to @AiurArtanis and @formp3 for identifying the affected
2760 completion surfaces.
2761 - [sky-sun-moon](https://github.com/sky-sun-moon) (`@sky-sun-moon`) — reported
2762 the missing full per-turn input, reasoning, tool, and assistant pages that
2763 shaped Turn Inspector navigation (#1682).
2764 - [cy2311](https://github.com/cy2311) (`@cy2311`) — reported the Windows launch
2765 path that now ships and installs a Windows Terminal-aware batch launcher
2766 (#1854).
2767 - [demian-welt](https://github.com/demian-welt) (`@demian-welt`) — provided the
2768 reproducible pre-header SSE transport failure behind the bounded HTTP/1.1
2769 retry (#4683).
2770 - [BrathonBai](https://github.com/BrathonBai) (`@BrathonBai`) — reported the
2771 Tabby/CJK IME candidate-window jump that led to the hide-diff-position-show
2772 cursor transaction (#5023).
2773 - M-Maciej (@M-Maciej) — the real-world organization-coordinator use case and
2774 5–30 minute cadence requirement behind cancellable cross-turn goal delays
2775 (#5508).
2776 - cyq1017 (@cyq1017) — approval outcomes are persisted before execution can
2777 proceed: receipts commit to a session-owned log first, unpersistable
2778 evidence blocks the tool, stale decisions are rejected, and resume
2779 reconstructs closed and interrupted approvals (#5491, closes #5360).
2780 - aboimpinto (@aboimpinto) — the TUI-owned dependency-injection and migration
2781 infrastructure that makes slash-command extraction safe: seven capability
2782 facets, a dual-path dispatch seam, and source-aware CI enforcement so a
2783 command slice cannot claim migration while it still accepts concrete `App`
2784 (#5506, EPIC-005/FEAT-015 under #5316, which they also filed).
2785 - wuisabel-gif (@wuisabel-gif) — the TUI header now names the active
2786 repository or linked worktree before the branch and dirty marker, derived
2787 from Git's common directory and capped by shell density tier (#5511, the
2788 repo/worktree slice of #5437).
2789 - SparkofSpike (@SparkofSpike) — Tier 1 of the Chinese docs localization:
2790 Chinese and Indonesian documentation moves to `docs/zh_hans/` and
2791 `docs/id/` with redirect stubs held at the old paths for one release cycle
2792 (#5507, epic #5482, which they also filed).
2793 - Lstarsky0 (@Lstarsky0) — `docs/hooks` and `docs/troubleshooting` move onto
2794 the dictionary spine, retiring their inline bilingual literals in favor of
2795 locale dictionaries with token-aware code spans (#5504, closes #5337, which
2796 they also filed).
2797 - Lstarsky0 (@Lstarsky0) — `docs/constitution` and `docs/runtime-api` follow
2798 the same dictionary spine: 28 inline `isZh` branches become typed English
2799 and Chinese dictionaries held to key and token parity, while the other
2800 sixteen locales keep the English fallback (#5517, a further phase of #5337).
2801 - @thejayjetson — the header status-indicator report that pinned the
2802 regression to a specific setting, with every value, theme, and
2803 `fancy_animations` combination already ruled out (#5512).
2804 - hxfhd (@hxfhd) — reported the deterministic cross-session contamination
2805 class behind this release's session-ownership boundary, plus route
2806 budgeting evidence (#5518).
2807 - sfdzhmr (@sfdzhmr) — reported the route budgeting root causes that exact
2808 route-limit propagation now closes (#5516).
2809
2810 ## [0.9.9] - 2026-08-18
2811
2812 Codewhale v0.9.9 is a truth-and-resilience release: the shell tool can no
2813 longer wedge a session when the host runs out of disk or descriptors,
2814 unverified context windows and output ceilings are labeled honestly at every
2815 surface, DeepSeek V4 is priced on the published peak/off-peak tiers, SSE
2816 UTF-8 fails closed in every dialect, Fleet shadowing is visible, bwrap gets
2817 container essentials and extra roots, the `dsh` skin rides the bundle
2818 profile, the `agent` tool schema is down to 12 fields, and README/website
2819 locales grow to 18 and 8.
2820
2821 ### Fixed
2822
2823 - The lowercase `bash` tool no longer wedges when its complete-output spill
2824 file cannot be created: a full temp volume or exhausted descriptor table
2825 used to fail *every* call — `echo ok` included — with the harness-internal
2826 "Failed to create streaming shell output" and never recover until the
2827 host was cleaned up. The spill is now best-effort (the bounded tail is
2828 still returned and the truncation notice says why the full-output path is
2829 missing), and any remaining spawn/stream failure names the exhausted
2830 resource — disk, file descriptors, memory — and says the next call is safe
2831 to retry (#5465; the wedge that took out the owner's own 0.9.9 session).
2832 - A concrete route/offering output limit now outranks the conservative
2833 8,192-token compatibility guess for an uncatalogued model. Routes that
2834 publish no output limit remain fail-closed, documented model ceilings stay
2835 authoritative, and a route limit can never raise the requested cap (#5460).
2836 - Context-window honesty at every surface (#5239, #5441): the
2837 `model-name hint` and `fallback` rungs of the context-window ladder are
2838 guesses, and every surface that renders one now says so — the status line,
2839 `/status`, `/config`, the context-pressure message, the model picker chips,
2840 and the auto-router inventory. Unverified windows still drive real budgets
2841 (compaction trigger, context meter, output reservation); they just stop
2842 reading as capabilities anyone checked. A window parsed from an `_Nk`
2843 model-name suffix (`qwen3-32b-256k` → 256K) is now its own
2844 `model-name hint` rung below `catalog`, because it is optimistic rather
2845 than conservative — a catalog or provider-reported value beats it. The
2846 `[providers.<name>] context_window` override remains the hard fix and
2847 renders as `configured` with no marker.
2848 - Output-ceiling honesty (#5440): an Anthropic-family model the catalog does
2849 not describe keeps the 64K Messages floor as its clamp and the ChatGPT/
2850 Codex OAuth route keeps its 4K policy, but `OutputCeilingSource` gained an
2851 `unverified` rung for both, so exec-stream receipts and the model picker
2852 label them `unverified`/"assumed floor" instead of `documented`. Clamp
2853 values are unchanged.
2854 - Telemetry default-on is visible (#5441): `codewhale doctor`'s
2855 runtime-posture section gained a `telemetry=on (default)`-style row with
2856 the source that decided it (cli | env | config | default), and
2857 `codewhale config get telemetry` reports the resolved consent with its
2858 source instead of `key not found` on a machine whose batches ship. Truth
2859 change only; resolution and behavior are untouched.
2860 - Fleet: a scout's read-only shell carve-out (#5428) is now honored by both
2861 the posture gate and the execution envelope, so `git log`, `find | head`,
2862 `npm view` and the other bounded read-only commands run in-place instead
2863 of being refused as "Executes" (#5426). Delegation still never widens
2864 authority: the role-isolation test and docs/SUBAGENTS.md pin that a child
2865 cannot exceed its parent's posture (#5426, #5435).
2866 - `/rename` and `/title` now apply mid-first-turn: the session file does
2867 not exist until the first autosave, so the rename fell through with
2868 NotFound; the shared path now prefers the per-session checkpoint and
2869 rebuilds from App state, with a PTY regression test through the live
2870 event loop (#5430).
2871 - `integrations dsh plan` no longer refuses DeepSeek's default
2872 Responses-dialect route (`deepseek-v4-flash`); Responses and
2873 Anthropic-Messages routes are carried through pi-ai
2874 `openai-responses` / `anthropic-messages` instead of being approximated
2875 or refused; only credentialed base URLs are still refused, with an error
2876 that names provider and model (#5434).
2877 - Session cost no longer sits at `unverified_live_pricing` when live pricing
2878 cannot be verified (control-plane 503, Models.dev capabilities-only
2879 overlays): provider-docs bundled fallback rates for the DeepSeek V4
2880 family on Fireworks / OpenCode Zen restore a usable figure, live
2881 per-provider rows still win, and `kimi-k3` stays unpriced until a
2882 published rate exists (#5241; harvested from #5402).
2883 - Release assets: `release.yml` asset-freshness checks compare against the
2884 release job's own `started_at`, so job-level reruns of the npm step are no
2885 longer poisoned by earlier uploads (#5429).
2886 - macOS CI: the `agent_focus_pty` auto-review receipt test waited on a
2887 worker that had already completed and raced the rail's focus; it now holds
2888 the child's wrap-up and waits for a settled live row (refs #5056, #5403).
2889 - DeepSeek V4 pricing follows the published peak/off-peak tiers (peak
2890 01:00–04:00 and 06:00–10:00 UTC; off-peak is half of peak) for
2891 `deepseek-v4-flash` and `deepseek-v4-pro` in USD and CNY, resolved from
2892 each turn's recorded time; the stale single-tier rows understated cost up
2893 to ~4×. Because every direct DeepSeek first-party rate is now
2894 time-windowed, the scorecard fails closed (`missing_recorded_time`) on an
2895 undated DeepSeek turn instead of guessing a tier (#5470; #5241 follow-up,
2896 verified against api-docs.deepseek.com on 2026-08-17).
2897 - SSE UTF-8 split across HTTP/2 DATA frames now fails closed in every
2898 streaming dialect: a shared strict decoder, tail flush, and
2899 `decode_failed` propagation (`InvalidSseUtf8`) replace the per-dialect
2900 approximations, with byte-chunk decoder tests (#5374; supersedes draft
2901 #5404).
2902 - CI: `release_four_read_only_fleet_roles_launch_with_canonical_prompts`
2903 answered Fleet children with SSE while they call the blocking JSON path;
2904 the parse failure was retried and double-counted the worker on slow macOS
2905 runners (#5471; refs #5056).
2906 - Context: every web tool surface (`Web`, `web_search`, `web.run`,
2907 `fetch_url`) now uses the noisy-result soft limit, so large fetches are
2908 compacted like shell output instead of consuming the ordinary hard limit
2909 (#5474, thanks @h3c-hexin).
2910 - Routing: a lowercase saved selector such as `glm-5.2` resolves against the
2911 owning Z.ai / DeepSeek catalog row (case-fold fallback, only when exactly
2912 one provider-owned wire id matches) instead of being classified as another
2913 provider's bare model (#5475, thanks @h3c-hexin; diagnosis by @asto18089
2914 in Pinvou/CodeWhale#14).
2915 - Model catalog brought current as of 2026-08-17 against the official
2916 pricing pages: gpt-5.6-terra / gpt-5.6-luna rates, `claude-sonnet-5` keeps
2917 $2/$10 (the announced September increase was withdrawn), `claude-opus-5`
2918 added, `kimi-k3` and `kimi-k2.7-code-highspeed`, `MiniMax-M2.7-highspeed`,
2919 Mistral first-party rows, xAI `grok-4.5` / `grok-4.3` with long-context
2920 tiers, Gemini and Qwen limits, and RedNote's `dots3-note` preview as an
2921 OpenRouter row (no first-party API exists yet) — every number carries its
2922 source and a pinned test (#5485).
2923 - Website: copy on codewhale.net rewritten in plain declarative sentences —
2924 one idea per sentence, numbers from the generated facts, no self-narration
2925 — with a voice sheet at docs/design/WEB_VOICE.md (#5483).
2926 - CI: the release workflows no longer restore npm/cargo caches after
2927 checking out a caller-supplied SHA — the CodeQL cache-poisoning Highs
2928 #88–#107 are closed with a contract test over the workflow files (#5463).
2929 - Compact TUI rows below 60 columns no longer reserve a hidden session-metrics
2930 strip, so narrow terminals reclaim the row instead of clipping the
2931 transcript (#5486).
2932 - Ghostty's truecolor underwater field now uses a dedicated synchronized
2933 60 FPS lane instead of the legacy 30 FPS compatibility cap, with continuous
2934 caustic fades replacing visibly stepped color changes.
2935 - Live reasoning's advertised `Space:expand` action now runs before the
2936 composer's first-character paste-burst hold, while spaces in an active paste
2937 remain payload. The newest reasoning preview also spends only genuinely free
2938 viewport rows before truncating instead of stopping at the fixed 10/12-row
2939 fallback on roomy terminals.
2940 - Strict `cargo doc` builds no longer fail on bare URLs in rustdoc comments;
2941 the remaining links are explicit Markdown targets (#5489).
2942
2943 ### Changed
2944
2945
2946 - The model-facing `agent` tool advertises exactly 12 fields — `action`,
2947 `prompt`, `type`, `profile`, `name`, `agent_id`, `message`, `until`,
2948 `detached`, `worktree`, `write_roots`, `resume_from` — down from 33
2949 (#5324, refs #5123). Budgets (`max_steps`, `wall_time_secs`, `max_depth`),
2950 routing overrides (`model`, `model_strength`, `thinking`), worktree-path
2951 knobs, the deliberate/spawn-contract fields and the wait/status/interrupt
2952 extras moved off the advertised schema. Every removed field stays
2953 parse-accepted and honored unchanged (same contract as `token_budget`), so
2954 saved transcripts, ACP/MCP clients and Fleet configs replay as-is; the
2955 #5426/#5435 containment clamps are untouched. Child budgets now resolve
2956 from role defaults (60/120 turns, 1800 s wall time, unchanged clamps) and
2957 new `[subagents]` keys `default_max_steps` / `default_wall_time_secs`.
2958 Because the tool catalog is part of the session-pinned prompt prefix
2959 (docs/CACHE.md), upgrading re-fills the KV prefix once per session.
2960 - TUI prose — user messages, assistant answers, and reasoning/thinking —
2961 now wraps at the full content width on wide terminals, matching
2962 tool/status cells, instead of stopping at a 105-column rail that left a
2963 dead right margin on ultrawide displays (#5436).
2964 - Configured skill prompts are stable across session roots and operating
2965 systems: only custom configured roots hide their physical path, ordinary
2966 workspace/global skills keep a discoverable privacy-safe path, warning
2967 replacements are boundary-aware (including non-UTF-8 Unix paths), and
2968 Windows separators render as `/`. The skills prompt is also 50 bytes
2969 leaner without raising a runtime-contract ceiling (#5492, #5473).
2970 - Auto-router classifier requests accept `[auto.router] timeout_secs`, while
2971 preserving the existing default when the key is absent (#5494).
2972 - Every `ci.yml` job now has an explicit 10–90 minute timeout appropriate to
2973 its workload, bounding stale assigned runners instead of inheriting
2974 GitHub's six-hour default (#5495).
2975 - The docs shell and shared web components now route localized copy through
2976 the typed dictionary spine; these are two incremental phases of #5337,
2977 not completion of the full epic (#5488, #5490).
2978 - Dependency: rusqlite 0.40.2 (#5391).
2979 - Documentation: stale A/B/C-tier references, provider defaults, module
2980 descriptions, and line anchors now match the current code (#5481).
2981
2982 ### Added
2983
2984 - `[transcript] prose_measure` (positive integer, optional): caps prose
2985 wrap at N columns for owners who want a bounded reading measure on
2986 ultrawide terminals. `0` or absent keeps the full width; negative or
2987 non-integer values are rejected with a clear config error. Tool, diff,
2988 and status cells never inherit the cap (#5436).
2989 - Localization: README translations for Français, Deutsch, 繁體中文, हिन्दी,
2990 Türkçe, Italiano, Polski, العربية and Català join the existing nine
2991 (#5451); codewhale.net routes fr, de, ca, hi, tr, it, pl and ar (with
2992 `dir="rtl"` plumbing) as partial locales (#5453).
2993 - Docs: README Integrations section (incl. the DeepSeek Harness `dsh` plugin
2994 path, docs/INTEGRATIONS_DSH.md) localized across all READMEs; RFC keeping
2995 the deterministic-first auto-review hybrid (#5427); Claude Code parity
2996 reference for agents/workflows/plugins/skills
2997 (docs/design/CLAUDE_CODE_PARITY.md); config.example.toml / SUBAGENTS.md /
2998 TOOL_LIFECYCLE.md brought back in line with the code (#5447).
2999 - `dsh` integration: the Codewhale palette is applied through the bundle
3000 profile via dsh's documented `overrideTokens` (on by default;
3001 `codewhale integrations dsh update --skin false` turns it off), replacing
3002 the 0.9.8 exported-CSS skin that dsh's inline body variables overrode
3003 (docs/design/DSH_BUNDLE_SKIN.md, docs/INTEGRATIONS_DSH.md) (#5469).
3004 - `dsh` integration: an ambient ocean scene behind the DSH web UI — slow
3005 whale silhouettes, a school of `><>` glyph fish, bubbles — drawn on a
3006 canvas under a translucent veil of the Codewhale palette, plus an explicit
3007 responsive `WHALE BROTHERS / CODEWHALE × DEEPSEEK HARNESS` lockup; light
3008 and dark, ~30 fps capped, paused when hidden, a static frame under
3009 `prefers-reduced-motion`; on by default with the skin,
3010 `codewhale integrations dsh update --ocean false` turns it off (#5484).
3011 - Fleet: agent shadowing is visible — a roster-row badge, a Layers block in
3012 agent detail, and a `doctor` "Fleet roster layers" section (JSON
3013 `operate_fleet.roster.multi_layer`), in all 15 TUI locales. Layer collapse
3014 and `[fleet.profiles]` migration stay for 0.9.10 (#5098).
3015 - Sandbox: bwrap containers get the `--dev/--proc/--tmpfs` essentials plus
3016 configurable extra roots (`bwrap_ro_roots` / `bwrap_dev_roots`) so
3017 toolchains that live outside the workspace stay reachable read-only
3018 (#5410).
3019 - Tests: `crates/tui/tests/README.md` states the keyless assembled-journey
3020 rule and maps the Auto-Review guardian acceptance items to the engine
3021 journeys that exercise them (#5361).
3022 - OrcaRouter's default endpoint is classified as an aggregator billing
3023 surface, so pricing and session-cost reporting use the correct billing
3024 posture instead of treating it as a first-party provider (#5493).
3025 - Dependencies: ratatui 0.30.2, thiserror 2.0.20.
3026
3027 ### Removed
3028
3029 - `dsh` integration: the exported-CSS skin file and its "skin export" status
3030 line (superseded by the bundle-applied `overrideTokens` skin, #5469).
3031
3032 ### Contributors
3033
3034 - hexin (@h3c-hexin) — a concrete route/offering output limit outranks the
3035 8,192-token compatibility guess for an uncatalogued model (#5461, closes
3036 #5460); web tool results use the noisy soft limit (#5474); owned direct
3037 model casing resolves safely (#5475); and configured-skill prompts stay
3038 stable across ephemeral roots and operating systems (#5492, #5473).
3039 - Gabriel-Degret (@Gabriel-Degret) — configurable auto-router classifier
3040 timeout (#5494; first contribution).
3041 - @asto18089 — diagnosed the Z.ai `glm-5.2` casing collision and wrote the
3042 first provider-scoped fix in Pinvou/CodeWhale#14 (carried upstream in
3043 #5475).
3044 - Reports and reproductions that shaped this release: @hardy922 (context-
3045 window honesty, #5239), @redstar (bwrap extra roots, #5410), @all-lopezg
3046 (SSE UTF-8 garbling on DeepSeek Flash, #5374), @alitvak69 (unverified live
3047 pricing, #5241), and @wuisabel-gif (the macOS filtered-suite hang
3048 investigation on #5056).
3049
3050 ## [0.9.8] - 2026-08-16
3051
3052 Codewhale v0.9.8 ships the remaining assigned finish. Remaining web
3053 settings polish moves to v0.9.9. Prefab third-party templates that have
3054 a published OpenAI-compatible host ship here (#5350).
3055
3056 ### Fixed
3057
3058 - `sudo` (and `su`/setuid helpers) work again for wheel-group administrators
3059 who want Codewhale to be able to escalate: the Linux startup hardening's
3060 irreversible `PR_SET_NO_NEW_PRIVS` flag — inherited by every child process —
3061 is now skippable with `CODEWHALE_NO_NEW_PRIVS=0` (#5413). The flag stays on
3062 by default; the no-ptrace and no-core-dump measures are never skipped.
3063
3064 - Abort-class process deaths no longer poison the terminal (#5424). A
3065 stack overflow, allocation failure, or double panic skips the panic hook
3066 and every cleanup guard, which is how a v0.9.7 user's mid-turn exit left
3067 mouse capture leaking SGR sequences into their shell. An
3068 async-signal-safe handler now restores the terminal modes and appends a
3069 one-line cause marker to `~/.codewhale/crashes/last-fatal-signal.log`
3070 before re-raising, keeping the honest 128+signal wait status. A SIGKILL
3071 (OOM killer) remains uninterceptable by design.
3072
3073 ### Changed
3074
3075 - Prompt-cache prefix is pinned for the session. The tool loop no longer
3076 recomposes the system prompt from disk on every model step, so an agent
3077 writing a file no longer busts the provider KV prefix cache mid-turn. The
3078 system prompt and tool catalog are re-composed only on a declared header
3079 change (`/model`, mode, goal, session resume), which re-pins under a logged
3080 reason; an undeclared change is reported as drift and the original pin is
3081 kept instead of silently becoming the new baseline. Workspace, AGENTS.md,
3082 skills, memory, and goal drift now reaches the model as one bounded
3083 `<context_update>` user message at the next user turn — a history append,
3084 not a header rewrite. `/cache stats` shows the pin reason, the last-miss
3085 reason, the undeclared-drift count, and the context-update count. See
3086 [docs/CACHE.md](docs/CACHE.md).
3087
3088 - Plugin compatibility is now per-component. A reviewed, trusted, enabled
3089 bundle that mixes Skills or MCP with unsupported commands, agents, hooks,
3090 LSP, native, filesystem-roots, or lifecycle-mutation declarations keeps the
3091 supported adapters active and reports the rest as inactive (`full` /
3092 `partial` / `unsupported`). All-unsupported bundles still cannot be enabled.
3093 The capability hash is now v2 and binds this build's activation policy, so
3094 older v1 receipts and any later adapter-enablement change fail closed as
3095 needs-review. Skills and each MCP transport re-request their own capability
3096 at the consumption boundary.
3097
3098 ### Added
3099
3100 - Opt-in multiline composer mode (`composer_multiline_mode = true`) makes
3101 Enter insert a newline and Shift+Enter send. Alt+Enter, Ctrl+J, and supported
3102 Ctrl+Enter/Cmd+Enter behavior stays unchanged (#5345, @AiurArtanis).
3103
3104 - `/plugin marketplace add|list|show|remove|install` completes the
3105 federated marketplace journey (#5311). `add` reads one LOCAL catalog
3106 document in the real published schemas (Kimi, Claude, Codex, or
3107 Codewhale native) — no network, regular files only — and persists it
3108 beside the plugin state with the same hardened, fail-closed store.
3109 `list`/`show` render every candidate with per-entry diagnostics,
3110 display-only tiers, and honest install plans that say when Codewhale
3111 cannot fetch a source; `install` routes through the existing reviewed
3112 installer, so installed bundles still enter disabled and untrusted.
3113 Foreign auto-install policy (Codex `INSTALLED_BY_DEFAULT`) is visibly
3114 ignored; nothing is auto-installed, auto-trusted, or granted vendor
3115 trust.
3116
3117 - `/rc` attach now includes an observed `owner/name` git remote when the
3118 folder has a GitHub, CNB, or Gitee origin, so CWC can label the paired
3119 session. Paths stay off the wire. Reconnect after both this client and
3120 CWC #202 land to backfill existing empty rows.
3121
3122 - The local Runtime web client keeps the thread rail clipped so **New
3123 thread** cannot paint over the session fact chips. Chips wrap instead
3124 of sliding under the rail.
3125
3126 - Z.ai `GLM-5.3` is live on the Coding Plan and is now the default direct
3127 Z.ai model: `DEFAULT_ZAI_MODEL` resolves to `GLM-5.3` in both
3128 `codewhale-tui` and `codewhale-config`, and it is the first `/model` row
3129 after `/provider zai`. Explicit `GLM-5.2` selections (`model = "GLM-5.2"`
3130 and its `glm-5.2` aliases) keep their own id — only the default moved.
3131 Limits and reasoning options still inherit from `GLM-5.2` until Z.ai
3132 publishes distinct 5.3 numbers. No USD price is claimed. A live call
3133 can still 429 with entitlement code 1311 on accounts that are not
3134 provisioned for 5.3.
3135
3136 - The TUI transcript renders Markdown blockquotes (`>` lines) with a quote
3137 rail — nested quotes, inline bold/code/links, wrapped continuation rows, and
3138 selection copy that keeps the quote text and skips the rail chrome.
3139
3140 - Sub-agent details show the resolved model, fleet role, and type. Labels
3141 use the session/role name instead of a generic Agent N (#5371, #5287).
3142
3143 - Documented catalogue output ceilings (including DeepSeek V4's 384K maximum)
3144 remain authoritative bounds, while ordinary requests start at a safe 64K
3145 cap and explicit overrides can raise it within the resolved route window. A
3146 clean output-limit stop continues the turn instead of killing it (#5373,
3147 #5516, #5518). Thanks @sfdzhmr and @hxfhd for the route evidence.
3148
3149 - Ollama Cloud is a first-class hosted provider (`/provider ollama-cloud`)
3150 on the official OpenAI-compatible `https://ollama.com/v1` route. Local
3151 Ollama stays keyless. The exact released `ollama` + Cloud URL tuple keeps
3152 a bounded compatibility path across saved sessions, Fleet, and nested
3153 subagents; neighboring remotes stay custom and fail closed against
3154 inherited official credentials.
3155
3156 - Homebrew ships a `codewhale` formula. `brew tap Hmbown/deepseek-tui &&
3157 brew install codewhale` is the install path; `brew upgrade codewhale`
3158 updates it. The legacy `deepseek-tui` formula remains a deprecated alias
3159 for one overlap release.
3160
3161 - `/title [name|off]` sets a per-session tab/window title, shown as
3162 `[title] …` in front of the terminal window title (`Codewhale` /
3163 `reasoning…` / `using tool…` / `done`). The `title` config key supplies
3164 the default (`/config title … --save` persists it); multi-window
3165 workflows can tell parallel sessions apart at a glance. `/title` is
3166 independent of `/rename`, which keeps naming the session in the picker
3167 and composer. Control, bidi, and zero-width format characters are
3168 stripped from both the saved session name and the window title, so the
3169 picker, the Runtime API, `codewhale sessions`, and the OSC 0 tab title
3170 all carry the same escape-free text (#5419, #5430).
3171 - Eden AI is a named OpenAI-compatible Chat Completions provider (`edenai`,
3172 aliases `eden-ai` / `eden_ai`) with `EDENAI_API_KEY`, global and EU base-URL
3173 overrides, a live provider-scoped model catalog, and
3174 `deepseek/deepseek-v4-pro` as the verified default. Generic reasoning fields
3175 stay omitted because Eden AI routes multiple upstream model families
3176 (#5422, Kai Nacke).
3177 - Children (sub-agents and Fleet workers) inherit the session's permission
3178 posture faithfully: Auto-Review's deterministic floor and model guardian
3179 decide a worker's held calls (fail closed when unavailable, never a
3180 prompt); under Ask a held call is raised in the parent's approval UI and
3181 the worker waits visibly; Full Access still fails closed on the safety
3182 floor. Each prompt-less decision is a one-line note in that worker's
3183 transcript (focus mode) and an audit-log record.
3184 - Worker role defaults keep what the role does not intend to withhold:
3185 every built-in role keeps network reads; `planner` may run read-only
3186 shell probes; `custom` inherits the parent's write/network/shell posture
3187 and is narrowed only by its explicit tool list or the spawning call.
3188 Read-only roles (`scout`, `reviewer`, `planner`, `verifier`,
3189 `consultant`) still never write the workspace. The focused worker's
3190 header states its effective posture from the runtime snapshot.
3191 - `/workflow status`, `/workflow cancel [run_id]`, `/workflow settings`, and
3192 `/workflow help` are answered by Codewhale itself from the run journal and
3193 live run state — no model turn — and `/workflow run <path>` launches a
3194 checked-in workflow as-is. `/config workflow` and `/config goal` explain
3195 the effective tables. The workflow tool now honors the session `[workflow]`
3196 table (`automatic`, `auto_start_read_only`, `require_approval_for_writes`,
3197 limits) instead of product defaults.
3198 - Goal mode enters as readily as DeepSeek Harness: the agent may create the
3199 session goal when a direct request describes a verifiable multi-turn end
3200 state, and Codewhale shows a one-line `Goal set` receipt with how to pause
3201 or clear it. Bare `/goal` shows plain progress (and how to continue when no
3202 turn is running), prints usage on an empty session instead of asking the
3203 model, and `/goal help|status` are reserved words.
3204
3205 - Whale Teams in the terminal: the six Signal Cut whale identities (Scout,
3206 Patch, Harbor, Echo, Keel, Lantern) appear as species badges on `/fleet`
3207 roster rows and worker rows, with an identity portrait in the roster detail
3208 pane and a six-state word (Resting, Thinking, Working, Waiting for you,
3209 Blocked, Offline) derived only from the child's real runtime status. Colors
3210 come from the theme tokens, every glyph has an ASCII fallback, and the
3211 working wake animates only under full motion. See
3212 `docs/design/WHALE_TEAMS_TUI.md`.
3213 - A session metrics strip on the phase row (`4 turns · 108 steps │ LLM
3214 11m46s · Tool call 1m52s │ TTFT avg 1.5s · 120 tok/s │ Cache hit 99% │
3215 Input 9.3M`), on by default as the `session_metrics` footer item
3216 (`/statusline`, `[tui].status_items`). Every value comes from engine
3217 receipts — turn starts, per-model-call usage with stream time,
3218 time-to-first-token and whole-call time, tool start/complete edges, and
3219 provider-reported cache and input tokens. Cells without evidence are
3220 omitted, never estimated. `/status` prints the untrimmed line; the phase
3221 row sheds its lowest-value groups to fit the columns it actually has.
3222 - Auto-Review decisions nobody was prompted for are now visible in the
3223 transcript as one-line notes: model-guardian allow/deny verdicts with
3224 their risk tier and stated reason, guardian failures (denied, fail
3225 closed), deterministic policy blocks, and holds Auto-Review denied
3226 without pausing. The audit log keeps the full record. `/permissions`
3227 ends with the active posture, what it decides on its own versus never,
3228 and the audit-log path. The footer's `Esc to interrupt` hint is
3229 localized. See `docs/design/AUTO_MODE_PARITY.md` for the Claude Code /
3230 Kimi Code parity ledger and follow-ups.
3231 - `codewhale integrations dsh status|plan|connect|update|launch|disable|enable|remove`
3232 connects an existing official DeepSeek Harness (`dsh` 0.1.0-rc.6, verified)
3233 through Codewhale using only its documented seams: a `--patch` overlay that
3234 pins the exact Codewhale provider/model/endpoint identity (native
3235 `deepseek-official` route, or a hand-declared `openai-completions` route
3236 named `codewhale-<provider>` for OpenAI-compatible providers), the
3237 Codewhale permission posture exported as `DSH_PERMISSION_MODE`, and an
3238 append-only receipt. Codewhale writes only under
3239 `$CODEWHALE_HOME/integrations/dsh/`, never copies API keys or edits DSH
3240 files, never broadens permissions (`--allow-full-access` only mirrors an
3241 existing Codewhale full-access posture), and reports not-installed /
3242 offline / incompatible / detected / connected / stale-config /
3243 stale-version / disabled honestly. Anthropic Messages and OpenAI Responses
3244 routes are refused as not carriable. The documented DSH plugin path is an
3245 explicit opt-in: `install-bundle` materializes a Codewhale bundle package
3246 (`codewhale-dsh-bundle`, MIT notice retained) and installs it with
3247 `dsh plugin --profile codewhale add <path>` into a dedicated `codewhale`
3248 profile (pnpm required, reported truthfully when missing; `web`/`headless`
3249 untouched), so `dsh --profile codewhale` alone carries the identity;
3250 `update` regenerates the bundle patch and `remove-bundle` reverses it,
3251 leaving the DSH-owned profile directory in place. `/setup tools` and `codewhale doctor`
3252 show the read-only detection state; `doctor` also lists the DSH read-only
3253 credential consent alongside Codex and Grok. The optional `--skin` export
3254 writes a Codewhale token stylesheet generated from the TUI palette
3255 (Blue Stage dark/light, ombre water column, mode/permission/state colors,
3256 reduced-motion fallbacks); DSH exposes no custom-theme API, so the sheet is
3257 labeled an unsupported overlay and is never injected. See
3258 `docs/INTEGRATIONS_DSH.md`.
3259
3260 ### Fixed
3261
3262 - Selecting the `google` provider kind resolved to the `antigravity`
3263 TUI identity (and vice versa): the agy provider entry was inserted at
3264 different positions in the config-level enum and the TUI's
3265 discriminant-indexed lookup table. The table now matches the enum, so
3266 provider pickers, sorted display, and kind round-trips are correct.
3267
3268 - The provider picker's key-entry stage accepted typed input and pastes
3269 for OAuth-only providers after `antigravity` declared OAuth
3270 acquisition; those gates now key off the OAuth acquisition class
3271 instead of a hard-coded provider identity.
3272
3273 - The webhook hook sink no longer panics when its HTTP client fails to
3274 build; it falls back to a default client (#5381, EvanProgramming).
3275
3276 - Session-index JSONL writes are serialized behind a process-wide mutex
3277 so concurrent state stores cannot drop an append during compaction
3278 (#5382, EvanProgramming; complements the cross-process file lock).
3279
3280 - A billed `max_tokens` stop followed by a transport error fails the turn
3281 instead of continuing into a second request. A clean output-limit stop
3282 still continues. Mid-size context windows keep the ordinary 65K internal
3283 reservation so compaction does not collapse to the 1K headroom floor
3284 when the catalogue documents a matching output ceiling.
3285
3286 - Thinking cycle, `/effort`, and Settings now walk each model's real ladder
3287 instead of the DeepSeek off/high/max shortcut. Grok 4.6 is
3288 auto/low/medium/high/xhigh (cannot disable); Grok 4.5 is
3289 auto/low/medium/high; first-party DeepSeek keeps a documented `low` tier.
3290 `/effort` persists and receipts through the same path as Ctrl+T.
3291
3292 - Google Gemini is its own backend (`/provider google`) on the official
3293 OpenAI-compatible route with thought-signature capture/replay and
3294 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) is
3295 a separate provider: consent-gated read-only import of the official
3296 CLI's login, then a text-only cloud-code stream
3297 (`/v1internal:streamGenerateContent`). Tools, images, and unknown SSE
3298 shapes fail closed. Gemini 3.7 Flash is not advertised until a live
3299 turn succeeds on this wire. The website 44-count still excludes
3300 Antigravity.
3301
3302 - DeepSeek Flash SSE on macOS no longer turns mid-character HTTP/2
3303 flushes into U+FFFD replacement characters (#5374). Invalid UTF-8
3304 fails the line instead of using lossy decode.
3305
3306 - `[workshop] read_result_max_bytes` and `tool_result_max_bytes` raise
3307 the model-visible read/tool-result floor; they never lower the
3308 compile-time defaults and cap at 2MiB (#5367).
3309
3310 - Fireworks and OpenCode Zen DeepSeek V4 Flash/Pro keep a bundled
3311 family rate when the live control plane is down, so session cost is
3312 not stuck on `unverified_live_pricing` (#5241). `kimi-k3` stays
3313 unpriced until a published rate exists.
3314
3315 - Provider setup ships a typed beginner template catalog (#5350). OpenCode
3316 Zen/Go stay first-class key-only rows with their documented hosts and
3317 curated models. SenseNova fills a named OpenAI-compatible table on the
3318 published `https://token.sensenova.cn/v1` host (`S` or `/provider setup
3319 sensenova`). Agnes is listed as unpublished because this repository has
3320 no published URL. `/provider` `P` and Settings → beginner templates open
3321 the list; `T` tests `/models` and refreshes status without treating 2xx
3322 as model-ready. `/model` names a failed Models.dev refresh as
3323 `refresh failed; catalog available` instead of `cache failed`.
3324
3325 - Privileged release workflows no longer restore rust-cache, sccache,
3326 or npm caches after checking out a caller-supplied SHA (CodeQL
3327 cache-poisoning #88–#106). Catalog drift no longer prints raw
3328 bundled/upstream blobs (#107).
3329
3330 - Cancelling a turn now cancels its foreground child agents with it.
3331
3332 - Empty compaction no longer wipes conversation history.
3333
3334 - Wide terminals and tmux panes fill the full available width again for the
3335 transcript and composer (#5322). The brief v0.9 session-shell side gutter
3336 is gone so expanding a pane rematerializes layout the same way shrinking
3337 does.
3338
3339 - The agent tool schema rejects empty calls.
3340
3341 - The local web client keeps recovered stream gaps closed, user questions
3342 answerable, manual bootstrap access intact, and streamed prose quiet for
3343 assistive tech.
3344
3345 - Website zh-Hans copy now says 宪章, matching the TUI pack (#5397,
3346 Lstarsky0).
3347
3348 - Public website provider facts include Google Gemini and Ollama Cloud
3349 (44 runnable routes). Antigravity stays credential-plane-only.
3350 Harvested from #5398 (Lstarsky0) with that correction.
3351
3352 - The website models page carries a truthful read-only settings preview
3353 built from repository facts; it never implies the site can change local
3354 configuration (#5370, #5411, mvanhorn).
3355
3356 - The canonical `ultra` reasoning effort now maps to each provider's
3357 maximum tier alongside the legacy `ultracode` alias, instead of being
3358 silently dropped (#5303, #5409, buiducnhat).
3359
3360 - Session titles truncate by character count, not byte offset, so
3361 multi-byte titles (CJK, emoji) cut at the intended width and word
3362 boundary instead of past the limit (#5415).
3363 - Wide terminals and tmux panes fill the full available width again for the
3364 transcript and composer (#5322). The brief v0.9 session-shell side gutter is
3365 gone so expanding a pane rematerializes layout the same way shrinking does.
3366 - The background verifier test drives the current libtest executable
3367 instead of the rustup `rustc` shim, so the TUI suite no longer depends
3368 on `$HOME` or holds the process-wide test environment lock across an
3369 async wait (#5056, #5423, Isabel Wu).
3370
3371 ### Removed
3372
3373 - The source-structure budget ratchet (CI step, checker, baseline JSON).
3374 It measured line counts, not quality: every legitimate feature required
3375 a hand-edited ceiling and the accompanying "review" was self-review, so
3376 it bought ceremony, not protection. Behavior-measuring gates (dead-code,
3377 runtime-contract, persistence-backlog) stay enforced.
3378 - DeepSeek can reuse a key already stored by official DeepSeek Harness
3379 (`dsh`) after
3380 `codewhale auth external-consent --provider deepseek --mode read-only`.
3381 Codewhale reads only `DEEPSEEK_API_KEY` from the exact granted
3382 `$DSH_HOME/.credentials.yaml` and never writes or refreshes that file.
3383 - The TUI markdown parser now honors CommonMark fence-length rules: a ````
3384 opener is not closed by a shorter ``` line, so `>` content inside a longer
3385 fence stays literal code instead of escaping into a quote.
3386 - Sub-agents finalize when the parent session id changes, so a closed
3387 session cannot block new children as a live owner (#5372).
3388 - Child spawn-route receipts stay live and usage is deduped by response
3389 (#5366).
3390 - Doctor keeps persisted setup readiness across first-run / update
3391 checkpoints (#5340).
3392 - Approval default selection is applied and explained; agents are told
3393 when approvals are disabled (#5293).
3394 - A `/models` 2xx probe is a connection check, not model readiness.
3395 - Site layout uses one container, the ticker no longer implies false
3396 provider readiness, and install links stay in the active locale.
3397
3398 ### Contributors
3399
3400 - EvanProgramming (@EvanProgramming) — webhook client panic fallback
3401 (#5381); session-index JSONL mutex (#5382).
3402 - Lstarsky0 (@Lstarsky0) — session peek hides internal runtime events
3403 (#5376); thinking-ladder test re-pin (#5378); provider-count follow-ups
3404 (#5383/#5384); macOS agy fixture canonicalization (#5392); zh-Hans 宪章
3405 terminology (#5397); regenerated website facts harvested and corrected
3406 from #5398.
3407 - Matt Van Horn (@mvanhorn) — read-only models settings preview on the
3408 website (#5411, fixes #5370).
3409 - Nhat Bui (@buiducnhat) — canonical `ultra` reasoning effort mapped across
3410 provider effort tables (#5409); session titles truncated by character
3411 count, not byte offset (#5415).
3412 - Sh1Zuku (@SparkofSpike) — `/title` and the session name in the terminal
3413 tab/window title, plus the mid-turn title deadlock fix (#5419).
3414 - Kai Nacke (@redstar) — Eden AI provider registration, aliases,
3415 `EDENAI_API_KEY`, and the global/EU endpoints (#5422).
3416 - Isabel Wu (@wuisabel-gif) — background verifier test isolated from
3417 rustup and `$HOME` (#5423, slice of #5056).
3418
3419 ## [0.9.7] - 2026-08-12
3420
3421 Codewhale v0.9.7 keeps the catalog ordinary. Grok 4.6 lands as a normal catalog
3422 row instead of a provider-shaped pile of special cases, OrcaRouter joins as a
3423 named provider, and a panic-safety advisory in `lru` is cleared by lifting the
3424 pin that caused it rather than living around it.
3425
3426 ### Added
3427
3428 - Grok 4.6 is the direct xAI default, with the `grok` alias moving onto it and
3429 `grok-4.5` still explicitly selectable. Its 500K context, text/image input,
3430 tool and structured-output support, `low`/`medium`/`high`/`xhigh` reasoning
3431 efforts (default `high`), and server-side web search all come from the
3432 Models.dev-shaped catalog rather than model-specific code. `reasoning_effort`
3433 reaches the wire only on the exact first-party `https://api.x.ai/v1` route,
3434 and the usage-aware 200K-token pricing boundary is scoped to direct xAI so
3435 aggregator routes reusing the model slug cannot inherit xAI billing.
3436 - OrcaRouter is a first-class named provider: `ORCAROUTER_API_KEY`, default base
3437 URL `https://api.orcarouter.ai/v1`, `deepseek/deepseek-v4-pro` default,
3438 `orcarouter/auto` routing, CLI `--provider` selector, and TUI picker entries
3439 (#5321).
3440
3441 ### Changed
3442
3443 - Reasoning-effort normalization and the model picker read a model's published
3444 `reasoning_options` list from the catalog instead of collapsing every route to
3445 the historic Low/Medium ladder. Any catalog row that publishes an effort list
3446 keeps its own vocabulary.
3447 - Docs record DeepSeek's live `DeepSeek-V4-Pro-0813` backend label while the
3448 callable API ID stays `deepseek-v4-pro`. No aliases are remapped and no
3449 `deepseek-v4-pro[1m]` selector is sent.
3450
3451 ### Fixed
3452
3453 - Auto-Review once again executes proven read/build/test shell commands and
3454 bounded workspace writes without opening an approval modal. Explicit policy
3455 blocks, unknown tools, publish operations, secret actions, MCP mutations,
3456 and shell commands requiring approval still fail closed (#5323; reported by
3457 USTHzhanglu and root-caused by Lstarsky0).
3458 - Copying a user or assistant message takes its canonical content instead of
3459 reserialized transcript lines, keeping role glyphs, continuation rails, and
3460 visual wrapping out of the clipboard while preserving authored Unicode,
3461 Markdown, and hard line breaks. Tool and Thinking cells stay on the existing
3462 full-transcript path (#5319).
3463 - `load_session` no longer runs crash recovery on every read. Snapshot reads go
3464 through a side-effect-free `load_session_snapshot` and recovery is explicit
3465 via `recover_session_for_resume`, so an embedding host inspecting a durable
3466 session while a tool is still running no longer gets a spurious crash repair
3467 (#5320).
3468
3469 ### Security
3470
3471 - `lru` moves to 0.18 to clear RUSTSEC-2026-0253, where `LruCache::pop()` was
3472 not panic-safe and could leave dangling list pointers. The `ratatui-core`
3473 `=0.1.0` pin that transitively forced `lru` ^0.16 is lifted, so
3474 `ColorCompatBackend` now answers `get_cursor_position()` from tracked cursor
3475 state — the upstream-recommended workaround for the startup CPR race
3476 (ratatui/ratatui#2483, ratatui/ratatui#2640) that the pin originally worked
3477 around. `ratatui` itself stays pinned at `=0.30.0`, so the API surface is
3478 unchanged.
3479
3480 ### Known issues
3481
3482 - The integration test
3483 `exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero`
3484 is a confirmed flake under parallel load ("service pid file never appeared").
3485 It passes in isolation and is unrelated to any v0.9.7 change.
3486
3487 ### Contributors
3488
3489 - XhesicaFrost (@XhesicaFrost) — canonical message copy (#5319).
3490 - h3c-hexin (@h3c-hexin) — session snapshot and crash-recovery split (#5320).
3491 - XiaoHuo888-hue (@XiaoHuo888-hue) — OrcaRouter provider registration (#5321).
3492 - USTHzhanglu (@USTHzhanglu) — Auto-Review regression report and Windows
3493 evidence (#5323).
3494 - Lstarsky0 (@Lstarsky0) — Auto-Review regression root-cause analysis (#5323).
3495
3496 ## [0.9.6] - 2026-08-11
3497
3498 Codewhale v0.9.6 is a subtractive release: fewer runtime guards, one stable
3499 prompt, truthful provider endings, and a smaller compaction path that preserves
3500 the provider cache. The changes were grounded by matched Terminal-Bench 2.1
3501 runs against Pi 0.8.41 and by dogfooding repeated manual compaction.
3502
3503 ### Added
3504
3505 - `web_search` defaults to Firecrawl Cloud without an API key; keyless requests
3506 are headerless and quota-bounded, while an optional user key raises limits.
3507 - Green web builds on `main` now emit an actionable manual-deploy reminder, so
3508 site changes cannot quietly appear shipped while Cloudflare still serves an
3509 older revision.
3510 - Mistral AI is a first-class provider route, including Codestral models,
3511 first-party reasoning support, authentication, picker entries, and aliases.
3512 - Headless `Bash` can transfer explicitly requested persistent Unix services
3513 out of an exec run, with ownership and cleanup receipts.
3514 - `/remote-env` opens hosted Work from the current GitHub or CNB branch tip and
3515 states exactly which unpushed, dirty, ignored, secret, and session state stays
3516 local.
3517 - Linux ARM64 release and nightly assets are static musl builds with native
3518 launch checks.
3519 - Maintainers can report observed daily active installs from the same anonymous,
3520 aggregate telemetry dataset; no additional client data is collected.
3521 - Fleet-dispatched members under a read-only evidence (no-network) ceiling now
3522 keep the `Web` tool's read-only `search` and `fetch` actions — parity with an
3523 ordinary scout — while every reaching surface (`web.run`, `fetch_url`,
3524 `github`, MCP) stays denied and the sentinel-backed capability envelope
3525 remains the fail-closed backstop.
3526 - `/fleet setup` can show an optional, deterministic, unratified role-to-model
3527 advisory built only from configured ready routes. Accept, edit, and reject
3528 all remain inside the existing human-reviewed profile save boundary; the
3529 advisory never launches a Fleet or writes a second configuration.
3530 - `/update` checks for a newer Codewhale release and installs it from inside
3531 the TUI, while `tui_help` gives agents the same command and key map users see.
3532 - Markdown file paths render as OSC 8 links where the terminal supports them,
3533 and every agent row can open that agent's transcript directly.
3534 - ACP editor sessions can execute multi-round file, search, Git, patch, and
3535 explicitly enabled shell tool calls through the shared Runtime registry.
3536 Shell access requires both the client's terminal capability and Codewhale's
3537 headless shell opt-in, and cancellation stops an in-flight tool before the
3538 turn returns (#5225 by @rafaelcavalheri).
3539 - Lowercase `read` returns bounded typed PNG, JPEG, GIF, and WebP results to
3540 image-capable Chat, Responses, Anthropic, and ACP routes. Text-only routes
3541 receive an explicit omission receipt; image bytes never spill into ordinary
3542 transcript, export, compaction, or relay text.
3543
3544 ### Changed
3545
3546 - Anonymous usage counting is on by default for fresh installs and disclosed in
3547 a native first-run Codewhale modal with an immediate opt-out. Prior declines
3548 remain off. Codewhale does not collect conversations, code, prompts, files,
3549 repo or branch names, credentials, model content, or per-turn activity
3550 timelines.
3551 - Wide terminals use a responsive, full-screen ocean canvas with modest
3552 gutters: prose keeps a readable measure while tools, diffs, work surfaces,
3553 the composer, and status chrome can use the available width. Turn and major
3554 activity seams breathe without padding every call inside a tool group.
3555 - Root CLI help describes product actions directly instead of exposing internal
3556 TUI/runtime layers.
3557 - `Bash action="wait"` now blocks by default when a wait is requested; callers
3558 can still ask for a nonblocking snapshot, and persistent service ownership
3559 remains explicit.
3560 - Compaction is one cache-stable summary request followed by one committed
3561 replacement summary and a bounded recent-message tail. Older saved sessions
3562 still restore.
3563 - Ask, Work, Auto-Review, and Full Access share one stable base prompt. Modes
3564 continue to differ through permissions and the live tool catalog; the former
3565 Act label is now Work throughout the product and shipped locales.
3566 - Full Access now auto-approves non-bypassable tools consistently, and the
3567 default choice shown on ordinary approval cards is configurable.
3568 - Model, context-window, dispatch-name, and nested-agent spawn receipts report
3569 the route and limits actually used rather than silently substituting a
3570 guessed identity.
3571 - Child-agent launches mint one immutable route receipt before admission and
3572 preserve it through status, interruption, completion, resume, Work Graph,
3573 and ledger projections, so provider/model attribution cannot drift (#5305).
3574 - Goal runs no longer stop because of internal continuation, repeated-gap, or
3575 unanswered-question guards. Explicit user limits and terminal goal states
3576 remain authoritative.
3577 - Account-owned `/rc` remote control now keeps exclusive ownership and a
3578 crash-recoverable delivery journal until the server acknowledges terminal,
3579 approval, failure, and snapshot state.
3580 - `todo_write` is an optional progress surface rather than required model
3581 ceremony.
3582 - New turns use one small, stable toolbox: `read`, `write`, `edit`, `bash`,
3583 `agent`, `todo_write`, and `tool_search`. The optional progress tool stays
3584 visible as familiar working memory; specialized native, Web, MCP, plugin,
3585 memory, task, and verification tools are policy-filtered and searchable;
3586 activated schemas stay in a bounded per-conversation cache. Every sub-agent
3587 keeps its own search and cache, including policy-allowed Web research, while
3588 forked context and parent activations remain warm starts rather than allowlists.
3589 - The direct file and shell schemas follow Pi's deliberately small contract:
3590 bounded complete-line reads, hash-free writes, unambiguous multi-edit with
3591 BOM/CRLF preservation and conservative fuzzy matching, and one foreground
3592 `bash` command with a bounded chronological output tail. Modes change
3593 execution authority, not those primitive names.
3594 - Codewhale no longer re-states the To-do list to the model. The model learns
3595 what is on the list from the tool result its own `todo_write` call returned,
3596 which is ordinary conversation history — the same way Pi's To-do works. The
3597 transient `<codewhale:work_state>` block that used to ride the tail of every
3598 parent turn-loop and sub-agent step request is gone, along with the stable
3599 system prefix being disturbed by list changes. A snapshot is still shown once,
3600 where a person asked for it: the `<codewhale:fork_state>` block a newly forked
3601 sub-agent is handed, `/relay` handoff instructions, and the agent card. The
3602 complete To-do stays visible in the UI. A structural test asserts real
3603 outbound provider request bodies do not carry the list.
3604 - Scout and Reviewer name the read-only investigator roles. Both expose exactly
3605 one shell entry point — canonical lowercase `bash`, bounded by the strict
3606 read-only classifier — and the legacy `Bash` alias stays denied in the catalog
3607 and at dispatch. Previously a case-insensitive name match let a call spelled
3608 `Bash` execute through that carve-out, returning raw shell to a read-only role.
3609
3610 ### Fixed
3611
3612 - Sending more context while a lowercase `bash` command is running now moves
3613 the command to `/jobs` and returns a successful running receipt instead of
3614 falsely reporting `Command exited with code -1`; the process keeps running
3615 and its completion still arrives through the normal runtime event.
3616
3617 - First-run usage disclosure now opens as a native Codewhale modal instead of a
3618 shell questionnaire before application startup. Telemetry remains unarmed
3619 until the native choice is made, and an in-memory Disable choice governs the
3620 current session even when its preference cannot be saved.
3621 - `/compact` completion, failure, queued, duplicate, and mailbox outcomes are
3622 durable transcript receipts instead of short-lived toasts. A stray terminal
3623 event can no longer leave every later compaction stuck as already running.
3624 - Compaction now follows Codex's simple transcript shape: recent user context
3625 followed by one ordinary history checkpoint. It never appends the summary,
3626 the To-do list, or volatile shell/worker state to the standing system prompt;
3627 reloads migrate the persisted carrier back into exactly one history item.
3628 - Automatic compaction uses a percentage of the real context window, clamped to
3629 the route's spendable ceiling. Pressure comes from the current parent-route
3630 prompt, not cumulative billing or child-model usage.
3631 - Compaction, review, verify, routing, setup, Fleet, MCP, RLM, vision,
3632 translation, and sub-agent calls inherit the resolved route's normal output,
3633 sampling, and reasoning policy. Small internal-task token caps no longer
3634 truncate thinking routes or special-case individual providers.
3635 - Incomplete provider responses fail truthfully across ordinary turns and every
3636 internal model consumer. Partial text stays interrupted, pending tool calls do
3637 not execute, and billed usage is retained.
3638 - Transport-only `(reasoning omitted)` placeholders no longer enter new
3639 transcripts and are filtered from restored sessions. Reasoning expand/collapse
3640 actions stay attached to the exact rendered cell, including after replacement,
3641 restore, filtering, and resize (#5291).
3642 - Step-budget exhaustion is a typed failure and cannot release a pending
3643 persistent service. Cancellation after terminal usage still charges the turn.
3644 - Deferred tools now preserve a completed result when a provider reuses its
3645 tool-call ID on the retry turn, preventing successful plugin calls from
3646 entering a repeated execution loop.
3647 - Website setup, provider, diagnostics, Fleet, and single-runtime claims now
3648 match the source candidate.
3649 - Opening the sub-agent register no longer hides the to-do list: the Agents
3650 panel shows the full register and the durable checklist together, and the
3651 register header is a two-way door that returns to Tasks on a second click.
3652 - The ⌥V / Alt+V details chord opens the selected work-surface row's own
3653 inspector instead of the transcript's nearest tool cell, so a selected
3654 to-do row shows its own content rather than the latest reasoning.
3655 - The first-run usage disclosure now asks a clear question — "Help improve
3656 Codewhale?" — with unambiguous "Yes, keep anonymous counts" / "No, turn off
3657 tracking" choices in every shipped locale, and states the persistent opt-out
3658 command. Consent semantics are unchanged: telemetry stays unarmed until a
3659 choice is made.
3660 - macOS screencapture screenshots referenced in a message are copied to a
3661 stable attachments directory the moment the message is received, and the
3662 reference is rewritten to the stable path, so the image still exists when
3663 the agent reads it. Only files under a screencapture "Temporary Items"
3664 directory are touched; copies are idempotent and a failed copy keeps the
3665 original reference.
3666 - Manual `/compact` during an active turn now queues even when the engine's
3667 bounded op mailbox is saturated. The request defers client-side, retries as
3668 mailbox slots free, and cannot latch as already running after it settles.
3669 - Interactive `/load`, startup `--resume`, and `/resume` picker paths preserve
3670 the persisted provider, endpoint, and model identity; picker resume also
3671 leaves a durable transcript receipt.
3672 - Relative `mcp_config_path` values no longer depend on the launch directory or
3673 silently load an empty server pool: Codewhale warns and falls back to the
3674 user-global MCP configuration. Explicit absolute paths remain authoritative.
3675 - Alibaba Model Studio `qwen3.8-max` and `qwen3.8-max-preview` still stream
3676 their current reasoning, but no longer replay historical `reasoning_content`
3677 that those routes do not accept. Historical reasoning replay is now gated by
3678 the exact provider/API/model contract, so unknown `*-thinking` lookalikes
3679 fail closed while documented Qwen, Kimi, DeepSeek, Mistral, Anthropic, and
3680 Responses continuity rules remain intact.
3681 - Compatibility File/patch calls retain optional content-hash guards when a
3682 caller supplies them. The new direct `write` and `edit` schemas do not expose
3683 hash or prior-read ceremony.
3684 - Shell previews hold back incomplete UTF-8 sequences instead of emitting
3685 replacement characters, and compaction receipts report token deltas.
3686 - Nested agents may narrow but can never widen their inherited depth budget
3687 (#5317 by @ousamabenyounes).
3688 - Container publication now assembles AMD64 and ARM64 images in parallel on
3689 native runners from the already-verified static release binaries, then
3690 publishes and checks one multi-architecture manifest. It no longer rebuilds
3691 both targets through the single long-running QEMU job that lost its runner.
3692
3693 - Google Gemini is its own backend (`/provider google`) on the official
3694 OpenAI-compatible route with thought-signature capture/replay and
3695 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
3696 as a separate credential-plane provider: consent-gated read-only import
3697 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
3698 precedence; requests fail closed until the cloud-code wire protocol is
3699 implemented.
3700
3701 ### Removed
3702
3703 - The no-progress guard, repeated-read guard, and injected tool-error strategy
3704 coaching. Productive polling, repeated inspection, and model-owned recovery
3705 are no longer interrupted by runtime heuristics.
3706 - Never-wired decision-card, keybinding, hover, shell-execution, engine-op, and
3707 release-script paths were deleted so the supported runtime has one route for
3708 each behavior.
3709
3710 ### Contributors
3711
3712 - Xavier Pestel (@xavierpestel-ai) — Mistral AI provider route (#5295).
3713 - Ben Younes (@ousamabenyounes) — inherited nested-agent depth cap (#5317).
3714 - Rafael Cavalheri (@rafaelcavalheri) — ACP agentic tool turns (#5225).
3715
3716 ## [0.9.5] - 2026-08-08
3717
3718 Codewhale v0.9.5 consolidates the terminal application into one compiled
3719 runtime while preserving the familiar `codewhale` and `codew` commands. It
3720 also expands the managed Runtime API, makes session and Fleet work easier to
3721 inspect and resume, and removes the hidden local continuation backstop that
3722 could end productive work without a final assistant response.
3723
3724 ### Added
3725
3726 - **`model = "auto"` for prompt-based tier selection**: When set, the
3727 dispatcher analyses the user's prompt before delegating to the TUI and
3728 selects `deepseek-v4-pro` for complex tasks or `deepseek-v4-flash` for simple
3729 tasks (PR #5257).
3730 - Runtime API controls for persistent goals, bounded memory inspection, MCP
3731 server and skill lifecycle management, and durable Fleet receipt evidence.
3732 - Append-only session-tree history with `/tree`, `/branch`, `/fork`, and
3733 `/resume`, plus `/rc` remote control and managed login.
3734 - A unified Fleet roster for built-in dispatch postures and a pinned indicator
3735 that keeps active background work visible above the composer.
3736 - Incremental MCP registry refreshes that return the local snapshot immediately
3737 and update it in the background.
3738 - Scout and Reviewer agents can use a bounded direct-command evidence shell for
3739 read-only workspace, Git, and GitHub inspection, and can keep private working
3740 notes in their own To-do while the durable transcript retains their evidence.
3741
3742 ### Changed
3743
3744 - `codewhale-cli` now contains the terminal runtime directly. Release installers
3745 expose byte-identical `codewhale` and `codew` commands without a separate TUI
3746 executable. v0.9.5 introduced deprecated `codewhale-tui-*` release filenames
3747 as byte-identical compatibility copies; later releases retain those filenames
3748 while installed v0.9.4 clients remain supported upgrade sources.
3749 - Startup release checks cache successful lookups for one hour. The updater
3750 downloads and verifies the primary runtime once, then refreshes any existing
3751 `codew` or legacy `codewhale-tui` command paths from the same bytes.
3752 - Headless `codewhale exec` runs and verifier benchmark rollouts no longer
3753 impose a 100-step default. `--max-turns` remains available as an explicit
3754 opt-in ceiling; Fleet workers retain their separately configured budget.
3755 - Goal token and time budgets are telemetry rather than default stop
3756 conditions, and automatic goal continuation is unlimited unless the user
3757 explicitly configures a continuation ceiling.
3758 - Command-palette and slash-completion shadowing now share one alias-aware
3759 discovery contract.
3760 - The website install guidance, localized product copy, navigation controls,
3761 social metadata, and Cloudflare build pipeline now describe and deploy the
3762 same one-runtime release contract.
3763
3764 ### Fixed
3765
3766 - The hidden 20-step no-user-input backstop no longer ends productive turns.
3767 Tool results, queued steering, child completions, REPL feedback, and goal
3768 continuations can all reach the next provider step and a final assistant
3769 response; explicit user-configured limits and genuine stuck-loop guards remain.
3770 - Complete error details are directly inspectable after a failure instead of
3771 leaving the terminal with a clipped, unrecoverable error fragment.
3772 - A newly minted OAuth credential is adopted in the same provider-selection
3773 flow instead of requiring a second picker trip.
3774 - Fresh session titles can replace a stale cached `New Session` placeholder,
3775 unknown model context limits fail loudly, and release/source-install fallbacks
3776 no longer request binaries removed by the single-runtime conversion.
3777
3778 ### Contributors
3779
3780 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) fixed stale
3781 cached session titles that could pin the `New Session` placeholder.
3782 - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) built the
3783 shared alias-aware command discovery contract and acceptance coverage.
3784 - [Sun Zhenyuan](https://github.com/bistack) (`@bistack`) contributed the
3785 background incremental MCP Registry refresh.
3786 - [SKY ZHAO](https://github.com/skyzhao1223) (`@skyzhao1223`) contributed
3787 prompt-based `model = "auto"` routing in PR #5257.
3788
3789 ## [0.9.4] - 2026-08-07
3790 Codewhale v0.9.4 ships the release-train harness work: the familiar Fleet
3791 roster/setup face with a clear operator-leader and user/folder scope, a
3792 work strip that keeps actionable agents instead of a permanent archive,
3793 waiting policy that forbids polling without freezing independent work,
3794 calmer tool output and session recovery, account/Workflow-search/
3795 automation/handoff surfaces, a shorter translation-ready website, and
3796 release-blocker fixes across permissions, DeepSeek Responses, SQLite,
3797 File edits, terminal width, and Windows installation.
3798
3799 ### Added
3800
3801 - Memory maintenance: `remember` gains `revise` and `retire` beside the
3802 default `append`. Both name the exact note they target and both require
3803 the evidence for the change. Append-only memory decays — a correction
3804 sits behind the note it contradicts and both keep reaching the model —
3805 so the model can now keep its own durable notes true instead of only
3806 adding to them.
3807 - An audit trail for durable state the model writes about you. Every
3808 in-place memory edit is journalled to `memory/JOURNAL.md`, and every
3809 continual-harness `refine` / `remove` to a `JOURNAL.md` beside its state,
3810 each with before, after, and evidence. Harness removal previously left no
3811 record at all even though the entry leaves state entirely, so the journal
3812 is now the only place its content survives.
3813 - A first-run tip that says so: the first time Codewhale saves something
3814 durable it points at `/memory`, translated into all fifteen complete
3815 locale packs. This state shaped later sessions and nothing ever mentioned
3816 it existed.
3817
3818 - Sub-agent checkpoint resume: `agents/followup` resumes an
3819 `interrupted_continuable` child from its checkpoint into a fresh agent loop —
3820 new agent id, original prompt plus the prior conversation tail — when a
3821 runtime is attached, and otherwise keeps queue-only semantics with the
3822 `continuation_handle` returned; a second followup on the same interrupted id
3823 returns the existing resumed target instead of spawning a duplicate (PR #5242).
3824 - MCP Registry discovery with Registry-first tool selection: `registry_sync`
3825 surfaces the eligible local stdio catalog as a complete model-side candidate
3826 set, connect-failure messages classify early-exit and usage-help output and
3827 point recovery at the next Registry candidate, and a bundled `mcp-discovery`
3828 skill documents the flow (PR #5238).
3829 - Progressive fresh-context disclosure: fresh sessions ship a minimal
3830 constitutional kernel — ground truth, user intent and scope, truthful
3831 completion, guarantees in mechanism, and precedence — with procedural
3832 playbooks disclosed on demand, an opt-in project context pack
3833 (`project_context_pack_enabled`) counted in context reports, and `load_skill`
3834 catalogue discovery via `name="list"`; the measured fresh-context budget
3835 drops by roughly 40% (PR #5077).
3836 - Named Fleet store v2: one self-contained TOML Fleet per configuration
3837 (`schema = "fleet"`), with scope-explicit selection (user-global default vs
3838 folder override), migration receipts from legacy role profiles, and atomic
3839 saves that refuse to clobber a different Fleet on the same slug.
3840 - Scout replaces the user-facing "faster" control: catalog-verified fast
3841 siblings only, never a guessed model name; pinned Scout survives operator
3842 changes.
3843 - Truthful model-picker rows: vision/tools/limits chips only when the catalog
3844 knows, with provider → family → exact model grouping.
3845
3846 - **Opt-in product telemetry, off by default.** A first-run notice asks once, on
3847 a terminal, with declining pre-selected — Enter declines. Nothing is collected
3848 unless both `telemetry = true` and a recorded "Enable" answer are present, so
3849 a `telemetry = true` written before this release stays inert: the key has been
3850 settable and inert for a long time, and setting it was never consent.
3851
3852 An enabled session sends its batches to the first-party ingest endpoint,
3853 `https://telemetry.codewhale.net/v1/telemetry`, which is the shipped default
3854 for `telemetry_endpoint`. That is a Cloudflare Worker whose complete source is
3855 in this repository under `telemetry-ingest/`; it writes to Workers Analytics
3856 Engine, whose row is exactly `_sample_interval`, `blob1`–`blob20`, `dataset`,
3857 `double1`–`double20`, `index1`, and `timestamp` — **there is no IP, country,
3858 or geo column**, so storing one is structurally impossible rather than merely
3859 disabled. The handler reads two request headers, never touches the request's
3860 geo properties, logs nothing, and validates against a closed field set that
3861 rejects an entire batch carrying any unpublished key. Cloudflare's retention
3862 for that data is a fixed three months. Setting `telemetry_endpoint = ""`
3863 instead writes each batch to `$CODEWHALE_HOME/telemetry/dryrun.jsonl` and
3864 constructs no HTTP client at all, so you can read exactly what would have been
3865 sent.
3866
3867 Turning it off is an answer, not a flag: it deletes the random install id,
3868 truncates every buffered event, and leaves a permanent tombstone that a
3869 session already running re-checks before it appends and before it sends. A
3870 failed wipe fails closed. `CODEWHALE_TELEMETRY=0` is a hard floor that beats
3871 `--telemetry true` and the config key, and a value the parser cannot read
3872 also resolves to off. Fleet workers are hard-off. A repo-local
3873 `.codewhale/config.toml` can set neither key.
3874
3875 Never collected: prompts, completions, tool arguments, diffs, file contents,
3876 filenames, paths, git remotes, repo or branch names, memory entries, chat
3877 history, credentials (not even a boolean asserting one exists), model ids,
3878 custom provider table names, MCP server names, error or panic message bodies,
3879 per-event timestamps, keystrokes, clipboard, screenshots, or location. The
3880 full schema is [`docs/TELEMETRY.md`](docs/TELEMETRY.md), and a test parses the
3881 field names out of that file and asserts set equality with the structs the
3882 serializer uses.
3883
3884 This supersedes the roadmap's previous "no Codewhale product telemetry" entry,
3885 which moves from "Ruled out" to an opt-in framing. What stays ruled out:
3886 always-on or silent telemetry, per-keystroke or per-tool-call phone-home, and
3887 any third-party ad or analytics SDK in the runtime binary.
3888 - Registered `GLM-5.3` (direct Z.ai) and `z-ai/glm-5.3` (OpenRouter) as
3889 selectable GLM routes, with their aliases (`glm-5.3`, `glm-5-3`,
3890 `zai-glm-5.3`, `zai-glm-5-3`). Z.ai had **not released GLM-5.3 as of
3891 2026-08-03** — the ids are registered so they resolve to the Z.ai/OpenRouter
3892 routes instead of being rewritten to another vendor's model, and they will
3893 fail upstream until Z.ai ships the model. Metadata (context, output,
3894 reasoning controls) is inherited wholesale from `GLM-5.2` pending official
3895 Z.ai release metadata; pricing is intentionally absent, and `GLM-5.2` remains
3896 the default Z.ai model. No third-party gateway roster gained the model:
3897 OpenCode Zen, OpenCode Go, Alibaba Model Studio, and TelecomJS publish no
3898 glm-5.3 entry, so Codewhale advertises none.
3899
3900 - Managed Codewhale account commands (`account login`, `status`, `logout`, and
3901 `keys`) with browser device flow, profile- and origin-scoped secure sessions,
3902 refresh/revocation, redacted BYOK-vault management, and a token-free Runtime
3903 account receipt. Provider authentication remains separate, and `cloud`
3904 remains a compatibility alias.
3905 - `/automation` operator controls to list, inspect, pause, resume, delete, and
3906 run durable automations. Creation remains on the approval-gated
3907 model-visible `automation` tool.
3908 - A provider-neutral `WorkflowSearchSpec` authoring and freeze boundary, plus
3909 structured 2–16-candidate experimental search in the best-of-N Workflow
3910 starter. It freezes baseline, route, evidence, evaluator, gate, score, budget,
3911 and review policy before admission; it validates gate/scoring commands but
3912 does not execute or certify them itself.
3913 - The bundled generation-9 `handoff` skill for compact, decision-ready
3914 continuation across sessions.
3915 - Expanded terminal LaTeX rendering for aligned and matrix environments,
3916 cases, arrays, text/font/accent commands, brackets, symbols, and
3917 command-aware scripts (PR #4981).
3918 - Exact 40-character build provenance and secure account-session capability
3919 receipts on `/v1/runtime/info`; unknown source provenance continues to fail
3920 closed.
3921 - Acceptance-level Gherkin coverage locking the existing user-command
3922 precedence, alias shadowing, fallback, and invalid-command error contract
3923 (PR #4992).
3924 - Agent Plugins v1.0.0: consume, publish, and slugify packaged sub-agent
3925 briefs, with an install/update/uninstall on-ramp in the TUI (PR #5182). A
3926 plugin bundles a prompt, posture, and routing as one shareable artifact;
3927 on-disk migration of the older `plugin.toml` scaffold is deliberately out
3928 of scope for this train.
3929 - `send_later`: a model-callable one-shot delayed continuation tool, so the
3930 model can schedule a single future nudge without an operator-approved
3931 durable automation (PR #5138).
3932 - `/advisor`: an opt-in background advisor watcher for live turns (PR #5139).
3933 - Notification quiet mode with per-category switches and action-first copy
3934 (PR #5066).
3935 - Automation scheduling forms — one-shot `ONCE`, five-field cron, and honest
3936 watcher modes — created through the approval-gated `automation` tool
3937 (PR #5183).
3938 - Sub-agent `resume_from` continuation chains (PR #5142), child-result
3939 diff-tainting when a claimed diff is not visible to git, per-turn usage
3940 receipts on the exec stream-json stream, and spawn receipts that report
3941 the model each sub-agent actually ran on.
3942 - Transport resilience: sub-agent exec transport retries with a 600 s
3943 default (PR #5210), SSE header stalls retryable instead of fatal, and
3944 headless turn resume after mid-stream network drops with an `EX_TEMPFAIL`
3945 exit.
3946 - Session durability and control: a deterministic compaction continuation
3947 contract (PR #5064), persisting interrupted output (PR #5206), stop-word
3948 cancellation (PR #5207), token-counter refresh (PR #5204), deny-by-default
3949 approval cards (PR #5090), and the Operate completion gate (PR #5067).
3950 - zh-Hant promoted to a full shipped locale with complete `en.json` parity
3951 (PR #5143).
3952 - A persistent update-available chip in the header, with the startup update
3953 check throttled and naming the right command.
3954 - RLM static intent extraction for code blocks (`rlm_block_intent.rs`)
3955 landed as groundwork for a future code-mode approval flow; it is not yet
3956 wired into the turn pipeline and ships dormant by design.
3957
3958 ### Changed
3959
3960 - `/fleet` is the familiar roster/setup face again. The operator row is the
3961 Fleet leader (session model); the header names the selected saved Fleet and
3962 whether it is user-global or folder-scoped. Named-Fleet switching lives under
3963 `/fleet fleets` (Enter selects in the row's own scope). Session route changes
3964 stay temporary until `/fleet save`, `/fleet save-as`, or `/model save-default`.
3965 - Waiting-for-subagents directions forbid peek/status polling and sleep-as-wait,
3966 but allow independent work that does not depend on a child's result — the
3967 parent no longer freezes mid-turn with useful non-conflicting work available.
3968 - `workflow run` no longer requires `--fleet`; a saved Fleet is an optional pin
3969 layer over roles + the session route.
3970 - Homepage and getting-started copy is shorter and scannable across locales,
3971 with dictionary key and `{brand}` token parity preserved.
3972
3973 - Tool results now render as ordinary bounded previews with real expansion;
3974 storage, retention-ledger, and internal evidence language no longer leak into
3975 normal transcripts.
3976 - Prose wrapping, goal state, modal questions, composer-tail behavior, and
3977 ambient motion now follow one deterministic interface contract across narrow
3978 terminals and fast streams.
3979 - Scout and reviewer Fleet roles gain network access and the bounded
3980 verification surface for real reconnaissance while retaining the no-write,
3981 no-raw-shell security floor.
3982 - Workflow runs may describe up to 1,000 tasks while admitting at most 16 live
3983 tasks at once through the host concurrency gate. Tournament ordering now
3984 supports explicit score-first selection while retaining its cost-first
3985 default.
3986 - Runtime permission compatibility inputs resolve to one live
3987 `permission_posture`. Auto-Review can proceed without approval or structured
3988 question modals, unresolved holds fail closed, and a call planned under stale
3989 authority is retried after a posture change (PR #5025).
3990 - Duplicate and drifting per-turn metadata has been removed in favor of
3991 runtime-owned authority, and large inline account and skill tests now live in
3992 owned test seams.
3993 - Pinned Ratatui to 0.30.0 and ratatui-core to 0.1.0. ratatui-core 0.1.1+
3994 makes `Terminal::clear()` issue a blocking cursor-position report that
3995 raced the TUI input loop and could kill first launch; both pins are
3996 load-bearing, because 0.30.0 declares `ratatui-core ^0.1` and would
3997 otherwise resolve forward on its own (PR #5192 by @bistack; upstream
3998 ratatui/ratatui#2640).
3999 - Updated globset to 0.4.19, clap-complete to 4.6.8,
4000 futures-util to 0.3.33, libc to 0.2.189, actions/stale to 11.0.0, and
4001 docker/login-action to 4.5.2. The locked graph also includes the
4002 event-listener 5.4.2 fix for RUSTSEC-2026-0221.
4003 - The progress surface now speaks plainly everywhere: the last user-visible
4004 "Work update is pending" notices say "To-do list", the tool constructor and
4005 the docs name `todo_write` as the single canonical progress tool, and
4006 `work_update`, `TodoWrite`, and `todo` stay registered as hidden
4007 compatibility aliases so saved transcripts keep replaying.
4008 - Sub-agent and `agents/wait` waits stay short by default and by cap:
4009 blocking waits default to 30 s and refuse to block past 120 s, because a
4010 blocked wait deafens the session to typed input and settled children
4011 already report back as `<codewhale:subagent.done>` sentinels.
4012 - `Bash` `action=wait` honors `timeout_secs` (seconds) and bare `timeout`
4013 (milliseconds) alongside canonical `timeout_ms`, and `block` as an alias
4014 for `wait`, so a habit formed on other wait tools gets the duration it
4015 asked for instead of silently falling back to the 30 s default; the result
4016 metadata reports the real `wait_timeout_ms` applied.
4017
4018 ### Fixed
4019
4020 - The memory journal is no longer indexed as memory. It is Markdown in the
4021 memory tree, so the source walk collected it and every retired note
4022 re-entered the searchable set under its `before:` line — putting the
4023 exact facts a revision had just removed back into the prompt.
4024 - `memory_path` pointed at an already-native store no longer derives a
4025 second store nested inside it, which silently wrote somewhere other than
4026 the file the user named.
4027 - `muse` and `muse-spark` resolved to `muse-spark-1.1` in the agent
4028 registry while config had defaulted to `muse-spark-1.2`, so the CLI and
4029 app-server routed those aliases somewhere the configured default never
4030 pointed. The registry now carries 1.2 and the contributor variant.
4031
4032 - An explicit `type=builder` (or its `implementer` alias) plus
4033 `write_authority=read_only` now fails closed at spawn instead of launching a
4034 labeled write role that silently had only read-only tools and then self-BLOCKED
4035 after burning a turn (#5123). The check is deliberately narrow, because two
4036 neighbouring combinations are legitimate and stay legal:
4037 - `type=worker` + `read_only` — worker is the unnamed default (it renders as
4038 `general`) and takes its capability from authority, not from its name, so a
4039 read-only worker is an ordinary general-purpose child. Worker, scout,
4040 reviewer, and verifier remain the four canonical read-only Fleet roles.
4041 - any `role` + `read_only` — `role` is an identity for roster resolution, not
4042 a capability claim, so an acceptance Workflow can still resolve
4043 `implementer` to its saved profile while scoping that child to verification.
4044
4045 Callers that spelled a read-only narrowing as `type: "implementer"` should
4046 move it to `role: "implementer"`.
4047 - User-global credentials survive an explicit workspace `CODEWHALE_CONFIG_PATH`
4048 that selects a route with no local key — readiness probes the user-global
4049 provider table before concluding a key is missing.
4050 - Sub-agent token figures on the work bar accumulate input+output (the same
4051 total the worker budget uses) instead of completion tokens alone; elapsed
4052 time still freezes when the child settles.
4053 - Live work-bar rows for sub-agents show how many to-dos they still have
4054 left (`N left`) when the child's own list has unsettled items — never a
4055 fabricated zero when no list exists.
4056
4057 - Surfaces no longer claim an OS sandbox on platforms that cannot enforce one.
4058 The policy resolver takes no platform input, so on default Linux (bubblewrap
4059 is opt-in) and on all Windows the header chip read `files: workspace` and
4060 `/status` read `sandbox workspace-write` while nothing was restricted. Both
4061 now resolve the real backend and say `(unenforced)`.
4062 - `tool_category` hook conditions matched only retired tool names, so a
4063 `category = "shell"` **deny** hook — the security control `docs/HOOKS.md`
4064 documents — silently never fired. Categories now use the registered names,
4065 and multi-action tools classify by action.
4066 - A `Retry-After` header of `-5`, `nan`, or `1e300` crashed the request task
4067 (`Duration::from_secs_f64` panics on a negative). Parsing is now guarded and
4068 bounded to one hour.
4069 - Bearer tokens no longer leak into operator-visible receipts. `Authorization:
4070 Bearer <jwt>` split into two tokens and the JWT matched no redaction rule;
4071 prefix matching was also case-sensitive, so `SK-live-…` survived.
4072 - `prune_older_than` destroyed the NEWEST rollback snapshots and kept the old
4073 ones — on every boot, for any workspace with snapshots spanning the retention
4074 window. Both prune paths now share one orphan-chain rebuild and preserve each
4075 survivor's real timestamp.
4076 - An absolute or relative command path no longer defeats every execpolicy deny
4077 rule (`/bin/rm -rf /` did not match a `rm -rf /` rule), and a typed `Allow`
4078 rule no longer auto-approves a chained suffix such as `git log ; curl … | sh`.
4079 - Wrong types on `File` read range params and `Bash` stdin/cwd/task_id are now
4080 errors instead of silent defaults — a `start_line:"1200"` string used to
4081 return the head of the file, and a non-string `stdin` ran the command with no
4082 stdin and reported success.
4083 - Multibyte tool ids no longer panic the context inspector, wide (CJK) text no
4084 longer overflows the decision card, and a hostname like `127.evil.example.com`
4085 is no longer treated as loopback.
4086 - Refusals name calls the model can actually make (`rlm action='open'` rather
4087 than a retired `rlm_open`; `Bash` rather than `exec_shell`).
4088
4089 - Sub-agent dispatch no longer aborts the process. The Tokio runtime was built
4090 by `#[tokio::main]`, leaving every worker thread on the 2 MiB default while
4091 only the owner thread received the explicit 16 MiB stack — and the engine runs
4092 on a worker. A debug-build `agent` dispatch exceeded that stack and raised
4093 SIGABRT, which is not a panic and so could not be caught; the process died
4094 mid-spawn with no child request ever issued. Release builds were unaffected.
4095 - Fleet profiles that pin a provider no longer leak a bare model id onto the
4096 session route. `model_overrides` exported each role's model while dropping its
4097 provider, so a scout pinned to another provider's model was dispatched against
4098 the active client and denied at the wire — visible as an instant auth failure
4099 on the first sub-agent of a fan-out.
4100 - The rail's Pinned panel no longer spends four rows saying "No active work".
4101 An empty panel now collapses like the Tasks panel always has, and the settings
4102 migration no longer folds the default `sidebar_focus = "auto"` into a pinned
4103 always-on strip, which had silently handed that panel to every user who had a
4104 settings file at all. (An *empty* panel collapses; a panel holding settled
4105 to-dos or finished workers is not empty — see the standing-register entry
4106 below.)
4107 - The work bar keeps settled to-dos and an honest Subagents header, while
4108 completed/cancelled workers collapse out of the Top strip so fan-outs do not
4109 permanently eat the transcript. Failed or interrupted workers stay visible
4110 (they still need attention). Settled agents remain reachable through the
4111 Agents panel and catalog. To-do rows say their state in words (pending /
4112 in progress / completed / cancelled), and sub-agent rows carry type,
4113 objective, elapsed, and input+output tokens. Every work row is a door in
4114 every rail panel and placement: click and Enter open the row's world
4115 (work inspector / agent details — finished agents included) instead of
4116 doing nothing. A click after the detail pager closed itself reopens the
4117 detail rather than being swallowed by a stale toggle.
4118 - The rail strip yields its rows to the transcript when the terminal cannot
4119 seat both, so the idle ocean survives at 24 rows instead of being evicted.
4120 - `code_execution` and `js_execution` no longer describe themselves to the model
4121 as sandboxed. Both are ordinary local subprocesses with no seccomp, jail, or
4122 container (PR #5221 by @h3c-hexin and @asto18089).
4123 - Model Studio reasoning controls now fail closed on the host rather than on the
4124 provider enum, so a custom `base_url` no longer receives Alibaba-specific
4125 `enable_thinking` fields, and `qwen3.8-max` is no longer sent a thinking
4126 switch it does not accept (PR #5233 by @Inference1, closing #5203).
4127 - `config.example.toml` no longer claims Shift+Tab cycles the reasoning tier.
4128 Shift+Tab cycles the permission posture; Ctrl+T cycles reasoning
4129 (found by @vFONGv, PR #5229).
4130
4131 - Alibaba Model Studio reasoning controls are now route- and model-scoped
4132 instead of provider-wide (#5203, harvested from #5233 by
4133 [@Inference1](https://github.com/Inference1)). Codewhale sends
4134 `enable_thinking` / `preserve_thinking` / `reasoning_effort` only when the
4135 configured `base_url` is a verified Alibaba Chat Completions host, so
4136 pointing a `modelstudio-*` provider ID at a custom gateway no longer injects
4137 DashScope's dialect into it. `qwen3.8-max` and `qwen3.8-max-preview` are
4138 thinking-only and no longer receive an `enable_thinking: false` they cannot
4139 honor; `preserve_thinking` is sent for the models documented to accept it, so
4140 their reasoning trace survives into the next turn; and `deepseek-v4*` /
4141 `glm-5.x` map the reasoning tier onto the documented `high` / `max` ladder.
4142
4143 - xAI device login now recovers from a config that points at a missing
4144 Codewhale-owned credential generation instead of failing every attempt
4145 with a generic activation error, and finalize failures report the full
4146 error chain (#5032).
4147 - API keys saved to the secret store no longer read as unconfigured for
4148 providers that are not currently active; a configured Kimi/Moonshot key
4149 survives provider switches and restarts without re-entry (#5033).
4150 - Switching to the Codex provider with no saved model now lands on the live
4151 roster's flagship model instead of a stale static default (#5034).
4152 - Worktree-isolated Fleet builders no longer contend on the per-workspace
4153 delegated-coordination lock, and a failed lock acquisition is retried on
4154 use instead of being memoized for the life of the process (#5036).
4155 - Fleet dispatch now rebinds the child client when the resolved profile
4156 model requires a different wire protocol (DeepSeek flash on Responses),
4157 instead of failing deterministically on the worker's first request
4158 (#5042).
4159 - DeepSeek Responses now sends `reasoning.effort: "none"` for the Off tier,
4160 shows a truthful notice instead of silently discarding server-side
4161 `web_search_call` items, and parses cache-hit, cache-miss, cache-write, and
4162 pricing telemetry while retaining the OpenAI-style nested fallback.
4163 - File edits now explain no-op and missing-search failures, reject newly
4164 unbalanced C/C++ preprocessor replacements, handle the reported
4165 CRLF/non-ASCII cases, and safely relocate stale unified-diff hunks only when
4166 whole-file context is unique (PRs #5008 and #5030).
4167 - Circled digits, enclosed alphanumerics, and keycap graphemes use consistent
4168 two-column measurement in Codewhale, Ratatui, and CJK terminals, preventing
4169 missing-character and phantom-space corruption (PR #5001).
4170 - SQLite connections install their busy timeout before locking setup and avoid
4171 rewriting persistent WAL mode on every open, removing the concurrent-open
4172 release-gate failure.
4173 - The Windows installer preserves long current-user `PATH` values, their
4174 registry type, and unrelated entries across install and uninstall (PR #5006).
4175 - Provider configuration no longer contains user-reachable panic paths when
4176 metadata or prior credential state is missing.
4177 - Resuming a session restores composer text only from a same-session persisted
4178 draft; submitted prompts and internal background-runtime envelopes remain in
4179 history instead of appearing in the composer (PR #5029).
4180 - Shared CI now handles bot-authored issue-link checks, provisions cargo-deny's
4181 toolchain, and fetches the locked test graph before offline runtime-budget
4182 validation.
4183 - Re-quote each linker argument in the Windows OpenHarmony clang launcher so a
4184 spaced SDK path (e.g. the default `D:\DevEco Studio\...` install) keeps its
4185 `--sysroot` intact through the final Rust link, and extend the no-SDK release
4186 guard to keep the re-quoting contract (PR #5095).
4187
4188 - The shell tool reports the real elapsed wait time in its result content
4189 instead of echoing the requested timeout (PR #5240).
4190 - Transcript wheel scrolling under iTerm2: xterm alternate-scroll (DECSET
4191 1007) now stays off while mouse capture is active, so wheel events arrive as
4192 mouse events instead of being converted into arrow keys (#5223, PR #5234).
4193 - A stalled model stream no longer ends the turn as `Completed` over a
4194 frozen reasoning block: a mid-stream chunk-timeout now counts toward the
4195 stream-error budget, so a stall with nothing streamed retries the request
4196 transparently, and a stall that exhausts the retry budget fails the turn
4197 with the real reason instead of reporting success.
4198 - A finished background shell task now wakes the engine even when no goal is
4199 active: the idle loop starts an ordinary runtime turn so the completion
4200 reaches the model immediately instead of sitting unclaimed until the user
4201 types (a dead provider route claims the completion once and reports where
4202 the output lives instead of re-arming the same error every tick).
4203 - Sub-agent final reports that exceed the summary budget are now spilled to
4204 a session artifact, and the truncation footer names the
4205 `retrieve_tool_result` ref for the elided middle instead of telling the
4206 model the bytes are unrecoverable; write failures degrade to the honest
4207 no-ref footer.
4208 - An interactive mid-stream network drop after partial output no longer fails
4209 the turn: the partial reply is preserved as a committed assistant message,
4210 a runtime continuation message is appended, and the request is re-issued
4211 bounded by the stream-retry budget.
4212 - Large pasted input is no longer sent to the model twice as inline text and
4213 as a backup `.md` paste file; the submitted message now carries only the
4214 `@`-mention so the model reads the file once.
4215 - A builder sub-agent can run ordinary shell writes again. Write claims
4216 outlive the agents that register them, so a workspace accumulated one per
4217 builder that ever ran — six completed agents left four standing claims in
4218 testing — and the shared-checkout gate counted those long-finished children
4219 as live contenders. Every later builder was refused `Bash` writes with
4220 "cannot prove a bounded file target" and pushed toward worktree isolation,
4221 which puts the work in a checkout the operator never looks at. The gate now
4222 asks the question it meant to ask: is another *running* child writing in this
4223 shared checkout. Concurrent writers are still gated; a lone builder writes in
4224 the workspace you are actually watching.
4225 - Ctrl-C during the first moments of startup no longer kills Codewhale
4226 outright. The terminating-signal handlers were registered inside the task
4227 that waits on them, and a spawned task does not run until the scheduler
4228 first polls it, so a SIGINT arriving in that window hit the default
4229 disposition — the process died with no exit code, no terminal restore, and
4230 no session record. The handlers are now installed synchronously, before
4231 the telemetry notice and before arming, so the window is closed.
4232 - The documented tool list on the docs site named `update_plan` and
4233 `work_update` as coordination tools. Neither is callable by the model —
4234 `update_plan` replays older Plan artifacts and `work_update` is a hidden
4235 compatibility alias — so the page listed two tools a reader cannot use and
4236 omitted `todo_write`, the one they can.
4237
4238 ### Security
4239
4240 - Bumped `nanoid` past GHSA-2v37-7h3g-55p8 (a custom generator given size
4241 zero could loop indefinitely), restoring a zero-advisory `npm audit` for
4242 the website.
4243
4244 - Google Gemini is its own backend (`/provider google`) on the official
4245 OpenAI-compatible route with thought-signature capture/replay and
4246 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
4247 as a separate credential-plane provider: consent-gated read-only import
4248 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
4249 precedence; requests fail closed until the cloud-code wire protocol is
4250 implemented.
4251
4252 ### Removed
4253
4254 - The default model-facing SlopLedger implementation, its storage-oriented
4255 transcript language, and the `/debt`, `/cleanup`, `/slop`, and `/canzha`
4256 command surface.
4257
4258 ### Contributors
4259
4260 - [Sh1Zuku](https://github.com/SparkofSpike) (`@SparkofSpike`) contributed
4261 LaTeX rendering in PR #4981, completed circled-digit/keycap width handling in
4262 PR #5001, and delivered actionable File-edit recovery in PR #5008; for this
4263 train he resumed interrupted sub-agents from checkpoints in PR #5242,
4264 surfaced real shell wait elapsed time in PR #5240, and kept alternate-scroll
4265 off while mouse capture is active in PR #5234.
4266 - [XhesicaFrost](https://github.com/XhesicaFrost) (`@XhesicaFrost`) fixed long
4267 Windows user-PATH preservation in PR #5006.
4268 - [Paulo Aboim Pinto](https://github.com/aboimpinto) (`@aboimpinto`) added the
4269 user-command dispatch acceptance contract in PR #4992.
4270 - [DracheTek](https://github.com/DracheTek) (`@DracheTek`) provided the
4271 multilingual, CRLF-heavy File-edit failure report in issue #5003.
4272 - [An Ziwu](https://github.com/MuRongMoQing) (`@MuRongMoQing`) reported the
4273 Windows PATH-overwrite defect in issue #4685.
4274 - [shenjackyuanjie](https://github.com/shenjackyuanjie) (`@shenjackyuanjie`)
4275 fixed the Windows OpenHarmony linker re-quoting for spaced SDK paths in
4276 PR #5095.
4277 - [bistack](https://github.com/bistack) (`@bistack`) contributed MCP Registry
4278 discovery with Registry-first tool selection in PR #5238.
4279 - [vFONGv](https://github.com/vFONGv) (`@vFONGv`) wrote the zh-CN Windows
4280 beginner guide with screenshots in PR #5229, harvested after its base branch
4281 was accidentally deleted during maintainer cleanup.
4282 - [mky](https://github.com/mky) (`@mky`) fixed the FreeBSD build (PR #5254, `rquickjs` `bindgen` on FreeBSD).
4283 - [cacdcaecawae](https://github.com/cacdcaecawae) (`@cacdcaecawae`) contributed embedder-owned sub-agent state roots (PR #5252).
4284
4285 ## [0.9.3] - 2026-07-31
4286
4287 This is the Codewhale v0.9.3 source candidate. It is not a published release
4288 until the matching tag, packages, checksums, and release assets exist.
4289
4290 DeepSeek V4 Flash is now a first-class Codewhale route, and the agent-facing
4291 tool surface has been reduced to the canonical action tools that current
4292 models actually need. This release also hardens credential, authorization,
4293 durability, compaction, and macOS File Provider boundaries while deleting
4294 stale runtime and dependency surface.
4295
4296 ### Added
4297
4298 - Native `deepseek-v4-flash` support over DeepSeek's Responses API, including
4299 stateless reasoning-item replay, semantic SSE terminal events, structured
4300 function calls and outputs, `apply_patch`, and model-aware wire-format
4301 selection. Exact current Flash IDs use Responses; future direct
4302 `deepseek-vN-*` model IDs inherit that route conservatively, while custom
4303 DeepSeek-compatible endpoints retain Chat Completions unless configured
4304 otherwise.
4305 - A pipe-only `codewhale auth print-api-key` handoff for explicitly selected
4306 providers. It shares Codewhale's home-scoped credential authority, refuses
4307 terminal output, and prevents sentinel placeholders from becoming live
4308 credentials.
4309 - Per-turn `max_tool_calls` enforcement at the engine admission gate, plus a
4310 named-file write scope with a separate read seam. The runtime now rejects
4311 over-budget calls before execution and keeps the operator's write boundary
4312 explicit (#4415).
4313 - Runtime-contract, source-structure, and persistence-backlog ratchets that
4314 name drift instead of allowing large ownership surfaces to grow silently
4315 (#3921, #4785).
4316
4317 ### Changed
4318
4319 - Model-visible built-ins now use the canonical `Bash`, `File`, and `Run`
4320 action schemas. `apply_patch` remains available as the one direct custom
4321 edit tool supported by DeepSeek Responses. The bundled stop-ship workflow,
4322 Fleet fixtures, shell shortcut, and engine tests use the same canonical
4323 vocabulary.
4324 - Canonical `File { action: "write" }` requests now pass through the same
4325 semantic repo-law checks as the former write path. Approval, Full Access,
4326 and workflow execution cannot bypass the repository safety floor by choosing
4327 the canonical schema.
4328 - Codewhale home resolution is shared across the CLI, TUI, state, and secret
4329 stores. `doctor` is offline by default, distinguishes credential source from
4330 availability, and reports one consistent path snapshot.
4331 - Durable runtime event writes are serialized across simultaneous processes,
4332 blocking history waits move off async workers, and provider quota exhaustion
4333 remains typed and retryable through compaction (#4522).
4334 - Skill discovery caches the merged catalog behind watched-mtime validation;
4335 large skill, engine, subagent, UI, and ambient-ocean test blocks now live in
4336 owned test seams.
4337 - Reasoning summaries stay in the user's language, complete jellyfish
4338 silhouettes relocate around transcript text, and cached ocean frames include
4339 their palette identity (#4807).
4340 - The authorization-order contract now documents and tests how modes, hooks,
4341 permission rules, safety floors, repo law, approvals, and sandboxing compose
4342 (PR #4980).
4343
4344 ### Fixed
4345
4346 - macOS sandbox extensions cover CloudStorage/File Provider workspaces without
4347 broadening unrelated paths; thanks @Watcher24 for the #4085 report and
4348 reproduction.
4349 - Foreground shell state detaches before steering, so an interrupted command
4350 cannot keep owning the composer (PR #4979).
4351 - MCP application-level failures and malformed error envelopes fail closed
4352 instead of looking like successful tool output.
4353 - Optional PDF failures are truthful and PDF classification no longer misses
4354 supported inputs.
4355 - Bracketed-paste contents are redacted from traces, and credential diagnostics
4356 never treat placeholder sentinels as usable keys.
4357
4358 - Google Gemini is its own backend (`/provider google`) on the official
4359 OpenAI-compatible route with thought-signature capture/replay and
4360 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
4361 as a separate credential-plane provider: consent-gated read-only import
4362 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
4363 precedence; requests fail closed until the cloud-code wire protocol is
4364 implemented.
4365
4366 ### Removed
4367
4368 - The legacy callable aliases `exec_shell`, `run_shell_command`, `read_file`,
4369 `write_file`, `list_dir`, `grep_files`, `file_search`, and the duplicate
4370 Work/RLM registrations. Historical transcript and policy semantics remain
4371 readable, but new model turns receive only the canonical action surface.
4372 - The bundled PDF parser dependency chain, replacing it with the smaller
4373 optional extraction boundary tracked by #4382.
4374
4375 ### Contributors
4376
4377 - [Turisla](https://github.com/greyfreedom) (`@greyfreedom`) documented and
4378 locked the authorization-order contract in PR #4980.
4379 - [Nightt](https://github.com/nightt5879) (`@nightt5879`) fixed foreground
4380 shell detachment before steering in PR #4979.
4381 - [Watcher24](https://github.com/Watcher24) (`@Watcher24`) provided the macOS
4382 File Provider report and reproduction for #4085.
4383 - [Fred Leitz](https://github.com/fleitz) (`@fleitz`) retains required
4384 source-candidate credit for the canonical `Bash` workspace fix from PR #4673
4385 and issue #4674.
4386
4387 ## [0.9.2] - 2026-07-29
4388
4389 This is the Codewhale v0.9.2 source candidate. It is not a published release
4390 until the matching tag, packages, checksums, and release assets exist.
4391
4392 ### Changed — behavior
4393
4394 - **Legacy `model = auto` no longer elects a network classifier on its own.**
4395 Holding a DeepSeek API key used to silently select `deepseek-v4-flash` as the
4396 classifier for every Auto turn — a per-turn cost on a route nobody asked for,
4397 and one provider privileged over the rest. Auto now stays local and free
4398 unless an explicit `[auto.router]` block names a provider and model.
4399
4400 **If you relied on the implicit default**, restore it explicitly:
4401
4402 ```toml
4403 [auto.router]
4404 provider = "deepseek"
4405 model = "deepseek-v4-flash"
4406 ```
4407
4408 `[auto.router]` remains legacy `model = auto` configuration. It is unrelated
4409 to a Fleet's Adaptive Reasoning Router, which is a saved service referenced by
4410 name from a Fleet file and decides only how hard an already-frozen route
4411 thinks.
4412
4413 Landed since v0.9.1, not yet released. A cluster of defects found by a
4414 read-through audit of the policy engine, the MCP proxy, the session index,
4415 and the app-server bridge — several of them cases where the wrong outcome
4416 was reached silently, behind a response or a log line that looked fine. The
4417 release also adds opt-in session, reasoning, localization, and inspectability
4418 surfaces; existing defaults remain stable unless an entry below explicitly
4419 says otherwise.
4420
4421 ### Added
4422
4423 - `/permissions` now lists the active user permission-rule source, each rule's
4424 effective matcher and global/repository scope, and whether that scope applies
4425 in the current workspace. `/permissions remove <number>` previews deletion
4426 and requires a snapshot-bound confirmation token, so a concurrent edit
4427 cannot move a different rule under the confirmed index. Appends and removals
4428 share one adjacent lock, preserve unrelated TOML formatting and comments,
4429 atomically replace `permissions.toml`, and reload the live user ruleset
4430 without clearing session-only approvals. `/config ask-rules` remains a
4431 compatibility entry; rule creation, glob/directory rules, and deny
4432 persistence remain out of scope (#1186, PR #4960 by @greyfreedom).
4433
4434 - `/preview-request` (aliases `/dryrun` and `/preview_request`) is a human-only,
4435 provider-free inspection of the next primary turn. Production dispatch and
4436 preview share one prepared-request seam across Chat Completions, Anthropic
4437 Messages, and OpenAI Responses, so the manifest reads the final wire model,
4438 reasoning controls, tool choice, tool schemas, and body hash from the same
4439 value production sends. Route, tool, or body facts that require Auto's
4440 provider classifier, an MCP connection, mutable hooks, compaction, or queued
4441 runtime injections remain typed unavailable. The manifest reports exact
4442 primary role/lane identity, upstream route-source provenance, requested and
4443 effective reasoning, canonical JSON sizes, conservative offline estimates,
4444 and provider-reported usage as unavailable because no request ran. It never
4445 adds a model-visible tool, sends a provider call, or prints prompt, message,
4446 credential, endpoint-path, or workspace-path content. The explicit
4447 `/preview-request base-prompt` mode prints only the exact effective base
4448 prompt; effective system text remains protected behind its final hash. The
4449 exact body includes the same authoritative transient Work/To-do tail used by
4450 production, including graph-backed state newer than the legacy projection.
4451 Preflight preserves production's separately framed base-plus-Work estimate,
4452 and fails closed when the authoritative projection is unavailable. An
4453 exhausted active goal token budget also produces a typed unavailable result
4454 before any outbound request is built.
4455 (#1004, #3928; dry-run concept harvested from PR #1099 by @GTC2080 / TaoMu.)
4456
4457 - Slash commands, hotbar actions, and CLI entrypoints for the same Lane/Fleet
4458 lifecycle operation now share one typed control-plane contract
4459 (`codewhale-lane::control`): a stable `<domain>.<verb>` id, read-vs-write
4460 authority, persistence scope, exact-identity target selection, retryability,
4461 lifecycle outcome, and one bounded, sanitized receipt. `docs/COMMAND_CONTROL_PLANE.md`
4462 documents it (#1888).
4463
4464 - `/lane [list|status|interrupt|restart|resume]` — durable Lane control from the
4465 composer, backed by the same executor `codewhale lane …` calls. `codewhale
4466 lane interrupt|restart|resume` are the matching CLI verbs; `lane stop` stays as
4467 a compatibility spelling of `lane interrupt`. Appending `@<lifecycle-seq>` to a
4468 lane id fences a write to the exact durable generation you observed, so a
4469 concurrent transition is rejected as a conflict rather than acted on (#1888).
4470
4471 - `codewhale fleet list` and `/fleet [list|status|interrupt|resume]` — durable
4472 Fleet run inspection and control from either surface, through shared DTOs that
4473 carry the exact provider, provider-table id, model, effective reasoning tier,
4474 and route source when the ledger records them, and a typed `not_recorded` /
4475 `not_applicable` / `redacted` reason when it does not. Requested-vs-effective
4476 reasoning is never back-filled: the ledger persists the effective tier only, so
4477 the requested tier reports `not_recorded` (#4022).
4478
4479 - The bundled skill pack now ships a `help` skill (catalog generation 7). It is
4480 `invocation: explicit-only`, so it never enters the model's ambient catalogue
4481 and costs no prompt budget. Its body is a routing card that points at the
4482 surfaces this build actually exposes — `/help` and `/help <command>`,
4483 `/skills` and `/skills inspect`, `/config`, `doctor`, and the `docs/` tree
4484 when the workspace is a Codewhale checkout — and explicitly forbids pasting a
4485 command list or settings table into context (#4698).
4486
4487 - `crates/tui/assets/skills-catalog-matrix.json`: an authored, provider-free
4488 expectation matrix covering every bundled skill (tier, invocation, aliases,
4489 ambient-catalogue eligibility, shadowed aliases). Contract tests in
4490 `crates/tui/src/skills/catalog_matrix.rs` assert a bijection between the
4491 fixture and the shipped bundle, so the starter pack cannot change without an
4492 explicit fixture update. The matrix covers positive eligibility and explicit
4493 load, non-activation negatives, alias resolution, explicit-only exclusion,
4494 alias-vs-canonical collision precedence, and prompt-budget invariants (no
4495 duplicate catalogue entries, no aliases as extra entries, and the shipped
4496 pack fitting inside the 12 000-char budget with no omitted-skills line). These
4497 are deterministic registry/catalog/resolver assertions and make no claim about
4498 semantic model routing (#4698).
4499
4500 - Locale-routing coverage for the complete bundled catalog across every shipped
4501 locale (`en`, `ja`, `zh-Hans`, `zh-Hant`, `pt-BR`, `es-419`, `vi`, `ko`). No
4502 bundled skill ships a localized routing description and none was invented;
4503 the tested contract is deterministic fallback to the canonical English
4504 description, with the rendered catalogue byte-identical across locales.
4505 Exact-tag match, primary-subtag fallback, and English fallback are covered
4506 against a synthetic authored fixture, and the parity test fails if a bundled
4507 skill ever gains localized metadata without source-backed coverage (#4698).
4508
4509 - `docs/LIVE_SMOKE.md`: copy-pasteable, opt-in live-smoke instructions for Kimi
4510 K3 and a second provider/model (DeepSeek). The runs are manual only — nothing
4511 in CI, tests, or skills invokes them. They use `env -i` plus a throwaway
4512 `CODEWHALE_HOME`; `HOME` is left unset rather than repurposed, and ambient
4513 provider variables are not forwarded. The operator names the credential
4514 variable explicitly, and the isolated child reads its value with echo off,
4515 restores the prior terminal state on exit or interruption, and never persists
4516 the value or puts it in a command argument. The page states the expected
4517 route/model/reasoning/tool receipt fields while treating provider errors as
4518 unclassified until provider configuration, authentication/entitlement, and
4519 harness behavior have been corroborated independently (#4698).
4520
4521 - Approval cards can now remember eligible safe shell and file-write approvals
4522 as exact `allow` rules scoped to the current repository. Remembered shell
4523 commands use complete-command matching, validated file and patch paths remain
4524 workspace-relative, and dangerous, critical, or repo-law-held requests stay
4525 ineligible and continue to require review.
4526
4527 - `tui.header_items` (array of strings, optional, default `[]`): an opt-in
4528 header chip showing cumulative session token usage as input / cache-hit /
4529 output. Set `header_items = ["tokens"]` under `[tui]` to enable it. The
4530 chip is the only elidable element of the header — the git label, context
4531 meter, and version stamp keep their space, and narrow terminals drop the
4532 chip rather than the baseline chrome. Unknown entries are warned about and
4533 skipped so configs written by newer builds stay loadable by older ones
4534 (#4520 requested by @eugenicum; PR #4610 by @XhesicaFrost, harvested with
4535 co-authorship).
4536
4537 - `thinking_default_expanded` lets reasoning blocks start open while keeping
4538 Space as the per-block toggle. The setting is persisted, available through
4539 native and runtime configuration, and documented for SSH/tmux accessibility
4540 (issue #4925 and PR #4928 by @M-Maciej).
4541
4542 - The transcript renders a conservative subset of LaTeX math as readable
4543 Unicode without rewriting fenced/inline code, ordinary currency, escaped
4544 dollars, or unknown commands. The contribution from PR #4973 by
4545 @SparkofSpike was hardened and landed through PR #4974; reported by
4546 @antarikshraya in #4957.
4547
4548 - Session control now includes a sessions rail, shared archive projection,
4549 picker archive controls, and opt-in interactive auto-resume with explicit
4550 handoff behavior. The work closes the remaining session-browsing direction
4551 from #2934; thanks @cy2311 for the original report.
4552
4553 - The bundled contributor-onboarding skill can sync contribution context,
4554 select the appropriate gate, and prepare a digest without inflating the
4555 ambient skill catalog. It follows the contributor-navigation request in
4556 #4227 by @JayBeest.
4557
4558 - Bahasa Indonesia now has a complete repository documentation suite and a
4559 registered website dictionary alongside the shipped TUI locale (PRs #4962
4560 and #4972 by @atmosuwiryo, closing #4789).
4561
4562 - Reasoning content can keep its rail, italics, cursor, and expansion controls
4563 while disabling only the warm background highlight. The independent setting
4564 is persisted and localized (#4089; reported by @elijahchan2019).
4565
4566 - StepFun setup now asks whether a key belongs to PAYG or Step Plan, keeps the
4567 two endpoint/billing routes distinct, and localizes the choice across the
4568 complete packs (#4526; reported by @whp233).
4569
4570 - OpenCode Zen is a separate model-aware API-key provider. Its curated catalog
4571 selects Responses, Anthropic Messages, or Chat Completions per model;
4572 unsupported Gemini and unknown models fail closed, and missing Zen
4573 credentials never fall through to ChatGPT/Codex OAuth guidance. The
4574 implementation from closed PR #4467 by @snail-vs (snailoniu) is preserved in
4575 the candidate.
4576
4577 - Markdown exports correlate prompts with stable workspace restore-point ids
4578 and say when correlation is unavailable or ambiguous, completing the
4579 remaining restoration/export direction from #2494 by @wywsoor.
4580
4581 ### Fixed
4582
4583 - Permission setup now consistently presents the product postures Ask,
4584 Auto-Review, and Full Access instead of leaking the internal `never` token.
4585 The same resolved sandbox policy now drives execution and UI receipts: Plan
4586 stays read-only, Ask and Auto-Review stay workspace-scoped, and Full Access
4587 is actually unsandboxed unless a stricter effective configuration wins.
4588
4589 - Fleet setup no longer stalls when a user explicitly selects a configured
4590 Codex or Grok external-consent route. The selected route is activated and
4591 validated before saving, roster roles open directly on their Model step,
4592 Review saves on the first Enter, and new profiles default to the personal
4593 profile directory that the roster loads on the next session.
4594
4595 - Provider credential dialogs now share one wrapping, secret-safe API-key
4596 surface across every non-OAuth provider. A key already present in durable
4597 storage is reported as configured without rendering it, typing or pasting is
4598 clearly framed as replacement, narrow help text remains visible, and Codex
4599 and Grok OAuth flows remain token-free in this modal.
4600
4601 - Ctrl+O again opens the complete recorded reasoning detail for the selected,
4602 active, or latest reasoning block. The whole-turn Turn Inspector moved to
4603 Ctrl+Alt+O and `/turn inspect`, removing the shortcut collision while keeping
4604 raw leaf detail and post-flush reasoning discoverable.
4605
4606 - Failed child agents now deliver a distinct high-priority failure receipt to
4607 their owning parent with a sanitized failure class, elapsed work, and a full
4608 transcript handle. Parent-to-child message, follow-up, and interrupt tools
4609 now use one hierarchy-checked mailbox path, and persisted nested completion
4610 envelopes remain safely restorable across instruction-text revisions.
4611
4612 - Background-shell completion events now carry only bounded tails plus a
4613 retrievable exact-evidence handle. Terminal foreground Bash results are
4614 acknowledged at the direct tool-result boundary and are no longer emitted a
4615 second time as background completion artifacts.
4616
4617 - Providerless Fleet and child-agent fixed-model routes now reject only
4618 high-confidence foreign-provider model ids before creating a worktree, while
4619 explicit provider/model pairs, custom and local endpoints, unknown ids, and
4620 aggregator wire-id resolution retain their intended behavior.
4621
4622 - Manual compaction now preserves and reports the supplied provider failure
4623 class instead of replacing it with an opaque generic error. This does not
4624 infer quota exhaustion when the recorded failure does not prove it.
4625
4626 - The ambient jellyfish keep complete, readable silhouettes while animating,
4627 and the website favicon now uses the Signal Current desktop tile instead of
4628 the legacy whale mark.
4629
4630 - ACP JSON-RPC responses preserve numeric request ids for avante.nvim while
4631 retaining the negotiated string-id exception for Zed (PR #4929 by
4632 @atmosuwiryo).
4633
4634 - Restored shell cells whose job no longer exists stop displaying live
4635 spinners and settle into a truthful stale/no-output state across transcript,
4636 phase strip, and sidebar (PR #4937 by @LI-Jialu, closing #4547).
4637
4638 - Interrupted checkpoints and timed recovery snapshots remain checkpoints
4639 instead of being promoted into orphan session files, preventing duplicate
4640 `/resume` entries (PR #4963 by @SparkofSpike).
4641
4642 - Every shipped locale is admitted by the typed settings schema and native
4643 chooser, with complete/partial status kept independent and tested (PR #4856
4644 by @nightt5879, closing #4786). Context-menu hover hit-testing also accounts
4645 for its title row (PR #4897 by @XhesicaFrost; reported by @SparkofSpike in
4646 #4803).
4647
4648 - OSC 52 and SSH/tmux clipboard transport run on one bounded background worker
4649 rather than blocking input and rendering on the TUI loop; late transport
4650 failures still surface through the status path (PR #4896 by @nightt5879,
4651 closing #4159).
4652
4653 - Non-streaming model calls receive a generation-length response budget rather
4654 than the SSE header-open timeout, while actual SSE opens share the bounded
4655 cross-provider transport seam. The equivalent fix direction came from
4656 closed PR #4743 by @vibecoding-skills.
4657
4658 - Resumed sessions diagnose a deleted inherited workspace before shell launch
4659 instead of failing as an opaque Windows process error (report #4100 by
4660 @redjade75723). DeepSeek native tool-call wrapper tokens are also scrubbed
4661 from visible streaming and completed output as a grounded fail-soft follow-up
4662 to report #3880 by @hardy922; that report's exact emitted marker remained
4663 unconfirmed.
4664
4665 - Auto model routing now preserves the user's requested reasoning effort
4666 through startup, provider/model changes, session restore, the picker,
4667 Ctrl+T, and Hotbar actions. The tier is normalized only after the concrete
4668 provider route is known instead of being silently replaced by Auto
4669 (#4941, PR #4961 by @nightt5879).
4670
4671 - Auto-compaction now defaults on for every known model context window,
4672 including Kimi K3's 1,048,576-token routes. Persisting only an
4673 `auto_compact_threshold` or `auto_compact_threshold_percent` now counts as
4674 opt-in intent, while an explicit `auto_compact = false` remains authoritative.
4675 `/config` reports the effective state, percentage, and computed token trigger.
4676
4677 - Per-provider `context_window` overrides are now documented and visible in
4678 `/config`, provider setup help, diagnostics, and the example configuration.
4679 The effective override consistently drives preflight budgeting, the context
4680 meter, and compaction; this lets a user cap a 1M Kimi route to 256K when their
4681 Coding Plan tier has the smaller window.
4682
4683 - Agent Details now projects status, model, elapsed time, and step counts from
4684 the same row snapshot as the primary agents list, eliminating contradictory
4685 worker state between the two surfaces.
4686
4687 - Composer submission and its hints now share one state machine. Portable
4688 terminals use Enter to queue during a running turn and Enter again to steer;
4689 Ctrl/Cmd+Enter is accepted only when an enhanced terminal reports it and is
4690 no longer advertised as universally available.
4691
4692 - `edit_file` now matches LF-only model search text against CRLF files,
4693 preserves the file's line-ending style for replacement text, and still
4694 rejects newline-normalized duplicate matches as non-unique (#4764).
4695 Implemented in PR #4942 by @nightt5879; reported and root-caused by
4696 @LmeSzinc.
4697
4698 - `/fleet status` read the current TUI session's sub-agents while `codewhale
4699 fleet status` read the durable `.codewhale/fleet.jsonl` ledger — two different
4700 things wearing one name, so a run started by `codewhale fleet run` never
4701 appeared in the TUI. `/fleet status` now reads the durable ledger through the
4702 same code path as the CLI; the session view keeps its own name as
4703 `/fleet workers` (`/subagents` and `n` still work). When a workspace has no
4704 ledger, both surfaces report a typed `no_fleet_ledger` reason instead of an
4705 empty-looking "all clear", and neither creates the ledger as a side effect of
4706 reading it (#4022).
4707
4708 - `codewhale fleet status` (and `list`/`interrupt`/`resume`) created
4709 `.codewhale/fleet.jsonl` as a side effect of opening the manager, then
4710 reported `no_fleet_ledger` for the file it had just made — so the second
4711 invocation showed an empty Fleet where none existed. The CLI now refuses
4712 those verbs before the manager is constructed, matching `/fleet` (#4022).
4713
4714 - `fleet resume <run-id>` accepted any string. An id absent from the ledger
4715 reconciled nothing but still wrote a run-status record keyed by whatever was
4716 typed, and reported `no_change`. Unknown ids are now refused as `not_found`
4717 before any durable write (#4022).
4718
4719 - `lane interrupt` reported `transitioned` even when it changed nothing —
4720 another process's stop looked like our own. The Runtime backend now reports
4721 whether *this* call performed the transition, and a no-op is `no_change`.
4722 The `@<lifecycle-seq>` fence is also evaluated inside the registry's per-Lane
4723 lock rather than before it, so a stale fence refuses without running Runtime
4724 teardown instead of racing between the check and the stop (#1888).
4725
4726 - `/lane` no longer runs Runtime teardown on the TUI composer thread. Reads on
4727 the slash surface skip reconciliation (which probes tmux and takes a lock)
4728 and say so on the receipt instead of implying freshness; `lane interrupt` is
4729 CLI-only until that work runs off-thread, and reports
4730 `surface_not_supported` naming `codewhale lane interrupt` (#4022).
4731
4732 - The hotbar is no longer modelled as a third control surface. A slot binds a
4733 slash command and fires it with no argument, so it runs *as* the slash
4734 surface; the contract now declares which verb a bare press actually reaches
4735 (`hotbar_bare_dispatch`, true only for `lane.list`) instead of advertising
4736 target-taking verbs as hotbar-reachable (#1888).
4737
4738 - `codewhale lane list --json` and `lane status --json` keep emitting the
4739 `LaneRecord` shape they always have — the receipt did not replace it. The
4740 human `lane status` output also regained `branch`, `session`, `socket`,
4741 `attach`, and `log`, which the first cut of the shared DTO had dropped
4742 (#1888).
4743
4744 - No surface advertises a backend it does not have. `lane restart` and
4745 `lane resume` have no implementation — a Lane is re-created by
4746 `codewhale lane start`, and a stopped Lane's Runtime session is gone — so all
4747 three surfaces refuse them with `backend_not_implemented` and say why.
4748 `fleet restart` drives the manager loop to completion, which only the CLI
4749 runs, so `/fleet restart` reports `surface_not_supported` and names the CLI
4750 command rather than quietly doing a smaller thing (#1888).
4751
4752 - Deny rules in `permissions.toml` no longer miss a command because of an
4753 intervening flag: deny matching is token-based with flag-skipping and
4754 backtracking, so a `git push` rule still catches
4755 `git -c foo=bar push`. Path matching folds case only on platforms whose
4756 filesystems are case-insensitive, and the default approval branch no
4757 longer proposes the working directory as a network host.
4758
4759 - MCP tool calls run once. A failed call is no longer retried as if it
4760 were a failed lookup, qualified-name resolution collects every match and
4761 reports an ambiguity instead of taking whichever the hash map yielded
4762 first, and registering a server whose name collides with an existing one
4763 after sanitization is now an error rather than a silent overwrite.
4764 The equivalent call-once fix direction came from closed PR #4756 by
4765 @adity982.
4766
4767 - The session index survives a torn line: an unparseable entry is skipped
4768 rather than aborting the whole read, appends carry their data through to
4769 disk, and appends and compaction share a lock so a compaction can no
4770 longer race an append into a lost record.
4771
4772 - `Edit` counts as a write tool for workflow elevation, and the TUI's
4773 write/shell classification now delegates to one shared allowlist rather
4774 than keeping a second copy that could drift.
4775
4776 - A rejected `app/config/set` stays a no-op. Previously an invalid value
4777 still tore down the cached runtime bridge, killing the child runtime and
4778 orphaning every other in-flight stdio thread behind a response that
4779 correctly reported failure.
4780
4781 - A malformed project `config.toml` is no longer indistinguishable from
4782 having no project config. Because a project config may only *tighten*
4783 approval and sandbox policy, silently discarding a broken one dropped a
4784 repository's restrictions back to the looser user defaults; the setup
4785 wizard now says so, naming the file but never quoting its contents.
4786
4787 - An expired lane worktree no longer leaves its branch behind, which made
4788 reusing the same lane name fail with "branch already exists". A branch
4789 still carrying unmerged commits is kept — a TTL lapsing is not consent
4790 to delete someone's work.
4791
4792 - An in-flight `thread/message` turn can be stopped. The stdio loop keeps
4793 reading while a turn streams, so the new `thread/interrupt` request (and
4794 `shutdown`) can reach a runaway turn instead of waiting on the very turn
4795 they were meant to stop.
4796
4797 - Precedence is stated only in the constitution's "Whose word wins" section.
4798 Memory hygiene no longer ships an inverted Tier list that put the
4799 constitution above the user's current request; approval, compaction, and
4800 personality overlays describe behavior without rank vocabulary; and the
4801 authority recap points at the single source rather than restating a second
4802 ladder.
4803
4804 - `<turn_meta>` carries facts (mode, posture, model, workspace), not mode
4805 doctrine or permission-question essays re-asserted every user message.
4806
4807 - The project context pack (pretty-printed workspace tree) is off by default
4808 and opt-in via `[context] project_pack = true`. Language law is compressed
4809 while keeping the English-constitution / user-language-reply contract.
4810
4811 - Modal lists and config pickers wrap selection at both ends (Down past the
4812 last row returns to the top). Home-directory resolution prefers
4813 `HOME`/`USERPROFILE` via `effective_home_dir` across remaining call sites so
4814 Windows tests that fake the home env vars match production paths. The
4815 equivalent home-directory sweep came from closed PR #4760 by
4816 @EvanProgramming.
4817
4818 ### Changed
4819
4820 - Prefix-cache tool catalog entries store only the SHA-256 digest, not the
4821 joined catalog string. Unused plan-transition validation helpers are removed.
4822
4823 - Settings sections now hold only what they claim (#4751). Fleet keeps
4824 Fleet/member concerns; `/goal` moved to a **Session** section and Workflow
4825 orchestration to its own **Workflow** section. The inert DeepSeek-only
4826 `default_model` fallback moved out of Model settings into an explicit
4827 **Legacy** section — exact-Fleet users switch Fleets, not fallback models;
4828 the config field is retained because the runtime still reads it. This is
4829 presentation only: the persisted keys (`goal_command`, `workflow`,
4830 `default_model`), their values, scopes, and runtime behavior are unchanged.
4831
4832 - Auto model routing is scoped to the active provider. The classifier
4833 inventory no longer discloses other providers' runnable routes (or the fact
4834 that their credentials exist), a classifier reply naming another provider is
4835 refused, the local heuristic no longer falls back to a different provider
4836 when the active one is unusable, and the implicit DeepSeek-flash classifier
4837 is skipped for non-DeepSeek sessions. Auto receipts and the model picker
4838 hint report the active-provider-only scope instead of "runnable providers".
4839 Cross-provider Auto is available only through the persisted `[auto]
4840 cross_provider = true` opt-in (an explicit `[auto.router]` route remains its
4841 own opt-in for the classifier call). Same-provider strong/fast selection and
4842 `[auto] cost_saving` are unchanged.
4843
4844 - The QA pseudo-terminal acceptance harness now parses frames with `rio-vt`
4845 behind its existing neutral frame/color surface, retaining the assertions
4846 while removing the `vt100` dependency (PR #4931 by @raphamorim).
4847
4848 - Anthropic Messages and OpenAI Responses stream opening now share the
4849 `client/stream_entry.rs` seam already used by Chat Completions: one bounded
4850 response-header wait, shared dual/HTTP-1.1 policy selection, at most one
4851 HTTP/1.1 fallback on a classified HTTP/2 header stall, and common idle-timeout
4852 diagnostics. Wire-specific authentication, headers, endpoints, decoding, and
4853 rate-limit behavior remain at each adapter edge. The timeout-placement
4854 diagnosis and fix direction came from closed PR #4743 by
4855 @vibecoding-skills.
4856
4857 ### Security
4858
4859 - Release containers now publish an SBOM attestation and pin maximum-mode
4860 provenance explicitly so supply-chain metadata cannot silently weaken with a
4861 builder-default change (PR #4958 by @kobihikri).
4862
4863 ### Contributors
4864
4865 Thank you to the contributors whose code, reports, and reviews shaped v0.9.2:
4866
4867 - [@greyfreedom](https://github.com/greyfreedom) — exact repository-scoped
4868 allow grants and cross-platform path semantics (PR #4761), plus safe
4869 permission-rule listing and snapshot-bound removal (PR #4960).
4870 - [@nightt5879](https://github.com/nightt5879) — off-event-loop clipboard
4871 writes (PR #4896), complete locale exposure in settings (PR #4856), CRLF-safe
4872 edits (PR #4942), and reasoning-effort preservation across automatic model
4873 routing (PR #4961).
4874 - [@XhesicaFrost](https://github.com/XhesicaFrost) — the configurable
4875 session-token header (PR #4610) and context-menu hover alignment (PR #4897).
4876 - [@cyq1017](https://github.com/cyq1017) — the hooks configuration/executor
4877 split from PR #4087.
4878 - [@snail-vs](https://github.com/snail-vs) (snailoniu) — OpenCode Zen's
4879 model-aware routes, authentication, documentation, and test isolation from
4880 closed PR #4467, whose contributor commits are preserved in the candidate.
4881 - [@SparkofSpike](https://github.com/SparkofSpike) — the zh-Hans translation
4882 quality review harvested from PR #4908, duplicate-session fix in PR #4963,
4883 LaTeX implementation from PR #4973 landed through #4974, and the context-menu
4884 reproduction in #4803.
4885 - [@GTC2080](https://github.com/GTC2080) — the request-preview concept from
4886 PR #1099.
4887 - [@h3c-hexin](https://github.com/h3c-hexin) — non-UTF-8 `fetch_url`
4888 decoding direction from PR #4909.
4889 - [@fleitz](https://github.com/fleitz) — required source-candidate credit for
4890 the canonical `Bash` no-`cwd` workspace fix and regression in PR #4673
4891 (issue #4674).
4892 - [@LmeSzinc](https://github.com/LmeSzinc) — the Windows CRLF `edit_file`
4893 reproduction, root-cause analysis, and affected-code anchors in issue #4764.
4894 - [@atmosuwiryo](https://github.com/atmosuwiryo) — ACP numeric-id compatibility
4895 (PR #4929) and the Indonesian documentation and website locale (PRs #4962
4896 and #4972).
4897 - [@M-Maciej](https://github.com/M-Maciej) — the expanded-by-default reasoning
4898 setting and its original report (PR #4928, issue #4925).
4899 - [@raphamorim](https://github.com/raphamorim) — migration of the QA PTY frame
4900 parser to `rio-vt` (PR #4931).
4901 - [@LI-Jialu](https://github.com/LI-Jialu) — truthful finalization of restored
4902 stale shell cells (PR #4937).
4903 - [@kobihikri](https://github.com/kobihikri) — release-container SBOM and
4904 explicit provenance mode (PR #4958).
4905 - [@EvanProgramming](https://github.com/EvanProgramming),
4906 [@adity982](https://github.com/adity982), and
4907 [@vibecoding-skills](https://github.com/vibecoding-skills) — equivalent fix
4908 direction for the effective-home sweep (#4760), MCP call-once behavior
4909 (#4756), and streaming/non-streaming timeout split (#4743).
4910 - [@antarikshraya](https://github.com/antarikshraya) — the LaTeX transcript
4911 rendering report in #4957.
4912 - [@eugenicum](https://github.com/eugenicum) — the token-header request and
4913 output-presentation measurements in #4520 and #4468.
4914 - [@whp233](https://github.com/whp233) — the StepFun/OpenCode subscription-route
4915 request in #4526.
4916 - [@redjade75723](https://github.com/redjade75723),
4917 [@hardy922](https://github.com/hardy922),
4918 [@JayBeest](https://github.com/JayBeest),
4919 [@elijahchan2019](https://github.com/elijahchan2019),
4920 [@cy2311](https://github.com/cy2311), and
4921 [@wywsoor](https://github.com/wywsoor) — reports and product direction behind
4922 the stale-workspace diagnosis (#4100), native-tool-token filtering (#3880),
4923 contributor onboarding (#4227), optional reasoning highlight (#4089),
4924 session control (#2934), and export/restore correlation (#2494).
4925
4926 ## [0.9.1] - 2026-07-24
4927
4928 ### Dogfood follow-ups (2026-07-24)
4929
4930 ### Added
4931
4932 - `/compact [focus]`: the manual compaction command now accepts an
4933 optional focus argument that is injected into the summary prompt, and
4934 the compaction summary itself becomes a structured nine-section
4935 successor briefing (primary intent, key concepts, files and code,
4936 errors and fixes, problem solving, user messages, pending tasks,
4937 current work, next step) that carries earlier compaction summaries
4938 forward and explicitly forbids tool use — replacing the free-form
4939 "under N words" instruction. Codewhale's pin/working-set and
4940 V4 prefix-cache-aligned machinery are unchanged.
4941
4942 - Saved workflows become slash commands: `*.workflow.js` files under
4943 `<workspace>/.codewhale/workflows/` and `~/.codewhale/workflows/` are
4944 discovered as `/name` commands that accept custom arguments (forwarded
4945 to the run's `args`), launch through the `workflow` tool in the
4946 background, and report their run id. Hand-written `.md` commands with
4947 the same name always win. The workflow tool's `source_path` now also
4948 accepts the user-global `~/.codewhale/workflows/` store, and every
4949 settled run leaves a durable synthesized report under
4950 `.codewhale/reports/<run_id>.md` (status, goal, gates, progress,
4951 result, verification).
4952
4953 ### Fixed
4954
4955 - Disambiguate the two Kimi K3 model-picker rows, which read as an
4956 unexplained duplicate: bare `k3` is now labeled "Kimi Code plan route"
4957 with its default 262K window annotated as the plan-tier floor (raisable
4958 via the provider `context_window` setting for plans that include 1M),
4959 and `kimi-k3` is labeled "Moonshot direct route" with its 1M window.
4960 Both remain distinct, valid routes for the same underlying model.
4961 - Close the model-facing `agent` tool role schema: the `type` property now
4962 publishes the canonical JSON Schema enum `["worker", "scout", "planner",
4963 "reviewer", "builder", "verifier", "custom"]` instead of describing the
4964 accepted values in prose. Legacy aliases are no longer advertised to
4965 models; they remain accepted only at replay/deserialization boundaries.
4966 Provider schema sanitizers (Chat Completions, strict mode, Anthropic
4967 Messages / OpenAI Responses, Moonshot/Kimi) are pinned by test to
4968 preserve the closed enum.
4969
4970 ### Changed
4971
4972 - Rework the ambient idle ocean: the water now holds exactly one loose
4973 wedge school of fish, jellyfish, bubbles, and the rare whale cameo —
4974 seaweed and bio-dust are removed. Fish swim on a wrap-around path and
4975 always face the way they move (direction can only change while the
4976 school is off-screen); the lead fish carries an eye (`><o>`).
4977 Jellyfish become a pulsing bell with a lagging swaying tentacle. All
4978 ambient marks now glow via background→ink color lerp: a travelling
4979 sin² wave through the school, a floor-bounded pulse for jellyfish,
4980 and occasional raised-cosine glints on bubbles, with deliberately
4981 non-matching periods so nothing strobes in sync.
4982
4983 - Rename the internal delegated-worker role type from `SubAgentType` to
4984 `FleetRole` with canonical variants (`Worker`, `Scout`, `Planner`,
4985 `Reviewer`, `Builder`, `Verifier`, `Custom`) matching the public Fleet
4986 vocabulary one-to-one. Wire behavior is unchanged: serialization emits
4987 canonical Fleet values only, and persisted `agent_type` fields plus
4988 documented legacy spellings (`general`, `explore`, `plan`, `review`,
4989 `implementer`, …) continue to load at deserialization/parse boundaries;
4990 unknown role tokens still fail closed with the canonical vocabulary in
4991 the error.
4992
4993
4994 The Codewhale v0.9.1 source candidate includes a first-class local web client over the Runtime API,
4995 first-class OpenCode Go and TelecomJS TokenHub providers and restored xAI device login,
4996 calendar-correct hourly automations, a buildable OpenHarmony workflow-js
4997 target, and hardening for Auto routing, remote-terminal clipboard transport,
4998 restart recovery, and a coherent TUI, Work, evidence, and public release
4999 surface.
5000
5001 ### Added
5002
5003 - Add `codewhale web [--port 7878]`, a first-class loopback-only browser
5004 client over the canonical Runtime API. The dependency-free embedded shell
5005 supports thread lifecycle, snapshot-then-SSE transcripts, turn start/steer/
5006 interrupt, approvals, and user questions, including pending-request recovery
5007 across tab reloads, while leaving unsupported managed,
5008 files, PTY, model-selection, and Fleet controls absent. Browser auth uses a
5009 short-lived one-time loopback capability exchanged for an opaque, bounded,
5010 process-local HttpOnly, SameSite=Strict session cookie with a same-origin
5011 mutation guard; Runtime tokens never enter URLs, HTML, browser storage, logs,
5012 or browser-launch arguments (#4423).
5013 - Add OpenCode Go as a first-class, subscription-backed Chat Completions
5014 provider with `[providers.opencode_go]`, `OPENCODE_GO_API_KEY`, and the eight
5015 models currently documented on its `/v1/chat/completions` endpoint. Models
5016 served only through OpenCode Go's Anthropic `/messages` endpoint remain out
5017 of this narrow route until Codewhale supports per-model wire selection
5018 (#1481 by @seanthefuturegorilla; implementation harvested from PR #773 by
5019 @zhangweiii and PR #1050 by @sternelee).
5020 - Add TelecomJS TokenHub as a first-class Chat Completions provider with
5021 `[providers.telecomjs]`, `TELECOMJS_API_KEY`, and a key-scoped live
5022 `/v1/models` refresh. Models.dev and provider-specific catalogs remain in
5023 separate source partitions so either refresh order preserves both; refreshes
5024 do not delete the other source's rows, matching model ids from unrelated
5025 providers do not fabricate metadata, and chat requests omit unsupported
5026 reasoning fields (PR #4370 by @baendlorel; harvested with co-authorship).
5027 - Prepare native Windows ARM64 `codewhale`, `codew`, and `codewhale-tui`
5028 binaries, npm selection, updater support, and standard/portable release
5029 archives. Build and smoke them on GitHub's native Windows 11 ARM runner,
5030 and move Linux ARM64 release builds to the native Ubuntu ARM runner to
5031 remove the slower multi-arch cross-link setup (#4267 by @w1w218).
5032 - `load_skill` tool now supports listing: omit `name` or pass `"list"` to
5033 see all available skills without loading one (#4651).
5034 - Add a unified `/skills` manager with one precedence-aware root catalog,
5035 bounded duplicate/shadow/conflict auditing, package provenance, and
5036 validated install, update, remove, and trust mutations (PR #4679 by
5037 @SamhandsomeLee).
5038 - Add a safe Agent Details view and bounded, structured `current_activity` to
5039 the single Work projection, sourced from worker events instead of renderer
5040 string inference. Rows stay compact, exact evidence is opt-in, and raw child
5041 output never enters the parent transcript (#2889 and #4636; design direction
5042 by @aboimpinto, preserved from #2694).
5043 - Make exact results and delegated coordination durable: non-inline tool output
5044 becomes immutable session-owned evidence behind bounded receipts; File
5045 mutations add configurable success-only diffs; and decisions and write
5046 contention survive restart with typed neutral-fan-in records (#4619, #4636,
5047 #4647).
5048 - Runtime API provider registry and atomic provider-switch endpoints
5049 (`GET /v1/providers`, `GET /v1/providers/{id}/models`,
5050 `POST /v1/providers/{id}/switch`) so the web GUI renders a dynamic
5051 provider/model picker without the setConfig+reload clobber (#4658).
5052 - Typed filter (`/`) in the Fleet setup wizard's Model step: substring
5053 match over provider id, display label, and model id keeps
5054 OpenRouter-scale catalogs navigable (#4639).
5055 - `[auto.router]` config: explicit provider/model/thinking for the Auto
5056 mode classifier route; unset keeps the DeepSeek flash default, and
5057 missing credentials fall back to the local heuristic.
5058
5059 ### Changed
5060
5061 - Keep the top activity bar literal and actionable: active To-dos appear first,
5062 followed by Sub-agents, while generic operations and coordination stay in
5063 the detail surface. Completed-only bars auto-hide, and top/side layouts can
5064 be resized by dragging their divider and retain the chosen size (#4700,
5065 #4702).
5066 - Use each theme's semantic colors for composer mode and permission rails, and
5067 show a larger inline reasoning preview with clearer local/full expansion
5068 affordances (#4699, #4701).
5069 - Simplify the model-facing runtime around stable action tools (`File`, `Git`,
5070 `Run`, deferred `Web`, and durable task and automation families), with legacy
5071 spellings hidden for replay. Fresh sessions no longer reserve a Work surface
5072 before real work exists (PR #4675).
5073 - Give the terminal shell one deliberate visual language: cool Plan → Act →
5074 Operate and warm Ask → Auto-Review → Full Access ramps match between header
5075 and split composer edges; transcript rhythm groups related activity; a
5076 refined whale keeps the empty state calm; and one-cell live motion with
5077 truthful labels distinguishes reasoning, reading, tool use, and verification
5078 without exposing private reasoning text. Reduced-motion and animation-off
5079 settings freeze it, while ASCII-safe terminals retain the signal (#4676,
5080 #4677).
5081 - Unified shell tool: the model now sees a single `Bash` tool with an `action`
5082 parameter (run/wait/interact/cancel). Legacy `exec_shell*` names remain as
5083 hidden compat aliases for transcript replay, and the tool-search catalog
5084 keeps `Bash` active by default (#4625).
5085 - Tool output inline preview increased from 6 to 12 lines (4 head + 4 tail)
5086 before the fold indicator; full pager (`v` key) unchanged (#4603).
5087 - Mode changes (`/mode agent|plan|operate`) now persist to `settings.toml`
5088 and restore across sessions (#4628).
5089 - Billing provenance: every outgoing API request carries an
5090 `x-codewhale-provenance` header with client version and provider (#4324).
5091 - The `/model` picker's typed search now ranks results: provider-name
5092 matches first (drill-down), then exact id, then id-prefix, then the
5093 active provider's rows (#4639).
5094 - System prompt text consolidated into a single `prompts/text.rs`
5095 module (byte-exact constants replacing 17 layered files);
5096 composition order, constitution-first binding, and locale/personality
5097 variants unchanged.
5098 - Ask, Auto-Review, Full Access, and Never resolve through one permission
5099 contract: `resolve_tool_permission` in the engine and
5100 `resolve_approval_request_disposition` in the UI share one truth table for
5101 session grants/denials, non-bypassable policy holds, and modal prompts
5102 (#4412).
5103 - Collapsed multi-struct tool families into single action-dispatched tools
5104 (`AutomationTool`, `TasksTool`, `GithubTool`, `RlmTool`) while keeping
5105 legacy tool names as hidden compatibility aliases for transcript replay.
5106 - Operate-mode children default to leaf depth (`max_depth=0`) unless the
5107 caller explicitly grants a deeper budget (#4598).
5108
5109 ### Fixed
5110
5111 - Restore `uwu` theme config round-tripping and keep header permission colors
5112 and authored idle-whale geometry aligned with the selected theme (#4696).
5113 - Default canonical `Bash` runs with no explicit `cwd` to the active
5114 `ToolContext.workspace`, including an isolated sub-agent worktree, instead of
5115 falling through to the shared shell manager's parent workspace. The regression
5116 test detects the selected workspace through marker files so it remains
5117 meaningful across PowerShell path spellings (#4674, PR #4673 by @fleitz).
5118 - Generate QuickJS bindings for `aarch64-unknown-linux-ohos` with the native
5119 SDK's libclang and sysroot, carry the OHOS target and sysroot through final
5120 linking, and keep unsupported persistent PTY dependencies out of the target
5121 while retaining non-PTY `exec_shell` support (#4470 by @shenjackyuanjie;
5122 original bindgen approach in #4384 by @shenyongqing).
5123 - Honor `[auto] cost_saving = true` in provider-aware heuristic and classifier
5124 routing, using only validated same-provider fast siblings and deriving
5125 fallback candidates from their actual provider so Auto cannot invent a
5126 cross-provider model. Providers without a known fast sibling stay on the
5127 active model (#4486; partial #4405).
5128 - Make terminal-client clipboard behavior truthful over SSH: use OSC 52
5129 outside tmux, stock `tmux load-buffer -w` inside tmux, and bracketed paste
5130 for client-to-remote text. Graphical text and image access now requires
5131 credible forwarding or an explicit override, transport failures no longer
5132 claim success, and help distinguishes terminal text paste from graphical
5133 image attachment (#4484).
5134 - Keep a fresh TUI Work surface from rendering prior-session worker snapshots
5135 or durable-task terminal receipts whose creation or completion predates the
5136 current app start. Active durable tasks remain visible, and shared history
5137 stays available through `/tasks` and archived agent views (#4488; partial
5138 #4416).
5139 - Make doctor and setup output distinguish static configuration, command
5140 availability, MCP protocol readiness, and backend health instead of
5141 presenting configured routes as live-healthy. Ordinary doctor runs no
5142 longer wake loopback/self-hosted providers unless `--probe-local` is
5143 explicitly requested (#4485; partial #4406).
5144 - Serialize test-only configuration-path readers with temporary environment
5145 redirects so the Windows provider-persistence matrix cannot observe another
5146 test's transient `CODEWHALE_HOME` or config path (#4483, closing #4463).
5147 - Restore direct Moonshot `kimi-k3` to its documented 1,048,576-token
5148 context window and 131,072-token output limit instead of treating the live
5149 model as an unknown legacy 128K route. The existing Kimi Code tiered `k3`
5150 route and credential reuse remain unchanged (#4481).
5151 - Keep read-before-edit snapshots in the engine session so a file read remains
5152 valid across turns and context compaction, while a new session still starts
5153 with an empty tracker (#4475 by @Angel-Hair).
5154 - Make `apply_patch` expose the canonical `replace` operation while continuing
5155 to accept deprecated `changes` payloads through one validation path. Mixed
5156 patch, replace, and compatibility modes now fail before any write (#4476 by
5157 @Angel-Hair).
5158 - Show the prompt-cache hit rate in the phase strip when the Cache status item
5159 is enabled, using overflow-safe rounded integer math and leaving compact or
5160 disabled status layouts unchanged (#4474 by @dmitri-0).
5161 - Preserve Solarized Light's canonical Base3 (`#fdf6e3`) shell background
5162 instead of tinting it green-grey through the default underwater Ombre
5163 treatment, while retaining foreground ambient life (#4457 by
5164 @AiurArtanis; PR #4471 by @nightt5879).
5165 - Register `/slop` and `/canzha` as compatibility aliases of `/debt`, while
5166 keeping user-command ownership truthful across dispatch, help, slash
5167 completion, alias copy, and typo suggestions (PR #4680 by @nightt5879).
5168 - Fail closed on legacy Kimi CLI credential imports: remove Codewhale's
5169 hard-coded first-party-client impersonation and refresh request, never
5170 auto-enable or rewrite imported credentials, and label the compatibility
5171 route as a read-only imported token. An explicitly configured, still-valid
5172 access token remains usable until expiry; missing, malformed, and expired
5173 imports recover through the supported Kimi Code API-key route while
5174 first-class OAuth awaits Codewhale's own vendor registration (#4417,
5175 partially addressed).
5176 - Restore xAI/Grok device-code OAuth login against the live xAI OIDC
5177 contract: discovery with issuer/endpoint validation and documented
5178 fallbacks, user-principal scope set, RFC 8628 `slow_down` backoff capped at
5179 code expiry, bounded, sanitized error reporting for denial, expiry, and
5180 malformed responses, and a shared blocking-worker boundary for both CLI and
5181 TUI login so reqwest's blocking client never creates or drops its private
5182 runtime inside Codewhale's Tokio runtime (#4410).
5183 - Anchor `FREQ=HOURLY` automations with `BYHOUR`/`BYMINUTE` to persisted
5184 local-calendar slots so intervals keep their wall-clock phase across DST,
5185 restart, resume, RRULE updates, duplicate-slot recovery, and post-run
5186 advancement. Nonexistent clock slots are skipped and ambiguous slots run at
5187 their first occurrence (#4381 by @h3c-hexin).
5188 - Give content-watch drafts canonical identities: the link and semantic-drift
5189 watchers now write and dedup through one canonical draft-storage key with
5190 deterministic hash-suffixed IDs, validate and bound model drift output
5191 before any KV writes, and show truthful admin draft labels, so unchanged
5192 findings dedup and changed findings re-draft instead of colliding (#4453).
5193 - Make model-policy JSON repair consider object and array payloads in source
5194 order, matching nested delimiters across quoted strings and escapes and
5195 returning the earliest balanced candidate that parses, instead of letting
5196 an unmatched opening delimiter or object-first preference corrupt array
5197 payloads (#4430).
5198 - Convert persisted sub-agent completion and still-running control events into
5199 concise, non-authoritative resume checkpoints, keeping their raw runtime
5200 envelopes, sentinels, and retry instructions out of restored model and TUI
5201 conversation state (#4409).
5202 - Deliver failed, stopped, and stale sub-agent outcomes exactly once to the
5203 awaiting parent, lifecycle mailbox, and TUI before closing their runtime
5204 state. Restart now reconciles orphaned queued/model/tool-wait worker records
5205 to interrupted while preserving checkpoints, and cancelled workers no
5206 longer read as completed in the TUI (#4408).
5207 - Give host applications a cancellation boundary for MCP OAuth login so a
5208 stalled or abandoned provider login no longer hangs the calling session
5209 (#4380).
5210 - Avoid blocked reader joins after Windows process kills so terminated shell
5211 sessions cannot hang their readers (#4383).
5212 - Give stdin-less observer hooks immediate EOF and contain timed-out hook
5213 process trees so descendants and pipe readers cannot leak after the parent
5214 shell exits (#4489 by @luismateusvargas).
5215 - Preserve the full unsigned Windows PTY process status instead of collapsing
5216 every high-bit exception or NTSTATUS to `2147483647`, including decimal and
5217 hexadecimal diagnostic metadata for device retests (#4100 by
5218 @redjade75723).
5219 - Keep the Hotbar Setup action list synchronized with keyboard focus when the
5220 selection moves beyond the visible rows, including Down past `/export`
5221 (#4418).
5222 - Route Windows OpenHarmony Cargo links through the repository's target-aware
5223 clang launcher so the final Rust link keeps its target, sysroot, and MUSL
5224 flags, and extend the no-SDK release guard to protect that contract. This
5225 completes [@shenjackyuanjie](https://github.com/shenjackyuanjie)'s PR #4470
5226 setup alongside [@shenyongqing](https://github.com/shenyongqing)'s original
5227 bindgen approach in PR #4384.
5228 - Reconcile the website roadmap with reality: the retired share-link
5229 direction is now an explicit non-goal, Workrooms is the considered
5230 direction, and the local web client appears as underway, in English and
5231 Chinese (#3418).
5232 - System-prompt skills block and skill-load warnings no longer embed absolute
5233 home/workspace paths; entries render workspace-relative or `~/…` so the
5234 byte-stable prompt prefix never leaks private paths. A new invariant test
5235 guards absolute paths, API keys, and workspace paths in the prefix (#4632).
5236 - Mode/permission baseline unit tests no longer read the developer's live
5237 `settings.toml`; they isolate config I/O to a temp directory (#4628).
5238 - Enter no longer freezes the composer on send: dispatch splits into a
5239 sync prepare phase (instant history + spinner) and a spawned async
5240 phase (auto-route, preflight, engine send), with submits gated while
5241 a dispatch is in flight (#4605).
5242 - Self-hosted routes keep explicit per-model output limits for unknown
5243 wire aliases instead of the generic 4K fallback (#4655 by @h3c-hexin;
5244 PR #4656).
5245 - Chat Completions idle-timeout errors now include received-byte and
5246 timing telemetry, distinguishing prefill stalls from mid-stream
5247 stalls with truncated tool-call arguments (#4657 by @h3c-hexin).
5248 - `set_config` provider writes now keep the in-memory route in step,
5249 so a following model write lands in the new provider's table instead
5250 of clobbering the previous provider's root default_text_model (#4658
5251 by @gaord, with a follow-up route-sync fix).
5252
5253 ### Security
5254
5255 - Restrict cross-origin Runtime API browser preflights to the documented
5256 authentication and content headers, explicitly allowing `Authorization`
5257 instead of relying on a wildcard (#4454).
5258
5259 ### Contributors
5260
5261 Thank you to the contributors whose code, reports, and reviews shaped v0.9.1:
5262
5263 - [@h3c-hexin](https://github.com/h3c-hexin) — calendar-anchored hourly
5264 automation recurrence (PR #4381), the MCP OAuth cancellation report
5265 (#4380), explicit limits for unknown local models (PR #4656 / #4655),
5266 and idle-timeout progress telemetry (PR #4657).
5267 - [@gaord](https://github.com/gaord) — Runtime API provider registry and
5268 atomic provider-switch endpoints (PR #4658).
5269 - [@SamhandsomeLee](https://github.com/SamhandsomeLee) — the unified `/skills`
5270 root catalog, audit/provenance model, validated mutations, manager UI, and
5271 acceptance coverage (PR #4679), plus Enter-send lag diagnosis and fix
5272 direction for #4605 (PR #4654; landed via the release-lane async-dispatch
5273 split).
5274 - [@aboimpinto](https://github.com/aboimpinto) — the Layer 5.1 user-command
5275 registry boundary from PR #3278; the exact authored evidence commit from PR
5276 #4046, preserved intact in the integration graph; and the #2870 follow-up
5277 audit whose metadata and malformed-sibling gaps shaped the final corrections.
5278 Paulo also provided the structured, redacted Agent Details and
5279 `current_activity` direction preserved from #2694/#2889 and the real-PTY
5280 lifecycle acceptance direction from #2886.
5281 - [@baendlorel](https://github.com/baendlorel) — TelecomJS TokenHub provider
5282 support and key-scoped live-catalog direction from PR #4370, harvested into
5283 the current provider architecture with co-authorship preserved.
5284 - [@zhangweiii](https://github.com/zhangweiii) and
5285 [@sternelee](https://github.com/sternelee) — the original first-class
5286 OpenCode Go implementations (PRs #773 and #1050), harvested into the
5287 current provider architecture.
5288 - [@seanthefuturegorilla](https://github.com/seanthefuturegorilla) — the
5289 canonical OpenCode Go/Zen provider request and acceptance direction
5290 (#1481).
5291 - [@nightt5879](https://github.com/nightt5879) — `/debt` compatibility aliases
5292 with dispatch-consistent user-command shadowing across discovery surfaces
5293 (PR #4680), plus the Solarized Light background preservation fix (PR #4471).
5294 - [@AiurArtanis](https://github.com/AiurArtanis) — the Solarized Light
5295 regression report and reproduction (#4457).
5296 - [@shenjackyuanjie](https://github.com/shenjackyuanjie) — the HarmonyOS
5297 workflow-js bindgen, portable-pty gating, and SDK environment work
5298 (PR #4470).
5299 - [@shenyongqing](https://github.com/shenyongqing) — the original HarmonyOS
5300 bindgen approach (PR #4384), carried into the landed implementation.
5301 - [@luismateusvargas](https://github.com/luismateusvargas) — the Windows hook
5302 process-leak reproduction, process-tree analysis, and EOF fix direction
5303 (#4489).
5304 - [@redjade75723](https://github.com/redjade75723) — the persistent Windows PTY
5305 report that exposed lossy high-bit process-status handling (#4100).
5306 - [@w1w218](https://github.com/w1w218) — the Windows ARM64 release request and
5307 real-device motivation (#4267).
5308 - [@Angel-Hair](https://github.com/Angel-Hair) — session-owned read-before-edit
5309 tracking and the explicit, backwards-compatible `apply_patch` replacement
5310 contract (PRs #4475 and #4476).
5311 - [@dmitri-0](https://github.com/dmitri-0) — configurable cache-hit visibility
5312 in the phase strip (PR #4474).
5313 - [@fleitz](https://github.com/fleitz) — the canonical `Bash` no-`cwd`
5314 workspace fix and regression test that keep isolated sub-agent commands in
5315 their own worktree (PR #4673, closing #4674).
5316 - [@SparkofSpike](https://github.com/SparkofSpike) — the Windows Ctrl+O
5317 reproduction that exposed pre-pager result truncation and conflicting composer
5318 shortcut routing (#4482), and the exact Vim-space regression reproduction
5319 verifying the v0.9.1 input path already contains the needed global binding
5320 (PR #4477).
5321
5322 ### Security
5323
5324 - Harden the public community-site boundary: scheduled review drafts now use
5325 one canonical freshness namespace, admin discard is restricted to validated
5326 draft objects, public feed requests cannot spend the server-held GitHub
5327 token, and maintainer login bodies are type- and size-bounded before parsing.
5328
5329 ## [0.9.0] - 2026-07-16
5330
5331 Codewhale v0.9.0 replaces the default terminal shell with the underwater
5332 interaction system, makes Operate message-first, and hardens the Fleet,
5333 Workflow, routing, accounting, and release surfaces that support day-to-day
5334 agent work. The release also expands localization and gives the public site a
5335 quieter, docs-first community foundation. Its provider work replaces the old
5336 hand-maintained picker boundary with live ProviderLake discovery and adds the
5337 largest curated model-and-pricing expansion in the project so far.
5338
5339 ### Fixed — final integration
5340
5341 - Redact configured, environment, file-backed, and bare active credentials
5342 from every tool result before it crosses any model-provider wire protocol;
5343 retrieved spillover content is sanitized again at that boundary. The
5344 `read_file` tool also refuses CodeWhale configuration, backup, and
5345 credential-store paths, preventing routine tool use from exposing those
5346 local files.
5347 - Keep immediate TUI submit failures inside the shell: custom-provider route
5348 preflight and closed-mailbox errors now restore the exact composer draft and
5349 selected skill for retry, with a sticky visible error instead of exiting.
5350 - Anchor automatic compaction thresholds to the route's spendable input
5351 budget after output reservation and safety headroom, so large-output and
5352 tight self-hosted routes compact before provider context rejection. The TUI
5353 pre-send gate and warning copy now use the same token threshold as the
5354 engine. Preserve the 262K Kimi route's usable input budget and use the
5355 documented 32K default generation budget instead of mirroring the context
5356 window as output (#4293 by @SamhandsomeLee, #4368 by @bruce6135, and #4378
5357 by @mvanhorn).
5358 - Fail closed instead of reporting base-rate dollar estimates for direct OpenAI
5359 GPT-5.4/5.4 Pro, GPT-5.5 (including dated snapshots), and GPT-5.6
5360 Sol/Terra/Luna requests above 272K input tokens. Exact tiered accounting
5361 remains deferred to the generalized pricing schema; smaller 5.4 variants,
5362 GPT-5.5 Pro, Codex subscription, and foreign-provider routes are unchanged
5363 (#4317).
5364 - Retire `deepseek-chat` and `deepseek-reasoner` before they reach DeepSeek's
5365 first-party OpenAI or Anthropic wire APIs, migrating both to the documented
5366 `deepseek-v4-flash` replacement while preserving legacy non-thinking /
5367 thinking intent when no explicit reasoning tier is set. Aggregator, Wanjie
5368 Ark, self-hosted, and custom endpoint model ids remain provider-owned (#4320).
5369 - Make Operate a message-first multitask surface: ordinary prompts work without
5370 a Workflow, direct parent tools follow the same approval, sandbox, shell,
5371 ask-rule, and repository protections as Act, and follow-ups can queue while
5372 work is active. Bounded background workers remain preferred for independent,
5373 parallel, isolated, or long-running work; child handoffs cannot inherit
5374 standing Full Access, and each dispatch produces one durable completion
5375 receipt.
5376 - Let personal Fleet profiles in `CODEWHALE_HOME/agents` travel across
5377 repositories while project profiles in `.codewhale/agents` override them.
5378 Saving refreshes the live roster, and the UI now says explicitly that profile
5379 availability does not expand workspace, trust, or filesystem authority.
5380 - Move file-mention discovery onto one bounded, generation-safe background
5381 worker so a slow filesystem read cannot freeze composer input. Exact paths
5382 resolve on send; fuzzy matches stay in the completion popup instead of
5383 silently attaching an arbitrary same-name file (#4365 by @WavesMan, with the
5384 initial bounded-walk approach from #4367 by @LeoLin990405).
5385 - Keep the opt-in `remember` tool in the model-visible first-turn catalog so
5386 durable preference capture works without requiring a model to discover a
5387 tool it cannot yet know exists (#4373 by @Angel-Hair and #4377 by
5388 @mvanhorn).
5389 - Make `review` handle a staged snapshot relative to a base ref by comparing
5390 the branch merge-base tree with the index. This preserves committed and
5391 staged branch work, excludes unstaged edits, and avoids the invalid
5392 `git diff --cached <base>...HEAD` form.
5393 - Honor each MCP server's advertised discovery capabilities before calling
5394 optional tools, resources, templates, or prompts; keep optional probes
5395 independently bounded and fail-soft (#4308 by @nsfoxer).
5396 - Make offline `scorecard` pricing provider-aware: `turn_end` records carry the
5397 effective route and a non-secret billing surface, runtime exports and
5398 supported aliases ingest cleanly, legacy/unknown routes remain explicitly
5399 unpriced, and route-scoped cache and recorded-time pricing replace model-only
5400 guesses. Historical runtime aggregates use each turn's recorded time;
5401 costless catalog routes fail closed while exact provider-owned hand-price
5402 rows remain available. StepFun PAYG and Step Plan usage now stay distinct
5403 without persisting raw endpoint URLs, so subscription quota is never reported
5404 as token spend (#4335). Completion-only shell, manual-compaction, and purge
5405 events remain visible to `turn_end` observers as explicitly non-model
5406 lifecycle records. This builds on the scorecard introduced by @findshan in
5407 #3388.
5408 - Preserve named custom-provider identity across TUI sessions, `exec --resume`,
5409 runtime threads, exports, cache and Workflow receipts. Restores resolve the
5410 saved provider against live configuration before creating a client, never
5411 infer a provider from the model ID, and fail closed when the named route was
5412 removed, invalid, or ambiguous (#4334).
5413 - Bind credentials to the endpoint that owns them. Environment-selected custom
5414 hosts can no longer inherit saved provider keys, keyring entries, OAuth, or
5415 ambient provider variables; only an explicitly source-marked CLI key may
5416 follow an explicit CLI endpoint override. `auth_mode = "none"` also strips
5417 credential-shaped custom headers consistently in the TUI and app server,
5418 while keyless loopback routes remain usable as local runtimes.
5419 - Make hosted runtime threads deterministic and provider-exact: serialize
5420 thread, turn, and event mutation; keep cancellation ownership with the host;
5421 preserve the selected provider through every durable turn; terminalize
5422 exceptional streams once; and prevent the runtime manager from silently
5423 dispatching unclaimed goal continuations or child turns.
5424 - Treat required user confirmation as a real goal blocker instead of a failed
5425 goal, and explain how to recover when a previously cached approval is denied.
5426 Cached-denial recovery is also committed as a settled transcript receipt, so
5427 tool completion or a later status update cannot erase it from scrollback or
5428 accessibility output. The notice now describes matching, process-scoped
5429 denials truthfully across all shipped locales; approval audits honor
5430 `CODEWHALE_HOME`, and expired status toasts cannot remain trapped behind a
5431 persistent entry. Both states remain visible and actionable instead of
5432 looking like unexplained model or tool failure (#4374 and #4375 by
5433 @Angel-Hair, with the final hardening in #4385 by @nightt5879).
5434 - Make Fleet launch and teardown deterministic: route flags are placed before
5435 `exec`, workers are contained in owned Unix sessions or Windows Job Objects,
5436 and cancellation reaps surviving descendants with bounded escalation before
5437 manager state settles. Fence progress, terminal status, verification
5438 receipts, and evidence by durable attempt generation so a stale process can
5439 never complete or overwrite a restarted attempt; terminal state and receipt
5440 now commit atomically, stale-heartbeat decisions use a full lease CAS,
5441 exhausted-retry alerts are exactly once, and crash-truncated ledger tails are
5442 quarantined before the next append. Standalone CLI and Runtime API restart
5443 controls now drive the replacement attempt through a real executor to its
5444 terminal receipt, while per-run manager ownership prevents concurrent
5445 controllers from launching the same attempt twice.
5446 - Keep the stopship Workflow fixture bounded to measured 24k-per-turn role
5447 budgets and a 360k aggregate. Authored child step and wall-time limits now
5448 reach the live runtime, including launch-queue wait; promoted evidence stays
5449 intact between roles, tool-free handoff consumers omit tool fields on the
5450 provider wire, and a terminal `BLOCK` fails the Workflow instead of producing
5451 a successful Lane receipt. Free-form descriptions no longer fabricate write,
5452 shell, or network risk; unknown structured risk remains fail-closed.
5453 - Keep repository trust affirmative and explicit: only `1`/`Y` are advertised
5454 as acceptance keys, while Enter remains non-affirmative and explains the
5455 required choice.
5456 - Replace literal legal and doctrinal metaphors in Simplified Chinese setup and
5457 `/constitution` copy with direct collaboration terminology reviewed by a
5458 native speaker (#4369 by @hmr-BH).
5459 - Keep the transcript reviewable while an inline approval card is active:
5460 Page Up/Down, modified arrows, Home/End, and the mouse wheel now move through
5461 the visible evidence without changing or dismissing the pending decision
5462 (#4371 by @amuthantamil).
5463 - Match generated worker names to the active UI language while preserving
5464 explicit user names, and tighten the 89x50 shell rhythm across Fleet rows,
5465 choice dialogs, transcript boundaries, and the idle composer.
5466 - Put docs content and search before the full index on small screens, reduce
5467 mobile dead space, and keep the public community copy focused on issues,
5468 pull requests, and international contributors.
5469
5470 ### Changed — the underwater shell
5471
5472 - Replace the default TUI shell with the underwater interaction system: one
5473 renderer owns the header, top work strip, transcript ledger, composer, and
5474 footer, with explicit compact/normal/wide tiers and no legacy sidebar or
5475 dashboard in the default path. The legacy composition survives only behind
5476 the internal `classic` treatment.
5477 - Add a distinct pre-session launch screen — new session, new worktree (with
5478 inline naming and real lane provisioning), scoped resume count, changelog,
5479 quit — with reliable non-colliding keys and row/keyboard parity.
5480 - Render turns as a ledger: user message, short narration, settled tool
5481 receipts, and exactly one live row. Fast tool bursts land directly as
5482 batch receipts (no spinner churn), completed receipts stay inspectable,
5483 failures hold a coral receipt with stderr one `v` away, and one shared
5484 tool rail replaces nested card borders.
5485 - Make completion a one-shot exhale: `working -> finishing -> done` in the
5486 footer only, with no transcript repaint, no lingering loop, and no stale
5487 cancel action in the completed state.
5488 - Rebuild the secondary rooms on one hairline grammar — config, setup,
5489 sessions, help, context, theme, model/route, Fleet, file attach — each
5490 with a title hairline, row objects with focus/selection/mouse parity,
5491 one panel-owned scroll rail, and wrapped action footers.
5492 - Make `/model` a model-first atomic route picker across configured
5493 providers: provider and model switch together on apply, and every row
5494 prints the resolved model. `/theme` gains a live preview with truthful
5495 Esc revert across all 12 shipped themes.
5496 - Add a live context inspector (Alt+C) backed by the current route: exact
5497 system/messages/free token buckets, a proportional map, drill-down into
5498 the detail pager, and no frozen session while it is open.
5499 - Project Workflow runs as an in-stream run map: a collapsed one-line card
5500 that unfolds into per-lane rows with role, resolved model, worktree,
5501 elapsed track, and per-member running/waiting/failed/cancelled/done
5502 states, plus gates and a debrief built only from real run data. Child
5503 transcripts never flood the parent shell.
5504 - Unify Fleet into roster/setup/workers rooms: the operator is pinned first
5505 with the live session route, members show resolved route truth (inherit /
5506 fast lane / pinned), and the workers tab is a control surface with
5507 row-local open/stop and real lifecycle counts.
5508 - Distinguish repository-law approvals from ordinary approvals: the
5509 constitution prompt names its authority, source, matched rule, and target,
5510 and Full Access never bypasses it. Ordinary approvals render as a still
5511 coral band above the visible transcript.
5512 - Keep streaming honest and cheap: provider-unit deltas replace per-grapheme
5513 queueing, the transcript is top-anchored so appended lines stop shifting
5514 settled rows, ambient animation stops during real work, and ordinary
5515 completion no longer triggers full-screen clears (verified by render-diff
5516 logs: suffix updates of tens of cells while streaming, zero periodic
5517 full repaints).
5518 - Give every underwater treatment ambient life: ombre breathes its water
5519 column while flat and Terminal-owned keep the idle fish and bubble
5520 (foreground-only for Terminal), a typed treatment setting replaces string
5521 comparisons, reduced motion freezes life legibly, `fancy_animations =
5522 false` stills the chrome, and typing scatters the fish immediately. Fish
5523 keep a one-cell gap from occupied text; the whale remains the single brand
5524 mark and returns to stillness between caustic sweeps.
5525 - Bring the whale mark to life with a soft diagonal caustic sweep, then let it
5526 genuinely rest. Active markers now share a smoother 8 Hz clock after the
5527 existing earned-motion delay, while reduced motion, hidden/off-screen views,
5528 modal ownership, and compact-terminal redraw budgets remain authoritative.
5529 The motion is adapted from the Apache-2.0 Grok Build interaction language,
5530 not copied as a global pulse or high-frequency receipt cascade.
5531 - Keep compact terminals operable: `/config` and `/resume` collapse
5532 secondary chrome before sacrificing their selectable rows at 40x12 and
5533 60x16, bodies budget for the footer's real wrapped height, and the
5534 selection stays visible through resizes.
5535 - Route footer notices through the classified toast system so informational
5536 acknowledgements (for example "Auto-compaction enabled") expire instead of
5537 becoming permanent idle chrome, while warnings and errors hold as sticky
5538 notices until their window passes.
5539 - Complete the `CODEWHALE_ASCII_SAFE=1` decorative tier: the whale mark,
5540 context meter, braille state markers (mapped by dot density so the working
5541 bubble still reads as a rising fill), bubbles, rails, and role/lane glyphs
5542 all narrow to semantic ASCII while user, model, and CJK text passes
5543 through untouched. Verified by whole-surface rendered-buffer sweeps.
5544 - Repair the Help catalog to match handler truth (`Alt+G`, `Alt+Shift+G`,
5545 `Alt+[`, `Alt+]`, `Alt+L`, `Alt+?`), and give theme, Help, model, and
5546 config rows direct mouse paths with the same activation as Enter.
5547
5548 ### Changed — integrated runtime and TUI
5549
5550 - Make worker delegation route-aware and identity-safe: workers receive a
5551 small role-scoped system prompt instead of stale parent/model boilerplate,
5552 faster routes resolve through the configured provider, and opening a worker
5553 shows its complete available transcript. Remove `token_budget` from the
5554 ordinary model-facing Agent schema so agents do not micromanage ad-hoc
5555 launches; explicit legacy calls remain readable for compatibility.
5556 - Mature `/config` interaction for enumerated and boolean settings with
5557 pickers/toggles, mouse-wheel scrolling, stable focus, and configured-provider
5558 selection. Startup mode is now only Agent or Plan; legacy `operate`/`yolo`
5559 settings migrate to Agent with permission posture represented separately.
5560 - Show where effective permission policy comes from and keep profile,
5561 environment, project, managed, and requirements-controlled posture read-only
5562 in the in-session editor. Runtime presets edit only proven user-owned root
5563 settings and no longer persist temporary environment overlays.
5564 - Restore the original four-line whale mark and make ambient ocean motion
5565 coherent across the full scroll surface: one continuous ombre, eased fish
5566 that face their direction of travel, fish in otherwise blank scrollback, and
5567 explicit reduced-motion and animation controls.
5568 - Keep model reasoning in the transcript rather than the Tasks strip, retain
5569 the live header status indicator, separate worker and success colors, and use
5570 the same rail grammar for both work-strip and transcript scrollbars.
5571 - Present the default Z.AI Coding Plan route, including child routes, as
5572 subscription quota instead of estimated per-token dollars. No undocumented
5573 account endpoint is called by this change.
5574
5575 ### Added
5576
5577 - Thinking Machines Lab's Inkling through Together using the exact wire model
5578 `thinkingmachines/inkling`, with `inkling` and `together-inkling` aliases and
5579 exact `none` / `minimal` / `low` / `medium` / `high` / `max` reasoning
5580 values. Codewhale does not invent a context window, price, or offline picker
5581 claim while the provider's public catalog metadata remains inconsistent.
5582 - Expand the verified offline catalog with Claude Sonnet 5, Claude Fable 5,
5583 GPT-5.3 Codex, and Qwen3.7 Plus, including time-aware Sonnet 5 introductory
5584 pricing and explicit cache rates. Refresh stale GLM-5.1, Kimi K2.6, Trinity,
5585 Qwen3.6, Nemotron, Anthropic, GLM-5.2, Kimi K2.7 Code, GLM-5 Turbo, and
5586 GPT-5 Codex price or limit rows; keep Xiaomi MiMo explicitly unpriced where
5587 the provider's token plan and pay-as-you-go surfaces cannot be distinguished.
5588 - MiniMax Messages provider support for MiniMax-M3 and MiniMax-M2.7, with
5589 OpenAI-compatible and Messages routes, regional endpoint guidance, request
5590 coverage, catalog limits, and tier-aware pricing (PR #4354 by @octo-patch).
5591 - Dynamic MCP server infrastructure and an approval-gated tool that lets the
5592 model start a configured MCP server from chat context. Harvested from
5593 #3869 and #3866 by @bistack with authorship preserved.
5594 - Parent `--disallowed-tools` restrictions now flow into sub-agents and Fleet
5595 workers by default, including deny-wins, wildcard, catalog-filtering, and
5596 multi-generation inheritance coverage. Harvested from #4096 by @JayBeest
5597 (#4042).
5598 - Korean (ko) UI locale with full key parity and onboarding/setup wiring
5599 (PR #4347 by @moduvoice).
5600 - Localize the entire underwater layer: 104 new UI strings — launch menu,
5601 phase words, mode/permission chips, footer hints, session picker, context
5602 inspector, route and theme pickers, Fleet roster, workflow status, sidebar
5603 work strip, repository-law approval copy, and file-attach titles — wired
5604 through MessageIds and translated into ja, zh-Hans, es-419, pt-BR, vi,
5605 and ko. Every complete pack now holds exact raw key parity with English
5606 (856 keys), enforced by new tests that the old English-fallback gate could
5607 not perform. The permission chip maps from typed state, so localization
5608 can never silently collapse it. Machine-authored translations follow each
5609 pack's existing terminology and are flagged for native review.
5610 - Anthropic adapter: sanitize top-level `oneOf`/`anyOf`/`allOf` in tool
5611 input schemas so affected tools no longer fail the whole request with
5612 HTTP 400 (PR #4346 by @qinlinwang).
5613 - Anthropic pricing: bill cache-write tokens at published rates
5614 (PR #4348 by @knqiufan, #4318).
5615 - NetBSD: generate QuickJS bindings at build time so `codewhale-workflow-js`
5616 compiles (PR #4349 by @ci4ic4).
5617 - Real-PTY release gates for six-worker fan-out liveness with Esc cancel,
5618 multi-terminal route isolation, queued steering via terminal-safe Ctrl+G
5619 (with Ctrl+S retained where the terminal forwards it), the one-shot
5620 completion footer, and per-theme ANSI output for every shipped palette.
5621
5622 ### Fixed
5623
5624 - Make release publication complete and source-anchored: every build checks out
5625 the resolved tag commit, tag movement is rejected before GHCR, GitHub
5626 Release, Homebrew, Cargo, or npm writes, and registry helpers require a clean
5627 checkout exactly matching the remote tag. Manual recovery runs are
5628 exact-tag-only and execute the same parity gate as automatic tag pushes.
5629 - Publish a coherent distribution set: both checksum manifests now contain
5630 usable public basenames and cover the full 29-asset matrix; GHCR, Homebrew,
5631 GitHub archives, and the Linux x64 CNB mirror carry `codewhale`, `codew`, and
5632 `codewhale-tui`. The CNB shortcut now fails clearly outside Linux/OpenHarmony
5633 x64 instead of promising assets that the mirror does not build.
5634 - Preserve task text when a skill is invoked through dollar, unified-slash, or
5635 explicit skill syntax, while keeping bare skill invocations and management
5636 subcommands intact (PR #4372 by @nightt5879, co-authored by @CCChisato;
5637 #3915).
5638 - Honor MCP server discovery capabilities: require advertised or legacy
5639 `tools/list`, keep optional resource/template/prompt probes independently
5640 bounded and fail-soft, and format descriptions Unicode-safely (#4308,
5641 harvested with co-authorship from @nsfoxer).
5642 - Age-evict terminal sub-agent worker records from the state ledger so
5643 long-lived, high-fan-out sessions do not keep rewriting multi-megabyte
5644 terminal history (#4217; root-cause and fix direction from @yekern).
5645 - Resolve the sub-agent completion/cancellation race with one terminal-state
5646 claim: cancellation suppresses late mailbox/parent/UI delivery, while a
5647 completed result remains publicly running until its notification is safely
5648 delivered.
5649 - Keep Workflow panel controls from stealing ordinary composer letters. Enter,
5650 Delete, Up/Down, and Esc own panel actions; typed characters return focus to
5651 the composer and start the message normally.
5652 - Preserve the composer prompt gutter from the first typed character through
5653 wrapping, scrolling, cursor placement, and mouse hit-testing so the `>` does
5654 not disappear or make input appear to jump.
5655 - Emit terminal-native OSC 8 metadata for rendered URLs without placing escape
5656 payload bytes in the measured text, keeping long links visible, selectable,
5657 and clickable in supporting terminals.
5658
5659 - Keep headless structured output terminal-clean: `codewhale exec` engines
5660 no longer emit interactive terminal-title/taskbar OSC sequences, so
5661 `--output-format stream-json` stdout stays parseable, escape-free JSONL.
5662 Interactive TUI sessions keep their terminal chrome.
5663 - Localization honesty: the parity gate was blinded by its own English
5664 fallback — two keybinding rows (`KbCyclePermissions`, `KbCycleThinking`)
5665 were missing from all five "complete" packs and now ship translated; the
5666 Operate-mode copy that drifted in English was retranslated in every pack
5667 (including zh-Hant's slice); three MessageIds absent from
5668 ALL_MESSAGE_IDS are visible to tests again; and the `/config`
5669 theme/locale hints and the invalid-locale error derive from the shipped
5670 registries instead of stale hand lists that advertised 4 of 12 themes
5671 and 4 of 8 locales.
5672 - The setup wizard's constitution step no longer claims a "55-line core"
5673 in any language (the bundled core is larger today); the guided draft says
5674 "the bundled core stays active" instead.
5675 - In-app selection copy is rail-clean and now regression-tested: copied
5676 transcript text excludes the `▎ ╎ │ ●` decorations via cache metadata
5677 (#4208 — thanks @eugenicum for the report and code-aware fix direction;
5678 terminal-native selection with mouse capture off remains a product
5679 decision on the proposed `rail_style` option).
5680
5681 ### Docs
5682
5683 - Stamp every 0.9-era roadmap document with an explicit status (current,
5684 historical, superseded, principle-only, or future RFC), correct trackers
5685 that recorded unshipped work as done, and describe what remains after
5686 v0.9.0 in `docs/AGENT_RUNTIME.md`.
5687 - Add `docs/rfcs/UNIFIED_PROVIDER_LOGIN.md`: one `codewhale auth login`
5688 surface for Anthropic, OpenAI Codex, and xAI, with the Anthropic adapter
5689 gated on verifying flow permissions before any constants are adopted.
5690 - Refresh `docs/ACCESSIBILITY.md` for treatment-independent ambient life
5691 and the completed ASCII tier.
5692
5693 ### Changed — runtime foundations
5694
5695 - Make the advertised Android/Termux release target buildable by generating
5696 QuickJS bindings against the Android NDK instead of expecting an upstream
5697 pre-generated `aarch64-linux-android` binding file, and give Android CLI/TUI
5698 HTTP clients a preconfigured rustls root store (Mozilla WebPKI roots) so
5699 standalone Termux processes stop panicking inside
5700 `rustls-platform-verifier`'s JVM expectations (#4236, #4242).
5701 - Rebalance the bundled Constitution after the v0.8.67 prompt ablation: keep
5702 the procedural policy tail in mode-specific layers, while restoring concise
5703 behavioral guidance for momentum, causal investigation, constraint-first
5704 decisions, mechanism-backed guarantees, and clean continuity.
5705 - Wire live catalog cache into provider/model pickers without dropping stale or
5706 prior rows after TTL expiry / refresh failure (#4139). Remove the dead
5707 `OFFERING_SEEDS` hand table so the bundled Models.dev catalog is the sole
5708 seed source; pickers show a compact `stale` / `cache failed` chrome chip when
5709 the Models.dev layer is past TTL or last refresh failed.
5710 - Make `work_update` the sole model-facing To-do / Work progress tool (#4132).
5711 `checklist_*` and `todo_*` remain registered as hidden compat aliases for
5712 transcript replay; `update_plan` stays Strategy metadata/context/route, not
5713 a second checklist. Mode/approval prompts nudge the single surface.
5714 - Demote the bundled Models.dev snapshot to an offline/stale fallback after
5715 live catalog refresh (#4188). ProviderLake precedence is live Models.dev >
5716 bundled seed > legacy hardcoded completion names; pickers, inventory, and
5717 subagent validation stay catalog-backed, and Codewhale-only providers keep
5718 defaults when Models.dev has no rows.
5719
5720 ### Added
5721 - Wire xAI device-code OAuth into `codewhale auth xai-device`, the TUI
5722 `/auth xai-device` command, and guided provider setup, with comment-preserving
5723 auth-mode persistence and loopback exchange coverage (#4257).
5724 - Add GPT-5.6 Sol, Terra, and Luna to the OpenAI API route, including their
5725 1.05M context metadata, 128K output limits, pricing, and `max` reasoning
5726 effort. Add Meta Model API as a first-class OpenAI-compatible provider for
5727 Muse Spark 1.1 with 1M context, tool/reasoning metadata, provider aliases,
5728 and both `META_MODEL_API_KEY` and Meta's `MODEL_API_KEY` credential names.
5729 - Catalog automation: `scripts/catalog_models_dev.py` refreshes secret-free
5730 Models.dev / OpenRouter listings and validates the offline seed snapshot
5731 (`snapshot --check`) without ever persisting API keys (#4117).
5732 - `/model` picker cycles six catalog views with `A` (Configured → Catalog →
5733 Recent → Coding → Cheap → Long context) and richer row metadata from the
5734 live/bundled catalog (context, max output, tools, reasoning, price/M,
5735 freshness). Discoverability views do not auto-apply a surprising route
5736 (#4115).
5737
5738 - Workflow runs are now durable: every run appends to a
5739 `.codewhale/workflow-runs.jsonl` journal and hydrates on startup, so
5740 `workflow status` survives restarts; runs left `running` by a dead process
5741 are recovered as failed (#4011). The transcript renders workflow tool
5742 output as a run card (status, goal, children, progress, verification)
5743 instead of a generic one-liner (#4038), and `workflow` accepts a `verify`
5744 flag that runs post-completion verification gates and fails the run when
5745 gates fail (#4013).
5746 - Hotbar sources for MCP tools and skills: MCP tool slots prefill the
5747 composer (execution stays behind the normal tool-approval flow) and skill
5748 slots activate through the existing `$skill` alias (#2068, #2069).
5749 - Mode & permission surface: Tab cycles Plan → Act → Operate; Shift+Tab
5750 cycles the Agent permission posture (Ask / Auto-Review / Full Access) with
5751 a footer permission chip; Ctrl+T cycles reasoning effort and Ctrl+Shift+T
5752 opens the live transcript overlay. Operate is the orchestration mode
5753 (delegate, wait, inspect, dispatch) and raises sub-agent fan-out while
5754 focusing the Agents sidebar.
5755 - Provider lake facade: the provider/model pickers, hotbar, and model
5756 inventory now enumerate configured providers' models from the bundled
5757 catalog (with an `A` toggle to browse the full catalog), replacing the
5758 hardcoded per-provider model table (#3830 follow-up).
5759 - Added Cursor-integrated-terminal dogfood evidence for the published v0.8.67
5760 release, covering installed binary provenance, release/publication checks,
5761 headless runtime smoke, setup QA, and remaining manual visual TUI checks.
5762 - README and README.zh-CN now point users to the community-maintained
5763 CodeWhale for VS Code GUI frontend while clarifying that this repository's
5764 `extensions/vscode/` scaffold remains the read-only Phase 0 viewer (#4035).
5765
5766 ### Fixed
5767
5768 - Sub-agent waiting no longer peek→sleep polls: `agent(action="wait")` joins
5769 children, unchanged peeks are throttled (~30s) with an anti-polling nudge,
5770 and mode prompts teach the join primitive (#4097). Harvested from PR #4098
5771 by [@Mr-Moon121](https://github.com/Mr-Moon121) (Jeffrey Luna).
5772 - `/provider` picker remembers catalog/configured view and highlighted row
5773 across reopen, matching `/model` picker memory.
5774 - Mode picker roster is exactly Act / Plan / Operate (no Multitask, no
5775 numeric `4`/`5` gaps). Legacy `yolo`/`4` remain invisible one-way
5776 permission shorthand for Act + Bypass.
5777
5778 - Fleet setup is a role/profile roster editor, not a provider-scoped model
5779 picker: the Model step lists routes from every configured provider (not
5780 only the active one), a picked route's provider is persisted explicitly in
5781 the saved profile TOML (`provider = "..."`, never inferred from the model
5782 id), and the loader/route resolver read that field back out verbatim. The
5783 draft-preview save keypress no longer competes with a separate pager's
5784 `g`/`G` scroll bindings — the exact TOML preview now renders inline on the
5785 same Review step that saves it (#4093).
5786 - `codewhale fleet run` and interactive in-process Fleet launches now honor a
5787 profile-pinned provider/model route instead of merely recording it on the
5788 receipt. Headless workers receive the non-secret `--provider` and `--model`
5789 pair; TUI workers resolve the same explicit route in process. Credentials
5790 still come from the worker's environment, provider is never inferred from a
5791 model id, and unpinned workers continue to inherit the run route (#4093,
5792 #4193).
5793 - The Fleet setup `m` model-assisted redraft no longer drops a picked
5794 cross-provider route: the provider/model the operator chose are re-pinned
5795 onto the drafted profile (a model draft is always `provider: None`), so
5796 saving it keeps the explicit route instead of persisting an ambiguous,
5797 provider-scoped profile (#4093).
5798 - Saving a Fleet profile now fails with a clear message when it pins a
5799 provider that has no configured credentials, using the same
5800 configured-provider check the model picker uses (#4093).
5801 - Workflow correctness: completion polling fails closed instead of
5802 fabricating success when a sub-agent reports no terminal status; cancel
5803 interrupts the JS VM (cancel handle + abort) and blocks further spawns;
5804 and `budget.spent()` reports real manager-scope usage instead of always 0.
5805 - Sub-agent spawns validate the model↔provider pair before dispatch:
5806 inherited/faster routes remap foreign models to the provider's catalog
5807 default, and explicit pins fail fast with a diagnostic instead of an
5808 upstream model-not-found error.
5809 - TUI stability: engine event drains break every 8–16 events / 8 ms to keep
5810 input live (#1830, #2317, #1198); the terminal input pump restarts after
5811 stall recovery on macOS/Linux too; the startup raw-mode probe no longer
5812 leaks raw mode on timeout; recovery snapshots persist every 45 s during
5813 long turns and the offline queue persists on every push (#1830);
5814 queue/steer paths surface toasts while streaming (#2317, #1338); and
5815 modal submit errors re-open the modal instead of being swallowed (#1198).
5816 - Core/state: paused jobs persist as paused across restarts; unarchive
5817 updates the in-memory cache; tool dispatch has a timeout; MCP
5818 notifications no longer receive responses; corrupted checkpoints surface
5819 errors instead of loading empty state; the session index compacts instead
5820 of growing unbounded; and recording thread-goal usage no longer
5821 self-deadlocks the state store.
5822 - Runtime compaction summaries are now persisted into `/v1` thread records so
5823 engine reloads and restarts preserve compacted context. Contributed by
5824 MXAntian (@MXAntian) (#4091).
5825 - The TUI leaves xterm alternate-scroll mode off when mouse capture is disabled,
5826 preserving native terminal text selection in light-theme/no-mouse-capture
5827 sessions. Contributed by Nightt (@nightt5879) (#4088, #4026).
5828 - The public `/api/github/feed` endpoint is now forced dynamic on Cloudflare so
5829 it returns live GitHub activity instead of a build-time empty feed.
5830
5831 ### Security
5832
5833 - Require bearer authentication for `/v1/chat/completions`, compare tokens in
5834 constant time, return accurate 4xx/5xx statuses, bound request bodies and SSE
5835 frames, redact secrets from stdio `config get`, and reliably reap the runtime
5836 child during shutdown.
5837 - Keep trust precedence and secret persistence fail-closed: user ExecPolicy
5838 rules outrank agent-layer rules, chained commands cannot propose unsafe
5839 trusted-prefix amendments, and config and secret writes are atomic with
5840 filesystem synchronization on every supported platform.
5841
5842 ### Changed
5843
5844 - Tool-hang watchdog trimmed from 15 minutes to 10 (#1862); approval modal
5845 footer hints use a higher-contrast tier (#3380); status/mode copy is
5846 disclosed once across header, footer, cards, and sidebar instead of
5847 repeated per layer.
5848 - Removed the unused `tui::whale_routes` taxonomy module and its tests.
5849 Contributed by Darrell Thomas (@DarrellThomas) (#4041, #3852).
5850
5851 ### Deprecated
5852
5853 - YOLO mode: `--yolo`, `default_mode = "yolo"`, and the hotbar YOLO action
5854 now map to Act + Full Access permissions via a compatibility shim and
5855 show a one-shot deprecation notice. Removal is deferred beyond v0.9.0 so
5856 this release does not break existing scripts without a dedicated cutover.
5857
5858 - Google Gemini is its own backend (`/provider google`) on the official
5859 OpenAI-compatible route with thought-signature capture/replay and
5860 fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) joins
5861 as a separate credential-plane provider: consent-gated read-only import
5862 of the official CLI's login with `ANTIGRAVITY_API_KEY`/`AGY_ADC_AUTH`
5863 precedence; requests fail closed until the cloud-code wire protocol is
5864 implemented.
5865
5866 ### Removed
5867
5868 - Remove the deprecated `deepseek` and `deepseek-tui` binary shims in this
5869 breaking release. `codewhale`, `codew`, and `codewhale-tui` are the supported
5870 entry points; existing DeepSeek provider support and legacy config/session
5871 migration remain intact.
5872
5873 ### Known issues
5874
5875 - Android/Termux arm64 remains a preview in v0.9.0. The target, asset wiring,
5876 updater selection, dependency graph, and source-build path have automated or
5877 static coverage, but shell/PTY/config/TUI startup and runtime behavior remain
5878 unverified on a real device (#4236, #4242). Do not use a GNU/Linux arm64
5879 archive in Termux.
5880
5881 ### Contributors
5882
5883 Thank you to the international community whose code, reports, reviews, and
5884 reproductions shaped v0.9.0:
5885
5886 - [@amuthantamil](https://github.com/amuthantamil),
5887 [@bistack](https://github.com/bistack),
5888 [@bruce6135](https://github.com/bruce6135),
5889 [@CCChisato](https://github.com/CCChisato),
5890 [@ci4ic4](https://github.com/ci4ic4),
5891 [@cyq1017](https://github.com/cyq1017), and
5892 [@DarrellThomas](https://github.com/DarrellThomas).
5893 - [@eugenicum](https://github.com/eugenicum),
5894 [@findshan](https://github.com/findshan),
5895 [@gaord](https://github.com/gaord),
5896 [@hmr-BH](https://github.com/hmr-BH),
5897 [@hongqitai](https://github.com/hongqitai), and
5898 [@idling11](https://github.com/idling11).
5899 - [@JayBeest](https://github.com/JayBeest),
5900 [@knqiufan](https://github.com/knqiufan),
5901 [@LeoLin990405](https://github.com/LeoLin990405),
5902 [@moduvoice](https://github.com/moduvoice),
5903 [@mvanhorn](https://github.com/mvanhorn),
5904 [@Mr-Moon121](https://github.com/Mr-Moon121), and
5905 [@MXAntian](https://github.com/MXAntian).
5906 - [@Angel-Hair](https://github.com/Angel-Hair),
5907 [@nightt5879](https://github.com/nightt5879),
5908 [@nsfoxer](https://github.com/nsfoxer),
5909 [@octo-patch](https://github.com/octo-patch),
5910 [@qinlinwang](https://github.com/qinlinwang),
5911 [@SamhandsomeLee](https://github.com/SamhandsomeLee), and
5912 [@taixinguo](https://github.com/taixinguo).
5913 - [@WavesMan](https://github.com/WavesMan),
5914 [@wuisabel-gif](https://github.com/wuisabel-gif), and
5915 [@yekern](https://github.com/yekern).
5916
5917 ---
5918
5919 Older releases: [CHANGELOG.md](https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md) and [docs/CHANGELOG_ARCHIVE.md](https://github.com/Hmbown/CodeWhale/blob/main/docs/CHANGELOG_ARCHIVE.md).
5920
5920 lines MARKDOWN