const WEB_SIMULATION_BOUNDARY = "linuxcnc_task_motion_hal_wasm_simulation_runtime"; const ALLOWED_NATIVE_PROBE_STATUSES = new Set([ "passed", "ready_disabled_by_default", "skipped_missing_host_runtime", ]); export function createNativeTaskHalReadinessAudit({ sourceManifest = {}, nativeProbe = {}, fullExecutionBoundary = {}, taskHalRuntimeReadiness = {}, taskHalStatus = {}, generatedAt = new Date().toISOString(), artifactPaths = {}, } = {}) { const taskSourceCount = numberFrom(sourceManifest.task_source_count); const halSourceCount = numberFrom(sourceManifest.hal_source_count); const motionSourceCount = numberFrom(sourceManifest.motion_source_count); const sourceManifestReady = truthy(sourceManifest.task_hal_source_manifest_ready) && truthy(sourceManifest.task_hal_reference_source_ready) && taskSourceCount > 0 && halSourceCount > 0 && motionSourceCount > 0; const nativeProbeStatus = String( nativeProbe.native_probe_status || nativeProbe.trt_task_hal_runtime_probe_status || "missing", ); const nativeProbeOk = String(nativeProbe.native_task_hal_probe || "") === "ok" && ALLOWED_NATIVE_PROBE_STATUSES.has(nativeProbeStatus); const nativePromotionBlocked = !truthy(nativeProbe.trt_task_hal_promotion_allowed) && String(nativeProbe.nativeTaskReady) !== "true" && String(nativeProbe.nativeHalSyncReady) !== "true"; const taskReady = Boolean( fullExecutionBoundary.taskRuntimeReady || taskHalRuntimeReadiness.taskRuntimeReady || taskHalStatus.summary?.taskRuntimeReady, ); const motionReady = Boolean( fullExecutionBoundary.motionRuntimeReady || taskHalRuntimeReadiness.motionRuntimeReady || taskHalStatus.summary?.motionRuntimeReady, ); const halReady = Boolean( fullExecutionBoundary.halRuntimeReady || taskHalRuntimeReadiness.halRuntimeReady || taskHalStatus.summary?.halRuntimeReady, ); const halSyncReady = Boolean( fullExecutionBoundary.halSyncReady || taskHalRuntimeReadiness.halSyncReady || taskHalStatus.summary?.halSyncReady, ); const fullBoundarySimulationReady = Boolean( fullExecutionBoundary.semanticBoundary === WEB_SIMULATION_BOUNDARY && fullExecutionBoundary.fullLinuxCncProgramExecutionReady === true && fullExecutionBoundary.promotionAllowed === true, ); const hardwareBlocked = fullExecutionBoundary.hardwareDrive === false && fullExecutionBoundary.hostRealtimeKernel === false && fullExecutionBoundary.hostExternalUserMProcessReady === false && fullExecutionBoundary.hostToolDbProcessReady === false && fullExecutionBoundary.arbitraryUserMExecution === false; const toolUserWebSimulationReady = fullExecutionBoundary.externalUserMProcessReady === true && fullExecutionBoundary.externalUserMProcessScope === "web_simulation_only" && fullExecutionBoundary.toolDbProcessReady === true && fullExecutionBoundary.toolDbProcessScope === "web_simulation_only"; const webSimulationConsistent = sourceManifestReady && nativeProbeOk && nativePromotionBlocked && taskReady && motionReady && halReady && halSyncReady && fullBoundarySimulationReady && toolUserWebSimulationReady && hardwareBlocked; return { apiName: "web-rtcp-5axis-native-task-hal-readiness-audit", batch: "M18-native-task-hal-source-and-artifact-audit", generatedAt, status: webSimulationConsistent ? "ok" : "blocked", semanticBoundary: WEB_SIMULATION_BOUNDARY, promotionScope: "web_simulation_only", taskHalWebSimulationBoundaryConsistent: webSimulationConsistent, webSimulation: { promoted: fullBoundarySimulationReady, taskRuntimeReady: taskReady, motionRuntimeReady: motionReady, halRuntimeReady: halReady, nativeTaskReady: fullExecutionBoundary.nativeTaskReady === true, nativeHalSyncReady: fullExecutionBoundary.nativeHalSyncReady === true, fullLinuxCncProgramExecutionReady: fullExecutionBoundary.fullLinuxCncProgramExecutionReady === true, promotionAllowed: fullExecutionBoundary.promotionAllowed === true, }, nativeHostAndHardware: { nativeProbe: nativeProbeOk ? "ok" : "blocked", nativeProbeStatus, nativePromotionAllowed: truthy(nativeProbe.trt_task_hal_promotion_allowed), hardwareDrive: false, hostRealtimeKernel: false, externalUserMProcessReady: false, toolDbProcessReady: false, hostExternalUserMProcessReady: false, hostToolDbProcessReady: false, arbitraryUserMExecution: false, }, toolUserWebSimulation: { externalUserMProcessReady: fullExecutionBoundary.externalUserMProcessReady === true, externalUserMProcessScope: fullExecutionBoundary.externalUserMProcessScope || "not_ready", toolDbProcessReady: fullExecutionBoundary.toolDbProcessReady === true, toolDbProcessScope: fullExecutionBoundary.toolDbProcessScope || "not_ready", ready: toolUserWebSimulationReady, }, sourceManifest: { ready: sourceManifestReady, taskSourceCount, halSourceCount, motionSourceCount, nmlSourceCount: numberFrom(sourceManifest.nml_source_count), libnmlSourceCount: numberFrom(sourceManifest.libnml_source_count), referenceSourceReady: truthy(sourceManifest.task_hal_reference_source_ready), vendorSourceReady: truthy(sourceManifest.task_hal_vendor_source_ready), vendorHashMatchReady: truthy(sourceManifest.task_hal_vendor_hash_match_ready), }, gates: { task_hal_web_simulation_boundary_consistent: webSimulationConsistent ? 1 : 0, native_task_hal_host_probe_status: nativeProbeStatus, hardware_drive: 0, host_realtime_kernel: 0, external_user_m_process_ready: toolUserWebSimulationReady ? 1 : 0, tool_db_process_ready: toolUserWebSimulationReady ? 1 : 0, host_external_user_m_process_ready: 0, host_tool_db_process_ready: 0, promotion_scope: "web_simulation_only", }, artifacts: artifactPaths, blockers: webSimulationConsistent ? [] : buildBlockers({ sourceManifestReady, nativeProbeOk, nativePromotionBlocked, taskReady, motionReady, halReady, halSyncReady, fullBoundarySimulationReady, toolUserWebSimulationReady, hardwareBlocked, }), }; } function buildBlockers(checks) { const blockers = []; if (!checks.sourceManifestReady) blockers.push("task/HAL source manifest proof is incomplete"); if (!checks.nativeProbeOk) blockers.push("native host probe did not produce an accepted default status"); if (!checks.nativePromotionBlocked) blockers.push("native probe unexpectedly allowed promotion"); if (!checks.taskReady) blockers.push("task runtime is not ready in the Web simulation boundary"); if (!checks.motionReady) blockers.push("motion runtime is not ready in the Web simulation boundary"); if (!checks.halReady) blockers.push("HAL runtime is not ready in the Web simulation boundary"); if (!checks.halSyncReady) blockers.push("task/motion/HAL sync is not ready in the Web simulation boundary"); if (!checks.fullBoundarySimulationReady) blockers.push("full execution boundary is not promoted for Web simulation"); if (!checks.toolUserWebSimulationReady) blockers.push("tool DB or controlled user-M Web simulation is not ready"); if (!checks.hardwareBlocked) blockers.push("hardware/native process blocked fields are not explicitly false"); return blockers; } function truthy(value) { return value === true || value === 1 || value === "1" || value === "true"; } function numberFrom(value) { const numeric = Number(value); return Number.isFinite(numeric) ? numeric : 0; }