diff --git a/text18.txt b/text18.txt index af56770..fe1cad5 100644 --- a/text18.txt +++ b/text18.txt @@ -516,3 +516,61 @@ git diff --check ok `qtdragon_hd_z_compensation`、`qtvcp_screens/qtdragon`。 3. 将 `axis/vismach/puma/puma_seam_weld.ngc` 与 `axis/rose_engine/rcone_demo.ngc` 纳入 browser diagnostics candidate evidence,形成非 QtDragon 的 promotion 案例。 + +### 二、2026-06-18 QtDragon Family Browser Diagnostics Promotion + +本批接续上一批 candidate report,完成 QtDragon family 全组 browser diagnostics evidence +推进,并保持 inventory baseline 不变。 + +新增实质能力: + +- `VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS` 的 `qtdragon-on-abort` target 补齐: + - `qtdragon/qtdragon_xyz45/qtdragon_xyza.ini`; + - `qtdragon/qtdragon_xyz45/on_abort.ngc`; + - `qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini`; + - `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc`; +- release diagnostics validation 从只要求 + `qtdragon-multi-joint-on-abort` 扩展为要求 QtDragon family 6 个 candidate 全部 + ready: + - `qtdragon-multi-joint-on-abort`; + - `qtdragon-xyz-on-abort`; + - `qtdragon-xyz45-on-abort`; + - `qtdragon-hd-xyz-on-abort`; + - `qtdragon-hd-z-compensation-on-abort`; + - `qtvcp-screens-qtdragon-on-abort`; +- 每个 QtDragon candidate 必须满足: + - `complete === true`; + - `currentNodeInventoryStatus === "PASS"`; + - `blockedKind === "-"`; + - `targetBrowserEvidence === "explicit-browser-diagnostics"`; + - source files 同时包含对应 LinuxCNC INI 与 G-code 文件; +- real browser simulation diagnostics artifact 同步要求 QtDragon family 全组 candidate + evidence; +- coverage matrix 注释从“browser representative delegated to woodpecker”同步为 + virtual HAL promotion candidate gate 已导出 explicit browser diagnostics evidence; +- promotion analysis 文档新增本批 QtDragon family promotion evidence 小节。 + +语义边界: + +- 本批没有降低 inventory skip count; +- 当前 baseline 仍是 `executed=28`、`passed=28`、`skipped=131`、 + `unexpected_fail=0`; +- 本批只推进 source-derived diagnostics evidence,不新增 + G-code/interpreter/planner/kinematics/remap 语义; +- virtual HAL 已满足 Web 方式数控系统仿真系统,并在仿真范围内替代 LinuxCNC + realtime HAL、`halcmd`、motion controller; +- virtual HAL 仍不提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或 native + HAL module ABI; +- `L4-PYTHON-REMAP`、`L4-TOOL-DB`、`L4-USER-M-PROCESS`、`UPSTREAM-DEMO` 仍保持 + locked; +- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM。 + +下一步工作建议: + +1. 推进非 QtDragon browser diagnostics promotion: + `axis/vismach/puma/puma_seam_weld.ngc` 与 + `axis/rose_engine/rcone_demo.ngc`。 +2. 为 PUMA / rose engine 增加 release diagnostics validation 中的 required candidate + gate,形成非 Qt、非 on-abort family 的 promotion proof。 +3. 之后再设计 macro/load non-main fixture report,不把 macro/load 误作为 standalone + browser main program 执行。 diff --git a/wasm-port/docs/sim-config-coverage-promotion-analysis.md b/wasm-port/docs/sim-config-coverage-promotion-analysis.md index e97b4ed..c5c9554 100644 --- a/wasm-port/docs/sim-config-coverage-promotion-analysis.md +++ b/wasm-port/docs/sim-config-coverage-promotion-analysis.md @@ -175,6 +175,44 @@ wasm-port/tests/sdk/node/verify_sdk_surface.sh SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh ``` +## 2026-06-18 QtDragon Family Promotion Evidence + +The first promotion-candidate gate has now been extended from a single +`qtdragon/qtdragon_multi_joint/on_abort.ngc` row to the full QtDragon +on-abort family: + +- `qtdragon/qtdragon_multi_joint/on_abort.ngc` +- `qtdragon/qtdragon_xyz/on_abort.ngc` +- `qtdragon/qtdragon_xyz45/on_abort.ngc` +- `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc` +- `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc` +- `qtvcp_screens/qtdragon/on_abort.ngc` + +The implementation remains a diagnostics/evidence promotion, not an inventory +baseline change. The rows still report Node inventory `PASS` with matrix +`INV`, but the virtual HAL promotion candidate report and real browser +diagnostics artifact now require every QtDragon candidate to be complete, to +name its LinuxCNC INI and G-code source files, to keep `currentNodeInventoryStatus +=== "PASS"`, and to target `explicit-browser-diagnostics`. + +The virtual HAL sim-config source coverage target also includes the previously +missing QtDragon `qtdragon_xyz45` and `qtdragon_hd_z_compensation` INI/program +source files. This keeps the report source-derived from vendored LinuxCNC +machine files rather than browser-owned CNC behavior. + +Inventory baseline remains: + +```text +sim_configs_wasm_node_inventory_executed=28 +sim_configs_wasm_node_inventory_passed=28 +sim_configs_wasm_node_inventory_skipped=131 +sim_configs_wasm_node_inventory_unexpected_fail=0 +``` + +The next practical promotion slice is to add non-Qt evidence for +`axis/vismach/puma/puma_seam_weld.ngc` and +`axis/rose_engine/rcone_demo.ngc`. + ## Boundary Statement This analysis relies on the improved virtual HAL only for Web simulation diff --git a/wasm-port/docs/sim-configs-coverage-matrix.md b/wasm-port/docs/sim-configs-coverage-matrix.md index 01fe78d..aefd555 100644 --- a/wasm-port/docs/sim-configs-coverage-matrix.md +++ b/wasm-port/docs/sim-configs-coverage-matrix.md @@ -617,14 +617,14 @@ Legend: | `qtaxis/non-trivial/scara/remap_subs/428remap.ngc` | `qtaxis/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | | `qtaxis/non-trivial/scara/remap_subs/429remap.ngc` | `qtaxis/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | | `qtaxis/non-trivial/scara/remap_subs/430remap.ngc` | `qtaxis/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | -| `qtdragon/qtdragon_multi_joint/on_abort.ngc` | `qtdragon/qtdragon_multi_joint` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | -| `qtdragon/qtdragon_xyz/on_abort.ngc` | `qtdragon/qtdragon_xyz` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | -| `qtdragon/qtdragon_xyz45/on_abort.ngc` | `qtdragon/qtdragon_xyz45` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | -| `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc` | `qtdragon_hd/qtdragon_hd_xyz` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | -| `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc` | `qtdragon_hd/qtdragon_hd_z_compensation` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | +| `qtdragon/qtdragon_multi_joint/on_abort.ngc` | `qtdragon/qtdragon_multi_joint` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; virtual HAL promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | +| `qtdragon/qtdragon_xyz/on_abort.ngc` | `qtdragon/qtdragon_xyz` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; QtDragon family promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | +| `qtdragon/qtdragon_xyz45/on_abort.ngc` | `qtdragon/qtdragon_xyz45` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; QtDragon family promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | +| `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc` | `qtdragon_hd/qtdragon_hd_xyz` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; QtDragon family promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | +| `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc` | `qtdragon_hd/qtdragon_hd_z_compensation` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; QtDragon family promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | | `qtvcp_screens/industrial_lathe_wear/toolchange.ngc` | `qtvcp_screens/industrial_lathe_wear` | `macro_load` | `PASS` | `-` | `-` | `-` | `-` | `-` | inventory-only macro/load path; macro_load class coverage is represented by `axis/external_offsets/circles.ngc` unless this family is deliberately promoted later | | `qtvcp_screens/non-trivial/scara/remap_subs/428remap.ngc` | `qtvcp_screens/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | | `qtvcp_screens/non-trivial/scara/remap_subs/429remap.ngc` | `qtvcp_screens/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | | `qtvcp_screens/non-trivial/scara/remap_subs/430remap.ngc` | `qtvcp_screens/non-trivial` | `remap_subroutine` | `PASS` | `-` | `-` | `N/A` | `N/A` | `ASSET-ONLY` | subroutine asset; validate by parse/remap path rather than standalone main-program execution | -| `qtvcp_screens/qtdragon/on_abort.ngc` | `qtvcp_screens/qtdragon` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table now allow Node inventory coverage; browser representative still delegated to the shared `woodpecker/on_abort.ngc` class sample | +| `qtvcp_screens/qtdragon/on_abort.ngc` | `qtvcp_screens/qtdragon` | `main` | `PASS` | `-` | `-` | `INV` | `-` | `-` | vendored INI/tool-table allow Node inventory coverage; QtDragon family promotion candidate gate now exports explicit browser diagnostics evidence while inventory baseline remains unchanged | | `woodpecker/on_abort.ngc` | `woodpecker` | `main` | `PASS` | `-` | `-` | `REP` | `REP` | `-` | Layer 4 deterministic on_abort class representative now covered | diff --git a/wasm-port/runtime/sdk/src/linuxcnc-hal.js b/wasm-port/runtime/sdk/src/linuxcnc-hal.js index 6e8a876..732efd3 100644 --- a/wasm-port/runtime/sdk/src/linuxcnc-hal.js +++ b/wasm-port/runtime/sdk/src/linuxcnc-hal.js @@ -97,8 +97,12 @@ export const VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS = Object.freeze([ "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc", "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini", "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc", "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini", "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc", ]), diff --git a/wasm-port/runtime/sdk/src/project-release-readiness.js b/wasm-port/runtime/sdk/src/project-release-readiness.js index 63f7264..a3eed12 100644 --- a/wasm-port/runtime/sdk/src/project-release-readiness.js +++ b/wasm-port/runtime/sdk/src/project-release-readiness.js @@ -88,6 +88,51 @@ const BLOCKED_RUNTIME_FAMILIES = [ const PROJECT_RELEASE_READINESS_ARTIFACT_API = "project-release-readiness-report"; const PROJECT_RELEASE_READINESS_ARTIFACT_VERSION = 1; +const REQUIRED_QTDRAGON_PROMOTION_CANDIDATES = [ + { + id: "qtdragon-multi-joint-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc", + ], + }, + { + id: "qtdragon-xyz-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc", + ], + }, + { + id: "qtdragon-xyz45-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc", + ], + }, + { + id: "qtdragon-hd-xyz-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc", + ], + }, + { + id: "qtdragon-hd-z-compensation-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc", + ], + }, + { + id: "qtvcp-screens-qtdragon-on-abort", + sourceFiles: [ + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini", + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc", + ], + }, +]; + function isVirtualHalSimConfigSourceCoverageReady(report) { const coverage = objectOrEmpty(report); return coverage.apiName === "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report" && @@ -96,7 +141,24 @@ function isVirtualHalSimConfigSourceCoverageReady(report) { arrayOrEmpty(coverage.missingTargets).length === 0 && arrayOrEmpty(coverage.missingCapabilities).length === 0 && arrayOrEmpty(coverage.sourceFiles).includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini") && - arrayOrEmpty(coverage.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc"); + arrayOrEmpty(coverage.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc") && + arrayOrEmpty(coverage.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini") && + arrayOrEmpty(coverage.sourceFiles).includes( + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + ); +} + +function hasRequiredQtDragonPromotionCandidates(rows) { + return REQUIRED_QTDRAGON_PROMOTION_CANDIDATES.every((candidate) => + rows.some((row) => + row.id === candidate.id && + row.complete === true && + row.currentNodeInventoryStatus === "PASS" && + row.blockedKind === "-" && + row.targetBrowserEvidence === "explicit-browser-diagnostics" && + candidate.sourceFiles.every((file) => arrayOrEmpty(row.sourceFiles).includes(file)) + ) + ); } function isVirtualHalMotionControllerMatrixReady(report) { @@ -131,15 +193,7 @@ function isVirtualHalSimConfigPromotionCandidateReportReady(report) { arrayOrEmpty(candidateReport.blockedCandidateIds).length === 0 && arrayOrEmpty(candidateReport.missingManifestFiles).length === 0 && arrayOrEmpty(candidateReport.missingRequiredReports).length === 0 && - rows.some((row) => - row.id === "qtdragon-multi-joint-on-abort" && - row.complete === true && - row.currentNodeInventoryStatus === "PASS" && - row.blockedKind === "-" && - row.targetBrowserEvidence === "explicit-browser-diagnostics" && - arrayOrEmpty(row.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") && - arrayOrEmpty(row.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc") - ); + hasRequiredQtDragonPromotionCandidates(rows); } export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifact = {}) { diff --git a/wasm-port/tests/browser/real_simulation_page_smoke.html b/wasm-port/tests/browser/real_simulation_page_smoke.html index 27126a2..11a56f4 100644 --- a/wasm-port/tests/browser/real_simulation_page_smoke.html +++ b/wasm-port/tests/browser/real_simulation_page_smoke.html @@ -408,6 +408,38 @@ throw new Error(`simulation virtual HAL registry/integrity drift: ${JSON.stringify(initialVirtualHalRegistry)}`); } const diagnosticsArtifact = api.exportDiagnosticsArtifact(); + const expectedQtDragonPromotionCandidates = [ + [ + "qtdragon-multi-joint-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc", + ], + [ + "qtdragon-xyz-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc", + ], + [ + "qtdragon-xyz45-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc", + ], + [ + "qtdragon-hd-xyz-on-abort", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc", + ], + [ + "qtdragon-hd-z-compensation-on-abort", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc", + ], + [ + "qtvcp-screens-qtdragon-on-abort", + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini", + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc", + ], + ]; if ( diagnosticsArtifact.apiName !== "real-browser-simulation-diagnostics-artifact" || diagnosticsArtifact.statusHistory.length === 0 || @@ -419,12 +451,18 @@ !diagnosticsArtifact.virtualHalSourceCompliance?.sourceFiles?.includes("linuxcnc/src/hal/utils/halcmd_commands.cc") || 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") || + !diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini") || diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.complete !== true || - !diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.rows?.some((row) => - row.id === "qtdragon-multi-joint-on-abort" && - row.complete === true && - row.currentNodeInventoryStatus === "PASS" && - row.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") + !expectedQtDragonPromotionCandidates.every(([id, iniPath, gcodePath]) => + diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.rows?.some((row) => + row.id === id && + row.complete === true && + row.currentNodeInventoryStatus === "PASS" && + row.targetBrowserEvidence === "explicit-browser-diagnostics" && + row.sourceFiles.includes(iniPath) && + row.sourceFiles.includes(gcodePath) + ) ) || diagnosticsArtifact.virtualHalCommandScriptFixtures?.complete !== true || !diagnosticsArtifact.virtualHalCommandScriptFixtures?.coveredActions?.includes("loadusr") || @@ -865,9 +903,14 @@ !api.getVirtualHalSimConfigSourceCoverageReport().sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc") || promotionCandidateReport.complete !== true || promotionCandidateReport.inventoryBaselineUnchanged !== true || - !promotionCandidateReport.rows.some(({ id, targetBrowserEvidence }) => - id === "qtdragon-multi-joint-on-abort" && - targetBrowserEvidence === "explicit-browser-diagnostics" + !expectedQtDragonPromotionCandidates.every(([id, iniPath, gcodePath]) => + promotionCandidateReport.rows.some((row) => + row.id === id && + row.complete === true && + row.targetBrowserEvidence === "explicit-browser-diagnostics" && + row.sourceFiles.includes(iniPath) && + row.sourceFiles.includes(gcodePath) + ) ) || api.getVirtualRealtimeHalRuntimeReport().ready !== true || api.getVirtualHalSimulationRuntimeReport().replacesHostRuntimeForSimulation !== true diff --git a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs index c389ed9..d336dfc 100644 --- a/wasm-port/tests/sdk/node/verify_sdk_surface.mjs +++ b/wasm-port/tests/sdk/node/verify_sdk_surface.mjs @@ -747,6 +747,13 @@ assert.equal(simConfigSourceCoverageReport.missingTargets.length, 0); assert.equal(simConfigSourceCoverageReport.missingCapabilities.length, 0); assert.equal(simConfigSourceCoverageReport.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true); assert.equal(simConfigSourceCoverageReport.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc"), true); +assert.equal(simConfigSourceCoverageReport.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini"), true); +assert.equal( + simConfigSourceCoverageReport.sourceFiles.includes( + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + ), + true, +); assert.equal(simConfigSourceCoverageReport.rows.every(({ sourceDerived }) => sourceDerived), true); assert.equal(virtualHalRuntime.getSimConfigSourceCoverageReport({ manifestText: sourceManifestText }).complete, true); assert.equal(VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES.length >= 8, true); @@ -767,17 +774,51 @@ assert.equal(simConfigPromotionCandidateReport.missingCandidates.length, 0); assert.equal(simConfigPromotionCandidateReport.blockedCandidateIds.length, 0); assert.equal(simConfigPromotionCandidateReport.missingManifestFiles.length, 0); assert.equal(simConfigPromotionCandidateReport.missingRequiredReports.length, 0); -assert.equal( - simConfigPromotionCandidateReport.rows.some((row) => - row.id === "qtdragon-multi-joint-on-abort" && - row.complete === true && - row.currentNodeInventoryStatus === "PASS" && - row.targetBrowserEvidence === "explicit-browser-diagnostics" && - row.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") && - row.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc") - ), - true, -); +const expectedQtDragonPromotionCandidates = [ + [ + "qtdragon-multi-joint-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc", + ], + [ + "qtdragon-xyz-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc", + ], + [ + "qtdragon-xyz45-on-abort", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini", + "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc", + ], + [ + "qtdragon-hd-xyz-on-abort", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc", + ], + [ + "qtdragon-hd-z-compensation-on-abort", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini", + "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc", + ], + [ + "qtvcp-screens-qtdragon-on-abort", + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini", + "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc", + ], +]; +for (const [id, iniPath, gcodePath] of expectedQtDragonPromotionCandidates) { + assert.equal( + simConfigPromotionCandidateReport.rows.some((row) => + row.id === id && + row.complete === true && + row.currentNodeInventoryStatus === "PASS" && + row.targetBrowserEvidence === "explicit-browser-diagnostics" && + row.sourceFiles.includes(iniPath) && + row.sourceFiles.includes(gcodePath) + ), + true, + ); +} assert.equal(simConfigPromotionCandidateReport.rows.every(({ blockedKind }) => blockedKind === "-"), true); assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({ manifestText: sourceManifestText, @@ -864,6 +905,8 @@ assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true); assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true); assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"), true); +assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini"), true); +assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc"), true); assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini"), true); const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS }); assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true);