锁定虚拟HAL宏加载阻断证据

This commit is contained in:
2026-06-18 05:21:30 +08:00
parent 506a6357c1
commit 014081f1f9
10 changed files with 221 additions and 6 deletions

View File

@@ -700,3 +700,68 @@ browser diagnostics proof。
3. 如 UI-family 边界不清晰,先增加 negative fixture gate证明
`L4-PYTHON-REMAP` / Python UI process 相关 macro/load 不会被 macro/load fixture
report 误解锁。
### 五、2026-06-18 Macro Load Blocked Fixture Lock
本批按上一节建议先评估 `gscreen/silverdragon/macros/tool_sensor.ngc`。结论是不能直接
作为 positive macro/load fixture 推进:当前 generated boundary evidence 显示 owning
machine file `gscreen/silverdragon/silverdragon.ini` 在 vendored manifest 中不可用,且该
family 涉及 Python UI/process 边界风险。为避免 virtual HAL 误解锁 Python UI 或
Python remap family本批新增 negative fixture gate。
新增实质能力:
- 新增 `VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES`
- `createVirtualHalSimConfigMacroLoadFixtureReport()` 新增:
- `blockedRows`
- `blockedFixturePromotionViolations`
- summary row`blocked-fixture-lock`
- 首批 blocked fixture
- `silverdragon-tool-sensor-python-ui-boundary`
- `fixturePath` 为
`linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc`
- `owningIniPath` 为
`linuxcnc/configs/sim/gscreen/silverdragon/silverdragon.ini`
- `blockedKind` 为 `PYTHON-UI-PROCESS`
- 必须 `excludedFromPositiveFixtures === true`
- `gmoccapy-on-abort-python-remap-boundary`
- `fixturePath` 为
`linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc`
- `owningIniPath` 为 `linuxcnc/configs/sim/gmoccapy/6_axis.ini`
- `blockedKind` 为 `L4-PYTHON-REMAP`
- 必须 `excludedFromPositiveFixtures === true`
- release diagnostics validation 新增 required negative evidence
- `blockedFixturePromotionViolations.length === 0`
- SilverDragon `tool_sensor.ngc` 与 gmoccapy `on_abort.ngc` 必须存在于
`blockedRows`
- 两者不能出现在 positive macro/load fixture rows
- real simulation smoke 与 SDK smoke 同步验证 blocked fixture lock
- coverage matrix 对 `gscreen/silverdragon/macros/tool_sensor.ngc` 注释更新为 blocked
negative fixture
- promotion analysis 文档新增 Macro/Load Blocked Fixture Lock 小节。
语义边界:
- 本批没有降低 inventory skip count
- 当前 baseline 仍是 `executed=28`、`passed=28`、`skipped=131`、
`unexpected_fail=0`
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
- 本批没有把 SilverDragon、gmoccapy 或任何 Python UI / Python remap family 作为
virtual HAL positive fixture 推进;
- virtual HAL 已满足 Web 方式数控系统仿真系统,并在仿真范围内替代 LinuxCNC
realtime HAL、`halcmd`、motion controller
- virtual HAL 仍不提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI、native
HAL module ABI、Python UI process emulation 或 Python remap runtime
- `L4-PYTHON-REMAP`、`L4-TOOL-DB`、`L4-USER-M-PROCESS`、`UPSTREAM-DEMO` 仍保持
locked
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM。
下一步工作建议:
1. 为 macro/load fixture report 增加 UI-family candidate audit
`gscreen/industrial_lathe_wear/toolchange.ngc` 与
`qtvcp_screens/industrial_lathe_wear/toolchange.ngc` 先作为 audit rows 评估。
2. 只有 owning INI、machine files、tool table、UI/process declaration 都有
LinuxCNC source evidence且不需要 Python UI process emulation 时,才允许转为
positive non-main fixture。
3. 如证据仍不完整,继续扩展 blocked fixture lock不降低 inventory baseline。

View File

