@protoboardai/ext-tscircuit 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +59 -0
  3. package/README.md +493 -2
  4. package/evals/announce-pcb-fallback/case.ts +67 -0
  5. package/evals/catch-swapped-nets/case.ts +69 -0
  6. package/evals/generate-imu-board/case.ts +60 -0
  7. package/evals/locked-board-fix-upstream/case.ts +70 -0
  8. package/lib/checks.ts +464 -0
  9. package/lib/config.ts +384 -0
  10. package/lib/fingerprint.ts +144 -0
  11. package/lib/footprints.ts +370 -0
  12. package/lib/kicad/cli.ts +93 -0
  13. package/lib/kicad/drc.ts +95 -0
  14. package/lib/kicad/fields.ts +65 -0
  15. package/lib/kicad/handoff.ts +112 -0
  16. package/lib/kicad/netlists.ts +311 -0
  17. package/lib/kicad/probe.cjs +21 -0
  18. package/lib/kicad/project.ts +594 -0
  19. package/lib/kicad/refdes.ts +130 -0
  20. package/lib/kicad/schematic.ts +624 -0
  21. package/lib/kicad/sexpr.ts +117 -0
  22. package/lib/land-geometry.ts +177 -0
  23. package/lib/land-patterns.ts +706 -0
  24. package/lib/layout.ts +236 -0
  25. package/lib/models.ts +284 -0
  26. package/lib/native.ts +199 -0
  27. package/lib/outputs.ts +383 -0
  28. package/lib/paste.ts +69 -0
  29. package/lib/probe.cjs +31 -0
  30. package/lib/runtime.ts +185 -0
  31. package/lib/silk.ts +141 -0
  32. package/lib/source.ts +472 -0
  33. package/lib/stepfile.ts +210 -0
  34. package/lib/suppliers.ts +39 -0
  35. package/ops/circuit.ts +270 -0
  36. package/ops/kicad.ts +636 -0
  37. package/ops/package.ts +156 -0
  38. package/package.json +70 -4
  39. package/protoboard-extension.json +313 -0
  40. package/skills/circuit-board/SKILL.md +494 -0
  41. package/skills/circuit-board/references/pcb-workflow.md +87 -0
  42. package/skills/kicad-cli/SKILL.md +210 -0
  43. package/skills/kicad-layout-review/SKILL.md +275 -0
