ThePirateRay/scripts/run_m1_no_device_acceptance.py

156 lines
5 KiB
Python

"""Consolidate the transport-free M1 regression evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
PINNED_COMMIT = "c28918c87f8273dd1d244f5a057addc192807fa5"
EVIDENCE = {
"addon_lifecycle": "rayforge-addon-spike.json",
"graphical_workflow_model": "rayforge-graphical-workflow.json",
"layer_model": "rayforge-layer-model.json",
"recipe_model": "rayforge-recipe-model.json",
"jcz_equivalence": "rayforge-jcz-equivalence.json",
"jcz_negative_cases": "rayforge-jcz-negative-cases.json",
"cancel_recovery": "rayforge-jcz-cancel-recovery.json",
"lightburn_mopa_import": "rayforge-lightburn-mopa-import.json",
"lightburn_device_import": "rayforge-lightburn-device-import.json",
}
def _commit_of(source: Path) -> str:
result = subprocess.run(
["git", "-C", str(source), "rev-parse", "HEAD"],
check=True,
capture_output=True,
text=True,
)
return result.stdout.strip()
def _run_check(command: list[str], environment: dict[str, str]) -> dict:
result = subprocess.run(
command,
cwd=ROOT,
check=False,
capture_output=True,
text=True,
timeout=120,
env=environment,
)
combined = (result.stdout + result.stderr).strip()
if result.returncode != 0:
raise RuntimeError(combined or f"check failed: {command}")
return {
"status": "passed",
"command": command,
"output_tail": combined.splitlines()[-4:],
}
def _load_evidence() -> dict[str, dict]:
fixture_dir = ROOT / "tests" / "fixtures"
results = {}
for name, filename in EVIDENCE.items():
path = fixture_dir / filename
results[name] = {
"path": path.relative_to(ROOT).as_posix(),
"sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
"report": json.loads(path.read_text(encoding="utf-8")),
}
return results
def run(source: Path) -> dict:
commit = _commit_of(source)
if commit != PINNED_COMMIT:
raise RuntimeError(f"expected Rayforge {PINNED_COMMIT}, found {commit}")
temp_dir = ROOT / ".build" / "acceptance-temp"
temp_dir.mkdir(parents=True, exist_ok=True)
environment = os.environ.copy()
environment["TEMP"] = str(temp_dir)
environment["TMP"] = str(temp_dir)
repository_checks = {
"unit_tests": _run_check(
[sys.executable, "-m", "unittest", "discover", "-s", "tests"],
environment,
),
"public_repo_guard": _run_check(
[sys.executable, "scripts/check_public_repo.py", "."],
environment,
),
}
evidence = _load_evidence()
graphical = evidence["graphical_workflow_model"]["report"]
negative = evidence["jcz_negative_cases"]["report"]
cancellation = evidence["cancel_recovery"]["report"]
device_import = evidence["lightburn_device_import"]["report"]
transport_free = all(
item["report"].get("transport") is None
for item in evidence.values()
if "transport" in item["report"]
)
controller_unreachable = (
graphical["controller_backend_reachable"] is False
)
checks = {
"repository_checks_passed": all(
item["status"] == "passed" for item in repository_checks.values()
),
"transport_free": transport_free,
"controller_backend_unreachable": controller_unreachable,
"negative_cases_fail_closed": negative["all_failed_closed"],
"cancel_requires_recovery": cancellation[
"restart_without_recovery_rejected"
],
"incomplete_import_blocks_encoding": not device_import[
"addon_profile_seam"
]["encoding_allowed"],
}
passed = all(checks.values())
return {
"checkpoint": "M1 no-device acceptance",
"status": "passed" if passed else "failed",
"rayforge_commit": commit,
"hardware_access": False,
"controller_backend_reachable": not controller_unreachable,
"checks": checks,
"repository_checks": repository_checks,
"evidence": evidence,
"remaining_manual_gates": [
"packaged Windows GUI interaction",
"reviewed promotion of imported MOPA settings",
],
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("rayforge_checkout", type=Path)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
(ROOT / ".build").mkdir(exist_ok=True)
result = run(args.rayforge_checkout.resolve())
rendered = json.dumps(result, indent=2, sort_keys=True) + "\n"
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(rendered, encoding="utf-8", newline="\n")
print(f"status={result['status']}")
print(f"sha256={hashlib.sha256(rendered.encode()).hexdigest()}")
return 0 if result["status"] == "passed" else 1
if __name__ == "__main__":
raise SystemExit(main())