#!/usr/bin/env python3 # Author: Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca """Leakage audit on the built data layer → results/data/leakage_audit.json (exit code 1 if any check fails). python3 scripts/05_leakage_audit.py [--synthetic] [--subjects 300] [--asof-rows 20000] """ from __future__ import annotations import argparse import sys import time import polars as pl from agentic_valuation.config import PROCESSED, RESULTS, SYNTHETIC, load_config from agentic_valuation.data.leakage import audit, to_json def main() -> None: ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("--synthetic", action="store_true") ap.add_argument("--subjects", type=int, default=300) ap.add_argument("--asof-rows", type=int, default=20_000, help="rows (whole municipalities) for the feature-matrix perturbation test") args = ap.parse_args() base = SYNTHETIC if args.synthetic else PROCESSED t0 = time.perf_counter() analytic = pl.read_parquet(base / "analytic.parquet") splits = pl.read_parquet(base / "splits.parquet") subs = pl.read_parquet(base / "llm_subsamples.parquet") matrix = pl.read_parquet(base / "feature_matrix.parquet") if (base / "feature_matrix.parquet").exists() else None geo = pl.read_parquet(base / "geo_features.parquet") if (base / "geo_features.parquet").exists() else None n_by = {"validation": 40, "test": 60, "holdout": 30} if args.synthetic else None report = audit(analytic, splits, subs, matrix, geo, load_config("data"), n_subjects=args.subjects, n_by_split=n_by, asof_sample=args.asof_rows) report["synthetic"] = args.synthetic report["seconds"] = round(time.perf_counter() - t0, 1) out = RESULTS / "data" / ("leakage_audit_synthetic.json" if args.synthetic else "leakage_audit.json") out.parent.mkdir(parents=True, exist_ok=True) out.write_text(to_json(report)) for c in report["checks"]: print(f"[{'PASS' if c['passed'] else 'FAIL'}] {c['name']}: checked={c['n_checked']} failed={c['n_failed']}") print(f"all_passed={report['all_passed']} seconds={report['seconds']} → {out}") sys.exit(0 if report["all_passed"] else 1) if __name__ == "__main__": main()