The committed gate needs frozen, reproducible data without dumping real UK
addresses into the repo. Add:
- harness anonymise_payload + stable_hash: hash street address + cert number
into opaque, dedup-stable tokens; blank secondary address lines + post_town;
keep postcode + all component/lodged fields (gov data is OGL). Unit-tested.
- scripts/build_epc_prediction_fixture.py: curate qualifying postcodes (>=1
SAP 10.2 target + >=2 distinct addresses) from the local scratch corpus,
anonymise, freeze under tests/fixtures/epc_prediction/.
- The frozen fixture: 15 postcodes / 280 certs / 36 SAP-10.2 targets.
Verified no plaintext address_line_1 and post_town all blank.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"One scorer, two harnesses" (ADR-0030): the committed gate, the local script,
and the future battle-test must run the *same* scoring. Extract it:
- domain/epc_prediction/validation.py — `iter_predictions` (the single
leave-one-out orchestration: latest-per-address hold-out, SAP-10.2 target
filter, all-vintage source) + `evaluate_component_accuracy` (calculator-free
ComponentAccuracy aggregation, the primary signal). Unit-tested.
- harness/epc_prediction_corpus.py — `load_corpus(dir)` IO: corpus dir ->
Comparable cohorts (maps payloads, carries address + registration_date).
validate_epc_prediction.py now just loads + calls the scorer for the component
section and iterates iter_predictions for the calculator-floored end-to-end.
Identical numbers (181 targets, SAP MAE 6.34) — behaviour-preserving.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>