Highlights:
* New `centroid_xyz` / `vertex_count` / `triangle_count` columns on
`instances.parquet` — Phase 1a of the federated-model clash-control
feature. Lets agents compose cross-model duplicate detection and
broad-phase clash candidate filtering as pure DuckDB queries against
the substrate. Cache schema bumped 4 -> 5.
* New `ifcfast.clash(bundle_dir, tolerance_m=0.0, ...)` Python
primitive. Reads the substrate, broad-phases via parry3d AABB
overlap, narrow-phases candidate pairs as true mesh-mesh
intersection / distance, writes `clashes.parquet`. Tolerance and
output are always in metres regardless of source file linear unit.
* New `geom` kernel module (parry3d 0.17 + nalgebra 0.33) — engine
layer for the clash work and the upcoming cut-openings / OOBB /
PCA features. Foundation, not a one-off.
* New `ifcfast-clash BUNDLE_DIR [--tolerance N]` binary mirroring
the Python entry.
* Substrate parquet files now carry `ifcfast.unit_scale` and
`ifcfast.version` as parquet schema metadata. Backwards-compatible.
* Wheel default features now include `bundle`, `geom`, and `clash`
so the substrate writer and clash engine work out of the box on
`pip install ifcfast`.
See CHANGELOG.md for the full diff and AGENTS.md for the
substrate-output + narrow-phase-clash sections.