#!/usr/bin/env python3 """Freeze the selected-case evidence index without hiding blockers.""" from __future__ import annotations import hashlib import json from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] REPORT = ROOT / "coverage/axis3-tutorial-closure-index.report.json" INPUTS = ( Path("coverage/axis3-tutorial-complete.report.json"), Path("coverage/axis3-tutorial-native-run.report.json"), Path("coverage/axis3-tutorial-tool-io.report.json"), Path("coverage/axis3-tutorial-sequence.report.json"), Path("coverage/axis3-tutorial-persistence.report.json"), Path("coverage/gui-browser-visual-fe-m4.report.json"), ) def canonical(value: Any) -> str: return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) def generate() -> dict[str, Any]: reports = {path.as_posix(): json.loads((ROOT / path).read_text(encoding="utf-8")) for path in INPUTS} sequence = reports["coverage/axis3-tutorial-sequence.report.json"] statuses = {path: report.get("status") for path, report in reports.items()} report: dict[str, Any] = { "schema": "axis3-tutorial-closure-index.v1", "task_id": "TUTORIAL-14", "context_id": "linuxcnc-2.10.0-pre0-wasm-m1-py-c1", "case": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial", "entrypoint": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini", "scope": "selected-case-only", "status": "blocked" if sequence.get("status") == "blocked" else "verified", "implementation_status": "verified_scoped", "input_reports": [{"path": path.as_posix(), "status": reports[path.as_posix()].get("status"), "report_sha256": reports[path.as_posix()].get("report_sha256")} for path in INPUTS], "task_status": {"TUTORIAL-00..11": "verified_scoped", "TUTORIAL-12": sequence.get("status"), "TUTORIAL-13": reports["coverage/axis3-tutorial-persistence.report.json"].get("status"), "TUTORIAL-14": "blocked_by_retained_divergence" if sequence.get("status") == "blocked" else "verified"}, "first_divergence": sequence.get("first_divergence"), "goldens": {"loader": "fnv1a64:4a0e0041bdc491fe", "startup": "fnv1a64:c58e658b6cb3f213", "motion": "fnv1a64:83e51ec6ced82ba7", "program": "fnv1a64:79b6b470739e0e14", "checkpoint": "fnv1a64:10e366f530b2f5cb", "persistence": "fnv1a64:7984fdfabec7d093"}, "visual_assets": ["coverage/axis3-tutorial-visual/native-axis.png", "coverage/axis3-tutorial-visual/chromium-desktop.png", "coverage/axis3-tutorial-visual/chromium-mobile.png"], "blockers": [ {"id": "native_home_all_semantics", "status": "SOURCE_DEFINED", "reason": "exact INI omits HOME_SEQUENCE; source AXIS semantics use individual Z/X/Y home and recorder follows that path"}, {"id": "manual_toolchange_dialog", "status": "SOURCE_DEFINED_ACK_PIN", "reason": "source hal_manualtoolchange exposes change_button; recorder completes the real HAL handshake through that pin"}, {"id": "release_matrix", "status": "blocked_external", "reason": "Firefox/Safari minimums, OPFS physical crash oracle and full release remain outside selected-case scope"}, ], "statuses": statuses, "release_action": "STOP_RELEASE", "boundaries": ["closure is complete only as selected-case implementation evidence", "no blocker is promoted to parity", "all future continuation remains this exact case"], } report["report_sha256"] = hashlib.sha256(canonical(report).encode()).hexdigest() REPORT.write_text(json.dumps(report, ensure_ascii=False, sort_keys=True, indent=2) + "\n", encoding="utf-8") print(f"axis3_tutorial_closure_index={report['status']} report_sha256={report['report_sha256']}") return report if __name__ == "__main__": raise SystemExit(0 if generate()["status"] in {"verified", "blocked"} else 1)