← Commit history
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.122\ No newline at end of file+1.9.123\ No newline at end of file
adom-bridge-fusion-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "fusion360",-  "version": "1.9.122",-  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.137/adom-bridge-fusion-v1.9.122.zip",-  "sha256": "6c654c30b623b07ed26a5b388d969eebba4180f66bac205c30e467bc7c3a3847",-  "size": 458429,+  "version": "1.9.123",+  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.139/adom-bridge-fusion-v1.9.123.zip",+  "sha256": "32f28501be653cb137b4388718b9bd64bd6da24e8fe979673d124fef6830c61b",+  "size": 458698,   "verbPrefixes": [     "fusion_"   ],
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.9.122",+  "version": "1.9.123",   "description": "Drive Autodesk Fusion 360 from the cloud: launch Fusion, electronics board layout, design rules, exports (STEP/IGES/STL/3MF/USDZ/OBJ/DXF/DWG/Gerbers/BOM/CPL), fast APS server-indexed cloud search plus browse/recent/file-info/versions, cloud file download/upload and folder creation, and in-app parametric modeling (fusion_run_modeling_script). Never-charge: APS calls are capped to the free tier.",   "homepage": "https://wiki.adom.inc/adom/fusion-bridge",   "author": "Adom Inc.",
describe.py+1−1
@@ -14,7 +14,7 @@ _STATUS = "fusion_get_app_state" # Compact source table: name -> (summary, input, output, timeout, statusVerb, longRunning, example) _T = [     # ── Lifecycle ──────────────────────────────────────────────────────────-    ("fusion_create_library", "ONE-CALL library creation for web-control (one call = one consent). TWO entry shapes: A) {libraryPath, stepPath} - a ready .lbr plus the 3D; B) {kicadSymbolPath, kicadFootprintPath, stepPath, pinMap?} - KiCad sources, converted via adom-lbr (the canonical converter), pinMap = explicit {pinName: padName} for when pin numbers do not match pad names (BGA-style). Chains convert -> bind 3D -> prove (four evidence frames + verdict) in the BACKGROUND and returns immediately; poll fusion_prove_result (stage narrates, prove carries the verdict). stepPath is required for a PROVEN library - no real 3D body without it.", {"libraryPath": "optional str (shape A, or output path for B)", "kicadSymbolPath": "optional str", "kicadFootprintPath": "optional str", "stepPath": "optional str (required for proven)", "pinMap": "optional {pinName: padName}", "name": "optional str"}, {"started": "bool", "statusVerb": "str"}, 30, "fusion_prove_result", True, {"libraryPath": "C:/Temp/PART.lbr", "stepPath": "C:/Temp/PART.step"}),+    ("fusion_create_library", "ONE-CALL library creation for web-control (one call = one consent). TWO entry shapes: A) {libraryPath, stepPath} - a ready .lbr plus the 3D; B) {kicadSymbolPath, kicadFootprintPath, stepPath, pinMap?} - KiCad sources; needs adom-lbr, which is Linux-container-only by platform rule, so on Windows/Mac boxes shape B refuses IMMEDIATELY (adom_lbr_unavailable, before any staging or Fusion launch - fusion_readiness reports kicadIngest up front). Convert at AUTHORING time in a container and use shape A. pinMap = explicit {pinName: padName} for when pin numbers do not match pad names (BGA-style). Chains convert -> bind 3D -> prove (four evidence frames + verdict) in the BACKGROUND and returns immediately; poll fusion_prove_result (stage narrates, prove carries the verdict). stepPath is required for a PROVEN library - no real 3D body without it.", {"libraryPath": "optional str (shape A, or output path for B)", "kicadSymbolPath": "optional str", "kicadFootprintPath": "optional str", "stepPath": "optional str (required for proven)", "pinMap": "optional {pinName: padName}", "name": "optional str"}, {"started": "bool", "statusVerb": "str"}, 30, "fusion_prove_result", True, {"libraryPath": "C:/Temp/PART.lbr", "stepPath": "C:/Temp/PART.step"}),     ("fusion_start", "Launch Fusion 360 (if needed) and wait for the AdomBridge add-in to be ready.",      {}, {"success": "bool", "addinReady": "bool", "status": "str"}, 150, None, True, {}),     ("fusion_stop", "Gracefully STOP Fusion 360: close docs cleanly + WM_CLOSE, then wait. NO force-kill - the clean opposite of fusion_start. If a window will not close it returns failure; use fusion_kill then.",
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.9.138",+  "version": "1.9.139",   "type": "app",   "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.",   "dependencies": {
page.json+10−7
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.9.138",+  "version": "1.9.139",   "type": "app",   "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.",   "dependencies": {@@ -11,6 +11,10 @@     "uninstall": "./uninstall.sh"   },   "tags": [+    "ab",+    "bridge",+    "fusion",+    "desktop-app",     "fusion360",     "autodesk",     "cad",@@ -70,7 +74,10 @@     "build a basic parts library",     "add a 3d model to a component",     "make a fusion 360 library with 3d",-    "set up the fusion bridge"+    "set up the fusion bridge",+    "fusion dashboard",+    "fusion status page",+    "open the fusion launch page"   ],   "discovery_pitch": "Use the Adom Bridge Fusion 360 bridge when the user wants to DRIVE Autodesk Fusion 360 from the cloud: open/search their team's Fusion cloud designs, lay out a PCB or do electronics, export STEP/IGES/STL/Gerbers/BOM, or build a component library with real rendering 3D. It runs Fusion on the user's own machine via Adom Bridge. NOT for web/browser/login/form-filling (that's the native-browser extension) and NOT for KiCad (that's the kicad bridge).",   "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",@@ -99,9 +106,5 @@       "label": "Part volume",       "prompt": "How much material does each printed part in this assembly use?"     }-  ],-  "author": {-    "name": "John Lauer",-    "email": "[email protected]"-  }+  ] }\ No newline at end of file
server.py+38−50
@@ -1749,6 +1749,11 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict:         "installing": installing,         "running": running,         "ready": ready,+        # CAPABILITY, knowable before staging a single file (#43 follow-up): shape B of+        # fusion_create_library needs adom-lbr, which is Linux-container-only by platform+        # rule - so on Windows/Mac this is False and the caller should convert at+        # authoring time and send shape A (.lbr + .step).+        "kicadIngest": bool(_find_adom_lbr()),         "bridgeVersion": BRIDGE_VERSION,         **stale_info,         "_hint": (hint + " NOTE: " + result_note) if result_note else hint,@@ -9493,6 +9498,26 @@ COMMAND_HANDLERS["prove_library"] = _handle_prove_library   +def _kicad_ingest_unavailable_error() -> dict:+    """The shape-B refusal, shared by import_kicad and the create_library fast-fail.++    Platform rule (John, 2026-08-21): a bridge runs on Windows or Mac; ALL Adom binaries+    are Linux-container-only. So KiCad conversion can never happen on this box, and the+    contract is authoring-time: convert in a container, publish the validated .lbr on the+    part page, hand the bridge shape A (.lbr + .step)."""+    return {"success": False, "errorCode": "adom_lbr_unavailable",+            "kicadIngest": False,+            "error": "adom-lbr (the canonical KiCad->EAGLE converter) does not run on this "+                     "platform - Adom binaries are Linux-container-only by design - and this "+                     "bridge deliberately does NOT convert KiCad formats itself.",+            "_hint": ("Convert at AUTHORING time, where adom-lbr genuinely runs: in a "+                      "container, `adom-lbr generate --sym <.kicad_sym> --fp <.kicad_mod> "+                      "-o <out.lbr>` (auto-linted), publish the .lbr on the part page, then "+                      "call fusion_create_library shape A {libraryPath, stepPath}. "+                      "fusion_readiness reports kicadIngest so this is knowable before "+                      "staging files or launching Fusion.")}++ def _find_adom_lbr() -> str:     """Locate adom-lbr on THIS box (the canonical KiCad->EAGLE converter, adom/adom-lbr)."""     import shutil as _sh@@ -9508,44 +9533,12 @@ def _find_adom_lbr() -> str:   -def _install_adom_lbr_windows() -> str:-    """SELF-INSTALL adom-lbr on this box (doctrine: never hand the user an install step).--    Probes the wiki for a windows release asset (requested in adom-lbr#6) and caches it-    under %LOCALAPPDATA%\\Programs\\adom-lbr. Returns the exe path, or "" while no-    windows asset exists yet - at which point the caller's error says conversion is-    container-side for now. The moment Ray ships the asset, this verb starts working on-    fresh boxes with no code change.-    """-    import urllib.request as _u-    la = os.environ.get("LOCALAPPDATA", "")-    if not la:-        return ""-    dest_dir = os.path.join(la, "Programs", "adom-lbr")-    dest = os.path.join(dest_dir, "adom-lbr.exe")-    if os.path.exists(dest):-        return dest-    try:-        req = _u.Request("https://wiki.adom.inc/api/v1/pages/adom-lbr/releases")-        rels = json.loads(_u.urlopen(req, timeout=15).read()).get("releases") or []-        ver = rels[0].get("version") if rels else None-        if not ver:-            return ""-        url = "https://wiki.adom.inc/download/adom/adom-lbr/%s/adom-lbr.exe" % ver-        os.makedirs(dest_dir, exist_ok=True)-        tmp = dest + ".tmp"-        with _u.urlopen(url, timeout=60) as r, open(tmp, "wb") as f:-            f.write(r.read())-        os.replace(tmp, dest)-        print("[Fusion Bridge] self-installed adom-lbr %s -> %s" % (ver, dest))-        return dest-    except Exception:-        try:-            os.remove(dest + ".tmp")-        except Exception:-            pass-        return ""-+# _install_adom_lbr_windows was DELETED (2026-08-21). The platform rule it violated:+# a bridge runs on Windows or Mac, and ALL Adom binaries are Linux-container-only by+# deliberate decision - there will never be a windows adom-lbr asset for it to fetch+# (adom-lbr#6 withdrawn, adom-lbr#8 retracted by its own filer). Conversion happens at+# AUTHORING time in a container; the published .lbr is the runtime contract (page+# issue #43, adom-bridge#92).   def _apply_pin_map(lbr_path: str, pin_map: dict) -> dict:@@ -9610,18 +9603,7 @@ def _handle_import_kicad(fusion_info: dict, args: dict) -> dict:                 "error": "Pass kicadSymbolPath and/or kicadFootprintPath."}     tool = _find_adom_lbr()     if not tool:-        tool = _install_adom_lbr_windows()-    if not tool:-        return {"success": False, "errorCode": "adom_lbr_unavailable",-                "error": "adom-lbr (the canonical KiCad->EAGLE converter) is not installed "-                         "on this box, and this bridge deliberately does NOT convert KiCad "-                         "formats itself.",-                "_hint": ("Conversion is owned by adom/adom-lbr - one converter for the whole "-                          "ecosystem. From a CONTAINER: `adom-lbr generate --sym <.kicad_sym> "-                          "--fp <.kicad_mod> -o <out.lbr>` (auto-linted), then stage the .lbr "-                          "to this box (send_files, dest under %TEMP%) and use the fusion_show_* "-                          "verbs. A windows release asset of adom-lbr has been requested so this "-                          "verb can run it on-box.")}+        return _kicad_ingest_unavailable_error()     if not lbr_p:         base = (sym_p or mod_p).rsplit("/", 1)         stem = base[-1].rsplit(".", 1)[0]@@ -9777,6 +9759,12 @@ def _handle_create_library(fusion_info: dict, args: dict) -> dict:                 "_hint": "Shape A: {libraryPath, stepPath}. Shape B: {kicadSymbolPath, "                          "kicadFootprintPath, stepPath, pinMap?}. stepPath is required for "                          "a PROVEN library - without it there is no real 3D body."}+    # SHAPE B FAILS AT THE FRONT DOOR, never three stages in (#43 follow-up, 2026-08-21):+    # the old flow staged files, launched Fusion (a minute of the user's time), and THEN+    # discovered adom-lbr is absent - which on Windows/Mac it always is, by platform rule.+    # Knowable up front, so refused up front; fusion_readiness carries the same flag.+    if (sym_p or mod_p) and not _find_adom_lbr():+        return _kicad_ingest_unavailable_error()      import uuid as _uuid     run_id = _uuid.uuid4().hex[:12]