From 0cc1303fd9e31c012b619a13b2da4099794a3722 Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Tue, 9 Jun 2026 20:39:51 +0700 Subject: [PATCH] docs(plan): sync Task 13 attach-snapshot with double-render fix Co-Authored-By: Claude Opus 4.8 (1M context) --- .../plans/2026-06-09-spacesh-m0-m1.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/DOCS/superpowers/plans/2026-06-09-spacesh-m0-m1.md b/DOCS/superpowers/plans/2026-06-09-spacesh-m0-m1.md index 4473675..fa49609 100644 --- a/DOCS/superpowers/plans/2026-06-09-spacesh-m0-m1.md +++ b/DOCS/superpowers/plans/2026-06-09-spacesh-m0-m1.md @@ -2702,13 +2702,15 @@ pub fn spawn_surface( } Some(SurfaceMsg::Attach { reply }) => { let _ = reply.send(bcast.subscribe()); } Some(SurfaceMsg::AttachSnapshot { reply }) => { - // Flush pending into the grid first so the snapshot is current, - // but DO NOT broadcast here; subscribe before any further output. - if !pending.is_empty() { - grid.feed(&pending); - let _ = bcast.send(std::mem::take(&mut pending)); - flush_deadline = None; - } + // Subscribe + snapshot ONLY — do not touch `pending`. + // This arm is atomic within the single actor (no await, no flush + // can interleave), so subscribing before snapshotting guarantees the + // new receiver gets exactly the output emitted AFTER this snapshot. + // Any accumulated `pending` (not yet fed to the grid) is left alone: + // 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 snap = snapshot_ansi(&grid); let _ = reply.send((snap, sub));