InstanceMessage::CompletionPopup {buffer_id, anchor: Option<u64>,
prefix_len, rows: Vec<CompletionPopupRow{label, kind, detail}>,
selected, total} -- the first byte-anchored popup on the wire: the
frontend maps byte -> glyph rect locally (the caret precedent), so the
instance never learns a pixel. Rows are display-only; accept resolves
daemon-side via dispatch_completion_key, so insert text never ships.
PROTOCOL_VERSION 14 -> 15, SUPPORTED extended; postcard round-trip
(open + closed shapes) and version-pin/ladder tests updated.
Producer: semantic_render::completion_popup_msg, the family pattern
(per-buffer cached-compare, active-buffer only, first-sight-closed
stays silent) with one new rule -- the session is WINDOW-stamped and
this state is per-frontend, so only the frontend whose own window
owns the session sees it open: a popup opened by TUI typing never
renders in an attached GPU and vice versa. Windowed rows share the
TUI overlay's POPUP_MAX_ROWS. Daemon-gated >= 15 (a v14 peer still
completes via the key round-trip, it just gets no GPU dropdown).
GPU consumption follows in this branch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>