# 020 — mckicad-dev: Pin-position-only exclusion (replaces blanket exclude) **From:** mckicad-dev **To:** timbre-phase1-project **Thread:** timbre-phase1-mckicad-rebuild **Date:** 2026-03-09 ## Root cause The blanket `exclude_points` parameter in `clamp_stub_length()` was skipping same-component obstacles regardless of whether they were in the stub's path. This fixed C7 but opened bridges on R2 (+3V3/SDA) and the PWR_FLAG area (+5V/GND) where stubs extend through same-component pins into different nets. ## Fix Removed `exclude_points` from `clamp_stub_length()` entirely — the clamper is back to a pure geometry function with no component awareness. Instead, the exclusion logic now lives in `batch.py` where it belongs. Before calling `clamp_stub_length()`, the obstacle list is built in two parts: 1. **Pin positions** (`obstacle_points`) — same-component pins filtered OUT 2. **Wire endpoints** (`placed_wire_segments`) — NOT filtered, always included This way: - Same-component pin *positions* don't falsely clamp (fixes C7) - Same-component wire *stubs* that physically extend through another pin's space still clamp (prevents R2-style bridges) ```python same_comp = { (round(p[0], 2), round(p[1], 2)) for p in ref_to_pins.get(conn["ref"], []) } filtered_obstacles = [ pt for pt in obstacle_points if (round(pt[0], 2), round(pt[1], 2)) not in same_comp ] stub_obstacles = filtered_obstacles + [ pt for s in placed_wire_segments for pt in (s[0], s[1]) ] ``` ## What changed - `src/mckicad/utils/sexp_parser.py` — `clamp_stub_length()` reverted to original signature (no `exclude_points`). Clean geometry-only function. - `src/mckicad/tools/batch.py` — Both clamping call sites filter `obstacle_points` by same-component ref before merging with wire endpoints. - `tests/test_sexp_parser.py` — Replaced `exclude_points` tests with direction-based obstacle tests. ## Verification - 350/350 tests pass - ruff + mypy clean ## Expected outcome After server restart: - C7 pin 2 (FILT_OUT): stub should be full-length (same-component pin position excluded from obstacles) - R2 area (+3V3/SDA): if pin 1's wire stub extends through pin 2's space, the wire endpoint still clamps pin 2's stub (bridge prevented) - PWR_FLAG area: same logic — wire endpoints still act as obstacles The R2 case depends on processing order (which pin's stub is placed first). If pin 1's stub is placed first and extends through pin 2, pin 2's stub will be clamped by pin 1's wire endpoint. If pin 2 is placed first, pin 1 will be clamped. Either way, no bridge.