Implement WebAssembly runtime and kinematics coverage

This commit is contained in:
2026-08-21 06:04:48 +08:00
parent 5dd614c335
commit 554b72dae8
112 changed files with 47148 additions and 807 deletions

View File

@@ -12,6 +12,7 @@ from __future__ import annotations
import argparse
import hashlib
import json
import re
from pathlib import Path
from typing import Iterable
@@ -29,6 +30,11 @@ BUILD_FILES = (
Path("linuxcnc/VERSION"),
Path("linuxcnc/meson.build"),
)
KINEMATICS_CONFIG_RE = re.compile(
r"(?:^|\s)KINEMATICS\s*=|\bloadrt\s+(?:\[KINS\]KINEMATICS|[^\s#;]*(?:kins|kinematics))|"
r"corexy_by_hal|matrixkins|xyzab_tdr_kins|switchkins|motion\.switchkins-type",
re.IGNORECASE,
)
def sha256(path: Path) -> str:
@@ -83,9 +89,9 @@ def make_entry(repo_root: Path, root_kind: str, path: Path) -> dict[str, object]
}
def make_manifest_entry(source: dict[str, object]) -> dict[str, object]:
def make_manifest_entry(source: dict[str, object], repo_root: Path | None = None) -> dict[str, object]:
source_id = str(source["source_id"])
return {
entry = {
"id": f"seed:{source_id}",
"feature_id": None,
"source": source_id,
@@ -108,6 +114,48 @@ def make_manifest_entry(source: dict[str, object]) -> dict[str, object]:
"exclusion_reason": None,
"mapping_status": "needs_owner",
}
source_path = str(source["path"])
is_kinematics_source = source_path.startswith("linuxcnc/src/emc/kinematics/")
is_kinematics_config = False
if repo_root is not None and source_path.startswith(("linuxcnc/configs/sim/", "linuxcnc/tests/")) and Path(source_path).suffix.lower() in {".ini", ".inc", ".hal"}:
path = repo_root / source_path
if path.is_file():
is_kinematics_config = bool(KINEMATICS_CONFIG_RE.search(path.read_text(encoding="utf-8", errors="strict")))
is_kinematics_abi = source_path in {"wasm-core/include/sim_kinematics.h", "wasm-core/src/sim_kinematics.c", "wasm-core/tests/sim_kinematics_test.c", "wasm-core/tests/sim_kinematics_test_main.c"}
is_delta_source = source_path.startswith("linuxcnc/src/emc/kinematics/lineardelta") or source_path.startswith("linuxcnc/src/emc/kinematics/rotarydelta")
is_delta_config = is_kinematics_config and any(token in source_path.lower() for token in ("ldelta", "rdelta"))
is_delta_implementation = is_kinematics_abi and source_path in {"wasm-core/include/sim_kinematics.h", "wasm-core/src/sim_kinematics.c", "wasm-core/tests/sim_kinematics_test.c", "wasm-core/tests/sim_kinematics_test_main.c"}
is_tripod_source = source_path == "linuxcnc/src/emc/kinematics/tripodkins.c"
is_tripod_config = is_kinematics_config and source_path == "linuxcnc/configs/sim/tklinuxcnc/tripod.ini"
is_genhex_source = source_path in {"linuxcnc/src/emc/kinematics/genhexkins.c", "linuxcnc/src/emc/kinematics/genhexkins.h"}
is_genhex_config = is_kinematics_config and source_path == "linuxcnc/configs/sim/axis/vismach/hexapod-sim/hexapod.ini"
is_genhex_hal = source_path == "linuxcnc/configs/sim/axis/vismach/hexapod-sim/kinematics.hal"
is_genhex_implementation = source_path in {"wasm-core/include/sim_kinematics.h", "wasm-core/src/sim_kinematics.c", "wasm-core/tests/sim_kinematics_test.c", "wasm-core/tests/sim_kinematics_test_main.c"}
is_corexy_hal = source_path in {
"linuxcnc/src/hal/components/corexy_by_hal.comp",
"linuxcnc/configs/sim/axis/corexy/corexy_by_hal.ini",
"linuxcnc/configs/sim/axis/corexy/corexy_by_hal.hal",
"linuxcnc/configs/sim/axis/corexy/corexy_by_kins.ini",
"wasm-core/include/sim_hal.h",
"wasm-core/src/sim_hal.c",
"wasm-core/tests/sim_hal_test.c",
"wasm-core/tests/sim_hal_test_main.c",
}
if is_kinematics_source or is_kinematics_config or is_kinematics_abi or is_corexy_hal:
# K0-INV-01 audits are source-closure evidence, not an implementation
# claim. Keep the seed planned while linking every kinematics source
# to the deterministic report and its explicit blocked oracle.
entry.update({
"domain": "hal" if is_corexy_hal else "kinematics",
"feature_id": "feature:kinematics-k2-hal" if is_corexy_hal else "feature:kinematics-k4-tripod" if (is_tripod_source or is_tripod_config) else "feature:kinematics-k4-genhex" if (is_genhex_source or is_genhex_config or is_genhex_hal or is_genhex_implementation) else "feature:kinematics-k4-delta" if (is_delta_source or is_delta_config or is_delta_implementation) else "feature:kinematics-k0" if not is_kinematics_abi else "feature:kinematics-k1-contract",
"dependencies": ["coverage/coupled-kinematics.report.json", "coverage/config-resources.jsonl"] if is_corexy_hal else ["coverage/tripod-kinematics.report.json", "coverage/delta-kinematics.report.json"] if (is_tripod_source or is_tripod_config) else ["coverage/genhex-kinematics.report.json", "coverage/kinematics-source-closure.report.json"] if (is_genhex_source or is_genhex_config or is_genhex_hal or is_genhex_implementation) else ["coverage/delta-kinematics.report.json", "coverage/kinematics-source-closure.report.json"] if (is_delta_source or is_delta_config or is_delta_implementation) else ["coverage/source-index.jsonl", "coverage/source-symbols.jsonl"] if is_kinematics_source else ["coverage/kinematics-source-closure.report.json", "coverage/config-resources.jsonl"] if is_kinematics_config else ["wasm-core/include/sim_kinematics.h", "wasm-core/CMakeLists.txt"],
"outputs": ["coverage/corexy-hal.report.json"] if is_corexy_hal else ["coverage/tripod-kinematics.report.json"] if (is_tripod_source or is_tripod_config) else ["coverage/genhex-kinematics.report.json"] if (is_genhex_source or is_genhex_config or is_genhex_hal or is_genhex_implementation) else ["coverage/delta-kinematics.report.json"] if (is_delta_source or is_delta_config or is_delta_implementation) else ["coverage/kinematics-source-closure.report.json", "coverage/trivkins-integration.report.json", "coverage/coupled-kinematics.report.json", "coverage/fiveaxis-kinematics.report.json", "coverage/trt-kinematics.report.json", "coverage/robot-kinematics.report.json", "coverage/genser-kinematics.report.json"] if is_kinematics_source else ["coverage/kinematics-config-graph.report.json", "coverage/kinematics-oracle-samples.jsonl", "coverage/kinematics-oracle.report.json", "coverage/kinematics-golden-schema.json", "coverage/coupled-kinematics.report.json", "coverage/fiveaxis-kinematics.report.json", "coverage/trt-kinematics.report.json", "coverage/robot-kinematics.report.json", "coverage/genser-kinematics.report.json"] if is_kinematics_config else ["coverage/kinematics-abi-contract.json", "coverage/kinematics-mapping-contract.json", "coverage/kinematics-numeric-policy.json", "coverage/coupled-kinematics.report.json", "coverage/fiveaxis-kinematics.report.json", "coverage/trt-kinematics.report.json", "coverage/robot-kinematics.report.json", "coverage/genser-kinematics.report.json"],
"errors": ["blocked:linuxcnc/unit_tests/kinematics missing from locked source"],
"test_id": "audit:K2-HAL-01" if is_corexy_hal else "audit:K4-TRIPOD-01" if (is_tripod_source or is_tripod_config) else "audit:K4-HEX-01" if (is_genhex_source or is_genhex_config or is_genhex_hal or is_genhex_implementation) else "audit:K4-DELTA-01" if (is_delta_source or is_delta_config or is_delta_implementation) else "audit:K0-INV-01" if is_kinematics_source else "audit:K0-INV-02" if is_kinematics_config else "audit:K1-CONTRACT-01",
"oracle": {"status": "blocked", "report": "coverage/corexy-hal.report.json" if is_corexy_hal else "coverage/tripod-kinematics.report.json" if (is_tripod_source or is_tripod_config) else "coverage/genhex-kinematics.report.json" if (is_genhex_source or is_genhex_config or is_genhex_hal or is_genhex_implementation) else "coverage/delta-kinematics.report.json" if (is_delta_source or is_delta_config or is_delta_implementation) else "coverage/kinematics-source-closure.report.json"},
"mapping_status": "audited_blocked" if not is_corexy_hal else "verified_partial",
})
return entry
def write_jsonl(path: Path, entries: Iterable[dict[str, object]]) -> None:
@@ -122,7 +170,7 @@ def generate(repo_root: Path, source_index: Path, manifest: Path) -> tuple[int,
sources = [make_entry(repo_root, kind, path) for kind, path in iter_files(repo_root)]
sources.sort(key=lambda item: str(item["source_id"]))
write_jsonl(source_index, sources)
write_jsonl(manifest, (make_manifest_entry(source) for source in sources))
write_jsonl(manifest, (make_manifest_entry(source, repo_root) for source in sources))
return len(sources), len(sources)