Skip to content

Stabilize TUI refresh, scrolling, and responsive layout - #863

Open
ihearttokyo wants to merge 2 commits into
getagentseal:mainfrom
ihearttokyo:codex/fix-tui-refresh-layout
Open

Stabilize TUI refresh, scrolling, and responsive layout#863
ihearttokyo wants to merge 2 commits into
getagentseal:mainfrom
ihearttokyo:codex/fix-tui-refresh-layout

Conversation

@ihearttokyo

@ihearttokyo ihearttokyo commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

This change makes CodeBurn's interactive terminal dashboard stable during refreshes, scrollable at every supported layout, and predictable at every terminal width.

  • Preserve the active Optimize view and the user's vertical position during background refreshes.
  • Enforce a one-minute minimum automatic refresh interval while retaining --refresh 0 for fully static sessions.
  • Pin the first dashboard page to the top of a terminal-sized viewport, with line, page, Home, and End navigation across the full dashboard.
  • Render panels in a stable 3/2/1-column sequence with left-aligned bars, justified metrics, full costs when space permits, readable headings, and ten Daily Activity rows.
  • Grow three-column panels symmetrically until the dashboard reaches the lesser of 256 columns or the current data's renderable width.
  • Reflow on the first frame at the 135/134 and 90/89 breakpoints without stale content or a blank screen above 256 terminal columns.

Why this was happening

Three terminal behaviors were interacting. A background reload could finish after the user entered Optimize and replace state belonging to the active view. Ink's resize hook could paint once with the previous column count before React received the new width. Finally, the alternate screen intentionally has no terminal scrollback, while the dashboard rendered a tree taller than the terminal without supplying its own viewport.

The result was a view that could disappear during refresh, briefly render the wrong column arrangement during resize, or expose no way to reach panels below the visible terminal rows.

What changed

Refresh and viewport stability

  • Auto-refresh scheduling remains active only in the dashboard view.
  • Results arriving after the user changes views are discarded.
  • Background work keeps the current frame mounted rather than entering a loading state.
  • The interactive tree now renders inside a clipped, terminal-height viewport.
  • Up/down move one application row; Page Up/Page Down move one viewport; Home/End jump to the bounds.
  • Scroll offset remains React state across refresh and resize rerenders. A real navigation to another view, period, provider, or day starts at the top.
  • Daily Activity retains j/k line navigation and uses Shift+Space/Space for its own paging, avoiding a key conflict with application scrolling.

Responsive rendering

  • Panels retain source order while flowing through three, two, and one columns.
  • A shared row renderer keeps colored bars at the left edge and distributes metric cells evenly.
  • Project labels truncate before cost, avg/s, session, and overhead headings.
  • Model metric cells derive their width from the full formatted cost, including the estimated-cost marker, whenever the panel has room.
  • The three-column dashboard expands evenly, one panel character per three added terminal columns, subject to the data-derived and 256-column ceilings.

Resize correctness

  • A prepended resize handler captures the new terminal width before Ink paints.
  • Interactive rendering keeps the alternate-screen isolation and clears only when the dashboard's rendered width changes.
  • Growth beyond the dashboard cap preserves the existing frame.

User impact

Users can leave Optimize open while CodeBurn runs, scroll every dashboard panel in one-, two-, or three-column layouts, and keep their place through refreshes. Resizing produces an immediate ordered reflow. Wide windows retain a populated dashboard, long paths no longer consume metric headings, and costs remain legible when the available width can hold them.

Testing

  • Dashboard regression suite: 39 tests passed, including one-, two-, and three-column viewport scrolling and rerender position preservation.
  • Real-data Ghostty coverage: 135, 134, 90, 89, 256, 300, and 342 columns.
  • Live 160-column PTY path: Page Down reached lower panels and Page Up restored the pinned header.
  • npx tsc --noEmit
  • npm run build (CLI and browser dashboard)
  • git diff --check

The repository-wide run completed with 2,495 passing tests. It retains two unrelated Copilot parser failures, one unrelated durable-total parity failure, and 26 missing-jsdom environment errors.

Keep background refreshes from blanking or replacing the active Optimize view, and enforce a one-minute minimum refresh interval.\n\nRework the dashboard into a stable 3/2/1-column flow with left-aligned bars, justified metric columns, readable project headings, and a ten-row Daily Activity viewport.\n\nSynchronize resize state before Ink paints so breakpoint transitions do not leave stale frames, preserve content beyond 256 terminal columns, and cap the dashboard at the current data's renderable width. Add focused regression coverage and a submission statement documenting live Ghostty validation.
@ihearttokyo

Copy link
Copy Markdown
Contributor Author

Submission note

Commit 4c856b3 addresses the dashboard as one coherent interactive surface. Background refreshes now respect the view the user is actually looking at, terminal resizes enter React before Ink paints, and every panel follows the same layout rules for bars, labels, and metrics.

The practical result is stable navigation and predictable rendering: Optimize remains open during background work; enabled refreshes occur no more than once per minute; panels flow through 3/2/1 columns in source order; metric headings stay readable beside long project paths; and very wide terminals preserve a populated dashboard within the data-derived 256-column ceiling.

Validation covered real CodeBurn data in Ghostty, including first-frame captures across the 135→134 and 90→89 breakpoints and populated frames through 342 columns. The focused 36-test dashboard suite, TypeScript compilation, CLI production bundle, Semgrep, co-author guard, Firstlook, and Windows package build are all green.

Pin the interactive dashboard to a terminal-sized viewport and add line,
page, home, and end navigation without sacrificing the alternate-screen
resize protections. Preserve the viewport offset across background refreshes
and ordinary rerenders while resetting cleanly for a new view or period.

Give daily-history paging its own Space binding, render full model costs
whenever the panel can hold them, and spell out the project session heading.
Extend the responsive dashboard regressions across one-, two-, and
three-column viewports and update the submission evidence.
@ihearttokyo ihearttokyo changed the title Stabilize TUI refresh and responsive layout Stabilize TUI refresh, scrolling, and responsive layout Jul 31, 2026
@ihearttokyo

Copy link
Copy Markdown
Contributor Author

Added the viewport follow-up in 6f3f91e.

The alternate screen solved stale resize frames, but it also removed terminal scrollback. CodeBurn was still rendering the entire dashboard as one taller-than-terminal tree, which left the lower panels unreachable. The new root viewport clips the application to the live terminal height and owns a persistent vertical offset: arrows scroll by line, Page Up/Page Down by screen, and Home/End jump to the bounds. Refresh and resize rerenders retain that offset; actual navigation begins at the top.

This follow-up also incorporates the visual corrections from the latest captures. The project heading now says session, and model metric cells size themselves from the full rendered cost—including ~ for estimated pricing—before truncating labels. Daily Activity keeps j/k, with Shift+Space/Space reserved for its own paging.

Validation now covers scrolling at 80, 100, and 160 columns, position preservation across rerenders, a live 160-column PTY Page Down/Page Up path, 39 focused dashboard tests, TypeScript, the complete CLI and browser build, and patch hygiene. The PR description has been updated with the root cause, controls, evidence, and the remaining unrelated repository-suite failures.

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.

1 participant