Two bugs fixed:
1. jq parsed webhook as plain array but payload is {body:{commits:[...]}} —
fell back to Cargo.toml catch-all, triggering full recompile every push.
2. Single needs-compile flag gave no granularity — now split into
needs-services and needs-training with path-based detection.
crates/ml/ only → training + services (ml-training-service depends on ml)
services/ only → services only, skip training (saves ~5.5min CUDA compile)
infra/ only → skip both compiles entirely
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>