98 lines
4.5 KiB
Python
98 lines
4.5 KiB
Python
#!/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())
|