a73x

053ae6ef

docs: the run header is a delta, after the size gate refused the absolute one

a73x   2026-09-04 17:00

Commit message
docs: the run header is a delta, after the size gate refused the absolute one

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CsWfuJFQbTfGtKZLS5qw4q

docs/superpowers/plans/2026-09-04-cells-on-the-wire.md
Old New
@@ -20,7 +20,8 @@
20 - Any hand-run rig exports an isolated `XDG_STATE_HOME` and `XDG_RUNTIME_DIR` first. 20 - Any hand-run rig exports an isolated `XDG_STATE_HOME` and `XDG_RUNTIME_DIR` first.
21 - Never quote a speed number from the dev tree; byte counts are fine. 21 - Never quote a speed number from the dev tree; byte counts are fine.
22 - Frame numbers: `snapshot = 0x95`, `delta = 0x96`, `scrollback_chunk = 0x97`; `0x81`, `0x85`, `0x87` retired and never reused. 22 - Frame numbers: `snapshot = 0x95`, `delta = 0x96`, `scrollback_chunk = 0x97`; `0x81`, `0x85`, `0x87` retired and never reused.
23 - Colour packing: `0` none, `(1 << 24) | index` palette, `(2 << 24) | r << 16 | g << 8 | b` RGB. Run flags bits 0–10 = ghostty `Style.Flags` bit order; bit 15 = `ascii`. Cell head = `wide << 6 | text_len`, `text_len ≤ 63`. 23 - Colour packing in memory: `0` none, `(1 << 24) | index` palette, `(2 << 24) | r << 16 | g << 8 | b` RGB. Style flags bits 0–10 = ghostty `Style.Flags` bit order. Cell head = `wide << 6 | text_len`, `text_len ≤ 63`.
24 - Run header (revised 2026-09-04 after the Task 2 gate refused the 16-byte absolute form): `u16 LE count` ++ `u8 mask` ++ present fields — mask bit0 `flags` (u16 LE follows), bit1 `fg`, bit2 `bg`, bit3 `ul`, bit7 `ascii`; a present colour is `u8 code` (0 none, 1 palette + 1 index byte, 2 RGB + 3 bytes). Absent fields are UNCHANGED from the previous run of the same row; the first run of a row starts from the default style. Task 1's golden bytes were rewritten to this form in Task 2's fix round.
24 25
25 --- 26 ---
26 27
docs/superpowers/specs/2026-09-04-cells-on-the-wire-design.md
Old New
@@ -70,16 +70,27 @@ Cells past `ncells` up to the grid width are default-style blanks, so the
70 encoder stops at the last cell that is not one (a cell whose content is a 70 encoder stops at the last cell that is not one (a cell whose content is a
71 bare background colour is NOT blank). 71 bare background colour is NOT blank).
72 72
73 A **run** is `RunHeader` (16 B: `u16 LE count`, `u16 LE flags`, `u32 LE fg`, 73 A **run** is a header that carries only what CHANGED since the previous run
74 `u32 LE bg`, `u32 LE ul`) followed by `count` cells: 74 of the same row — the shape SGR has, which is why VT rows are small — then
75 75 `count` cells. The first run of a row starts from the default style; a row
76 is self-contained, so nothing carries between rows or frames.
77
78 - `u16 LE count` ++ `u8 mask` ++ the present fields in order. `mask` bit 0:
79 `flags` present, `u16 LE` follows; bit 1: `fg` present; bit 2: `bg`
80 present; bit 3: `ul` present; bit 7: `ascii`. A present colour is `u8
81 code` — 0 none, 1 palette then one index byte, 2 RGB then three bytes.
82 A default first run is 3 bytes; a palette foreground change is 5.
83 (The first cut was a 16-byte absolute header, and the measurement gate
84 refused it: vim 1.45×, htop 1.56× — see decisions.md, 2026-09-04.)
76 - `flags` bits 0–10 are ghostty's `Style.Flags` verbatim — bold 0, italic 1, 85 - `flags` bits 0–10 are ghostty's `Style.Flags` verbatim — bold 0, italic 1,
77 faint 2, blink 3, inverse 4, invisible 5, strikethrough 6, overline 7, 86 faint 2, blink 3, inverse 4, invisible 5, strikethrough 6, overline 7,
78 underline style 8–10 (none 0, single 1, double 2, curly 3, dotted 4, 87 underline style 8–10 (none 0, single 1, double 2, curly 3, dotted 4,
79 dashed 5). Bit 15 is `ascii`: every cell of the run is ONE byte in 88 dashed 5). `ascii` means every cell of the run is ONE byte in
80 `0x20..0x7E`, narrow, with no per-cell header. 89 `0x20..0x7E`, narrow, with no per-cell header.
81 - Colours are packed as `wasm_core.packColor` does today: `0` none, 90 - In memory (`CellStyle`, the grid, the wasm viewport) colours stay packed
82 `1<<24 | index` palette, `2<<24 | r<<16 | g<<8 | b` RGB. 91 as `wasm_core.packColor` does today: `0` none, `1<<24 | index` palette,
92 `2<<24 | r<<16 | g<<8 | b` RGB; the wire spells the same three cases as
93 the code byte above.
83 - A non-`ascii` cell is `u8 head` = `wide << 6 | text_len` then `text_len` 94 - A non-`ascii` cell is `u8 head` = `wide << 6 | text_len` then `text_len`
84 bytes of UTF-8 — the whole grapheme cluster, capped at 63 bytes (the 95 bytes of UTF-8 — the whole grapheme cluster, capped at 63 bytes (the
85 encoder keeps the leading codepoints that fit). `wide` is 0 narrow, 1 96 encoder keeps the leading codepoints that fit). `wide` is 0 narrow, 1