接续上一轮,先做 L4-USER-M-PROCESS,完全接入仿真系统

结论:已将 L4-USER-M-PROCESS 的 millturn M128/M129 受控状态转换接入 virtual HAL、真实 browser simulation、OPFS 会话 payload、SDK API 和 release diagnostics validation;外部 user-M process execution 与 promotion 仍保持 locked,不伪装为 native process 解锁。
This commit is contained in:
2026-06-20 06:33:00 +08:00
parent 15b98c3ecf
commit d0e55ba11e
12 changed files with 676 additions and 7 deletions

View File

@@ -10,6 +10,7 @@
import {
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
createVirtualHalCommandScriptFixtureReport,
createVirtualHalMillturnUserMProcessBoundaryReport,
createVirtualHalMotionControllerMatrixReport,
createVirtualHalSimConfigMacroLoadFixtureReport,
createVirtualHalSimConfigEvidenceExpansionReport,
@@ -433,6 +434,16 @@
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
],
}),
virtualHalMillturnUserMProcessBoundary: createVirtualHalMillturnUserMProcessBoundaryReport({
manifestEntries: [
"linuxcnc/configs/sim/axis/vismach/millturn/millturn.ini",
"linuxcnc/configs/sim/axis/vismach/millturn/example.ngc",
"linuxcnc/configs/sim/axis/vismach/millturn/mcodes/M128",
"linuxcnc/configs/sim/axis/vismach/millturn/mcodes/M129",
"linuxcnc/configs/sim/axis/vismach/millturn/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/millturn/remap_subs/429remap.ngc",
],
}),
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: diagnosticsVirtualHalState }),
virtualHalMotionControllerMatrix: diagnosticsMotionControllerMatrix,
};

View File

