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
v0.1.27: review switches documents, reports skipped checks
7 files changed
+88−35
CHANGELOG.md+4@@ -1,5 +1,9 @@ # Changelog +## 0.1.27 — 2026-09-01+- **`review_board` switches documents and returns PARTIAL results.** Altium holds one current document, so a board read and a sheet read cannot both be "now" — with a schematic focused, the previous version failed the whole review because `read_board` had nothing current. It now takes optional `board` and `sheet` paths and activates each in turn (like `cross_check`), and when one document cannot be read it still runs the checks that CAN run.+- **`skipped` names every check that did not run and why** — "no board read", "no schematic read — pass includeSchematic:true". A review that silently drops half its checks reads exactly like a clean board, which is the failure mode worth engineering against.+ ## 0.1.26 — 2026-09-01 - **The Adom house rule is now a check.** `vendor_part_numbers` (warning) flags any purchased component missing Mouser / DigiKey / LCSC part numbers — Mouser named first because it is the preferred vendor, so if only one gets filled in, that is the one. Test points, fiducials and mounting holes are exempt: they are not purchased parts, and flagging them would train people to ignore the check. - `missing_datasheets` (info) and `schematic_placeholder_values` (error) — the latter catches default Comments at the SOURCE, where the BOM is actually generated from, rather than only on placed parts.
adom-bridge-altium-manifest.json+4−4@@ -1,9 +1,9 @@ { "name": "altium",- "version": "0.1.26",- "url": "https://wiki.adom.inc/download/adom/altium-bridge/0.1.26/adom-bridge-altium-v0.1.26.zip",- "sha256": "4d39499ee8bbf1af001b29043920415852e95cc8d9820393595f49fed75558b7",- "size": 125669,+ "version": "0.1.27",+ "url": "https://wiki.adom.inc/download/adom/altium-bridge/0.1.27/adom-bridge-altium-v0.1.27.zip",+ "sha256": "14e69c2e7d8543c9ae4a87ffc415d422ed124e4f32c8457cc558ece41ae89e93",+ "size": 126211, "verbPrefixes": [ "altium_" ],
adom-bridge-altium-v0.1.27.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "altium", "displayName": "Altium Designer",- "version": "0.1.26",+ "version": "0.1.27", "description": "Drive Altium Designer from Adom: a resident DelphiScript agent (eval + the 1,100-command process launcher), the X2 -R command line, UIA over the VCL shell, dialogs by PID, screenshots of every Altium window, and Altium 365.", "homepage": "https://wiki.adom.inc/adom/altium-bridge", "docs": "https://wiki.adom.inc/adom/altium-bridge",
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "altium-bridge",- "version": "0.1.26",+ "version": "0.1.27", "type": "app", "description": "Skills for your container so your AI knows how to drive the Altium Designer bridge (altium_* verbs). The bridge runtime itself is the release zip; Adom Bridge loads that.", "tags": [
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-0.1.26+0.1.27
src/server.py+77−28@@ -1746,54 +1746,103 @@ REVIEW_NOT_IMPLEMENTED = { def h_review_board(args):- """Run the design-review checks over ONE board read (plus the current sheet, if asked).+ """Run the design-review checks. One agent round trip per document; all analysis in the bridge. - One agent round trip, all the analysis in the bridge. Findings name the exact designator, net or- layer and say what is wrong — never 'verify X'. `severity` is error | warning | info.+ Altium holds ONE current document, so a board read and a sheet read cannot both be "now" — this+ activates each in turn when given `board` / `sheet` paths, exactly like cross_check.++ Returns PARTIAL results rather than nothing: if the board cannot be read, the schematic checks+ still run and `skipped` says which checks had no data and why. A review that fails wholesale+ because one document was not current is a review nobody runs. """ g = _need_licensed() if g: return g+ timeout = float(args.get("timeout", 90))+ board, sheet = {}, None+ board_err = sheet_err = None++ def _open(path):+ bad = _validate_openable(path)+ if bad:+ return bad+ o = agent.call("open", {"path": path}, timeout=timeout)+ d = o.get("data") or {}+ return None if d.get("ok", True) else {"error": d.get("error")}++ if args.get("board"):+ e = _open(args["board"])+ if e:+ return {"success": False, "stage": "board", **e} r = agent.call("read_board", {"sections": "components,nets,layers,copper,occupancy,outline",- "limit": args.get("limit", 2000)},- timeout=float(args.get("timeout", 90)))- board = r.get("data") or {}- if not board.get("ok"):- return r- sheet = None- if args.get("includeSchematic"):- sr = agent.call("read_schematic", {"sections": "components", "params": "1"},- timeout=float(args.get("timeout", 90)))- sd = sr.get("data") or {}- sheet = sd if sd.get("ok") else None+ "limit": args.get("limit", 2000)}, timeout=timeout)+ bd = r.get("data") or {}+ if bd.get("ok"):+ board = bd+ else:+ board_err = bd.get("error") or "board read failed"++ want_sheet = bool(args.get("includeSchematic") or args.get("sheet"))+ if want_sheet:+ if args.get("sheet"):+ e = _open(args["sheet"])+ if e:+ sheet_err = e.get("error")+ if not sheet_err:+ sr = agent.call("read_schematic", {"sections": "components", "params": "1"}, timeout=timeout)+ sd = sr.get("data") or {}+ if sd.get("ok"):+ sheet = sd+ else:+ sheet_err = sd.get("error") or "schematic read failed"++ if not board and not sheet:+ return {"success": False, "boardError": board_err, "schematicError": sheet_err,+ "_hint": "Nothing could be read. Pass board:<path> and/or sheet:<path> — Altium holds "+ "only ONE document current, so the review activates each in turn."}+ wanted = args.get("checks")- findings = []- ran = [] unknown = sorted(set(wanted or []) - {n for n, _ in BOARD_CHECKS})+ findings, ran, skipped = [], [], {} for name, fn in BOARD_CHECKS: if wanted and name not in wanted: continue+ needs_sheet = name in ("vendor_part_numbers", "missing_datasheets", "schematic_placeholder_values",+ "duplicate_designators")+ if not board and not needs_sheet:+ skipped[name] = f"no board read ({board_err})"+ continue+ if needs_sheet and not sheet:+ skipped[name] = ("no schematic read" + (f" ({sheet_err})" if sheet_err else+ " — pass includeSchematic:true or sheet:<path>"))+ continue ran.append(name) try: findings.extend(fn(board, sheet))- except Exception as e: # a broken check must not lose the other checks' findings+ except Exception as e: findings.append({"check": name, "severity": "info", "message": f"check {name} failed to run: {e}"}) order = {"error": 0, "warning": 1, "info": 2}- findings.sort(key=lambda f: (order.get(f.get("severity"), 9), f.get("check"), str(f.get("designator") or f.get("net") or f.get("layer") or "")))+ findings.sort(key=lambda f: (order.get(f.get("severity"), 9), f.get("check"),+ str(f.get("designator") or f.get("net") or f.get("layer") or ""))) counts = {} for f in findings: counts[f["severity"]] = counts.get(f["severity"], 0) + 1- out_unknown = {"unknownChecks": unknown} if unknown else {}- return {"success": True, "board": board.get("board"),- "findings": findings, "counts": counts, "checksRun": ran,- "availableChecks": [n for n, _ in BOARD_CHECKS], **out_unknown,- "notImplemented": REVIEW_NOT_IMPLEMENTED,- "roundtripMs": r.get("roundtripMs"),- "_hint": ("A clean result means the checks that RAN found nothing — see notImplemented for "- "what this review cannot see yet (board outline, ratsnest, silkscreen geometry). "- "Add includeSchematic:true to also read the current sheet.")}-+ out = {"success": True, "board": board.get("board"), "sheet": (sheet or {}).get("document"),+ "findings": findings, "counts": counts, "checksRun": ran,+ "availableChecks": [n for n, _ in BOARD_CHECKS],+ "notImplemented": REVIEW_NOT_IMPLEMENTED,+ "_hint": ("A clean result means the checks that RAN found nothing. `skipped` lists checks with "+ "no data; `notImplemented` lists what this review cannot see yet.")}+ if skipped:+ out["skipped"] = skipped+ if unknown:+ out["unknownChecks"] = unknown+ if board_err:+ out["boardError"] = board_err+ if sheet_err:+ out["schematicError"] = sheet_err+ return out def h_read_board(args):