@@ -254,9 +254,32 @@ Release diagnostics validation now requires
keep `inventoryBaselineUnchanged === true`, every row must have
`nonMainFixture === true`, and `standaloneMainViolations` must stay empty.
The next practical slice is to extend this report with one more non-main family
such as `gscreen/silverdragon/macros/tool_sensor.ngc`, after proving the owning
machine files and UI/process boundary do not cross into Python UI emulation.
## 2026-06-18 Macro/Load Blocked Fixture Lock
The macro/load report now also carries a blocked-fixture lock. This is a
negative evidence gate: it proves selected macro/load paths are not included in
positive virtual HAL fixtures when their owner boundary is still unavailable or
outside the virtual HAL scope.
The first blocked fixture rows are:
- `gscreen/silverdragon/macros/tool_sensor.ngc`
- `gmoccapy/macros/on_abort.ngc`
`tool_sensor.ngc` is intentionally not promoted because the owning
`gscreen/silverdragon/silverdragon.ini` machine file is not available in the
vendored manifest, and promoting it would require a Python UI/process boundary
proof rather than virtual HAL diagnostics alone. `gmoccapy/macros/on_abort.ngc`
remains locked behind `L4-PYTHON-REMAP` and LinuxCNC-owned Python
remap/prolog/epilog runtime proof.
Release diagnostics validation now requires
`blockedFixturePromotionViolations` to stay empty and requires both blocked
rows to be excluded from positive macro/load fixtures. This prevents virtual
HAL from accidentally unlocking Python UI or Python remap families.
The next practical slice is to add a machine-readable candidate audit for other
UI-family macro/load rows before promoting any new positive fixture.
## Boundary Statement

View File

@@ -612,7 +612,7 @@ Legend:
| `gscreen/industrial_lathe_wear/toolchange.ngc` | `gscreen/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 |
| `gscreen/silverdragon/macros/auto_zref.ngc` | `gscreen/silverdragon` | `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 |
| `gscreen/silverdragon/macros/laserzero.ngc` | `gscreen/silverdragon` | `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 |
| `gscreen/silverdragon/macros/tool_sensor.ngc` | `gscreen/silverdragon` | `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 |
| `gscreen/silverdragon/macros/tool_sensor.ngc` | `gscreen/silverdragon` | `macro_load` | `PASS` | `-` | `-` | `-` | `-` | `-` | virtual HAL macro/load report keeps this as a blocked negative fixture until the missing SilverDragon owning INI and Python UI/process boundary are proven; not promoted by virtual HAL |
| `gscreen/silverdragon/macros/touch_plate.ngc` | `gscreen/silverdragon` | `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 |
| `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 |

View File

@@ -328,12 +328,15 @@ private page state.
browser diagnostics evidence, and the required virtual HAL reports for
QtDragon on-abort, PUMA seam-weld, and rose-engine promotion planning.
- `VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES` and
`VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES` plus
`createVirtualHalSimConfigMacroLoadFixtureReport()` expose non-main
macro/load fixture evidence for virtual HAL diagnostics. The report keeps
`nonMainFixture === true`, separates fixture paths from manifest-backed
LinuxCNC source files, and prevents macro/load rows such as rose-engine
`rcone.ngc` or external-offsets `queuebuster.ngc` from being promoted as
standalone browser main programs.
standalone browser main programs. Blocked fixture rows such as SilverDragon
`tool_sensor.ngc` remain excluded until their Python UI/process boundary is
proven outside virtual HAL.
- `createVirtualHalSourceComplianceReport()` is the machine-readable gate for
the virtual HAL source rule. It maps replacement targets, runtime
capabilities, and HAL pin families back to LinuxCNC source files such as

View File

