from __future__ import annotations import argparse import json from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] DEFAULT_REPORT = ROOT / "Temp" / "operational_report.json" DEFAULT_OUT = ROOT / "Temp" / "strategy_harness_score.json" def _load(path: Path) -> dict[str, Any]: data = json.loads(path.read_text(encoding="utf-8")) return data if isinstance(data, dict) else {} def _section_map(report: dict[str, Any]) -> dict[str, dict[str, Any]]: rows = report.get("sections") or [] out: dict[str, dict[str, Any]] = {} for row in rows: if isinstance(row, dict): name = str(row.get("name") or "") if name: out[name] = row return out def main() -> int: p = argparse.ArgumentParser() p.add_argument("--report-json", default=str(DEFAULT_REPORT)) p.add_argument("--out", default=str(DEFAULT_OUT)) args = p.parse_args() report_path = Path(args.report_json) out_path = Path(args.out) if not report_path.is_absolute(): report_path = ROOT / report_path if not out_path.is_absolute(): out_path = ROOT / out_path report = _load(report_path) sec = _section_map(report) summary = report.get("summary") if isinstance(report.get("summary"), dict) else {} checks = [ ("routing_trace", "routing_serving_trace" in sec), ("serving_trace_v2", "routing_serving_trace_v2" in sec), ("export_gate_diag", "export_gate_diagnosis" in sec), ("decision_trace", "decision_trace_table" in sec), ("buy_sell_blueprint", "concise_hts_input_sheet" in sec), ("watch_ledger", "reference_price_ledger" in sec), ("fundamental_v1", "fundamental_quality_gate_v1" in sec), ("fundamental_v2", "fundamental_multifactor_v2" in sec), ("horizon_lock", "horizon_allocation_lock_v1" in sec), ("smart_money_liquidity", "smart_money_liquidity_gate_v1" in sec), ("growth_quality", "earnings_growth_quality_v1" in sec), ("market_share_proxy", "market_share_proxy_v1" in sec), ("cashflow_stability", "cashflow_stability_v1" in sec), ("routing_decision_explain", "routing_decision_explain_v1" in sec), ("cash_recovery_plan", "cash_recovery_plan_crdl" in sec), ("heat_present", bool(summary.get("found_heat"))), ("settlement_present", bool(summary.get("found_settlement"))), ("canonical_order_ok", bool(summary.get("canonical_order_ok"))), ("json_validation_status_present", bool(summary.get("json_validation_status"))), ] passed = sum(1 for _, ok in checks if ok) total = len(checks) score = round(passed / total * 100, 2) if total else 0.0 missing = [name for name, ok in checks if not ok] result = { "score_pct": score, "passed": passed, "total": total, "status": "PASS_100" if score == 100.0 else ("PASS" if score >= 95 else "NEEDS_UPGRADE"), "missing": missing, "checks": [{"name": n, "ok": ok} for n, ok in checks], } out_path.parent.mkdir(parents=True, exist_ok=True) out_path.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())