Commit Graph

128 Commits

Author SHA1 Message Date
Noah Piqué
ef42eb60bb fix: correct pin location calculation and symbol reference dedup in kicad-skip
Three bugs fixed in the schematic component and pin locator pipeline:

1. component_schematic: remove redundant symbol.append() after clone()
   kicad-skip's clone() already inserts the raw element into the schematic
   tree. The subsequent NamedCollection.append() detects the reference as
   already registered (from the elementRename triggered by setting
   property.Reference.value) and renames it "R1_" with a trailing
   underscore, causing all subsequent pin lookups to fail.

2. pin_locator: negate lib y coordinate before rotation
   lib_symbols in .kicad_sch use library y-up convention; schematic
   coordinates use y-down. get_pin_location now negates pin_rel_y before
   applying rotation, matching KiCad's own transform order (same approach
   as _transform_local_point in schematic_analysis.py).

3. pin_locator: add .rstrip("_") guard in all symbol reference lookups
   Defensive guard against any residual cases where kicad-skip writes a
   trailing underscore to the Reference property value.

Also fixes the self-test script to use template_with_symbols.kicad_sch
(which contains placed _TEMPLATE_* symbols) rather than the expanded
template (which only contains lib_symbols definitions and has no cloneable
instances).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:10:47 +02:00
Noah Piqué
ab2500fb8d fix: correct pin location calculation and symbol reference dedup in kicad-skip
Three bugs fixed in the schematic component and pin locator pipeline:

1. component_schematic: remove redundant symbol.append() after clone()
   kicad-skip's clone() already inserts the raw element into the schematic
   tree. The subsequent NamedCollection.append() detects the reference as
   already registered (from the elementRename triggered by setting
   property.Reference.value) and renames it "R1_" with a trailing
   underscore, causing all subsequent pin lookups to fail.

2. pin_locator: negate lib y coordinate before rotation
   lib_symbols in .kicad_sch use library y-up convention; schematic
   coordinates use y-down. get_pin_location now negates pin_rel_y before
   applying rotation, matching KiCad's own transform order (same approach
   as _transform_local_point in schematic_analysis.py).

3. pin_locator: add .rstrip("_") guard in all symbol reference lookups
   Defensive guard against any residual cases where kicad-skip writes a
   trailing underscore to the Reference property value.

Also fixes the self-test script to use template_with_symbols.kicad_sch
(which contains placed _TEMPLATE_* symbols) rather than the expanded
template (which only contains lib_symbols definitions and has no cloneable
instances).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:31:14 +01:00
Eugene Mikhantyev
e06082bb44 chore: normalize schematic.py and apply black to create_schematic signature
Bundles two changes for python/commands/schematic.py:
  1. CRLF → LF line-ending normalization (matches the bulk renormalize
     from the previous commit — was held back here because black would
     also need to re-reformat it).
  2. Black reflow of create_schematic()'s parameter list, which exceeded
     the line length. Pre-existing drift, no logic change.

`git show --ignore-all-space HEAD` shows just the 2-line signature diff.
2026-04-18 15:24:02 +01:00
Eugene Mikhantyev
bfc25639c2 chore: normalize all tracked files to LF line endings
Mechanical application of the `.gitattributes` rules from the prior commit.
All 50 files differ only in line endings — verified by
`git diff --cached --ignore-all-space` being empty.

Before: main had 42 CRLF + 27 LF Python files plus mixed-ending in YAML,
templates, and shell scripts. After: every text file is LF (except the
Windows-native *.ps1, *.bat scripts which remain CRLF per gitattributes).

