"""Build the per-property inspection report over an EPC-JSON dump, offline. Reads a directory of API-shaped EPC JSON (identical to the EPC API response — what `from_api_response` parses), runs each cert through the Modelling harness, and writes the three-section report (calculator error vs lodged SAP, Plans + costings, recommended measures + their triggers) as Markdown and CSV. No database, no network — run it against a cached dump fetched by `scripts.fetch_epc_dump`. Run from the worktree root so imports resolve to this checkout, not /workspaces/model. # no args -> the committed golden cohort (57 real API certs) python -m scripts.run_property_report # your fetched dump, optional goal band (default C) python -m scripts.run_property_report epc_dump C """ from __future__ import annotations import sys from pathlib import Path _REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap from harness.report import ( # noqa: E402 build_property_reports, format_report_csv, format_report_markdown, parity_report_for, ) _DEFAULT_DIR = _REPO_ROOT / "tests/domain/sap10_calculator/rdsap/fixtures/golden" _MARKDOWN_PATH = Path("property_report.md") _CSV_PATH = Path("property_report.csv") def main() -> None: args = sys.argv[1:] directory = Path(args[0]) if args else _DEFAULT_DIR goal_band = args[1] if len(args) > 1 else "C" paths = sorted(directory.glob("*.json")) if not paths: print(f"no *.json files under {directory}") raise SystemExit(1) print( f"building inspection report over {len(paths)} EPC JSON(s) from " f"{directory} (goal band {goal_band}), offline — no database...\n" ) reports = build_property_reports(paths, goal_band=goal_band) parity = parity_report_for(reports) flagged = sum(1 for report in reports if report.sap_error_exceeds_threshold) errored = sum(1 for report in reports if report.calculator_error is not None) print( f"calculator parity: {parity.case_count} scorable · " f"MAE {parity.global_mae:.2f} · bias {parity.global_bias:+.2f}\n" f"flagged |Δ|>0.5 : {flagged}\n" f"calculator errors: {errored}" ) _MARKDOWN_PATH.write_text(format_report_markdown(reports), encoding="utf-8") _CSV_PATH.write_text(format_report_csv(reports) + "\n", encoding="utf-8") print(f"\nwrote {_MARKDOWN_PATH.resolve()}") print(f"wrote {_CSV_PATH.resolve()}") if __name__ == "__main__": main()