Skip to content

fix(vterm): track SGR per cell so re-attach replays colors#24

Merged
aksOps merged 1 commit into
mainfrom
fix/vterm-color-replay
Jun 11, 2026
Merged

fix(vterm): track SGR per cell so re-attach replays colors#24
aksOps merged 1 commit into
mainfrom
fix/vterm-color-replay

Conversation

@aksOps

@aksOps aksOps commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Re-attaching to a session rendered it black and white: vterm stored bare runes and discarded SGR by design, so Redraw (the replay a new attach client receives) repainted the screen colorless. The SIGWINCH nudge only rescues full-screen TUIs; inline agents (claude, omp) never repaint their history.

Fix

Per-cell SGR tracking + attribute-aware replay:

  • cell = rune + attr (16/256/truecolor fg+bg, bold/dim/italic/underline/blink/reverse/strike).
  • Real SGR parser incl. colon sub-parameter forms (38:5:196, 38:2::r:g:b, 4:0) and 58 underline-color skip.
  • Back-color-erase: erases/scroll-reveals/inserts fill with the current background (colored bars replay intact); resize keeps bg-colored blank rows consistently with Redraw.
  • Redraw repaints each cell with its original attributes; reset-prefixed transitions; reset before the cursor park.
  • Capture/peek stays plain text by contract; history stays plain (scrollback replays uncolored — only the visible screen carries attributes).

Test plan

  • 6 new tests: color replay (16/256/truecolor), bright+bg, attribute-off codes, colon forms, BCE, EL-with-bg; existing 28 vterm tests unchanged except the Redraw prefix assertion (now expects the leading attribute reset).
  • Full suite + -race green; adversarially reviewed (one finding — resize/Redraw blank-row inconsistency — fixed in-branch).

The emulator stored bare runes and discarded SGR by design, so the
replay a re-attaching client receives (Redraw) repainted the screen
black and white; the follow-up resize nudge only rescues full-screen
TUIs that fully repaint on SIGWINCH - inline agents (claude, omp) never
repaint their history, so everything stayed monochrome until new output
arrived.

Track attributes per cell and replay them:
  - cell = rune + attr (16/256/truecolor fg+bg, bold/dim/italic/
    underline/blink/reverse/strike), stamped from the terminal's current
    SGR state
  - a real SGR parser, including colon sub-parameter forms (38:5:196,
    38:2::r:g:b, 4:0) and a 58 underline-color skip
  - back-color-erase: erases, scroll-revealed rows, and inserted blanks
    fill with the current background so colored bars replay intact;
    resize keeps bg-colored blank rows the same way Redraw paints them
  - Redraw repaints each cell with its original attributes (reset
    prefix, per-run transitions, reset before the cursor park)

Capture/peek stays plain text by contract, and history stays plain
rowText - scrollback replays uncolored; only the visible screen carries
attributes.
@sonarqubecloud

Copy link
Copy Markdown

@aksOps aksOps merged commit 4439270 into main Jun 11, 2026
13 checks passed
@aksOps aksOps deleted the fix/vterm-color-replay branch June 11, 2026 08:04
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