← Commit history

v0.9.93: kicad_show_* family (Fusion fusion_show_* parity) — one clean verb per surface: symbol/footprint/3d_chip/schematic/2d_board/3d_board/library

John Lauer ·6fcf58a02e ·2mo ago ·parent 8f165af
7 files changed +160−9
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.92+0.9.93
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.92",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.92/adom-bridge-kicad-v0.9.92.zip",-  "sha256": "8e5b2159ed87fad4a7e0b1be7a6d912bda21c61d9c87251e1e4a5bdfdff5383e",-  "size": 385143,+  "version": "0.9.93",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.93/adom-bridge-kicad-v0.9.93.zip",+  "sha256": "aa2783fe9d50896d4ee466cb4cd4f25bbff25cffa9eacff1bf4133edb71cd5b5",+  "size": 387661,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-14T18:49:19Z",+  "released_at": "2026-08-14T18:53:13Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
adom-bridge-kicad-v0.9.93.zipadded
⋯ 1 unchanged line ⋯
bridge.json+9−2
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.92",+  "version": "0.9.93",   "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.",   "homepage": "https://wiki.adom.inc/adom/adom-bridge",   "author": "Adom Inc.",@@ -65,7 +65,14 @@     "kicad_demo",     "kicad_launch",     "kicad_uninstall",-    "kicad_state"+    "kicad_state",+    "kicad_show_symbol",+    "kicad_show_footprint",+    "kicad_show_3d_chip",+    "kicad_show_schematic",+    "kicad_show_2d_board",+    "kicad_show_3d_board",+    "kicad_show_library"   ],   "statusVerb": "kicad_status",   "timeouts": {
handlers/show.pyadded+104
@@ -0,0 +1,104 @@+"""show.py — kicad_show_* verbs: one clean, self-documenting verb per KiCad+surface, so a caller (ab, a web demo, an AI) NEVER hand-assembles a workflow.++Mirrors the Fusion bridge's fusion_show_* family (#24 follow-up, John 2026-08-14):+the bridge is the expert on which window shows what, so it owns a named verb for+each surface instead of making callers guess file types / editor combos.++The six surfaces a hardware person thinks in, plus library browse:++  kicad_show_symbol      -> Symbol Editor at a symbol (or a library)   [design/lib]+  kicad_show_footprint   -> Footprint Editor at a footprint (or a library)+  kicad_show_3d_chip     -> 3D Viewer of the FOOTPRINT (single part in 3D)+  kicad_show_schematic   -> Schematic Editor on a .kicad_sch+  kicad_show_2d_board    -> PCB Editor (2D) on a .kicad_pcb+  kicad_show_3d_board    -> 3D Viewer of the BOARD (whole assembly in 3D)+  kicad_show_library     -> Symbol OR Footprint Editor filtered to a library++Every one is a thin, arg-normalizing wrapper over the existing open_* handlers —+same background-first behavior, same verified loads — but with an obvious name+and an obvious argument. All accept the KiCad analogue of Fusion's deviceset:+symbolName/footprintName (+ optional libraryName), or filePath for the docs.+"""+from handlers.open_files import handle_open_board, handle_open_schematic+from handlers.open_symbol_editor import handle_open_symbol_editor+from handlers.open_footprint_editor import handle_open_footprint_editor, handle_open_3d_viewer+++def handle_show_symbol(kicad_info: dict, args: dict) -> dict:+    """Show a schematic SYMBOL in the Symbol Editor. Args: symbolName (+ libraryName),+    or libraryName alone to browse a library."""+    r = handle_open_symbol_editor(kicad_info, args or {})+    r.setdefault("surface", "symbol")+    return r+++def handle_show_footprint(kicad_info: dict, args: dict) -> dict:+    """Show a FOOTPRINT in the Footprint Editor. Args: footprintName (+ library),+    or library alone to browse."""+    r = handle_open_footprint_editor(kicad_info, args or {})+    r.setdefault("surface", "footprint")+    return r+++def handle_show_3d_chip(kicad_info: dict, args: dict) -> dict:+    """Show a single part in 3D — the FOOTPRINT's 3D view (Fusion's Create3DPackage+    analogue). Loads the footprint first if footprintName is given, then its 3D viewer."""+    a = dict(args or {})+    if a.get("footprintName") or a.get("footprint") or a.get("library"):+        loaded = handle_open_footprint_editor(kicad_info, a)+        if not loaded.get("success") and not loaded.get("editorOpened"):+            loaded["surface"] = "3d_chip"+            return loaded+    r = handle_open_3d_viewer(kicad_info, {**a, "editor": "fp"})+    r.setdefault("surface", "3d_chip")+    return r+++def handle_show_schematic(kicad_info: dict, args: dict) -> dict:+    """Show a SCHEMATIC (2D) in the Schematic Editor. Args: filePath (.kicad_sch)."""+    r = handle_open_schematic(kicad_info, args or {})+    if isinstance(r, dict):+        r.setdefault("surface", "schematic")+    return r+++def handle_show_2d_board(kicad_info: dict, args: dict) -> dict:+    """Show the 2D BOARD LAYOUT in the PCB Editor. Args: filePath (.kicad_pcb)."""+    r = handle_open_board(kicad_info, args or {})+    if isinstance(r, dict):+        r.setdefault("surface", "2d_board")+    return r+++def handle_show_3d_board(kicad_info: dict, args: dict) -> dict:+    """Show the whole board in 3D — the BOARD's 3D viewer. Opens the board first if+    filePath is given, then the PCB 3D viewer."""+    a = dict(args or {})+    if a.get("filePath"):+        opened = handle_open_board(kicad_info, {"filePath": a["filePath"],+                                                "reason": a.get("reason", "show 3D board")})+        if isinstance(opened, dict) and not opened.get("success"):+            opened["surface"] = "3d_board"+            return opened+    r = handle_open_3d_viewer(kicad_info, {**a, "editor": "pcb"})+    r.setdefault("surface", "3d_board")+    return r+++def handle_show_library(kicad_info: dict, args: dict) -> dict:+    """Browse a LIBRARY (symbol or footprint). Args: libraryName (+ kind:'symbol'|'footprint',+    default 'symbol'). No part is loaded — the tree is filtered to the library."""+    a = dict(args or {})+    lib = a.get("libraryName") or a.get("library")+    if not lib:+        return {"success": False, "error": "libraryName is required",+                "_hint": "kicad_show_library {\"libraryName\":\"Device\"} — add kind:\"footprint\" for the footprint side."}+    kind = (a.get("kind") or "symbol").lower()+    if kind in ("footprint", "fp"):+        r = handle_open_footprint_editor(kicad_info, {"library": lib, "timeout": a.get("timeout")})+    else:+        r = handle_open_symbol_editor(kicad_info, {"libraryName": lib, "timeout": a.get("timeout")})+    if isinstance(r, dict):+        r.setdefault("surface", "library")+    return r
server.py+30
@@ -30,6 +30,8 @@ from capabilities import build_capability_report from handlers.open_files import handle_open_board, handle_open_schematic from handlers.open_symbol_editor import handle_open_symbol_editor from handlers.open_footprint_editor import handle_open_footprint_editor, handle_open_3d_viewer+from handlers.show import (handle_show_symbol, handle_show_footprint, handle_show_3d_chip,+    handle_show_schematic, handle_show_2d_board, handle_show_3d_board, handle_show_library) from handlers.software_opengl import handle_enable_software_opengl from handlers.diagnostics import handle_diagnostics from handlers.close_windows import (@@ -219,6 +221,27 @@ _VERB_CATALOG = {         "hint": "Absolute filePath to a board; opens the 3D viewer. Follow with screenshot_all to capture it.",         "related": ["kicad_open_board", "kicad_screenshot_all", "kicad_close_3d_viewer"],         "pitfalls": ["3D models only render if the footprints reference installed 3D model files", "the viewer takes a few seconds to render — wait before screenshotting"]},+    "show_symbol": {"summary": "Show a schematic symbol in the Symbol Editor (design/library surface).", "long": True,+        "hint": "kicad_show_symbol {\"symbolName\":\"R\",\"libraryName\":\"Device\"} — verified background load. libraryName alone browses the library.",+        "related": ["kicad_show_footprint", "kicad_show_3d_chip", "kicad_show_library"], "pitfalls": ["the symbol must be in an installed sym-lib-table library"]},+    "show_footprint": {"summary": "Show a footprint in the Footprint Editor.", "long": True,+        "hint": "kicad_show_footprint {\"footprintName\":\"R_0603_1608Metric\",\"library\":\"Resistor_SMD\"}. library alone browses.",+        "related": ["kicad_show_symbol", "kicad_show_3d_chip"], "pitfalls": ["cold Footprint Editor spawns a fresh pcbnew + loads all fp libs — allow ~20-30s"]},+    "show_3d_chip": {"summary": "Show a single part in 3D (the footprint's 3D view).", "long": True,+        "hint": "kicad_show_3d_chip {\"footprintName\":...,\"library\":...} loads the footprint then its 3D viewer. No args = 3D of whatever footprint is loaded.",+        "related": ["kicad_show_footprint", "kicad_show_3d_board"], "pitfalls": ["software-OpenGL boxes render slowly; the window can self-raise late (guarded)"]},+    "show_schematic": {"summary": "Show a schematic (2D) in the Schematic Editor.", "long": True,+        "hint": "kicad_show_schematic {\"filePath\":\"...kicad_sch\"}. Prefer kicad_lint_schematic first for unfamiliar files.",+        "related": ["kicad_show_2d_board", "kicad_show_3d_board"], "pitfalls": ["absolute Windows path; no %VAR% expansion"]},+    "show_2d_board": {"summary": "Show the 2D board layout in the PCB Editor.", "long": True,+        "hint": "kicad_show_2d_board {\"filePath\":\"...kicad_pcb\"}. Prefer kicad_lint_board / kicad_run_drc first.",+        "related": ["kicad_show_3d_board", "kicad_show_schematic"], "pitfalls": ["absolute Windows path; no %VAR% expansion"]},+    "show_3d_board": {"summary": "Show the whole board in 3D (the board's 3D viewer).", "long": True,+        "hint": "kicad_show_3d_board {\"filePath\":\"...kicad_pcb\"} opens the board then its 3D viewer. No filePath = 3D of the open board.",+        "related": ["kicad_show_2d_board", "kicad_show_3d_chip"], "pitfalls": ["3D render self-raise is late on slow boxes — the focus guardian handles it"]},+    "show_library": {"summary": "Browse a symbol or footprint library (no part loaded).", "long": False,+        "hint": "kicad_show_library {\"libraryName\":\"Device\"} (add kind:\"footprint\" for the fp side). Filters the tree to the library.",+        "related": ["kicad_show_symbol", "kicad_show_footprint"], "pitfalls": ["the library must be registered in the sym-/fp-lib-table"]},     "close_symbol_editor": {"summary": "Close the Symbol Editor window.", "long": False,         "hint": "Closes the Symbol Editor if open; no-op otherwise.",         "related": ["kicad_open_symbol_editor", "kicad_close"], "pitfalls": ["unsaved edits may prompt — save first if you made changes"]},@@ -455,6 +478,13 @@ COMMAND_HANDLERS = {     "open_symbol_editor": handle_open_symbol_editor,     "open_footprint_editor": handle_open_footprint_editor,     "open_3d_viewer": handle_open_3d_viewer,+    "show_symbol": handle_show_symbol,+    "show_footprint": handle_show_footprint,+    "show_3d_chip": handle_show_3d_chip,+    "show_schematic": handle_show_schematic,+    "show_2d_board": handle_show_2d_board,+    "show_3d_board": handle_show_3d_board,+    "show_library": handle_show_library,     "close_symbol_editor": handle_close_symbol_editor,     "close_footprint_editor": handle_close_footprint_editor,     "close_3d_viewer": handle_close_3d_viewer,
skills/kicad-bridge-test/run_verb_tests.py+11−1
@@ -130,6 +130,15 @@ def matrix(w: dict) -> dict:                                   note="e2e load of a stock footprint (needs the 0.9.84 lib self-heal)"),         "open_3d_viewer":    dict(phase=3, args={"reason": "daily verb test"}, timeout=200),         "open_editors":      dict(phase=3, args={}, check="editors_listed"),+        # ---- phase 3b: show_* surface verbs (Fusion-parity clean names)+        "show_symbol":       dict(phase=3, args={"symbolName": "R", "libraryName": "Device"}, check="ok", timeout=160),+        "show_footprint":    dict(phase=3, args={"footprintName": "R_0603_1608Metric", "library": "Resistor_SMD"}, timeout=180),+        "show_3d_chip":      dict(phase=3, args={}, timeout=200, note="3D of the loaded footprint"),+        "show_schematic":    dict(phase=3, args={"filePath": S, "reason": "verb test"}, timeout=160),+        "show_2d_board":     dict(phase=3, args={"filePath": B, "reason": "verb test"}, timeout=160),+        "show_3d_board":     dict(phase=3, args={"reason": "verb test"}, timeout=200),+        "show_library":      dict(phase=3, args={"libraryName": "Device"}, timeout=160),+         "state":             dict(phase=3, args={"maxWidth": 640}, check="state_shots", timeout=160,                                   note="#22: every KiCad window as inline base64 + logical state"),         "window_info":       dict(phase=3, args={}),@@ -355,7 +364,8 @@ def main():         print(f"  kicad_{verb:24} {'PASS' if passed else 'FAIL'}")      PHASE3_ORDER = ["launch", "open_board", "open_schematic", "open_symbol_editor",-                    "state",+                    "show_schematic", "show_2d_board", "show_symbol", "show_footprint",+                    "show_3d_chip", "show_3d_board", "show_library", "state",                     "open_footprint_editor", "open_3d_viewer", "open_editors",                     "window_info", "screenshot_all", "dismiss_dialogs", "send_key",                     "click", "bridge_call"]