app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
v0.9.133: #31 root cause - stale discovery files at scale poisoned plugin resolution; dead-pid files are now skipped AND deleted inline during resolution, plus a boot-time sweep
6 files changed
+50−7
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.132+0.9.133
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.132",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.132/adom-bridge-kicad-v0.9.132.zip",- "sha256": "dc819a2aeac90a41f6cc25288fabf8859229a097457409b0d695291dd0487151",- "size": 414054,+ "version": "0.9.133",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.133/adom-bridge-kicad-v0.9.133.zip",+ "sha256": "b89504a941f9c10bd884af64e9e66819290ed3751cca4f5b8750f156e1b3aadf",+ "size": 414617, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-16T20:18:14Z",+ "released_at": "2026-08-16T20:19:46Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.133.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.132",+ "version": "0.9.133", "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.",
handlers/bridge_client.py+21@@ -245,6 +245,27 @@ def _resolve_plugin(exe_name: str, pid: int | None = None) -> tuple[dict | None, continue if pid is not None and meta.get("pid") != pid: continue+ # STALE-FILE SELF-CLEAN (#31 root cause, 2026-08-16): dozens of test+ # runs left dead-pid discovery files, and probing every one with an+ # HTTP timeout made resolution slower than callers' budgets — the+ # plugin looked 'not running' while alive. A dead PID is a cheap+ # kernel check: skip AND delete such files inline so the mess never+ # accumulates again.+ m_pid = meta.get("pid")+ if m_pid:+ try:+ import ctypes as _ct+ h = _ct.windll.kernel32.OpenProcess(0x1000, False, int(m_pid))+ if h:+ _ct.windll.kernel32.CloseHandle(h)+ else:+ try:+ path.unlink()+ except OSError:+ pass+ continue+ except Exception:+ pass candidates.append(meta) if not candidates: return None, {
server.py+22@@ -1051,6 +1051,28 @@ def main(): except Exception: pass + # #31 hygiene: dead-pid discovery files accumulate across KiCad restarts+ # and poison plugin resolution at scale — sweep them once per boot.+ try:+ import ctypes as _ct+ import tempfile as _tf+ from pathlib import Path as _P+ for _f in _P(_tf.gettempdir()).glob("adom-kicad-bridge-*.json"):+ try:+ _pid = int(_f.stem.rsplit("-", 1)[-1])+ except ValueError:+ continue+ _h = _ct.windll.kernel32.OpenProcess(0x1000, False, _pid)+ if _h:+ _ct.windll.kernel32.CloseHandle(_h)+ else:+ try:+ _f.unlink()+ except OSError:+ pass+ except Exception:+ pass+ port = DEFAULT_PORT if "--port" in sys.argv: idx = sys.argv.index("--port")