# Design miss 08 — Non-item document state only syncs at seed; `lib_symbols` is a landmine for the symbol-libraries milestone

**Severity:** design gap (silent divergence for settings edits; structural blocker later)
**Status:** IMPLEMENTED 2026-07-03 — see [18](18-miss08-opts-12-13.md) (lib_symbols channel + coarse layout save-sync; nets stay seed-frozen by design)

## Where

- `web/pcbjam-shared/src/kicad-y.ts:79-94` — `kdoc_layout` is written by `docToY`
  (seed) and only ever *appended to / pruned* by `applyDeltaToY` for root **items**;
  non-item layout slots are never updated live
- `web/pcbjam-shared/src/items-wire.ts:85-117` — `unwrapWireItem` deliberately strips
  the blob's envelope, including a symbol blob's `(lib_symbols …)` cache ("sender
  context, not document content")
- `wasm/bindings/eeschema_embind.cpp:786-808` — `doApplyItems`' `findLib` fallback
  chain: blob's own lib cache (stripped upstream) → live screen's cache → nullptr
- Drift flags: `web/standalone/src/wasm/collab/drift-detect.ts:110-115`
  (`layoutChanged` / `metaChanged` are computed and reported — but nothing consumes
  them beyond telemetry)

## What doesn't sync (by design, today)

Everything that lives in `layout` (non-uuid forms at the document root):

- eeschema: title block, paper size/orientation, `(settings …)`, `lib_symbols`
- pcbnew: `(setup …)` (design rules), net declarations (`(net N "NAME")` at root),
  layer table, title block / paper

A peer editing the title block or board setup diverges silently from the room and
from other peers; drift-detect reports `layoutChanged` forever and nothing repairs it
([10-miss-no-repair-path.md](10-miss-no-repair-path.md)). Because ydoc-mode opens
materialize from the doc, the *author's own* settings edit is lost on the next reload
(the saved file went to the API, but the doc wins on open — see the save-vs-room note
in [10](10-miss-no-repair-path.md)).

## The `lib_symbols` landmine

Today symbol placement is blocked (no bundled symbol libraries), which masks this.
When that lands:

1. Sender places a symbol → the emit's clipboard blob carries the symbol AND its
   `(lib_symbols …)` definition (that's what `aForClipboard` Format does).
2. `unwrapWireItem` **strips** the `lib_symbols` envelope → the definition never
   enters the Y.Doc.
3. Peers apply the symbol; `findLib` falls back to the live screen's cache — which
   doesn't have the definition for a symbol the peer has never seen → `nullptr` →
   symbol added without a `LIB_SYMBOL` (renders broken).
4. Worse, persistently: the room's `layout.lib_symbols` still has only the seed-time
   definitions, so `docToFile` produces a schematic referencing a lib id it doesn't
   contain — an invalid file.

## Fix directions

- **Short term (before symbol placement ships):** stop stripping `lib_symbols` on the
  eeschema wire. Either merge the blob's definitions into a dedicated
  `kdoc_libsymbols` Y.Map (keyed by lib id, LWW per definition — definitions are
  content-addressed-ish and rarely conflict), or fold them into the layout's
  `lib_symbols` slot on upsert. Mirror on apply: render the definitions into the wire
  so `findLib`'s first branch works.
- **Layout state generally:** decide per class:
  - *Settings/title block:* add a coarse "layout rev" sync — on local save (the
    existing `onSave` hook) diff the saved file's layout against the doc's
    (`docDelta` covers items; layout needs a slot-list compare, which
    `drift-detect` already does) and write changed non-item slots into `kdoc_layout`
    with LWW-at-slot-head granularity. Coarse but converging.
  - *Net declarations (pcbnew):* must be kept in step if/when net-creating edits are
    possible in the standalone; otherwise document explicitly that nets are
    seed-frozen.
- **Minimum bar if deliberately deferred:** document the freeze and make drift-detect's
  `layoutChanged` distinguish "expected class" (title block) from "unexpected"
  (missing lib_symbols), so telemetry stays actionable.
