← Commit history

Delete FUSION_3D_FINDINGS.md

John Lauer ·1552a34669 ·4mo ago ·parent b0d14e8
1 file changed −202
FUSION_3D_FINDINGS.mddeleted−202
@@ -1,202 +0,0 @@-# Fusion 3D-package findings (live log, 2026-06-28)--Hard-won findings from cracking "attach the real 3D chip to a Fusion library package." Captured as we-go so the final MAKING_LIBRARIES.md + fusion-libraries skill are complete and correct. Newest insight-at the bottom of each section.--## 1. Use chip-fetcher's curated LIBRARY, not a raw /tmp download--`chip-fetcher/library/<MPN>/` is curated and carries **variant-specific** files. For Fusion, the right-inputs are the **`.fusion`** variant (generated by Adom's `adom-sfconvert`), paired with the curated-named 3D:--| File | Use |-|---|---|-| `<MPN>.fusion.kicad_sym` | symbol, Fusion-tuned -> feed to adom-lbr |-| `<MPN>.fusion.kicad_mod` | footprint, Fusion-tuned -> feed to adom-lbr |-| `<MPN>-named.step` | the curated 3D (part number etched on top; oriented). Pair this with the footprint |-| `<MPN>.kicad_mod` / `.manufacturer.*` / `.altium.*` | raw / other-EDA variants, NOT for Fusion |--MISTAKE made + fixed: I first built the `.lbr` from a raw `/tmp/adom-chip-fetcher-*/EAGLE/*.lbr` and-the thin 245KB `manufacturer.step`. That gave a footprint/3D size mismatch. Switching to-`.fusion.kicad_mod` + `-named.step` is the fix. (Convention confirmed in `chip-fetcher/src/thumbnails.rs`:-it builds the lbr with `--name <mpn>.fusion` from the `.fusion` files.)--## 2. adom-lbr is the right tool; pass it the .fusion files--`adom-lbr generate --sym <MPN>.fusion.kicad_sym --fp <MPN>.fusion.kicad_mod -o <MPN>.lbr --name <MPN>`-then `adom-lbr validate <MPN>.lbr`. adom-lbr has no 3D/URN flag (it is symbol+footprint only); the 3D-is attached separately in Fusion (sections 4-6). The VENDOR EAGLE `.lbr` must NOT be fed to-`Create3DPackage` - it fails Fusion's XML parser ("File doesn't contain valid XML data"); an-adom-lbr-generated `.lbr` parses fine.--## 3. Getting the .lbr / .step onto Windows--The pipeline runs in the cloud container; Fusion runs on Windows; there is NO container->Windows push-verb. Serve the files (`python3 -m http.server 8931`) and pull them with `shell_execute` +-`Invoke-WebRequest -OutFile C:\Users\<user>\adom-lib\...`. Build the shell JSON with `json.dumps`-(Windows paths need `\\`).--## 4. Opening the footprint in the 3D viewer (Package3DEnvironment)--- `fusion_open_lbr` the `.lbr` so the **library document is ACTIVE** (required).-- `fusion_execute_text_command {"command":"Electron.Create3DPackage C:/.../<MPN>.lbr"}` opens the-  **`Package3DEnvironment`** workspace showing the footprint (green courtyard + pads + `>NAME`/`>VALUE`).-  ERROR if the library is not active: "Please run the command in library document."-- Command defs in that env: `Package3DCmd`, `Package3DCreateCmd`, `Package3DStop` (Stop = FINISH).--## 5. Placing the real 3D chip via the API (works)--Inside the env, with `fusion_run_modeling_script`:-```python-d = adsk.fusion.Design.cast(app.activeProduct); root = d.rootComponent-im = app.importManager-im.importToTarget(im.createSTEPImportOptions("C:/.../<MPN>-named.step"), root)   # the real body-oc = root.occurrences.item(root.occurrences.count-1)-# auto-orient: rotate the smallest bbox dimension to Z so it lies flat-# (named.step is usually already Z-thin; raw STEP often imports Y-up and needs +90 about X)-```-The chip imports at correct scale and sits on the footprint.--## 6. The library-context commands (the proper in-library path)--Enumerating command defs while the **library** is active surfaced the real in-library commands:-- `Electron::AddCustom3DModel` - opens a design to add a custom 3D model to the selected package.-- `AttachToFootprintCmd` - attaches the modeled body to the footprint (this is what maps it back +-  mints the eagle URN). It is INTERACTIVE (holds the main thread waiting for a footprint-align confirm),-  so it resists pure-API completion; recover with Escape if it wedges.-- also: `Electron::EditCustom3DModel`, `Electron::PackageFromWeb`, `Electron::RemoveCustom3DModel`.--## 7. THE URN SCHEME (the crux)--A library `.lbr` references a 3D package by **`urn:adsk.eagle:package:NNNNN/V`** (managed-library scheme),-NOT the **`urn:adsk.wipprod:...`** scheme that `fusion_aps_upload` / `save_to_cloud` produce. So you-cannot just paste an uploaded-STEP URN into the `.lbr`. The eagle URN is minted only when Fusion's 3D-Package Generator FINISHes mapped to the package. The `.lbr` markup (from the EAGLE spec + Autodesk-forum): `<packages3d><package3d urn="urn:adsk.eagle:package:N/V" type="model">...</package3d></packages3d>`-and the device carries `override_package3d_urn` / a `<package3dinstance package3d_urn="...">`.--## 8. Open item--The one step not yet automated end-to-end: minting + mapping the eagle URN (the FINISH inside the-in-library generator). Current plan: open the footprint env with the chip placed (sections 4-5), let-the human align + FINISH/save once, then export that `.lbr`, read the exact `package3d` markup + eagle-URN, and from there automate the edit-and-reupload for every future chip.--## 9. Integration test (adom-lbr.fusion3d/1 sidecar) - results--Tested the adom-lbr-fixed `.lbr` + `ads.fusion3d.json` sidecar end to end:-- **Footprint writer fix: VERIFIED.** The new `adom-lbr generate` emits a real 4-sided LQFP-64-  (16 left / 16 right / 16 top / 16 bottom `<smd>`, X & Y ±5.74 mm), 64 `<connect>` intact. Opens in-  Fusion as a proper QFP, not a 2-column placeholder. (Format nit: the `<smd>` have **no `rot=`** - fine-  for square pads, but non-square pads on the top/bottom sides would need `rot="R90"`.)-- **URN minting: the assumed scheme is WRONG.** Running the 3D Package Generator-  (`Create3DPackage` -> import model -> `Package3DStop`/FINISH -> Save) mints-  **`urn:adsk.wipprod:dm.lineage:...`** (a regular user cloud design), NOT the-  **`urn:adsk.eagle:package:NNN/V`** the manifest expects. Fusion's generator saves a *custom* 3D model-  as an ordinary cloud file (wipprod), not a managed eagle package.-- **Binding the wipprod URN: FAILS.** Writing `<packages3d><package3d urn="urn:adsk.wipprod:dm.lineage:...">`-  + a device `<package3dinstance package3d_urn="...">` into the `.lbr` and reopening gives-  **"<file>.lbr has errors and cannot be opened. Close the empty design file..."** So a wipprod URN is-  not valid in `package3d`; the `.lbr` genuinely needs an `adsk.eagle:package` URN.-- **THE REMAINING BLOCKER:** how to mint an `adsk.eagle:package` URN for a custom model. The standalone-  generator path does not produce one. The in-library `Electron::AddCustom3DModel` + `AttachToFootprintCmd`-  path (section 6) is the likely minter, but it is interactive. This is the crux to crack next.--## 10. Capturing GUI error dialogs (Fusion) - ALWAYS check owned popups--Fusion error dialogs (e.g. "<file>.lbr has errors and cannot be opened") are **owned popups**: they do-NOT enumerate in `desktop_list_windows` and are invisible to a plain capture of the main window. A-`fusion_*` verb can return `success:true` while an error dialog is actually up.--**`desktop_screenshot_window {hwnd}` (AD v1.8.177+) captures them automatically** and returns them at the-TOP LEVEL: **`ownedPopupCount`** (always present; 0 = none) + **`_screenshots[]`** (each owned popup:-`title`, `kind:"owned_popup"`, `localSafePath`, `rect`, `coordMap`). The CLI auto-pulls each popup PNG.--RULE: after every Fusion open / `execute_text_command` / generator FINISH, grab-`desktop_screenshot_window` on the Fusion main hwnd and **check `ownedPopupCount` / read the-`screenshots[]` array** (each entry: `title`, `localSafePath`, `coordMap`, `shotId`; the CLI auto-pulls-each PNG to `/tmp/ad-shots/`). Do NOT just read `output.data.image` (that is the main window only and-misses owned dialogs). Treat `ownedPopupCount > 0` as "a dialog is up - read each popup before proceeding."-(Field note: `_screenshots`/`_popups_note` are doc-strings; the real array is `screenshots`.)--## 11. SUCCESS - the WORKING 3D-attach flow (supersedes the section 9 "bind fails" path)--The manual `package3d`-XML / pre-minted-URN approach (section 9) was a dead end. The **generator FINISH,-launched from the open library, DOES bind the 3D to the deviceset** - no XML editing, no wipprod URN.-Proven end-to-end on ADS8588SIPM (LQFP-64): the Content Manager tree shows the 3D nested under the-package under the deviceset, the Packages panel's `Package` column flips from `Placeholder` to the part-name, and the 3D preview becomes the real chip. **This is the first time the full Fusion electronics 3D-attach has been automated through the bridge.**--The repeatable sequence (all via existing verbs):-1. Build the `.lbr` from the chip-fetcher **`.fusion`** variant (`adom-lbr generate`); footprint must be a-   real 4-sided package (the writer fix). Stage `.lbr` + the model STEP to Windows.-2. `fusion_open_lbr` the `.lbr` so the **library is the ACTIVE document**.-3. `fusion_execute_text_command Electron.Create3DPackage <C:/...lbr>` -> opens `Package3DEnvironment`-   showing the footprint.-4. `fusion_run_modeling_script`: `importManager.importToTarget(createSTEPImportOptions(<C:/...step>), root)`,-   then auto-orient (rotate the smallest bbox dim to Z so it lies flat on the footprint).-5. `fusion_run_modeling_script`: `ui.commandDefinitions.itemById("Package3DStop").execute()` (FINISH).-6. A **Save** dialog appears (owned dialog) -> `desktop_ui_click` its-   `QTApplication.QTFrameWindow.standardActions.SaveButton`.-7. Back on the library: the deviceset's package now carries the real 3D. **The right-panel preview LAGS** --   re-grab the window (or click the package in the Content Manager) to see `Package`=part-name + the real-   3D; the tree is the source of truth, the preview refresh is delayed.--PITFALL corrected: do NOT conclude "it didn't bind" from a stale gray preview right after FINISH - check-the Content Manager tree / the `Package` column, and re-grab after a moment.--## 12. GROUND TRUTH - exactly how Fusion bakes the 3D URN into the .lbr--Exported the bound library to `.flbr` (`fusion_export_source` with a `.flbr` extension), which is a-Fusion document ZIP; the EAGLE library XML lives in `.../electron.BlobParts/ExtFile<uuid>` (24 KB,-`<eagle version="9.7.0">`). It DOES contain the 3D, and here is the exact markup Fusion writes for a-CUSTOM (user-uploaded) 3D model:--```xml-<packages3d>-  <package3d name="ADS8588SIPM" urn="" wip_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"-             locally_modified="yes" type="model">-    <description>ADS8588SIPM</description>-    <packageinstances><packageinstance name="ADS8588SIPM"/></packageinstances>-  </package3d>-</packages3d>-<!-- and inside the matching <device ...>: -->-<package3dinstances>-  <package3dinstance package3d_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"/>-</package3dinstances>-```--THE DELTA (why the section-9 manual bind failed):-- `urn=""` is **EMPTY** for a custom model (the `urn` slot is for MANAGED `urn:adsk.eagle:package:N/V`-  content only). The actual reference goes in **`wip_urn=`**.-- The URN form is the **versioned file URN** `urn:adsk.wipprod:fs.file:vf.<id>?version=1`, NOT the-  `dm.lineage` form. (`fusion_aps_upload`/`save_to_cloud` return a `dm.lineage` lineage URN; the-  `?version=1` file URN is the one to use - get it from `fusion_aps_file_info`/the saved version.)-- Add **`locally_modified="yes"`** and `type="model"`.-- The device's `<package3dinstance package3d_urn="...">` uses the SAME `fs.file:vf...?version=1` form.--So the manifest's `adsk.eagle:package` assumption is only for managed-library parts; for a-self-uploaded model the binding is a `wip_urn` (fs.file:vf) with empty `urn`. With this exact shape,-adom-lbr (or the bridge) CAN write the binding directly given the model's versioned file URN - no-generator UI needed. (The generator FINISH path also works and is what produced this reference.)--## 13. Resolved sidecar contract (answers to adom-lbr v1.1.1)--**Q: what does the sidecar ship for the FINISH path?** Just `model.path` + `package` + `placement`.-That is sufficient - the bridge does Create3DPackage -> import -> orient -> FINISH -> Save. `placement`-stays useful as an orientation hint/override (the bridge's auto-orient is "rotate smallest bbox dim to Z";-a known pin-1 rotation/offset in `placement` lets adom-lbr override it when a part needs it).--**Q: write the minted wip_urn back to the sidecar (status -> bound)?** YES, record it - for idempotency-(re-runs detect "already bound"), provenance (which model version), and to enable the offline `bind-3d`-fast-path later. BUT the **in-Fusion library is the runtime source of truth**; the sidecar record is-bookkeeping that **adom-lbr owns + writes**. The bridge's part is to REPORT the minted URN: after the-Save, `fusion_aps_file_info {query:"<package>"}` returns the saved 3D-package design's tip-**`fs.file:vf.<id>?version=N`** URN - adom-lbr writes that into the sidecar (`urn`, `urn_status:"bound"`).--**Q: dm.lineage vs fs.file in the .lbr?** ONLY the versioned **`fs.file:vf.<id>?version=N`** goes in the-`.lbr` - in both `wip_urn=` and the device `package3d_urn=`. NEVER `dm.lineage` in the `.lbr` (Fusion pins-a specific version, consistent with `locally_modified="yes"`). `dm.lineage` is the stable cross-version ID;-keep it (optionally) only as SIDECAR provenance for re-resolving the latest version, never in the binding.