← Commit history
dashboard/kicad_dashboard.py+1−1
@@ -49,7 +49,7 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path from urllib.parse import unquote, urlparse -VERSION = "4.7.0"+VERSION = "4.7.1" AI_THREAD = "kicad-dashboard" DEFAULT_PORT = 8931 UI_DIR = Path(__file__).resolve().parent / "ui"
dashboard/ui/newbie-panel.js+32−1
@@ -519,6 +519,37 @@      * fleet mismatch comes back in a form the check is blind to. This asserts the panel's      * left edge against the PANE, which covers the whole ancestor chain in one number.      * (parts-search, 2026-08-25, reasoning about what the new yardstick still could not see.) */+    /* PHRASE HEADROOM AS A ROW, not a console warning nobody reads: "does not truncate TODAY"+     * and "has room" are different claims.+     * MEASURE need AGAINST AN OFFSCREEN nowrap PROBE. Do NOT use clientWidth - scrollWidth:+     * for a block span with overflow:hidden, scrollWidth is max(clientWidth, content), so that+     * expression SATURATES AT 0 for anything that fits, whether it fits by 1px or by 180px. It+     * still goes negative correctly when text overflows, so it looks like a working metric.+     * Two apps independently reported "0px headroom, one character from truncating" off it;+     * remeasured with this probe, neither had less than 141px of slack. A metric that can only+     * return one value on success is not evidence of success. */+    var spans = [].slice.call(panel.querySelectorAll('.anp-phrase span'));+    if (spans.length) {+      var probe = document.createElement('span');+      probe.style.cssText = 'position:absolute;visibility:hidden;white-space:nowrap;font:' ++                            getComputedStyle(spans[0]).font;+      document.body.appendChild(probe);+      var worst = 0, worstTxt = '', tight = 0;+      spans.forEach(function (sp) {+        probe.textContent = sp.textContent;+        var need = Math.ceil(probe.getBoundingClientRect().width);+        var have = Math.round(sp.getBoundingClientRect().width);+        var slack = have - need;+        if (worstTxt === '' || slack < worst) { worst = slack; worstTxt = sp.textContent.trim().slice(0, 40); }+        if (slack < 8) tight++;+      });+      probe.remove();+      var headOk = worst >= 8;+      if (!headOk) ok = false;+      rows.push({ what: 'phrase headroom', want: 'at least 8px of slack on every phrase',+                  got: worst + 'px on ' + JSON.stringify(worstTxt) + (tight > 1 ? ' (' + tight + ' tight)' : ''),+                  pass: headOk });+    }     var fam = getComputedStyle(panel.querySelector('.anp-phrase span') || panel).fontFamily;     var famOk = /Satoshi/.test(fam);     if (!famOk) ok = false;@@ -556,6 +587,6 @@   }    root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, copyText: copyText,-                           checkSend: checkSend, version: '2.17.0',+                           checkSend: checkSend, version: '2.19.1',                            TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "kicad-bridge",-  "version": "1.0.101",+  "version": "1.0.102",   "type": "app",   "description": "Skills for your container so your AI knows how to drive the KiCad bridge. The bridge runtime itself is the release zip; Adom Bridge loads that.",   "tags": [
page.json+1−1
@@ -4,7 +4,7 @@   "slug": "kicad-bridge",   "title": "KiCad - the KiCad Bridge",   "brief": "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.",-  "version": "1.0.101",+  "version": "1.0.102",   "tags": [     "kicad",     "pcb",
skills/kicad-bridge-dev/SKILL.md+33
@@ -425,6 +425,39 @@ the package. Two layers, two commands, every time.  Every one of these came from shipping something that looked verified and was not. +**A metric that returns one value on success proves nothing (2026-08-25).** I+reported "0px phrase headroom, one character from truncating" to the fleet, f7+shipped a whole new selfCheck row for it, and a second app "independently+confirmed" the same 0px. All of it was an artifact. I measured headroom as+`span.clientWidth - span.scrollWidth`, and for a block span with+`overflow:hidden`, `scrollWidth` is `max(clientWidth, content width)`: it returns+EXACTLY 0 for anything that fits, by 1px or by 180px. It saturates. The true+slack on those same six phrases was 141-180px. The second app matched me because+it used the same expression, not because the finding was real - two saturated+readings are one bug reported twice, never a confirmation. Measure width against+an OFFSCREEN nowrap probe (`position:absolute;visibility:hidden;white-space:nowrap`+with the span's computed `font`), which is what the fixed 2.19.0 row does. Before+reporting an unhealthy number, ASK WHAT A HEALTHY ONE LOOKS LIKE - here the answer+was "also 0", and that would have killed the report on the spot. Corollary: when+every value in a set ties, "the minimum" is just DOM order, which is why I named+the wrong phrase as the worst one (the real worst was "show me the board in kicad 3d").++**Force a collapsed pane OPEN before you measure it.** Same family as the+unforegrounded-tab trap. `.anp` carries `hidden`, and every rect in a hidden+subtree is 0, so the first run of the probe above returned `have: 0` and slack+-164 on all six rows - which reads exactly like catastrophic truncation. Set+`panel.hidden = false` (or call the instance's `open()`) and re-measure. Zero is+almost never a measurement; it is the shape of "you measured nothing".++**You can measure a fleet layout claim offline, honestly, if the font travels.**+newbie-panel embeds Satoshi as a base64 woff2, so the font program in my container+is byte-identical to John's. Serving the REAL page (`kicad_dashboard.py serve`) and+loading it in the puppeteer Chrome at `--window-size=734,...` reproduces his exact+geometry (scroller 734, panel 702, 2 columns) with no slot on his machine and no+bridge call. `/usr/bin/chromium-browser` is a snap stub that does not run; use+`~/.cache/puppeteer/chrome/linux-*/chrome-linux64/chrome`. Say plainly that the+number came from headless Chrome, not from his browser.+ **Your container is not a user's container.** `kicad-dashboard` "existed" for months as a 104-byte hand-written wrapper pointing at a dev clone, so `skip_if: command -v kicad-dashboard` reported SKIP on the maintainer's box and RUN on