← Commit history

Product name out of hints, examples and docs (wiki #118); skills package 1.0.152

John Lauer ·4c212c6642 ·5d ago ·parent 90ddbd0
4 files changed +9−9
docs/esc-routing-astra-prompt.md+1−1
@@ -18,7 +18,7 @@ Rules that are not optional: 4. Read `kicad_routing_state` and plan the routing yourself. Rules of the board: track 0.25 mm and clearance 0.2 mm by default (read the file's setup and netclass blocks and use them), via 0.8 mm with a 0.4 mm drill; signal traces on F.Cu and B.Cu with vias between them; the three phase nets (/DRV_SHA, /DRV_SHB, /DRV_SHC), +VBAT and the MOSFET drain and source connections want 1.0 mm tracks where the space allows and at least 0.5 mm; GND and +3V3 pads are NOT routed as traces: each such SMD pad gets a short stub and a via to its plane (In1.Cu for GND, In2.Cu for +3V3), thru-hole pads already reach the planes. Keep the current sense path (shunt to INA) short and paired. Route the short nets first. A `drc_rejected` means your plan crossed something: change the plan, do not force it. Write your own router or plan by hand; do not copy Claude's plan (it is on the page). 5. Record before the first commit: `desktop_record_start {"monitor": 0, "audio": false, "fps": 30, "reason": "Astra routing the ESC G431", "maxDurationMs": 1800000}`. Then land the plan with `kicad_route_net`, one net per call, passing the previous reply's revision as `expectedRevision`, about a second between calls so a viewer can follow. Do not speed anything up. 6. Finish with `kicad_routing_validate`: it must report the errors and unconnected count truthfully; the take is done only at 0 new errors and 0 unconnected (the 13 inherited library errors on this board, six malformed MOSFET courtyards and seven U2 pad clearances, are known and do not count). Unconnected items are not a result, they are a failed take: do what a human does until the ratsnest is gone. Route the failed nets first, use smaller vias where the rules allow (0.6 mm with a 0.3 mm drill is legal here; keep 0.8/0.4 on +VBAT and the phase nets), rip up and reroute, and when the same pins keep failing go back to placement: move the parts that block the escapes (test points, indicator LEDs and pull-ups out of the 2.5 mm band beyond the MCU's pin rows, the crystal and its two capacitors next to the oscillator pins) with `kicad_move_footprint`, then route again. The kicad-place-route-loop skill in the kicad-bridge package is the checklist. Report every loop you made, and keep the clock running through all of it. Then `desktop_record_stop`, `pull_file` the MP4, check frames at the start, middle and end, transcode to 1920 wide H.264 (`ffmpeg -i in.mp4 -vf scale=1920:-2 -c:v libx264 -crf 22 -pix_fmt yuv420p -movflags +faststart -an out.mp4`), make a poster, push both to the adom/codex page under docs/videos/ (`adom-wiki repo push adom/codex --files ...`), and confirm the MP4 URL returns 200.-6b. Routed is not finished: copper pours come next, before the numbers. Install the kicad-bridge skills package again (`adom-wiki pkg install adom/kicad-bridge`) and read the kicad-copper-pours skill; it says which nets get a pour (ground on both outer layers, the +VBAT rail block, one compact pour per phase, the GND_OUT return through the shunt), which never do (the bootstrap and gate-drive nodes, the crystal, the BEMF dividers and comparator inputs, the sense taps), the priorities, and the offline gate (`tools/add_pours.py` on the kicad-bridge page, then KiCad's DRC). The bridge verbs are new in 1.0.5 (insiders): `kicad_add_zone {filePath, expectedRevision, zones:[{net, layers, polygon, priority, connection}]}` lands the pours as one undo step after a filled DRC preflight, and `kicad_zone_state {filePath, refill:true}` reads back the filled copper per layer, which is the ablation metric (InstaPCB mills the copper away; every square millimetre a pour keeps is copper not removed). On arav-rog install 1.0.4 first: `bridge_install {"manifestUrl":"https://wiki.adom.inc/api/v1/pages/insiders/files/kicad-bridge/version.json","force":true}` and confirm `kicad_status` says 1.0.5. Report the filled copper per layer before and after the pours, and every net you chose not to pour and why. If a pour is choked by a trace or a part, move it (the loop skill) and route again; the clock keeps running.+6b. Routed is not finished: copper pours come next, before the numbers. Install the kicad-bridge skills package again (`adom-wiki pkg install adom/kicad-bridge`) and read the kicad-copper-pours skill; it says which nets get a pour (ground on both outer layers, the +VBAT rail block, one compact pour per phase, the GND_OUT return through the shunt), which never do (the bootstrap and gate-drive nodes, the crystal, the BEMF dividers and comparator inputs, the sense taps), the priorities, and the offline gate (`tools/add_pours.py` on the kicad-bridge page, then KiCad's DRC). The bridge verbs are new in 1.0.5 (insiders): `kicad_add_zone {filePath, expectedRevision, zones:[{net, layers, polygon, priority, connection}]}` lands the pours as one undo step after a filled DRC preflight, and `kicad_zone_state {filePath, refill:true}` reads back the filled copper per layer, which is the ablation metric (the 3rd party fab mills the copper away; every square millimetre a pour keeps is copper not removed). On arav-rog install 1.0.4 first: `bridge_install {"manifestUrl":"https://wiki.adom.inc/api/v1/pages/insiders/files/kicad-bridge/version.json","force":true}` and confirm `kicad_status` says 1.0.5. Report the filled copper per layer before and after the pours, and every net you chose not to pour and why. If a pour is choked by a trace or a part, move it (the loop skill) and route again; the clock keeps running.  7. The numbers, all of them, in the issue. First and most important: (a0) the wall clock from the moment John pasted this prompt to the moment the issue is filed, in minutes. Note the paste time in UTC as your very first action and put both timestamps in the issue; this is the number that goes on the chart, because it is what the human waited. Then, in the shape of https://wiki.adom.inc/api/pages/adom/kicad-bridge/files/demo/placement/fable/fable-stats.json: (a) planning time, first `kicad_routing_state` to first `kicad_route_net`, wall clock; (b) routing time, first commit to last, wall clock, and the number of commits, nets routed, segments, vias and total copper length in mm; (c) the validate result: errors, unconnected, violation types; (d) your session's token usage for this task (input, cached input, output) and the model name; (e) the dollar cost at OpenAI's published per-token price for the model (state the price and where it is published) and that cost as a percentage of a $200 per month plan; (f) sub-agents or worker threads spawned (zero is fine); (g) the bridge calls with timestamps; (h) what you rejected or retried, including any take you discarded. 8. File the issue: `adom-wiki issue create adom/kicad-bridge --category show-and-tell --title "Astra routing video: ESC G431 through kicad_route_net" --body "<video URL, poster URL, the numbers in 7, the exact commands>"`. No em dashes.
handlers/design_rules.py+4−4
@@ -11,7 +11,7 @@ values, it only resolves (fab, layers) to the page's file, stages it next to the board as <board stem>.kicad_dru (the name KiCad loads automatically), and optionally runs DRC so the caller sees the fab's limits applied. -InstaPCB is the house baseline and is listed first.+The 3rd party fab is the baseline and is listed first. """  from __future__ import annotations@@ -37,7 +37,7 @@ def _fetch(url: str) -> bytes: def _index() -> list[dict]:     data = json.loads(_fetch(INDEX_URL).decode("utf-8"))     vendors = data.get("vendors") or []-    # House baseline first, then the page's order.+    # Baseline fab first, then the page's order.     vendors.sort(key=lambda v: 0 if v.get("vendorSlug") == HOUSE_SLUG else 1)     return vendors @@ -79,13 +79,13 @@ def handle_list_design_rules(kicad_info: dict, args: dict) -> dict:         })     return {"success": True, "count": len(rows), "rules": rows, "indexUrl": INDEX_URL,             "_hint": ("Pick a row and call kicad_set_design_rules {\"fab\": <slug>, \"layers\": <n>, \"boardPath\": <.kicad_pcb>}. "-                      "adom-instapcb is the house baseline. Values come from the wiki page at call time, so do not copy them into code.")}+                      "Omit fab for the baseline fab (the 3rd party fab). Values come from the wiki page at call time, so do not copy them into code.")}   def handle_set_design_rules(kicad_info: dict, args: dict) -> dict:     """Stage a fab's KiCad rules file next to a board and (by default) run DRC. -    Args: fab (slug or name; default adom-instapcb), layers (int; default from+    Args: fab (slug or name; default: the baseline fab), layers (int; default from     the board's copper layer count when readable, else 2), process (optional),     boardPath (.kicad_pcb, required), druPath (local override instead of the     wiki file), runDrc (default true), keepExisting (default false: an existing
server.py+3−3
@@ -509,10 +509,10 @@ _VERB_CATALOG = {         "hint": "Splices a footprint into a board via s-expr (no GUI); good for previews.",         "related": ["kicad_open_board", "kicad_install_footprint"], "pitfalls": ["operates on the file — close the board in KiCad first or the edit races the GUI"]},     "list_design_rules": {"summary": "List the fabs / processes / layer counts on adom/pcb-design-rules.", "long": False,-        "hint": "kicad_list_design_rules {\"fab\":\"jlcpcb\"} (fab optional). Rows come from the wiki page at call time; InstaPCB is the house baseline.",+        "hint": "kicad_list_design_rules {\"fab\":\"jlcpcb\"} (fab optional). Rows come from the wiki page at call time; The 3rd party fab is the baseline.",         "related": ["kicad_set_design_rules", "kicad_lint_board"], "pitfalls": ["needs wiki.adom.inc reachable from the desktop"]},     "set_design_rules": {"summary": "Stage a fab's .kicad_dru next to a board and run DRC with it.", "long": False,-        "hint": "kicad_set_design_rules {\"fab\":\"adom-instapcb\",\"layers\":2,\"boardPath\":\"C:/.../x.kicad_pcb\"}. layers defaults to the board's copper count; druPath overrides the wiki file; runDrc:false to only stage.",+        "hint": "kicad_set_design_rules {\"fab\":\"jlcpcb\",\"layers\":2,\"boardPath\":\"C:/.../x.kicad_pcb\"}. layers defaults to the board's copper count; druPath overrides the wiki file; runDrc:false to only stage.",         "related": ["kicad_list_design_rules", "kicad_lint_board", "kicad_run_drc"], "pitfalls": ["replaces an existing <stem>.kicad_dru (backed up next to it); pass keepExisting:true to refuse instead", "an open PCB editor applies the file on its next DRC run"]},     "list_symbols": {"summary": "Names in a registered symbol library, with KiCad's own inventory.", "long": False,         "hint": "kicad_list_symbols {\"libraryName\":\"Adom\"} (default Adom; or libraryPath). Use a returned name as symbolName; the file name is often an MPN, not the symbol name.",@@ -606,7 +606,7 @@ _VERB_CATALOG = {         "hint": "Idempotent, non-interactive, best-effort per item. Removes plugin payload, Adom libraries + lib-table rows, mesa fallback DLLs, discovery files, screenshot cache, demo project. Never touches KiCad itself or user projects. dryRun:true previews.",         "related": ["kicad_bridge_status"], "pitfalls": ["a running KiCad can hold plugin .pyc files open — re-run after it exits if items fail"]},     "export_gerber": {"summary": "Export Gerbers from a board via kicad-cli.", "long": False,-        "hint": "Absolute board path + output dir; writes Gerber + drill files (JLCPCB/InstaPCB ready).",+        "hint": "Absolute board path + output dir; writes Gerber + drill files (JLCPCB / 3rd party fab ready).",         "related": ["kicad_export_step", "kicad_export_bom_csv", "kicad_run_drc"], "pitfalls": ["run kicad_run_drc first — don't ship Gerbers from a board with DRC violations"]},     "export_pdf": {"summary": "Export a PDF plot from a board/schematic.", "long": False,         "hint": "Absolute path + output; plots the doc to PDF via kicad-cli.",
skills/kicad-tour/hero/hero_builder.py+1−1
@@ -183,7 +183,7 @@ def main() -> int:            fill=WHITE, font=font(FG_BOLD, 56))      sub_a = "Send a custom symbol, footprint and 3D model into KiCad on the user's laptop."-    sub_b = "Open the schematic. Place the board. Render in 3D. Export gerbers to JLCPCB / InstaPCB."+    sub_b = "Open the schematic. Place the board. Render in 3D. Export gerbers to JLCPCB / 3rd party fab."     d.text((PAD, badge_y + badge_h + 14 + 64), sub_a,            fill=(220, 230, 232), font=font(SAT_REGULAR, 19))     d.text((PAD, badge_y + badge_h + 14 + 64 + 28), sub_b,