Skip to content

Shoreline: the TUI redesign, rebased onto main without the hitchhikers - #6258

Merged
Hmbown merged 5 commits into
mainfrom
feat/shoreline-redesign-rebased-20260915
Sep 16, 2026
Merged

Hmbown merged 5 commits into
mainfrom
feat/shoreline-redesign-rebased-20260915

Conversation

@Hmbown

@Hmbown Hmbown commented Sep 16, 2026

Copy link
Copy Markdown
Owner

The redesign half of #6222, cherry-picked onto current main (200 commits newer than that branch's base). Shoreline becomes the fresh-install default.

No-Issue: rescues the redesign commits from #6222, which stays open for its remaining work; see below for why this is a separate branch rather than a force-push.

Why #6222 looked unmergeable, and wasn't

tui-redesign reports 34 merge conflicts against main. Every single one is in crates/tui/plugins/computer-use/, and none of them is the redesign.

That branch carries ten commits, and its own description says five "are not the redesign at all" — they were stranded on a local main that was 129 behind and had never been pushed. The conflicts come entirely from those passengers:

Commit What Verdict
4517d294c0 Computer Use 0.2.2 sync all 34 conflicts; also overlaps open PR #6134
31146342b9 web /plugins page conflicts separately
4a85cb7877 0.9.13 + GPUI direction docs conflicts on web/lib/facts.generated.ts, a generated file
48e03f74bb runtime-api settings schema clean, unrelated
37b95e52f1 config Float setting kind clean, unrelated

Drop those five and the redesign applies almost cleanly. The headline commit — feat(palette): add Shoreline, and open on it — cherry-picks onto today's main with no conflict at all.

What is here

9d3f6f2a5  feat(palette): add Shoreline, the product-client palette, and open on it
a08d315d9  brand: retire the old traced marks, sync the canonical vector family
542867c88  test(tui): reconcile the theme surfaces with the Shoreline default
8839b6178  test(tui): re-bless the settings stage and config panel goldens
687e27c6f  docs(design): record the TUI redesign, and fix what it makes untrue

Shoreline is the fresh-install default, which is the part worth stating plainly since the commit subject buries it:

-            theme: "underwater".to_string(),
+            theme: "shoreline".to_string(),

crates/config/src/settings_schema.rs and the setting's doc comment move with it. underwater remains available, it is simply no longer what a new install opens on.

The one real conflict, and how it was resolved

web/app/opengraph-image.tsx. Both sides were right about different things:

  • main had moved the brand-SVG reads inside the handler, with a comment recording why: a top-level read made every ISR regeneration on Cloudflare Workers fail with a 500 and serve its build snapshot forever, because the Workers Node shim throws on fs.readFile.
  • the branch restored the top-level readFile(...).then(...) pattern — the exact shape main had just fixed — while renaming mark.svgmark-reversed.svg for the canonical vector family.

Resolved by keeping main's lazy accessor and taking the branch's filename. Taking either side wholesale would have lost a real fix or a real rename.

Evidence

