New doc 16: the full repro-suite map (per-bug unit/e2e paths with verified failure sites), the phase-C probe outcome, and four findings only the RUNNING system revealed: - F1: bug 03's sending half emits NOTHING — a child-only delete commit never triggers a flush at all (worse than the doc's predicted bare removed-wire); the GetWidth-assert tracer evidence and the fix implication. - F2: Firefox cannot host two kicad_editor tabs in one context (per-process wasm budget) — bug-01 two-tab repros are Chromium-only. - F3: headless emit WORKS on both pcbnew and eeschema — the legacy two-tab skip rationale and items-bridge localEdit omissions are stale. - F4: drift-detect is strictly ITEM-silent on the green path (no writer- formatting false positives). Cross-updates: 00 index + verdict note; 01/04/05/06/07 Verification sections gain their repro paths; 02 upgraded to runtime-CONFIRMED; 03 gains the F1 empirical correction; 11 (no v2 e2e coverage) CLOSED with a point-by-point status update — only the legacy retirement remains. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPfrVhfYgPPgtawjSssZfn
3.3 KiB
3.3 KiB
Design miss 09 — Undo is not collab-aware: Ctrl+Z reverts peers' work and re-broadcasts it
Severity: design gap (converges, but with surprising and destructive UX) Status: open decision
Where
wasm/bindings/eeschema_embind.cpp:722-724/:843-845andwasm/bindings/pcbnew_embind.cpp:806-809/:886-888— remote applies go throughSCH_COMMIT/BOARD_COMMITwithPush( "Collaborative edit" ), i.e. they create ordinary undoable entries on the receiving editor's stackweb/standalone/src/wasm/collab/kicad-binding.ts:176-188— the adopt path applies ALL doc roots as one wire batch → one giant commitweb/standalone/src/wasm/collab/sheet-manager.ts:188-191— parked-dirty rebind runs that adopt on every sheet revisit that saw remote traffic
What happens
Going through a real commit is the right call for model consistency (connectivity, ratsnest, ERC recompute like a UI edit) — but it has an unhandled consequence:
- Ctrl+Z reverts remote work. A remote apply is on the local undo stack. The user pressing undo after a peer's edit reverts the peer's change; the reversion is a normal local commit → it flushes → it propagates to everyone, including the original author. From the author's perspective their edit "randomly disappears".
- Adopt commits are undo bombs. The seed/adopt and the parked-dirty sheet rebind apply the entire sheet as one commit ("Collaborative edit (items)"). One Ctrl+Z after revisiting a sheet reverts the whole remote catch-up — potentially dozens of peers' edits — and broadcasts the stale sheet state to the room.
- Convergence is preserved (the system happily syncs the reverted state), which is exactly the problem: the damage replicates perfectly.
There is no loop risk (the reversion is applied on peers as a remote change and suppressed from re-emit), and redo behaves symmetrically. This is purely a policy/UX gap, not an algorithmic one — but it can destroy significant work with one keystroke, so it deserves an explicit decision rather than the current default.
Options
- Exclude remote applies from the undo stack. Both commit classes support pushing without undo (or the undo entry can be dropped after Push). Standard collaborative-editor semantics: undo is local-ops-only. This is the direction most products (Figma, Google Docs) take. Cost: KiCad's undo machinery assumes the stack mirrors model history; entries referencing items later replaced by remote applies must be invalidated or made resilient (item-by-uuid re-resolution at undo time — KiCad's PICKED_ITEMS_LIST holds pointers, so this needs care).
- Keep remote applies undoable but split adopt into per-item diffs (see 13-opt-parked-dirty-full-sheet-replace.md) so at least the bomb shrinks to the real delta. Doesn't fix (1), halves the blast radius.
- Minimum bar: name the undo entries distinctly (already done) and clear the undo stack on adopt (a full-sheet replace is a reasonable "history barrier"). Cheap, removes the worst case, keeps normal-sized remote entries undoable.
Recommendation: 3 now (one call at adopt time), 1 as the eventual model, evaluated
against how invasive pointer-invalidation is in PICKED_ITEMS_LIST.