Skip to content

0.10.2 readiness: green main again, then release-blocking fixes - #6957

Merged
Hmbown merged 49 commits into
mainfrom
claude/nice-bohr-h4i23r
Oct 11, 2026
Merged

Hmbown merged 49 commits into
mainfrom
claude/nice-bohr-h4i23r

Conversation

@Hmbown

@Hmbown Hmbown commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

This is the 0.10.2 release-readiness branch from the cloud session. The founder chose one draft PR per repo. Every commit is a self-contained slice on top of main, which has been merged in as it moved.

Commit Slice Refs
db29e64 The config group's guard tests count /connect and /disconnect. main carries the same fix as 7be1f48, and the two merged cleanly. —
42c5dcc Snapshot restore and /undo work on git 2.43 (Ubuntu 24.04). That version rejects checkout --end-of-options <id> -- <paths>. —
8eb23ad + 17a88a9 A self-cancelled background job no longer wakes a turn. A job that had already exited keeps its real exit status instead of "Killed, exit 0". Only the model's own cancel suppresses the completion, and cancel-all skips jobs that already exited. —
d33dc38 + ed25a29 A command that moves to the background after 30 s shows the /jobs notice instead of the model-facing receipt. tty:true does not count as moved. —
7b1dcd3 todo_write answers the model with a short receipt. —
85063be Goal usage counts the turn that completes, yields or blocks the goal. —
407cb8e + 82bef73 update_goal accepts progress with yield, and the TUI shows that stage report. Covers the schema text, 12 re-recorded conformance goldens, and the measured +7 B runtime-contract ceiling. —
d438379 The pet shows sub-agents while they run and lets a finished one rest. —
985967e Crisp half-block sprites, re-vendored as codewhale-ratatui 0.1.2 (upstream codewhale-hq/codewhale-ratatui#27). —
674dcc3 A silent running shell stays "running · no output for …" and keeps its Stop action. /jobs poll and stdin no longer consume the model's output cursor. #6931
f7264f7 The Bash Job inspector follows a running job: it refreshes every 2.5 s through a bounded read, never consuming the model's cursor. It stays pinned to new output until you scroll back, and Stop goes away when the job ends. Alt+V goes back to the one rule the footer hint uses, so a running card no longer takes over the card you are reading. A click pins its owner cell, so collapsing tool runs or appended cells cannot move the target. #6931
8fa735e + e99934a /jobs wait and /jobs poll open the live inspector instead of blocking the UI loop for up to 5 s on the ShellManager mutex. Dock shell rows open that inspector too: projection stops copying full stdout and stderr on every pass, and right-click keeps Stop. Dock task rows run /task show instead of failing with "Job task_… not found". #6931
02fd463 wait on a running job adds "Progress: last output Ns ago; output phase: …". The /jobs cancel receipt and the completion the model receives after a person's cancel say whether build artifacts survive. Two comments that 34bf656 made false are fixed. #6944
28ea342 /setup u/d act only on the working-agreement step; elsewhere they no longer close the wizard and turn a ratified agreement off. Retired footer hints no longer run a locked settings.toml transaction on every Tab/Shift+Tab/Esc. —
41c44ee The never-set ChatGPT originator authorize parameter and its dead branch are gone. Stored credentials keep the field so old files still parse. #6925
0cbdb9b RS-12's last test-only edge (fleet → crate::Cli) moves to the CLI tests. The runtime-boundary ratchet goes from test 35 to 32, and the roadmap numbers follow. #6939
d40be2b Three locale strings that misdescribed what happens: the Korean Never chip, the language screen's /settings set locale (now /config locale <tag> --save, in all 15 packs), and the English elevation Abort ("Skip only this tool call"). —
4b7a623 File edits use the patch verb and show their change summary once. Tool status words come from one table (done, failed, loaded, not run), and a hydrated tool loses the done check. —
a4603c3 The approval card uses its existing translated labels and description in every locale, not only zh-Hans. A typed is_preview replaces the English label match. —
cad2c00 Ollama adoption continues onboarding. Retry receipts stay in the transcript instead of an 8 s red toast. A turn that ended in failure is Error live and on resume, including an upgraded stall cell. /setup stops saying "You're ready." without a model, and a rejected key's reason survives the 6-row cap. —
34d35fa Mode receipts, /overview and /setup say Work. /zidong names the Full Access it grants. /mode usage is [work|plan|operate|1|2|3]. —
e53972a Delegated-agent cards name the running tool instead of "Core tool ". —
619a6d9 Markdown headings need # and render inline markup. Tables draw one header rule and pad ragged rows. —
be6ed76, cf068be, 8fee238, f518a5c, 85331b5, 1f7ebc9, cadd721, ae17d53, 9413b15, 79735df Behaviour-preserving performance work from a judged audit: the context meter keeps estimates for the unchanged prefix; write_atomic sweeps stale temps at most hourly per directory; /v1/usage reads the turn store once; tool contexts share the turn-start history (Arc); one compaction-pressure walk per step and allocation-free JSON sizing; four redundant ocean passes dropped; sub-agent checkpoints project only the bounded tail; retention skips the late-usage overlay; the pet tick does nothing while no pet runs; no codewhale-tui doctest pass, and schemars/rusqlite move to dev-dependencies. —
2f82993 CHANGELOG bullets for the above, plus the synced TUI changelog. —
811b6ed The 0.10.2 notes gain a Known limits block: the Windows dead-owner refusal (#6915), idle CPU not measured on FreeBSD/Linux (#6728), Models.dev tier pricing after a live refresh (#6396), and delegated-agent shells outside the agent detail (#6931). Refs #6915, #6728, #6396
e107caf UX polish slice 2, needing no product decision. Chrome: readiness says "endpoint reachable"; /rc failed in Failure ink and /setup reading the typed remote status; the full-error hint only when hidden; one clipboard receipt plus a translated failure; the fallback toast survives at 80-100 columns; no '...' clipping; auto→high; a cleaner elevation card. Cards: no checklist tool-name row and translated statuses; failed read/search entries show their reason; body rows stop repeating the header; · affordances; MCP calls never collapse; humanized run names. —
e71255e + 625f25b /constitution fixes from the session-export review. Ratify checks the reviewed digest, and ratifying one at a time works. Preview matches the injected block. Cache wording is honest, the wizard's authority order is fixed, notes are no longer silently truncated, and zh-Hans uses 宪章. —
49bd217 + d220add + e2ee2d2 CHANGELOG, the synced TUI changelog, the features row, and 0.10.2 credit parity on the website and contributor page. —
210904f pet/scripts/check-shared.py sends the current appearance schema. Main's b0f9cbc added two always-serialized fields, which broke the macOS Pet conformance check. —

KV-cache

  • Only 407cb8e touches the model-visible catalog: one sentence in update_goal's progress description, +7 B measured. That changes the session-pinned prefix for new sessions only.
  • These are append-only history:
    • the todo receipt;
    • the constitution messages;
    • 02fd463's wait progress line;
    • its kill_note on Killed shell-completion handoffs, a user-role runtime message already in the session log.

Issue

Refs #6931
Refs #6944
Refs #6925
Refs #6939
Refs #6915
Refs #6728
Refs #6396

The other slices are session-export and release-readiness fixes with no issue of their own. None of the commits closes an issue on merge.

How I tested it

Local codewhale-tui lib test binary (Ubuntu 24.04, git 2.43), built from the branch through d220add plus the goal change:

  • Focused run over commands:: snapshot:: tools::shell tool_cancellation pet_watch core::engine tools::goal tools::todo tool_routing shell_job_routing task_projection work_surface setup:: tui::history:
    • test result: FAILED. 2764 passed; 1 failed; 5 ignored.
    • The one failure is tui::views::fleet_setup::tests::model_step_detail_shows_capability_badges_for_known_models_only. It depends on process-shared registry state in that single-process libtest run.
    • Alone it passes (1 passed; 0 failed), and so does its module (54 passed; 0 failed).
    • CI's nextest isolates each test, and this PR does not touch that code.
  • conformance::: 33 passed; 0 failed.
  • tools::goal: 36 passed; 0 failed.

Compile and static checks

  • cargo check -p codewhale-tui --lib --tests --locked: exit 0, 0 warnings, at d220add plus the goal change.
  • cargo fmt --all -- --check: clean at e107caf.
  • scripts/release/check-versions.sh: OK.
  • check-contributor-credit.py: passes.
  • Ratchets:
    • module_graph.py --check: PASS {prod 11, test 32, late 1, uilib 1} over 117 modules;
    • blocking calls: 538;
    • dead code: 221, at budget;
    • test_check_runtime_contract_budget.py: 22 OK;
    • all 15 locale packs parse.

Hosted CI on e99934a (run 38149284218):

  • Test (ubuntu-latest): 19036 tests run: 19036 passed (4 slow), 34 skipped. This includes live_shell_job_pager_follows_new_output_until_scrolled_back, ending_a_live_shell_job_drops_stop, silent_running_job_detail_reads_quiet_not_stale and the moved default_max_turns_does_not_add_a_hidden_worker_cap.
  • Test (windows-latest), Lint, MSRV and Safety gate: success.

Hosted CI on 2f82993 (run 38156029258), covering everything through the performance commits and the merged main:

  • Test (ubuntu-latest): 19032 tests run: 19032 passed (4 slow), 34 skipped. That is 4 fewer than before because four markdown helper tests were removed with the code they tested.
  • Lint, MSRV and Safety gate: success.

Slice 2 (e107caf) locally: clippy (tui + localization) 0 warnings; cargo test -p codewhale-localization: 54 passed; 0 failed.

Hosted CI on e107caf (run 38160307827), the current head and the release candidate SHA:

  • Test (ubuntu-latest): 19032 tests run: 19032 passed (4 slow), 34 skipped.
  • Test (windows-latest), Test (macos-latest), Lint, MSRV (1.89), Safety gate, Version drift, Integrations, npm wrapper smoke, mobile runtime smoke and the extension-host runtimes on all three OSes: success.
  • CodeQL (rust, python, actions, javascript-typescript), cargo-deny, cargo-audit and every npm-audit: success.
  • Main has moved one commit since then (91dbd4f, events conformance goldens; green on main). It merges cleanly into this branch (git merge-tree exit 0), so the release cut from main after this PR merges carries both.

Not covered by the local binary

  • The commits after that build: 17a88a9, ed25a29, 625f25b, 407cb8e's ui/apply.rs line, and f7264f7 through e107caf.
  • cargo clippy -p codewhale-tui --lib --tests --locked -- -D warnings (CI's allow-list): 0 warnings on e2ee2d2 (Finished in 19m 54s), 28ea342 (3m 51s) and the tree at 2f82993 (15m 53s).
  • Hosted CI on e107caf (above) is the test run for these.

Not done here (founder or follow-up)

🤖 Generated with Claude Code

https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj

…/disconnect

0ff4ffd added /connect and /disconnect to the config command group but
left the two tests that pin that group's registry on the old 17 commands.
Hosted CI has been red on Windows since then (run 38129356685, job
114440346849: "18309 tests run: 18307 passed, 2 failed"):
- config_policy_keeps_host_registry_order_metadata_and_exact_capabilities
  expected no connect/disconnect after login;
- command_ownership_contract_is_enforced expected exactly 17 commands, got 19.
The green run on ed3fbec (38129634138) skipped every Rust test as a light
change, so it is not evidence for this code.

Both tests now name the two commands in their registered position, and the
count is 19. The neighbouring comment that claimed the production groups hold
exactly 96 commands was already false and no longer states a number.

Checks (Ubuntu 24.04 container): nextest -p codewhale-tui --lib
-E 'test(/^commands::/)': 1192 tests run: 1177 passed, 15 failed. Both
guard tests passed. The 15 failures are all snapshot restore/undo tests that
fail on git 2.43's `checkout --end-of-options` (fixed separately; hosted CI
runs git 2.55 and is unaffected).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
claude added 28 commits October 11, 2026 12:51
Snapshot restore ran `git checkout --end-of-options <id> -- <paths>`.
git 2.43, which Ubuntu 24.04 ships, rejects that form with "fatal: only one
reference expected, 2 given", so /undo and restore failed there. That form
shipped in v0.10.1 (593be41). Hosted CI runs git 2.55, so it never saw
the failure.

Both checkout call sites drop `--end-of-options`. The id passed there is a
SnapshotId, which is validated as 40 or 64 hex characters. It can never
start with '-', so the option guard protected nothing that reaches it. The
`--` separator before the paths stays.

Evidence: on this Ubuntu 24.04 container (git 2.43),
`nextest run -p codewhale-tui --lib -E 'test(/^commands::/)'` on db29e64
gave `1192 tests run: 1177 passed, 15 failed`. All 15 failures were snapshot
restore and undo tests failing with "only one reference expected". The
re-run with this change is pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… its exit

Two session-export defects in the background-shell cancel path:

- Cancelling your own background job also queued its completion
  notification. The session then got a "finished" event for a job it had
  just killed, and a new model turn could start from it.
  `ShellManager::kill` now marks a job it killed as
  `completion_reported`, so the completion drain skips it.
- A job that exited between the user's look and the cancel was still
  killed and reported as "Killed" with exit 0.
  `BackgroundShell::kill` now polls first and returns without signalling
  when the process has already finished. The cancel receipt then reports
  the real status and exit ("... Nothing was killed.") instead of "Canceled
  background command".

Evidence: cargo fmt --all -- --check is clean. The compile and the
tools::shell / tool_cancellation tests are pending a local test build and
hosted CI on #6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…lainly

When a foreground bash call outlived its wait and moved to the background,
the card copied the model's receipt ("Background task started: shell-42
... use task_shell_wait ...") into its live output. That told the user how
the model should poll, not what happened. Ctrl+B already showed a user
notice for the same transition.

- A running Exec result no longer seeds `live_output` with the model's
  receipt. The card keeps its live task identity, and output arrives from
  the job as before.
- The auto-background case pushes the same `ShellWaitReleased` toast as
  Ctrl+B ("... keep running in /jobs"), at Info level for 6 s. A call the
  model started with background:true gets no toast, because nothing moved.
- canonical_background_bash_keeps_live_task_identity_for_follow_up_actions
  now asserts the card has no copied receipt.

Evidence: cargo fmt --all -- --check is clean. The compile and the ui test
are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Every todo_write call returned the whole checklist to the model. A
long-running session paid for the full list again on each update, although
the model had just written that list in its own call. That was a
session-export finding.

The structured-result compactor now handles a todo_write result:
- it keeps the "Todo list updated (...)" header with its counts;
- it adds the item in progress ("In progress: #3 ...") or "No item in
  progress".
- The full list stays in the tool result's metadata, and the TUI's todo
  panel still renders from it.

Model-visible means logged: the receipt is a deterministic projection of
the logged tool result and metadata, so the session log reconstructs it.
KV-cache: tool results are append-only history; the cached prefix is
unchanged.

The todo_snapshot doc comment, docs/TOOL_LIFECYCLE.md, docs/SUBAGENTS.md
(and their zh_hans copies) and the test_cases_13 comment now say the
model learns its list from its own todo_write call, confirmed by the
receipt.

Evidence: cargo fmt --all -- --check is clean. The compile and the
core::engine::context tests are pending a local test build and hosted CI
on #6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… goal

A session-export review found that goal usage never moved:
`tokens_used` stayed at 0 against 1,309,909 tokens actually spent, and
`time_used_seconds` was always 0. Usage was recorded after the turn ended,
but only while the goal was still active. A turn that completed, yielded
or blocked the goal had already left it inactive by then, and the usual
goal turn ends exactly that way. So the turns that did the work were never
counted.

- `GoalState::record_usage` takes the turn's start `Instant`. It also
  counts when the goal has an objective and finished at or after that
  start, so the turn that finished the goal is charged. Earlier turns are
  not.
- `record_goal_usage_for_turn` takes the turn's start (`turn.started_at`
  or the compaction start) and derives elapsed seconds from it. The now
  unused `TurnContext::elapsed` is removed.
- The existing goal, turn_loop, test_cases_04/15 and preview tests pass
  `Instant::now()` for the new argument.

Evidence: cargo fmt --all -- --check is clean. The compile and the goal
tests are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
The pet read only `app.agent_roster`, which AgentList refreshes between
turns. A sub-agent therefore appeared only after it finished. A finished
one stayed "working" until the next refresh.

`pet_watch::full::live_rows` overlays live state onto that roster when the
pet renders:
- `app.subagent_cache` supplies each agent's status (its worker status or
  the terminal-projection mapping), parked state, model, usage and steps.
  An agent the roster has not listed yet is added from the cache.
