推进QtDragon虚拟HAL浏览器诊断证据

This commit is contained in:
2026-06-18 04:53:59 +08:00
parent 0bc6896b36
commit 3bc3b453c4
7 changed files with 275 additions and 35 deletions

View File

@@ -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

View File

@@ -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 |

View File

@@ -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",
]),

View File

@@ -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 = {}) {

View File

@@ -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

View File

@@ -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);