@@ -241,6 +241,9 @@
!api?.stepVirtualHalMotionController ||
!api?.getVirtualHalSimulationRuntimeReport ||
!api?.getVirtualHalSimulationReplacementReport ||
!api?.getVirtualHalMillturnUserMProcessBoundaryReport ||
!api?.getMillturnUserMProcessState ||
!api?.applyMillturnUserMProcessState ||
!api?.getVirtualHalSourceComplianceReport ||
!api?.getVirtualHalSimConfigSourceCoverageReport ||
!api?.getVirtualHalSimConfigPromotionCandidateReport ||
@@ -442,7 +445,66 @@
) {
throw new Error(`simulation virtual HAL registry/integrity drift: ${JSON.stringify(initialVirtualHalRegistry)}`);
}
const diagnosticsArtifact = api.exportDiagnosticsArtifact();
let diagnosticsArtifact = api.exportDiagnosticsArtifact();
const millturnUserMBoundary = api.getVirtualHalMillturnUserMProcessBoundaryReport();
if (
millturnUserMBoundary.apiName !== "linuxcnc-wasm-virtual-hal-millturn-user-m-process-boundary-report" ||
millturnUserMBoundary.boundaryClass !== "L4-USER-M-PROCESS" ||
millturnUserMBoundary.complete !== true ||
millturnUserMBoundary.webSimulationSatisfied !== true ||
millturnUserMBoundary.executionEnabled !== false ||
millturnUserMBoundary.promotionAllowed !== false ||
millturnUserMBoundary.processExecutionReady !== false ||
millturnUserMBoundary.rows.length !== 2 ||
!millturnUserMBoundary.rows.some(({ userMCode, remapCode, stateTargetCount }) => userMCode === "M128" && remapCode === "M428" && stateTargetCount === 12) ||
!millturnUserMBoundary.rows.some(({ userMCode, remapCode, stateTargetCount }) => userMCode === "M129" && remapCode === "M429" && stateTargetCount === 12) ||
doc.body.dataset.userMProcessPhase !== "ready" ||
doc.querySelector('[data-user-m-process="boundary"]')?.textContent !== "L4-USER-M-PROCESS" ||
doc.querySelector('[data-user-m-process="path"]')?.textContent !== "axis/vismach/millturn/example.ngc" ||
doc.querySelector('[data-user-m-process="execution"]')?.textContent !== "disabled" ||
doc.querySelector('[data-user-m-process="promotion"]')?.textContent !== "locked"
) {
throw new Error(`simulation millturn user-M boundary drift: ${JSON.stringify(millturnUserMBoundary)}`);
}
const millturnM128 = api.applyMillturnUserMProcessState("M128");
if (
millturnM128.apiName !== "linuxcnc-wasm-virtual-hal-millturn-user-m-process-state-result" ||
millturnM128.userMCode !== "M128" ||
millturnM128.remapCode !== "M428" ||
millturnM128.stateMode !== "mill" ||
api.readVirtualHalPin("motion.switchkins-type")?.value !== 0 ||
api.readVirtualHalPin("ini.x.min_limit")?.value !== -300 ||
api.readVirtualHalPin("ini.z.max_limit")?.value !== 0 ||
doc.body.dataset.userMProcessPhase !== "applied" ||
doc.body.dataset.userMProcessActiveCode !== "M128" ||
doc.body.dataset.userMProcessActiveMode !== "mill" ||
doc.querySelector('[data-user-m-process="active-code"]')?.textContent !== "M128" ||
doc.querySelector('[data-user-m-process="active-remap"]')?.textContent !== "M428" ||
doc.querySelector('[data-user-m-process="active-mode"]')?.textContent !== "mill" ||
doc.querySelector('[data-user-m-process="switchkins"]')?.textContent !== "0"
) {
throw new Error(`simulation M128 user-M state did not apply: ${JSON.stringify(millturnM128)}`);
}
const millturnM129 = api.applyMillturnUserMProcessState("M129");
if (
millturnM129.userMCode !== "M129" ||
millturnM129.remapCode !== "M429" ||
millturnM129.stateMode !== "turn" ||
api.readVirtualHalPin("motion.switchkins-type")?.value !== 1 ||
api.readVirtualHalPin("motion.analog-out-03")?.value !== 1 ||
api.readVirtualHalPin("kinstype.is-0")?.value !== 0 ||
api.readVirtualHalPin("kinstype.is-1")?.value !== 1 ||
api.readVirtualHalPin("ini.x.max_limit")?.value !== 0 ||
api.readVirtualHalPin("ini.z.max_limit")?.value !== 300 ||
api.getMillturnUserMProcessState().activeMode !== "turn" ||
doc.querySelector('[data-user-m-process="active-code"]')?.textContent !== "M129" ||
doc.querySelector('[data-user-m-process="active-remap"]')?.textContent !== "M429" ||
doc.querySelector('[data-user-m-process="active-mode"]')?.textContent !== "turn" ||
doc.querySelector('[data-user-m-process="switchkins"]')?.textContent !== "1"
) {
throw new Error(`simulation M129 user-M state did not apply: ${JSON.stringify(millturnM129)}`);
}
diagnosticsArtifact = api.exportDiagnosticsArtifact();
const promotionCandidateSummary = api.getVirtualHalPromotionCandidateSummary();
const expectedPromotionCandidates = [
[
@@ -542,7 +604,14 @@
diagnosticsArtifact.virtualHalSimulationReplacement?.sourceCompliance?.webSimulationSatisfied !== true ||
diagnosticsArtifact.virtualHalSourceCompliance?.complete !== true ||
diagnosticsArtifact.virtualHalSourceCompliance?.webSimulationSatisfied !== true ||
!diagnosticsArtifact.virtualHalSourceCompliance?.sourceFiles?.includes("linuxcnc/configs/sim/axis/vismach/millturn/mcodes/M128") ||
!diagnosticsArtifact.virtualHalSourceCompliance?.sourceFiles?.includes("linuxcnc/src/hal/utils/halcmd_commands.cc") ||
diagnosticsArtifact.virtualHalMillturnUserMProcessBoundary?.complete !== true ||
diagnosticsArtifact.virtualHalMillturnUserMProcessBoundary?.boundaryClass !== "L4-USER-M-PROCESS" ||
diagnosticsArtifact.virtualHalMillturnUserMProcessState?.activeUserMCode !== "M129" ||
diagnosticsArtifact.virtualHalMillturnUserMProcessState?.activeMode !== "turn" ||
diagnosticsArtifact.virtualHalMillturnUserMProcessState?.executionEnabled !== false ||
diagnosticsArtifact.virtualHalMillturnUserMProcessState?.promotionAllowed !== false ||
diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.complete !== true ||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini") ||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini") ||
@@ -976,6 +1045,8 @@
savedVirtualHalSession.sessionDiagnostics?.ready !== true ||
savedVirtualHalSession.sessionDiagnostics?.validation?.ready !== true ||
savedVirtualHalSession.sessionDiagnostics?.validation?.motionControllerMatrixReady !== true ||
savedVirtualHalSession.snapshot?.payload?.virtualHal?.millturnUserMProcessBoundary?.complete !== true ||
savedVirtualHalSession.sessionDiagnostics?.diagnosticsArtifact?.virtualHalMillturnUserMProcessBoundary?.complete !== true ||
savedVirtualHalSession.sessionDiagnostics?.diagnosticsArtifact?.virtualHalMotionControllerMatrix?.complete !== true ||
doc.body.dataset.virtualHalSessionPhase !== "saved" ||
!doc.querySelector("[data-virtual-hal-session-status]")?.textContent.includes("Saved HAL session")
@@ -991,7 +1062,8 @@
savedSessionDiagnosticsArtifact.validation?.ready !== true ||
diagnosticsWithSavedSession.virtualHalSessionDiagnostics?.ready !== true ||
diagnosticsWithSavedSession.virtualHalSessionDiagnostics?.validation?.ready !== true ||
diagnosticsWithSavedSession.virtualHalSessionDiagnostics?.diagnosticsArtifact?.virtualHalSourceCompliance?.complete !== true
diagnosticsWithSavedSession.virtualHalSessionDiagnostics?.diagnosticsArtifact?.virtualHalSourceCompliance?.complete !== true ||
diagnosticsWithSavedSession.virtualHalSessionDiagnostics?.diagnosticsArtifact?.virtualHalMillturnUserMProcessBoundary?.complete !== true
) {
throw new Error(`AXIS-style virtual HAL session diagnostics did not become release-ready: ${JSON.stringify(diagnosticsWithSavedSession.virtualHalSessionDiagnostics)}`);
}