| Clean re-run (results.json, forecasts.csv deleted, regenerated twice) byte-identical |
PASS |
| forecasts.csv has 144 rows: 36 per (model, horizon) |
PASS |
| target_date − origin_date = horizon months for every row |
PASS |
| Naive forecasts independently recomputed as last non-missing obs <= origin |
PASS |
| Exactly 1 missing actual per (model,horizon) (target 2025-10-01) -> n_evaluated = 35 each, 36−1 |
PASS |
| MAE <= RMSE for every model/horizon; RMSEs > 0 |
PASS |
| rel_improvement = 1 − rmse_model/rmse_naive (computed directly in code) |
PASS |
| Chronology: first_origin 2023-07-01 < last_origin 2026-06-01; training data always truncated to <= origin (s.index <= t in code) |
PASS |
| Exclusion ledger: 945 − 1 − 3 = 941 = n_analysed |
PASS |
| Magnitude vs baseline: model forecasts differ from naive by at most 0.016 pp; model RMSE within 3% of naive |
PASS (plausible: AR(2)-diff coefficients small, intercept ~0) |