@@ -7,6 +7,7 @@ export {
VIRTUAL_HAL_COVERAGE_STATES,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,

View File

@@ -363,6 +363,25 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
}),
]);
export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES = Object.freeze([
Object.freeze({
id: "silverdragon-tool-sensor-python-ui-boundary",
fixturePath: "linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc",
owningIniPath: "linuxcnc/configs/sim/gscreen/silverdragon/silverdragon.ini",
blockedKind: "PYTHON-UI-PROCESS",
dependencyClass: "macro-load-python-ui-boundary",
reason: "Owning SilverDragon UI machine file is not available in the vendored manifest; promotion would require Python UI process boundary proof outside virtual HAL.",
}),
Object.freeze({
id: "gmoccapy-on-abort-python-remap-boundary",
fixturePath: "linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc",
owningIniPath: "linuxcnc/configs/sim/gmoccapy/6_axis.ini",
blockedKind: "L4-PYTHON-REMAP",
dependencyClass: "macro-load-python-remap-boundary",
reason: "gmoccapy macro/load rows remain locked behind LinuxCNC-owned Python remap/prolog/epilog runtime proof.",
}),
]);
export const VIRTUAL_HAL_COVERAGE_STATES = Object.freeze({
simulated: "simulated",
bridgeOnly: "bridge-only",
@@ -2852,6 +2871,7 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
const fixtures = options.fixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES;
const blockedFixtures = options.blockedFixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES;
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
const manifestSet = new Set([
...sourceManifestSetFromText(options.manifestText ?? ""),
@@ -2908,11 +2928,30 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
.filter((row) => row.nonMainFixture !== true || row.targetBrowserEvidence !== "non-main-fixture-diagnostics")
.map((row) => row.id);
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
const positiveFixturePaths = new Set(rows.map((row) => normalizeLinuxCncSourcePath(row.fixturePath)));
const blockedRows = blockedFixtures.map((fixture) => {
const excludedFromPositiveFixtures = !positiveFixturePaths.has(normalizeLinuxCncSourcePath(fixture.fixturePath));
return {
id: fixture.id,
source: "linuxcnc-configs-sim-source-derived-virtual-hal-macro-load-blocked-fixture",
fixturePath: fixture.fixturePath,
owningIniPath: fixture.owningIniPath,
blockedKind: fixture.blockedKind,
dependencyClass: fixture.dependencyClass,
excludedFromPositiveFixtures,
reason: fixture.reason,
complete: excludedFromPositiveFixtures,
};
});
const blockedFixturePromotionViolations = blockedRows
.filter((row) => row.excludedFromPositiveFixtures !== true)
.map((row) => row.id);
const complete = rows.length > 0 &&
missingFixtures.length === 0 &&
blockedFixtureIds.length === 0 &&
standaloneMainViolations.length === 0 &&
missingManifestFiles.length === 0;
missingManifestFiles.length === 0 &&
blockedFixturePromotionViolations.length === 0;
return {
apiName: "linuxcnc-wasm-virtual-hal-sim-config-macro-load-fixture-report",
reportVersion: 1,
@@ -2928,11 +2967,14 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
missingFixtures,
blockedFixtureIds,
standaloneMainViolations,
blockedFixturePromotionViolations,
missingManifestFiles,
rows,
blockedRows,
summaryRows: [
{ id: "fixtures", label: "Macro/load fixtures", value: `${rows.length}` },
{ id: "non-main", label: "Non-main fixture gate", value: standaloneMainViolations.length === 0 ? "passed" : `violations ${standaloneMainViolations.length}` },
{ id: "blocked-fixture-lock", label: "Blocked fixture lock", value: blockedFixturePromotionViolations.length === 0 ? "passed" : `violations ${blockedFixturePromotionViolations.length}` },
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedFixtureIds.length === 0 ? "passed" : `blocked ${blockedFixtureIds.length}` },
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" },

View File

@@ -168,6 +168,19 @@ const REQUIRED_MACRO_LOAD_FIXTURES = [
},
];
const REQUIRED_BLOCKED_MACRO_LOAD_FIXTURES = [
{
id: "silverdragon-tool-sensor-python-ui-boundary",
fixturePath: "linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc",
blockedKind: "PYTHON-UI-PROCESS",
},
{
id: "gmoccapy-on-abort-python-remap-boundary",
fixturePath: "linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc",
blockedKind: "L4-PYTHON-REMAP",
},
];
function isVirtualHalSimConfigSourceCoverageReady(report) {
const coverage = objectOrEmpty(report);
return coverage.apiName === "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report" &&
@@ -206,6 +219,7 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
arrayOrEmpty(fixtureReport.missingFixtures).length === 0 &&
arrayOrEmpty(fixtureReport.blockedFixtureIds).length === 0 &&
arrayOrEmpty(fixtureReport.standaloneMainViolations).length === 0 &&
arrayOrEmpty(fixtureReport.blockedFixturePromotionViolations).length === 0 &&
arrayOrEmpty(fixtureReport.missingManifestFiles).length === 0 &&
REQUIRED_MACRO_LOAD_FIXTURES.every((fixture) =>
rows.some((row) =>
@@ -216,6 +230,15 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
row.fixturePath === fixture.fixturePath &&
fixture.sourceFiles.every((file) => arrayOrEmpty(row.sourceFiles).includes(file))
)
) &&
REQUIRED_BLOCKED_MACRO_LOAD_FIXTURES.every((fixture) =>
arrayOrEmpty(fixtureReport.blockedRows).some((row) =>
row.id === fixture.id &&
row.fixturePath === fixture.fixturePath &&
row.blockedKind === fixture.blockedKind &&
row.excludedFromPositiveFixtures === true &&
row.complete === true
)
);
}

View File

@@ -19,6 +19,7 @@ export {
VIRTUAL_HAL_AXES,
VIRTUAL_HAL_AXISUI_PINS,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,

View File

@@ -469,6 +469,18 @@
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
],
];
const expectedBlockedMacroLoadFixtures = [
[
"silverdragon-tool-sensor-python-ui-boundary",
"linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc",
"PYTHON-UI-PROCESS",
],
[
"gmoccapy-on-abort-python-remap-boundary",
"linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc",
"L4-PYTHON-REMAP",
],
];
if (
diagnosticsArtifact.apiName !== "real-browser-simulation-diagnostics-artifact" ||
diagnosticsArtifact.statusHistory.length === 0 ||
@@ -493,6 +505,7 @@
)
) ||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.complete !== true ||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.blockedFixturePromotionViolations?.length !== 0 ||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, ...sourceFiles]) =>
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.rows?.some((row) =>
row.id === id &&
@@ -504,6 +517,15 @@
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
)
) ||
!expectedBlockedMacroLoadFixtures.every(([id, fixturePath, blockedKind]) =>
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.blockedRows?.some((row) =>
row.id === id &&
row.fixturePath === fixturePath &&
row.blockedKind === blockedKind &&
row.excludedFromPositiveFixtures === true &&
row.complete === true
)
) ||
diagnosticsArtifact.virtualHalCommandScriptFixtures?.complete !== true ||
!diagnosticsArtifact.virtualHalCommandScriptFixtures?.coveredActions?.includes("loadusr") ||
diagnosticsArtifact.virtualHalMotionControllerMatrix?.complete !== true ||
@@ -955,6 +977,7 @@
macroLoadFixtureReport.complete !== true ||
macroLoadFixtureReport.inventoryBaselineUnchanged !== true ||
macroLoadFixtureReport.standaloneMainViolations.length !== 0 ||
macroLoadFixtureReport.blockedFixturePromotionViolations.length !== 0 ||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, ...sourceFiles]) =>
macroLoadFixtureReport.rows.some((row) =>
row.id === id &&
@@ -965,6 +988,15 @@
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
)
) ||
!expectedBlockedMacroLoadFixtures.every(([id, fixturePath, blockedKind]) =>
macroLoadFixtureReport.blockedRows.some((row) =>
row.id === id &&
row.fixturePath === fixturePath &&
row.blockedKind === blockedKind &&
row.excludedFromPositiveFixtures === true &&
row.complete === true
)
) ||
api.getVirtualRealtimeHalRuntimeReport().ready !== true ||
api.getVirtualHalSimulationRuntimeReport().replacesHostRuntimeForSimulation !== true
) {

View File

@@ -36,6 +36,7 @@ import {
VIRTUAL_HAL_COVERAGE_STATES,
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
@@ -548,6 +549,8 @@ assert.match(sdkIndexText, /\bcreateVirtualHalSimConfigPromotionCandidateReport\
assert.match(sdkReadmeText, /\bcreateVirtualHalSimConfigPromotionCandidateReport\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES\b/);
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES\b/);
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES\b/);
assert.match(sdkIndexText, /\bcreateVirtualHalSimConfigMacroLoadFixtureReport\b/);
assert.match(sdkReadmeText, /\bcreateVirtualHalSimConfigMacroLoadFixtureReport\b/);
assert.match(sdkIndexText, /\bcreateVirtualHalSourceComplianceReport\b/);
@@ -843,6 +846,7 @@ assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
}).complete, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.length >= 2, true);
const simConfigMacroLoadFixtureReport = createVirtualHalSimConfigMacroLoadFixtureReport({
manifestText: sourceManifestText,
});
@@ -857,6 +861,7 @@ assert.equal(simConfigMacroLoadFixtureReport.manifestChecked, true);
assert.equal(simConfigMacroLoadFixtureReport.missingFixtures.length, 0);
assert.equal(simConfigMacroLoadFixtureReport.blockedFixtureIds.length, 0);
assert.equal(simConfigMacroLoadFixtureReport.standaloneMainViolations.length, 0);
assert.equal(simConfigMacroLoadFixtureReport.blockedFixturePromotionViolations.length, 0);
assert.equal(simConfigMacroLoadFixtureReport.missingManifestFiles.length, 0);
assert.equal(
simConfigMacroLoadFixtureReport.rows.some((row) =>
@@ -882,6 +887,26 @@ assert.equal(
),
true,
);
assert.equal(
simConfigMacroLoadFixtureReport.blockedRows.some((row) =>
row.id === "silverdragon-tool-sensor-python-ui-boundary" &&
row.fixturePath === "linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc" &&
row.blockedKind === "PYTHON-UI-PROCESS" &&
row.excludedFromPositiveFixtures === true &&
row.complete === true
),
true,
);
assert.equal(
simConfigMacroLoadFixtureReport.blockedRows.some((row) =>
row.id === "gmoccapy-on-abort-python-remap-boundary" &&
row.fixturePath === "linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc" &&
row.blockedKind === "L4-PYTHON-REMAP" &&
row.excludedFromPositiveFixtures === true &&
row.complete === true
),
true,
);
assert.equal(virtualHalRuntime.getSimConfigMacroLoadFixtureReport({
manifestText: sourceManifestText,
}).complete, true);