Skip to content

Commit 515eef8

Browse files
author
CodeWhale Bot
committed
fix(tui): restore the launch mark and finish community candidate notes
Restore the canonical raster-derived mark in a responsive header while retaining full-width session rows and reachable launch controls. Pin the first-party catalog to marketplace d8640b1 after its three-OS CI passed, including the matching Computer Use fix. Credit AdityaVG13 and record branch/compaction fixes in the candidate changelog and website ledger. Validation: mark/launch/marketplace focused tests 51 passed, 0 failed; fresh npm test 551 passed, 0 failed; npm run check:web passed; fmt and version consistency checks passed (48 feature-note references). The candidate remains 0.9.14; no release or publication.
1 parent 4ab08d4 commit 515eef8

8 files changed

Lines changed: 153 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ tag, packages, checksums and release assets exist.
1414

1515
### Contributors
1616

17+
- **[@AdityaVG13](https://github.com/AdityaVG13)** — fixed composer wrapping, tab/caret placement, pasted and editor-returned draft history, painted-column transcript copying, explicit terminal foregrounds, and headless user-input tool availability ([#6363](https://github.com/Hmbown/Codewhale/pull/6363), [#6365](https://github.com/Hmbown/Codewhale/pull/6365)).
1718
- **[@aboimpinto](https://github.com/aboimpinto)** — moved the TUI session-export slice onto shared command contracts (FEAT-025): a session-export contract facet with one shared sanitizer, `/export` routed through the facet, pinned with baseline-captured goldens and gates ([#6096](https://github.com/Hmbown/Codewhale/pull/6096)).
1819
- **[@BX166](https://github.com/BX166)** — contributed the AICraft provider template and its documentation ([#6171](https://github.com/Hmbown/Codewhale/pull/6171)). It was closed unmerged, but it is what surfaced the decision to stop special-casing named OpenAI-compatible hosts ([#6289](https://github.com/Hmbown/Codewhale/issues/6289)).
1920
- **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — reported the session-retention defects behind archive-past-the-cap and empty-session cap occupancy ([#6136](https://github.com/Hmbown/Codewhale/issues/6136), [#6137](https://github.com/Hmbown/Codewhale/issues/6137)), the resume-failure design behind durable transcript errors ([#6138](https://github.com/Hmbown/Codewhale/issues/6138)), and the gaps behind the opt-in approval timeout ([#6101](https://github.com/Hmbown/Codewhale/issues/6101)), `codewhale exec --hooks` ([#6099](https://github.com/Hmbown/Codewhale/issues/6099)), Markdown drag-copy ([#6156](https://github.com/Hmbown/Codewhale/issues/6156)), and the browsable, current-aware session picker ([#6014](https://github.com/Hmbown/Codewhale/issues/6014)); the goal token-budget hard stop ([#6013](https://github.com/Hmbown/Codewhale/issues/6013)) and the fleet no-progress guard shared with child workers ([#6015](https://github.com/Hmbown/Codewhale/issues/6015)) landed as first slices of two larger proposals, and the runtime-store session refusal ([#6207](https://github.com/Hmbown/Codewhale/issues/6207)).
@@ -216,6 +217,16 @@ tag, packages, checksums and release assets exist.
216217

217218
### Fixed
218219

220+
- Branch navigation preserves sibling histories, stable entry IDs and timestamps
221+
through autosave, resume and forks, and synchronizes the selected branch into
222+
the live engine. Thanks to @7jrxt42BxFZo4iAnN4CX for the report (#6367).
223+
- Compaction now writes local diagnostic records for completed passes and
224+
automatic refusals. `codewhale metrics` reports them with summarizer token
225+
usage; text-mode exec retains its session after attempting compaction.
226+
Historical artifacts are not backfilled. Thanks to @7jrxt42BxFZo4iAnN4CX
227+
for identifying the missing producer (#6368).
228+
- The opening workbench retains the canonical Codewhale mark in a responsive
229+
header while keeping recent-session titles full-width and actions clickable.
219230
- `serve --acp` no longer ignores the approval posture. The ACP adapter
220231
hardcoded `ApprovalMode::Suggest`, so `--yolo` (and any configured
221232
`approval_policy`) never reached admission: every mutating tool parked

crates/tui/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ tag, packages, checksums and release assets exist.
1414

1515
### Contributors
1616

17+
- **[@AdityaVG13](https://github.com/AdityaVG13)** — fixed composer wrapping, tab/caret placement, pasted and editor-returned draft history, painted-column transcript copying, explicit terminal foregrounds, and headless user-input tool availability ([#6363](https://github.com/Hmbown/Codewhale/pull/6363), [#6365](https://github.com/Hmbown/Codewhale/pull/6365)).
1718
- **[@aboimpinto](https://github.com/aboimpinto)** — moved the TUI session-export slice onto shared command contracts (FEAT-025): a session-export contract facet with one shared sanitizer, `/export` routed through the facet, pinned with baseline-captured goldens and gates ([#6096](https://github.com/Hmbown/Codewhale/pull/6096)).
1819
- **[@BX166](https://github.com/BX166)** — contributed the AICraft provider template and its documentation ([#6171](https://github.com/Hmbown/Codewhale/pull/6171)). It was closed unmerged, but it is what surfaced the decision to stop special-casing named OpenAI-compatible hosts ([#6289](https://github.com/Hmbown/Codewhale/issues/6289)).
1920
- **[@7jrxt42BxFZo4iAnN4CX](https://github.com/7jrxt42BxFZo4iAnN4CX)** — reported the session-retention defects behind archive-past-the-cap and empty-session cap occupancy ([#6136](https://github.com/Hmbown/Codewhale/issues/6136), [#6137](https://github.com/Hmbown/Codewhale/issues/6137)), the resume-failure design behind durable transcript errors ([#6138](https://github.com/Hmbown/Codewhale/issues/6138)), and the gaps behind the opt-in approval timeout ([#6101](https://github.com/Hmbown/Codewhale/issues/6101)), `codewhale exec --hooks` ([#6099](https://github.com/Hmbown/Codewhale/issues/6099)), Markdown drag-copy ([#6156](https://github.com/Hmbown/Codewhale/issues/6156)), and the browsable, current-aware session picker ([#6014](https://github.com/Hmbown/Codewhale/issues/6014)); the goal token-budget hard stop ([#6013](https://github.com/Hmbown/Codewhale/issues/6013)) and the fleet no-progress guard shared with child workers ([#6015](https://github.com/Hmbown/Codewhale/issues/6015)) landed as first slices of two larger proposals, and the runtime-store session refusal ([#6207](https://github.com/Hmbown/Codewhale/issues/6207)).
@@ -216,6 +217,16 @@ tag, packages, checksums and release assets exist.
216217

217218
### Fixed
218219

220+
- Branch navigation preserves sibling histories, stable entry IDs and timestamps
221+
through autosave, resume and forks, and synchronizes the selected branch into
222+
the live engine. Thanks to @7jrxt42BxFZo4iAnN4CX for the report (#6367).
223+
- Compaction now writes local diagnostic records for completed passes and
224+
automatic refusals. `codewhale metrics` reports them with summarizer token
225+
usage; text-mode exec retains its session after attempting compaction.
226+
Historical artifacts are not backfilled. Thanks to @7jrxt42BxFZo4iAnN4CX
227+
for identifying the missing producer (#6368).
228+
- The opening workbench retains the canonical Codewhale mark in a responsive
229+
header while keeping recent-session titles full-width and actions clickable.
219230
- `serve --acp` no longer ignores the approval posture. The ACP adapter
220231
hardcoded `ApprovalMode::Suggest`, so `--yolo` (and any configured
221232
`approval_policy`) never reached admission: every mutating tool parked

crates/tui/assets/first-party-marketplace.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"repository": "https://github.com/Hmbown/codewhale-plugin-marketplace",
3-
"revision": "a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc",
3+
"revision": "d8640b17f27542e7122c76368724196f92a0af61",
44
"catalog": {
55
"name": "codewhale",
66
"description": "First-party Codewhale extensions: the plugins and skills Codewhale ships, maintained in the open so anyone can propose a change.",
77
"version": "2",
88
"plugins": [
99
{
1010
"name": "computer-use",
11-
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc#path=plugins/computer-use",
11+
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/d8640b17f27542e7122c76368724196f92a0af61#path=plugins/computer-use",
1212
"version": "0.11.2",
1313
"description": "Control apps with Codewhale. macOS beta; Windows and Linux backends are experimental and source-only.",
1414
"homepage": "https://codewhale.net/computer-use",
@@ -21,7 +21,7 @@
2121
},
2222
{
2323
"name": "whalesong",
24-
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc#path=plugins/whalesong",
24+
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/d8640b17f27542e7122c76368724196f92a0af61#path=plugins/whalesong",
2525
"version": "0.2.0",
2626
"description": "Review agent traces and failures, compare runs, and turn session timing into audio. Requires the local Whalesong platform.",
2727
"homepage": "https://github.com/Hmbown/codewhale-plugin-marketplace",
@@ -30,7 +30,7 @@
3030
},
3131
{
3232
"name": "whalewiki",
33-
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc#path=plugins/whalewiki",
33+
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/d8640b17f27542e7122c76368724196f92a0af61#path=plugins/whalewiki",
3434
"version": "0.2.0",
3535
"description": "Understand a repo, find where to change it, and see which docs depend on a file. Source citations, freshness checks and a searchable offline reader.",
3636
"homepage": "https://github.com/Hmbown/codewhale-plugin-marketplace",
@@ -39,7 +39,7 @@
3939
},
4040
{
4141
"name": "cloudflare-docs",
42-
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc#path=plugins/cloudflare-docs",
42+
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/d8640b17f27542e7122c76368724196f92a0af61#path=plugins/cloudflare-docs",
4343
"version": "0.1.0",
4444
"description": "Search current Cloudflare documentation through its official remote MCP. No account or credential required.",
4545
"homepage": "https://github.com/Hmbown/codewhale-plugin-marketplace",
@@ -48,7 +48,7 @@
4848
},
4949
{
5050
"name": "codewhale-skills",
51-
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/a9c2302c96b03ebf64a1562ea4ccdaea32c3c5cc#path=skills",
51+
"source": "https://codeload.github.com/Hmbown/codewhale-plugin-marketplace/tar.gz/d8640b17f27542e7122c76368724196f92a0af61#path=skills",
5252
"version": "1.1.0",
5353
"description": "47 workflows for coding, research, documents, email, calendar, travel, shopping and local audio. Account and tool setup is separate; see the skill directory.",
5454
"homepage": "https://github.com/Hmbown/codewhale-plugin-marketplace",

crates/tui/src/tui/mark.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,75 @@
1-
//! Terminal color transitions and graphics capability diagnostics.
2-
//! Launch identity is now a compact wordmark; no image is transmitted.
1+
//! The Codewhale mark, derived from the canonical founder raster by
2+
//! `scripts/brand/braille-mark.py`, and terminal color/capability helpers.
3+
//! The launch header paints the mark as terminal cells; no image is transmitted.
34
45
use std::sync::OnceLock;
56

67
use ratatui::style::Color;
78

9+
/// Rungs of the mark's scale ladder, each generated at its own box.
10+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11+
pub enum MarkSize {
12+
/// Box 22×6, ink 14×6 — the launch screen's hero mark. Generated from the
13+
/// same founder raster as the smaller rungs, at a size where the whale
14+
/// reads as a whale.
15+
Large,
16+
/// Box 11×3, ink 7×3 — the launch header's mark.
17+
Small,
18+
/// Box 8×2, ink 5×2 — for stages too narrow for the header lines beside
19+
/// the small rung.
20+
Tiny,
21+
}
22+
23+
// generated by scripts/brand/braille-mark.py from brand/codewhalemarkfinal.png
24+
// (founder hero whale 504x453px, threshold 0.3, aspect preserved,
25+
// edge columns trimmed, eye carved)
26+
27+
// LARGE: box 22x6 -> ink 14x6
28+
const LARGE_ROWS: [&str; 6] = [
29+
" ⣀⣴⣶⣾⣶⣆ ",
30+
"⢀⣼⣿⠛⠉⠉⠙⠻⠟⠃ ",
31+
"⢸⣿⡇ ⢀⣀⣤⣤⣤⣤⡀",
32+
"⢸⣿⣷⣤⣤⣶⣿⣿⣿⡿⠟⠉⣹⠁",
33+
"⠈⢻⣿⣿⣿⣿⣿⣷⠟ ⢀⡴⠁ ",
34+
" ⠈⠉⠽⠿⣿⠥⠤⠒⠉ ",
35+
];
36+
37+
// SMALL: box 11x3 -> ink 7x3
38+
const SMALL_ROWS: [&str; 3] = [
39+
"⢠⡶⠛⠧⠄ ", //
40+
"⣿⣄⣠⣤⣶⠶⠆",
41+
"⠘⠻⣿⣗⠡⠊ ",
42+
];
43+
44+
// TINY: box 8x2 -> ink 5x2
45+
const TINY_ROWS: [&str; 2] = [
46+
"⢠⡞⠛⢂⣀", //
47+
"⠘⠿⣿⠍⠉",
48+
];
49+
50+
impl MarkSize {
51+
/// Cell footprint as `(cols, rows)` — the ink's, not the design box's.
52+
#[must_use]
53+
pub const fn cells(self) -> (u16, u16) {
54+
match self {
55+
Self::Large => (14, 6),
56+
Self::Small => (7, 3),
57+
Self::Tiny => (5, 2),
58+
}
59+
}
60+
61+
/// The braille rows for this rung. Blank cells are spaces so the
62+
/// renderer leaves the field behind them untouched.
63+
#[must_use]
64+
pub const fn rows(self) -> &'static [&'static str] {
65+
match self {
66+
Self::Large => &LARGE_ROWS,
67+
Self::Small => &SMALL_ROWS,
68+
Self::Tiny => &TINY_ROWS,
69+
}
70+
}
71+
}
72+
873
/// Blend `from` toward `to` (0.0 → `from`, 1.0 → `to`). At 0 the mark is
974
/// exactly the field colour, so it rises out of the water rather than over it.
1075
#[must_use]

crates/tui/src/tui/underwater.rs

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,13 +1591,41 @@ pub fn launch_empty_state(app: &App, area: Rect) -> LaunchEmptyState {
15911591
// Built before the fit ladder runs: how many rows the block wants is a
15921592
// fact about this workspace's servers, not about the pane.
15931593
let mcp_block = mcp_launch_lines(app, text_width);
1594-
let fit = launch_fit(
1595-
height,
1594+
// Brand occupies the header only; recent titles retain the whole reading lane.
1595+
// Scale the canonical raster derivative before sacrificing any controls.
1596+
use crate::tui::mark::MarkSize;
1597+
let mut mark = if crate::tui::color_compat::ascii_safe_enabled() {
1598+
None
1599+
} else if height >= 14 && text_width >= 40 {
1600+
Some(MarkSize::Large)
1601+
} else if height >= 8 && text_width >= 26 {
1602+
Some(MarkSize::Small)
1603+
} else if height >= 4 && text_width >= 19 {
1604+
Some(MarkSize::Tiny)
1605+
} else {
1606+
None
1607+
};
1608+
let mark_extra = mark.map_or(0, |size| usize::from(size.cells().1).saturating_sub(2));
1609+
let mut fit = launch_fit(
1610+
height.saturating_sub(mark_extra),
15961611
entries.len(),
15971612
has_more,
15981613
app.launch.claude_code_detected,
15991614
mcp_block.lines.len(),
16001615
);
1616+
if mark.is_some() && !(fit.brand && fit.context) {
1617+
// At the absolute height floor the wordmark yields to the actions too.
1618+
mark = None;
1619+
fit = launch_fit(
1620+
height,
1621+
entries.len(),
1622+
has_more,
1623+
app.launch.claude_code_detected,
1624+
mcp_block.lines.len(),
1625+
);
1626+
}
1627+
let header_width =
1628+
text_width.saturating_sub(mark.map_or(0, |size| usize::from(size.cells().0) + 2));
16011629
let spacious = fit.blanks == LAUNCH_SEPARATORS;
16021630
let visible: Vec<LaunchRecentEntry> = entries.into_iter().take(fit.shown).collect();
16031631
let card_rows = launch_card_rows(locale, &visible, fit.see_all);
@@ -1608,15 +1636,15 @@ pub fn launch_empty_state(app: &App, area: Rect) -> LaunchEmptyState {
16081636
let brand = "codewhale";
16091637
let version = format!("v{}", env!("CODEWHALE_BUILD_VERSION"));
16101638
let mut spans = vec![Span::styled(
1611-
semantic_truncate(brand, text_width),
1639+
semantic_truncate(brand, header_width),
16121640
Style::default().fg(theme.accent_primary).bold(),
16131641
)];
1614-
if text_width >= text_display_width(brand) + 1 + text_display_width(&version) {
1642+
if header_width >= text_display_width(brand) + 1 + text_display_width(&version) {
16151643
spans.push(Span::styled(
16161644
format!(
16171645
"{}{version}",
16181646
" ".repeat(
1619-
text_width - text_display_width(brand) - text_display_width(&version)
1647+
header_width - text_display_width(brand) - text_display_width(&version)
16201648
)
16211649
),
16221650
Style::default().fg(theme.text_muted),
@@ -1631,17 +1659,30 @@ pub fn launch_empty_state(app: &App, area: Rect) -> LaunchEmptyState {
16311659
app.workspace_context.as_deref(),
16321660
);
16331661
let mut spans = vec![Span::styled(
1634-
semantic_truncate(&workspace, text_width),
1662+
semantic_truncate(&workspace, header_width),
16351663
Style::default().fg(theme.text_soft),
16361664
)];
16371665
if let Some(branch) = identity.branch {
16381666
let detail = format!(" · {branch}");
1639-
if text_display_width(&workspace) + text_display_width(&detail) <= text_width {
1667+
if text_display_width(&workspace) + text_display_width(&detail) <= header_width {
16401668
spans.push(Span::styled(detail, Style::default().fg(theme.text_muted)));
16411669
}
16421670
}
16431671
text.push(Some(Line::from(spans)));
16441672
}
1673+
if let Some(mark) = mark {
1674+
text.resize_with(usize::from(mark.cells().1), || None);
1675+
for (row, dots) in mark.rows().iter().enumerate() {
1676+
let mut spans = vec![
1677+
Span::styled(*dots, Style::default().fg(theme.accent_primary)),
1678+
Span::raw(" "),
1679+
];
1680+
if let Some(line) = text[row].take() {
1681+
spans.extend(line.spans);
1682+
}
1683+
text[row] = Some(Line::from(spans));
1684+
}
1685+
}
16451686
// The migration notice, while there is still a question to answer. It
16461687
// retires for good once `/import-claude` has been run.
16471688
if fit.notice {
@@ -2094,7 +2135,7 @@ mod launch_card_tests {
20942135
with_mcp(app_with_recent(&["one", "two", "three", "four", "five"], 9)),
20952136
] {
20962137
for width in [0u16, 1, 2, 3, 8, 12, 20, 31, 32, 40, 44, 64, 80, 120, 200] {
2097-
for height in 0u16..=10 {
2138+
for height in 0u16..=30 {
20982139
let state = launch_empty_state(&app, Rect::new(0, 0, width, height));
20992140
assert!(
21002141
state.lines.len() <= usize::from(height),

docs/CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ notes, and relevant issue/PR comments.
3232

3333
**Merged or adapted contributions**
3434

35+
- **[AdityaVG13](https://github.com/AdityaVG13)** — composer wrapping, pasted/editor draft history, painted-column transcript copying, tab/caret placement, explicit terminal foregrounds, and headless user-input tool availability ([#6363](https://github.com/Hmbown/Codewhale/pull/6363), [#6365](https://github.com/Hmbown/Codewhale/pull/6365)); both PRs merged with their original ancestry.
3536
- **[aboimpinto](https://github.com/aboimpinto)** — moved the TUI session-export slice onto shared command contracts (FEAT-025): a session-export contract facet with one shared sanitizer, `/export` routed through the facet, pinned with baseline-captured goldens and gates ([#6096](https://github.com/Hmbown/Codewhale/pull/6096)).
3637

3738
**Reports and reproductions**

0 commit comments

Comments
 (0)