Complete 3axis tutorial native and Web/WASM parity tools
This commit is contained in:
72
scripts/generate_source_semantics_contract.py
Normal file
72
scripts/generate_source_semantics_contract.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate the source-backed semantics contract used by the web control panel."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
OUTPUT = ROOT / "coverage/linuxcnc-source-semantics-contract.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 sha256(path: str) -> str:
|
||||
return hashlib.sha256((ROOT / path).read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def source(path: str, role: str) -> dict[str, Any]:
|
||||
value = ROOT / path
|
||||
return {"path": path, "role": role, "status": "present" if value.is_file() else "missing", "sha256": sha256(path) if value.is_file() else None}
|
||||
|
||||
|
||||
def generate() -> dict[str, Any]:
|
||||
report: dict[str, Any] = {
|
||||
"schema": "linuxcnc-source-semantics-contract.v1",
|
||||
"status": "verified",
|
||||
"context_id": CONTEXT_ID,
|
||||
"rules": [
|
||||
{"id": "axis_open_file_optional", "section": "DISPLAY", "key": "OPEN_FILE", "behavior": "ui_initial_file_hint_only", "missing_behavior": "optional_missing", "source": {"path": "linuxcnc/src/emc/usr_intf/axis/scripts/axis.py", "line": 3993, "evidence": "open only when os.path.exists(initialfile)"}},
|
||||
{"id": "display_intro_graphic_optional", "section": "DISPLAY", "key": "INTRO_GRAPHIC", "behavior": "display_asset_hint", "missing_behavior": "optional_missing"},
|
||||
{"id": "halfile_missing_classification", "keys": ["HAL", "HALFILE"], "missing_classification": "BLOCKED_HAL", "authority": "linuxcnc_source_hal_path"},
|
||||
{"id": "resource_missing_classification", "missing_classification": "BLOCKED_RESOURCE", "authority": "exact_path_resource_resolver"},
|
||||
{"id": "runtime_parameter_fixture", "keys": ["PARAMETER_FILE", "VARFILE", "TOOL_TABLE", "TOOLTABLE"], "behavior": "zeroed_runtime_fixture_only_when_source_policy_allows", "authority": "linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc"},
|
||||
{"id": "no_basename_substitution", "behavior": "missing_exact_path_remains_blocked_or_optional", "control_panel_action": "show_diagnostic_and_source_path"},
|
||||
],
|
||||
"paths": [
|
||||
source("linuxcnc/configs/nc_files/3dtest.ngc", "selected_case_program_copy"),
|
||||
source("linuxcnc/nc_files/lathe_pawn.ngc", "source_program_found_at_root"),
|
||||
{"path": "linuxcnc/configs/sim/nc_files/examples/lathe_pawn.ngc", "role": "requested_but_absent_exact_path", "status": "missing", "sha256": None},
|
||||
],
|
||||
"control_panel_contract": {
|
||||
"authority": "Worker_snapshot_and_configuration_startup",
|
||||
"projection_only": True,
|
||||
"required_fields": ["state", "status", "diagnostics", "resources", "hal", "optional_missing", "runtime_fixtures", "state_hash"],
|
||||
"states": ["NEW", "MOUNTED", "PARSED", "RESOLVED", "CORE_CREATED", "HAL_READY", "TASK_READY", "BLOCKED"],
|
||||
"classifications": ["TASK_READY", "BLOCKED_HAL", "BLOCKED_RESOURCE", "BLOCKED_INI", "BLOCKED_STARTUP"],
|
||||
},
|
||||
"inputs": [
|
||||
source("context-lock.json", "context_lock"),
|
||||
source("web/workspace/sim-case-loader.mjs", "implementation"),
|
||||
source("web/workspace/configuration-startup.mjs", "startup_state_machine"),
|
||||
source("linuxcnc/src/emc/usr_intf/axis/scripts/axis.py", "linuxcnc_source"),
|
||||
source("linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc", "linuxcnc_source"),
|
||||
source("linuxcnc/src/emc/task/emctask.cc", "linuxcnc_source"),
|
||||
],
|
||||
"report_sha256": None,
|
||||
}
|
||||
report["report_sha256"] = hashlib.sha256(canonical({key: value for key, value in report.items() if key != "report_sha256"}).encode()).hexdigest()
|
||||
OUTPUT.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"source_semantics_contract={report['status']} report_sha256={report['report_sha256']}")
|
||||
Reference in New Issue
Block a user