pcbjam/docs/features/ysync-review/00-overview.md
Gergő Törcsvári 62ca571802
feat(ysync): lib_symbols travel + layout save-sync (miss 08), TS hot-path opts (12), diff-on-rebind adopt (13) — doc 18
Miss 08A: the binding stores wire-carried (lib_symbols …) definitions in
kdoc_libsymbols and prefixes them on apply wires — a joiner that never saw a
symbol adopts it WITH its definition (new e2e ysync-libsymbols.spec.ts).
Miss 08B: registerSaveHook gains onSavedText; WasmTool routes saved-file text
to syncLayoutToY (per sheet room via the manager's syncLayoutFromSave, or the
single-room doc) so title block / paper / setup edits converge instead of
drifting. Opt 12 (TS half): zod off the observer hot path (yToItemUnchecked),
children index built once per conversion. Opt 13: seed()'s adopt diffs the
editor snapshot against the doc view and applies only the doc-authoritative
difference — clean rebinds apply nothing, the adopt undo entry shrinks to the
real changed set. Opt 14 deliberately deferred (doc 18). All TS-side; no wasm
rebuild (the C++ blob/findLib sides already carried definitions).

Verified: shared 107, standalone 79 (+2 known pre-existing wasm-assets),
ysync e2e 21/21 chromium, collab regression 21/3-skip firefox.

Bumps: web/pcbjam-shared (lib_symbols channel + syncLayoutToY + opts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgThWXtdvrYLK47EDFoGdq
2026-07-06 08:57:58 +02:00

6.7 KiB
Raw Blame History

Yjs ⇄ KiCad sync review — overview and index

Full-stack review (2026-07-02) of the collaborative-editing synchronization between the Y.Doc and the internal state of eeschema / pcbnew. Scope read end to end:

  • Shared Slot model: web/pcbjam-shared/src/{kicad-doc,kicad-y,items-wire,kicad-delta,sexpr}.ts
  • Runtime binding: web/standalone/src/wasm/collab/{kicad-binding,sheet-manager,provider,drift-detect,index}.ts
  • App wiring: web/standalone/src/components/WasmTool.tsx
  • C++ bridges: wasm/bindings/{eeschema,pcbnew}_embind.cpp
  • Tests: web/standalone/src/wasm/collab/*.test.ts, tests/kicad/*-collab.spec.ts, tests/collab/browser-entry.ts

How the sync works (context for every finding)

The production path is the v2 "items" wire (ysync 0008). C++ keeps a per-uuid scalar snapshot (itemToJson) as a diff baseline; a BOARD_LISTENER / SCHEMATIC_LISTENER treats commits as "something changed" triggers, and a post-settle flushDiff (CallAfter + COROUTINE) compares snapshots and emits each changed item as a full s-expr blob. The TS side re-flattens each blob into uuid-keyed items with parent links (itemsWireToDelta), diffs against the Y.Doc's kdoc_items map, and writes item-level updates (applyDeltaToY). Remote Y events go the other way: deltaFromYEvents → render the item's full subtree s-expr → kicadCollabApplyItems, which does an idempotent remove-by-uuid + re-add through a real commit. Seeding is seed-once: the first tab writes fileToDoc(file) into the empty room; joiners adopt the doc wholesale. Drift detection periodically compares a scratch save against yToDoc and reports (never repairs) divergence.

The overall shape — post-settle diff, idempotent full-item upserts, echo suppression by origin tag plus C++ rebaseline — is sound and a good fit for the asyncify/wasm constraints. The findings below are the places where it breaks or leaks.

Verdict / suggested order of attack

UPDATE 2026-07-03: bugs 0107 are all FIXED — see 17 for the fix record (done in the batch order below), two additional findings (F5: doc 16's F4 was an artifact of bug 01, file-seeded bodies are now editor-normalized; F6: the 0008 "asyncify-fragile envelope parse" was a layer-name bug, now fixed), and the remaining follow-ups. Every repro below now runs as a plain regression test. Misses 0810 and opts 1214 (beyond what the dirty-set emit already delivers) remain open.

Every bug below has a runnable expected-fail reproduction test, and the v2 e2e port (miss 11) is DONE — see 16 for the suite map and four empirical findings the running system added (notably: bug 03's sending half emits NOTHING, not the bare removal the doc predicted).

  1. Fix 01 immediately (one line).
  2. Then 02 and 03 (small, contained, data-corrupting).
  3. Fold 04 and 05 into one change: blob-hash / dirty-set change detection plus targeted rebaseline. This also delivers most of 12.
  4. 06 and 07 are race windows — narrow them after the e2e port (11) gives regression cover.

Index

Bugs

# File One-liner
01 01-bug-first-tab-listener-never-registered.md Fresh-room seeding tab never registers the C++ change listener → its edits never sync
02 02-bug-footprint-blob-zeroes-pad-nets.md Footprint blobs strip pad net codes → net data loss propagates to peers, doc, and files
03 03-bug-child-removal-dangling-slot.md Child-only deletion leaves a dangling {item} slot in the parent's Y body → renders throw
04 04-bug-lossy-change-detection.md Change detection is a lossy scalar projection → rotations, field text edits, pad edits never sync
05 05-bug-rebaseline-swallows-local-edits.md Global rebaseline after apply can silently drop concurrent local edits and receiver-side cleanup
06 06-bug-concurrent-seed-duplicates-layout.md Two clients seeding an empty room concurrently duplicate kdoc_layout → corrupt materialization
07 07-bug-sheet-switch-stale-down-hook.md Sheet switch leaves onItems pointing at the old room → cross-room contamination window

Design misses

# File One-liner
08 08-miss-layout-state-never-syncs.md Non-item state (title block, settings, lib_symbols) only syncs at seed
09 09-miss-undo-not-collab-aware.md Ctrl+Z reverts remote work and re-broadcasts it; adopt commits are undo bombs
10 10-miss-no-repair-path.md Drift is detected and reported but never repaired
11 11-miss-no-v2-e2e-coverage.md Two-tab e2e exercises the legacy wire; the production v2 stack has no end-to-end test

Optimizations

# File One-liner
12 12-opt-hot-path-full-model-work.md O(full-model) work (incl. zod) on every edit/apply/remote batch
13 13-opt-parked-dirty-full-sheet-replace.md Parked-dirty sheet rebind re-applies the whole sheet instead of the delta
14 14-opt-item-granularity-bandwidth.md Item-level body granularity ships the whole item per nudge; LWW drops concurrent property edits

Plan & results

# File One-liner
15 15-plan-repro-tests-and-v2-e2e.md The approved plan: repro tests for bugs 0107 + the v2 e2e port
16 16-repro-suite-results-and-empirical-findings.md Plan 15 executed (2026-07-03): suite map, verified failure sites, empirical findings F1F4
17 17-fixes-bugs-01-07.md Bugs 0107 fixed & verified (2026-07-03); findings F5F6; remaining follow-ups
18 18-miss08-opts-12-13.md Miss 08 (lib_symbols + layout save-sync) + opts 12/13 implemented; opt 14 deferred (2026-07-03)