Records the 9.1–9.3 scoring and the QB1–QB3 follow-on findings that
manual validation surfaced (read-only-mirror sourcing, per-tick
whole-file recompute, line-relative glyph offsets). Marks the framing
doc CLOSED and retires Phase A finding A8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Manual validation of 9.2 surfaced finding QB1: the CurrentLine wash
never appeared, and 9.1's Selection never actually rendered either.
Root cause: `Selection` and `CurrentLine` are the only two
per-WINDOW-state decorations; every other rendered family (StyleSpans,
diagnostics, inlay hints, minimap) is keyed to the shared BUFFER. The
producer emits both from the viewing frontend's own window
(`active_window_for(self.frontend_id)`). pmacs-gpu is a read-only
mirror with no input path — it never sends Key/cursor events, so its
own window's cursor stays pinned at 0 and its selection stays None.
Both decorations are therefore inert in pmacs-gpu: CurrentLine paints
a static line-0 wash (invisible at alpha 0.08) and Selection never
appears. What the user actually watches is the *editing* frontend's
(their TUI's) cursor — which is peer presence.
Fix is consumer-only — no producer or protocol change. The wire
already carries it: `InstanceMessage::PresenceUpdate { frontend_id,
buffer_id, cursor, selection }` is broadcast by the daemon to every
`multi_frontend` recipient, pmacs-gpu already negotiates
`multi_frontend: true`, and it was simply dropping the message at its
`_ => None` catch-all.
Q#5 (recorded in the framing doc): peer presence is the authoritative
cursor/selection source for a read-only mirror.
- New `peer_presences: HashMap<FrontendId, PeerPresence>` state,
cleared on BufferSnapshot (peer offsets are prior-buffer-relative).
- New `PresenceUpdate` arm stores per-peer (buffer_id, cursor,
selection) and requests a redraw.
- `peer_background_rects` replaces the old
`decoration_background_rects`: renders `CurrentLine` over the source
line holding each peer's cursor (`source_line_range`) and
`Selection` over each peer's selected range, both via the shared
`push_glyph_extent_rects` (the former inline glyph-overlap loop,
extracted). Own-window Selection/CurrentLine in `current_decorations`
are no longer drawn as backgrounds — they're inert for a read-only
mirror. Diagnostic (foreground) decorations are untouched.
- The producer keeps emitting own-window Selection/CurrentLine (9.1/
9.2) unchanged — correct and forward-looking for when pmacs-gpu
gains its own input in Phase B; simply unconsumed-for-backgrounds by
the mirror today.
Deferred within the stance (documented): per-peer stable colors (single
peer reuses the Selection/CurrentLine colors), peer caret glyph +
"user N" label, and own-vs-peer cursor merge once input lands.
New tests: `source_line_range_locates_enclosing_line` +
`source_line_range_handles_empty_and_leading_newline`. The peer
rect generation itself needs a laid-out buffer (font system) and is
covered by the manual probe.
Two pre-existing functions tipped past clippy's 100-line limit by the
additions (`State::new` 101, `apply_attach_message` 116, a per-variant
match dispatcher); both get `#[allow(clippy::too_many_lines)]`,
matching the precedent on `semantic_render::render_frame`.
Gates green:
- cargo fmt --all -- --check
- cargo clippy --all-targets --workspace -- -D warnings
- cargo clippy --all-targets --workspace --features crdt -- -D warnings
- pmacs lib 1329 + pmacs-protocol 11
- pmacs-gpu unit 15 (+2 source_line_range tests)
- m4_acceptance 88, m11_5_semantic_acceptance (--features crdt) 2
Manual probe: daemon + TUI attach + pmacs-gpu attach. Move the cursor
in the TUI — pmacs-gpu's CurrentLine wash should track the TUI's line.
Select text in the TUI — the Selection wash should mirror it. Both
should now actually appear and follow the editing frontend.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Retires the first half of Phase A's deferred finding A8 (background-
bearing decoration kinds couldn't render through cosmic-text's
foreground-only `Attrs`). `DecorationKind::Selection` now paints a
translucent blue rectangle under the selected glyphs in pmacs-gpu,
reusing the wgpu `QuadRenderer` that shipped for the minimap in
session 7.
The framing doc (`docs/pmacs-gpu-quad-backgrounds-framing.md`)
commits the load-bearing decisions before code lands: stance (α)
for Q#2 — single render pass, three draws in the order backgrounds
→ text → minimap — is what this commit implements. Q#1 (CurrentLine
source location, stance α: producer-side from
`core.active_window_for(self.frontend_id).cursor`) and Q#3 (per-line
cadence, stance β) are sketched for session 9.2; Q#4 defers search
backgrounds awaiting an upstream pmacs search feature.
Three components:
1. `decoration_kind_to_bg_color` helper, sibling of the existing
`decoration_kind_to_color`. Returns `Some([f32; 4])` RGBA for
Selection; `None` for CurrentLine (9.2), SearchMatch /
SearchMatchActive (deferred), and the four diagnostic kinds
(foreground-only). New unit tests assert disjoint total cover
between the two helpers across the eight kinds.
2. `State::decoration_background_rects` walks
`Buffer::layout_runs()`, finds glyphs whose `[start, end)`
overlaps each background-bearing decoration's `ByteRange`, and
produces one `MinimapRect` per laid-out visual line that
contributes glyphs. Multi-line selections fan out as N rects.
3. Render-order change in `State::render`: a `bg_buffer` is built
ahead of the minimap buffer and drawn first in the render pass
(before `text_renderer.render`), so selection fills sit under
the glyphs with the 0.30-alpha letting source color show through.
Minimap continues to draw last.
Gates green:
- cargo fmt --all -- --check
- cargo clippy --all-targets --workspace -- -D warnings
- cargo clippy --all-targets --workspace --features crdt -- -D warnings
- pmacs-gpu unit: 13 (+2 new bg-color helper tests)
- pmacs lib: 1325, pmacs-protocol: 11
- m4_acceptance: 88, m11_5_semantic_acceptance (--features crdt): 2
Bet exercise so far: bet #1 (multi-line vertex decomposition) is
implicitly tested by the layout-run loop but waits on visual
validation for honest scoring. Bet #2 (overlap composition) is not
exercised in 9.1 — Selection is the only background kind, so no
overlaps with CurrentLine or future kinds. Bet #3 (cadence) is a
9.2 concern.
Manual probe: launch daemon + TUI attach + pmacs-gpu attach against
any file, select text in the TUI, verify the pmacs-gpu window paints
a translucent blue rectangle over the selected glyphs that tracks
selection extension. Multi-line selection should produce per-visual-
line rectangles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>