test(panel): Q5 --- the projection-seam drain, witnessed
Closes the gap recorded through tasks 18 and 19. The third drain sits inside the daemon's per-frontend frame loop, which no unit row could enter, so it was written down as owed rather than assumed covered by its neighbours. The seam is now `project_semantic_frame`, extracted from that loop. It returns its messages UNWRITTEN, and that is what makes the ordering assertable: a caller holding them has by construction not sent the successor frame, so a release already delivered at that moment provably precedes it rather than merely arriving alongside it. The row arms a gesture on a reporting terminal, takes the panel away so publish_absent_panel cancels from inside projection, calls the seam, and asserts the child already has the release while the successor frame is still in the caller's hands. It bites its own drain and no other: removing the drain from the seam fails Q5 while Q1-Q4 stay green on the effect and detach drains. Grid sessions no longer reach the drain at all --- they hold no panel and no gesture --- which is tighter than the previous per-fid call. Also folds in the reported prose typo, and records the gate's precondition: a foreign C++/java build has been at load 114+ through this work, and the three wall-clock rows that redded under it were green in isolation every time. Running the gate into that would manufacture another U6/U9/U10 rotating-red incident. 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
70999e22ac
commit
85946bf9b6
|
|
@ -353,10 +353,13 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
||||||
and with that assert compiled out the byte-order assertion
|
and with that assert compiled out the byte-order assertion
|
||||||
catches the same defect — which is what a release build relies
|
catches the same defect — which is what a release build relies
|
||||||
on.
|
on.
|
||||||
- **Q5 is OWED.** The projection-seam drain needs a row that drives
|
- **Q5 is CLOSED.** The projection seam is extracted as
|
||||||
the real per-frontend frame loop; the unit rows call
|
`project_semantic_frame`, which returns its messages **unwritten**
|
||||||
`render_frame` directly and never enter it. Recorded rather than
|
— so a caller holding them has by construction not sent the
|
||||||
treated as covered by its neighbours.
|
successor frame, and a release already delivered at that moment
|
||||||
|
provably precedes it. The row bites its own drain and no other:
|
||||||
|
removing it fails Q5 while Q1–Q4 stay green on the other two
|
||||||
|
drain points.
|
||||||
- **LANDED: the authority-loss matrix (task 19).** §5b wired `Absent`
|
- **LANDED: the authority-loss matrix (task 19).** §5b wired `Absent`
|
||||||
and left the other four transitions armed — inert while nothing
|
and left the other four transitions armed — inert while nothing
|
||||||
consumed the latch, defects the moment cancellation gained an
|
consumed the latch, defects the moment cancellation gained an
|
||||||
|
|
@ -372,8 +375,7 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
||||||
cancellation, which a mutation confirms it catches. The count is
|
cancellation, which a mutation confirms it catches. The count is
|
||||||
asserted in the row, because a loop that quietly stops covering a
|
asserted in the row, because a loop that quietly stops covering a
|
||||||
combination passes exactly as loudly as one that covers them all.
|
combination passes exactly as loudly as one that covers them all.
|
||||||
Each quadrant **drains
|
Each quadrant **drains explicitly and asserts the effect** — the exact release bytes
|
||||||
explicitly** and asserting the effect — the exact release bytes
|
|
||||||
for a reporting terminal, the cleared empty selection for a
|
for a reporting terminal, the cleared empty selection for a
|
||||||
document, and an empty slot afterwards. An earlier version
|
document, and an empty slot afterwards. An earlier version
|
||||||
stopped at `has_pending_release()` and would have passed while
|
stopped at `has_pending_release()` and would have passed while
|
||||||
|
|
@ -404,8 +406,15 @@ from #171 and #215 — the correction the 1b lane missed, honoured here.
|
||||||
gone, so the completion has nothing left to clear and the
|
gone, so the completion has nothing left to clear and the
|
||||||
gesture ending is the whole effect. Written into the row rather
|
gesture ending is the whole effect. Written into the row rather
|
||||||
than left as a silently absent assertion.
|
than left as a silently absent assertion.
|
||||||
- **REMAINING:** Q5's acceptance-shaped row, then the full head-exact
|
- **REMAINING: the full head-exact gate, then the PR.** The gate
|
||||||
gate and the PR.
|
wants a QUIET machine: a foreign C++/java build has been running at
|
||||||
|
load 114+ through this work, and the wall-clock rows
|
||||||
|
(`composition_overhead_under_ten_percent`,
|
||||||
|
`m6_2_pty_streaming_respects_byte_ceiling`,
|
||||||
|
`full_buffer_summary_flatten_scales_on_large_grammar_file`) redded
|
||||||
|
under it and were green in isolation every time. That is U6/U9/U10
|
||||||
|
territory and running the gate into it would manufacture another
|
||||||
|
rotating-red incident.
|
||||||
- **Two test seams added for this:** an opt-in child-input tap
|
- **Two test seams added for this:** an opt-in child-input tap
|
||||||
(`start_send_tap_for_test`) and a drag-state read
|
(`start_send_tap_for_test`) and a drag-state read
|
||||||
(`view_is_dragging_for_test`). Nothing else exposes what the child
|
(`view_is_dragging_for_test`). Nothing else exposes what the child
|
||||||
|
|
|
||||||
107
src/daemon.rs
107
src/daemon.rs
|
|
@ -1019,6 +1019,36 @@ fn panel_event_epochs_are_current(
|
||||||
.is_some_and(|geometry| geometry.geometry_epoch == geometry_epoch)
|
.is_some_and(|geometry| geometry.geometry_epoch == geometry_epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Project one SEMANTIC frontend's frame, paying any release that
|
||||||
|
/// projection itself raised before the caller can write the result
|
||||||
|
/// (parent 48, drain point three).
|
||||||
|
///
|
||||||
|
/// **The seam exists because the cancellation happens too deep to pay
|
||||||
|
/// itself.** A mapping-generation advance cancels the live gesture
|
||||||
|
/// INSIDE `render_frame`, while the successor `PresentMapped` is still
|
||||||
|
/// being built, so "before that frame is produced" is not a place that
|
||||||
|
/// exists. This is the first place that is: projection has returned,
|
||||||
|
/// and none of what it returned has been written.
|
||||||
|
///
|
||||||
|
/// Returning the messages UNWRITTEN is what makes the ordering
|
||||||
|
/// testable — a caller holding them has, by construction, not yet sent
|
||||||
|
/// the successor frame, so a release already delivered at that moment
|
||||||
|
/// provably precedes it.
|
||||||
|
///
|
||||||
|
/// Grid sessions do not come here: they hold no panel and no gesture.
|
||||||
|
fn project_semantic_frame(
|
||||||
|
editor: &mut EditorState,
|
||||||
|
semantic_states: &mut HashMap<FrontendId, crate::semantic_render::SemanticRenderState>,
|
||||||
|
fid: FrontendId,
|
||||||
|
) -> Vec<InstanceMessage> {
|
||||||
|
let messages = semantic_states
|
||||||
|
.get_mut(&fid)
|
||||||
|
.map(|sem| sem.render_frame(editor))
|
||||||
|
.unwrap_or_default();
|
||||||
|
drain_pending_release(editor, semantic_states, fid);
|
||||||
|
messages
|
||||||
|
}
|
||||||
|
|
||||||
/// Deliver the release this frontend is owed, if any (parent 48).
|
/// Deliver the release this frontend is owed, if any (parent 48).
|
||||||
///
|
///
|
||||||
/// **Order is the ruling, not just the existence of a slot.** A
|
/// **Order is the ruling, not just the existence of a slot.** A
|
||||||
|
|
@ -1578,8 +1608,8 @@ fn dispatcher_loop(
|
||||||
// out locally); it still receives `CursorByte` below
|
// out locally); it still receives `CursorByte` below
|
||||||
// (semantic implies `crdt_replica`) and participates in
|
// (semantic implies `crdt_replica`) and participates in
|
||||||
// presence. A grid session takes the M5.2 cell path.
|
// presence. A grid session takes the M5.2 cell path.
|
||||||
let messages = if let Some(sem) = semantic_states.get_mut(fid) {
|
let messages = if semantic_states.contains_key(fid) {
|
||||||
sem.render_frame(editor)
|
project_semantic_frame(editor, &mut semantic_states, *fid)
|
||||||
} else {
|
} else {
|
||||||
// T M10.9 — gather other-frontend presences for the
|
// T M10.9 — gather other-frontend presences for the
|
||||||
// overlay paint. Reads `last_broadcast` (updated by
|
// overlay paint. Reads `last_broadcast` (updated by
|
||||||
|
|
@ -1597,16 +1627,6 @@ fn dispatcher_loop(
|
||||||
render_state.render_frame(editor, *fid, &terminal_snapshots, &other_presences)
|
render_state.render_frame(editor, *fid, &terminal_snapshots, &other_presences)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parent 48 — THE PROJECTION SEAM. A mapping-generation
|
|
||||||
// advance cancels the live gesture INSIDE `render_frame`,
|
|
||||||
// while the successor `PresentMapped` is still being built,
|
|
||||||
// so "before that frame is produced" is not a place that
|
|
||||||
// exists. This is the first point that is: projection has
|
|
||||||
// returned and none of what it returned has been written.
|
|
||||||
// Draining here keeps the release ahead of the frame whose
|
|
||||||
// own new mapping is what required it.
|
|
||||||
drain_pending_release(editor, &mut semantic_states, *fid);
|
|
||||||
|
|
||||||
// Vterm Stage 3 — a semantic frontend showing a terminal has
|
// Vterm Stage 3 — a semantic frontend showing a terminal has
|
||||||
// no document cursor: the identity buffer is empty, so a
|
// no document cursor: the identity buffer is empty, so a
|
||||||
// `CursorByte` would describe byte 0 of a buffer with no
|
// `CursorByte` would describe byte 0 of a buffer with no
|
||||||
|
|
@ -8740,6 +8760,69 @@ mod tests {
|
||||||
// rather than unit shaped. Recorded as OWED rather than assumed
|
// rather than unit shaped. Recorded as OWED rather than assumed
|
||||||
// covered by its neighbours.
|
// covered by its neighbours.
|
||||||
|
|
||||||
|
/// Q5 — a release raised by PROJECTION is paid before the frame
|
||||||
|
/// that raised it can be written.
|
||||||
|
///
|
||||||
|
/// This is the third drain, and the only one a unit row could not
|
||||||
|
/// reach before: it sits inside the daemon's per-frontend frame
|
||||||
|
/// loop. `project_semantic_frame` is that seam, extracted --- it
|
||||||
|
/// returns the messages UNWRITTEN, so a caller holding them has by
|
||||||
|
/// construction not sent the successor frame yet, and a release
|
||||||
|
/// already delivered at that moment provably precedes it.
|
||||||
|
///
|
||||||
|
/// Recorded as OWED through tasks 18 and 19; this closes it.
|
||||||
|
#[test]
|
||||||
|
fn q5_a_projection_raised_release_precedes_the_frame_that_raised_it() {
|
||||||
|
let fid = FrontendId(870);
|
||||||
|
let (mut editor, mut states, mut render, _panel, buffer_id, epochs) =
|
||||||
|
terminal_panel_session_at(fid, true, PROTOCOL_VERSION);
|
||||||
|
let cell = pmacs_protocol::CellCoord::new(1, 2);
|
||||||
|
|
||||||
|
send_press(
|
||||||
|
&mut editor,
|
||||||
|
&mut states,
|
||||||
|
&mut render,
|
||||||
|
fid,
|
||||||
|
PROTOCOL_VERSION,
|
||||||
|
epochs,
|
||||||
|
buffer_id,
|
||||||
|
cell,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
child_stream(&editor),
|
||||||
|
vec![SGR_PRESS_1_2.to_vec()],
|
||||||
|
"fixture: the press reached the child"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
states[&fid].has_accepted_gesture(),
|
||||||
|
"fixture: the gesture is live"
|
||||||
|
);
|
||||||
|
|
||||||
|
// The panel stops being presentable. `publish_absent_panel`
|
||||||
|
// cancels from INSIDE projection, which cannot deliver.
|
||||||
|
editor.hide_panel_for_test(fid);
|
||||||
|
|
||||||
|
let messages = project_semantic_frame(&mut editor, &mut states, fid);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
child_stream(&editor),
|
||||||
|
vec![SGR_RELEASE_1_2.to_vec()],
|
||||||
|
"the release must already be delivered when projection hands \
|
||||||
|
its messages back --- the caller has not written them, so \
|
||||||
|
this is the release preceding the successor frame, not \
|
||||||
|
merely both arriving"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!messages.is_empty(),
|
||||||
|
"fixture: projection really did produce the successor frame \
|
||||||
|
whose own transition required that release"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!states[&fid].has_pending_release(),
|
||||||
|
"and nothing is left owed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Q6 — a SECOND PRESS with the first still live: the old release
|
/// Q6 — a SECOND PRESS with the first still live: the old release
|
||||||
/// reaches the child before the new press.
|
/// reaches the child before the new press.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue