Feature Audit Report — SoccerPredictAI¶
Date: 2026-04-28
Auditor: GitHub Copilot (Claude Opus 4.7) — /skill-ml-system-audit full (audit 02/12)
Scope: Feature pipeline — engineering, leakage, contract, train ↔ inference consistency
Baseline: docs/validation/20260424/02_feature_audit.md
Delta vs baseline¶
No source files under src/features/, src/pipelines/features.py, src/pipelines/inference.py, or params.yaml modified since 2026-04-26. Baseline findings remain in force.
Confirmed inventory¶
- 4 rolling groups × 5 metrics × 5 windows × 3 sides + ELO ⇒ 363 columns in
features.parquet. - Model input via
select_model_features():side="diff",window_sizes=[1,3],include_elo=True→diff_*(w1, w3) +diff_elo_pre+sex. - Single contract:
features_meta.parquet(built from rolling cols viaparse_feature(), ELO appended afterwards — order verified safe).
Train ↔ inference consistency¶
| Path | Code reuse |
|---|---|
Training (features.py) |
build_team_match_table + add_rolling_features + to_match_level + compute_elo_ratings + select_model_features |
Batch inference (inference.py) |
Same functions — full parity ✅ |
Online POST /predict/ (tasks/predict.py) |
No server-side recomputation — client must supply pre-computed features |
Leakage analysis (re-confirmed)¶
- Rolling:
.shift(1)before.rolling().sum()→ no current-match leakage. Sort key[teamId, startTimeUtc, id]deterministic. - ELO: pre-match ratings only, documented in
elo.pydocstring. - Target:
outcome_1x2inbuild_team_match_tableonly via shifted history.
✅ No leakage detected.
Risk register (re-confirmed)¶
| ID | Severity | Description | Status |
|---|---|---|---|
| F-01 | P1 | Online POST /predict/ relies on client to supply features — no server-side feature contract enforcement |
Open |
| F-02 | P1 | No runtime check that classification.window_sizes ⊆ features.window_sizes — silent NaN risk |
Open |
| F-03 | P2 | select_model_features() API exposes include_h2h / include_rest_days but these features are not implemented |
Open |
| F-04 | P2 | coverage_w{n} columns produced but never selected into model input |
Open |
| F-05 | P3 | No input schema validation in compute_all_match_features() — missing columns become silent NaN/0 |
Open |
Summary¶
| Aspect | Status |
|---|---|
| Rolling features (4 groups) — train/inference parity | ✅ |
| ELO — train/inference parity, no leakage | ✅ |
Single feature contract (features_meta.parquet) |
✅ |
| H2H / rest_days advertised in API | ❌ not implemented |
| Server-side feature recomputation for online predict | ❌ |
| Runtime guard on window_sizes subset | ❌ |
Recommendation: address F-01 (server-side feature lookup or strict request schema validation) and F-02 (assertion at pipeline init) — both protect production from quiet failures.
See baseline §1–§5 for code-level detail.