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
Optimization 14 — Item-level body granularity: whole-item payloads per nudge, LWW drops concurrent property edits
Severity: known/documented v1 tradeoff — recorded here so its costs are visible when prioritizing Status: open (deliberate design decision; revisit trigger below)
Where
web/pcbjam-shared/src/kicad-y.ts:23-26— the documented v1 choice: an item'sbodyis ONE plain-JSON value → item-level merge; "deep Y types per slot (field-level merge inside one item) are the later refinement"upsertYItem(kicad-y.ts:60-72) — any body change rewrites the whole body value
Costs as shipped
- Bandwidth / update-log growth ∝ item size, not edit size. Nudging a footprint
1 mm re-writes its full flattened subtree into the Y.Doc: the update ships the
whole body JSON, and the sync server persists it in the room's update log until
compaction. For a 100-pad footprint that's kilobytes per nudge. (The flatten
already helps a lot — pads/fields/pins are separate items, so a child edit only
re-writes the child + the lifted parent body — but the parent body itself embeds
{item}refs plus all non-item slots, and pcbnew'sliftBlobre-emits the parent for every child change.) - Last-writer-wins at item granularity. Two peers concurrently editing two
different properties of the same item (one moves a text, the other edits its
string) resolve by Yjs LWW on
body— one peer's edit is silently discarded. Convergent, but lossy in exactly the case CRDTs are chosen for. The flatten means this only bites within one item (concurrent pad edits on the same footprint are fine — different items), which is why it's been acceptable so far. - Body comparison is
JSON.stringifyequality (upsertYItem,sameKicadItem) — fine at current sizes; becomes part of the hot-path cost at scale (12-opt-hot-path-full-model-work.md).
The refinement path (when justified)
The kicad-doc.ts header already sketches it: map each body/v slot list to a
Y.Array of slot Y.Maps instead of one JSON value.
- Concurrent different-slot edits merge instead of LWW-dropping.
- Updates ship only changed slots.
- The zod schema remains the post-merge structural check (this is why slot lists were designed as uniform ordered arrays — the shape is already CRDT-ready).
Costs to respect:
- ordered-list CRDT semantics introduce interleaving anomalies for concurrent inserts at the same position (slot order is file order — usually stable, so low risk);
- the conversion layer (
itemsWireToDelta/deltaToItemsWire/yToItem) must become slot-diff-aware — a meaningful rewrite ofkicad-y.ts's write path; - per-slot Y overhead (item count × slot count Y structs) raises baseline doc size.
Revisit trigger
Not worth doing speculatively. Revisit when either:
- server-side room storage / bandwidth per session becomes a measured cost, or
- concurrent same-item edits become a real reported UX complaint (e.g. two people routing in the same area fighting over one track's endpoints), or
- the 04/12 rework lands — that change touches the same conversion layer, and doing the slot refinement then amortizes the rewrite.