from __future__ import annotations import json from pathlib import Path import sys PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from config.client import utc_now_iso from config.settings import LOGS_DIR def _read_json(path: Path) -> dict: if not path.exists(): return {} try: return json.loads(path.read_text(encoding="utf-8")) except Exception: return {} def _exists(path: Path) -> dict[str, object]: return { "path": str(path), "exists": path.exists(), "is_dir": path.is_dir() if path.exists() else False, "is_file": path.is_file() if path.exists() else False, } def main() -> int: external_root = PROJECT_ROOT / "external" foxy_probe_report_path = LOGS_DIR / "foxylink_probe_report.json" checks = { "external_root": _exists(external_root), "foxylink_repo": _exists(external_root / "FoxyLink"), "foxylink_src": _exists(external_root / "FoxyLink" / "src"), "foxylink_readme": _exists(external_root / "FoxyLink" / "README.md"), "foxylink_probe_report": _exists(foxy_probe_report_path), "universal_tools_repo": _exists(external_root / "tools_ui_1c"), "universal_tools_src": _exists(external_root / "tools_ui_1c" / "src"), "universal_tools_readme": _exists(external_root / "tools_ui_1c" / "README.md"), "universal_tools_cfe": _exists(external_root / "dist" / "UI.cfe"), "ut_blocker_note": _exists(PROJECT_ROOT / "docs" / "ut_compatibility_blocker_2026-03-22.md"), } gate_report = _read_json(LOGS_DIR / "deep_accounting_mvp_gate.json") slot3_report = _read_json(LOGS_DIR / "slot3_recon_report.json") foxy_probe_report = _read_json(foxy_probe_report_path) gate_verdict = gate_report.get("final_verdict") gate_check2_status = ( gate_report.get("checks", {}) .get("posting_to_subconto123_to_counterparty_contract_item", {}) .get("status") ) slot3_totals = slot3_report.get("totals", {}) slot3_non_null = int(slot3_totals.get("rows_with_non_null_slot3_total", 0) or 0) slot3_joined = int(slot3_totals.get("rows_with_joined_slot3_total", 0) or 0) foxy_probe_classification = str(foxy_probe_report.get("classification") or "") foxy_probe_status = foxy_probe_report.get("response", {}).get("status_code") foxylink_artifacts_ready = all( checks[key]["exists"] for key in ("foxylink_repo", "foxylink_src", "foxylink_readme") ) ut_artifacts_ready = all( checks[key]["exists"] for key in ("universal_tools_repo", "universal_tools_src", "universal_tools_readme", "universal_tools_cfe") ) ut_branch_blocked = checks["ut_blocker_note"]["exists"] slot3_closed = slot3_joined > 0 gate_passed = gate_verdict == "OData sufficient for MVP accounting ontology" foxy_endpoint_reachable = foxy_probe_classification == "reachable" report = { "generated_at": utc_now_iso(), "project_root": str(PROJECT_ROOT), "checks": checks, "gate_summary": { "gate_verdict": gate_verdict, "check2_status": gate_check2_status, }, "slot3_summary": { "rows_with_non_null_slot3_total": slot3_non_null, "rows_with_joined_slot3_total": slot3_joined, "slot3_closed_for_gate": slot3_closed, }, "foxylink_endpoint_summary": { "classification": foxy_probe_classification, "status_code": foxy_probe_status, "reachable": foxy_endpoint_reachable, }, "readiness": { "foxylink_artifacts_present": foxylink_artifacts_ready, "universal_tools_artifacts_present": ut_artifacts_ready, "ut_branch_blocked": ut_branch_blocked, "odata_gate_passed": gate_passed, "ready_for_foxylink_poc": foxylink_artifacts_ready and not gate_passed, "ready_for_foxylink_semantic_probe": ( foxylink_artifacts_ready and foxy_endpoint_reachable and not gate_passed ), }, } output_path = LOGS_DIR / "deeper_access_readiness.json" output_path.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8") print(f"[ok] saved: {output_path}") print( "[ok] readiness: " f"foxylink_artifacts_present={report['readiness']['foxylink_artifacts_present']}, " f"foxy_endpoint_reachable={report['foxylink_endpoint_summary']['reachable']}, " f"ut_branch_blocked={report['readiness']['ut_branch_blocked']}, " f"gate_passed={report['readiness']['odata_gate_passed']}, " f"slot3_joined={slot3_joined}" ) return 0 if __name__ == "__main__": raise SystemExit(main())