Walk every .wom under <zoneDir|projectDir>, run the welded
watertight check from cli_weld + the same edge-analysis as
--info-mesh-stats, and report PASS/FAIL with the per-mesh
failure detail (boundary / non-manifold edge counts).
Exit code is the number of failures (capped at 255), so
CI pipelines can gate on `--audit-watertight $project` and
fail the build if any mesh isn't a closed solid.
Smoke-tested over 61 procedurally-generated WOMs:
• 49 PASS — most stand-alone primitives are watertight
• tent_fixed FAIL with 5 boundary edges = the intentional
door cutout (correct surface count)
• woodpile / bed / well variants FAIL with non-manifold
edges = adjacent stacked cylinders/legs sharing corners
(correct geometry callout)
Defaults to weld eps 1e-4 — a good balance for procedural
output where positions are exact rationals at typical scales.
Continues the modularization. Moves the four audit handlers
(--validate-zone-pack, --validate-project-packs, --info-zone-deps,
--info-project-deps) into their own file using the same
handle<Family>(int& i, int argc, char** argv, int& outRc) pattern.
Side-cleanup: the two project-scope audits had identical
subprocess-fanout structure (enumerate zones → run per-zone
command → tally PASS/FAIL → print summary). Consolidated that
into a shared runPerZoneAudit helper. Saves ~80 lines of
duplicated dispatch code.
main.cpp drops 28,070 → 27,736 lines (-334). Audit family is
fully self-contained (~330 lines), behavior unchanged
(verified all 4 commands against existing test zones).