Console-only color enforcement + full ANSI remap #11

Open
opened 2026-07-21 18:07:27 +00:00 by agent · 0 comments
Member

Plan: Console-only color enforcement + full ANSI remap

Goal

Only res-console enforces the residual amber palette. All other apps (res-sh, res-login, res-edit, res-code, res-calc, res-sheets) inherit the terminal's existing color theme. res-console applies the full 16-color ANSI remap (ApplyPalette) so child processes inside the console get amber-ized. On exit, the console resets the terminal to defaults.

res-theme is exempt — it is the theme editor/preview tool and manages its own OSC sequences.

Relationship to existing work

This builds on issue #3 ("Unified residual theming (two-mode per-app)"), which already implemented per-app unified_theme opt-in for res-edit, res-code, res-calc, and res-sheets. This issue completes the enforcement model by:

  1. Removing palette enforcement from res-sh and res-login
  2. Making res-console the sole strict enforcer with full ANSI remap
  3. Fixing the inverted UnifiedTheme semantics in res-console

Current bugs

  1. res-console/main.go has inverted UnifiedTheme logic: true → inherit, false → amber. Should be true → amber, false → inherit.
  2. res-console uses ApplyConsolePalette() (fg/bg only) instead of ApplyPalette() (full 16-color remap).
  3. res-sh and res-login still force the full palette via ApplyPalette + RES_THEME_ENFORCED.
  4. console/config/config.go Defaults() has UnifiedTheme as Go zero value (false), but console should default to amber.
  5. docs/design/aesthetic.md still says res-sh and res-login are enforcers.

Implementation steps

Step 1 — Remove enforcement from res-sh

  • File: core/cmd/res-sh/main.go
  • Delete the ApplyPalette / ResetPalette / RES_THEME_ENFORCED block (lines 42-46).
  • res-sh runs in whatever colors the terminal already has.
  • Remove "golang.org/x/term" import if no longer needed.

Step 2 — Remove enforcement from res-login

  • File: core/cmd/res-login/main.go
  • Remove applyThemeGuard() function entirely (lines 378-389).
  • Remove all defer applyThemeGuard(...) calls:
    • Line 138: defer applyThemeGuard(t.File())() in runLogin()
    • Line 210: defer applyThemeGuard(os.Stdout)() in runSelect()
    • Line 253: defer applyThemeGuard(t.File())() in runDryRun()
  • res-login runs in whatever colors the terminal already has.

Step 3 — Fix res-console as sole enforcer

  • File: core/cmd/res-console/main.go
  • Fix UnifiedTheme inversion. Current code:
    if cfg.Console.UnifiedTheme {
        theme.InitInherit()  // BUG: true means inherit
    } else {
        // applies amber
    }
    
    Should be:
    if cfg.Console.UnifiedTheme {
        // Apply amber theme (default)
        tuiCfg, err := theme.LoadConfig()
        if err != nil {
            tuiCfg = theme.DefaultConfig()
        }
        if cfg.Console.Accent != "" {
            tuiCfg.Foreground = cfg.Console.Accent
        }
        theme.InitTheme(tuiCfg)
        if os.Getenv("RES_THEME_ENFORCED") != "1" {
            theme.ApplyPalette(os.Stdout)  // Full 16-color remap
            os.Setenv("RES_THEME_ENFORCED", "1")
            defer theme.ResetPalette(os.Stdout)
        }
    } else {
        theme.InitInherit()
    }
    
  • Switch from ApplyConsolePalette() to ApplyPalette() for full 16-color ANSI remap.

Step 4 — Fix console config defaults

  • File: core/internal/libs/console/config/config.go
  • Set UnifiedTheme: true in Defaults():
    return Config{
        Console: ConsoleConfig{
            ScrollbackLines: defaults.ConsoleHistoryLines,
            UnifiedTheme:    true,  // console enforces amber by default
        },
    }
    
  • Update consoleTOMLTemplate comment:
    # unified_theme    = true                                   # true = apply residual amber palette (default); false = inherit terminal colors
    

Step 5 — Semantic color model for tools

  • Files: Various tool packages that use hardcoded amber hex or lipgloss styles
  • Tools should use standard ANSI indexed colors for semantic roles:
    • ANSI 2 (green) → success / OK
    • ANSI 1 (red) → error / urgent
    • ANSI 4 (blue) → path / context
    • ANSI 7 (white) → text / command
  • When running inside res-console, the full ANSI remap converts these to amber tones.
  • When running standalone, they render as the terminal's native colors.
  • Affected areas to audit:
    • core/internal/libs/shell/remnant/prompt.go — prompt styling
    • core/lib/edit/ — editor syntax highlighting
    • extra/internal/code/ — IDE chrome
    • Any direct lipgloss.Color("#ffb000") or theme.LAmber usage in tools

