Open-source coding agent for your terminal, built in Rust and on a journey of continuous community improvement. Issues and PRs welcome.
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
ci: isolate Buildkite tests from personal Fleet state Reuse the TUI hermetic-home convention through one shared command wrapper. Seal nextest and doctests, including the existing unprivileged Linux path, without changing selected-Fleet validation or runner configuration. Remove inherited canonical/legacy home and config overrides so per-test fixtures keep precedence. Preserve the real toolchain homes and explicit stack settings, defaulting to the existing 16 MiB CI stack. Point the TUI runner at its actual library tests instead of the empty executable target. Validation on macOS, with Cargo offline and synthetic outer state: - Old representative Fleet invocation: 0 passed / 1 failed (expected). - Isolated identical invocation: 1 passed / 0 failed; outer hashes unchanged. - Full Buildkite script: 14,231 passed / 0 failed / 15 skipped; no LEAK. - Doctests: 3 passed / 0 failed / 8 ignored. - Focused Fleet/settings/log tests: 105 passed / 0 failed. - Boundary shell cases: 3 passed / 0 failed. - Migrated TUI config-panel golden test: 1 passed / 0 failed; nonzero asserted. - Shell syntax, ShellCheck, and git diff --check passed. Preserved initial full run: 14,187 passed / 44 failed / 15 skipped (43 config/home assertions and one unproven-cause plugin PTY timeout). The initial library-target smoke overflowed the default thread stack; it passes with the existing CI default. Full Buildkite already used 16 MiB. Root npm test and npm run check:web both exit 1: missing scripts, zero tests. Hosted CI and the Linux uid transition were not executed locally. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 2 天前 | |
wip(v0.8.67): fleet roster + whaleflow-js cutover checkpoint Safety checkpoint of multi-agent cutover work (fleet roster core, whaleflow-js runtime, /fleet roster view, audit fix lanes). Tree may not compile: the agent-tool profile edit in tools/subagent/mod.rs was interrupted mid-edit (credit exhaustion). Checkpoint precedes repair. | 2 个月前 | |
fix(prompts): single precedence source, facts-only turn_meta, lean prefix Closes the constitution P0 cluster and the first prefix-token cut: - #4777: delete the inverted MEMORY_GUIDANCE Tier ladder; assert precedence only in BASE_PROMPT § Whose word wins; slim Authority Recap to a pointer; reject rank-restating recap overrides; align .codewhale/constitution.json authority[] with the canonical five. - #4778: strip Tier/Statute/Article vocabulary from approval, compaction, memory, and personality overlays so layers describe behavior, not rank. - #4780: turn_meta keeps mode/posture as facts and stops re-embedding mode doctrine and permission-question essays every user message. - #4781: project context pack defaults off (opt-in via project_pack=true). - #4784: compress LANGUAGE_PROMPT while keeping English law / user-language reply, including reasoning_content and next-turn switch. Tests: only_the_constitution_states_precedence, memory hygiene, turn_meta fact-only assertions, project_pack default-off. | 1 个月前 | |
ci: terminate hung tests after ten minutes and name the command a dispatch smoke stalled on The Windows test job for the 0.9.12 candidate ran 90 minutes and was killed by the runner with 13,924 passed and two tests still running: commands::tests::every_registered_command_dispatches_to_a_handler and every_command_alias_dispatches_to_a_handler, which execute every slash command against an isolated app. Both pass on Linux and macOS (every command returns within 31 ms locally), so the stall is inside one handler on Windows and the killed job left no output to say which. The ci nextest profile now terminates a test after ten slow-timeout periods (10 minutes) and reports it as failed with its captured output, and the two smoke tests print a breadcrumb before and after each command, so the next Windows run names the handler instead of timing out the job. Shipped binary bytes are unchanged: both edits are test-only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bs5x11yXAg3sJ4giZf4krF | 2 天前 | |
fix(devcontainer): support Windows development Use a dedicated development image so Cargo builds have the Rust toolchain, rustfmt, pkg-config, and DBus headers instead of inheriting the minimal release runtime.\n\nReplace the host HOME bind mount with named volumes for CodeWhale state and Cargo artifacts. This avoids invalid Windows HOME expansion, preserves non-root write access, and keeps Rust build churn off the workspace bind mount.\n\nDocument the Dev Container storage and rebuild behavior.\n\nVerification:\n- Built the Dev Container image with Docker Desktop\n- Verified non-root Cargo, Rust, Git, pkg-config, DBus discovery, and writable state/target paths\n- cargo build --locked\n- cargo test -p codewhale-config --locked (cherry picked from commit 8b1ceea7f03394246fa86b9a23b7c75fe661dd46) Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com> | 1 个月前 | |
fix(vscode): make the extension's send path work, and close the security holes The extension had never successfully started a turn. `startTurn` accepted only HTTP 200/202 while the runtime's `start_thread_turn` (crates/tui/src/runtime_api.rs:4613-4632) returns `StatusCode::CREATED` as its ONLY success path, so every send failed. `git log -- src/api.ts` is a single commit: this was never a regression, it shipped that way and was never run end to end. api.ts (send path): - Status handling now tests a RANGE (`isOk`: >= 200 && < 300) through one `ensureOk` helper routed through every call site, rather than enumerating codes at eleven of them. 201 is accepted because it is 2xx, not because it is special-cased — the same shape the embedded web client already used at crates/tui/src/runtime_web/app.mjs:873, which is why that client worked against the same runtime this one choked on. - The runtime's JSON `error.message` is surfaced on every route; previously only startTurn passed it through. - 409 is typed: a second send while a turn is live is "already running", and interrupting when nothing streams is "nothing to stop", not an error. Security (extension.ts, runtime.ts, secrets.ts): - SecretStorage now wins over the settings token, matching what secrets.ts, the manifest and the README all already promised. Previously a repo-local .vscode/settings.json could supply a bearer AND retarget `runtimeHost`, and the token rode every request — opening a repo was enough. - The runtime token is passed to the terminal via environment instead of `--auth-token` in argv, which was visible in shell history and `ps`. - status.ts nonce uses a CSPRNG, matching chat.ts. Chat correctness and accessibility (chat.ts, transcript.ts): - Transcript prefers `detail` over the 280-char `summary`, so reload shows the reply instead of a stub. - `operation_key` is reused on retry, so a timeout and resend no longer creates two turns; the dead SSE stream is cleared so reconnect can fire. - The composer keeps its text until the turn is accepted. - Tool paths are parsed out of `metadata.tool_input` and treated as untrusted. The durable fix is runtime-side and is NOT taken here. - Focus styling and roles/labels added; there were none. Chrome (package.json, extension.ts): - Chat is contributed to the secondary sidebar with an activity-bar fallback, gated on `codewhale.noSecondarySidebar`, which is set at activation from `vscode.version` (>= 1.106). One ChatView instance serves both view ids and `reveal()` focuses whichever resolved. - `engines.vscode` stays `^1.96.2` and the threshold is enforced at runtime, matching the shipping Codex extension; raising the floor would have cut off 1.90-1.105 users and made the fallback unreachable for nothing. CI and dev loop (ci.yml, .gitignore, .vscode/): - CI runs the extension tests. Nothing ran them before, which is how a send path that could not work stayed green. - launch.json/tasks.json give a working F5 host. The root `.gitignore`'s bare `.vscode/` silently swallowed them, so a negation was added — without it these files exist locally and vanish on commit. Gates: cd extensions/vscode && npx tsc --noEmit -> clean cd extensions/vscode && npm test -> tests 42, pass 42, fail 0 (baseline before this was 25) manifest/provider coherence: every declared view id has a provider; no provider lacks a manifest entry; context key set at activation. Not done, deliberately: the Runtime view still exists, so this is not yet a single-view Agents panel. Removing it spans extension.ts, status.ts and two commands; a half-removal is worse than either state. Gate item 5 — a human driving one real turn in an Extension Development Host — remains unproven. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D4rk4NXwyy6wmvii9Lp84P Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 11 小时前 | |
fix(web): give the terminal preview room in the hero 407 tests passed across 47 files; production build 785 pages. Lint 0 errors, 2 existing logo warnings; locale/catalog checks passed. EN and ZH inspected at 390x844 and 1280x900; no narrow page overflow and Copy remains in bounds with visible keyboard focus. Local preview only; no hosted CI or deployment claimed. | 2 天前 | |
fix(release): promote tested v0.9.11 nonbenchmark candidate Promotes the fully gated non-benchmark candidate while preserving the benchmark tree exactly from the prior release-PR head. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 16 天前 | |
feat(web): count usage by default and move the choice to the privacy page The website no longer opens a consent sheet. Anonymous counting of page, docs, install-copy and download totals is on by default; the privacy page hosts the status and the Turn off / Turn on control, and the footer "Usage data" link points there. The historical storage key is kept so an opt-out recorded under the old opt-in policy stays off, unreadable stored state fails closed, and nothing records an acceptance on the visitor's behalf. The envelope moves to schema 3 / notice 5 to match the runtime and ingest. Trust page, FAQ, roadmap, and docs/public-surface-facts.json describe the default-on 0.9.12 behavior and name the published 0.9.11 release as the one that asked first. The privacy policy gains an "Anonymous usage counting" section (effective date September 4, 2026). Screenshot provenance records the founder capture's visible build, v0.9.12 (15fe6983bfa5), and the README image becomes a lossless 1136x615 downscale of that same capture. Gates on this tree: vitest 407 passed / 0 failed (47 files); tsc clean; eslint 0 errors (2 pre-existing img warnings); check:locales, check:facts, check:docs pass; clean `next build --webpack` succeeded. Browser check of the production build in EN/ZH at 390x844 and 1280x900 passed with no console errors and no horizontal overflow. Receipt: docs/operating/website-usage-default-on-receipt-20260904.md. The Rust root has no `npm test` / `check:web`; they were not run. No deployment claimed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bs5x11yXAg3sJ4giZf4krF | 2 天前 | |
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 <bot@codewhale.net> * 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 <bot@codewhale.net> * 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 <bot@codewhale.net> * brand: trace supplied whale assets Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * brand: use white icon tile Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * brand: deepen ombre light stop Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * tui: localize image rejection recovery Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 c5c42b7d91 used). A second bare Enter inside that window with an empty composer promotes the just-queued message to a Steer through `attempt_steer_with_queue_fallback` — the same path Ctrl+Enter takes, so there is one steering path. A second Enter with new text is an ordinary queue; Ctrl+Enter still steers immediately; outside a turn Enter is unchanged. `enter_with_double_tap` is the one decision point again (`take_queued_for_double_tap_steer` routes through it), and `submit_disposition_does_not_mutate_the_queue` stays true. The posture bar advertises the gesture while the window is open (`PostureHintEnterAgain`, next commit). Tests (cargo test -p codewhale-tui --lib <filter> --locked): double_tap: test result: ok. 3 passed; 0 failed enter_with: test result: ok. 5 passed; 0 failed submit_disposition: test result: ok. 6 passed; 0 failed Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * tui(shell): one owner per fact — posture bar, metrics line, no dead hints Design: SHELL-DESIGN-20260901 §2.0 item 3, §2.2, §2.3, §2.3b, §2.11 and the founder's 2026-09-02 redirect (Claude Code's grammar, less always-on information). Under the composer there are exactly two chrome rows in the default state, then the work surface only when it has content: ▶▶ ask (Shift+Tab) · work (Tab) · 2 agents · Esc to interrupt /rc … deepseek-v4 · ctx 61% · $0.42 · ttft 400ms · 40 tok/s · ↓ 1.2K Ctrl+/ help Fact → owner, before → after (composed 80x24 / 120x32 frames, working turn with two sub-agents; "strip" = the work-surface bottom view): fact before after context % info line metrics line cost footer (+ info line when priced) metrics line model info line metrics line provider info line (wide) metrics line (wide) ttft / tok/s / ↓ behind /cost only metrics line repo slug info line (+ idle empty state) launch header / git view (not chrome) branch info line (+ idle empty state) launch header / git view (not chrome) mode footer posture bar permission footer posture bar phase word footer ("sub-agents underway") transcript active row (not chrome) elapsed footer ("1m 15s") roster rows (per agent) agent count indicator row + info "pod 2/2" + "whales 2/4" posture bar ("2 agents") + dock tab + strip header (+ dock tab, strip header — other slice) task/shell count indicator row above the composer posture bar help hint footer keys legend (F1) + info line (Ctrl+/) metrics line (Ctrl+/), from the binding other key hints footer "⌥V:output", compact "? help" none; cycle keys next to the chip they cycle live hint footer "Esc to interrupt" posture bar hint slot ≥80 % microcopy footer right slot posture bar hint slot (outranks the hint) notice / rc footer right slot / — posture bar right slot Dead key hints removed: `F1:keys` / `fn+F1:keys` (Help binding's `footer_chord` is now `Ctrl+/`; `info_help_hint` derives from the binding), compact `? help`, and the `footer_action_hints` family. The mode/permission cycle keys print only when the binding table admits them at the current focus (no `(Tab)` on the launch stage). Row order: composer → posture bar → metrics line → roster/to-do. The #5286 background-work chip above the composer is gone (it repeated the posture bar's counts); `PendingWork` stays as the counts' source. Goldens re-blessed and read: footer_* (posture bar), infoline_startup_*, infoline_work_* (metrics line), settings_* (the settings preview's bottom row); infoline_settings_* deleted with the settings-path segment. Commands run (CARGO_BUILD_BUILD_DIR=…/mega-frame, RUST_MIN_STACK=16777216): cargo check -p codewhale-tui --all-targets clean cargo test -p codewhale-tui --lib infoline --locked test result: ok. 11 passed; 0 failed cargo test -p codewhale-tui --lib tideline_tests test result: ok. 64 passed; 0 failed cargo test -p codewhale-tui --lib one_owner_tests test result: ok. 4 passed; 0 failed cargo test -p codewhale-tui --lib shell_key_routing test result: ok. 13 passed; 0 failed cargo test -p codewhale-tui --lib localization::tests test result: ok. 49 passed; 0 failed cargo test -p codewhale-tui --lib --locked test result: FAILED. 11893 passed; 8 failed (config_panel golden re-blessed after; the other 7: 4 fail on HEAD without this change (fleet rename in flight), tmux clipboard passes alone, none in files this change touches) cargo clippy … -D warnings 6 pre-existing errors, none in this change's hunks (config.rs:2106/2796, apply.rs:759, event_loop.rs:464, session_state.rs:1004, work_surface/input.rs:401) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(launch): checkpoint for overnight takeover — braille mark + kitty tier + Claude-Code launch header compile and pass lib tests; PTY cucumber tests still wait on the old heading Compiles (cargo check --all-targets clean). Lib tests for mark::, underwater::, mouse_ui::, localization:: pass: test result: ok. 120 passed; 0 failed (needs RUST_MIN_STACK=16777216 like scripts/dev-test.sh; the rust_i18n static overflows a 2 MiB test thread with or without this change). Startup goldens re-blessed and read. Clippy is red only in files outside this slice (config.rs, apply.rs, session_state.rs, work_surface/input.rs, and a pre-existing event_loop.rs borrow). Not done: crates/tui/tests/cucumber/{screen_mode_inline_pty, active_composer_pointer_pty,plugin_e2e_acceptance}.rs still wait for "What are we working on?" and press 'w'; they need the new marker ("Codewhale v") and a typed message + Enter to begin the session. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(rail): checkpoint for overnight takeover — dock views compile, 136/137 work_surface tests pass, files/notepad/git views are stubs Foundation for the one bottom dock (founder redirect 2026-09-02): RailPanel is now the eight-view cycle (agents, tasks, background, files, notepad, context, git, price; Pinned folded into tasks), an auto rule opens agents/tasks/background while they have content, explicit picks stick until Esc, and Ctrl+Tab / Ctrl+] (fwd) + Ctrl+Shift+Tab (back) cycle. Context and price views render as rows; files, notepad, git are stubs in views.rs. The classic sidebar line panels and their dead consumers are deleted. Known: agent_rows_show_role_assignment_and_open_the_agent_transcript fails (role_label 'worker' vs 'general'); role derivation is untouched here and the failure is believed to predate this work — unverified. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(operate): checkpoint for overnight takeover — auto-goal + contract land; one Operate approval test needs a goal-complete mock Operate now turns a non-trivial prompt into the goal through the same GoalState::create path as explicit_goal_directive, appends the Operate contract once as a user-role runtime message (append-only history, not the prefix), shows the Operate goal receipt, and carries the new mode copy in all 15 locale packs plus docs/MODES.md. Compiles. Passing: goal (134), prompts (133, incl. every_mode_shares_one_prompt_per_host), localization (49), runtime_handoff (14), session_peek (15), history_cells (2), both new engine tests. Known failing: core::engine::tests::operate_model_shell_uses_normal_approval_and_workspace_sandbox — its mocked model never reports the auto-set goal complete, so the turn re-prompts to max_steps (wiremock expect(1) sees 199). Six clippy needless_borrow/collapsible_if hits pre-exist on the branch base. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(fleet): checkpoint for overnight takeover — #5815 review findings 1-9 fixed, compiles, fleet tests green Findings against the fleet-as-models work (verified against the current tree, then fixed): 1. `toggle_fleet_model` decides presence by member rows, not the projected role list (a role-less row projects to no role, so the old `all(== "operator")` was vacuously true). Regression test `toggle_removes_a_role_less_member_row` fails on the previous commit ("got Unchanged { … operator route … }") and passes now. 2. `selected_or_default` loads an existing personal `My fleet` instead of overwriting it and never writes or selects before the add succeeds; `FleetModelChange::Added` carries `created_fleet` + `selected_fleet`. 3. `fleet_models` returns `Result<Vec<_>, FleetStoreError>`: a broken explicit selection is surfaced in `/fleet models`, `/models`, and the picker's ⇧F instead of reading as "session model only". 4. `add_fleet_model` dedupes roles (case-insensitive) and returns `Unchanged` without touching the file when every role is present (test compares bytes and mtime). 5. `App.config` startup snapshot removed. `/fleet add|remove` now return `AppAction::FleetAddModel|FleetRemoveModel`; the UI arm validates the provider against the live `Config` (`fleet_provider_rejection`, `fleet_catalog_rejection`, re-exported from `commands`). 6. ⇧F applies the same provider gate as `/fleet add`. 7. One roster path: `sync_fleet_roster` (extracted from the FleetStoreChanged arm) plus `App::fleet_roster_stale`, flushed once per event-loop iteration; `/fleet add|remove`, ⇧F, and every UI-side auto-enroll site set it (`auto_enroll_fleet_model` now returns bool). 8. ⇧F receipts go through `push_status_toast` (Success/Info, 6 s) and `set_sticky_status` (Error); no new `status_message` writes. 9. All new fleet prose is `tr(locale, MessageId::Fleet…)` (27 keys, translated in all 15 packs); `FleetModelError` is typed with a localized `message(locale)`. 10. No stale "`a` in /models" doc comment exists in the current tree. Also re-blessed `config_panel_{80x24,120x32}` goldens (the Config tab label says Fleet); the diff is that one label. Evidence (this tree): cargo check -p codewhale-tui --all-targets --locked -> Finished cargo test -p codewhale-tui --lib --locked -- fleet::members groups::core::fleet model_picker format_helpers fleet_roster localization golden hotbar command_palette fleet::store -> 257 passed; 1 failed (slash_source_matches_command_palette_ command_entries: reads ~/.claude/skills and finds `impeccable`; fails identically on main in this environment) cargo clippy … -D warnings (CI flags) -> the only remaining error is crates/tui/src/tui/work_surface/input.rs:401 collapsible_if, which belongs to the work_surface lane and predates this commit cargo fmt --all -- --check -> clean sh scripts/check-tui-product-vocabulary.sh -> exit 0 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * feat(tui): launch card, canonical role vocabulary, DashScope descriptor, test fixes - Launch is now our own card take (founder, 2026-09-02): thin top line ⑂ branch path; centred bordered card with the whale mark, Codewhale + version, one true announcement (no-model warning / MCP news), and the menu New worktree / Resume session / Changelog / Quit with real chords right-aligned; Enter runs the highlighted entry, Up/Down move it, and typing goes straight to the composer. The card dissolves on the first keystroke or command (≤240ms, instant under reduced motion); the working screen then shows ⑂ branch path + ⋮ MCP n/m, the session_start receipt, and the posture bar + metrics line (hidden while the card is up). The composer's bottom rule carries model (effort) · permission — the route's one launch reading. - Role vocabulary: fixtures and the stopship fleet/workflow now use the canonical tokens (explore/implement/reviewer/test); the workflow JS wire accepts canonical spellings with the pre-rename ones as aliases (AgentType serde rename+alias, serialized form is canonical). - Alibaba Model Studio (DashScope) joins the data-driven descriptor table: international compatible-mode endpoint, DASHSCOPE_API_KEY, live /v1/models as the Qwen model authority (never a compiled id). - Tests: role-keyed gate fixtures moved to canonical tokens; the operate model-shell test now seals the goal through the deferred update_goal tool (deferral retry included) instead of pausing blindly; the slash-source hotbar test isolates HOME; ⚠ and ⋮ gained ASCII fallbacks; launch goldens re-blessed for the card. * feat(tui): retire Pod from copy; canonical workflow fixture; gate clean-up - Pod literal sweep across fleet views, worker runtime, sub-agent tool, managed API, and command groups: user-facing copy now says Fleet (founder vocabulary decision; /fleet canonical, /pod and 'codewhale pod' stay as compatibility aliases). Roster tests that encoded the retired Pod-public/Fleet-internal split now assert the public Fleet vocabulary. - workflows/stopship + fleets/stopship use canonical role names (explore/implement/reviewer/test); the workflow crate's own stopship tests and required-roles list follow. - Operate mode-picker hint shortened to fit 80 columns in every locale. - Cucumber PTY launch flows: wait for the launch card, type the first prompt and press Enter; the live shell is proven by the launch stage's top line disappearing and the metrics line's ctx reading (the interrupt hint needs a live turn, which an offline route never starts). The stopship acceptance feature expects the canonical /fleet help copy. - CHANGELOG receipts synced; DESIGN.md shell direction records the card, posture bar + metrics line, and the bottom view cycle. * test(cucumber): launch-card PTY contract fixes - The launch-card wait uses the menu's New worktree entry — unique to the card; the bare wordmark also matches onboarding copy. - The live-shell proof is the launch stage's top line disappearing plus the metrics line's ctx reading; the interrupt hint needs a live turn, which an offline route never starts, and the help hint sheds first at the 40-column floor by design (SHELL-DESIGN-20260901 §2.2). - The pointer-submit queue proof takes the offline onboarding seed into account: the receipt toast proves the gesture, and the queue count grows by exactly one. * docs(readme): restore the canonical product screenshot the web contract pins The brand header redesign dropped the assets/screenshot.webp embed; the web public-surface contract pins the README and the website to one canonical optimized screenshot (byte-identical, 1562x1256 lossless VP8L). Re-embed it. * test: platform-robust pointer-submit wait and cap-warning diagnostics - The pointer queue proof accepts either the transient receipt toast or the queue-count increment: toast timing differs across runners, and a 20 s wait missed a toast the queue dump proved had fired. - The context-cap posture test dumps the drawn rows when the warning count misses, instead of a bare 0 != 1, so a platform-specific shed (the hint sheds first when the left run exceeds its budget) is visible in CI. * test: fix the linux-only context-cap shed; bounded pointer-click retry - The context-cap posture test drew at 100 columns, where a backend-less platform (linux CI paints 'files: workspace (unenforced)') sheds the cap hint first, so the warning count read 0. Draw at 140 columns, where the hint survives with the notice present; verified locally. - The pointer queue proof retries the [↑] click once, re-finding the affordance first: under runner load a redraw can shift cells between the find and the click, so the first SGR gesture lands nowhere. * fix(gates): tool-catalog budget covers the fleet rename; readme stamps; pointer baseline - The Pod->Fleet sweep grew every mode's tool-schema surface by 58 bytes (+14 tokens). The receipts are re-measured and the one-way ceilings in scripts/runtime-contract-budget.json are raised to them as the explicit maintainer decision the gate asks for (the rename is the founder's 2026-09-01 vocabulary call). - The README screenshot embed changed README.md; the 18 translated READMEs re-stamp (the embed is language-neutral HTML - no prose changed, so no retranslation was needed). - The pointer queue baseline is captured while the composer is empty: the pending preview row hides while a draft sits in the composer, so the pre-click depth read None and the growth proof could not fire. * test: re-click then keep polling until the deadline The qa_harness Instant wrapper does not implement Div, and the retry's single read raced the app processing the second gesture: poll to the full deadline, re-click once at the half-way point. * test: pointer queue diagnostics (baseline/expected/last-seen) in the failure output * test: pointer poll keeps per-iteration state only (unused-assignment gate) * fix: Copilot review findings — planner wire spelling and Advisor copy - workflow::AgentType::Plan serializes as the canonical 'planner' ('plan'/'awaiter' stay accepted aliases), matching the FleetRole vocabulary the mega PR declares. - Web: the vocabulary docs metadata, the vocabulary module header, and the docs-map topic description say Advisor (the public advisory term) instead of the retired Consultant spelling. - Polish home dictionary: restore 'Podwodna powłoka terminala' — the fleet-vocabulary sweep had merged 'Fleet' into the compound word 'Podwodna' (underwater), producing the non-word 'fleetwodna'. * test: pointer proof accepts preview-appears when no baseline count is painted * test: the tolerant preview-appears proof (the arm the last commit missed) --------- Signed-off-by: CodeWhale Bot <bot@codewhale.net> Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 5 天前 | |
cloud agent: product-owned Daytona snapshot + two fixes found by running agents inside a Computer (#5745) * computer: add product-owned codewhale-cloud-agent Daytona snapshot definition Pins the released v0.9.11 Linux x64 engine (commit 96d13a0bc3f4, sha256 c02969556e51e138afa3fe9c97a1359878cd3d1986b1ce1f5fa96c93c6909416) into a debian:bookworm-slim Computer image with the agent toolchain (git, node 22, python3, ripgrep, build-essential), non-root agent user, and /workspace prepared for the cloud dispatcher (PRD 4.5). Built and probed on Daytona as snapshot codewhale-cloud-agent (4 CPU / 8 GB / 10 GB). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aDEyM2a4pPZ9qqMDrP5YX Signed-off-by: CodeWhale Bot <bot@codewhale.net> * exec: honour dispatcher-forwarded --provider/--model on --resume/--continue The `codewhale` dispatcher rejects `--provider`/`--model` after `exec` and forwards the top-level flags as CODEWHALE_PROVIDER / CODEWHALE_MODEL. `resolve_exec_resume_route` only looked at the exec-level flags, so `codewhale --provider modelstudio-token-plan --model qwen3.8-flash exec --continue ...` silently restored the saved route (observed in the Daytona cloud-agent e2e on 2026-08-30: the resumed turn ran on deepseek-v4-pro). Fold the launch overrides into the explicit route signals for resume; a fresh session already treated them as explicit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aDEyM2a4pPZ9qqMDrP5YX Signed-off-by: CodeWhale Bot <bot@codewhale.net> * subagent: scope session-name reservation to the live session A completed worker hydrated from a previous session's workspace ledger is invisible to status/peek/followup (`Agent not found in the active session`), yet spawn still refused its name with "already in use by agent_id ... (status: completed)". A second `codewhale exec` in the same workspace could not spawn worker-a/worker-b again and burned six turns recovering (Daytona cloud-agent e2e, 2026-08-30). Skip prior-session agents in the collision check, matching the other model-facing actions. The existing duplicate-name test now stamps the manager's own boot id so it keeps covering the live-session case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aDEyM2a4pPZ9qqMDrP5YX Signed-off-by: CodeWhale Bot <bot@codewhale.net> * computer: disclose Daytona create-time env persistence; require post-create key injection Signed-off-by: CodeWhale Bot <bot@codewhale.net> * computer: align snapshot docs and tests with the post-create credential contract - Dockerfile/README: Daytona create-time env is server-visible; provider secrets must never be injected at create time. Post-create delivery over an execution channel (stdin, never argv) into a 0600 file, removed at teardown, is the only documented path. The provider env table is reframed as reference for a future supported bridge, and api_key_env is correctly described as holding an env-var name, not a file path. - Image/probe receipts re-labeled as manual image evidence, not launch proof; the snapshot remains an image definition, not a wired dispatcher. - tui: test-only strengthening — exec_resume route override covered end-to-end through Config::load with CODEWHALE_PROVIDER/CODEWHALE_MODEL; session-name reservation test now hard-expects same-name respawn. Local proof (RUST_MIN_STACK=33554432, --locked): subagent 676/676, exec_resume 4/4, session_name 7/7; cargo fmt --check clean. Signed-off-by: CodeWhale Bot <bot@codewhale.net> * fix(tui): release Runtime Chat owner lock before same-process reopen Safety-gate hermetic tests failed on failed_state_writes_never_become_in_memory_authority_and_exact_retry_reopens with WouldBlock after drop-then-reopen of the same account session (#5735). Unlock on Drop, and retry only WouldBlock, so a just-closed fd is not reported as another owner. A lock that stays held is still ownership. Local proof (hermetic HOME, RUST_MIN_STACK=8388608, --locked): runtime_chat_relay 16/16; Safety-gate tui filter 344/344; execpolicy 108/108 plus authorization_order 1/1; PR exec_resume/session-name 4/4. Signed-off-by: CodeWhale Bot <bot@codewhale.net> * docs: record Pod public-roster surface in the unreleased changelog Feature commit 84f42aefc017 (#5776) landed on main without a durable release-note receipt, so Version drift failed after merging origin/main into this branch. The gate requires #5776 in CHANGELOG.md. Signed-off-by: CodeWhale Bot <bot@codewhale.net> --------- Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 6 天前 | |
Merge pull request #5997 from Hmbown/test/cu-embed-consistency-guard test(plugins): pin the computer-use embed list to the vendored tree | 5 小时前 | |
fix(release): promote tested v0.9.11 nonbenchmark candidate Promotes the fully gated non-benchmark candidate while preserving the benchmark tree exactly from the prior release-PR head. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 16 天前 | |
Merge branch 'main' into fix/runtime-store-failures-visible-5931 | 6 小时前 | |
fix(vscode): make the extension's send path work, and close the security holes The extension had never successfully started a turn. `startTurn` accepted only HTTP 200/202 while the runtime's `start_thread_turn` (crates/tui/src/runtime_api.rs:4613-4632) returns `StatusCode::CREATED` as its ONLY success path, so every send failed. `git log -- src/api.ts` is a single commit: this was never a regression, it shipped that way and was never run end to end. api.ts (send path): - Status handling now tests a RANGE (`isOk`: >= 200 && < 300) through one `ensureOk` helper routed through every call site, rather than enumerating codes at eleven of them. 201 is accepted because it is 2xx, not because it is special-cased — the same shape the embedded web client already used at crates/tui/src/runtime_web/app.mjs:873, which is why that client worked against the same runtime this one choked on. - The runtime's JSON `error.message` is surfaced on every route; previously only startTurn passed it through. - 409 is typed: a second send while a turn is live is "already running", and interrupting when nothing streams is "nothing to stop", not an error. Security (extension.ts, runtime.ts, secrets.ts): - SecretStorage now wins over the settings token, matching what secrets.ts, the manifest and the README all already promised. Previously a repo-local .vscode/settings.json could supply a bearer AND retarget `runtimeHost`, and the token rode every request — opening a repo was enough. - The runtime token is passed to the terminal via environment instead of `--auth-token` in argv, which was visible in shell history and `ps`. - status.ts nonce uses a CSPRNG, matching chat.ts. Chat correctness and accessibility (chat.ts, transcript.ts): - Transcript prefers `detail` over the 280-char `summary`, so reload shows the reply instead of a stub. - `operation_key` is reused on retry, so a timeout and resend no longer creates two turns; the dead SSE stream is cleared so reconnect can fire. - The composer keeps its text until the turn is accepted. - Tool paths are parsed out of `metadata.tool_input` and treated as untrusted. The durable fix is runtime-side and is NOT taken here. - Focus styling and roles/labels added; there were none. Chrome (package.json, extension.ts): - Chat is contributed to the secondary sidebar with an activity-bar fallback, gated on `codewhale.noSecondarySidebar`, which is set at activation from `vscode.version` (>= 1.106). One ChatView instance serves both view ids and `reveal()` focuses whichever resolved. - `engines.vscode` stays `^1.96.2` and the threshold is enforced at runtime, matching the shipping Codex extension; raising the floor would have cut off 1.90-1.105 users and made the fallback unreachable for nothing. CI and dev loop (ci.yml, .gitignore, .vscode/): - CI runs the extension tests. Nothing ran them before, which is how a send path that could not work stayed green. - launch.json/tasks.json give a working F5 host. The root `.gitignore`'s bare `.vscode/` silently swallowed them, so a negation was added — without it these files exist locally and vanish on commit. Gates: cd extensions/vscode && npx tsc --noEmit -> clean cd extensions/vscode && npm test -> tests 42, pass 42, fail 0 (baseline before this was 25) manifest/provider coherence: every declared view id has a provider; no provider lacks a manifest entry; context key set at activation. Not done, deliberately: the Runtime view still exists, so this is not yet a single-view Agents panel. Removing it spans extension.ts, status.ts and two commands; a half-removal is worse than either state. Gate item 5 — a human driving one real turn in an Extension Development Host — remains unproven. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D4rk4NXwyy6wmvii9Lp84P Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 11 小时前 | |
feat: fleet simplified to role layer over subagents | 4 天前 | |
chore(deps): bump the npm_and_yarn group across 2 directories with 2 updates Bumps the npm_and_yarn group with 1 update in the /integrations/feishu-bridge directory: [qs](https://github.com/ljharb/qs). Bumps the npm_and_yarn group with 2 updates in the /extensions/vscode directory: [qs](https://github.com/ljharb/qs) and [fast-uri](https://github.com/fastify/fast-uri). Updates `qs` from 6.15.2 to 6.16.0 - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.15.2...v6.16.0) Updates `qs` from 6.15.2 to 6.16.0 - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.15.2...v6.16.0) Updates `fast-uri` from 3.1.5 to 3.1.7 - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.7) --- updated-dependencies: - dependency-name: qs dependency-version: 6.16.0 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: qs dependency-version: 6.16.0 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: fast-uri dependency-version: 3.1.7 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com> (cherry picked from commit a21880b6ac351271def8236621a7550905b85876) | 3 天前 | |
misc: replace stdenv.isLinux with stdenv.hostPlatform.isLinux | 10 天前 | |
release: 0.9.12 in the tree Founder asked for a 0.9.12 build to test. This bumps the version everywhere `scripts/release/check-versions.sh` audits, so the tree is internally consistent rather than half-bumped: workspace `Cargo.toml`, all 66 internal `codewhale-*` path-dependency pins across 14 crate manifests, `Cargo.lock`, the npm packages and both lockfiles, the VS Code extension, the remote-smoke `RELEASE_TAG` default, and the generated `web/lib/facts.generated.ts`. The changelog's `[Unreleased]` section already described 0.9.12 work, so it is promoted to `## [0.9.12]` with a fresh empty `[Unreleased]` above it and the compare links added — the mechanical release-notes move, not a judgement about scope. One new entry records that computer use now ships with the binary. `check-versions.sh` reports `Version state OK: workspace=0.9.12, npm=0.9.12, npm-binary=0.9.12, lockfile in sync.` Its remaining output is the pre-existing advisory about already-merged commits in the v0.9.11..HEAD range that never got release-note receipts; that predates this commit and still blocks the release paths until someone writes them. This is a version bump, not a release: no tag, no push, no prepare-release.sh. Gates on the bumped tree: fmt clean; clippy --workspace --all-targets --locked -D warnings clean; tui 11659 passed/13 skipped, tui-integration 280/0, tui-cucumber 16/0, cli 339/0, config 634/1 skipped, lane 67/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013r9fgwt1HYymrB7iZGSkCm | 4 天前 | |
fix(packaging): preserve AUR compatibility alias Keep the existing codewhale-tui symlink when codewhale-bin upgrades while installing codew from the consolidated archive. Pin the package-layout regression and make the Omarchy documentation match the compatibility contract. | 13 天前 | |
fix(tui): measure circled digits and keycaps as 2 columns everywhere (#4479) (#5001) The v0.9.1 fix (9be600bf4) made CodeWhale's own width helpers grapheme- aware, but Ratatui's renderer still measures ambiguous-width characters through its own unicode-width dependency, whose width() reports Enclosed Alphanumerics (circled digits/letters) as 1 column while CJK terminals paint them as 2. The 1-column cell placement shifts every downstream column by one, producing the intermittent missing-characters / phantom-space glitch that mouse selection only temporarily repairs. Fix the width accounting at all three layers: 1. Patch unicode-width 0.2.2 via [patch.crates-io] so UnicodeWidthChar:: width() and UnicodeWidthStr::width() report 2 columns for Enclosed Alphanumerics (U+2460-U+24FF), Dingbat Circled Digits (U+2776-U+2793), and Circled Numbers on Black Square (U+3248-U+324F). The patch is scoped to exactly those ranges; box-drawing glyphs and ellipsis keep their 1-column non-CJK widths, so table borders and truncation do not regress. 2. Keep the explicit range override in char_display_width as a defense in depth that does not depend on the patch. 3. Keep the U+20E3 override in grapheme_display_width / markdown_grapheme_width for keycap sequences that lack an FE0F variation selector (unicode-width reports those as 1 column too). Adds regression tests asserting UnicodeWidthChar::width('\u{2460}') == Some(2) and that circled digits count as 2 columns in text_display_width, plus the existing keycap suite. 26 ui_text tests and 52 markdown_render tests pass. | 1 个月前 | |
fix(release): enforce supported Cargo and retain publication checks Use one Cargo publication dry run for all 21 crates before uploading, with an explicit Cargo 1.90+ release-tool requirement and crates.io destination. Update the runbook and test resumability without weakening full artifact verification. Validation: 5/5 offline tarball fixtures passed; real 21-crate publication dry run passed with no upload; real two-crate unpublished dependency dry run passed; publication order, bash syntax, and git diff --check passed. Runtime root has no npm test/check:web scripts. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 2 天前 | |
feat(telemetry): accept disclosed default-on usage policy without fabricated consent Add closed schema3/notice_version5 ingest and generated CWC contract. Preserve original v1 first-party-only and v2/consent4 semantics, reject mixed policy fields before storage or forwarding, and retain IP/host/operator/content guards. Existing Analytics Engine column positions remain fixed; schema_version distinguishes old consent from new notice metadata. Document the founder's amended default-on/opt-out policy and preserve prior declines. Rust/app preference changes are integrated separately. Validation: ingest 171 passed, 0 failed across 6 files; TypeScript, facts, 23 documentation topics and git diff checks passed. Original validator rejects the new v3 fixture; current validator accepts v2 and v3. Proposed Rust v3 fixture accepted by ingest; sender proof pending Rust integration. Root npm test && npm run check:web exits1 because no test script exists (0 tests, check:web not reached). No hosted deployment, processor activation or runtime-installed policy change claimed. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 2 天前 | |
chore(web): regenerate facts for the new git_commit_plan tool `git_commit_plan` (#5870, fixes #3999) is the 76th model-visible tool, so the committed `web/lib/facts.generated.ts` went stale at toolCount 75 and `npm run check:facts` failed the Lint & Type Check gate. Regenerated with `cd web && npm run prebuild`; only the facts file is committed. `changelog.generated.ts` also moves under that script, but its drift comes from CHANGELOG entries merged in from main and is unrelated to this PR, so it is left alone. Gate: `npm run check:facts` → OK, committed facts.generated.ts matches workspace. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D4rk4NXwyy6wmvii9Lp84P Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 14 小时前 | |
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 <bot@codewhale.net> * 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 <bot@codewhale.net> * 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 <bot@codewhale.net> * brand: trace supplied whale assets Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * brand: use white icon tile Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * brand: deepen ombre light stop Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * tui: localize image rejection recovery Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <hmbown@gmail.com> * 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 <noreply@anthropic.com> 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 c5c42b7d91 used). A second bare Enter inside that window with an empty composer promotes the just-queued message to a Steer through `attempt_steer_with_queue_fallback` — the same path Ctrl+Enter takes, so there is one steering path. A second Enter with new text is an ordinary queue; Ctrl+Enter still steers immediately; outside a turn Enter is unchanged. `enter_with_double_tap` is the one decision point again (`take_queued_for_double_tap_steer` routes through it), and `submit_disposition_does_not_mutate_the_queue` stays true. The posture bar advertises the gesture while the window is open (`PostureHintEnterAgain`, next commit). Tests (cargo test -p codewhale-tui --lib <filter> --locked): double_tap: test result: ok. 3 passed; 0 failed enter_with: test result: ok. 5 passed; 0 failed submit_disposition: test result: ok. 6 passed; 0 failed Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * tui(shell): one owner per fact — posture bar, metrics line, no dead hints Design: SHELL-DESIGN-20260901 §2.0 item 3, §2.2, §2.3, §2.3b, §2.11 and the founder's 2026-09-02 redirect (Claude Code's grammar, less always-on information). Under the composer there are exactly two chrome rows in the default state, then the work surface only when it has content: ▶▶ ask (Shift+Tab) · work (Tab) · 2 agents · Esc to interrupt /rc … deepseek-v4 · ctx 61% · $0.42 · ttft 400ms · 40 tok/s · ↓ 1.2K Ctrl+/ help Fact → owner, before → after (composed 80x24 / 120x32 frames, working turn with two sub-agents; "strip" = the work-surface bottom view): fact before after context % info line metrics line cost footer (+ info line when priced) metrics line model info line metrics line provider info line (wide) metrics line (wide) ttft / tok/s / ↓ behind /cost only metrics line repo slug info line (+ idle empty state) launch header / git view (not chrome) branch info line (+ idle empty state) launch header / git view (not chrome) mode footer posture bar permission footer posture bar phase word footer ("sub-agents underway") transcript active row (not chrome) elapsed footer ("1m 15s") roster rows (per agent) agent count indicator row + info "pod 2/2" + "whales 2/4" posture bar ("2 agents") + dock tab + strip header (+ dock tab, strip header — other slice) task/shell count indicator row above the composer posture bar help hint footer keys legend (F1) + info line (Ctrl+/) metrics line (Ctrl+/), from the binding other key hints footer "⌥V:output", compact "? help" none; cycle keys next to the chip they cycle live hint footer "Esc to interrupt" posture bar hint slot ≥80 % microcopy footer right slot posture bar hint slot (outranks the hint) notice / rc footer right slot / — posture bar right slot Dead key hints removed: `F1:keys` / `fn+F1:keys` (Help binding's `footer_chord` is now `Ctrl+/`; `info_help_hint` derives from the binding), compact `? help`, and the `footer_action_hints` family. The mode/permission cycle keys print only when the binding table admits them at the current focus (no `(Tab)` on the launch stage). Row order: composer → posture bar → metrics line → roster/to-do. The #5286 background-work chip above the composer is gone (it repeated the posture bar's counts); `PendingWork` stays as the counts' source. Goldens re-blessed and read: footer_* (posture bar), infoline_startup_*, infoline_work_* (metrics line), settings_* (the settings preview's bottom row); infoline_settings_* deleted with the settings-path segment. Commands run (CARGO_BUILD_BUILD_DIR=…/mega-frame, RUST_MIN_STACK=16777216): cargo check -p codewhale-tui --all-targets clean cargo test -p codewhale-tui --lib infoline --locked test result: ok. 11 passed; 0 failed cargo test -p codewhale-tui --lib tideline_tests test result: ok. 64 passed; 0 failed cargo test -p codewhale-tui --lib one_owner_tests test result: ok. 4 passed; 0 failed cargo test -p codewhale-tui --lib shell_key_routing test result: ok. 13 passed; 0 failed cargo test -p codewhale-tui --lib localization::tests test result: ok. 49 passed; 0 failed cargo test -p codewhale-tui --lib --locked test result: FAILED. 11893 passed; 8 failed (config_panel golden re-blessed after; the other 7: 4 fail on HEAD without this change (fleet rename in flight), tmux clipboard passes alone, none in files this change touches) cargo clippy … -D warnings 6 pre-existing errors, none in this change's hunks (config.rs:2106/2796, apply.rs:759, event_loop.rs:464, session_state.rs:1004, work_surface/input.rs:401) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(launch): checkpoint for overnight takeover — braille mark + kitty tier + Claude-Code launch header compile and pass lib tests; PTY cucumber tests still wait on the old heading Compiles (cargo check --all-targets clean). Lib tests for mark::, underwater::, mouse_ui::, localization:: pass: test result: ok. 120 passed; 0 failed (needs RUST_MIN_STACK=16777216 like scripts/dev-test.sh; the rust_i18n static overflows a 2 MiB test thread with or without this change). Startup goldens re-blessed and read. Clippy is red only in files outside this slice (config.rs, apply.rs, session_state.rs, work_surface/input.rs, and a pre-existing event_loop.rs borrow). Not done: crates/tui/tests/cucumber/{screen_mode_inline_pty, active_composer_pointer_pty,plugin_e2e_acceptance}.rs still wait for "What are we working on?" and press 'w'; they need the new marker ("Codewhale v") and a typed message + Enter to begin the session. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(rail): checkpoint for overnight takeover — dock views compile, 136/137 work_surface tests pass, files/notepad/git views are stubs Foundation for the one bottom dock (founder redirect 2026-09-02): RailPanel is now the eight-view cycle (agents, tasks, background, files, notepad, context, git, price; Pinned folded into tasks), an auto rule opens agents/tasks/background while they have content, explicit picks stick until Esc, and Ctrl+Tab / Ctrl+] (fwd) + Ctrl+Shift+Tab (back) cycle. Context and price views render as rows; files, notepad, git are stubs in views.rs. The classic sidebar line panels and their dead consumers are deleted. Known: agent_rows_show_role_assignment_and_open_the_agent_transcript fails (role_label 'worker' vs 'general'); role derivation is untouched here and the failure is believed to predate this work — unverified. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(operate): checkpoint for overnight takeover — auto-goal + contract land; one Operate approval test needs a goal-complete mock Operate now turns a non-trivial prompt into the goal through the same GoalState::create path as explicit_goal_directive, appends the Operate contract once as a user-role runtime message (append-only history, not the prefix), shows the Operate goal receipt, and carries the new mode copy in all 15 locale packs plus docs/MODES.md. Compiles. Passing: goal (134), prompts (133, incl. every_mode_shares_one_prompt_per_host), localization (49), runtime_handoff (14), session_peek (15), history_cells (2), both new engine tests. Known failing: core::engine::tests::operate_model_shell_uses_normal_approval_and_workspace_sandbox — its mocked model never reports the auto-set goal complete, so the turn re-prompts to max_steps (wiremock expect(1) sees 199). Six clippy needless_borrow/collapsible_if hits pre-exist on the branch base. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * wip(fleet): checkpoint for overnight takeover — #5815 review findings 1-9 fixed, compiles, fleet tests green Findings against the fleet-as-models work (verified against the current tree, then fixed): 1. `toggle_fleet_model` decides presence by member rows, not the projected role list (a role-less row projects to no role, so the old `all(== "operator")` was vacuously true). Regression test `toggle_removes_a_role_less_member_row` fails on the previous commit ("got Unchanged { … operator route … }") and passes now. 2. `selected_or_default` loads an existing personal `My fleet` instead of overwriting it and never writes or selects before the add succeeds; `FleetModelChange::Added` carries `created_fleet` + `selected_fleet`. 3. `fleet_models` returns `Result<Vec<_>, FleetStoreError>`: a broken explicit selection is surfaced in `/fleet models`, `/models`, and the picker's ⇧F instead of reading as "session model only". 4. `add_fleet_model` dedupes roles (case-insensitive) and returns `Unchanged` without touching the file when every role is present (test compares bytes and mtime). 5. `App.config` startup snapshot removed. `/fleet add|remove` now return `AppAction::FleetAddModel|FleetRemoveModel`; the UI arm validates the provider against the live `Config` (`fleet_provider_rejection`, `fleet_catalog_rejection`, re-exported from `commands`). 6. ⇧F applies the same provider gate as `/fleet add`. 7. One roster path: `sync_fleet_roster` (extracted from the FleetStoreChanged arm) plus `App::fleet_roster_stale`, flushed once per event-loop iteration; `/fleet add|remove`, ⇧F, and every UI-side auto-enroll site set it (`auto_enroll_fleet_model` now returns bool). 8. ⇧F receipts go through `push_status_toast` (Success/Info, 6 s) and `set_sticky_status` (Error); no new `status_message` writes. 9. All new fleet prose is `tr(locale, MessageId::Fleet…)` (27 keys, translated in all 15 packs); `FleetModelError` is typed with a localized `message(locale)`. 10. No stale "`a` in /models" doc comment exists in the current tree. Also re-blessed `config_panel_{80x24,120x32}` goldens (the Config tab label says Fleet); the diff is that one label. Evidence (this tree): cargo check -p codewhale-tui --all-targets --locked -> Finished cargo test -p codewhale-tui --lib --locked -- fleet::members groups::core::fleet model_picker format_helpers fleet_roster localization golden hotbar command_palette fleet::store -> 257 passed; 1 failed (slash_source_matches_command_palette_ command_entries: reads ~/.claude/skills and finds `impeccable`; fails identically on main in this environment) cargo clippy … -D warnings (CI flags) -> the only remaining error is crates/tui/src/tui/work_surface/input.rs:401 collapsible_if, which belongs to the work_surface lane and predates this commit cargo fmt --all -- --check -> clean sh scripts/check-tui-product-vocabulary.sh -> exit 0 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSVsAXZJnKGZmqkwH1CeKH * feat(tui): launch card, canonical role vocabulary, DashScope descriptor, test fixes - Launch is now our own card take (founder, 2026-09-02): thin top line ⑂ branch path; centred bordered card with the whale mark, Codewhale + version, one true announcement (no-model warning / MCP news), and the menu New worktree / Resume session / Changelog / Quit with real chords right-aligned; Enter runs the highlighted entry, Up/Down move it, and typing goes straight to the composer. The card dissolves on the first keystroke or command (≤240ms, instant under reduced motion); the working screen then shows ⑂ branch path + ⋮ MCP n/m, the session_start receipt, and the posture bar + metrics line (hidden while the card is up). The composer's bottom rule carries model (effort) · permission — the route's one launch reading. - Role vocabulary: fixtures and the stopship fleet/workflow now use the canonical tokens (explore/implement/reviewer/test); the workflow JS wire accepts canonical spellings with the pre-rename ones as aliases (AgentType serde rename+alias, serialized form is canonical). - Alibaba Model Studio (DashScope) joins the data-driven descriptor table: international compatible-mode endpoint, DASHSCOPE_API_KEY, live /v1/models as the Qwen model authority (never a compiled id). - Tests: role-keyed gate fixtures moved to canonical tokens; the operate model-shell test now seals the goal through the deferred update_goal tool (deferral retry included) instead of pausing blindly; the slash-source hotbar test isolates HOME; ⚠ and ⋮ gained ASCII fallbacks; launch goldens re-blessed for the card. * feat(tui): retire Pod from copy; canonical workflow fixture; gate clean-up - Pod literal sweep across fleet views, worker runtime, sub-agent tool, managed API, and command groups: user-facing copy now says Fleet (founder vocabulary decision; /fleet canonical, /pod and 'codewhale pod' stay as compatibility aliases). Roster tests that encoded the retired Pod-public/Fleet-internal split now assert the public Fleet vocabulary. - workflows/stopship + fleets/stopship use canonical role names (explore/implement/reviewer/test); the workflow crate's own stopship tests and required-roles list follow. - Operate mode-picker hint shortened to fit 80 columns in every locale. - Cucumber PTY launch flows: wait for the launch card, type the first prompt and press Enter; the live shell is proven by the launch stage's top line disappearing and the metrics line's ctx reading (the interrupt hint needs a live turn, which an offline route never starts). The stopship acceptance feature expects the canonical /fleet help copy. - CHANGELOG receipts synced; DESIGN.md shell direction records the card, posture bar + metrics line, and the bottom view cycle. * test(cucumber): launch-card PTY contract fixes - The launch-card wait uses the menu's New worktree entry — unique to the card; the bare wordmark also matches onboarding copy. - The live-shell proof is the launch stage's top line disappearing plus the metrics line's ctx reading; the interrupt hint needs a live turn, which an offline route never starts, and the help hint sheds first at the 40-column floor by design (SHELL-DESIGN-20260901 §2.2). - The pointer-submit queue proof takes the offline onboarding seed into account: the receipt toast proves the gesture, and the queue count grows by exactly one. * docs(readme): restore the canonical product screenshot the web contract pins The brand header redesign dropped the assets/screenshot.webp embed; the web public-surface contract pins the README and the website to one canonical optimized screenshot (byte-identical, 1562x1256 lossless VP8L). Re-embed it. * test: platform-robust pointer-submit wait and cap-warning diagnostics - The pointer queue proof accepts either the transient receipt toast or the queue-count increment: toast timing differs across runners, and a 20 s wait missed a toast the queue dump proved had fired. - The context-cap posture test dumps the drawn rows when the warning count misses, instead of a bare 0 != 1, so a platform-specific shed (the hint sheds first when the left run exceeds its budget) is visible in CI. * test: fix the linux-only context-cap shed; bounded pointer-click retry - The context-cap posture test drew at 100 columns, where a backend-less platform (linux CI paints 'files: workspace (unenforced)') sheds the cap hint first, so the warning count read 0. Draw at 140 columns, where the hint survives with the notice present; verified locally. - The pointer queue proof retries the [↑] click once, re-finding the affordance first: under runner load a redraw can shift cells between the find and the click, so the first SGR gesture lands nowhere. * fix(gates): tool-catalog budget covers the fleet rename; readme stamps; pointer baseline - The Pod->Fleet sweep grew every mode's tool-schema surface by 58 bytes (+14 tokens). The receipts are re-measured and the one-way ceilings in scripts/runtime-contract-budget.json are raised to them as the explicit maintainer decision the gate asks for (the rename is the founder's 2026-09-01 vocabulary call). - The README screenshot embed changed README.md; the 18 translated READMEs re-stamp (the embed is language-neutral HTML - no prose changed, so no retranslation was needed). - The pointer queue baseline is captured while the composer is empty: the pending preview row hides while a draft sits in the composer, so the pre-click depth read None and the growth proof could not fire. * test: re-click then keep polling until the deadline The qa_harness Instant wrapper does not implement Div, and the retry's single read raced the app processing the second gesture: poll to the full deadline, re-click once at the half-way point. * test: pointer queue diagnostics (baseline/expected/last-seen) in the failure output * test: pointer poll keeps per-iteration state only (unused-assignment gate) * fix: Copilot review findings — planner wire spelling and Advisor copy - workflow::AgentType::Plan serializes as the canonical 'planner' ('plan'/'awaiter' stay accepted aliases), matching the FleetRole vocabulary the mega PR declares. - Web: the vocabulary docs metadata, the vocabulary module header, and the docs-map topic description say Advisor (the public advisory term) instead of the retired Consultant spelling. - Polish home dictionary: restore 'Podwodna powłoka terminala' — the fleet-vocabulary sweep had merged 'Fleet' into the compound word 'Podwodna' (underwater), producing the non-word 'fleetwodna'. * test: pointer proof accepts preview-appears when no baseline count is painted * test: the tolerant preview-appears proof (the arm the last commit missed) --------- Signed-off-by: CodeWhale Bot <bot@codewhale.net> Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 5 天前 | |
ci(cnb): post shadow GitHub check runs from linux rust gates (#5746) Import the codewhale-cnb-bridge GitHub App credentials from the CNB KeyStore (codewhale.net/codewhale-ci-secrets, github-bridge.yml) via the documented imports mechanism, and add an endStages bridge step to the linux rust gates pipeline that mints an installation token and posts a non-required 'linux rust gates -cnb' Check Run on the exact GitHub SHA being built, with the conclusion mapped from CNB_PIPELINE_STATUS. Per the shadow-parity protocol in the CNB-primary CI design: GitHub Actions stays canonical and required, no GitHub gate flips, and the bridge runs in endStages so a bridge outage can never fail the CNB pipeline itself. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: CodeWhale Bot <bot@codewhale.net> | 6 天前 | |
fix(release): embed user-theme schema inside codewhale-tui package cargo publish and the Docker image both failed because palette/user_theme.rs include_str!'d docs/schemas/..., which is outside the crate package and excluded by .dockerignore. Copy the schema into crates/tui/src/assets and include it from there so crates.io packaging and container builds can compile codewhale-tui. Keep a .dockerignore exception for docs/schemas as belt-and-suspenders for other embeds. | 1 个月前 | |
feat: add Mistral AI as a first-class provider route Wire Mistral AI / la Plateforme into the shared provider registry, TUI provider enum, provider-scoped config/env overrides, static model registry, context-window metadata, reasoning wiring, docs, and examples. The route uses Mistral's OpenAI-compatible Chat Completions endpoint at https://api.mistral.ai/v1 with 'mistral-code-latest' as the default model (Codestral coding model, 256K context). Model IDs verified live against https://api.mistral.ai/v1/models: the static registry ships 'mistral-code-latest' (accepts 'codestral-latest' as alias for backward compatibility), 'mistral-medium-latest', 'mistral-small-latest', 'magistral-small-latest', and 'mistral-large-latest'. All models report 262144 (256K) context on /v1/models except mistral-code-latest at 256000; earlier drafts of this PR had those windows reversed. Reasoning is wired end-to-end for the three models that advertise 'reasoning: true' on /v1/models — mistral-medium-latest, mistral-small-latest, and magistral-small-latest. Codewhale sends 'reasoning_effort' (Mistral currently accepts 'none' or 'high' only; intermediate tiers return HTTP 400 code 3051), parses the polymorphic 'content: [{type: thinking, thinking: [{type: text, text: ...}], closed: bool}, {type: text, text: ...}]' shape emitted by reasoning models, and replays the thinking trace back into multi-turn history per docs.mistral.ai/capabilities/reasoning. Non-reasoning models (mistral-code-latest, mistral-large-latest) never receive the field because Mistral would reject it. FIM (/v1/fim/completions) is not wired. Provider aliases: mistral-ai, mistralai, la-plateforme. Env vars: MISTRAL_API_KEY, MISTRAL_BASE_URL, MISTRAL_MODEL. Auth via API key from https://console.mistral.ai/api-keys, config, or 'codewhale auth set'. Test env-poisoning: EnvGuard captures/removes/restores MISTRAL_* so tests stay reproducible when a user has these vars exported in their shell. Validation: - cargo fmt --all -- --check - cargo clippy --workspace --all-targets --all-features --locked (with the documented allow list) -- No issues found - cargo test --workspace --all-features --locked -- 22 pre-existing failures in crates/tui git-shell tests (worktree init failing on 'git commit' in isolated tempdirs), verified identical count on origin/main at 91bca01a9 and unrelated to this change - python3 scripts/check-provider-registry.py -- passed - codewhale --provider mistral --model mistral-medium-latest exec against api.mistral.ai returned a correct reasoning-mode response - codewhale --provider mistral --model mistral-large-latest exec succeeded without HTTP 400 code 3051 (verifies the model-aware reasoning gate) - TUI smoke previously validated: /status shows mistral + mistral-code-latest, /provider lists Mistral, tool call end-to-end Assisted by Codex CLI for implementation and multiple Oracle review passes (correctness + convention + Hunter's inline review) that surfaced the ProviderArg clap enum gap, the ModelRegistry silent fallthrough to DeepSeek, the Codestral context-window regression, the EnvGuard env-poisoning flake, and the model-ID / context-window / reasoning-support mistakes from the initial docs-slug pass now corrected against the live /v1/models catalog. | 29 天前 | |
fix(ci): keep Tideline goldens LF on Windows checkouts crates/tui/src/tui/goldens/*.txt fell through to the `* text=auto` fallback, so a Windows checkout converted all forty goldens to CRLF. golden_harness.rs::render_golden_text always joins rows with LF and assert_matches_golden compares the fs::read_to_string bytes directly, so Test (windows-latest) failed all eight golden tests with a pure \r\n diff. Same fix, same reason, as the telemetry golden JSON above. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 9 天前 | |
fix(vscode): make the extension's send path work, and close the security holes The extension had never successfully started a turn. `startTurn` accepted only HTTP 200/202 while the runtime's `start_thread_turn` (crates/tui/src/runtime_api.rs:4613-4632) returns `StatusCode::CREATED` as its ONLY success path, so every send failed. `git log -- src/api.ts` is a single commit: this was never a regression, it shipped that way and was never run end to end. api.ts (send path): - Status handling now tests a RANGE (`isOk`: >= 200 && < 300) through one `ensureOk` helper routed through every call site, rather than enumerating codes at eleven of them. 201 is accepted because it is 2xx, not because it is special-cased — the same shape the embedded web client already used at crates/tui/src/runtime_web/app.mjs:873, which is why that client worked against the same runtime this one choked on. - The runtime's JSON `error.message` is surfaced on every route; previously only startTurn passed it through. - 409 is typed: a second send while a turn is live is "already running", and interrupting when nothing streams is "nothing to stop", not an error. Security (extension.ts, runtime.ts, secrets.ts): - SecretStorage now wins over the settings token, matching what secrets.ts, the manifest and the README all already promised. Previously a repo-local .vscode/settings.json could supply a bearer AND retarget `runtimeHost`, and the token rode every request — opening a repo was enough. - The runtime token is passed to the terminal via environment instead of `--auth-token` in argv, which was visible in shell history and `ps`. - status.ts nonce uses a CSPRNG, matching chat.ts. Chat correctness and accessibility (chat.ts, transcript.ts): - Transcript prefers `detail` over the 280-char `summary`, so reload shows the reply instead of a stub. - `operation_key` is reused on retry, so a timeout and resend no longer creates two turns; the dead SSE stream is cleared so reconnect can fire. - The composer keeps its text until the turn is accepted. - Tool paths are parsed out of `metadata.tool_input` and treated as untrusted. The durable fix is runtime-side and is NOT taken here. - Focus styling and roles/labels added; there were none. Chrome (package.json, extension.ts): - Chat is contributed to the secondary sidebar with an activity-bar fallback, gated on `codewhale.noSecondarySidebar`, which is set at activation from `vscode.version` (>= 1.106). One ChatView instance serves both view ids and `reveal()` focuses whichever resolved. - `engines.vscode` stays `^1.96.2` and the threshold is enforced at runtime, matching the shipping Codex extension; raising the floor would have cut off 1.90-1.105 users and made the fallback unreachable for nothing. CI and dev loop (ci.yml, .gitignore, .vscode/): - CI runs the extension tests. Nothing ran them before, which is how a send path that could not work stayed green. - launch.json/tasks.json give a working F5 host. The root `.gitignore`'s bare `.vscode/` silently swallowed them, so a negation was added — without it these files exist locally and vanish on commit. Gates: cd extensions/vscode && npx tsc --noEmit -> clean cd extensions/vscode && npm test -> tests 42, pass 42, fail 0 (baseline before this was 25) manifest/provider coherence: every declared view id has a provider; no provider lacks a manifest entry; context key set at activation. Not done, deliberately: the Runtime view still exists, so this is not yet a single-view Agents panel. Removing it spans extension.ts, status.ts and two commands; a half-removal is worse than either state. Gate item 5 — a human driving one real turn in an Extension Development Host — remains unproven. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D4rk4NXwyy6wmvii9Lp84P Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 11 小时前 | |
chore: map github web committer | 4 个月前 | |
fix(tui): the footer's permission chip outranks the mode word (#5796) * fix(tui): the footer's permission chip outranks the mode word Founder-reported: the "full access" posture chip was missing from the footer in operate mode. The merged footer paints the posture lockup left-to-right and drops any chip that would run past the left block's edge, so the *last* chip was always the first casualty — and the order was [mode, permission]. Operate mode made it reproducible rather than occasional: `operate` is the longest of the three mode words, so it consumed the cells `full access` needed and the footer silently stopped reporting that the session could write anywhere. A preference word must not outbid a safety fact. When only one chip fits, permission keeps the cells; painting order stays mode-then-permission so the lockup does not shift when both fit. Regression test sweeps widths 40..=120 and asserts no width keeps the mode word while shedding permission. Without the fix it fails at width 69 — an ordinary split-pane width, not a degenerate one. tui footer_: 33 passed; 0 failed (existing posture and golden tests included, no golden drift). cargo fmt --check clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LmeqaZAesoHjT8N9PR7S2c * docs(agents): code first, then tests Founder rule, 2026-09-01. The implementation is written and proven to run first; tests are added afterward to cover what was actually built. No TDD here, and this overrides any skill or default that mandates it (superpowers `test-driven-development` in particular). An existing test that only encodes old behavior is evidence, not a veto. Placed beside the existing selective-evidence policy it extends, and scoped so it does not cancel the "Claiming a test passed" rule: a regression test written after a fix still has to be shown failing without it. That rule is what makes an after-the-fact test worth keeping, and it is the only part of test-first discipline that was ever earning its cost. No conflicting TDD mandate exists in the scoped crate guidance (checked crates/*/AGENTS.md and docs/). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LmeqaZAesoHjT8N9PR7S2c --------- Co-authored-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 6 天前 | |
Merge pull request #5972 from Hmbown/fix/runtime-store-failures-visible-5931 tui: a failing runtime store is a visible notice, not a log line | 5 小时前 | |
docs: adopt the ponytail decision ladder (#5787) Founder-directed. From dietrichgebert/ponytail -- 'the laziest senior dev in the room', 'the best code is the code you never wrote'. Encodes the ladder verbatim rather than paraphrasing it: 1. Does this need to exist? -> Skip it 2. Already in this codebase? -> Reuse it 3. Stdlib does it? -> Use it 4. Native platform feature? -> Use it 5. Installed dependency? -> Use it 6. One line? -> One line 7. Only then: the minimum that works Two parts of the source method matter as much as the rungs and are kept explicit. The ladder runs *after* understanding the problem -- lazy about solutions, never about reading the code first. And it never cuts trust-boundary validation, data-loss handling, security, or accessibility. Rung 2 is the one this repository keeps failing, so the section says so and points at the existing model_*/ *_config / provider_* grep rule rather than restating it. Two corollaries earned here are added because the ladder does not cover them: an abstraction must delete caller code, and migrate the last consumer or do not start. Carries no counts. AGENTS.md's first line says to derive changing state from the repository rather than from instructions, so the dead-code corollary points at scripts/check-dead-code-budget.py instead of freezing a number. CLAUDE.md gets a pointer, not a copy. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: CodeWhale Bot <bot@codewhale.net> | 6 天前 | |
docs: add CODE_OF_CONDUCT.md Add Contributor Covenant Code of Conduct v2.1 to establish community guidelines and set clear expectations for participant behavior. | 4 个月前 | |
docs: add Indonesian documentation suite and README.id.md Add README.id.md linked to main README, CONTRIBUTING.id.md, and comprehensive Indonesian documentation suite in docs/*.id.md. Pass check-readme-translations.py validation. | 1 个月前 | |
docs(changelog): merge-session receipts (#5749, #5751, #5791, #5738, #5721, first-paint, paste-burst, Ctrl+C) One batched receipts commit per merge session; PRs no longer edit the changelog (policy note added to CONTRIBUTING.md). | 6 天前 | |
feat(build): opt-in rusty_alloc global allocator feature Add an off-by-default `rusty-alloc` cargo feature to codewhale-tui and codewhale-cli (#5872) that maps the `#[global_allocator]` static to rusty_alloc (the pure-Rust mimalloc v2.4.5 remake — no C compiler, no build script on that path) instead of the default mimalloc. The issue's sketch pinned `rusty_alloc` and used `rusty_alloc_api::RustyAlloc`; the GlobalAlloc impl actually lives in the `rusty_alloc-api` crate (the crate's documented surface), so that is the dependency — it pulls the rusty_alloc 1.1.6 core transitively at the same version. Default build is unchanged: the mimalloc static compiles exactly as before behind `#[cfg(not(feature = "rusty-alloc"))]`. Build with: cargo build -p codewhale-tui --features rusty-alloc Gates (worktree tmp/wt-5872-rusty-alloc, shared target dir): - cargo fmt --all: clean - cargo check -p codewhale-tui --locked: clean (2m31s) - cargo check -p codewhale-tui --locked --features rusty-alloc: clean (5m10s) - cargo check -p codewhale-cli --locked --features rusty-alloc: clean (2m04s) - cargo clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_or: clean (5m20s) - cargo deny check: advisories ok, bans ok, licenses ok, sources ok (both new crates are MIT; no deny.toml entry needed) - cargo test -p codewhale-tui --lib --locked: 11868 passed, 1 failed, 13 ignored (357s). The failure, remote_control::tests::separate_predispatch_crashes_on_one_run_get_distinct_recovery_turn_ids, passes in isolation on rerun (1 passed, 0 failed) and is unrelated to allocator wiring — the lib test target does not compile the changed src/main.rs. Reporting it as the one non-green result of the run. CHANGELOG [Unreleased] entry + sync-changelog.sh + regenerated web/lib/changelog.generated.ts (derive-changelog.mjs idempotent). Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 20 小时前 | |
feat(build): opt-in rusty_alloc global allocator feature Add an off-by-default `rusty-alloc` cargo feature to codewhale-tui and codewhale-cli (#5872) that maps the `#[global_allocator]` static to rusty_alloc (the pure-Rust mimalloc v2.4.5 remake — no C compiler, no build script on that path) instead of the default mimalloc. The issue's sketch pinned `rusty_alloc` and used `rusty_alloc_api::RustyAlloc`; the GlobalAlloc impl actually lives in the `rusty_alloc-api` crate (the crate's documented surface), so that is the dependency — it pulls the rusty_alloc 1.1.6 core transitively at the same version. Default build is unchanged: the mimalloc static compiles exactly as before behind `#[cfg(not(feature = "rusty-alloc"))]`. Build with: cargo build -p codewhale-tui --features rusty-alloc Gates (worktree tmp/wt-5872-rusty-alloc, shared target dir): - cargo fmt --all: clean - cargo check -p codewhale-tui --locked: clean (2m31s) - cargo check -p codewhale-tui --locked --features rusty-alloc: clean (5m10s) - cargo check -p codewhale-cli --locked --features rusty-alloc: clean (2m04s) - cargo clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_or: clean (5m20s) - cargo deny check: advisories ok, bans ok, licenses ok, sources ok (both new crates are MIT; no deny.toml entry needed) - cargo test -p codewhale-tui --lib --locked: 11868 passed, 1 failed, 13 ignored (357s). The failure, remote_control::tests::separate_predispatch_crashes_on_one_run_get_distinct_recovery_turn_ids, passes in isolation on rerun (1 passed, 0 failed) and is unrelated to allocator wiring — the lib test target does not compile the changed src/main.rs. Reporting it as the one non-green result of the run. CHANGELOG [Unreleased] entry + sync-changelog.sh + regenerated web/lib/changelog.generated.ts (derive-changelog.mjs idempotent). Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 20 小时前 | |
web: Tidal Folio — paper-to-navy site, serif voice, real v0.9.12 capture, consented usage counting The website becomes a folio read under the sea, per the founder's refined direction (codewhale-ops/design/website-20260904/tidal-folio-illustrated- direction.png): Whale Ivory paper and a Newsreader title voice above the waterline, the TUI's own navy and blue below, one drawn element — the strata in components/strata.tsx, geometry from palette tokens, no photograph — and the founder's own v0.9.12 development-build capture floating at the waterline, captioned as exactly that. Design system - :root maps the historical token names to the paper sheet (WHALE_TEXT_BODY ivory, LIGHT_* inks, WHALE_COBALT/COMPOSER for action); one shared rule re-inks every dark subtree (.ocean-column, .site-footer, the opt-in docs dark sheet) with the whale tokens, so components are written once. - scripts/export-design-tokens.py now also exports the TUI's LIGHT_* preset as --light-*; web/app/tokens.css regenerated (64 tokens). - Newsreader (next/font/google) for h1/h2; Plex Condensed keeps h3/h4. - Scroll-reveal removed; the page is complete and static. - Docs default to paper; dark is the opt-in sheet. Copy and information architecture - Homepage: what a person gains (their models, capable agents, control on their machine); a models chapter; the four-step start; a waterline; an availability chapter stating terminal released, web app account sign-in available with the workbench a development preview, desktop a development build, cloud computers not available yet. No cloud claim, no "intent to verified work" checklist. - New /product page (lib/content/product.ts), in the sitemap and llms.txt. - Nav: Product · Models · Pricing · Docs; Start/Install/FAQ/Community/ Contribute move to the compact sheet's second group and the footer. "Register" becomes "Create account". - IDENTITY_PHRASE and every locale's footer tagline follow the new direction; all 18 home dictionaries rewritten in their own language with the new key contract (HomeDict), GT catalogs re-exported. - Account entry copy moves to lib/content/account-entry.ts. Screenshot - web/public/codewhale-tui.png is the founder's PNG byte-for-byte (sha256 c95df932…); assets/screenshot.webp is a lossless WebP of it for the READMEs; docs/public-surface-facts.json describes the capture as a development build whose Full Access posture is not a default. Usage counting (PostHog frontend scope) - lib/telemetry/product-usage.ts: closed schema v2 / consent v4 envelope, 13 u32 counters, random v4 install id rotated at 90 days, fail-closed consent, opt-out clears counts and identity and cancels delivery, other tabs' revocation honoured; matches the backend golden fixture. - app/api/product-telemetry: same-origin forwarder, inert unless CODEWHALE_TELEMETRY_INGEST_URL is the exact canonical ingest; forwards the validated body only, 1.5 s bound, no retry. No SDK, no token in the browser. - components/usage-consent.tsx: explicit, reversible consent sheet; footer "Usage data" control; page_view/docs_view on route change; data-usage marks for login/signup/download; install_copy from the copy button; error_shown from the error boundary. Gates run from web/ (2026-09-04): - npm test (vitest): 47 files, 398 passed, 0 failed - npm run check:facts: OK; check:docs: PASS; check:tokens: up to date (64 tokens); check:locales: PASS + GT catalog OK - npm run lint: 0 errors, 2 pre-existing <img> warnings - npm run build: succeeded (Next 16.3.3), /api/product-telemetry dynamic - Rendered at 1440 and 390 px on a local production server (port 3120): /en /zh /en/product /en/models /en/pricing /en/install /en/docs /en/signin, HTTP 200, zero console errors. Not proven here: hosted CI, deployment, live ingest delivery, PostHog processing, customer acceptance. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017QBm1xR9f5Dojf3PWsR4Ry | 2 天前 | |
fix(release): promote tested v0.9.11 nonbenchmark candidate Promotes the fully gated non-benchmark candidate while preserving the benchmark tree exactly from the prior release-PR head. Signed-off-by: CodeWhale Bot <bot@codewhale.net> | 16 天前 | |
Initial release v0.1.0 DeepSeek TUI - Unofficial terminal UI + CLI for DeepSeek models. Features: - Interactive TUI with multiple modes (Normal, Plan, Agent, YOLO, RLM, Duo) - Comprehensive tool access with approval gating - File operations, shell execution, task management - Sub-agent system for parallel work - MCP integration for external tool servers - Session management and skills system - Cross-platform support (macOS, Linux, Windows) 🤖 Generated with [Claude Code](https://claude.ai/code) | 7 个月前 | |
merge(web): integrate illustrated site and GitHub-first installation Preserve the website authorship and supplied development screenshot. Share bounded request reading between forms and telemetry and reconcile the media evidence wording in PRODUCT.md. Validation: 407 website tests passed, 0 failed in 47 files; facts/docs/locales/tokens, lint and webpack production build passed (2 existing image warnings). Web tree matches tested 62f3a39086; Rust/Cargo/config inputs match fd98, whose 14277/0/14 and CI Clippy evidence is retained. Root npm test/check:web scripts are unavailable. No publication or release. | 2 天前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(readme): link the community CodeWhale for VS Code GUI frontend Add a compact "GUI frontend" section to README.md right after "Use" so terminal users who prefer a graphical interface can discover the community-maintained CodeWhale for VS Code extension (installed from the VS Code Marketplace; GitHub hosts the source). Mirror the section into all 18 translated READMEs and refresh their source stamps so the translation drift gate stays green. README-only; no code or behavior changes. | 7 小时前 | |
docs(public): align release facts with runtime Derive website sandbox facts from explicit runtime capability markers instead of source filenames. Document actual platform wrappers, narrow model and audit claims, and make two-package/three-command installs exact. Verify release assets under their manifest filenames before renaming them, with an executable contract test for every Unix snippet. Refresh localized README receipts and keep source-candidate toolCount at 66. Signed-off-by: Hunter B <hmbown@gmail.com> | 1 个月前 | |
feat(config): add one shared RFC 8628 device-code polling primitive CodeWhale had two hand-rolled device-code pollers with nothing shared between them (crates/cli/src/cloud.rs poll_device, crates/tui/src/ xai_oauth.rs poll_device_token + device_poll_backoff). The xAI one decided whether to keep polling by substring-matching its own error strings, which is why slow_down handling was stringly typed. Port pi's pollOAuthDeviceCodeFlow to Rust as codewhale_config:: device_code::DeviceCodePoll, generic over the poll result and free of I/O: the caller supplies poll and sleep. It carries pi's accumulated fixes, which CodeWhale did not all have: - RFC 8628 3.2 default of 5s when the server omits interval - slow_down that PREFERS a server-supplied interval over the client-tracked one, because a purely client-tracked interval polls early forever under WSL/VM clock drift; RFC 8628 3.5's +5s step is the fallback - a deadline from expires_in that is never slept past, including after backoff - a distinct timeout message once any slow_down was seen Also ports pi's validateVerificationUri as validate_browser_verification_uri: the URI comes off the wire and is handed to a browser opener, so it must not be able to launch file:, javascript:, or a custom app scheme. pi requires https; this allows http on a loopback host as well, matching the loopback allowance crates/cli/src/cloud.rs already makes for a self-hosted test API. The primitive never holds, formats, or logs token material: T is opaque to the module and no Debug/Display derive touches it. Ported from pi (MIT, Copyright (c) 2025 Mario Zechner), packages/ai/src/auth/oauth/device-code.ts and .../xai.ts; notice carried in THIRD_PARTY_NOTICES.md and at the top of the new module. Implemented with agent assistance. Signed-off-by: Hunter Bown <hmbown@gmail.com> | 17 天前 | |
sandbox: ship the workspace into the ShannonNet session before each command `sandbox_shannon_sync` (default on): the Shannon backend walks the workspace with git's ignore rules (.gitignore, local/global excludes, .git itself; symlinks and files over 16 MiB skipped), stamps files by length and mtime, and before each command ships only what the worker's per-World session has not seen — the whole tree once, then edits and deletions — as gzip tar chunks of at most 6 MiB raw through `shannon cap invoke --action sync`. Commands then run in that writable /work with the files the Engine just edited, and their outputs persist across commands, so remote builds and test suites work. A failed sync fails the command rather than running it on a stale tree; the backend sends `destroy` (detached) when it drops. The World attachment grants invoke,sync,destroy only when sync is on. Tests (stand-in `shannon` CLI recording argv): first command ships exactly the non-ignored tree, an unchanged tree ships nothing, an edit plus a deletion ship exactly those, every sync precedes its command; chunking at the raw-byte limit. Docs: config.example.toml, docs/SANDBOX.md, CHANGELOG. Counterpart in ShannonNet abf72c1 (ADR-0012: per-World session containers, path-safe extraction, `make demo-codewhale` runs that repository's Go tests inside a synced session). Gates: cargo fmt --check ok; cargo clippy -p codewhale-tui --lib --tests -D warnings ok; sandbox::shannon 8 passed / 0 failed. Full suite (RUST_MIN_STACK=8388608 as CI): 11686 passed; 1 failed — remote_control::tests::separate_predispatch_crashes_on_one_run_get_distinct_recovery_turn_ids ("saved session still owns an unfinished account turn"), untouched by this diff, passing in isolation and with its module (remote_control::tests: 77 passed / 0 failed); the run overlapped a Docker Go build on this host. An earlier full run of the same tree shape was 11685 passed / 0 failed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jw7EuFvtYMHHK5Cu6JLEjc (cherry picked from commit 31830b635d944c493aac6159d10b89949014e999) | 21 小时前 | |
build(deps): carry one jsonschema stack again (690 → 685 packages) The dependabot bump of the workspace `jsonschema` pin to 0.49 (d85be3b76) left schemaui 0.12 — which still requires ^0.46, including its latest 0.12.4 — on the old line, so the graph compiled jsonschema, jsonschema-regex, referencing, and fancy-regex twice (5.8 s + 3.2 s of the cold lib-test build for the two jsonschema units alone) and `cargo deny check bans` warned on all four. Pin the workspace back to the 0.46 line schemaui can share, with a note to move both together, and drop the stale jni/jni-sys/redox_syscall skips deny reported as unmatched or unnecessary. `cargo deny check bans` and `check advisories` are clean; `--locked` still resolves; codewhale-workflow-js and the tui schema tests pass. multiple-versions stays "warn". | 22 天前 | |
chore(deps): bump fenix from `2b240cd` to `e0f7f51` Bumps [fenix](https://github.com/nix-community/fenix) from `2b240cd` to `e0f7f51`. - [Commits](https://github.com/nix-community/fenix/compare/2b240cd75dabb93338e1a3e6029898022bad0f52...e0f7f5109090e4ebc9f3c969b961966cd7a61013) --- updated-dependencies: - dependency-name: fenix dependency-version: e0f7f5109090e4ebc9f3c969b961966cd7a61013 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> | 5 天前 | |
misc: replace stdenv.isLinux with stdenv.hostPlatform.isLinux | 10 天前 | |
release: 0.9.12 in the tree Founder asked for a 0.9.12 build to test. This bumps the version everywhere `scripts/release/check-versions.sh` audits, so the tree is internally consistent rather than half-bumped: workspace `Cargo.toml`, all 66 internal `codewhale-*` path-dependency pins across 14 crate manifests, `Cargo.lock`, the npm packages and both lockfiles, the VS Code extension, the remote-smoke `RELEASE_TAG` default, and the generated `web/lib/facts.generated.ts`. The changelog's `[Unreleased]` section already described 0.9.12 work, so it is promoted to `## [0.9.12]` with a fresh empty `[Unreleased]` above it and the compare links added — the mechanical release-notes move, not a judgement about scope. One new entry records that computer use now ships with the binary. `check-versions.sh` reports `Version state OK: workspace=0.9.12, npm=0.9.12, npm-binary=0.9.12, lockfile in sync.` Its remaining output is the pre-existing advisory about already-merged commits in the v0.9.11..HEAD range that never got release-note receipts; that predates this commit and still blocks the release paths until someone writes them. This is a version bump, not a release: no tag, no push, no prepare-release.sh. Gates on the bumped tree: fmt clean; clippy --workspace --all-targets --locked -D warnings clean; tui 11659 passed/13 skipped, tui-integration 280/0, tui-cucumber 16/0, cli 339/0, config 634/1 skipped, lane 67/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013r9fgwt1HYymrB7iZGSkCm | 4 天前 | |
fix(deps): bump undici 7.28.0->7.29.0 (override), fast-uri 3.1.4->3.1.5, brace-expansion to fixed lines — clears 23 Dependabot alerts | 1 个月前 | |
chore: use stable rust toolchain channel Cargo already enforces the workspace MSRV through rust-version, so let rustup select the current stable toolchain instead of pinning contributors to exactly Rust 1.88. Fixes #3570. | 2 个月前 |
Codewhale
Codewhale 是一款面向终端的开源编程智能体,使用 Rust 构建,并与用户一起在公开协作中不断改进。

English · 日本語 · Tiếng Việt · Bahasa Indonesia · 한국어 · Español · Português · Русский · Українська · Français · Deutsch · 繁體中文 · हिन्दी · Türkçe · Italiano · Polski · العربية · Català
安装
macOS / Linux:推荐安装官方 GitHub Release。
curl -fsSL https://codewhale.net/install.sh | sh
"$HOME/.local/bin/codewhale"
Windows 请使用 GitHub Releases
中的安装器或压缩包。已有的直接安装使用 codewhale update;它会显示当前可执行文件路径,
并保留比已发布版本更新的构建。npm 和 Cargo 是次要打包选项。
迁移与 PATH 排查见安装指南。
首次运行会帮助你连接提供商,也可以选择保持离线。Codewhale 还支持 Cargo、Docker、Nix、Scoop、预构建压缩包、Android/Termux 和 CNB 镜像。请参阅安装指南。
每种 shell 只需一条命令即可启用 Tab 补全——codewhale completion bash|zsh|fish|powershell|elvish。请参阅 shell 补全。
使用
像与队友交流一样向 Codewhale 描述任务:
Fix the failing tests and explain what changed.
也可以不打开 TUI,直接运行任务:
codewhale exec "fix the failing tests and explain what changed"
Codewhale 可以读取你的代码仓库、编辑文件、运行命令、检查结果,并持续推进目标。由你决定授予它多少访问权限。
GUI 前端
更喜欢图形界面?社区维护的 CodeWhale for VS Code 扩展把同一个智能体放进 VS Code 侧边栏——聊天、线程会话、实时 diff 与任务管理,全部基于同一个 Runtime API,会话与终端保持同步。可从 VS Code Marketplace 安装;源码见 GitHub。
为什么选择 Codewhale
- 使用你想要的模型。 连接托管提供商,或通过 Ollama、vLLM、SGLang 使用本地模型。使用
/model切换提供商和模型。 - 掌控始终在你手中。 Plan 模式为只读。Ask、Auto-Review 和 Full Access 会清晰展示审批行为。
/undo可撤销上一轮操作,/restore可将工作区恢复到较早的快照。 - 让长时间任务井然有序。 保存会话、设置持久的
/goal、在工作流运行前进行审查,并协调多个智能体,同时不让其内部指令混入你的对话记录。 - 扩展你已有的智能体。 连接 MCP 服务器和技能、配置钩子,并将智能体角色作为可读文件保存在项目或个人设置中。
在 TUI 中运行 /help 可查看命令和键盘快捷键。
安全
Codewhale 在你的机器上运行,并仅拥有你授予的访问权限。审批模式和仓库规则会限制智能体的行为;在支持的平台上,可选的操作系统沙箱可提供更强的执行边界。未知的模型价格会保持显示为未知,而不会被误报为免费。
文档
加入社区
当人们使用 Codewhale、反馈不顺手之处并帮助修复问题时,它就会变得更好。如果缺少某个提供商、工作流体验不佳,或终端界面妨碍了你,请提交 issue。如果你知道如何改进,请提交 pull request。我们欢迎首次贡献,贡献者也会保留已合入工作的署名。
加入 Discord,或在微信添加 Hunter(hunterbown)并申请加入 Whale Brothers 群。
项目历史
Codewhale 起初名为 deepseek-tui,至今仍保留与其配置和会话的兼容性。如今它已不偏向任何提供商,由社区独立维护,也不隶属于任何模型提供商。
感谢每一位贡献者,以及帮助项目成长的开源社区。请参阅贡献者记录。
许可证
项目介绍
适用于 DeepSeek 模型的编码代理,可在终端运行【此简介由AI生成】