Complete 3axis tutorial native and Web/WASM parity tools

This commit is contained in:
2026-08-24 14:01:30 +08:00
parent 938654b19d
commit 7e90142b63
147 changed files with 17639 additions and 557 deletions

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Compare native AXIS and Web/WASM manual-tool evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
OUTPUT = Path("coverage/axis3-tutorial-native-web-tool-comparison.report.json")
CASE = "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini"
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(value: Any) -> str:
return hashlib.sha256(canonical(value).encode()).hexdigest()
def load(root: Path, path: str) -> dict[str, Any]:
return json.loads((root / path).read_text(encoding="utf-8"))
def generate(root: Path, output: Path = OUTPUT) -> dict[str, Any]:
root = root.resolve()
native = load(root, "coverage/axis3-tutorial-manual-ui-verification.report.json")
web = load(root, "coverage/axis3-tutorial-web-manual-verification.report.json")
parity = load(root, "coverage/axis3-tutorial-web-wasm-complete-parity.report.json")
native_ok = native.get("status") == "verified" and native.get("window", {}).get("title", "").find("3dtest.ngc") >= 0 and all(item.get("returncode") == 0 for item in native.get("screenshots", []))
web_ok = web.get("status") == "verified" and web.get("case") == CASE and all(item.get("bytes", 0) > 0 for item in web.get("screenshots", []))
shared = {
"case": CASE,
"context_id": CONTEXT_ID,
"program": "linuxcnc/nc_files/3dtest.ngc",
"native_source_files": "coverage/axis3-tutorial-native-run.report.json",
"wasm_source_files": "coverage/axis3-tutorial-web-wasm-complete-parity.report.json",
}
checks = {
"native_tool_verified": {"status": "verified" if native_ok else "blocked", "report": "coverage/axis3-tutorial-manual-ui-verification.report.json"},
"web_tool_verified": {"status": "verified" if web_ok else "blocked", "report": "coverage/axis3-tutorial-web-manual-verification.report.json"},
"same_case_and_context": {"status": "verified" if native.get("case") == "linuxcnc/configs/sim/axis/vismach/3axis-tutorial" and web.get("case") == CASE else "blocked", **shared},
"same_operation_intent": {"status": "verified" if [row.get("state") for row in native.get("transitions", [])] == ["WINDOW_VISIBLE", "ESTOP_RESET", "ON", "ALL_HOMED_REQUESTED", "AUTO_RUN_REQUESTED"] and [row.get("state") for row in web.get("states", []) if row.get("label") in {"ready", "estop", "power", "homed", "running", "complete"}] else "blocked", "native": [row.get("state") for row in native.get("transitions", [])], "web_labels": [row.get("label") for row in web.get("states", []) if row.get("label") in {"ready", "estop", "power", "homed", "running", "complete"}]},
"visual_evidence_nonempty": {"status": "verified" if native_ok and web_ok else "blocked", "native_screenshots": len(native.get("screenshots", [])), "web_screenshots": len(web.get("screenshots", []))},
"wasm_acceptance_regression": {"status": "verified" if parity.get("status") == "verified" and parity.get("passed_command_count") == parity.get("required_command_count") else "blocked", "passed": parity.get("passed_command_count"), "required": parity.get("required_command_count")},
}
report: dict[str, Any] = {
"schema": "axis3-tutorial-native-web-tool-comparison.v1",
"task_id": "AXIS3-NATIVE-WEB-TOOL-COMPARISON-01",
"context_id": CONTEXT_ID,
"case": CASE,
"status": "verified" if all(item["status"] == "verified" for item in checks.values()) else "blocked",
"conclusion": "native_and_web_tools_match_selected_case_workflow" if all(item["status"] == "verified" for item in checks.values()) else "tool_comparison_blocked",
"shared_inputs": shared,
"tools": {
"native": {"tool": "tool/linuxcnc-axis-manual-execution", "report": "coverage/axis3-tutorial-manual-ui-verification.report.json", "window": native.get("window"), "screenshots": native.get("screenshots"), "transitions": native.get("transitions")},
"web": {"tool": "tool/linuxcnc-web-wasm-manual-execution", "report": "coverage/axis3-tutorial-web-manual-verification.report.json", "browser": web.get("browser"), "screenshots": web.get("screenshots"), "states": [row for row in web.get("states", []) if row.get("label") in {"ready", "estop", "power", "homed", "running", "complete"}]},
},
"checks": checks,
"boundaries": ["simulation-only", "native process uses POSIX non-realtime fallback", "Web visual uses Chromium SwiftShader", "real hardware and full LinuxCNC parity are outside selected-case tool comparison"],
"report_sha256": None,
}
report["report_sha256"] = digest({key: value for key, value in report.items() if key != "report_sha256"})
destination = output if output.is_absolute() else root / output
destination.parent.mkdir(parents=True, exist_ok=True)
destination.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=ROOT)
parser.add_argument("--output", type=Path, default=OUTPUT)
args = parser.parse_args()
report = generate(args.repo_root.resolve(), args.output)
print(f"axis3_tool_comparison={report['status']} conclusion={report['conclusion']}")
return 0 if report["status"] == "verified" else 1
if __name__ == "__main__":
raise SystemExit(main())