Repository navigation
feat: color-encoding tiers derived from capability evidence - #148
natemoo-re wants to merge 2 commits into
Conversation
The renderer resolves an emission tier (truecolor / 256 / 16) from its capability snapshot instead of hardcoding 24-bit truecolor, per specs/color-encoding-spec.md. Capability state is authoritative in the WASM instance; the host pushes it at creation and after capability folds, and a tier change forces a complete redraw. Standard palette colors keep their classic indices when downmapped. Closes #60
Changeset suggestionThe current changeset no longer matches this PR. This review contains a corrected replacement. Why: Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently. Changeset bump does not match the consumer-visible impact. Changeset does not name the affected public API confidently. Changeset contains implementation or roadmap noise. Changeset contains unsupported consumer-facing claims. View the proposed changeset---
'@bomb.sh/tty': minor
---
Changes the renderer's SGR color encoding to derive from terminal capability evidence instead of always emitting 24-bit truecolor sequences.
Terminals with truecolor evidence (`RGB`/`Tc` terminfo extension, `COLORTERM`, `max_colors ≥ 2²⁴`, or a `colordepth` probe response via `term.update()`) receive byte-identical truecolor output. Without evidence, cells emit 256-color SGR (`\x1b[38;5;Nm`) when the resolved palette exceeds 16 colors, or 4-bit SGR (`\x1b[31m`) at or below 16. Standard palette colors keep their classic indices; grays use the 240-step grayscale ramp; everything else rounds to the 6×6×6 cube. A tier change between frames forces a complete redraw.
**The default behavior changed:** a `Term` created without color evidence now emits 256-color bytes where it previously emitted truecolor. Run `detectTerminal()` and pass its result to `createTerm`, or fold probe responses with `term.update()`, to restore truecolor output on terminals that support it.
#### Migration
```diff
import { createTerm } from "@bomb.sh/tty";
+ import { detectTerminal } from "@bomb.sh/tty";
- const term = await createTerm({ width, height });
+ const terminfo = await detectTerminal();
+ const term = await createTerm({ width, height, terminfo });
```Review this changeset manually If this draft is correct, react with 🚀 and Cooper will commit it to this branch.
|
| @@ -0,0 +1,20 @@ | |||
| --- | |||
There was a problem hiding this comment.
Changeset needs revision.
Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently. Changeset bump does not match the consumer-visible impact. Changeset does not name the affected public API confidently. Changeset contains implementation or roadmap noise. Changeset contains unsupported consumer-facing claims.
View the proposed replacement
---
'@bomb.sh/tty': minor
---
Changes the renderer's SGR color encoding to derive from terminal capability evidence instead of always emitting 24-bit truecolor sequences.
Terminals with truecolor evidence (`RGB`/`Tc` terminfo extension, `COLORTERM`, `max_colors ≥ 2²⁴`, or a `colordepth` probe response via `term.update()`) receive byte-identical truecolor output. Without evidence, cells emit 256-color SGR (`\x1b[38;5;Nm`) when the resolved palette exceeds 16 colors, or 4-bit SGR (`\x1b[31m`) at or below 16. Standard palette colors keep their classic indices; grays use the 240-step grayscale ramp; everything else rounds to the 6×6×6 cube. A tier change between frames forces a complete redraw.
**The default behavior changed:** a `Term` created without color evidence now emits 256-color bytes where it previously emitted truecolor. Run `detectTerminal()` and pass its result to `createTerm`, or fold probe responses with `term.update()`, to restore truecolor output on terminals that support it.
#### Migration
```diff
import { createTerm } from "@bomb.sh/tty";
+ import { detectTerminal } from "@bomb.sh/tty";
- const term = await createTerm({ width, height });
+ const terminfo = await detectTerminal();
+ const term = await createTerm({ width, height, terminfo });
```|
Size Increased — +2.9 KB 125.5 KB unpacked |
commit: |
CI's lint job flagged the unused InputEvent import and the two control-character regexes (the same no-control-regex suppression term.test.ts uses). Local verify runs fmt only, which is why lint slipped; deno lint is now clean on this branch.
262c219 to
23559ee
Compare
Closes #60.
What
The renderer now resolves a color tier from its capability snapshot instead of hardcoding 24-bit truecolor:
colorModeoverride — capability evidence is the single lever (TINV-3); an override would be a second source of truth that can contradict probe responses. Callers control the encoding the same way they control every other capability:detectTerminal()or folding probe responses throughterm.update().emit_attr(where the color is known): nominal-16 exact match → exact cube → grayscale ramp → nearest cube; ties resolve to the lowest index. Standard palette colors keep their classic indices —rgba(255,0,0)→\x1b[31m/\x1b[41munder"16",\x1b[38;5;1munder"256"— exactly the pins from 💡 Color-encoding modes (16-color / 256-color) derived from terminfo #60's repro.colorsvalue and truecolor flag are pushed once at creation and after capability folds, never copied per render. Resizes must not reset them to baseline.Spec
New focused feature spec
specs/color-encoding-spec.md(renderer-spec §7.8 explicitly defers color encoding to "a focused feature specification"). Conforming edits: §7.8 drops color encoding from its deferred list; §8.1 cross-references the new spec from theterminfoparameter. No public API signatures change.With no color evidence, the baseline
{colors: 256, trueColor: false}now resolves to "256" — the renderer emits 256-color SGR where it previously hardcoded truecolor. This is the terminfo-spec §7.1 evidence model applied to emission ("Truecolor is not assumed at baseline; it requires positive evidence") and matches theTermOptionsdoc from #133 ("the renderer uses the 256-color baseline"). The issue's "byte-identical to today" guarantee holds for truecolor-evidenced terminals (CI-2). The three files that pin\x1b[38;2;bytes (term/border/colortests) now inject a shared truecolor-evidence fixture so they continue to exercise the truecolor tier explicitly; the new default is pinned once intest/color-encoding-modes.test.ts.Tests
test/color-encoding-modes.test.ts: all three tiers, tier-resolution boundaries (8/16/17,colors ≥ 2²⁴, granted flag), bg codes, palette round-trip (exhaustive 256 sweep), defaults (CI-6), truecolor byte-identitydeno task verifyclean; changeset includedRefs: