Add a deep-linkable, reload-safe route /l/<libId>/<tool> (LibToolPage) that boots
the editor scoped to one backend library; the home page's lib chips become
anchors to it (full nav → clean Emscripten). Local lib FILES stay in-place
(bytes can't be URL-addressed).
Fix empty lib trees against a registry server: fileless/lib-scoped launches use
the placeholder projectId "local", which was sent as x-pcbjam-project — the
closed server then scoped its (0005 mirror) lib resolution to a non-existent
project and returned nothing. Suppress the project header for "local"; real
backend projects keep sending their uuid and keep project-scoped resolution.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Open a single library scoped to itself in its editor: a backend lib (HomePage
chip → scopedLibsSource) or a local .kicad_sym/.kicad_mod file (LocalProjectView
→ localFileLibsSource + a browser-side multi-symbol .kicad_sym parser). WasmTool
gains an optional libsSource override (transparent default). All via the existing
lib bridge — no MEMFS doc open, no fork changes.
Also fix a systemic editor boot failure: the build split the wx glue into
wx.js + wx-dom.js, but boot.ts only injected wx.js + <tool>.js. wx-dom.js defines
window.wxDomCreateControl (used by every tool to build its UI), so without it the
canvas rendered but no wx controls did (ReferenceError: wxDomCreateControl is not
defined). Inject wx-dom.js between wx.js and the tool, best-effort (older non-DOM
builds tolerated). Bump pcbjam-shared for LIB_EXTENSION_TOOL.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework HomePage into KiCad-launcher-style zones: local file-load, a Tools grid,
backend projects, and a backend libraries listing (useLibs over the shared
listLibs). The Tools grid shows all seven tools in KiCad's standalone order
(Schematic/Symbol/PCB/Footprint editors, Gerber Viewer, Calculator, Drawing
Sheet); clicking a tool or a library launches the editor with no project
(launchedTool → WasmTool slug=local) — file-less editors browse backend libs,
document editors open blank. Harden the web e2e global-setup to assert the
self-provisioned origin libs (Device, Resistor_SMD) are present, failing fast.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the KiCad symbol/footprint brace-scanner parsers + a combined extractor
into web/backend/src/extract/; ensure-example-libs blobless/sparse-clones a
curated KiCad 10.0.3 slice and extracts to a gitignored .libs/ on dev/start, so
a bare GPL clone has libraries with no closed repo present. libsConfig() defaults
LIBS_DIR to ./.libs. vite honors STANDALONE_PORT (strictPort) so a second editor
can run on :3049 alongside the closed stack.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
standalone: LibsSource abstraction (remote over the contract + static fallback),
generic window.kicadLibs provider, sym-lib-table generated from the backend's
lib list at boot (replaces the spike). backend: serve pre-built self-contained
symbol bodies from LIBS_DIR (listLibs/listLibItems + raw item-body route).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The KiCad e2e collab specs rebuild apps/kicad/collab-bundle.js with esbuild
(collab/build.mjs), bundling web/standalone/src/wasm/collab/* and its
@pcbjam/shared import. That package is the web/pcbjam-shared submodule, resolved
through the web/ pnpm workspace — which CI never installed, so the build failed
with: [ERROR] Could not resolve "@pcbjam/shared". Install the web/ workspace
(links @pcbjam/shared + pulls the bundle's runtime deps zod/@ts-rest/core/yjs)
before the e2e step.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Standalone wx test apps (contextmenu, scrollbar) + e2e specs proving the
wxScrollBar control, the wxScrolledWindow gutter, and DoPopupMenu.
- KiCad in-app specs: pl_editor + pcbnew canvas right-click context menus and
scrolled-panel scrollbar gutters, with baseline screenshots.
- build-wx-wasm.sh: serial -j1 fallback when the parallel build trips the
intermittent clean-build race (a generated header read mid-rewrite by
concurrent compiles; never happens at -j1). Recovery resumes from built
objects; a genuine error still fails the serial pass.
- Bump wxwidgets submodule (context menus + draggable scrollbars).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Commit 7dc1bf2 renamed scripts/build-wxuniversal-wasm.sh to
build-wx-wasm.sh but missed the CI workflow, so the "Build wxWidgets
(wxUniversal WASM)" step ran a script that no longer exists. Update the
run command in ci-ubicloud.yml plus the two stale comments referencing
the old name (ci-ubicloud.yml:43, scripts/common/stages.sh:7).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump wxwidgets (8814ddb) for the two DOM-port fixes and add their reproductions:
- tests/apps/standalone/{textctrl-reentry,tooltip-lifetime}: standalone wx repro
apps + Makefile.wasm targets (textctrl links -fexceptions to throw from a
wxEVT_TEXT handler), driven by tests/e2e/dom-port-bugs.spec.ts. Each app is
deterministic and self-contained (no UB, ASAN, or timing dependence).
- docs/features/wx-dom-port/branch-review.md: branch review with findings #2/#3
marked fixed and a "Bug reproductions and fixes" section, including the
asyncify + legacy-EH gotcha (catch/destructor landing pads are unreliable
while unwinding through asyncify frames).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Submodule pointer bump for the wxMenuBar dangling-child fix that resolved the 18 DOM-port kicad e2e failures. Also adds the async-debug dossier (docs/features/async/08-10) root-causing the 'indirect call to null' / 'signature mismatch' family to the menu-bar use-after-free, and folds the asyncify harness into 'npm test' (new test:wx for wx-only); tests/README + WHATWORKS updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All three repos rebased linearly: root onto origin/main (21 commits),
kicad fast-forwarded to origin/wasm-port (693c513293), wxwidgets onto
origin/wasm-port (014f67e6c1 — modal LIFO resolvers, pump
resolve-on-error, sync clipboard IsSupported). Our own IsSupported fix
was superseded by main's and shrank to its warning comment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- wxwidgets -> 25281178d2: wxClipboard::IsSupported answered via a 2 s
Asyncify suspend on KiCad's idle path; overlapping suspensions
corrupted Asyncify.currData ('indirect call to null'/'signature
mismatch' storms after every document load — bug 2 of features/async).
It now answers synchronously. The storms and 2 s UI stalls are gone.
- 58 kicad screenshot baselines regenerated from the green run (the old
set was canvas-only and died with the canvas port).
- visual-notes: bug 29 + the known-red list — the 10 file-loading kicad
specs (load-pcb, collab bridges, eeschema-ui keyboard/dialog) remain
red on the unfixed asyncify substrate (bug 3, per-context currData
authority). Bisect-verified pre-existing: binaries built from the
pre-consolidation wx tree fault identically. Greening them is the
async feature's exit criterion, deliberately out of scope here.
Gates: wx e2e 292/0/1 skipped; kicad 32 passed / 10 known-red / 2
skipped (parity +1 with pre-consolidation, minus the timeout storms).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-time refresh from a fully green run (292/0/1): the client-origin
projection fix moved every notebook's tab strip to its true position
(content shifted by the strip height), and many baselines predated the
DOM-native notebook entirely. 10 new screenshots (gal/menu/spinctrl
flows that previously never ran green), 159 updated, 100 untouched.
compare-screenshots.sh is clean against the gate run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure file moves: the canvas baseline set (331 PNGs) is deleted, the DOM
set becomes tests/baseline-screenshots/, and the DOM pcbnew reference
image becomes wizard-04-finish-headless.png. 73 kicad-flow baselines
existed only on the canvas side; they are regenerated from a green DOM
run in a follow-up commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every
piece of side-by-side plumbing so there is exactly one build and one test
flow:
- scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no
--dom/--enable-universal; builds into build-wasm/wxwidgets
- build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom;
apps build straight into tests/apps (Makefile.wasm PORT conditionals
collapsed; wx.js + wx-dom.js always pre-js)
- docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom /
-universal suffixes removed; kicad builds to kicad-<app>, outputs to
output/; wx.js/wx-dom.js copied from the real source path
(/workspace/wxwidgets/build/wasm — the old build-wasm path never
existed and silently failed)
- setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is
gone — the 7 checked-in kicad pages now reference wx-dom.js directly
- playwright configs serve apps/; fixtures drop the test-results/dom and
logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort
unconditionally; pcbnew.spec uses one reference image;
appearance.spec assertions unconditional
- compare/update-baseline-screenshots.sh: --port removed
- tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and
carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs)
now actually builds and runs here (it needed host-side boost+glm via
scripts/deps; the bundle had been missing, timing the whole spec out)
- tests: clickCanvas() dispatches via page.mouse (DOM widgets
legitimately cover the canvas; locator actionability refused the
click); the comprehensive spec drives wxChoice through its native
<select> (browser-owned popup cannot be coordinate-clicked)
- docs: README/CLAUDE.md/build.md script names and dirs;
features/wx-dom-port README reframed (DOM is THE port), visual-notes
bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv'
- wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk)
Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run
ever with the gal-webgl specs green (28 scenarios + load + sequential).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New tests/kicad/appearance.spec.ts: tab cycle through Layers/Objects/
Nets and back (with blank-rows regression assertion), wheel scrolling
in Layers (movement + exact scroll-back restoration) and Objects, with
screenshots per state. All 3 pass against the DOM pcbnew.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wx submodule: DOM elements clip to ancestor viewports; ScrollWindow
moves children (scrolled panes work); DOM-layer input forwards into the
wx mouse pipeline (hover/wheel/right-click over DOM elements); DOM-
native wxNotebook (real tab buttons, generic island notebook retired
from the DOM build); universal hover-driven tooltip layer (works for
canvas-island widgets with no DOM node). Gates: dom 255/0, canvas 263/0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The wx test-app mirror (build-wasm-test.sh --dom, rsync --delete) wiped
the kicad bundles setup-kicad-wasm.sh syncs into apps-dom/kicad —
apps/kicad only carries the checked-in HTML. Exclude kicad/ (that dir is
owned by the setup script). Add 'npm run serve:dom' for browsing the
DOM-port apps; plain 'npm run serve' serves the canvas dir, which has no
kicad bundles in this worktree (canvas KiCad was never built here).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All six apps build and run; full kicad e2e suite green under WX_PORT=dom
(28 passed / 1 flaky / 2 skipped / 0 failed). Closing fixes this phase:
menu JSON serializer (wxString::Format empty-return on KiCad labels),
main-frame visibility root (browser page has no hidden state), stateless
keyboard arbitration (Firefox fires no focusout on element removal),
out_dir scope in upstream's pipelined postprocess. Docs + visual notes
updated; per-port kicad reference screenshots in place.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upstream 680edd's pipelining moved dyncall/finalize/asyncify into
postprocess_app(), where build_app's local out_dir was out of scope —
the DOM flavor post-processed '/pcbnew.js'. Shared out_dir_for() helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pcbnew.spec.ts picks wizard-04-finish-headless-dom.png under WX_PORT=dom
(native chrome styling differs from univ pixels by design); reference
seeded from the verified loaded-editor state incl. the DOM menubar.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pipeline: lexer generation (pcbcommon) ordered before the embind
pre-compile — a fresh-build-tree chicken-and-egg any new volume would
hit (generated pcb_lexer.h was included via -I${KICAD_BUILD}/common
before anything generated it). DOM flavor outputs flow through the
host-mounted output/dom/. pcbnew e2e on DOM: editor loads fully (layer
manager, toolbars, WebGL viewport, registry metrics), draw-lines test
passes; the header pixel-reference assertion fails as expected (native
DOM styling vs univ pixels) — port-aware references pending.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WX_PORT=dom flows host → docker container → build scripts:
build-kicad-target.sh selects wxwidgets-dom + kicad-<app>-dom trees;
docker/build.sh passes the env through, copies outputs to output-dom/
incl. wx-dom.js, and post-processes there; build-wxuniversal-wasm.sh
honors WX_PORT and accepts --no-clean again (the kicad pipeline calls it
with that flag — Phase 1's stricter parser had broken the canvas docker
path). setup-kicad-wasm.sh syncs DOM bundles into tests/apps-dom/kicad
and injects the wx-dom.js script tag into the kicad pages;
playwright-kicad.config.ts serves apps-dom under WX_PORT=dom.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fork delta vs wasm-port: 8 commits, ~107 files — port directory, 35
dispatch headers, build-system entries, 1-line prntbase.cpp condition,
2 generic-notebook bug fixes. No univ/aui/stc changes. Tracker-hook
migration deliberately deferred while the canvas port is alive (the DOM
port doesn't need the hooks; univ's die with univ). Patches in
features/feature/wx-dom-port/ via create-feature-patches.sh.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>