docs(framing): SS5a revision 15 --- answers review of 14, mostly by correction
Four blocking gaps, all of them cases where revision 14 asserted a guarantee its own mechanism did not provide. 1. Q#BP-R4's release half was bookkeeping in an effect's clothes. It ruled that a chrome Up "consumes" the latch and claimed this stops a child being left button-down. It stops nothing: update_accepted_gesture does `let _ = state.consume_accepted_gesture()` at daemon.rs:1067, and terminal chrome returns at editor.rs:2862-2870, BEFORE apply_terminal_gesture at :2899. P3/P4 asserted only that the latch empties, so they would have passed while the child heard nothing --- the failure looking fixed because the bookkeeping looked right. Now ruled as TERMINATE, with a per-target completion effect (child release, or local terminal-selection completion, or the document completion SS5b already assigned here), a no-duplicate leg, and P3 written explicitly against the latch-only assertion. 2. The pending-release slot had an invariant and no ordering. The seam replays before it arms (daemon.rs:2608-2616), so a check inside arm_accepted_gesture could only fire after the new press had already reached the child. Drain order is now part of the ruling: before any subsequent panel-pointer effect, before detach teardown, before the next frame --- with an old-release-before-new-press row that reads the child's byte order, and the invariant demoted to a backstop. 3. The ground truth was knowingly false, and the workflow requires scouting before framing. RE-MEASURED at2c0d3ffinstead of deferred. Two clauses the old table called MISSING are DONE on this branch --- panel selection and terminal mouse reporting --- the vertical wheel works, and the horizontal wheel turns out to be an UNRULED gap sitting in a catch-all arm with no comment. Revision 15 names it rather than ruling it, because inventing a ruling inside a re-measurement is how an unexamined default becomes a decision. The72da24atable is kept as history. 4. "This lane MOVES the grade" was wrong against the authoritative scorecard. Step 5/GPU is floored Partial by 5(a) IME, so completing 5(c) cannot lift it, and step 8 is already Works on all three columns. The draft had read this section's MISSING column as if it were the scorecard; COHERENCE.md is the only thing that decides grades. Also drops a false TUI claim --- dispatch_semantic_panel_pointer has exactly two callers, both FrontendEvent arms, so only semantic legacy and mapped peers reach it --- and clears two merged-state contradictions: SS5b no longer says "Nothing implemented", and the lane no longer says the v26 correction is owed by 1b while the block below records SS5b making it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
parent
2c0d3ff907
commit
cda078fa91
|
|
@ -281,7 +281,8 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
|||
**`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 14 AWAITING APPROVAL;
|
||||
- **No PR yet. Checkpoint: framing revision 15 AWAITING APPROVAL
|
||||
(revision 14 was reviewed and had four blocking gaps, all answered);
|
||||
IMPLEMENTATION STILL PAUSED, now on approval rather than on a
|
||||
blocker.** §5a's replay contract is approved at revision 12; revision
|
||||
13 ruled Q#BP-R3 and blocked the lane on a protocol-bearing mapping
|
||||
|
|
@ -332,11 +333,15 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
|||
inverse mapping, stable across focus/styling/cursor/selection-only
|
||||
repaints so drags survive — as **appended** wire variants with
|
||||
bilateral gating.
|
||||
- **Chain: §5b (protocol) → panel replay → GUI arc 1b.** §5b takes the
|
||||
next protocol version, so **1e's `OpenTarget` moves to the one
|
||||
after**. **That edit is OWED BY THE 1b BRANCH**, which already
|
||||
revises `docs/gui-stage1-input-framing.md` (`:1011`, `:1221` still
|
||||
say v25); making it here would collide at 1b's scheduled rebase. Commit one was the ground-truth
|
||||
- **Chain: ~~§5b (protocol) →~~ panel replay → GUI arc 1b.** §5b took
|
||||
**v25**, so 1e's `OpenTarget` is **v26**. **That edit is NOT owed by
|
||||
the 1b branch** — this bullet said it was, and said making it here
|
||||
would collide at 1b's rebase. **§5b made it, in
|
||||
`docs/gui-stage1-input-framing.md`, and merged as #242**: a canonical
|
||||
document saying v25 is false the moment v25 is taken, and an expected
|
||||
rebase conflict was not grounds for leaving it wrong. Corrected here
|
||||
because this bullet and the merged-#242 block below it were saying
|
||||
opposite things. Commit one was the ground-truth
|
||||
re-measurement; 6 added the four replay edges; **7 answers review of
|
||||
6; **8 answers review of 7** — R-c is target × gesture-ORIGIN
|
||||
(terminals reject all chrome kinds and raw chrome coords fail the
|
||||
|
|
|
|||
|
|
@ -1968,30 +1968,84 @@ cannot preserve the old panel-focused attach leak.
|
|||
preserving the Stage 1 unknown-value rollback assertions; the Stage 3 PR
|
||||
then runs the full gate suite.
|
||||
|
||||
## 5a. Acceptance 48 — ground truth, MEASURED at `72da24a` (2026-08-14)
|
||||
## 5a. Acceptance 48 — ground truth, RE-MEASURED at `2c0d3ff` (2026-08-20)
|
||||
|
||||
**Status: revision 14 — AWAITING APPROVAL.** Revision 13 ruled Q#BP-R3
|
||||
**Status: revision 15 — AWAITING APPROVAL.** Revision 13 ruled Q#BP-R3
|
||||
and **blocked** this lane on a protocol-bearing mapping generation.
|
||||
That slice was framed as §5b, approved at revision 16, and **merged as
|
||||
#242 (`47b5463`)**, so **revision 13's block is DISCHARGED** and its
|
||||
ruling stands as history rather than as a gate. Revision 14 answers
|
||||
what the lane inherits from a substrate that changed underneath it:
|
||||
the meaning of the dispatcher's answer (**Q#BP-R4**, new), the rows
|
||||
§5b's split table assigned here, the cancellation record's missing
|
||||
resting place, four transitions that strand a live gesture, and a
|
||||
ground truth whose every anchor has moved. **The measurement date in
|
||||
this heading is now false and revision 14 owes its replacement.**
|
||||
ruling stands as history rather than as a gate. Revision 14 answered
|
||||
what the lane inherits from a substrate that changed underneath it.
|
||||
|
||||
**Revision 15 answers review of 14, and four of its five changes are
|
||||
corrections rather than additions:**
|
||||
|
||||
- **Q#BP-R4's release half was bookkeeping wearing an effect's
|
||||
clothes.** It said a chrome `Up` should "consume" the latch and
|
||||
claimed that prevents a child left button-down. It prevents nothing:
|
||||
the daemon drops the record, and terminal chrome returns before
|
||||
replay. Now ruled as **TERMINATE**, with the row asserting the
|
||||
child's release or the local selection's completion — and a
|
||||
no-duplicate leg.
|
||||
- **The pending-release slot had an invariant but no ordering.** The
|
||||
seam replays before it arms, so the invariant could only fire after
|
||||
the damage. **Drain order is now part of the ruling** — before any
|
||||
subsequent panel-pointer effect, before detach teardown, before the
|
||||
next frame — with an old-release-before-new-press row.
|
||||
- **The ground truth was knowingly false and is now RE-MEASURED**, at
|
||||
`2c0d3ff`, rather than deferred to implementation. Two clauses the
|
||||
old table called MISSING are DONE, and a third — the horizontal
|
||||
wheel — turns out to be an unruled gap.
|
||||
- **"This lane MOVES the grade" was wrong.** Step 5/GPU is floored
|
||||
`Partial` by 5(a) IME and step 8 is already `Works`; no journey cell
|
||||
moves. The draft had read this section's own MISSING column as if it
|
||||
were the scorecard.
|
||||
- Q#BP-R4 also **drops a false TUI claim**: only semantic legacy and
|
||||
mapped peers reach this dispatcher.
|
||||
|
||||
**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.
|
||||
that `PanelPointer` replayed nothing past focus. **That is no longer
|
||||
the state of this branch**, and the paragraph that said so — with the
|
||||
wheel "dead on both axes" — is superseded below. This lane has since
|
||||
landed the document and terminal replay, and §5b merged underneath it.
|
||||
1b still rebases onto this lane's merge.
|
||||
|
||||
**Acceptance 48 is not unimplemented — it is HALF implemented**, and
|
||||
the halves were never separated in writing. Measured clause by clause:
|
||||
**RE-MEASURED at `2c0d3ff`, the tip this revision was written against.**
|
||||
The 2026-08-14 measurement was taken at `72da24a`, **before this
|
||||
branch's own implementation commits and before §5b**, so it described
|
||||
neither the branch nor main. Every anchor in it had also moved. It is
|
||||
kept below as history; **this table is the current one**:
|
||||
|
||||
| clause | status at `2c0d3ff` | production anchor |
|
||||
|---|---|---|
|
||||
| click-to-focus | **DONE** | `activates` → `focus_window` (`src/editor.rs:2888`) |
|
||||
| terminal panel: non-`Move` activates, hover does neither | **DONE** | the same `activates`, split by `is_terminal` |
|
||||
| focused-only auto-scroll clamp; passive preserves `view_top` | **DONE** | `src/editor.rs:2698`, which cites "A2A-3 / parent 48" |
|
||||
| move/drag tails coalesce; press/release/context/wheel lossless and ordered | **DONE** | `coalesce_kind` (`pmacs-gpu/src/attach.rs:338`) |
|
||||
| **panel selection** | **DONE — was MISSING** | `replay_panel_document_gesture` (`src/editor.rs:2914`), called at `:2903`: `Down`/`Drag`/`Up(Left)`, shift-extend, double-click word select, right-press |
|
||||
| **terminal mouse reporting** | **DONE — was MISSING** | `apply_terminal_gesture` called at `src/editor.rs:2899`, viewport `content_rows` |
|
||||
| **wheel moves the panel's viewport** | **VERTICAL DONE — was MISSING** | `ScrollUp`/`ScrollDown` → `scroll_window` (`src/editor.rs:2925`) |
|
||||
| **horizontal wheel** | **INERT, AND UNRULED** | `ScrollLeft`/`ScrollRight` fall into the catch-all no-op arm (`src/editor.rs:3004`) **with no comment and no ruling** — the old table's "dead on both axes" became half-true without anyone deciding the other half |
|
||||
| **listview row selection** | **MISSING** | — no listview handling on the replay path; Q#BP-R1 ruled the semantics (single click selects only), and nothing implements them |
|
||||
| without disturbing the document mirror | **the constraint on all of the above** | — |
|
||||
|
||||
**Two findings the re-measurement produced**, neither of which a
|
||||
line-number patch would have surfaced:
|
||||
|
||||
- **The horizontal wheel is an unruled gap, not a deferral.** It sits
|
||||
in a catch-all arm beside `Move` and the non-left buttons, so it
|
||||
reads as deliberate and is not. **Revision 14 does not rule it** —
|
||||
it names it, because inventing a ruling inside a re-measurement is
|
||||
how an unexamined default becomes a decision.
|
||||
- **Two of the four "MISSING" effects are DONE on this branch.** The
|
||||
section had been telling every reader that replay does nothing while
|
||||
the branch it describes had implemented most of it.
|
||||
|
||||
### Superseded — the 2026-08-14 measurement at `72da24a`
|
||||
|
||||
Kept because it is what the lane was scoped against, and because two of
|
||||
its verdicts are now wrong rather than merely stale. Measured clause by
|
||||
clause:
|
||||
|
||||
| clause | status | production anchor |
|
||||
|---|---|---|
|
||||
|
|
@ -2687,14 +2741,50 @@ the pointer happens to be:
|
|||
|
||||
- **ARM** only on `Accepted` **and** `Down(Left)`. A chrome press
|
||||
begins nothing.
|
||||
- **CONSUME** on any `Up(Left)` that was **not `Refused`** — so
|
||||
`Accepted` **or** `Consumed`. A button-up over the mode line still
|
||||
ends the gesture; declining to consume it would strand the gesture
|
||||
and leave the child holding the button down, which is the same
|
||||
failure §5b's round 4 named. A **`Refused`** release is different in
|
||||
- **TERMINATE** on any `Up(Left)` that was **not `Refused`** — so
|
||||
`Accepted` **or** `Consumed`. A **`Refused`** release is different in
|
||||
kind: out-of-grid or wrong-buffer means the daemon cannot tell the
|
||||
event is even about this gesture, and §5b already pinned that it
|
||||
must not consume.
|
||||
event is even about this gesture, and §5b already pinned that it must
|
||||
not consume.
|
||||
|
||||
**"TERMINATE", not "consume", and the distinction is the whole of
|
||||
review finding 1.** An earlier draft of this ruling said consume, and
|
||||
justified it by claiming it prevents a child left button-down. **It
|
||||
prevents no such thing.** Emptying the latch is bookkeeping;
|
||||
`update_accepted_gesture` currently does `let _ =
|
||||
state.consume_accepted_gesture()` (`src/daemon.rs:1067`) — it **takes
|
||||
the record and drops it**. And on the path that matters, terminal
|
||||
chrome returns at `src/editor.rs:2862`–`:2870`, **before**
|
||||
`apply_terminal_gesture` at `:2899`, so the child is never told
|
||||
anything. A latch that empties while the child stays pressed is
|
||||
*exactly* the failure the draft claimed to prevent, now invisible
|
||||
because the bookkeeping looks right.
|
||||
|
||||
**RULED: a non-`Refused` `Up(Left)` must produce the target's
|
||||
completion effect, and the row asserts the EFFECT, not the latch.**
|
||||
|
||||
| target | required completion effect |
|
||||
|---|---|
|
||||
| terminal panel, child reporting on | the **release is reported to the child** — the same report an in-content `Up` produces, at the gesture's last content cell per R-c2 |
|
||||
| terminal panel, child reporting off | the **local terminal selection completes** — the selection the drag built is finalised, not abandoned |
|
||||
| document panel | the document gesture completes at the last content cell; an empty selection is cleared **without moving point** (the effect §5b's split table already assigns here) |
|
||||
|
||||
**And exactly once.** A completion delivered here must not be delivered
|
||||
again by a later cancellation of the same gesture, which is reachable
|
||||
because the four stranding transitions below can fire afterwards.
|
||||
|
||||
| # | mutation | must bite |
|
||||
|---|---|---|
|
||||
| P1 | chrome press returns `Accepted` | a chrome `Down(Left)` does not arm |
|
||||
| P2 | `Refused` treated as `Accepted` | §5b's four `g5_substrate_a_refused_*` rows |
|
||||
| P3 | chrome `Up` empties the latch but delivers **no** completion | the child-release / selection-completion row — **the latch-only assertion must NOT satisfy this** |
|
||||
| P4 | `Refused` release delivers a completion | a refused release leaves both the latch and the child untouched |
|
||||
| P5 | completion delivered, then a later cancellation delivers another | the no-duplicate-release row |
|
||||
|
||||
**P3 is written against the earlier draft's own weakness.** A row that
|
||||
asserts only `has_accepted_gesture() == false` passes while the child
|
||||
receives nothing, so the row must read the child's reported bytes or
|
||||
the terminal's selection state.
|
||||
|
||||
**That asymmetry is what earns the third state.** Under it, all three
|
||||
outcomes are behaviourally distinct at the latch, so each is
|
||||
|
|
@ -2710,12 +2800,18 @@ falsifiable:
|
|||
**R-c2 does not discharge P3.** The producer normalizes a release that
|
||||
lands on chrome back to the last content cell, so a conforming
|
||||
frontend should not send one — but the daemon's contract cannot rest
|
||||
on the producer's good behaviour, and a TUI or legacy peer reaches the
|
||||
same path. Producer-side normalization and daemon-side consumption are
|
||||
**both** required, and the existing GPU row
|
||||
on the producer's good behaviour, and **a legacy `PanelPointer` peer
|
||||
predates that normalization entirely**. Producer-side normalization and
|
||||
daemon-side termination are **both** required, and the existing GPU row
|
||||
(`a_press_on_the_bands_mode_line_neither_arms_nor_reports_content`)
|
||||
covers only the producer half.
|
||||
|
||||
**No TUI claim is made here.** An earlier draft said a TUI reaches the
|
||||
same path; it does not. `dispatch_semantic_panel_pointer` has exactly
|
||||
two callers, both `FrontendEvent` arms in `src/daemon.rs` (`:2609`,
|
||||
`:2680`), so **only semantic legacy and mapped peers reach it** — the
|
||||
TUI goes through `dispatch_mouse`.
|
||||
|
||||
#### The rows §5b's split table assigned here
|
||||
|
||||
§5b states its own split rather than leaving it to whoever runs the
|
||||
|
|
@ -2752,17 +2848,38 @@ dropped.
|
|||
**RULED: one pending-release SLOT per frontend, not a queue.** The
|
||||
latch holds at most one gesture per frontend, so at most one release
|
||||
can be owed at a time, and the slot is bounded by construction rather
|
||||
than by a cap someone has to choose. **The invariant is load-bearing
|
||||
and therefore owed a witness**: arming while a release is still
|
||||
pending must be impossible. If that witness fails, the slot is the
|
||||
wrong shape and this ruling is wrong — which is the point of asserting
|
||||
it rather than assuming it.
|
||||
than by a cap someone has to choose.
|
||||
|
||||
**AND THE DRAIN ORDER IS PART OF THE RULING, because an invariant alone
|
||||
is a detector, not a guard.** An earlier draft asserted only that
|
||||
arming over a pending release is impossible. That check would sit
|
||||
inside `arm_accepted_gesture` — and the seam replays **before** it:
|
||||
`dispatch_semantic_panel_pointer` runs its effects and only then does
|
||||
`update_accepted_gesture` arm (`src/daemon.rs:2608`–`:2616`). So the
|
||||
invariant can fail **only after the new press has already reached the
|
||||
child or moved the selection**. It would report the collision one
|
||||
effect too late.
|
||||
|
||||
**A pending termination DRAINS FIRST:**
|
||||
|
||||
1. **before any subsequent panel-pointer effect** for that frontend —
|
||||
the drain happens ahead of `dispatch_semantic_panel_pointer`, not
|
||||
after it, so the old gesture's release reaches the child before the
|
||||
new gesture's press does;
|
||||
2. **before detach teardown**, so a frontend that goes away does not
|
||||
take an owed release with it — detach is one of the four stranding
|
||||
transitions below, and it is the one with no later opportunity;
|
||||
3. **before the frontend's next frame is produced**, so a cancellation
|
||||
raised during projection cannot be overtaken by the frame that
|
||||
caused it.
|
||||
|
||||
| # | mutation | must bite |
|
||||
|---|---|---|
|
||||
| Q1 | drop the record instead of parking it | the cancelled-gesture release row |
|
||||
| Q2 | park it but never drain | the same row, from the delivery side |
|
||||
| Q3 | allow arming over a pending release | the invariant witness above |
|
||||
| Q3 | drain **after** `dispatch_semantic_panel_pointer` instead of before | the **old-release-before-new-press ordering row** — assert the child's byte stream carries the release ahead of the press, not merely that both arrive |
|
||||
| Q4 | skip the drain on detach | the detach row: an owed release is delivered before teardown |
|
||||
| Q5 | allow arming over a pending release | the invariant witness — kept, now as a **backstop** behind the ordering rows rather than as the guarantee |
|
||||
|
||||
#### Four transitions strand a live gesture, and they become defects HERE
|
||||
|
||||
|
|
@ -2804,10 +2921,19 @@ patch. A table that is right about *what* is missing and wrong about
|
|||
|
||||
- **Journey steps touched: 5** — Edit, clause (c) selection, kill and
|
||||
yank — **and 8** — Open terminal, clause (b) input and output
|
||||
round-trip. **Unlike §5b, this lane MOVES the grade.** §5b hardened
|
||||
steps that already worked; §5a's own table lists panel selection,
|
||||
listview row selection, terminal mouse reporting and the wheel as
|
||||
**MISSING**, and this lane is what supplies them.
|
||||
round-trip. **NO JOURNEY-CELL GRADE MOVES**, and an earlier draft
|
||||
claimed one. Checked against the authoritative scorecard rather than
|
||||
inferred from this section's own MISSING column:
|
||||
- **Step 5 / GPU is `Partial`, and stays `Partial`.** It is floored
|
||||
by **5(a)** — no IME, no `set_ime_allowed`, so composed and CJK
|
||||
input is impossible (`COHERENCE.md:462`). Completing 5(c) inside a
|
||||
panel cannot lift a cell held down by a different clause. That is
|
||||
§2a's aggregation rule working as designed.
|
||||
- **Step 8 is already `Works` on all three columns.** There is no
|
||||
grade left to move; 8(b) is hardened, not opened.
|
||||
- The draft's error was reading §5a's MISSING column as if it were
|
||||
the scorecard. **A section-local gap list is not a journey grade**,
|
||||
and the one place that decides grades is `COHERENCE.md`.
|
||||
- **Interaction islands: none added.** It **completes** the existing
|
||||
panel island rather than opening a new one — the same gestures the
|
||||
band already advertises, finally reaching their target.
|
||||
|
|
@ -2825,7 +2951,11 @@ which changes their return value and not their behaviour.
|
|||
|
||||
## 5b. The cell-mapping generation — a protocol slice (Q#BP-R3)
|
||||
|
||||
**Status: revision 16 — APPROVED 2026-08-15. Nothing implemented.**
|
||||
**Status: revision 16 — APPROVED 2026-08-15. IMPLEMENTED AND MERGED as
|
||||
#242 (`47b5463`), 2026-08-20.** The "Nothing implemented" this line
|
||||
carried until then was left behind by the merge; the slice's own
|
||||
"What the slice actually landed, row by row" subsection below had been
|
||||
contradicting it.
|
||||
Revision 16 answers review of 15; three of its items reverse a rule 15
|
||||
introduced:
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue