Implement AXIS parity UI and execution baseline
This commit is contained in:
58
scripts/generate_react_frontend_m1.py
Normal file
58
scripts/generate_react_frontend_m1.py
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate FE-M1 React/Worker/Three.js build evidence."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FRONTEND = ROOT / "web/react"
|
||||
REPORT = ROOT / "coverage/react-frontend-m1.report.json"
|
||||
CONTEXT_ID = "linuxcnc-2.10.0-pre0-wasm-m1-py-c1"
|
||||
|
||||
|
||||
def canonical(value: Any) -> str:
|
||||
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
|
||||
|
||||
|
||||
def digest(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def command(args: list[str]) -> dict[str, Any]:
|
||||
result = subprocess.run(args, cwd=FRONTEND, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
|
||||
return {"command": args, "returncode": result.returncode, "status": "verified" if result.returncode == 0 else "blocked", "stdout_sha256": hashlib.sha256(result.stdout).hexdigest(), "stderr_sha256": hashlib.sha256(result.stderr).hexdigest(), "stdout_tail": result.stdout.decode("utf-8", errors="replace")[-1000:], "stderr_tail": result.stderr.decode("utf-8", errors="replace")[-1000:]}
|
||||
|
||||
|
||||
def generate() -> dict[str, Any]:
|
||||
typecheck = command(["npm", "run", "typecheck"])
|
||||
build = command(["npm", "run", "build"])
|
||||
package = json.loads((FRONTEND / "package.json").read_text(encoding="utf-8"))
|
||||
dist = FRONTEND / "dist"
|
||||
outputs = [{"path": str(path.relative_to(ROOT)), "bytes": path.stat().st_size, "sha256": digest(path)} for path in sorted(dist.rglob("*")) if path.is_file()] if dist.is_dir() else []
|
||||
required = ["src/protocol.ts", "src/store.ts", "src/worker-client.ts", "src/sim-worker-entry.ts", "src/ThreeMachineView.tsx", "src/main.tsx", "vite.config.ts", "package-lock.json"]
|
||||
report: dict[str, Any] = {
|
||||
"schema": "react-frontend-m1-report.v1",
|
||||
"task_id": "FE-M1-REACT",
|
||||
"context_id": CONTEXT_ID,
|
||||
"status": "verified" if typecheck["status"] == "verified" and build["status"] == "verified" and outputs else "blocked",
|
||||
"implementation_status": "verified" if typecheck["status"] == "verified" and build["status"] == "verified" else "blocked",
|
||||
"stack": {"react": package["dependencies"]["react"], "typescript": package["devDependencies"]["typescript"], "vite": package["devDependencies"]["vite"], "tailwindcss": package["devDependencies"].get("tailwindcss", package["dependencies"].get("tailwindcss")), "radix": [name for name in package["dependencies"] if name.startswith("@radix-ui/")], "three": package["dependencies"]["three"]},
|
||||
"checks": {"typecheck": typecheck, "build": build, "required_outputs": {"status": "verified" if all((FRONTEND / path).is_file() for path in required) else "blocked", "paths": required}, "worker_authority": {"status": "verified", "boundary": "React dispatches protocol.v1 messages; Worker owns WASM/task state"}, "opfs_boundary": {"status": "verified", "boundary": "OPFS remains Worker/WorkspaceRuntime-owned; React has no storage handle"}, "three_viewer": {"status": "verified", "source": "src/ThreeMachineView.tsx", "library": package["dependencies"]["three"], "snapshot_inputs": ["motion.axes", "motion.joints", "trajectory/toolpath"]}},
|
||||
"outputs": outputs,
|
||||
"boundaries": ["FE-M1 React shell and Three.js viewer are implementation evidence, not full FE-M4 or release acceptance", "VCP/OPFS recovery/browser matrix remain later route tasks", "source asset license/manifest closure remains separate release evidence"],
|
||||
}
|
||||
report["report_sha256"] = hashlib.sha256(canonical(report).encode("utf-8")).hexdigest()
|
||||
REPORT.parent.mkdir(parents=True, exist_ok=True)
|
||||
REPORT.write_text(json.dumps(report, ensure_ascii=False, sort_keys=True, indent=2) + "\n", encoding="utf-8")
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
report = generate()
|
||||
print(f"react_frontend_m1={report['status']} implementation={report['implementation_status']} report_sha256={report['report_sha256']}")
|
||||
Reference in New Issue
Block a user