← Commit history

Publish 1.6.52

John Lauer ·ad2e5a3b4d ·3mo ago ·parent be488a7
2 files changed +17−510
CHANGELOG.md+16−509
@@ -3,6 +3,18 @@ All notable changes to the Adom Desktop Fusion 360 bridge, newest first. Canonical: https://wiki.adom.inc/adom/adom-desktop-fusion-bridge · GitHub backup: `adom-inc/adom-desktop-fusion-bridge` +## 1.6.48-1.6.52 - 2026-07-06 (pkg hygiene, no runtime change)++- Declared the `adom/adom-desktop` pkg dependency (SDK two-artifact audit, #83).+- Trimmed the install tarball from ~1.18 MB to ~90 KB: dropped the 1 MB `hero.png` (a wiki+  billboard served from `/files`, not an install asset) and the publish-channel `PUBLISHING.md`.+- De-duplicated the library docs: `MAKING_LIBRARIES.md` / `LIBRARY_FINDINGS.md` had drifted root+  copies (broken relative image links) alongside the canonical `fusion-libraries` skill copies;+  removed the root copies. Moved `CREATING_BASIC_PARTS_LIBRARIES.md` into the `fusion-multipart-libraries`+  skill and fixed the cross-skill references.+- Split this changelog: recent versions ship in the tarball, older entries moved to+  `CHANGELOG_ARCHIVE.md` (kept on the wiki, not shipped).+ ## 1.6.47 - 2026-07-06  - **Tightened seat-dialog detection to DIALOG-SHAPED owned popups (fixes a false positive from@@ -115,513 +127,8 @@ Canonical: https://wiki.adom.inc/adom/adom-desktop-fusion-bridge · GitHub backu   auto-reclaims on it deterministically, and `fusion_readiness` reports `licensingDialog:true` with a   clear hint instead of a vague "add-in not responding" hang. -## 1.6.37 - 2026-07-06--- **`fusion_readiness` no longer lies `ready:true` for a stuck/dead Fusion** (John caught it). It only-  checked for the "Signing in" window when the add-in was silent - but a STALE add-in server from a-  just-killed instance keeps port 8774 answering, so `addin_ok` went True while the CURRENT Fusion sat-  stuck on "Signing in", and readiness reported ready. Now the Fusion-process window title is checked-  WHENEVER running (authoritative: "Signing in" == not ready), and `ready` additionally requires the-  add-in to actually RESPOND (a live main thread), not just the process to exist. Added a distinct-  "running but add-in not responding yet" hint so a half-launched Fusion is never mistaken for ready.-- **Proactive foreground-lock during launch = no more flicker.** The reactive minimize-guard alone-  left a visible flash (window appears, then shrinks). Now the launch raises the Windows-  foreground-lock timeout so Fusion's splash/main/seat windows are DENIED a foreground grab outright-  (taskbar flash, not a real steal), restored to the user's original value when the launch window ends.--## 1.6.36 - 2026-07-06--- **Codified the background-launch rules in the `fusion-bridge-dev` skill** (John's request): the-  ctypes handle-truncation gotcha (the silent killer behind 1.6.33/1.6.34), how to VERIFY the guard by-  objective `GetWindowPlacement().showCmd == 2` state rather than by eye, and that the guard only fires-  on a FRESH launch (kill first for a clean background state). Verified live on the laptop: a clean-  `fusion_start` leaves `Fusion360 showCmd=2` (minimized) - the window never sits in the foreground.--## 1.6.35 - 2026-07-06--- **Fixed the focus-guard doing NOTHING due to a ctypes handle-truncation bug** (the real reason-  1.6.33/1.6.34 still let windows steal focus, caught 2026-07-06). `user32.GetForegroundWindow()` was-  called with no `restype`, so ctypes defaulted the returned HWND to `c_int` and TRUNCATED it to 32-  bits on 64-bit Windows - `ShowWindowAsync` then got a garbage handle and silently no-op'd, so the-  guard never actually minimized anything and the user had to alt-tab back themselves. Now the guard-  sets proper `restype`/`argtypes` (HWND/DWORD/BOOL) so handles survive, and polls at 0.1s. Family-  windows that steal focus are now genuinely minimized within ~100ms.--## 1.6.34 - 2026-07-06--- **Focus-guard now covers the whole Autodesk launch FAMILY** (fix for the 1.6.33 guard, caught live).-  The guard only demoted `Fusion360.exe` windows, but the splash "Loading additional modules"-  (`FusionLauncher.exe`) and the "Signing in" / **"Active Sessions Exceeded"** dialogs-  (`AdskIdentityManager.exe`) slipped past and yanked the user's foreground. Now `_fusion_family_pids()`-  matches every family process image and the guard (150s) minimizes any of them that steals focus.-- **Seat conflict ("Active Sessions Exceeded") now AUTO-RECLAIMS the license instead of asking**-  (John: "just grab the license back... no harm, the user can reclaim on the other machine"). The-  dialog is a CEF modal that ignores background SendInput, so the launch handler frees the seat at the-  SOURCE via `_reclaim_seat_from_peers()` (cross-AD `fusion_stop` to peer ADs), kills the local instance-  stuck on the dialog, and relaunches clean - no conflict dialog, no user prompt, fully background.--## 1.6.33 - 2026-07-06--- **Fusion now launches in the BACKGROUND - never steals the user's foreground** (John's directive).-  The bridge runs on a machine the user is actively working on, and a bare `Popen([launcher])` opened-  Fusion's splash + main window in the foreground, yanking focus off their work. Now `ensure_fusion_-  running()` starts the launcher MINIMIZED + NOT ACTIVATED (`STARTUPINFO SW_SHOWMINNOACTIVE`) and fires-  a ~120s **focus-guard** daemon that minimizes (no-activate) *only* a Fusion window that is *currently*-  the foreground (focus-theft detected via `GetForegroundWindow` + PID match, so it never fights a user-  who deliberately opened Fusion). The add-in still loads fully while minimized. Foreground is now-  opt-in, only when a verb's job is to SHOW the user. Codified as a HARD invariant in the-  `fusion-bridge-dev` skill so every future window-opening path follows it.--## 1.6.32 - 2026-07-06--- **Fixed a false positive in 1.6.31's `updating` detection** (caught immediately on a real laptop-  during a regression pass). Fusion NEVER prunes old `webdeploy\production` builds, so a normal-  machine accumulates many stale ones (the laptop had 5, dating back to April, Fusion not even-  running) - and the bare "2+ builds" heuristic fired permanently, falsely telling callers "Fusion-  is auto-updating, restarting every 30-60s" when Fusion was simply closed. `fusion_update_in_progress()`-  now requires ACTIVE streaming: 2+ launcher builds AND at least one build dir modified in the last-  ~20 min. Stale leftovers no longer trigger it; the genuine mid-update flap still does.--## 1.6.31 - 2026-07-05--- **`fusion_readiness` now reports a distinct `updating:true` status when Fusion is applying an-  auto-update.** New `fusion_update_in_progress()` detects the tell-tale TWO+ webdeploy `production`-  builds coexisting; while that applies, Fusion crash-restarts itself every ~30-60s, so verbs-  intermittently saw a bare "not running" that read as a crash. Readiness now flags `updating:true`-  with a hint to poll/retry (it stabilizes once the update finishes) rather than treat the flap as-  fatal. Both hardening items came straight out of the fresh-VM battery.-- **Preference verbs (`fusion_set_preference`/`fusion_get_preferences`) retry once on a transient-  add-in connection error.** The first call can hit the add-in mid doc-transition (e.g. right after-  opening a Library, when the pref script must create a Design) and come back "not running" though-  Fusion is up; a ~1.5s retry clears it (seen live on the battery - failed first call, passed on-  retry). A genuinely-down Fusion just costs one extra 1.5s attempt.--## 1.6.30 - 2026-07-05--- **`fusion_install_fusion` and `fusion_start` now live-detect too** (completing the 1.6.29 fix). Both-  still trusted the stale bridge-start `fusion_info.installed` snapshot: on the fresh VM,-  `fusion_install_fusion` REFUSED with "already installed" though disk was `NO_WEBDEPLOY`, blocking the-  reinstall, and `fusion_start` would launch into the void. Both now call `detect_fusion()` for the-  on-disk truth; `fusion_start` also reassigns from it so a launch immediately after a fresh install-  uses a current `exe_path`. Found + fixed live during the fresh-VM battery.--## 1.6.29 - 2026-07-05--- **Fixed `fusion_readiness` trusting a stale install cache.** It read the bridge-START-  `fusion_info.installed` snapshot and only re-detected when that was False - so after Fusion was-  UNINSTALLED (or a VM reset wiped it) while the bridge kept running, readiness still reported-  `installed/running/ready:true` on a machine with `NO_WEBDEPLOY` on disk (found live during a-  fresh-VM validation on ADOMBASELINE). It now ALWAYS live-detects via `detect_fusion()` (a fast-  filesystem scan), so readiness reflects reality whether Fusion was just installed OR just removed.--## 1.6.28 - 2026-07-05--- **New `fusion_set_preference` + `fusion_get_preferences` verbs** - drive Fusion's appearance and-  navigation settings programmatically, applied LIVE (no restart). Server-only orchestrators (they-  compose an `adsk` preferences script and run it via the existing add-in `run_modeling_script`, so-  no add-in redeploy). Friendly keys: `theme` (light/darkblue/darkgray/classic/device/dark),-  `invertScrollZoom` (mouse scroll/zoom direction), `orbitScheme`-  (fusion360/alias/inventor/solidworks/tinkercad/powermill), `modelingOrientation` (yup/zup),-  `gestureNav`, `cameraPivot`, `lengthUnit` (mm/cm/m/in/ft, active design). Per-key outcome is-  reported in `applied` and the resulting state in `current`. Discovered via a live introspection of-  `app.preferences.generalPreferences` on ADOMBASELINE.-- **Note on theme availability:** not every Fusion build ships every theme. On the current webdeploy-  only **LightGray, DarkBlue, Device** were available (`Dark Gray theme not available` / `Classic-  theme not available` raise on assignment), so the verb tries candidates and reports per-key-  failures; `dark` resolves to Dark Gray then falls back to Dark Blue. Dark mode was set live on the-  VM's Fusion this way (Dark Blue).--## 1.6.27 - 2026-07-05--- **Fixed a false-positive in 1.6.26's new `needsSignin` readiness detection** (caught live before-  release to any consumer). 1.6.26 derived `needsSignin` from `classify_launch_dialogs()`, which-  enumerates ALL top-level windows and so matched a stray Edge **browser tab** titled "Sign in --  Autodesk" - reporting `needsSignin:true` while Fusion was actually signed in and drivable. Now the-  detection is scoped to the **Fusion-process window** (`get_fusion_window_info` title/`mainEnabled`)-  and is only evaluated when the **add-in isn't responding** (a responding add-in = past sign-in =-  drivable), so a leftover browser tab can never trigger it. Verified on ADOMBASELINE: signed-in-  Fusion now reports `ready:true`.--## 1.6.26 - 2026-07-05--- **Adopted AD 1.9.84's direct API (disc #78): the bridge now calls `notify_user` ITSELF, cross-AD.**-  New `ad_client.py` talks back to AD over `$ADOM_DIRECT_API_URL/command` with the-  `X-Adom-Bridge-Token` attribution header. It **capability-probes `GET /commands`** (not hardcoded)-  so it degrades gracefully on older AD, enumerates peer ADs via `targets`, and can route any verb to-  a peer with a cross-AD `target`. **Dropped the old "AD can't notify" workaround** (returning a-  `notifyUser` payload for the driving AI to relay). On a launch that surfaces a seat/licensing-  **DECISION** dialog (a true wall that can suspend/close Fusion on the user's OTHER machine), the-  bridge now fires `notify_user` directly with `reach_user=True` — fanning out to `"all"` peers when-  it may be running unattended on a VM, so the toast lands wherever the user is. Response carries-  `notifyDelivered`. Sign-in stays automate-first (NOT auto-notified).-- **Fixed `fusion_readiness` lying `ready:true` during sign-in.** Fusion can be running yet blocked by-  the first-run Autodesk sign-in modal (main UI disabled, add-in can't serve). Readiness now detects-  the `signin_required` window via the launch classifier and returns `ready:false` + `needsSignin:true`-  instead of "READY - drive Fusion" (which sent verbs into a wall). Found live on ADOMBASELINE.-- **Baked the PROVEN sign-in sequence into the `needsSignin` hint + `fusion-onboarding` skill**-  (validated live 2026-07-05): clear stale `signin.autodesk.com` tabs (expired codes = "Sign-in-  request expired") → "Retry browser sign-in" for one fresh request → click "Open Product" with-  **`desktop_click` (SendInput=isTrusted)**, NOT `desktop_ui_click` (UIA doesn't fire the protocol) →-  tick "Always allow" + "Open" on the in-page "open Autodesk Identity Manager?" overlay (not an owned-  popup) → poll readiness. Documents the `nbrowser`/CDP headless variant and the isTrusted requirement.--## 1.6.25 - 2026-07-04--- **Sign-in is now AUTOMATED-FIRST, with the path baked into the verb's `_hint` + a `notifyUser`-  payload (John's directive).** On `needsSignin`, `fusion_start` now tells the AI to: (1) check-  `nbrowser_readiness` and drive the Autodesk OAuth via the native-browser extension over CDP when-  it's on the same browser Fusion opened sign-in in (fast + headless - beats the ~2min request-  expiry that defeats background `desktop_ui_click`, the failure seen live on the VM drill); (2) else-  `desktop_ui_click` the Sign In / Open Product buttons FAST; (3) ONLY if both fail, relay the new-  structured `notifyUser:{title,body,level}` payload to `notify_user`. The goal is: automate-  everything, pull the user in (via a toast) only for a true wall - never auto-enter password/2FA.--## 1.6.24 - 2026-07-04--- **Two more launch dialogs are now classified IN CODE (caught live on the clean-VM drill):**-  "Fusion is already open / Multiple instances are not supported" (category `already_open` --  auto-dismissed via Cancel; a singleton is never double-launched) and the first-run Autodesk-  "Welcome to Fusion / Signing in" window (category `signin_required` - SURFACED, never auto-closed,-  with a `_hint` to notify + drive Sign In / Open Product without touching credentials). Added an-  explicit `AUTO_DISMISS_CATEGORIES` set so only benign acks get WM_CLOSE'd; decisions + sign-in are-  returned as `needsUserDecision`/`needsSignin`. Fixes a latent bug where sign-in would have been-  auto-closed.--## 1.6.23 - 2026-07-04--- **NEW `fusion_install_fusion` - install Fusion for the user with ZERO approval-gated shell.** The-  clean-VM drill showed every shell_execute step (download/spawn/tasklist) hits AD's "approve 1 hr"-  gate; bridge verbs run as trusted installed code and don't. The verb downloads Autodesk's official-  Client Downloader inside the bridge (urllib), is ELEVATION-AWARE (--globalinstall when admin,-  PER-USER otherwise - a non-elevated globalinstall dies silently on UAC, learned live), spawns it-  detached, and returns promptly. `fusion_readiness` now live-redetects and reports `installing:true`-  while the streamer runs. Declared as `detect.installVerb` (AD >=1.9.79) + in hostAppOptionalVerbs-  so it forwards on a Fusion-less box - completing the contract slot left empty in 1.6.22.--## 1.6.22 - 2026-07-04--- **Adopted AD 1.9.79's two new GENERIC bridge contracts** (previously Fusion-specific AD-core code):-  (1) `detect` gains `hostAppOptionalVerbs` (readiness/describe/get_app_state/status + the APS verbs --  all answer without Fusion running; AD now detects only INSTALLED, this bridge owns RUNNING and-  fast-fails `fusion_not_running` pre-add-in, no hang); (2) NEW `timeouts` block - per-verb HTTP-  budgets are now bridge-owned (AD's fallbacks + tuned values: build_library_3d 1800s,-  capture_library_views 600s, make_3d_package 200s, run_modeling_script 180s, generate_package 120s;-  `open*` prefix 150s). Timeouts stay NON-terminal ({stillRunning, statusVerb}). Docs note AD's-  not-installed errorCode is now generic `host_app_not_installed` (+hostApp field).--## 1.6.21 - 2026-07-04--- **Docs/skills audit (all three tiers).** USER skill: `fusion_generate_package` added to the core-  verbs table + a `bridge_restarting` cold-start row (AD >=1.9.77: poll `fusion_readiness`, never a-  not-installed signal; read-only verbs forward mid-respawn). DEV skill: deploy section rewritten for-  the FusionAddins reality (install to ALL dirs, never-ask-user-to-restart). README fully overhauled:-  11 capability sections incl. EPG package generation + markings, the architecture SVG, and the-  parent/child dialog breakthrough.--## 1.6.20 - 2026-07-04--- **The 10% marking margin is now ENFORCED by measurement, not estimated.** Fusion's text font runs-  wider than the 0.75h glyph estimate ('ADOM-A' rendered edge-to-edge - John caught it), so after-  placing the text the verb measures its REAL sketch bbox and shrink-to-fits if it busts the margin-  box (both axes; up to 2 passes). The manifest records `textWidthMeasuredMm` + `fitIterations`.--## 1.6.19 - 2026-07-04--- **Markings run along the LONGEST axis of the top face** (auto-rotated 90 deg when the long axis is-  sketch-y) - maximum room for the text (John's rule). **Multi-line markings** work: newline-joined-  text (MPN + variant) with per-line auto-fit (h = min(boxH/(1.35*lines), boxW/(0.75*maxChars))).-- **Sidecar manifest for marking refreshes:** with `outputStep`, `<step>.manifest.json` records every-  setting picked + WHY + the calculated bboxes (chip bbox, top-5% band, face extents, text box,-  height, rotation). To refresh a marking (e.g. add a variant on line 2), re-call the verb with the-  manifest's `type` + `paramsCm` (`unitsCm:true`) + the new etch text - deterministic generation-  reproduces placement exactly. Manifest also returned inline; `_hint` teaches the whole workflow.--## 1.6.18 - 2026-07-04--- **Chip markings are now READABLE: raised WHITE text by default (John's spec).** Humans need-  contrast - a dark-on-dark emboss is invisible - so `fusion_generate_package` now marks chips with a-  thin POSITIVE extrude painted white (silkscreen-style, via EPG's own rgb-appearance utility; white-  survives into the colored STEP). `etchStyle:"engraved"` keeps the sunken laser cut.-- **Top-surface finding is now the bbox-band algorithm (in CODE, not just the skill):** whole-chip-  bounding box -> only upward planar faces in the TOP 5% height band -> largest area wins -> text-  laid out with a 10% margin inside that face. The verb's `_hint` teaches all of this + per-family-  param names on every call; the fusion-build-parts-library skill gained a "creating chips" section.--## 1.6.16 - 2026-07-04--- (1.6.17) Etch auto-fit measures the face in SKETCH space (model-bbox axes can be swapped vs the-  text's baseline axis) + a 0.75h glyph width - 'LM358' now fits fully on a SOIC-8 top.-- `fusion_generate_package` etch auto-fit is now WIDTH-aware: text height is capped by box-width /-  char-count (a glyph is ~0.62h wide), so a 5-char MPN like 'LM358' fits instead of cropping-  (height-only fit rendered 'M35' on a SOIC-8 - caught on the live verify).--## 1.6.15 - 2026-07-03--- **NEW `fusion_generate_package` - parametric IPC packages from Fusion's BUILT-IN-  ElectronicsPackageGenerator, with laser-etched markings, in one headless call.** Give it a `type`-  (~50 EPG families: chip/soic/qfn/qfp/bga/sot23/dfn/melf/ecap/crystal/headers/...) + `params` (mm,-  auto-converted to EPG's cm) and it drives EPG's generator modules directly (no GUI), optionally-  **laser-etches** a marking (`etch:"103"` / an MPN) into the body top as REAL cut geometry, and-  exports STEP (`outputStep`) - the etch survives into the STEP for KiCad. Proven live on a fresh VM:-  0603 + '103' etch + valid 233KB STEP (121 faces) in ~2s. EPG is located dynamically across-  webdeploy hashes + install roots (never hardcoded); missing EPG returns `errorCode:epg_not_found`.-  Etch targets the LARGEST body's top face (terminals tie the molded body on max-Z - learned live).-  This is the royalty-free path to whole component libraries: our own generated output, not-  license-restricted vendor models.--## 1.6.14 - 2026-07-03--- **#63 ROOT-CAUSED + FIXED: Fusion MOVED its add-in directory; we now install to ALL of them.**-  2025+ Fusion scans `%APPDATA%\Autodesk\FusionAddins\` and SILENTLY ignores the legacy-  `Autodesk Fusion[ 360]\API\AddIns\` dirs (proven live on a fresh install: add-in in the legacy dir-  never loaded through a full launch; moved to FusionAddins it came up in 20s, runOnStartup honored,-  zero manual enabling). `install_addin.py` now installs/uninstalls to EVERY known location-  (TARGET_CANDIDATES, newest first), `fusion_detect` scans all of them, and the add-in-not-responding-  errors carry the FusionAddins explanation + a stable `errorCode`.-- **⛔ NEVER ask the user to restart Fusion / enable the add-in - baked into code + skills.** Every-  hint that said "restart Fusion 360" / "enable via UTILITIES > ADD-INS" now instructs the AI to DO-  IT ITSELF (`fusion_stop` + `fusion_start`); the USER skill (convention 6), fusion-onboarding, and-  CLAUDE.md all carry the rule. Doing the work for the user is the point of the bridge.--## 1.6.13 - 2026-07-03--- **`bridge.json` dependencies described honestly.** Dropped `fusion360: ">=2.0.0"` - Fusion 360 is-  the HOST APP (already declared in the `detect` block, and it uses date/webdeploy versions, not a-  ">=2.0.0" semver), not a package dependency. Corrected the stale `python: ">=3.11"` to `>=3.10`-  (the real floor - the code uses 3.10 `X | None` unions; AD provisions + pins Python 3.12.13). The-  user-facing wiki Dependencies tab stays empty, which is correct: this bridge has no external-  wiki-package deps (the add-in is bundled, the APS layer is in-repo).--## 1.6.12 - 2026-07-03--- **Launch now WATCHES for licensing/launch dialogs in CODE (not just a skill), found live on the-  ADOMBASELINE first-run test.** `_handle_launch` enumerates ALL top-level windows the instant the-  Fusion process is up and classifies the dialogs that block a first launch but are owned by the-  Autodesk FAMILY (AdskIdentityManager / FusionLauncher), so the Fusion-scoped classifier misses-  them: **"Active Sessions Exceeded"** + **"Suspend Remote Session"** (seat conflict) and **"Error-  Launching Streamed Application / missing or incomplete / re-install"** (an incomplete webdeploy-  folder). Benign launch-error acks are **auto-dismissed** (WM_CLOSE, background). A seat-conflict is-  a **DECISION** dialog: the bridge returns `needsUserDecision:true` + `setupDialogs[]` + a `_hint`-  that says fire a `notify_user` and ASK the user which option to take (the options-  suspend/shut-down Fusion on their OTHER machine) - it NEVER auto-picks. New helpers in-  `dialog_classify.py`: `classify_launch_dialogs`, `close_dialog_bg`, `DECISION_CATEGORIES`.--## 1.6.11 - 2026-07-03--- **Detect a system-wide (`--globalinstall`) Fusion, not just per-user (fixes a broken onboarding-  loop, found on the ADOMBASELINE fresh-VM test).** The fusion-onboarding skill installs Fusion with-  `--globalinstall`, which lands the launcher under `%ProgramFiles%\Autodesk\webdeploy\production\`,-  but detection (both `fusion_detect.py` and the `bridge.json` `detect` block) only checked-  `%LOCALAPPDATA%`. So an AI-installed Fusion was INVISIBLE - onboarding "succeeded" yet the bridge +-  AD `bridge_readiness` still reported `no-app`. Detection now scans `%LOCALAPPDATA%`, `%ProgramFiles%`,-  `%ProgramFiles(x86)%` (and `%ProgramW6432%`), preferring a complete install (has `.ini`) + newest.-- **Notify the user on EVERY active step.** Per the "the AI does everything, but pull the user in when-  only they can act" rule: the USER skill's convention 4 and fusion-onboarding now mandate an AD-  `notify_user` toast the instant the user must do something (Autodesk sign-in, 2FA, a UAC/elevation-  prompt, license acceptance), and a progress toast for long installs - never silently wait on a-  screen they aren't watching.--## 1.6.10 - 2026-07-03--- **"Fusion not installed" hints now honor the SDK Tier-2 cardinal rule (found on a fresh-AD test).**-  Testing a first-time run on a clean AD 1.9.74 VM (ADOMBASELINE, no Fusion) showed the bridge's-  not-installed hints said "Fusion cannot be installed programmatically... ask the user to install it-  from autodesk.com... then retry" - a breach of the rule that the AI must OFFER to install the host-  app itself and NEVER tell the user to do it manually. All 4 not-installed hints (+ the `/status`-  tooltip) now offer AI-driven install via the `fusion-onboarding` skill (silent-install + Autodesk-  sign-in). Note: the correct probe for a "what EDA tools are installed" sweep is AD's-  `bridge_readiness` (side-effect-free aggregate with `edaToolsInstalled` + per-bridge `state:no-app`);-  verified it reports Fusion cleanly on the fresh VM via this bridge's `detect` block.--## 1.6.9 - 2026-06-30--- **`fusion_start` no longer dead-ends on a slow first launch (fixes #63, Arav's blocker 1).** A first-  launch (fresh install: component downloads/updates/cloud sync) can take 2-4 min, far past AD's ~60s-  relay request cap - so `{"timeout":300}` could never win and the call looked like a hard failure.-  Now the launch confirms the Fusion process, then waits for the add-in only within a budget that-  stays UNDER the relay cap; if the add-in isn't up yet it returns `{success:true, stillLaunching:true,-  statusVerb:"fusion_readiness"}` with a `_hint` to POLL `fusion_readiness` until `ready:true` (never-  re-call `fusion_start`). Fast/normal launches still return "launched successfully" as before. The-  USER-skill cold-start table gained a `stillLaunching` row.--## 1.6.8 - 2026-06-30--- **Stale add-in is no longer a SILENT failure (fixes #55, Drew's report).** The add-in now REPORTS-  its version (`AdomBridge.manifest` → `/health` + `/status`), and the bridge compares it to the-  version it bundles. `fusion_readiness` and `fusion_addin_status` now return `addinVersion` /-  `expectedAddinVersion` / `addinStale` (+ a re-sync `_hint`), and any add-in command the running-  add-in is too old to know (e.g. `open_by_urn`, which silently broke `fusion_aps_open` for Drew) now-  comes back with `errorCode:"addin_stale"` and the exact fix (`fusion_stop` then `fusion_start` to-  re-sync from cache with Fusion closed). Add-in manifest bumped 1.0.2 → 1.0.3.-- **Bridge-SDK re-audit against the updated SDK.** (1) `bridge.json` `verbs[]` re-synced to the-  authoritative `fusion_describe` catalog (was stale: 40 → 53 verbs; added the library/3D + board +-  app-state verbs; `statusVerb` `fusion_get_app_state` is now listed; dropped the dead-  `fusion_apply_instapcb_rules`). (2) The USER skill's cold-start section now encodes all **8** SDK-  conventions (was 5), led by an `errorCode` response→meaning→action table (incl. the new-  `addin_stale` row) and the reuse-don't-relaunch + surface-`_hint`-verbatim conventions.--## 1.6.7 - 2026-06-30--- **AD 1.9.63 alignment (discussion #57).** (1) The bridge HTTP server now honors **`ADOM_BIND_HOST`**-  (`os.environ.get("ADOM_BIND_HOST", "127.0.0.1")`) instead of a hardcoded host, so it never binds a-  public interface and never trips the Windows Firewall "allow access?" prompt AD guarantees users-  won't see. (2) Docs/skills updated to the new **runtime-provisioning** reality: AD provisions Python-  itself (system if on PATH, else a portable no-UAC python-build-standalone copy pinned to 3.12.13,-  spawned by absolute path) - the bridge must **never** bootstrap/download its own Python; state is-  checkable via AD's new `runtimes` verb. No self-bootstrap code existed to remove; only the-  "auto-installs Python" wording in SKILL.md / fusion-onboarding / CLAUDE.md was corrected.--## 1.6.6 - 2026-06-30--- **Bridge-SDK self-audit pass.** bridge.json: `homepage` now points to the wiki page (was github - a-  stale default); removed the redundant top-level `healthEndpoint` (it lives inside `spawn`); added-  `spawn.persistent` + an explicit `prewarm: {assets: []}` (Fusion is a detected HOST APP + AD-  auto-installs Python, so nothing to prewarm). `discovery_triggers` rewritten to 16 everyday-  user-task phrasings (dropped verb-name/internal jargon) + a `discovery_pitch`. The USER skill now-  opens with a cold-start "read before you panic" + `fusion_readiness` pointer. `fusion-bridge-dev`-  (a dev skill) is no longer shipped in the user skills pkg (source-only).--## 1.6.5 - 2026-06-30--- **Host-app DETECTION declared (AD >=1.9.47).** bridge.json gains a `detect` block-  (`hostApp: "Fusion 360"`, Windows `%LOCALAPPDATA%\Autodesk\webdeploy\production\*\FusionLauncher.exe`-  mirroring `fusion_detect.py`, macOS `/Applications/Autodesk Fusion[ 360].app`) so AD DETECTS Fusion-  (the user's host app) instead of trying to install it. The status path fast-fails cleanly when-  Fusion isn't running.-- **NEW `fusion_readiness` verb** - a fast `{installed, running, ready, hostApp, bridgeVersion}` check-  that never launches Fusion; the `fusion-onboarding` skill now opens with it (and AD's-  `bridge_readiness`). CLAUDE.md notes AD now auto-installs Python in the background, so the deploy-  trap's spawn case is handled by AD.--## 1.6.4 - 2026-06-29--- **Folder hygiene, part 2: `make_3d_package` no longer saveAs-es to the project ROOT either.** v1.6.3-  fixed the upload target but the f3d `saveAs` still landed in the shared root - now it saves into-  `Adom AI Workspace/<task>` (found/created in the active project), so a build leaves ZERO loose files-  in root.-- **Dialogs are dismissed in the BACKGROUND now (no focus steal).** New `_dismiss_dialogs_bg` uses-  `close_window` (WM_CLOSE via PostMessage = Cancel/No), NEVER `send_key`/Escape (which calls-  SetForegroundWindow and yanks Fusion to the foreground). `fusion_capture_library_views` now-  auto-dismisses the "Create new symbol/footprint '<name>'?" prompt that pops when a DEVICESET name is-  passed to `.sym`/`.pac` in a shared-footprint library (the symbol/package is named by the combo, e.g.-  `R-0603`, not `R-0603-10K`) - and its `_hint` + the `fusion-driving` skill now teach the right names-  + the background-dismiss rule.--## 1.6.3 - 2026-06-29--- **Cloud folder hygiene - the bridge NEVER writes loose files to a project ROOT anymore.** Root cause-  of a real incident: `fusion_make_3d_package` defaulted its upload to the shared Adom project ROOT, so-  a big build dumped 100+ loose f3d files into the team's root and colleagues complained. Now uploads-  default to an AI-owned **`Adom AI Workspace`** folder with a **per-task subfolder**-  (`build_library_3d` derives the task from the .lbr name), and `fusion_aps_upload` **REFUSES** a known-  root folderId (`errorCode: refused_root_upload`). New **`fusion-cloud-hygiene`** skill.-- **NEW `fusion_cleanup_cloud_files`** - precisely delete a list of cloud files **by lineage urn** (not-  by name), so cleaning up AI clutter can't touch a teammate's file in a shared folder. The add-in-  delete gained a `fileId`/`lineageUrn` exact-match path.--## 1.6.2 - 2026-06-29--- **`fusion_capture_library_views` settle fix.** It fired the screenshot ~0.4s after `EDIT`, before-  the editor actually switched - so a shot could capture the PREVIOUS part (a mislabeled view). Now it-  waits a tunable **`settle`** (default 1.5s) after each `EDIT` before framing + capturing, so the shot-  matches its label.-- **Skill: the SHARED-FOOTPRINT pattern for whole-catalog libraries.** `fusion-multipart-libraries`-  now documents how a 138-part library is really 10 footprints + 138 devicesets: collapse the catalog-  to its unique `(type, package)` combos, `fusion_build_library_3d` the ~10 bases (10 uploads, not-  138), then clone each base deviceset per value (sharing its symbol + package + 3D binding). Proven-  by building the entire Adom basic parts library (138 parts, all Mapped + rendering).--## 1.6.1 - 2026-06-29--- **NEW `fusion_capture_library_views` - the views EEs actually trust.** Given a list of packages-  (and the .lbr open), it runs `EDIT <deviceset>.sym/.pac/.dev` + `WINDOW FIT` + a background-  screenshot and returns, per part: the **SYMBOL** (full pinout), the **FOOTPRINT** (pad array +-  Copper/Silkscreen/Mask layer stack), and the **COMPONENT** view (Content Manager: symbol + the-  package table with the footprint<->package **Mapped ✓** + pin/pad counts). The 3D before/after-  shots never showed these.-- **`_inject_package3d_bindings` is now MERGE-AWARE + idempotent.** It reads bindings already in the-  .lbr and accumulates the new ones (new wins), so re-running `fusion_build_library_3d` for just the-  parts that failed NO LONGER wipes the parts that already succeeded (the "a subset re-run dropped my-  earlier bindings" trap). `fusion_build_library_3d` now reads its own `outLbrPath` when re-run, each-  part **self-retries once** on a transient first-part failure, and its `_hint` documents the-  **relay-timeout reality** (a many-part run exceeds the ~60s relay request timeout but keeps running-  server-side - verify by the bound .lbr + the PNGs, then re-run any missing parts).--## 1.6.0 - 2026-06-29--- **NEW `fusion_build_library_3d` - build a whole RENDERING multi-part 3D library in ONE call.** Give-  it the combined `.lbr` + a `parts[]` list (`{package, lbrPath, modelPath}`); for each part it makes-  the footprint+chip f3d package (no GUI dialogs), collects the `wip_urn`, then **injects ALL bindings-  in one pass** (`_inject_package3d_bindings` - the EAGLE `<packages3d>` + per-device-  `<package3dinstances>` surgery the AI used to hand-write) and opens the finished library once.-  Returns per-part urns + a `screenshots[]` of every before/after. Each part is independent, so a-  Fusion reset mid-run just means re-running the failed parts.-- **`fusion_make_3d_package` got two upgrades:** (1) `projectId`/`folderId` are now **optional** --  they default to the MAIN-project upload folder (`_discover_upload_target`), so the AI no longer has-  to `fusion_aps_browse` for them; (2) pass **`captureLabel`** to auto-capture a **BEFORE** (the-  footprint in the 3D viewer) and **AFTER** (the chip placed flat on its pads) hwnd-targeted-  background screenshot, returned as `before`/`after`. A viewport `fit()` frames each shot.-- Both verbs added to `fusion_describe` (the Verbs tab) and gated as Fusion-required.--## 1.5.13 - 2026-06-29--- **Rich teaching hints on `fusion_make_3d_package`:** its `_hint` now spells out NEXT step (the exact-  binding markup), what to EXPECT (check_dialogs==0, footprint+chip preview, pad alignment), the-  SPEEDUP (batch per part -> hand-merge all -> open once), and the PITFALLS (needs Fusion running; a-  raw STEP renders nothing; never FINISH the Package3D generator). Skill gained a matching-  "Speedups + what to expect" section.--## 1.5.12 - 2026-06-29--- **`fusion_make_3d_package` now produces a PROPER component package (footprint + chip).** It opens the-  lbr and runs `Electron.Create3DPackage` to load the package's FOOTPRINT into the generator, imports-  the chip ONTO it, orients flat, and `saveAs` an f3d - so the 3D model contains the footprint-  (pads + courtyard) AND the chip, merged and **aligned** (the chip's pads land on the footprint pads-  in the 3D viewer, which is the whole point of that viewer). The 1.5.11 verb imported into an empty-  Design, giving a chip with NO footprint. New required arg: **`lbrPath`**. Proven on the full 10-part-  library (`AdomBasicParts3D_v2`).-- `fusion-multipart-libraries` skill updated to the footprint-aware recipe.--## 1.5.11 - 2026-06-29--- **NEW `fusion_make_3d_package` verb - a RENDERING per-package 3D model with ZERO GUI dialogs.** It-  imports a STEP into a throwaway Design, orients it flat, saves an `.f3d`, uploads it via APS, and-  returns a `fs.file:vf` `wip_urn` to hand-write into a library's `<packages3d>`. This is the-  dialog-free replacement for the Create3DPackage generator (whose FINISH is trapped behind two-  unbeatable "Fusion360" CEF modals). **Proven on a full 10-part Adom basic-parts library-  (R/C/L/LED/nRF54L15) - every package renders its real chip, flat on its footprint.**-- **`fusion-multipart-libraries` skill rewritten as SOLVED** - the f3d recipe end to end + the key-  gotcha (a *raw STEP* upload binds but does NOT render: "Thumbnail download failed"; an *f3d* renders)-  + the GUI-generator dead end to avoid.-- New skills **`fusion-driving`** (read the dialog/owned-popup array after every mutating op; never-  fullscreen-capture) and **`fusion-cloud-save`** (Hub-upload / saveAs discipline); `fusion-libraries`-  cross-linked to both.-- README + SKILL now link the component-library docs (the skills + `CREATING_BASIC_PARTS_LIBRARIES.md`).--## 1.5.10 - 2026-06-29--- Dialog-capture false-positive fix: a docked panel (Browser/Timeline) shares the "Fusion360" title-  but does NOT disable the main window, so a generic-titled candidate is now only surfaced when the-  main window is actually disabled (a real modal is up). Stops the auto dialog-capture crying wolf.--## 1.5.9 - 2026-06-28--- **Auto dialog-array capture after every mutating `fusion_*` verb:** enumerates + screenshots any-  owned popup / modal by hwnd (background, never fullscreen) and returns it plus an "analyze this-  before proceeding" hint, so the AI cannot fly blind past a Save / "are you sure you want to close" /-  recovery dialog.-- **NEW `fusion_check_dialogs` verb** - poll the current dialog/owned-popup array on demand.-- Dialog classifier: new rules for the Hub upload-in-progress ("packages are being uploaded... lose-  these changes") and "save was cancelled / cannot be saved while packages are being uploaded" modals;-  the generic/unknown fallback no longer says "dismiss" (which could click Yes on a data-loss confirm).--## 1.5.8 - 2026-06-28--- `bridge.json`: added `updateManifestUrl` (+ `healthEndpoint`) so Adom Desktop auto-update works (it-  was null, which broke auto-update - discussion #31).--## 1.5.7 and earlier+## Older versions -- `fusion_attach_3d_package` (GUI Package3D generator flow - superseded for multi-part work by-  `fusion_make_3d_package`), APS fast cloud search, the Electronics workflow verbs, and exports. See-  the git history on the wiki page.+Entries for **1.6.37 and earlier** live in [`CHANGELOG_ARCHIVE.md`](https://wiki.adom.inc/adom/adom-desktop-fusion-bridge) (full history,+kept on the wiki page's Files tab, not shipped in the install tarball). The per-release changelog+for every version is also on the page's **Releases** tab.
page.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-desktop-fusion-bridge",-  "version": "1.6.51",+  "version": "1.6.52",   "type": "app",   "description": "Drive Autodesk Fusion 360 from the cloud via Adom Desktop: 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 with browse/recent/versions, cloud download/upload and folder creation, and in-app parametric modeling. Never-charge: APS calls are capped to the free tier.",   "dependencies": {