cargo check -p codewhale-tui -p codewhale-palette --all-features --locked   clean
cargo fmt --all -- --check                                                 clean
cargo clippy --workspace --all-targets --all-features --locked
  (CI's exact allow list)                                                  clean
test result: ok. 71 passed; 0 failed    (theme, goldens, settings_stage,
                                         config_panel; --test-threads=1)

Both re-blessed goldens pass on the new base — dock_tabs_match_80x24_golden and work_stage_matches_goldens_at_blocker_sizes — which is the check that would have caught a bad rebase.

One untidiness, stated rather than hidden: the rebase surfaced a rustfmt difference in themes.rs (main's toolchain collapses a match arm the old base wrapped as a block). The fix landed in the docs commit rather than the palette commit it belongs to. Behaviour-neutral; I left it rather than doing history surgery on someone else's commits.

Not a force-push, deliberately

#6222 is someone else's branch and their draft. Force-pushing it would silently drop five commits they may still want — the runtime-api settings-schema route and the Float setting kind are both clean and useful, and the Computer Use sync overlaps an open PR that should decide its own fate.

So this is additive. If the owner of #6222 prefers, close it in favour of this and re-land the two clean passengers separately; #6222's own "what is left" list is unaffected either way.

🤖 Generated with Claude Code

CodeWhale Bot added 5 commits September 15, 2026 17:08
The terminal and the GPUI desktop window now cite one palette. Shoreline is
the warm charcoal ground (`#211F23`), one raised plate (`#2B282E`), one
restrained blue for action and selection (`#90B9FF`), Signal Gold for the
human lane, and the whale's ivory ink — the same slots
`codehwhale-gpui/src/workspace/mod.rs` installs into `Theme`.

It ships as two presets (`shoreline`, `shoreline-light`), and it is the
fresh-install default in `Settings::default`, the settings schema, the
theme picker's reset value, and the malformed-selector fallback. The
`underwater` theme keeps the painted water column, the ombre and the
ambient life; it is a choice now, not the ground the product opens on.

Shoreline is listed in `adapt::theme_remap_active`, so every direct
terminal constant lands on the preset's slots instead of a navy-tuned
value. Its mode badges keep the shipped mode ramp: a mode colour must
differ from `accent_primary`, because `theme_semantic_foreground_role`
resolves modes first and would otherwise read the action lane as
`ModeAgent`.

Evidence:
- `cargo test -p codewhale-palette --lib --locked` — 81 passed, 0 failed.
  That includes `every_selectable_theme_clears_the_text_floor`,
  `every_selectable_theme_keeps_action_and_working_roles_distinct_on_ansi16`,
  `every_selectable_theme_keeps_mode_badges_distinct` and
  `every_selectable_theme_keeps_permission_lanes_distinct` over the two new
  presets.
- `cargo build -p codewhale-cli --locked` — ok.
- Real PTY capture of `target/debug/codewhale` on a fresh `CODEWHALE_HOME`:
  field `#211F23`, chrome `#1A181C`, plates `#2B282E`, accent `#90B9FF`,
  muted `#B0A7B2`, gold `#F6C453`. The braille whalemark is unchanged.
- Not yet run: `codewhale-tui` tests. Expected fallout is the
  `theme_picker_*` goldens (two new rows) and tests asserting the old
  default string; reconciled in the next commit.

(cherry picked from commit c1e89cb)
The repo's brand/mark.svg + wordmark traces were an earlier lower-fidelity
trace of the C-curl whale (black currentColor instead of the navy family),
and crates/tui/src/runtime_web/codewhale-192.png was still the retired
diving-whale tile served by the embedded runtime web client.

- brand/ and web/public/brand/ now carry byte-identical copies of the
  canonical family (codewhale-apps/packages/brand/svg/), adding the missing
  mark-mono and mark-reversed variants.
- extensions/vscode/media/codewhale.svg uses the family mono mark.
- runtime_web/codewhale-192.png is the canonical 192 tile (same bytes as
  codewhale-apps apps/web/public/icons/codewhale-192.png).
- opengraph-image.tsx reads mark-reversed.svg (the family's white-on-navy
  variant) instead of string-replacing currentColor, which the family
  mark.svg does not contain; wordmark aspect corrected to the family's
  1024x160 viewBox.
- Deleted brand/mark-navy.svg (duplicate of the family navy mark),
  brand/wordmark0901.png + wordmarkinverted.png (only consumer was the
  retired generator; founder rasters preserved in
  codewhale-apps/packages/brand/source/), and scripts/brand/trace-brand.py
  (regenerated the retired trace; not referenced by CI). The founder brand
  sheet brand/codewhalemarkfinal.png stays as scripts/brand/braille-mark.py's
  input.
- PRODUCT.md and the public-auth-routes provenance comment updated to name
  the canonical family home.

Checks: npx tsc --noEmit (web) exit 0. Asset swap + comments; runtime_web
route tests reference the icon path, not bytes.

(cherry picked from commit 116a57b)
Two new presets mean the theme list is 17 rows where it was 15, and the
fresh-install selector is `shoreline` where it was `underwater`. This is the
expectation fallout, not a behaviour change: the picker's reset value, the
digit-jump and wrap tests, the row-count assertions in both theme-list
suites, and the four `theme_picker_*` / `edit_theme_*` golden buffers.

The digit tests keep their intent. `3` now jumps to Shoreline (it still
follows System and Terminal); the persistence test uses `9` -> Grayscale
because Catppuccin Mocha moved past the 1-9 jump range. The theme-list test
now anchors its boxed selection on index 6 (Blue Stage) since Shoreline and
Shoreline Light sit ahead of Underwater.

Evidence:
- `CODEWHALE_BLESS_GOLDENS=1 ./scripts/dev-test.sh tui theme` —
  56 tests run: 56 passed, 0 failed, 12424 skipped. The four goldens were
  deleted first because `assert_matches_golden` only blesses a *missing*
  file, never a drifted one.
- Running the same filter as a bare `cargo test` (no hermetic HOME) failed
  two tests — `arrow_navigation_wraps_at_picker_edges` and
  `theme_picker_uses_shared_settings_controller` — because they read the
  real user theme directory and saw a `custom:` row. Both pass under the
  sanctioned wrapper; that flake is pre-existing, not introduced here, and
  is named in the handoff rather than papered over.
- `crates/tui/src/tui/views/mod.rs` carried one line of another agent's
  in-flight work (`ModalKind::PetHabitat`). My three hunks in that file were
  staged apart from it; that peer has since committed them into
  `116a57b81` on this branch. The `PetHabitat` line is still unstaged and
  untouched.

(cherry picked from commit dd1420e)
The settings stage and the config panel both render the theme list, so both
carry the two new rows. The stage anchors its boxed selection on index 6
(Blue Stage) rather than 4, which is now Underwater.

Evidence:
- `CODEWHALE_BLESS_GOLDENS=1 ./scripts/dev-test.sh tui views::` —
  323 tests run: 322 passed, 1 failed. The one failure,
  `tui::views::tests::every_settings_row_reaches_a_store`
  ("auto_compact_threshold_percent shows a row that settings.toml will not
  take"), is pre-existing on `main` at the branch point: the schema row and
  that exact assertion are both present in `4a85cb7877`, and
  `Settings::set` has never accepted that key. It is not this change.
- `./scripts/dev-test.sh tui-integration palette_audit` — 3/3 passed.
- `python3 scripts/export-design-tokens.py --check` — up to date, 64 tokens.
  The new `SHORELINE_*` constants are deliberately outside the exporter's
  `(WHALE|LIGHT)_*` pattern, so the web's `tokens.css` is untouched.

(cherry picked from commit fe84f80)
`docs/design/TUI_REDESIGN.md` is the anchor for this branch: the Shoreline
palette table and the three mechanisms that make the re-ink hold, the
seven-project market survey and its convergent rules, the two things the
survey says we already get right, and the two deliberately not done (the
composer stays full width; the ocean is not deleted).

It also names the remaining work with the seams already located: the
one-status-row merge, and the interaction re-homing that has to land in the
same commit or the slice ships a regression (the metrics line owns the
`/model` and context-inspector pointer targets).

`DESIGN.md` carried two defects this change exposed:

- The palette owner was written as `crates/tui/src/palette/tokens.rs`. That
  path has not existed for some time; the owner is `crates/palette/src/tokens.rs`.
- Anti-slop rule 2 stated that "the ocean column's field is the TUI's own
  chrome → bg descent". That was true of the TUI's default and is not any
  more — the default is Shoreline. The rule now says what is true: the
  column is the site's descent, and the navy water column is the terminal's
  selectable `underwater` theme.

Also records, without fixing, the two failures that pre-date this branch on
`main` at `4a85cb7877`, and the two picker tests that are order-dependent
under a bare `cargo test` because they read the real user theme directory.

Checks: `cargo test -p codewhale-palette --lib --locked` 81/81;
`./scripts/dev-test.sh tui` 12461 run, 12459 passed, 2 failed (both
pre-existing); `./scripts/dev-test.sh tui-integration palette_audit` 3/3;
`python3 scripts/export-design-tokens.py --check` up to date.

(cherry picked from commit cabdc0c)
Copilot AI lite review requested due to automatic review settings September 16, 2026 00:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 4m 4s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context (read PR description, diff, changed files)
  • Understand the request (code review per repo custom instructions)
  • Review correctness bugs
  • Review provider/model/route safety implications (N/A — palette/theme/brand only, no model routing code touched)
  • Review reuse/simplification/dead code
  • Review test coverage
  • Review security implications
  • Post final review summary

Summary

This is a clean, well-executed rebase of the Shoreline redesign. The ThemeId/SELECTABLE_THEMES/normalize_theme_name additions are exhaustive and consistent across every match arm, the contrast audit (theme_contrast_violations) is data-driven off SELECTABLE_THEMES so it automatically covers the two new presets without any test changes needed, and the digit-jump / golden test updates correctly account for the new theme-list indices (verified SELECTABLE_THEMES order against the '9' → Grayscale and '3' → Shoreline test changes — both are correct). No provider/model/route logic is touched here.

I found one real regression and a few small doc/dead-code loose ends from the rebase.


1. extensions/vscode/media/codewhale.svg — lost documented behavior, not just a comment

This file previously carried both an explanatory comment and fill="currentColor", specifically because VS Code masks viewsContainers.activitybar icons (confirmed wired up in extensions/vscode/package.json:151,159) but the comment called out that currentColor was chosen so the icon "also adapts if ever rendered directly" (docs, GitHub preview, etc. — anywhere outside VS Code's masking pipeline). The PR replaces the whole file with the raw mark-mono.svg trace, which drops the comment entirely and hardcodes fill="#000000". Inside VS Code the mask likely still overrides the color, so this may be invisible there, but it silently regresses the "renders correctly outside VS Code" property the deleted comment exists to protect, and throws away the reasoning (including the codewhale-ops/CURRENT_DECISIONS.md reference) for no stated reason.

Fix this →

2. web/app/opengraph-image.tsx:19-20 — dead .replace() call

readFile(join(process.cwd(), "public/brand/mark-reversed.svg")),
...
return [mark.toString().replace("currentColor", "#ffffff"), ...

mark-reversed.svg (new in this PR) already ships a hardcoded fill="#FFFFFF", not currentColor. The .replace() is now a no-op — harmless today only because the source file happens to already be white, but it no longer does what the code implies and will silently do nothing if the source SVG's color ever changes.

Fix this →

3. PRODUCT.md:91 — stale path this same PR fixed elsewhere

DESIGN.md corrects crates/tui/src/palette/tokens.rscrates/palette/src/tokens.rs in two places in this diff, but PRODUCT.md:91 still has the old, wrong path ("the colour tokens are owned by crates/tui/src/palette/tokens.rs").

Fix this →

4. Dangling references to the deleted scripts/brand/trace-brand.py

This PR deletes scripts/brand/trace-brand.py (and PRODUCT.md correctly documents its retirement), but two other files outside the diff still describe it as current: scripts/brand/whale-points.py's module docstring ("Source of truth is the same one trace-brand.py uses...") and web/app/manifest.ts's header comment ("rasterised from app/icon.svg by scripts/brand/trace-brand.py"). Neither is functionally broken (both are just comments), but both now describe a script that no longer exists.

Fix this →

Nit: "codehwhale-gpui" (transposed letters) appears in both crates/palette/src/tokens.rs's new Shoreline comment and docs/design/TUI_REDESIGN.md — should be codewhale-gpui. Cosmetic only.

Not reviewed / out of scope

Per the task's offline-boundary and evidence policy, I didn't run cargo test/cargo clippy myself in this pass — the PR description already reports cargo check, cargo fmt --all -- --check, cargo clippy (CI's allow list), and 71 passed; 0 failed for the relevant theme/golden/settings suites, which is consistent with what the diff shows (exhaustive match arms, re-blessed goldens, updated index-dependent tests).

@Hmbown
Hmbown merged commit 3cb49bb into main Sep 16, 2026
44 of 46 checks passed
@Hmbown
Hmbown deleted the feat/shoreline-redesign-rebased-20260915 branch September 16, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants