_build_connectivity() used sch.list_component_pins() which returns
empty for custom library symbols. Added a second pass that falls back
to parse_lib_symbol_pins() + transform_pin_to_schematic() for any
component that returned 0 pins from the API. This brings custom IC
pins (e.g. ESP32-P4's 105 pins) into the union-find net graph.
kicad-sch-api has two parsing gaps: get_symbol_definition() returns
None for non-standard library prefixes (e.g. Espressif:ESP32-P4),
and there is no sch.global_labels attribute for (global_label ...)
nodes. This adds a focused parser that reads directly from the raw
.kicad_sch file as a fallback, integrated into the connectivity
engine, pin extraction, and label counting tools.
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.
New modules:
- patterns/ library: decoupling bank, pull resistor, crystal oscillator
placement with power symbol attachment and grid math helpers
- tools/batch.py: atomic file-based batch operations with dry_run
- tools/power_symbols.py: add_power_symbol with auto #PWR refs
- tools/schematic_patterns.py: MCP wrappers for pattern library
- tools/schematic_edit.py: modify/remove components, title blocks, annotations
- resources/schematic.py: schematic data resources
43 new tests (99 total), lint clean.