pmacs/pmacs-protocol/src
Levi Neuwirth e5076ff277
feat(protocol): LineWrapFacts at v22, and the GPU stops inheriting a default
The GPU is not a grid consumer --- it ignores the CellDelta family and
lays out locally --- so ui.line-wrap reaching the viewport reaches only
the TUI. Without a wire message, setting truncate would change one
frontend and leave the other wrapping: exactly the cross-frontend
disagreement this stage exists to remove.

LineWrapFacts is appended after PanelFrame, the final v21 variant, so
no postcard discriminant moves. PROTOCOL_VERSION 21 -> 22;
ADVERTISED_PROTOCOL_VERSION stays at 20, per its own doc --- moving the
advertised baseline is reserved for changes that cannot be expressed
additively, and this one can. A v21 frontend negotiates v21, never
receives the variant, and keeps its behavior.

It carries buffer_id because the mode is buffer-local. That is also why
the daemon must resend on BUFFER SWITCH, not only on attach and config
change: font size is global, wrap mode is not, so moving from a
truncate buffer to a wrap buffer changes the effective mode with no
config event at all. The GPU handler leans on that --- it ignores a
message for any buffer other than the one on screen, rather than
keeping a per-buffer cache.

On the GPU side the document buffer had never called set_wrap, so it
was running on cosmic-text's constructor default of WordOrGlyph: word
wrap nobody chose. code_wrap makes it explicit in both directions and
settles on Wrap::Glyph. Character wrap is what the grid can implement
identically without pulling UAX #14 into it, and what Emacs does by
default. GUI users lose word wrap --- a deliberate, documented trade
for the two frontends agreeing, and it belongs in the release notes.

Changing wrap reflows the document exactly like a font change, so the
retained scroll anchor is repaired through the existing
normalize_code_scroll rather than left pointing at a row that no longer
exists.

Three test updates that were NOT stale assertions. The version pin and
the resume ladder both had to widen, and the GPU's byte-exact bootstrap
test failed because SUPPORTED_PROTOCOL_VERSIONS still ended at 21 ---
the handshake was genuinely rejecting v22. That test earned its keep.

Two new GPU witnesses. the_gpu_honors_an_explicit_non_wrap_mode is the
discriminating case framing section 7 asked for: the existing
wrapped_caret test passes against a wrap nobody configured, so it
cannot tell "honors the setting" from "the default happened to match".
Comparing row counts across the two modes can.

Gates: fmt, workspace clippy -D warnings, diff --check, --lib 1912/0,
crdt 2097/0, protocol 25/0, pmacs-gpu 223/0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
2026-08-07 16:54:13 +02:00
..
cell.rs protocol v6: per-severity diagnostic underline colors (SGR 58) 2026-06-10 19:16:42 -04:00
crdt.rs session 1 commit 3/4: CrdtOp moved to pmacs-protocol 2026-05-20 09:32:09 -04:00
ids.rs session 1 commit 1/4: workspace + identity types moved to pmacs-protocol 2026-05-20 09:11:33 -04:00
lib.rs feat(protocol): one scroll classifier, so the frontends cannot disagree 2026-08-06 23:04:38 +02:00
message.rs feat(protocol): LineWrapFacts at v22, and the GPU stops inheriting a default 2026-08-07 16:54:13 +02:00
panel.rs feat(bottom-panel): split the GPU document bottom into three boundaries 2026-07-29 18:30:57 -04:00
scroll.rs fix(protocol): saturating_mul undercounted the percentage silently 2026-08-06 23:08:10 +02:00
terminal.rs Keep the v21 panel wire dark for v20 clients 2026-07-28 14:08:17 -04:00
transport.rs session M-1 — Pointer wire + daemon byte-space mouse semantics 2026-06-10 13:10:17 -04:00
wire_grid.rs fix(panel): review round 1 — buffer_id, the transport ratchet, shared bounds 2026-07-26 17:31:04 -04:00