- `app.agent_progress` supplies the current activity line, and adds a row
  for an agent known only by progress.
- Elapsed time ticks from `started_at` only while the agent runs. A
  finished agent keeps its recorded duration.

It reads the cache and progress maps directly, so the history is not
walked on every animation frame.
`subagent_routing::worker_status_for_terminal_projection` becomes
pub(crate) for this reader.

Evidence: cargo fmt --all -- --check is clean. The compile and the
pet_watch tests are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
The pet looked blurred in the terminal. Upstream 387562b had replaced
Sprite's nearest-neighbour lookup with an alpha-weighted box filter, which
smears avatar tiles at every scale except 1:1. The whale cove was also
rasterized with 4x4 supersampling (2x2 above 64 px), so every edge became
a fractional-alpha pixel that Sprite then blended toward the background.

Re-vendored from upstream 8f51c6bccadeb11278cda1e2481a116573e5d233
(codewhale-hq/codewhale-ratatui#27):
- `Sprite::sample` takes the source pixel under the target pixel's centre.
- `whale_motion/pixels.rs` rasterizes one sample per pixel. The cove's
  deliberate layer opacities keep their translucency; only the
  anti-aliased rim goes.
Upstream, with this change: `cargo test --locked`, 787 passed, 0 failed
(46 test binaries).

The vendored crate goes to 0.1.2. It is the crates.io publish source, and it
gained DotWhale after 0.1.1 was published, so the packaged codewhale-tui
cannot compile against crates.io 0.1.1. Also changed:
- crates/tui and pet/tui depend on 0.1.2, and both lockfiles are updated
  (cargo metadata --locked passes for the workspace and for pet/tui);
- UPSTREAM.json records the upstream commit and the file hashes;
- the vendored CHANGELOG has a 0.1.2 entry;
- scripts/release/check-versions.sh allows 0.1.2;
- the deconstruction roadmap names 0.1.2.

Publishing codewhale-ratatui 0.1.2 to crates.io is a founder step and
comes before the codewhale-tui publish.

Evidence: cargo fmt --all -- --check is clean. The engine compile and the
pet_watch tests are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6931. The issue's headline case was a running recursive search shown
as "run running · stale · no output 2m 07s". After 60 s without output,
`job_snapshot` flagged a live, non-PTY job `stale`. The inspector, the
/jobs list, the work dock and the Runtime API all read `stale` as "process
gone":
- the Stop action disappeared (shell_job_routing `live = Running && !stale`,
  work_surface `shell_inspector_body`);
- the detail said "stale after restart; the process is no longer running";
- "(no output yet)" was suppressed;
- the API refused resize as "no longer running" and reported no tty.

- A live process is never `stale`. `job_snapshot` sets `stale: false`;
  only `remember_stale_job` (a restart snapshot, status Killed) sets it,
  which is the "known-stale" job docs/RUNTIME_API.md describes. The 60 s
  threshold becomes `QUIET_NO_OUTPUT_AFTER` and only drives presentation.
- The exec card reads "running · no output for 2m 07s" instead of
  "running · stale · no output …". Silence is not shown as hung, which
  acceptance 2 requires.
- `/jobs poll` and `/jobs stdin` no longer consume the model's unread
  output. Both called `poll_delta_for_session`, which advances the model's
  stdout cursor (acceptance 4).
  - `poll` opens the inspector from `inspect_job_for_session`.
  - `/jobs wait` uses the new `wait_job_for_session`, which waits through
    the same `wait_while_running` loop `get_output_delta` uses, then
    inspects.
  - `stdin` shows the job's one-line status and tail.
  - `poll_delta_for_session` has no callers left and is removed.
- Alt+V with no selection prefers the newest running shell only when it is
  visible in the transcript viewport. It no longer takes over the completed
  card the user is looking at (acceptance 1). A click or selection still
  targets that exact card.
- shell_job_routing.rs records its known limitations. The inspector is a
  snapshot with no follow mode; `/jobs poll` re-reads it. Named PTY
  sessions live in the terminal dock (#6912), not /jobs.
- Tests updated where this change made them wrong:
  - running_job_snapshot_keeps_silent_live_job_live asserts a silent live
    job is not stale and still exposes its quiet time;
  - the stale-running fixture in ui/tests.rs is `stale: false`, and its
    header assertion uses the new label;
  - QUIET_NO_OUTPUT_AFTER replaces the old constant name.

Still open in #6931:
- a follow-mode or auto-refreshing inspector;
- listing delegated agents' shells in the agent detail;
- the PTY journeys on the installed candidate at normal and narrow widths.

Evidence: cargo fmt --all -- --check is clean. The compile and the
tools::shell / tui tests are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ng say what happens

Session-export review of /constitution. Each item was read on both sides
before changing it.

- ratify promised it would be "refused if the base changed after you
  reviewed it", but it re-read the live file and handed that same digest
  back, so the guard could never fire. `/constitution suggestions` now
  records the digest the user reviewed on `App`, and ratify passes that to
  `UserConstitution::ratify`. Ratify without a review says to review first.
  A ratify after the file moved is refused as StaleBase. The existing ratify
  test now reviews before it ratifies, and checks the unreviewed refusal.
- `preview` claimed to show "the exact block that would be injected", but
  rendered `source="<absolute home path>"`, while the engine injects
  `render_block(None)` (`source="user-global"`). It now renders the same
  block.
- ratify and migrate said the prompt-cache prefix "moved" or "survives".
  The constitution reaches the model as a session message appended at turn
  admission (`record_current_constitution`), outside the cached prefix, as
  prompts.rs's `user_global_constitution_is_captured_outside_the_stable_prefix`
  asserts. The messages now say so, and so does the user_constitution
  module doc. The migrate test checks the new wording.
- The setup wizard printed the assembly order (bundled → user-global → repo
  → AGENTS → memory → current request) under "HIERARCHY OF AUTHORITY".
  That reverses the base prompt's ranking, which says it "is stated here
  and nowhere else". The line is removed from all 15 locale templates, and
  so is the now-unused SetupCheckpointLayerOrder message. "Your direct
  requests always outrank this document" stays.
- The wizard capped the user's own note at 4000 characters, then appended
  it to a ~300-character template. save_to then trimmed the total to 4000,
  silently cutting off the end of the user's own text. The note is now
  capped at MAX_NOTES_LEN - 1000 while typing, so the saved file keeps all
  of it. The longest template is 335 characters before labels.
- zh-Hans used 协作准则 in the /constitution manager and 宪章 (the
  docs/zh_hans/GLOSSARY.md term) elsewhere, sometimes on the same screen.
  It now uses 宪章 throughout, including the model-draft status line.
- The help usage line and docs/CONFIGURATION.md now list base,
  suggestions, ratify, migrate and rollback. The step is named "Working
  agreement" as the wizard shows it. docs/GUIDE.md no longer calls
  /constitution a way to customize the bundled layer.

Not changed here:
- A signed-in user still sees the local file as "active", although the
  account profile is what the model gets. The fix needs an async account
  check, because the credential store must not be read on the UI loop.
- The Runtime API's GET and preview `modelGuidance` shapes differ.
- `doctor` reports autonomy from an inactive file.
- The context inspector lists the personal constitution as a system-prompt
  layer.

Evidence: cargo fmt --all -- --check is clean, and every edited locale file
parses as JSON. The compile and the commands::core::constitution tests are
pending a local test build and hosted CI on #6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…isconnect

- The CHANGELOG 0.10.2 section gains Added (`/connect` and `/disconnect`,
  #6950) and Fixed lines for the slices on this branch:
  - git 2.43 /undo, shell cancel, the 30 s background notice and the
    todo_write receipt;
  - goal usage, pet live rows and crisp sprites, #6931 and /constitution;
  - the fixes that already landed on main for #6953, #6954, #6955, #6923,
    #6947 and #6945, plus the Auto-Review guardian budget, skills, MCP
    reconnect, the pet owner idle exit, tool headers, /jobs and the one-row
    gap.
- Contributors: @LIghtJUNction for #6950, #6947 added to @SparkofSpike, and
  #6952 added to @Lstarsky0.
- crates/tui/CHANGELOG.md was regenerated with scripts/sync-changelog.sh;
  the tui crate include_str!s it.
- docs/features.toml: the plugin-oauth-providers summary names /disconnect
  next to /connect (111 characters, under the 120 limit).

Evidence: ./scripts/release/check-versions.sh --require-dated-release
prints "Version state OK: workspace=0.10.2, npm=0.10.2, npm-binary=0.10.2,
lockfile in sync" and "Feature release-note receipts OK: 8 linked issue
reference(s) checked in v0.10.1..HEAD".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ibutor page

CI on 054b122 failed "Lint & Type Check": web/lib/public-copy.test.ts:167
compares the 0.10.2 CHANGELOG contributor handles with the website credit
arrays and the docs/CONTRIBUTORS.md band. The previous commit (49bd217)
added @LIghtJUNction (#6950) to the CHANGELOG. The website still listed
them under UNRELEASED_CONTRIBUTORS, which RELEASE_CONTRIBUTORS does not
include.

- web/lib/release-credits.ts moves @LIghtJUNction from
  UNRELEASED_CONTRIBUTORS to RELEASE_CONTRIBUTORS, as its own comment
  describes for the release that carries the work. UNRELEASED_CONTRIBUTORS
  is now empty.
- The docs/CONTRIBUTORS.md v0.10.2 band gains the #6950 line, and adds
  #6947 to SparkofSpike's entry and #6952 to Lstarsky0's, matching the
  CHANGELOG.

Evidence: a python3 re-implementation of the test's three handle
extractions gives the same 8 sorted handles for the CHANGELOG, the website
arrays and the doc band (@BX166 @LIghtJUNction @Lstarsky0 @SparkofSpike
@asto18089 @dajiaohuang @gaord @jayanthvee).
`python3 scripts/check-contributor-credit.py`: "Every contributor in the
window is credited on all three surfaces." The vitest run itself is
CI's job on this PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ips exited jobs

Follow-up to 8eb23ad, from an adversarial review of that slice.

- 8eb23ad marked a killed job's completion as reported inside
  `ShellManager::kill`, which /jobs, the Runtime API and the model's cancel
  all share. When a person stopped a job the model had started, the model
  was therefore never told. `kill` is neutral again. The model's own cancel
  marks the jobs it actually killed through the new `mark_cancel_reported`.
  A person's cancel still reaches the model as a Killed completion.
- Cancel-all picked jobs by their cached status. A job that had exited
  since the last poll was "canceled": the model's receipt said "Canceled 1
  background command" with status Killed, and its real Completed event
  followed. `/jobs cancel all` said the same. `kill_running_for_session` now
  polls each of the session's jobs before selecting the running ones, and
  returns only the jobs it actually killed.

Evidence: cargo fmt --all -- --check is clean. Compile and tests are
pending: the running local test build predates this edit, and hosted CI on
#6957 runs them on this push.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Follow-up to d33dc38, from an adversarial review of that slice. The
moved-to-jobs toast is meant only for a foreground wait that ran out, so a
call started in the background gets none. The check looked only at
`background`, but `tty:true` also starts in the background (the schema
says "implies background"). A tty call therefore came back Running at once
and showed "... keep running in /jobs" although nothing had moved.
`tty:true` now counts as an explicit background start.
`exec_is_background` itself is unchanged, because the start-path wait
dedupe also uses it.

Evidence: cargo fmt --all -- --check is clean. Compile and the tool_routing
and ui tests are pending a local build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Follow-up to e71255e, from an adversarial review of that slice. Ratify
now checks the digest reviewed in `/constitution suggestions`, but that
digest stayed at its pre-ratify value. The next `/constitution ratify
<id>` was therefore refused as StaleBase, although the only change since
the review was the user's own ratification. A repeated `ratify c1` also
said StaleBase instead of "already ratified".

`ratify_text` now returns the saved file's digest
(`ratification.after_digest`) on success, and the command stores it as the
reviewed digest. An edit made outside the session is still refused as
stale.

Evidence: cargo fmt --all -- --check is clean. Compile and the
commands::core::constitution tests are pending a local build and hosted CI
on #6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
"Pet conformance / recorder (macos-latest)" failed on
#6957 (run 38141362016, job 114475791414) at
pet/scripts/check-shared.py:97:
  styled=frame_when(d,lambda f:f['appearance']==appearance)
  AssertionError: Accepted state did not reach the frame projection

Cause: main's b0f9cbc ("/pet style and language, pixel whale body",
committed unbuilt) added `body_style` and `text_language` to `Appearance`
(pet_watch/appearance.rs:56-59). Both use `#[serde(default)]` and are
always serialized. The owner stores the parsed appearance and echoes it
whole (owner.rs:665), so the frame carries 10 keys while the fixture sent
8. The strict equality at :97, and again after the crash restart at :107,
could never hold. The owner kept answering /v1/frame for the full 5 s,
so this is not a stall. The failure is deterministic; Windows runs that
step only on macOS (`if: runner.os == 'macOS'`), so it never saw it.
Pet conformance runs only on PRs that touch pet paths, so this PR is the
first run since b0f9cbc.

The product's full echo is intended. shared.html builds and reads both
fields, and the persisted and live appearance must agree. So the fixture
moves to the current schema instead of the owner hiding defaults. It sends
non-default values ('bodyStyle':'pixel', 'textLanguage':'ja'), so the round
trip and the restart now also prove the new fields persist. With
eventColors False, owner.rs:619-623 still writes `particle` into
style.r/g/b for any body style, so the colour assertion at :98 holds.

Evidence: `python3 -I -m py_compile pet/scripts/check-shared.py` passes.
The script drives the owner binary, so the run itself is the macOS
recorder job on this push.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…age report shows

A session-export review found update_goal rejected `progress` sent with
`status: "yield"` ("progress is only accepted with status not_achieved or
advisory"). Yield means a finished stage handed back to the user, which is
exactly when a progress estimate is most useful.

- update_goal accepts `progress` with yield, and stores it on the yielded
  goal after `mark_yielded`. `record_progress` only records on an active
  goal, so it would have dropped it. The refusal text names yield. The
  schema description says "Optional with not_achieved, advisory or yield".
- The TUI shows the progress receipt for a yield too (ui/apply.rs). Paused
  and complete goals keep their last report silent; a yield is the stage
  report the user is handed back with. The schema promises the estimate is
  "shown to the user as reported progress". An adversarial review flagged
  that without this, a yield's estimate reached only the model.
- The existing progress-rejection test expects the new refusal text.
- CHANGELOG notes it, and crates/tui/CHANGELOG.md is re-synced.

Model-visible and KV-cache: one sentence of update_goal's schema
description changes, 7 bytes longer. That changes the session-pinned tool
catalog for new sessions only; a running session keeps its pinned prefix.
The 12 conformance goldens that pin the catalog were re-recorded with
CODEWHALE_CONFORMANCE_UPDATE=1 (CI unset). Normalized, their diff moves
only:
- the description text, and a fixed-width preview shifted 7 characters;
- the sha256 values and the short "frozen: <digest>" label;
- tools_bytes and payload_json_bytes, each +7;
- a `.codewhale/state/.gitignore` entry in the event goldens'
  workspace_after. That entry comes from main's 491d3df, which writes
  that file and was committed with its tests left to CI, so main's
  golden_turn_events_match was already stale.

Evidence, on a local lib test binary (Ubuntu 24.04) built from this
branch with the goal.rs change:
- `conformance::`: test result: ok. 33 passed; 0 failed.
- `tools::goal`: test result: ok. 36 passed; 0 failed.
The ui/apply.rs condition was added after that build. cargo fmt --check
is clean, and hosted CI compiles and runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6957 Lint. 407cb8e made update_goal accept a progress estimate
with yield and named yield in the progress description. The
runtime-contract ratchet measured that on hosted Linux (run 38144890574,
Lint job 114486327862) as +7 bytes on every Plan, Act and Operate
surface:
- full and active, Plan: 55163 -> 55170 and 36173 -> 36180;
- full and active, Act/Operate: 84384 -> 84391 and 37703 -> 37710;
- +1 to +2 estimated tokens on each.
The ratchet confirmed base b1e39f4 passes, so this commit adds the
debt; it is intended.

No tool enters or leaves a surface, and every identity is unchanged.
The twelve ceilings take the exact CI values, with a dated
_codex_20261011_goal_yield_remeasure note, as d54a098 did.
scripts/test_check_runtime_contract_budget.py: Ran 22 tests, OK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…clicked card

Refs #6931. Acceptance 4 (follow mode; refresh without the model's cursor)
and acceptance 1 (a new card never takes over the target).

Follow mode:
- When the Bash Job pager opens on a running job, it records the job id.
- On its 2.5 s tick, the event loop re-reads that job through
  `inspect_job_for_session`. This is a bounded read, under try_lock as
  `refresh_shell_exec_live_output` does, and never touches the model's
  output cursor. The event loop then swaps the text into the open pager.
- A view at the bottom stays pinned to the newest row. Scrolling up, Home,
  `gg` or a search jump stops following; End, `G` or scrolling back to the
  bottom resumes it.
- When the job ends or leaves the session, refresh stops and Stop is
  removed, because it no longer applies (acceptance 5: inapplicable
  controls are disabled).
- The Status line reads "running · no output for 2m 05s" once a live job
  has been quiet for QUIET_NO_OUTPUT_AFTER. It uses the label the exec card
  already uses.
- `ViewStack::top_pager_mut` is the downcast, next to `refresh_extensions`.

Alt+V target:
- 674dcc3 sent Alt+V with no selection to the newest running shell on
  screen before anything else. That bypassed
  `detail_cell_index_for_viewport`, which the footer hint also uses. So a
  running card that scrolled into view took over the completed card the
  user was reading, and the hint and the key disagreed. Alt+V now resolves
  only through `detail_target_cell_index`.
  `newest_visible_running_shell_cell` is deleted. A running shell stays
  reachable by click, by the work dock and by /jobs.
- A selection stored only its rendered line. When a run of successful tool
  cards collapsed above it, or cells were appended while an active cell was
  open, that line pointed at another card. A click now also records its
  owner cell as the existing `TranscriptActionOwner` (cell index plus
  transcript identity epoch). Space-fold already uses it.
  `rebase_active_cell_bindings` shifts the owner with the other bindings.
  Any other identity change (folds, rollback) invalidates it, and the
  target falls back to the line. Alt+V, the detail target and Ctrl+O
  prefer the owner.
- CHANGELOG lines that advertised the old Alt+V rule are corrected.

Known limits, stated in shell_job_routing.rs:
- new output reaches the pager up to 2.5 s late;
- the work dock's inspector is still a snapshot;
- delegated agents' shells appear in /jobs and the dock with their Owner,
  not in the agent's detail;
- named PTYs live in the terminal dock (#6912).

Focused tests: the issue asks for them in acceptance 7.
- pager: follow, unfollow and resume, and dropping Stop when the job ends;
- shell_job_routing: a silent running job reads quiet, not stale, with
  "(no output yet)";
- the existing stale-list test now shares the snapshot fixture.

Evidence: cargo fmt --all clean. clippy -p codewhale-tui --lib --tests
(-D warnings) is running locally on this exact tree; the focused tests
run in hosted CI on #6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…rvived

Refs #6944, acceptance 1 and 2 for what the model and the person read.

- `ShellManager::running_progress` polls a live job and reads its bounded
  1,200-byte tails (`job_snapshot`). It returns "Progress: last output Ns
  ago; output phase: …" using the existing `output_phase_hint`.
  - A running single-task `wait` puts that line ahead of the delta result.
  - A multi-task `wait` adds it to each running id's line.
  - Silence plus phase separates "still compiling" from a stall without
    another poll.
  - Metadata and `build_shell_delta_tool_result` are unchanged.
- The /jobs cancel receipt (`format_shell_poll`) and the shell completion
  handoff the model receives after a person's cancel now name whether
  compile artifacts survive. They use the `kill_outcome_note` the model's
  own cancel path already shows. The handoff adds a `kill_note` key on
  Killed events only. It is an append-only user-role message that is
  already in the session log, so the KV-cache prefix is unchanged.
- `tools::shell_output` becomes pub(crate) so the TUI receipt can reuse
  the note.
- Two comments that 34bf656 made false no longer claim that Full Access
  cannot bypass the background floor (turn_loop.rs, auto_review.rs).

Known limit: cargo prints no "crate N of M" or "k/N tests" to a non-TTY
pipe, so the phase stays coarse (compiling / build finished / running /
unrecognized).

Not here:
- (a) unpolled mid-run progress events;
- (b) deleting `Run(action=tests)`;
- (c) the measured side-by-side.
These are founder questions.

Evidence: cargo fmt --all clean; clippy pending locally on this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6925. Since the sign-in repair, every `OAuthProviderParams` sets
`originator: None`. The authorize-URL branch that appended it could not
run, and its doc comment described a ChatGPT requirement that no longer
holds.

- The field, its five `None` initializers and the dead branch are removed.
- `OwnedAuthEntry.originator` stays, so credential files written by older
  builds still parse. A new ChatGPT login stores `None` there.
- `authorize_url_uses_documented_chatgpt_parameters_and_pkce` already
  asserts that the URL has no `originator=`.
- The `oauth` module is private to the crate, so no published API changes.

Evidence: cargo fmt --all clean; clippy pending locally on this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6939 (RS-12). The test `default_max_turns_does_not_add_a_hidden_worker_cap` parsed the worker
argv with `crate::Cli` from inside fleet/executor.rs. That was the
remaining `test fleet|lib.rs 3` edge.

- The test moves unchanged in substance into
  lib/terminal_mode_test_cases_03.rs. That is where 0f48161 put its
  sibling.
- The task is built from JSON, and the launch spec comes from the public
  `fleet_task_to_worker_spec_with_profiles`. No visibility changes.
- The runtime-boundary baseline drops from test 35 to test 32 (`module_graph.py --update`,
  then --check PASS 11/32/1/1 over 117 closure modules).
- DECONSTRUCTION_ROADMAP.md's gates and the 0.10.5 edge list follow the
  new baseline.
- TUI_DECONSTRUCTION.md records RS-12 as landed.

Evidence: python3 scripts/split/module_graph.py --check: [runtime-boundary]
PASS: {prod 11, test 32, late 1, uilib 1, doc 0} (117 closure modules).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… progress

Refs #6931, #6944.
- The inspector bullet says it follows output, drops Stop when the
  command ends, and that Alt+V keeps the clicked card.
- The silent-shell bullet loses the clause that advertised the removed
  'running shell first' Alt+V rule.
- A new bullet covers wait progress and the kill note.
- crates/tui/CHANGELOG.md is regenerated by scripts/sync-changelog.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…nspector

Refs #6931 (acceptance 4 and 5, "inspectable and stoppable"). Found by
the 0.10.2 UX audit's live-work lens; each finding was checked against
the code before this change.

- `/jobs wait <id>` called `wait_job_for_session(…, 5_000)` on the UI
  event loop. It held the ShellManager std Mutex and slept in 100 ms
  steps, so the screen and the model's shell tools stalled for up to
  5 s, against the #6149 blocking-call rule. `poll` and `wait` now
  parse to the same action as `show`: the live-following pager from
  f7264f7. The `ShellJobAction::Poll` variant, its handler arm and
  `wait_job_for_session`, which had no other caller, are deleted.
- Work-dock shell rows, live and finished, ran `shell_inspector_body`
  in every projection. That is several passes per frame, on every dock
  tab: a `try_lock`, then `inspect_job_for_session`, which polls the
  child and copies the full retained stdout and stderr (up to 16 MiB
  each). The pager it opened was a frozen snapshot that said "Open this
  row to watch live output". Shell rows now run `/jobs show <id>`, and
  `shell_inspector_body` is deleted, so projection never touches
  ShellManager.
- The right-click menu keeps "Stop work" for a running shell
  (`/jobs cancel <id>` behind the same in-menu confirm). The pager has
  its confirmed `s` Stop.
- Durable task rows ran `/jobs show task_…` against the shell manager,
  which printed "Command lookup failed: Job task_… not found". They now
  run `/task show <id>`, and RLM pseudo-rows (`rlm-N`) have no action.
- Tests updated where this made them wrong: the live shell row's
  primary action, and the shell-prefixed task rows' `/task show`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ip settings I/O

Found by the 0.10.2 UX audit (first-run and chrome lenses); each was
checked against the code before this change.

- `/setup` mapped `u` (bundled) and `d` (defer) with no step guard.
  Pressing either on the Provider, Permissions, Remote or Ready step
  closed the wizard. `prompts.rs` treats Bundled and Deferred as "user
  constitution disabled", so a ratified working agreement silently
  stopped applying. Both arms now carry the
  `selected_step() == SetupStep::Constitution` guard their g/a/f/k
  neighbours already have.
- `note_footer_hint_used` ran a locked `settings.toml` transaction
  (process mutex, fd lock, read and parse) on the UI thread for every
  Tab, Shift+Tab, Ctrl+], Esc interrupt and agent arrow, forever. It
  now returns early once the in-memory count is retired. That count is
  seeded from settings at startup, so a hint retired in another
  instance still counts. Its doc comment claimed it never blocks the
  input path; it now says what really happens.
- CHANGELOG: the #6931 bullet adds `/jobs wait`, dock shell rows and
  task rows; a new bullet covers the `/setup` keys.
  crates/tui/CHANGELOG.md is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6931. 8fa735e pointed work-dock shell rows at the live-following
Bash Job pager, so the known-limitations note's 'the work dock's inspector
is still a snapshot' became false. The note now names the three ways the
pager opens; the remaining limits (2.5 s latency, delegated-agent shells
outside the agent detail, PTYs in the terminal dock) are unchanged.
Comment-only; no code change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
claude added 20 commits October 11, 2026 15:35
From the 0.10.2 UX audit. Each was checked against the code first.

- ko ChipPermissionNever said '묻지 않음' ("doesn't ask"), which reads as
  auto-run on the deny-all Never chip. It is now '허용 안 함', the word
  /status already uses for the same posture.
- OnboardLanguageBlurb, in all 15 packs, told a new user to change
  language with `/settings set locale <tag>`, which answers
  "Usage: /settings [text]". The command is now
  `/config locale <tag> --save`, which persists the locale. The
  translated prose and placeholder words are unchanged.
- en ElevationOptionAbortDesc said "Cancel this run", but the handler
  denies only the tool call and the turn continues. It now says "Skip
  only this tool call", as the other packs do. The test-only English
  mirror in approval/elevation.rs and its assertion follow.

All 15 packs still parse, and `rg '/settings set locale' crates/localization`
finds nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… table

From the 0.10.2 UX audit (transcript-cards lens), checked against the
code before the change.

- The most common card, a file edit, used the generic "• tool" verb
  because PatchSummaryCell passes the title "File", which
  tool_family_for_title did not map. "File" now maps to the Patch family.
  The card's header carries the receipt's change summary, and the bold
  first body row that repeated it is gone. With inline diffs off, the
  header keeps the calm outcome label. The pager, inspect text and exact
  diff are unchanged.
- One transcript said "run Done", "tool done", "run issue" (failed) and
  "✓ tool tool loaded - retry required".
  - en ToolReceiptDone is lowercase like every other pack.
  - tool_status_label says "failed" for Failed (Warning stays "issue")
    and "loaded, not run" for Hydrated.
  - A hydrated tool gets the neutral glyph, not the done check.
  - activity_detail's duplicate table is deleted and its four call sites
    use tool_status_label.
  - The exploring card's per-entry prefix also says "failed", so a
    failed read card no longer says "failed" in its header and "issue" on
    its row.
- Tests whose copy changed are updated. The behavioural asserts are
  kept: hydrated is still not reported done, and failed is still not
  reported hydrated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
From the 0.10.2 UX audit (errors-toasts and localization lenses, merged),
checked against the code first.

On the most safety-critical surface, 13 of 15 locales showed translated
options next to English field labels (Command, Dir, File, Preview…) and
an English "About" sentence. localize_detail_label and
description_for_locale gated existing ApprovalLabel*/ApprovalDesc*
MessageIds to zh-Hans only. The packs already carry them, and the pager
already used tr(ApprovalLabelPreview) for every locale.

- The MessageId-backed label arms apply to every locale. The hard-coded
  Chinese arms stay zh-only.
- The category description comes from tr(locale, ApprovalDesc*) for
  every non-English locale.
- ApprovalDetail gains a typed `is_preview`, set where the Preview detail
  is built. The live card and the legacy band read it instead of matching
  the English label "Preview", so the 3/5-row preview bound holds in
  every locale.
- impacts_for_locale is unchanged: its zh builder carries literal
  Chinese.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
From the 0.10.2 UX audit (first-run and errors-toasts lenses). Each item
was checked against the code first.

Ollama adoption. When a local Ollama model was adopted during first run,
the picker was popped and onboarding set to None. That skipped the trust
question and the ready screen, and mark_onboarded never ran, so the next
launch restarted onboarding. It now calls
advance_onboarding_after_provider. The adoption test expects TrustDirectory
or Ready.

Retry receipts stay in the transcript. They also wrote status_message,
which the legacy classifier turned into an 8-second red Error toast that
hid the later "recovered" line. A receipt now adds its System cell and
nothing else.

A turn that ended in failure reads as Error, live and on resume.
- present_turn_failure and the resume replay of saved outcomes used
  Warning, which goes against the pinned
  a_failure_that_ended_the_work_is_never_a_warning rule.
- The terminal stream-open branch in model_step promotes a Warning
  envelope to Error before sending it. `recoverable`, `category` and
  `code` are untouched, so provider fallback is unchanged.
- When an earlier Warning error cell (a stream stall) already showed the
  failure, present_turn_failure upgrades that cell to Error. The live
  view then matches the record that resume replays.

/setup honesty.
- The final step no longer says "You're ready." without a working
  provider. It reuses the Provider step's title and blurb and leads its
  action bar with P (provider). C (customize) is listed because it was
  already handled.
- The key-entry modal puts the rejection reason first, so the 6-row cap
  drops guidance rather than the reason.
- Its continue/back footers use SetupActionContinue/SetupActionBack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ants

From the 0.10.2 UX audit (commands-help and localization lenses, merged),
checked against the code first.

The picker, chip, hotbar and settings say "Work", but several places
still said "Act":
- `/mode work` replied "Switched to Act mode.";
- /overview printed "Mode: ACT";
- /setup showed "Work intent: Act";
- the startup-default notice spliced in "Act".
All four now use AppModeUi::display_name_localized.

/zidong and `/mode yolo` switch to Full Access, with shell and trust on,
but replied only "Switched to Act mode.". They now reply "Switched to
Full Access (Work)." (tr(HotbarActionModeYoloName)).

The /mode usage is now "/mode [work|plan|operate|1|2|3]", and the usage
error prints MODE_INFO.usage instead of a hand copy that also listed
"agent". The English hints that still said "Act" ("Act + Full Access",
"applies in Act and Operate", "Act mode will expose shell") now say
Work.

Unchanged: AppMode::display_name, label() and the hotbar short_label.
Session export and the hotbar metadata cross-check depend on them.

Tests that pinned "Act" are updated: config yolo, the allow_shell
messages, the app permission-cycle toast, and the help filters
"mode [act" → "mode [work".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…<call id>"

From the 0.10.2 UX audit (transcript-cards and live-work lenses), checked
against the code first.

drive_child_actor sent `format!("Core tool {id}")` to the parent mailbox
on ToolExecutionStarted, and recorded "Core tool {id} settled" on
completion, so every delegated card read "Core tool call_7f3a9c2e
running". Event::ToolCallStarted, which carries the name, fell through
to `_ => {}`.

A local map from call id to the tool's model-facing name is filled on
ToolCallStarted. The card now reads "read running" and then "read done"
or "read failed", falling back to "tool". It uses the raw name, the one
the progress meta's `.with_tool(name)` already records, rather than the
retired policy alias (read_file), so both surfaces agree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…s lose per-row rules

From the 0.10.2 UX audit (transcript-cards lens), checked against the
code before the change.

- parse_heading accepted '#' with no following space, so a reply line
  like '#6235 fixed the race' became an H1 with a 40-column rule. It now
  follows CommonMark: 1-6 '#' then whitespace or end of line.
- Headings rendered through the plain wrapper, so '## Changes to `x`'
  showed literal backticks and asterisks. They now use the inline path
  paragraphs use, with the heading style.
  render_wrapped_line_tagged, and wrap_code_line and wrap_text which
  only it reached, are deleted with their four direct unit tests. Two
  comments that named wrap_text are corrected.
- Tables pushed a rule after every row, nearly doubling their height.
  A rule now marks only the header separator, the header row is bold,
  and ragged rows are padded to the column count so they line up with
  the borders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
From the 0.10.2 Rust optimization audit (memory lens, judged safe-now).

The cost. apply_engine_session_projection cleared the UI's per-message
token cache on every engine projection, and the engine sends one per tool
result. The next frame's estimated_context_tokens then re-estimated every
message on the UI thread. That includes serializing every ToolUse input
to a String, so a write_file carrying a whole file was serialized again
for each later tool result.

The change.
- set_api_messages already counted the leading messages that are
  unchanged and then dropped that number. It now returns it, and the
  projection truncates the cache to that prefix instead of clearing it.
  The estimates kept are for messages equal to the ones they were
  computed from, so every value matches what a full clear produces.
- In-place edits go through api_messages_mut, for example
  replace_matching_assistant_text, and a prefix compare cannot see them.
  So api_messages_mut now clears the cache, and the edit shows sooner
  than before.
- push_api_message appends through Arc::make_mut directly, so appends
  keep the cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…once an hour

From the 0.10.2 Rust optimization audit (blocking lens, judged safe-now).

The cost. Every private single write_atomic, and every write_atomic_batch
parent, ran is_codewhale_owned_state_dir (up to 4 canonicalize calls) and
then a full read_dir of the directory looking for stale temp files. Those
temps only become stale after STALE_AFTER (1 h). A fork that clones
hundreds of items paid one directory scan per item, measured at 22 ms
each.

The change. A process-wide map from directory to last sweep, using the
same OnceLock<Mutex<…>> pattern as settings_transaction_mutex, lets
sweep_owned_dir_if_due skip both the owned check and the read_dir when
the directory was swept less than STALE_AFTER ago. Expired entries are
dropped, so the map holds only directories touched in the last hour.
The owned check and the sweep themselves are unchanged. A cached entry
can only skip a sweep; it can never cause one in a directory that is not
owned.

Comments the change made false are corrected: the AtomicWriteScope::Single
and write_atomic_batch docs, the call site, and the two runtime_threads.rs
comments that described a per-item sweep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…r thread

From the 0.10.2 Rust optimization audit (io lens, judged safe-now).

The cost. aggregate_usage called list_turns_for_thread for every thread.
Each call is list_all_turns, which reads and parses every turn file, plus
a retain. So one GET /v1/usage cost T x N file reads, inline on a Tokio
worker.

The change follows the pattern thread_list_facts and running_threads
already use (#3757). One spawn_blocking on a cloned store lists the
threads and reads all turns once, grouped by thread id. The async side
accumulates in the same thread order and still validates each thread id.
A join error reads 'Runtime usage aggregation task failed', matching
aggregate_usage_for_thread. Totals and ordering are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…opying it

From the 0.10.2 Rust optimization audit (memory lens, judged safe-now).

The cost. SessionObjectSnapshot.messages was Vec<Message>, and
build_tool_context_for_turn filled it with
self.session.messages.clone().into(). AppendLog::into_inner deep-copies
whenever the Arc is shared, and the engine always shares it. ToolContext
derives Clone, and live_tool_context clones the registry context per
call. So about 8 full copies of the history stayed resident per turn,
plus 2-3 per tool call.

The change. The field is Arc<Vec<Message>> and is filled from the
existing AppendLog::snapshot(). SessionObjectSnapshot::new takes
impl Into<Arc<Vec<Message>>>, so the existing vec![] callers compile
unchanged. Every reader only iterates, indexes or borrows as &[Message].
The snapshot is immutable: AppendLog mutates only through Arc::make_mut,
so tools still see exactly the turn-start view. Debug output is
identical. Nothing model-visible, persisted or serialized changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… without allocating

From the 0.10.2 Rust optimization audit (turn-loop lens, judged safe-now).

The redundant walk.
- run_auto_compaction first computes
  live = turn.live_input_tokens_for_compaction(messages, system, …),
  which is already max(E, billed + growth). E is
  estimate_input_tokens_for_pressure over the same messages and system
  prompt.
- It then gated on compaction_pressure_reached_with_billed(messages,
  system, config, live). Below the threshold, which is most steps, that
  recomputed the same E with a second full-history walk before
  returning max(E, live) >= threshold.
- Since live >= E, that equals live >= threshold. The gate now compares
  live with the threshold directly.
- When live is None, E is 0 and both forms are 0 >= threshold.
- compaction_pressure_reached_with_billed keeps its other callers, and
  the sentence in its doc that described the double pass is removed.

JSON sizing. estimate_tokens_for_message serialized each ToolUse,
ServerToolUse, ToolSearchToolResult and CodeExecutionToolResult value to
a String only to take its length. compact_json_len now counts the bytes
through serde_json::to_writer into the existing utils::CountingWriter.
That gives the same compact-formatter count with no allocation. ToolUse
keeps its 100-token fallback.

Every estimate and every compaction decision is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
From the 0.10.2 Rust optimization audit (ui-hot-path lens, judged
safe-now). The default theme is underwater, so this runs on every frame.

The underwater shell block painted the full frame with the surface_bg
ground and then repainted four sub-rects (strip, side work, work chat,
preview) with the same ground.

Why the four repaints changed nothing:
- Nothing is drawn between the full-frame pass and those four.
- Each pass uses the same column, theme, ground and ocean
  semantic-surface slice.
- The frame area is the buffer area, so the first pass already visits
  every cell.
- Water depends only on the absolute row: paint_native pins the viewport
  to y, and paint_matching_native passes no samples.

The four passes are removed. The composer, plugin-CTA, footer and
workbar passes, which use different grounds, stay. The comment above the
full-frame pass no longer implies more surface_bg passes follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…ole child history twice

From the 0.10.2 Rust optimization audit (memory lens, judged safe-now).

The cost.
- insert_subagent_full_transcript_handle and build_subagent_checkpoint
  each ran safe_tool_result_message_projection over the whole child
  history, which is a to_vec copy, only to keep a 256 KiB / 1 MiB tail.
- Sizing each message took a serde_json::to_string allocation.
- On the Core path, the transcript writer's projected sync found its
  cursor already advanced by the raw sync, so the copy bought nothing.

The change.
- bounded_tail_messages walks newest-first and projects one message at a
  time until the budget, keeping the always-keep-final rule.
- approximate_message_bytes counts serialized bytes with CountingWriter.
  The count is identical and still falls back to 1024.
- The writer projects only its unsynced suffix.
- Callers pass the raw history. The doc comment says it returns projected
  messages, because re-projecting is lossy.

The persisted checkpoint and transcript bytes are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…erlay

From the 0.10.2 Rust optimization audit (io lens, judged safe-now).

Every save ends with cleanup_old_sessions, which called
list_session_records. That applied apply_late_usage_to_metadata to every
saved session: a lock-file open, a blocking fd_lock read, a tombstone
read and a ledger parse per record. Retention only orders and archives
by metadata it never reads costs from, so all of that was wasted on
every save.

The overlay moves into list_sessions, the only other caller, which
applies it to each record after listing. Retention gets the raw
metadata, and the session list a person sees is unchanged. The
list_session_records doc says it is list_sessions without the overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…t runs

From the 0.10.2 Rust optimization audit (ui-hot-path lens, judged
safe-now).

The cost. pet_watch::tick runs on every event-loop iteration. Every 30
ms it called crossterm window_size(), which on unix opens /dev/tty, does
an ioctl and closes it. It also read CODEWHALE_PET_GRAPHICS, allocated
the locale, ran ShellPhase::from_app and built a live::View. All of that
happened even when no pet worker existed, and the view was then dropped
unread.

The change. last_tick still advances unconditionally inside the 30 ms
gate, so timing is unchanged. The phase, probe, env read, locale and
View build all move inside 'if let Some(worker)'. The notices drain
reads app.pet_watch.worker, which ends the mutable borrow before
ShellPhase::from_app. A running pet sees exactly the same view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
… dev-dependencies

From the 0.10.2 Rust optimization audit (build-size lens, judged
safe-now).

Doctests. codewhale-tui has no runnable doc example: its fences are 7
ignore, 1 rust,ignore, and text/json/sh blocks. Yet
'cargo test --doc' still built a rustdoc test harness for the crate on
every run. Its [lib] now sets doctest = false. BUILD_PERFORMANCE.md
says why. The workspace doctest inventory (3 passing / 8 ignored across
21 crates, all 8 ignored in codewhale-tui) is marked as not re-measured.

Dependencies. schemars and rusqlite are used only under cfg(test): the
schemars derive is cfg_attr(test, …), and rusqlite appears only in test
modules. Both move to [dev-dependencies] with the same versions and
features. rusqlite stays in the workspace's normal build through
codewhale-memory, codewhale-state and codewhale-app-server, so its
features are unchanged. Cargo.lock is unchanged, and --locked still
resolves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
User-facing bullets for d40be2b through 79735df: setup honesty, the
Ollama first run, failure severity and retry notices, file-edit cards and
status words, delegated-agent cards, markdown headings and tables,
approval labels in every locale, the Work mode name, the three locale
strings, and the UI-thread and memory work. crates/tui/CHANGELOG.md is
regenerated by scripts/sync-changelog.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Refs #6915, #6728, #6396, #6931. The 0.10.2 notes had no known-limits
block, so four limits of the current candidate went unstated:
- the Windows dead-owner start refusal ('Windows stale-owner recovery is
  not qualified', app-server/src/lib.rs);
- idle CPU not measured on FreeBSD or Linux;
- base-rate pricing above a Models.dev context tier, which can only
  happen after a live refresh because the bundled catalog has 0 tiered
  rows (checked);
- delegated agents' shells shown in /jobs and the dock, not in the
  agent's detail.
Any of these that the founder fixes before the tag comes out of this
block. crates/tui/CHANGELOG.md is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
…on't repeat themselves

The 0.10.2 UX audit's second slice. The judge marked it as needing no
product decision; it was held back only by the 12-item cap. Every
sub-item was re-checked against the tree before the change, and an
adversarial review's three findings are fixed here.

First run, chrome and errors:
- Provider readiness says "endpoint reachable · model not checked"
  instead of "models endpoint 2xx". It deliberately does not say "key
  works": providers with a public /models answer 2xx to a bad key.
- remote_control::Status is reachable through one typed accessor.
  '/rc failed' paints in Failure ink, not Info, and /setup reads the
  enum. It used to match English status-line prefixes, so a failed
  remote showed as "not available".
- An error cell offers "Alt+V:full error" only when the error wraps past
  4 rows. Alt+V still opens every error.
- Clipboard: native copy and cut say "Copied to the clipboard" through a
  typed toast, and a failure says "Clipboard copy failed: {error}". That
  is the new MessageId ClipboardCopyFailed, translated in all 15 packs.
  The duplicate Cmd+C composer path calls copy_active_selection.
- NotificationProviderFallback leads with the switch and puts the reason
  after a clause joint in every pack, so the toast survives at 80-100
  columns instead of vanishing below about 146.
- notice_budget also respects the permission chip's floor, so the kit
  never clips a notice with '...'.
- The effort field reads "auto→high", not "auto: high".
- The elevation card drops its duplicate in-body heading and the
  "Tool: exec_shell" row when a command is shown.
  ElevationTitleSandboxDenied had no other use and is removed from the
  enum and all packs.

Transcript cards:
- The checklist card drops its "checklist: <tool>" row. The legacy
  change card maps raw statuses through TodoStatus to four new
  translated MessageIds ("in progress", not "in_progress").
- A failed read or search entry carries its reason: ExploringEntry.error
  is set from the tool result on failure.
  - A single-entry card shows up to 6 rows and Alt+V when rows are hidden.
  - A multi-entry card shows only the first line, because the cell holds
    one detail record and Alt+V there could open a sibling's record.
- Body rows no longer repeat what the header already shows in full:
  - exploring done/live, web-search query and image path;
  - a generic card's name, and its args when the header carries them.
    That compares the value alone or a " · value" suffix, not a raw
    suffix.
- No double space, and the parallel strip lists only non-zero counts.
- Every affordance row joins with " · ". "Output shortened" gets the
  transcript rail like its siblings.
- MCP calls no longer collapse into a run summary (their side effects
  cannot be known). Run summaries show "read file", not "read_file".

Tests whose pinned copy changed are updated: clipboard receipts, the
effort label, elevation titles in en/zh-Hans/ja/zh-Hant, the checklist
status, the collapsed-run summaries, readiness, and two ExploringEntry
literals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
@Hmbown
Hmbown marked this pull request as ready for review October 11, 2026 22:48
Copilot AI balanced review requested due to automatic review settings October 11, 2026 22:48

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@Hmbown
Hmbown merged commit ef35e39 into main Oct 11, 2026
52 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The cross-cutting 136-file release branch includes runtime, authentication, execution, and UI changes whose remaining installed-candidate and PTY validation requires final human review.

0 open findings

What changed in this PR

Prepares Codewhale 0.10.2 by consolidating release-blocking correctness, observability, UX, localization, performance, and release-documentation work.

Changes:

  • Improves shell-job inspection, cancellation, background execution, goal handling, and sub-agent presentation.
  • Corrects OAuth, snapshots, constitution workflows, approval UI, localization, and markdown rendering.
  • Updates performance paths, conformance fixtures, release metadata, documentation, and vendored ratatui assets.
File Description
CHANGELOG.md Documents 0.10.2 changes and limits.
Cargo.lock Updates resolved dependencies.
crates/​config/​src/​user_constitution.rs Corrects constitution projection and ratification.
crates/​localization/​locales/​ca.json Updates Catalan UI copy.
crates/​localization/​locales/​de.json Updates German UI copy.
crates/​localization/​locales/​en.json Updates English UI copy.
crates/​localization/​locales/​es-419.json Updates Latin American Spanish copy.
crates/​localization/​locales/​fr.json Updates French UI copy.
crates/​localization/​locales/​hi.json Updates Hindi UI copy.
crates/​localization/​locales/​id.json Updates Indonesian UI copy.
crates/​localization/​locales/​ja.json Updates Japanese UI copy.
crates/​localization/​locales/​ko.json Updates Korean UI copy.
crates/​localization/​locales/​pt-BR.json Updates Brazilian Portuguese copy.
crates/​localization/​locales/​ru.json Updates Russian UI copy.
crates/​localization/​locales/​uk.json Updates Ukrainian UI copy.
crates/​localization/​locales/​vi.json Updates Vietnamese UI copy.
crates/​localization/​locales/​zh-Hans.json Updates Simplified Chinese copy.
crates/​localization/​locales/​zh-Hant.json Updates Traditional Chinese copy.
crates/​localization/​src/​lib.rs Extends localized message definitions.
crates/​tui/​CHANGELOG.md Synchronizes TUI release notes.
crates/​tui/​Cargo.toml Adjusts TUI dependencies and doctests.
crates/​tui/​src/​commands/​groups/​config/​config.rs Updates configuration command behavior.
crates/​tui/​src/​commands/​groups/​config/​mod.rs Adjusts config command registration.
crates/​tui/​src/​commands/​groups/​core/​constitution.rs Fixes constitution review and ratification.
crates/​tui/​src/​commands/​groups/​core/​core.rs Updates mode command copy and usage.
crates/​tui/​src/​commands/​groups/​utility/​jobs.rs Routes job inspection through the live pager.
crates/​tui/​src/​commands/​mod.rs Updates command dispatch.
crates/​tui/​src/​commands/​traits.rs Adjusts command contracts.
crates/​tui/​src/​compaction.rs Reduces compaction work.
crates/​tui/​src/​core/​authority/​auto_review.rs Refines approval behavior.
crates/​tui/​src/​core/​engine.rs Updates engine lifecycle handling.
crates/​tui/​src/​core/​engine/​compaction.rs Consolidates compaction-pressure calculation.
crates/​tui/​src/​core/​engine/​context.rs Shares turn-start context history.
crates/​tui/​src/​core/​engine/​preview/​tests.rs Updates preview expectations.
crates/​tui/​src/​core/​engine/​tests/​test_cases_04.rs Updates engine regressions.
crates/​tui/​src/​core/​engine/​tests/​test_cases_13.rs Updates engine regressions.
crates/​tui/​src/​core/​engine/​tests/​test_cases_15.rs Updates engine regressions.
crates/​tui/​src/​core/​engine/​turn_loop.rs Corrects turn completion accounting.
crates/​tui/​src/​core/​engine/​turn_loop/​model_step.rs Refines model-step lifecycle handling.
crates/​tui/​src/​core/​turn.rs Improves context estimation.
crates/​tui/​src/​fleet/​executor.rs Relocates CLI parsing coverage.
crates/​tui/​src/​lib/​terminal_mode_test_cases_03.rs Updates terminal-mode coverage.
crates/​tui/​src/​oauth.rs Removes the unsupported OAuth parameter.
crates/​tui/​src/​provider_readiness.rs Clarifies provider readiness states.
crates/​tui/​src/​remote_control.rs Updates remote-control status handling.
crates/​tui/​src/​rlm/​session.rs Refines session context sharing.
crates/​tui/​src/​runtime_handoff.rs Updates runtime handoff behavior.
crates/​tui/​src/​runtime_threads.rs Adjusts runtime initialization boundaries.
crates/​tui/​src/​session_manager.rs Updates session restoration state.
crates/​tui/​src/​snapshot/​repo.rs Restores snapshots on Git 2.43.
crates/​tui/​src/​todo_snapshot.rs Shortens todo tool receipts.
crates/​tui/​src/​tools/​goal.rs Adds yield progress and usage accounting.
crates/​tui/​src/​tools/​mod.rs Updates tool registration and status handling.
crates/​tui/​src/​tools/​shell.rs Fixes job cancellation, polling, and inspection.
crates/​tui/​src/​tools/​shell/​tests.rs Updates shell-job coverage.
crates/​tui/​src/​tools/​subagent/​engine.rs Refines delegated-agent execution.
crates/​tui/​src/​tools/​subagent/​mod.rs Bounds checkpoint projection and lifecycle state.
crates/​tui/​src/​tui/​active_cell.rs Updates active-cell rendering state.
crates/​tui/​src/​tui/​app.rs Integrates new UI and job state.
crates/​tui/​src/​tui/​app/​init.rs Adjusts application initialization.
crates/​tui/​src/​tui/​app/​tests.rs Updates application behavior coverage.
crates/​tui/​src/​tui/​app/​types.rs Extends typed application state.
crates/​tui/​src/​tui/​approval.rs Localizes approval presentation.
crates/​tui/​src/​tui/​approval/​elevation.rs Simplifies elevation cards.
crates/​tui/​src/​tui/​approval/​previews.rs Adds typed preview state.
crates/​tui/​src/​tui/​approval/​tests.rs Updates approval coverage.
crates/​tui/​src/​tui/​footer_hints.rs Corrects footer controls and clipping.
crates/​tui/​src/​tui/​history.rs Refines history-cell presentation.
crates/​tui/​src/​tui/​history/​checklist.rs Removes redundant checklist labels.
crates/​tui/​src/​tui/​history/​file_mutation.rs Uses patch-oriented edit presentation.
crates/​tui/​src/​tui/​history/​tests.rs Updates history rendering coverage.
crates/​tui/​src/​tui/​history/​tool_output.rs Improves tool output status rendering.
crates/​tui/​src/​tui/​history/​tool_run.rs Humanizes tool-run presentation.
crates/​tui/​src/​tui/​markdown_render.rs Fixes headings and table rendering.
crates/​tui/​src/​tui/​mouse_ui.rs Pins clicked transcript operations.
crates/​tui/​src/​tui/​mouse_ui/​primary_tests.rs Updates mouse interaction coverage.
crates/​tui/​src/​tui/​pager.rs Adds live, followable job inspection.
crates/​tui/​src/​tui/​pet_watch/​full.rs Shows delegated agents in the pet view.
crates/​tui/​src/​tui/​pet_watch/​mod.rs Reduces idle pet work.
crates/​tui/​src/​tui/​phase_strip.rs Updates phase and failure presentation.
crates/​tui/​src/​tui/​provider_picker.rs Refines provider onboarding states.
crates/​tui/​src/​tui/​selection.rs Tracks stable transcript selection ownership.
crates/​tui/​src/​tui/​setup/​mod.rs Fixes setup navigation and status copy.
crates/​tui/​src/​tui/​shell_job_routing.rs Formats and refreshes job inspectors.
crates/​tui/​src/​tui/​subagent_routing.rs Improves delegated-agent labels and state.
crates/​tui/​src/​tui/​tool_routing.rs Centralizes tool status presentation.
crates/​tui/​src/​tui/​ui/​activity_detail.rs Opens the selected operation’s details.
crates/​tui/​src/​tui/​ui/​apply.rs Applies updated goal and error states.
crates/​tui/​src/​tui/​ui/​event_loop.rs Refreshes live job inspectors.
crates/​tui/​src/​tui/​ui/​frame.rs Updates UI framing and fallback layout.
crates/​tui/​src/​tui/​ui/​handlers.rs Routes job and task actions.
crates/​tui/​src/​tui/​ui/​task_projection.rs Avoids repeatedly copying shell output.
crates/​tui/​src/​tui/​ui/​tests.rs Updates integrated UI coverage.
crates/​tui/​src/​tui/​views/​help.rs Updates help presentation.
crates/​tui/​src/​tui/​views/​mod.rs Registers revised views.
crates/​tui/​src/​tui/​widgets/​approval_band_legacy.rs Uses translated approval metadata.
crates/​tui/​src/​tui/​widgets/​mod.rs Updates widget exports.
crates/​tui/​src/​tui/​widgets/​tool_card.rs Refines tool-card statuses and affordances.
crates/​tui/​src/​tui/​work_surface/​model.rs Updates job, task, and agent projections.
crates/​tui/​src/​utils.rs Throttles stale atomic-temp cleanup.
crates/​tui/​tests/​fixtures/​conformance/​events/​approval_denied.golden.jsonl Re-records approval-denied events.
crates/​tui/​tests/​fixtures/​conformance/​events/​cancel_midstream.golden.jsonl Re-records cancellation events.
crates/​tui/​tests/​fixtures/​conformance/​events/​one_tool_call.golden.jsonl Re-records single-tool events.
crates/​tui/​tests/​fixtures/​conformance/​events/​parallel_tool_calls.golden.jsonl Re-records parallel-tool events.
crates/​tui/​tests/​fixtures/​conformance/​events/​plain_answer.golden.jsonl Re-records plain-answer events.
crates/​tui/​tests/​fixtures/​conformance/​events/​provider_error_after_tool_call.golden.jsonl Re-records provider-error events.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​agent_suggest.golden.json Updates agent prompt golden.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​agent_suggest.tools.golden.json Updates agent tool-catalog golden.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​plan_mode.golden.json Updates plan-mode prompt golden.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​plan_mode.tools.golden.json Updates plan-mode tools golden.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​trusted_project_instructions.golden.json Updates trusted-project prompt golden.
crates/​tui/​tests/​fixtures/​conformance/​prompt/​trusted_project_instructions.tools.golden.json Updates trusted-project tools golden.
docs/​BUILD_PERFORMANCE.md Documents build-performance changes.
docs/​CONFIGURATION.md Updates configuration guidance.
docs/​CONTRIBUTORS.md Synchronizes contributor credits.
docs/​GUIDE.md Updates user-facing command guidance.
docs/​SUBAGENTS.md Documents delegated-agent behavior.
docs/​TOOL_LIFECYCLE.md Documents revised tool lifecycle.
docs/​design/​DECONSTRUCTION_ROADMAP.md Updates runtime-split progress.
docs/​design/​TUI_DECONSTRUCTION.md Updates TUI boundary metrics.
docs/​features.toml Registers the user-visible feature changes.
docs/​zh_hans/​SUBAGENTS.md Updates Chinese sub-agent documentation.
docs/​zh_hans/​TOOL_LIFECYCLE.md Updates Chinese lifecycle documentation.
pet/​scripts/​check-shared.py Sends the current appearance schema.
pet/​tui/​Cargo.lock Updates pet TUI dependency resolution.
pet/​tui/​Cargo.toml Updates the pet TUI dependency.
scripts/​release/​check-versions.sh Updates release-version validation.
scripts/​runtime-boundary-baseline.json Lowers runtime-boundary counts.
scripts/​runtime-contract-budget.json Updates the measured contract ceiling.
vendor/​codewhale-ratatui/​CHANGELOG.md Records vendored rendering changes.
vendor/​codewhale-ratatui/​Cargo.lock Updates vendored dependency resolution.
vendor/​codewhale-ratatui/​Cargo.toml Versions the vendored crate.
vendor/​codewhale-ratatui/​UPSTREAM.json Records upstream provenance.
vendor/​codewhale-ratatui/​src/​avatar_sprite.rs Adds crisp half-block sprites.
vendor/​codewhale-ratatui/​src/​whale_motion/​pixels.rs Updates pixel rendering.
web/​lib/​release-credits.ts Adds 0.10.2 contributor credit.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants