Implement AXIS parity UI and execution baseline
This commit is contained in:
97
scripts/generate_technical_delivery_report.py
Normal file
97
scripts/generate_technical_delivery_report.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Aggregate complete-simulation technical evidence without changing release gates."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
REPORTS = (
|
||||
"coverage/configuration-startup-runtime.report.json",
|
||||
"coverage/rs274-interpreter-closure.report.json",
|
||||
"coverage/o-word-runtime.report.json",
|
||||
"coverage/tp-blend.report.json",
|
||||
"coverage/task-program-state.report.json",
|
||||
"coverage/motion-state.report.json",
|
||||
"coverage/kinematics-base.report.json",
|
||||
"coverage/advanced-kinematics.report.json",
|
||||
"coverage/hal-graph.report.json",
|
||||
"coverage/component-capability.report.json",
|
||||
"coverage/plc-runtime.report.json",
|
||||
"coverage/device-twin.report.json",
|
||||
"coverage/io-ack.report.json",
|
||||
"coverage/python-runtime-closure.report.json",
|
||||
"coverage/python-api.report.json",
|
||||
"coverage/python-callbacks.report.json",
|
||||
"coverage/trace-export.report.json",
|
||||
"coverage/reconciliation.report.json",
|
||||
"coverage/offline-migration.report.json",
|
||||
"coverage/worker-protocol.report.json",
|
||||
"coverage/editor-workflow.report.json",
|
||||
"coverage/authoritative-panels.report.json",
|
||||
"coverage/machine-view.report.json",
|
||||
"coverage/recovery-ux.report.json",
|
||||
"coverage/native-oracle-closure.report.json",
|
||||
"coverage/startup-matrix-closure.report.json",
|
||||
"coverage/determinism.report.json",
|
||||
"coverage/browser-matrix-closure.report.json",
|
||||
)
|
||||
|
||||
|
||||
def canonical(value: Any) -> str:
|
||||
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def generate(root: Path, output: Path) -> dict[str, Any]:
|
||||
records = []
|
||||
missing = []
|
||||
for name in REPORTS:
|
||||
path = root / name
|
||||
if not path.is_file():
|
||||
missing.append(name)
|
||||
continue
|
||||
try:
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
records.append({"path": name, "schema": value.get("schema"), "task_id": value.get("task_id"), "status": value.get("status"), "report_sha256": value.get("report_sha256"), "file_sha256": sha256(path)})
|
||||
except Exception as exc:
|
||||
records.append({"path": name, "status": "blocked", "error": str(exc)})
|
||||
verified = [record for record in records if record.get("status") == "verified"]
|
||||
not_verified = [record for record in records if record.get("status") != "verified"]
|
||||
report: dict[str, Any] = {
|
||||
"schema": "complete-simulation-technical-delivery.v1",
|
||||
"context_id": "linuxcnc-2.10.0-pre0-wasm-m1-py-c1",
|
||||
"status": "verified" if not missing and not not_verified else "partial",
|
||||
"technical_track": "complete-linuxcnc-simulation",
|
||||
"report_count": len(records),
|
||||
"verified_count": len(verified),
|
||||
"partial_or_blocked_count": len(not_verified),
|
||||
"missing_reports": missing,
|
||||
"reports": records,
|
||||
"release": {"status": "blocked", "action": "STOP_RELEASE", "candidate_eligible": False, "blockers": ["manifest_seed_unassigned", "accepted_entries_missing", "official_oracle_missing", "configuration_resources_missing", "browser_matrix_unverified", "license_closure_incomplete"]},
|
||||
"invariants": {"context_lock_unchanged": True, "abi_protocol_schema_unchanged": True, "owner_gate_unchanged": True, "real_hardware_excluded": True, "official_oracle_not_fabricated": True},
|
||||
"next_action": "release/owner track remains nextTask.md WAIT-OWNER-01; no automatic release acceptance",
|
||||
}
|
||||
report["report_sha256"] = hashlib.sha256(canonical(report).encode()).hexdigest()
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text(json.dumps(report, ensure_ascii=False, sort_keys=True, indent=2) + "\n", encoding="utf-8")
|
||||
return report
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--repo-root", type=Path, default=Path(__file__).resolve().parents[1])
|
||||
parser.add_argument("--report", type=Path, default=Path("coverage/complete-simulation-technical-delivery.report.json"))
|
||||
args = parser.parse_args()
|
||||
report = generate(args.repo_root.resolve(), args.repo_root.resolve() / args.report)
|
||||
print(f"technical_delivery={report['status']} reports={report['report_count']} verified={report['verified_count']} release={report['release']['action']}")
|
||||
return 0 if report["status"] in {"verified", "partial"} else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user