Unlock full scrollback depth in railway ca session panes - #1065
Merged
codyde merged 1 commit intoAug 11, 2026
Merged
Conversation
codyde
force-pushed
the
railway/ca-tui-deep-scrollback
branch
from
August 9, 2026 21:57
e558245 to
d49e7f2
Compare
Scrolling was clamped to one screenful — a documented workaround for vt100 0.15's view composition underflowing past the screen height. vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the exact unicode-width pin that blocked the upgrade. Bump both, migrate the moved Parser::set_size/set_scrollback calls to Screen, drop the one-page ceilings in scroll_by and resize, and pin the behavior with tests: full-depth scroll, multi-notch wheel walks, deep offsets across resizes, churn (output + scroll + reshape interleaved), retention-limit clamping, and a full-frame render from deep history.
codyde
force-pushed
the
railway/ca-tui-deep-scrollback
branch
from
August 11, 2026 05:29
d49e7f2 to
7ee499e
Compare
codyde
changed the base branch from
master
to
railway/ca-manage-reset-refresh-auth
August 11, 2026 05:29
codyde
merged commit Aug 11, 2026
aadd9e7
into
railway/ca-manage-reset-refresh-auth
11 checks passed
codyde
added a commit
that referenced
this pull request
Aug 11, 2026
Scrolling was clamped to one screenful — a documented workaround for vt100 0.15's view composition underflowing past the screen height. vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the exact unicode-width pin that blocked the upgrade. Bump both, migrate the moved Parser::set_size/set_scrollback calls to Screen, drop the one-page ceilings in scroll_by and resize, and pin the behavior with tests: full-depth scroll, multi-notch wheel walks, deep offsets across resizes, churn (output + scroll + reshape interleaved), retention-limit clamping, and a full-frame render from deep history.
codyde
added a commit
that referenced
this pull request
Aug 11, 2026
* Add railway ca manage, clear cached auth on refresh, and setup reset `railway ca manage` jumps the TUI straight to the manage screen, skipping the front-door menu. `--refresh-auth` now clears the local Claude setup-token cache before re-minting, instead of only skipping the remote reuse check (a stale/revoked cached token previously never got replaced). `railway ca setup --reset`, and a "Reset to default" choice in the interactive prompts, clear saved cloud agent preferences and the cached token together. * Unlock full scrollback depth in railway ca session panes (#1065) Scrolling was clamped to one screenful — a documented workaround for vt100 0.15's view composition underflowing past the screen height. vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the exact unicode-width pin that blocked the upgrade. Bump both, migrate the moved Parser::set_size/set_scrollback calls to Screen, drop the one-page ceilings in scroll_by and resize, and pin the behavior with tests: full-depth scroll, multi-notch wheel walks, deep offsets across resizes, churn (output + scroll + reshape interleaved), retention-limit clamping, and a full-frame render from deep history. * feat(ca): add Opt+[ to cycle back to the previous session (#1066) * Unlock full scrollback depth in railway ca session panes Scrolling was clamped to one screenful — a documented workaround for vt100 0.15's view composition underflowing past the screen height. vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the exact unicode-width pin that blocked the upgrade. Bump both, migrate the moved Parser::set_size/set_scrollback calls to Screen, drop the one-page ceilings in scroll_by and resize, and pin the behavior with tests: full-depth scroll, multi-notch wheel walks, deep offsets across resizes, churn (output + scroll + reshape interleaved), retention-limit clamping, and a full-frame render from deep history. * feat(ca): add Opt+[ to cycle back to the previous session Opt+] already cycles forward through open session panes; this adds the reverse chord. Opt+[ is recognized where the terminal can express it unambiguously: as a real ALT event under the kitty keyboard protocol (which the TUI already enables), or as the composed curly double quote macOS sends when Option is not mapped to Meta. Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to the CSI prefix every arrow key starts with — so it never surfaces as a key event there. The chord goes dead in those terminals but can never misfire or steal a cursor key. Also updates the footer hint to advertise both directions. * Lead the ca Manage tree with agents instead of projects (#1067) * Unlock full scrollback depth in railway ca session panes Scrolling was clamped to one screenful — a documented workaround for vt100 0.15's view composition underflowing past the screen height. vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the exact unicode-width pin that blocked the upgrade. Bump both, migrate the moved Parser::set_size/set_scrollback calls to Screen, drop the one-page ceilings in scroll_by and resize, and pin the behavior with tests: full-depth scroll, multi-notch wheel walks, deep offsets across resizes, churn (output + scroll + reshape interleaved), retention-limit clamping, and a full-frame render from deep history. * feat(ca): add Opt+[ to cycle back to the previous session Opt+] already cycles forward through open session panes; this adds the reverse chord. Opt+[ is recognized where the terminal can express it unambiguously: as a real ALT event under the kitty keyboard protocol (which the TUI already enables), or as the composed curly double quote macOS sends when Option is not mapped to Meta. Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to the CSI prefix every arrow key starts with — so it never surfaces as a key event there. The chord goes dead in those terminals but can never misfire or steal a cursor key. Also updates the footer hint to advertise both directions. * Lead the ca Manage tree with agents instead of projects The Manage screen is about cloud agents, but they rendered at depth 3 of a workspace > project > environment > agent > session tree — two container levels to expand before reaching the thing the screen exists to show, with the environment level almost always a single-child passthrough. Invert the presentation: every environment that has agents is promoted to an always-expanded top-level group, labelled with its project (plus /env when the environment isn't production and the project has several). Agents render directly beneath with their status glyphs, sessions still nested under their agent. Groups sort by liveliness — anything running floats up — then default project, then name; the cursor is anchored by row identity so re-sorts never move the selection. Projects with agent-less environments wait in a collapsible "other projects" tail, default project first and undimmed. The tail opens itself while there are no agents to show (so a fresh account still gets the browse tree, behind a hint) and folds away once groups exist; toggling it by hand sticks. Every environment stays reachable there for n, t, and r — including empty ones in projects whose other environments have agents. Refreshes no longer blank a loaded environment while the reply is in flight, so groups stay put through the wake/sleep watch polls, and a failed refresh keeps the stale list with the error in the status line instead of hiding agents that exist. The data model and RowKind index tuples are unchanged — this is a rework of the rows() flattener, the expansion handlers, and the rendering; myCloudAgents already delivered everything at startup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
railway casession panes could only scroll back one screenful, no matter how much history the emulator held. This removes that limit: scrollback now reaches the full retained history (4000 lines).Why it was limited
The one-page clamp in
Session::scroll_bywas a deliberate workaround, documented in place: vt100 0.15.2 composes the scrolled view asscrollback[len-offset..] ++ rows[..rows_len-offset], and an offset deeper than the screen height underflows the second subtraction — a panic in debug, and in release a silent wrap that renders the live screen ("scrolling does nothing").resize()carried a matching clamp so a shrinking pane couldn't strand an offset past the new height.The workaround's comment said upgrading vt100 was blocked on ratatui's exact pin of
unicode-width = "=0.2.0". Both halves of that blocker have since resolved upstream:visible_rowsnow bounds withtake(rows_len)+saturating_sub).ratatui-core, which acceptsunicode-width >=0.2.0, <=0.2.2, so it co-resolves with vt100 0.16.Changes
ratatui0.29 → 0.30,vt1000.15 → 0.16.Parser::set_size/set_scrollbackare now onScreen(viascreen_mut()), andCell::contents()returns&str.scroll_by— the emulator clamps to the history that exists, and the settled offset is read back as before.set_size.No ratatui API in this codebase changed in 0.30: the upgrade produced zero ratatui compile errors across all five TUIs (cloud agent, develop, metrics, scale, volume browser), and none of the 0.30 breaking-changes items (
block::Title,Flex::SpaceAround,layout::Alignment, customBackendimpls, braille symbol tables) are used here.Tests
Six new tests pressure the removed limit from every direction, in both debug (where the old emulator panicked) and release (where it silently no-opped):
scrolling_reaches_the_whole_history— 20 screens of output;scroll_by(isize::MAX)lands on the first line ever printed,isize::MINreturns to live.scrolling_walks_past_one_screenful— successive wheel notches through the realscroll()entry point keep going past the pane height (the exact thing the clamp prevented).a_deep_scroll_survives_resize— a deep offset rides through shrinking and growing panes without underflow or a stuck view.scrollback_survives_churn— live output, scrolls, and reshapes interleaved; the held offset always matches the emulator and the view always renders.scrollback_clamps_at_capacity— 4200+ lines overflow the 4000-line retention; full depth clamps to exactly 4000 and shows real (oldest retained) history.a_deeply_scrolled_pane_draws_old_history— full-frame render viarender_session→screen_lines→Screen::cellwith the view several screens deep: old lines drawn, tail out of view, "scrolled back" badge shown.Full suite: 954 passed. The 3
auth_simfailures are pre-existing on master in this environment (fail identically on an unmodified checkout) and unrelated.