Skip to content

feat(tui): integrate the 0.9.12 Tideline shell - #5774

Merged
Hmbown merged 29 commits into
mainfrom
integrate/0912-tideline-cli-20260831
Aug 31, 2026
Merged

feat(tui): integrate the 0.9.12 Tideline shell#5774
Hmbown merged 29 commits into
mainfrom
integrate/0912-tideline-cli-20260831

Conversation

@Hmbown

@Hmbown Hmbown commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Outcome

Integrates the 0.9.12 Tideline TUI stack on one main-based branch and closes the composed-shell, picker, localization, and pending-work regressions found by human and automated review.

  • keeps one topbar, one composer, one transcript, and one merged footer
  • retains all four startup routes at the 40-column floor and keeps compact labels localized
  • routes pointer submit through the same real dispatch path as keyboard submit
  • reserves the visible [↑] submit control across text wrapping, cursor placement, frame bookkeeping, and mouse mapping, including an 80x8 / 74-character regression
  • removes the passive duplicate active-session rail and the test-only live-work helper with misleading production intent
  • keeps ? help discoverable beside non-urgent footer receipts when the row can hold both
  • adds persistent type-to-search picker behavior: lowercase a, p, and r search; Shift+A changes catalog view; Shift+P pins; Ctrl+R refreshes
  • removes the approximate block-glyph brand substitute; terminal surfaces use the Codewhale wordmark/direct copy because the canonical raster mark has no approved glyph projection
  • adds a real offline PTY acceptance matrix for 40x12, 60x16, 80x24, 100x32, and 140x40
  • makes public TUI locale values consistently say Pod while retaining Fleet only as internal compatibility keys

This main-based integration supersedes the overlapping TUI stack in #5753, #5758, #5760, #5762, #5763, #5765, #5770, and #5773. It preserves their commits and authorship while correcting the rejected mark and duplicate passive rail introduced in the later composition.

Local evidence at 358c081c1a008e9d7ca4693254077c5dab53fd19

  • cargo fmt --all -- --check
  • git diff --check
  • scripts/dev-cargo.sh test -p codewhale-tui --lib --locked
    • 11,632 passed; 0 failed; 13 ignored
  • scripts/dev-cargo.sh check -p codewhale-tui -p codewhale-cli --all-features --locked
  • sh scripts/check-tui-product-vocabulary.sh
  • python3 scripts/check-tui-locale-parity.py
    • all 15 shipped packs: 1903/1903; PASS

Earlier exact-branch PTY evidence still applies to the retained harness:

  • scripts/dev-cargo.sh test -p codewhale-tui --test cucumber active_composer_pointer_submit_queues_without_provider --features long-running-tests --locked -- --nocapture
    • 1 passed; 0 failed; all five terminal sizes exercised

Closes #5768

These are source and local-test receipts only. Hosted CI, packaged artifacts, merge, and release remain separate gates.


Devin Review

CodeWhale Bot and others added 26 commits August 30, 2026 17:32
(cherry picked from commit ca18b92)
Hosted Lint on #5770 failed clippy::collapsible_if in the compact
startup-composer fallback. Same cells; no behavior change.

Refs #5768
Signed-off-by: Hunter Bown <hmbown@gmail.com>
The clippy collapsible_if repair was still two lines; rustfmt --check
wants the let-chain on one line.

Refs #5768
Signed-off-by: Hunter Bown <hmbown@gmail.com>
Startup already paints `[↑]` from tideline_composer_geometry. The
active-session ComposerWidget now restores that same three-cell
affordance after input and routes pointer clicks through
decide_composer_submit plus the existing Enter dispatch branches.

Compact/quiet composers still shed the control. Empty clicks do not
move the caret or consume the draft.

Refs #5771
Signed-off-by: Hunter Bown <hmbown@gmail.com>
The blocker-size startup goldens still pinned the retired flat
composer strip, so startup_matches_goldens_at_blocker_sizes failed on
ubuntu and windows CI. The 40x10 floor golden is unchanged: the
composer sheds at that size by design.

