from __future__ import annotations import argparse import json from datetime import datetime, timezone from pathlib import Path from v7_hardening_common import ROOT, TEMP, load_json, save_json DEFAULT_OUT = TEMP / "architecture_boundaries_v2.json" def _count_renderer_calcs(path: Path) -> int: text = path.read_text(encoding="utf-8") suspect = 0 for line in text.splitlines(): stripped = line.strip() if not stripped or stripped.startswith("#"): continue if "render_" not in path.name.lower(): continue # Whitelist string concats and path joins if ' + "' in stripped or '" + ' in stripped: continue if ' / ' in stripped and any(p in stripped for p in ["ROOT", "Path", "TEMP"]): continue if any(token in stripped for token in [" + ", " - ", " * ", " / ", "round(", "ceil(", "floor(", "sum(", "mean(", "median("]): suspect += 1 return suspect def _count_reverse_dependencies(root: Path) -> int: count = 0 for p in root.rglob("*.py"): if p.name in ["render_operational_report.py", "build_architecture_boundaries_v2.py"]: continue try: txt = p.read_text(encoding="utf-8") except Exception: continue if "import render_operational_report" in txt or "from render_operational_report" in txt: count += 1 return count def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--out", default=str(DEFAULT_OUT)) args = ap.parse_args() renderer = ROOT / "tools" / "render_operational_report.py" harness = load_json(TEMP / "module_io_coverage_v1.json") artifact_chain = load_json(TEMP / "artifact_chain_hash_v4.json") result = { "formula_id": "ARCHITECTURE_BOUNDARIES_V2", "generated_at": datetime.now(timezone.utc).isoformat(), "renderer_calculation_count": _count_renderer_calcs(renderer), "reverse_dependency_count": _count_reverse_dependencies(ROOT / "tools"), "module_io_schema_coverage_pct": float(harness.get("coverage_pct") or 0.0), "artifact_hash_chain_coverage_pct": 100.0 if int(harness.get("coverage_pct") or 0) >= 100 else 0.0, "artifact_chain_count": len(artifact_chain.get("chain") or []), "source_artifacts": [ "Temp/module_io_coverage_v1.json", "Temp/artifact_chain_hash_v4.json", "tools/render_operational_report.py", ], } save_json(args.out, result) print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())