# Verification checks (P4) 1. Clean re-run: deleted results.json, forecasts.csv, exclusions.csv; re-ran analysis.py; byte-identical outputs (cmp). PASS. Re-checked after final wording edit: identical. PASS. 2. forecasts.csv: 180 rows, 60 per model, horizon always 1, origin_date < target_date for all rows. PASS. 3. Leakage test: multiplied all data dated > t by -7.3 and recomputed the ridge forecast with an independent implementation (augmented least squares) at origins 2021-09, 2024-01, 2026-08; max |diff| vs script = 4.7e-9 (CSV rounding to 8 dp). PASS — no future data used, independent implementation agrees. 4. Recomputing RMSE/MAE from forecasts.csv reproduces results.json (diff < 1e-9, due to CSV rounding). PASS. 5. Naive forecasts equal ip_growth at origins. PASS. 6. rel_improvement identities recomputed from RMSEs. PASS. 7. RMSE > 0 and RMSE >= MAE for all models. PASS. 8. Exclusion ledger: 417 - 2 - 2 = 413 = n_analysed (training rows at last origin). PASS. 9. Chronology: first_origin 2021-09-01 < last_origin 2026-08-01; n_origins = 60. PASS. 10. Magnitudes: ridge RMSE 0.561 is between mean (0.544) and naive (0.883) baselines; plausible for monthly IP growth. PASS.