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
Publish 1.9.352
12 files changed
+2736−22
.insiders-stage/fusion-bridge/version.json+4−4.release-page-head+1−1page.json+26−10rust/Cargo.lock+230−5rust/lbr/tests/fixtures/syn_deadconnect.lbr+155rust/lbr/tests/fixtures/syn_duppad.lbr+155rust/lbr/tests/fixtures/syn_noteagle.lbr+2rust/lbr/tests/fixtures/syn_truncated.lbr+3rust/lbr/tests/golden.rs+43rust/lbr/tests/golden/preflight_and_parts.json+2075tests/run_verb_tests.py+41−2tools/promotions.log+1.insiders-stage/fusion-bridge/version.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.351",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.351/adom-bridge-fusion-v1.9.351.zip",- "sha256": "952c3fefe331f31cfb77b39d4d72cfc198ffce6f6440e60512a844b23738aac3",- "size": 1662129,+ "version": "1.9.352",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.352/adom-bridge-fusion-v1.9.352.zip",+ "sha256": "8a98eae5d5701d98df966ecc013f7a03cb02271fe96447933d60ae91d6ebb8af",+ "size": 2164901, "verbPrefixes": [ "fusion_" ],
.release-page-head+1−1@@ -1 +1 @@-4a5d97ad1ce0388c66cecc3bf059fc7397bee45b+71367bb995d9d638a8f1bd1a29712b530a8b094d
page.json+26−10@@ -11,10 +11,6 @@ "uninstall": "./uninstall.sh" }, "tags": [- "ab",- "bridge",- "fusion",- "desktop-app", "fusion360", "autodesk", "cad",@@ -79,10 +75,7 @@ "build a basic parts library", "add a 3d model to a component", "make a fusion 360 library with 3d",- "set up the fusion bridge",- "fusion dashboard",- "fusion status page",- "open the fusion launch page"+ "set up the fusion bridge" ], "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.",@@ -111,5 +104,28 @@ "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.lock+230−5@@ -10,9 +10,11 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-fusion-bridge"-version = "1.9.351"+version = "1.9.352" dependencies = [+ "chrono", "fusion-core",+ "fusion-lbr", "fusion-os-mac", "fusion-os-win", "serde_json",@@ -29,6 +31,15 @@ dependencies = [ "memchr", ] +[[package]]+name = "android_system_properties"+version = "0.1.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"+dependencies = [+ "libc",+]+ [[package]] name = "arbitrary" version = "1.4.2"@@ -44,6 +55,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" +[[package]]+name = "autocfg"+version = "1.5.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"+ [[package]] name = "base64" version = "0.22.1"@@ -72,12 +89,29 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]]+name = "chrono"+version = "0.4.45"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"+dependencies = [+ "iana-time-zone",+ "num-traits",+ "windows-link",+]+ [[package]] name = "chunked_transfer" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" +[[package]]+name = "core-foundation-sys"+version = "0.8.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"+ [[package]] name = "crc32fast" version = "1.5.1"@@ -149,7 +183,7 @@ dependencies = [ [[package]] name = "fusion-core"-version = "1.9.351"+version = "1.9.352" dependencies = [ "serde", "serde_json",@@ -159,7 +193,7 @@ dependencies = [ [[package]] name = "fusion-lbr"-version = "1.9.351"+version = "1.9.352" dependencies = [ "regex", "roxmltree",@@ -171,19 +205,43 @@ dependencies = [ [[package]] name = "fusion-os-mac"-version = "1.9.351"+version = "1.9.352" dependencies = [ "fusion-core", ] [[package]] name = "fusion-os-win"-version = "1.9.351"+version = "1.9.352" dependencies = [ "fusion-core", "windows-sys 0.59.0", ] +[[package]]+name = "futures-core"+version = "0.3.34"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"++[[package]]+name = "futures-task"+version = "0.3.34"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"++[[package]]+name = "futures-util"+version = "0.3.34"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"+dependencies = [+ "futures-core",+ "futures-task",+ "pin-project-lite",+ "slab",+]+ [[package]] name = "getrandom" version = "0.2.17"@@ -207,6 +265,30 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]]+name = "iana-time-zone"+version = "0.1.65"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"+dependencies = [+ "android_system_properties",+ "core-foundation-sys",+ "iana-time-zone-haiku",+ "js-sys",+ "log",+ "wasm-bindgen",+ "windows-core",+]++[[package]]+name = "iana-time-zone-haiku"+version = "0.1.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"+dependencies = [+ "cc",+]+ [[package]] name = "icu_collections" version = "2.3.0"@@ -327,6 +409,17 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]]+name = "js-sys"+version = "0.3.104"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"+dependencies = [+ "cfg-if",+ "futures-util",+ "wasm-bindgen",+]+ [[package]] name = "libc" version = "0.2.189"@@ -361,6 +454,15 @@ dependencies = [ "simd-adler32", ] +[[package]]+name = "num-traits"+version = "0.2.19"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"+dependencies = [+ "autocfg",+]+ [[package]] name = "once_cell" version = "1.21.4"@@ -373,6 +475,12 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]]+name = "pin-project-lite"+version = "0.2.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"+ [[package]] name = "potential_utf" version = "0.1.6"@@ -484,6 +592,12 @@ dependencies = [ "untrusted", ] +[[package]]+name = "rustversion"+version = "1.0.23"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"+ [[package]] name = "serde" version = "1.0.229"@@ -520,6 +634,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [+ "indexmap", "itoa", "memchr", "serde",@@ -539,6 +654,12 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +[[package]]+name = "slab"+version = "0.4.12"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"+ [[package]] name = "smallvec" version = "1.16.0"@@ -706,6 +827,51 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]]+name = "wasm-bindgen"+version = "0.2.127"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"+dependencies = [+ "cfg-if",+ "once_cell",+ "rustversion",+ "wasm-bindgen-macro",+ "wasm-bindgen-shared",+]++[[package]]+name = "wasm-bindgen-macro"+version = "0.2.127"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"+dependencies = [+ "quote",+ "wasm-bindgen-macro-support",+]++[[package]]+name = "wasm-bindgen-macro-support"+version = "0.2.127"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"+dependencies = [+ "bumpalo",+ "proc-macro2",+ "quote",+ "syn 2.0.119",+ "wasm-bindgen-shared",+]++[[package]]+name = "wasm-bindgen-shared"+version = "0.2.127"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"+dependencies = [+ "unicode-ident",+]+ [[package]] name = "webpki-roots" version = "0.26.11"@@ -724,6 +890,65 @@ dependencies = [ "rustls-pki-types", ] +[[package]]+name = "windows-core"+version = "0.62.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"+dependencies = [+ "windows-implement",+ "windows-interface",+ "windows-link",+ "windows-result",+ "windows-strings",+]++[[package]]+name = "windows-implement"+version = "0.60.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.119",+]++[[package]]+name = "windows-interface"+version = "0.59.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.119",+]++[[package]]+name = "windows-link"+version = "0.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"++[[package]]+name = "windows-result"+version = "0.4.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"+dependencies = [+ "windows-link",+]++[[package]]+name = "windows-strings"+version = "0.5.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"+dependencies = [+ "windows-link",+]+ [[package]] name = "windows-sys" version = "0.52.0"
rust/lbr/tests/fixtures/syn_deadconnect.lbradded+155@@ -0,0 +1,155 @@+<?xml version="1.0" encoding="utf-8"?>+<!DOCTYPE eagle SYSTEM "eagle.dtd">+<eagle version="9.6.2">+<drawing>+<settings><setting alwaysvectorfont="no"/></settings>+<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="no" altdistance="0.01" altunitdist="inch" altunit="inch"/>+<layers>+<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>+<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>+<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>+<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>+<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>+<layer number="20" name="Dimension" color="15" fill="1" visible="yes" active="yes"/>+<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>+<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>+<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>+<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>+<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>+<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>+<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>+<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>+<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="yes"/>+<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>+<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="yes"/>+<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>+<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>+<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>+<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>+<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>+<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>+<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/>+<layer number="49" name="Reference" color="7" fill="1" visible="yes" active="yes"/>+<layer number="91" name="Nets" color="2" fill="1" visible="yes" active="yes"/>+<layer number="92" name="Busses" color="1" fill="1" visible="yes" active="yes"/>+<layer number="93" name="Pins" color="2" fill="1" visible="no" active="yes"/>+<layer number="94" name="Symbols" color="4" fill="1" visible="yes" active="yes"/>+<layer number="95" name="Names" color="7" fill="1" visible="yes" active="yes"/>+<layer number="96" name="Values" color="7" fill="1" visible="yes" active="yes"/>+<layer number="97" name="Info" color="7" fill="1" visible="yes" active="yes"/>+<layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/>+</layers>+<library>+<description>USB serial converter, UART, SOIC-16</description>+<packages>+<package name="SOIC-16_3.9x9.9mm_P1.27mm">+ <description>SOIC-16, 3.9 x 9.9 mm, 1.27 mm pitch</description>+ <smd name="1" x="-2.4750" y="4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="2" x="-2.4750" y="3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="3" x="-2.4750" y="1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="4" x="-2.4750" y="0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="5" x="-2.4750" y="-0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="6" x="-2.4750" y="-1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="7" x="-2.4750" y="-3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="8" x="-2.4750" y="-4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="9" x="2.4750" y="-4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="10" x="2.4750" y="-3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="11" x="2.4750" y="-1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="12" x="2.4750" y="-0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="13" x="2.4750" y="0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="14" x="2.4750" y="1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="15" x="2.4750" y="3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="16" x="2.4750" y="4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <polygon width="0.1200" layer="21">+ <vertex x="-2.6000" y="5.0100"/>+ <vertex x="-2.8400" y="5.3400"/>+ <vertex x="-2.3600" y="5.3400"/>+ </polygon>+ <polygon width="0.1000" layer="51">+ <vertex x="-0.9750" y="4.9500"/>+ <vertex x="1.9500" y="4.9500"/>+ <vertex x="1.9500" y="-4.9500"/>+ <vertex x="-1.9500" y="-4.9500"/>+ <vertex x="-1.9500" y="3.9750"/>+ </polygon>+ <wire x1="-2.0600" y1="5.0600" x2="2.0600" y2="5.0600" width="0.1200" layer="21"/>+ <wire x1="-2.0600" y1="5.0050" x2="-2.0600" y2="5.0600" width="0.1200" layer="21"/>+ <wire x1="-2.0600" y1="-5.0600" x2="-2.0600" y2="-5.0050" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="5.0600" x2="2.0600" y2="5.0050" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="-5.0050" x2="2.0600" y2="-5.0600" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="-5.0600" x2="-2.0600" y2="-5.0600" width="0.1200" layer="21"/>+ <text x="0" y="6.020" size="1.27" layer="25" align="bottom-center">>NAME</text>+ <text x="0" y="-6.020" size="1.27" layer="27" align="top-center">>VALUE</text>+</package>+</packages>+<symbols>+<symbol name="CH340G">+ <description>USB serial converter, UART, SOIC-16</description>+ <wire x1="-12.7" y1="15.239999999999998" x2="12.7" y2="15.239999999999998" width="0.254" layer="94"/>+ <wire x1="12.7" y1="15.239999999999998" x2="12.7" y2="-15.239999999999998" width="0.254" layer="94"/>+ <wire x1="12.7" y1="-15.239999999999998" x2="-12.7" y2="-15.239999999999998" width="0.254" layer="94"/>+ <wire x1="-12.7" y1="-15.239999999999998" x2="-12.7" y2="15.239999999999998" width="0.254" layer="94"/>+ <text x="-5.0800" y="13.9700" size="1.27" layer="95" align="center">>NAME</text>+ <text x="1.2700" y="13.9700" size="1.27" layer="96" align="center">>VALUE</text>+ <pin name="GND" x="-17.78" y="-7.620000000000001" length="middle" direction="pwr"/>+ <pin name="TXD" x="17.78" y="12.7" length="middle" direction="out" rot="R180"/>+ <pin name="RXD" x="-17.78" y="10.16" length="middle" direction="in"/>+ <pin name="V3" x="-17.78" y="-10.16" length="middle" direction="out"/>+ <pin name="UD+" x="17.78" y="0" length="middle" direction="io" rot="R180"/>+ <pin name="UD-" x="17.78" y="-2.540000000000001" length="middle" direction="io" rot="R180"/>+ <pin name="XI" x="-17.78" y="7.619999999999999" length="middle" direction="in"/>+ <pin name="XO" x="17.78" y="10.16" length="middle" direction="out" rot="R180"/>+ <pin name="CTS" x="-17.78" y="5.079999999999999" length="middle" direction="in"/>+ <pin name="DSR" x="-17.78" y="0" length="middle" direction="in"/>+ <pin name="RI" x="-17.78" y="-2.540000000000001" length="middle" direction="in"/>+ <pin name="DCD" x="-17.78" y="2.539999999999999" length="middle" direction="in"/>+ <pin name="DTR" x="17.78" y="7.619999999999999" length="middle" direction="out" rot="R180"/>+ <pin name="RTS" x="17.78" y="5.079999999999999" length="middle" direction="out" rot="R180"/>+ <pin name="R232" x="-17.78" y="12.7" length="middle" direction="in"/>+ <pin name="VCC" x="-17.78" y="-12.7" length="middle" direction="pwr"/>+</symbol>+</symbols>+<devicesets>+<deviceset name="CH340G" prefix="U">+ <description>USB serial converter, UART, SOIC-16</description>+ <gates>+ <gate name="G$1" symbol="CH340G" x="0" y="0"/>+ </gates>+ <devices>+ <device name="" package="SOIC-16_3.9x9.9mm_P1.27mm">+ <connects>+ <connect gate="G$1" pin="NOPE_GND" pad="1"/>+ <connect gate="G$1" pin="TXD" pad="2"/>+ <connect gate="G$1" pin="RXD" pad="3"/>+ <connect gate="G$1" pin="V3" pad="4"/>+ <connect gate="G$1" pin="UD+" pad="5"/>+ <connect gate="G$1" pin="UD-" pad="6"/>+ <connect gate="G$1" pin="XI" pad="7"/>+ <connect gate="G$1" pin="XO" pad="8"/>+ <connect gate="G$1" pin="CTS" pad="9"/>+ <connect gate="G$1" pin="DSR" pad="10"/>+ <connect gate="G$1" pin="RI" pad="11"/>+ <connect gate="G$1" pin="DCD" pad="12"/>+ <connect gate="G$1" pin="DTR" pad="13"/>+ <connect gate="G$1" pin="RTS" pad="14"/>+ <connect gate="G$1" pin="R232" pad="15"/>+ <connect gate="G$1" pin="VCC" pad="16"/>+ </connects>+ <technologies><technology name=""/></technologies>+ </device>+ </devices>+</deviceset>+</devicesets>+</library>+</drawing>+</eagle>
rust/lbr/tests/fixtures/syn_duppad.lbradded+155@@ -0,0 +1,155 @@+<?xml version="1.0" encoding="utf-8"?>+<!DOCTYPE eagle SYSTEM "eagle.dtd">+<eagle version="9.6.2">+<drawing>+<settings><setting alwaysvectorfont="no"/></settings>+<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="no" altdistance="0.01" altunitdist="inch" altunit="inch"/>+<layers>+<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>+<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>+<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>+<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>+<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>+<layer number="20" name="Dimension" color="15" fill="1" visible="yes" active="yes"/>+<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>+<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>+<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>+<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>+<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>+<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>+<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>+<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>+<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="yes"/>+<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>+<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="yes"/>+<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>+<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>+<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>+<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>+<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>+<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>+<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/>+<layer number="49" name="Reference" color="7" fill="1" visible="yes" active="yes"/>+<layer number="91" name="Nets" color="2" fill="1" visible="yes" active="yes"/>+<layer number="92" name="Busses" color="1" fill="1" visible="yes" active="yes"/>+<layer number="93" name="Pins" color="2" fill="1" visible="no" active="yes"/>+<layer number="94" name="Symbols" color="4" fill="1" visible="yes" active="yes"/>+<layer number="95" name="Names" color="7" fill="1" visible="yes" active="yes"/>+<layer number="96" name="Values" color="7" fill="1" visible="yes" active="yes"/>+<layer number="97" name="Info" color="7" fill="1" visible="yes" active="yes"/>+<layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/>+</layers>+<library>+<description>USB serial converter, UART, SOIC-16</description>+<packages>+<package name="SOIC-16_3.9x9.9mm_P1.27mm">+ <description>SOIC-16, 3.9 x 9.9 mm, 1.27 mm pitch</description>+ <smd name="1" x="-2.4750" y="4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="1" x="-2.4750" y="3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="3" x="-2.4750" y="1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="4" x="-2.4750" y="0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="5" x="-2.4750" y="-0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="6" x="-2.4750" y="-1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="7" x="-2.4750" y="-3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="8" x="-2.4750" y="-4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="9" x="2.4750" y="-4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="10" x="2.4750" y="-3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="11" x="2.4750" y="-1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="12" x="2.4750" y="-0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="13" x="2.4750" y="0.6350" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="14" x="2.4750" y="1.9050" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="15" x="2.4750" y="3.1750" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <smd name="16" x="2.4750" y="4.4450" dx="1.9500" dy="0.6000" layer="1" roundness="50"/>+ <polygon width="0.1200" layer="21">+ <vertex x="-2.6000" y="5.0100"/>+ <vertex x="-2.8400" y="5.3400"/>+ <vertex x="-2.3600" y="5.3400"/>+ </polygon>+ <polygon width="0.1000" layer="51">+ <vertex x="-0.9750" y="4.9500"/>+ <vertex x="1.9500" y="4.9500"/>+ <vertex x="1.9500" y="-4.9500"/>+ <vertex x="-1.9500" y="-4.9500"/>+ <vertex x="-1.9500" y="3.9750"/>+ </polygon>+ <wire x1="-2.0600" y1="5.0600" x2="2.0600" y2="5.0600" width="0.1200" layer="21"/>+ <wire x1="-2.0600" y1="5.0050" x2="-2.0600" y2="5.0600" width="0.1200" layer="21"/>+ <wire x1="-2.0600" y1="-5.0600" x2="-2.0600" y2="-5.0050" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="5.0600" x2="2.0600" y2="5.0050" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="-5.0050" x2="2.0600" y2="-5.0600" width="0.1200" layer="21"/>+ <wire x1="2.0600" y1="-5.0600" x2="-2.0600" y2="-5.0600" width="0.1200" layer="21"/>+ <text x="0" y="6.020" size="1.27" layer="25" align="bottom-center">>NAME</text>+ <text x="0" y="-6.020" size="1.27" layer="27" align="top-center">>VALUE</text>+</package>+</packages>+<symbols>+<symbol name="CH340G">+ <description>USB serial converter, UART, SOIC-16</description>+ <wire x1="-12.7" y1="15.239999999999998" x2="12.7" y2="15.239999999999998" width="0.254" layer="94"/>+ <wire x1="12.7" y1="15.239999999999998" x2="12.7" y2="-15.239999999999998" width="0.254" layer="94"/>+ <wire x1="12.7" y1="-15.239999999999998" x2="-12.7" y2="-15.239999999999998" width="0.254" layer="94"/>+ <wire x1="-12.7" y1="-15.239999999999998" x2="-12.7" y2="15.239999999999998" width="0.254" layer="94"/>+ <text x="-5.0800" y="13.9700" size="1.27" layer="95" align="center">>NAME</text>+ <text x="1.2700" y="13.9700" size="1.27" layer="96" align="center">>VALUE</text>+ <pin name="GND" x="-17.78" y="-7.620000000000001" length="middle" direction="pwr"/>+ <pin name="TXD" x="17.78" y="12.7" length="middle" direction="out" rot="R180"/>+ <pin name="RXD" x="-17.78" y="10.16" length="middle" direction="in"/>+ <pin name="V3" x="-17.78" y="-10.16" length="middle" direction="out"/>+ <pin name="UD+" x="17.78" y="0" length="middle" direction="io" rot="R180"/>+ <pin name="UD-" x="17.78" y="-2.540000000000001" length="middle" direction="io" rot="R180"/>+ <pin name="XI" x="-17.78" y="7.619999999999999" length="middle" direction="in"/>+ <pin name="XO" x="17.78" y="10.16" length="middle" direction="out" rot="R180"/>+ <pin name="CTS" x="-17.78" y="5.079999999999999" length="middle" direction="in"/>+ <pin name="DSR" x="-17.78" y="0" length="middle" direction="in"/>+ <pin name="RI" x="-17.78" y="-2.540000000000001" length="middle" direction="in"/>+ <pin name="DCD" x="-17.78" y="2.539999999999999" length="middle" direction="in"/>+ <pin name="DTR" x="17.78" y="7.619999999999999" length="middle" direction="out" rot="R180"/>+ <pin name="RTS" x="17.78" y="5.079999999999999" length="middle" direction="out" rot="R180"/>+ <pin name="R232" x="-17.78" y="12.7" length="middle" direction="in"/>+ <pin name="VCC" x="-17.78" y="-12.7" length="middle" direction="pwr"/>+</symbol>+</symbols>+<devicesets>+<deviceset name="CH340G" prefix="U">+ <description>USB serial converter, UART, SOIC-16</description>+ <gates>+ <gate name="G$1" symbol="CH340G" x="0" y="0"/>+ </gates>+ <devices>+ <device name="" package="SOIC-16_3.9x9.9mm_P1.27mm">+ <connects>+ <connect gate="G$1" pin="GND" pad="1"/>+ <connect gate="G$1" pin="TXD" pad="2"/>+ <connect gate="G$1" pin="RXD" pad="3"/>+ <connect gate="G$1" pin="V3" pad="4"/>+ <connect gate="G$1" pin="UD+" pad="5"/>+ <connect gate="G$1" pin="UD-" pad="6"/>+ <connect gate="G$1" pin="XI" pad="7"/>+ <connect gate="G$1" pin="XO" pad="8"/>+ <connect gate="G$1" pin="CTS" pad="9"/>+ <connect gate="G$1" pin="DSR" pad="10"/>+ <connect gate="G$1" pin="RI" pad="11"/>+ <connect gate="G$1" pin="DCD" pad="12"/>+ <connect gate="G$1" pin="DTR" pad="13"/>+ <connect gate="G$1" pin="RTS" pad="14"/>+ <connect gate="G$1" pin="R232" pad="15"/>+ <connect gate="G$1" pin="VCC" pad="16"/>+ </connects>+ <technologies><technology name=""/></technologies>+ </device>+ </devices>+</deviceset>+</devicesets>+</library>+</drawing>+</eagle>
rust/lbr/tests/fixtures/syn_noteagle.lbradded+2@@ -0,0 +1,2 @@+<?xml version="1.0"?>+<html><body>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</body></html>
rust/lbr/tests/fixtures/syn_truncated.lbradded+3@@ -0,0 +1,3 @@+<?xml version="1.0" encoding="utf-8"?>+<!DOCTYPE eagle SYSTEM "eagle.dtd">+<e
rust/lbr/tests/golden.rs+43@@ -9,6 +9,8 @@ fn artifact_names_match_the_python_bridge() { for e in fs::read_dir(dir).unwrap().flatten() { let p = e.path(); if p.extension().and_then(|x| x.to_str()) != Some("lbr") { continue; }+ // syn_*.lbr are deliberately broken preflight fixtures+ if p.file_name().unwrap().to_string_lossy().starts_with("syn_") { continue; } let xml = fs::read_to_string(&p).unwrap(); let got = fusion_lbr::artifact_names(&xml).unwrap(); let golden_path = format!("{}/tests/golden/{}.json", env!("CARGO_MANIFEST_DIR"), p.file_stem().unwrap().to_str().unwrap());@@ -119,3 +121,44 @@ fn bundle_staging_matches_python() { assert!(!tmp.join("evil.lbr").exists()); let _ = fs::remove_dir_all(&tmp); }++#[test]+fn preflight_and_lints_match_the_python_bridge() {+ let root = env!("CARGO_MANIFEST_DIR");+ let g: serde_json::Value = serde_json::from_str(&fs::read_to_string(format!("{root}/tests/golden/preflight_and_parts.json")).unwrap()).unwrap();+ let mut checked = 0;+ for (name, case) in g.as_object().unwrap() {+ if name == "__missing__" { continue; }+ let path = std::path::PathBuf::from(format!("{root}/tests/fixtures/{name}"));+ let pf = fusion_lbr::preflight_lbr(&path);+ let want = &case["preflight"];+ assert_eq!(pf.ok, want["ok"].as_bool().unwrap(), "{name}: preflight ok");+ let want_checks = want["checks"].as_array().unwrap();+ assert_eq!(pf.checks.len(), want_checks.len(), "{name}: check count {:?}", pf.checks);+ for (mine, theirs) in pf.checks.iter().zip(want_checks) {+ assert_eq!(mine.check, theirs["check"].as_str().unwrap(), "{name}: check order");+ assert_eq!(mine.ok, theirs["ok"].as_bool().unwrap(), "{name}: {} ok", mine.check);+ // parser error strings legitimately differ between roxmltree and ElementTree+ if mine.ok || mine.check != "xml-parses" { assert_eq!(mine.detail, theirs["detail"].as_str().unwrap(), "{name}: {} detail", mine.check); }+ }+ assert_eq!(pf.metadata_ok, want["metadataOk"].as_bool(), "{name}: metadataOk");+ assert_eq!(pf.metadata_hint.as_deref(), want["_metadataHint"].as_str(), "{name}: metadata hint");+ if let Some(mw) = &pf.metadata_warnings {+ assert_eq!(serde_json::to_value(mw).unwrap(), want["metadataWarnings"], "{name}: preflight metadata warnings");+ }+ // the standalone lint+ if let Ok(xml) = fs::read_to_string(&path) {+ let lint = fusion_lbr::lint_part_metadata(&xml);+ let want_l = &case["lint"];+ assert_eq!(lint.ok, want_l["ok"].as_bool().unwrap(), "{name}: lint ok");+ if want_l["error"].is_null() {+ assert_eq!(serde_json::to_value(&lint.warnings).unwrap(), want_l["warnings"], "{name}: lint warnings");+ assert_eq!(serde_json::to_value(&lint.totals).unwrap(), want_l["totals"], "{name}: lint totals");+ }+ }+ checked += 1;+ }+ assert!(checked >= 10, "checked {checked}");+ let missing = fusion_lbr::preflight_lbr(std::path::Path::new("C:/nope/missing.lbr"));+ assert!(!missing.ok && missing.checks.len() == 1 && missing.checks[0].check == "file-readable");+}
rust/lbr/tests/golden/preflight_and_parts.jsonadded+2075@@ -0,0 +1,2075 @@+{+ "ABM8-16.000MHZ-B2-T.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 3 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "Four pin crystal, GND on pins 2 and 4",+ "name": "ABM8-16.000MHZ-B2-T",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "Crystal_SMD_3225-4Pin_3.2x2.5mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "ABM8-16.000MHZ-B2-T.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 3 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "7565 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "7565 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "4 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "CH340G.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 1 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "USB serial converter, UART, SOIC-16",+ "name": "CH340G",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "SOIC-16_3.9x9.9mm_P1.27mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "CH340G.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 1 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "9776 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "9776 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "16 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "Demo_Board.lbr": {+ "library_parts": {+ "_hint": "5 deviceset(s), 5 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 21 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "Microchip LAN7800 SuperSpeed USB 3.1 Gen1 to 10/100/1000 Ethernet Controller, QFN-48",+ "name": "LAN7800",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "QFN-48_7x7mm",+ "technology": ""+ }+ ]+ },+ {+ "description": "USB serial converter, UART, SOIC-16",+ "name": "CH340G",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "SOIC-16_3.9x9.9mm_P1.27mm",+ "technology": ""+ }+ ]+ },+ {+ "description": "",+ "name": "STM32L431RCT6TR",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "LQFP-64_10x10mm_P0.5mm",+ "technology": ""+ }+ ]+ },+ {+ "description": "Four pin crystal, GND on pins 2 and 4",+ "name": "ABM8-16.000MHZ-B2-T",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "Crystal_SMD_3225-4Pin_3.2x2.5mm",+ "technology": ""+ }+ ]+ },+ {+ "description": "Light emitting diode",+ "name": "IN-S63BTG",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "IN-S63BTG",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "Demo_Board.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 5,+ "variants": 5,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ },+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 5,+ "variants": 5,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ },+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 21 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "47513 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "47513 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "5 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "5 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "5 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "135 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ },+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "ABM8-16.000MHZ-B2-T",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "symbol_pins_stacked",+ "detail": "pins 'G' and 'G@2' sit at the same point (0.0, -5.08); one hides the other",+ "symbol": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "generic_description",+ "detail": "description 'Four pin crystal, GND on pins 2 and 4' says the class, not the part (value, package, maker)",+ "deviceset": "ABM8-16.000MHZ-B2-T"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 5,+ "variants": 5,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "IN-S63BTG.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 2 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "Light emitting diode",+ "name": "IN-S63BTG",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "IN-S63BTG",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "IN-S63BTG.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 2 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "7259 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "7259 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "2 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "IN-S63BTG",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "IN-S63BTG"+ },+ {+ "code": "generic_description",+ "detail": "description 'Light emitting diode' says the class, not the part (value, package, maker)",+ "deviceset": "IN-S63BTG"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "LAN7800.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 5 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "Microchip LAN7800 SuperSpeed USB 3.1 Gen1 to 10/100/1000 Ethernet Controller, QFN-48",+ "name": "LAN7800",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "QFN-48_7x7mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "LAN7800.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 5 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "18585 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "18585 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "49 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "LAN7800",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "LAN7800"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '1' and '48' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '12' and '13' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '24' and '25' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '36' and '37' are only 0.11 mm apart",+ "package": "QFN-48_7x7mm"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "STM32L431RCT6TR.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 10 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "",+ "name": "STM32L431RCT6TR",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "LQFP-64_10x10mm_P0.5mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "STM32L431RCT6TR.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 10 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "20255 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "20255 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "64 connect(s), all resolving",+ "ok": true+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "deviceset_no_description",+ "detail": "No <description>. Fusion's Content Manager shows this to whoever places the part; without it they are picking on a symbol outline alone.",+ "deviceset": "STM32L431RCT6TR"+ },+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "STM32L431RCT6TR",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "STM32L431RCT6TR"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '7' and '8' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '9' and '10' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '23' and '24' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '25' and '26' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '39' and '40' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '41' and '42' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '55' and '56' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ },+ {+ "code": "pad_clearance",+ "detail": "pads '57' and '58' are only 0.20 mm apart",+ "package": "LQFP-64_10x10mm_P0.5mm"+ }+ ],+ "ok": true,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "__missing__": {+ "library_parts": {+ "error": "[Errno 2] No such file or directory: 'C:/nope/missing.lbr'",+ "errorCode": "library_unreadable",+ "libraryPath": "C:/nope/missing.lbr",+ "success": false+ },+ "no_path": {+ "acceptedArgs": [+ "libraryPath",+ "lbrPath",+ "filePath",+ "path"+ ],+ "error": "No library path given; the file was never examined.",+ "errorCode": "no_path_argument",+ "success": false+ },+ "preflight": {+ "checks": [+ {+ "check": "file-readable",+ "detail": "[Errno 2] No such file or directory: 'C:/nope/missing.lbr'",+ "ok": false+ }+ ],+ "errors": [+ "file-readable: [Errno 2] No such file or directory: 'C:/nope/missing.lbr'"+ ],+ "ok": false+ }+ },+ "syn_deadconnect.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 1 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "USB serial converter, UART, SOIC-16",+ "name": "CH340G",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "SOIC-16_3.9x9.9mm_P1.27mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "syn_deadconnect.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 1 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "9781 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "9781 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "connects reference missing pins",+ "ok": false+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [+ "connects-resolve: connects reference missing pins"+ ],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ],+ "ok": false,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "syn_duppad.lbr": {+ "library_parts": {+ "_hint": "1 deviceset(s), 1 orderable variant(s); 0 carry an MPN and 0 a distributor PN. 1 warning(s) in `warnings` - these do NOT stop the library opening, but an EE cannot order from it as-is. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [+ {+ "description": "USB serial converter, UART, SOIC-16",+ "name": "CH340G",+ "variants": [+ {+ "attributes": {},+ "device": "",+ "fullName": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "package": "SOIC-16_3.9x9.9mm_P1.27mm",+ "technology": ""+ }+ ]+ }+ ],+ "libraryPath": "syn_duppad.lbr",+ "metadataOk": false,+ "success": true,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "lint": {+ "ok": false,+ "totals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ]+ },+ "preflight": {+ "_metadataHint": "The library will open, but 1 part-metadata warning(s) mean an EE cannot order from it: MPN / MANUFACTURER / a distributor PN (MOUSER_PN, DIGIKEY_PN, LCSC_PN) are what this bridge's own BOM export reads, and variants that share geometry are told apart ONLY by these. See fusion_library_parts for the per-variant breakdown.",+ "checks": [+ {+ "check": "file-readable",+ "detail": "9776 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "9776 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <eagle>",+ "ok": true+ },+ {+ "check": "packages-nonempty",+ "detail": "1 package(s)",+ "ok": true+ },+ {+ "check": "symbols-present",+ "detail": "1 symbol(s)",+ "ok": true+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "1 deviceset(s)",+ "ok": true+ },+ {+ "check": "connects-resolve",+ "detail": "connects reference missing pads",+ "ok": false+ },+ {+ "check": "pads-unique",+ "detail": "duplicate pad names - Fusion's importer refuses the ENTIRE library over these: SOIC-16_3.9x9.9mm_P1.27mm/1 x2. Rename to e.g. 17, 17@2, 17@3...",+ "ok": false+ }+ ],+ "errors": [+ "connects-resolve: connects reference missing pads",+ "pads-unique: duplicate pad names - Fusion's importer refuses the ENTIRE library over these: SOIC-16_3.9x9.9mm_P1.27mm/1 x2. Rename to e.g. 17, 17@2, 17@3..."+ ],+ "metadataOk": false,+ "metadataWarnings": [+ {+ "code": "variant_missing_part_numbers",+ "detail": "Missing MPN, MANUFACTURER, a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN). This bridge's own BOM export reads these exact attribute names, so the BOM comes out blank for this part.",+ "deviceset": "CH340G",+ "missing": [+ "MPN",+ "MANUFACTURER",+ "a distributor PN (MOUSER_PN/DIGIKEY_PN/LCSC_PN)"+ ],+ "variant": "CH340G"+ }+ ],+ "ok": false,+ "partTotals": {+ "devicesets": 1,+ "variants": 1,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "syn_noteagle.lbr": {+ "library_parts": {+ "_hint": "0 deviceset(s), 0 orderable variant(s); 0 carry an MPN and 0 a distributor PN. No metadata warnings. The full orderable identity is deviceset + device + technology (e.g. TJA1050 + T + -AUTO), because EAGLE puts package variants on <device> and grade/temperature variants on <technology> - which is how two variants share geometry and remain different parts.",+ "attributeNames": [+ "MPN",+ "MANUFACTURER",+ "MOUSER_PN",+ "DIGIKEY_PN",+ "LCSC_PN"+ ],+ "devicesets": [],+ "libraryPath": "syn_noteagle.lbr",+ "metadataOk": true,+ "success": true,+ "totals": {+ "devicesets": 0,+ "variants": 0,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": []+ },+ "lint": {+ "ok": true,+ "totals": {+ "devicesets": 0,+ "variants": 0,+ "withDistributor": 0,+ "withMpn": 0+ },+ "warnings": []+ },+ "preflight": {+ "checks": [+ {+ "check": "file-readable",+ "detail": "348 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "348 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": true+ },+ {+ "check": "xml-parses",+ "detail": "",+ "ok": true+ },+ {+ "check": "root-is-eagle",+ "detail": "root is <html>",+ "ok": false+ },+ {+ "check": "packages-nonempty",+ "detail": "EMPTY <packages> - Fusion opens this to a silent 'No Components' library",+ "ok": false+ },+ {+ "check": "symbols-present",+ "detail": "0 symbol(s)",+ "ok": false+ },+ {+ "check": "text-align-valid",+ "detail": "all <text> align values are EAGLE values",+ "ok": true+ },+ {+ "check": "devicesets-present",+ "detail": "no <deviceset> - EDIT <name>.dev will raise Fusion's Create-new prompt",+ "ok": false+ },+ {+ "check": "pads-unique",+ "detail": "all pad names unique per package",+ "ok": true+ }+ ],+ "errors": [+ "root-is-eagle: root is <html>",+ "packages-nonempty: EMPTY <packages> - Fusion opens this to a silent 'No Components' library",+ "symbols-present: 0 symbol(s)",+ "devicesets-present: no <deviceset> - EDIT <name>.dev will raise Fusion's Create-new prompt"+ ],+ "metadataOk": true,+ "metadataWarnings": [],+ "ok": false,+ "partTotals": {+ "devicesets": 0,+ "variants": 0,+ "withDistributor": 0,+ "withMpn": 0+ }+ }+ },+ "syn_truncated.lbr": {+ "library_parts": {+ "error": "unclosed token: line 3, column 0",+ "errorCode": "library_unreadable",+ "libraryPath": "syn_truncated.lbr",+ "success": false+ },+ "lint": {+ "error": "unclosed token: line 3, column 0",+ "ok": false,+ "warnings": []+ },+ "preflight": {+ "checks": [+ {+ "check": "file-readable",+ "detail": "77 bytes",+ "ok": true+ },+ {+ "check": "size-sane",+ "detail": "77 bytes - a real EAGLE library is never this small (truncated transfer?)",+ "ok": false+ }+ ],+ "errors": [+ "size-sane: 77 bytes - a real EAGLE library is never this small (truncated transfer?)"+ ],+ "ok": false+ }+ }+}
tests/run_verb_tests.py+41−2@@ -140,7 +140,6 @@ t("fusion_set_auto_update", "daily", {}, {"ok": True}, "no args = read-only") t("fusion_assembly_bom", "daily", {}, {"pred": "ok_or_budget"}, "either a BOM (small doc) or the fast bom_walk_budget_exceeded refusal (3D PCB) - both are the verb working as designed") t("fusion_dismiss_blocking_dialogs", "daily", {}, {"ok": True}, "no-op when nothing is blocking")-t("fusion_load_design_rules", "manual", note="mutates the board's DRC rules") # ── stage 3: document flows on the canonical board ────────────────────────── # ORDER IS THE TEST: 2D-context verbs (Electron.*, gerbers/BOM/CPL, stackup,@@ -247,6 +246,36 @@ for v in ("fusion_stop", "fusion_kill", "fusion_signin", "fusion_signin_2fa", "f "fusion_install_fusion", "fusion_notify_owner", "fusion_open_by_urn_note"): t(v, "manual", note="lifecycle/human-wall verbs; manual tier") +# ── triage of 2026-09-03 (the verbs the daily run flagged as untriaged) ──────────────────+# Read-only bridge/state verbs run daily; anything that drives Fusion's GUI or writes to the+# cloud is weekly (exercised by the drills) or manual with the reason recorded.+t("fusion_action_ledger", "daily", {"limit": 5}, {"ok": True})+t("fusion_addin_status", "daily", {}, {"ok": True})+t("fusion_alerts", "daily", {"sinceSec": 300}, {"ok": True, "fields": ["alerts"]})+t("fusion_verb_times", "daily", {}, {"ok": True})+t("fusion_live_feed", "daily", {"action": "poll"}, {"ok": True}, "one poll of the feed; no waiting")+t("fusion_prove_result", "daily", {}, {}, "shape only: the last completed run, or an honest 'none yet'")+t("fusion_set_driving_badge", "daily", {}, {"ok": True}, "no-args form is a pure pref read")+t("fusion_set_window_sizing", "daily", {}, {"ok": True}, "no-args form is a pure pref read")+t("fusion_cancel_run", "negative", {"runId": "no-such-run"}, {"errorCode": None, "pred": None}, "expect an honest 'unknown runId'")+t("fusion_preflight_lbr", "negative", {"libraryPath": "C:/nope/missing.lbr"}, {"errorCode": None, "pred": None}, "expect a refusal naming the missing file")+t("fusion_library_parts", "negative", {"libraryPath": "C:/nope/missing.lbr"}, {"errorCode": None, "pred": None}, "expect a refusal naming the missing file")+t("fusion_take_screenshot", "weekly", {}, {"ok": True}, "needs Fusion up; hwnd-targeted background capture")+t("fusion_activate_document", "weekly", {"name": "Untitled"}, {}, "needs an open document; shape only")+t("fusion_library_manager", "weekly", {}, {"ok": True}, "drives the GUI (Library Manager), reads nothing destructive")+t("fusion_plan_library_import", "weekly", {"parts": []}, {}, "planner with no parts answers honestly; the drills cover the real thing")+t("fusion_create_library", "manual", note="the five-part drill covers it (fusion_install_library_bundle -> prove)")+t("fusion_install_library_bundle", "manual", note="the five-part drill covers it; needs a bundle zip on the box")+t("fusion_managed_library_create", "manual", note="creates a managed library on the hub (cloud write)")+t("fusion_managed_library_link", "manual", note="drives LIBRARY.IO dialogs against the hub")+t("fusion_managed_library_pull", "manual", note="drives LIBRARY.IO dialogs against the hub")+t("fusion_managed_library_push", "manual", note="drives LIBRARY.IO dialogs; cloud write")+t("fusion_managed_library_unlink", "manual", note="drives LIBRARY.IO dialogs against the hub")+t("fusion_reset_workspace", "manual", note="closes the user's documents")+t("fusion_restart_for_addin", "manual", note="restarts Fusion")+t("fusion_save_to_cloud", "manual", note="cloud write; exercised by the drills")+t("fusion_web_signin", "manual", note="opens a browser on the user's machine")+ PLAN = P # -- Section map ------------------------------------------------------------@@ -267,6 +296,16 @@ PLAN = P SECTION_ORDER = ["gui-driving", "cad-3d-bom", "mcp-server", "python-addin", "aps", "auth-tokens", "exports", "bridge-lifecycle"] _SECTION_BY_VERB = {+ "fusion_action_ledger": "bridge-lifecycle", "fusion_addin_status": "python-addin", "fusion_alerts": "gui-driving",+ "fusion_verb_times": "bridge-lifecycle", "fusion_live_feed": "bridge-lifecycle", "fusion_prove_result": "cad-3d-bom",+ "fusion_set_driving_badge": "bridge-lifecycle", "fusion_set_window_sizing": "gui-driving", "fusion_cancel_run": "cad-3d-bom",+ "fusion_preflight_lbr": "cad-3d-bom", "fusion_library_parts": "cad-3d-bom", "fusion_take_screenshot": "gui-driving",+ "fusion_activate_document": "gui-driving", "fusion_library_manager": "gui-driving", "fusion_plan_library_import": "cad-3d-bom",+ "fusion_create_library": "cad-3d-bom", "fusion_install_library_bundle": "cad-3d-bom",+ "fusion_managed_library_create": "aps", "fusion_managed_library_link": "aps", "fusion_managed_library_pull": "aps",+ "fusion_managed_library_push": "aps", "fusion_managed_library_unlink": "aps",+ "fusion_reset_workspace": "gui-driving", "fusion_restart_for_addin": "bridge-lifecycle",+ "fusion_save_to_cloud": "aps", "fusion_web_signin": "auth-tokens", "fusion_start": "gui-driving", "fusion_stop": "gui-driving", "fusion_kill": "gui-driving", "fusion_get_app_state": "gui-driving", "fusion_dismiss_blocking_dialogs": "gui-driving", "fusion_open_cloud_file": "gui-driving", "fusion_open_design": "gui-driving",@@ -299,7 +338,7 @@ _SECTION_BY_VERB = { "fusion_export_cpl": "exports", "fusion_export_optimized_glb": "exports", "fusion_fetch_optimized_glb": "exports", "fusion_board_stackup": "exports", "fusion_web_export": "exports",- "fusion_load_design_rules": "exports", "fusion_set_design_rules": "exports",+ "fusion_set_design_rules": "exports", "fusion_readiness": "bridge-lifecycle", "fusion_describe": "bridge-lifecycle", "fusion_uninstall": "bridge-lifecycle", "fusion_set_seat_takeover": "bridge-lifecycle", "fusion_set_auto_update": "bridge-lifecycle", }
tools/promotions.logadded+1@@ -0,0 +1 @@+2026-09-03T16:09:23Z promoted 1.9.351 attest: uh oh, we better get this out there and working