app
Altium - the Altium Bridge
Public Made by Adomby adom
Adom Bridge for Altium Designer: a resident DelphiScript agent gives the AI eval, the 1,100-command process launcher, all 8 EDA surfaces with screenshots, compile/ERC, DRC, OutJob outputs, native SchLib/PcbLib authoring with STEP 3D bodies, and dialog handling by PID.
← Commit history
Verb battery covers all 146 verbs: phase 3.5 builds lane.PcbDoc from the fixture footprints and runs the AI Flow board-lane verbs on it (build_board, routing_state, set_design_rules, add_rule, move_parts, route_net, place_vias, select_net, zoom_to, remove_items, ripup_nets, apply_pours, pour_state, repour, remove_pours, set_outline, silk_state, apply_silkscreen, routing_drc), then build_schematic + export_manufacturing on its own project; list_installed_libraries and uninstall_library (dryRun). On DESKTOP-BAR6S0F, bridge 0.2.48: PASS 144, FAIL 1 (ensure_licensed: #19), SKIP 1 (a365_logout), uncovered 0.
1 file changed
+43
dev-skills/altium-bridge-test/run_verb_tests.py+43@@ -153,6 +153,9 @@ def matrix(w): M["build_footprint"] = dict(phase=2, **ref("no spec given: must refuse by name", libraryPath=PL)) M["cleanup_libs"] = dict(phase=2, **anyo("library housekeeping", libraryPath=SL)) M["save"] = dict(phase=2, **ok(filePath=SL))+ M["list_installed_libraries"] = dict(phase=2, **ok())+ M["uninstall_library"] = dict(phase=2, **anyo("SAFETY: dryRun only, removes nothing; a named not-installed refusal also passes",+ libraryName="Adom_Test", dryRun=True)) # ---- phase 3: schematic + board built from the scratch libraries -------------------------- M["place_on_sch"] = dict(phase=3, **ok(libraryPath=SL, symbolName="TST_SOIC8;TST_QFN24;TST_BGA36", schPath=SD, title="battery",@@ -185,6 +188,46 @@ def matrix(w): M["open_project"] = dict(phase=3, **ref("no project given: must refuse by name")) M["run_erc"] = dict(phase=3, **anyo("ERC needs a compiled project: named refusal is a pass", filePath=SD)) + # ---- phase 3.5: the AI Flow board lane on its OWN scratch board ----------------------------+ # build_board makes lane.PcbDoc from the fixture footprints (two SOIC8s, N1 = U1.8-U2.1 straight+ # across, GND = U1.4/U2.5), then every live-board verb edits it in turn: read, rules, move, route,+ # via, select/zoom, remove, rip up, pour (repoured outside the script engine: the agent stops and+ # restarts for a few seconds), outline, silkscreen, DRC. build_schematic then draws lane.SchDoc in+ # its own project with lane.PcbDoc, and export_manufacturing runs that project's OutJob.+ LB, LS, LP = D + "/lane.PcbDoc", D + "/lane.SchDoc", D + "/lane.PrjPcb"+ lane_nets = {"N1": ["U1.8", "U2.1"], "GND": ["U1.4", "U2.5"]}+ lane_parts = [{"ref": "U1", "footprint": "TST_SOIC8", "x": 10, "y": 10, "rotation": 0},+ {"ref": "U2", "footprint": "TST_SOIC8", "x": 30, "y": 10, "rotation": 0}]+ n_comps = lambda d: len(d.get("components") or (d.get("data") or {}).get("components") or [])+ M["build_board"] = dict(phase=3.5, timeout=300, **ok(pcbPath=LB, libraryPath=PL, outline={"rect": [0, 0, 40, 20]},+ parts=lane_parts, nets=lane_nets),+ check=lambda d: d.get("placed") == 2 and not d.get("wrongPins"))+ M["routing_state"] = dict(phase=3.5, **ok(expectPath=LB), check=lambda d: n_comps(d) == 2)+ M["set_design_rules"] = dict(phase=3.5, timeout=300, **ok(clearance=0.2, trackWidth={"min": 0.15, "preferred": 0.25, "max": 2},+ holeToHole=0.25, polygonConnect="relief"))+ M["add_rule"] = dict(phase=3.5, **ok(kind="clearance", name="Battery", scope1="InNet('N1')", gap=0.3))+ M["move_parts"] = dict(phase=3.5, **ok(parts=[{"ref": "U2", "x": 29, "y": 10, "rotation": 0}], expectPath=LB))+ M["route_net"] = dict(phase=3.5, **ok(net="N1", width=0.25, paths=[[{"pad": "U1.8"}, {"pad": "U2.1"}]], expectPath=LB))+ M["place_vias"] = dict(phase=3.5, **ok(vias=[{"net": "GND", "x": 20, "y": 16, "size": 0.6, "drill": 0.3}], expectPath=LB))+ M["select_net"] = dict(phase=3.5, **ok(net="N1", zoom=True))+ M["zoom_to"] = dict(phase=3.5, **ok(ref="U1"))+ M["remove_items"] = dict(phase=3.5, **ok(vias=[{"x": 20, "y": 16}], expectPath=LB))+ M["ripup_nets"] = dict(phase=3.5, **ok(nets=["N1"], expectPath=LB))+ M["apply_pours"] = dict(phase=3.5, timeout=300, **ok(pours=[{"net": "GND", "layer": "B.Cu", "points": [[1, 1], [39, 1], [39, 19], [1, 19]],+ "connect": "relief"}]))+ M["pour_state"] = dict(phase=3.5, **ok())+ M["repour"] = dict(phase=3.5, timeout=300, **ok())+ M["remove_pours"] = dict(phase=3.5, **ok(pours="all"))+ M["set_outline"] = dict(phase=3.5, **ok(outline={"rect": [0, 0, 40, 20], "cornerRadius": 1}))+ M["silk_state"] = dict(phase=3.5, **ok())+ M["apply_silkscreen"] = dict(phase=3.5, **ok(texts=[{"text": "BATTERY", "x": 20, "y": 18, "size": 1}]))+ M["routing_drc"] = dict(phase=3.5, timeout=300, **ok())+ M["build_schematic"] = dict(phase=3.5, timeout=600, **ok(schPath=LS, libraryPath=SL, pcbLibPath=PL, pcbPath=LB, projectPath=LP, title="battery lane",+ parts=[{"ref": "U1", "symbol": "TST_SOIC8", "block": "core", "footprint": "TST_SOIC8"},+ {"ref": "U2", "symbol": "TST_SOIC8", "block": "core", "footprint": "TST_SOIC8"}],+ nets=lane_nets))+ M["export_manufacturing"] = dict(phase=3.5, timeout=400, **ok(projectPath=LP, pcbPath=LB))+ # ---- phase 4: outputs -------------------------------------------------------------------- M["export_step"] = dict(phase=4, timeout=300, **anyo("STEP of the battery board", filePath=PD, output=D + "/battery.step")) M["export_bom"] = dict(phase=4, **anyo("missing OutJob: named refusal (the demo OutJob opens its .xlsx on screen)", outjobPath=D + "/missing.OutJob"))