← Commit history
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.13.28\ No newline at end of file+1.13.29\ No newline at end of file
CHANGELOG.md+4−1
@@ -3,7 +3,10 @@ All notable changes to the Adom Bridge Fusion 360 bridge, newest first. Canonical: https://wiki.adom.inc/adom/fusion-bridge ยท GitHub backup: `adom-inc/fusion-bridge` -## 1.13.29 (unreleased)+## 1.13.29 (2026-10-30)++- `fusion_inspect_bodies` brings the design's 3D board forward and reads again when the 2D board or schematic is in+  front (it answered "'NoneType' object has no attribute 'rootComponent'" right after review_board); `shown3d` says so.  - `fusion_sch_batch` (the standard's sch_batch, agreed on eda-bridge-standard#29): schematic edits all or nothing. Each op   is a standard sch_* verb with its arguments, run as that verb runs, so it sees the sheet as the earlier ops left it.
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.13.28",+  "version": "1.13.29",   "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.",
dashboard/Cargo.lock+1−1
@@ -4,7 +4,7 @@ version = 4  [[package]] name = "fusion-dashboard"-version = "1.13.28"+version = "1.13.29" dependencies = [  "serde_json", ]
dashboard/Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.13.28"+version = "1.13.29" edition = "2021"  [dependencies]
install.sh+1−1
@@ -21,7 +21,7 @@ echo "Installed fusion-bridge skills: $(ls "$PKG_DIR/skills" 2>/dev/null | tr '\ # binary (the three-artifact pattern: bridge zip -> ab, THIS pkg -> container skills + # this download, page media -> wiki). Per the wiki's PKG_VS_RELEASE policy, binaries are # platform-tagged RELEASE assets, never tarball content - the installer fetches them.-DASH_VERSION="1.13.28"+DASH_VERSION="1.13.29" DASH_URL="https://wiki.adom.inc/download/adom/fusion-bridge/${DASH_VERSION}/fusion-dashboard" DEST="" if [ -w /usr/local/bin ]; then DEST=/usr/local/bin
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.13.28",+  "version": "1.13.29",   "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+2−2
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.13.28",+  "version": "1.13.29",   "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": {@@ -152,4 +152,4 @@   "confirmed_user_skills": [     "fusion-design-efficiency"   ]-}\ No newline at end of file+}
rust/Cargo.lock+5−5
@@ -19,7 +19,7 @@ dependencies = [  [[package]] name = "adom-fusion-bridge"-version = "1.13.28"+version = "1.13.29" dependencies = [  "adom-eda-checks",  "base64",@@ -299,7 +299,7 @@ dependencies = [  [[package]] name = "fusion-core"-version = "1.13.28"+version = "1.13.29" dependencies = [  "serde",  "serde_json",@@ -310,7 +310,7 @@ dependencies = [  [[package]] name = "fusion-lbr"-version = "1.13.28"+version = "1.13.29" dependencies = [  "regex",  "roxmltree",@@ -322,14 +322,14 @@ dependencies = [  [[package]] name = "fusion-os-mac"-version = "1.13.28"+version = "1.13.29" dependencies = [  "fusion-core", ]  [[package]] name = "fusion-os-win"-version = "1.13.28"+version = "1.13.29" dependencies = [  "fusion-core",  "windows-sys 0.59.0",
rust/Cargo.toml+1−1
@@ -4,7 +4,7 @@ members = ["core", "lbr", "os-win", "os-mac", "bridge"]  # One version for the whole bridge, in lockstep with BRIDGE_VERSION (tools/release.sh bumps both). [workspace.package]-version = "1.13.28"+version = "1.13.29" edition = "2021" license = "MIT" 
rust/bridge/src/orchestrations.rs+8−1
@@ -998,12 +998,19 @@ pub fn inspect_bodies(args: &Value, pass: &dyn Fn(&str, Value) -> Value) -> Valu     let world = args["worldSpace"].as_bool().unwrap_or(false);     let occ = args["occurrence"].as_str().unwrap_or("");     let script = INSPECT_BODIES_SCRIPT.replace("__WORLD__", if world { "True" } else { "False" }).replace("__OCC__", &if occ.is_empty() { "None".to_string() } else { fusion_lbr::py_repr_str(occ) });-    let res = pass("run_modeling_script", json!({"script": script}));+    let mut res = pass("run_modeling_script", json!({"script": script}));+    // the 2D board or schematic in front has no Design to read: the design's 3D board is brought+    // forward and the read runs again (the battery met this right after review_board)+    let mut shown_3d = false;+    if res["success"].as_bool() != Some(true) && res["error"].as_str().map(|e| e.contains("rootComponent")).unwrap_or(false) {+        if pass("show_3d_board", json!({}))["success"].as_bool() == Some(true) { shown_3d = true; res = pass("run_modeling_script", json!({"script": script})); }+    }     if res["success"].as_bool() != Some(true) { return res; }     let data = res["data"].clone();     let Some(mut payload) = data.get("result").filter(|p| p.is_object()).cloned() else { return json!({"success": false, "error": "inspect_bodies returned no structured result", "errorCode": "inspect_failed", "data": data, "_hint": "The read-back script ran but produced no result dict. Usually means no active Design; open a document and retry."}) };     let n = payload["bodyCount"].as_i64().unwrap_or(0);     payload["success"] = json!(true);+    if shown_3d { payload["shown3d"] = json!(true); }     payload["_hint"] = json!(if n > 0 { format!("Bounding boxes, volumes and areas are in MILLIMETRES (Fusion's API is centimetres; converted here so you do not have to). Check bbox Z against where the part SHOULD sit - a wrong offset renders perfectly and is invisible in a screenshot. cylindricalFaceCount is the cheap way to confirm holes were actually cut: a symmetric cut that reaches nothing fails SILENTLY with no exception, and the count is what surfaces it. {}", if !world { "Pass worldSpace:true to resolve bodies through their occurrence transforms and verify assembly placement." } else { "worldSpace:true - occurrence bodies are proxies already resolved into assembly space." }) } else { "No bodies found. If you expected some, the active document may not be the one you built into (pass expectDocument on mutating verbs to catch that), or the design is empty.".to_string() });     payload }