#!/usr/bin/env python3 from __future__ import annotations import argparse import json import re from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] NUM_RE = re.compile(r"(? str: raw = path.read_text(encoding="utf-8") try: payload = json.loads(raw) except Exception: return raw if isinstance(payload, dict) and isinstance(payload.get("sections"), list): chunks: list[str] = [] for section in payload["sections"]: if isinstance(section, dict): chunks.append(str(section.get("markdown") or "")) return "\n".join(chunks) return raw def _format_candidates(value: Any) -> set[str]: candidates: set[str] = set() if isinstance(value, bool) or value is None: return candidates if isinstance(value, int): candidates.add(str(value)) return candidates if isinstance(value, float): raw = f"{value}" candidates.add(raw) candidates.add(f"{value:.2f}".rstrip("0").rstrip(".")) candidates.add(f"{value:.1f}".rstrip("0").rstrip(".")) candidates.add(str(int(value)) if value.is_integer() else raw) return candidates text = str(value).strip() if text: candidates.add(text) return candidates def _report_contains_any(report_text: str, value: Any) -> bool: for candidate in _format_candidates(value): if candidate and candidate in report_text: return True return False def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--report", default="Temp/operational_report.json") ap.add_argument("--packet", default="Temp/final_decision_packet_active.json") ap.add_argument("--strict", action="store_true") args = ap.parse_args() report_path = Path(args.report) packet_path = Path(args.packet) report_text = _load_text(report_path) packet = json.loads(packet_path.read_text(encoding="utf-8")) mismatches = [] for section_key, field_key in SYNC_KEYS: value = (packet.get(section_key) or {}).get(field_key) if value is None: mismatches.append(f"missing_packet:{section_key}.{field_key}") continue if not _report_contains_any(report_text, value): mismatches.append(f"{section_key}.{field_key}={value}") result = { "formula_id": "REPORT_NUMERICAL_SYNC_V1", "report_number_count": len([m.group(0) for m in NUM_RE.finditer(report_text)]), "packet_sync_field_count": len(SYNC_KEYS), "mismatch_count": len(mismatches), "mismatches": mismatches[:50], "gate": "PASS" if not mismatches else "FAIL", } print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if not mismatches else 1 if __name__ == "__main__": raise SystemExit(main())