← Commit history

Update 4 file(s)

John Lauer ·5bcdf40872 ·1mo ago ·parent 6918556
4 files changed +52−13
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.209\ No newline at end of file+0.9.210\ No newline at end of file
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.209",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.209/adom-bridge-kicad-v0.9.209.zip",-  "sha256": "4386290016fec8694f8d2f384c1698ce0e4fae92c1249a499b6349599ce82aed",-  "size": 477661,+  "version": "0.9.210",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.210/adom-bridge-kicad-v0.9.210.zip",+  "sha256": "c06dc627507b8fe6d94afa33475f36af0602e319682ebf2e79cf5e1e3501228a",+  "size": 478408,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-20T14:05:00Z",+  "released_at": "2026-08-20T14:25:00Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.209",+  "version": "0.9.210",   "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/kicad_ui.py+45−6
@@ -101,6 +101,21 @@ _SHOT_MAX_FILES = 300           # and a hard ceiling for a heavy test day # stepShots are simply bigger, so the same count now costs far more disk. What a # user actually cares about is megabytes, so cap those too. _SHOT_MAX_BYTES = 40 * 1024 * 1024++# 0.9.210 (John, 2026-08-20: "step files could be up to 200mb"). Two hazards the+# size cap introduced, both worth naming because a janitor that deletes the+# wrong file is far worse than a directory that grows:+#+#  1. It deleted ANY file it found. Nothing but this bridge's own captures should+#     ever be removed by it. STEP/WRL/GLB exports live under+#     Documents/adom-part-exports today, so they are not in the blast radius -+#     but "not today" is not a safety property. Only files this bridge NAMED are+#     eligible now, matched on prefix AND extension.+#  2. A single file larger than the whole cap made the trim loop delete every+#     other file and still finish over budget - maximum destruction, zero+#     benefit. An oversized file is now left alone and REPORTED instead.+_SHOT_PREFIX = "kicad"+_SHOT_EXTS = (".png", ".bmp", ".webp") _last_prune = 0.0  @@ -118,12 +133,15 @@ def prune_screenshots(force: bool = False) -> dict:     _last_prune = now     removed = 0     freed = 0+    report_foreign: dict = {}+    report_oversized: list = []     for d in (SCREENSHOT_DIR,) + _LEGACY_SCREENSHOT_DIRS:         try:             if not os.path.isdir(d):                 continue             legacy = d != SCREENSHOT_DIR             entries = []+            skipped_foreign = 0             for name in os.listdir(d):                 fp = os.path.join(d, name)                 try:@@ -132,7 +150,14 @@ def prune_screenshots(force: bool = False) -> dict:                     continue                 if not os.path.isfile(fp):                     continue+                # OURS ONLY. A file we did not write is never ours to delete.+                if not (name.lower().startswith(_SHOT_PREFIX)+                        and name.lower().endswith(_SHOT_EXTS)):+                    skipped_foreign += 1+                    continue                 entries.append((st.st_mtime, st.st_size, fp))+            if skipped_foreign:+                report_foreign[d] = skipped_foreign             entries.sort()             # A retired directory is drained entirely; the live one keeps a window.             doomed = list(entries) if legacy else [@@ -144,11 +169,18 @@ def prune_screenshots(force: bool = False) -> dict:                     keep = keep[len(keep) - _SHOT_MAX_FILES:]                 # Then trim by SIZE, oldest first, so one heavy run cannot leave                 # tens of megabytes behind just because it stayed under the count.-                total = sum(sz for _mt, sz, _fp in keep)+                # Leave any single file that is bigger than the entire cap: it+                # can never be trimmed INTO budget, and chasing it would delete+                # everything else for nothing.+                oversized = [e for e in keep if e[1] > _SHOT_MAX_BYTES]+                trimmable = [e for e in keep if e[1] <= _SHOT_MAX_BYTES]+                if oversized:+                    report_oversized.extend(os.path.basename(e[2]) for e in oversized)+                total = sum(sz for _mt, sz, _fp in trimmable)                 i = 0-                while total > _SHOT_MAX_BYTES and i < len(keep):-                    doomed.append(keep[i])-                    total -= keep[i][1]+                while total > _SHOT_MAX_BYTES and i < len(trimmable):+                    doomed.append(trimmable[i])+                    total -= trimmable[i][1]                     i += 1             for _mt, size, fp in doomed:                 try:@@ -164,8 +196,15 @@ def prune_screenshots(force: bool = False) -> dict:                     pass         except Exception:             pass-    return {"removed": removed, "freedMB": round(freed / 1048576.0, 1),-            "dir": SCREENSHOT_DIR}+    out = {"removed": removed, "freedMB": round(freed / 1048576.0, 1),+           "dir": SCREENSHOT_DIR}+    if report_foreign:+        out["leftAlone"] = report_foreign+        out["_hint"] = ("Files this bridge did not write were found here and NOT touched. "+                        "The janitor only removes its own captures (kicad*.png/.bmp/.webp).")+    if report_oversized:+        out["oversizedKept"] = report_oversized+    return out  # KiCad window title keywords (wxWidgets windows use class wxWindowNR) KICAD_TITLE_KEYWORDS = [