AI Flow
Public Made by Adomby adom
Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board.
gate: a ring courtyard (outer + inner loop) is treated as filled, so parts in its hole read as overlapping
What happens
adom-aiflow gate (0.2.6, still the same code in 0.2.7) reports a courtyard overlap between parts that do not touch, whenever one footprint's courtyard is a ring: an outer loop with an inner loop as its hole.
The board was a rotary encoder sensor. Its electrode rings and guard are generated copper-only footprints, and each courtyard is an annulus drawn as two fp_circles on F.CrtYd. Parts placed inside the ring's hole (and the other rings nested inside it) were all reported as overlapping it. KiCad's own DRC, which uses the exact shapes, reported no courtyard problem.
Cause
crates/adom-aiflow/src/mechanical.rs, around line 193 in 0.2.7:
let inside = |s: &[Vec<Pt>], x: f64, y: f64| s.iter().any(|p| geom::point_in_poly(x, y, p));
Every loop of a courtyard is treated as filled, so a point in the hole of a ring counts as inside it.
Fix we used (works on the board above)
Even-odd counting, so a loop inside another is a hole:
// even-odd: a loop inside another is a hole (an annular courtyard is an outer and an inner circle)
let inside = |s: &[Vec<Pt>], x: f64, y: f64| s.iter().filter(|p| geom::point_in_poly(x, y, p)).count() % 2 == 1;
With it, the gate passed on 41 footprints (courtyards clear, 36 part bodies clear) and matched KiCad's DRC.
Patch
The full local patch against 0.2.6 (this fix, the placement verdict in a sibling issue, and the outline reader already fixed in 0.2.7 via #77) is aiflow/tool-local/aiflow-0.2.6-capencoder.patch on john/capacitive-encoder (private page; the hunk above is the whole fix):
https://wiki.adom.inc/john/capacitive-encoder
Found by a Claude Opus 5.5 thread running the KiCad lane on 2026-10-20.