@@ -0,0 +1,210 @@
1
+ ---
2
+ name: kicad-cli
3
+ description: Run KiCad 10's kicad-cli on a Protoboard board's KiCad project — DRC and ERC with JSON reports and exit codes, Gerbers and Excellon drill, position file, STEP and GLB, SVG and PDF plots, netlist, BOM, and file-format upgrade — and know where the results belong (a locked board's circuit:export writes out/ itself; manual runs go to a scratch folder). Also the fallback before lock: when circuit:generate or circuit:export fails, inspect the circuit:kicad preview with these commands while the model and tscircuit stay the truth. Use when checking or exporting from <board>/kicad/ or tscircuit/kicad/, or when circuit:export reports a kicad-cli failure.
4
+ ---
5
+
6
+ # kicad-cli
7
+
8
+ ```
9
+ locked board: src/boards/<b>/kicad/<b>.kicad_pcb ── circuit:export ──▶ out/ (gerber/, pnp.csv, board.step, board.glb, *.svg, drc.json)
10
+ └── manual kicad-cli ─▶ a scratch folder (never out/)
11
+ before lock: circuit:kicad ──▶ src/boards/<b>/tscircuit/kicad/ (a preview, rewritten each time) ── kicad-cli ─▶ scratch
12
+ ```
13
+
14
+ `kicad-cli` is KiCad's command-line tool. The stack declares it as a tool
15
+ (`kicad-cli`, KiCad 10): `circuit:lock` and `circuit:kicad` need it, and
16
+ `circuit:export` of a locked board runs it. This skill is the reference for
17
+ running it by hand: to check a board, to look at a layer, or to see why an
18
+ export failed. The review itself is **kicad-layout-review**.
19
+
20
+ ## Purpose
21
+
22
+ Give an agent the exact KiCad 10 commands, flags, exit codes and report
23
+ formats for a Protoboard board's KiCad project, and the rule for where their
24
+ output may go. Use it after lock for checks and inspection, and before lock as
25
+ a fallback when the tscircuit path fails.
26
+
27
+ ## Inputs
28
+
29
+ | Input | Where |
30
+ | --- | --- |
31
+ | A locked board's project | `src/boards/<b>/kicad/<b>.kicad_pcb`, `<b>.kicad_sch`, `<b>.kicad_pro` |
32
+ | A preview project (any board) | `src/boards/<b>/tscircuit/kicad/`, written by `npx protoboard run circuit:kicad --module <b>` |
33
+ | KiCad 10 | `kicad-cli version` prints `10.x`; `npx protoboard doctor` shows the tool |
34
+
35
+ Flags change between KiCad versions (KiCad 10 dropped HPGL board plots, for
36
+ one). When in doubt, `kicad-cli <group> <command> --help` is the authority.
37
+ Spell help out as `--help`: in `pcb render`, `-h` means height.
38
+
39
+ ## Steps
40
+
41
+ ### 1. Checks
42
+
43
+ ```bash
44
+ P=src/boards/<b>/kicad/<b> # or src/boards/<b>/tscircuit/kicad/<b> for a preview
45
+ S=$(mktemp -d)
46
+
47
+ kicad-cli pcb drc --format json --units mm --severity-all \
48
+ --schematic-parity --refill-zones --exit-code-violations \
49
+ -o "$S/drc.json" "$P.kicad_pcb"
50
+
51
+ kicad-cli sch erc --format json --units mm --severity-all \
52
+ --exit-code-violations -o "$S/erc.json" "$P.kicad_sch"
53
+ ```
54
+
55
+ | Exit | Meaning |
56
+ | --- | --- |
57
+ | 0 | ran; no violations (or `--exit-code-violations` was not given) |
58
+ | 5 | ran; the report lists violations (only with `--exit-code-violations`) |
59
+ | 3 | the input file could not be loaded |
60
+ | 1 | bad arguments (an unknown flag or value); read stderr |
61
+ | other non-zero | another failure; read stderr |
62
+
63
+ Use `--format json` (the default `report` is text for people). The DRC report
64
+ (`$schema` `https://schemas.kicad.org/drc.v1.json`) has `kicad_version`,
65
+ `source`, `coordinate_units`, and three lists: `violations`,
66
+ `unconnected_items` and `schematic_parity`. The ERC report has the same header
67
+ and `sheets[]`, each with `path` and `violations`. Every entry has `type`,
68
+ `severity` (`error`, `warning`, `exclusion`), `description` and `items[]`
69
+ (each with `description`, `pos` {x, y} and `uuid`). Count by severity, group
70
+ by `type`, and name findings by the designator in the item description.
71
+
72
+ `--refill-zones` refills pours in memory before checking; adding
73
+ `--save-board` writes the refill into the board, which is an edit to the
74
+ layout of record: only when the person asks. `--schematic-parity` needs the
75
+ `.kicad_sch` beside the board under the same name.
76
+
77
+ ### 2. Fabrication outputs
78
+
79
+ ```bash
80
+ # Gerbers: always name the layers; with no --layers every layer is plotted (User, Margin, Courtyard too)
81
+ kicad-cli pcb export gerbers -o "$S/gerber/" \
82
+ -l F.Cu,B.Cu,F.Paste,B.Paste,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,Edge.Cuts \
83
+ --subtract-soldermask "$P.kicad_pcb" # 4 layers: add In1.Cu,In2.Cu
84
+
85
+ # Drill, Excellon, mm, plated and non-plated in separate files, with a map
86
+ kicad-cli pcb export drill -o "$S/gerber/" --format excellon \
87
+ --drill-origin absolute --excellon-units mm --excellon-zeros-format decimal \
88
+ --excellon-separate-th --generate-map --map-format gerberx2 "$P.kicad_pcb"
89
+
90
+ # Position file (pick-and-place)
91
+ kicad-cli pcb export pos -o "$S/pos.csv" --format csv --units mm \
92
+ --side both --exclude-dnp "$P.kicad_pcb"
93
+ ```
94
+
95
+ Keep Gerbers, drill and position on the same origin: the commands above all
96
+ use the absolute origin. Add `--use-drill-file-origin` to the Gerbers and the
97
+ position file together, and `--drill-origin plot` to the drill, if a fab wants
98
+ the auxiliary origin. The position CSV columns are `Ref,Val,Package,PosX,PosY,Rot,Side`
99
+ (`Side` is `top` or `bottom`). The project's `out/pnp.csv` is not this file:
100
+ `circuit:export` re-keys it by UHD instance through `tscircuit/refdes.json`.
101
+
102
+ Before calling a board ready, look at every Gerber layer. The quickest way is
103
+ an SVG per layer of the board itself:
104
+
105
+ ```bash
106
+ kicad-cli pcb export svg -o "$S/layers/" --mode-multi --page-size-mode 2 \
107
+ --exclude-drawing-sheet -l F.Cu,B.Cu,F.Mask,B.Mask,F.Silkscreen,B.Silkscreen,Edge.Cuts "$P.kicad_pcb"
108
+ ```
109
+
110
+ ### 3. 3D, plots, netlist, BOM
111
+
112
+ ```bash
113
+ kicad-cli pcb export step -o "$S/board.step" --force --subst-models --no-dnp "$P.kicad_pcb"
114
+ kicad-cli pcb export glb -o "$S/board.glb" --force --subst-models --no-dnp \
115
+ --include-tracks --include-pads --include-zones --include-silkscreen --include-soldermask "$P.kicad_pcb"
116
+
117
+ kicad-cli pcb export svg -o "$S/pcb-top.svg" --mode-single --page-size-mode 2 \
118
+ --exclude-drawing-sheet -l F.Cu,F.Mask,F.Silkscreen,Edge.Cuts "$P.kicad_pcb"
119
+ kicad-cli pcb export svg -o "$S/pcb-bottom.svg" --mode-single --mirror --page-size-mode 2 \
120
+ --exclude-drawing-sheet -l B.Cu,B.Mask,B.Silkscreen,Edge.Cuts "$P.kicad_pcb"
121
+ kicad-cli pcb export pdf -o "$S/pcb.pdf" --mode-multipage -l F.Cu,B.Cu,Edge.Cuts "$P.kicad_pcb"
122
+
123
+ kicad-cli sch export svg -o "$S/sch/" --exclude-drawing-sheet "$P.kicad_sch" # a folder: <b>.svg for the root sheet, <b>-<sheet>.svg for each sub-sheet
124
+ kicad-cli sch export pdf -o "$S/schematic.pdf" "$P.kicad_sch"
125
+
126
+ kicad-cli sch export netlist --format kicadxml -o "$S/netlist.xml" "$P.kicad_sch" # or kicadsexpr (the default)
127
+
128
+ kicad-cli sch export bom -o "$S/bom.csv" \
129
+ --fields 'Reference,Value,Footprint,MPN,Manufacturer,LCSC,UHD_Instance,${QUANTITY}' \
130
+ --labels Refs,Value,Footprint,MPN,Manufacturer,LCSC,Instance,Qty \
131
+ --group-by Value,Footprint,MPN --exclude-dnp "$P.kicad_sch"
132
+ ```
133
+
134
+ STEP and GLB carry the part bodies the footprints link at
135
+ `${KIPRJMOD}/3d/<file>.step`; a body missing there shows as a bare footprint.
136
+ The KiCad BOM is for comparing with the model: the project's `out/bom.csv`
137
+ comes from the model, not from KiCad. `--preset` and `--format-preset` name
138
+ presets saved in the project; none are built in. `--include-excluded-from-bom`
139
+ does nothing in KiCad 10.
140
+
141
+ ### 4. Upgrade
142
+
143
+ ```bash
144
+ cp "$P.kicad_pcb" "$S/" && kicad-cli pcb upgrade "$S/<b>.kicad_pcb"
145
+ cp "$P.kicad_sch" "$S/" && kicad-cli sch upgrade "$S/<b>.kicad_sch" # --force resaves even when already current
146
+ ```
147
+
148
+ Lock already saves both files in KiCad 10's format. Upgrade by hand only to
149
+ read a file from an older KiCad, and on a copy.
150
+
151
+ ## Decision points
152
+
153
+ **Before lock, as a fallback.** This is the fallback the **circuit-board** skill names.
154
+ When `circuit:generate` or `circuit:export` fails on an unlocked board, an
155
+ agent may run `npx protoboard run circuit:kicad --module <b>` and use the
156
+ commands above on `tscircuit/kicad/` to see what is wrong (DRC findings by
157
+ designator, a layer image, the netlist). The preview is rewritten every time
158
+ and is never the layout of record. The UHD model and the tscircuit build stay
159
+ the truth: fix the problem there (the module, `circuit.config.ts`,
160
+ `layout.json`, `footprints.json`, `board.tsx`, per **circuit-board**) and
161
+ generate again. Do not hand-edit the preview to get a board out.
162
+
163
+ If the person wants to finish the board in KiCad instead, that is a lock.
164
+ Locking is a human decision: explain what it changes (KiCad becomes the
165
+ layout of record; `circuit:generate` refuses without `--force`) and ask
166
+ before running `circuit:lock` or `circuit:unlock`.
167
+
168
+ ## Outputs
169
+
170
+ - A locked board's `circuit:export` runs these commands itself and writes
171
+ `out/`. Do not reproduce that by hand, and never write into `out/` or
172
+ `kicad/` from a manual run.
173
+ - Manual runs write to a scratch folder outside the project, for example
174
+ `S=$(mktemp -d)`, and nothing there is committed.
175
+ - `pcb upgrade` and `sch upgrade` rewrite their input file in place; run them
176
+ on a copy unless the person asked for the project to be upgraded.
177
+
178
+ ## Verification
179
+
180
+ ```bash
181
+ kicad-cli version # 10.x
182
+ npx protoboard check --format json # a locked board: CIRCUIT_LOCKED and no CIRCUIT_KICAD_* error
183
+ git status --short src/boards # a manual run left nothing in out/ or kicad/
184
+ ```
185
+
186
+ ## Failure handling
187
+
188
+ | Symptom | Do |
189
+ | --- | --- |
190
+ | `kicad-cli: command not found`, or `circuit:export` says it is missing | Install KiCad 10 (`npx protoboard doctor` names the tool); the locked board cannot export without it |
191
+ | `kicad-cli version` prints 9.x or older | Use KiCad 10; the project is saved in KiCad 10's format |
192
+ | Exit 3 | Wrong path, or a file KiCad cannot parse: `protoboard check` reports `CIRCUIT_KICAD_UNREADABLE`; restore from git |
193
+ | DRC exit 5 | Read `drc.json`; fix in KiCad (**kicad-layout-review**). `circuit:export` stops on a DRC error unless `--force` |
194
+ | `schematic_parity` entries | Run Update PCB from Schematic in KiCad; check reports `CIRCUIT_KICAD_PARITY` |
195
+ | A 3D body missing in STEP/GLB | The file under `kicad/3d/` is missing or the footprint's model path changed |
196
+ | `pcb export hpgl` | Not available in KiCad 10; use SVG or PDF |
197
+
198
+ ## Hard rules
199
+
200
+ 1. Manual output goes to a scratch folder; `out/` belongs to `circuit:export`
201
+ and `kicad/` to the person editing the board.
202
+ 2. No `--save-board` and no in-place `upgrade` of the board of record unless
203
+ the person asked.
204
+ 3. Before lock, the preview is for looking only; the model and tscircuit are
205
+ the truth.
206
+ 4. Ask before `circuit:lock`, `circuit:unlock` or `circuit:lock --input
207
+ refresh=true`.
208
+ 5. Nothing is uploaded or ordered.
209
+
210
+ Source: derived from KiStack (American-Embedded/kistack @ 8494dbd, MIT), rewritten.
@@ -0,0 +1,275 @@
1
+ ---
2
+ name: kicad-layout-review
3
+ description: Review and finish a locked board's layout in KiCad 10 — placement, decoupling loops, return paths, clearances, silkscreen, courtyards, mounting holes, edge clearance, thermal relief and the fab's DFM rules — run DRC and ERC through kicad-cli and read their JSON reports, bring model changes in with Update PCB from Schematic without losing placement, then run protoboard check and act on every CIRCUIT_KICAD_* finding. Use after circuit:lock, when someone asks for a layout review of <board>/kicad/, or when check reports CIRCUIT_LOCKED or a CIRCUIT_KICAD_* code.
4
+ ---
5
+
6
+ # KiCad layout review
7
+
8
+ ```
9
+ UHD board module ── circuit:lock (a human decides) ──▶ <board dir>/kicad/<b>.kicad_pcb (layout of record)
10
+ ▲ │ review, hand edits in KiCad
11
+ │ model changes go here first ▼
12
+ └──────────── check finds CIRCUIT_KICAD_* (handoff record vs model vs KiCad; nothing written back)
13
+ ```
14
+
15
+ Once a board is locked, KiCad holds its layout and tscircuit does not. The
16
+ UHD board module still says what is on the board and how it is connected.
17
+ This skill is the review and finishing pass in KiCad, and the loop that keeps
18
+ KiCad and the model in agreement. Command details for every `kicad-cli` call
19
+ are in the **kicad-cli** skill; the lock itself is in **circuit-board** and the
20
+ spec `docs/specs/pcb-kicad-handoff.md`.
21
+
22
+ ## Purpose
23
+
24
+ Get a locked board to the point where a fab would build it and it would work:
25
+ parts placed for short loops and clean returns, DRC clean against the fab's
26
+ own rules, silkscreen readable, mechanical features where the enclosure
27
+ expects them, and `protoboard check` free of `CIRCUIT_KICAD_*` errors. Use it
28
+ after `circuit:lock`, when asked to review a board in KiCad, and whenever
29
+ check reports a `CIRCUIT_KICAD_*` code.
30
+
31
+ ## Inputs
32
+
33
+ | Input | Where |
34
+ | --- | --- |
35
+ | The KiCad project | `src/boards/<b>/kicad/`: `<b>.kicad_pro`, `<b>.kicad_pcb`, `<b>.kicad_sch`, `<b>.pretty/`, `<b>.kicad_sym`, `3d/` |
36
+ | The handoff record | `src/boards/<b>/kicad/handoff.json` (`state: "locked"`, `lockedAt`, the netlist as handed off) |
37
+ | Reference designators | `src/boards/<b>/tscircuit/refdes.json` (instance path to designator; kept across lock, unlock and re-lock) |
38
+ | The model | `src/boards/<b>/<b>.uhd.ts` and its parts' datasheets (decoupling tables, layout guidelines, thermal pad notes) |
39
+ | Enclosure constraints | `circuit.config.ts` (fixed placements, keep-outs, mounting holes) and **enclosure-cad** |
40
+ | The fab's capabilities | the fab's published minimums for track, space, drill, annular ring, mask web, silkscreen width, board-edge clearance |
41
+ | KiCad 10 | `kicad-cli version` prints 10.x; **kicad-cli** skill |
42
+
43
+ Every symbol and footprint carries `Reference`, `Value`, `Footprint`, `MPN`,
44
+ `Manufacturer`, `LCSC` (when the part has an LCSC offer), `UHD_Instance` and
45
+ `UHD_Part`. Use `UHD_Instance` to get from a designator back to the model.
46
+
47
+ ## Steps
48
+
49
+ ### 0. Before any edit: where the fix belongs
50
+
51
+ KiCad is the last place a board changes, not the first. Protoboard is the
52
+ orchestrator: the model owns the data and the build steps write the KiCad
53
+ project, so do not manage KiCad libraries, symbols or footprints by hand
54
+ unless the job needs something Protoboard cannot do (then say so first, as
55
+ the fallback rule in **circuit-board** asks). Before editing, say in one line
56
+ where each fix belongs, in this order (**circuit-board** step 0):
57
+
58
+ 1. the UHD model (parts, connections, values, designators, MPN and LCSC
59
+ fields, test pads);
60
+ 2. the tscircuit stage (placement, widths, rules, keep-outs, land patterns,
61
+ `circuit.config.ts`);
62
+ 3. the stack (a converter or provider bug: a garbled schematic, mangled pin
63
+ names, wrong silkscreen text; report it with the command and output, do
64
+ not hand-patch the output);
65
+ 4. KiCad: only the hand finish the stages above cannot produce (routing
66
+ touch-ups, final placement nudges, silkscreen).
67
+
68
+ **A locked board is not fixed in place.** When a fix belongs at levels 1 to
69
+ 3, propose unlocking and re-locking rather than editing KiCad, and say
70
+ plainly what that loses: `circuit:unlock` moves `kicad/` to
71
+ `kicad-archive/<stamp>/`, and the hand routing, placement and silkscreen work
72
+ done since `lockedAt` does not come back by itself. The person decides; ask.
73
+
74
+ **Mistakes and design choices.** List each finding as one or the other: a
75
+ mistake (a DRC violation, a wrong net, a value against the datasheet) is
76
+ fixed where it belongs; a design choice (where a part sits, a layer, a
77
+ trade-off made on purpose) is proposed, and you ask before changing it.
78
+
79
+ **Long work, small areas, the router.** Before a long pass (hand-routing many
80
+ nets, re-placing a section), say what it will do and roughly how long it
81
+ takes, and ask when it is optional. When the routing is poor, look for the
82
+ cause first (parts too close, rules that do not fit, a placement that forces
83
+ crossings) and propose that fix before routing by hand. Do not polish a small
84
+ area before asking whether it needs doing at all. Never make placeholder
85
+ footprints or 3D models from datasheets while the part's UHD artifacts or its
86
+ JLC/LCSC source has one; ask first when none does.
87
+
88
+ ### 1. Confirm the state and who is editing
89
+
90
+ ```bash
91
+ npx protoboard check --format json # CIRCUIT_LOCKED (info) for the board; note every CIRCUIT_KICAD_* already present
92
+ ```
93
+
94
+ Only one writer at a time. If the person has the board open in KiCad, do not
95
+ write `<b>.kicad_pcb` yourself: propose changes (designator, position,
96
+ rotation, side, the reason) and let them apply, or wait until they save and
97
+ close. Work on the files in `kicad/`; do not create a second board file
98
+ beside them.
99
+
100
+ ### 2. Take a baseline
101
+
102
+ Run DRC and ERC into a scratch folder (never `out/`, never `kicad/`), as the
103
+ **kicad-cli** skill describes:
104
+
105
+ ```bash
106
+ S=$(mktemp -d)
107
+ kicad-cli pcb drc --format json --severity-all --schematic-parity --refill-zones \
108
+ --exit-code-violations -o "$S/drc.json" src/boards/<b>/kicad/<b>.kicad_pcb
109
+ kicad-cli sch erc --format json --severity-all --exit-code-violations \
110
+ -o "$S/erc.json" src/boards/<b>/kicad/<b>.kicad_sch
111
+ ```
112
+
113
+ Exit 0 means no violations, 5 means the report has some. Read the JSON rather
114
+ than the console text:
115
+
116
+ - DRC: `violations[]`, `unconnected_items[]`, `schematic_parity[]`. Each entry
117
+ has `type` (for example `clearance`, `courtyards_overlap`,
118
+ `copper_edge_clearance`, `silk_over_copper`), `severity`, `description`,
119
+ and `items[]` with the object's `description`, `pos` (mm) and `uuid`.
120
+ - ERC: `sheets[].violations[]`, same entry shape.
121
+
122
+ Group by `type`, count by `severity`, and name each finding by designator so a
123
+ person can find it. `--refill-zones` refills pours in memory only; leave out
124
+ `--save-board` unless the person asked for the refill to be saved.
125
+
126
+ Also export the copper, mask and silkscreen layers as SVG into the same
127
+ scratch folder and look at them, top and bottom.
128
+
129
+ ### 3. Review the layout
130
+
131
+ Work through each point and write down what you found, with the designator,
132
+ the datasheet section that supports the call, whether it is a mistake or a
133
+ design choice, and where its fix belongs (step 0).
134
+
135
+ | Area | What to check |
136
+ | --- | --- |
137
+ | Placement | Parts grouped by function; the MCU's crystal next to its pins; the regulator's input cap, inductor, output cap and feedback divider tight around it as its datasheet's layout example shows; sensitive analog away from switching nodes; parts aligned on a grid, same orientation in a group; nothing on the bottom unless the design calls for it. |
138
+ | Decoupling | Each decoupling capacitor at the pin it serves, smallest value nearest, with the via to ground beside its own pad so the loop (pin, cap, ground via, back) is as small as the board allows. A cap shared across the board is a finding. |
139
+ | Return paths | A continuous ground under every fast or sensitive trace; no split or slot in the plane under a signal that crosses it; stitching vias along pour edges and next to layer-change vias of fast signals; no copper islands left floating. |
140
+ | Clearances | Track, space and via sizes meet the net classes in `<b>.kicad_pro` and the fab's minimums; higher-voltage nets have the spacing their voltage needs. |
141
+ | Silkscreen | Every designator readable, not over pads or vias, not under a part body, one orientation or two at most; pin-1 and polarity marks visible after assembly. |
142
+ | Courtyards | No overlaps (`courtyards_overlap`); room for rework around fine-pitch parts and for the nozzle around tall parts. |
143
+ | Mounting holes | At the positions and diameters in `circuit.config.ts` (the enclosure is built around them); keep copper and parts out of the screw head's and standoff's footprint. |
144
+ | Edge clearance | Copper, pads and vias clear of `Edge.Cuts` by at least the fab's minimum (`copper_edge_clearance`); connectors that a cable mates sit at the edge with their mouth facing out, matching the frames **enclosure-cad** uses. |
145
+ | Thermal | Exposed pads have the via array and paste pattern the datasheet asks for; regulators and power parts have the copper area their dissipation needs; pours to through-hole pins use thermal relief so they can be soldered. |
146
+ | DFM | A second DRC with the fab's rules (step 4). Also acid traps, slivers in pours, annular ring on vias, mask web between fine-pitch pads, and fiducials if the assembler asks for them. |
147
+
148
+ Antenna keep-outs and fixed placements from `circuit.config.ts` still hold
149
+ after the move to KiCad; check them by eye, since KiCad's DRC does not know
150
+ the config.
151
+
152
+ ### 4. DRC against the fab's rules
153
+
154
+ The rules exported at lock come from the config and are looser than a fab's.
155
+ Set the fab's minimums in Board Setup (constraints and net classes) or in a
156
+ custom rules file `<b>.kicad_dru`, then run DRC again. Record which rule set
157
+ and which fab the clean run was against.
158
+
159
+ ### 5. Hand edits
160
+
161
+ Placement, routing, pours, silkscreen and stitching are KiCad edits and stay
162
+ in KiCad. After each meaningful edit, save, then:
163
+
164
+ ```bash
165
+ npx protoboard check --format json
166
+ ```
167
+
168
+ and act on what it reports (table below). Parts and connections are not KiCad
169
+ edits: a pin swap, a new test point, a fiducial, a different value or a
170
+ different package starts in the UHD board module, never only in KiCad.
171
+
172
+ A KiCad edit that a re-lock would lose and the stack cannot make yet (a logo,
173
+ a zone the provider does not draw, a silkscreen note) is recorded as a
174
+ post-lock step in the project's `docs/post-lock.md`: what, why, the exact
175
+ edit, and how to check it. It is applied from that list after every lock,
176
+ never left as a silent hand edit.
177
+
178
+ ### 6. Bring a model change into KiCad
179
+
180
+ Nothing is written back to UHD and nothing is pushed into KiCad
181
+ automatically. When the model changes (a part added or removed, a land
182
+ pattern, a connection, a value or MPN):
183
+
184
+ 1. Make the change in the UHD board module first (**circuit-board** step 1)
185
+ and run `protoboard check`: it reports `CIRCUIT_KICAD_STALE`,
186
+ `CIRCUIT_KICAD_MODEL_CHANGED` or `CIRCUIT_KICAD_FIELDS` with the diff.
187
+ 2. Make the same change in the KiCad schematic: the symbol, its fields
188
+ (`Reference` from `tscircuit/refdes.json`, `Value`, `Footprint` as
189
+ `<b>:<entry>`, `MPN`, `Manufacturer`, `LCSC`, `UHD_Instance`, `UHD_Part`)
190
+ and its connections.
191
+ 3. In the PCB editor run **Tools > Update PCB from Schematic**. Symbols and
192
+ footprints are linked by the symbol's UUID (the footprint's `path`), so
193
+ leave the option that re-links footprints by reference designator off;
194
+ existing footprints keep their positions and routing, and only new
195
+ footprints arrive unplaced. Leave footprint deletion off unless the change
196
+ removed a part, and replace footprints only when the land pattern changed.
197
+ 4. Place and route what is new, run DRC, and run `protoboard check` again.
198
+ The change should now show as `CIRCUIT_KICAD_APPLIED`.
199
+ 5. Ask the person before recording it: `npx protoboard run circuit:lock
200
+ --module <b> --input refresh=true` re-records the handoff from the model and
201
+ the KiCad files as they are now.
202
+
203
+ If the change is large (many parts, a new outline, a re-layout of the
204
+ schematic, renamed pins), say so and propose unlocking, fixing it upstream
205
+ and re-locking instead. Say which KiCad work would be lost (step 0) and which
206
+ post-lock steps would be applied again. Unlocking is the person's decision.
207
+
208
+ ## Decision points
209
+
210
+ | Decision | Rule |
211
+ | --- | --- |
212
+ | A model change since lock | Small (a part, a value, a connection): bring it into KiCad (step 6). Large (many parts, a new outline): propose unlock, fix upstream, re-lock, and say what KiCad work it loses; the person decides |
213
+ | A schematic that reads badly, pin names that are wrong, silkscreen text that is wrong | A converter or provider bug (level 3): report it; do not re-lay out or rename in KiCad, since a re-lock reproduces it |
214
+ | A KiCad edit that must survive a re-lock | A post-lock step in `docs/post-lock.md` (step 5) |
215
+ | A finding the fab's rules allow | Record the fab and the rule; leave it |
216
+ | A fixed placement or keep-out in the way | Ask; it changes only with `circuit.config.ts` |
217
+ | `CIRCUIT_KICAD_APPLIED` | Ask before `circuit:lock --input refresh=true` |
218
+
219
+ ## Outputs
220
+
221
+ | Output | Where |
222
+ | --- | --- |
223
+ | The finished layout | `src/boards/<b>/kicad/` (committed) |
224
+ | Fabrication outputs | `src/boards/<b>/out/` from `circuit:export` (never by hand) |
225
+ | Reports | a scratch folder; the review's findings in your answer |
226
+
227
+ ## Verification
228
+
229
+ ```bash
230
+ npx protoboard check --format json # CIRCUIT_LOCKED only: no CIRCUIT_KICAD_* error or warning
231
+ kicad-cli pcb drc --format json --severity-all --schematic-parity --exit-code-violations -o "$S/drc.json" src/boards/<b>/kicad/<b>.kicad_pcb # exit 0 with the fab's rules
232
+ npx protoboard run circuit:export --module <b> # drc.json in out/ is clean; export does not fail on DRC
233
+ ```
234
+
235
+ Report what you reviewed, what you changed, which findings remain and why,
236
+ and which fab's rules the clean DRC used.
237
+
238
+ ## Failure handling
239
+
240
+ What check reports on a locked board, and what to do:
241
+
242
+ | Code | Means | Do |
243
+ | --- | --- | --- |
244
+ | `CIRCUIT_LOCKED` (info) | KiCad is the layout of record since `lockedAt` | Nothing; review in KiCad, not in tscircuit |
245
+ | `CIRCUIT_KICAD_STALE` (error) | The model added or removed a part, changed a land pattern, the outline, holes, layers or thickness, and KiCad lacks it | Step 6, or propose unlocking |
246
+ | `CIRCUIT_KICAD_MODEL_CHANGED` | Connections between existing parts changed in the model | Rewire in the KiCad schematic, Update PCB from Schematic, reroute |
247
+ | `CIRCUIT_KICAD_FIELDS` | MPN, manufacturer, value or LCSC changed in the model | Update those fields on the symbol, then Update PCB from Schematic |
248
+ | `CIRCUIT_KICAD_APPLIED` (info) | The model change is in KiCad too | Ask, then `circuit:lock --input refresh=true` |
249
+ | `CIRCUIT_KICAD_PART_MISSING` (error) | A part was deleted in KiCad | Restore it (Update PCB from Schematic brings the footprint back); remove a part only in the model |
250
+ | `CIRCUIT_KICAD_PART_EXTRA` | KiCad has a part the model lacks | Add it to the model (a fiducial or test point belongs there) or delete it in KiCad |
251
+ | `CIRCUIT_KICAD_FOOTPRINT_CHANGED` | A footprint was swapped in KiCad | Put the handed-off footprint back, or change the land pattern in the model first |
252
+ | `CIRCUIT_KICAD_NET_RENAMED` | A net was renamed in KiCad, same pins | Restore the model's net name |
253
+ | `CIRCUIT_KICAD_NET_CHANGED` (error) | A pin is on another net in KiCad | Undo it in KiCad; if the new connection is right, change the model first |
254
+ | `CIRCUIT_KICAD_PARITY` | Schematic and board disagree | Update PCB from Schematic; the DRC `schematic_parity[]` list names the parts |
255
+ | `CIRCUIT_KICAD_UNREADABLE` (error) | A KiCad file is missing or does not parse | Restore it from git; re-save from KiCad 10 |
256
+
257
+ ## Hard rules
258
+
259
+ 1. The model is the truth for parts and connections. Make those changes in
260
+ the UHD board module first; KiCad catches up by hand; nothing is written
261
+ back to UHD.
262
+ 2. Locking, unlocking and `refresh=true` are the person's decisions: ask
263
+ before running any of them.
264
+ 3. Never move a part the config fixes, never shrink a mounting hole or keep-out,
265
+ without the person agreeing and the config changing with it.
266
+ 4. Reports and test exports go to a scratch folder, never to `out/` or into
267
+ `kicad/`.
268
+ 5. One writer on `<b>.kicad_pcb` at a time.
269
+ 6. Say where a fix belongs before editing (the model, the tscircuit stage, a
270
+ stack bug, then KiCad). Never fix in KiCad what belongs upstream: propose
271
+ unlock and re-lock, saying what would be lost.
272
+ 7. A KiCad edit that must survive a re-lock is a documented post-lock step,
273
+ never a silent hand edit.
274
+
275
+ Source: derived from KiStack (American-Embedded/kistack @ 8494dbd, MIT), rewritten.