← Commit history
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.13.56\ No newline at end of file+1.13.57\ No newline at end of file
CHANGELOG.md+5
@@ -3,6 +3,11 @@ 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.57 (2026-11-02)++`fusion_edit_tracks` sets a fine grid before moving a track's end: without it MOVE snapped the end to the board's grid, the+readback found it elsewhere, and the edit was undone.+ ## 1.13.56 (2026-11-02)  The rulings on standard #29:
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.13.56",+  "version": "1.13.57",   "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.56"+version = "1.13.57" dependencies = [  "serde_json", ]
dashboard/Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.13.56"+version = "1.13.57" 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.56"+DASH_VERSION="1.13.57" 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.56",+  "version": "1.13.57",   "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.56",+  "version": "1.13.57",   "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.56"+version = "1.13.57" dependencies = [  "adom-eda-checks",  "base64",@@ -299,7 +299,7 @@ dependencies = [  [[package]] name = "fusion-core"-version = "1.13.56"+version = "1.13.57" dependencies = [  "serde",  "serde_json",@@ -310,7 +310,7 @@ dependencies = [  [[package]] name = "fusion-lbr"-version = "1.13.56"+version = "1.13.57" dependencies = [  "regex",  "roxmltree",@@ -322,14 +322,14 @@ dependencies = [  [[package]] name = "fusion-os-mac"-version = "1.13.56"+version = "1.13.57" dependencies = [  "fusion-core", ]  [[package]] name = "fusion-os-win"-version = "1.13.56"+version = "1.13.57" 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.56"+version = "1.13.57" edition = "2021" license = "MIT" 
rust/bridge/src/routing_script.py+3
@@ -1218,9 +1218,12 @@ def edit_tracks(app, root, board, meta, args):         return {'success': False, 'mutated': False, **meta, 'errorCode': 'nothing_to_do', 'results': results, 'error': 'No track could be edited'}     visible = _visible_layers(root)     try:+        # without a fine grid MOVE snaps a track's end to the board's grid, and it reads back somewhere else+        app.executeTextCommand('Electron.run GRID MM 0.001;')         for c in cmds:             app.executeTextCommand('Electron.run ' + c)     finally:+        app.executeTextCommand('Electron.run GRID LAST;')         _restore_display(app, visible)     _, after, meta2 = snapshot(app, args)     now = objects(after)[2]
tests/sch_drill.py+22−2
@@ -188,8 +188,28 @@ print('%-34s %s' % (results[-1][0], 'PASS' if results[-1][1] is None else 'FAIL r = call('fusion_place_parts', {'expectDocument': 'Untitled', 'parts': [{'library': LBR, 'footprint': 'R0603', 'ref': 'R50', 'x': 5, 'y': 5}]}) results.append(('place_parts linked refused', expect(r.get('errorCode') == 'linked_board', '%s %s' % (r.get('errorCode'), str(r.get('error'))[:90])))) print('%-34s %s' % (results[-1][0], 'PASS' if results[-1][1] is None else 'FAIL  ' + str(results[-1][1])))-state = call('fusion_routing_state', {'expectDocument': 'Untitled'})-print('tracks on the board:', len(state.get('tracks') or []), '(edit_tracks needs one: see tests/sch_drill.py)')+# a track to edit: R1 and R2 share no net yet, so draw one on a part's net with a plain wire on Top+pad = next((p_ for p_ in call('fusion_routing_state', {'expectDocument': 'Untitled'}).get('pads') or [] if p_.get('net') == 'NB'), None)+if pad:+    x0, y0 = pad.get('x'), pad.get('y')+    call('fusion_electron_run', {'command': "LAYER 1; CHANGE WIDTH 0.2mm; WIRE 'NB' (%gmm %gmm) (%gmm %gmm);" % (x0, y0, x0, y0 + 4)})+tracks = [t for t in call('fusion_routing_state', {'expectDocument': 'Untitled'}).get('tracks') or [] if t.get('net') == 'NB']+tid = tracks[0].get('id') if tracks else None+results.append(('a track to edit, with an id', expect(tid, 'no track on NB: %d tracks' % len(tracks))))+print('%-34s %s' % (results[-1][0], 'PASS' if results[-1][1] is None else 'FAIL  ' + str(results[-1][1])))+++def track_widths():+    return {t.get('id'): t.get('width') for t in call('fusion_routing_state', {'expectDocument': 'Untitled'}).get('tracks') or [] if t.get('net') == 'NB'}+++step('edit_tracks width', 'fusion_edit_tracks', {'expectDocument': 'Untitled', 'tracks': [{'id': tid, 'width': 0.4}]},+     lambda r: expect(r.get('verified') and abs((track_widths().get(tid) or 0) - 0.4) < 1e-6, 'width now %s' % track_widths().get(tid)))+step('edit_tracks end', 'fusion_edit_tracks', {'expectDocument': 'Untitled', 'tracks': [{'id': tid, 'end': [x0 + 2, y0 + 4] if pad else [0, 0]}]},+     lambda r: expect(r.get('verified') and any(abs(t['end']['x'] - x0 - 2) < 1e-3 for t in call('fusion_routing_state', {'expectDocument': 'Untitled'}).get('tracks') or [] if t.get('net') == 'NB'), 'end did not move'))+r = call('fusion_edit_tracks', {'expectDocument': 'Untitled', 'tracks': [{'id': 'track:NOPE:1:0,0,1,1', 'width': 0.3}]})+results.append(('edit_tracks unknown id', expect(r.get('errorCode') == 'nothing_to_do', str(r.get('errorCode')))))+print('%-34s %s' % (results[-1][0], 'PASS' if results[-1][1] is None else 'FAIL  ' + str(results[-1][1])))  dialogs = call('fusion_check_dialogs', {}).get('count') results.append(('no dialog left', expect(not dialogs, '%s dialog(s) open' % dialogs)))