This eliminates the noisy-diff failure mode seen in PR #102, where a
small logic change produced a 918-line diff due to whole-file CRLF→LF
conversion.
2026-04-18 15:23:00 +01:00
Eugene Mikhantyev
0bc31b2043 refactor: remove dead list_library_symbols stub
The placeholder static method on LibraryManager (library_schematic.py)
returned [] and had no dispatch entry or caller. The real tool of the
same name lives in library_symbol.py.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:14:53 +01:00
Eugene Mikhantyev
4ec63f7544 Merge pull request #107 from mixelpixx/fix/get-symbol-info-spice-opamp
fix: get_symbol_info returns neighboring symbol's data for short blocks
2026-04-18 14:46:49 +01:00
Eugene Mikhantyev
e5cd924b0a Merge pull request #102 from ffindog/fix/netlist-label-at-pin
fix: resolve nets when labels are placed directly at pin endpoints
2026-04-18 14:37:46 +01:00
Tom
a422e4eb0c Merge pull request #87 from tnemrap/fix/create-schematic-path
fix: create_schematic now respects the path parameter
2026-04-18 14:33:58 +02:00
Tom
56e6aead88 Update python/commands/schematic.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-18 14:31:22 +02:00
Eugene Mikhantyev
55ec4950d9 fix: get_symbol_info returns wrong data for every small symbol
Parser used a 5000-char heuristic slice per symbol; any symbol block
shorter than 5000 chars bled into the next one, and last-write-wins in
the properties dict ensured the neighbor's data clobbered the target.
Reported as Simulation_SPICE:OPAMP returning PJFET data.

Switch to parenthesis-depth tracking to find the true end of each
(symbol ...) block. Also surface Sim.Pins so agents can read opamp pin
numbering without inferring it from schematic placement.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 12:55:41 +01:00
Leah Armstrong
101b4e1dad feat: add hierarchy tools (hierarchical label + sheet pin)
Two new tools for managing hierarchical schematic connections:

- add_schematic_hierarchical_label: create sheet interface ports on
  sub-sheet schematics. These are the sub-sheet side of hierarchical
  connections, linking to sheet pins on the parent.

- add_sheet_pin: add pins to sheet symbol blocks on the parent
  schematic. Targets the correct sheet by matching the Sheetname
  property. The pinName must match a hierarchical_label in the
  sub-sheet.

Both tools use text-based S-expression insertion (not sexpdata
round-trip) to preserve KiCad's native file formatting. Labels
include proper justification based on orientation: left-justify for
rightward labels (0°), right-justify for leftward labels (180°).

Wire manager additions:
- _find_insertion_point(): locates sheet_instances block or final paren
- _text_insert(): inserts formatted S-expression text at the right position
- _make_hierarchical_label_text(): generates hierarchical_label S-expression
- _make_sheet_pin_text(): generates sheet pin S-expression
- WireManager.add_hierarchical_label(): static method for label insertion
- WireManager.add_sheet_pin(): static method for pin insertion into
  named sheet blocks

12 unit tests covering insertion, orientation/justification mapping,
parameter validation, multi-sheet targeting, and error handling.
2026-04-15 12:32:09 -04:00
ffindog
ef660afdb4 fix: resolve nets when labels are placed directly at pin endpoints
get_net_connections() built its match-point set exclusively from wire
endpoints. If a net label was placed directly at a pin endpoint with no
wire segment (valid KiCad style), the function returned 0 connections
because connected_wire_points was empty.

Fix: build all_match_points as the union of connected wire endpoints and
label positions. Pin matching checks both, so label-at-pin schematics
produce correct netlists alongside traditional wired schematics.

Also handles the case where the schematic object has no wire attribute
at all — instead of returning early, we continue with label positions
as the sole match points.

Tests: tests/test_label_at_pin_net_connections.py (11 unit tests)
  - label at pin, no wire → pin found
  - label at pin, within/outside tolerance
  - label via wire → still found (regression)
  - mixed wired and direct labels on same net
  - no wire attribute → still detects label-at-pin
  - template symbols skipped

Black/isort/flake8/mypy verified manually (pre-commit local npm hook
fails to install on Windows due to MobaXterm path environment issue).
2026-04-15 22:40:14 +10:00
ffindog
5d87d9bc74 merge: upstream/main (57 commits) — preserve PR #102 net label fix
Merged upstream/main into our fork. Conflict in connection_schematic.py
resolved by taking upstream's file and re-applying our fix:
- all_match_points = connected_wire_points | label positions
- Allows nets where labels are placed directly at pin endpoints (no wire)

