pmacs/src
Levi Neuwirth 5fe7eb30b6 fix(bottom-panel): finish the panel port, not one omission at a time
Review round 1: six findings, four sharing one shape — the panel layer was a
partial port of the document/terminal layer, and the tests asserted the
declaration side only, so each omission was invisible. Audited as a port
rather than patched as a list.

GEOMETRY AGREEMENT (P1). Three grids had drifted apart. The declaration
subtracted `TEXT_LEFT` from its width against the parent framing's explicit
contract ("`total.cols` describes the full-width panel grid beginning at
x=0; document `TEXT_LEFT`/gutter padding is unrelated"), while painting and
hit-testing used the document-dependent `mono_advance` and the declaration
used the stable probe. So daemon columns could overflow the surface and a
click could resolve to a different cell than the one painted — and the new
test separated the two advances and then asserted only the declaration, so
it saw none of it.

The fix is structural, not three edits: the advance is cached BEHIND the
declaration (`PanelBand::declared_advance`) and painting and hit-testing read
it. They cannot disagree, because there is one value. The band's rect is now
x = 0 across the full surface width, and the fractional right-edge remainder
is band background that maps to no cell — which is what the framing says and
what `hit_test_cell`'s column bound already enforced.

GESTURES (P1). Only `Move` was sent. Left press never armed, so `Drag(Left)`
was never emitted and panel selection could not work; releases outside the
band were dropped, leaving the daemon holding a button down; right-click and
wheel never consulted the band at all and were applied to the document
underneath.

The root cause is that four handlers each decided for themselves whether the
band owned a pixel, and three did not ask. There is now ONE authority —
`PointerSurface` / `classify_pointer_surface` — and all four route through
it, so a future handler cannot quietly forget the band. `PanelBackground` is
its own arm: the remainder is the band's pixel even though it emits no
`PanelPointer`, so it must not fall through either.

PASSIVE CARET (P1). The producer ships `cursor` for a passive panel too — it
is the window's real point and the daemon does not suppress it — so painting
it unconditionally put a second insertion caret on screen. Gated on
`frame.focused`, the presentation bit Q#BP14b reserves for exactly this.

UNDERLINES (P2). `build_grid` planned them and nobody consumed them. Straight
forms now ride the quad batch and curly rides the squiggle pipeline, the same
split the terminal path makes for the same reason.

VERSION MISMATCH (P2). The daemon reported the advertised baseline as the
server version while its own `PROTOCOL_VERSION` is 21, contradicting the wire
field's own documentation and inverting the upgrade advice. The field doc now
states what each side can know, and the acceptance is re-pinned — it had been
holding the wrong value in place.

Two gaps the audit found beyond the six, same shape:
  * the headless probe never armed the panel wire at all, so no probe could
    ever exercise a band;
  * a disconnect left the band on screen — the frozen, live-looking surface
    the terminal arm already refuses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
2026-07-29 22:29:24 -04:00
..
audit V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
bin fix(lsp): close review round 1 on the resource-op delete guard 2026-07-29 11:45:43 -04:00
lua_bindings fix(lsp): close review round 1 on the resource-op delete guard 2026-07-29 11:45:43 -04:00
packages feat(persistence): autosave + crash recovery (Arc 3 phase 3) 2026-07-09 10:24:08 -04:00
terminal feat(terminal): copy mode over retained scrollback 2026-07-26 10:10:27 -04:00
ansi.rs fix(vterm): parse VT index operations 2026-07-21 15:31:15 -04:00
async_runtime.rs feat(dired): the directory view (Stage 1) 2026-07-25 14:54:58 -04:00
attach.rs feat(bottom-panel): activate protocol v21 by frontend counter-offer 2026-07-29 17:42:08 -04:00
attach_dispatch.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
attach_reconnect.rs Pin toolchain to 1.95.0 + mechanical clippy/rustc fixes 2026-05-18 11:38:57 -04:00
autosave.rs fix(persistence): adopt clears the old owner's skip cache; failing sweeps are loud 2026-07-09 12:06:49 -04:00
buffer.rs fix(buffer): fan out generated writes, and clear the history that exists 2026-07-26 13:43:22 -04:00
buffer_mirror.rs M10.10: complete optimistic-apply keystroke path + Day-5 corrections 2026-05-15 16:40:46 -04:00
buffer_registry.rs T M4.5 L1: cross-file nav foundations — per-buffer file_path, jump ring, x-file go-to-def 2026-05-19 09:53:29 -04:00
builtin_packages.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
cell.rs session 1 commit 2/4: cell wire types moved to pmacs-protocol 2026-05-20 09:20:24 -04:00
code_action.rs T M4.5 L4: WorkspaceEdit resource ops (create/rename/delete file) 2026-05-19 12:31:35 -04:00
command.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
completion.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
completion_framework.rs fix(completion): address TUI-validation findings (LSP query gaps, scoping, prefix keys, window scope) 2026-07-07 16:54:14 -04:00
config.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
config_registry.rs fix(config): reject wrongly-typed spec fields; make trim-on-save buffer-aware 2026-07-21 18:29:18 -04:00
crdt.rs fix(buffer): fan out generated writes, and clear the history that exists 2026-07-26 13:43:22 -04:00
daemon.rs fix(bottom-panel): finish the panel port, not one omission at a time 2026-07-29 22:29:24 -04:00
daemon_attach.rs CI fixes v2 2026-05-18 13:12:10 -04:00
definition.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
desktop.rs feat(window): window parameters, fixed extents, and the display policy 2026-07-24 13:53:14 -04:00
diag.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
display_width.rs feat(render): unify tab-width projection 2026-07-22 15:03:30 -04:00
document_highlight.rs T M4.5: documentSymbol / workspace symbol / documentHighlight 2026-05-18 22:15:03 -04:00
editor.rs Close review round 1: five findings, plus one the sweep found 2026-07-28 18:52:43 -04:00
editor_core.rs Close review round 1: five findings, plus one the sweep found 2026-07-28 18:52:43 -04:00
file_io.rs feat(persistence): autosave + crash recovery (Arc 3 phase 3) 2026-07-09 10:24:08 -04:00
fold.rs fix(fold): address PR #142 review round 1 2026-07-23 13:42:20 -04:00
fold_view.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
font_pref.rs feat(font): FontFacts wire + daemon half (v17, FontPref, producer) 2026-07-18 11:45:51 +01:00
formatting.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
frontend.rs feat(panel): bottom-panel Stage 2B — the v21 protocol layer 2026-07-26 16:52:54 -04:00
fs.rs fix(dired): address PR #165 review round 1 2026-07-25 15:21:26 -04:00
hash.rs feat(persistence): autosave + crash recovery (Arc 3 phase 3) 2026-07-09 10:24:08 -04:00
help.rs feat: wire major modes through key dispatch 2026-07-21 20:25:48 -04:00
highlight.rs fix(test): make acc12 pin the claim it names (review round 1) 2026-07-25 10:18:27 -04:00
hook.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
hover.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
inlay_hint.rs Close pmacs-gpu phase A audit 2026-05-28 12:49:23 -04:00
instance_buffer.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
instance_render.rs test(vterm): prove Stage 2 TUI integration 2026-07-21 20:16:23 -04:00
key.rs Fix PTY final-output drain race 2026-05-04 09:44:30 -04:00
keymap_stack.rs feat: wire major modes through key dispatch 2026-07-21 20:25:48 -04:00
keymap_tree.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
lib.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
locations.rs T M4.5: nav requests — references/declaration/typeDefinition/implementation 2026-05-18 21:39:02 -04:00
lockfile.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
lsp.rs feat(statusline): add composable modeline segments at protocol v18 2026-07-21 12:01:25 -04:00
lsp_status.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
lua.rs feat(completion): Lua driver, popup bindings, LSP scoping + flush seams 2026-07-07 12:09:25 -04:00
lua_isolation.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
main.rs fix(gpu): preserve session isolation during target publish 2026-07-23 21:25:33 -04:00
mcp.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
menu.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
message_bus.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
minibuffer.rs feat(persistence): state foundation + saveplace + recentf (Arc 3 phase 1) 2026-07-08 17:57:39 -04:00
optimistic.rs feat(edit): auto-pairing (Arc 2) 2026-07-11 17:11:56 +01:00
overlay.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
overlay_color.rs M10.10 ship gate 2026-05-13 16:28:46 -04:00
overlay_paint.rs feat(window): window parameters, fixed extents, and the display policy 2026-07-24 13:53:14 -04:00
prepare_rename.rs T M4.5: textDocument/prepareRename (backlog item 3) 2026-05-19 14:23:57 -04:00
presence.rs M11.1: semantic-frontend protocol scaffolding (wire + capability) 2026-05-18 19:39:07 -04:00
process.rs test(process): read the pid without ticking in the fast-exit tests 2026-07-25 22:25:05 -04:00
project.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
project_index.rs T M4.5 L1: cross-file nav foundations — per-buffer file_path, jump ring, x-file go-to-def 2026-05-19 09:53:29 -04:00
protocol.rs feat(bottom-panel): split the GPU document bottom into three boundaries 2026-07-29 18:30:57 -04:00
rename.rs T M4.5 L4: WorkspaceEdit resource ops (create/rename/delete file) 2026-05-19 12:31:35 -04:00
rope.rs session 1 commit 3/4: CrdtOp moved to pmacs-protocol 2026-05-20 09:32:09 -04:00
search.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
semantic_client.rs T M4.5: documentSymbol / workspace symbol / documentHighlight 2026-05-18 22:15:03 -04:00
semantic_render.rs Close PR 187 review round 2 2026-07-28 21:30:50 -04:00
semantic_tokens.rs Fix stale TUI styling after edits 2026-05-26 11:15:23 -04:00
signature.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
socket_path.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
state.rs fix(persistence): never clobber unclaimed crash data; buffer-keyed cleanup 2026-07-09 10:52:10 -04:00
statusline.rs fix(panel): close Stage 2A review round 2 (2 P1, 1 P2) 2026-07-26 10:38:21 -04:00
symbol.rs T M4.5: documentSymbol / workspace symbol / documentHighlight 2026-05-18 22:15:03 -04:00
syntax.rs feat(lean4): editing surface + Stage 1 acceptance (Q#LN5, LN6, LN17) 2026-07-25 09:59:48 -04:00
text_view.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
transport.rs session 3 commit 1/N: move transport codec to pmacs-protocol 2026-05-20 12:07:32 -04:00
view.rs feat(fold): Stage 2 — grid (daemon-rendered) collapse 2026-07-23 19:24:07 -04:00
window.rs fix(panel): close Stage 2A review round 1 (4 P1, 2 P2) 2026-07-26 10:02:01 -04:00
worker.rs fix(worker): deterministic pool teardown; EditorState::drop signals workers 2026-07-07 15:20:53 -04:00
workers_buffer.rs fix(dired): address PR #165 review round 1 2026-07-25 15:21:26 -04:00