The board photos live in pcb-retrace's IndexedDB, not as CMMS
attachments, so the assistant had no way to see them and burned all its
tool-call rounds looking. cmms-bridge.js now downscales each project
photo (long edge ~1400px, JPEG q0.8 - a phone photo lands under ~300KB)
and sends them alongside the buffer in the cmms-ai-editor-buffer reply
as `images: [{id,name,mime,data_base64}]` (max 6). The CMMS
read_board_image tool surfaces one at a time.
The chat's get-buffer request can arrive before studio.js init() has
built the DB / selected a board (or while an existing project ZIP is
still streaming in), which read back as "the editor is still loading".
- buildProjectView() waits up to 4.5s for db + a board, then still
returns a valid (possibly empty) project view with a "no board open"
note rather than null - only a missing db is "still loading".
- init() with no loadUrl (a "+ New board RE") now ensures a starter
board exists (studio.js only auto-creates one when the whole DB is
empty, not when the selected device just has no boards).
- reply prefers evt.source, falls back to a DOM query for the chat
iframe (cad-editor hit an unusable cross-realm Window).
- [cmms-pcb-bridge] console tracing on every step.
cmms-bridge.js gains a window 'message' listener answering the CMMS AI
assistant's cmms-ai-editor-* protocol (same role as cad-editor's Rust
listener, since studio.html is the top-level page here):
- cmms-ai-editor-get-buffer -> replies { type:'cmms-ai-editor-buffer',
buffer: <JSON> } — device/board name, placed components
({label,value,desc,x,y}), nets ({name,pins:[...]}), and the imported
board-photo list.
- cmms-ai-editor-apply (editor:'pcb') -> parses a JSON patch of proposed
components + nets and merges it into the open project (upsert components
by label, nets by name; new parts with no coordinate are staggered so
they're draggable; net pins inherit their component's position if it
exists). Refreshes the BOM list / map / nets view. Nothing is saved -
the user checks each against the board photo and clicks Save.
Inert unless window.PCBRETRACE_CONFIG is set.
New docs/cmms-bridge.js — inert unless window.PCBRETRACE_CONFIG is present
(only public/vendor/pcb-retrace/edit.php in the CMMS sets it). When set:
- injects "Save" / "Save & close" into the top bar; hides the standalone
import/export/share buttons.
- on boot, if config.loadUrl is set, pulls the project .pcbretrace.zip
from the CMMS and restores it silently (reuses processUrlImport).
- Save builds the whole-device ZIP in memory and POSTs it multipart to
the CMMS attachment endpoint (action/csrf/job_id/id/original_name/file,
same contract as circuit-edit.php); first save of a new board switches
to in-place updates.
studio.js:
- exportDeviceZIP() split into buildDeviceZIP(pass, forCmms) -> {blob,
filename} + a thin exportDeviceZIP() wrapper. forCmms adjusts the
embedded README + manifest.source.
- importFile/processZIP/processUrlImport take an opts arg; opts.silent
skips the restore/import confirms and re-throws instead of alert().
- init() awaits window.CMMS.init() at the end when present.
studio.html: loads cmms-bridge.js (defer, after studio.js).
Standalone pcb.etaras.com / local use is unchanged — every new path is
gated on the config object or opts.silent, both absent by default.
Dark mode: config.dark is recorded as data-theme="dark" but studio.html
is light-only today; CMMS-theme-follow is a later task.
Upstream loads zip.js, OpenCV.js, WireBender (JS+WASM) and Google Fonts
from CDNs at runtime, and includes a Google Tag / gtag.js snippet. The
CMMS deployment forbids external requests. Changes:
- docs/vendor/ — local copies of opencv.js (Apache-2.0), zip.min.js
(BSD-3-Clause), WireBender.{js,wasm} (AGPL-3.0/commercial, source at
github.com/dev-lab/WireBender), and the three Google fonts (OFL, latin
subset). SOURCE.txt records provenance.
- studio.html / schema.html — zip.js + opencv.js + fonts @import point at
docs/vendor/.
- inspect-traces.js / schema/layout.js — WireBender import() + locateFile
point at docs/vendor/wirebender/.
- every *.html — Google Tag / gtag.js snippet removed.
No behaviour change; kicad-symbols zip was already bundled + local.
CMMS embedding hooks (window.PCBRETRACE_CONFIG, save-back, AI bridge)
land in a later commit.