docs(framing): acceptance 48 re-measured --- it is HALF implemented
Ground truth before code, and the lane entry in the same commit, per the standing correction from #171 and #215 --- the one the 1b lane missed. Base `githubsucks/main` @ `72da24a`. No implementation yet. **AC48 IS NOT UNIMPLEMENTED. IT IS HALF IMPLEMENTED**, and nothing had written the halves down separately, which is how "PanelPointer drives listview rows, selection, terminal reporting and focus" could sit next to a dispatcher that does none of the first three. Landed already: click-to-focus and the terminal activation rule (`src/editor.rs:2701`); the focused-only auto-scroll clamp with a passive panel's `view_top` preserved (`:2569`, which has cited parent 48 all along); and the coalescing rules --- `Move`/`Drag` tails coalesce while press/release/context/wheel stay lossless and ordered (`pmacs-gpu/src/attach.rs:374`). Missing: listview row selection, panel selection, terminal mouse reporting, wheel replay. **AND THE REPLAY IS MOSTLY WIRING.** `apply_terminal_gesture` (`src/editor.rs:3525`) is already "the one terminal pointer path, shared by both frontend kinds" and already drives child mouse reporting, selection and scrollback; a panel terminal needs the SAME CALL, with `side_window_for` + `TerminalViewKey` + the `panel_grid_size` the dispatcher already fetches. `scroll_window` (`:3845`) is window-scoped including its cursor carry, and documents that a wheel "names the pane under the pointer and does NOT activate it". This is why a wheel-only bridge would be the wrong shape: the shared path takes every kind at once, and the wheel-only version would have to grow a second one later. **The scoping hazard, and why no ruling is needed.** `set_cursor_byte`, `begin_selection` and `clear_selection` are ACTIVE-WINDOW scoped (`src/editor_core.rs:1216`, `:4691`), so replaying naively from the panel path would move the DOCUMENT's point --- exactly what AC48's "without disturbing the document mirror" forbids. The existing activation rule already resolves it: activation runs before replay in the same dispatch, and the gestures that need the active-window API are precisely the ones that activate. The single gesture that does not --- a document panel's wheel --- needs only the window-scoped `scroll_window`. **One genuine question, opened not answered: Q#BP-R1.** Does a listview row VISIT on click, or only select? `listview.lua` binds visiting to RET/SPC (`:610`) and there is no pointer precedent anywhere in the file. Single-click-visits matches a file tree; click-selects, double-click-visits matches an editor list; AC48 says "row selection" and nothing more. This lane implements SELECTION and does not invent activation, because the difference is whether a click navigates the user's document. Gates: all nine green under `env -u TMPDIR`, log 20260814T113155Z. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
parent
72da24adea
commit
d97dcdfc46
|
|
@ -270,6 +270,68 @@ hazard in a shape that looks committed. **A documented error message
|
||||||
that never appears is worse than no documentation**, because the reader
|
that never appears is worse than no documentation**, because the reader
|
||||||
waits for a signal that is not coming.
|
waits for a signal that is not coming.
|
||||||
|
|
||||||
|
## Panel-pointer replay (parent acceptance 48) — ACTIVE, 1b's prerequisite
|
||||||
|
|
||||||
|
**Written with the branch's FIRST commit**, per the standing correction
|
||||||
|
from #171 and #215 — the correction the 1b lane missed, honoured here.
|
||||||
|
|
||||||
|
- **Branch `panel-pointer-replay`**, base `githubsucks/main` @
|
||||||
|
**`72da24a`** exactly, in worktree
|
||||||
|
`/home/jeans/Repos/personal/pmacs-panel-replay`.
|
||||||
|
**`githubsucks/panel-pointer-replay` is the authoritative tip** (the
|
||||||
|
ref, not a SHA). Recover with
|
||||||
|
`git fetch githubsucks && git checkout panel-pointer-replay`.
|
||||||
|
- **No PR yet. Checkpoint: framing revision 5 (§5a) AWAITING APPROVAL;
|
||||||
|
NO IMPLEMENTATION WRITTEN.** The first commit is the ground-truth
|
||||||
|
re-measurement, per the standing method.
|
||||||
|
- **Why this lane exists.** `PanelPointer` **replays nothing**:
|
||||||
|
`dispatch_semantic_panel_pointer` (`src/editor.rs:2674`) validates,
|
||||||
|
focuses, returns. A panel wheel is dead on both axes and so is every
|
||||||
|
gesture past focus. **GUI arc 1b is BLOCKED on this lane and rebases
|
||||||
|
onto its merge commit.**
|
||||||
|
- **No new framing document.** Acceptance 48 is already ruled in
|
||||||
|
`docs/bottom-panel-framing.md`; §5a adds ground truth to it.
|
||||||
|
- **The measurement's headline: AC48 is HALF implemented**, and nothing
|
||||||
|
had written the halves down separately.
|
||||||
|
- **DONE:** click-to-focus and the terminal activation rule
|
||||||
|
(`src/editor.rs:2701` and its `activates`); the focused-only
|
||||||
|
auto-scroll clamp with passive `view_top` preserved (`:2569`, which
|
||||||
|
already cites parent 48); the coalescing rules — `Move`/`Drag`
|
||||||
|
tails coalesce, press/release/context/wheel lossless
|
||||||
|
(`pmacs-gpu/src/attach.rs:374`).
|
||||||
|
- **MISSING:** listview row selection, panel selection, terminal
|
||||||
|
mouse reporting, wheel replay.
|
||||||
|
- **The replay is mostly WIRING; both mechanisms exist.**
|
||||||
|
`apply_terminal_gesture` (`src/editor.rs:3525`) is *"the one terminal
|
||||||
|
pointer path, shared by both frontend kinds"* and already drives
|
||||||
|
child reporting, selection and scrollback — a panel terminal needs
|
||||||
|
the same call, with `side_window_for` + `TerminalViewKey` +
|
||||||
|
`panel_grid_size` (which the dispatcher already fetches).
|
||||||
|
`scroll_window` (`:3845`) is window-scoped, cursor carry included.
|
||||||
|
**A wheel-only bridge is the wrong shape** — the shared path takes
|
||||||
|
every kind at once.
|
||||||
|
- **The scoping hazard, and why it needs no ruling.** `set_cursor_byte`
|
||||||
|
(`src/editor_core.rs:1216`), `begin_selection` (`:4691`) and
|
||||||
|
`clear_selection` are **active-window scoped**; used naively they
|
||||||
|
would move the DOCUMENT's point, which AC48 forbids. **Activation
|
||||||
|
runs before replay in the same dispatch**, and the gestures needing
|
||||||
|
that API are exactly the ones that activate. The only gesture that
|
||||||
|
does not activate — a document panel's wheel — needs only the
|
||||||
|
window-scoped `scroll_window`.
|
||||||
|
- **OPEN: Q#BP-R1** — does a listview row **visit** on click, or only
|
||||||
|
select? `listview.lua` binds visiting to RET/SPC (`:610`) and there
|
||||||
|
is no pointer precedent. **This lane implements selection and does
|
||||||
|
not invent activation.**
|
||||||
|
- **Gates:** the four `bottom_panel_*` acceptance suites plus
|
||||||
|
`PMACS_REQUIRE_GPU=1 cargo test -p pmacs-gpu`. **No `--protocol`** —
|
||||||
|
`PanelPointer` and every `MouseKind` it carries already exist on the
|
||||||
|
wire.
|
||||||
|
- **Expected rebase conflict, flagged deliberately:** the `gui-stage1b`
|
||||||
|
branch inserts its own lane at this same position and corrects three
|
||||||
|
stale headers below (#239/#240 still marked OPEN, "1a is next").
|
||||||
|
Those corrections are **left to that branch**; this lane does not
|
||||||
|
duplicate them. The conflict is a normal insertion collision.
|
||||||
|
|
||||||
## `scripts/gate` TMPDIR isolation — PR #240 OPEN
|
## `scripts/gate` TMPDIR isolation — PR #240 OPEN
|
||||||
|
|
||||||
**Written with the branch's first commit**, per the standing correction
|
**Written with the branch's first commit**, per the standing correction
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,16 @@ protocol v20, 2026-07-24. Amended by the pre-implementation dependency
|
||||||
verification in §0.6: the folding dependency is cleared, and one geometry
|
verification in §0.6: the folding dependency is cleared, and one geometry
|
||||||
caller-census error is corrected.**
|
caller-census error is corrected.**
|
||||||
|
|
||||||
|
**Revision 5 — 2026-08-14, AWAITING APPROVAL. Adds §5a: acceptance 48
|
||||||
|
re-measured against production at `72da24a`.** The finding is that AC48
|
||||||
|
is **half implemented** — focus, activation, the focused-only clamp and
|
||||||
|
the coalescing rules all landed; **listview row selection, panel
|
||||||
|
selection, terminal mouse reporting and wheel replay did not**, so
|
||||||
|
`PanelPointer` reaches `dispatch_semantic_panel_pointer` and stops at
|
||||||
|
focus. No ruling in §3 or §5 changes. **One question is opened,
|
||||||
|
Q#BP-R1**, on whether a listview row visits on click; this lane
|
||||||
|
implements selection and does not answer it.
|
||||||
|
|
||||||
Give pmacs a **bottom panel**: a buffer displayed in a fixed-height window
|
Give pmacs a **bottom panel**: a buffer displayed in a fixed-height window
|
||||||
pinned to the bottom of the frame, resizable by dragging its divider, which
|
pinned to the bottom of the frame, resizable by dragging its divider, which
|
||||||
feature code targets **by policy** instead of by stealing the selected window.
|
feature code targets **by policy** instead of by stealing the selected window.
|
||||||
|
|
@ -1770,6 +1780,95 @@ cannot preserve the old panel-focused attach leak.
|
||||||
preserving the Stage 1 unknown-value rollback assertions; the Stage 3 PR
|
preserving the Stage 1 unknown-value rollback assertions; the Stage 3 PR
|
||||||
then runs the full gate suite.
|
then runs the full gate suite.
|
||||||
|
|
||||||
|
## 5a. Acceptance 48 — ground truth, MEASURED at `72da24a` (2026-08-14)
|
||||||
|
|
||||||
|
**Why this section exists.** GUI arc Stage 1b's ground-truth pass found
|
||||||
|
that `PanelPointer` **replays nothing**: `dispatch_semantic_panel_pointer`
|
||||||
|
(`src/editor.rs:2674`) validates the coord, resolves the side window,
|
||||||
|
focuses when the gesture activates, and returns `true`. Its own doc
|
||||||
|
defers replay to *"parent acceptance 48… Stage 2B-3"*. **A panel wheel
|
||||||
|
is dead today on both axes**, and so is every other panel gesture past
|
||||||
|
focus. 1b is blocked on this lane and rebases onto its merge.
|
||||||
|
|
||||||
|
**Acceptance 48 is not unimplemented — it is HALF implemented**, and
|
||||||
|
the halves were never separated in writing. Measured clause by clause:
|
||||||
|
|
||||||
|
| clause | status | production anchor |
|
||||||
|
|---|---|---|
|
||||||
|
| click-to-focus | **DONE** | `dispatch_semantic_panel_pointer`'s `activates` → `focus_window` (`src/editor.rs:2701`) |
|
||||||
|
| terminal panel: non-`Move` activates, hover does neither | **DONE** | the same `activates` computation, split by `is_terminal` |
|
||||||
|
| focused-only auto-scroll clamp; passive preserves `view_top` | **DONE** | `src/editor.rs:2569`, which already cites "A2A-3 / parent 48" |
|
||||||
|
| move/drag tails coalesce; press/release/context/wheel lossless and ordered | **DONE** | `pmacs-gpu/src/attach.rs:374`–`:381` — `Move` key 6, `Drag` key 7, everything else unkeyed |
|
||||||
|
| **listview row selection** | **MISSING** | — |
|
||||||
|
| **panel selection** | **MISSING** | — |
|
||||||
|
| **terminal mouse reporting** | **MISSING for panels** | the path exists: `apply_terminal_gesture` |
|
||||||
|
| **wheel moves the panel's viewport** | **MISSING** | the mechanism exists: `scroll_window` |
|
||||||
|
| without disturbing the document mirror | **the constraint on all of the above** | — |
|
||||||
|
|
||||||
|
### The replay is mostly WIRING, and both mechanisms already exist
|
||||||
|
|
||||||
|
**Terminals.** `apply_terminal_gesture` (`src/editor.rs:3525`) is
|
||||||
|
documented as *"The one terminal pointer path, shared by both frontend
|
||||||
|
kinds"* — TUI via crossterm, semantic frontend via
|
||||||
|
`FrontendEvent::TerminalPointer` — and it already drives child mouse
|
||||||
|
reporting, selection and scrollback. A panel terminal needs the **same
|
||||||
|
call**, not a second implementation: `side_window_for`
|
||||||
|
(`src/editor_core.rs:3146`) gives the window, `TerminalViewKey::new`
|
||||||
|
the key, and `panel_grid_size` — which the dispatcher **already
|
||||||
|
fetches** — the viewport size. **A wheel-only bridge here would be the
|
||||||
|
wrong shape**: the shared path handles every kind at once.
|
||||||
|
|
||||||
|
**Documents.** `scroll_window` (`src/editor.rs:3845`) is window-scoped
|
||||||
|
throughout, cursor carry included, and says so: *"a wheel event names
|
||||||
|
the pane under the pointer and does NOT activate it, so the map must
|
||||||
|
come from `win_id`"*. Its cursor carry moves **that window's** point —
|
||||||
|
the panel's own, not the document mirror.
|
||||||
|
|
||||||
|
### The scoping hazard, and why the activation rule already answers it
|
||||||
|
|
||||||
|
**The selection and cursor API is ACTIVE-WINDOW scoped.**
|
||||||
|
`set_cursor_byte` (`src/editor_core.rs:1216`), `begin_selection`
|
||||||
|
(`:4691`) and `clear_selection` all write `active_window_mut()`. Used
|
||||||
|
naively from the panel path they would move the **document's** point —
|
||||||
|
precisely what "without disturbing the document mirror" forbids.
|
||||||
|
|
||||||
|
**No new ruling is needed, because the ordering already rules it.**
|
||||||
|
Activation runs *before* replay in the same dispatch, and the gestures
|
||||||
|
that need the active-window API are exactly the ones that activate:
|
||||||
|
|
||||||
|
- **Document panel** — `activates` on `Down(_)`. A drag-select is
|
||||||
|
Down → Drag → Up, and the Down focused the panel, so the later
|
||||||
|
gestures act on an active window legitimately.
|
||||||
|
- **Terminal panel** — `activates` on every non-`Move`, so reporting,
|
||||||
|
selection and wheel all run focused. This is AC48's own
|
||||||
|
controller-ownership clause.
|
||||||
|
- **The one gesture that does NOT activate** is a document panel's
|
||||||
|
wheel — and it needs only `scroll_window`, which is window-scoped.
|
||||||
|
|
||||||
|
So the rule is: **replay after activation, and anything reachable
|
||||||
|
without activation must use a window-scoped mechanism.** Both halves
|
||||||
|
are satisfiable with what exists.
|
||||||
|
|
||||||
|
### Q#BP-R1 — is a listview row's activation a click or a double-click? **OPEN**
|
||||||
|
|
||||||
|
The one question the measurement could not answer from the tree.
|
||||||
|
`builtin/runtime/listview.lua` binds visiting to **RET/SPC**
|
||||||
|
(`:610`–`:611`), reading `pmacs.editor.cursor_line()` and calling
|
||||||
|
`on_visit`. There is no pointer precedent: nothing in the file mentions
|
||||||
|
a mouse.
|
||||||
|
|
||||||
|
So a pointer gesture can *move* to a row unambiguously, but **whether a
|
||||||
|
single click also VISITS is a product decision with no existing
|
||||||
|
answer** — single-click-visits matches a file tree, click-selects /
|
||||||
|
double-click-visits matches an editor list, and AC48's wording
|
||||||
|
("drives listview row selection") names selection only.
|
||||||
|
|
||||||
|
**This lane implements row SELECTION and does not invent activation.**
|
||||||
|
If visiting on click is wanted it should be ruled explicitly rather
|
||||||
|
than arriving as a side effect of wiring, because it is the difference
|
||||||
|
between a click that navigates the user's document and one that does
|
||||||
|
not.
|
||||||
|
|
||||||
## 6. Deferred (named)
|
## 6. Deferred (named)
|
||||||
|
|
||||||
Left / right / top side windows; multiple slots per side; **rehoming a leaf
|
Left / right / top side windows; multiple slots per side; **rehoming a leaf
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue