Skip to content

fix(ui-tui): a skin owns the terminal's DEFAULT foreground (OSC-10) — kills the invisible-text class - #69632

Merged
OutThisLife merged 1 commit into
mainfrom
bb/skin-terminal-default-fg
Jul 22, 2026
Merged

fix(ui-tui): a skin owns the terminal's DEFAULT foreground (OSC-10) — kills the invisible-text class#69632
OutThisLife merged 1 commit into
mainfrom
bb/skin-terminal-default-fg

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

Follow-up to #69616, hit one demo later: composer themed, but the agent's response body went black-on-black the same way. Same class, different call site — and the class is the thing to kill.

The class

The skin repaints the terminal background via OSC-11, but every token rendered without an explicit color — markdown body, borders, anything default-fg — falls back to the terminal's default foreground, which belongs to the HOST profile's polarity, not the skin's. Dark skin + light terminal ⇒ near-black text on pure black. Everything the theming engine explicitly paints (headers, accents, status colors, the placeholder) flips perfectly; the hole is precisely the tokens it doesn't paint. Chasing every <Text> (what #69616 did for the input) is unwinnable one call site at a time.

Fix — own the default itself

When a skin authors a background (the existing opt-in), applySkin now paints the terminal's default foreground from the resolved theme's text color via OSC-10, beside the OSC-11 background it already painted. Every default-fg token — present and future — re-bases onto the skin atomically, exactly like the background. No skin background ⇒ both defaults restore to the terminal's own; a skinless session never touches the terminal.

  • terminalModes: the OSC-11 background slot generalizes to defaultColorSlot(10 | 11) — one paint/clear/exit-restore contract, painted-state tracked per slot, exit reset appends only what was actually painted.
  • reapplyTheme repaints the fg too: polarity flips swap paired palettes, moving the text tone while the skin's background stays put.
  • #69616's explicit input theming stays on top — the composer is first-class themed, not merely default-correct.

Tests

  • terminalModes — the slot contract runs table-driven over both OSC codes: paint from hex, ignore junk/non-TTY, exit-reset restores only-if-painted, dropping the color releases the default
  • createGatewayEventHandler — the invariant: a skin owning the background paints both defaults, fg == theme.color.text; dropping the background releases both (OSC-110 + OSC-111)
  • full ui-tui suite 125 files / 1344✓; typecheck, lint, prettier clean

…ide the OSC-11 background

The input fix's sibling, hit immediately after: the composer was themed but
AGENT text went black-on-black the same way. Root cause is the class, not
the call site — markdown body, borders, and every token rendered without an
explicit color falls back to the terminal's DEFAULT foreground, which
belongs to the HOST profile's polarity, not the skin's. A dark skin on a
light terminal repaints the backdrop via OSC-11 while thousands of
default-fg cells stay near-black.

Chasing every <Text> is unwinnable. Instead own the default itself: when a
skin authors a background (the existing opt-in), paint the default
foreground from the resolved theme's text color via OSC-10. Every unthemed
token — present and future — re-bases onto the skin atomically, exactly
like the background.

terminalModes: the OSC-11 slot generalizes to defaultColorSlot(10|11) —
same paint/clear/exit-restore contract, tracked per slot, so a skinless
session still never touches the terminal. reapplyTheme repaints the fg too:
polarity flips swap paired palettes, moving the text tone while the
background stays.

Tests: slot contract runs table-driven over both OSC codes; handler test
pins the invariant (default fg == theme text; dropping the background
releases both defaults). Suite 1344✓, typecheck/lint/prettier clean.
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

running on 1f65221

CI timings

CI timings · View job

Wall time 7m28s vs 8m10s (-8.6%). 3 job(s) slower, 3 faster, 1 unchanged.

  • Build&Test Docker image / build (amd64, ubuntu-latest, linux/amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=do...: -25.0s
  • Build&Test Docker image / build (arm64, ubuntu-24.04-arm, linux/arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope...: +14.0s
  • OSV scan / Scan lockfiles / osv-scan: -11.0s
  • Detect affected areas: +2.0s
  • OSV scan / Emit review status: -1.0s

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jul 22, 2026
@OutThisLife
OutThisLife enabled auto-merge July 22, 2026 21:33
@OutThisLife
OutThisLife merged commit e0d62b5 into main Jul 22, 2026
29 checks passed
@OutThisLife
OutThisLife deleted the bb/skin-terminal-default-fg branch July 22, 2026 21:34
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…nal-default-fg

fix(ui-tui): a skin owns the terminal's DEFAULT foreground (OSC-10) — kills the invisible-text class
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…nal-default-fg

fix(ui-tui): a skin owns the terminal's DEFAULT foreground (OSC-10) — kills the invisible-text class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants