Commit graph pcbjam/wasm/bindings
Author SHA1 Message Date
Gergő Törcsvári
b1320afab9
feat(eeschema): hierarchical subschema collaboration — per-sheet rooms, lazy seed, save flow, embind + e2e
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:55:30 +02:00
Istvan Matejcsok
0cbb6738ec fix: 🐛 symbol_editor_embind.cpp 2026-06-12 16:07:09 +02:00
Gergő Törcsvári
8131bf9bac
feat: standalone save/load routing + VITE_DOC_SOURCE ydoc mode
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:05:40 +02:00
Gergő Törcsvári
07863da416
feat: ysync 0008 Stage D — wire the v2 items collab into the app + verify
- WasmTool: hard cutover to startKicadCollab (gates on
  kicadCollabSnapshotItems; scalar reconciler no longer runs in the app)
- file-seed (ysync 0005 tie-in): empty rooms are seeded from the opened
  file via fileToDoc/docToY (meta+layout+items — file recoverable from the
  Y.Doc alone); populated rooms still adopt (seed-once unchanged)
- binding: gate UP applies until seed() — the provider's initial state
  sync otherwise streams the full doc into an editor that already holds
  the file (trapped eeschema's paste path in the real app)
- pcbnew blobForItem: footprints Format a uuid-corrected copy directly —
  SaveSelection's copy regenerated mandatory-field uuids (FOOTPRINT copy
  ctor assigns into fresh fields), breaking wire identity (rebuild)
- roundtrip.spec on the v2 items wire; new passing pcbnew
  footprint-containment round trip (the 0004 containment win); full
  fixture stays fixme on the tracked envelope-parse limit
- real-app two-tab emit verified for eeschema + pcbnew (see 0008 doc)

Full kicad suite: 45 passed, 3 skipped (known), 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:05:40 +02:00
Gergő Törcsvári
3a06a267b0
feat: v2 per-item s-expr collab bridge in all three tools (ysync 0008 Stage C)
Add kicadCollabSnapshotItems / kicadCollabApplyItems / window.kicadCollab.onItems
to pl_editor, eeschema, pcbnew — per-item native-blob payloads
({added/changed:[{sexpr,parent}], removed:[uuid]}) alongside the untouched scalar
wire (legacy collab specs stay green).

- pl_editor: itemBlob per item; apply = SetPageLayout(append) + replace-by-uuid
  (pointer-snapshot safe); bare payloads get the kicad_wks envelope. Snapshot +
  apply + emit verified headless.
- eeschema: clipboard Format per item (symbols carry their lib_symbols); apply
  mirrors the native paste — LoadContent into a throwaway sheet → detach →
  replace-by-uuid → symbol lib relink (blob's lib_symbols first, live screen's
  second) → SCH_COMMIT, in the CallAfter+COROUTINE context. Snapshot + apply
  verified headless (a "lost" lone junction turned out to be correct connection
  cleanup — test uses text).
- pcbnew: blobForItem per ROOT item with child→footprint lifting in flushDiff;
  apply = makeFromBlob + commit replace-by-uuid on the fiber; bare non-footprint
  payloads get wrapInBoardEnvelope (live board layer table). Snapshot + footprint
  replace/add WITH children (the 0004 containment gap, closed) + removal verified
  headless. Track/via/zone/text blob-apply hits the documented asyncify-fragile
  envelope parse (reconfirmed empirically — a verbatim SaveSelection segment
  envelope dies silently in the commit) and stays on the legacy scalar apply;
  tracked in ysync 0008 status.
- eeschema/pcbnew scheduleFlush now runs flushDiff inside a COROUTINE: the
  per-item Format in the v2 emit needs the fiber stack (0007 lesson). Their emit
  remains unverifiable headless (both legacy two-tab tests are test.skip:
  "open=false → SCH_COMMIT no-ops" / "harness can't PAINT") — verify in the real
  app at Stage D; pl_editor's emit IS verified.
- tests/kicad/items-bridge.spec.ts: per-tool suite (snapshot uuids → local-edit
  emit (where drivable) → apply changed/added/removed via save-readback → no
  apply echo). 3/3 pass; roundtrip + collab suites unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:05:40 +02:00
Gergő Törcsvári
2163c36f28
feat: per-tool save exports + file⇄yjs round-trip tests (0004 §A, phases 2–4)
Block A save embind exports + the round-trip integration harness.