Upstream changes include: security fixes (8 vulns), new schematic tools
(get_net_at_point, find_orphaned_wires, snap_to_grid, get_wire_connections),
generate_netlist rewrite via kicad-cli, wire preservation on component move,
schematic analysis tools, KiCad 10 support.
2026-04-15 22:27:41 +10:00
ffindog
00a59a590b fix: resolve nets when labels are placed directly at pin endpoints
get_net_connections() previously required wire segments between net
labels and component pins. If a label was placed exactly at a pin
endpoint (no wire), the net was silently dropped and generate_netlist
returned 0 nets.

Fix: build all_match_points as the union of connected wire endpoints
and label positions. Pin matching now checks both, so label-at-pin
schematics (valid KiCad style) produce correct netlists alongside
traditional wired schematics.
2026-04-15 22:10:22 +10:00
Eugene Mikhantyev
ba09fc4e0f fix: change snap_to_grid default grid from 2.54mm to 1.27mm (50 mil)
Half of all valid KiCAD schematic pin positions are on the 50-mil
(1.27mm) grid but not the 100-mil (2.54mm) grid — e.g. 26.67mm = 21 ×
1.27mm. Snapping to 2.54mm displaced those coordinates by 1.27mm,
moving labels off their pins and increasing floating-label count.

KiCAD source confirms: DEFAULT_CONNECTION_GRID_MILS = 50 and the ERC
off-grid check uses exact integer modulo against this value, so any
displacement breaks connectivity unconditionally.

Also update the kicad-source absolute path in CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 18:10:55 +01:00
Eugene Mikhantyev
1df6332aa8 refactor: address code review issues — remove stale import, fix misleading var name, eliminate redundant adjacency build, add warning log on pin-angle failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 17:32:18 +01:00
Eugene Mikhantyev
4f733bb3db refactor: consolidate get_pin_net into get_wire_connections
get_pin_net was a superset of get_wire_connections with the same
coordinate-based flood-fill but two extra response fields (net, query_point)
and a reference+pin input mode. Having both tools confused LLM tool selection.

get_wire_connections now:
- Returns net (label name or null) and query_point in all response paths
- Accepts reference+pin input in addition to x/y coordinates,
  resolving the pin endpoint via PinLocator internally

get_pin_net tool, handler, schema, TS registration, and tests removed.
test_wire_connectivity.py updated with coverage for all new behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 17:02:35 +01:00
Eugene Mikhantyev
4895bf169c feat: add connected_pin_count to list_schematic_nets and list_floating_labels tool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:46:32 +01:00
Eugene Mikhantyev
e826cf3d32 feat: add get_net_at_point tool for coordinate-based net lookup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:29:46 +01:00
Eugene Mikhantyev
5f3c20d308 feat: add get_pin_net tool for direct net/pin queries
Answers "what net is pin X of component Y on?" without requiring
callers to triangulate from list_schematic_nets or know a wire
coordinate first.

Accepts either {reference, pin} (resolved via PinLocator) or {x, y}
coordinate. Returns net label name (or null for unnamed nets), all
connected pins, wire segments, and the resolved query point.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:19:14 +01:00
Eugene Mikhantyev
9387683368 feat: add snap_to_grid schematic tool
Adds a new MCP tool that snaps wire endpoints, junction positions, and
net label coordinates to the nearest grid point (default 2.54 mm). Off-grid
coordinates cause wires that appear visually connected to fail ERC checks
because KiCAD uses exact IU integer matching internally; this tool eliminates
that class of error before running ERC.