Step 6 — Transparent background by default

  • theme.DefaultConfig() already has TransparentBg: true.
  • Verify ApplyPalette() and ApplyConsolePalette() emit \x1b]111\x1b\\ (reset background) instead of \x1b]11;<hex>\x1b\\ when activeTransparentBg is true.
  • Already correct in palette.go lines 96-98 and 113-115.
  • No code changes needed; verify with test.

Step 7 — Update docs

  • File: docs/design/aesthetic.md
    • Update "theme enforcement" section (lines 140-155): only res-console enforces.
    • Update "terminal palette" section (lines 180-198): console DOES remap ANSI indices.
    • Fix the unified_theme exception description (lines 170-172): true = amber, false = inherit.
  • File: docs/console/console-design.md
    • Update color model section (lines 61-99): document full ANSI remap.
    • Add note about OSC 104 limitation for palette reset.
  • File: docs/README.md
    • Update tool descriptions to reflect inherit-by-default behavior.

Step 8 — Verification

  • cd core && go build ./... && CGO_ENABLED=1 go test ./...
  • cd extra && go build ./... && go test ./...
  • Manual check scenarios:
    1. res-console starts with amber palette, child ls --color=auto shows amber tones, exit restores terminal colors.
    2. res-sh standalone does NOT change terminal colors.
    3. res-login does NOT change terminal colors.
    4. res-edit / res-code inside console show amber chrome when console has unified theme.
    5. res-theme preview works independently of console enforcement.

