validate_schematic now exports a netlist via kicad-cli to traverse the
full sheet hierarchy for connectivity analysis, replacing the single-file
kicad-sch-api approach that returned zeros on hierarchical projects.
Unconnected pins derived from ERC pin_not_connected count.
Combines hierarchy-aware ERC (via root schematic resolution) with
connectivity analysis and optional baseline comparison into one atomic
call. Supports fail_on parameter to gate pass/fail on specific ERC
violation types (default: multiple_net_names). Baseline comparison
detects connection count decreases and unconnected pin increases as
regressions.
Replaces the 20+ tool call workflow of running ERC + connectivity on
each sub-sheet individually.
280/280 tests pass, ruff + mypy clean.
Wire collision detection: apply_batch now tracks placed wire segments and
detects collinear stubs on the same axis with overlapping ranges belonging
to different nets. Colliding wires shift perpendicular to their axis by
1.27mm, preventing KiCad from merging wire segments into mega-nets.
Project-local library resolution: apply_batch now scans batch component
lib_ids for unknown libraries and registers them with kicad-sch-api's
SymbolLibraryCache via sym-lib-table parsing before component placement.
Unblocks projects using Samacsys and other non-standard symbol libraries.
Root ERC: run_schematic_erc accepts root=True to resolve to the project
root schematic before running kicad-cli, enabling hierarchy-aware ERC
that eliminates ~180 false-positive global_label_dangling warnings from
sub-sheet isolation.
270/270 tests pass, ruff + mypy clean.
KiCad 9 nests violations under sheets[].violations instead of
a top-level violations key. The parser now iterates all sheets
and aggregates violations, with a fallback for flat format.
Group results by net name instead of per-pin, keeping the summary
compact enough to stay inline even for 100+ pin components. Add
anomaly detection (unconnected pins, high-fanout nets, auto-named
nets) and optional pin/net filters. Wire coordinates are now opt-in
via include_wires flag to avoid flooding the calling LLM with
coordinate noise.
Refactors _build_connectivity() into a two-layer state builder so the
union-find internals (pin_at, label_at, wire_segments) are accessible
to new analysis tools without duplicating the 200-line connectivity engine.
New tools:
- audit_wiring: trace all wires connected to a component, report per-pin
net membership with wire segment coordinates and connected pins
- remove_wires_by_criteria: bulk-remove wires by coordinate filters
(y, x, min/max ranges, tolerance) with dry_run preview support
- verify_connectivity: compare actual wiring against an expected
net-to-pin mapping, report matches/mismatches/missing nets
New sexp_parser utilities:
- parse_wire_segments: extract (wire ...) blocks with start/end/uuid
- remove_sexp_blocks_by_uuid: atomically remove blocks by UUID set
Root cause: kicad-sch-api doesn't back-populate comp.pins or sch.nets
on loaded schematics. All data is accessible through alternative APIs.
Pin extraction: use comp.get_symbol_definition().pins for metadata and
sch.list_component_pins(ref) for schematic-transformed positions.
Connectivity: new wire-walking engine using union-find on coordinates.
Walks wires, pin positions, labels, and power symbols to reconstruct
the net graph. Replaces broken ConnectivityAnalyzer/sch.nets fallbacks.
Eliminates 'unhashable type: Net' crash.
Hierarchy: use sch.sheets.get_sheet_hierarchy() instead of the broken
sheets.data.get("sheet", []) raw dict approach.
Labels: supplement sch.get_statistics() with sch.labels.get_statistics()
and sch.hierarchical_labels for accurate counts.
99 tests passing, lint clean.