chore: close wasm status contract work
This commit is contained in:
@@ -21,6 +21,13 @@ const lineExecutionComparison = compareLineExecutionTrace(nativeEvidence, webEvi
|
||||
const axisValuesByLineComparison = compareAxisValuesByLine(nativeEvidence, webEvidence);
|
||||
const gcodeExecutionProcessComparison = compareGcodeExecutionProcess(nativeEvidence, webEvidence);
|
||||
const strictComparison = compareStrictEvidence(nativeEvidence, webEvidence);
|
||||
const functionalChecks = compareFunctionalEvidence(nativeEvidence, webEvidence, {
|
||||
pathComparison,
|
||||
lineExecutionComparison,
|
||||
axisValuesByLineComparison,
|
||||
gcodeExecutionProcessComparison,
|
||||
strictComparison,
|
||||
});
|
||||
|
||||
const checks = [
|
||||
check("profile", "native axis mask is XYZBC", nativeEvidence.coverage?.axisProfile === true, {
|
||||
@@ -204,26 +211,44 @@ const checks = [
|
||||
];
|
||||
|
||||
const failed = checks.filter((item) => item.status !== "pass");
|
||||
const functionalFailed = functionalChecks.filter((item) => item.status !== "pass");
|
||||
const blockers = [
|
||||
...(nativeEvidence.status === "blocked" ? nativeEvidence.blocker ? [nativeEvidence.blocker] : ["native-blocked"] : []),
|
||||
...(webEvidence.blockers || []).map((blocker) => blocker.id),
|
||||
];
|
||||
const surfaceSummary = {
|
||||
checkCount: checks.length,
|
||||
passCount: checks.length - failed.length,
|
||||
failCount: failed.length,
|
||||
legacyComparePassCount: checks.length - failed.length,
|
||||
legacyCompareFailCount: failed.length,
|
||||
blockers,
|
||||
nativeStatus: nativeEvidence.status,
|
||||
webStatus: webEvidence.status,
|
||||
};
|
||||
const functionalSummary = {
|
||||
status: functionalFailed.length === 0 ? "pass" : "fail",
|
||||
checkCount: functionalChecks.length,
|
||||
passCount: functionalChecks.length - functionalFailed.length,
|
||||
failCount: functionalFailed.length,
|
||||
requiredImprovements: functionalFailed.map((item) => ({
|
||||
category: item.category,
|
||||
requirement: item.requirement,
|
||||
evidence: item.evidence,
|
||||
})),
|
||||
};
|
||||
|
||||
const report = {
|
||||
apiName: "xyzbc-trt-native-web-evidence-comparison",
|
||||
status: failed.length === 0 ? "pass" : "fail",
|
||||
status: failed.length === 0 && functionalFailed.length === 0 ? "pass" : "fail",
|
||||
comparedAt: new Date().toISOString(),
|
||||
nativePath,
|
||||
webPath,
|
||||
summary: {
|
||||
checkCount: checks.length,
|
||||
passCount: checks.length - failed.length,
|
||||
failCount: failed.length,
|
||||
blockers,
|
||||
nativeStatus: nativeEvidence.status,
|
||||
webStatus: webEvidence.status,
|
||||
},
|
||||
summary: surfaceSummary,
|
||||
surfaceSummary,
|
||||
functionalSummary,
|
||||
checks,
|
||||
functionalChecks,
|
||||
pathComparison,
|
||||
lineExecutionComparison,
|
||||
axisValuesByLineComparison,
|
||||
@@ -236,11 +261,14 @@ const report = {
|
||||
uiBehaviorComparison: strictComparison.axisUiBehaviorComparison,
|
||||
visualComparison: strictComparison.visualComparison,
|
||||
strictComparison,
|
||||
requiredImprovements: failed.map((item) => ({
|
||||
category: item.category,
|
||||
requirement: item.requirement,
|
||||
evidence: item.evidence,
|
||||
})),
|
||||
requiredImprovements: [
|
||||
...failed.map((item) => ({
|
||||
category: item.category,
|
||||
requirement: item.requirement,
|
||||
evidence: item.evidence,
|
||||
})),
|
||||
...functionalSummary.requiredImprovements,
|
||||
],
|
||||
semanticBoundary: "native_linuxcnc_vs_web_opfs_wasm_xyzbc_trt_evidence_comparison",
|
||||
};
|
||||
|
||||
@@ -445,6 +473,152 @@ function statusObject(passed, evidence = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function compareFunctionalEvidence(nativeEvidence, webEvidence, {
|
||||
pathComparison,
|
||||
lineExecutionComparison,
|
||||
axisValuesByLineComparison,
|
||||
gcodeExecutionProcessComparison,
|
||||
strictComparison,
|
||||
}) {
|
||||
const nativeErrors = errorPathIds(nativeEvidence);
|
||||
const webErrors = errorPathIds(webEvidence);
|
||||
const requiredIllegalPaths = [
|
||||
"run-while-estop",
|
||||
"run-before-homed",
|
||||
"wrong-mode",
|
||||
"missing-file",
|
||||
"bad-switchkins-type",
|
||||
"remap-stop",
|
||||
];
|
||||
const taskPolicy = webEvidence.taskHalEquivalence?.taskPolicy
|
||||
|| webEvidence.nativeStateFlowReview?.buttonInterlocks
|
||||
|| {};
|
||||
const webExecution = webEvidence.taskHalEquivalence?.taskHal || {};
|
||||
const webBasicSim = webEvidence.basicSimEquivalent || webEvidence.taskHalEquivalence?.basicSimEquivalent || {};
|
||||
const semanticPath = pathComparison.semanticExecutionVsSemanticExecution || {};
|
||||
const runtimeReady = strictComparison.runtimeExecutionComparison?.status === "pass";
|
||||
const taskHalReady = strictComparison.taskHalFullStateComparison?.status === "pass";
|
||||
const sourceUiReady = strictComparison.axisUiBehaviorComparison?.status === "pass";
|
||||
const errorReady = strictComparison.errorPathComparison?.status === "pass";
|
||||
|
||||
return [
|
||||
check("functional", "cppTaskStateMachineParity", taskHalReady
|
||||
&& webEvidence.taskHalEquivalence?.ready === true
|
||||
&& webEvidence.nativeStateFlowReview?.ready === true
|
||||
&& ["estop", "estop-reset", "on"].includes(String(taskPolicy.taskState || ""))
|
||||
&& ["manual", "auto", "mdi"].includes(String(taskPolicy.taskMode || ""))
|
||||
&& ["idle", "reading", "paused", "waiting"].includes(String(taskPolicy.interpState || "")), {
|
||||
linuxCncRules: ["emcTaskSetState", "determineState", "EMC_STAT.task"],
|
||||
nativeReady: nativeEvidence.taskHalFullState?.ready,
|
||||
webReady: webEvidence.taskHalFullState?.ready,
|
||||
taskPolicy,
|
||||
}),
|
||||
check("functional", "cppModeGateParity", sourceUiReady
|
||||
&& errorReady
|
||||
&& nativeErrors.has("wrong-mode")
|
||||
&& webErrors.has("wrong-mode")
|
||||
&& taskPolicy.canExecuteMdi === false
|
||||
&& taskPolicy.canRunAuto === false, {
|
||||
linuxCncRules: ["emcTaskSetMode", "AUTO non-idle/manual gate", "AXIS manual_ok/mdi gate"],
|
||||
nativeWrongModeRepresented: nativeErrors.has("wrong-mode"),
|
||||
webWrongModeRepresented: webErrors.has("wrong-mode"),
|
||||
taskPolicy,
|
||||
}),
|
||||
check("functional", "cppHomingParity", taskHalReady
|
||||
&& webBasicSim.ready === true
|
||||
&& webBasicSim.homing?.allConfiguredAxesHomed === true
|
||||
&& Array.isArray(nativeEvidence.taskStateFlow?.states)
|
||||
&& nativeEvidence.taskStateFlow.states.some((state) => Array.isArray(state.homed)), {
|
||||
linuxCncRules: ["EMC_JOINT_HOME", "EMCMOT_JOINT_HOME", "homing.c HOME_START/HOME_FINISHED"],
|
||||
nativeTaskStateFlowReady: nativeEvidence.taskStateFlow?.ready,
|
||||
webHoming: webBasicSim.homing,
|
||||
}),
|
||||
check("functional", "cppRunGateParity", taskHalReady
|
||||
&& errorReady
|
||||
&& nativeErrors.has("run-while-estop")
|
||||
&& webErrors.has("run-while-estop")
|
||||
&& nativeErrors.has("run-before-homed")
|
||||
&& webErrors.has("run-before-homed")
|
||||
&& webExecution.completed === true
|
||||
&& webExecution.eventCount > 0
|
||||
&& pathComparison.executionVsExecution.comparable === true, {
|
||||
linuxCncRules: ["EMC_TASK_PLAN_RUN", "all_homed", "program open", "motion plan loaded"],
|
||||
nativeErrorPaths: [...nativeErrors],
|
||||
webErrorPaths: [...webErrors],
|
||||
webExecution,
|
||||
executionPath: {
|
||||
nativeSampleCount: pathComparison.executionVsExecution.nativeSampleCount,
|
||||
webSampleCount: pathComparison.executionVsExecution.webSampleCount,
|
||||
},
|
||||
}),
|
||||
check("functional", "cppPauseResumeParity", taskHalReady
|
||||
&& webExecution.eventCount > 0
|
||||
&& typeof taskPolicy.canPause === "boolean"
|
||||
&& typeof taskPolicy.canResume === "boolean"
|
||||
&& semanticPath.status === "pass"
|
||||
&& semanticPath.machineStateMismatchCount === 0, {
|
||||
linuxCncRules: ["EMC_TASK_PLAN_PAUSE", "EMC_TASK_PLAN_RESUME", "EMCMOT_PAUSE", "EMCMOT_RESUME"],
|
||||
taskPolicy: {
|
||||
canPause: taskPolicy.canPause,
|
||||
canResume: taskPolicy.canResume,
|
||||
interpState: taskPolicy.interpState,
|
||||
},
|
||||
semanticExecutionMachineStateMismatchCount: semanticPath.machineStateMismatchCount,
|
||||
}),
|
||||
check("functional", "cppStepParity", taskHalReady
|
||||
&& typeof taskPolicy.canRunAuto === "boolean"
|
||||
&& lineExecutionComparison.status === "pass"
|
||||
&& axisValuesByLineComparison.status === "pass"
|
||||
&& gcodeExecutionProcessComparison.status === "pass"
|
||||
&& gcodeExecutionProcessComparison.nativeExecutionStepCount > 0
|
||||
&& gcodeExecutionProcessComparison.webExecutionStepCount > 0, {
|
||||
linuxCncRules: ["EMC_TASK_PLAN_STEP", "EMCMOT_STEP", "motion id/current line progression"],
|
||||
lineExecution: {
|
||||
nativeTraceCount: lineExecutionComparison.nativeTraceCount,
|
||||
webTraceCount: lineExecutionComparison.webTraceCount,
|
||||
},
|
||||
gcodeExecution: {
|
||||
nativeExecutionStepCount: gcodeExecutionProcessComparison.nativeExecutionStepCount,
|
||||
webExecutionStepCount: gcodeExecutionProcessComparison.webExecutionStepCount,
|
||||
},
|
||||
}),
|
||||
check("functional", "illegalCommandParity", errorReady
|
||||
&& requiredIllegalPaths.every((id) => nativeErrors.has(id) && webErrors.has(id))
|
||||
&& strictComparison.limitInterlocksComparison?.status === "pass", {
|
||||
linuxCncRules: ["runtime command rejection", "UI policy gate consistency", "operator error parity"],
|
||||
requiredIllegalPaths,
|
||||
nativeErrorPaths: [...nativeErrors],
|
||||
webErrorPaths: [...webErrors],
|
||||
limitInterlocksStatus: strictComparison.limitInterlocksComparison?.status,
|
||||
}),
|
||||
check("functional", "realProgramExecutionParity", runtimeReady
|
||||
&& pathComparison.semanticExecutionVsSemanticExecution.status === "pass"
|
||||
&& lineExecutionComparison.status === "pass"
|
||||
&& axisValuesByLineComparison.status === "pass"
|
||||
&& gcodeExecutionProcessComparison.status === "pass", {
|
||||
linuxCncRules: ["real G-code line/currentLine/motion/path/status parity"],
|
||||
runtimeExecutionStatus: strictComparison.runtimeExecutionComparison?.status,
|
||||
semanticExecution: {
|
||||
nativeSampleCount: semanticPath.nativeSampleCount,
|
||||
webSampleCount: semanticPath.webSampleCount,
|
||||
maxTcpErrorMm: semanticPath.maxTcpErrorMm,
|
||||
maxJointError: semanticPath.maxJointError,
|
||||
maxToolAxisAngleDeg: semanticPath.maxToolAxisAngleDeg,
|
||||
},
|
||||
lineExecutionStatus: lineExecutionComparison.status,
|
||||
axisValuesStatus: axisValuesByLineComparison.status,
|
||||
gcodeExecutionStatus: gcodeExecutionProcessComparison.status,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
function errorPathIds(evidence) {
|
||||
return new Set((evidence.errorPathParity?.paths || [])
|
||||
.filter((item) => item?.nativeExpected !== false && item?.webRepresented !== false)
|
||||
.map((item) => item.id)
|
||||
.filter(Boolean));
|
||||
}
|
||||
|
||||
function comparePathEvidence(nativeEvidence, webEvidence) {
|
||||
const samplePeriodMs = 50;
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user