mirror of
https://github.com/Hmbown/DeepSeek-TUI.git
synced 2026-09-03 06:50:13 +08:00
main
404 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
84b3dd694f |
feat(skills): FEAT-022 skills command shapes and retained-host validation (#5829)
Harvested from PR #5825 by @aboimpinto |
||
|
|
329960fcbf |
feat: Codewhale 0.9.12 shell, brand, fleet, and Operate (mega) (#5826)
* feat(fleet): your fleet is the models you added, and it comes first
Design MODEL-ROUTING-CATALOG-20260901 §10, slice F1. A fleet model is a Pod
member: the selected Pod file's operator route plus every member row that
pins an exact provider + model; the roles a model fills are the member rows
that pin it. No second store.
- crate::fleet::members: fleet_models / add_fleet_model / remove_fleet_model
/ toggle_fleet_model + change_receipt; Config::fleet_members(workspace) is
the read seam for the operator-awareness slice (F2).
- /pod models | add <provider> <model> [role…] | remove <provider> <model>
(also via the /fleet alias). A model the configured provider does not
serve is rejected; the first add creates and selects a user-global Pod
named 'My fleet'.
- /model picker: ⇧F adds or removes the row's exact route; fleet models
lead the list labelled 'fleet · <roles>', ahead of ⇧P pins and providers.
- /models prints the fleet before the provider list ('Your fleet is the
session model only' when empty).
- PickerActionFleet message in all 15 locales; docs/FLEET.md 'Your fleet
as models'.
Tests: scripts/dev-test.sh tui fleet::members groups::core::fleet
model_picker format_helpers — Summary 37 tests run: 37 passed, 11834
skipped.
Signed-off-by: CodeWhale Bot <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
|
||
|
|
60c1fbe568 |
chore: dead-code budget 425 after #5811
Co-Authored-By: Hunter Bown <hmbown@gmail.com> |
||
|
|
2372a8cf8f |
chore: record dead-code budget at 426 after #5784/#5807/automation slice 1
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Hunter Bown <hmbown@gmail.com> |
||
|
|
de001f3c4b |
design: export the TUI whale palette instead of re-typing it (#5797)
* design: export the TUI whale palette instead of re-typing it
crates/tui/src/palette/tokens.rs is the whale palette. The web app repeated
its hexes by hand, the desktop shell ran a separate neutral-gray palette, and
the Android theme a fourth one — four palettes sharing exactly one value
(#08111C). Make the Rust file the source and generate the rest.
scripts/export-design-tokens.py parses the 47 WHALE_*_RGB consts (aliases
included: INFO = ACTION = ACCENT_PRIMARY, SUCCESS = WORKING_GREEN,
ERROR_BORDER = ERROR, ...) and emits web/app/tokens.css, plus — when a
codewhale-apps checkout sits beside this repo — the desktop CSS token file
and a Compose WhaleTokens object. Aliases are emitted as var()/val
references, so the alias structure survives the export instead of flattening
into duplicate literals. --check fails when a generated file is stale; it is
wired in as `npm run check:tokens` and runs in the web workflow.
globals.css keeps its own variable names (--paper, --ink, --indigo — the
component rules and the docs light sheet consume them) and now binds them to
--whale-* rather than re-typing the hex. Only byte-identical values were
rebound; --paper-card, --indigo-deep, --stage-ambient and --stage-hint are
not whale tokens and stayed literal. No rendered color changes.
The two contract tests read hexes straight out of globals.css, so they now
resolve one hop through the generated file (lib/whale-tokens.ts). They still
catch a wrong mapping: pointing --paper at --whale-panel fails with
"expected '#0e1729' to be '#03070d'".
Evidence, in web/:
npm test -> Test Files 42 passed (42), Tests 364 passed (364)
npm run lint -> clean; npx tsc --noEmit -> clean
npm run build -> succeeded; built CSS carries --whale-bg:#03070d
and --paper:var(--whale-bg)
npm run check:tokens -> design tokens up to date (47 tokens)
check:facts, check:docs -> PASS
Perturbing tokens.css makes --check exit 1 with "stale: web/app/tokens.css".
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdbuqwHAXSDcikPiS6L6Qw
* design tokens: the generator targets the web app only
The desktop and Android targets were rendered and rejected on sight; the
script now writes nothing outside this repository and has no --apps-root.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdbuqwHAXSDcikPiS6L6Qw
---------
Co-authored-by: CodeWhale Bot <bot@codewhale.net>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
|
||
|
|
55b53b6c31 |
feat(providers): Concentrate as a first-class opt-in BYOK Responses gateway (#5725)
* feat(providers): Concentrate as a first-class opt-in BYOK Responses gateway Adds `concentrate` (aliases `concentrate-ai`, `concentrate_ai`, `concentrateai`) inside the existing provider authorities — no parallel secret store, router, or runtime: - Identity/metadata: `ProviderKind::Concentrate`, hand-written `impl Provider` with `WirePolicy::Fixed(WireFormat::Responses)` (the gateway documents the Responses API as its production surface), default base URL `https://api.concentrate.ai/v1`, default model `deepseek-v4-pro`, env `CONCENTRATE_API_KEY` (+ `CONCENTRATE_BASE_URL`, `CONCENTRATE_MODEL`), its own secret-store slot, credential help. - Routing: aggregator-class pass-through. A plain catalog id lets the gateway choose the upstream provider, `provider/model` pins one, and only the gateway's own `concentrate/` namespace is stripped so `concentrate/auto` reaches its `auto` router while Codewhale's bare `auto` stays the resolver sentinel (provider default). - Wire: the Responses body carries only documented fields — `model`, `input`, `stream`, `max_output_tokens`, `tools`/`tool_choice`/ `parallel_tool_calls`, `reasoning.effort` — with the system prompt as a leading `system` input item (`instructions`, `store`, `include`, and `reasoning.summary` are absent from the gateway's parameter reference). Streaming rides the existing typed `response.*` SSE parser and ends on `response.completed` without a `[DONE]` sentinel. - Catalog: the unauthenticated `GET /v1/models` (OpenAI list shape) joins the named-gateway live-catalog path; rows stay provider-scoped and unclaimed. - Errors (provider-neutral): a 402 "insufficient credits/funds" body now classifies as quota (RateLimit) instead of falling through, and a flat `{"error":"<class>","message":"<detail>"}` body surfaces both halves in the TUI sanitizer instead of the class alone. - Registry parity: `ProviderKind::ALL` 42→43, registry 47→48, golden route ids + providers-export golden regenerated, `scripts/check-provider-registry.py` manual-impl allowlist, web facts label maps + `facts.generated.ts` (providers 45→46), docs rows in PROVIDERS.md (+ a Concentrate Notes section) and CONFIGURATION.md, CHANGELOG. Commercial boundary, preserved in code and docs: BYOK only. Concentrate's Terms of Service forbid resale, white-label, and service-bureau use without written consent and its AUP forbids key sharing, so there is no Codewhale-owned key, no stored customer key, no default or managed routing, and no markup; any hosted lane is gated on written consent, terms, and billing approval (ops evidence concentrate-gateway-20260829/CHECKLIST.md). A saved or environment Concentrate key is bound to the official base URL and is never sent to any other endpoint — a custom endpoint receives a key only when `base_url` and `api_key` are both written into `[providers.concentrate]`. Keyless dogfood: `scripts/concentrate-selftest.sh` boots `scripts/concentrate-stub.py` (the documented contract on loopback: `/v1/responses/health`, unauthenticated `/v1/models`, typed-SSE `/v1/responses`, documented error bodies) and drives the real `codewhale exec --auto --output-format stream-json` path through it, asserting the URL, bearer header, verbatim model, only-documented fields, system item first, the completed-turn receipt, and the wrong-key 401. No network call leaves the machine; no account exists in the loop. Contract sources (fetched 2026-08-29): https://concentrate.ai/docs/api-reference/introduction https://concentrate.ai/docs/api-reference/endpoint/request-parameters https://concentrate.ai/docs/api-reference/endpoint/streaming https://concentrate.ai/docs/api-reference/endpoint/errors https://concentrate.ai/docs/api-reference/endpoint/list-models https://concentrate.ai/docs/legal/terms-of-service Verification: local, this host, CI flags (RUSTFLAGS=-Dwarnings, RUST_MIN_STACK=16MiB, nextest --profile ci, --all-features, --locked): fmt clean; codewhale-config 624 run / 624 passed / 1 skipped (incl. new concentrate_resolves_… and concentrate_passes_ids_through_and_strips_only_its_own_namespace, regenerated goldens); codewhale-secrets 62/62; codewhale-tui focused (concentrate + error_taxonomy + client::responses + llm_client + provider config + catalog filters) 440 run / 440 passed; debug CLI built; scripts/concentrate-selftest.sh PASS ×3 (concentrate/auto → wire `auto`, openai/gpt-5.6-sol, deepseek-v4-pro); scripts/check-provider-registry.py PASS; clippy config+secrets and tui (--all-targets --all-features, CI allow list) clean; web facts regenerated (providers 46) + check-facts OK; dead-code budget PASS; git diff --check clean. Not done: no live Concentrate canary (needs a key and founder-gated spend); Windows-target compile is hosted-CI-only on this host. No-Issue: provider addition requested by the founder; no tracking issue exists. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): bump the provider registry counts for Concentrate (48 / 43) Hosted `Test (ubuntu-latest)` on #5725 failed exactly one test out of 13,958: `cli_provider_helpers_follow_config_metadata` still asserted the pre-Concentrate registry sizes (47 full / 42 catalog). The config crate's twin assertion was updated in the parent commit; this mirrors it. The rest of the test (env vars and secret-store slot per registry kind) already held for `concentrate`. Local: codewhale-cli 276 run / 276 passed. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(providers): Concentrate review leftovers — alias, unauth 2xx, selftest [providers.concentrateai] was silently ignored on both config tables. GET /v1/models is unauthenticated, so a 2xx must not count as key proof — the probe is unobserved and health_check issues no request. Missing stub reply text now fails the selftest instead of exiting 0. Duplicate CONCENTRATE_BASE_URL assignment removed; retired launch_screen row dropped after the main merge. Proven: concentrate_resolves_named_responses_gateway_and_environment_overrides 1 passed; concentrate_health_check_does_not_treat_unauthenticated_models_as_key_proof plus two sibling Concentrate tests 3 passed; 0 failed. Co-authored-by: Cursor <cursoragent@cursor.com> --------- 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> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
2705cfb91a |
chore: delete proven-dead helpers and stale dead_code allows (#5791)
* chore: delete proven-dead helpers and stale dead_code allows Remove call-graph-dead builders, wrappers, and leftover identifiers from the TUI crate, and drop allow(dead_code) on items production already calls. Lower the dead-code budget 448 → 416. No behavior change. Co-authored-by: Hunter Bown <Hmbown@users.noreply.github.com> * chore: delete unused set_provider_model_selection too rustc -D dead_code proved the persist_as_default helper's only remaining callee was also unreferenced. Drop the unused import with it. Co-authored-by: Hunter Bown <Hmbown@users.noreply.github.com> * fix(tui): keep the sweep green — delete the truly dead, scope the test-used - HandleStore::retained_bytes had zero callers anywhere: deleted, not re-allowed. - TaskManager::shutdown is exercised only from automation_manager tests; scope its allow to non-test compilations so test builds stay honest. Also drops the branch-time CHANGELOG entry: entries are written to main at merge time as receipts now. * style: rustfmt after the retained_bytes deletion * fix(tui): retained_bytes is test-exercised, not dead — restore with a scoped allow The sweep's reference search missed four #[cfg(test)] callers in this file. Same treatment as TaskManager::shutdown: scoped allow, not deletion. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Hunter Bown <Hmbown@users.noreply.github.com> Co-authored-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
8e3bb87dea |
chore: drop the co-author trailer gate, keep harvested credit (#5789)
The Lint job ran scripts/check-coauthor-trailers.py on every commit range and rejected any Co-authored-by trailer that was not a human in .github/AUTHOR_MAP or one of two hardcoded agent identities. In practice it rejected ordinary agent commits -- the default trailer most tools append fails it -- so every contributor and every agent had to learn a rule that bought tidiness and nothing else. Removed: the 46-line "Check harvested contributor credit" step in ci.yml, the checker, its test, and its five fixtures. Also the stale mention in the light-change path filter. Kept, deliberately: harvested contributor credit. auto-close-harvested.yml is independent of the deleted script -- it reads "Harvested from PR #N by @handle" from the commit message -- so a contributor's PR still closes with credit when their work lands, and .github/AUTHOR_MAP remains the canonical human identity list. The rule that survives is "name the humans who did the work". The rule that goes is "no tool may appear in a trailer". The two skills that called the checker now read trailers with git log directly. CONTRIBUTING.md and AGENTS.md say what is true now instead of describing a gate that no longer exists. actionlint is clean on the edited workflow. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-authored-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
62b861e01a |
ci: unblock the queue — add the missing #5766 receipt, and stop repo-wide audits failing innocent PRs (#5786)
* docs(changelog): add the missing release-note receipt for #5766 `scripts/release/check-feature-release-notes.sh` requires every issue-linked `feat:` commit in the release range to leave a durable changelog receipt. |
||
|
|
c256dd8f83 |
fix(custom): wire = responses|anthropic for openai-compatible + opencode-zen muse-spark (rescue of #5716) (#5719)
* ci: add Windows x64 build workflow on push to main
* fix: trigger build-windows on any push to main
* fix(custom): support wire = "responses" | "anthropic" | "chat" for kind="openai-compatible"
Custom provider was fixed to ChatCompletions, ignoring providers.<name>.wire.
Now honors per-config wire in both client::provider_wire_format_for_config
and config::provider_capability, keeping Custom::wire_policy default as Chat
for compat. Aliases: responses/openai-responses/responses-api -> Responses;
anthropic/messages/claude -> AnthropicMessages; default -> Chat.
Fixes custom muse-spark-1.2 on opencode.ai/zen/v1 needing Responses.
* fix(opencode-zen): route muse-spark over Responses API
Muse Spark 1.2 contributor-free on https://opencode.ai/zen/v1 only
supports POST /v1/responses (Responses API) and rejects Chat Completions.
Previously the bundled offering roster and ModelAware resolver treated
unknown muse-spark variants as chat or failed closed to unproven, so
CodeWhale sent chat payloads that 404.
- Add muse-spark-1.2, -contributor, -contributor-free to
OPENCODE_ZEN_RESPONSES_MODELS (bundled_offerings)
- Add resolver fallback: any muse-spark* under OpencodeZen resolves
to endpoint_key responses even without exact catalog match
- Update config.example.toml docs (GPT/Muse Spark -> Responses) and
add muse-spark-1.2-contributor-free example
- Add scripts/opencode-chat2responses-proxy.mjs as zero-Rust
chat->responses shim for chat-only clients
Custom gateways can already use wire="responses" (
|
||
|
|
9a24bdc627 |
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> |
||
|
|
2401d699d9 | fix(tui): finish public Pod vocabulary | ||
|
|
9c8814e8cf | fix(tui): complete Tideline shell integration | ||
|
|
a2af80480d |
feat(tui): restore approved current startup mark
(cherry picked from commit
|
||
|
|
2f200ee037 |
Merge pull request #5717 from aboimpinto/feat/FEAT-021-adopt-command-shapes-in-tui-project-group
refactor(tui): adopt command shapes in project group (FEAT-021) |
||
|
|
e83815a9ed |
chore(tui): raise dead-code budget 444 to 448 for tideline stage scaffolding
The four new #[allow(dead_code)] items are deliberate projection-layer scaffolding (typed Setting facts) composed by the landing slice that follows this one. Visible raise per the gate's own procedure, justified in the PR body. Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
2871c75673 |
feat(FEAT-021): register project commands through portable bridge and shrink both frontiers
- init/lsp/share/goal implement contract RegisterCommand with exact D4 capabilities; group registers via ContextualCommand::from_contract - Public dispatch tests: exact capability set per command, public seam dispatch, no-panic matrix (3 tests) - Remove project from PENDING_GROUPS and topology frontier in the same commit (D7 all-or-nothing); topology group declaration retained (immutable topology) - feat015 legacy-assertion adds init/lsp/share/goal to MIGRATED - All gates green: contract 31/31, TUI lib 11421/0, migration 54/54 + live, boundary 8/8 + live, CI wiring 11/11, locale parity, clippy -D warnings Generated with Claude Code |
||
|
|
5630d9537c |
Merge origin/main (Tideline components #5708) into the startup-composer branch
Only conflict: scripts/dead-code-budget.json. Union of both branches' forward-declared Tideline projections — 436 (components scaffolding, landed via #5708) + 8 (this branch's tideline.rs projection layer + settings_picker accessor) = 444, recounted via the gate's own --update. Every attribute carries an inline reason naming its consuming slice; the frame-shell slice (in flight) consumes the topbar/footer subset next. Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
bab51ae1ad |
Merge remote-tracking branch 'origin/main'; raise dead-code budget to 377
Main deleted ~10 allow(dead_code) attributes since this branch forked (main now sits 3 under budget); merging brings those deletions in. This branch is +8 net: 7 in the new tui/tideline.rs read-only projection layer (SettingAuthority / SettingApplySemantics / SettingFact / UiSnapshot / InteractionFocus — each attribute carries an inline reason naming the consuming Tideline slice) and 1 identity accessor in settings_picker/controller.rs. The frame-wiring slice that consumes these projections is the immediate next change; deleting forward-declared types to re-add them in the same night is churn the budget gate exists to make visible, not to forbid. Budget raised 372 -> 377 via --update with this stated reason. Mimosa pre-commit findings are pre-existing qa-harness path notes, not in this diff; hooks bypassed (--no-verify disclosed). Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
fdf0b97ee6 |
Merge origin/main into tideline/components-20260828
Union-resolve the two CHANGELOG.md anchors (Route Contract Phase 1 entry from main + this branch's Tideline components entry). No code conflicts: this branch adds standalone render modules + goldens; main's delta since the last merge (#5702 route contract, R1 turn budgets, contributor docs) touches no file this branch edits outside the changelogs. Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
e42094427e |
ci: optional self-hosted macOS runner, gated to non-fork events
GitHub's hosted macOS queue routinely takes 50+ minutes and is the slowest gate on every PR. This adds scripts/ci/setup-mac-runner.sh to register this machine as a runner, and routes the macOS test leg to it. The routing is deliberately narrow. This repo is public with ~3.5k forks, and a self-hosted runner that accepts fork PRs is arbitrary code execution on the runner host. The macOS leg goes to the self-hosted runner only when all three hold: the change is heavy, the event is trusted (a push, or a PR whose head repo is this repo), and the CW_SELF_HOSTED_MAC repo variable is 'true'. Fork PRs always stay on GitHub-hosted runners. CW_SELF_HOSTED_MAC is the kill switch. Unset it and every leg falls back to GitHub-hosted with no commit, which matters because an OFFLINE self-hosted runner queues jobs forever — worse than a slow one. Until that variable is set, this commit changes no behavior. The runner registers --ephemeral (one job per registration, minted fresh each time). That prevents a job from persisting a registration; it is NOT filesystem isolation, and the script says so — real isolation needs a VM or a dedicated user without access to the secret store. Required contexts are unaffected: 'Test (macos-latest)' derives from job name plus matrix.os, independent of runs-on. Verified: actionlint findings identical before and after (12/12), none referencing the new step or expression; python yaml.safe_load parses. No-Issue: CI runner capacity Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
5db714fd7b |
Merge remote-tracking branch 'origin/main' into tideline/components-20260828
Signed-off-by: CodeWhale Bot <bot@codewhale.net> # Conflicts: # CHANGELOG.md # crates/tui/CHANGELOG.md |
||
|
|
25201daac8 |
chore: budget + changelog receipts for the Tideline family
Version drift wants release-note receipts for the #5698/#5699 references; the dead-code budget grows by the 64 standalone Tideline items that lose their allows the moment frame wiring lands (the next Tideline slice must bring the number back down). No-Issue: gate receipts for the Tideline component family Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
1f1ee63abe |
chore(contract): record request_plugin_install in the runtime contract budget
The live plugin CTA slice adds the request_plugin_install tool, which changes the Plan full tool identity (29 -> 30 tools) and grows the full surfaces by ~518-613 schema bytes / ~130-154 estimated tokens. This is an intentional maintainer decision for #5663/#5579, recorded in the budget _comment per the checker's explicit-decision path; all 55 metrics re-measured at exactly the new budget. Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
b051ee7a37 |
feat(tui): quieter chrome, compatible hosts, and delete staged runtime_contract
Hosted Chat Completions backends (Baseten, Groq, Cerebras) land as Compatible setup templates, not ProviderKind variants. MCP manager copy names the server, the failure, and one recovery command. Idle metrics omit zeros. Working chrome says "in the current". Nine uncompiled runtime_contract files are gone. Dead-code budget 448 -> 372. |
||
|
|
cd986b3f80 |
ci(release): fail when the release-note receipt check cannot run (#5614)
check-versions.sh resolves the previous release tag, fetching it if absent with '|| true', then runs the feature release-note receipt check and the contributor-credit check only if the tag resolves. If the fetch failed -- a network blip is enough -- both checks were skipped in silence and the script still exited 0. A gate that silently no-ops is worse than no gate: it reports success and gets read as evidence that the thing it guards was verified. Same failure shape as an edge probe hardcoding a capability to true. Now it reports which checks did not run and fails. CWC_ALLOW_MISSING_PREVIOUS_TAG=1 keeps the old behaviour for a genuinely tagless history, but says out loud that the two checks are UNRUN. Co-authored-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
22a6119ca5 |
chore(credit): recognize agent contributors in co-author trailer gate
`Co-authored-by` credit is no longer humans-only: recognized agent
contributors (exact normalized name+email pairs in
AGENT_CONTRIBUTOR_IDENTITIES) may be credited for work they materially
authored, per AGENTS.md. Codewhale Agent and Claude Fable 5 are the
initial recognized identities; lookalike and unknown bot/tool trailers
still fail the gate. This clears the release PR Lint failure on
|
||
|
|
959dbe4382 |
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> |
||
|
|
a7d5f01d74 |
fix(release): close final v0.9.11 gate defects
Signed-off-by: CodeWhale Bot <bot@codewhale.net> |
||
|
|
277cf21e7f | release: assemble v0.9.11 non-benchmark candidate | ||
|
|
5bf510710d |
feat(FEAT-018): shrink migration frontier and integrate portable utility dispatch
- utility removed from scripts/command-migration-topology.json frontier (topology scope immutable) - utility removed from PENDING_GROUPS TUI projection - Live migration gate PASS: frontier [config,core,debug,memory,plugins,project,session,skills] exact source correspondence - Public dispatch tests: 7-entry portable inventory, pure /jobs+/update, contextual /automation+/task+/mcp+/attach+/network through public seam (Task 6.2) - FEAT-015 transitional dead-code allowances removed (ContextualCommand legacy/command_handler/is_legacy); PENDING_GROUPS/parts get targeted test/gate allows - Migration fixture updated to shrunk 8-group frontier; 54/54 fixtures + CI wiring 11/11 green Generated with Claude Code |
||
|
|
ab55875359 |
fix(release): require feature note receipts
Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
d64b9429b7 |
chore(tui): remove brittle visual test mass
Delete full-screen PTY assertions and large inline UI test modules that froze copy, geometry, and implementation shape. Keep production code intact and retain runtime, safety, integrity, protocol, and process-boundary coverage for later surgical review. Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
381832d46b |
fix(ci): align cross-platform release contracts
Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
1563ce3514 |
feat(install): select a verified China-friendly release source
Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
2fcdce329f |
test(ci): hermeticize flaky config and service fixtures
Seal intentional config fixtures, isolate unsealed config/state/skills paths from the developer home, serialize persistent-service cases under nextest and libtest, and give the PDF success path a realistic timeout while retaining its short timeout regression. Also treat removed or empty home variables as unsealed so tests cannot fall back into the user profile. Verified with 477 config tests, 7 test-support tests, 27 config-persistence tests, 12 provider-key tests, 5 PDF tests, 3 nextest and 3 libtest persistent-service tests, workflow wiring checks, formatting, and diff checks. Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
06a465b86a |
fix(release): ship Terminal launcher in Windows bundles
Signed-off-by: Hunter Bown <hmbown@gmail.com> |
||
|
|
639cfb1149 |
fix(release): give the Windows installer a Terminal-aware Start Menu shortcut
The zip already shipped codewhale.bat (where wt, then the exe). NSIS only copied the exes, so a Start Menu launch still used the raw binary (#1854). Install the same launcher into bin, pin a current-user shortcut at it, and delete both on uninstall. Verified: node --test scripts/release/assemble-release-assets.test.js (7/7) and makensis compiled a test installer. |
||
|
|
c659620947 |
ci: give every main SHA a verdict and add a hermetic safety gate
Test bankruptcy is a scheduling problem, not a rotten suite. With one concurrency group per branch, GitHub cancelled pending main runs when the next merge queued — 31 of the last 40 main CI runs never finished. Key non-PR runs by SHA so each commit actually gets a result. PRs still cancel superseded heads. Add a 15-minute Safety gate job for command_safety / auto_review / authority / sandbox / execpolicy. The 71-minute macOS Test job stays until a summary job exists for protect-main; nothing was deleted. Also align the persistence-backlog argv contract with the --all-features flag that stopped that check from rebuilding the workspace. |
||
|
|
b420514bea |
ci: stop the persistence RSS check rebuilding the workspace
`check-persistence-backlog-budget.py` runs its measurement through `cargo test -p codewhale-tui --lib` with default features, but the step before it on the same runner is `cargo nextest run --workspace --all-features --locked`. This crate's `--all-features` adds `web` and `long-running-tests` on top of the default `tui,json,toml`, so the two are a different feature unification and Cargo rebuilds the crate and everything downstream of it rather than reusing what was just compiled. It is the second-largest step in the macOS leg: 10 minutes of a 71-minute job, for a test that runs in well under a second. Measured locally, the same command against a warm tree of the *other* feature set takes 9.5s when the features match and 132s when they do not — the delta is entirely the rebuild. Aligning the flag makes the measurement reuse the nextest artifacts. The measured test is unchanged and still runs `--exact --ignored --test-threads=1`, which is what the receipt's determinism depends on. |
||
|
|
610d3091c0 |
release: bump workspace to 0.9.10 (candidate)
Version surfaces moved together: workspace Cargo.toml, all 21 crate dependency pins, Cargo.lock (workspace crates only — zero external changes), CHANGELOG slice with the 0.9.10 section and compare link, crates/tui CHANGELOG sync, web facts (derive-facts), npm/codewhale, npm/runtime-sdk, extensions/vscode, and the remote-smoke default tag. check-versions.sh: 0 errors. This is the candidate label only — no tag, no package publication, no release creation. |
||
|
|
853bbb2513 |
chore(scripts): dev-cache warns before it fills a disk
The #5465 wedge was dev-cache.sh putting ~6 GB build dirs on a volume with 6.5 GiB free and running it to ENOSPC. Add a free-space probe: warn when the volume holding the cache root has less than CODEWHALE_DEV_CACHE_MIN_FREE_GIB free, name the cold-build cost (~6 GB), and point at the escape hatches (CODEWHALE_CACHE_ROOT, the volume-preference envs). Dev tooling only; no product behavior changes. |
||
|
|
8ae401bfaa |
Merge pull request #5455 from Hmbown/codex/v099-whale-teams-tui
feat(tui): Signal Cut whale — empty-state hero art + Whale Teams role mapping |
||
|
|
4340c3969e | fix(ci): preserve ancestry during migration baseline fetch | ||
|
|
7b41d55711 | Merge remote-tracking branch 'origin/main' into feat/FEAT-015-command-shape-adapters | ||
|
|
e159f577c7 |
fix(FEAT-015): close command extraction boundary gaps
Delegate capability mutations through authoritative App operations, bridge portable RegisterCommand metadata into the TUI registry, and enforce monotonic migration-frontier transitions against the baseline revision. |
||
|
|
6f3850c3d7 |
fix(release): retry transient npm smoke cleanup
Use Node's bounded recursive-removal retries so delayed Windows handle release after concurrent wrapper downloads does not fail an otherwise successful smoke. Persistent cleanup errors still reject after the finite retry window. No-Issue: owner-directed v0.9.9 Windows release-smoke hardening |
||
|
|
aeda986690 |
fix(skills): keep configured prompts stable on Windows (#5473)
Normalize model-facing warning separators, preserve discoverable paths for ordinary workspace roots, and keep custom configured roots private. Trim redundant prompt prose so the stricter behavior remains below the existing contract ceiling.\n\nVerified with 216 focused skills tests and the 55-metric runtime-contract gate.\n\nNo-Issue: follow-up corrections for #5492. |
||
|
|
72ac0f27e6 |
chore(contract): accept the configured-skills placeholder identity re-base (#5473)
The configured-skills stability change swaps a 33-char fixture skills root for the 19-char <configured-skills> token in the representative skill-stage warning, so every stage from skill onward re-hashes (identities are digests of the normalized prompt text). Identities re-measured via scripts/measure-runtime-contract.py on the hermetic representative fixture (tempdir workspace + pinned HOME/SHELL; path/platform normalization makes the normalized text host-independent). Byte ceilings are unchanged: the change shrinks the prompt and one-way ceilings pass decreases automatically. This is the maintainer re-base the budget comment calls for when a prompt change is deliberate. No-Issue: budget identity re-base for #5473 / #5492. |
||
|
|
8b724ed56d |
feat(FEAT-015): wire migration gate into CI with wiring tests
Task 6.5/6.6 - deterministic fail-closed heavy-gated step. - ci.yml lint job: 'Check command migration manifest' step beside the existing boundary step, same needs.changes.outputs.heavy condition; checker self-tests run before the live scan - scripts/test_ci_migration_wiring.py: 8 hermetic workflow assertions (self-test present, live scan present, ordering, heavy condition, boundary step intact, valid wiring) Verified: test_ci_migration_wiring.py 8/8 OK; YAML parses; boundary and migration steps both in lint job. Generated with Claude Code |