Changelog

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.58 - 2026-07-08

  • Long cloud ops now SURVIVE AD's 60s relay cap (John: "get all 4 pins perfect" + "update your code with your learnings"). fusion_build_library_3d cloud Package3D + Hub upload takes MINUTES, but the relay hard-caps requests at ~60s and timeoutSeconds is ignored - so the synchronous build got its thread killed at 60s, wrote no bound .lbr, and lost every wip_urn (a demo board's 4th pin came back a flat pad). It now runs DETACHED (async default true) + is POLLABLE: returns immediately, keeps building in a daemon thread, writes the bound .lbr when done; caller polls it for one <package3d wip_urn=urn:...> per part. async:false for fast machines.
  • Background, no-dialog EAGLE board import documented + steered to. For a .brd with placed <elements>, fusion_open_board (newDesignFromLocal) instantiates them with ZERO modal dialogs / ZERO foreground - vs fusion_new_electronics_from_eagle's ImportSCHAndBRDCmd, which pops two Open dialogs that STEAL focus. The import verb no longer dead-ends when the AD direct API is absent; it points to fusion_open_board. NEW: embed <packages3d> + a per-<element> package3d_urn in the .brd to get REAL 3D component bodies on the board (Fusion resolves the Hub urns) - documented in the verb docstring.
  • Fixed the HWND-truncation window-finder bug (cost hours). handlers/fusion_ui.py declared NO ctypes argtypes, so 64-bit HWND handles truncated to 32-bit c_int - _find_fusion_hwnd's GetWindowTextW/IsWindowVisible ran on garbage handles and matched nothing, so get_fusion_window_info returned mainHwnd:None even though Fusion's window plainly existed, blinding all background driving. Declared HWND argtypes/restypes for the window funcs so the full handle marshals.

1.6.57 - 2026-07-08

  • APS sign-in now REMEMBERS the browser+profile that authed to Autodesk and reuses it, instead of firing webbrowser.open at the OS default (John: "power users have tons of browsers with tons of profiles ... cache what browser you used when you successfully logged in ... don't be lazy"). The old code blindly opened the OS default browser, which on a multi-browser box is usually the wrong one (no warm Autodesk/SSO session / wrong profile) and forces a needless fresh login. Now start_signin: (1) launches a browser+profile passed in the call, else (2) the REMEMBERED one (~/.adom/fusion-aps/signin-browser.json) via a real --profile-directory/--new-window launch, else (3) opens NOTHING and returns needsExtensionOpen:true so the caller drives authUrl in the user's real browser via nbrowser_open_window (new window) — the OS default is only used when the caller explicitly passes allowDefaultBrowser:true. New verbs fusion_aps_set_browser / fusion_aps_get_browser / fusion_aps_forget_browser persist the choice across sessions.
  • Notify-before-foreground, baked into code (John: "if you have no other choice than to foreground, let me know with an ad notify ... do this via code"). SendInput key/click paths need Fusion in the FOREGROUND, which steals the user's focus mid-work. _notify_before_foreground() now fires an AD notify (reach_user, debounced to one per 45s burst) BEFORE fusion_send_key / fusion_click_fusion foreground Fusion, telling the user WHY, reminding that Adom ALWAYS drives in the background and only foregrounds as a last resort, and ribbing Fusion for not being AI-native enough to allow background driving (hoping Autodesk makes it fully AI-drivable soon). Prefer the background path first (e.g. fusion_open_board's dialog-free newDesignFromLocal, desktop_ui_*, WM_CLOSE).

1.6.55 - 2026-07-07

  • Universal error-dialog guard, baked into every mutating/open verb (John: "you have to screenshot to get the parent/child array to constantly look for errors ... bake this into every command"). A malformed .lbr makes Fusion pop an owned "Error" dialog (".lbr has errors and cannot be opened") while Document.newDesignFromLocal still returns ok (it opened an EMPTY design behind the error), so open_lbr reported success on a library that never loaded. New operation_error dialog classification (title "Error" / "cannot be opened" / "has errors") + a shared _apply_failure_dialogs() now runs after every open/mutating verb: it screenshots the owned popup (hwnd-targeted, background), flips the result to success:false + errorCode:fusion_operation_error with the exact resolution, attaches the shot to data.errorDialog, and dismisses the pure-ack popup so it can't wedge the next command. A failed op can no longer be returned as success.