Refs #5768
Signed-off-by: Hunter Bown <hmbown@gmail.com>
active_composer_submit_rect created a click target at widths 6-11 and
heights >= 3, but the painter only draws the enclosure and its [↑]
affordance when enclosed_composer_panel_fits holds (width >= 12). The
hitbox now uses that same predicate, so no invisible submit target can
exist where the panel sheds. Also repair the empty-composer quiet-row
test for this branch's own design: the quiet content row now hosts the
shared send affordance on exactly its recorded hitbox cells.

Refs #5771
Signed-off-by: Hunter Bown <hmbown@gmail.com>
…inter

dispatch_session_composer_submit mirrored the keyboard Enter branches by
hand and had already drifted (edit_in_progress undo ordering). Extract
submit_decided_composer_input — slash-menu selection, draft consumption,
and the memory/shell/command/message branches — used by both the Enter
arm and the mouse send dispatcher. Caller-specific gates stay put:
transcript-only shortcuts and forced-submit chords remain keyboard-only;
SendQueuedNow and the paste-burst probe remain in the dispatcher. No
event behavior changes.

Refs #5771
Signed-off-by: Hunter Bown <hmbown@gmail.com>
…20260830' into feat/tideline-active-composer-send-20260830
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

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


Claude is reviewing this PR

Todo list

  • Gather context (diff vs origin/main, repo instructions)
  • Understand the request (code review of PR feat(tui): integrate the 0.9.12 Tideline shell #5774)
  • Review correctness/panics/error-handling (event loop, mouse, composer routing)
  • Review session_boot/topbar/phase_strip startup changes
  • Review widgets/frame/underwater/tideline rendering
  • Review provider/model/route safety invariant
  • Review settings/localization/tests/docs/scripts
  • Review reuse/simplification
  • Review test coverage
  • Review security
  • Post final review

Running 4 parallel sub-reviews across the diff (65 files, +2627/-1245). Will consolidate findings shortly.

@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

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


Claude is reviewing this PR

Todo list

  • Gather context (diff vs origin/main, repo instructions)
  • Understand the request (code review of PR feat(tui): integrate the 0.9.12 Tideline shell #5774)
  • Review correctness/panics/error-handling (event loop, mouse, composer routing)
  • Review session_boot/topbar/phase_strip startup changes
  • Review widgets/frame/underwater/tideline rendering
  • Review provider/model/route safety invariant
  • Review settings/localization/tests/docs/scripts
  • Review reuse/simplification
  • Review test coverage
  • Review security
  • Post final review

Running 4 parallel sub-reviews across the diff (67 files, +2901/-1506). Will consolidate findings shortly.

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 5 potential issues.

Devin Review

Comment on lines +1831 to +1838
if has_panel {
crate::tui::composer_chrome::render_tideline_composer_submit(
area,
buf,
&self.app.ui_theme,
true,
crate::tui::color_compat::ascii_safe_enabled(),
);

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.

🟡 Send control hides typed text

Long multiline drafts reach the bottom-right cells, where render_tideline_composer_submit overwrites three visible characters. Hidden text still submits unchanged.

Prompt for agents
The active composer paints the [↑] affordance after rendering input, but its content geometry and wrapping still use the entire inner width. On the submit row, input can therefore occupy the same three cells and becomes visually hidden while remaining in the submitted draft. Update ComposerWidget geometry, wrapping, cursor placement, and mouse mapping to reserve the submit cells on that row, or place the control in space that input never owns. Add coverage proving a draft ending on the submit row remains fully visible and cursor-addressable.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +3430 to +3435
let option_label = if layout.strip.width < 56 {
match index {
0 => "worktree",
1 => "chat",
_ => option.label,
}

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.

🟡 Localized startup shows English labels

Below 56 columns, option_label replaces localized names with English “worktree” and “chat”. Every translated startup displays mixed-language options.

Prompt for agents
The narrow startup option strip introduces renderer-local English labels for the worktree and chat actions. This violates crates/tui/AGENTS.md and crates/tui/locales/AGENTS.md and makes every non-English locale display mixed-language startup copy below 56 columns. Add typed MessageId entries for compact option labels, translate them in every complete locale pack, and pass the localized values into the startup projection instead of branching on English literals in underwater.rs.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread crates/tui/src/localization.rs Outdated
Comment on lines +1409 to +1412
// Active-session Tideline rail group labels.
TidelineRuns,
TidelineWhales,
TidelineRunningCount,

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.

🔍 Unused Tideline locale entries

The three new Tideline* messages have no production consumer. They appear to preserve copy for the passive rail removed by this change.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +3581 to 3596
fn retired_launch_screen_setting_is_accepted_and_dropped_on_save() {
let tmp = tempfile::tempdir().expect("tempdir");
let path = tmp.path().join("settings.toml");
std::fs::write(&path, "launch_screen = false\n").expect("legacy settings");

let settings = Settings::load_persisted_from_candidates(Some(path.clone()), None, None)
.expect("legacy setting must remain readable");
settings
.save_to_path(&path)
.expect("save normalized settings");

let saved = std::fs::read_to_string(&path).expect("read normalized settings");
assert!(
!settings.launch_screen,
"returning users enter a session directly"
!saved.contains("launch_screen"),
"the retired setting must not be written back: {saved}"
);

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.

📝 Info: Legacy setting migration remains readable

Existing launch_screen values remain readable. Unknown settings fields are accepted, and the next save omits this retired key.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +108 to +124
/// Semantic severity for the compact boot activity notice.
///
/// The text carries no color names or inferred state. Its consumer maps this
/// closed state into the Tideline palette, so a plugin warning cannot inherit
/// an unrelated MCP color merely because both use the same footer slot.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionBootActivityLevel {
Active,
Attention,
Failure,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionBootActivityChip {
pub text: String,
pub level: SessionBootActivityLevel,
}

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.

📝 Info: Boot severity stays typed

Compact boot notices retain typed severity. Failed services and invalid plugins remain distinct from review-only plugin states and active connections.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@codewhale-agent codewhale-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codewhale review

Integrates the 0.9.12 Tideline TUI shell, retires the launch_screen setting, renames Fleet to Pod across locale packs, adds a typed pending-work projection, and refactors shared composer geometry. The PR is broad and well-evidenced with locale parity, golden buffer, and PTY matrix receipts.

Findings

  • [WARNING] live_work_from_app is test-only but documented for production status surfaces (crates/tui/src/tui/background_indicator.rs)
    The new whole-session projection live_work_from_app is annotated #[cfg(test)], yet its doc comment says to use it for a whole-session status surface that must account for live shells. Any non-test caller such as a Tideline rail rendering the new TidelineRuns/TidelineWhales messages would fail to compile, or would be forced to use pending_work_from_app, which deliberately excludes live shells. Clarify whether this helper is intended as test-only or should be available in normal builds.
  • [WARNING] Shared composer shell always renders the [↑] submit target (crates/tui/src/tui/composer_chrome.rs)
    render_tideline_composer_shell unconditionally calls render_tideline_composer_submit, so any caller that uses this shared shell for a compact/quiet composer will paint the [↑] send control. The PR description states compact/quiet composers still omit the control, but this new shared code path has no compact or show_submit parameter. Confirm all compact/quiet paths bypass this shell or add an explicit flag.
  • [INFO] Fleet-to-Pod rename leaves legacy Fleet key names (crates/tui/locales/en.json)
    User-facing values were updated from Fleet to Pod across all locale packs, but corresponding message keys remain ConfigSectionFleet, ConfigLabelFleetSpawnDepth, FleetDraftTitle, HomeOperateModeFleetTip, etc. This is not a runtime bug, but it can confuse future maintenance and makes the product-vocabulary policy harder to enforce. Consider renaming the keys with migration or documenting the legacy key names.

Assessment

The integration is broad and backed by a lot of evidence, including locale parity and PTY matrix receipts. The visible changes are mostly coherent; the main risks are the test-only whole-session projection and the unconditional shared composer submit affordance, both of which need either code/tests or clearer confirmation before merge.


Advisory review by Codewhale (codewhale review --pr 5774 --post, head 2401d699d9a70d64326cb60792e4315556d2f55c). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

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


Claude finished reviewing this PR

Todo list

  • Gather context (diff vs origin/main, repo instructions)
  • Understand the request (code review of PR feat(tui): integrate the 0.9.12 Tideline shell #5774)
  • Review correctness/panics/error-handling (event loop, mouse, composer routing)
  • Review session_boot/topbar/phase_strip startup changes
  • Review widgets/frame/underwater/tideline rendering
  • Review provider/model/route safety invariant
  • Review settings/localization/tests/docs/scripts
  • Review reuse/simplification
  • Review test coverage
  • Review security
  • Post final review

Summary

Broad, well-evidenced integration of the 0.9.12 Tideline shell. The keyboard/mouse composer-submit unification in event_loop.rs (submit_decided_composer_input shared tail) is a real simplification — I traced the old inline Enter handler against the new extracted function and the gates (SendQueuedNow, slash-menu selection, #-memory quick-add, bang-shell, /edit undo) are preserved exactly, and mouse-only gating (composer_enter_would_submit) is correctly scoped to the mouse dispatcher only. The session_boot.rs rewrite (multi-row receipt → typed SessionBootActivityLevel/SessionBootActivityChip) is internally consistent — I confirmed boot_activity_ink in phase_strip.rs maps all three variants and no caller still references the removed is_hidden/receipt_lines/activity_chip. The launch_screen setting retirement is safe: Settings has no deny_unknown_fields, so an old launch_screen = true/false in settings.toml deserializes fine and is silently dropped on next save (verified by the new test). No provider/model-prefix routing inference found anywhere in this diff (v0.8.65 EPIC #2608 invariant not at risk here — the diff's only "provider" hits are locale copy).

Findings

1. Confirmed: the shared [↑] submit affordance can overlap live composer text (correctness)
crates/tui/src/tui/widgets/mod.rscomposer_content_geometry (line ~1211) and composer_height's content_width computation never subtract the 3-cell submit width; only the 2-cell side rails and prompt gutter are reserved. cursor_pos (line ~1853) derives cursor_x/cursor_y from that same unreserved text_width(), and ComposerWidget::render (line ~1831) repaints render_tideline_composer_submit after the input Paragraph, unconditionally, whenever has_panel is true. So once a multi-line draft fills the composer's last content row up to the right rail, the trailing 1-3 visible characters (and potentially the terminal cursor itself) get overwritten by [↑] — the draft text is unaffected (nothing is lost on submit), but it becomes invisible while typing, and a click on those cells always resolves to submit (mouse_ui.rs checks active_composer_submit_rect before mouse_pos_to_char_index), never to caret placement in the user's own text. This matches Devin's inline finding on this file (comment on crates/tui/src/tui/widgets/mod.rs:1838) — I independently verified it against the geometry/cursor code and it holds. The existing test enclosed_composer_send_hitbox_matches_painted_cells only asserts the icon paints where expected; it doesn't assert the text never reaches under it. Fix: reserve the submit's 3 columns in composer_content_geometry/composer_height's width budget (mirroring how panel_side_inset already reserves the rails) rather than painting over content after the fact.
Fix this →

2. Confirmed: dead scaffolding left behind by the passive-rail removal (reuse/simplification)

  • crates/tui/src/tui/background_indicator.rs: live_work_from_app is #[cfg(test)]/pub(crate), but the doc comment on pending_work_from_app tells future readers to "use live_work_from_app for a whole-session status surface" as if it's a real production API — it compiles out of release builds entirely.
  • crates/tui/src/localization.rs:1410-1412: MessageId::TidelineRuns, TidelineWhales, TidelineRunningCount have zero tr() call sites (grep confirms only their own declaration/ALL_MESSAGE_IDS entry). Both are remnants of the "active-session Tideline rail" this PR's description says it removed; keeping them makes it look like a rail-consuming caller still exists. Either wire a real caller or delete both alongside the removal.

3. New renderer-local English literals in the startup option strip (locale policy)
crates/tui/src/tui/underwater.rs:3430-3435 — below 56 columns, index 0/1 render hardcoded "worktree"/"chat" instead of option.label. Note TidelineOption::approved_set() (line ~3085, unchanged by this diff) already stores &'static str literals like "New worktree"/"Chat only" rather than tr(locale, MessageId::...), so the option strip was already not localized at any width — this isn't a wide→narrow regression the way it might first look. But crates/tui/AGENTS.md is explicit: "User-visible prose uses tr(locale, MessageId::...)" and "Do not add renderer-local language branches." This PR adds a second, narrower-width hardcoded-English branch on top of the pre-existing gap rather than fixing it, compounding the debt the policy exists to prevent.

4. Info: render_tideline_composer_shell always paints [↑] (no compact flag) — appears mitigated
Flagged by the automated Codewhale review as a WARNING. I checked: render_tideline_composer_shell has exactly one call site (underwater.rs:1237), gated by panel_area: Option<Rect> which is only Some when startup.composer.enclosed (i.e. app.composer_border) is true and the dock meets the minimum size — so the quiet/compact opt-out never reaches this function today. Worth a debug_assert! or a compact parameter on the shared shell itself if a second caller is ever added, since nothing currently stops one from doing so silently.

Nits

  • crates/tui/locales/en.json (and all packs): the Fleet→Pod copy rename keeps ConfigSectionFleet, FleetDraftTitle, HomeOperateModeFleetTip-style message-id names — not a bug, just a maintenance trap already called out by the Codewhale bot review; agreed it's low priority.

@codewhale-agent codewhale-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codewhale review

PR #5774 integrates the Tideline TUI shell on a main-based branch, corrects composed-shell regressions, rebrands Fleet to Pod across locales, removes the retired launch_screen setting, and refactors composer geometry and pending-work projection. Local test receipts indicate the crate compiles and tests pass.

Findings

  • [WARNING] TidelineComposerHitboxes.border doc comment contradicts new behavior (crates/tui/src/tui/composer_chrome.rs:459)
    The doc comment for TidelineComposerHitboxes still says the struct captures the [↑] submit rect and the top-border ring (click = focus the composer), but the implementation now sets border to geometry.focus, which is the full composer Rect. This can mislead future maintainers about the click target semantics.
  • [INFO] live_work_from_app is test-only while documented as a production helper (crates/tui/src/tui/background_indicator.rs)
    The new live_work_from_app function is annotated #[cfg(test)] and therefore unavailable in production code. Its doc comment says it should be used for a whole-session status surface that must account for live shells. If such a surface is planned for production, this helper cannot be used as described.

Suggestions

  • crates/tui/src/tui/composer_chrome.rs:459 — Update the doc comment to match the new behavior: the border field now covers the full composer focus area, not just the top border ring. This prevents future confusion about click target semantics.

Assessment

The PR is well-scoped and includes substantial test coverage. The main concerns are a stale doc comment and a test-only helper whose production intent is unclear. No blocking correctness issues were identified in the reviewed diff.


Advisory review by Codewhale (codewhale review --pr 5774 --post, head b6883982e2a887d15c5fcffd3b1f57686f043abe). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.

/// rect and the top-border ring (click = focus the composer).
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)] // translation scaffolding: wired by the landing slice
pub struct TidelineComposerHitboxes {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[WARNING] TidelineComposerHitboxes.border doc comment contradicts new behavior

The doc comment for TidelineComposerHitboxes still says the struct captures the [↑] submit rect and the top-border ring (click = focus the composer), but the implementation now sets border to geometry.focus, which is the full composer Rect. This can mislead future maintainers about the click target semantics.

/// rect and the top-border ring (click = focus the composer).
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)] // translation scaffolding: wired by the landing slice
pub struct TidelineComposerHitboxes {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Update the doc comment to match the new behavior: the border field now covers the full composer focus area, not just the top border ring. This prevents future confusion about click target semantics.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

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


Claude's review of the latest push (358c081)

Todo list

  • Gather context (diff vs origin/main, repo instructions, prior review threads)
  • Check whether latest commit ("close Tideline review gaps") addresses prior findings
  • Review correctness/panics/error-handling in the fix commit
  • Review provider/model/route safety invariant
  • Review reuse/simplification
  • Review test coverage
  • Review security
  • Post final review

Summary

This push (358c081, "close Tideline review gaps") is a targeted follow-up that resolves every substantive finding from the prior three review rounds (Devin, Codewhale bot, and my own earlier pass). I diffed 358c081 in isolation and traced each fix against the original finding:

Verified fixes

  1. Composer submit overlap (Devin + my earlier finding, widgets/mod.rs) — Fixed correctly. New composer_inner_area() derives the text plane from tideline_composer_geometry(area).content, so wrapping, composer_height, cursor placement (cursor_pos), and mouse_ui.rs's handle_composer_mouse all now share one geometry that reserves the [↑] control's 3 cells plus a 1-cell breathing gap. Added test enclosed_composer_reserves_submit_cells_for_a_74_character_draft renders a 74-char draft and asserts the wrapped text, cursor position, and painted [↑] glyph never collide — this is real coverage of the exact scenario Devin flagged, not just a geometry-math assertion.

  2. Renderer-local English literals in the narrow startup strip (Devin's 2nd finding, underwater.rs) — Fixed correctly. "worktree"/"chat" literals are replaced with tr(startup.locale, MessageId::LaunchMenuWorktreeCompact/ChatCompact), TidelineStartup now carries a locale field wired from app.ui_locale, and all 15 locale packs got real translations (verified PickerActionPin/LaunchMenuWorktreeCompact/LaunchMenuChatCompact present in all 15 files). New test startup_option_strip_uses_localized_compact_labels_when_narrow renders at zh-Hans and asserts the compact labels are 工作树/聊天, not English — good regression coverage.

  3. Dead Tideline* locale entries (Devin's 3rd finding + my finding, localization.rs) — Removed cleanly (TidelineRuns/TidelineWhales/TidelineRunningCount deleted from the enum, ALL_MESSAGE_IDS, and all 15 locale JSON files). Confirmed zero remaining references anywhere in the tree.

  4. live_work_from_app test-only-but-documented-as-production (Codewhale bot, both rounds) — Resolved by deleting the function entirely rather than papering over the doc comment; collect_pending_work lost its now-unused include_shells parameter. Confirmed no remaining callers. This is the right call per repo guidance (delete unused code rather than leave a compatibility shim).

  5. Stale TidelineComposerHitboxes.border doc comment (Codewhale bot, round 2) — Fixed: comment now correctly says "the full rounded shell" instead of "the top-border ring," matching the geometry.focus-based implementation. New assertion in composer_hitboxes_match_painted_cells pins hitboxes.border == area at every tested size.

Additional change in this commit (not tied to a prior finding)

model_picker.rs — plain p/a/r no longer trigger pin/cycle-view/refresh when the query is empty; those now require Shift+P/Shift+A/Ctrl+R. This fixes a real (if previously unflagged) bug: a user typing a model/provider search that happens to start with p, a, or r (e.g. anthropic, azure, phi, route) would have the first keystroke silently consumed as a command instead of starting the search. Covered by two new tests (lowercase_picker_action_letters_begin_a_model_search, shifted_picker_actions_cycle_views_pin_and_refresh_explicitly) plus a footer-hint render test. Minor tradeoff: a search intentionally starting with a capital P/A now triggers pin/cycle instead of typing that character — acceptable since search is the common case and matching is presumably case-insensitive either way.

Other checks

  • No provider/model-prefix routing inference in this diff (v0.8.65 EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant not implicated — same conclusion as the earlier round).
  • No new dead code, no unwrap/expect added on fallible paths in the reviewed hunks.
  • I was not able to execute cargo check/cargo test/cargo clippy in this sandboxed run (tool permissions block Bash cargo invocations here), so this review is source-level only. The PR body's own local receipts (cargo test -p codewhale-tui --lib, clippy, locale-parity script) and the in-progress hosted CI runs (CI, Codewhale PR Review) remain the actual gates for compilation/runtime correctness — CI was still in_progress as of this review.

No blocking issues found in this push. All previously flagged findings have real fixes with matching regression tests, and the one additional change (model-picker key shadowing) is a genuine, well-tested improvement.
· branch integrate/0912-tideline-cli-20260831

@codewhale-agent codewhale-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codewhale review

This PR integrates the Tideline startup/shell stack, localizes Fleet→Pod, adds shared composer submit geometry and pending-work state normalization, and expands CI checks. The diff is mostly mechanical and well-supported by tests; remaining concerns are compatibility edges and whether the advertised picker behavior is fully covered by visible code and tests.

Findings

  • [WARNING] Retired launch_screen setting has no interactive command migration path (crates/tui/src/settings.rs)
    The settings field and its 'launch_screen' | 'launch' parser arms are removed. A file-load test was added, but no coverage exists for the in-session setting command or other paths that may encounter the key. Users with this key in persisted config get the new startup behavior, but an interactive setting command would now be rejected/unknown. Consider documenting the retirement or keeping a compatibility alias.
  • [WARNING] Advertised picker type-to-search behavior is not visible in the diff
    The PR description claims persistent lowercase a/p/r search, Shift+A catalog view, Shift+P pin, and Ctrl+R refresh, but the shown changes only add locale strings for PickerActionPin and compact launch labels. No picker dispatch, state, or tests are included in the visible diff, so the correctness of the advertised behavior cannot be assessed from this PR alone.
  • [INFO] Tideline composer geometry overlaps the submit target on very narrow widths (crates/tui/src/tui/composer_chrome.rs)
    The fixed submit reservation is 5 cells (right rail + breathing + 3-cell [↑]), but the render helpers only bail out when width < 6. At widths 6 and 7, the derived submit rect starts before or at the content origin, allowing content to overwrite the submit affordance. The 40-column floor is safe, but consistent behavior for embedded narrow surfaces would need a width < 8 guard or a different content-width derivation.

Assessment

Solid integration with extensive local verification and useful regression tests. No blocking correctness issue was found in the visible diff, but I recommend confirming the picker behavior is covered by actual code/tests and tightening the narrow-composer guard before merge.


Advisory review by Codewhale (codewhale review --pr 5774 --post, head 358c081c1a008e9d7ca4693254077c5dab53fd19). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.

@Hmbown
Hmbown merged commit 3d87d2f into main Aug 31, 2026
29 checks passed
@Hmbown
Hmbown deleted the integrate/0912-tideline-cli-20260831 branch August 31, 2026 18:17
Hmbown pushed a commit that referenced this pull request Aug 31, 2026
Resolve conflicts from merging 3d87d2f (Tideline shell integration, PR #5774):

- Locale JSONs (15 packs): union of both sides' keys — keep this branch's
  41 new/corrected Subagents* and session-vs-ledger wording values, and add
  main's Tideline keys (LaunchMenuChatCompact, LaunchMenuWorktreeCompact,
  PickerActionPin). Key sets verified identical across all packs.
- commands/groups/core/core.rs: keep this branch's 'Fetching current-session
  sub-agents...' assertion, matching the resolved en SubagentsFetching value
  read via tr(MessageId::SubagentsFetching).

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
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.

Compose and verify the Tideline shell as one coherent running TUI

1 participant