feat(pcb): add atomic schematic-to-board update - #215
Conversation
Merge of main plus one blocking fix found by running the PR's own live acceptance test against KiCAD 10.0.5. plan_revision hashed the raw netlist source, and `kicad-cli sch export netlist` stamps (date "...T14:48:16") and its own version into every export. The revision therefore changed EVERY SECOND for a design nobody touched, and since apply requires the revision a dry run returned, apply could only succeed when both calls landed inside the same wall-clock second. Two consecutive dry runs on an unchanged design produced identical plans (68 additions each) and different revisions; the live test failed with stale_plan_revision 1.2s after its own dry run. The revision now covers what the plan reads -- components and nets -- with the volatile export header excluded. Nested (date ...) inside component fields is design content and still counts. A KiCad upgrade no longer invalidates outstanding plans either. Verified against KiCAD 10.0.5 on a disposable copy of the complex_hierarchy demo with its 68 board footprints stripped: dry run `ready` (68 planned) -> apply `applied` -> dry run `noop`, the PR's own acceptance criterion, which failed before this fix and passes after. Independently confirmed by asking KiCad to save its own live state: the board file went 0 -> 68 footprints across 68 distinct references, and kicad-cli DRC parses the result with a live ratsnest. Counts: sch_export 6 -> 7, 196 registered + 6 meta = 202. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Reviewed against the contract, and this implements it faithfully — I checked each ruling in the code rather than against the description:
Then I ran your own acceptance test against KiCAD 10.0.5, and it failed. The blocker: the plan revision changed every second
So the revision moved on the clock, not on the design. Two consecutive dry runs on an untouched design produced identical plans — 68 additions each — and different revisions. Since apply requires the revision a dry run returned, apply could only ever succeed if both calls landed inside the same wall-clock second. Your live test failed for me at That is why it passed for you and failed for me: it is a race, and the losing case is the one that matters — a human reading the plan before applying it, which is the entire point of having a plan. Fixed on your branch ( Verification after the fixDisposable copy of KiCad's Your acceptance criterion, passing. Then, independently of the tool under test, I asked KiCad to save its own live state: the board file went 0 → 68 footprints across 68 distinct references, and Two notes, neither blocking
Excellent work, and thank you for holding implementation until the contract was settled — it made this reviewable in a way a 1,800-line PR usually isn't. Merging once CI confirms. |
|
Follow-up fix pushed in The previous The revision identity now structurally encodes only the parsed top-level Local verification:
|
…xx#170/mixelpixx#199) # Conflicts: # DEV.md # README.md # tool-directory.md
|
Took your structural hash over my string-stripping — yours is right and mine had a real hole: Re-verified live against KiCAD 10.0.5 on a fresh fixture (a second disposable copy of Also rebased the counts — main moved again while this was in review (#170 added the |
A minor: new tools, a new toolset, and update_pcb_from_schematic. Schematic-to-board sync (#187/#215) lands the tool the PCB skill had been instructing for months without it existing. Plan/apply with an explicit revision, one KiCad undo entry per apply. Three data-corruption fixes: (paper "User" W H) was being destroyed on every typed-model write, making the sheet unloadable (#208); netclasses were written into the board file, which KiCad then rejected (#190); and zones landed on net 0 on KiCad 10 boards (#192). Behaviour changes: netclasses and design rules write .kicad_pro; zones refuse an undeclared net and refuse entirely while KiCad holds the board; add_zone no longer returns net_id; annotations upsert rather than append; #PWR numbers are reused after deletion; place_component fails on a footprint with no reference field; the plugin stops its HTTP server on a clean KiCAD exit. 19 toolsets, 200 tools.
Summary
Closes #187.
Adds
update_pcb_from_schematicto thesch_exporttoolset as the accepted live-KiCad, plan/apply workflow:kicad-cli sch export netlist --format kicadsexprready,noop, orconflictfor dry runs and requiresexpected_plan_revisionfor applyattempt_ipc_writein onerun_commit, with no file fallback and one KiCad undo entryDesign and compatibility
The planner is a pure module with focused tests. Export, hierarchy validation, footprint resolution, plan construction, revision validation, and routing preflight all happen before the commit. Only IPC mutations run inside the single commit, and every per-item result propagates with
?so any failure drops the whole batch.This adds one tool without changing existing tool inputs or behavior. Registry/documentation totals move to 189 registered tools plus 6 meta tools (195 total). README, DEV guide, tool directory, troubleshooting, and the bundled KiCad PCB skill are updated together.
Verification
cargo test --workspace --locked --lib --testscargo test --workspace --locked --doccargo clippy --workspace --locked --all-targets -- -D warningscargo fmt --all -- --checkcargo test -p konnect --locked --test live_kicad_tools schematic_sync_apply_then_dry_run_is_noop -- --ignored --exact --nocaptureThe live test verified dry-run
ready-> applyapplied-> dry-runnoopagainst an open board and saved hierarchical schematic.Risk and rollback
The tool is deliberately live-IPC-only. A missing/rejected IPC connection returns a conflict instead of touching the board file. Routed-net changes and unevaluable inputs fail closed before
begin_commit; apply mutations share one KiCad commit, so failures drop the batch and Ctrl-Z reverses a successful sync as one action.