app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
← Commit history
Merge PR #305: kicad-lane: release script pushes only the KiCad reference to the EDA Bridge Standard (standard-lane owns the page)
4 files changed
+32−24
rust/README.md+1−1@@ -48,7 +48,7 @@ standard's verbs; `verbs/standard.json` on the standard's page has each one's su `catalog.rs`'s test `every_verb_has_a_standard_decision` fails until every verb is one of the three, and `bridge_json_declares_exactly_the_catalog` fails until `bridge.json` lists it. Each new verb also needs an entry in the verb battery (`skills/kicad-bridge-test/run_verb_tests.py`): the battery fails a catalog verb it does not test.-`tools/build_native_release.py --publish` then syncs `bridge.json` and refreshes the standard's KiCad coverage by itself.+`tools/build_native_release.py --publish` then syncs `bridge.json` and pushes `reference/kicad-<ver>.json` to the standard; the standard-lane thread regenerates the coverage (ping it, pinned issue #3 there). ## Adding a verb
skills/kicad-bridge-dev/SKILL.md+1−1@@ -149,7 +149,7 @@ standard's verbs; `verbs/standard.json` on the standard's page has each one's su `catalog.rs`'s test `every_verb_has_a_standard_decision` fails until every verb is one of the three, and `bridge_json_declares_exactly_the_catalog` fails until `bridge.json` lists it. Each new verb also needs an entry in the verb battery (`skills/kicad-bridge-test/run_verb_tests.py`): the battery fails a catalog verb it does not test.-`tools/build_native_release.py --publish` then syncs `bridge.json` and refreshes the standard's KiCad coverage by itself.+`tools/build_native_release.py --publish` then syncs `bridge.json` and pushes `reference/kicad-<ver>.json` to the standard; the standard-lane thread regenerates the coverage (ping it, pinned issue #3 there). ## Adding a verb (3 places, keep in sync)
skills/kicad-bridge-publish/SKILL.md+8−4@@ -273,8 +273,12 @@ insiders release never writes or pushes it: only `tools/promote.py` does, with a Before `--publish`: the verb battery passes on the test box (`run_verb_tests.py`, which fails any catalog verb it does not test) and `cargo test --workspace` passes (`every_verb_has_a_standard_decision`, the `bridge.json` check).-`build_native_release.py --publish` then syncs `bridge.json`'s verb list to the catalog and refreshes the standard's-KiCad coverage itself: `reference/kicad-<ver>.json` from the release's verbs, `tools/generate.py`, and a push of the-files that moved to adom/eda-bridge-standard. A verb that does a standard job under another name gets an alias in-`catalog::ALIASES` first, or the coverage table does not count it.+`build_native_release.py --publish` then syncs `bridge.json`'s verb list to the catalog and pushes+`reference/kicad-<ver>.json` (the release's verbs) to adom/eda-bridge-standard, and nothing else there. The page+belongs to the standard-lane thread, which regenerates the coverage: after the push, ping it (its session name is in the+page's pinned issue #3) or open an issue titled `kicad-lane: <what>`. Never run the standard's `generate.py` and push its+outputs; the release script prints the coverage it expects instead. A verb that does a standard job under another+name gets an alias in `catalog::ALIASES` first (or an entry in the kicad section of the standard's+`tools/equivalents.json`), or the coverage table does not count it. A job the standard lacks is proposed on an issue+there, then added to `tools/proposed.json` once standard-lane agrees.
tools/build_native_release.py+22−18@@ -257,30 +257,34 @@ def publish_zip(ver, zpath, sha, notes): print(" Boxes pick it up on the 4 h poll, or now with bridge_install {manifestUrl: the insiders version.json, force: true}") def refresh_standard(ver, zpath):- """Write reference/kicad-<ver>.json (this release's verbs, aliases included) into a fresh clone of- adom/eda-bridge-standard, run its tools/generate.py, and push the files that moved. A failure here is- reported, never fatal: the release has already shipped."""- import filecmp, tempfile+ """Push reference/kicad-<ver>.json (this release's verbs, aliases included) to adom/eda-bridge-standard, and nothing+ else: standard-lane owns the page and regenerates its coverage (pinned issue #3 there). The coverage KiCad would+ get is computed in a scratch clone and printed, never pushed. A failure here is reported, never fatal: the release+ has already shipped."""+ import tempfile with zipfile.ZipFile(zpath) as z: verbs = sorted(set(json.loads(z.read("bridge.json"))["verbs"])) base = Path(tempfile.mkdtemp(prefix="eda-std-"))- fresh, pristine = base / "std", base / "pristine"- for d in (fresh, pristine):- r = subprocess.run(["adom-wiki", "repo", "clone", "adom/eda-bridge-standard", "--dir", str(d)], capture_output=True, text=True)- if r.returncode != 0:- print(f"WARNING: could not clone adom/eda-bridge-standard; refresh its KiCad coverage by hand ({r.stderr[-200:]})")- return- (fresh / "reference" / f"kicad-{ver}.json").write_text(json.dumps({"bridge": "kicad", "version": ver, "verbs": verbs}, indent=1) + "\n")- g = subprocess.run([sys.executable, "tools/generate.py"], cwd=fresh, capture_output=True, text=True)- if g.returncode != 0:- print(f"WARNING: the standard's generate.py failed; nothing pushed there: {g.stderr[-300:]}")+ fresh, check = base / "std", base / "check"+ r = subprocess.run(["adom-wiki", "repo", "clone", "adom/eda-bridge-standard", "--dir", str(fresh)], capture_output=True, text=True)+ if r.returncode != 0:+ print(f"WARNING: could not clone adom/eda-bridge-standard; push reference/kicad-{ver}.json by hand ({r.stderr[-200:]})") return- moved = [f"reference/kicad-{ver}.json"] + [f for f in ("verbs/coverage.json", "verbs/standard.json", "docs/coverage.md", "README.md")- if not filecmp.cmp(fresh / f, pristine / f, shallow=False)]- r = subprocess.run(["adom-wiki", "repo", "push", "adom/eda-bridge-standard", "-m", f"KiCad bridge {ver} reference ({g.stdout.strip()})", "--files"] + moved,+ ref = f"reference/kicad-{ver}.json"+ (fresh / ref).write_text(json.dumps({"bridge": "kicad", "version": ver, "verbs": verbs}, indent=1) + "\n")+ r = subprocess.run(["adom-wiki", "repo", "push", "adom/eda-bridge-standard", "-m", f"kicad-lane: KiCad bridge {ver} reference", "--files", ref], cwd=fresh, capture_output=True, text=True) ok = '"ok": true' in r.stdout or "PUSH_UNCHANGED" in r.stdout + r.stderr- print(f"EDA Bridge Standard: {g.stdout.strip()} -> {'pushed ' + ', '.join(moved) if ok else 'push FAILED: ' + (r.stdout + r.stderr)[-300:]}")+ if not ok:+ print(f"EDA Bridge Standard: push of {ref} FAILED: {(r.stdout + r.stderr)[-300:]}")+ return+ # read it back from a second clone, and work out the coverage standard-lane's regeneration will show+ subprocess.run(["adom-wiki", "repo", "clone", "adom/eda-bridge-standard", "--dir", str(check)], capture_output=True, text=True)+ same = (check / ref).exists() and (check / ref).read_text() == (fresh / ref).read_text()+ g = subprocess.run([sys.executable, "tools/generate.py"], cwd=check, capture_output=True, text=True)+ print(f"EDA Bridge Standard: pushed {ref} ({'read back' if same else 'NOT found on a fresh clone'}); "+ f"expected after regeneration: {g.stdout.strip() or g.stderr[-200:]}. Now ping standard-lane to regenerate: "+ f"a SendMessage to the session named in adom/eda-bridge-standard issue #3, or a 'kicad-lane:' issue there.") if __name__ == "__main__":