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.9 KiB
Bug 02 — Footprint blobs zero pad net codes; net data loss propagates to peers, the Y.Doc, and materialized files
Severity: high (silent, converging data corruption on boards with nets)
Status: open — runtime-CONFIRMED 2026-07-03: the snapshot blob carries the pads
with (net 1 "SIG") stripped (repro below)
Where
wasm/bindings/pcbnew_embind.cpp:275-322—blobForItem, specifically the footprint branch'spad->SetNetCode( 0 )loop (:293-295)- Consumers:
flushDiff'sliftBlob(:593-618),pcbCollabSnapshotItems(:996-1019),doApplyItems(:822-894)
What happens
blobForItem copies clipboard SaveSelection's "make safe to transfer" steps for
footprints, including zeroing every pad's net code before Format(). That is correct
for pasting into a foreign board (net codes are per-board indices), but the collab
wire connects peers editing the same board with identity-by-uuid — nets should
survive.
Concrete flow for a plain footprint move on the sender:
flushDiffsees the footprint's scalar json changed →liftBlob→ footprint blob with netless pads goes out on the v2 wire (wChanged).- TS
itemsWireToDeltare-flattens the blob; the pad items' bodies differ from the Y.Doc's (which still has(net N "NAME")from the file seed) → pads areupdated→ the Y.Doc's pad bodies lose their nets. - Peers receive the change, render the footprint from the (now netless) Y view, and
doApplyItemsdoes remove+add — the peer's board now has net-0 pads on that footprint. Ratsnest lines to it disappear; DRC connectivity changes. - The sender's own editor still has nets → the sender now permanently drifts from the Y.Doc (drift-detect will report it forever).
- Once the peer touches the same footprint, its (already netless) blob flows back and the session converges on netless pads everywhere.
- In
docSource: "ydoc"mode the next open materializes the board from the doc (docToFile) — the author's file itself loses pad nets across a reload.
Also note: pcbCollabSnapshotItems (editor-snapshot seeding and adopt comparisons)
uses the same blob, so even the seed path bakes in the loss when the room is seeded
from the editor snapshot instead of the file. The file-seed path (fileToDoc)
preserves nets — until the first footprint edit destroys them.
Why the "safety" step doesn't apply here
MapNets remapping only runs for the (kicad_pcb …) envelope parse
(makeFromBlob, :346-368); bare footprint blobs never get net remapping — they get
nothing, because the nets were already stripped at the source. Peers in a collab
session share the same net table lineage, so the paste-into-foreign-board rationale
doesn't hold.
Fix direction
- In
blobForItem's footprint branch, drop theSetNetCode(0)loop (keep the mandatory-field uuid restore andSetLocked(false)). - Verify on the receiving side that pad
(net N "NAME")tokens parse correctly against the live board (io.SetBoard(aBoard)should resolve them). If net codes can diverge between peers after local edits, remap by name on apply (the same thingMapNetsdoes for envelope boards) rather than trusting the code. - Add a regression test: seed a board with netted pads, move a footprint on tab A, assert tab B's pad nets AND the Y.Doc pad bodies still carry the nets.
Repro
tests/kicad/ysync-repros-pcbnew.spec.ts "footprint blob preserves pad nets"
(test.fail), with the green "footprint blob embeds its pad children" precondition
pinning that only the nets — not the pads — are missing. See
16.
Related
- 04-bug-lossy-change-detection.md — pad property edits are separately invisible to the differ; this file is about the emit payload, that one about the emit trigger.