Risks

  • ResetPalette() uses OSC 104 which not all terminals support. Terminals without OSC 104 support will retain the amber palette after console exit. This is a known limitation; document it in docs/console/console-design.md.
  • res-theme is exempt from this rule (it's the theme editor/preview tool). It already manages its own OSC sequences.
  • Changing res-calc/res-sheets from always-amber to inherit-by-default (from issue #3) may surprise users who expected amber. Document in release notes.

Open questions

  • Should we add a "save original palette" mechanism for terminals without OSC 104? (Deferred — complex, requires synchronous terminal query.)
  • Should res-sh prompt use ANSI colors (green for success indicator, etc.) instead of hardcoded amber lipgloss styles? (Part of Step 5 — semantic color model.)
# Plan: Console-only color enforcement + full ANSI remap ## Goal Only `res-console` enforces the residual amber palette. All other apps (`res-sh`, `res-login`, `res-edit`, `res-code`, `res-calc`, `res-sheets`) inherit the terminal's existing color theme. `res-console` applies the **full 16-color ANSI remap** (`ApplyPalette`) so child processes inside the console get amber-ized. On exit, the console resets the terminal to defaults. `res-theme` is exempt — it is the theme editor/preview tool and manages its own OSC sequences. ## Relationship to existing work This builds on **issue #3** ("Unified residual theming (two-mode per-app)"), which already implemented per-app `unified_theme` opt-in for `res-edit`, `res-code`, `res-calc`, and `res-sheets`. This issue completes the enforcement model by: 1. Removing palette enforcement from `res-sh` and `res-login` 2. Making `res-console` the sole strict enforcer with full ANSI remap 3. Fixing the inverted `UnifiedTheme` semantics in `res-console` ## Current bugs 1. `res-console/main.go` has **inverted `UnifiedTheme` logic**: `true` → inherit, `false` → amber. Should be `true` → amber, `false` → inherit. 2. `res-console` uses `ApplyConsolePalette()` (fg/bg only) instead of `ApplyPalette()` (full 16-color remap). 3. `res-sh` and `res-login` still force the full palette via `ApplyPalette` + `RES_THEME_ENFORCED`. 4. `console/config/config.go` `Defaults()` has `UnifiedTheme` as Go zero value (`false`), but console should default to amber. 5. `docs/design/aesthetic.md` still says `res-sh` and `res-login` are enforcers. ## Implementation steps ### Step 1 — Remove enforcement from res-sh - **File:** `core/cmd/res-sh/main.go` - Delete the `ApplyPalette` / `ResetPalette` / `RES_THEME_ENFORCED` block (lines 42-46). - `res-sh` runs in whatever colors the terminal already has. - Remove `"golang.org/x/term"` import if no longer needed. ### Step 2 — Remove enforcement from res-login - **File:** `core/cmd/res-login/main.go` - Remove `applyThemeGuard()` function entirely (lines 378-389). - Remove all `defer applyThemeGuard(...)` calls: - Line 138: `defer applyThemeGuard(t.File())()` in `runLogin()` - Line 210: `defer applyThemeGuard(os.Stdout)()` in `runSelect()` - Line 253: `defer applyThemeGuard(t.File())()` in `runDryRun()` - `res-login` runs in whatever colors the terminal already has. ### Step 3 — Fix res-console as sole enforcer - **File:** `core/cmd/res-console/main.go` - Fix `UnifiedTheme` inversion. Current code: ```go if cfg.Console.UnifiedTheme { theme.InitInherit() // BUG: true means inherit } else { // applies amber } ``` Should be: ```go if cfg.Console.UnifiedTheme { // Apply amber theme (default) tuiCfg, err := theme.LoadConfig() if err != nil { tuiCfg = theme.DefaultConfig() } if cfg.Console.Accent != "" { tuiCfg.Foreground = cfg.Console.Accent } theme.InitTheme(tuiCfg) if os.Getenv("RES_THEME_ENFORCED") != "1" { theme.ApplyPalette(os.Stdout) // Full 16-color remap os.Setenv("RES_THEME_ENFORCED", "1") defer theme.ResetPalette(os.Stdout) } } else { theme.InitInherit() } ``` - Switch from `ApplyConsolePalette()` to `ApplyPalette()` for full 16-color ANSI remap. ### Step 4 — Fix console config defaults - **File:** `core/internal/libs/console/config/config.go` - Set `UnifiedTheme: true` in `Defaults()`: ```go return Config{ Console: ConsoleConfig{ ScrollbackLines: defaults.ConsoleHistoryLines, UnifiedTheme: true, // console enforces amber by default }, } ``` - Update `consoleTOMLTemplate` comment: ```toml # unified_theme = true # true = apply residual amber palette (default); false = inherit terminal colors ``` ### Step 5 — Semantic color model for tools - **Files:** Various tool packages that use hardcoded amber hex or lipgloss styles - Tools should use **standard ANSI indexed colors** for semantic roles: - ANSI 2 (green) → success / OK - ANSI 1 (red) → error / urgent - ANSI 4 (blue) → path / context - ANSI 7 (white) → text / command - When running inside `res-console`, the full ANSI remap converts these to amber tones. - When running standalone, they render as the terminal's native colors. - **Affected areas to audit:** - `core/internal/libs/shell/remnant/prompt.go` — prompt styling - `core/lib/edit/` — editor syntax highlighting - `extra/internal/code/` — IDE chrome - Any direct `lipgloss.Color("#ffb000")` or `theme.LAmber` usage in tools ### Step 6 — Transparent background by default - `theme.DefaultConfig()` already has `TransparentBg: true`. - Verify `ApplyPalette()` and `ApplyConsolePalette()` emit `\x1b]111\x1b\\` (reset background) instead of `\x1b]11;<hex>\x1b\\` when `activeTransparentBg` is true. - **Already correct** in `palette.go` lines 96-98 and 113-115. - No code changes needed; verify with test. ### Step 7 — Update docs - **File:** `docs/design/aesthetic.md` - Update "theme enforcement" section (lines 140-155): only `res-console` enforces. - Update "terminal palette" section (lines 180-198): console DOES remap ANSI indices. - Fix the `unified_theme` exception description (lines 170-172): `true` = amber, `false` = inherit. - **File:** `docs/console/console-design.md` - Update color model section (lines 61-99): document full ANSI remap. - Add note about OSC 104 limitation for palette reset. - **File:** `docs/README.md` - Update tool descriptions to reflect inherit-by-default behavior. ### Step 8 — Verification - `cd core && go build ./... && CGO_ENABLED=1 go test ./...` - `cd extra && go build ./... && go test ./...` - Manual check scenarios: 1. `res-console` starts with amber palette, child `ls --color=auto` shows amber tones, exit restores terminal colors. 2. `res-sh` standalone does NOT change terminal colors. 3. `res-login` does NOT change terminal colors. 4. `res-edit` / `res-code` inside console show amber chrome when console has unified theme. 5. `res-theme` preview works independently of console enforcement. ## Risks - `ResetPalette()` uses OSC 104 which not all terminals support. Terminals without OSC 104 support will retain the amber palette after console exit. This is a known limitation; document it in `docs/console/console-design.md`. - `res-theme` is exempt from this rule (it's the theme editor/preview tool). It already manages its own OSC sequences. - Changing `res-calc`/`res-sheets` from always-amber to inherit-by-default (from issue #3) may surprise users who expected amber. Document in release notes. ## Open questions - Should we add a "save original palette" mechanism for terminals without OSC 104? (Deferred — complex, requires synchronous terminal query.) - Should `res-sh` prompt use ANSI colors (green for success indicator, etc.) instead of hardcoded amber lipgloss styles? (Part of Step 5 — semantic color model.)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
residual/.agent#11
No description provided.