feat(tui): integrate the 0.9.12 Tideline shell - #5774
Conversation
(cherry picked from commit 2001b8f)
(cherry picked from commit 370a7fc)
(cherry picked from commit 07ab498)
(cherry picked from commit d9b9d6d)
(cherry picked from commit 59417c9)
(cherry picked from commit a2dba22)
(cherry picked from commit 888957e)
(cherry picked from commit 5512159)
(cherry picked from commit a936482)
(cherry picked from commit c04a3cc)
(cherry picked from commit e2c7225)
(cherry picked from commit 55fb926)
(cherry picked from commit d9bd021)
(cherry picked from commit ca18b92)
(cherry picked from commit 4b60408)
(cherry picked from commit d073ae1)
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>
…eline-active-composer-send-20260830
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
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Claude finished @Hmbown's task in 1m 19s —— View job Claude is reviewing this PR
|
|
Claude finished @Hmbown's task in 1m 2s —— View job Claude is reviewing this PR
|
| 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(), | ||
| ); |
There was a problem hiding this comment.
🟡 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.
Was this helpful? React with 👍 or 👎 to provide feedback.
| let option_label = if layout.strip.width < 56 { | ||
| match index { | ||
| 0 => "worktree", | ||
| 1 => "chat", | ||
| _ => option.label, | ||
| } |
There was a problem hiding this comment.
🟡 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.
Was this helpful? React with 👍 or 👎 to provide feedback.
| // Active-session Tideline rail group labels. | ||
| TidelineRuns, | ||
| TidelineWhales, | ||
| TidelineRunningCount, |
| 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}" | ||
| ); |
| /// 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, | ||
| } |
There was a problem hiding this comment.
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 projectionlive_work_from_appis 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 usepending_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_shellunconditionally callsrender_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 nocompactorshow_submitparameter. 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 remainConfigSectionFleet,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 finished @Hmbown's task in 4m 44s —— View job Claude finished reviewing this PRTodo list
SummaryBroad, well-evidenced integration of the 0.9.12 Tideline shell. The keyboard/mouse composer-submit unification in Findings1. Confirmed: the shared 2. Confirmed: dead scaffolding left behind by the passive-rail removal (reuse/simplification)
3. New renderer-local English literals in the startup option strip (locale policy) 4. Info: Nits
|
There was a problem hiding this comment.
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: theborderfield 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 { |
There was a problem hiding this comment.
[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 { |
There was a problem hiding this comment.
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 finished @Hmbown's task in 2m 48s —— View job Claude's review of the latest push (
|
There was a problem hiding this comment.
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.
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>

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.[↑]submit control across text wrapping, cursor placement, frame bookkeeping, and mouse mapping, including an 80x8 / 74-character regression? helpdiscoverable beside non-urgent footer receipts when the row can hold botha,p, andrsearch;Shift+Achanges catalog view;Shift+Ppins;Ctrl+RrefreshesThis 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
358c081c1a008e9d7ca4693254077c5dab53fd19cargo fmt --all -- --checkgit diff --checkscripts/dev-cargo.sh test -p codewhale-tui --lib --locked11,632 passed; 0 failed; 13 ignoredscripts/dev-cargo.sh check -p codewhale-tui -p codewhale-cli --all-features --lockedsh scripts/check-tui-product-vocabulary.shpython3 scripts/check-tui-locale-parity.py1903/1903; PASSEarlier 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 -- --nocapture1 passed; 0 failed; all five terminal sizes exercisedCloses #5768
These are source and local-test receipts only. Hosted CI, packaged artifacts, merge, and release remain separate gates.