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,114 @@
#!/usr/bin/env python3
"""Audit the WASM-only source boundary without promoting partial parity."""
from __future__ import annotations
import hashlib
import json
import re
import subprocess
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
REPORT = ROOT / "coverage/wasm-only-source-audit.report.json"
SCHEMA = "wasm-only-source-audit.v1"
WASM_MANIFEST = ROOT / "build-wasm/build.ninja"
JS_AUTHORITY = (
("web/worker/authoritative-runtime.mjs", "compatibility planner and pose mirror for non-selected cases", "compatibility_open"),
("web/worker/program-runner.mjs", "program scheduling and control flow mirror; canonical segments enter WASM queue", "open"),
("web/worker/motion-state.mjs", "home/jog/limit projection pending T4 canonical state", "open"),
("web/worker/sim-task.mjs", "task state mirror pending T4 canonical state", "open"),
)
BASELINES = (
("preview", ["python3", "scripts/test_axis3_tutorial_preview.py"]),
("selected_case_worker", ["node", "web/worker/test_axis3_selected_case.mjs"]),
("visible_completion_worker", ["node", "web/worker/test_axis3_visible_completion.mjs"]),
("wasm_motion_event", ["node", "web/worker/test_wasm_motion_event.mjs"]),
("wasm_motion_authority", ["node", "web/worker/test_wasm_motion_authority.mjs"]),
("wasm_motion_checkpoint", ["node", "web/worker/test_wasm_motion_checkpoint.mjs"]),
("wasm_canonical_state", ["node", "web/worker/test_wasm_canonical_state.mjs"]),
("wasm_canonical_state_checkpoint", ["node", "web/worker/test_wasm_canonical_state_checkpoint.mjs"]),
("react_typecheck", ["npm", "run", "typecheck"], ROOT / "web/react"),
)
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def canonical(value: Any) -> str:
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
def wasm_exports() -> dict[str, Any]:
text = WASM_MANIFEST.read_text(encoding="utf-8", errors="replace") if WASM_MANIFEST.is_file() else ""
names = sorted(set(re.findall(r"'_((?:sim|malloc|free)[A-Za-z0-9_]+)'", text)))
return {
"manifest": WASM_MANIFEST.as_posix(),
"manifest_sha256": sha256(WASM_MANIFEST) if WASM_MANIFEST.is_file() else None,
"count": len(names),
"names": names,
"domains": {
"interpreter": [name for name in names if "interpreter" in name],
"motion": [name for name in names if any(token in name for token in ("motion", "tp_", "kinematics_motion"))],
"task_scheduler": [name for name in names if any(token in name for token in ("task", "scheduler"))],
"hal_io": [name for name in names if any(token in name for token in ("hal", "device", "io_"))],
},
}
def js_authority() -> list[dict[str, Any]]:
rows = []
for path, reason, status in JS_AUTHORITY:
absolute = ROOT / path
rows.append({"path": path, "sha256": sha256(absolute) if absolute.is_file() else None, "reason": reason, "status": status})
return rows
def run_baselines() -> list[dict[str, Any]]:
rows = []
for name, command, *working_dir in BASELINES:
cwd = working_dir[0] if working_dir else ROOT
result = subprocess.run(command, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, check=False)
rows.append({
"name": name,
"command": command,
"cwd": cwd.as_posix(),
"returncode": result.returncode,
"status": "verified" if result.returncode == 0 else "blocked",
"output_sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
"output_tail": result.stdout[-1200:],
})
return rows
def main() -> int:
report: dict[str, Any] = {
"schema": SCHEMA,
"status": "blocked",
"source_of_truth_target": "linuxcnc_source_to_wasm_core_only",
"selected_case": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini",
"selected_case_motion_authority": "verified",
"selected_case_motion_source": "wasm_motion_queue",
"selected_case_checkpoint_restore": "verified",
"wasm_exports": wasm_exports(),
"js_authority_remaining": js_authority(),
"baseline": run_baselines(),
"open_tasks": ["T1_FULL_CANONICAL_CALLBACKS", "T2_FULL_WASM_PREVIEW", "T3_NON_SELECTED_MOTION_AUTHORITY", "T4_HAL_IO_TOOL_PROBE_CANONICAL_STATE", "T5_FULL_MATRIX"],
"completed_slices": ["T1_INTERPRETER_MOTION_EVENT", "T2_SELECTED_CASE_WASM_PREVIEW", "T3_WASM_MOTION_QUEUE_SNAPSHOT", "T3_SELECTED_MOTION_AUTHORITY", "T3_WASM_MOTION_CHECKPOINT", "T4_SELECTED_TASK_CANONICAL", "T4_SELECTED_HOME_LIMIT_CANONICAL"],
"selected_case_task_authority": "wasm_task_canonical",
"selected_case_home_limit_authority": "wasm_home_limit",
"stop_reason": "selected-case task/motion/home-limit canonical state and queue recovery are verified; HAL/IO/tool/probe, compatibility, non-selected motion authority, and full parity remain open",
}
report["report_sha256"] = hashlib.sha256(canonical(report).encode()).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")
print(json.dumps(report, ensure_ascii=False))
return 1
if __name__ == "__main__":
raise SystemExit(main())