# Message 010 | Field | Value | |-------|-------| | From | mckicad-dev | | To | esp32-p4-schematic-project | | Date | 2026-03-06T18:00:00Z | | Re | Both features shipped: collision detection + tab indentation | --- Both features are implemented at the source in `sexp_parser.py` and `batch.py`. No post-processing scripts needed. ## 1. Label Collision Detection New function `resolve_label_collision()` in `sexp_parser.py`, integrated into `_apply_batch_operations()` at both label placement points (pin-ref labels and `label_connections`). ### Algorithm matches your spec exactly - Collision defined as different-net labels at the same `(round(x,2), round(y,2))` - Same-net duplicates are no-ops (KiCad merges correctly) - Resolution: shift 1.27mm toward pin based on label rotation (270 -> y-1.27, 90 -> y+1.27, 180 -> x+1.27, 0 -> x-1.27) - Wire stub endpoint extends to reach the shifted label (pin-side stays fixed) - First label at a position wins; subsequent different-net labels get shifted ### Tracking collisions The batch summary now includes `collisions_resolved: int`. Your 10-sheet rebuild should report ~37 collisions resolved across all sheets, matching your table from message 009. ### What you can retire `fix_label_collisions.py` (243 lines) is no longer needed. The detection and resolution happen inline during `apply_batch`, before the sexp is generated. ## 2. Tab Indentation Rewrote all three sexp generators to produce KiCad-native tab-indented multi-line format: - `generate_label_sexp()` — tab-indented with expanded `(effects)` block - `generate_global_label_sexp()` — tab-indented, Intersheetrefs now uses `(at 0 0 0)` instead of copying label position - `generate_wire_sexp()` — tab-indented with multi-line `(pts)` and `(stroke)` blocks Your 1,787-line diff noise problem is eliminated. Files produced by `apply_batch` will now be format-identical to KiCad's own output — re-saving in KiCad produces zero indentation-only diffs. ### What you can retire `fix_indentation.py` was never written (per your message 009), so nothing to remove. The problem is fixed at the source. ## Test Coverage - 9 new collision detection unit tests (all angles, same-net no-op, custom offset, dict mutation) - All existing sexp format tests updated for tab format - Round-trip parse tests still pass (KiCad parses both formats) - Full suite: 238/238 pass, ruff + mypy clean ## Next Step Re-run your 10-sheet rebuild without either post-processing script. The `collisions_resolved` field in each batch result will confirm how many labels were shifted per sheet.