Save exports (wasm/bindings, GPL):
- pcbnew: kicadSaveBoard(path) via PCB_IO_KICAD_SEXPR::SaveBoard(GetBoard()).
- eeschema: kicadSaveSchematic(path) via SCH_IO_KICAD_SEXPR::SaveSchematicFile.
  Saves GetCurrentSheet().Last() (NOT Schematic().Root()): the wasm open-flow
  nests the opened doc under an auto-created project root, so Root()'s screen
  holds only a child-sheet symbol, not the loaded items.
  (pl_editor already had kicadSaveDrawingSheet.)

Round-trip harness (tests/kicad/roundtrip.spec.ts):
- load fixture → save (ORIG) → kicadCollabSnapshot → reload (fresh wasm) →
  open empty → kicadCollabApply → save (REGEN) → assert sexprDiff(ORIG,REGEN).equal.
- Two separate pages (extract closed before rebuild opens) so the process-global
  wasm heap frees between boots (pcbnew ~190MB). Open both sides from the same
  filename (eeschema embeds it as the root Sheetfile property). pcbnew boots the
  seeded pcbnew-collab.html (plain pcbnew.html's first-run wizard blocks boot).
- pl_editor + eeschema round trips PASS (lossless). pcbnew is test.fixme with
  tracked apply-coverage findings (footprints/zones not reconstructed; segment
  width + via size lost; fp_text→gr_text) — bridge gaps for follow-up, not test bugs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:05:39 +02:00
Gergő Törcsvári
b672c54189
fix(pcbnew): collab syncs real item layer — devirtualize Get/SetLayer; collab on by default 2026-06-09 06:04:00 +02:00
Gergő Törcsvári
2ee87889fa
feat(pcbnew): collab adds board text natively (PCB_TEXT) incl. justification
A board-level graphic text (Place→Text) lands in Drawings() and would otherwise hit the
same asyncify-fragile (kicad_pcb …) envelope-blob wall as via/zone on add. So PCB_TEXT
reconstructs NATIVELY: itemToJson emits size/thickness/angle plus horizontal & vertical
justification, mirror, and bold/italic (the text string was already emitted for any
EDA_TEXT); makeItem builds a fresh PCB_TEXT and restores all of them. flushDiff skips the
blob for PCB_TEXT_T. Footprint child text is unaffected — it syncs by move, and its add
is carried by the footprint blob.

Justification matters: it anchors the glyphs relative to the text POSITION, so without it
a left-justified text reconstructed centered on the peer and rendered visibly offset even
though GetPosition() matched (which is why the anchor-only headless check missed it).

Verified two-tab in the real app: a left/bottom-justified bold text added in tab A
reconstructs in tab B at the exact position with matching justification + string. Headless:
a board-text round-trip add test (sample text is left/bottom-justified) asserts the
position AND that hjust/vjust/text round-trip. 7 passed, 1 skipped, 0 aborts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 06:03:59 +02:00
Gergő Törcsvári
9dbfddc527
feat(pcbnew): collab adds footprints (s-expr blob) + vias/zones (native)
Footprint add reconstructs from the bare `(footprint …)` s-expr clipboard blob via
CLIPBOARD_IO (SetWriter/SetReader redirect it to a string for headless/wasm). The
non-footprint `(kicad_pcb …)` envelope parse (parseBOARD) is asyncify-fragile in wasm
— commit.Add of an envelope-parsed item silently stages nothing and subsequent virtual
dispatch traps ("index out of bounds"), the same wall that deferred the eeschema symbol
blob — so vias and zones reconstruct NATIVELY instead: itemToJson emits drill/layer-pair
for a PCB_VIA and the outline polygon for a ZONE, and makeItem builds a fresh PCB_VIA /
ZONE. flushDiff attaches the blob only to types that need it (footprints/board graphics);
tracks/vias/zones skip it. Includes the dangling-parent fix for the envelope path
(SetParent before delete) which footprints don't hit.

Build: kicad_clipboard.h pulls in the generated pcb_lexer.h (emitted into the common
build subdir by make_lexer) — added -I${KICAD_BUILD}/common to the embind include path.

Tests: sample board gains a via + zone; snapshot asserts their native fields are emitted,
and three round-trip add tests (footprint via blob, via/zone native) delete then re-add
each by uuid and confirm it returns at the same position. 6 passed, 1 skipped, 0 aborts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 06:03:59 +02:00
Gergő Törcsvári
f60abaa349
fix(pcbnew): collab syncs footprint silkscreen text; un-no-op test-move helper
Bug 1 — footprint child text now syncs. forEachTopItem also visits each footprint's
TEXT children by their own uuid (GetFields() PCB_FIELDs + GraphicalItems() PCB_TEXT),
so moving a silkscreen reference/value/user text — which leaves the footprint origin
unchanged — produces a diff. Apply needed only a guard: the removed loop skips items
with a parent footprint (a footprint delete cascades to its children, so don't
double-remove). ResolveItem already resolves child uuids and BOARD_COMMIT::undoLevelItem
rolls a child Modify up to the footprint, so Modify+SetPosition (in the existing
COROUTINE) just works. itemToJson now carries text for EDA_TEXT items.

Bug 2 — kicadCollabTestMoveFirst no longer no-ops. Its CallAfter now runs the move
inside a COROUTINE fiber (like doApply) so the virtual BOARD_ITEM::Move dispatches
instead of asyncify-no-opping.

Tests: sample board gains a footprint with a Reference field + user fp_text; snapshot
test asserts the footprint and both text children are emitted by uuid; a new test
moves each child by uuid and asserts the footprint origin stays put. 3 pass, 1 skipped.
Verified two-tab in the real app: C1's reference text move syncs A->B, no footprint moves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 06:03:59 +02:00
Gergő Törcsvári
2dc55c6138
feat(pcbnew): Yjs collab bridge — snapshot/diff emit + BOARD_COMMIT apply (move/delete/track-add), verified two-tab in real app
pcbnew's half of the unified Yjs collab bridge (4th tool; yjs-bridge commit 4),
a near-verbatim port of the eeschema design. Root-repo only — kicad/wxwidgets
submodules untouched.

- wasm/bindings/pcbnew_embind.cpp: BOARD_LISTENER trigger + post-settle snapshot
  diff emit; BOARD_COMMIT apply inside a CallAfter + COROUTINE fiber (so a new
  item's GAL view->Add dispatches correctly). Move/delete sync for any top-level
  item by uuid; native PCB_TRACK add. Footprint/via/zone add deferred.
- WasmTool.tsx: add pcbnew to COLLAB_TOOLS.
- tests/apps/kicad/pcbnew-collab.html: seeded (wizard-free) harness, leaving
  pcbnew.html untouched for its wizard test.
- tests/kicad/pcbnew-collab.spec.ts: snapshot + apply(move/remove/add) — 2 pass,
  two-tab skipped headless.

Verified two-tab in the real web app: footprint move applies + syncs A->B.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 06:03:59 +02:00
Gergő Törcsvári
9f8628cfb2
fix(eeschema): collab converges on big drags — emit a post-settle snapshot diff
The batched-emit fix still lost segments on a large connected drag (peer
dropped the P3-C1 wire). Deeper cause: the SCHEMATIC_LISTENER fires in
pushSchEdit BEFORE RecalculateConnections (sch_commit.cpp ~402 vs ~430), so
every emit was pre-cleanup RAW geometry; the cleanup that follows (merge
collinear wires, drop/split junctions) was never broadcast. The peer rebuilt
the raw edit and ran its own cleanup over a different dirty scope, so the two
peers cleaned up differently and the peer lost segments.

Replace the listener-list emit with a post-settle full-model snapshot DIFF
(snapshotByUuid), flushed via CallAfter once Push (cleanup included) returns —
capturing tab A's final, already-clean geometry. The peer applies that and
re-cleaning already-clean geometry is idempotent, so they converge. The native
listener is now just a change trigger. g_baseline holds the last-broadcast
state; doApply and kicadCollabSnapshot rebaseline so applied/seed items aren't
re-broadcast (echo). Mirrors pl_editor's snapshot-differ; no kicad-fork change.

Verified two-tab, rigorously (real edit: tabA state changed AND tabA===tabB
byte-for-byte): a wire reroute plus U1A/U1B/C2 symbol drags all converge
exactly. eeschema-collab + eeschema-ui suites green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:59:21 +02:00
Gergő Törcsvári
f2a6deaf7b
fix(eeschema): collab drag no longer drops segments — batch one edit into one delta
A single SCH_COMMIT::Push fires OnItemsAdded/Removed/Changed separately and
synchronously, then RecalculateConnections once. COLLAB_LISTENER emitted each
category as its own delta, so the peer applied one atomic edit as three separate
commits, each with its own connectivity recompute. On a large connected drag the
junction at the wires' new crossing (added) was applied before the wires moved
(changed) -> dangling junction -> the peer's cleanup deleted it (lost segments).

COLLAB_LISTENER now buffers added/changed/removed (serialized in each synchronous
callback) and flushes one combined delta after Push returns, coalesced via
CallAfter. doApply applies it atomically removed->changed->added in a single
commit with one recompute, so the junction survives. Verified two-tab: a G-drag
of U1A that previously left the peer at 74 items / 7 junctions now emits one
delta {a:1,c:4,r:1} and both tabs converge at 75 / 8.

Root-repo only; kicad and wxwidgets untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:43 +02:00
Gergő Törcsvári
b577c05fae
fix(eeschema): wasm dialog positioning (web .window CSS) + collab SCH_SHAPE add via coroutine fiber stack
Thrust A — dialogs render top-left with OK clipped in the WEB app (not the
test harness): root cause was the React shell missing the .window /
.window-canvas CSS that wx.js relies on (it positions each dialog div via
inline left/top, which need position:absolute). Added the rules to
web/apps/frontend/src/index.css. Native draw-text now works end-to-end;
symbol/power choosers render (placing still blocked by absent libraries).

Thrust B — collab apply of a newly-added SCH_SHAPE trapped in KiCad core
(SCH_COMMIT::Push CHT_ADD -> GAL view->Add, an asyncify invoke_* mis-dispatch)
because doApply ran off a fiber stack. doApply now runs inside a COROUTINE so
it executes on a libcontext fiber, the same context native draws use; the add
dispatches correctly. Re-enabled the SCH_SHAPE converter (rect/circle). Added
thirdparty/libcontext to the embind include path (tool/coroutine.h needs it).
Verified two-tab: rectangle + circle drawn in tab A sync + render in tab B.
Extended eeschema-collab.spec.ts apply test with a SCH_SHAPE add.

All changes root-repo only; kicad and wxwidgets forks untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:43 +02:00
Gergő Törcsvári
6bd17aeb26
fix(eeschema): collab move carries the symbol/label text fields along
After the body-move devirtualization, moving a symbol synced the body to the peer but
left its reference/value text behind: SCH_SYMBOL::Move()/SCH_LABEL_BASE::Move() move the
child fields via an inner virtual field.Move() that also mis-dispatches in the apply
context. Move the fields explicitly with a devirtualized SCH_FIELD::Move (moveFields).
Verified: a moved symbol's text label now follows the body on the peer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:43 +02:00
Gergő Törcsvári
2d1d7c4681
fix(eeschema): collab sync of symbol/junction/label moves; bump wxwidgets (toolbar focus)
The changed-path used the virtual SCH_ITEM::Move(), which silently no-ops from the
apply/CallAfter context (asyncify call_indirect mis-dispatch) for every non-wire item —
so moving a symbol synced on the sender but not the peer. Devirtualize Move() with an
explicit class-qualified call (moveItemTo), which is statically bound (a plain call, not
call_indirect) and executes. Verified: a symbol move now propagates. Also bumps wxwidgets
to ea599f7 (toolbar clicks no longer steal canvas keyboard focus).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:42 +02:00
Gergő Törcsvári
04b011d032
feat(eeschema): collab SCH_SHAPE emit + defensive text; defer shape/symbol add (asyncify trap); un-skip apply e2e
- itemToJson hand-maps SCH_SHAPE geometry (SHAPE_T, start/end, arc center,
  bezier ctrl pts, stroke width, fill) for emit + the changed/move path.
- makeItem: parent + default-size SCH_TEXT (mirrors createNewText).
- SCH_SHAPE/SCH_SYMBOL `added` reconstruction deferred: committing a new
  shape/symbol traps in SCH_COMMIT::Push from the programmatic apply context
  (asyncify invoke_* mis-dispatch, not the boundary 'signature mismatch' the
  dyncall shim catches). makeItem returns nullptr -> graceful 'no converter'.
- Un-skipped + extended the headless apply e2e (move via sx/sy line form,
  delete, text-add); apply works headless (old 'Push no-ops' belief was stale).
- features/yjs-bridge/0006: full findings (bugs 1+2 don't reproduce, etc).

No kicad-fork change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:42 +02:00
Gergő Törcsvári
890e7b317c
feat(eeschema): collab apply converters for text, labels, no-connect
Extend doApply added-item construction beyond wires: SCH_TEXT, SCH_LABEL /
SCH_GLOBALLABEL / SCH_HIERLABEL (position + text + label shape), and SCH_NO_CONNECT.
Serialize text (any EDA_TEXT) and label shape in itemToJson. Moving/deleting existing
items of any type already worked (generic changed->Move and removed->Remove); this adds
their reconstruction on add.

Still uncovered: SCH_SYMBOL (needs lib-symbol + fields/orientation) and graphic shapes
(SCH_SHAPE). Known issues to fix next: adding text freezes the app; circles (SCH_SHAPE)
don't sync; deletes don't apply; wire moves only partially converge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:42 +02:00
Gergő Törcsvári
b5b1a0ac05
fix(wasm): dynCall signature-mismatch fallback + eeschema collab wire converters
Two things, both verified in the real web app (two-tab eeschema collab).

1. dynCall crash fix (all apps) — scripts/common/shims/dyncall-binding.js.tmpl.
   Programmatic editor edits trapped with 'indirect call signature mismatch': the
   asyncify-instrumented wasmExports[dynCall_<sig>] trampoline does call_indirect with a
   stale type for some table indices (post-asyncify+O2) even though the table entry is
   valid. Proven by patching the built js: at the trap getWasmTableEntry(index) SUCCEEDS
   where the trampoline fails. Fix: the shim now catches the 'signature mismatch'
   RuntimeError and falls back to getWasmTableEntry; the Asyncify unwind sentinel and real
   exceptions re-throw, so instrumentation/unwind is untouched for normal calls. This
   unblocks ALL programmatic edits, not just collab (e.g. eeschema SCH_ITEM::Move).

2. eeschema collab apply converters (wasm/bindings/eeschema_embind.cpp).
   doApply now handles added-item construction (build the SCH_ITEM with the delta's uuid
   via const_cast — as the s-expr parser does — + commit.Add) and richer SCH_LINE
   serialization (start/end/layer) so wire edits reconstruct on the peer. Implemented for
   SCH_LINE (wires) + SCH_JUNCTION; other types log 'no converter for added type' and are
   skipped (next batch). eeschema re-enabled in the web app collab gate.

Tests: eeschema-collab.spec snapshot (green); apply/two-tab skipped — they no-op headless
because the e2e harness's kicadOpenFile returns false (OpenProjectFiles bails before
building the connectivity graph), so SCH_COMMIT::Push doesn't persist. Verified in-app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:42 +02:00
Gergő Törcsvári
4f8c2d1f56
feat(eeschema): collab bridge read/emit + build fixes; apply WIP (yjs-bridge commit 3)
eeschema's half of the Yjs collaborative bridge, reusing the generic reconciler /
BroadcastChannel transport unchanged. Zero kicad-fork change: native SCH_ITEM uuid +
native SCHEMATIC_LISTENER. All in the wasm layer (wasm/bindings/eeschema_embind.cpp).

Working (verified in the web app):
- kicadCollabSnapshot(): enumerate sch.Hierarchy() -> LastScreen()->Items() as
  {id,type,x,y}; registers the listener on first call
- emit: SCHEMATIC_LISTENER subclass -> per-item delta via window.kicadCollab.onDelta;
  fires on real SCH_COMMIT::Push (a real wire move broadcasts added/removed/changed)

Apply is a documented follow-up (gated off so a peer tab can't crash): SCH_ITEM::Move
traps with 'indirect call signature mismatch' when invoked outside a KiCad tool
coroutine (Asyncify+fiber+exception-trampoline). Modify/Clone/GetPosition all work;
only the virtual Move write traps. Fix direction: route apply through TOOL_MANAGER.

Also: build-kicad-target.sh now force-relinks when only <app>_embind.cpp changed (the
embind .o isn't a make dep, so new bindings silently vanished), and adds the
expected/rtree/fmt thirdparty includes the eeschema bindings need.

Tests: eeschema-collab.spec.ts covers snapshot (green); apply/two-tab skipped with the
blocker noted. WasmTool gates collab to pl_editor only until eeschema apply works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:41 +02:00
Gergő Törcsvári
83b3418778
feat(pl_editor): Yjs collaborative bridge — differ/apply + generic reconciler (yjs-bridge commit 2)
Bidirectional bridge between pl_editor's DS_DATA_MODEL and a Yjs doc, two same-origin
tabs syncing over BroadcastChannel. Full architecture in features/yjs-bridge/0001-0002.

C++ (wasm layer, wasm/bindings/pl_editor_embind.cpp — public DS_DATA_MODEL API only,
zero added fork divergence beyond the OnModify hook):
- snapshot-differ ChangeSource: diff model vs last-emitted snapshot on OnModify,
  emit per-item delta JSON via EM_ASM window.kicadCollab.onDelta
- kicadCollabApply(json): apply remote delta by uuid — scalars (text/segment/rect)
  by field, polygon/bitmap via SetPageLayout-append blob; reseed snapshot + HardRedraw
- kicadCollabSnapshot() (seed/baseline), s_applyingRemote echo guard, and a
  kicadCollabTestAddText() PoC local-edit hook
- wire format: {added:[item],changed:[item],removed:[uuid]}, item = {id,type,...fields}

JS (web/apps/frontend/src/wasm/collab/, generic + schema-agnostic):
- reconciler: uuid-keyed Y.Map of per-item Y.Map; down = onDelta→Y, up = observe→apply,
  origin-tagged echo suppression; seed-once join adopts the doc authoritatively
- broadcast-transport: minimal BroadcastChannel Yjs provider (query/state catch-up)
- WasmTool wiring behind ?collab=1 (pl_editor only); gated debug logging

Tests: tests/kicad/pl_editor-collab.spec.ts — single-page C++ contract (snapshot/apply
changed+removed+added/echo-suppression) + two-tab BroadcastChannel A<->B propagation.
Reconciler+yjs bundled via esbuild (tests/collab/build.mjs, npm run build:collab).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:41 +02:00
Gergő Törcsvári
7d49007473
feat(pl_editor): add KIID m_Uuid + (uuid) to .kicad_wks format (yjs-bridge commit 1)
Bump kicad submodule to the per-item uuid identity change, plus the wasm/test
infra to verify it:

- wasm/bindings/pl_editor_embind.cpp: test-only kicadSaveDrawingSheet(path) hook
  that serializes the singleton DS_DATA_MODEL to MEMFS (also a building block for
  the bridge's later materialize-to-file path)
- tests/kicad/pl_editor-uuid.spec.ts: open->save->read-back e2e proving (uuid …)
  backfill (4 distinct uuids) and load->save round-trip preservation

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:56:38 +02:00
Gergő Törcsvári
8341573c5c
feat(web): wire pl_editor + symbol_editor tools (open, wizard-skip, UI)
Add the two newly WASM-ported editors to the web app the same way as the
existing tools:

- pl_editor (drawing-sheet, .kicad_wks): PL_EDITOR_FRAME overrides
  OpenProjectFiles, so it gets the generic kicadOpenFile embind hook
  (wasm/bindings/pl_editor_embind.cpp) for deterministic open. Mapped
  .kicad_wks -> pl_editor in EXTENSION_TOOL.
- symbol_editor (symbol library): SYMBOL_EDIT_FRAME does NOT override
  OpenProjectFiles, so it's treated as file-less (boot standalone, opens
  libraries via its own UI). Added to FILELESS_TOOLS.

Both boot through single_top.cpp's STARTWIZARD, so both seed config to skip the
first-run wizard (TOOL_NEEDS_CONFIG_SEED) and get a /usr/bin/<binary> argv0.

contract: add to TOOLS, plus a TOOL_LABELS map for friendly names. The project
UI now renders file-less launch links generically from FILELESS_TOOLS and
per-file "Open in <label>" links from EXTENSION_TOOL (auto file-type detection),
so adding a tool needs no UI edits.

Verified in-browser: pl_editor opens a .kicad_wks (renders the sheet),
symbol_editor boots wizard-free; both with 0 console errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 21:49:04 +02:00
Gergő Törcsvári
735e5aa8e9
feat(web): checkpoint web app init
- frontend (Vite/React) + server (Hono/Drizzle) scaffold under web/
- eeschema WASM embind kicadOpenFile hook + programmatic open-flow
- skip KiCad first-run setup wizard by seeding default config in preRun
- dev: auto-sync output/ WASM artifacts into tests/apps/kicad via link-wasm

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 20:32:19 +02:00
Istvan Matejcsok
0464470733 add calculator build 2026-05-28 17:28:17 +02:00
Viktor Vaczi
9c271996c2 Fix KiCad WASM build and runtime errors
Build improvements:
- Change -O0 to -O1 to fix "local count too large" asyncify error
- Add wasm-emscripten-finalize to host (Docker OOMs on large WASM)
- Use -gseparate-dwarf for smaller main binary with debug info
- Build native protoc for code generation
- Add more functions to asyncify removelist

Runtime fixes:
- Add inject-dyncall-shims.sh to fix "dynCall_* is not defined" in Emscripten 4.x
- Update wxwidgets with browserInfo.name fix

New stubs and bindings:
- Add Embind bindings for JavaScript interop
- Add stubs for scripting, API plugin, PCB frame, navlib

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 16:30:53 +01:00