docs(plan): sync Task 13 attach-snapshot with double-render fix

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 20:39:51 +07:00
parent f1630633e5
commit 0cc1303fd9
@@ -2702,13 +2702,15 @@ pub fn spawn_surface(
} }
Some(SurfaceMsg::Attach { reply }) => { let _ = reply.send(bcast.subscribe()); } Some(SurfaceMsg::Attach { reply }) => { let _ = reply.send(bcast.subscribe()); }
Some(SurfaceMsg::AttachSnapshot { reply }) => { Some(SurfaceMsg::AttachSnapshot { reply }) => {
// Flush pending into the grid first so the snapshot is current, // Subscribe + snapshot ONLY — do not touch `pending`.
// but DO NOT broadcast here; subscribe before any further output. // This arm is atomic within the single actor (no await, no flush
if !pending.is_empty() { // can interleave), so subscribing before snapshotting guarantees the
grid.feed(&pending); // new receiver gets exactly the output emitted AFTER this snapshot.
let _ = bcast.send(std::mem::take(&mut pending)); // Any accumulated `pending` (not yet fed to the grid) is left alone:
flush_deadline = None; // the normal 6ms/16KiB flush path delivers it to ALL subscribers —
} // including this new one — exactly once, and it is NOT in the snapshot.
// No gap, no double-render. (Broadcasting pending here would re-send
// already-snapshotted bytes to the new client via the bridge path.)
let sub = bcast.subscribe(); let sub = bcast.subscribe();
let snap = snapshot_ansi(&grid); let snap = snapshot_ansi(&grid);
let _ = reply.send((snap, sub)); let _ = reply.send((snap, sub));