1.6.54 - 2026-07-07

  • Fixed 3D auto-orient laying TALL through-hole parts on their side (John caught it: a machine pin's 3D came in horizontal). make_3d_package / attach_3d_package / build_library_3d always rotated the SMALLEST bbox dim to Z (correct for a flat SMD chip, wrong for a tall pin whose long axis is already Z). Now a tall-part guard keeps a part vertical when its largest dimension is already Z, and only flattens a clearly-thin part whose thin axis isn't Z yet. Verified: machine pins stay vertical, a flat 0603 stays flat, a chip imported on its edge still gets flattened.
  • attach_3d_package and build_library_3d parts[] now honor an orient flag (default true) so a caller can skip auto-orient for an already-correctly-oriented STEP.

1.6.53 - 2026-07-07

  • Fixed slow-machine opens being mislabeled "add-in not running" (caught live on a GPU-less Azure VM). _orchestrate_open_lbr's Document.newDesignFromLocal call had a fixed 30s read timeout; on software-rendered machines the open takes 60s+, so the proxy timed out and the canned error claimed the ADD-IN was down while the document was actually opening fine - fusion_build_library_3d then aborted every part on a lie. Now: 120s timeout AND on any failure the open is VERIFIED BY STATE (poll get_app_state for the expected document) before failing - the doc actually being open outranks the synchronous return.
  • NEW verb fusion_notify_owner - deterministic last-resort human escalation (John's rule). Toasts the user's MAIN computer by fanning out cross-AD to every relay peer, so a bridge on an unattended VM still reaches them. For true human walls only (password/2FA, UAC); hints tell the driving AI to exhaust programmatic options first and not to re-toast.
  • Hints now teach the parent/child screenshot discipline: never poll blind, never fullscreen - desktop_screenshot_window returns a screenshots[] array where every OWNED POPUP rides back as its own child shot; launch/sign-in hints now say to READ those.

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 1.6.46). 1.6.46 matched any owned popup wider than 300px, but Fusion's own side panels (Data Panel / browser rail, ~300x785) are owned popups too - so the moment a document was open, find_licensing_dialog() flagged a drivable Fusion as "blocked by a seat dialog" and readiness reported ready:false forever (caught live on winvm: get_app_state succeeded while readiness lied). The seat modal is always WIDE (823x262 / 1235x527); side panels are narrow. Detection now requires width >= 480, so the panels are excluded and the real dialog still matches.

1.6.46 - 2026-07-06

  • Fixed the seat/licensing dialog going UNDETECTED (John caught it live on winvm). The "Suspend Remote Session" seat-confirm variant is only 823x262, but find_licensing_dialog() required height 320-820, so it silently slipped through - readiness reported licensingDialog gone while the dialog sat there blocking the whole launch. Root cause: detecting a modal by a fragile SIZE window. Now detected DETERMINISTICALLY by the owned-popup signal: a seat/sign-in modal is always an OWNED POPUP of the main Fusion window (the splash/main app never are), found via GetWindow(GW_OWNER) in family_windows(). Size is only a fallback.
  • Resolution is now SCREENSHOT-VERIFIED, not heuristic-verified. _resolve_seat_dialog() clicks 'Continue' (background UIA) then confirms the dialog truly cleared by reading the parent window's ownedPopupCount via desktop_screenshot_window (parent/child screenshotting) - instead of trusting the same size filter that had false-'resolved' it. This is the check that would have caught the earlier "I solved it" that hadn't.
  • Closed the auto-resolve GAP. The launch loop only auto-resolved the seat dialog during its ~50s window. But the dialog also appears LATER (minutes post-sign-in, when the license server notices too many sessions), long after that loop exited. fusion_readiness now SELF-HEALS: whenever it detects the dialog it auto-resolves it in the background and re-probes - so the seat is handled in CODE no matter when it shows up, and the AI never has to notice or act.
  • ctypes GetWindow given explicit restype/argtypes (HWND) to avoid 64-bit handle truncation.

1.6.45 - 2026-07-06

  • Add-in changes now AUTO-DEPLOY - the bridge no longer only installs the add-in when it's MISSING. Startup guarded install_addin() behind if not addin_installed, so a STALE add-in was never UPDATED: any add-in fix (e.g. the 1.6.44 get_parameters fix) failed to reach users who already had a copy - it silently kept running the old add-in. Now the bridge ALWAYS syncs on startup (idempotent - copies only changed files; safe while Fusion is up, lands on the next respawn with Fusion closed). This is a real distribution bug - without it, none of our add-in fixes shipped to existing installs.

1.6.44 - 2026-07-06 (add-in 1.0.4)

  • Fixed fusion_get_parameters crashing on non-numeric parameters (found during the laptop verb battery). Parameter.value throws "Parameter is not numeric type" for string/text params, which blew up the entire enumeration. Every field is now read defensively so one odd parameter never kills the call. Add-in bumped to 1.0.4.

1.6.43 - 2026-07-06

  • Docs + hints caught up to the real (UIA) seat-dialog handling. The fusion-bridge-dev skill now records the hard facts: it's a QT dialog (not CEF), titled just "Fusion360", its "Continue" button is UIA-invokable in the BACKGROUND, the radios are NOT in the a11y tree, kill+relaunch never frees a server-held seat (dead code), retry-until-verified-gone, and the seat check outranks a stale add-in port. Response hints now NARRATE what the bridge is doing + what happens next: fusion_start says it launched in the background (don't foreground), whether it auto-resolved a seat dialog, and to poll fusion_readiness; the readiness licensingDialog hint describes the UIA auto-resolve (not the old "free it from peer machines" text).

1.6.42 - 2026-07-06

  • Seat-resolve now RETRIES until the dialog is verified gone, and takes priority over a stale add-in port (the bug that made 1.6.40 look solved when it wasn't - John caught it live). Two fixes: (1) the first UIA Continue Invoke on a mid-render dialog silently NO-OPs, so the launch loop now re-invokes every tick until find_licensing_dialog no longer sees it, instead of clicking once; (2) the loop and fusion_readiness no longer trust the add-in probe while the seat dialog is up - a STALE add-in server from a prior killed instance keeps port 8774 answering, which made the loop break early and readiness report licensingDialog:false/ready:* while the dialog sat right there on screen. Seat dialog now blocks ready whenever detected. Verified: full verb battery passes on the laptop (modeling, EPG+etch->STEP 234KB, export 234KB, dark mode) once the seat dialog is auto-cleared.

1.6.41 - 2026-07-06

  • Instant-minimize: disable the minimize ANIMATION during launch so the focus-guard's minimize is a single-frame vanish, not the visible slide-down that read as a 'flash' (John). Combined with the 1.6.40 seat auto-resolve (no more stuck sign-in retry loop = no repeated foregrounding) and the foreground-lock, a background launch should now be imperceptible. SPI_SETANIMATION off during the guard window, restored to the user's original value when it ends. (Chosen over virtual-desktop isolation, which proved un-shippable: Win11 virtual-desktop control is undocumented, per-build, and the driver won't even install cleanly - it would make the bridge brittle across Windows updates.)

1.6.40 - 2026-07-06

  • THE seat-dialog fix: fusion_start now auto-resolves "Active Sessions Exceeded" via UIA in the BACKGROUND (John pushed me back to UIA - it was the answer). The launch handler is now a deterministic state loop: poll the add-in round-trip (ground truth for drivable) while, each tick, detecting the seat dialog (find_licensing_dialog, by process+size) and invoking its native 'Continue' button with desktop_ui_click via the AD direct API - which UIA-Invokes it WITHOUT foregrounding (proven: "Clicked in the BACKGROUND - the window did NOT come to the foreground"). Suspend is pre-selected, so Continue grabs the license. This un-sticks the launch, which is what caused the endless foreground-stealing: a blocked seat dialog made Fusion retry sign-in in a loop, foregrounding every retry. No more kill+relaunch (the licensing server keeps the seat anyway) and no notify/punt to the user.

1.6.39 - 2026-07-06

  • Dev skill: added THE CORE GOAL (John) - the entire reason this bridge exists is for the AI to run EVERYTHING so the user never does anything manual. Never ask the user to click/close/sign-in; the only acceptable walls are UAC/elevation and a password/2FA we must not enter. Any flow that still needs the user is the next bug to fix in the bridge, not the user's job. Reinforces detecting
    • handling state deterministically in code, not via the AI following skills.

1.6.38 - 2026-07-06

  • Deterministic, process-based detection of the seat/licensing dialog (John: track state in CODE, not via the AI following skills). The "Active Sessions Exceeded" dialog's window TITLE is literally just "Fusion360" (the text is CEF body content), so the title-based classifier never caught it - it silently blocked Fusion's main thread for a whole session. New family_windows() enumerates visible top-level windows by OWNING PROCESS (Fusion360 / FusionLauncher / AdskIdentityManager), and find_licensing_dialog() finds the licensing modal by process + dialog size. fusion_start now auto-reclaims on it deterministically, and fusion_readiness reports licensingDialog:true with a clear hint instead of a vague "add-in not responding" hang.

Older versions

Entries for 1.6.37 and earlier live in CHANGELOG_ARCHIVE.md (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.