← Commit history

v0.9.191: SDK #38 canonical response contract - windowEtiquette enum replaces openedInBackground, errorCode foreground_reason_required replaces _foregroundRefused; old keys retained for the migration window

John Lauer ·a3d6dacd96 ·1mo ago ·parent 4f2cf2c
5 files changed +23−10
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.190+0.9.191
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.190",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.190/adom-bridge-kicad-v0.9.190.zip",-  "sha256": "236a0956ddb424a4137f079597f585193aabad886f56f0c1990601d9e471be00",-  "size": 459265,+  "version": "0.9.191",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.191/adom-bridge-kicad-v0.9.191.zip",+  "sha256": "5ac6c8bcff75ef1f8a701ff2b70b21e2d1255c118d16bc1265f6c02b8fcd956e",+  "size": 459559,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-19T20:53:17Z",+  "released_at": "2026-08-19T21:14:02Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
adom-bridge-kicad-v0.9.191.zipadded
⋯ 1 unchanged line ⋯
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.190",+  "version": "0.9.191",   "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.",
server.py+16−3
@@ -933,14 +933,27 @@ def dispatch_command(command: str, args: dict) -> dict:                 pass             if isinstance(result, dict):                 result["_broughtToUser"] = bool(_shown)+                # SDK #38: what a caller BRANCHES on is a contract and gets a+                # stable non-underscore key; what it merely reads stays a _hint.+                # So a refusal is an errorCode, not a doc string, and where the+                # window went is an enum rather than a boolean that cannot grow.+                result["windowEtiquette"] = "foreground" if _shown else "background"                 if not _shown:-                    result["_foregroundRefused"] = ("foreground requested without foregroundReason - "-                                                   "pass foregroundReason:'<why the user needs to see this>' "-                                                   "and the bridge will caption it for 3s, then foreground.")+                    result["errorCode"] = "foreground_reason_required"+                    result["_foregroundRefused"] = (   # deprecated, migration window+                        "foreground requested without foregroundReason - "+                        "pass foregroundReason:'<why the user needs to see this>' "+                        "and the bridge will caption it for 3s, then foreground.")+                    result["_hint"] = (+                        "errorCode foreground_reason_required: re-call with foreground:true AND "+                        "foregroundReason:'<why the user needs to see this>'.")             _user_fg = None  # don't also restore-away what the user just asked to see         elif command in _SPAWNS_WINDOW and isinstance(result, dict) and result.get("success", True):             # John's contract (2026-08-16): ALWAYS tell the calling AI that the             # window opened in the BACKGROUND and exactly how to foreground it.+            # SDK #38 canonical key; openedInBackground kept for the migration+            # window so a pinned runner does not break, deprecated on sight.+            result.setdefault("windowEtiquette", "background")             result.setdefault("openedInBackground", True)             result.setdefault("_foregroundHint",                               "Window opened in the BACKGROUND - the user's foreground was not "