- python/commands/schematic_snap.py: core snap logic with in-place sexp mutation
- python/kicad_interface.py: route + handler
- python/schemas/tool_schemas.py: JSON schema (gridSize, elements params)
- src/tools/schematic.ts: TypeScript MCP tool registration
- tests/test_snap_to_grid.py: 20 unit + integration tests (all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:03:35 +01:00
Eugene Mikhantyev
58bb08a252 feat: add find_orphaned_wires schematic analysis tool
Detects wire segments with at least one dangling endpoint — an endpoint
not connected to a component pin, net label, or another wire.  These
cause ERC 'wire end unconnected' violations and are a common symptom of
incomplete routing or stray stub wires.

Algorithm uses exact KiCad IU (10 000 IU/mm) coordinate matching,
consistent with wire_connectivity.py:
  1. Build an endpoint-frequency map for all wires (IU precision)
  2. Collect anchored IU points: component pins (via PinLocator),
     net labels / global_labels, power symbol pins
     (via _parse_virtual_connections)
  3. An endpoint is dangling when it is touched by exactly one wire AND
     is not an anchored point; the containing wire is reported

Does not require the KiCad UI to be running.

Changes:
  python/commands/schematic_analysis.py — find_orphaned_wires() function
  python/kicad_interface.py             — handler + route registration
  python/schemas/tool_schemas.py        — MCP schema entry
  src/tools/schematic.ts                — TypeScript server.tool() call
  tests/test_schematic_analysis.py      — 7 integration tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:44:12 +01:00
Eugene Mikhantyev
94125eda7f fix: add pin-snapping and coordinate feedback to net label tools
add_schematic_net_label now accepts optional componentRef + pinNumber to
snap the label directly to the exact pin endpoint via PinLocator, removing
all approximation risk.  The response always includes actual_position and,
when snapping was used, snapped_to_pin — so the caller gets confirmation
of exactly where the label landed.

connect_to_net return type changed from bool to Dict, returning
pin_location, label_location, and wire_stub on success so agents no
longer need a separate verification call to confirm placement.

connect_passthrough updated to check result.get("success") against the
new dict return.  tool_schemas.py and schematic.ts updated to match
(position is now optional, componentRef/pinNumber/labelType/orientation
added, connect_to_net schema field names corrected).

17 new unit tests in tests/test_net_label_pin_snapping.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:12:11 +01:00
Michael Parment
01011487d0 fix: merge upstream type annotations into create_schematic signature
Combined our path parameter fix with upstream's type annotation additions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:43:13 +02:00
Michael Parment
b3ca93a98d fix: create_schematic now respects the path parameter
Previously the path argument to create_schematic() was accepted by the
tool schema but silently ignored in SchematicManager.create_schematic()
(python/commands/schematic.py). The schematic file was always written
using only the bare filename, resolving to the MCP server's working
directory.

On systems where that directory is not writable (e.g. Program Files,
OneDrive-synced folders) this caused:
  [Errno 13] Permission denied: 'myproject.kicad_sch'

Fix:
- Add path: Optional[str] = None parameter to SchematicManager.create_schematic()
- Compute output_path as os.path.join(path, base_name) when path is given
- Forward the resolved path from _handle_create_schematic() into create_schematic()

Tests: added tests/test_create_schematic_path.py with three unit tests
covering: path respected, no-path fallback, and no double-suffix on .kicad_sch names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:27:53 +02:00
Eugene Mikhantyev
9b1024a8f3 chore: enable strict mypy checks and fix pre-commit mypy hook
Add type annotations to all previously untyped functions and remove 9
suppressed error codes (call-arg, assignment, return-value, operator,
has-type, dict-item, misc, list-item, annotation-unchecked) by fixing
the underlying type issues.

Add [[tool.mypy.overrides]] with ignore_missing_imports for KiCAD-specific
modules (pcbnew, sexpdata, skip, cairosvg, kipy, PIL) so the pre-commit
mypy hook passes in its isolated venv. Add types-requests and pytest to
additional_dependencies in .pre-commit-config.yaml.

Also fixes several real bugs uncovered by stricter checks: incorrect static
calls to instance methods in swig_backend, wrong return type on get_size,
missing value param in BoardAPI.place_component, variable shadowing in
kicad_process.py, unqualified LibraryManager reference in kicad_interface,
and missing top-level Path import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 23:50:54 +01:00
William Viana
0bc00b1451 fix: prevent pcbnew stdout noise from causing sync_schematic_to_board timeouts
The TS<->Python communication channel uses stdout for JSON responses.
pcbnew's C++ SWIG layer can write warnings and diagnostics directly to
C-level stdout (fd 1), corrupting the JSON framing. The TS parser then
never sees valid JSON and the command times out after 30 seconds.

Three changes fix this:

1. Python stdout redirect: In main(), save the original stdout fd for
   exclusive JSON response use, then redirect fd 1 to stderr so all
   pcbnew C++ output goes to logs instead of the response pipe.

2. Robust TS JSON parser: tryParseResponse() now uses newline-delimited
   parsing as a fallback. The Python side writes single-line JSON
   terminated by \n; the parser uses this as the completion signal
   instead of brace-matching, which prevents premature resolution of
   truncated chunked responses. Non-JSON preamble lines are logged
   and stripped.

3. Fix stray print() calls: Converted print() to logger in
   component_schematic.py and library_schematic.py so they don't
   leak to stdout during normal operations.

Also adds sync_schematic_to_board to the longRunningCommands list for
an appropriate timeout value.
2026-04-03 11:24:42 -07:00
Eugene Mikhantyev
d58283ef0a feat: synthesize wires for touching-pin connections on component move
When moving a schematic component whose pins directly touch pins of
stationary components (no wire segment, just pin-to-pin contact),
synthesize bridge wires to preserve the electrical connection after
the move. Also fixes duplicate-pin-position collision in old_to_new
map and updates symbol reference assignment to use setAllReferences.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 23:41:42 +01:00
Eugene Mikhantyev
a152b75db3 feat: move_schematic_component with wire preservation (drag behavior)
When moving a schematic component, connected wires are stretched/shifted
to follow the component (like KiCAD's drag behaviour), preserving
connectivity instead of leaving dangling wire stubs.

Also fixes property labels (value, reference, etc.) so they shift with
the symbol rather than staying at their original positions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 20:34:22 +01:00
Eugene Mikhantyev
c44bd9205d style: sort Python imports with isort
Add isort configuration (profile=black, line_length=100) to pyproject.toml,
add isort pre-commit hook, and auto-sort imports across all Python source files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:02:24 +01:00
Eugene Mikhantyev
75cead0860 style: apply Black formatting to all Python files
Add [tool.black] config to pyproject.toml and Black hook to
.pre-commit-config.yaml (rev 26.3.1), then auto-format all Python
source and test files with line-length=100, target-version=py310.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:01:08 +01:00
Eugene Mikhantyev
eee5bfb9ed chore: set up pre-commit framework with general hooks
Add .pre-commit-config.yaml with pre-commit-hooks v5.0.0 (trailing
whitespace, end-of-file fixer, yaml/json checks, large file guard,
merge conflict detection). Add minimal pyproject.toml. Auto-fix
trailing whitespace and missing end-of-file newlines across the
codebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 12:58:36 +01:00
Eugene Mikhantyev
3e84957698 style: apply Black formatting to pin_locator.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 12:38:17 +01:00
Eugene Mikhantyev
7d53272cb1 fix: replace hardcoded contributor paths in __main__ blocks
Replace /home/chris/... absolute paths with Path(__file__)-relative
equivalents in wire_manager.py and pin_locator.py so the test
scripts work on any machine.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 12:28:27 +01:00
Eugene Mikhantyev
038beb6d26 refactor: use module-level Symbol constants in delete_wire and delete_label
Replace inline Symbol() allocations with the existing _SYM_WIRE/_SYM_PTS/_SYM_XY
constants and new _SYM_AT/_SYM_LABEL constants for consistency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 12:22:54 +01:00
Eugene Mikhantyev
a11dd5fac9 style: apply Black and Prettier formatting to PR-changed files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 12:22:54 +01:00
mixelpixx
a76c5bc74b Merge pull request #61 from Mehanik/fix/tool-schema-descriptions
feat: add_schematic_wire & add_schematic_junction with pin snapping and polyline routing
2026-03-28 15:40:58 -04:00
mixelpixx
ac1ea89eb5 Merge pull request #74 from mfiumara/feature/move-component-layer-option
Add layer option to move_component tool
2026-03-27 20:31:13 -04:00
George Evangelopoulos
7ab88adaed kicad_mod parser 2026-03-27 20:22:17 +01:00
George Evangelopoulos
b467d1cff9 fixed broken tool due to naming inconsistencies 2026-03-27 19:52:54 +01:00
Mattia Fiumara
dd388470be Add layer option to move_component to support flipping components
Adds an optional `layer` parameter (e.g., 'F.Cu', 'B.Cu') to the
move_component tool. When specified, the component is flipped to
the target layer if it's not already on it. The response now also
includes the component's layer after the move.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 18:09:24 +01:00
mixelpixx
b02c3ba6fe Merge pull request #71 from LeahArmstrong/fix/jlcpcb-download-and-search
fix: JLCPCB database download and FTS search

Thanks! you rock.  JLCPCB parts things has been a headache. I will look over the whole implementation this weekend.
2026-03-24 20:53:27 -04:00
Eugene Mikhantyev
3bd3c3a962 feat: add wire/junction tools with pin-snapping and T-junction support
- Rename add_schematic_connection → add_schematic_wire with waypoints[] parameter
- Add snapToPins (default true) to snap wire endpoints to nearest pin
- Expose add_schematic_junction as an MCP tool
- Break existing wires at new wire endpoints for T-junction support
- Remove orphaned add_connection / add_wire / get_pin_location from ConnectionManager
- Update tool registry to reflect renamed schematic tools in TS layer
- Add 76 tests for wire/junction handler dispatch, schema validation, and WireManager corner cases
- Apply Black and Prettier formatting to changed files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 21:46:36 +00:00
Eugene Mikhantyev
9f89437918 chore: apply Black formatting and add tests for get_wire_connections
- Apply Black formatting to wire_connectivity.py, kicad_interface.py,
  and tool_schemas.py (changed files only)
- Add python/tests/conftest.py with pcbnew/skip C-extension stubs
- Add python/tests/test_wire_connectivity.py with 29 unit tests covering
  schema validation, handler dispatch, parameter validation, and core
  logic (_to_iu, _parse_wires, _build_adjacency, _find_connected_wires,
  get_wire_connections)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:26:25 +00:00
Eugene Mikhantyev
018f4a278d refactor: switch get_wire_connections to exact IU matching throughout
Remove the 0.5mm query tolerance in favour of exact integer-unit matching
on all coordinate lookups (seed, label bridging, pin matching), mirroring
KiCad's own connectivity algorithm. Callers must supply exact wire endpoint
coordinates (e.g. from list_schematic_wires).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
8414784b78 docs: clarify get_wire_connections requires endpoint coordinates
Update tool description and Python docstring to make clear that the
query point must be at a wire endpoint or junction — midpoints of
wire segments are not matched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
de0eca2ed7 refactor: remove redundant junction processing from wire connectivity
Shared-endpoint adjacency already connects all wires meeting at the same
point, making explicit junction handling a no-op duplicate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
f120034846 refactor: extract wire connectivity into module with KiCad-native IU matching
Move wire connectivity logic from _handle_get_wire_connections into
commands/wire_connectivity.py. Use KiCad's internal integer unit system
(10,000 IU/mm) with exact coordinate matching instead of tolerance-based
float comparison, mirroring how KiCad itself determines connectivity.

Key improvements:
- Exact integer matching for wire endpoints (O(1) dict lookup vs O(n) grid scan)
- Junction support for T-connections
- Multi-unit symbol support (removed incorrect processed_refs dedup)
- Single public API: get_wire_connections()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Leah Armstrong
ca40a2b332 fix: JLCPCB database download and FTS search
The JLCSearch API (jlcsearch.tscircuit.com) /components/list.json
endpoint ignores the offset parameter, returning the same 100 parts
on every request. This caused download_jlcpcb_database to loop
indefinitely, importing duplicate data for hours while blocking the
single-threaded Python process.

- Add download_jlcpcb.py: standalone script that downloads the
  pre-built jlcparts database from yaqwsx/jlcparts GitHub Pages
  (~1GB compressed, 7M+ parts, completes in ~4 minutes)
- Fix FTS search: add prefix wildcards to search terms so partial
  MPN matches work (e.g. "BQ25895" now finds "BQ25895RTWR")
2026-03-24 12:04:29 -04:00
Eugene Mikhantyev
59bd4c4acf style: apply Black formatting to changed files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 21:37:05 +00:00