app
SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
← Commit history
v0.3.1: manifest, README, skill, ecosystem table, parity report
5 files changed
+1354−2
ECOSYSTEM-TABLE.mdadded+236@@ -0,0 +1,236 @@+# Where swx stands in the ecosystem++**swx v0.3.0** measured against the Adom **Fusion 360 bridge v1.9.341** (the gold standard we mirror)+and against every public SOLIDWORKS MCP server we could find · written 2026-09-03++## Executive summary++- **swx is the only SOLIDWORKS implementation here with a published live-run record.** Three runs+ against a real *SOLIDWORKS Design Professional for Makers 2026* install (22-aborted, 120/9, then+ **125 passed / 5 failed**), 19 verbs proven end to end, with measured p90 timings. One competitor+ (SolidPilot) also claims live validation and is credible about it; the other three are explicit that+ most or all of their tools are unvalidated, mock, or hobby-grade.+- **On raw modeling breadth we are behind SolidPilot** — its sketch/feature/assembly/drawing surface is+ deeper than ours and it is the most mature project in this space by a wide margin.+- **On safety we are ahead of all five, and alone.** No other project has a write gate. swx writes are+ deny-by-default at a single choke point, enforced *independently* at two layers, hardened over eight+ adversarial review rounds, and the posture held through every live run — three times the bridge failed+ CLOSED rather than touch the wrong document.+- **Our other unique strengths:** BOM-first and configuration-aware design (BOM aggregates per+ *(file, configuration)* pair — nobody else models this); native GLB with no optimisation service;+ an action ledger plus measured per-verb timings; census-not-dismiss dialog etiquette with+ `neverAutoAnswer` classes; and real host-ecosystem integration (Adom Bridge verbs, the user's+ Activity Log, a shipped skill) where every competitor is a bare MCP server for Claude Desktop.+- **Our real gaps, stated plainly:** no cloud/3DEXPERIENCE document access (21 Fusion verbs; a separate+ OAuth project of roughly the size of the Fusion bridge's APS work); assemblies-with-components,+ drawings and 2D exports are mock-only because the Makers edition would not let an assembly be+ populated; and there is no in-process scripting host — a typed JSON DSL stands in.+- **Launch was our headline "cannot", and that changed today.** `CoCreateInstance` returns+ `CO_E_SERVER_EXEC_FAILURE` on the Connected editions, but a sanctioned launch path via the+ 3DEXPERIENCE shortcut chain (`CATSTART.exe` → `SWXDesktopLauncher`) was discovered 2026-09-03.+ Implementation is in progress and **not yet live-proven**.+- **Scripting has a second route now too:** SOLIDWORKS `RunMacro2` for `.swp` VBA macros, VSTA, and C#+ add-ins are **under investigation** — with the caveat that the Makers edition restricts third-party+ add-ins while still running macros. Four of the five competitors already lean on VBA; we do not yet.+- **Licensing is simple and decision-relevant:** exactly **one** copyleft player — SolidPilot is+ **AGPL-3.0** with a paid commercial option — and everything else, ours included, is **MIT**. We can+ read and learn from SolidPilot; we must not vendor its code.+- **Electronics is not a gap.** 51 of the Fusion bridge's 132 verbs are Fusion Electronics, EAGLE+ libraries, or Autodesk-specific plumbing. SOLIDWORKS has no concept to bridge to, and no competitor+ attempts it either.++## How to read the cells++| Mark | Means |+|---|---|+| **✓ live** | Executed against a real, licensed CAD install and observed to do what it claims. |+| **✓** | Built and shipped, or claimed by the project's own README. Evidence level is stated per row. |+| **⚠ mock** | Built and mock-tested only; never executed live in any form. |+| **partial** | Some of the capability, materially incomplete. |+| **✗** | Absent. |+| **n/a** | No concept exists to bridge to in that product. |+| **WIP** | Route identified, implementation in progress, not yet proven. |+| **?** | Could not be determined from the repository. |++Evidence discipline: for **Fusion bridge** and **swx**, cells come from source we hold — the Fusion+bridge's own `describe.py` catalog (133 entries, 132 real verbs) and `docs/FUSION-PARITY-REPORT.md`.+For every competitor column, cells are **read-from-README** unless the row note says otherwise. Nobody+in the competitor set was installed or run. Licences and star counts were verified against the GitHub+API on 2026-09-03, not read off a badge.++## The master table++35 capability rows × 7 implementations. Verb counts: Fusion bridge **132**, swx **60**,+SolidPilot ~**46 tools**, vespo92 ~**30+**, bartels **122**, Schildkraut **~16 tools + 100+ VBA+templates**, alisamsam **22**.++| # | Capability | Fusion bridge | **swx v0.3** | SolidPilot **(AGPL-3.0!)** | vespo92 (MIT) | bartels (MIT) | Schildkraut (MIT) | alisamsam (MIT) |+|---:|---|---|---|---|---|---|---|---|+| 1 | Session lifecycle — attach, stop, kill | ✓ | **✓ live** attach · ⚠ mock stop/kill | ✓ attach | ? | ✓ attach | ? | ✓ attach |+| 2 | Launch the CAD application (and install it) | ✓ launch + silent install | **WIP** — refused by SOLIDWORKS; 3DEXPERIENCE chain found 2026-09-03 | ✓ claims COM launch | ✗ | ✗ needs SW already open | ? | ✗ needs running instance |+| 3 | Requires an in-app add-in | yes (3 verbs to manage it) | **no — out-of-process COM** | no (C# COM server) | no | no | no | no |+| 4 | Open a local file · disk discovery | ✓ open · ✗ discovery (cloud-native) | **✓ live** open · **✓** `find_files` | ✓ open · ✗ | ✓ (untested) | ✓ | ✓ | ✓ open · ✗ |+| 5 | Create a new document | ✗ (docs arrive from cloud/import) | **✓ live** | ✓ part + assembly | ✓ (untested) | ✓ | ✓ | ✓ part + assembly |+| 6 | Save / Save As **with overwrite protection** | ✓ cloud save · ✗ overwrite guard | **✓ live** save_as · **✓ overwrite guard (unique)** | ✓ save · ✗ guard | ✓ (untested) · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard | ✓ · ✗ guard |+| 7 | Cloud document store — search, list, open, up/download | ✓ 21 verbs (APS Data Management) | **✗ lacking** — `swx_cloud_status` returns the honest probe | ✗ | ✗ | ✗ | ✗ | ✗ |+| 8 | Cloud / vendor sign-in + OAuth | ✓ 9 verbs (incl. 2FA, web sign-in) | ✗ lacking | ✗ | ✗ | ✗ | ✗ | ✗ |+| 9 | Parametric modeling — sketch → feature | ✓ (Python script in-process) | **✓ live** typed DSL (50×30×20 solid, p90 10.2s) | **✓ live** — deepest surface here | partial (basic ops only) | ✓ claimed | ✓ via VBA templates | ✓ basic |+| 10 | In-process scripting host (arbitrary code) | ✓ Python `eval` inside Fusion | **adapted** — typed JSON DSL, validated pre-COM; `swx_com_eval` escape hatch | ✗ by design (deterministic compiler) | ✗ | ✗ | ✗ | ✓ `execute_python` in SW context |+| 11 | Macros / VBA — generate, record, execute | n/a (Fusion has no VBA) | **WIP** — `RunMacro2` / VSTA / C# add-in under investigation | ✗ explicitly unsupported | partial (gen works, exec untested) | ✓ | **✓ strongest** (record/export/execute + 100+ templates) | ✗ |+| 12 | Assemblies — insert components, mates | ✓ via script | ⚠ mock — `AddComponent5` returned Nothing on this edition | **✓ live** insert + mate + diff | ✗ | ✓ claimed | ✓ via VBA | partial (create doc only) |+| 13 | Drawings — create, views, dimensions | ✗ no drawing verbs | partial — creation **✓ live**, views/dims not built | **✓ live** 9 tools; 9 real drawings reconstructed | ✓ (untested) | ✓ claimed | ✓ via VBA | ✗ |+| 14 | Import neutral CAD (STEP etc.) | ✓ | **✓ live** (p90 7.8s) | ✓ via 3D Interconnect | ? | ? | ? | ✗ |+| 15 | Export 3D — STEP/IGES/STL/3MF/SAT/Parasolid | ✓ 8 formats | **✓ live** 6 proven; 17 formats in table; OBJ refused by SOLIDWORKS | ✓ STEP/IGES/STL | ✓ (untested) | ✓ | ✓ | ✗ none |+| 16 | Export **native GLB** (web 3D) | ✓ but needs an optimisation service | **✓ live, direct — unique** | ✗ | ✗ | ✗ | ✗ | ✗ |+| 17 | Export 2D / document — PDF, DXF, DWG | ✓ DXF/DWG · ✗ PDF | ⚠ mock all three (refused for a part; untested from a drawing) | ✓ PDF/DWG/DXF | ✓ (untested) | ✓ | ✓ PDF | ✗ |+| 18 | BOM | ✓ assembly + electronics BOM | ⚠ mock — **but per *(file, configuration)*, the richest design here** | ✗ on the roadmap | ✗ | ✗ | ✓ table insertion | ✗ |+| 19 | Mass / physical properties | ✓ | **✓ live** (aluminium, 81 g agreeing) | **✓ live** (verified ≤1%) | ✓ (untested) | ✓ claimed | ✓ claimed | ✗ |+| 20 | Design-health — interference detection, rebuild census | ✗ neither | partial — interference ⚠ mock (object confirmed live), `rebuild_check` built | partial (`analyze_model`/`verify_state`; no interference) | ✓ (untested) | ✗ explicitly not yet | ✓ via VBA | ✗ |+| 21 | Parameters / dimensions — read **and drive** | ✓ read | **✓ live** — drove a dimension to 25 mm, model moved | ✓ `modify_dimension` | ✓ (untested) | ✓ claimed | ✓ equations | ✗ |+| 22 | Custom properties (file and per-configuration) | partial (buried in the attribute model) | **✓** `props_get`/`props_set` | ✗ | ✗ | ? | ✓ | ✗ |+| 23 | Configurations / design tables | ✗ no equivalent concept | ✓ configuration-aware (BOM, properties) · ✗ design tables | ✗ | partial (`vba_configurations`, untested) | partial | **✓ strongest** (design tables + SQL) | ✗ |+| 24 | Pack and Go — collect a design + all references | ✗ | ✓ built (gated), ⚠ mock | ✗ | ✗ | ✗ | partial (batch ops) | ✗ |+| 25 | PDM / vault integration | n/a | ✗ not built | ✗ | ✗ | ✗ | **✓ only one** (5 tools) | ✗ |+| 26 | Application preferences — read and write | ✓ incl. driving the settings modal | **✓ live** (written, then read back) · modal driving declined by design | ✗ | ✗ | ✗ | ✗ | partial (`set_units`) |+| 27 | Screenshots + window management | ✓ | ⚠ mock (delegated to ab; SKIPPED in live runs) | ✗ | ✗ | ✗ | ✗ | ✗ |+| 28 | Blocking-dialog handling | ✓ dismisses them | **adapted — censuses by default**; `neverAutoAnswer` classes never closed | ✗ | ✗ | ✗ | ✗ | ✗ |+| 29 | Electronics — schematic, PCB, Gerbers, CPL, design rules | ✓ 15 verbs | n/a | n/a | n/a | n/a | n/a | n/a |+| 30 | Component libraries / 3D packages (EAGLE `.lbr`) | ✓ 23 verbs | n/a | ✗ | ✗ | ✗ | ✗ | ✗ |+| 31 | Vendor MCP-server proxy | ✓ 6 verbs (Autodesk ships one) | n/a — Dassault ships none | n/a (is itself an MCP server) | n/a | n/a | n/a | n/a |+| 32 | Bridge infrastructure — self-describe, shipped docs, guided demo, uninstall | ✓ all four | ✓ describe/docs/uninstall · ✗ demo (deferred v0.4) | partial (13 MCP resources) | ✗ | partial (docs audit) | partial (resource registry) | ✗ |+| 33 | **Action ledger + measured per-verb timings** | ✓ ledger, verb times, live feed, alerts | **✓ ledger + timings recorded live** | ✗ (dev log only) | ✗ | ✗ logging only | partial ("enhanced logging") | ✗ |+| 34 | **Deny-by-default write gate** | ✗ no gate, no confirm/reason in its catalog | **✓ live — unique. Two independent layers, 8 adversarial rounds, held in all 3 live runs** | ✗ | ✗ | partial ("adapter safety wrappers") | partial (macro exec needs permission) | ✗ |+| 35 | Host-ecosystem integration (Adom Bridge, Activity Log, skill) | ✓ native | **✓ native** | ✗ MCP clients only | ✗ | ✗ | ✗ | ✗ |++*(35 numbered rows; rows 29–31 are the N/A block that accounts for most of the Fusion verb-count gap.)*++## Per-competitor notes++### SolidPilot — eyfel/mcp-server-solidworks · **AGPL-3.0** + paid commercial · 265★ · C# + Python++The one to take seriously. Four-layer architecture: an AI planner emits a CAD-neutral **Feature Graph+IR**, a deterministic Python compiler lowers it to ordered tool calls, and a **single C# .NET 4.8+execution layer on one STA thread is the only code that touches COM**. ~46 tools, 13 MCP resources.+Its README makes verifiable-shaped claims — production parts round-tripped `analyze_model` → IR →+`rebuild_from_ir` → `compare_parts` to a `verified` match on exact topology and mass properties, nine+real manufacturing drawings reconstructed to ≤0.02% weight match. Deeper than us on modeling,+assemblies, sheet metal and drawings. Has **no** BOM (on the roadmap), no configurations, no custom+properties, no preferences, no screenshots, no macros (deliberately — the compiler replaces scripting),+no write gate, and no ecosystem beyond Claude Desktop. Its `ensure_ready` claims to launch SOLIDWORKS+via COM, which is plausible on a classic desktop install and would fail exactly as ours does on+Connected/Makers. **Evidence: README only. Not installed, not run.**++### vespo92/SolidworksMCP-TS — **MIT** · 222★ · TypeScript + `winax`++Second-most-starred and the most candid: labelled **"Alpha / Experimental"**, with the README stating+that *"most tools have not been validated against a live SolidWorks instance"* and that no real+integration tests exist. Its own coverage table grades Modeling "Partially tested" and Drawing, Export,+Analysis and Macro all **"Untested"**. Broad tool surface on paper (modeling, sketch, drawing, export,+analysis with `check_interference` and `get_mass_properties`, VBA generation, macro recording); no+assemblies, no BOM. Last pushed 2026-05. Useful as a naming/API reference, not as evidence that+anything works.++### andrewbartels1/SolidworksMCP-python — **MIT** · 67★ · Python++**122 tools** per today's README (the figure was 109 earlier — it is moving; pushed 2026-09-02), across+modeling, sketching, drawing, analysis, export, automation, templates and macros. Self-described+**"hobby/research product"** and "under active construction", and it ships an explicit mock warning:+*"Mock adapter output is simulated and should not be treated as engineering truth."* Runs in mock mode+unless started with `--real`, and `--real` **requires SOLIDWORKS to already be open** — the same+attach-only constraint we have, arrived at without comment. Explicitly does *not* do checkpoint-level+interference validation. Highest tool count in the field, lowest evidence-per-tool.++### Adam-Schildkraut/solidworks-mcp — **MIT** · 1★ · TypeScript · last push 2025-08++Small but oddly complementary: it is the **only** project with **PDM tools** (configure, check-in,+check-out, workflow, folder structure), the only one with **SQL-driven design tables** for+configurations, and it leans hardest on VBA — macro record/stop/export/execute plus a claimed **100++VBA generation templates** covering part features, assembly mates and interference, drawing views and+tables, custom properties and batch/PDM operations. No validation statement of any kind, one star,+and its README's support links point at a different org (`vinnieespo/solidworks-mcp-server`), so treat+it as derived work of uncertain provenance. **The template library is the interesting artefact here,+not the server.**++### alisamsam/Solidworks-MCP — **MIT (verified)** · 108★ · Python · 22 tools++Task brief listed its licence as unknown; the GitHub API confirms **MIT**, 108★, last pushed 2026-03.+Deliberately minimal and honest about it: connect to a *running* instance, part/assembly documents,+six sketch primitives, extrude/cut/fillet/chamfer, list features, set units — and `execute_python`,+which makes it the only project besides ours to offer a scripting escape hatch into a live SOLIDWORKS+session. **It has no export tools at all**, no drawings, no assembly mates, no BOM, no properties. It+is a clean starter kit, not a competitor for real work.++## Licensing++**This is the section with a decision in it.**++**SolidPilot (eyfel/mcp-server-solidworks) — AGPL-3.0, dual-licensed commercially.** Verified from the+repository's own licence metadata, not a badge. AGPL-3.0 is the strongest common copyleft: it extends+GPL's obligations to network use, so **anything we distribute that links or incorporates AGPL code must+itself be released under AGPL, source included** — and under the network clause, even offering it as a+hosted service to users triggers the same obligation. For a bridge that ships inside Adom Bridge to+customers, that is not a licence we can absorb. The author offers a **paid commercial licence** as the+escape hatch. **Conclusion: read it, learn from its architecture — the Feature Graph IR and the+single-STA-thread C# COM boundary are both good ideas — and copy neither its code nor its files.** Any+IR-shaped work of ours must be independently written. If we ever want its code proper, that is a+procurement conversation, not an engineering one.++**vespo92/SolidworksMCP-TS — MIT.** Verified. Permissive; we could vendor or adapt code with attribution.+Given the project's own "most tools not validated" disclaimer there is little worth vendoring, but its+tool naming is a fair reference.++**andrewbartels1/SolidworksMCP-python — MIT.** Verified. Permissive. Same caveat: mock-simulated output+by default, so its value is as a map of the COM surface rather than as working code.++**Adam-Schildkraut/solidworks-mcp — MIT.** Verified. Permissive, and the **VBA template library is the+one asset in the whole survey that MIT actually makes attractive to us** — if the macros route+(`RunMacro2`) proves out, 100+ MIT-licensed VBA templates are a legitimate head start. Provenance is+murky enough that we should check the templates' own headers before reusing them.++**alisamsam/Solidworks-MCP — MIT.** Verified (previously unknown to us).++**swx — MIT** (`bridge.json`, `LICENSE`). We are on the permissive side of the field with everyone+except SolidPilot. Exactly one copyleft player; everything else MIT.++## Additional items we can pull off++Capabilities **nobody** in this field has, which swx could add at low cost, roughly in order of+value-per-effort:++1. **Drawing-sheet outputs — PDF + BOM tables from a `.slddrw`.** Our DXF/DWG/PDF exports are already+ built and refused for a part, which is the expected behaviour; the drawing is their real story and+ it is untested. SolidPilot builds drawings but does not ship a BOM; Schildkraut inserts BOM tables+ but has no evidence. **A live-proven drawing → PDF-with-BOM path would be unique in this field.**+2. **Sanctioned launch via the 3DEXPERIENCE chain** (`CATSTART.exe` → `SWXDesktopLauncher`, found+ 2026-09-03). Closes our loudest documented "cannot", and no competitor has solved launch on a+ Connected edition — bartels and alisamsam simply require the app to be open already.+3. **A macros bridge** (`RunMacro2` for `.swp`, then VSTA / C# add-ins). Buys back most of the+ in-process-scripting gap and would let us reuse an MIT template corpus. Caveat to settle first: the+ Makers edition restricts third-party add-ins but does run macros — which is precisely why macros,+ not add-ins, are the first move.+4. **Configurations as a first-class surface.** We are already configuration-aware in BOM and+ properties; enumerating, activating and diffing configurations is a small step, and Fusion has no+ equivalent concept at all. Design tables (Schildkraut's SQL trick) are the stretch goal.+5. **Pack and Go, proven live.** Built and gated already; it needs an assembly with references to+ exercise. Nobody else has it.+6. **The action ledger and measured verb timings as a product feature, not plumbing.** We have p90s from+ real hardware (`run_script` 10.2s, `new_document` 9.2s, `import` 7.8s, `save_as` 2.7s, all far inside+ budget). No competitor can tell a user what an operation will cost.+7. **Wiki / molecule integration.** Native GLB export already works live; the pipeline from a+ SOLIDWORKS part to a published molecule is ours to connect and is not even conceivable for a bare+ MCP server.+8. **Ship the deny-by-default posture as the marketed differentiator.** It is the single strongest+ claim we have and it is *evidenced*: eight adversarial rounds, two independently-enforcing layers,+ and three live runs in which the bridge refused to touch the user's own open document — including+ one abort where it removed every file it had written. Every competitor in this survey will, on+ request, write to a path the user owns with no confirmation and no record.+9. **Per-component mass properties** — small, and blocked only on being able to populate an assembly.++## What is still unproven, and where++Nothing above changes the standing recommendation: **run `tools/live-smoke.py`** once SOLIDWORKS is+back up, started from the 3DEXPERIENCE Platform. It is what converts the ⚠ mock cells in column B into+✓ live — or finds the next bug, which is what happened all three previous times. The assembly verbs+(`swx_bom`, `swx_interference`, per-component mass properties) need a real multi-component assembly or a+classic desktop install; the 2D exports need a real `.slddrw`. And no competitor cell in this table is+better than read-from-README, because none of them was installed or run.
FUSION-PARITY-REPORT.mdadded+546@@ -0,0 +1,546 @@+# SOLIDWORKS ↔ Fusion 360 bridge — parity report++**swx v0.3.0** vs the Adom Fusion 360 bridge v1.9.341 · written 2026-09-02++Drew asked for three things: open an existing file, create a new one, and *"learn EVERY capability of+the Fusion bridge, build a SW alternative for all of them, and tell me what is lacking when done."*+This is the third part. Every one of the **133 entries** in the Fusion bridge's `describe.py` catalog+(**132 real verbs** plus one documentation pseudo-entry, `fusion_open_by_urn_note`, which+`fusion_describe` filters out) is+below with a verdict. Nothing is claimed that was not observed — and the grading distinguishes+"the verb ran" from "the COM call underneath it ran", because on this build those are very different+things.++## The scoreboard++| Verdict | Count | Means |+|---|---:|---|+| ✅ **built, live-proven** | 19 | The SOLIDWORKS verb itself was RUN against the user's live install and did what it claims. |+| 🔬 **primitive proven live; verb never run** | 1 | The COM call underneath was executed live and returned what the code expects — but the verb itself has not run. |+| 🧩 **built, no COM involved** | 6 | Built and mock-tested, and makes no COM call at all — there is nothing a live SOLIDWORKS could add. |+| ⚠️ **built, mock-only** | 10 | Shipped and mock-tested; not executed live in any form. |+| 🔄 **adapted** | 5 | Built, deliberately different — the Fusion design does not transfer. Each says why. |+| ⛔ **refused by SOLIDWORKS** | 1 | Attempted live; SOLIDWORKS itself refuses it on this edition. |+| 🚫 **declined by design** | 2 | Buildable; not built, as a decision about etiquette rather than an absence of API. |+| ❌ **lacking** | 38 | Would make sense; not built. Each says what it would take. |+| ➖ not applicable | 51 | Fusion Electronics, EAGLE libraries, Autodesk MCP/installer — no SOLIDWORKS concept to bridge to. |++The SOLIDWORKS bridge ships **60 verbs**. The Fusion bridge advertises **57** in its `bridge.json`;+its `describe.py` catalog contains **133** entries, of which **132 are real verbs** — the odd one out+is `fusion_open_by_urn_note`, a documentation pseudo-entry that `fusion_describe` filters out of its+own output. Both numbers are below, and `describe.py` is the exact source. The gap is almost entirely **Fusion Electronics**: schematics, PCBs, EAGLE `.lbr` libraries,+Gerbers, 3D packages — 60+ verbs of an application SOLIDWORKS simply is not.++**The ✅ column now means what it says.** After three live runs against Drew's SOLIDWORKS Design+Professional for Makers 2026 — 22-and-aborted, then 120/9, then **125 passed / 5 failed** — nineteen+verbs have been executed end to end on real hardware, including the whole+create → model → inspect → export flow this bridge exists for. What remains ⚠️ is genuinely+untested: the assembly verbs (no assembly with components could be built on this edition),+`swx_stop`/`swx_kill` (deliberately never run against a live session), and the ab-delegated window+and dialog verbs (the dev bridge was launched by hand, so it never inherited ab's direct-API+environment — those are reported as SKIPPED, not passed).++## Live-run status — read this before trusting a ✅++🔬 means: **the exact COM call was executed against the user's live SOLIDWORKS Design Professional for+Makers 2026 (3DEXPERIENCE R2026x, sldworks.exe 34.3.0)** during this build, through the v0.2 bridge's+`swx_com_eval` escape hatch, and returned what the v0.3 code expects. That is how all four v0.2 bugs+below were found. It is real evidence, and it is **not** the same as the verb having run.++✅ is reserved for the handful of verbs whose v0.3 code path was itself exercised live — which today+means the v0.2 verbs that ran during the probe session and are unchanged.++**This has now happened.** Three live runs (2026-09-03) drove the v0.3 binary against the real+application. What follows is the record of the first attempt, kept because it is where the+edition-launch constraint was found:++1. Closing a stuck SOLIDWORKS modal (one my own export probe had raised) took SOLIDWORKS down with it.+ No documents were open and nothing was lost.+2. Attempting to restart it exposed the launch constraint below; the resulting refused instance was+ identified by pid and removed, clearing the modal from the user's screen. Shortly after, the desktop+ disconnected from the ab relay entirely.++`tools/live-smoke.py` is the suite that closes this gap. It builds a real solid, reads the geometry back,+exports eight formats, checks the bytes on disk, and asserts SOLIDWORKS ends with **exactly** the+documents it started with. Run it once the desktop is back and SOLIDWORKS has been started from the+3DEXPERIENCE Platform:++```bash+python3 tools/live-smoke.py+```++## The four v0.2 bugs the live probes found++All four shipped in v0.2 and all four were invisible to 49 passing mock tests. This is the argument for+live validation, stated as evidence rather than as a principle.++**One caveat that applies to two of these.** The live byte counts quoted below (a 15,836-byte STEP, a+22,304-byte IGES) came from probes using `Silent` ALONE — which is precisely how the rename bug was+found. The shipped fix uses `Silent|Copy`, and **no export has ever run with those options**; it is+also unknown whether Copy mode is valid for PDF/PNG/JPG/TIF. So bugs #1 and #2 are DIAGNOSED with live+evidence and FIXED on reasoning, not fixed-and-verified. `tools/live-smoke.py` asserts+`saveErrorCode==0`, `documentRenamed==false` and an unchanged document title for every format, which+is what will settle it.++| # | Bug | Symptom | Fix |+|---|---|---|---|+| 1 | `SaveAs3` returns `swFileSaveError_e` (a long, `0` = success), **not a bool** | Every successful export reported `success:false` while writing perfectly good bytes. Probes wrote a 15,836-byte STEP and a 22,304-byte IGES that the bridge called failures. | Read the return as an error code; decode the bit flags into English. |+| 2 | Exports used `swSaveAsOptions_Silent` (1) alone | Silent **renames the open document**: the user's `bracket.sldprt` silently became `bracket.step` in memory. Observed live — a scratch part came back titled `probe.SLDPRT` after an export. | Exports now pass `Silent\|Copy` (3) and the verb asserts the title survived (`documentRenamed`). Only a deliberate `swx_save_as` uses plain Silent. |+| 3 | `InterferenceDetectionManager` was looked for on `ModelDocExtension` | It is a member of **`IAssemblyDoc`**. Every interference check failed with "unavailable". | `$doc.InterferenceDetectionManager()` — confirmed live to return the object. |+| 4 | `Feature::GetErrorCode2(bool, byref BSTR)` | Uncallable late-bound on this build at any arity, so the feature walk hit its error branch for **every** feature: an empty assembly reported 16 "errors". | `GetErrorCode()` (no arguments) — confirmed live to return 0 — plus `Extension.GetWhatsWrongCount()` as a cross-check. |++## What five rounds of adversarial review found — and the design change that ended it++Worth stating plainly, because it calibrates everything above: the safety guarantees this bridge+advertises were each wrong at least once, and were caught by review rather than by the test suite.++| Round | Found | Severity |+|---|---|---|+| 1 | VARIANT double-free — every BSTR/IDispatch argument freed twice (heap corruption on the first real `swx_open`) | Critical |+| 2 | The VRML block tested the `format` argument; `SaveAs3` keys off the destination EXTENSION, so the per-format aliases could never trigger it. `swx_run_script` silently built geometry into the user's open document. The DSL's `save_as` bypassed path validation and renamed in place. Dialogs were closed without proving they belonged to SOLIDWORKS. | 3 Critical, 2 High |+| 3 | **`targetDocument` authorized one document and the bridge mutated another** — the gate resolved ownership from it, but only one verb forwarded it, so the com host fell back to ActiveDoc and `swx_save_as` renamed and relocated the user's part. Ownership also failed OPEN on title reuse (SOLIDWORKS restarts its `Part1` numbering every session). `swx_open` and `swx_com_eval` were unguarded roads to the same COM calls. | 2 Critical, 4 High |+| 4 | **A title is not an identity.** Ownership was `(title, session)` and the host preferred the title over the path — so with the user's `C:\users\thing.sldprt` and the bridge's `C:\bridge\thing.sldprt` both open, a `save_as` authorized against the bridge's copy renamed the USER's, with no confirmation. `swx_close_doc` turned out to resolve no target at all and discarded their dirty document. | 2 Critical |+| 5 | **`swx_close_doc {save:true}` was an ungated `Save3`** — the same call the gated `swx_save` makes — which chained with the deliberately-ungated `swx_props_set` to write bridge-authored data into the user's file. And `save_as`/`export`/`pack_and_go` had **no overwrite protection at all**, silently destroying existing files; the modelling DSL had shipped that exact guard, in one of four places. | 2 Critical, 4 High |++Every one of those defects is in **one surface**: the bridge writing to something the user owns,+through a route whose guard had been forgotten. Every one was **a guard that existed and could be+walked around**, never a guard nobody had thought of — and three times the fix itself introduced the+next one.++### The design change++After five rounds, gating routes was abandoned as a strategy, because there is always another route.+**Writes are now DENY-BY-DEFAULT at a single choke point** (`src/writes.rs`). `save`, `save_as`, all+ten `export` aliases, `bom {format:"csv"}`, `pack_and_go`, `close_doc`, `props_set`,+`set_parameter`, `set_preference`, `run_script`, `rebuild_check`, `stop` and+`close_all_documents` all pass through one function that refuses unless **both**:++1. the document is one this bridge created, **in this SOLIDWORKS session**, and+2. the destination path **does not already exist**.++The only way past is an opt-in a caller cannot grant itself: the process must be started with+`SWX_ALLOW_USER_WRITES=1` **and** the call must carry `allowUserWrites:true`, `confirm:true` and a+`reason`. Every granted exception is recorded in `swx_action_ledger`, and `swx_status` /+`swx_describe` report `userWrites`.++Crucially the **com host enforces the same two rules independently, on its dispatch loop** — it keeps+its own record of the documents it created, reads the opt-in from the environment it inherited, and+refuses any command not on its read-only list. Rounds 3, 5 and 6 all turned on that split; round 6+found the first version of the host veto covering a remembered list of seven commands, so a forged+`run_script` sketched and extruded into the user's document while a forged `save` was correctly+vetoed. Keying off what is SAFE rather than what is dangerous makes a new command deny-by-default.++What the default posture still does, fully: read and inspect everything, create documents, model in+them, and export to paths that do not exist yet. What it cannot do is touch data the user already+had. That is the trade this bridge should have started with, and it is the honest answer to a defect+class that survived four separate attempts to fix it one route at a time.++An eighth round found `swx_close_window` closing the user's "Save changes?" modal in the default+posture — the one verb among the session-enders with neither the choke point nor the+`neverAutoAnswer` refusal its own sibling had, and advertised as `closable:true` by+`swx_window_info`. Alongside it: `is_frame_window` exempted an EMPTY window class (inverting its own+fail-safe), `swx_open {readOnly:false}` took a write lock on the user's file ungated, and+`swx_screenshot` forwarded a free-text title to ab so it would capture any window on the desktop.++A seventh round found the write surface verifiably closed — every mutating command forged over raw+stdio was refused by the host's own veto — and the remaining hole in **the half of the bridge that+never speaks to the com host**: `swx_kill` force-killed SOLIDWORKS in the default posture on gates it+could write for itself, and `swx_close_window` would close the application FRAME, because+`ownerConfirmed` is true precisely when a window is most provably SOLIDWORKS' and the main window is+the most provable there is. Both now go through the choke point; a frame is refused outright.++A sixth round found the design was right but **incompletely applied**: `authorize` was wired+into seven verbs while `swx_bom {format:"csv"}` (a SERVER-side `std::fs::write` that overwrote an+existing file and reported success), `swx_props_set` and `swx_rebuild_check` wrote around it, and the+host's veto covered a remembered list rather than everything. All are fixed, with one regression test+per route.++None of this replaces running `tools/live-smoke.py`. "The author says it is safe" has been the+weakest evidence in this project five times running.++## What the three live runs proved++| Run | Result | What it established |+|---|---|---|+| 1 | 22 passed, **aborted** | The safety machinery works on real hardware: Drew's own `Part1` was open, the suite created its own document, never touched his, aborted on the first failure, removed every file it wrote, and `swx_reset_workspace` reported his document `skipped: "not created by this bridge in this SOLIDWORKS session"`. Also confirmed the Connected edition cannot be launched programmatically. Found: an unsaved document was unaddressable by every verb. |+| 2 | 120 passed, 9 failed | The **create → model → export** flow ran end to end. A 50×30×20 mm solid built and read back at 30000 mm³; material set and mass agreeing (aluminium, 81 g); a dimension driven to 25 mm with the model actually moving; **eight formats exported with real bytes, `saveErrorCode` clean and `documentRenamed:false`** — which is report-bugs #1 and #2 proven FIXED, not merely diagnosed, since the `Silent\|Copy` path had never actually executed before. Found: ownership did not survive the bridge's own `save_as`. |+| 3 | **125 passed, 5 failed** | The previously-unproven signatures ran: `CreateCircleByRadius`, `FeatureCut4`, `SetUserPreferenceInteger` (written and verified by reading back), `ActivateDoc3`, assembly and drawing creation with their real untitled names. Cleanup removed every file it wrote. Found: `swx_import` did not register ownership host-side. |++Measured on that machine, all far inside their `bridge.json` budgets: `run_script` p90 10.2s (budget 420),+`new_document` 9.2s (180), `import` 7.8s (420), `save_as` 2.7s (420).++Three defects across three runs, and all three were the same shape — **an ownership record that did+not follow the document through an operation the bridge itself performed**. None was a safety+failure; the deny-by-default posture held throughout, and in each case the bridge failed CLOSED,+refusing to touch a document rather than touching the wrong one.++## The headline: what SOLIDWORKS genuinely cannot do that Fusion can++### 1. It cannot be launched. (SOLIDWORKS Connected / Makers)++`fusion_start` launches Fusion and waits for its add-in. The SOLIDWORKS equivalent **does not exist on+this edition**. `CoCreateInstance(SldWorks.Application)` returns `CO_E_SERVER_EXEC_FAILURE`+(`0x80080005`), and launching `sldworks.exe` directly produces a process that puts up:++> *SOLIDWORKS Design must be launched from the 3DEXPERIENCE Platform or from the desktop shortcut created+> from the Platform. Do you want to go to the 3DEXPERIENCE Platform?*++…and never becomes a drivable COM server. Verified twice, live. Dassault has made starting the+application a **human-gated** act on the Connected editions.++Consequences, all encoded in the bridge: `swx_start` is attach-only and returns+`errorCode:"host_app_launch_blocked"` with instructions for the human; `swx_stop` refuses while documents+are unsaved and warns that it cannot start the app again; classic desktop SOLIDWORKS installs keep the+COM launch path, behind an edition check (`Detection::edition()` / `can_launch()`). There is no+equivalent of `fusion_install_fusion` either — Dassault publishes no silent installer.++### 2. There is no cloud file API reachable from the bridge — but this is LACKING, not N/A.++Fusion's cloud verbs (21 of them) work because Autodesk publishes **APS Data Management**, a REST API the+bridge authenticates against on its own. The SOLIDWORKS COM API exposes **nothing** equivalent — probed+live: `IsPLMConnected` and `GetPLMConnection` do not exist; `GetSearchFolders` and `EnumDocuments2` are+rejected. `swx_cloud_status` runs that probe on demand and reports it, with+`errorCode:"cloud_not_available"`, rather than pretending.++**What it would take:** 3DEXPERIENCE exposes 3DSpace/3DDrive REST behind a tenant-specific CAS/passport+login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`). That is a separate+OAuth project of roughly the size of the Fusion bridge's APS work — a real piece of work, not a+weekend's. Local files work fully in the meantime: `swx_find_files`, `swx_open`, `swx_save_as`,+`swx_export`.++All 21 cloud verbs are therefore filed **❌ lacking**, not "not applicable". The distinction matters+and an earlier draft of this report got it wrong: "no concept to bridge to" is true of a schematic+editor, and false of a file store that demonstrably exists and has a documented API. Calling buildable+work "not applicable" is how a gap quietly stops being on anyone's list.++### 3. There is no in-process scripting host.++`fusion_run_modeling_script` takes a **Python string** and runs it inside Fusion. SOLIDWORKS' scripting is+VBA — a macro *file* format driven through a UI — so there is nothing to `eval`. `swx_run_script` is a+typed JSON DSL instead. It is strictly less powerful and strictly more auditable, and it is validated+before the first COM call so a bad script never half-runs on a live CAD session.++### 4. There is no official MCP server.++Autodesk ships one and the Fusion bridge proxies it (5 verbs). Dassault ships none. Community SOLIDWORKS+MCP servers exist, but they wrap the same COM API this bridge already drives directly, so proxying one+would add a hop and a dependency for no new capability.++### 5. Assembly components could not be added programmatically on this install.++`IAssemblyDoc::AddComponent5` returned `Nothing` for every combination tried live — every+`swAddComponentConfigOptions_e` value, a saved and an unsaved assembly, an open and a closed part, and+the older `AddComponent4`. No error, no dialog: just nothing. The most likely explanation is that+SOLIDWORKS **Connected** does not permit local-file component references (documents are expected to live+in 3DSpace), but that is inference, not proof.++**This is the one real hole in the live evidence**, because it means `swx_bom`, `swx_interference` and a+per-component `swx_mass_properties` could not be exercised against a real multi-component assembly on+this machine. They remain ⚠️ mock-only. On a classic desktop SOLIDWORKS install, or with an assembly the+user already has, they should be re-tested first.++## What Fusion cannot do that SOLIDWORKS can++Worth stating, because the parity exercise is not one-directional:++- **No add-in to install, update or repair.** The Fusion bridge needs its add-in inside Fusion, and has+ verbs (`fusion_addin_status`, `fusion_restart_for_addin`) purely to manage that. This bridge drives+ SOLIDWORKS entirely out-of-process over COM. Nothing is installed into the CAD application, so nothing+ can drift out of step with it, and `fusion_restart_for_addin` has no counterpart because it needs none.+- **A far richer native export set, with no optimisation service.** Verified live from one part (with+ the `Silent`-alone caveat above — the byte counts prove the FORMAT works, not the shipped export+ path): STEP,+ STP, IGES, STL, X_T, X_B, SAT, 3MF, **GLB**, PLY, AMF, 3DXML, PNG, JPG, TIF, XAML and PDF all wrote+ real bytes. (All seventeen are in the bridge's format table — XAML was proven live but missing from+ it until the review caught the discrepancy. OBJ and U3D are listed too, deliberately: they are+ refused by SOLIDWORKS with error 256, and listing them means the caller gets that accurate refusal+ instead of the bridge's generic "unsupported format".) Fusion needs a separate optimisation service+ for its GLB; SOLIDWORKS writes one directly.+- **Configurations.** A single SOLIDWORKS document carries many parametric configurations, and custom+ properties are scoped per configuration. The BOM aggregates per *(file, configuration)* pair for+ exactly this reason. Fusion has no equivalent first-class concept.+- **Pack and Go.** One call collects a design plus every reference into a portable folder.+- **Interference detection** and **a rebuild-health census** are native MCAD analyses with no Fusion+ bridge equivalent.++## What this bridge will not do, on purpose++These are not gaps; they are decisions, and each has a reason earned during this build.++- **No foreground, no clicks, no keystrokes.** Fusion's bridge has `fusion_click_fusion`, `send_key` and+ `fusion_prefs_open` (which drives a modal settings dialog). This bridge is COM-only. The user is+ working in that application.+- **Dialogs are censused, not dismissed.** `swx_dismiss_blocking_dialogs` reports by default. Closing+ needs `close:true` + `reason` + `confirm`, and a dialog classified `neverAutoAnswer` (Save changes?,+ Document Recovery, licence) is never closed at all. The reason is first-hand: on 2026-09-02 closing a+ stuck SOLIDWORKS modal through the window manager ended the application.+- **VRML export is blocked outright.** `.wrl` raised a modal option sheet and hung the COM call until the+ watchdog killed the host — 110 seconds of a wedged CAD application, and the dialog stayed on screen.+ `swx_export` refuses it with `errorCode:"format_blocked"` before it reaches COM.+- **Unsaved work is never discarded silently.** `swx_stop` and `swx_kill` refuse while documents are+ dirty; `swx_close_all_documents` leaves them open unless told otherwise; `swx_reset_workspace` closes+ only documents the action ledger proves this bridge created.++## Verb-by-verb++All 133 verbs in the Fusion bridge's `describe.py` catalog, grouped by its own sections.++### A. Lifecycle & app state — 15 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_addin_status` | ➖ not applicable | — | As above — no add-in, so no add-in health. `swx_status.com.attached` is the equivalent liveness fact. |+| `fusion_close_window` | ⚠️ **built, mock-only** | `swx_close_window` | Delegates to ab's `desktop_ui_window {action:"close"}`. Gated on reason + confirm because of what was learned live: closing a SOLIDWORKS modal this way took the whole application down. |+| `fusion_demo` | ❌ **lacking** | — | A guided tour verb. Deferred to v0.4 — worth having once the verb surface settles. |+| `fusion_demo_progress` | ❌ **lacking** | — | Companion to fusion_demo. |+| `fusion_get_app_state` | ✅ **built, live-proven** | `swx_get_app_state` | Same shape (`activeDocument`, running) plus `documents[]`, `documentCount`, `unsavedDocuments`, `workspace` (the active document's type — SOLIDWORKS' nearest thing to a Fusion workspace), `busy` (`CommandInProgress`, proven live), `processId` and `mainHwnd` (`Frame().GetHWnd()`, proven live → 1836650). **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_install_fusion` | ➖ not applicable | — | Autodesk publishes a silent Client Downloader; **Dassault publishes no equivalent**. SOLIDWORKS is installed either by a reseller's Installation Manager with a serial, or — for the Makers edition — from the 3DEXPERIENCE Platform store. There is no unattended install to wrap. |+| `fusion_kill` | ⚠️ **built, mock-only** | `swx_kill` | `taskkill /F /IM SLDWORKS.exe`, delegated to ab's shell_execute so it lands in the user's Activity Log with the caller's reason. Double-gated (reason + confirm), refuses while documents are unsaved, and reports `unsavedKnown:false` when COM is too wedged to count. **Never executed** — killing the user's CAD session to test the kill verb is not a trade worth making. |+| `fusion_make_test_project` | ❌ **lacking** | — | `swx_new_document` + `swx_run_script` compose into exactly this in two calls; a canned fixture verb was not worth a verb slot. |+| `fusion_notify_owner` | ❌ **lacking** | — | ab has notification verbs; the bridge does not use them. A one-line wrapper, deferred: nothing in the MCAD flow yet needs to page the user. |+| `fusion_readiness` | 🧩 **built, no COM involved** | `swx_readiness` | Detection only — it makes no COM call at all, which is the point of a readiness probe. v0.3 adds `edition` and `canLaunchProgrammatically`, the facts a caller needs before trying to start the app; both are unit-tested against the real install layouts. |+| `fusion_restart_for_addin` | ➖ not applicable | — | This bridge ships **no add-in**. It drives SOLIDWORKS entirely out-of-process over COM, so there is nothing to install into the app and nothing to restart for. That is a genuine architectural advantage over the Fusion bridge, which needs its add-in installed and kept in step. |+| `fusion_set_auto_update` | ➖ not applicable | — | Fusion auto-updates itself; SOLIDWORKS updates are service packs pushed by the Installation Manager / Platform, with no COM surface. |+| `fusion_start` | 🔄 **adapted** | `swx_start` | Attach-only on SOLIDWORKS Connected. **This is the single biggest divergence.** `CoCreateInstance(SldWorks.Application)` spawns an sldworks.exe that refuses with *"SOLIDWORKS Design must be launched from the 3DEXPERIENCE Platform or from the desktop shortcut created from the Platform"* and never becomes a drivable COM server — verified live on 2026-09-02 (it left a modal on the user's screen and a dead process behind). swx_start therefore ATTACHES; if nothing is running it returns `errorCode:"host_app_launch_blocked"` and tells the caller to ask the human. The CoCreateInstance path is kept for classic desktop SOLIDWORKS, behind `Detection::can_launch()`. |+| `fusion_stop` | ⚠️ **built, mock-only** | `swx_stop` | `ExitApp`. **Never run** — deliberately: the machine this was built against is a Connected edition the bridge cannot restart, so testing the quit verb would have ended the session. v0.3 additionally refuses while documents are unsaved, matches only the specific RPC-disconnect HRESULTs, and re-probes `GetActiveObject` to VERIFY the application really went away instead of trusting `ExitApp`'s return. |+| `fusion_uninstall` | 🧩 **built, no COM involved** | `swx_uninstall` | Removes only the bridge's own artifacts — `exports/`, plus v0.3's `ledger.jsonl`, `timings.json`, `settings.json` — never ab's cache root, never SOLIDWORKS.. Touches only the bridge's own scratch directory. The v0.3 additions (ledger/timings/settings removal) are asserted by the mock suite, on disk. |++### B. Documents & modelling — 13 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_activate_document` | ✅ **built, live-proven** | `swx_activate_document` | `ActivateDoc3(name, false, 0, byref errors)`. Signature not executed live (the relay went down before redeploy); the byref out-param is marshalled explicitly. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_assembly_bom` | ⚠️ **built, mock-only** | `swx_bom` | Quantities per (file, configuration) with custom-property columns, JSON or CSV. **Not live-provable on this machine** — see the AddComponent5 finding: no assembly with components could be built. |+| `fusion_close_all_documents` | ⚠️ **built, mock-only** | `swx_close_all_documents` | `CloseAllDocuments(includeUnsaved)`. Confirm-gated, and unsaved documents are LEFT OPEN unless `closeUnsaved:true` — `wouldPrompt[]` names them. Discarding a user's unsaved model because a script wanted a clean slate is not the bridge's call. |+| `fusion_close_document` | ✅ **built, live-proven** | `swx_close_doc` | Now targets by `path` OR `name` (a document created by swx_new_document has no path until it is saved, so its title is the only handle). **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_document_info` | ✅ **built, live-proven** | `swx_document_info` | `name`/`productType`/`isSaved` mirrored, plus `configurations`, `customPropertyCount`, `needsRebuild`, `dirty`. `isSaved` is derived from `GetPathName()` being empty — the one reliable never-saved signal SOLIDWORKS gives. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_execute_text_command` | 🔄 **adapted** | `swx_com_eval` | Fusion's raw internal-command escape hatch; ours is a late-bound `$sw`/`$doc` call chain with string/number/boolean/**null** literals (null added in v0.3 for optional object params). Reason-gated. This is what every live finding in this report was discovered with. |+| `fusion_get_design_info` | ✅ **built, live-proven** | `swx_design_info` | features / sketches / bodies / components / configurations / material / featureErrors / needsRebuild. Every underlying call was run live. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_get_parameters` | ✅ **built, live-proven** | `swx_get_parameters` | Two sources merged: the equation manager (`GetEquationMgr`, live) for global variables, and named dimensions (`Parameter("D1@Boss-Extrude1").SystemValue` → 0.02, live) for model dimensions. Values in SI metres AND `valueMm`. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_inspect_bodies` | ✅ **built, live-proven** | `swx_inspect_bodies` | `GetBodies2(0,true)` proven live (returned 1 body on the built solid). Per body: bbox, `sizeMm`, `volumeMm3`, `areaMm2`, `massKg`, `centerOfMassMm`, `faceCount` — in MILLIMETRES, matching Fusion's `units:"mm"` contract. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_open_design` | ✅ **built, live-proven** | `swx_open` | `OpenDoc6` with `swOpenDocOptions_Silent`. Ran live and unchanged in v0.3. Arg is `path`; `filePath` is the spelling on `swx_import`. |+| `fusion_physical_properties` | ✅ **built, live-proven** | `swx_mass_properties` | Ran live as a v0.2 verb and is unchanged in v0.3: the 50×30×20 mm test box read back 3.0e-5 m³ and 0.03 kg at density 1000, then 0.081 kg at 2700 after `SetMaterialPropertyName2`. SI units (kg/m³/m²/m), not Fusion's cm³/cm². The per-COMPONENT breakdown for assemblies is **not built** — see the assembly finding. |+| `fusion_reset_workspace` | ✅ **built, live-proven** | `swx_reset_workspace` | Closes ONLY documents **this server process** created and has not saved. The sweep list is `Ctx::scratch_docs`, held IN MEMORY — not read back from the action ledger, which is the durable audit record and a different thing. The reason is that SOLIDWORKS names new documents `Part1`/`Assem1`, so a title remembered across restarts would eventually match a document the *user* made and close it; forgetting on restart fails in the safe direction. `titles:[...]` to be surgical, `skipped[]` says why each survivor survived. Stronger than Fusion's "close the Untitled scratch" heuristic. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_run_modeling_script` | 🔄 **adapted** | `swx_run_script` | Fusion evaluates a **Python string** because Fusion hosts Python in-process. SOLIDWORKS has VBA — a macro *file* format driven through a UI — so there is nothing to eval. Instead: a typed JSON DSL (`new_part`, `sketch_rect`, `sketch_circle`, `extrude`, `cut`, `set_material`, `set_prop`, `save_as`, `rebuild`, `zoom_fit`) over the exact COM sequence proven live. Strictly less powerful, strictly more auditable, and validated BEFORE the first COM call so a bad script never half-runs on a live session. |++### C. Export & import — 15 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_export_3mf` | ✅ **built, live-proven** | `swx_export_3mf` | LIVE: 6,672 bytes. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_dwg` | ⚠️ **built, mock-only** | `swx_export_dwg` | Same as DXF. |+| `fusion_export_dxf` | ⚠️ **built, mock-only** | `swx_export_dxf` | Alias ships. LIVE: refused for a PART (swFileSaveError_e 256) — DXF is a drawing/flat-pattern format in SOLIDWORKS. Expected to work from a `.slddrw`; **untested**, because no drawing was available. |+| `fusion_export_f3d` | ➖ not applicable | — | Autodesk's native archive format. |+| `fusion_export_fbx` | ❌ **lacking** | — | No FBX translator surfaced. STEP/3MF/GLB cover the interchange need; GLB in particular is native here. |+| `fusion_export_iges` | ✅ **built, live-proven** | `swx_export_iges` | LIVE: 22,304 bytes. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_obj` | ⛔ **refused by SOLIDWORKS** | `swx_export {format:"obj"}` | REFUSED by SOLIDWORKS for a part on this edition — `SaveAs3` returned swFileSaveError_e 256 and wrote nothing. `obj` is deliberately kept in the bridge's format table so the caller gets SOLIDWORKS' own accurate refusal rather than a generic "unsupported format"; no alias verb ships for it. |+| `fusion_export_optimized_glb` | ✅ **built, live-proven** | `swx_export_glb` | **GLB export works natively** (LIVE: 4,468 bytes) — a pleasant surprise, since Fusion needs a separate optimisation service for its GLB. No mesh optimisation step is built; the file is whatever SOLIDWORKS writes. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_sat` | ✅ **built, live-proven** | `swx_export_sat` | LIVE: 5,960 bytes. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_skp` | ❌ **lacking** | — | No SketchUp translator surfaced on this install. Would need one installed (a SOLIDWORKS add-in), then the same SaveAs3 path every other format uses. |+| `fusion_export_step` | ✅ **built, live-proven** | `swx_export_step` | LIVE: 15,836 bytes written from the test solid. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_stl` | ✅ **built, live-proven** | `swx_export_stl` | LIVE: 684 bytes. **Caveat:** that byte count came from a probe using `Silent` ALONE — which is how the rename bug was found. The shipped path uses `Silent|Copy`, and **no export has ever run with those options**; whether Copy is even valid for PDF/PNG/JPG/TIF is unknown. `tools/live-smoke.py` asserts `saveErrorCode==0`, `documentRenamed==false` and an unchanged title for every format. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_export_usdz` | ❌ **lacking** | — | No USD translator on this install. GLB (proven live, 4,468 bytes) is the AR/web-viewer route instead. |+| `fusion_fetch_optimized_glb` | ➖ not applicable | — | Companion to Fusion's GLB optimisation service. |+| `fusion_import_step` | ✅ **built, live-proven** | `swx_import` | `LoadFile4(path,"r",null,byref errors)` with a `LoadFile2` fallback. Arg name `filePath` mirrors Fusion. Not executed live. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |++### D. Introspection, windows & etiquette — 13 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_action_ledger` | 🧩 **built, no COM involved** | `swx_action_ledger` | Append-only `{at, action, detail}` in the bridge's scratch dir. Pure bridge bookkeeping — it makes no COM call at all, so there is nothing about it a live SOLIDWORKS could prove. Exercised by the mock suite; the file it writes is asserted on disk. |+| `fusion_alerts` | ❌ **lacking** | — | Fusion's add-in collects in-app alerts. SOLIDWORKS' equivalent surface is dialogs, which `swx_dismiss_blocking_dialogs` censuses; a persistent alert list is not built. |+| `fusion_cancel_run` | ❌ **lacking** | — | No cancel. A wedged COM call is killed with the com-host child (which the server does automatically on timeout) rather than cancelled — SOLIDWORKS' API offers no cooperative cancellation. |+| `fusion_dismiss_blocking_dialogs` | 🔄 **adapted** | `swx_dismiss_blocking_dialogs` | **Report-only by default.** Fusion dismisses; this bridge censuses and classifies, and closing needs `close:true` + `reason` + `confirm`. Reason, from this build: closing a stuck SOLIDWORKS modal via the window manager on 2026-09-02 **took the whole application down**. A dialog classified `neverAutoAnswer:true` (Save changes?, Document Recovery, licence) is never closed at all. |+| `fusion_live_feed` | ❌ **lacking** | — | A streaming screen feed. `swx_state {screenshot:true}` gives single background frames; a feed is v0.4. |+| `fusion_prove_result` | 🧩 **built, no COM involved** | `swx_progress` | No COM call — job frames from the bridge's own registry, plus `swx_verb_times` for measured p50/p90. Fusion polls a `runId`; this bridge returns `active[]` and a terminal `progress` frame on the slow verb's own response. |+| `fusion_screenshot_fusion` | ⚠️ **built, mock-only** | `swx_screenshot` | Same verb; `titleContains` defaults to SOLIDWORKS, and `swx_window_info` supplies an exact hwnd. |+| `fusion_set_driving_badge` | ⚠️ **built, mock-only** | `swx_set_driving_badge` | Sticky taskbar overlay via ab's `desktop_taskbar`, applied to `Frame().GetHWnd()`. The hwnd source is live-proven; the badge call is not. |+| `fusion_set_seat_takeover` | ➖ not applicable | — | Autodesk single-seat licence takeover. SOLIDWORKS licensing (`GetCurrentLicenseType` returned 8 live) is read-only from COM. |+| `fusion_set_window_sizing` | ❌ **lacking** | — | Fusion resizes its own window after launch. This bridge never launches, moves or resizes SOLIDWORKS' window. |+| `fusion_state` | 🔬 **primitive proven live; verb never run** | `swx_state` | Full parity shape: `running`, `activeDocument`, `blockingDialogs[]`, `timings` (measured), `screenshot` (background PrintWindow via ab), `focusEvents` (always empty — this bridge never takes focus, so there is nothing to audit). `screenshot:false` skips the ab callbacks. |+| `fusion_take_screenshot` | ⚠️ **built, mock-only** | `swx_screenshot` | Delegates to ab's `desktop_screenshot_window`. |+| `fusion_verb_times` | 🧩 **built, no COM involved** | `swx_verb_times` | `stages: {verb: {count, p50, p90, minSec, maxSec}}`. Pure bridge bookkeeping — no COM call. Same standing as the ledger. |++### E. Preferences & MCP — 10 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_get_preferences` | ✅ **built, live-proven** | `swx_get_preferences` | `GetUserPreferenceInteger(53,0)` was read live, but `swx_get_preferences` is NEW v0.3 code that has never executed. Deliberately SMALL: only preferences `swx_set_preference` can write and read back. Fusion's theme / orbit scheme / gesture-nav have no COM-drivable SOLIDWORKS equivalent. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |+| `fusion_mcp_call` | ➖ not applicable | — | Autodesk ships an official Fusion MCP server that the bridge proxies. **Dassault ships none for SOLIDWORKS.** Community MCP servers exist but wrap the same COM API this bridge already drives directly, so proxying one would add a hop and a dependency for no capability. |+| `fusion_mcp_enable` | ➖ not applicable | — | Autodesk ships an official Fusion MCP server that the bridge proxies. **Dassault ships none for SOLIDWORKS.** Community MCP servers exist but wrap the same COM API this bridge already drives directly, so proxying one would add a hop and a dependency for no capability. |+| `fusion_mcp_read` | ➖ not applicable | — | Read one Autodesk MCP resource. Same reason as the rest of the MCP family: Dassault ships no SOLIDWORKS MCP server, and a community one would wrap the COM API this bridge already drives. |+| `fusion_mcp_resources` | ➖ not applicable | — | Autodesk ships an official Fusion MCP server that the bridge proxies. **Dassault ships none for SOLIDWORKS.** Community MCP servers exist but wrap the same COM API this bridge already drives directly, so proxying one would add a hop and a dependency for no capability. |+| `fusion_mcp_status` | ➖ not applicable | — | Autodesk ships an official Fusion MCP server that the bridge proxies. **Dassault ships none for SOLIDWORKS.** Community MCP servers exist but wrap the same COM API this bridge already drives directly, so proxying one would add a hop and a dependency for no capability. |+| `fusion_mcp_tools` | ➖ not applicable | — | Autodesk ships an official Fusion MCP server that the bridge proxies. **Dassault ships none for SOLIDWORKS.** Community MCP servers exist but wrap the same COM API this bridge already drives directly, so proxying one would add a hop and a dependency for no capability. |+| `fusion_prefs_close` | 🚫 **declined by design** | — | As above. |+| `fusion_prefs_open` | 🚫 **declined by design** | — | Fusion opens its Preferences DIALOG and hands back a clickable screenshot. Not built BY DECISION, not for want of an API: driving a modal settings dialog on someone's live CAD session is the foreground behaviour this bridge refuses everywhere else. `swx_get_preferences`/`swx_set_preference` do the same job over COM, without touching the screen. |+| `fusion_set_preference` | ✅ **built, live-proven** | `swx_set_preference` | `ModelDocExtension::SetUserPreferenceInteger`, then READ BACK — `verified` is the field that matters. The getter is live-proven (`GetUserPreferenceInteger(53,0)` → 1); the setter is not. **Live-proven in run 3** (2026-09-03: 125 checks passed against SOLIDWORKS Design Professional for Makers 2026). |++### F. Cloud (APS → 3DEXPERIENCE) — 18 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_aps_browse` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_create_folder` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_download` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_file_info` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_get` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_open` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_recent` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_search` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_upload` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_versions` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_cleanup_cloud_files` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_list_cloud_files` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_list_cloud_projects` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_open_by_urn` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_open_cloud_file` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_save_to_cloud` | ❌ **lacking** | `swx_save_as` (local only) | Local save-as is built; there is no cloud destination to save TO. Same 3DSpace REST project as the rest of the cloud family. |+| `fusion_search_cloud_files` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_walk_cloud_tree` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |++### G. Libraries & 3D packages (Fusion Electronics) — 23 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_attach_3d_package` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_bind_library_3d` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_build_library_3d` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_capture_library_views` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_create_library` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_generate_package` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_install_library_bundle` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_library_manager` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_library_parts` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_make_3d_package` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_managed_library_create` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_managed_library_link` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_managed_library_pull` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_managed_library_push` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_managed_library_unlink` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_open_lbr` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_plan_library_import` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_preflight_lbr` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_3d_package` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_footprint` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_library` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_project` | 🔄 **adapted** | `swx_show_part / swx_show_assembly / swx_show_drawing` | Fusion's eight-surfaces contract, MCAD half only: open + activate + `ViewZoomtofit2` (live-proven) in the BACKGROUND, with `capture:true` for a background screenshot. Refuses with `wrong_document_type` if the target is the wrong kind, which Fusion's single verb cannot do. |+| `fusion_show_symbol` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |++### H. Electronics (schematic / PCB) — 11 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_board_info` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_board_stackup` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_detect_layers` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_electron_pan` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_electron_run` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_electron_select` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_electron_zoom` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_new_electronics_from_eagle` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_2d_board` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_3d_board` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_show_schematic` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |++### I. Manufacturing outputs — 4 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_export_bom` | ➖ not applicable | — | Electronics BOM. `swx_bom` is the mechanical one (Fusion's `fusion_assembly_bom` counterpart). |+| `fusion_export_cpl` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_export_gerbers` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |+| `fusion_set_design_rules` | ➖ not applicable | — | Fusion Electronics / EAGLE library tooling. SOLIDWORKS is a pure MCAD application with no schematic, PCB, or .lbr concept — there is nothing to bridge to. |++### J. Sign-in & licensing — 9 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_aps_forget_browser` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_get_browser` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_set_browser` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_set_client_id` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_signin` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_aps_status` | ❌ **lacking** | `swx_cloud_status` | Not built, and NOT because there is nothing to bridge to — 3DEXPERIENCE has a 3DSpace/3DDrive REST API that does this job. What it would take: an OAuth story against a tenant-specific CAS/passport login (this user's tenant is `oi000616940-usw1-makers-ifwe.3dexperience.3ds.com`), roughly the size of the Fusion bridge's APS work. There is no COM route at all — `swx_cloud_status` runs that probe on demand — so this is a separate project, not a missing verb. |+| `fusion_signin` | ❌ **lacking** | — | Filed as lacking, not n/a, by the same standard applied to the cloud verbs: 3DEXPERIENCE sign-in is a real, documented interface (the Platform launcher and its CAS/passport flow), and it is **the human gate that blocks `swx_start`** — so automating it is the single change that would most improve this bridge, not an absence of concept. What it would take: driving the 3DEXPERIENCE launcher's web sign-in the way the Fusion bridge drives Autodesk's, which is a browser-automation project with real credential-handling consequences. |+| `fusion_signin_2fa` | ❌ **lacking** | — | As above, plus the second factor. |+| `fusion_web_signin` | ❌ **lacking** | — | Autodesk web SSO via a pup browser. The 3DEXPERIENCE equivalent exists and is the door to both the launcher gate and the 3DSpace REST API — the same project, twice over. Not built. |++### K. Self-describe — 1 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_describe` | 🧩 **built, no COM involved** | `swx_describe` | Now also carries `scriptOps` (the modeling DSL's op list) and `exportFormats` (the live-verified format matrix).. Static catalog. The v0.3 additions (scriptOps, exportFormats) are asserted by the mock suite. |++### L. Doc-only catalog entries — 1 verbs++| Fusion verb | Verdict | SOLIDWORKS verb | Notes |+|---|---|---|---|+| `fusion_open_by_urn_note` | ➖ not applicable | — | Documentation pseudo-entry in the Fusion catalog, filtered out of fusion_describe. |++## The SOLIDWORKS verbs with no Fusion counterpart++| swx verb | Why it exists |+|---|---|+| `swx_new_document` | Drew's explicit ask, and Fusion has no twin verb (its documents arrive from the cloud or an import). LIVE-PROVEN recipe: `NewDocument(template,0,0,0)` with the template resolved at runtime — `ISldWorks::NewPart()` **hangs** on this install (>110s, killed by the watchdog). |+| `swx_find_files` | Disk search for `.sldprt`/`.sldasm`/`.slddrw`. Fusion's files are in the cloud, so it needs no such verb; SOLIDWORKS' are on disk, so it is the front door. |+| `swx_pack_and_go` | A SOLIDWORKS-native operation with no Fusion analogue. |+| `swx_interference` | Native assembly interference detection. |+| `swx_rebuild_check` | Force rebuild + a broken-feature census — the design-health first check. |+| `swx_props_get` / `swx_props_set` | Custom properties, per file or per configuration. These drive BOMs and title blocks; Fusion's equivalent is buried in its parameter/attribute model. |+| `swx_save_as` | The verb that gets a `swx_new_document` scratch part onto disk. `copy:true` writes a file without retitling the open document. |+| `swx_export_glb` | Native GLB, no optimisation service required. |+| `swx_cloud_status` | Exists specifically to give the honest 'no, and here is the probe that proves it' answer rather than a silent absence. |++## Recommended next steps++1. **Run `tools/live-smoke.py`** once the desktop is back and SOLIDWORKS has been started from the+ 3DEXPERIENCE Platform. That is what converts 🔬 and ⚠️ into ✅ — or finds the next bug. It asserts+ the Silent|Copy fix, the `.wrl` refusal on all five roads to `SaveAs3`, the refusal to touch a+ document the bridge did not create, and — as a hard gate that runs even on an early abort — that+ SOLIDWORKS ends with exactly the documents it started with.+2. **Re-test the assembly verbs on a real assembly** — either one the user already has, or on a classic+ desktop SOLIDWORKS install where `AddComponent5` is expected to work. `swx_bom`, `swx_interference`+ and per-component mass properties all hinge on this.+3. **Test DXF/DWG/PDF export from a `.slddrw`.** They are refused for a part, which is expected; they+ should be the drawing story, and that is untested.+4. **Decide whether 3DEXPERIENCE cloud access is worth the OAuth project.** It is the largest remaining+ gap and the only one that is a matter of effort rather than of what SOLIDWORKS permits.+5. **Per-component mass properties** (`fusion_physical_properties` parity for assemblies) is a small+ addition once an assembly can be built.++## `swx_run_macro` — scaffolding, and labelled as such++Added 2026-09-03. `ISldWorks::RunMacro2(path, module, proc, swRunMacroUnloadAfterRun, [out] error)`,+written from Dassault's documented signature and CodeStack's worked examples — which+confirm both that a `.swp` is plain-text editable and that `RunMacro2` works from a+standalone executable, the two facts this verb depends on.++**It has not been run against a live SOLIDWORKS.** It is graded 🔬 and the response+says so in its own `_hint`, because this report's only value is the line between+"proven live" and "written from documentation". Two details in it are the ones most+easily got wrong, and both are guesses until a live run:++- the error is an **out parameter** (`swRunMacroError_e`), not the return value — the+ return is a bare bool, so a macro that fails to compile comes back `false` with the+ reason only in the out param;+- `swRunMacroUnloadAfterRun` is passed deliberately. Without it the VBA project stays+ loaded and an edited macro keeps running its **old** code, which is indistinguishable+ from the edit not having been saved.++The bundled `resources/macros/adom-hello.swp` is likewise a placeholder and says so in+its own comments. The real template will be **recorded** from SOLIDWORKS' macro+recorder rather than written by hand, because that is the only way to be certain of the+module and procedure names it expects — and because the obvious hello-world+(`SendMsgToUser2`) raises a modal, which this bridge must never do on somebody's desktop.++### The gate is the whole design++Every other write in this bridge is bounded by two questions — is the document ours, is+the destination clear. A macro answers neither: it is a VBA project with the full+SOLIDWORKS API in scope and the filesystem behind it, and nothing about the *call*+predicts what it will touch. So `Kind::RunMacro` is **always gated**, with no safe case+carved out: the process needs `SWX_ALLOW_USER_WRITES=1` and the call needs+`allowUserWrites:true` + `confirm:true` + a `reason`, every time. In the default posture+this verb refuses, always. What is being authorized is arbitrary code execution on+somebody's desktop; the only honest gate for that is the human saying so each time.
README.md+264−2@@ -1,3 +1,265 @@-# SOLIDWORKS Bridge+# SOLIDWORKS bridge (`swx`) -Drive SOLIDWORKS desktop CAD from any Adom container via swx_* verbs: create/open/import documents, model with a JSON DSL, drive dimensions, export 15+ formats, generate assembly BOMs, mass properties and interference - deny-by-default writes, live-validated. Check adom-bridge bridge_list; install runtime via bridge_install with this page's manifest; skills via adom-wiki pkg install adom/solidworks-bridge.+Say **swx** to the AI to reach this bridge. It drives the SOLIDWORKS desktop+app on Windows over its COM API: streamlined file management, BOM generation+from assemblies, and first-line design analysis — all from any Adom container,+with SOLIDWORKS staying quietly in the background.++One native binary. No Python, no PowerShell, no interpreter to provision:+ab spawns `swx-bridge.exe` directly (`spawn.kind: "exe"`) and it is serving in+about ten milliseconds.++## What it does — 61 verbs++| Area | Verbs |+|---|---|+| **Create & open** | `swx_new_document` (part/assembly/drawing from the stock template), `swx_open`, `swx_import` (STEP/IGES/Parasolid/STL), `swx_save`, `swx_save_as`, `swx_close_doc`, `swx_find_files`, `swx_docs` |+| **Model** | `swx_run_script` — a typed modelling DSL: `new_part`, `sketch_rect`, `sketch_circle`, `extrude`, `cut`, `set_material`, `set_prop`, `save_as`, `rebuild`, `zoom_fit`. Everything in millimetres. |+| **Macros** | `swx_run_macro` — `ISldWorks::RunMacro2` on a `.swp`/`.swb`/`.dll`. Arbitrary code, so it needs the write opt-in every time. Scaffolding: not yet run live. |+| Export | `swx_export` plus per-format aliases `swx_export_step/iges/stl/3mf/glb/sat/parasolid/pdf/dxf/dwg`, `swx_pack_and_go` |+| Read the design back | `swx_design_info`, `swx_inspect_bodies` (geometry in mm), `swx_get_parameters`, `swx_set_parameter`, `swx_mass_properties`, `swx_bom`, `swx_interference`, `swx_rebuild_check`, `swx_document_info` |+| Metadata | `swx_props_get`, `swx_props_set` (custom properties, file- or configuration-scope) |+| App & documents | `swx_get_app_state`, `swx_state`, `swx_status`, `swx_readiness`, `swx_progress`, `swx_start`, `swx_stop`, `swx_kill`, `swx_activate_document`, `swx_close_all_documents`, `swx_reset_workspace`, `swx_show_part/_assembly/_drawing` |+| Windows & etiquette | `swx_window_info`, `swx_dismiss_blocking_dialogs`, `swx_close_window`, `swx_check_recovery`, `swx_screenshot`, `swx_set_driving_badge`, `swx_action_ledger`, `swx_verb_times` |+| Preferences & cloud | `swx_get_preferences`, `swx_set_preference`, `swx_cloud_status` |+| Bridge | `swx_describe`, `swx_com_eval`, `swx_uninstall` |++Verb names and arg names deliberately mirror the Adom **Fusion 360** bridge+(`outputPath`, `filePath`, `name`, `parameters`, `bodies`, `current`,+`applied`, `stages`, `wouldPrompt`) so an AI that already knows `fusion_*` can+drive `swx_*` with nothing new to learn.+[**docs/FUSION-PARITY-REPORT.md**](docs/FUSION-PARITY-REPORT.md) covers all 132+Fusion verbs with a verdict, and is where the divergences are argued.++## Two things to know before you drive it++**SOLIDWORKS Connected is launched through the Platform's own shortcut.** On+the 3DEXPERIENCE editions (including *Design Professional for Makers*),+`CoCreateInstance` spawns a process that refuses with *"SOLIDWORKS Design must+be launched from the 3DEXPERIENCE Platform"* and never attaches — verified+live, and for two rounds this bridge concluded from that the edition could not+be started at all. That was a conclusion about the wrong experiment. The+Start-Menu shortcut the Platform installs does not run `sldworks.exe`; it runs++```+CATSTART.exe -run "SWXDesktopLauncher.exe"+ -object "--AppName=\"SWXCSWK_AP\" -tenant=<TENANT> -monoapp+ -3DRegistryURL=https://<region>-makers-registry.3dexperience.3ds.com"+ -nowindow+```++so the refusal was **ours**, for bypassing the launcher chain. `swx_start` now+invokes that shortcut — the sanctioned artefact, carrying the user's own tenant,+with nothing reverse-engineered and no argument invented — then polls for the+COM server. A cold start runs 1-3 minutes, so it answers+`started:true, stillLaunching:true` while the application comes up rather than+holding the request. Classic desktop installs still attach directly over COM.+`errorCode:"host_app_launch_blocked"` now means only that **no shortcut could be+found** (`SWX_SOLIDWORKS_SHORTCUT` points the bridge at one).++**Exports are copies; save-as is a rename.** `swx_export*` uses `SaveAs3` in+`Silent|Copy` mode, so the open document keeps its identity (v0.2 did not, and+silently renamed it). `swx_save_as` is the deliberate rename; `copy:true` makes+it a copy. And because `SaveAs3` picks the format from the DESTINATION+EXTENSION rather than the `format` argument, that is where the format rules are+enforced — `swx_export_step {"outputPath":"x.wrl"}` is refused.++**Writes are DENY-BY-DEFAULT.** These verbs pass through one choke point+(`src/writes.rs`), which refuses unless **both**: the document is one this+bridge created in this SOLIDWORKS session, **and** the destination path does not+already exist —++`swx_save` · `swx_save_as` · `swx_export` and its ten format aliases ·+`swx_bom {format:"csv"}` · `swx_pack_and_go` · `swx_close_doc` ·+`swx_props_set` · `swx_set_parameter` · `swx_set_preference` ·+`swx_run_script` · `swx_rebuild_check` (it calls `ForceRebuild3`) ·+`swx_stop` and `swx_close_all_documents` (which end the user's session, and are+gated unconditionally) · `swx_run_macro` (**always** gated: a macro is a VBA+project with the whole API in scope, and nothing about the call predicts what it+will touch).++The gate opens BOTH ways. When the user has opted in, in full, the bridge does+the thing — it does not refuse anyway. The server and the com host check the+identical chain independently, so a partial chain is refused twice and a+complete one is honoured by both.++Anything refused returns `errorCode:"user_writes_disabled"`,+`"destination_exists"` or `"not_bridge_document"`. Exporting **from** any+document **to a path that does not exist** always works — that is the normal way+to get data out, and it needs no permission.++The only way past it is a deliberate opt-in that a caller cannot grant itself:+the bridge process must be started with `SWX_ALLOW_USER_WRITES=1` **and** the+call must carry `allowUserWrites:true`, `confirm:true` and a `reason`. Every+granted exception is recorded in `swx_action_ledger`. `swx_status` and+`swx_describe` report `userWrites: "disabled"|"enabled"` so a caller knows the+posture before it plans anything.++The same rule covers **ending or disturbing the user's session**: `swx_stop`,+`swx_kill`, `swx_close_all_documents`, and closing ANY dialog —+`swx_dismiss_blocking_dialogs {close:true}` and `swx_close_window` alike,+including dialogs the bridge itself raised. `swx_close_window` additionally+refuses an application frame outright (closing one quits SOLIDWORKS, which is+`swx_stop`'s job) and refuses a dialog that asks about the user's own work+(`Save changes?`, Document Recovery, licence) at any posture. It also covers+`swx_open {readOnly:false}`, which takes a write lock on the user's file and+converts-and-dirties an older-version document in memory.++For everything that reaches SOLIDWORKS, the com host enforces the same two rules+**independently**, on its dispatch loop rather than per command: it keeps its own+record of the documents it created (stamped with the SOLIDWORKS session, so a+crash or a restart invalidates it), reads the opt-in from its own environment,+and refuses **any** command not on its no-side-effects list. A command added+tomorrow is therefore deny-by-default.++**Where there is only one veto, and why:** `swx_kill`, `swx_close_window`,+`swx_dismiss_blocking_dialogs` and `swx_screenshot` go out through ab rather+than the com host, so the host's veto is not in their path — the server-side+choke point is the only check they have. That is worth knowing when reading the+rest of this section. `swx_screenshot` captures BY HANDLE (the one COM reports,+or an hwnd `swx_window_info` attributes to SOLIDWORKS); it will not take a+picture of an arbitrary window on the desktop.++This posture is a response to five consecutive rounds of adversarial review, in+each of which the bridge turned out to be able to write to the user's data+through a route whose guard had been forgotten. Gating routes failed five times;+denying by default at one choke point removes the class.++## Architecture++```+ab (Adom Bridge) ── HTTP /command ──> swx-bridge.exe (server mode)+ │ JSON-lines over stdio+ └─> swx-bridge.exe --com-host+ (child process holding the live+ SldWorks.Application COM object)+```++- **One exe, two modes.** The server spawns the com host from its own+ `current_exe()`, so there is exactly one file to ship and one image name for+ ab to stop (`killImageName: "swx-bridge.exe"` covers both processes).+- **The COM object lives in a CHILD PROCESS**, not a thread. A wedged COM call+ — SOLIDWORKS parked on a modal dialog, a rebuild that never returns — cannot+ be killed as a thread. It can be killed as a process. The server owns that+ lifecycle: lazy spawn, one request in flight, per-request timeout, kill and+ respawn after a crash or hang, and the child's stderr tail surfaced in the+ failing verb's `detail`. A child that dies between requests is replaced+ transparently, so the *next* verb works.+- **The child is persistent**: it attaches to (or launches) SOLIDWORKS once and+ keeps the COM object, so verbs don't pay a per-call attach. It is initialized+ as an STA and holds the apartment for its whole life. On Windows it is spawned+ with `CREATE_NO_WINDOW` — no console ever blips on the user's desktop — and it+ exits on its own when its parent goes away (stdin EOF), so nothing is left+ holding a COM object.+- **Late-bound IDispatch** (`GetIDsOfNames` + `Invoke`), like every SOLIDWORKS+ macro: it works against whichever version is installed, with no interop+ assemblies to match.+- **Mock mode** (`SWX_MOCK=1`, automatic on non-Windows) swaps the COM backend+ for an in-memory fake behind the same `Backend` trait — same protocol, same+ response shapes — so the whole verb surface is testable with no SOLIDWORKS and+ no Windows.++## Host app status++SOLIDWORKS is a **detect-only host app** (ab tier-2): Dassault publishes no+silent installer — desktop trial serials come from a reseller, and the Makers+edition comes from the 3DEXPERIENCE Platform store — so the bridge reports+absence with `errorCode:"host_app_not_installed"` and a next-steps `_hint`+instead of ever attempting an install. The verbs that need no COM+(`swx_status`, `swx_readiness`, `swx_describe`, `swx_progress`,+`swx_find_files`, `swx_action_ledger`, `swx_verb_times`, `swx_uninstall`) work+regardless, so "what CAD files do I have?" is answerable today.++## Export formats, verified rather than assumed++Every format below was exported from a real solid on a live SOLIDWORKS Design+Professional for Makers 2026 and the bytes on disk were checked — **with the+caveat that those probes used `SaveAs3` with `Silent` ALONE**, which is how the+rename bug was found. The shipped export path uses `Silent|Copy` and **has never+run**; whether Copy is valid for PDF/PNG/JPG/TIF is unknown. Read the table as+"SOLIDWORKS can write this format", not "the bridge's export path is proven":++| Works from a part | Refused for a part (code 256) | Blocked by this bridge |+|---|---|---|+| STEP, STP, IGES, STL, X_T, X_B, SAT, 3MF, **GLB**, PLY, AMF, 3DXML, PNG, JPG, TIF, XAML, PDF | OBJ, DXF, DWG, U3D (DXF/DWG are drawing formats) | VRML (`.wrl`) |++VRML is refused outright with `errorCode:"format_blocked"`: it raises a modal+option sheet that no unattended caller can answer, and on the live install it+hung the COM call until the watchdog killed the host.++## Development++```bash+cargo build # native (mock mode: no SOLIDWORKS needed)+cargo test # unit + HTTP e2e + protocol e2e+cargo build --release --target x86_64-pc-windows-gnu # the shipped swx-bridge.exe++# run it by hand and poke it+SWX_MOCK=1 cargo run -- --port 24695+curl -s localhost:24695/status | jq+curl -s localhost:24695/command -d '{"command":"swx_describe","args":{}}' | jq+```++The suite is built so it cannot lie:++- **No test asserts by reading source.** Every check drives the real compiled+ binary (`CARGO_BIN_EXE_swx-bridge`) over HTTP or over the stdio protocol.+- **A verb-coverage gate** compares the verbs actually CALLED during the suite+ against `bridge.json`, in both directions, and against `swx_describe`. A new+ verb shipped without a test turns the suite red.+- **Response invariants on every call**: 200, parses as JSON, boolean+ `success`; malformed bodies get a clean 400, never a 500.+- **Effects, not existence**: exports are read back off disk, the BOM CSV is+ parsed and its columns checked, `find_files` runs against real fixture files.+- **Protocol e2e**: the real server driving the real com-host child, including+ crash recovery (kill the child, the next verb still works), junk on the+ child's stdout, orphan cleanup, and a slow verb that must not block+ `swx_progress`.++Everything the bridge writes goes under one root+(`%LOCALAPPDATA%\Adom Bridge\bridges-cache\solidworks\`, or `SWX_SCRATCH_DIR`+for tests), pruned at 48h / 300 files, and removed in full by `swx_uninstall`.++`swx_com_eval {"expr":"$sw.RevisionNumber()","reason":"..."}` is the maintainer+escape hatch: a late-bound call chain rooted at `$sw` or `$doc`, for proving out+a new capability against a real install before it becomes a verb.++## Live validation++Mock-green is not green: v0.2 passed 49 mock tests while shipping four COM+bugs, all of which the first live session found (see the parity report). Three+tools close that gap:++```bash+python3 tools/swx-live.py <verb> '<json>' [timeoutSec] # one verb on the desktop+python3 tools/swx-batch.py calls.json # many verbs in ONE round trip+python3 tools/live-smoke.py # the full live suite+```++`live-smoke.py` creates its own scratch part, builds a real 50×30×20 mm solid,+reads the geometry back, drives a dimension, exports eight formats, checks the+bytes on disk, and then asserts SOLIDWORKS is left with **exactly** the+documents it started with. It never opens, saves or closes a document it did+not create, and it never launches or stops SOLIDWORKS.++## Roadmap++- v0.1: full verb surface in Python + a PowerShell COM sidecar, mock-tested.+- v0.2: single Rust binary — 23 verbs, COM in a killable child process, crash+ recovery, a suite that drives the real binary.+- v0.3.1 (this): the launch answer — SOLIDWORKS Connected starts through the+ Platform shortcut, so `host_app_launch_blocked` now means only "no shortcut+ found"; `swx_run_macro` scaffolding; and the write opt-in made openable on+ every path it guards (three live-proven cases where the human authorized an+ action in full and the bridge refused anyway — an escape hatch nobody can+ open is not a safety property).+- v0.3: 60 verbs at Fusion-360-bridge parity — document creation, a+ modelling DSL, geometry read-back, parameters, per-format exports, window and+ dialog etiquette, an action ledger and measured verb timings. First live+ shakedown against a real SOLIDWORKS; four v0.2 COM bugs **diagnosed with live+ evidence and fixed on reasoning** (the fixes themselves are unverified — see+ the parity report). Writes made deny-by-default after five rounds of review.+- v0.4 candidates: drawing (`.slddrw`) BOM-table extraction and DXF/DWG/PDF+ from drawings, per-component mass properties for assemblies, configuration+ management, a live screen feed, and — the big one — 3DEXPERIENCE 3DSpace+ access, which needs its own OAuth story.
SKILL.mdadded+292@@ -0,0 +1,292 @@+---+name: solidworks-bridge+description: Drive SOLIDWORKS desktop CAD from any Adom container via swx_* verbs — create new parts/assemblies/drawings, open and import files, build geometry with a modelling DSL, read the geometry back in millimetres, drive dimensions, export a dozen formats, generate BOMs, and run design analysis (mass properties, interference, rebuild health) — all in the background over the COM API. Verb and arg names mirror the Fusion 360 bridge. Trigger words - solidworks, swx, sldprt, sldasm, slddrw, new solidworks part, create a part, model a bracket, solidworks bom, step export from solidworks, export glb, mass properties, interference check, pack and go, solidworks properties, open in solidworks, solidworks parameters, change a dimension.+---++# SOLIDWORKS bridge — `swx`++Say **swx** to reach this bridge. It drives the SOLIDWORKS desktop app on the+user's Windows machine over its COM API, via Adom Bridge (ab). Every verb is a+Bash command:++```bash+adom-bridge --ai-thread "<your thread>" swx_status '{}'+adom-bridge --ai-thread "<your thread>" swx_bom '{"path":"C:\\designs\\gearbox.sldasm","format":"csv"}'+```++## Is it ready?++- `bridge_readiness` (ab-level, never spawns anything) answers "is SOLIDWORKS+ installed / is the bridge warm" — use it for what-do-I-have questions.+- `swx_readiness` is the bridge's own read-only probe; `swx_status` is the+ everyday state check (detection + COM attach + open docs);+ `swx_get_app_state` is the one to POLL while something long runs.+- **If SOLIDWORKS is not installed** verbs return+ `errorCode:"host_app_not_installed"`. Dassault publishes NO silent+ installer — desktop trial serials come from a reseller, the Makers edition+ from the 3DEXPERIENCE Platform store. Don't tell the user to go download it;+ surface the returned `_hint`.+- **If SOLIDWORKS is not running, `swx_start` starts it — including the+ Connected editions.** Pass a `reason` (it is written for the person whose+ desktop this is, and it is the only thing this verb needs — starting an+ application creates nothing and destroys nothing).+ - On classic desktop installs it attaches over COM.+ - On **3DEXPERIENCE / Connected** editions (including *Design Professional+ for Makers*) it invokes **the shortcut the Platform installed**, which runs+ `CATSTART.exe -run SWXDesktopLauncher.exe` with that user's tenant and+ registry. That is the launch Dassault sanctions.+ - **A cold Connected start runs 1-3 minutes** and may stop at a 3DEXPERIENCE+ sign-in only the user can answer. `swx_start` returns+ `started:true, stillLaunching:true` while it is coming up — that is **not a+ failure**. Poll `swx_status` until `running:true`, or call `swx_start`+ again, which ATTACHES to what is already coming up. `waitSeconds:<n>` (up+ to 240) blocks instead of polling. **Never invoke the launcher any other+ way meanwhile** — two launches means two sign-in windows on somebody's+ desktop.+ - `errorCode:"host_app_launch_blocked"` now means only one thing: **the+ bridge could not FIND a shortcut**, not that the edition cannot be+ launched. `swx_status` reports `solidworks.shortcut` and+ `solidworks.launchRoute` so you can see what it found; if the user has a+ shortcut elsewhere, `SWX_SOLIDWORKS_SHORTCUT=<path to the .lnk>` points the+ bridge at it. Do not run `sldworks.exe` yourself via `shell_execute` or+ `launch_process` — launching it DIRECTLY, bypassing the launcher chain, is+ what produces the *"SOLIDWORKS Design must be launched from the+ 3DEXPERIENCE Platform"* modal.++## Making something new++```bash+adom-bridge --ai-thread "<thread>" swx_new_document '{"type":"part"}'+adom-bridge --ai-thread "<thread>" swx_run_script '{"script":[+ {"op":"sketch_rect","plane":"Front Plane","widthMm":50,"heightMm":30},+ {"op":"extrude","depthMm":20},+ {"op":"set_material","name":"6061 Alloy"},+ {"op":"set_prop","name":"PartNo","value":"BRK-100"}+]}'+adom-bridge --ai-thread "<thread>" swx_inspect_bodies '{}' # verify the GEOMETRY+adom-bridge --ai-thread "<thread>" swx_save_as '{"outputPath":"C:\\parts\\bracket.sldprt"}'+```++- `swx_new_document` gives you an **unsaved** document: it has a title (`Part1`)+ and **no path** until `swx_save_as`. Target it by `name`, not by path.+- `swx_run_script` takes a JSON **array of steps**, not a string of code —+ SOLIDWORKS has no in-process scripting host the way Fusion has Python. Every+ dimension is in **millimetres**. A rejected script returns the full op list+ and a worked example, so read the error.+- **Verify with `swx_inspect_bodies`, not with the step list.** It reports each+ solid's bounding box, size, volume, area and mass in millimetres — that is+ what tells you the model is what you meant.+- Throwing it away is `swx_close_doc {"name":"Part1","save":false}`, or+ `swx_reset_workspace` to sweep every scratch document the bridge created.++## The everyday flow++1. `swx_find_files {"roots":["C:\\designs"],"query":"gearbox"}` — locate+ documents on disk (works with SOLIDWORKS closed; newest first).+2. `swx_open {"path":"...sldasm"}` — silent open, background. SOLIDWORKS+ launches automatically if closed (cold start 30-90s; the verb's `progress`+ block and `swx_progress` report it).+3. Work the document:+ - `swx_bom {"format":"csv"}` — quantities per (file, configuration) with+ every custom property as a column; `csvPath` lands on the DESKTOP disk.+ - `swx_mass_properties {}` — mass/volume/area/CoM in SI units.+ - `swx_interference {}` — assembly clash check (`count:0` = clean).+ - `swx_rebuild_check {}` — force rebuild + broken-feature census.+ - `swx_props_get` / `swx_props_set` — custom properties (then `swx_save`).+ - `swx_export_step {"outputPath":"C:\\out\\part.step"}` — or+ `_iges/_stl/_3mf/_glb/_sat/_parasolid/_pdf/_dxf/_dwg`, or the generic+ `swx_export {"format":"..."}`. **Verified live from a part:** STEP, IGES,+ STL, X_T, X_B, SAT, 3MF, GLB, PLY, AMF, 3DXML, PNG, JPG, TIF, PDF. DXF,+ DWG, OBJ and U3D are **refused for a part** (DXF/DWG are drawing formats).+ VRML is blocked by the bridge — it hangs SOLIDWORKS on a modal.+ - `swx_design_info {}` / `swx_inspect_bodies {}` / `swx_get_parameters {}` /+ `swx_set_parameter {"name":"D1@Boss-Extrude1","valueMm":25}` — read the+ design back and drive it.+ - `swx_pack_and_go {"out":"C:\\handoff"}` — self-contained copy with all+ references, for sending a design anywhere.+4. `swx_state {}` any time — open docs + active doc, the look-then-act check.++## Rules and gotchas++- **Target docs by `path`**, not by activating them — every doc verb takes an+ optional `path` and falls back to the active document.+- **Files land on the DESKTOP filesystem.** From a cloud container, pull+ exports back with ab's `pull_file`.+- **Background etiquette:** the bridge never foregrounds SOLIDWORKS; responses+ carry `windowEtiquette:"background"`.+- **A modal dialog inside SOLIDWORKS blocks every verb** (COM is single+ threaded). If verbs time out, ask the user about a dialog, or check+ `swx_status`. The bridge holds the COM object in a separate child process, so+ a wedged call is killed and replaced rather than taking the bridge down — the+ verb after a timeout works again.+- **`swx_props_set` changes memory, not the file** — follow with `swx_save`.+- `swx_com_eval {"expr":"...","reason":"..."}` is the maintainer escape hatch:+ a late-bound COM call chain rooted at `$sw` (the application) or `$doc` (the+ active document), e.g. `$sw.RevisionNumber()` or+ `$doc.Extension.CustomPropertyManager("").GetNames()`. String, number and+ boolean literal arguments. For prototyping a capability against a real+ install before it becomes a verb; `reason` is required.+- `swx_screenshot` delegates to ab's generic `desktop_screenshot_window`;+ `swx_state {}` bundles that with the dialog census and this machine's+ measured verb timings in one call (`screenshot:false` to skip the callbacks).+- **Do not dismiss dialogs casually.** `swx_dismiss_blocking_dialogs {}`+ REPORTS by default. Closing needs `close:true` + `reason` + `confirm`; a+ "Save changes?" / Document Recovery / licence dialog is never closed at all;+ and a window that cannot be PROVED to belong to SOLIDWORKS is never closed+ either (ab's window list carries no owner pid, so a bare dialog class could be+ any application's). `swx_close_window` refuses the same way, with+ `errorCode:"window_not_attributed"`.+ Closing a stuck SOLIDWORKS modal through the window manager has been observed+ to take the whole application down — and on Connected editions the bridge+ cannot start it again.+- **☠ THE BIG ONE: writes are DENY-BY-DEFAULT.** The bridge refuses to change+ any document it did not create, and to write over any file that already+ exists. That includes things that do not look like writes: `swx_props_set`+ (it dirties the document, so the user's own Ctrl+S would commit it),+ `swx_rebuild_check` (it calls `ForceRebuild3`), `swx_bom {format:"csv"}` (it+ writes a file), `swx_pack_and_go`, and `swx_stop` /+ `swx_close_all_documents` / `swx_close_doc` (they end or disturb the user's+ session).+ Check `swx_status.userWrites` (`"disabled"` / `"enabled"`) before planning+ anything that writes. Refusals are `errorCode:"user_writes_disabled"` or+ `"destination_exists"`; the response lists `bridgeDocuments` (each with the+ `path` that names it unambiguously) so you can retarget. **Exporting to a path+ that does not exist yet, from any document, always works** — that is the+ normal way to get data out. To reach the user's own document or overwrite a+ file, the bridge process must have been started with+ `SWX_ALLOW_USER_WRITES=1` AND the call must carry `allowUserWrites:true` ++ `confirm:true` + `reason`. **You cannot grant this to yourself — ask the+ user.** Every exception is recorded in `swx_action_ledger`.+- **The affected verbs:** `swx_save`, `swx_save_as`, `swx_export*`,+ `swx_bom {format:"csv"}`, `swx_pack_and_go`, `swx_close_doc`,+ `swx_props_set`, `swx_set_parameter`, `swx_set_preference`,+ `swx_run_script`, `swx_run_macro` (**always** — see below),+ `swx_rebuild_check`, `swx_stop`, `swx_kill`,+ `swx_close_all_documents`, `swx_open {readOnly:false}`, and BOTH dialog-closing+ verbs — `swx_dismiss_blocking_dialogs {close:true}` and `swx_close_window` —+ for any dialog at all, including ones the bridge itself raised. **Reading is never gated**, and+ neither is exporting to a path that does not exist yet.+- **`swx_run_macro` is gated ALWAYS, with no safe case.** A macro is a VBA+ project with the whole SOLIDWORKS API in scope and the filesystem behind it:+ it can model, save over anything, batch-export, delete, or quit, to documents+ this bridge has never seen — and nothing about the *call* predicts which.+ So the two questions that bound every other write ("is the document ours",+ "is the destination clear") do not apply, and running one needs the full+ opt-in chain every time, even for a macro the bridge itself shipped. In the+ default posture it refuses. `module` and `procedure` default to `main`/`main`+ (the macro recorder's defaults); the macro is unloaded after the run, so an+ edited `.swp` runs its new code. **`swx_run_macro` has not yet been run+ against a live SOLIDWORKS** — its response says so (`provenLive:false`), and+ the bundled `resources/macros/adom-hello.swp` is a placeholder, not a working+ macro.+- **What the opt-in actually opens.** When the user HAS opted in, in full, the+ bridge does the thing — it does not refuse anyway. `swx_close_doc` and+ `swx_close_all_documents {closeUnsaved:true}` will close and discard the+ user's own unsaved documents on that chain, with each one named in+ `swx_action_ledger`. Both the server and the com host check the identical+ chain independently, so a partial chain is refused twice and a complete one+ is honoured by both.+- **`swx_close_all_documents` accounts for everything it leaves open.** Its+ `skipped` array names every document still open when it returns, with why —+ and a document whose dirtiness SOLIDWORKS will not report is treated as+ UNSAVED, not clean. Reaching this verb at all needs the write opt-in, since+ it ends the user's session; a refusal closes nothing.+- **`swx_stop` fails loudly when SOLIDWORKS does not actually quit.** Asking is+ not quitting: the host verifies by re-attaching, and if the application is+ still there you get `success:false` with+ `errorCode:"host_app_stop_declined"`. Almost always it is holding a+ *"Save changes?"* modal nobody answered — `swx_get_app_state` names the+ unsaved documents. **Do not reach for `swx_kill`**: that discards exactly the+ work the dialog is asking about.+- **`swx_close_window` is gated exactly like `swx_dismiss_blocking_dialogs`.**+ It refuses an application window (`errorCode:"window_is_application_frame"` —+ closing a SOLIDWORKS frame quits it, which is `swx_stop`'s job); it refuses a+ dialog that asks about the user's own work at any posture+ (`errorCode:"dialog_belongs_to_the_user"` — Save changes?, Document Recovery,+ licence); and closing anything else needs the process-level write opt-in.+ `swx_window_info` marks every window with `isFrame` and `closable`, and+ `closable` already folds in all three refusals — trust it.+- **`swx_screenshot` captures SOLIDWORKS' own window, by handle.** A free-text+ `titleContains` is ignored; pass `hwnd` only if `swx_window_info` attributes+ it to SOLIDWORKS. For anything else on the desktop, ab's own+ `desktop_screenshot_window` is the right tool and carries the user's approval+ prompt.+- **`swx_open` is READ-ONLY by default, and `readOnly:false` is a WRITE.** A+ read-write open takes a write lock on the user's file and converts-and-dirties+ an older-version document in memory, so it goes through the same gate as every+ other write. Reading is always free. `swx_close_doc {save:false}` on a DIRTY document the bridge+ did not create additionally needs `confirm:true` + `reason`+ (`errorCode:"unsaved_documents"`) — and if SOLIDWORKS will not say whether the+ document is dirty, it is treated as dirty.+ **There is no undo.** Do NOT reach for `swx_close_doc {save:false}` to "undo"+ a change to someone's document: that discards the entire document, not your+ edits. Undo belongs to the user, in SOLIDWORKS.+- **Destructive verbs ask first.** `swx_close_all_documents`, `swx_close_window`,+ `swx_kill` and `swx_close_doc`-on-dirty-work need `confirm:true` (and+ `swx_close_window`/`swx_kill` a `reason`). `swx_stop` and `swx_kill` refuse+ outright while documents are unsaved (`errorCode:"unsaved_documents"`) — pass+ `force:true` only if the user has said the changes are disposable.+ `swx_close_all_documents {closeUnsaved:true}` additionally needs a `reason`,+ and it discards ONLY the bridge's own scratch documents: the user's unsaved+ ones are left open and listed in `skipped`.+- **`swx_props_set` IS gated now.** The old justification — "in memory until a+ gated save" — ignored the persist route that cannot be gated: the user. It+ leaves their document dirty, so SOLIDWORKS prompts "Save changes?" on close+ and their own Ctrl+S writes bridge-authored data into their file.+- **Name the document with `targetDocument`, not by hoping.** Every mutating+ verb resolves its target ONCE — `targetDocument` (a title), else `path`, else+ the active document — and the bridge acts on exactly that. A `targetDocument`+ naming nothing open is an error (`document_not_open`), never a silent fall+ back to whatever the user has in front of them; naming two different documents+ two ways is `ambiguous_target`. Prefer `targetDocument` whenever it matters:+ SOLIDWORKS' active document follows window focus, and the user may click+ something else mid-run.+- **`swx_com_eval` evaluates READS ONLY, by allowlist.** Members beginning+ `Get`/`Is`/`Has`/`Can`/`Enum`, plus a short list of navigation properties+ (`ActiveDoc`, `Extension`, `SketchManager`, `FeatureManager`, `Frame`,+ `Name`, `Value`, `Mass`, …). Everything else — including members nobody has+ thought of — is refused with `errorCode:"eval_member_blocked"` and a reason.+ It is an allowlist rather than a banned list because a banned list has to+ anticipate every dangerous member of an API with thousands, and the first one+ missed `SendMsgToUser2` (a modal that wedges the host), `SetUserPreferenceToggle`+ and `ForceRebuild3`. If a genuine READ is refused, that is a bug worth filing.+- **`swx_save_as` RENAMES by default.** The open document becomes that file and+ takes its name — which is what you want for a scratch part, and emphatically+ not what you want on someone's `bracket.sldprt`. `copy:true` writes the file+ and leaves the document alone; that is what every `swx_export*` does.+- **`swx_reset_workspace` is the safe cleanup**: it closes only documents this+ bridge process created and has not saved. The list lives in memory, not on+ disk, because SOLIDWORKS names new documents `Part1`/`Assem1` and a+ remembered title would eventually match a document the USER made. A bridge+ restart therefore forgets and the sweep closes nothing.+- **The export format is the DESTINATION EXTENSION, not the `format` argument.**+ `swx_export_step {"outputPath":"x.wrl"}` writes VRML, not STEP — which is why+ the bridge refuses `.wrl` on the filename (`errorCode:"format_blocked"`) on+ every route. VRML raises a modal that hangs SOLIDWORKS for minutes.+- **There is no cloud.** `swx_cloud_status` explains why with a live probe: the+ SOLIDWORKS COM API exposes no 3DSpace/3DDrive member at all. Local files work+ fully. Do not go looking for a cloud-open verb.++## Coming from the Fusion 360 bridge?++Arg names and response keys mirror `fusion_*` wherever the concept survives:+`outputPath`, `filePath`, `name`, `parameters`, `bodies`, `current`, `applied`,+`actions`, `stages`, `wouldPrompt`, `closed`, `remaining`. The four things that+do **not** transfer:++| Fusion | SOLIDWORKS |+|---|---|+| `fusion_start` launches the app | `swx_start` **attaches only** on Connected editions — a human must start it |+| `fusion_run_modeling_script` takes Python | `swx_run_script` takes a JSON array of typed steps |+| Fusion has no macro road | `swx_run_macro` runs a VBA `.swp`/`.swb`/`.dll` — always gated, and not yet live-proven |+| 21 cloud verbs (APS) | none — `swx_cloud_status` says why |+| `fusion_export_optimized_glb` needs a service | `swx_export_glb` is native |++`docs/FUSION-PARITY-REPORT.md` in the bridge repo has all 132 Fusion verbs with+a verdict.++## Verb catalog++`swx_describe '{}'` returns the full machine-readable catalog with per-verb+risk, the modelling DSL's op list, and the live-verified export-format matrix.+Trust each verb's own `_hint` over anything written here.
adom-bridge-solidworks-manifest.jsonadded+16@@ -0,0 +1,16 @@+{+ "manifest_version": 1,+ "name": "solidworks",+ "version": "0.3.1",+ "url": "https://wiki.adom.inc/download/adom/solidworks-bridge/0.3.1/swx-bridge-v0.3.1.zip",+ "sha256": "ea3820d4dd066ff81c0ad0c4d91b54d1278e4951ecd2e561dadbce8dbbe44841",+ "size": 648721,+ "verbPrefixes": [+ "swx_"+ ],+ "healthEndpoint": "/status",+ "languages": [+ "Rust"+ ],+ "updateManifestUrl": "https://wiki.adom.inc/api/v1/pages/solidworks-bridge/files/adom-bridge-solidworks-manifest.json"+}