docs(framing): revise panel replay contract after review
Make the three-state panel-pointer result a pre-effect disposition and replace the competing latch matrices with one complete lifecycle table. Accepted tails now require a live gesture, accepted release replay and record-driven termination are mutually exclusive, and the witnesses cover stale tails plus immediate and later duplicate completion. Place projection-raised release delivery at the enforceable daemon boundary after semantic rendering returns and before its messages are written. Keep the arm invariant as a backstop behind pointer, detach, and frame-order witnesses. Split horizontal-wheel ground truth by terminal reporting/local and document targets. Record the missing document-panel effect explicitly under GUI Stage 1b B1--B3, update that framing's surface scope, and synchronize the active-work checkpoint.
This commit is contained in:
parent
cda078fa91
commit
1fc3af63de
|
|
@ -281,13 +281,15 @@ 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 15 AWAITING APPROVAL
|
||||
(revision 14 was reviewed and had four blocking gaps, all answered);
|
||||
- **No PR yet. Checkpoint: §5a framing revision 16 and its GUI Stage
|
||||
1b revision-13 ownership amendment AWAITING APPROVAL (revision 15
|
||||
was reviewed, corrected and folded into this branch);
|
||||
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
|
||||
generation; **that block is DISCHARGED** — the slice merged as #242
|
||||
(`47b5463`).
|
||||
blocker.** §5a's **pre-merge** replay contract was approved at
|
||||
revision 12; revisions 14–16 are the post-merge amendment now under
|
||||
review. Revision 13 ruled Q#BP-R3 and blocked the lane on a
|
||||
protocol-bearing mapping generation; **that block is DISCHARGED** —
|
||||
the slice merged as #242 (`47b5463`).
|
||||
- **MERGED main into this branch** at `b758c2e` rather than rebasing:
|
||||
the lane's 12 commits include 10 framing revisions over the same
|
||||
800–1000 line doc regions, so a rebase meant twelve rounds of
|
||||
|
|
@ -314,14 +316,22 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
|||
§5b and this lane gave `dispatch_semantic_panel_pointer`'s `bool`
|
||||
different meanings — accepted-as-a-gesture versus consumed-here. A
|
||||
mode-line press therefore **arms the latch** on this branch today.
|
||||
**Q#BP-R4** rules a three-state `PanelPointerOutcome`, with an
|
||||
asymmetric latch rule: arm only on `Accepted` + `Down(Left)`,
|
||||
consume on any `Up(Left)` that was not `Refused`.
|
||||
- **Revision 14 also carries** the rows §5b's split table assigned
|
||||
here, a **pending-release slot** for the cancellation record §5b
|
||||
leaves nowhere to wait, the **four transitions** that strand a live
|
||||
gesture once effects attach, and a **re-measurement obligation**:
|
||||
every production anchor in §5a has moved, evidenced in the revision.
|
||||
**Q#BP-R4** rules a three-state `PanelPointerOutcome`, classified
|
||||
**before** target effects. Only an `Accepted` `Down(Left)` arms;
|
||||
left `Drag`/`Up` require a live record; an accepted `Up` performs
|
||||
ordinary replay once, a consumed/chrome `Up` performs the recorded
|
||||
completion once, and a refused `Up` preserves the record.
|
||||
- **Revision 16 carries** the rows §5b's split table assigned here, a
|
||||
**pending-release slot** for the cancellation record §5b leaves
|
||||
nowhere to wait, and the **four transitions** that strand a live
|
||||
gesture once effects attach. Drain order is executable: before the
|
||||
next panel-pointer effect; before detach teardown; and, for a
|
||||
projection-raised cancellation, after `render_frame` returns but
|
||||
before any returned message is written. Ground truth is re-measured
|
||||
at `2c0d3ff`. Document-panel horizontal scrolling is a named deferral
|
||||
to GUI Stage 1b B1–B3; a horizontal tick whose terminal precedence
|
||||
selects child reporting already emits SGR, and the local terminal
|
||||
branch has no horizontal viewport effect.
|
||||
- **THE BLOCKER, and why the earlier acceptance failed.** A
|
||||
`PanelPointer` names a cell; nothing on the wire says which inverse
|
||||
mapping the frontend saw, so the daemon inverts against whatever is
|
||||
|
|
@ -387,32 +397,26 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
|||
**controller identity** catches the shared-path mutation, since
|
||||
`apply_terminal_gesture` claims at `src/editor.rs:3571` before local
|
||||
handling and activation alone claims nothing.
|
||||
- **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.**
|
||||
- **Why this lane exists, re-measured at `2c0d3ff`.** The branch now
|
||||
replays document selection, terminal mouse reporting and vertical
|
||||
wheels; the remaining acceptance-48 effect is **listview row
|
||||
selection**. Q#BP-R4 and §5b's inherited rows still need
|
||||
implementation: pre-effect disposition/latch ordering, fixed-domain
|
||||
gesture tails, exact-once termination, cancellation effects and the
|
||||
pending-release drains. **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 (`:2568`–`:2571`, 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.
|
||||
- **Current clause split.** DONE: click/focus and terminal activation;
|
||||
focused-only auto-scroll with passive `view_top` preserved; lossless
|
||||
and coalesced event delivery; panel document selection; terminal
|
||||
child reporting/local selection; vertical document and terminal
|
||||
wheel effects. MISSING here: listview row selection and the
|
||||
lifecycle/cancellation effects above. Horizontal wheel is split:
|
||||
child-reporting terminal ticks already emit codes 66/67; the local
|
||||
terminal branch is deliberately inert; document-panel `view_left`
|
||||
is explicitly GUI Stage 1b B1–B3's effect, matching the production
|
||||
comment in `src/editor.rs:2999`–`:3003`.
|
||||
- **The scoping hazard.** `set_cursor_byte` (`src/editor_core.rs:1216`),
|
||||
`begin_selection` (`:4691`) and `clear_selection` are
|
||||
**active-window scoped**; used naively they would move the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
# Bottom panel — framing (window placement + side windows)
|
||||
|
||||
**Revision 16 — 2026-08-20, AWAITING APPROVAL.** Revision 16 closes
|
||||
review of 15: Q#BP-R4 is one pre-effect disposition/gesture-lifecycle
|
||||
table; projection-raised releases drain after `render_frame` returns
|
||||
and before its messages are written; horizontal-wheel ground truth is
|
||||
split by target/domain and the missing document effect is explicitly
|
||||
owned by GUI Stage 1b; superseded current-state text is removed from
|
||||
this section and the active-work ledger.
|
||||
|
||||
**Revision 4 — pre-implementation, DRAFT after review round 3 plus landed-state
|
||||
audit. Ground truth: canonical `main` @ `ddaa80d` (documentation landing #152;
|
||||
runtime @ `0dd16a5`, GPU initial target / #148 after folding Stage 2 / #149),
|
||||
|
|
@ -7,7 +15,7 @@ protocol v20, 2026-07-24. Amended by the pre-implementation dependency
|
|||
verification in §0.6: the folding dependency is cleared, and one geometry
|
||||
caller-census error is corrected.**
|
||||
|
||||
**Revision 13 — 2026-08-14, AWAITING APPROVAL. Q#BP-R3 is OVERRULED:
|
||||
**Previously, revision 13 — 2026-08-14. Q#BP-R3 was OVERRULED:
|
||||
the lane BLOCKS on a protocol-bearing cell-mapping generation (new
|
||||
§5b).** Revision 12 accepted current-state hit semantics on three
|
||||
bounds, and all three were wrong — a **foreign** edit moves the mapping
|
||||
|
|
@ -1970,13 +1978,22 @@ cannot preserve the old panel-focused attach leak.
|
|||
|
||||
## 5a. Acceptance 48 — ground truth, RE-MEASURED at `2c0d3ff` (2026-08-20)
|
||||
|
||||
**Status: revision 15 — AWAITING APPROVAL.** Revision 13 ruled Q#BP-R3
|
||||
**Status: revision 16 — 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 answered
|
||||
what the lane inherits from a substrate that changed underneath it.
|
||||
|
||||
**Revision 16 closes review of 15.** It replaces the two competing
|
||||
Q#BP-R4 matrices with one pre-effect disposition/lifecycle table;
|
||||
names the projection drain at the only enforceable seam — after
|
||||
`render_frame` returns and before its messages are written; splits
|
||||
horizontal-wheel ground truth by target and gesture domain; records
|
||||
GUI Stage 1b as the owner of document-panel horizontal scrolling; and
|
||||
removes revision 14's now-false remeasurement obligation from the live
|
||||
section and ledger.
|
||||
|
||||
**Revision 15 answers review of 14, and four of its five changes are
|
||||
corrections rather than additions:**
|
||||
|
||||
|
|
@ -1995,7 +2012,8 @@ corrections rather than additions:**
|
|||
- **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.
|
||||
wheel — exposed an ownership gap that revision 16 now splits and
|
||||
assigns explicitly.
|
||||
- **"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
|
||||
|
|
@ -2024,19 +2042,24 @@ kept below as history; **this table is the current one**:
|
|||
| 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 |
|
||||
| **vertical wheel moves the panel's viewport** | **DONE — was MISSING** | document `ScrollUp`/`ScrollDown` → `scroll_window` (`src/editor.rs:2925`); reporting and local terminal paths share `apply_terminal_gesture` |
|
||||
| **horizontal wheel, terminal precedence selects child reporting** | **RECEIVER DONE; PRODUCER AWAITS GUI 1b** | `apply_terminal_gesture` reaches `encode_mouse`, whose `ScrollLeft`/`ScrollRight` codes are 66/67 (`src/terminal/input.rs:130`–`:131`) |
|
||||
| **horizontal wheel, terminal precedence selects local handling** | **RULED INERT** | Shift, reporting-off or a scrolled-back view can select the local branch; terminal scrollback is vertical and there is no local horizontal viewport, so the shared path deliberately has no `ScrollLeft`/`ScrollRight` arm |
|
||||
| **horizontal wheel, document panel** | **NAMED DEFERRAL: GUI Stage 1b B1–B3** | `ScrollLeft`/`ScrollRight` are claimed and dropped at `src/editor.rs:3004`; the comment at `:2999`–`:3003` already assigns horizontal panel scrolling to 1b, whose framing now explicitly includes the panel-document surface |
|
||||
| **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.
|
||||
- **"Horizontal wheel" was not one verdict.** A tick for which terminal
|
||||
precedence selects child reporting already sends the horizontal SGR
|
||||
code; the local terminal branch has no horizontal viewport to move;
|
||||
only a document panel lacks an effect. That last leg is a **named
|
||||
deferral to GUI Stage 1b B1–B3**,
|
||||
not an unexplained catch-all: 1b owns horizontal tick production,
|
||||
sign, per-surface residuals and the window-targeted `view_left`
|
||||
effect. The panel-replay lane remains 1b's prerequisite.
|
||||
- **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.
|
||||
|
|
@ -2694,7 +2717,7 @@ R-d's orphan is distinct from R-b's: **R-b's arrives from a passive
|
|||
panel, R-d's from a replaced or re-declared one**, and an
|
||||
implementation can fix either alone.
|
||||
|
||||
### Revision 14 — what §5b changed underneath this lane
|
||||
### Revisions 14–16 — what §5b changed underneath this lane
|
||||
|
||||
#### Q#BP-R4 — what does `dispatch_semantic_panel_pointer`'s answer MEAN? **RULED: a three-state outcome, not a bool**
|
||||
|
||||
|
|
@ -2722,30 +2745,49 @@ fixed, re-entering by merge rather than by edit.
|
|||
| **a three-state outcome** | **RULED** |
|
||||
|
||||
```rust
|
||||
/// What the dispatcher did with a panel gesture.
|
||||
/// How an authenticated panel event relates to the authoritative
|
||||
/// panel surface, decided BEFORE any target effect.
|
||||
pub enum PanelPointerOutcome {
|
||||
/// Neither this panel's nor well-formed: no grid, out of grid, no
|
||||
/// side window, or a buffer that is not the one shown there.
|
||||
/// Not addressable as this panel: no grid, out of grid, no side
|
||||
/// window, or a buffer that is not the one shown there.
|
||||
Refused,
|
||||
/// This panel's, and handled HERE deliberately --- the chrome
|
||||
/// swallows of Q#BP-R2 and R-c. Not a content gesture.
|
||||
/// This panel owns the cell/event, but it is deliberately not a
|
||||
/// content gesture --- the chrome claims of Q#BP-R2 and R-c.
|
||||
Consumed,
|
||||
/// Reached the target as a content gesture.
|
||||
/// A content gesture for the resolved target.
|
||||
Accepted,
|
||||
}
|
||||
```
|
||||
|
||||
**The latch rule, and it is NOT "arm and consume on `Accepted`".** The
|
||||
two halves are asymmetric, because a release ends a gesture wherever
|
||||
the pointer happens to be:
|
||||
**The outcome is a DISPOSITION, not proof that an effect already ran.**
|
||||
It is decided before replay. The current function combines validation,
|
||||
classification and mutation, but that ordering cannot implement §5b's
|
||||
stale-tail rule: an `Up` or `Drag` with no accepted `Down` has already
|
||||
reached the child/selection before the daemon consults the latch. The
|
||||
implementation may split the function into classify/apply helpers or
|
||||
use an equivalent single wrapper, but these two facts are fixed:
|
||||
|
||||
- **ARM** only on `Accepted` **and** `Down(Left)`. A chrome press
|
||||
begins nothing.
|
||||
- **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.
|
||||
1. the editor remains the **only** authority that derives
|
||||
`Refused`/`Consumed`/`Accepted`; the daemon never re-derives chrome,
|
||||
target kind or content bounds;
|
||||
2. disposition and the live-gesture check both complete **before** a
|
||||
left `Drag`/`Up` target effect.
|
||||
|
||||
**One transition table is authoritative:**
|
||||
|
||||
| event | `Refused` | `Consumed` | `Accepted` |
|
||||
|---|---|---|---|
|
||||
| `Down(Left)` | no effect; do not arm | no target effect; do not arm | apply the content press, then arm **from the effect result** so target/domain/encoding and `reached_child` describe what actually happened |
|
||||
| `Drag(Left)` | no effect; retain any live record | no target effect; retain any live record | no live record → inert; live record → continue in the **recorded domain**, update its last valid content cell |
|
||||
| `Up(Left)` | no effect; retain any live record for a later authoritative cancellation | no live record → inert; live record → deliver the **recorded completion** at its last valid content cell, then take it | no live record → inert; live record → apply the ordinary in-content completion **once**, then take it; do **not** also run recorded completion |
|
||||
| every other kind | no effect; no latch change | no target effect; no latch change | apply its one-shot content effect; never arm or consume the left-gesture latch |
|
||||
|
||||
This is the required asymmetry. A chrome press begins nothing. A
|
||||
chrome release can end a live gesture, but a refused release cannot be
|
||||
known to concern it. An accepted release already performs the ordinary
|
||||
target effect; a consumed release has not, so it terminates from the
|
||||
record. A stale `Drag`/`Up` with no accepted `Down` is inert rather than
|
||||
sending a child tail or changing selection.
|
||||
|
||||
**"TERMINATE", not "consume", and the distinction is the whole of
|
||||
review finding 1.** An earlier draft of this ruling said consume, and
|
||||
|
|
@ -2760,42 +2802,42 @@ 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.**
|
||||
**RULED: a live gesture plus non-`Refused` `Up(Left)` must produce the
|
||||
target's completion effect exactly once, 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 on | the **release is reported to the child in the recorded encoding** — an accepted content `Up` uses its accepted cell; a consumed/chrome `Up` uses 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.
|
||||
**And exactly once.** An accepted `Up` must not replay normally and
|
||||
then also run the record-driven completion. Any completion must take
|
||||
the record, so a later cancellation of the same gesture — reachable
|
||||
through the four stranding transitions below — cannot repeat it.
|
||||
|
||||
| # | 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 |
|
||||
| P2 | `Refused` treated as `Accepted` | §5b's four `g5_substrate_a_refused_*` rows plus their no-target-effect assertions |
|
||||
| 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 |
|
||||
| P5 | an accepted content `Up` replays normally **and** invokes record-driven completion | the exact child stream contains one release, not two |
|
||||
| P6 | completion delivered, then a later cancellation delivers another | the no-duplicate-release row |
|
||||
| P7 | an accepted `Up` with no live record reaches the target | the stale-release row: no child bytes and no local/document selection mutation |
|
||||
| P8 | an accepted `Drag` with no live record reaches the target | the orphan-drag row: no child bytes and no cursor/selection mutation |
|
||||
|
||||
**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
|
||||
falsifiable:
|
||||
|
||||
| # | 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 | `Consumed` treated as `Refused` for `Up` | a chrome `Up(Left)` consumes a live gesture |
|
||||
| P4 | consume gated on `Accepted` alone | the same chrome-release row as P3, from the other side |
|
||||
**That asymmetry is what earns the third state.** `Refused` preserves a
|
||||
live gesture, `Consumed` owns the surface but runs only a recorded
|
||||
completion, and `Accepted` reaches content. Each is behaviourally
|
||||
distinct at the effect/lifecycle seam, and the single matrix above is
|
||||
the witness contract.
|
||||
|
||||
**R-c2 does not discharge P3.** The producer normalizes a release that
|
||||
lands on chrome back to the last content cell, so a conforming
|
||||
|
|
@ -2869,9 +2911,15 @@ effect too late.
|
|||
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.
|
||||
3. **after semantic projection returns and before any message it
|
||||
returned is filtered or written.** Mapping cancellation is
|
||||
discovered *inside* `SemanticRenderState::render_frame`, while the
|
||||
successor `PresentMapped` is being constructed, so "before that
|
||||
frame is produced" is impossible. The enforceable daemon seam is
|
||||
immediately after `sem.render_frame(editor)` returns
|
||||
(`src/daemon.rs:1428`–`:1430`) and before `for msg in &messages`
|
||||
(`:1591`). The pending termination drains there, so the successor
|
||||
frame cannot overtake the release its new mapping required.
|
||||
|
||||
| # | mutation | must bite |
|
||||
|---|---|---|
|
||||
|
|
@ -2879,7 +2927,8 @@ effect too late.
|
|||
| Q2 | park it but never drain | the same row, from the delivery side |
|
||||
| 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 |
|
||||
| Q5 | enter the returned-message write loop before draining a projection-raised release | the daemon-order witness records the termination effect before the first successor-frame write |
|
||||
| Q6 | 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
|
||||
|
||||
|
|
@ -2899,23 +2948,13 @@ motion. The daemon side has the same shape and needs the same
|
|||
independently discriminating legs rather than one shared "resets
|
||||
something" assertion.
|
||||
|
||||
#### The ground truth must be RE-MEASURED, and this is evidenced
|
||||
#### Re-measurement closed in revision 16
|
||||
|
||||
This section's heading says `72da24a`. **Every production anchor in it
|
||||
has moved**, measured at `b758c2e`:
|
||||
|
||||
| §5a claims | actually |
|
||||
|---|---|
|
||||
| `dispatch_semantic_panel_pointer` at `src/editor.rs:2674` | `:2809` |
|
||||
| `apply_terminal_gesture` at `src/editor.rs:3525` | `:3875` |
|
||||
| `scroll_window` at `src/editor.rs:3845` | `:4195` |
|
||||
| `Absent` clears the latch at `pmacs-gpu/src/main.rs:6909` | `:7206` |
|
||||
|
||||
**The clause table itself is NOT assumed to have survived.** §5b
|
||||
rewrote the dispatcher this lane measured, so each DONE/MISSING verdict
|
||||
is owed a re-measurement before implementation, not a line-number
|
||||
patch. A table that is right about *what* is missing and wrong about
|
||||
*where* is the kind of record that gets trusted and then misleads.
|
||||
The authoritative clause table is now the `2c0d3ff` table at the start
|
||||
of §5a. The `72da24a` table is retained only under its explicit
|
||||
**Superseded** heading. Revision 14's line-movement inventory did its
|
||||
job by forcing a clause-by-clause scout; it is no longer a live
|
||||
implementation obligation.
|
||||
|
||||
#### Coherence impact (`COHERENCE.md` §20)
|
||||
|
||||
|
|
@ -2926,11 +2965,12 @@ patch. A table that is right about *what* is missing and wrong about
|
|||
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
|
||||
input is impossible (`COHERENCE.md:468`). 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.
|
||||
- **Step 8 is already `Works` on all three columns**
|
||||
(`COHERENCE.md:471`). 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`.
|
||||
|
|
@ -2941,7 +2981,7 @@ patch. A table that is right about *what* is missing and wrong about
|
|||
- **Background work: none started**, and no existing attribution
|
||||
changes.
|
||||
|
||||
#### What revision 14 does NOT do
|
||||
#### What revisions 14–16 do NOT reopen
|
||||
|
||||
It does not re-open Q#BP-R1 (single click selects only), Q#BP-R2 (a
|
||||
terminal panel's chrome wheel is consumed, not clamped), or R-a/R-b/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
# GUI arc, Stage 1 — input foundation (framing)
|
||||
|
||||
**Status: revision 12 — APPROVED.** Revision 12 is §2's ground-truth
|
||||
**Status: revision 13 — AWAITING APPROVAL with bottom-panel §5a
|
||||
revision 16.** Revision 13 changes no previously ruled outcome. It
|
||||
makes B1–B3's “per surface” scope explicit for the panel-document
|
||||
surface, closing the ownership gap exposed by §5a's remeasurement:
|
||||
panel replay is the prerequisite, while GUI 1b owns horizontal tick
|
||||
production, residuals and the document-panel `view_left` effect.
|
||||
|
||||
**Previously, revision 12 — APPROVED.** Revision 12 is §2's ground-truth
|
||||
re-measurement for Stage 1a and changes no ruling; it carries two
|
||||
corrections to claims that were wrong at the original anchor too.
|
||||
|
||||
|
|
@ -308,9 +315,9 @@ The crate has **exactly one** executable `event_loop.exit()`, in
|
|||
|
||||
| # | Contract | Witness | Mutation |
|
||||
|---|---|---|---|
|
||||
| B1 | Residual per **axis and surface** | deltas discarded | share one accumulator → surface-switch jump |
|
||||
| B2 | Wheel-right raises leftmost column; wheel-down raises top line | `x` discarded | invert a sign → that axis's row |
|
||||
| B3 | Clamps at content bounds; never a negative origin | no horizontal scroll to clamp | remove clamp → **at-bounds row: origin goes negative and the view blanks** |
|
||||
| B1 | Residual per **axis and surface** — primary document, panel document and minimap are distinct owners | deltas discarded | share one accumulator → primary↔panel or document↔minimap surface-switch jump |
|
||||
| B2 | Wheel-right raises the leftmost column of the **document surface under the pointer**; wheel-down raises its top line. Primary-document horizontal state stays frontend-local; a panel-document tick reaches the daemon's window-targeted `view_left` path | `x` discarded; panel replay currently claims and drops document `ScrollLeft`/`ScrollRight` | invert a sign → that axis's row; omit the panel effect → primary moves while the panel remains inert |
|
||||
| B3 | Each document surface clamps at its own content bounds; never a negative origin, and wrap pins horizontal origin to zero | no horizontal scroll to clamp | remove a clamp → **at-bounds row: that surface's origin goes negative and the view blanks**; reuse primary bounds for a panel → unequal-width surface row fails |
|
||||
| B4 | Middle-click paste uses **PRIMARY on Linux** | no middle-click path | use `CLIPBOARD` → B4 only |
|
||||
| B5 | I-beam over text content only | no I-beam | extend over the gutter → B5 only |
|
||||
| B6 | Wheel over the minimap scrolls the **document viewport** with **its own residual accumulator**; click/drag remains scrub | **a FULL tick already scrolls today** — minimap pixels are `Elsewhere` (`main.rs:2061`) and the wheel falls through to `scroll_by_lines` (`main.rs:3373`). What fails is **fractional accumulation**, and **residual ownership distinct from the document's**: sub-tick minimap deltas are discarded, and a **surface-switch fractional witness** (part-tick over the minimap, then over the document) must not carry residue across | share the document's accumulator → the surface-switch fractional row jumps |
|
||||
|
|
@ -322,6 +329,18 @@ blank**. The bound is *width − viewport*, saturating at zero for buffers
|
|||
narrower than the viewport, and **the right-bound witness asserts the
|
||||
final display column is still visible**.
|
||||
|
||||
**Panel-replay consequence, ruled after §5a's 2026-08-20
|
||||
re-measurement.** “Horizontal panel wheel” has three receiver outcomes,
|
||||
not one. When terminal precedence selects child reporting it already
|
||||
forwards `ScrollLeft` and `ScrollRight` as SGR codes 66/67. The local
|
||||
terminal branch — selected by Shift, reporting-off or a scrolled-back
|
||||
view — has no horizontal viewport and remains inert. **B1–B3 own the missing
|
||||
document-panel leg**: fractional production/residuals in the GPU, the
|
||||
lossless `PanelPointer` tick, and the daemon's window-targeted
|
||||
`view_left` effect and clamp. This is a named deferral from panel replay,
|
||||
whose source comment already assigned it here; it does not make the
|
||||
prerequisite lane implement half of 1b early.
|
||||
|
||||
**Why B6 changed — and revision 5's reason was wrong.** Scrubbing on
|
||||
wheel is not *impossible*: the wheel handler already reads the cached
|
||||
`state.pointer_pos` for surface routing (`main.rs:3337`), so an absolute
|
||||
|
|
|
|||
Loading…
Reference in New Issue