mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 10:36:05 -10:00
main
118
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
92b4900d15 |
fix(engine): stop replaying inference with unknown outcomes [skip ci]
Use typed dispatch confidence at retry owners; only proven transient pre-dispatch failures, ordinary429 and actual read-only operations may retry. Stop opened-stream replay and reqwest retry/redirect bypasses. Keep Interrupted child handback and source-bound primary unknown coverage through existing Runtime/TUI/exec owners; terminal exec failure exits1. Reconcile retry promises and parsed compatibility knobs in maintained docs. Validation: ordinary CLI build passed; 131 existing Engine and28 TUI checks passed via126+28 unchanged-source reuse,3 corrected fixtures,2 corrected multi-thread SSE fixtures. No new tests or comments. Original failed builds/check receipts retained. 40 local ordinary controls yielded 38 qualified and2 isolated safety-only observations retaining their full source-accounting failure underP04. Old CLI reproduced2acceptedPOSTs/ 2simulated effects; candidate ambiguous requests retained1/1 without replay. Existing bounded429/GET/pre-dispatch and manual next-turn controls passed. All2315 source inputs held frozen during each build/observation. Limits: full primary late/historical/isolated source accounting and broader P02 recovery remain open. HTTP/1 local proof only; no provider spend, Windows/Deepin/FreeBSD, installed package or final CI/release claim. Receipts: CW/artifacts/engine-0103-execution-20261102/ inference-retry-v4/RECEIPT.json and inference-retry-qa/RESULTS.json. |
||
|
|
0cf390f01e |
feat(tui): change mode and permissions mid-turn; record steering in Unreleased (CW-7552)
Mode and permission posture can now change while a turn is running. Tab, Shift+Tab, Alt shortcuts, /mode, the hotbar, /auto and /config mode|approval* no longer hit the #2982 turn lock; model, thinking and provider stay locked because they change the route the in-flight request is on. Decision: a change applies at the engine's next step in the same turn, not at the next turn and not by restarting the streaming response. The engine already drains the live authority snapshot before each tool batch, at every approval gate and at the per-step preparation boundary; a call nobody approved, or one whose approval is narrowed, is returned to the model to retry. New: the preparation boundary now records the mode notice (and Operate contract) via Engine::record_mode_context, so the next model request is told the new mode and the notice is a session message (model-visible means logged). While a turn runs, the TUI shows "<Mode> · <permissions> — applies at the agent's next step in this turn"; the engine's existing "Permissions: … · <mode>" status confirms the apply. Reference comparison (CW/refs): Codex steers at the next safe point and applies /model and /permissions to the next turn; Grok Build queues by default, injects steers at tool/model safe points and allows Plan/permission toggles mid-turn with turn-start reminders. Neither preempts the in-flight request. Steering itself: the preemption source from |
||
|
|
f421390771 |
feat(tui): Ctrl+C clears a non-empty idle composer before arming exit
Founder decision on #6237 (option A, 2026-10-25): plain Ctrl+C on an idle
composer that holds a draft clears it recoverably, and Ctrl+Z restores it
through the existing ClearedInputRestore path. The two-tap exit prompt arms
only once the composer is empty. Cancel still beats clear: a selection
copies first, then an in-flight turn, compaction or goal-continuation wait
is cancelled, and only after that does a non-empty composer clear. This
reverses the #1757 one-meaning-per-key split for Ctrl+C. It matches the
muscle memory from sibling tools that the issue describes.
ctrl_c_disposition gains a ClearInput branch between CancelTurn and
ConfirmExit. The clear body that the Esc ClearInput arm had inline is now
App::clear_composer_draft: it resets backtrack, disarms quit, drops
edit_in_progress, makes the recoverable clear and shows the restore tip.
Esc and the new Ctrl+C arm both call it. Disarming quit on clear means a
cleared draft restarts the order clear, then arm, then exit. Without the
disarm, Ctrl+C on an empty composer, then typing, then Ctrl+C twice would
exit right after the clear. On main, an armed prompt plus a draft exited
on the very next Ctrl+C. Esc-clear now disarms a pending exit too.
PR #7084 also added a ClearInput arm to the launch-screen Ctrl+C block.
That arm is left out because the block cannot be reached:
LaunchState.composer_focus is always true. handle_launch_composer_key
returns ComposerAuthority for Ctrl+C, so the key falls through to the
session-shell arm, which also clears a launch-screen draft.
The PR's three new tests and its added rationale comments are not carried.
The existing doc comments are updated to the new priority order.
docs/KEYBINDINGS.md now lists the global Ctrl-C row in real priority order
and adds an editing-table row. The [Unreleased] CHANGELOG entry is added. In-app key help now names
draft clearing in all 15 locale packs; the install guide agrees. The
pre-existing vocabulary failure is corrected by advertising only the
canonical --full-access flag in the TUI guide; the parser alias remains.
Verified as one frozen batch at 7db526a725 plus consensus patch
sha256 d6418055436eaada55f4cbedc954a0eeeb51d9d922716a3588006cf7932fab45:
- scripts/with-hermetic-test-home.sh scripts/dev-cargo.sh nextest run
-p codewhale-tui -p codewhale-localization --lib --locked:
15343 run, 15341 passed, 2 failed, 25 skipped; build 3m41s.
The two fixed-width rendered-fixture failures came from the long SSD
TMPDIR wrapping paths mid-needle. Same source/binary, shorter SSD TMPDIR,
only those two tests rerun: 2 passed, 15312 skipped. Distinct passing
coverage across both runs: 15289 TUI + 54 localization tests.
- scripts/with-hermetic-test-home.sh scripts/dev-cargo.sh test
--manifest-path vendor/codewhale-ratatui/Cargo.toml --locked --all-targets:
145 passed, 0 failed (128 library and 17 example tests).
- fmt and diff checks passed; changelog sync passed; runtime boundary PASS
(120 closure modules); dead-code budget 212; blocking-call budget 543
across 165 files; locale parity 2583 keys in all 15 packs.
- The vocabulary guard initially failed on an already-published advertised
legacy alias. Both refuters confirmed the docs-only correction; the
unchanged guard then passed. Web prebuild and check-facts passed.
Before peer reconciliation, only .gitignore, docs/MODES.md and generated web
documentation changed after native tests; frozen compiler inputs were identical.
Published peer commits aa45bf84ef/485382f81d then advanced main. Their exact
diff was integrated, preserving their ancestry and regenerating web docs.
Focused reconciliation nextest (TUI ops/runtime_info/spawn and CLI cloud
callers): 117 passed, 0 failed, 15698 skipped; source remained frozen
(104 TUI, 13 CLI). Command/filter and source SHA256
are retained in coordination/land-0103-20261025/reconciliation-test-run.json.
Final integrated tree
|
||
|
|
135319aa1a |
feat(acp): --full-access flag for serve --acp, accepted after the subcommand
Probing the installed 0.10.2 binary over ACP showed three things:
- `codewhale serve --acp` runs under Ask;
- `codewhale --yolo serve --acp` runs under Full Access;
- `codewhale serve --acp --yolo` is rejected ("unexpected argument", exit 2).
That last form is the one editors write in their agent config. Founder
decision: Full Access is yolo (ApprovalMode::Bypass). A configured
`sandbox_mode = "danger-full-access"` must not widen Ask or Auto-Review, and
no state may have the sandbox off while the agent still asks.
Changes:
- `--full-access` is the visible flag; `--yolo` stays an alias
(runtime_options.rs).
- The dispatcher lifts `--full-access` and `--yolo` out of the `serve`
passthrough arguments (`capture_serve_full_access`), stopping at a `--`
separator. It sets the same runtime option as the global flag, so the
value still flows through the CODEWHALE_YOLO env layer, and managed
config above that layer still wins. Setting `config.yolo` after load
would have bypassed a managed `yolo = false`.
- `serve --acp` writes one stderr line naming the ACP permission and
sandbox it will run with, computed with `sandbox_policy_for_turn`. When
Full Access is off, the line says how to turn it on.
- The ACP hint and the approval_policy "never" error name `--full-access`.
- `SandboxPolicy::config_value()` replaces a duplicated match in
`apply_requirements`.
- docs/MODES.md, docs/RUNTIME_API.md and CHANGELOG are updated.
Verified:
- `scripts/dev-cargo.sh build -p codewhale-cli --locked`: built, 0
warnings.
- The built binary was probed over ACP. For each launch, a fresh
CODEWHALE_HOME and runtime dir; then `initialize`, `session/new`, and a
read of the `permission` configOption:
- `serve --acp`: ask. stderr: "ACP permission: ask; sandbox:
workspace-write. For Full Access start with `codewhale serve --acp
--full-access` ...".
- `--full-access serve --acp`: full-access, with sandbox
danger-full-access.
- `serve --acp --full-access`: full-access.
- `serve --acp --yolo`: full-access.
- nextest codewhale-cli, filtered: 36 passed, including
`clap_command_definition_is_consistent` and
`yolo_flag_writes_only_the_codewhale_env_var`.
- nextest codewhale-tui, filtered to acp_server, requirements,
sandbox::policy and runtime_options: 61 passed (38 acp_server, 6
requirements).
- Not run: clippy, Windows, hosted CI.
The Seatbelt half of #4955 is not done.
Refs #6992 #4955
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
||
|
|
7d9ebfffeb |
fix: retry Chat opens on both HTTP versions, give body text an explicit ink, name the export command at every resume, and tell a read-only shell it is offline
Five founder-approved 0.10.2 riders, each independently reviewed by an adversarial reader before landing. #7045 — the Chat (SSE) stream open now goes through `client_for_policy` and `send_stream_open_with_retry` on both the default HTTP/2 policy and the HTTP/1.1 fallback, instead of a separate single-send fallback path that returned a raw response. The `reasoning_content` diagnostic moved onto the open error, so it also covers the default path, and the post-open non-success branch is a typed `LlmError`, matching the Responses adapter. `open_stream_json_with_retry` had no other caller and is deleted. Still open from #7045: the retry budget is bounded by `[stream] open_timeout_secs`; a plan-usage 429 is still classified as a transient rate limit; the "Retry stopped" line still names a per-kind counter. #7043 — the modal and underwater surfaces, fleet setup, the automations view, the worktree manager and three sites that had only a background now set `fg(palette::TEXT_PRIMARY)` for body text, so a surface's ink no longer depends on what was painted before it. `color_compat::enforce_cell_contrast` now maps `TEXT_BODY` to the terminal's own ink when the cell is unpainted (a `Color::Reset` background) and no ground was measured, which covers the ivory-on-white case on an unmeasured light terminal. Measured and painted grounds keep the previous behaviour. Existing test updated: `unknown_background_leaves_unpainted_cells_alone` became `unknown_background_gives_unpainted_body_text_the_terminal_ink`, which is what the change makes true. Deliberately NOT changed: the live transcript's block style. Its parity test `mounted_transcript_live_overlay_stream_resize_preview_and_links_match_frozen_painter` renders the legacy painter and the new one and asserts identical buffers; an `fg` on one side only breaks that contract, and the transcript's body text already gets correct ink from the contrast floor above. #6996 — `session_export::export_recovery_hint(id)` words the remedy once and names the real session id. It is used at the TUI resume, the executor resume and the Runtime API. `map_resume_thread_create_err` takes the session id and also treats "persisted provider route requires exact custom provider" as a client error, where it was previously reported as a 500. #7040 — `READONLY_OFFLINE_NETWORK_HINT` tells a refused read-only command that the run has no network, what would grant one, and to use a web tool or report the source unreachable. Emitted only when the command plausibly needs the network AND the result was sandbox-denied or looks like a network failure, and never over a bwrap setup failure that has its own hint. `finish_contract_bash_result` takes the hint as a new trailing parameter; both test call sites are updated. Known limit: a network attempt from Python or `gh` still gets no hint. #6992 — SANDBOX.md and CONFIGURATION.md, English and Chinese, now state that `sandbox_mode` can only narrow the sandbox the permission mode already chooses, so `danger-full-access` and `external-sandbox` take effect only in Full Access. Documentation only. Verification: k90 nextest (crates/tui lib, 22 filters): 4838 tests run, 4835 passed, 3 failed; after the three fixes below, the same 4838-test binary rerun of exactly those 3: 3 passed, 0 failed. cargo check -p codewhale-tui --lib --tests: exit 0 (12m26s). cargo fmt --all -- --check: exit 0. Refs #7045 Refs #7043 Refs #6996 Refs #7040 Refs #6992 Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
7b16979c64 |
feat(auto-review): stop a turn after repeated guardian denials
Auto-Review stops a turn after three guardian denials in a row, or ten of the turn's last fifty reviews, and the status line says why; the remaining calls in that batch are refused without another review. Timeouts and failed reviews do not count. The breaker sentence is carried as the turn's error, so hosts and runtime threads record it. Docs: docs/MODES.md and the zh_hans edition. Observed on the batch binary with a loopback mock whose guardian replies always deny: exactly three reviewer requests, then the footer reads "Auto-Review denied 3 actions in a row, so the turn was stopped." (artifacts/takeover-0102-20261021/obs/sessions). Refs #6478 Batch evidence (one combined tree, input hash a47518092a4c49de37d93381d392aec4fc4c28fd612f6e6192d327acf4736d95; the intermediate commits of this batch were not compiled on their own, only the combined tree): cargo fmt --check clean; tui lib nextest over the lane filters 4096 passed, 0 failed, plus 1268 passed after the changelog edit; fp55 shared-process cargo test 161 passed, 0 failed, 1 ignored; tui integration install::/skill_cli:: 42 passed, 0 failed; conformance goldens regenerated, 33 passed; execpolicy 89 command_safety and 256 crate tests passed; lane 74; runtime continual_harness 8; config private_directory 12, route/models_dev 121, configured_models 9; app-server daemon_client 1, daemon_socket 15; localization 54; clippy -D warnings on tui, execpolicy, lane, runtime, app-server and config clean with CI's exact flags (the plan's stricter run flagged 26 pre-existing sites outside the batch: 25 are lints CI allows, one collapsible_if is fixed in this batch); cargo check tui --all-targets clean (a first run failed on a half-applied call-site change of the citation fix; the rerun after the fix passed); aarch64-unknown-linux-gnu check of tui, app-server and config not run: the ring and libdbus-sys build scripts fail for the cross target on this Mac, so the Linux-only bubblewrap and boot-id paths were not type-checked here and need a Linux host; blocking-call budget 540 sites within budget; dead-code budget 214 at budget; sync-changelog --check, check-versions, check-bundled-plugin-claims, sync-marketplace --check and web check-facts all passed; npm wrapper node --test 101 passed, 0 failed. No hosted CI ran; final validation owns that. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
ac5b611fe0 |
fix: complete 0.10.2 terminal and release blockers
Match undo snapshots conservatively for long, multiline and trimmed prompts; keep terminal outcomes attached to the unchanged conversation prefix through rewinds, replacement and branching. Document exec Full Access, reject misplaced flags, honor stricter sandboxes, and report actual enforcement. Save tool-enabled exec sessions in every format with terminal failures and separate retention. Restore local-runtime onboarding and update complete locale packs and docs. Serialize RC test-binary builds to avoid the reproduced linker OOM. Replace both Chocolatey NSIS consumers with a checksum-pinned official installer and verified compiler version. Put the release summary first, retain detailed notes and contributor credits, and set an explicit release title. Validation on frozen 849af501cf plus this diff: workspace check and CI-flag Clippy passed; formatting passed; focused TUI 683 passed, 0 failed, 1 ignored; CLI 541 passed, 0 failed; feature registry 2 passed; localization 54 passed. The registry ran with the empty default feature disabled; an earlier redundant build was intentionally interrupted before tests. Source hashes stayed fixed. After excluding the held change and folding the pending changelog into 0.10.2 dated 2026-10-19, regenerated web data and ran the literal gate: npm test && npm run check:web passed. Wrapper 101, runtime SDK 19, extension host 413 passed/7 skipped, web 772 passed, dependency security 7 passed; all failure counts zero. Source hashes remained unchanged. The earlier stale-catalog failure was repaired before this final gate. README translations (18), locale coverage (16), release-body tests, dated version/changelog contracts and OHOS dependency guard passed. Final release body rendering preserves all notes and credits outside the held entry. Workflow syntax passed; full ShellCheck retained the same 12 pre-existing warnings. Independent reviews found no remaining concrete issue in scope. Held session-only key commit 849af501cf is excluded before pushing. The final candidate still needs exact-SHA hosted CI, RC artifacts and binary walkthrough; local checks do not qualify Windows provisioning, deployment or publication. Co-Authored-By: Claude Opus 5.5 <[email protected]> Co-Authored-By: Codex <[email protected]> |
||
|
|
ecf50ab598 |
fix(engine,shell): harness fixes from the DeepSeek/DSH parity comparison
On 2026-10-17 Codewhale and DeepSeek's own harness, DSH 0.2.1-rc.2, were compared on deepseek-flash (DeepSeek-V4.1-Flash-1017). The comparison covered wire format, multi-turn state, cache, prompt and tool surface, and mined 185 exec runs and 310 local sessions. A skeptic re-checked every finding. A blind patch A/B scored Codewhale's edit mode 5/5, DSH 3/5 and read-only JSON patches 2/5. Evidence is in CW/artifacts/deepseek-harness-parity-20261017/. This commit fixes the contained defects; CW-7450 tracks the rest. - zsh: the tool named bash runs $SHELL, and zsh's NOMATCH and EQUALS options broke Bash idioms the model writes, such as grep --include=*.rs and [ "$a" == "$b" ]. That caused 334 failures in 196 of 310 sessions, and in exec runs 175 greps never ran. ShellDispatcher::build_command_parts now starts zsh with +o nomatch +o equals (ShellKind::is_zsh), and ZSH_GUIDANCE says so. Display still uses the requested command. The same dispatcher runs user ! commands. - task_shell_wait is now in DEFAULT_ACTIVE_NATIVE_TOOLS. bash and its backgrounded results tell the model to call it directly and not to sleep-poll. Before, every long job cost a tool_search round trip plus a change:tool_surface re-pin (188 tool_search calls, 208 "sleep N" commands). KV-cache effect: the frozen prefix grows by one small tool schema, and the mid-session re-pin goes away. TOOL_SURFACE.md (en and zh_hans), MODES.md, public-surface-facts.json, web tools copy, the conformance goldens and the tests that pin the default list are updated. - exec_stream_final_answer_text skips runtime-owned user messages (runtime_handoff::is_runtime_owned_user_message) when locating the turn start. A background-shell completion appended after the answer no longer makes the receipt report an empty final answer, which happened in 52 of 185 runs; fleet then recorded no answer. - The engine's local stop_reason_is_output_limit is deleted, and continuation.rs now uses codewhale_models::is_output_limit_stop_reason, which strips the incomplete: prefix that the Responses parser adds. A reasoning-only output-limit stop on deepseek-flash is no longer re-sent up to two more times, and it now reports the output-limit message. The three extra spellings the local helper knew (model_length, output_limit, max_completion_tokens) move into the shared helper. The misplaced should_fail_no_sendable_content doc comment goes back on its function. - tool_choice "none" now reaches the provider. The Responses builder forwards none and keeps sending auto for every other choice, and the DeepSeek Chat path keeps none while thinking is on; required and named choices are still dropped there because DeepSeek returns a 400 for them. The compaction known-limit comment is updated to match. - is_incomplete_stop_reason treats insufficient_system_resource and aborted, DeepSeek Chat's interrupted-generation finish reasons, as incomplete. Every item except the zsh change was drafted by Codewhale running DeepSeek-V4.1-Flash-1017 in scratch exports. Claude reviewed each diff and corrected two of them: the stop spellings the shared helper lacked, and the stale compaction comment. Gates for this batch (source |
||
|
|
b093b61cea |
docs(modes): list /provider among the slash surfaces the turn lock covers
docs/MODES.md (en, zh_hans) said every live-route change, provider included,
is refused mid-turn on every surface. For /provider and the provider picker
that was only true from
|
||
|
|
be980da403 |
0.10.2 candidate: endpoint-scoped catalog, tiered pricing and release verification (#6968)
Squash of the 0.10.2 candidate branch wip/0.10.2-6396-handoff-20261012: endpoint-scoped model catalog and tiered pricing (#6396), the takeover fixes found while qualifying it, and the release-verification tooling. The full commit list and per-commit evidence are in PR #6968. Qualification of the squashed tree (head |
||
|
|
e6c08cf168 |
docs: drop the Full Access confirmation from modes, keybindings, runtime API and the 0.10.2 notes
Refs #6470. Follows the removal of the confirmation modal: MODES, KEYBINDINGS (en, zh-Hans) and RUNTIME_API (en, zh-Hans) no longer describe the popup, full_access_repos or the full_access_confirmation 400, and the 0.10.2 bullet now says only what ships: a 'Permissions changed to ...' transcript line plus a status item and thread.permissions_changed event in runtime threads. crates/tui/CHANGELOG.md regenerated with scripts/sync-changelog.sh; web lib/changelog.generated.ts is unchanged (derive-changelog.mjs reports current). web vitest: 772 passed; check-versions, readme translations, locale parity pass. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> |
||
|
|
f51193b368 |
docs: resync 18 README translations with the 0.10.2 README and drop retired vocabulary from MODES
|
||
|
|
58d082898c |
docs(modes): Shift+Tab away from repo-kept Full Access removes the saved grant
Observed in the real-terminal full-access journey on 0.10.2 (
|
||
|
|
34bf6568f2 |
0.10.2 candidate: MCP connects at start, background promotion, shell inspector, Full Access confirmation, Daytona and Sprite removal, composer-first launch, QA fixes
One integrated slice of the 0.10.2 release work, three-way merged onto
|
||
|
|
bdcc8cfc5f |
fix(tui): let Full Access actually grant Full Access; finish the file-search surface
Full Access is ApprovalMode::Bypass, but the deterministic Auto-Review floor
still hard-blocked calls under it: publish-like commands, destructive
background/headless work, and the Windows npm-launcher platform hold all
returned AutoReviewPlanDecision::Block. The founder's own semantics for the
posture are the opposite, and the engine already reports "Full Access" for it.
The floor now applies only in the reviewing postures (Suggest/Auto/Never).
ForcePrompt stays unchanged there; the Bypass arm of the disposition is gone
rather than merely unreachable, because it was the code that authored the
contradiction.
Existing tests updated to the posture they now describe (no new tests):
- policy-level: destroyer and publish-shape assertions run under Suggest,
Bypass coverage asserts no hold, the Windows platform-floor test splits
Bypass from the reviewing postures
- engine-level: the background-destructive test now requires execution
(victim fixture asserted written) instead of a block
- child gate: a detached agent's catastrophic shell is held in Auto/Suggest/
Never and runs under Bypass
- ACP: the Full Access case asserts one fewer failure and one more completed
and in_progress update, matching the call that now executes
Also completes the file-search promotion rows: the eager inventory literal
gains file_search behind FIM's already-landed exclusion, the hook classifier
table gains ("file_search", "other"), the canonical-action comment no longer
calls it deferred, the zh TOOL_SURFACE mirror matches the shipped twelve, and
file_search.rs is rustfmt-clean under the repo build lock.
Names the built-in safety floor as a reviewing-posture guard in docs/MODES.md,
docs/SUBAGENTS.md and the zh mirrors.
Test evidence: nextest -p codewhale-tui focused set (auto_review, acp_server,
child_permission_gate, child_host, test_cases_08/09/11/12, subagent tests)
34 passed / 0 failed on the final run; the wider 708-test run before it passed
704 with only the four assertions updated here failing.
|
||
|
|
1bddf50a7e |
fix(tui): repair undo identity, child approvals, plan handoff, OCR test
Land the four 0.10.2 release repairs from the frozen review batch. The source reviews passed. This commit adds local compile and focused-namespace evidence, not hosted CI. Hosted CI on this head is the full proof. Repairs: - Undo (commands/contract/debug_operations.rs, commands/debug_mutation_host_tests.rs): refuse ambiguous, repeated, truncated, multiline, missing or multipart request labels instead of matching display snippets. Exactly one held match is required, and force cannot bypass identity checks. Addresses the P1 review on debug_operations.rs:245-251. - Child approvals (core/engine/handle.rs, child_host.rs, tools/subagent/*): keep ApprovalDecider through the child Approved and Denied outcomes, so receipts attribute the actual decider. A timeout stays a denial, attributed to Host. Consumers migrated. Managed Computer Use consent authority is unchanged. - Plan handoff (tui/plan_handoff.rs, tui/app.rs, tui/app/init.rs, tui/ui/*, docs/GUIDE.md, docs/MODES.md, docs/zh_hans/GUIDE.md): successful nonempty Plan prose offers handoff and queues its exact text once. Failed preparation rolls back only an unchanged owned seed. Refs #6902. Addresses the P2 review on plan_handoff.rs:48. - OCR and CI (tools/image_ocr/host_tests.rs, .config/nextest.toml, .github/workflows/ci.yml): the cancellation fixture waits on an explicit descendant latch and observes cleanup, instead of racing a one-second write. OCR and PDF host tests join the max-threads-1 group. macOS test compilation sets CARGO_PROFILE_TEST_DEBUG=0 before cache setup. Local evidence (macOS arm64, debug, library tests; not CI): - cargo test -p codewhale-tui --lib --locked --no-run -j 2: exit 0, 0 errors, one linker note. - With RUST_MIN_STACK=8388608 (the workflow value in ci.yml): plan_handoff 16 passed, 0 failed; core::engine::tests::child_host 19 passed, 0 failed. - With the 2 MiB default test-thread stack: plan_handoff 15 of 16 and child_host 10 of 19 pass. The rest overflow the stack in debug builds. Measured stack need is 4 to 8 MiB. All nine child_host tests exist at HEAD and passed HEAD's CI on Linux and macOS. - debug_mutation_host_tests 38 of 38; the approval routing test an_agent_approval_answer_reaches_the_agent_while_the_engine_is_busy 1 of 1; image_ocr::host_tests 8 of 8, including real_host_ocr_cancellation_bounds_parser_tree_and_never_replays. - cargo fmt -p codewhale-tui -- --check and git diff --check: clean. Not run here: the full 19k-test suite, nextest, Windows, doctests, and hosted macOS timing. The previous macOS job exceeded 2h45m. Limits, as reviewed: checkpoint admission is queued acceptance, not disk durability, and an accepted queued checkpoint cannot be recalled. Pending Plan ownership is ephemeral. No restart recovery or permanent custody is claimed. Signed-off-by: CodeWhale Bot <[email protected]> Co-Authored-By: Claude Haiku 5.5 <[email protected]> |
||
|
|
6abe4d4445 |
wip(0.10.2): plan-handoff-regression
Applied cleanly on top of edit-approval-preview and approval-default-and-labels; all 15 locale packs carry the same 2486 keys as en.json. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
559442d09a |
wip(0.10.2): esc-esc-rewind-files
The footer change itself is already in the undo commit with the wording from
UNDO-DESIGN.md ('Files not changed; conversation rewound. /undo puts files
back'), so this patch's BACKTRACK_REWOUND_NOTICE hunk in apply.rs is dropped.
Kept: the docs and the footer-width test, rewritten to the design wording.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
||
|
|
9dbc2efe1a |
fix: name an exhausted xAI account, keep refusal reasons readable, and make Operate the full-strength mode
- llm_client: a 403 whose body says the account is out of credits (xAI: "You have run out of credits or need a Grok subscription") is QuotaExhausted, not AuthorizationError. Out-of-credits phrases join the quota evidence set. - sanitize: a key ending in an outcome word (failed, denied, rejected, expired, ...) is never a credential, so "Authorization failed: <reason>" no longer renders as "Authorization failed: [redacted]". - Operate contract (runtime_handoff): same tools and authority as Work, used at full strength. Each substantive request becomes a goal via create_goal (the host never created one, contrary to the old text), plan kept in todo_write, workflows and parallel agents by default, independent review before done, background commands, automations offered with approval. Removes the old hold-back lines. - todo_write: tells models to keep a list for multi-step work instead of "Optional"; deletes the test that forbade that guidance. - Mode hint and docs/MODES.md describe Operate the same way; conformance goldens re-recorded; parent prompt ceiling re-measured to 89,602 B. Tests (macOS): sanitize+config redact 37 passed; llm_client/runtime_handoff /todo/quota 129 passed; conformance:: 33 passed after re-record; parent_agent_surface_stays_within_measured_ceiling passes. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
|
|
c0fa462ad6 |
docs: reconcile interactive questions and Chinese session wording with runtime
Auto-Review still exposes deliberate questions in interactive hosts; omitted or zero question timeout is indefinite. Remove a stale provider-count claim and update two Chinese wording expectations to the reviewed current-session labels. Combined localization tests52/0; full npm740/0 and check:web passed. Command boundary and migration checks passed. Chinese native layout and real provider qualification remain separate. Signed-off-by: Hunter B <[email protected]> |
||
|
|
9a775fbf03 |
fix(exec): keep a positional - prompt literal; test the exec dispatch (#6688)
Review of #6692: 1. A lone positional `-` read stdin, which changed behavior for raw-prompt callers: cloud dispatch builds `codewhale exec --auto <job.prompt>`, so a job whose prompt is `-` would block on or fail reading stdin. Only `--prompt-file -` reads stdin now; a positional `-` is prompt text again. Help text, docs/MODES.md (+ zh_hans) and the CHANGELOG say so. 2. The tests called `resolve_exec_prompt` directly and would pass with the exec dispatch call site reverted. A new integration test runs the real `codewhale-tui exec` binary against a wiremock provider and checks the user message the model receives: a 200 KiB `--prompt-file` body, a `--prompt-file -` stdin body, and a literal `-` with stdin piped (never read). Tests: - cargo test -p codewhale-tui --lib -- exec_prompt_file read_capped_text exec_accepts_split exec_keeps test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 13795 filtered out - cargo test -p codewhale-tui --test integration -- exec_turn_usage test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 179 filtered out - Dispatch call site reverted to `join_prompt_parts(&args.prompt)`: exec_prompt_reaches_the_model_from_prompt_file_and_stdin test result: FAILED. 0 passed; 1 failed (left: "") - Lone positional `-` arm restored: the unit test blocked reading stdin (killed after 9 minutes), which is the regression itself. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_014ZwqatxgVFxHvovngywnks |
||
|
|
d0b42c215d |
fix(exec): read the prompt from --prompt-file or stdin (#6688)
Cause: `codewhale exec` accepted its prompt only as positional argv, so a prompt past the kernel's per-argument ceiling (131071 bytes on Linux) failed with E2BIG before Codewhale started, with no alternative transport. Fix: add `--prompt-file <PATH>` (`-` = stdin), mutually exclusive with the positional prompt, which is now `required_unless_present = "prompt_file"`; a lone positional `-` also reads stdin. `resolve_exec_prompt` produces the effective prompt before any model call and fails loudly on a missing, unreadable, non-UTF-8 or empty source. Reading goes through a shared `read_capped_text` (also used by `apply`'s stdin patch reader) with a named 64 MiB byte limit. `-` is refused with `--parent-death-watch`, which owns stdin for Fleet workers. Implicit stdin reading when no prompt is given is not added: exec callers (Fleet) inherit pipes on stdin. An argv-side byte guard is not possible: the kernel rejects the exec before Codewhale runs. Tests: - cargo test -p codewhale-tui --lib -- exec_prompt_file read_capped_text exec_accepts_split exec_keeps test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 13795 filtered out - With resolve_exec_prompt reverted to the pre-fix argv join: test result: FAILED. 0 passed; 1 failed (left: "" vs the 540 KB file body) - Built binary: 540001-byte file via --prompt-file and via `cat | exec -` resolve and reach provider routing; empty stdin -> "exec prompt from stdin is empty"; missing file -> "failed to open --prompt-file nope.txt"; positional + --prompt-file -> clap ArgumentConflict. Fixes #6688 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_014ZwqatxgVFxHvovngywnks |
||
|
|
669c32d53f |
fix(approvals): keep Full Access for destructive MCP tools; doctor and dismissal edge cases
Review of the 0.10.1 addendum-remainder commits (CW-11, U7, policy rule 9). CW-11 ( |
||
|
|
b90590369a |
feat(approvals): honour readOnlyHint from reviewed plugins (CW-11)
Every MCP tool outside the five built-in resource helpers prepared as Suggest, so each Chromewhale page_snapshot and Computer Use screenshot prompted, while session auto-approve let every tool through, destructive or not. The MCP tool annotations the servers already declare were dropped at parse time. - McpTool now parses the MCP `annotations` object (readOnlyHint, destructiveHint). - McpPool::to_api_tools, which builds the catalog each turn, records one approval hint per model tool name: TrustedReadOnly only when the server is a reviewed plugin (reviewed_plugin provenance, catalog still authorized) and the tool declares readOnlyHint true without destructiveHint; the same claim from any other server is ignored. Destructive for any tool that declares destructiveHint true. A server that loses its review or a hint loses the relaxation on the next catalog build. - prepare_tool_call treats a TrustedReadOnly tool like the built-in read helpers (Auto, read_only), and never lets session auto-approve cover a Destructive one. The approval card text says which applies. - Computer Use consent and app_script gates still run first and are unchanged: request_access declares readOnlyHint but consent calls keep their own required card. Known limitation (in mcp.rs): the hint map is process-wide, keyed by model tool name, because call preparation has no pool handle; two pools exposing the same model name from different servers overwrite each other. Plugin servers carry synthesized plugin-* names, so this needs a user server named like a plugin server. docs/MODES.md states the rule. No-Issue: 0.10.1 addendum C5 (CW-11) Checks (targeted, local, shared dirty tree): - cargo test -p codewhale-tui --lib -- only_a_reviewed_plugin mcp_annotation_hints mcp_write_preparation: 3 passed, 0 failed - cargo test -p codewhale-tui --lib -- mcp::tests tool_preparation (within the 448-test touched-module run): 0 failed Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||
|
|
d4e555b56d |
Blue ocean: agent docs describe, runtime enforces, model decides
Strip behavior laws the runtime already enforces (or never did) from agent-facing docs, keeping every safety boundary and everything automation parses: - Output rituals become default shapes that compress when trivial: cw-slice (ladder rung, owner, slice, evidence), cw-orient (status block skips normal fields), cw-handoff (unordered sections), SUBAGENTS delegation briefs (a sentence beats the template). - Numeric self-limits become enforcement notes: no 3-5 call law (docs + scout prompt), caps are for the runtime to queue/clamp, never a reason to pre-refuse or pre-shrink valid work. - Singletons become guard-or-convention: only the turn loop is guard-tested; BASE_PROMPT/agent-tool moves go with the code plus a new guard, not around a prose fence. - Roles state the enforced grant (read-only posture refuses writes; parent dispatches a builder) instead of personal prohibitions. - Workflow VM denylist redirects to child workers; FLEET wizard drops key-level manual detail; fan-in is the default shape, not the only legal pattern; git conflict guidance keeps the incident warning with judgment restored. Deliberately kept: authority clamp, approval routing, safety floor, quote-N-passed, handoff done/suspected/blocked separation, exact trailer/branch/receipt shapes, the machine-parsed five-heading subagent output contract, CACHE/tui-contracts code invariants. Tests: explore_prompt 2 passed; structured-briefs assertion passed. |
||
|
|
4de9e9e281 |
refactor(goal): the model decides goals; the host stops guessing from verb lists
Founder clarification, 2026-09-09 (docs/design/TUI_DECONSTRUCTION.md): "the harness should let the model decide when a goal, plan, delegation, further investigation, or verification is useful." Operate violated that with three conflicting authorities: `operate_goal_from_prompt` classified instructions with work-verb and chat-opener lists, `CreateGoalTool::description` said goals require an explicit request, and the host promoted a prompt before the model ever ran. The verb list produced exactly the absurdity it invites: "test respond with hello" became a persistent goal because "test" is a verb. - `operate_goal_from_prompt` and its vocabularies are deleted (~8.6 KB with tests). The engine creates a goal only from an explicit user declaration — `/goal` and the natural-language forms `explicit_goal_directive` parses — or when the model calls `create_goal`. No wording is classified. - `create_goal`'s description becomes the one model-facing contract: the model decides when a request is a durable objective, and is told what is not one (a question, a greeting, a one-shot edit, a conversational probe). - The create-refusal report is now always the explicit one: a `/goal` that `GoalState::create` refuses says so instead of being swallowed. - docs/MODES.md (Operate) updated to match; the design doc's "conflicting authorities" note is resolved by this change. Tests updated to the contract, not the old behavior: - `operate_never_promotes_wording_to_a_goal`: ordinary work prompts are ordinary turns in Operate and Work; an explicit declaration still creates the goal. - `operate_contract_is_appended_once_and_an_existing_goal_is_never_replaced` seeds its goal through the explicit declaration. - `operate_model_shell_uses_normal_approval_and_workspace_sandbox` declares its goal explicitly instead of relying on promotion. Evidence: goal filter "148 passed; 0 failed"; operate filter "55 passed; 0 failed"; clippy (CI's invocation, tui lib) clean. |
||
|
|
2a34e239b8 |
fix(workflow): run Fleet plans through the existing Engine workers
Bind planned steps to the saved Fleet model and narrowed authority, enforce shared budgets before child launch, and deliver dependency results and final handbacks through the existing Engine inbox. Keep headless sessions alive between phases and preserve cancellation and terminal journal failures. Completion receipts include measured descendant and continuation usage. The roster keeps supervision facts while addressed inspection retains routes, limits and diagnostics. Align Operate and Fleet documentation with this flow. Local verification: combined Workflow/Fleet/Engine selection 2053 passed, 0 failed, 5 ignored; final sub-agent selection 650 passed, 0 failed, 0 ignored. The twelve-worker status test measured one page of 3945 bytes. Workspace Clippy with the release gate allow flags, fmt and version checks exited 0. npm test: 534 passed, 0 failed; npm run check:web exited 0. Receipts: native-workflow-combined-tests-v7.json and native-workflow-final-delta-v9.json. Clean final-head qualification and exact-head hosted CI remain pending. Co-Authored-By: Claude Fable 5.1 <[email protected]> |
||
|
|
47eff23107 |
fix(operate): honor requests declining automatic goals
Keep the task runnable when a direct work request declines persistent goal tracking, including negated comma lists continued across lines. Preserve explicit goal directives and existing goal state. Validation: full workspace all-feature nextest 15315 passed, 0 failed, 21 skipped; two slow tests retained. Includes real Engine turn projection and opt-out phrasing regressions. CI-flags Clippy will run on the joined final candidate; no new installed-artifact claim. |
||
|
|
ccc5dadfa2 |
fix(tools): expose goal controls before continuation
Keep create_goal, get_goal and update_goal in the stable initial tool set. A model must be able to settle an active goal without discovering the lifecycle tool first. Clarify that prose status is not a state change, keep parent mutation unavailable to children, and update both mode guides. Validation: old source fails the production catalog regression (0 passed, 1 failed). Fixed scoped nextest: 156 passed, 0 failed; 12384 excluded by filter. Actual OpenAI-compatible request test verifies eager goal schemas and immediate update_goal execution. Existing 2 child-head expectations updated for read-only get_goal; LRU test still explicitly exercises a deferred fixture. No packaged/live or hosted CI claim. |
||
|
|
45a8b088db |
fix: make tool paths and operate goals follow user intent
Expand home-relative file paths through existing workspace and credential guards. Raise the uncatalogued output allowance while honoring explicit route and context limits. Stop promoting conversational prompts to persistent goals by word count and make startup recovery guidance readable. Validation: 212 selected Rust regressions passed, 0 failed, 12291 unselected; cargo fmt and git diff --check passed. Full workspace, hosted CI and packaged/live qualification remain pending. Signed-off-by: CodeWhale Bot <[email protected]> |
||
|
|
bc4c0bd8fa | feat: rename sidebar/rail to workbar, bottom default, /workbar command | ||
|
|
329960fcbf |
feat: Codewhale 0.9.12 shell, brand, fleet, and Operate (mega) (#5826)
* feat(fleet): your fleet is the models you added, and it comes first
Design MODEL-ROUTING-CATALOG-20260901 §10, slice F1. A fleet model is a Pod
member: the selected Pod file's operator route plus every member row that
pins an exact provider + model; the roles a model fills are the member rows
that pin it. No second store.
- crate::fleet::members: fleet_models / add_fleet_model / remove_fleet_model
/ toggle_fleet_model + change_receipt; Config::fleet_members(workspace) is
the read seam for the operator-awareness slice (F2).
- /pod models | add <provider> <model> [role…] | remove <provider> <model>
(also via the /fleet alias). A model the configured provider does not
serve is rejected; the first add creates and selects a user-global Pod
named 'My fleet'.
- /model picker: ⇧F adds or removes the row's exact route; fleet models
lead the list labelled 'fleet · <roles>', ahead of ⇧P pins and providers.
- /models prints the fleet before the provider list ('Your fleet is the
session model only' when empty).
- PickerActionFleet message in all 15 locales; docs/FLEET.md 'Your fleet
as models'.
Tests: scripts/dev-test.sh tui fleet::members groups::core::fleet
model_picker format_helpers — Summary 37 tests run: 37 passed, 11834
skipped.
Signed-off-by: CodeWhale Bot <[email protected]>
* fix(fleet): pass slugify by name (clippy redundant_closure)
cargo clippy -p codewhale-tui --all-targets -- -D warnings -A clippy::too_many_arguments -A clippy::uninlined_format_args -A clippy::unnecessary_map_or: no findings.
Signed-off-by: CodeWhale Bot <[email protected]>
* fix(tui): review fixes for fleet toggle and /pod add provider validation\n\n- Reject unconfigured provider ids in "/pod add" before writing, reusing\n the existing provider_is_configured_for_active predicate and custom\n provider table checks.\n- Add App.config snapshot so commands can consult the loaded config.\n- Update the stale DEFAULT_FLEET_NAME doc comment to mention ⇧F.\n- Sync crates/tui/CHANGELOG.md.
* style: cargo fmt
* fix(web): align react with react-dom 19.2.8 to unbreak npm ci
Dependabot #5801 bumped react-dom to 19.2.8, whose peer range requires
react 19.2.8; the lockfile still resolved react 19.2.6, so 'npm ci' in
web/ failed ERESOLVE on main and on every branch that merged it
(Lint & Type Check red). Align react to 19.2.8; install verified clean.
Signed-off-by: CodeWhale Bot <[email protected]>
* brand: trace supplied whale assets
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* brand: align icon ombre and generated tokens
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* brand: use white icon tile
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* brand: deepen ombre light stop
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* brand: wordmark takes the blue ombre
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* tui: recover from image-input rejections by non-vision routes
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* tui: localize image rejection recovery
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* chore: format 0.9.12 mega branch
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* Redesign Fleet role labels and agent cards
* feat(tui): launch hero as wordmark + small surfacing mark
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* design(tui): retune whale palette to codewhale navy / ombre sky
Field, chrome, panel, plate and raised surfaces move onto the brand navy
(#070C1D → #142352 → #1A2C63); interaction blue becomes the ombre sky
#6AA6DC, light-mode action the ombre cobalt #1535B2; ice/cyan/border/tool
tints follow. web/app/tokens.css regenerated via
scripts/export-design-tokens.py.
Co-Authored-By: Hunter Bown <[email protected]>
* test(tui): re-bless ink goldens for navy palette
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* web: Space Mono wordmark, quiet layout refresh, fleet vocabulary in site + docs
Space Mono (OFL) outlined wordmark rebuilt via scripts/build-wordmark.py,
wired as --font-display through next/font/google; body stays IBM Plex Sans,
code stays JetBrains Mono. Nav loses the issue strip, strapline, Discord badge
and second filled CTA; home loses the ticker, seals and tilt figure; docs
shell hero collapses to a one-line band; footer uses the inverted wordmark.
Public noun is fleet (/fleet, codewhale fleet, /docs/fleet canonical; /pod,
codewhale pod, /docs/pod remain compatibility aliases) across docs/, site
dictionaries, vocabulary contract and public-surface facts.
No-Issue: 0.9.12 website lane
* brand: keep the traced wordmark; drop Space Mono outline build
* web: IBM Plex Sans Condensed as display face
* brand: Plex Sans Condensed wordmark; nav mark; drop fabricated home demos; AA meta text
* feat(tui): bottom dock tabs — clickable panel switch + close
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* Fix Fleet role migration verification
* fix(tui): dock keys yield Tab to mode/permission cycles
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <[email protected]>
* web: Impeccable polish — type floors, heading outline, docs measure; add PRODUCT.md/DESIGN.md
* Resolve canonical Fleet roles to legacy members
* web: flat hero — drop cyan glow/gradients/shadow, muted eyebrows
* design: PRODUCT.md/DESIGN.md at repo root — shell direction, bottom dock, anti-slop rules, 0.9.12 tokens
* Auto-enroll used models into the Fleet
* brand: keep the founder's wordmark rasters as the source of truth
The web lane replaced brand/wordmark0901.png and brand/wordmarkinverted.png
with Plex Sans Condensed renders. The founder-supplied PNGs are the brand
source; the SVGs are re-traced from them in a following commit.
* tui(mark): the launch mark has one rung
The hero now paints the small mark over the wordmark, so the medium and
large rungs and the for_area ladder have no consumer and fail the
dead-code lint. Remove them rather than allow them.
* brand: trace the founder's wordmark to SVG
brand/wordmark.svg and wordmark-inverted.svg were an IBM Plex Sans
Condensed text render; the founder's wordmark is the rounded monoline in
brand/wordmark0901.png. scripts/brand/trace-brand.py now traces that PNG
(magick threshold 60% + trim, potrace -s --flat -t 20 -O 0.4 -a 1.2),
folds potrace's transform into one compact path in a tight 1874x264
viewBox, and writes the navy #142352 and white colourways from the same
geometry. The Plex builder scripts/build-wordmark.py is gone with it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* web: derive icons and OG image from the traced mark
app/icon.svg is now the white whale on the #142352 rounded tile as on the
founder's sheet; favicon.ico (48/32/16), apple-icon.png, icon-192.png and
icon-512.png are rasterised from it by scripts/brand/trace-brand.py, and
the manifest colours are the same navy. The social card keeps the navy
ground, white mark and traced wordmark and restores the identity phrase
the page-meta contract expects.
The nav sits on the dark field on every route, so it renders the inline
Whale (white brand ink) and the inverted wordmark instead of a
prefers-color-scheme picture pair; the wordmark box uses object-fit so
the ~7.1:1 trace scales inside the compact nav instead of squashing.
Exploration rasters web/public/brand/codewhale-mark-*.png and their
web/brand/mark tile sources had no consumers and are removed;
codewhale-mark.png stays (public-auth-routes pins its hash).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* web: map stray hard-coded colours to navy tokens
globals.css carried a handful of literal navy-family greys, ice hairlines,
seafoam borders and a cyan glow beside the generated --whale-* tokens.
Each now reads the token it was approximating (whale-bg/chrome/panel,
whale-ice, whale-accent-secondary, whale-action, whale-cyan,
whale-text-dim), and the docs light sheet inks the mark in the brand
navy via --whale-composer (#142352).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* palette: inventory WHALE_* tokens before the one-name-per-colour collapse
Shell design §2.6 (SHELL-DESIGN-20260901) measured "58 WHALE_* symbols;
one colour under five names; 5 dead tokens". Receipt before touching
anything, generated from crates/tui/src/palette/tokens.rs. "uses" is the
whole-word count across crates/ excluding the const's own definition and
`use`/`pub use` lines (wrapper consts inside tokens.rs count).
name value alias-of dead uses
WHALE_BG_RGB (7, 12, 29) 3
WHALE_CHROME_RGB (12, 21, 49) 1
WHALE_PANEL_RGB (16, 28, 64) 3
WHALE_COMPOSER_RGB (20, 35, 82) 3
WHALE_ELEVATED_RGB (26, 44, 99) 4
WHALE_SELECTION_RGB (30, 60, 143) 3
WHALE_TEXT_BODY_RGB (246, 242, 232) 10
WHALE_TEXT_SOFT_RGB (182, 192, 212) 4
WHALE_TEXT_MUTED_RGB (147, 160, 184) 3
WHALE_TEXT_HINT_RGB (138, 153, 179) 3
WHALE_TEXT_DIM_RGB (105, 119, 145) yes 0
WHALE_ACTION_RGB (106, 166, 220) 6
WHALE_COBALT_RGB (21, 53, 178) yes 0 (web: --whale-cobalt x3)
WHALE_ICE_RGB (221, 238, 249) yes 0 (web: --whale-ice, rustRgb("WHALE_ICE"))
WHALE_CYAN_RGB (120, 188, 232) 2
WHALE_ACCENT_SECONDARY_RGB (79, 209, 197) 11
WHALE_BRAND_ORANGE_RGB (255, 138, 61) 1
WHALE_BRAND_MAGENTA_RGB (240, 78, 184) 1
WHALE_HUMAN_RGB (246, 196, 83) 5
WHALE_ACCENT_PRIMARY_RGB = WHALE_ACTION_RGB WHALE_ACTION_RGB 8
WHALE_WORKING_GREEN_RGB (155, 214, 111) 5
WHALE_ACCENT_ACTION_RGB = WHALE_ACTION_RGB WHALE_ACTION_RGB yes 0
WHALE_ERROR_RGB (255, 134, 178) 9
WHALE_ERROR_HOVER_RGB (255, 156, 194) 3
WHALE_ERROR_SURFACE_RGB (43, 21, 34) 6
WHALE_ERROR_BORDER_RGB = WHALE_ERROR_RGB WHALE_ERROR_RGB 3
WHALE_ERROR_TEXT_RGB (255, 219, 232) 3
WHALE_WARNING_RGB (255, 122, 89) 4
WHALE_SUCCESS_RGB = WHALE_WORKING_GREEN_RGB WHALE_WORKING_GREEN_RGB 9
WHALE_INFO_RGB = WHALE_ACTION_RGB WHALE_ACTION_RGB 17
WHALE_BORDER_RGB (42, 63, 114) 1
WHALE_REASONING_TEXT_RGB (224, 153, 72) 13
WHALE_REASONING_SURFACE_RGB (42, 34, 24) 3
WHALE_REASONING_TINT_RGB (22, 36, 74) 7
WHALE_DIFF_ADDED_RGB (87, 199, 133) 3
WHALE_DIFF_DELETED_RGB = WHALE_ERROR_RGB WHALE_ERROR_RGB yes 0
WHALE_DIFF_ADDED_BG_RGB (18, 42, 34) 3
WHALE_DIFF_DELETED_BG_RGB (52, 24, 39) 3
WHALE_MODE_AGENT_RGB (126, 180, 232) 4 (via MODE_AGENT: 13)
WHALE_MODE_YOLO_RGB (255, 112, 160) 4 (via MODE_YOLO: 13)
WHALE_MODE_PLAN_RGB (185, 220, 236) 4 (via MODE_PLAN: 13)
WHALE_MODE_OPERATE_RGB (173, 136, 255) 4 (via MODE_OPERATE: 14)
WHALE_TOOL_LIVE_RGB = WHALE_ACCENT_SECONDARY_RGB 3 (via ACCENT_TOOL_LIVE: 5)
WHALE_TOOL_ISSUE_RGB = WHALE_ERROR_RGB 3 (via ACCENT_TOOL_ISSUE: 5)
WHALE_TOOL_OUTPUT_RGB = WHALE_TEXT_SOFT_RGB 3 (via TEXT_TOOL_OUTPUT: 13)
WHALE_TOOL_SURFACE_RGB (15, 26, 58) 3 (via SURFACE_TOOL: 5)
WHALE_TOOL_ACTIVE_RGB (24, 44, 94) 3 (via SURFACE_TOOL_ACTIVE: 9)
WHALE_ACCENT_PRIMARY Color(WHALE_ACCENT_PRIMARY_RGB) -> WHALE_ACTION 9
WHALE_ACTION Color(WHALE_ACTION_RGB) 85
WHALE_LIVE Color(WHALE_ACCENT_SECONDARY_RGB) 17
WHALE_HUMAN Color(WHALE_HUMAN_RGB) 41
WHALE_INFO Color(WHALE_INFO_RGB) -> WHALE_ACTION 105
WHALE_BG Color(WHALE_BG_RGB) 96
WHALE_CHROME Color(WHALE_CHROME_RGB) 5
WHALE_PANEL Color(WHALE_PANEL_RGB) 15
WHALE_COMPOSER Color(WHALE_COMPOSER_RGB) 5
WHALE_ERROR Color(WHALE_ERROR_RGB) 35
57 WHALE_* consts. Pure aliases (9): ACCENT_PRIMARY_RGB, ACCENT_ACTION_RGB,
ERROR_BORDER_RGB, SUCCESS_RGB, INFO_RGB, DIFF_DELETED_RGB, TOOL_LIVE_RGB,
TOOL_ISSUE_RGB, TOOL_OUTPUT_RGB. #[expect(dead_code)] (5): TEXT_DIM_RGB,
COBALT_RGB, ICE_RGB, ACCENT_ACTION_RGB, DIFF_DELETED_RGB.
Non-WHALE aliases of the same blue in tokens.rs: STATUS_INFO (8 uses),
ACCENT_PRIMARY (dead, 0). One colour, #6AA6DC, under seven symbols:
WHALE_ACTION(_RGB), WHALE_INFO(_RGB), WHALE_ACCENT_PRIMARY(_RGB),
WHALE_ACCENT_ACTION_RGB, STATUS_INFO, ACCENT_PRIMARY — 225 call sites.
Script: python3 over tokens.rs + grep -rnw crates; kept out of scripts/
(one-off receipt, the numbers live here).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* palette: one name per colour — collapse WHALE_INFO / WHALE_ACCENT_PRIMARY into WHALE_ACTION
Shell design §2.6: "`WHALE_INFO`, `WHALE_ACTION`, `WHALE_ACCENT_PRIMARY`
and their `_RGB` twins are one colour. Collapse to `WHALE_ACTION`."
Mechanical rename across crates/ (word-boundary sed, no value changes):
WHALE_INFO, WHALE_INFO_RGB -> WHALE_ACTION, WHALE_ACTION_RGB
WHALE_ACCENT_PRIMARY(_RGB) -> WHALE_ACTION(_RGB)
palette::STATUS_INFO -> palette::WHALE_ACTION
WHALE_ACCENT_ACTION_RGB, ACCENT_PRIMARY (dead aliases) -> deleted
The `STATUS_INFO` static in commands/groups/config is an unrelated
CommandInfo and is untouched.
Where two names met in one predicate (adapt.rs light/solarized/community
remaps, grayscale text-soft bucket, SemanticForegroundRole::Action) the
duplicate disjuncts are dropped; `use` lists deduped; the
"primary accent aligns with action" test collapses to its one live
assertion (action blue != human gold). The Blue Stage doc comment moves
onto WHALE_ACTION_RGB. `palette::grammar` untouched: it reads UiTheme
slots, never these consts.
Evidence (CARGO_BUILD_BUILD_DIR=.../mega-tokens):
cargo check -p codewhale-tui --all-targets -> Finished, 0 warnings
cargo clippy -p codewhale-tui --all-targets --all-features --locked
-- -D warnings (CI allow-list) -> clean
cargo test -p codewhale-tui --lib palette::tests:: --locked -- --skip command_palette
-> test result: ok. 59 passed; 0 failed
RUST_MIN_STACK=67108864 cargo test -p codewhale-tui --lib startup_ink --locked
-> test result: ok. 1 passed; 0 failed (ink goldens unchanged)
cargo test -p codewhale-tui --lib --locked -- menu_style cursor_accent color_compat
-> test result: ok. 36 passed; 0 failed
Pre-existing, not from this diff (reproduced on the stashed tree):
tui::command_palette tests, feat012_ac1 and the startup_ink golden
overflow the default test-thread stack in a debug build; they pass with
RUST_MIN_STACK=64MiB.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* palette: delete the dead whale tokens
Shell design §2.6: "delete the five dead tokens". Two of the five went
with the alias collapse (WHALE_ACCENT_ACTION_RGB, ACCENT_PRIMARY); this
removes the rest that have no consumer in crates/ and no web consumer:
WHALE_TEXT_DIM_RGB (105,119,145) 0 uses, no --whale-text-dim on the site
WHALE_DIFF_DELETED_RGB = WHALE_ERROR_RGB 0 uses, no --whale-diff-deleted
ACCENT_SECONDARY Color(WHALE_ACCENT_SECONDARY_RGB) 0 uses (TEXT_ACCENT/WHALE_LIVE carry it)
STATUS_NEUTRAL = TEXT_MUTED 0 uses
Kept, with a comment saying why the `#[expect(dead_code)]` is honest:
WHALE_COBALT_RGB and WHALE_ICE_RGB have no TUI consumer but the site
reads them through the token export (`--whale-cobalt` x3, `--whale-ice`
and `rustRgb("WHALE_ICE")` in web/lib/blue-stage-contract.test.ts).
Mode and tool-surface `_RGB` tuples stay: each is consumed through its
Color wrapper (MODE_AGENT/YOLO/PLAN/OPERATE 13-14 call sites each,
themes.rs + color_compat.rs; SURFACE_TOOL 5, SURFACE_TOOL_ACTIVE 9,
ACCENT_TOOL_LIVE 5, ACCENT_TOOL_ISSUE 5, TEXT_TOOL_OUTPUT 13). The §1
"12 tokens with zero consumers" counted the tuples, not their wrappers.
Evidence: cargo check -p codewhale-tui --all-targets -> Finished, 0 warnings;
cargo test -p codewhale-tui --lib palette::tests:: --locked -- --skip command_palette
-> test result: ok. 59 passed; 0 failed.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* web: regenerate tokens.css after the whale token collapse
scripts/export-design-tokens.py (never hand-edited). Ten lines gone:
--whale-accent-primary(-rgb), --whale-accent-action(-rgb),
--whale-info(-rgb), --whale-text-dim(-rgb), --whale-diff-deleted(-rgb).
No site stylesheet or component consumed any of them
(grep -rn "\-\-whale-" web/app web/components web/lib); the only
reference was the alias-chain example in web/lib/whale-tokens.ts's doc
comment, now `--whale-success` -> `--whale-working-green` -> `#9bd66f`
(the old example also quoted a hex that stopped being true a retune ago).
Evidence:
cd web && python3 ../scripts/export-design-tokens.py --check (CI: npm run check:tokens)
-> design tokens up to date (1 file(s), 42 tokens)
vitest run lib/blue-stage-contract lib/docs-theme-contract
-> Test Files 2 passed (2) / Tests 6 passed (6)
(vitest ran against the main checkout's node_modules via a temporary
symlink; this worktree has none installed.)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* docs(design): the status-bar grammar names the one blue token
STATUS_BAR_COLOR_GRAMMAR.md never named a collapsed token, so this is the
one sentence it needed: the Identity blue is `WHALE_ACTION`, its former
aliases (`WHALE_INFO`, `WHALE_ACCENT_PRIMARY`, `STATUS_INFO`) are gone, and
the whale theme's `info` / `accent_primary` slots both hold it. No other
document in the repo named them (grep over *.md, *.ts, *.tsx, *.css,
*.py, *.toml, *.yml, *.json outside node_modules); the root DESIGN.md
already speaks in CSS names.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* palette: the field follows the terminal-owned shell; `underwater` aliases deepsea
Shell design §2.0 decision 1 (founder: "We aren't supposed to be using a
blue background anymore"): ground is the terminal's; the navy field is
painted only under the opt-in deepsea column.
What was already true, verified before changing anything:
- Settings::default().theme is "terminal" (settings.rs:103).
- The whale pair (UI_THEME / LIGHT_UI_THEME) ends in
`.with_terminal_native_shell()`: surface, panel, composer, header and
footer are `Color::Reset`, pinned by
`whale_pair_flat_shells_are_terminal_native_without_erasing_semantic_surfaces`.
- The ink goldens' legend reads `a reset on reset`.
- OceanTreatment::Flat is the default; Deepsea repaints Reset cells through
OceanRamp::for_theme, which matches the whale pair by name + Reset shell.
The reviewer's citations (tokens.rs:6/:250/:465) are the token definitions
deepsea and the semantic surfaces still need, not the theme.
What was not true: ~90 direct `bg(palette::WHALE_BG)` paints in pickers,
overlays and full-screen views (provider_picker 14, views/mod.rs 11,
user_input, live_transcript, help, session/file/model pickers ...) bypass
the theme, and `adapt_bg_for_theme` only remapped them for
`theme_remap_active` presets. On the whale theme they laid navy patches
over the terminal ground. Rung 2 fix, one rule in palette/adapt.rs: the
field (`WHALE_BG` / `BACKGROUND_DARK`) always follows `ui.surface_bg` —
Reset on the whale pair, the user's `background_color` override when set,
the preset surface elsewhere. Panels, selection, elevation, error and
diff surfaces are untouched; no widget file changes.
`underwater` is now an accepted alias of `deepsea` in
settings.rs (normalize + `set`), OceanTreatment::parse and the
config_ui serde enum. Tests extended in place; the color_compat light
test now expects the Reset shell it already had for theme consumers.
DESIGN.md "Field" says the TUI ground is the terminal's own background
and the navy field is deepsea-only.
Contrast, all whale text/accent tokens on #000, #1e1e1e (VS Code),
#282c34 (One Dark), #002b36 (Solarized dark), #300a24 (Ubuntu), #0d1117
(GitHub dark), #282a36 (Dracula): body 12.5-18.8:1, soft 7.7-11.5, muted
5.3-8.0, hint 4.9-7.3 (floor 3:1), action 5.4-8.1, human 8.6-12.9, live
7.5-11.3, error 6.2-9.3, warning 5.5-8.2, green 8.2-12.2, reasoning
5.9-8.8. Only `border` (#2A3F72) is low, 1.4-2.1:1: a non-text hairline.
No token value changed.
Seen, tmux 80x24 PTY, TERM=xterm-256color COLORTERM=truecolor, hermetic
HOME, debug build, counting `48;2;R;G;B` background sequences:
default (Terminal theme): startup, /theme picker, Help — no painted
background before or after (picker shows only accent swatches).
Blue Stage selected via T/Down/Enter, then F1 Help:
before: 15 x `48;2;7;12;29` (WHALE_BG) + 1 x selection row
after: 1 x `48;2;30;60;143` (selection row only)
Startup stage on Blue Stage: none, before and after.
Evidence (CARGO_BUILD_BUILD_DIR=.../mega-tokens, RUST_MIN_STACK=16 MiB as CI):
cargo check -p codewhale-tui --all-targets -> Finished, 0 warnings
cargo test -p codewhale-tui --lib --locked -- color_compat palette::tests::
ocean:: ocean_treatment live_transcript views::tests startup_ink
--skip command_palette -> test result: ok. 238 passed; 0 failed
cargo test -p codewhale-tui --lib --locked (full) ->
test result: FAILED. 11901 passed; 7 failed; 13 ignored
1 was this change (color_compat light test, updated above); the other 6
are role-name / slash-list assertions from other lanes on this branch
(scout<->explore, worker<->general, slash.impeccable) and untouched.
Ink goldens unchanged.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* tests(palette_audit): re-pin whale roles to the retuned palette
`whale_roles_are_pinned_and_non_colliding` still pinned the pre-navy
values (WHALE_BG (3,7,13), ACTION (106,174,242), ...) and failed on this
branch before the token slice touched anything. Pins now match tokens.rs;
no colour value changes.
cargo test -p codewhale-tui --test integration --locked palette_audit
-> test result: ok. 3 passed; 0 failed
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* tui/cli/web: fleet is the public product term; /pod, codewhale pod stay aliases
Founder decision 2026-09-01: "fleet" is the customer-facing name for the
assembled model team and "Pod" is retired from product copy. `/fleet` is
the canonical slash command and `codewhale fleet` the canonical CLI verb;
`/pod`, `codewhale pod`, `loadout`, and `party` remain parser aliases.
Storage keys, the ledger file name, config tables, protocol identifiers,
and MessageId variant names keep their current spelling.
- CommandInfo name/aliases/usage, help text, and the unknown-verb error
flip to /fleet; `/fleet fleets` (saved/manage) is the saved-fleet picker
with `/fleet pods` kept as an alias.
- All 15 locale packs: localized values say fleet; the settings goldens
follow. `KbCompleteCycleModes` names the modes as Plan → Work → Operate
(Act is only a compatibility alias per docs/MODES.md).
- `scripts/check-tui-product-vocabulary.sh` now rejects `Pod` in en.json
instead of rejecting `fleet` in every pack.
- Hotbar id `slash.fleet` is canonical; persisted `slash.pod` normalizes.
- Fleet store error prose says fleet.
- Docs: PRODUCT.md lists the current role tokens (general, explore,
planner, reviewer, implement, test, advisor, custom) and names the old
spellings as aliases; docs/FLEET.md uses one role vocabulary;
web/lib/content/vocabulary.ts ADVISORY_ROLE is Advisor with consultant/
oracle as the legacy spellings (matches fleet/profile.rs migration).
Evidence:
sh scripts/check-tui-product-vocabulary.sh -> exit 0
cargo test -p codewhale-config -p codewhale-lane --locked
-> 638 passed; 0 failed / 62 passed; 0 failed
cargo test -p codewhale-cli --locked -- fleet pod -> 3 passed; 0 failed
cargo test -p codewhale-tui --lib --locked -- fleet::store fleet::members
fleet::identity -> 24 passed; 0 failed
cargo test -p codewhale-tui --lib --locked -- groups::core::fleet
localization command_palette hotbar fleet_roster settings widgets
fleet::control pod_workers -> 605 passed; 1 failed (the failure is
slash_source_matches_command_palette_command_entries, which reads the
machine's ~/.claude/skills and finds an `impeccable` skill; it fails
identically without this change)
cd web && npm test -- lib/content/vocabulary.test.ts -> 11 passed
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH
* chore(tui): clear the six clippy 1.98 errors the base lanes left
needless_borrow on provider_identity_for_persistence (five sites) and a
collapsible_if in the work-surface mouse path. No behaviour change.
* tui(composer): restore double-tap Enter as the send-now gesture
While a turn is running, the first bare Enter queues the message (as
before) and opens a 500 ms window (`App::DOUBLE_TAP_WINDOW`, the value
the removed code in
|
||
|
|
84f42aefc0 |
feat: make Pod the public roster surface (#5776)
* feat: make Pod the public roster surface Signed-off-by: CodeWhale Bot <[email protected]> * fix(tui): localize pod workers modal and restore fleet receipt compatibility Review-fix follow-up for the Pod public surface: - /pod workers modal routes all previously hardcoded English through tr() with 38 new MessageIds across all 15 shipped locales; a zh-Hans render test asserts no English leakage. - /pod workers means current-session sub-agents and /pod status the durable ledger, pinned per locale by a new localization test. - Durable receipt detail prefixes restored to the established fleet: spelling (lane render_detail, tui status_lines, resume detail) with regression tests at both layers; serde wire keys unchanged. Local proof (RUST_MIN_STACK=33554432, --locked): localization 49/49, fleet::control 11/11, subagents 33/33, commands fleet group 13/13, codewhale-lane 62/62; cargo fmt --check clean; locale key-set hash identical across all 15 packs. Signed-off-by: CodeWhale Bot <[email protected]> --------- Signed-off-by: CodeWhale Bot <[email protected]> Co-authored-by: CodeWhale Bot <[email protected]> |
||
|
|
806d93e826 |
docs(i18n): fix English doc inaccuracies and add first zh_hans translations for Tier-2 (#5613)
* docs: fix doc inaccuracies found in zh_hans review * docs: add zh_hans translation for INSTALL * docs: add zh_hans translation for KEYBINDINGS * docs: add zh_hans translation for GUIDE --------- Co-authored-by: Hunter Bown <[email protected]> |
||
|
|
22bf21dbca |
docs: align 0.9.10 public product truth
Signed-off-by: Hunter Bown <[email protected]> |
||
|
|
1a9600e7cd |
feat(tui): make /workflow /goal /auto one-keystroke discoverable
The engines already shipped; the remaining gap was visibility. Pin the orchestration trio at the top of the empty / menu, name them on the idle welcome and footer, put them in the first three Hotbar defaults, and add /auto as a host-only Auto-Review switch with when-to-use copy (#5439). Verified: cargo fmt --all -- --check; locale parity; command-migration manifest; cargo nextest -p codewhale-config --lib -- hotbar (5); codewhale-tui lib tests for empty slash pin, /auto, palette root, empty state, footer, hotbar defaults, and locale sync (32 passed). Signed-off-by: Hunter Bown <[email protected]> |
||
|
|
4999092c01 |
docs: match Full Access hold copy to the 2026-08-10 behavior
Registered non-bypassable holds auto-approve in Full Access rather than hard-blocking; repository-law and managed-policy holds still fail closed. The cited regression is non_bypassable_registered_tools_auto_approve_in_full_access. |
||
|
|
fc23323c44 |
docs: fix outdated A/B-tier references for v0.9.7
A-tier (contradicted the code): - RUNTIME_API.md: document the undo/patch-undo/retry/snapshot-restore endpoints that shipped but were marked deferred; drop product-name brand residue (DeepSeek engine/client/tools -> Codewhale) - AGENT_RUNTIME.md: rebrand shims removed in v0.9.0, file decomposition landed (ui.rs ~3.9k, main.rs stub), verifier contract path, v0.9.1 release precondition met (current line v0.9.7) - public-surface-facts.json + web test: defaultActive = the six DEFAULT_ACTIVE_NATIVE_TOOLS names (todo_write, not tool_search) - MODES.md: toolbox list matches the seven model-facing names; retired /set removed from active slash surfaces (legacy note kept) - KEYBINDINGS.md: Alt-P/A/Y = Plan/Work/Yolo, not Plan/Work/Operate B-tier (clearly stale): - ACCESSIBILITY.md: brand legacy first line; /settings set examples -> /config <key> <value> --save; section title - SKILLS.md: MAX_AVAILABLE_SKILLS_CHARS 12 000 -> 2 400 - FLEET.md / WORKFLOW_AUTHORING.md: Fleet rings 5/2 -> 8/3 - TERMUX.md: self-update requests only the codewhale-android-arm64 asset - OPERATIONS_RUNBOOK.md: RUST_LOG target deepseek_cli -> codewhale_tui - CATALOG_REFRESH.md: broken MODEL_PROVIDER_AUDIT.md -> PROVIDERS.md - CONFIGURATION.md: provider list 28 -> 40; /note primary path - MCP.md: "Running DeepSeek as an MCP Server" brand -> Codewhale; /mcp subcommand list (import/recommendations/add recommended) - web tools page: todo_write out of the Deferred group into its own schema row ARCHITECTURE.md updates (LLM client layer, sandbox backends, github.rs removal) that landed in the working tree are included. Verified: facts JSON valid, no broken .md links in docs, every claim cross-checked against code; web tests not run (node_modules absent). |
||
|
|
c43e53d284 |
Merge branch 'work/v098-workflows-goal-parity-20260815' into work/v098-integration-20260815
# Conflicts: # CHANGELOG.md # crates/tui/locales/ca.json # crates/tui/locales/de.json # crates/tui/locales/en.json # crates/tui/locales/es-419.json # crates/tui/locales/fr.json # crates/tui/locales/hi.json # crates/tui/locales/id.json # crates/tui/locales/ja.json # crates/tui/locales/ko.json # crates/tui/locales/pt-BR.json # crates/tui/locales/ru.json # crates/tui/locales/uk.json # crates/tui/locales/vi.json # crates/tui/locales/zh-Hans.json # crates/tui/locales/zh-Hant.json |
||
|
|
a98d9184e6 |
docs: describe host-side Workflow and Goal controls
Record the new control verbs, inferable create_goal, and the fact that the session [workflow] table is now honored. Correct the published auto_start_child_limit / max_children defaults (16 / 1000, matching config.example.toml). The example header's /workflow run form is now a real host verb; keep the CLI equivalent next to it. The design note is the lane audit against Grok Build and DeepSeek Harness: what shipped here, and what was left as follow-up (journal replay resume, a named saved-workflow registry, strategist restructure). |
||
|
|
43ffca8561 |
feat(tui): state a child's effective posture and document inheritance
The focused worker header now names write, network, and shell from the runtime permission snapshot, never guessed. New AgentFocusPosture strings are translated in every complete locale pack. Docs and the unreleased changelog describe the session-posture gate (Ask / Auto-Review / Full Access) and the role defaults that keep network reads and planner probes without widening write-only roles. |
||
|
|
16557b0705 |
refactor(tui): remove inert review guidance
Drop the natural-language Auto-Review knob that neither deterministic policy nor the guardian consumed. Existing configs with the retired key continue to parse, while the runtime and audit surface no longer pretend it has an effect. Refresh the Codex comparison to the exact locally verified guardian source; Kimi and DeepSeek Harness remain correctly documented as having no LLM reviewer. Agent assistance: Codex. |
||
|
|
962a006c8e |
refactor(tui): keep guardian inputs deterministic
Remove free-form Auto-Review guidance from the model request so the guardian sees only its fixed policy, the exact held call, and deterministic observations. Document the pinned evidence boundary: Codex provides an experimental LLM-review pattern, Kimi provides unattended-mode UX without a reviewer, and DeepSeek Harness provides sandbox and escalation contracts without Auto-Review. Agent assistance: OpenAI Codex. |
||
|
|
a75dec8b06 |
refactor(tui): make Auto-Review single-shot
Remove the user-intent ledger and reviewer retry loop. Review one exact held call with deterministic observations, account for that call, and fail closed on every unavailable answer. Document the safety baseline against the pinned DeepSeek Harness 0.1.0-rc.5 sandbox and approval contracts. Agent assistance: OpenAI Codex. |
||
|
|
59299dff35 |
fix(tui): make Auto-Review risk-first
Require a typed intrinsic risk on guardian decisions, deny high and critical outcomes mechanically, and retry only malformed or incomplete answers within one deadline while preserving usage. Keep repository-law holds fail-closed in every non-interactive posture instead of opening a hidden human approval modal. Design informed by local source audits of Codex Guardian, Kimi Code permission policies, and DeepSeek Harness approval/sandbox behavior. Agent assistance: OpenAI Codex performed the local comparison, implementation, and verification. |
||
|
|
34c541a5af |
feat(tui): add a fail-closed Auto-Review guardian
Keep deterministic policy and the built-in safety floor authoritative, then consult one stateless no-tools guardian only for fallback holds in interactive Auto mode. Bind that call to exact external-input evidence, keep expanded context non-authoritative, and deny on missing authorization, timeout, cancellation, provider failure, incomplete output, malformed JSON, or oversized exact context. The simplification removes inferred intent matchers, the reviewer toggle, remembered denial state, redundant rule actions, duplicate decision paths, and non-decision action variants. Agent assistance was used. Co-authored-by: Lstarsky0 <[email protected]> |
||
|
|
037aab9cf3 |
docs: align the v0.9.6 public surface
Document Work and To-do as the two product concepts, synchronize every shipped locale, publish the six-tool and typed-image contracts, and keep static web generation offline while live GitHub chrome refreshes after deployment. |
||
|
|
5798de8b39 |
build(release): native musl for Linux ARM64, and reconciled copy
Three v0.9.5 benchmark tasks could not launch Codewhale at all: mteb-leaderboard, mteb-retrieve, and pytorch-model-recovery run older ARM64 images, and the aarch64-unknown-linux-gnu artifact built on ubuntu-24.04-arm requires GLIBC_2.39. Release and nightly now build aarch64-unknown-linux-musl on the native ARM runner, alongside the x64 musl build that has shipped since v0.8.65. Both gain a static check (no ELF INTERP) plus a launch smoke on the matching native runner, so a dynamically linked or non-starting binary fails the build rather than the user's install. docs/INSTALL.md drops the arm64 glibc floor section and describes the v0.9.6 matrix. Also reconciles the copy the earlier commits invalidated: setup ratification text and all 15 locales stop attributing execution doctrine to "mode prompts", docs/MODES.md states Auto-Review's actual deterministic allow/deny behavior, and the source-structure, dead-code, and runtime-contract budgets are re-measured — the last locking down 25 decreased ceilings and the new mode-agnostic prompt-stage digests. |
||
|
|
c2c414ef73 |
docs: correct limits, /trust, and the Ollama default that were wrong in the unsafe direction
2026-08-04 model-facing-text audit. Four user-facing claims contradicted the
code, three of them in the direction that costs the user:
- CONFIGURATION.md said max_subagents 'defaults to 20 and is clamped to
1..=20' in four places. Code: DEFAULT_MAX_SUBAGENTS = 64, MAX_SUBAGENTS =
128 (config/subagent_limits.rs:13,17). Out-of-box concurrency is 3.2x the
documented figure, and a user writing max_subagents = 40 to 'raise it to
the max' was told it would clamp to 20 when it is honored in full. Same
shape for max_admitted: documented ceiling 200, actual
MAX_SUBAGENT_ADMISSION = 1024.
- Usage: codewhale [OPTIONS] [PROMPT]
codewhale [OPTIONS] <COMMAND> [ARGS]
Commands:
run Run interactive/non-interactive flows via the TUI binary
doctor Run Codewhale diagnostics
models List live provider API models via the TUI binary
speech Generate speech audio with Xiaomi MiMo TTS models via the TUI binary [aliases: tts]
sessions List saved TUI sessions
resume Resume a saved TUI session
rc Launch an interactive session and hand it to the Codewhale web app
fork Fork a saved TUI session
init Create a default AGENTS.md in the current directory
setup Bootstrap MCP config and/or skills directories
remote-setup Generate a remote Codewhale agent deploy bundle (cloud + chat bridge)
exec Run a non-interactive prompt through the TUI runtime
fleet Manage durable Agent Fleet runs via the TUI runtime
workflow Run checked-in Workflows through a Lane Runtime backend
lane Manage running workflow instances (Lanes) and Runtime backends (#4176)
review Run a Codewhale-powered code review over a git diff
apply Apply a patch file or stdin to the working tree
eval Run the offline TUI evaluation harness
mcp Manage TUI MCP servers
features Inspect TUI feature flags
serve Run a local TUI server
web Open the first-class local browser client over the canonical Runtime API
completions Generate shell completions for the TUI binary
login Configure provider credentials
logout Remove saved authentication state
auth Manage authentication credentials and provider mode
account Sign in to your Codewhale account and manage account-scoped provider keys [aliases: cloud]
mcp-server Run MCP server mode over stdio
config Read/write/list config values
model Resolve or list available models across providers
thread Manage thread/session metadata and resume/fork flows
sandbox Evaluate sandbox/approval policy decisions
app-server Run the canonical runtime API / control plane (HTTP/SSE, mobile, stdio)
completion Generate shell completions
metrics Print a usage rollup from the audit log and session store
update Check for and apply updates to the `codewhale` binary
help Print this message or the help of the given subcommand(s)
Arguments:
[PROMPT]...
Options:
--config <CONFIG>
--profile <PROFILE>
--provider <PROVIDER>
Provider selector; exec/fleet also accept configured custom provider identifiers
--model <MODEL>
--output-mode <OUTPUT_MODE>
--verbosity <LEVEL>
Controls transcript and output verbosity (normal, concise)
--log-level <LOG_LEVEL>
--telemetry <BOOL>
Opt in to anonymous product telemetry for this run (default off; CODEWHALE_TELEMETRY=0 always wins) [possible values: true, false]
--approval-policy <APPROVAL_POLICY>
--sandbox-mode <SANDBOX_MODE>
--api-key <API_KEY>
--base-url <BASE_URL>
-C, --workspace <DIR>
Workspace directory for TUI file tools
--mouse-capture
--no-mouse-capture
--skip-onboarding
--no-project-config
Skip loading project-level config, including the workspace-specific `[workspace]`/`[projects]` overlay from user config. Must appear before the subcommand; it is forwarded to the TUI ahead of the subcommand
-c, --continue
Continue the most recent interactive session for this workspace
-p, --prompt <PROMPT>
-h, --help
Print help
-V, --version
Print version said '(1-20)' while main.rs clamps to 128. Here the doc
was right and the help was wrong; both now say 1-128, default 64.
- MODES.md gave bare as the enable command. config.rs:2278 maps
"" | "status" | "list" to trust_status — bare /trust only REPORTS. A user
reads the status block, believes trust is on, and escalates to Full Access
when the next out-of-workspace operation fails. Now documents /trust on
and says plainly that bare /trust does not enable anything.
- CONFIGURATION.md gave as the Ollama default; the
string appears nowhere in crates/. provider_defaults.rs:109 is
deepseek-v4-flash. Self-hosted is where a bad default bites hardest.
Verified: limits read from config/subagent_limits.rs, /trust dispatch read
from config.rs:2278, Ollama default from provider_defaults.rs:109; tui
builds clean. Authored with agent assistance (Claude).
|
||
|
|
8869def98a |
fix(exec): resume headless turns after mid-stream network drops, exit EX_TEMPFAIL on infra failure
Terminal-Bench 2.1 (89 tasks, codewhale 0.9.4, deepseek-v4-flash):
5 of 7 NonZeroAgentExitCodeError forfeits were the identical failure —
the provider stream dropped mid-response ("error decoding response
body" after partial content), the #103 policy surfaced the warning and
failed the turn, and `codewhale exec` exited 1. regex-log passed the
smoke run and crashed in the full run: a nondeterministic transport
drop, not a task failure. Pi retries the same drops (332 retries, 0
crashes).
Engine (turn_loop + streaming policy):
- New should_resume_after_network_drop policy: in headless hosts
(exec / stream-json; terminal_chrome_enabled = false) a network-class
stream error after partial content now schedules a full request
re-issue, bounded by MAX_STREAM_RETRIES, exactly like the #2990
sleep-resume. The partial fragment was never committed and no tool
from the incomplete response executed, so replaying from the last
committed boundary cannot duplicate side effects. Interactive TUI
keeps the #103 surface-the-warning behavior. No error event is
emitted for attempts that will be retried; the budget-exhausted final
attempt still reports the real error.
Exec exit semantics (main.rs):
- Terminal failures with error_category network/timeout now exit 75
(EX_TEMPFAIL) instead of 1, so harnesses can distinguish retryable
infra failures from genuine task failures (still exit 1). No error is
masked: the stream-json error event, terminal metadata status=failed,
and error_category are unchanged.
- Recoverable mid-turn error events (e.g. stream-stall warnings) no
longer poison the exec run summary; the terminal TurnComplete carries
the authoritative outcome. Previously any recoverable warning forced
a non-zero exit even when the turn later completed.
Regression coverage:
- Pure policy tests for the headless/network/budget/cancel matrix.
- Engine-level tests with a flaky mock client: mid-stream drop recovers
(2 requests, completed, fragment discarded); budget exhaustion fails
with the real error and exactly one error event.
- Process-level acceptance (tests/exec_stream_drop_acceptance.rs): raw
TCP server truncates the SSE body mid-content-length, reproducing the
production decode error against the real binary — exit 0 after
recovery, exit 75 with error-channel reporting after exhaustion.
Gates: cargo fmt --all --check; cargo check -p codewhale-tui; targeted
tests 18/18 + acceptance 2/2; full codewhale-tui suite 10141 passed,
21 failed — all in the known pre-existing env-key/qa_pty set
(provider-catalog API-key panics + PTY visual matrix), none in the
touched paths.
|