app
Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
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.
← Commit history
Update 161 file(s)
13 files changed
+155−130
BRIDGE_VERSION+1−1addin/AdomBridge/http_server.py+15−1bridge.json+1−1dashboard/Cargo.lock+1−1dashboard/Cargo.toml+1−1install.sh+1−1package.json+2−5page.json+11−28rust/Cargo.toml+1−1rust/bridge/src/addin.rs+2−1rust/bridge/src/launch.rs+13rust/bridge/src/main.rs+5−3skills/fusion-routing/SKILL.md+101−86BRIDGE_VERSION+1−1@@ -1 +1 @@-1.10.0+1.10.1
addin/AdomBridge/http_server.py+15−1@@ -116,6 +116,18 @@ _watchdog_stop = threading.Event() _watchdog_thread = None +def _watchdog_note(text):+ """Append a watchdog line to the add-in's own log file (never Fusion's API from this thread)."""+ try:+ import os, time as _t+ p = os.path.join(os.path.expanduser("~"), ".adom", "fusion-bridge", "addin-watchdog.log")+ os.makedirs(os.path.dirname(p), exist_ok=True)+ with open(p, "a", encoding="utf-8") as f:+ f.write(_t.strftime("%Y-%m-%dT%H:%M:%S ") + text + "\n")+ except Exception:+ pass++ def _watchdog_loop(): """Force-release _main_thread_lock if a command has been busy too long.""" while not _watchdog_stop.is_set():@@ -129,7 +141,9 @@ def _watchdog_loop(): cmd_timeout = PER_COMMAND_TIMEOUT.get(cmd, COMMAND_TIMEOUT) if elapsed > cmd_timeout + WATCHDOG_GRACE: try:- adsk.core.Application.log(+ # Not a Fusion API call: this runs on the watchdog thread, and the add-in+ # keeps every API call on the main thread (issue #76 audit, 2026-09-06).+ _watchdog_note( f"AdomBridge: WATCHDOG force-releasing _main_thread_lock — " f"'{cmd}' held for {elapsed:.1f}s " f"(> {cmd_timeout}+{WATCHDOG_GRACE}s grace). "
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.10.0",+ "version": "1.10.1", "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.10.0"+version = "1.10.1" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.10.0"+version = "1.10.1" 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.10.0"+DASH_VERSION="1.10.1" 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+2−5@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.10.0",+ "version": "1.10.1", "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": {@@ -85,8 +85,5 @@ "adom-desktop-fusion-bridge is the Fusion 360 bridge for Adom Bridge; its fusion_* verbs are invoked through the adom-bridge CLI and drive Autodesk Fusion on the user's own desktop.", "adom-desktop-fusion-bridge desktop actions also pass Adom Bridge's own human-approval gate (caller identity, per-call reason, Activity Log) - a container approval is the first of two gates." ]- },- "files": [- "skills/fusion-routing/**"- ]+ } }
page.json+11−28@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.10.0",+ "version": "1.10.1", "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",@@ -57,8 +61,7 @@ "skills/fusion-dark-mode/**", "skills/fusion-file-search/**", "skills/fusion-mcp-and-preferences/**",- "skills/fusion-web-export/**",- "skills/fusion-routing/**"+ "skills/fusion-web-export/**" ], "discovery_triggers": [ "drive fusion 360",@@ -76,7 +79,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.",@@ -105,28 +111,5 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ],- "agent_permissions": {- "allow_bash": [],- "allow": [- "adom-desktop-fusion-bridge read-only verbs (via the adom-bridge CLI): fusion_readiness, fusion_get_app_state, fusion_addin_status, fusion_check_dialogs - state queries; they change nothing.",- "adom-desktop-fusion-bridge read-only verbs: fusion_alerts (reads Fusion's own log for toasts), fusion_document_info, fusion_window_info, fusion_board_info, fusion_library_parts - inspect only.",- "adom-desktop-fusion-bridge read-only verbs: fusion_prove_result (a persisted run report), fusion_plan_library_import (report-only preflight), fusion_list_cloud_projects, fusion_describe.",- "adom-desktop-fusion-bridge evidence captures fusion_screenshot_fusion and fusion_capture_library_views read pixels and write local image files only."- ],- "soft_deny": [- "adom-desktop-fusion-bridge lifecycle verbs fusion_stop, fusion_kill, fusion_restart_for_addin close or kill the Fusion application - keep the human prompt.",- "adom-desktop-fusion-bridge fusion_install_fusion silently installs Autodesk Fusion on the user's machine.",- "adom-desktop-fusion-bridge fusion_cleanup_cloud_files deletes files from the user's Autodesk cloud hub.",- "adom-desktop-fusion-bridge managed-library verbs (fusion_managed_library_push/pull/create/link/unlink) publish to or overwrite the user's library.io libraries."- ],- "environment": [- "adom-desktop-fusion-bridge is the Fusion 360 bridge for Adom Bridge; its fusion_* verbs are invoked through the adom-bridge CLI and drive Autodesk Fusion on the user's own desktop.",- "adom-desktop-fusion-bridge desktop actions also pass Adom Bridge's own human-approval gate (caller identity, per-call reason, Activity Log) - a container approval is the first of two gates."- ]- },- "author": {- "name": "John Lauer",- "email": "[email protected]"- }+ ] }
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.10.0"+version = "1.10.1" edition = "2021" license = "MIT"
rust/bridge/src/addin.rs+2−1@@ -277,7 +277,8 @@ pub fn pass_through(cmd: &str, args: &Value, ctx: &Ctx) -> Value { if total >= 2.0 && res.is_object() { let call_end = if t_call_done.get() > 0.0 { t_call_done.get() } else { t_body }; let r2 = |x: f64| (x * 100.0).round() / 100.0;- res["_timing"] = json!({"totalSec": r2(total), "preSec": r2(t_pre), "addinSec": r2(call_end - t_pre), "dialogsSec": r2(t_body - call_end), "postSec": r2(total - t_body)});+ res["_timing"] = json!({"totalSec": r2(total), "preSec": r2(t_pre), "addinSec": r2(call_end - t_pre), "dialogsSec": r2(t_body - call_end), "postSec": r2(total - t_body),+ "scope": "one exe pass-through of this verb only: excludes the relay hop, ab's queue, and any earlier pass-through a composite verb (routing, tour) made before this one, so the caller's wall clock can be longer"}); eprintln!("[fusion-bridge] {cmd} took {:.1}s: pre {:.1}s, add-in {:.1}s, dialogs {:.1}s, post {:.1}s", total, t_pre, call_end - t_pre, t_body - call_end, total - t_body); } res
rust/bridge/src/launch.rs+13@@ -298,6 +298,19 @@ pub fn gate(ctx: &Ctx, cmd: &str, args: &Value) -> Option<Value> { "_hint": "Call fusion_start to start Fusion 360, then wait for the add-in to become ready (fusion_start blocks until ready). Then retry this command."})); } if busy_status().is_some() { return None; } // the busy gate answers this one+ // Sign-in short-circuit (page issue #79): while the main window says "Signing in" the add-in+ // is not loaded yet, so probing it for 5s, then a 20s hang probe, then the restart-info+ // walk turned a known readiness state into a 60s+ addin_restart_required. Answer from the+ // window title instead, in well under a second.+ if let Some(facts) = Loopback::from_env().map(|ab| fusion_core::windows_facts::facts_from_ab(&ab, &ctx.caller)) {+ if facts.needs_signin {+ crate::fusion_prefs::action_ledger(&ctx.state_dir, "signin_gate", json!({"forCommand": cmd, "mainTitle": facts.main_title}));+ return Some(json!({"success": false, "errorCode": "needs_signin", "needsSignin": true, "hostResponding": true,+ "mainTitle": facts.main_title,+ "error": format!("Fusion is at the Autodesk sign-in screen ({}), so the add-in is not loaded yet and '{cmd}' cannot run. This is NOT an add-in fault and NOT a hang.", facts.main_title.as_deref().unwrap_or("Signing in - Autodesk Fusion")),+ "_hint": "Do NOT restart Fusion and do NOT diagnose the add-in: nothing loads until the user is signed in. Drive the sign-in with the fusion-autodesk-signin skill (fusion_signin), or ask the user to sign in, then poll fusion_readiness until needsSignin is false and ready is true, and retry this verb."}));+ }+ } if wait_for_addin(5) { return None; } let h = crate::readiness_exec::confirmed_hung(ctx); if h["hung"].as_bool() == Some(true) {
rust/bridge/src/main.rs+5−3@@ -515,6 +515,8 @@ fn main() { /// Forward an unported verb to the Python sidecar, identity headers intact. fn proxy(sidecar: &Arc<Mutex<Option<Sidecar>>>, raw: &str, caller: &Caller) -> Value { proxy_with_timeout(sidecar, raw, caller, 600) } +fn verb_of(raw: &str) -> String { serde_json::from_str::<Value>(raw).ok().and_then(|v| v["command"].as_str().or(v["verb"].as_str()).map(String::from)).unwrap_or_else(|| "?".into()) }+ fn proxy_with_timeout(sidecar: &Arc<Mutex<Option<Sidecar>>>, raw: &str, caller: &Caller, timeout_secs: u64) -> Value { // ab routes the first verb the moment /status is 2xx, which is before the sidecar has // bound its port: wait out the sidecar's startup (bounded) instead of failing that verb.@@ -523,9 +525,9 @@ fn proxy_with_timeout(sidecar: &Arc<Mutex<Option<Sidecar>>>, raw: &str, caller: "_hint": "Read ~/.adom/fusion-bridge/sidecar.log for the traceback, then bridge_kill {name:'fusion360'} so ab respawns the shell and its sidecar."}); } let (url, young) = match sidecar.lock().unwrap().as_ref() { Some(s) => { *launch::SIDECAR_URL.lock().unwrap() = Some(s.url("/command")); (s.url("/command"), s.started.elapsed() < Duration::from_secs(45)) }, None => return json!({- "success": false, "errorCode": "sidecar_absent",- "error": "This verb is not ported yet and the Python sidecar is not running.",- "_hint": "Set ADOM_SIDECAR_PYTHON to ab's provisioned python.exe, or run the Python bridge directly until this verb is ported."}) };+ "success": false, "errorCode": "sidecar_absent", "verb": verb_of(raw),+ "error": format!("No handler in this exe owns the verb '{}', and there is no Python sidecar to fall back to (the exe ships alone since 1.10.0).", verb_of(raw)),+ "_hint": "This is a verb-name problem, not a Fusion or add-in problem: check the name against fusion_describe (the frozen contract) and do not restart Fusion or diagnose the add-in for it. If the name IS in the contract, file it on the fusion-bridge wiki page: a listed verb reached the fallback."}) }; let mut r = ureq::post(&url).timeout(Duration::from_secs(timeout_secs)).set("Content-Type", "application/json"); if !caller.thread.is_empty() { r = r.set("X-Adom-Caller-Thread", &caller.thread); } if !caller.container.is_empty() { r = r.set("X-Adom-Caller-Container", &caller.container); }
skills/fusion-routing/SKILL.md+101−86@@ -1,90 +1,105 @@ --- name: fusion-routing-description: >-- Route and review PCB copper in Autodesk Fusion through Fusion Bridge. Use for trace paths,- vias, manufacturer design rules, power and ground connections, copper pours, thermal- spreading and copper-ablation layouts. Inspect the actual board and verify native copper,- connectivity and DRC. Applies to ordinary board work, independently of recording or demos.+description: Use when asked to route a net, draw traces, add vias, pour copper or reproduce the Astra routing demos live in Fusion with fusion_routing_state, fusion_route_net, fusion_routing_drc and fusion_plan_route. Two-layer geometric preflight, native Autodesk DRC before and after, manufacturer rules loaded from adom/pcb-design-rules first. Trigger words - route this net, draw a trace, add a via, copper pour, refill, ratsnest, airwires, DRC, design rules, JLCPCB rules, reproduce the routing demo. --- -# Routing and copper engineering in Fusion--Use the installed `fusion-bridge` skill for desktop discovery and application control.-Discover the live `fusion_describe` contract and check `fusion_readiness` before board calls.-If sign-in blocks readiness, resolve sign-in first; repeating board calls can produce slow,-misleading add-in restart diagnoses. Preserve pinned runtimes and existing user documents.-Work within the user's requested scope and save a recoverable checkpoint before replacing routes.--## Establish fabrication and electrical constraints--Honor a manufacturer/process already selected. Otherwise ask which manufacturer the user-wants, offering profiles returned by `fusion_set_design_rules {action:"list"}`. If undecided,-keep current rules explicitly provisional and continue inspection before dependent routing.--Load the selected fab, process and actual layer count with `fusion_set_design_rules`.-Export the loaded profile and inspect the file, including per-layer/per-object rules and-net classes. Compare rules by name and meaning, not file order or a successful command reply.-Legacy EAGLE keys such as `mdWireWire`, `msWidth` and `msDrill` do not describe every native-EDRU rule. Check native alerts for a rejected load. Keep the stricter applicable fabrication-and user/electrical constraints. A process's minimum isolation channel is not a universal-high-voltage clearance; derive insulation constraints from the actual environment and voltage.--Read [electrical priorities](references/electrical-priorities.md) for power paths, sensitive-signals, clean bends and via choices. Read [copper and thermal design](references/copper-thermal.md)-when assigning pours, retaining copper for ablation, or improving heat spreading.--## Select the supported routing path--Read `fusion_routing_state {expectDocument}` and retain its exact `boardId` and `revision`.-`fusion_route_net` requires these plus the exact net and points/paths. Coordinates and widths-are millimeters. Use pad references for endpoints where supported. Layer-changing waypoints-create through vias according to the live contract.--The conservative `fusion_route_net` preflight and bounded `fusion_plan_route` planner support-two-layer boards. The planner is a two-pad orthogonal A* search, not an all-net autorouter.-Do not feed it a four-layer power board or imply it enforces all electrical constraints.-For supported two-layer work, dry-run proposed geometry, inspect its electrical suitability,-then commit with the same guards. Replan after intervening changes.--For inner layers, native pours or other operations outside those verbs, use the documented-`fusion_run_modeling_script` / `fusion_electron_run` extension and the actual board stackup.-Native `LINE`, `VIA`, `POLYGON`, `CHANGE`, `RATSNEST` and `SHOW` are electronics commands,-not invented bridge verbs. These paths need their own identity checks, clearance analysis,-native readback and DRC; they do not inherit the dedicated routing verb's preflight guarantees.-Never transplant a worked example's layer numbers, dimensions or net names without inspection.--## Commit, inspect, and recover--Inspect semantic `success`, `verified`, `mutationAttempted`, returned copper and revision.-Use the next returned revision for the next edit. Operations are not an atomic Undo group.-On timeout or mismatch, inspect the board before deciding whether any operation needs retrying.--On affected Fusion builds a completed net can raise Autodesk's unexpected-condition modal.-If the reply carries `fusionUnexpectedCondition` or a classified `fusion_unexpected_condition`,-treat it as an application fault with possibly committed copper. Verify actual connectivity-and geometry, checkpoint, and inspect remaining alerts before continuing. Do not count modal-dismissal alone as a verified route or blindly repeat the final segment.--Use the existing Adom activity palette for useful progress when requested; respect its close-state and the user's foreground preference. Recording, narration and fixture replay are optional-presentation tasks, not prerequisites for routing a board.--## Validate and save--Refill copper before measuring connectivity. Run native DRC before and after with the same-selected rules, reporting inherited and new violations separately. `fusion_routing_drc` reads-approved errors as well; require `drc.checked`, clean applicable rules and no remaining-connections before calling the result connected and DRC-clean. A diagnostic rule profile-is not certification under the manufacturer's full profile. Check schematic parity/ERC and-power, thermal and signal-integrity requirements separately where relevant.--Inspect `documentHygiene` / `_hintDocumentHygiene`. Export a verified checkpoint with-`fusion_export_eagle_source` or save through the documented native/cloud workflow. Verify-output existence and usable contents. Exporting a file does not necessarily clear Fusion's-modified state. Close only completed task-owned scratch documents by exact name after verifying-the checkpoint; do not bulk-close or discard original user work.--Summarize actual changes, rule provenance, connectivity/DRC results, saved artifacts and remaining-engineering assumptions. Optional board-specific examples live under `demo/routing/` in the-Fusion Bridge wiki source; no example, video, Codex package or particular AI provider is required-to apply this skill.+Parent skill: [fusion-bridge](../../SKILL.md).++Read `fusion_routing_state {expectDocument}` and keep its `boardId` and `revision`.+Use an isolated test board until this development feature is promoted. Existing+user designs and pinned runtimes must be preserved.++Call `fusion_route_net` with the exact `expectDocument`, `boardId`,+`expectedRevision`, `net`, and `points` or `paths`. Coordinates/widths are mm;+copper layers are 1 and 16. Use `{pad:"J1.1"}` for pad coordinates or+`{x:14,y:17,layer:16}` to change outgoing layer with a through via.++`dryRun:true` checks all geometry without adding copper. Geometric preflight is+conservative and incomplete; it refuses unsupported boards. Every actual call+verifies the copper delta by a new Fusion export. Inspect semantic `success`,+`verified`, and `mutationAttempted`. A timeout or mismatch is not authorization+to replay. Commands are not an atomic Undo group.++For live playback, submit one segment/via per call with the consecutive returned+revision. Capture the actual window with `desktop_record_window_start` and+finalize with `desktop_record_window_stop`, including in error paths. Never+replace live copper with a simulated animation. Foreground is opt-in.++Finish with `fusion_routing_drc` using the same identity/revision guards. It+recomputes RATSNEST, runs native Autodesk DRC, and reads all errors including+approved ones. Require `drc.checked`, `drc.clean`, and no remaining nets before+claiming a connected, DRC-clean result. Save/export the final board separately.++See `demo/routing/README.md` for the tested scope, fixture, recorder and evidence.++For the 24-net crossover, see `demo/routing/crossbar/README.md`. Identical+via transitions shared by branches of one request produce one planned via.++For obstacle-aware planning, call `fusion_plan_route` with the same document,+board and revision guards plus `net`, `fromPad`, and `toPad`. It returns a+read-only `plan.route` for `fusion_route_net` and `plan.items` for visible+per-item commits. Grid, via cost, allowVias and bounded node/time limits are+optional. It is a two-pad orthogonal A* planner, not an all-net autorouter.+Use a fresh plan after intervening edits. See `demo/routing/obstacles/README.md`.++## Showing live calculations during a demo++Reuse `AdomActivityPalette`, its branding and close behavior. The repo's+`demo/routing/live_panel.py` serves the shared activity-palette component and SSE+from the container; `prepare_live_panel.py` attaches it to the existing palette.+Show pad endpoints, measured planner output, primitive creation, copper read-back+and native DRC results as they occur. Do not claim every operation has a live UI+unless the caller actually publishes these events. A lost DOM acknowledgment+stops the demo before the next mutation; do not reopen a user-closed palette.++Fusion palettes can be owned popup windows omitted by parent-window capture.+Inspect the popup screenshots and capture its HWND separately if necessary.+Check that both windows are visible, unminimized and large enough before recording.+Preserve raw takes and record synchronization limits when composing two captures.++## Before the first trace: which manufacturer, and whose rules win++Ask the user which board house will build the board before routing anything, unless they+already said. Load that house's rules into the open board and read them back, then keep the+stricter of the rules and the electrical constraints the user states:++```jsonc+fusion_set_design_rules {"action": "list"} // the vendors and tiers the wiki page adom/pcb-design-rules carries+fusion_set_design_rules {"fab": "jlcpcb", "layers": "2"} // the user's answer; process defaults to standard+fusion_set_design_rules {"action": "export", "outputPath": "C:/Users/<you>/Documents/<task>/rules-loaded.edru"}+```++- Read the exported file and quote `mdWireWire` (copper clearance), `msWidth` (minimum width)+ and `msDrill` back to the user before routing; `fusion_alerts {sinceSec:60}` must be empty,+ a refused rule file is an in-canvas toast, not an error.+- Route with `clearance` and `width` no smaller than the loaded rules. A user constraint that+ is stricter (a wider power trace, a larger creepage gap, a keep-out) wins over the vendor+ minimum; the vendor minimum wins over a request to go below it. Say which one you applied.+- `fusion_set_design_rules {}` with no arguments loads the bundled Adom InstaPCB rules. The+ published BQ25792 demos ran on a DIAGNOSTIC copy of those rules (one inherited all-object+ same-net spacing rule disabled on disposable copies); they do not establish compliance with+ the unmodified InstaPCB profile, and neither does a clean `fusion_routing_drc` under any+ profile other than the one the user asked for.++## Checkpoints, and what a save hint is not++Every add-in reply from 1.10.0 carries `documentHygiene` (which open documents need saving)+and, when something does, `_hintDocumentHygiene`. The bridge never saves, closes or discards+on its own. Checkpoint with `fusion_export_eagle_source {outputPath}` (a `.brd` beside your+task folder) or `fusion_save_to_cloud` at milestones and before ending; verify the file exists+and re-read the hint, because an export leaves Fusion's own modified state as it was. Close+only the scratch document this task opened, by its exact name, with+`fusion_close_document {name, save:false}`, after the checkpoint is verified. Never bulk-close.++## Reproducing the published demos from the installed package++The installed package carries these verbs in the bridge runtime and the fixture, plans and+recorders under `demo/routing/` in the page source (`adom-wiki repo clone adom/fusion-bridge`).+`demo/routing/README.md` is the fixture walkthrough; `demo/routing/bq25792/` holds the BQ25792+plans, replay scripts and audits for the videos on adom/codex. `tools/install-routing-dev.ps1`+is a developer helper for hand-installing an exe over a dev-pinned cache; an installed release+never needs it. `demo/routing/bq25792/thermal-reroute/` (video 12) is in the page source since PR #8; its+native scripts need explicit FUSION_DEMO_TARGET, ADOM_API and FUSION_DEMO_OUTPUT, and the+README separates the accepted replay from rejected candidates. One thing is still not+installable: the shared EDA skillpack (adom/eda-engineering) is browseable source only. A+reproduction that needs it must say so.