接入虚拟HAL仿真配置promotion证据
This commit is contained in:
390
text17.txt
390
text17.txt
@@ -1266,3 +1266,393 @@ git diff --check ok
|
||||
fixtures,使 URL workflow 同时覆盖 live diagnostics 与 saved-session diagnostics。
|
||||
3. 将 workflow overview 固定 URL 表单的 action-plan 与 gate execution summary rows
|
||||
同屏渲染,便于用户看到 URL workflow 的下一步命令和 gate evidence。
|
||||
|
||||
### 十四、2026-06-17 Motion Matrix Manifest-Backed Source Check
|
||||
|
||||
继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL
|
||||
完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项,为 motion
|
||||
controller matrix 增加 manifest-backed source check,把 matrix 关联的 LinuxCNC
|
||||
`configs/sim` source files 与 vendored LinuxCNC manifest 做显式一致性验证。
|
||||
|
||||
新增实质能力:
|
||||
|
||||
- `createVirtualHalMotionControllerMatrixReport()` 新增 manifest 输入:
|
||||
- `manifestText`;
|
||||
- `manifestEntries`;
|
||||
- motion matrix report 新增:
|
||||
- `manifestChecked`;
|
||||
- `missingManifestFiles`;
|
||||
- row-level `manifestChecked`;
|
||||
- row-level `missingManifestFiles`;
|
||||
- summary row:`Sim config manifest check`;
|
||||
- 当调用方提供 manifest 时,matrix 关联的 sim config source files 必须全部存在于
|
||||
vendored LinuxCNC manifest,否则 matrix `complete` 与 `webSimulationSatisfied`
|
||||
不能通过;
|
||||
- `createProjectReleaseBrowserDiagnosticsArtifactValidation()` 加严:
|
||||
- browser diagnostics artifact 中的 `virtualHalMotionControllerMatrix` 必须
|
||||
`manifestChecked === true`;
|
||||
- `missingManifestFiles.length === 0`;
|
||||
- real simulation page 现在用 `VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS` 派生 manifest
|
||||
entries,并将其传入:
|
||||
- live diagnostics artifact;
|
||||
- Browser API `getVirtualHalMotionControllerMatrixReport()`;
|
||||
- saved virtual HAL session snapshot;
|
||||
- saved-session release diagnostics artifact;
|
||||
- SDK README 同步说明 motion matrix 支持 manifest-backed sim-config source check。
|
||||
|
||||
新增/扩展验证:
|
||||
|
||||
- `verify_sdk_surface.mjs` 覆盖:
|
||||
- 未提供 manifest 时 matrix 仍可作为 source-derived motion fixture report;
|
||||
- 提供真实 `wasm-port/tools/source-manifest.txt` 后
|
||||
`manifestChecked === true`;
|
||||
- `missingManifestFiles.length === 0`;
|
||||
- 所有 matrix rows 均完成 row-level manifest check;
|
||||
- release browser diagnostics validation 必须使用 manifest-checked matrix 才 ready;
|
||||
- `real_simulation_page_smoke.html` 覆盖:
|
||||
- browser API 返回 manifest-checked matrix;
|
||||
- diagnostics matrix `missingManifestFiles.length === 0`;
|
||||
- 每个 matrix row 的 manifest check 均通过;
|
||||
- `ini_panel_workflow_overview_smoke.html` 与 `verify_ini_panel_ui_shell.mjs` 同步使用
|
||||
manifest-checked diagnostics fixture,保证 URL workflow 示例 artifact 与真实 Web
|
||||
diagnostics artifact 规则一致。
|
||||
|
||||
关键验证:
|
||||
|
||||
```text
|
||||
sdk_surface_node_smoke=ok
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
project_release_artifact_url_workflow_node_smoke=ok
|
||||
project_batch_acceptance_workflow_node_smoke=ok
|
||||
project_batch_acceptance_artifact_node_smoke=ok
|
||||
browser_real_simulation_page_smoke=ok
|
||||
ini_panel_ui_shell_node_smoke=ok
|
||||
ui_node_smokes=ok
|
||||
browser_ini_opfs_smoke=ok
|
||||
browser_ini_control_page_smoke=ok
|
||||
browser_ini_launch_smoke=ok
|
||||
browser_ini_workflow_overview_smoke=ok
|
||||
browser_ini_shell_integration_workflow_smoke=ok
|
||||
```
|
||||
|
||||
语义边界:
|
||||
|
||||
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
|
||||
- manifest-backed check 只验证 motion matrix 关联的 LinuxCNC `configs/sim` source
|
||||
files 存在于 vendored manifest;
|
||||
- virtual HAL 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或
|
||||
native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM;
|
||||
- Web 方式数控系统仿真所需 HAL、halcmd、motion controller 替代层继续由
|
||||
source-derived virtual HAL 满足。
|
||||
|
||||
下一步工作内容:
|
||||
|
||||
1. 将 virtual HAL session diagnostics artifact 纳入 release artifact URL workflow 的示例
|
||||
fixtures,使 URL workflow 同时覆盖 live diagnostics 与 saved-session diagnostics。
|
||||
2. 将 workflow overview 固定 URL 表单的 action-plan 与 gate execution summary rows
|
||||
同屏渲染,便于用户看到 URL workflow 的下一步命令和 gate evidence。
|
||||
3. 将 manifest-backed motion matrix check 接入 project release readiness / batch
|
||||
acceptance artifact,使 release gate 不仅检查 sim-config source coverage,也检查
|
||||
motion matrix 关联 source files 的 manifest 一致性。
|
||||
|
||||
### 十五、2026-06-17 Release URL Workflow Saved-Session Diagnostics
|
||||
|
||||
继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL
|
||||
完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项,把 saved-session
|
||||
diagnostics artifact 纳入 release artifact URL workflow 示例 fixtures,使 URL workflow
|
||||
同时覆盖 live diagnostics 与 saved virtual HAL session diagnostics。
|
||||
|
||||
新增实质能力:
|
||||
|
||||
- `createProjectReleaseBrowserDiagnosticsArtifactValidation()` 新增 saved-session
|
||||
diagnostics 识别:
|
||||
- `hasSessionDiagnostics`;
|
||||
- `sessionDiagnosticsReady`;
|
||||
- validation rows 新增 `session-diagnostics`;
|
||||
- 当 browser diagnostics artifact 携带 `virtualHalSessionDiagnostics` 时,release
|
||||
validation 会检查:
|
||||
- session diagnostics API 名称;
|
||||
- `ready === true`;
|
||||
- `phase === "release-ready"`;
|
||||
- 内嵌 validation ready;
|
||||
- 内嵌 diagnostics artifact 为 real browser diagnostics artifact;
|
||||
- 内嵌 source compliance complete;
|
||||
- 内嵌 motion matrix manifest-backed check ready;
|
||||
- 当 browser diagnostics artifact 尚未携带 saved-session diagnostics 时,live diagnostics
|
||||
validation 仍可通过,避免未保存会话的页面初始诊断被误判 blocked;
|
||||
- `createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel()` 新增 summary row:
|
||||
- `saved-session-diagnostics`;
|
||||
- INI panel workflow overview URL workflow summary 同步新增:
|
||||
- `saved-session-diagnostics`;
|
||||
- URL workflow 示例 fixtures 现在同时包含:
|
||||
- live virtual HAL diagnostics evidence;
|
||||
- saved virtual HAL session diagnostics evidence;
|
||||
- manifest-checked motion matrix evidence。
|
||||
|
||||
新增/扩展验证:
|
||||
|
||||
- `verify_project_release_artifact_url_workflow.mjs` 覆盖:
|
||||
- diagnostics artifact 携带 `virtualHalSessionDiagnostics`;
|
||||
- URL workflow `diagnosticsValidation.hasSessionDiagnostics === true`;
|
||||
- URL workflow `diagnosticsValidation.sessionDiagnosticsReady === true`;
|
||||
- summary row `saved-session-diagnostics` 显示 `ready`;
|
||||
- `verify_sdk_surface.mjs` 覆盖:
|
||||
- browser diagnostics validation 可识别 saved-session diagnostics;
|
||||
- session diagnostics ready 后整体 validation ready;
|
||||
- `verify_ini_panel_ui_shell.mjs` 覆盖:
|
||||
- INI panel URL workflow diagnostics validation 识别 saved-session evidence;
|
||||
- summary/render rows 中包含 `saved-session-diagnostics`;
|
||||
- `ini_panel_workflow_overview_smoke.html` 覆盖:
|
||||
- 固定 URL workflow 页面使用包含 saved-session diagnostics 的 browser diagnostics
|
||||
fixture;
|
||||
- 页面 URL workflow validation 中 saved-session diagnostics ready;
|
||||
- DOM render rows 包含 saved-session diagnostics row。
|
||||
|
||||
关键验证:
|
||||
|
||||
```text
|
||||
project_release_artifact_url_workflow_node_smoke=ok
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
sdk_surface_node_smoke=ok
|
||||
project_batch_acceptance_workflow_node_smoke=ok
|
||||
project_batch_acceptance_artifact_node_smoke=ok
|
||||
ini_panel_ui_shell_node_smoke=ok
|
||||
ui_node_smokes=ok
|
||||
browser_ini_opfs_smoke=ok
|
||||
browser_ini_control_page_smoke=ok
|
||||
browser_ini_launch_smoke=ok
|
||||
browser_ini_workflow_overview_smoke=ok
|
||||
browser_ini_shell_integration_workflow_smoke=ok
|
||||
browser_real_simulation_page_smoke=ok
|
||||
```
|
||||
|
||||
语义边界:
|
||||
|
||||
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
|
||||
- saved-session diagnostics artifact 只复用保存时已有的 source-derived virtual HAL
|
||||
reports;
|
||||
- URL workflow 只验证 browser diagnostics evidence 与 saved-session diagnostics
|
||||
evidence,不把 browser virtual HAL 声称为 Linux kernel hard-realtime ABI;
|
||||
- virtual HAL 仍不声称提供外部硬件驱动 ABI 或 native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM;
|
||||
- Web 方式数控系统仿真所需 HAL、halcmd、motion controller 替代层继续由
|
||||
source-derived virtual HAL 满足。
|
||||
|
||||
下一步工作内容:
|
||||
|
||||
1. 将 workflow overview 固定 URL 表单的 action-plan 与 gate execution summary rows
|
||||
同屏渲染,便于用户看到 URL workflow 的下一步命令和 gate evidence。
|
||||
2. 将 manifest-backed motion matrix check 接入 project release readiness / batch
|
||||
acceptance artifact,使 release gate 不仅检查 sim-config source coverage,也检查
|
||||
motion matrix 关联 source files 的 manifest 一致性。
|
||||
3. 增加 saved-session diagnostics 的负向 fixtures,验证缺失 session diagnostics、
|
||||
incomplete source compliance 或缺失 manifest-backed motion matrix 时 URL workflow
|
||||
会给出明确 blocked reason。
|
||||
|
||||
### 十六、2026-06-17 Workflow Overview URL Action Plan Gate Rows
|
||||
|
||||
继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL
|
||||
完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项,将 workflow
|
||||
overview 固定 URL 表单的 action-plan 与 gate execution summary rows 同屏渲染,让用户
|
||||
在页面输入 release artifact URL 与 browser diagnostics URL 后,可以同时看到 URL
|
||||
workflow 状态、下一步命令和 release gate evidence。
|
||||
|
||||
新增实质能力:
|
||||
|
||||
- `workflow-overview.html` 固定 URL workflow 表单下新增两个渲染区:
|
||||
- `data-workflow-overview-release-readiness-artifact-url-workflow-action-plan`;
|
||||
- `data-workflow-overview-release-readiness-artifact-gate-execution-summary`;
|
||||
- `runWorkflowOverviewReleaseReadinessArtifactUrlForm()` 现在在完成 URL workflow 后
|
||||
同屏 mount:
|
||||
- URL workflow summary rows;
|
||||
- URL workflow action-plan rows;
|
||||
- URL workflow gate execution summary rows;
|
||||
- `runWorkflowOverviewReleaseReadinessArtifactUrlForm()` 返回值新增:
|
||||
- `actionPlan`;
|
||||
- `actionPlanRenderState`;
|
||||
- `actionPlanMountResult`;
|
||||
- `gateExecutionSummary`;
|
||||
- `gateExecutionSummaryRenderState`;
|
||||
- `gateExecutionSummaryMountResult`;
|
||||
- Browser workflow overview API 新增 URL workflow action-plan DOM helpers:
|
||||
- `getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState()`;
|
||||
- `getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract()`;
|
||||
- `getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness()`;
|
||||
- `renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState()`;
|
||||
- `mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState()`;
|
||||
- SDK README 同步说明 fixed workflow overview URL form 可将 URL workflow action plan
|
||||
与 URL workflow rows 同屏渲染。
|
||||
|
||||
新增/扩展验证:
|
||||
|
||||
- `ini_panel_workflow_overview_smoke.html` 覆盖:
|
||||
- 新增 browser API 方法存在;
|
||||
- 固定 URL 表单执行后 `actionPlanMountResult.ready === true`;
|
||||
- 固定 URL 表单执行后 action-plan render state 包含 `next-command`;
|
||||
- 固定 URL 表单执行后 `gateExecutionSummaryMountResult.ready === true`;
|
||||
- 固定 URL 表单执行后 gate execution summary render state 包含
|
||||
`gate-ui-node-smokes`;
|
||||
- DOM 中 action-plan `next-command` 行显示 `none`;
|
||||
- DOM 中 gate execution summary 行显示 observed output matched;
|
||||
- `verify_ini_panel_browser.sh` 聚合确认 workflow overview、launch、control、
|
||||
shell integration browser flows 仍全部通过;
|
||||
- `verify_ui_node_smokes.sh` 聚合确认 UI shell/API manifest/docs 不回归;
|
||||
- `verify_sdk_surface.sh` 聚合确认 SDK surface 与 release URL workflow 不回归。
|
||||
|
||||
关键验证:
|
||||
|
||||
```text
|
||||
browser_ini_opfs_smoke=ok
|
||||
browser_ini_control_page_smoke=ok
|
||||
browser_ini_launch_smoke=ok
|
||||
browser_ini_workflow_overview_smoke=ok
|
||||
browser_ini_shell_integration_workflow_smoke=ok
|
||||
ini_panel_run_summary_node_smoke=ok
|
||||
ini_panel_run_workflow_node_smoke=ok
|
||||
ini_panel_session_summary_node_smoke=ok
|
||||
ini_panel_session_workflow_node_smoke=ok
|
||||
ini_panel_machine_file_summary_node_smoke=ok
|
||||
ini_panel_state_summary_node_smoke=ok
|
||||
ini_panel_control_page_controller_node_smoke=ok
|
||||
ini_panel_control_page_refresh_workflow_node_smoke=ok
|
||||
ini_panel_control_page_session_workflow_node_smoke=ok
|
||||
ini_panel_readonly_status_api_node_smoke=ok
|
||||
ini_panel_entry_manifest_node_smoke=ok
|
||||
ini_panel_launch_api_manifest_node_smoke=ok
|
||||
ini_panel_shell_integration_manifest_node_smoke=ok
|
||||
ini_panel_ui_shell_node_smoke=ok
|
||||
ini_panel_shell_control_page_contract_node_smoke=ok
|
||||
ini_panel_entry_docs_node_smoke=ok
|
||||
real_simulation_programs_node_smoke=ok
|
||||
ui_node_smokes=ok
|
||||
sdk_surface_node_smoke=ok
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
project_release_artifact_url_workflow_node_smoke=ok
|
||||
project_batch_acceptance_workflow_node_smoke=ok
|
||||
project_batch_acceptance_artifact_node_smoke=ok
|
||||
```
|
||||
|
||||
语义边界:
|
||||
|
||||
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
|
||||
- workflow overview 固定 URL 表单只显示和验证 release artifact、browser diagnostics、
|
||||
saved-session diagnostics、action-plan 与 gate execution evidence;
|
||||
- browser diagnostics artifact 中的 virtual HAL evidence 仍来自 source-derived virtual
|
||||
HAL reports;
|
||||
- virtual HAL 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或
|
||||
native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM;
|
||||
- Web 方式数控系统仿真所需 HAL、halcmd、motion controller 替代层继续由
|
||||
source-derived virtual HAL 满足。
|
||||
|
||||
下一步工作内容:
|
||||
|
||||
1. 将 manifest-backed motion matrix check 接入 project release readiness / batch
|
||||
acceptance artifact,使 release gate 不仅检查 sim-config source coverage,也检查
|
||||
motion matrix 关联 source files 的 manifest 一致性。
|
||||
2. 增加 saved-session diagnostics 的负向 fixtures,验证缺失 session diagnostics、
|
||||
incomplete source compliance 或缺失 manifest-backed motion matrix 时 URL workflow
|
||||
会给出明确 blocked reason。
|
||||
3. 将 workflow overview 固定 URL 表单的 saved-session diagnostics readiness 明确显示为
|
||||
独立状态行,便于用户区分 live diagnostics 与 saved-session diagnostics evidence。
|
||||
|
||||
### 十七、2026-06-17 Release Gate Motion Matrix And Saved-Session Negative Fixtures
|
||||
|
||||
继续按本文件铁律推进:虚拟 HAL 的功能完全来源于 LinuxCNC 源程序,并且虚拟 HAL
|
||||
完全满足 Web 方式数控系统仿真系统。本批完成上一节下一步第 1 项和第 2 项,把
|
||||
manifest-backed motion matrix check 接入 project release readiness / batch acceptance
|
||||
artifact,并为 saved-session diagnostics 增加 URL workflow 负向 fixtures。
|
||||
|
||||
新增实质能力:
|
||||
|
||||
- `project-release-readiness.js` 统一新增/使用 `isVirtualHalMotionControllerMatrixReady()`:
|
||||
- 要求 motion matrix `complete === true`;
|
||||
- 要求 `webSimulationSatisfied === true`;
|
||||
- 要求 `manifestChecked === true`;
|
||||
- 要求 `missingFixtures`、`missingSimConfigTargets`、`missingManifestFiles` 均为空;
|
||||
- 要求包含 `motion.distance-to-go`、`motion.in-position`;
|
||||
- 要求包含 LinuxCNC motion source:
|
||||
`linuxcnc/src/emc/motion/motion.c`、`linuxcnc/src/emc/motion/axis.c`;
|
||||
- 要求包含 external-offsets、QtDragon multi-joint、vismach puma sim config source
|
||||
evidence;
|
||||
- `createProjectReleaseReadinessReport()` 新增 release 级 gate evidence:
|
||||
- `virtualHalMotionControllerMatrix`;
|
||||
- `virtualHalMotionControllerMatrixReady`;
|
||||
- missing reason:`virtual-hal-motion-controller-matrix`;
|
||||
- summary row:`Virtual HAL motion controller matrix`;
|
||||
- `createProjectReleaseReadinessArtifactValidation()` 新增强制校验:
|
||||
- artifact 必须携带 manifest-backed motion matrix;
|
||||
- artifact 必须显式标记 `virtualHalMotionControllerMatrixReady === true`;
|
||||
- artifact validation rows 显示 motion matrix ready/missing;
|
||||
- `createProjectBatchAcceptanceWorkflow()` / `createProjectBatchAcceptanceReport()` 新增:
|
||||
- `virtualHalMotionControllerMatrix`;
|
||||
- `virtualHalMotionControllerMatrixReady`;
|
||||
- checklist 项:`virtual-hal-motion-controller-matrix`;
|
||||
- batch checklist 从 `4/4` 扩展为 `5/5 passed`;
|
||||
- release readiness artifact writer 与 batch acceptance artifact writer 均使用真实
|
||||
`wasm-port/tools/source-manifest.txt` 生成 manifest-backed motion matrix;
|
||||
- `loadProjectReleaseReadinessArtifactUrlWorkflow()` 新增可选:
|
||||
- `requireSavedSessionDiagnostics`;
|
||||
- 默认仍允许 live diagnostics artifact 在未保存 session 时通过;
|
||||
- 严格模式下,缺失 saved-session diagnostics 会输出
|
||||
`diagnostics.virtualHalSessionDiagnostics` blocked reason;
|
||||
- URL workflow saved-session diagnostics 负向 fixtures 覆盖:
|
||||
- live diagnostics 可通过,但严格要求 saved-session 时被 blocked;
|
||||
- saved-session diagnostics 内嵌 source compliance incomplete 时被 blocked;
|
||||
- saved-session diagnostics 内嵌 motion matrix 未 manifest-backed check 时被 blocked。
|
||||
|
||||
新增/扩展验证:
|
||||
|
||||
- `verify_project_release_readiness_artifact.mjs` 覆盖:
|
||||
- release readiness artifact 包含 manifest-backed motion matrix;
|
||||
- `virtualHalMotionControllerMatrixReady === true`;
|
||||
- matrix source evidence 包含 external offsets 与 QtDragon multi-joint sim config;
|
||||
- `verify_project_batch_acceptance_artifact.mjs` 覆盖:
|
||||
- batch artifact 携带 motion matrix;
|
||||
- matrix `manifestChecked === true`;
|
||||
- workflow motion matrix ready;
|
||||
- `verify_sdk_surface.mjs` 覆盖:
|
||||
- release readiness ready 需要 manifest-backed motion matrix;
|
||||
- batch acceptance report validation 需要 motion matrix;
|
||||
- report checklist 为 `5/5 passed`;
|
||||
- `verify_project_release_artifact_url_workflow.mjs` 覆盖:
|
||||
- 默认 URL workflow 同时支持 live diagnostics 与 saved-session diagnostics ready;
|
||||
- 严格 saved-session diagnostics 模式下,缺失 saved-session diagnostics 被 blocked;
|
||||
- incomplete source compliance 被 blocked;
|
||||
- missing manifest-backed motion matrix 被 blocked;
|
||||
- blocked reason 明确包含 `diagnostics.virtualHalSessionDiagnostics`。
|
||||
|
||||
关键验证:
|
||||
|
||||
```text
|
||||
project_release_artifact_url_workflow_node_smoke=ok
|
||||
sdk_surface_node_smoke=ok
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
project_batch_acceptance_workflow_node_smoke=ok
|
||||
project_batch_acceptance_artifact_node_smoke=ok
|
||||
project_release_readiness_artifact_node_smoke=ok
|
||||
git diff --check ok
|
||||
```
|
||||
|
||||
语义边界:
|
||||
|
||||
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
|
||||
- release readiness / batch acceptance 只校验 Web virtual HAL motion matrix 的
|
||||
source-derived evidence 与 manifest 一致性;
|
||||
- saved-session diagnostics 负向 fixtures 只验证 release evidence 缺失时的 blocked
|
||||
reason,不改变 LinuxCNC CNC 语义;
|
||||
- virtual HAL 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或
|
||||
native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM;
|
||||
- Web 方式数控系统仿真所需 HAL、halcmd、motion controller 替代层继续由
|
||||
source-derived virtual HAL 满足。
|
||||
|
||||
下一步工作内容:
|
||||
|
||||
1. 将 workflow overview 固定 URL 表单的 saved-session diagnostics readiness 明确显示为
|
||||
独立状态行,便于用户区分 live diagnostics 与 saved-session diagnostics evidence。
|
||||
2. 将 saved-session diagnostics 负向 fixtures 扩展到 ini-panel workflow overview browser
|
||||
smoke,验证页面 DOM 会显示 saved-session blocked/not provided。
|
||||
3. 将 release readiness / batch acceptance artifact 的 motion matrix manifest check 输出
|
||||
加入 README/handoff 文档,形成发布交接可读说明。
|
||||
|
||||
518
text18.txt
Normal file
518
text18.txt
Normal file
@@ -0,0 +1,518 @@
|
||||
项目接续文件:sim config coverage promotion 后续推进计划
|
||||
|
||||
生成时间:2026-06-18 CST
|
||||
|
||||
本文件接替 `text17.txt`,作为后续继续推进的接续文件。后续工作优先参考
|
||||
`text18.txt`;除非明确要求审计旧记录,不再回到 `text1` 到 `text17` 扩展进度。
|
||||
|
||||
一、当前完成情况摘要
|
||||
|
||||
1. LinuxCNC-backed WASM 核心仍是 CNC 语义来源。
|
||||
|
||||
- G-code / interpreter / planner / kinematics / canonical motion 语义仍来自 vendored
|
||||
LinuxCNC C/C++ 源码;
|
||||
- Browser / UI / SDK 只做 host boundary、文件装载、OPFS/session、virtual HAL runtime、
|
||||
仿真状态桥、测试胶水和报告;
|
||||
- 不在 JS 中重写 G-code 解释器、planner、kinematics、tool/parameter 语义。
|
||||
|
||||
2. virtual HAL 已完全满足 Web 方式数控系统仿真系统。
|
||||
|
||||
当前 virtual HAL 已具备并通过 gate 验证:
|
||||
|
||||
- LinuxCNC realtime HAL simulation replacement;
|
||||
- `halcmd` simulation replacement;
|
||||
- motion controller simulation replacement;
|
||||
- HAL pin/signal/param store;
|
||||
- `setp`、`sets`、`net`、`show`、`getp`、`gets`、`loadrt`、`loadusr`、`addf`、
|
||||
`start`、`stop` command workflow;
|
||||
- servo-period motion stepping;
|
||||
- axis/joint position feedback;
|
||||
- source compliance report;
|
||||
- sim-config source coverage report;
|
||||
- command script fixture report;
|
||||
- manifest-backed motion controller matrix report;
|
||||
- OPFS/session persistence;
|
||||
- saved-session release diagnostics evidence;
|
||||
- release readiness / batch acceptance artifact gate。
|
||||
|
||||
3. release gate 已接入 virtual HAL motion matrix。
|
||||
|
||||
已完成:
|
||||
|
||||
- `virtualHalMotionControllerMatrix`;
|
||||
- `virtualHalMotionControllerMatrixReady`;
|
||||
- release readiness artifact 强制校验 manifest-backed motion matrix;
|
||||
- batch acceptance artifact checklist 从 `4/4` 扩展为 `5/5 passed`;
|
||||
- saved-session diagnostics 负向 fixtures:
|
||||
- 缺失 saved-session diagnostics;
|
||||
- incomplete source compliance;
|
||||
- missing manifest-backed motion matrix。
|
||||
|
||||
4. sim config coverage promotion 已先形成分析文档。
|
||||
|
||||
新增分析文档:
|
||||
|
||||
```text
|
||||
wasm-port/docs/sim-config-coverage-promotion-analysis.md
|
||||
```
|
||||
|
||||
该文档已纳入:
|
||||
|
||||
```text
|
||||
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.sh
|
||||
```
|
||||
|
||||
当前结论:
|
||||
|
||||
- 当前 generated inventory 中没有“hard block 已清空但仍 SKIP 的 main program”;
|
||||
- 因此不应因为 virtual HAL 完善就直接降低 `skipped=131`;
|
||||
- 下一步应推进“case promotion”:把已有 Node `INV` 或代表覆盖案例推进到 browser
|
||||
diagnostics / release evidence;
|
||||
- blocked runtime families 仍不能由 virtual HAL 或 JS glue 直接解锁。
|
||||
|
||||
二、当前 sim config inventory baseline
|
||||
|
||||
当前必须保持的 baseline:
|
||||
|
||||
```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
|
||||
sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65
|
||||
sim_configs_wasm_node_inventory_skip_L4_PYTHON_REMAP=53
|
||||
sim_configs_wasm_node_inventory_skip_L4_TOOL_DB=1
|
||||
sim_configs_wasm_node_inventory_skip_L4_USER_M_PROCESS=1
|
||||
sim_configs_wasm_node_inventory_skip_NON_MAIN_CLASS=10
|
||||
sim_configs_wasm_node_inventory_skip_UPSTREAM_DEMO=1
|
||||
```
|
||||
|
||||
后续任何改动,只要涉及 inventory baseline,必须明确说明:
|
||||
|
||||
- 哪些 row 从何种状态变更;
|
||||
- 为什么 LinuxCNC source/runtime evidence 已满足;
|
||||
- 为什么不是 JS/browser 自行补语义;
|
||||
- 为什么没有破坏 blocked runtime promotion lock。
|
||||
|
||||
三、virtual HAL 完善后可以推进的范围
|
||||
|
||||
virtual HAL 现在可以支撑以下 Web 仿真 promotion 范围:
|
||||
|
||||
- HAL / HALUI / deterministic UI process declarations;
|
||||
- virtual `halcmd` workflow;
|
||||
- machine state;
|
||||
- motion feedback;
|
||||
- axis/joint feedback;
|
||||
- diagnostics artifact;
|
||||
- saved-session diagnostics artifact;
|
||||
- release readiness / batch acceptance evidence。
|
||||
|
||||
virtual HAL 仍不能解锁:
|
||||
|
||||
- Linux kernel hard-realtime ABI;
|
||||
- 外部硬件驱动 ABI;
|
||||
- native HAL module ABI;
|
||||
- Python UI process emulation;
|
||||
- Python remap runtime;
|
||||
- tool database process protocol;
|
||||
- external user-M process execution;
|
||||
- upstream-invalid demo code。
|
||||
|
||||
四、promotion 铁律
|
||||
|
||||
后续 sim config coverage promotion 必须满足:
|
||||
|
||||
1. LinuxCNC source/config evidence owns the behavior。
|
||||
2. Native 或当前 Node inventory evidence 已经通过;或者 row 是 macro/load /
|
||||
remap_subroutine,且有明确非主程序验证计划。
|
||||
3. 依赖仅限于 virtual HAL、HALUI、deterministic UI process declarations、machine
|
||||
files、tool tables、remap subroutine assets 或已由 LinuxCNC-backed runtime 覆盖的
|
||||
motion/kinematics evidence。
|
||||
4. Browser evidence 必须能导出:
|
||||
- virtual HAL source compliance;
|
||||
- sim-config source coverage;
|
||||
- command script fixtures;
|
||||
- manifest-backed motion matrix;
|
||||
- diagnostics artifact;
|
||||
- 如涉及 session,必须导出 saved-session diagnostics。
|
||||
5. row 不能属于:
|
||||
- `L4-PYTHON-REMAP`;
|
||||
- `L4-TOOL-DB`;
|
||||
- `L4-USER-M-PROCESS`;
|
||||
- `UPSTREAM-DEMO`;
|
||||
- standalone-main 执行语境下的 `ASSET-ONLY`。
|
||||
6. `verify_no_standalone_cnc_semantics.sh` 必须保持通过。
|
||||
|
||||
五、继续推进计划
|
||||
|
||||
### 1. 建立 promotion candidate report
|
||||
|
||||
新增机器可读候选报告,先只覆盖可推进案例,不改变 inventory baseline。
|
||||
|
||||
首批候选:
|
||||
|
||||
- `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`;
|
||||
- `axis/vismach/puma/puma_seam_weld.ngc`;
|
||||
- `axis/rose_engine/rcone_demo.ngc`。
|
||||
|
||||
每行至少记录:
|
||||
|
||||
- candidate id;
|
||||
- LinuxCNC source files;
|
||||
- INI path;
|
||||
- G-code path;
|
||||
- current Node inventory status;
|
||||
- current matrix browser status;
|
||||
- dependency class;
|
||||
- target browser evidence;
|
||||
- required virtual HAL reports;
|
||||
- blocked-family exclusion result。
|
||||
|
||||
建议 API / report 名称:
|
||||
|
||||
- `VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES`;
|
||||
- `createVirtualHalSimConfigPromotionCandidateReport()`;
|
||||
- report `apiName`:
|
||||
`linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report`。
|
||||
|
||||
### 2. 增加 candidate report gate
|
||||
|
||||
新增 Node gate 断言:
|
||||
|
||||
- candidate report `complete === true`;
|
||||
- candidate report `webSimulationSatisfied === true`;
|
||||
- candidate 不包含:
|
||||
- `L4-PYTHON-REMAP`;
|
||||
- `L4-TOOL-DB`;
|
||||
- `L4-USER-M-PROCESS`;
|
||||
- `UPSTREAM-DEMO`;
|
||||
- standalone main promotion 下的 `ASSET-ONLY`;
|
||||
- candidate 当前 Node status 必须为 `PASS` 或明确 non-main fixture candidate;
|
||||
- inventory baseline 保持:
|
||||
- `executed=28`;
|
||||
- `passed=28`;
|
||||
- `skipped=131`;
|
||||
- `unexpected_fail=0`。
|
||||
|
||||
建议接入:
|
||||
|
||||
- `verify_sdk_surface.mjs`;
|
||||
- `verify_sim_configs_coverage_docs.mjs`;
|
||||
- 后续可接入 release readiness artifact,但第一批先作为 SDK/docs gate。
|
||||
|
||||
### 3. 推进第一个 browser evidence 案例
|
||||
|
||||
建议首选:
|
||||
|
||||
```text
|
||||
qtdragon/qtdragon_multi_joint/on_abort.ngc
|
||||
```
|
||||
|
||||
选择原因:
|
||||
|
||||
- 当前 Node `INV`;
|
||||
- 无 hard runtime block;
|
||||
- 依赖 HAL/UI declarations 与 multi-joint machine context;
|
||||
- virtual HAL motion matrix 已映射 `qtdragon-on-abort`;
|
||||
- source evidence 已包含:
|
||||
`linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini`;
|
||||
- 可验证 virtual HAL 对 Web CNC 仿真系统的完整满足性。
|
||||
|
||||
目标 browser diagnostics evidence:
|
||||
|
||||
- candidate id 存在;
|
||||
- source files 完整;
|
||||
- current Node inventory status 为 `PASS`;
|
||||
- browser evidence ready;
|
||||
- virtual HAL source compliance complete;
|
||||
- sim-config source coverage complete;
|
||||
- command script fixtures complete;
|
||||
- motion matrix manifest checked;
|
||||
- diagnostics artifact 可被 release URL workflow 验证。
|
||||
|
||||
### 4. 扩展 release diagnostics validation
|
||||
|
||||
release browser diagnostics validation 后续新增 candidate evidence 校验:
|
||||
|
||||
- diagnostics artifact 包含 candidate promotion report;
|
||||
- candidate row ready;
|
||||
- candidate source files 完整;
|
||||
- candidate 不属于 hard-block family;
|
||||
- current Node status 为 `PASS`;
|
||||
- browser evidence ready;
|
||||
- virtual HAL reports complete;
|
||||
- motion matrix manifest checked。
|
||||
|
||||
URL workflow 中显示:
|
||||
|
||||
- candidate promotion evidence;
|
||||
- candidate browser diagnostics;
|
||||
- missing candidate reason;
|
||||
- next command / action plan。
|
||||
|
||||
### 5. 更新 coverage matrix 注释
|
||||
|
||||
只在 browser gate 通过后更新 matrix。
|
||||
|
||||
可更新方向:
|
||||
|
||||
- 将对应行从“browser delegated to `woodpecker`”改为 explicit browser diagnostics
|
||||
evidence;
|
||||
- 不改变 blocked runtime family;
|
||||
- 不降低 skip count;
|
||||
- 不把 Node `INV` 误写成 browser `REP`,除非实际 browser smoke/gate 已覆盖该 row。
|
||||
|
||||
首批可能更新:
|
||||
|
||||
```text
|
||||
qtdragon/qtdragon_multi_joint/on_abort.ngc
|
||||
```
|
||||
|
||||
### 6. 推进 QtDragon family 全组
|
||||
|
||||
在第一个 QtDragon multi-joint candidate 通过后,继续推进:
|
||||
|
||||
- `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`。
|
||||
|
||||
目标:
|
||||
|
||||
- 从 shared `woodpecker` representative delegation 变为 explicit browser diagnostics
|
||||
evidence;
|
||||
- 每个 row 都有独立 source evidence;
|
||||
- 每个 row 都保持 LinuxCNC-owned config/program evidence。
|
||||
|
||||
### 7. 推进 vismach / rose_engine 案例
|
||||
|
||||
后续候选:
|
||||
|
||||
- `axis/vismach/puma/puma_seam_weld.ngc`
|
||||
- 当前 Node `INV`;
|
||||
- 与 `puma_cube.ngc` 共用 PUMA machine context;
|
||||
- 目标是形成 PUMA 双案例 browser diagnostics evidence。
|
||||
- `axis/rose_engine/rcone_demo.ngc`
|
||||
- 当前 Node `INV`;
|
||||
- HAL process only;
|
||||
- 适合作为非 Qt、非复杂 vismach remap 的轻量 browser diagnostics 案例。
|
||||
|
||||
### 8. 设计 macro/load 非主程序 promotion
|
||||
|
||||
不要把 macro/load 当 browser main program 执行。
|
||||
|
||||
候选只作为 non-main fixture evidence:
|
||||
|
||||
- `axis/external_offsets/queuebuster.ngc`;
|
||||
- `axis/rose_engine/rcone.ngc`;
|
||||
- `gscreen/silverdragon/macros/tool_sensor.ngc`;
|
||||
- `gscreen/industrial_lathe_wear/toolchange.ngc`;
|
||||
- `qtvcp_screens/industrial_lathe_wear/toolchange.ngc`。
|
||||
|
||||
需要新增独立报告,而不是复用 main-program promotion:
|
||||
|
||||
- `createVirtualHalSimConfigMacroLoadFixtureReport()`;
|
||||
- 或将其作为 promotion candidate report 的 `nonMainFixture` 分类。
|
||||
|
||||
### 9. 保持 hard boundary lock
|
||||
|
||||
继续禁止以下 family promotion:
|
||||
|
||||
- `L4-PYTHON-REMAP`;
|
||||
- `L4-TOOL-DB`;
|
||||
- `L4-USER-M-PROCESS`;
|
||||
- `UPSTREAM-DEMO`。
|
||||
|
||||
这些只能通过 LinuxCNC-owned runtime proof 解锁,不能由 virtual HAL、browser UI、
|
||||
SDK glue 或 JS fixture 解锁。
|
||||
|
||||
六、建议下一批实际执行目标
|
||||
|
||||
下一批建议只做一个完整闭环:
|
||||
|
||||
1. 新增 promotion candidate report;
|
||||
2. 新增 candidate report Node gate;
|
||||
3. 将 `qtdragon/qtdragon_multi_joint/on_abort.ngc` 纳入 browser diagnostics evidence;
|
||||
4. release diagnostics validation 增加 candidate evidence ready 校验;
|
||||
5. docs / matrix 只做最小同步;
|
||||
6. inventory baseline 不变。
|
||||
|
||||
七、建议验证命令
|
||||
|
||||
每批至少运行:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
|
||||
wasm-port/tests/sdk/node/verify_sdk_surface.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
|
||||
```
|
||||
|
||||
如涉及 release artifact / URL workflow,再运行:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/sdk/node/verify_project_release_artifact_url_workflow.sh
|
||||
wasm-port/tests/host/verify_project_release_readiness_artifact.sh
|
||||
wasm-port/tests/sdk/node/verify_project_batch_acceptance_artifact.sh
|
||||
```
|
||||
|
||||
如涉及 ini-panel workflow overview,再运行:
|
||||
|
||||
```bash
|
||||
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
|
||||
```
|
||||
|
||||
八、后续记录规则
|
||||
|
||||
- 后续进度只追加到 `text18.txt`;
|
||||
- 每批只追加一个新的中文编号或 `###` 标题记录;
|
||||
- 提交前检查标题唯一性:
|
||||
|
||||
```bash
|
||||
awk '/^[一二三四五六七八九十百]+、|^### / {print}' text18.txt | sort | uniq -d
|
||||
```
|
||||
|
||||
- 不复制 `text17.txt` 的长历史;
|
||||
- 不把局部重排、断言挪动、路径整理作为主目标;
|
||||
- 每批必须产出至少一种可复用能力、可执行 gate、可验证 workflow 或明确 runtime
|
||||
boundary proof;
|
||||
- 对外表述必须同时说明:
|
||||
- virtual HAL 已完全满足 Web 方式数控系统仿真系统;
|
||||
- 在仿真范围内,virtual HAL 已替代 LinuxCNC realtime HAL / halcmd /
|
||||
motion controller;
|
||||
- 它不是 Linux kernel hard-realtime ABI;
|
||||
- 它不替代外部硬件驱动 ABI、native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM。
|
||||
|
||||
### 一、2026-06-18 Virtual HAL Sim Config Promotion Candidate Report
|
||||
|
||||
按本文件推进 virtual HAL 已满足 Web 仿真后的 sim config coverage promotion。本批完成
|
||||
“下一批实际执行目标”的第 1 到第 4 项:新增 source-derived promotion candidate report,
|
||||
新增 Node/browser gate,并把 `qtdragon/qtdragon_multi_joint/on_abort.ngc` 纳入 browser
|
||||
diagnostics / release validation evidence。inventory baseline 保持不变。
|
||||
|
||||
新增实质能力:
|
||||
|
||||
- 新增 `VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES`:
|
||||
- `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`;
|
||||
- `puma-seam-weld`;
|
||||
- `rose-engine-rcone-demo`;
|
||||
- 每个 candidate row 记录:
|
||||
- LinuxCNC INI source file;
|
||||
- LinuxCNC G-code source file;
|
||||
- current Node inventory status;
|
||||
- current matrix browser status;
|
||||
- dependency class;
|
||||
- target browser evidence;
|
||||
- required virtual HAL reports;
|
||||
- blocked-family exclusion;
|
||||
- 新增 `createVirtualHalSimConfigPromotionCandidateReport()`:
|
||||
- 输出 `linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report`;
|
||||
- 校验 source manifest;
|
||||
- 校验 candidate 不属于 `L4-PYTHON-REMAP` / `L4-TOOL-DB` /
|
||||
`L4-USER-M-PROCESS` / `UPSTREAM-DEMO`;
|
||||
- 校验 current Node inventory status 为 `PASS`;
|
||||
- 校验 required virtual HAL reports complete:
|
||||
source compliance、sim-config source coverage、command fixtures、
|
||||
manifest-backed motion matrix;
|
||||
- 显式输出 `inventoryBaselineUnchanged === true`;
|
||||
- `createLinuxCncVirtualHalRuntime()` 新增:
|
||||
- `getSimConfigPromotionCandidateReport()`;
|
||||
- SDK index、SDK README、browser simulation re-export 同步导出新常量和新 report API;
|
||||
- real simulation page 新增:
|
||||
- `getVirtualHalSimConfigPromotionCandidateReport()`;
|
||||
- diagnostics artifact 字段 `virtualHalSimConfigPromotionCandidates`;
|
||||
- release diagnostics validation 新增 candidate evidence 识别:
|
||||
- `hasPromotionCandidates`;
|
||||
- `promotionCandidatesReady`;
|
||||
- validation row:`sim-config-promotion-candidates`;
|
||||
- 如果 diagnostics artifact 携带 candidate report,则必须 complete;
|
||||
- 首批要求 `qtdragon-multi-joint-on-abort` candidate ready,且包含
|
||||
`qtdragon_xyyz.ini` 与 `on_abort.ngc` source evidence;
|
||||
- release URL workflow fixtures、ini-panel workflow fixtures 同步携带 candidate evidence。
|
||||
|
||||
新增/扩展验证:
|
||||
|
||||
- `verify_sdk_surface.mjs` 覆盖:
|
||||
- 新常量导出;
|
||||
- 新 report API 导出;
|
||||
- SDK README 文档化;
|
||||
- candidate report complete;
|
||||
- `inventoryBaselineUnchanged === true`;
|
||||
- blocked candidate 为 0;
|
||||
- missing manifest files 为 0;
|
||||
- missing required virtual HAL reports 为 0;
|
||||
- `qtdragon-multi-joint-on-abort` row ready;
|
||||
- runtime wrapper 可读取 candidate report;
|
||||
- release browser diagnostics validation 识别 candidate evidence ready;
|
||||
- `real_simulation_page_smoke.html` 覆盖:
|
||||
- browser API 暴露 `getVirtualHalSimConfigPromotionCandidateReport()`;
|
||||
- diagnostics artifact 内嵌 complete candidate report;
|
||||
- candidate report 包含 `qtdragon-multi-joint-on-abort`;
|
||||
- candidate row current Node status 为 `PASS`;
|
||||
- candidate row target browser evidence 为 `explicit-browser-diagnostics`;
|
||||
- `verify_project_release_artifact_url_workflow.mjs` 覆盖:
|
||||
- diagnostics artifact 携带 candidate evidence;
|
||||
- URL workflow diagnostics validation `hasPromotionCandidates === true`;
|
||||
- URL workflow diagnostics validation `promotionCandidatesReady === true`;
|
||||
- `verify_ini_panel_ui_shell.mjs` 覆盖:
|
||||
- ini-panel URL workflow diagnostics validation 识别 candidate evidence;
|
||||
- diagnostics validation candidate evidence ready;
|
||||
- `ini_panel_workflow_overview_smoke.html` 使用带 candidate evidence 的 diagnostics fixture。
|
||||
|
||||
关键验证:
|
||||
|
||||
```text
|
||||
sim_configs_coverage_docs_node_smoke=ok
|
||||
project_release_artifact_url_workflow_node_smoke=ok
|
||||
sdk_surface_node_smoke=ok
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
project_batch_acceptance_workflow_node_smoke=ok
|
||||
project_batch_acceptance_artifact_node_smoke=ok
|
||||
browser_real_simulation_page_smoke=ok
|
||||
ini_panel_ui_shell_node_smoke=ok
|
||||
browser_ini_opfs_smoke=ok
|
||||
browser_ini_control_page_smoke=ok
|
||||
browser_ini_launch_smoke=ok
|
||||
browser_ini_workflow_overview_smoke=ok
|
||||
browser_ini_shell_integration_workflow_smoke=ok
|
||||
git diff --check ok
|
||||
```
|
||||
|
||||
语义边界:
|
||||
|
||||
- 本批没有降低 inventory skip count;
|
||||
- 当前 baseline 仍是 `executed=28`、`passed=28`、`skipped=131`、
|
||||
`unexpected_fail=0`;
|
||||
- 本批没有新增 G-code/interpreter/planner/kinematics/remap 语义;
|
||||
- candidate report 只把已有 Node `PASS` / source-derived virtual HAL evidence 推进到
|
||||
browser diagnostics / release validation;
|
||||
- `L4-PYTHON-REMAP`、`L4-TOOL-DB`、`L4-USER-M-PROCESS`、`UPSTREAM-DEMO` 仍保持
|
||||
locked,不能由 virtual HAL 或 JS glue 解锁;
|
||||
- virtual HAL 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI 或
|
||||
native HAL module ABI;
|
||||
- G-code/interpreter/planner/canonical motion 语义仍来自 LinuxCNC-backed WASM。
|
||||
|
||||
下一步工作内容:
|
||||
|
||||
1. 将 `qtdragon/qtdragon_multi_joint/on_abort.ngc` 的 explicit browser diagnostics evidence
|
||||
同步到 coverage matrix 注释,把它从 delegated representative 记录为已具备 browser
|
||||
diagnostics evidence。
|
||||
2. 推进 QtDragon family 其余 candidate:
|
||||
`qtdragon_xyz`、`qtdragon_xyz45`、`qtdragon_hd_xyz`、
|
||||
`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 案例。
|
||||
185
wasm-port/docs/sim-config-coverage-promotion-analysis.md
Normal file
185
wasm-port/docs/sim-config-coverage-promotion-analysis.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Sim Config Coverage Promotion Analysis
|
||||
|
||||
This analysis records how the completed virtual HAL changes the next
|
||||
`linuxcnc/configs/sim` coverage-promotion work. It is intentionally an analysis
|
||||
document only: it does not promote rows, change inventory counts, or relax any
|
||||
blocked runtime family.
|
||||
|
||||
## Current Baseline
|
||||
|
||||
Current machine-readable inventory 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
|
||||
sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65
|
||||
sim_configs_wasm_node_inventory_skip_L4_PYTHON_REMAP=53
|
||||
sim_configs_wasm_node_inventory_skip_L4_TOOL_DB=1
|
||||
sim_configs_wasm_node_inventory_skip_L4_USER_M_PROCESS=1
|
||||
sim_configs_wasm_node_inventory_skip_NON_MAIN_CLASS=10
|
||||
sim_configs_wasm_node_inventory_skip_UPSTREAM_DEMO=1
|
||||
```
|
||||
|
||||
The current generated inventory has no skipped main-program row whose hard
|
||||
block is already empty. That matters: virtual HAL maturity should not be used
|
||||
as a blanket reason to reduce `skipped=131`. The next useful promotions are
|
||||
case promotions from Node inventory or representative coverage into browser,
|
||||
diagnostics, and release evidence.
|
||||
|
||||
## What Virtual HAL Unlocks
|
||||
|
||||
The virtual HAL is now a source-derived Web simulation replacement for these
|
||||
runtime surfaces:
|
||||
|
||||
- LinuxCNC realtime HAL simulation replacement;
|
||||
- `halcmd` simulation replacement;
|
||||
- motion controller simulation replacement;
|
||||
- HAL pin/signal/param store;
|
||||
- `setp`, `sets`, `net`, `show`, `getp`, `gets`, `loadrt`, `loadusr`, `addf`,
|
||||
`start`, and `stop` command workflow;
|
||||
- servo-period motion stepping;
|
||||
- axis/joint position feedback;
|
||||
- source-compliance, sim-config source coverage, command fixture, and motion
|
||||
matrix reports;
|
||||
- OPFS/session persistence and release diagnostics evidence.
|
||||
|
||||
That means Web coverage can now promote additional cases when their remaining
|
||||
dependency is HAL, HALUI, deterministic virtual `halcmd`, machine state, or
|
||||
motion feedback. It does not unlock rows whose defining behavior is Python
|
||||
remap runtime, tool database process protocol, external user-M process state,
|
||||
or upstream-invalid demo code.
|
||||
|
||||
## Promotion Rules After Virtual HAL
|
||||
|
||||
A sim-config case can move forward only when all of these are true:
|
||||
|
||||
1. LinuxCNC source/config evidence owns the behavior.
|
||||
2. Native or current Node inventory evidence already passes, or the row is a
|
||||
macro/load or subroutine class with an explicit non-main validation plan.
|
||||
3. Dependencies are limited to virtual HAL, HALUI, deterministic UI process
|
||||
declarations, machine files, tool tables, remap subroutine assets, or
|
||||
motion/kinematics evidence already covered by LinuxCNC-backed runtime.
|
||||
4. Browser evidence can export virtual HAL source compliance, sim-config
|
||||
source coverage, command fixtures, and manifest-backed motion matrix.
|
||||
5. The row is not `L4-PYTHON-REMAP`, `L4-TOOL-DB`, `L4-USER-M-PROCESS`, or
|
||||
`UPSTREAM-DEMO`.
|
||||
6. `verify_no_standalone_cnc_semantics.sh` remains green.
|
||||
|
||||
Promotion should mean a stronger evidence tier, not necessarily a lower skip
|
||||
count. For example, a row may move from Node `INV` to browser diagnostics
|
||||
evidence while the inventory baseline remains `executed=28`.
|
||||
|
||||
## Recommended Promotion Candidates
|
||||
|
||||
### Tier 1: Browser Evidence For Existing Node INV Rows
|
||||
|
||||
These rows already pass Node inventory and have no hard runtime block. Virtual
|
||||
HAL makes them good candidates for browser diagnostics/release evidence rather
|
||||
than only shared representative coverage.
|
||||
|
||||
| Candidate | Current coverage | Why it is now promotable |
|
||||
| --- | --- | --- |
|
||||
| `qtdragon/qtdragon_multi_joint/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Requires HAL/UI declarations and multi-joint machine context; virtual HAL motion matrix already maps `qtdragon-on-abort` and `qtdragon_xyyz.ini`. |
|
||||
| `qtdragon/qtdragon_xyz/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Same on-abort family, already part of virtual HAL sim-config source coverage evidence. |
|
||||
| `qtdragon/qtdragon_xyz45/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Adds rotary-axis machine context without requiring Python remap or external process runtime. |
|
||||
| `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Deterministic UI/HAL family, suitable for browser diagnostics artifact evidence. |
|
||||
| `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | HAL/UI machine state case; should be promoted only with explicit source evidence for the z-compensation INI. |
|
||||
| `qtvcp_screens/qtdragon/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | QTVCP on-abort surface, no Python-remap hard block in inventory. |
|
||||
| `axis/vismach/puma/puma_seam_weld.ngc` | Node `INV`, browser represented by `puma_cube.ngc` | Same vendored PUMA machine context; virtual HAL motion matrix already includes `vismach-remap-sims` and `puma.ini`. |
|
||||
| `axis/rose_engine/rcone_demo.ngc` | Node `INV` | HAL process only, no hard block; useful as a non-Qt/non-vismach browser diagnostics candidate. |
|
||||
|
||||
Expected next artifact shape:
|
||||
|
||||
- extend a source-derived candidate list in SDK or docs;
|
||||
- add browser diagnostics fixture rows, not a JS CNC interpretation path;
|
||||
- assert virtual HAL source compliance, sim-config source coverage, command
|
||||
fixtures, and motion matrix remain complete;
|
||||
- update matrix notes from delegated browser representative to explicit browser
|
||||
evidence only after the browser gate exists.
|
||||
|
||||
### Tier 2: Existing REP Rows Worth Splitting Into More Cases
|
||||
|
||||
These are already promoted as representative coverage. The next work is not to
|
||||
prove the class exists; it is to split representative buckets into more
|
||||
specific cases now that virtual HAL can carry machine state evidence.
|
||||
|
||||
| Candidate | Current coverage | Promotion goal |
|
||||
| --- | --- | --- |
|
||||
| `axis/vismach/5axis/bridgemill/5axisgui.ngc` | Node/browser `REP` | Add explicit HALUI MDI and W-axis diagnostics evidence. |
|
||||
| `axis/vismach/5axis/table-dual-rotary/demos/xyzab-tdr-demo.ngc` | Node/browser `REP` | Add dual-rotary ABC/AB feedback evidence in motion matrix rows. |
|
||||
| `axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc` | Node/browser `REP` | Add TRT machine-family diagnostics evidence separate from generic 5-axis class. |
|
||||
| `axis/vismach/melfa-sim/example.ngc` | Node/browser `REP` | Add robot/Genser remap-machine evidence with source files and session diagnostics. |
|
||||
| `axis/vismach/puma/puma_cube.ngc` | Node/browser `REP` | Keep as PUMA representative but pair with `puma_seam_weld.ngc` Node `INV` evidence. |
|
||||
|
||||
### Tier 3: Macro/Load Rows With No Hard Runtime Block
|
||||
|
||||
These rows are not standalone main-program targets, so they should not be
|
||||
promoted by executing them as browser main programs. They can move forward as
|
||||
explicit macro/load fixtures if the gate names them as non-main class evidence.
|
||||
|
||||
| Candidate | Current status | Promotion goal |
|
||||
| --- | --- | --- |
|
||||
| `axis/external_offsets/queuebuster.ngc` | `NON_MAIN_CLASS` | Add external-offset macro/load source fixture next to `circles.ngc`. |
|
||||
| `axis/lathe-fanucy/toolchange.ngc` | `NON_MAIN_CLASS` | Add macro/load fixture if the lathe-fanucy INI/tool context is vendored. |
|
||||
| `axis/rose_engine/rcone.ngc` | inventory-only macro/load | Pair with `rcone_demo.ngc` to prove rose-engine support assets load. |
|
||||
| `gscreen/industrial_lathe_wear/toolchange.ngc` | inventory-only macro/load | Candidate only if kept as macro/load evidence, not UI process emulation. |
|
||||
| `gscreen/silverdragon/macros/*.ngc` | inventory-only macro/load | Candidate for a small macro fixture subset, not all macros at once. |
|
||||
| `qtvcp_screens/industrial_lathe_wear/toolchange.ngc` | inventory-only macro/load | Candidate only as non-main fixture evidence. |
|
||||
|
||||
## Rows Still Not Promotable
|
||||
|
||||
Virtual HAL does not change these blocked decisions:
|
||||
|
||||
- `L4-PYTHON-REMAP`: still requires LinuxCNC-owned Python remap runtime proof.
|
||||
Examples include laser, many `axis/remap/*`, gmoccapy macro families, and
|
||||
table-rotary-spindle-nutating TWP demos.
|
||||
- `L4-TOOL-DB`: `axis/db_demo/base.ngc` still requires tool database process
|
||||
protocol proof, not only HAL state.
|
||||
- `L4-USER-M-PROCESS`: `axis/vismach/millturn/example.ngc` still requires
|
||||
external `USER_M_PATH` process state proof for `M128`/`M129`.
|
||||
- `UPSTREAM-DEMO`: `incremental_repetition_g533.ngc` remains a preserved
|
||||
upstream demo edge and must not be forced to pass by standalone semantics.
|
||||
- `ASSET-ONLY`: remap subroutines remain validated by parse/remap or owning
|
||||
main-program context, not standalone browser execution.
|
||||
|
||||
## Proposed Next Batch
|
||||
|
||||
The next implementation batch should avoid changing the inventory baseline.
|
||||
It should add a promotion-candidate report and one or two browser evidence
|
||||
fixtures.
|
||||
|
||||
Recommended first slice:
|
||||
|
||||
1. Add a machine-readable candidate report for Tier 1 rows:
|
||||
`qtdragon-on-abort`, `puma-seam-weld`, and `rose-engine`.
|
||||
2. Require every row to name LinuxCNC source files, INI files, G-code files,
|
||||
dependency class, current Node status, and target browser evidence.
|
||||
3. Add Node gate assertions that no candidate is in `L4-PYTHON-REMAP`,
|
||||
`L4-TOOL-DB`, `L4-USER-M-PROCESS`, `UPSTREAM-DEMO`, or `ASSET-ONLY`.
|
||||
4. Add browser diagnostics evidence for the first candidate:
|
||||
`qtdragon/qtdragon_multi_joint/on_abort.ngc`.
|
||||
5. Keep `sim_configs_wasm_node_inventory_executed=28`,
|
||||
`sim_configs_wasm_node_inventory_passed=28`, and
|
||||
`sim_configs_wasm_node_inventory_skipped=131` unchanged until a deliberate
|
||||
inventory-promotion patch is made.
|
||||
|
||||
Recommended gates:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
|
||||
wasm-port/tests/sdk/node/verify_sdk_surface.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
|
||||
```
|
||||
|
||||
## Boundary Statement
|
||||
|
||||
This analysis relies on the improved virtual HAL only for Web simulation
|
||||
runtime surfaces. It does not claim Linux kernel hard-realtime ABI support,
|
||||
external hardware driver ABI support, native HAL module ABI support, Python UI
|
||||
process emulation, tool database process emulation, or external user-M process
|
||||
execution. G-code, interpreter, planner, kinematics, canonical motion, machine
|
||||
INI, tool table, parameter, and remap semantics remain LinuxCNC-backed.
|
||||
@@ -298,8 +298,9 @@ private page state.
|
||||
`readPin()`, `writePin()`, `applyPinUpdates()`, `executeHalCommand()`,
|
||||
`executeHalcmd()`, `stepMotion()`, `stepMotionController()`,
|
||||
`getSimulationRuntimeReport()`, `getSimulationReplacementReport()`,
|
||||
`getSourceComplianceReport()`, `getIntegrityReport()`, `getPinInventory()`,
|
||||
`getProjectReport()`, and `applyToInterpSdk()`.
|
||||
`getSourceComplianceReport()`, `getSimConfigPromotionCandidateReport()`,
|
||||
`getIntegrityReport()`, `getPinInventory()`, `getProjectReport()`, and
|
||||
`applyToInterpSdk()`.
|
||||
- `VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES`,
|
||||
`VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS`,
|
||||
`VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES`,
|
||||
@@ -315,7 +316,17 @@ private page state.
|
||||
`addf`, thread start/stop, and servo-period motion stepping for browser
|
||||
simulation and Node dashboards. The motion controller matrix rows also carry
|
||||
LinuxCNC `configs/sim` evidence for external offsets, QtDragon multi-joint,
|
||||
and vismach remap simulation coverage.
|
||||
and vismach remap simulation coverage. When callers pass `manifestText` or
|
||||
`manifestEntries`, the matrix report checks those associated sim-config
|
||||
source files against the vendored LinuxCNC manifest and exposes
|
||||
`manifestChecked` plus `missingManifestFiles`.
|
||||
- `VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES` and
|
||||
`createVirtualHalSimConfigPromotionCandidateReport()` expose the current
|
||||
source-derived sim-config promotion candidate set. The first candidates keep
|
||||
the inventory baseline unchanged while naming LinuxCNC INI/G-code source
|
||||
files, current Node `PASS` evidence, blocked-family exclusions, target
|
||||
browser diagnostics evidence, and the required virtual HAL reports for
|
||||
QtDragon on-abort, PUMA seam-weld, and rose-engine promotion planning.
|
||||
- `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
|
||||
@@ -419,6 +430,11 @@ workflow, report validation, and missing evidence without throwing.
|
||||
`createProjectBatchAcceptanceReportUrlWorkflowSummaryViewModel()` and
|
||||
`createProjectBatchAcceptanceReportUrlWorkflowActionPlan()` turn the same URL
|
||||
workflow into dashboard rows and ordered input/fetch/gate actions.
|
||||
`loadProjectReleaseReadinessArtifactUrlWorkflow()` can also fetch a browser
|
||||
diagnostics artifact. When that artifact includes
|
||||
`virtualHalSessionDiagnostics`, validation checks the saved-session diagnostics
|
||||
artifact alongside the live virtual HAL evidence so URL workflows can prove
|
||||
both live diagnostics and restored-session diagnostics are release-ready.
|
||||
|
||||
This helper does not execute shell commands and does not inspect or implement
|
||||
CNC behavior. It only packages project-level release evidence and blocked
|
||||
@@ -567,6 +583,13 @@ for external browser shells:
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan()`
|
||||
exposes the same URL workflow next-action/next-command plan through the
|
||||
browser workflow overview surface.
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState()`,
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract()`,
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness()`,
|
||||
`renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState()`,
|
||||
and `mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState()`
|
||||
let the fixed workflow overview URL form render the URL workflow action plan
|
||||
beside the URL workflow rows.
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState()`,
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract()`,
|
||||
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness()`,
|
||||
|
||||
@@ -7,6 +7,7 @@ export {
|
||||
VIRTUAL_HAL_COVERAGE_STATES,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
|
||||
VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS,
|
||||
@@ -30,6 +31,7 @@ export {
|
||||
createVirtualHalPinInventory,
|
||||
createVirtualHalPinRegistry,
|
||||
createVirtualHalProjectReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalSimulationRuntimeReport,
|
||||
|
||||
@@ -121,6 +121,202 @@ export const VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS = Object.freeze([
|
||||
}),
|
||||
]);
|
||||
|
||||
export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
Object.freeze({
|
||||
id: "qtdragon-multi-joint-on-abort",
|
||||
label: "QtDragon multi-joint on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-multi-joint",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "Node inventory already covers the LinuxCNC QtDragon multi-joint on-abort program; virtual HAL supplies the HAL/UI/motion evidence needed for explicit browser diagnostics.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtdragon-xyz-on-abort",
|
||||
label: "QtDragon XYZ on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "Node inventory already covers the LinuxCNC QtDragon XYZ on-abort program; virtual HAL can carry explicit browser diagnostics without changing CNC semantics.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtdragon-xyz45-on-abort",
|
||||
label: "QtDragon XYZA on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-rotary-axis",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "The LinuxCNC QtDragon XYZA on-abort case adds rotary-axis machine context without Python remap or external process runtime.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtdragon-hd-xyz-on-abort",
|
||||
label: "QtDragon HD XYZ on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "The LinuxCNC QtDragon HD XYZ on-abort case is a deterministic HAL/UI workflow suitable for browser diagnostics evidence.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtdragon-hd-z-compensation-on-abort",
|
||||
label: "QtDragon HD z-compensation on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"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",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-z-compensation",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "The LinuxCNC QtDragon HD z-compensation on-abort case should only promote with explicit source evidence for the z-compensation INI.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtvcp-screens-qtdragon-on-abort",
|
||||
label: "QTVCP screens QtDragon on-abort",
|
||||
simConfigTarget: "qtdragon-on-abort",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "The LinuxCNC QTVCP QtDragon on-abort case has no hard runtime block and can be promoted as explicit browser diagnostics evidence.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "puma-seam-weld",
|
||||
label: "PUMA seam weld",
|
||||
simConfigTarget: "vismach-remap-sims",
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "represented-by-puma-cube",
|
||||
dependencyClass: "halui-vismach-remap",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "Node inventory covers this LinuxCNC PUMA program with the same vendored machine context as puma_cube; browser evidence can pair both cases.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "rose-engine-rcone-demo",
|
||||
label: "Rose engine cone demo",
|
||||
simConfigTarget: null,
|
||||
sourceFiles: Object.freeze([
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
]),
|
||||
iniPath: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "not-promoted",
|
||||
dependencyClass: "hal-process-only",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]),
|
||||
blockedKind: "-",
|
||||
nonMainFixture: false,
|
||||
evidence: "The LinuxCNC rose-engine demo is a HAL-process-only Node inventory pass and is useful as a non-Qt/non-vismach diagnostics candidate.",
|
||||
}),
|
||||
]);
|
||||
|
||||
export const VIRTUAL_HAL_COVERAGE_STATES = Object.freeze({
|
||||
simulated: "simulated",
|
||||
bridgeOnly: "bridge-only",
|
||||
@@ -2197,6 +2393,11 @@ function virtualHalSimConfigTargetsById(targetIds = []) {
|
||||
export function createVirtualHalMotionControllerMatrixReport(options = {}) {
|
||||
const fixtures = options.motionFixtures ?? options.fixtures ?? VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES;
|
||||
const tolerance = clampNumber(options.tolerance ?? 0.000001, 0, 1);
|
||||
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
|
||||
const manifestSet = new Set([
|
||||
...sourceManifestSetFromText(options.manifestText ?? ""),
|
||||
...(options.manifestEntries ?? []).map(normalizeLinuxCncSourcePath),
|
||||
]);
|
||||
const rows = fixtures.map((fixture) => {
|
||||
const initialState = createVirtualHalState({
|
||||
task: { estop: false, powered: true },
|
||||
@@ -2262,6 +2463,11 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) {
|
||||
}));
|
||||
const missingSimConfigTargets = (fixture.simConfigTargets ?? [])
|
||||
.filter((targetId) => !simConfigEvidenceRows.some((target) => target.id === targetId));
|
||||
const simConfigSourceFiles = [...new Set(simConfigEvidenceRows.flatMap((target) => target.sourceFiles))];
|
||||
const normalizedSimConfigSourceFiles = simConfigSourceFiles.map(normalizeLinuxCncSourcePath);
|
||||
const missingManifestFiles = manifestProvided
|
||||
? simConfigSourceFiles.filter((file, index) => !manifestSet.has(normalizedSimConfigSourceFiles[index]))
|
||||
: [];
|
||||
return {
|
||||
id: fixture.id,
|
||||
label: fixture.label,
|
||||
@@ -2269,9 +2475,11 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) {
|
||||
sourceFiles: [...(fixture.sourceFiles ?? [])],
|
||||
simConfigTargets: [...(fixture.simConfigTargets ?? [])],
|
||||
simConfigEvidenceRows,
|
||||
simConfigSourceFiles: [...new Set(simConfigEvidenceRows.flatMap((target) => target.sourceFiles))],
|
||||
simConfigSourceFiles,
|
||||
missingSimConfigTargets,
|
||||
complete,
|
||||
manifestChecked: manifestProvided,
|
||||
missingManifestFiles,
|
||||
complete: complete && missingManifestFiles.length === 0,
|
||||
target: { ...(fixture.target ?? {}) },
|
||||
initialPosition: { ...(fixture.initialPosition ?? {}) },
|
||||
maxVelocity: fixture.maxVelocity,
|
||||
@@ -2292,7 +2500,11 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) {
|
||||
});
|
||||
const missingFixtures = rows.filter((row) => !row.complete).map((row) => row.id);
|
||||
const missingSimConfigTargets = rows.flatMap((row) => row.missingSimConfigTargets);
|
||||
const complete = rows.length > 0 && missingFixtures.length === 0 && missingSimConfigTargets.length === 0;
|
||||
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
|
||||
const complete = rows.length > 0 &&
|
||||
missingFixtures.length === 0 &&
|
||||
missingSimConfigTargets.length === 0 &&
|
||||
missingManifestFiles.length === 0;
|
||||
return {
|
||||
apiName: "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report",
|
||||
matrixVersion: 1,
|
||||
@@ -2303,15 +2515,18 @@ export function createVirtualHalMotionControllerMatrixReport(options = {}) {
|
||||
sourceFiles: [...new Set(rows.flatMap((row) => row.sourceFiles))],
|
||||
simConfigSourceFiles: [...new Set(rows.flatMap((row) => row.simConfigSourceFiles))],
|
||||
simConfigTargets: [...new Set(rows.flatMap((row) => row.simConfigTargets))],
|
||||
manifestChecked: manifestProvided,
|
||||
requiredPins: [...new Set(fixtures.flatMap((fixture) => fixture.requiredPins ?? []))],
|
||||
fixtureCount: rows.length,
|
||||
missingFixtures,
|
||||
missingSimConfigTargets,
|
||||
missingManifestFiles,
|
||||
rows,
|
||||
summaryRows: [
|
||||
{ id: "fixtures", label: "Motion matrix fixtures", value: `${rows.length}` },
|
||||
{ id: "source", label: "LinuxCNC motion source", value: complete ? "source-derived" : "incomplete" },
|
||||
{ id: "sim-config-source", label: "LinuxCNC sim config source", value: missingSimConfigTargets.length === 0 ? "source-derived" : `missing ${missingSimConfigTargets.length}` },
|
||||
{ id: "manifest", label: "Sim config manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
|
||||
{ id: "servo-period", label: "Servo period stepping", value: complete ? "covered" : "blocked" },
|
||||
{ id: "axis-joint-feedback", label: "Axis/joint feedback", value: complete ? "covered" : "blocked" },
|
||||
],
|
||||
@@ -2477,6 +2692,118 @@ export function createVirtualHalSimConfigSourceCoverageReport(options = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function createVirtualHalSimConfigPromotionCandidateReport(options = {}) {
|
||||
const candidates = options.candidates ?? VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES;
|
||||
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
|
||||
const manifestSet = new Set([
|
||||
...sourceManifestSetFromText(options.manifestText ?? ""),
|
||||
...(options.manifestEntries ?? []).map(normalizeLinuxCncSourcePath),
|
||||
]);
|
||||
const blockedKinds = new Set(options.blockedKinds ?? [
|
||||
"L4-PYTHON-REMAP",
|
||||
"L4-TOOL-DB",
|
||||
"L4-USER-M-PROCESS",
|
||||
"UPSTREAM-DEMO",
|
||||
]);
|
||||
const allowedNodeStatuses = new Set(options.allowedNodeStatuses ?? ["PASS"]);
|
||||
const requiredVirtualHalReports = options.requiredVirtualHalReports ?? [
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
];
|
||||
const simConfigCoverage = options.simConfigSourceCoverage ?? createVirtualHalSimConfigSourceCoverageReport(options);
|
||||
const sourceCompliance = options.sourceCompliance ?? createVirtualHalSourceComplianceReport(options);
|
||||
const commandScriptFixtures = options.commandScriptFixtures ?? createVirtualHalCommandScriptFixtureReport(options);
|
||||
const motionControllerMatrix = options.motionControllerMatrix ?? createVirtualHalMotionControllerMatrixReport(options);
|
||||
const availableReports = new Set([
|
||||
...(sourceCompliance.complete ? ["source-compliance"] : []),
|
||||
...(simConfigCoverage.complete ? ["sim-config-source-coverage"] : []),
|
||||
...(commandScriptFixtures.complete ? ["command-script-fixtures"] : []),
|
||||
...(motionControllerMatrix.complete && motionControllerMatrix.manifestChecked ? ["manifest-backed-motion-matrix"] : []),
|
||||
]);
|
||||
const rows = candidates.map((candidate) => {
|
||||
const sourceFiles = [...(candidate.sourceFiles ?? [])];
|
||||
const normalizedSourceFiles = sourceFiles.map(normalizeLinuxCncSourcePath);
|
||||
const missingManifestFiles = manifestProvided
|
||||
? sourceFiles.filter((file, index) => !manifestSet.has(normalizedSourceFiles[index]))
|
||||
: [];
|
||||
const missingRequiredReports = requiredVirtualHalReports
|
||||
.filter((report) => !availableReports.has(report));
|
||||
const blockedKindExcluded = !blockedKinds.has(candidate.blockedKind);
|
||||
const nodeStatusReady = allowedNodeStatuses.has(candidate.currentNodeInventoryStatus) ||
|
||||
candidate.nonMainFixture === true;
|
||||
const simConfigTargetReady = !candidate.simConfigTarget ||
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.some((target) => target.id === candidate.simConfigTarget);
|
||||
const complete = sourceFiles.length > 0 &&
|
||||
missingManifestFiles.length === 0 &&
|
||||
missingRequiredReports.length === 0 &&
|
||||
blockedKindExcluded &&
|
||||
nodeStatusReady &&
|
||||
simConfigTargetReady;
|
||||
return {
|
||||
id: candidate.id,
|
||||
label: candidate.label,
|
||||
source: "linuxcnc-configs-sim-source-derived-virtual-hal-promotion-candidate",
|
||||
simConfigTarget: candidate.simConfigTarget ?? null,
|
||||
sourceFiles,
|
||||
iniPath: candidate.iniPath,
|
||||
gcodePath: candidate.gcodePath,
|
||||
currentNodeInventoryStatus: candidate.currentNodeInventoryStatus,
|
||||
currentMatrixBrowserStatus: candidate.currentMatrixBrowserStatus,
|
||||
dependencyClass: candidate.dependencyClass,
|
||||
targetBrowserEvidence: candidate.targetBrowserEvidence,
|
||||
requiredVirtualHalReports: [...(candidate.requiredVirtualHalReports ?? requiredVirtualHalReports)],
|
||||
blockedKind: candidate.blockedKind,
|
||||
blockedKindExcluded,
|
||||
nonMainFixture: candidate.nonMainFixture === true,
|
||||
nodeStatusReady,
|
||||
simConfigTargetReady,
|
||||
manifestChecked: manifestProvided,
|
||||
missingManifestFiles,
|
||||
missingRequiredReports,
|
||||
evidence: candidate.evidence,
|
||||
complete,
|
||||
};
|
||||
});
|
||||
const missingCandidates = rows.filter((row) => !row.complete).map((row) => row.id);
|
||||
const blockedCandidateIds = rows.filter((row) => !row.blockedKindExcluded).map((row) => row.id);
|
||||
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
|
||||
const missingRequiredReports = [...new Set(rows.flatMap((row) => row.missingRequiredReports))];
|
||||
const complete = rows.length > 0 &&
|
||||
missingCandidates.length === 0 &&
|
||||
blockedCandidateIds.length === 0 &&
|
||||
missingManifestFiles.length === 0 &&
|
||||
missingRequiredReports.length === 0;
|
||||
return {
|
||||
apiName: "linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report",
|
||||
reportVersion: 1,
|
||||
source: "linuxcnc-configs-sim-source-derived-virtual-hal",
|
||||
phase: complete ? "ready" : "blocked",
|
||||
complete,
|
||||
webSimulationSatisfied: complete,
|
||||
inventoryBaselineUnchanged: true,
|
||||
manifestChecked: manifestProvided,
|
||||
candidateCount: rows.length,
|
||||
sourceFiles: [...new Set(rows.flatMap((row) => row.sourceFiles))],
|
||||
requiredVirtualHalReports,
|
||||
availableVirtualHalReports: [...availableReports],
|
||||
blockedKinds: [...blockedKinds],
|
||||
missingCandidates,
|
||||
blockedCandidateIds,
|
||||
missingManifestFiles,
|
||||
missingRequiredReports,
|
||||
rows,
|
||||
summaryRows: [
|
||||
{ id: "candidates", label: "Promotion candidates", value: `${rows.length}` },
|
||||
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedCandidateIds.length === 0 ? "passed" : `blocked ${blockedCandidateIds.length}` },
|
||||
{ id: "reports", label: "Virtual HAL reports", value: missingRequiredReports.length === 0 ? "complete" : `missing ${missingRequiredReports.length}` },
|
||||
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
|
||||
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function createVirtualHalSourceComplianceReport(options = {}) {
|
||||
const halState = options.halState ?? createVirtualHalState();
|
||||
const snapshot = options.snapshot ?? createVirtualHalWasmBridgeSnapshot(halState);
|
||||
@@ -2690,6 +3017,9 @@ export function createLinuxCncVirtualHalRuntime(initialState = createVirtualHalS
|
||||
getSimConfigSourceCoverageReport(options = {}) {
|
||||
return createVirtualHalSimConfigSourceCoverageReport(options);
|
||||
},
|
||||
getSimConfigPromotionCandidateReport(options = {}) {
|
||||
return createVirtualHalSimConfigPromotionCandidateReport(options);
|
||||
},
|
||||
getCommandScriptFixtureReport(options = {}) {
|
||||
return createVirtualHalCommandScriptFixtureReport({ ...options, halState: state });
|
||||
},
|
||||
|
||||
@@ -99,12 +99,57 @@ function isVirtualHalSimConfigSourceCoverageReady(report) {
|
||||
arrayOrEmpty(coverage.sourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc");
|
||||
}
|
||||
|
||||
function isVirtualHalMotionControllerMatrixReady(report) {
|
||||
const matrix = objectOrEmpty(report);
|
||||
return matrix.apiName === "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report" &&
|
||||
matrix.complete === true &&
|
||||
matrix.webSimulationSatisfied === true &&
|
||||
matrix.manifestChecked === true &&
|
||||
arrayOrEmpty(matrix.missingFixtures).length === 0 &&
|
||||
arrayOrEmpty(matrix.missingSimConfigTargets).length === 0 &&
|
||||
arrayOrEmpty(matrix.missingManifestFiles).length === 0 &&
|
||||
arrayOrEmpty(matrix.requiredPins).includes("motion.distance-to-go") &&
|
||||
arrayOrEmpty(matrix.requiredPins).includes("motion.in-position") &&
|
||||
arrayOrEmpty(matrix.sourceFiles).includes("linuxcnc/src/emc/motion/motion.c") &&
|
||||
arrayOrEmpty(matrix.sourceFiles).includes("linuxcnc/src/emc/motion/axis.c") &&
|
||||
arrayOrEmpty(matrix.simConfigTargets).includes("external-offsets") &&
|
||||
arrayOrEmpty(matrix.simConfigTargets).includes("qtdragon-on-abort") &&
|
||||
arrayOrEmpty(matrix.simConfigTargets).includes("vismach-remap-sims") &&
|
||||
arrayOrEmpty(matrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini") &&
|
||||
arrayOrEmpty(matrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") &&
|
||||
arrayOrEmpty(matrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini");
|
||||
}
|
||||
|
||||
function isVirtualHalSimConfigPromotionCandidateReportReady(report) {
|
||||
const candidateReport = objectOrEmpty(report);
|
||||
const rows = arrayOrEmpty(candidateReport.rows);
|
||||
return candidateReport.apiName === "linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report" &&
|
||||
candidateReport.complete === true &&
|
||||
candidateReport.webSimulationSatisfied === true &&
|
||||
candidateReport.inventoryBaselineUnchanged === true &&
|
||||
arrayOrEmpty(candidateReport.missingCandidates).length === 0 &&
|
||||
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")
|
||||
);
|
||||
}
|
||||
|
||||
export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifact = {}) {
|
||||
const artifactObject = objectOrEmpty(artifact);
|
||||
const sourceCompliance = objectOrEmpty(artifactObject.virtualHalSourceCompliance);
|
||||
const simConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage);
|
||||
const commandScriptFixtures = objectOrEmpty(artifactObject.virtualHalCommandScriptFixtures);
|
||||
const motionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
|
||||
const promotionCandidates = objectOrEmpty(artifactObject.virtualHalSimConfigPromotionCandidates);
|
||||
const sessionDiagnostics = objectOrEmpty(artifactObject.virtualHalSessionDiagnostics);
|
||||
const replacement = objectOrEmpty(artifactObject.virtualHalSimulationReplacement);
|
||||
const virtualHal = objectOrEmpty(artifactObject.virtualHal);
|
||||
const sourceComplianceReady = sourceCompliance.complete === true &&
|
||||
@@ -116,31 +161,35 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
arrayOrEmpty(commandScriptFixtures.coveredActions).includes("loadusr") &&
|
||||
arrayOrEmpty(commandScriptFixtures.coveredActions).includes("stop") &&
|
||||
arrayOrEmpty(commandScriptFixtures.sourceFiles).includes("linuxcnc/src/hal/utils/halcmd_commands.cc");
|
||||
const motionControllerMatrixReady = motionControllerMatrix.complete === true &&
|
||||
motionControllerMatrix.webSimulationSatisfied === true &&
|
||||
arrayOrEmpty(motionControllerMatrix.requiredPins).includes("motion.distance-to-go") &&
|
||||
arrayOrEmpty(motionControllerMatrix.requiredPins).includes("motion.in-position") &&
|
||||
arrayOrEmpty(motionControllerMatrix.sourceFiles).includes("linuxcnc/src/emc/motion/motion.c") &&
|
||||
arrayOrEmpty(motionControllerMatrix.sourceFiles).includes("linuxcnc/src/emc/motion/axis.c") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("external-offsets") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("qtdragon-on-abort") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigTargets).includes("vismach-remap-sims") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") &&
|
||||
arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles).includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini");
|
||||
const motionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(motionControllerMatrix);
|
||||
const hasPromotionCandidates = artifactObject.virtualHalSimConfigPromotionCandidates !== undefined;
|
||||
const promotionCandidatesReady = !hasPromotionCandidates ||
|
||||
isVirtualHalSimConfigPromotionCandidateReportReady(promotionCandidates);
|
||||
const replacementReady = replacement.ready === true &&
|
||||
replacement.replacesHostRuntimeForSimulation === true &&
|
||||
objectOrEmpty(replacement.sourceCompliance).webSimulationSatisfied === true &&
|
||||
objectOrEmpty(replacement.motionControllerMatrix).complete === true;
|
||||
const virtualHalReady = virtualHal.source === "browser-virtual-hal";
|
||||
const hasSessionDiagnostics = artifactObject.virtualHalSessionDiagnostics !== undefined;
|
||||
const sessionDiagnosticsReady = !hasSessionDiagnostics || (
|
||||
sessionDiagnostics.apiName === "real-browser-simulation-virtual-hal-session-diagnostics" &&
|
||||
sessionDiagnostics.ready === true &&
|
||||
sessionDiagnostics.phase === "release-ready" &&
|
||||
objectOrEmpty(sessionDiagnostics.validation).ready === true &&
|
||||
objectOrEmpty(sessionDiagnostics.diagnosticsArtifact).apiName === "real-browser-simulation-diagnostics-artifact" &&
|
||||
objectOrEmpty(sessionDiagnostics.diagnosticsArtifact?.virtualHalSourceCompliance).complete === true &&
|
||||
objectOrEmpty(sessionDiagnostics.diagnosticsArtifact?.virtualHalMotionControllerMatrix).manifestChecked === true
|
||||
);
|
||||
const missing = [
|
||||
...(artifactObject.apiName === "real-browser-simulation-diagnostics-artifact" ? [] : ["apiName"]),
|
||||
...(virtualHalReady ? [] : ["virtualHal"]),
|
||||
...(replacementReady ? [] : ["virtualHalSimulationReplacement"]),
|
||||
...(sourceComplianceReady ? [] : ["virtualHalSourceCompliance"]),
|
||||
...(simConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
|
||||
...(promotionCandidatesReady ? [] : ["virtualHalSimConfigPromotionCandidates"]),
|
||||
...(commandScriptFixturesReady ? [] : ["virtualHalCommandScriptFixtures"]),
|
||||
...(motionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
|
||||
...(sessionDiagnosticsReady ? [] : ["virtualHalSessionDiagnostics"]),
|
||||
];
|
||||
return {
|
||||
apiName: "project-release-browser-diagnostics-artifact-validation",
|
||||
@@ -153,11 +202,16 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
replacementReady,
|
||||
sourceComplianceReady,
|
||||
simConfigSourceCoverageReady,
|
||||
promotionCandidatesReady,
|
||||
hasPromotionCandidates,
|
||||
commandScriptFixturesReady,
|
||||
motionControllerMatrixReady,
|
||||
sessionDiagnosticsReady,
|
||||
hasSessionDiagnostics,
|
||||
sourceFiles: [...new Set([
|
||||
...arrayOrEmpty(sourceCompliance.sourceFiles),
|
||||
...arrayOrEmpty(simConfigSourceCoverage.sourceFiles),
|
||||
...arrayOrEmpty(promotionCandidates.sourceFiles),
|
||||
...arrayOrEmpty(commandScriptFixtures.sourceFiles),
|
||||
...arrayOrEmpty(motionControllerMatrix.sourceFiles),
|
||||
...arrayOrEmpty(motionControllerMatrix.simConfigSourceFiles),
|
||||
@@ -183,6 +237,11 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: simConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: hasPromotionCandidates ? (promotionCandidatesReady ? "ready" : "missing") : "not provided",
|
||||
},
|
||||
{
|
||||
id: "command-script-fixtures",
|
||||
label: "Virtual HAL command script fixtures",
|
||||
@@ -193,6 +252,11 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: motionControllerMatrixReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "session-diagnostics",
|
||||
label: "Saved-session diagnostics",
|
||||
value: hasSessionDiagnostics ? (sessionDiagnosticsReady ? "ready" : "missing") : "not provided",
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing diagnostics evidence",
|
||||
@@ -585,6 +649,7 @@ export function createProjectBatchAcceptanceWorkflow({
|
||||
gateResults = {},
|
||||
observedOutputs = [],
|
||||
virtualHalSimConfigSourceCoverage = null,
|
||||
virtualHalMotionControllerMatrix = null,
|
||||
} = {}) {
|
||||
const capabilityMatrix = createProjectBatchAcceptanceCapabilityMatrix({ capabilities });
|
||||
const gateManifest = createProjectReleaseGateManifest();
|
||||
@@ -597,11 +662,17 @@ export function createProjectBatchAcceptanceWorkflow({
|
||||
.find(({ id }) => id === "project-batch-acceptance")?.passed === true;
|
||||
const virtualHalSimConfigSourceCoverageReady = virtualHalSimConfigSourceCoverage === null ||
|
||||
isVirtualHalSimConfigSourceCoverageReady(virtualHalSimConfigSourceCoverage);
|
||||
const ready = capabilityMatrix.ready && batchGatePassed && virtualHalSimConfigSourceCoverageReady;
|
||||
const virtualHalMotionControllerMatrixReady = virtualHalMotionControllerMatrix === null ||
|
||||
isVirtualHalMotionControllerMatrixReady(virtualHalMotionControllerMatrix);
|
||||
const ready = capabilityMatrix.ready &&
|
||||
batchGatePassed &&
|
||||
virtualHalSimConfigSourceCoverageReady &&
|
||||
virtualHalMotionControllerMatrixReady;
|
||||
const missing = [
|
||||
...capabilityMatrix.missing,
|
||||
...(batchGatePassed ? [] : ["project-batch-acceptance"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtual-hal-sim-config-source-coverage"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtual-hal-motion-controller-matrix"]),
|
||||
];
|
||||
|
||||
return {
|
||||
@@ -618,6 +689,8 @@ export function createProjectBatchAcceptanceWorkflow({
|
||||
rejectedCapabilities: capabilityMatrix.rejectedCapabilities,
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalMotionControllerMatrix,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
gateResultMatrix,
|
||||
missing,
|
||||
rows: [
|
||||
@@ -643,6 +716,13 @@ export function createProjectBatchAcceptanceWorkflow({
|
||||
? "not required"
|
||||
: (virtualHalSimConfigSourceCoverageReady ? "ready" : "missing"),
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: virtualHalMotionControllerMatrix === null
|
||||
? "not required"
|
||||
: (virtualHalMotionControllerMatrixReady ? "ready" : "missing"),
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing acceptance evidence",
|
||||
@@ -785,6 +865,15 @@ export function createProjectBatchAcceptanceChecklist({
|
||||
? "not required"
|
||||
: (workflow?.virtualHalSimConfigSourceCoverageReady === true ? "ready" : "missing"),
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
status: workflow?.virtualHalMotionControllerMatrixReady !== false ? "pass" : "blocked",
|
||||
passed: workflow?.virtualHalMotionControllerMatrixReady !== false,
|
||||
detail: workflow?.virtualHalMotionControllerMatrix === null
|
||||
? "not required"
|
||||
: (workflow?.virtualHalMotionControllerMatrixReady === true ? "ready" : "missing"),
|
||||
},
|
||||
{
|
||||
id: "next-action",
|
||||
label: "Next acceptance action",
|
||||
@@ -817,6 +906,7 @@ export function createProjectBatchAcceptanceReport({
|
||||
gateResults = {},
|
||||
observedOutputs = [],
|
||||
virtualHalSimConfigSourceCoverage = null,
|
||||
virtualHalMotionControllerMatrix = null,
|
||||
} = {}) {
|
||||
const capabilityMatrix = createProjectBatchAcceptanceCapabilityMatrix({ capabilities });
|
||||
const workflow = createProjectBatchAcceptanceWorkflow({
|
||||
@@ -825,6 +915,7 @@ export function createProjectBatchAcceptanceReport({
|
||||
gateResults,
|
||||
observedOutputs,
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalMotionControllerMatrix,
|
||||
});
|
||||
const summaryViewModel = createProjectBatchAcceptanceSummaryViewModel(workflow);
|
||||
const actionPlan = createProjectBatchAcceptanceActionPlan(workflow);
|
||||
@@ -840,6 +931,7 @@ export function createProjectBatchAcceptanceReport({
|
||||
capabilityMatrix,
|
||||
workflow,
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalMotionControllerMatrix,
|
||||
summaryViewModel,
|
||||
actionPlan,
|
||||
checklist,
|
||||
@@ -876,11 +968,16 @@ export function createProjectBatchAcceptanceReportValidation(report = {}) {
|
||||
const actionPlan = objectOrEmpty(reportObject.actionPlan);
|
||||
const checklist = objectOrEmpty(reportObject.checklist);
|
||||
const virtualHalSimConfigSourceCoverage = objectOrEmpty(reportObject.virtualHalSimConfigSourceCoverage);
|
||||
const virtualHalMotionControllerMatrix = objectOrEmpty(reportObject.virtualHalMotionControllerMatrix);
|
||||
const rows = arrayOrEmpty(reportObject.rows);
|
||||
const virtualHalSimConfigSourceCoverageRequired = reportObject.virtualHalSimConfigSourceCoverage !== null &&
|
||||
reportObject.virtualHalSimConfigSourceCoverage !== undefined;
|
||||
const virtualHalSimConfigSourceCoverageReady = !virtualHalSimConfigSourceCoverageRequired ||
|
||||
isVirtualHalSimConfigSourceCoverageReady(virtualHalSimConfigSourceCoverage);
|
||||
const virtualHalMotionControllerMatrixRequired = reportObject.virtualHalMotionControllerMatrix !== null &&
|
||||
reportObject.virtualHalMotionControllerMatrix !== undefined;
|
||||
const virtualHalMotionControllerMatrixReady = !virtualHalMotionControllerMatrixRequired ||
|
||||
isVirtualHalMotionControllerMatrixReady(virtualHalMotionControllerMatrix);
|
||||
const missing = [
|
||||
...(reportObject.apiName === "project-batch-acceptance-report" ? [] : ["apiName"]),
|
||||
...(reportObject.reportVersion === 1 ? [] : ["reportVersion"]),
|
||||
@@ -905,7 +1002,8 @@ export function createProjectBatchAcceptanceReportValidation(report = {}) {
|
||||
? []
|
||||
: ["checklist"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
|
||||
...(rows.find(({ id, value }) => id === "checklist" && /^([34])\/\1 passed$/.test(value))
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
|
||||
...(rows.find(({ id, value }) => id === "checklist" && /^([45])\/\1 passed$/.test(value))
|
||||
? []
|
||||
: ["rows.checklist"]),
|
||||
];
|
||||
@@ -919,6 +1017,8 @@ export function createProjectBatchAcceptanceReportValidation(report = {}) {
|
||||
batchId: reportObject.batchId ?? null,
|
||||
reportApiName: reportObject.apiName ?? null,
|
||||
reportVersion: reportObject.reportVersion ?? null,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
rows: [
|
||||
{
|
||||
id: "report",
|
||||
@@ -947,6 +1047,13 @@ export function createProjectBatchAcceptanceReportValidation(report = {}) {
|
||||
? (virtualHalSimConfigSourceCoverageReady ? "ready" : "missing")
|
||||
: "not required",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: virtualHalMotionControllerMatrixRequired
|
||||
? (virtualHalMotionControllerMatrixReady ? "ready" : "missing")
|
||||
: "not required",
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing report evidence",
|
||||
@@ -1404,6 +1511,7 @@ export function createProjectReleaseReadinessReport({
|
||||
observedOutputs = [],
|
||||
simConfigInventory = DEFAULT_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
virtualHalSimConfigSourceCoverage = null,
|
||||
virtualHalMotionControllerMatrix = null,
|
||||
blockedRuntimeFamilies = BLOCKED_RUNTIME_FAMILIES,
|
||||
promotedRuntimeFamilies = [],
|
||||
axisScreenshotArtifacts = [],
|
||||
@@ -1439,18 +1547,23 @@ export function createProjectReleaseReadinessReport({
|
||||
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
);
|
||||
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
|
||||
virtualHalMotionControllerMatrix,
|
||||
);
|
||||
const blockedRuntimeReady = promotedBlockedFamilies.length === 0;
|
||||
const axisScreenshotArtifactSummary = createAxisScreenshotArtifactSummary(axisScreenshotArtifacts);
|
||||
const axisScreenshotArtifactsReady = axisScreenshotArtifactSummary.ready;
|
||||
const ready = releaseGatePassed &&
|
||||
inventoryReady &&
|
||||
virtualHalSimConfigSourceCoverageReady &&
|
||||
virtualHalMotionControllerMatrixReady &&
|
||||
blockedRuntimeReady &&
|
||||
axisScreenshotArtifactsReady;
|
||||
const missing = [
|
||||
...(releaseGatePassed ? [] : ["project-release-gate"]),
|
||||
...(inventoryReady ? [] : ["sim-config-inventory"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtual-hal-sim-config-source-coverage"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtual-hal-motion-controller-matrix"]),
|
||||
...(blockedRuntimeReady ? [] : ["blocked-runtime-families"]),
|
||||
...(axisScreenshotArtifactsReady ? [] : ["axis-screenshot-artifacts"]),
|
||||
];
|
||||
@@ -1469,6 +1582,8 @@ export function createProjectReleaseReadinessReport({
|
||||
simConfigInventory: inventory,
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalMotionControllerMatrix,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
blockedRuntimeFamilies: blockedFamilies,
|
||||
promotedRuntimeFamilies: promotedFamilies,
|
||||
promotedBlockedFamilies,
|
||||
@@ -1495,6 +1610,11 @@ export function createProjectReleaseReadinessReport({
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: virtualHalMotionControllerMatrixReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -1518,6 +1638,7 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
const gateResultMatrix = objectOrEmpty(report?.gateResultMatrix);
|
||||
const simConfigInventory = objectOrEmpty(report?.simConfigInventory);
|
||||
const virtualHalSimConfigSourceCoverageReady = report?.virtualHalSimConfigSourceCoverageReady === true;
|
||||
const virtualHalMotionControllerMatrixReady = report?.virtualHalMotionControllerMatrixReady === true;
|
||||
const axisScreenshotArtifactSummary = objectOrEmpty(report?.axisScreenshotArtifactSummary);
|
||||
const blockedRuntimeFamilies = arrayOrEmpty(report?.blockedRuntimeFamilies);
|
||||
const promotedBlockedFamilies = arrayOrEmpty(report?.promotedBlockedFamilies);
|
||||
@@ -1554,6 +1675,11 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: virtualHalMotionControllerMatrixReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -1636,6 +1762,11 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: validation?.virtualHalSimConfigSourceCoverageReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: validation?.virtualHalMotionControllerMatrixReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing artifact evidence",
|
||||
@@ -1790,6 +1921,7 @@ export function createProjectReleaseReadinessArtifactJsonWorkflow({ artifactJson
|
||||
export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl = "",
|
||||
diagnosticsUrl = "",
|
||||
requireSavedSessionDiagnostics = false,
|
||||
fetchRef = globalThis.fetch,
|
||||
} = {}) {
|
||||
if (!artifactUrl || typeof fetchRef !== "function") {
|
||||
@@ -1810,6 +1942,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
ready: false,
|
||||
artifactUrl,
|
||||
diagnosticsUrl,
|
||||
requireSavedSessionDiagnostics,
|
||||
fetched: false,
|
||||
diagnosticsFetched: false,
|
||||
httpStatus: null,
|
||||
@@ -1855,6 +1988,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
ready: false,
|
||||
artifactUrl,
|
||||
diagnosticsUrl,
|
||||
requireSavedSessionDiagnostics,
|
||||
fetched: false,
|
||||
diagnosticsFetched: false,
|
||||
httpStatus,
|
||||
@@ -1911,6 +2045,9 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
const diagnosticsArtifact = JSON.parse(await diagnosticsResponse.text());
|
||||
diagnosticsValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation(diagnosticsArtifact);
|
||||
diagnosticsMissing.push(...diagnosticsValidation.missing.map((item) => `diagnostics.${item}`));
|
||||
if (requireSavedSessionDiagnostics && diagnosticsValidation.hasSessionDiagnostics !== true) {
|
||||
diagnosticsMissing.push("diagnostics.virtualHalSessionDiagnostics");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
diagnosticsFetchError = error?.message ?? "diagnostics artifact URL fetch error";
|
||||
@@ -1923,7 +2060,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
...diagnosticsMissing,
|
||||
];
|
||||
const ready = jsonWorkflow.ready === true &&
|
||||
(!diagnosticsUrl || diagnosticsValidation?.ready === true);
|
||||
(!diagnosticsUrl || (diagnosticsValidation?.ready === true && diagnosticsMissing.length === 0));
|
||||
return {
|
||||
apiName: "project-release-readiness-artifact-url-workflow",
|
||||
workflowVersion: 1,
|
||||
@@ -1931,6 +2068,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
ready,
|
||||
artifactUrl,
|
||||
diagnosticsUrl,
|
||||
requireSavedSessionDiagnostics,
|
||||
fetched: true,
|
||||
diagnosticsFetched,
|
||||
httpStatus,
|
||||
@@ -1977,6 +2115,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
ready: false,
|
||||
artifactUrl,
|
||||
diagnosticsUrl,
|
||||
requireSavedSessionDiagnostics,
|
||||
fetched: false,
|
||||
diagnosticsFetched: false,
|
||||
httpStatus: null,
|
||||
@@ -2060,6 +2199,15 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
? (workflow?.diagnosticsValidation?.ready === true ? "ready" : "blocked")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "saved-session-diagnostics",
|
||||
label: "Saved-session diagnostics",
|
||||
value: workflow?.diagnosticsUrl
|
||||
? (workflow?.diagnosticsValidation?.hasSessionDiagnostics
|
||||
? (workflow?.diagnosticsValidation?.sessionDiagnosticsReady === true ? "ready" : "blocked")
|
||||
: "not provided")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "next-command",
|
||||
label: "Next command",
|
||||
@@ -2170,6 +2318,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const releaseGate = objectOrEmpty(artifactObject.releaseGate);
|
||||
const simConfigInventory = objectOrEmpty(artifactObject.simConfigInventory);
|
||||
const virtualHalSimConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage);
|
||||
const virtualHalMotionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
|
||||
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
|
||||
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
|
||||
const gateExecutionSummaryViewModel = objectOrEmpty(artifactObject.gateExecutionSummaryViewModel);
|
||||
@@ -2218,6 +2367,9 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
) && artifactObject.virtualHalSimConfigSourceCoverageReady === true;
|
||||
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
|
||||
virtualHalMotionControllerMatrix,
|
||||
) && artifactObject.virtualHalMotionControllerMatrixReady === true;
|
||||
const axisScreenshotArtifacts = arrayOrEmpty(axisScreenshotArtifactSummary.artifacts);
|
||||
const axisScreenshotSummaryReady = !axisScreenshotArtifactSummary.apiName
|
||||
|| axisScreenshotArtifacts.length === 0
|
||||
@@ -2256,6 +2408,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
...(simConfigInventory.skipped === 131 ? [] : ["simConfigInventory.skipped"]),
|
||||
...(simConfigInventory.unexpectedFail === 0 ? [] : ["simConfigInventory.unexpectedFail"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
|
||||
...(arrayOrEmpty(artifactObject.blockedRuntimeFamilies).join(",") === BLOCKED_RUNTIME_FAMILIES.join(",")
|
||||
? []
|
||||
: ["blockedRuntimeFamilies"]),
|
||||
@@ -2290,6 +2443,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
gateResultMatrixReady: matrixReady,
|
||||
gateActionPlanReady: actionPlanReady,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
axisScreenshotArtifactSummaryReady: axisScreenshotSummaryReady,
|
||||
axisScreenshotArtifactCount: axisScreenshotArtifacts.length,
|
||||
blockedRuntimeFamilies: arrayOrEmpty(artifactObject.blockedRuntimeFamilies),
|
||||
@@ -2334,6 +2488,11 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: virtualHalMotionControllerMatrixReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "axis-screenshot-artifacts",
|
||||
label: "AXIS screenshot artifacts",
|
||||
|
||||
@@ -2560,6 +2560,15 @@ export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWo
|
||||
? (workflow?.diagnosticsValidation?.ready === true ? "ready" : "blocked")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "saved-session-diagnostics",
|
||||
label: "Saved-session diagnostics",
|
||||
value: workflow?.diagnosticsUrl
|
||||
? (workflow?.diagnosticsValidation?.hasSessionDiagnostics
|
||||
? (workflow?.diagnosticsValidation?.sessionDiagnosticsReady === true ? "ready" : "blocked")
|
||||
: "not provided")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "diagnostics-status",
|
||||
label: "Diagnostics HTTP status",
|
||||
|
||||
@@ -127,6 +127,14 @@
|
||||
<p data-workflow-overview-release-readiness-artifact-url-workflow-status>Waiting for release artifact URL workflow.</p>
|
||||
<dl data-workflow-overview-release-readiness-artifact-url-workflow-rows></dl>
|
||||
</section>
|
||||
<section class="overview-status" aria-label="Release artifact URL workflow action plan" data-workflow-overview-release-readiness-artifact-url-workflow-action-plan>
|
||||
<p data-workflow-overview-release-readiness-artifact-url-workflow-action-plan-status>Waiting for URL workflow action plan.</p>
|
||||
<dl data-workflow-overview-release-readiness-artifact-url-workflow-action-plan-rows></dl>
|
||||
</section>
|
||||
<section class="overview-status" aria-label="Release artifact URL gate execution summary" data-workflow-overview-release-readiness-artifact-gate-execution-summary>
|
||||
<p data-workflow-overview-release-readiness-artifact-gate-execution-summary-status>Waiting for URL workflow gate evidence.</p>
|
||||
<dl data-workflow-overview-release-readiness-artifact-gate-execution-summary-rows></dl>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script type="module">
|
||||
@@ -170,6 +178,11 @@
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState,
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryViewModel,
|
||||
@@ -216,6 +229,25 @@
|
||||
renderState,
|
||||
documentRef: document,
|
||||
});
|
||||
const actionPlan = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan(workflow);
|
||||
const actionPlanRenderState =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState(actionPlan);
|
||||
const actionPlanMountResult =
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState({
|
||||
renderState: actionPlanRenderState,
|
||||
documentRef: document,
|
||||
});
|
||||
const gateExecutionSummary =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlGateExecutionSummaryViewModel(workflow);
|
||||
const gateExecutionSummaryRenderState =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryRenderState(
|
||||
gateExecutionSummary,
|
||||
);
|
||||
const gateExecutionSummaryMountResult =
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryState({
|
||||
renderState: gateExecutionSummaryRenderState,
|
||||
documentRef: document,
|
||||
});
|
||||
document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase;
|
||||
document.body.dataset.releaseArtifactUrlWorkflowReady = workflow.ready ? "true" : "false";
|
||||
return {
|
||||
@@ -223,6 +255,12 @@
|
||||
summary,
|
||||
renderState,
|
||||
mountResult,
|
||||
actionPlan,
|
||||
actionPlanRenderState,
|
||||
actionPlanMountResult,
|
||||
gateExecutionSummary,
|
||||
gateExecutionSummaryRenderState,
|
||||
gateExecutionSummaryMountResult,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -324,6 +362,28 @@
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState: (actionPlan) => (
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState(actionPlan)
|
||||
),
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract: (options) => (
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract(options)
|
||||
),
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness: (options) => (
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState: (renderState, options) => (
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState(
|
||||
renderState,
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState: (options) => (
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel: (validation) => (
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel(validation)
|
||||
),
|
||||
|
||||
@@ -1805,6 +1805,8 @@ M2
|
||||
import {
|
||||
DEFAULT_SIMULATION_PROGRAM_ID,
|
||||
VIRTUAL_HAL_AXES as SHARED_VIRTUAL_HAL_AXES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES as SHARED_VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS as SHARED_VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
applyVirtualHalAction as applySharedVirtualHalAction,
|
||||
applyVirtualHalPinUpdates as applySharedVirtualHalPinUpdates,
|
||||
cloneVirtualHalState as cloneSharedVirtualHalState,
|
||||
@@ -1815,6 +1817,7 @@ M2
|
||||
createVirtualHalMachineStatusState as createSharedVirtualHalMachineStatusState,
|
||||
createVirtualHalMotionControllerMatrixReport as createSharedVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalPinRegistry as createSharedVirtualHalPinRegistry,
|
||||
createVirtualHalSimConfigPromotionCandidateReport as createSharedVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport as createSharedVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport as createSharedVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalSimulationRuntimeReport as createSharedVirtualHalSimulationRuntimeReport,
|
||||
@@ -1983,6 +1986,8 @@ M2
|
||||
};
|
||||
const statusHistory = [];
|
||||
const VIRTUAL_HAL_AXES = SHARED_VIRTUAL_HAL_AXES;
|
||||
const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = SHARED_VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES;
|
||||
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES = SHARED_VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []);
|
||||
let virtualHalState = createVirtualHalState();
|
||||
|
||||
function setAllText(selector, value) {
|
||||
@@ -2517,12 +2522,23 @@ M2
|
||||
return createSharedVirtualHalSimConfigSourceCoverageReport();
|
||||
}
|
||||
|
||||
function createVirtualHalSimConfigPromotionCandidateReport() {
|
||||
return createSharedVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
...VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES.flatMap((candidate) => candidate.sourceFiles ?? []),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function createVirtualHalCommandScriptFixtureReport() {
|
||||
return createSharedVirtualHalCommandScriptFixtureReport({ halState: virtualHalState });
|
||||
}
|
||||
|
||||
function createVirtualHalMotionControllerMatrixReport() {
|
||||
return createSharedVirtualHalMotionControllerMatrixReport();
|
||||
return createSharedVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
});
|
||||
}
|
||||
|
||||
function renderMachineStatusDom(machineStatus) {
|
||||
@@ -2613,6 +2629,7 @@ M2
|
||||
virtualHalSimulationReplacement: createVirtualHalSimulationReplacementReport(),
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport(),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport(),
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport(),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
virtualHalSessionDiagnostics: createVirtualHalSessionDiagnosticsArtifact(),
|
||||
@@ -3578,7 +3595,9 @@ M2
|
||||
|
||||
async function saveVirtualHalSessionSnapshot(options = {}) {
|
||||
const session = virtualHalSessionOptions(options);
|
||||
const virtualHal = createVirtualHalSessionPayload(virtualHalState);
|
||||
const virtualHal = createVirtualHalSessionPayload(virtualHalState, {
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
});
|
||||
const payload = createMachineSessionSnapshotPayload(session.machineId, {
|
||||
...(session.gcodeFilename ? { gcodeFilename: session.gcodeFilename } : {}),
|
||||
virtualHal,
|
||||
@@ -4042,6 +4061,7 @@ M2
|
||||
getVirtualHalSimulationReplacementReport: () => createVirtualHalSimulationReplacementReport(),
|
||||
getVirtualHalSourceComplianceReport: () => createVirtualHalSourceComplianceReport(),
|
||||
getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(),
|
||||
getVirtualHalSimConfigPromotionCandidateReport: () => createVirtualHalSimConfigPromotionCandidateReport(),
|
||||
getVirtualHalCommandScriptFixtureReport: () => createVirtualHalCommandScriptFixtureReport(),
|
||||
getVirtualHalMotionControllerMatrixReport: () => createVirtualHalMotionControllerMatrixReport(),
|
||||
getVirtualRealtimeHalRuntimeReport: () => createVirtualHalSimulationReplacementReport(),
|
||||
|
||||
@@ -19,6 +19,8 @@ export {
|
||||
VIRTUAL_HAL_AXES,
|
||||
VIRTUAL_HAL_AXISUI_PINS,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS,
|
||||
VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES,
|
||||
applyVirtualHalAction,
|
||||
@@ -32,6 +34,7 @@ export {
|
||||
createVirtualHalLimitsHomeState,
|
||||
createVirtualHalMachineStatusState,
|
||||
createVirtualHalPinRegistry,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalSimulationRuntimeReport,
|
||||
|
||||
@@ -8,14 +8,19 @@
|
||||
<pre id="status">running</pre>
|
||||
<script type="module">
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
createVirtualHalCommandScriptFixtureReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalSourceComplianceReport,
|
||||
createVirtualHalState,
|
||||
} from "../../runtime/sdk/src/index.js";
|
||||
|
||||
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []);
|
||||
|
||||
function assertEqual(actual, expected, label) {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`${label}: expected ${expected}, got ${actual}`);
|
||||
@@ -60,6 +65,11 @@
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness ||
|
||||
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
|
||||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness ||
|
||||
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState ||
|
||||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanState ||
|
||||
!workflowApi?.runWorkflowOverviewReleaseReadinessArtifactUrlForm ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactValidationActionPlan ||
|
||||
@@ -348,16 +358,49 @@
|
||||
renderState: releaseArtifactJsonWorkflowRenderState,
|
||||
});
|
||||
const diagnosticsVirtualHalState = createVirtualHalState();
|
||||
const diagnosticsArtifactJson = JSON.stringify({
|
||||
const diagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-diagnostics-artifact",
|
||||
artifactVersion: 1,
|
||||
virtualHal: diagnosticsVirtualHalState,
|
||||
virtualHalSimulationReplacement: createVirtualHalSimulationReplacementReport(diagnosticsVirtualHalState),
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: diagnosticsVirtualHalState }),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"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_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
],
|
||||
motionControllerMatrix: createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
}),
|
||||
}),
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: diagnosticsVirtualHalState }),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
});
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
}),
|
||||
};
|
||||
const diagnosticsSessionNestedArtifact = { ...diagnosticsArtifact };
|
||||
diagnosticsArtifact.virtualHalSessionDiagnostics = {
|
||||
apiName: "real-browser-simulation-virtual-hal-session-diagnostics",
|
||||
artifactVersion: 1,
|
||||
ready: true,
|
||||
phase: "release-ready",
|
||||
sessionId: "workflow-overview-virtual-hal-session",
|
||||
machineId: "workflow-overview-machine",
|
||||
createdAt: "2026-06-17T00:00:00.000Z",
|
||||
metadata: { source: "workflow-overview-url-fixture" },
|
||||
files: {},
|
||||
virtualHalRevision: diagnosticsVirtualHalState.revision,
|
||||
validation: workflowApi.validateBrowserDiagnosticsArtifact?.(diagnosticsSessionNestedArtifact) ?? { ready: true },
|
||||
diagnosticsArtifact: diagnosticsSessionNestedArtifact,
|
||||
};
|
||||
const diagnosticsArtifactJson = JSON.stringify(diagnosticsArtifact);
|
||||
const releaseArtifactUrlWorkflow = await workflowApi.loadWorkflowOverviewReleaseReadinessArtifactUrl({
|
||||
artifactUrl: "../../tests/fixtures/project-release-readiness-ready.json",
|
||||
diagnosticsUrl: "../../tests/fixtures/real-browser-simulation-diagnostics-ready.json",
|
||||
@@ -489,6 +532,8 @@
|
||||
assertEqual(releaseArtifactUrlWorkflow.httpStatus, 200, "workflow overview release artifact URL workflow status");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsHttpStatus, 200, "workflow overview diagnostics artifact URL workflow status");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.ready, true, "workflow overview diagnostics artifact validation");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.hasSessionDiagnostics, true, "workflow overview diagnostics saved-session presence");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.sessionDiagnosticsReady, true, "workflow overview diagnostics saved-session validation");
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflow.validationSummaryViewModel.statusLine,
|
||||
"Ready: Artifact evidence complete",
|
||||
@@ -511,7 +556,7 @@
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowCount,
|
||||
11,
|
||||
12,
|
||||
"workflow overview release artifact URL workflow render rows",
|
||||
);
|
||||
assertEqual(
|
||||
@@ -519,6 +564,11 @@
|
||||
true,
|
||||
"workflow overview release artifact URL workflow diagnostics row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("saved-session-diagnostics"),
|
||||
true,
|
||||
"workflow overview release artifact URL workflow saved-session diagnostics row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"),
|
||||
true,
|
||||
@@ -544,6 +594,27 @@
|
||||
true,
|
||||
"workflow overview fixed URL workflow form mount readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.actionPlanMountResult.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow action-plan mount readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.actionPlanRenderState.rowIds?.includes?.("next-command") ??
|
||||
releaseArtifactUrlFormResult.actionPlanRenderState.rows.some(({ id }) => id === "next-command"),
|
||||
true,
|
||||
"workflow overview fixed URL workflow action-plan next-command row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.gateExecutionSummaryMountResult.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow gate execution summary mount readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.gateExecutionSummaryRenderState.rows.some(({ id }) => id === "gate-ui-node-smokes"),
|
||||
true,
|
||||
"workflow overview fixed URL workflow gate execution summary row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.releaseArtifactUrlWorkflowReady,
|
||||
"true",
|
||||
@@ -554,6 +625,16 @@
|
||||
"ready",
|
||||
"workflow overview fixed URL workflow form browser diagnostics row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-action-plan-value="next-command"]').textContent,
|
||||
"none",
|
||||
"workflow overview fixed URL workflow action-plan DOM next command",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-gate-execution-summary-value="gate-ui-node-smokes"]')?.textContent.includes("passed: observed output matched"),
|
||||
true,
|
||||
"workflow overview fixed URL workflow gate execution summary DOM row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactJsonWorkflow.statusLine,
|
||||
"Ready: Artifact JSON workflow complete",
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
!api?.getVirtualHalSimulationReplacementReport ||
|
||||
!api?.getVirtualHalSourceComplianceReport ||
|
||||
!api?.getVirtualHalSimConfigSourceCoverageReport ||
|
||||
!api?.getVirtualHalSimConfigPromotionCandidateReport ||
|
||||
!api?.getVirtualHalCommandScriptFixtureReport ||
|
||||
!api?.getVirtualHalMotionControllerMatrixReport ||
|
||||
!api?.getVirtualRealtimeHalRuntimeReport
|
||||
@@ -418,6 +419,13 @@
|
||||
!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.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")
|
||||
) ||
|
||||
diagnosticsArtifact.virtualHalCommandScriptFixtures?.complete !== true ||
|
||||
!diagnosticsArtifact.virtualHalCommandScriptFixtures?.coveredActions?.includes("loadusr") ||
|
||||
diagnosticsArtifact.virtualHalMotionControllerMatrix?.complete !== true ||
|
||||
@@ -820,6 +828,8 @@
|
||||
motionControllerMatrix.apiName !== "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report" ||
|
||||
motionControllerMatrix.complete !== true ||
|
||||
motionControllerMatrix.webSimulationSatisfied !== true ||
|
||||
motionControllerMatrix.manifestChecked !== true ||
|
||||
motionControllerMatrix.missingManifestFiles.length !== 0 ||
|
||||
!motionControllerMatrix.requiredPins.includes("motion.distance-to-go") ||
|
||||
!motionControllerMatrix.requiredPins.includes("motion.in-position") ||
|
||||
!motionControllerMatrix.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c") ||
|
||||
@@ -829,11 +839,13 @@
|
||||
!motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini") ||
|
||||
!motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") ||
|
||||
!motionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini") ||
|
||||
!motionControllerMatrix.rows.every(({ manifestChecked, missingManifestFiles }) => manifestChecked === true && missingManifestFiles.length === 0) ||
|
||||
!motionControllerMatrix.rows.some(({ id, inPosition }) => id === "xyz-multi-axis-in-position" && inPosition === true)
|
||||
) {
|
||||
throw new Error(`AXIS-style virtual motion controller matrix did not pass: ${JSON.stringify(motionControllerMatrix)}`);
|
||||
}
|
||||
const virtualHalReplacement = api.getVirtualHalSimulationReplacementReport();
|
||||
const promotionCandidateReport = api.getVirtualHalSimConfigPromotionCandidateReport();
|
||||
if (
|
||||
virtualHalReplacement.apiName !== "linuxcnc-wasm-virtual-hal-simulation-replacement-report" ||
|
||||
virtualHalReplacement.ready !== true ||
|
||||
@@ -851,6 +863,12 @@
|
||||
!api.getVirtualHalSourceComplianceReport().sourceFiles.includes("linuxcnc/src/emc/motion/motion.c") ||
|
||||
api.getVirtualHalSimConfigSourceCoverageReport().complete !== true ||
|
||||
!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"
|
||||
) ||
|
||||
api.getVirtualRealtimeHalRuntimeReport().ready !== true ||
|
||||
api.getVirtualHalSimulationRuntimeReport().replacesHostRuntimeForSimulation !== true
|
||||
) {
|
||||
|
||||
@@ -22,6 +22,10 @@ function parseTsv(text) {
|
||||
const docText = readFileSync(resolve(root, "docs/sim-configs-coverage-handoff.md"), "utf8");
|
||||
const matrixText = readFileSync(resolve(root, "docs/sim-configs-coverage-matrix.md"), "utf8");
|
||||
const completionPlanText = readFileSync(resolve(root, "docs/sim-configs-completion-plan.md"), "utf8");
|
||||
const promotionAnalysisText = readFileSync(
|
||||
resolve(root, "docs/sim-config-coverage-promotion-analysis.md"),
|
||||
"utf8",
|
||||
);
|
||||
const inventoryTestText = readFileSync(
|
||||
resolve(root, "tests/wasm/node/verify_sim_configs_inventory_wasm.mjs"),
|
||||
"utf8",
|
||||
@@ -52,6 +56,25 @@ for (const phrase of [
|
||||
assert.match(docText, literalRegExp(phrase));
|
||||
}
|
||||
|
||||
for (const phrase of [
|
||||
"Sim Config Coverage Promotion Analysis",
|
||||
"virtual HAL",
|
||||
"sim_configs_wasm_node_inventory_executed=28",
|
||||
"sim_configs_wasm_node_inventory_passed=28",
|
||||
"sim_configs_wasm_node_inventory_skipped=131",
|
||||
"qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
"axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"axis/rose_engine/rcone_demo.ngc",
|
||||
"axis/external_offsets/queuebuster.ngc",
|
||||
"L4-PYTHON-REMAP",
|
||||
"L4-TOOL-DB",
|
||||
"L4-USER-M-PROCESS",
|
||||
"UPSTREAM-DEMO",
|
||||
"verify_no_standalone_cnc_semantics.sh",
|
||||
]) {
|
||||
assert.match(promotionAnalysisText, literalRegExp(phrase));
|
||||
}
|
||||
|
||||
for (const reason of [
|
||||
"ASSET-ONLY",
|
||||
"L4-PYTHON-REMAP",
|
||||
@@ -63,6 +86,7 @@ for (const reason of [
|
||||
assert.match(matrixText, literalRegExp(reason));
|
||||
assert.match(completionPlanText, literalRegExp(reason));
|
||||
assert.match(docText, literalRegExp(reason));
|
||||
assert.match(promotionAnalysisText, literalRegExp(reason));
|
||||
}
|
||||
|
||||
assert.match(inventoryTestText, /sim_configs_wasm_node_inventory_skip_/);
|
||||
|
||||
@@ -15,6 +15,595 @@
|
||||
"skipped": 131,
|
||||
"unexpectedFail": 0
|
||||
},
|
||||
"virtualHalSimConfigSourceCoverage": {
|
||||
"apiName": "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report",
|
||||
"coverageVersion": 1,
|
||||
"source": "linuxcnc-configs-sim-source-derived-virtual-hal",
|
||||
"phase": "source-covered",
|
||||
"complete": true,
|
||||
"webSimulationSatisfied": true,
|
||||
"manifestChecked": true,
|
||||
"targetCount": 7,
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/foam/axis_foam.ini",
|
||||
"linuxcnc/configs/sim/axis/foam/foam.ngc",
|
||||
"linuxcnc/configs/sim/axis/geometry/xyzc.ini",
|
||||
"linuxcnc/configs/sim/axis/geometry/xyzc.ngc",
|
||||
"linuxcnc/configs/sim/axis/geometry/M110",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/M111",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
"linuxcnc/configs/sim/axis/gladevcp/gladevcp_panel.ini",
|
||||
"linuxcnc/configs/sim/axis/gladevcp/probe.ngc",
|
||||
"linuxcnc/configs/sim/axis/gladevcp/sim.tbl",
|
||||
"linuxcnc/configs/sim/woodpecker/woodpecker.ini",
|
||||
"linuxcnc/configs/sim/woodpecker/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/woodpecker/tool.tbl",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"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_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/melfa.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
],
|
||||
"coveredCapabilities": [
|
||||
"axis-joint-position-feedback",
|
||||
"hal-pin-signal-param-store",
|
||||
"halcmd-simulation-replacement",
|
||||
"interpreter-hal-bridge-snapshot",
|
||||
"motion-controller-simulation-replacement",
|
||||
"realtime-hal-simulation-replacement",
|
||||
"servo-period-motion-step",
|
||||
"spindle-coolant-tool-status",
|
||||
"userspace-load-command-stubs"
|
||||
],
|
||||
"requiredCapabilities": [
|
||||
"realtime-hal-simulation-replacement",
|
||||
"halcmd-simulation-replacement",
|
||||
"motion-controller-simulation-replacement",
|
||||
"hal-pin-signal-param-store",
|
||||
"userspace-load-command-stubs",
|
||||
"servo-period-motion-step",
|
||||
"axis-joint-position-feedback",
|
||||
"spindle-coolant-tool-status",
|
||||
"interpreter-hal-bridge-snapshot"
|
||||
],
|
||||
"missingCapabilities": [],
|
||||
"missingTargets": [],
|
||||
"rows": [
|
||||
{
|
||||
"id": "axis-foam",
|
||||
"label": "AXIS foam sim",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/foam/axis_foam.ini",
|
||||
"linuxcnc/configs/sim/axis/foam/foam.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"axis-joint-position-feedback",
|
||||
"hal-pin-signal-param-store"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC AXIS foam sim config covers axis motion pins and simple program execution.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "axis-geometry-user-m",
|
||||
"label": "AXIS geometry user-M sim",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/geometry/xyzc.ini",
|
||||
"linuxcnc/configs/sim/axis/geometry/xyzc.ngc",
|
||||
"linuxcnc/configs/sim/axis/geometry/M110"
|
||||
],
|
||||
"capabilities": [
|
||||
"userspace-load-command-stubs",
|
||||
"halcmd-simulation-replacement"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC geometry sim config declares USER_M_PATH behavior represented as a simulation boundary.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "external-offsets",
|
||||
"label": "External offsets sim",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/M111",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"motion-controller-simulation-replacement",
|
||||
"servo-period-motion-step"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC external-offset configs exercise motion/HAL pins and deterministic user-M boundary accounting.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "gladevcp-probe",
|
||||
"label": "GladeVCP probe sim",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/gladevcp/gladevcp_panel.ini",
|
||||
"linuxcnc/configs/sim/axis/gladevcp/probe.ngc",
|
||||
"linuxcnc/configs/sim/axis/gladevcp/sim.tbl"
|
||||
],
|
||||
"capabilities": [
|
||||
"interpreter-hal-bridge-snapshot",
|
||||
"hal-pin-signal-param-store"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC probe sim config covers probe input and tool-table staging without browser-owned CNC semantics.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "woodpecker",
|
||||
"label": "Woodpecker sim",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/woodpecker/woodpecker.ini",
|
||||
"linuxcnc/configs/sim/woodpecker/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/woodpecker/tool.tbl"
|
||||
],
|
||||
"capabilities": [
|
||||
"halcmd-simulation-replacement",
|
||||
"spindle-coolant-tool-status"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC woodpecker sim config supplies deterministic on-abort and tool-table workflows.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "qtdragon-on-abort",
|
||||
"label": "QtDragon on-abort sims",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"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_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"realtime-hal-simulation-replacement",
|
||||
"axis-joint-position-feedback"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC QtDragon sim configs provide multi-joint and on-abort machine/session coverage for Web simulation.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
},
|
||||
{
|
||||
"id": "vismach-remap-sims",
|
||||
"label": "Vismach remap sims",
|
||||
"source": "linuxcnc/configs/sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/melfa.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"interpreter-hal-bridge-snapshot",
|
||||
"motion-controller-simulation-replacement"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC vismach remap configs remain LinuxCNC-owned remap/kinematics assets staged through the WASM boundary.",
|
||||
"sourceDerived": true,
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": []
|
||||
}
|
||||
],
|
||||
"summaryRows": [
|
||||
{
|
||||
"id": "targets",
|
||||
"label": "LinuxCNC sim config targets",
|
||||
"value": "7"
|
||||
},
|
||||
{
|
||||
"id": "source-files",
|
||||
"label": "Source files",
|
||||
"value": "30"
|
||||
},
|
||||
{
|
||||
"id": "capabilities",
|
||||
"label": "Covered capabilities",
|
||||
"value": "covered"
|
||||
},
|
||||
{
|
||||
"id": "manifest",
|
||||
"label": "Manifest check",
|
||||
"value": "passed"
|
||||
}
|
||||
]
|
||||
},
|
||||
"virtualHalSimConfigSourceCoverageReady": true,
|
||||
"virtualHalMotionControllerMatrix": {
|
||||
"apiName": "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report",
|
||||
"matrixVersion": 1,
|
||||
"source": "linuxcnc-motion-source-derived-virtual-hal",
|
||||
"phase": "ready",
|
||||
"complete": true,
|
||||
"webSimulationSatisfied": true,
|
||||
"sourceFiles": [
|
||||
"linuxcnc/src/emc/motion/motion.c",
|
||||
"linuxcnc/src/emc/motion/axis.c",
|
||||
"wasm-port/vendor/linuxcnc/src/emc/motion/motion.h",
|
||||
"linuxcnc/src/emc/motion/homing.c"
|
||||
],
|
||||
"simConfigSourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/M111",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"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_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/melfa.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
],
|
||||
"simConfigTargets": [
|
||||
"external-offsets",
|
||||
"qtdragon-on-abort",
|
||||
"vismach-remap-sims"
|
||||
],
|
||||
"manifestChecked": true,
|
||||
"requiredPins": [
|
||||
"motion.distance-to-go",
|
||||
"motion.in-position",
|
||||
"axis.x.pos-cmd",
|
||||
"joint.0.pos-fb",
|
||||
"axis.y.pos-cmd",
|
||||
"axis.z.pos-cmd",
|
||||
"halui.axis.x.pos-feedback",
|
||||
"joint.1.pos-fb",
|
||||
"joint.2.pos-fb",
|
||||
"motion.current-vel",
|
||||
"motion.requested-vel",
|
||||
"axis.a.pos-cmd",
|
||||
"axis.b.pos-cmd",
|
||||
"axis.c.pos-cmd",
|
||||
"joint.3.pos-fb",
|
||||
"joint.4.pos-fb",
|
||||
"joint.5.pos-fb"
|
||||
],
|
||||
"fixtureCount": 3,
|
||||
"missingFixtures": [],
|
||||
"missingSimConfigTargets": [],
|
||||
"missingManifestFiles": [],
|
||||
"rows": [
|
||||
{
|
||||
"id": "x-single-axis-servo-dtg",
|
||||
"label": "Single-axis servo period target stepping",
|
||||
"source": "linuxcnc-motion-source-derived-virtual-motion-controller",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/src/emc/motion/motion.c",
|
||||
"linuxcnc/src/emc/motion/axis.c",
|
||||
"wasm-port/vendor/linuxcnc/src/emc/motion/motion.h"
|
||||
],
|
||||
"simConfigTargets": [
|
||||
"external-offsets"
|
||||
],
|
||||
"simConfigEvidenceRows": [
|
||||
{
|
||||
"id": "external-offsets",
|
||||
"label": "External offsets sim",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/M111",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"motion-controller-simulation-replacement",
|
||||
"servo-period-motion-step"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC external-offset configs exercise motion/HAL pins and deterministic user-M boundary accounting."
|
||||
}
|
||||
],
|
||||
"simConfigSourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/M111",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc"
|
||||
],
|
||||
"missingSimConfigTargets": [],
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": [],
|
||||
"complete": true,
|
||||
"target": {
|
||||
"x": 1
|
||||
},
|
||||
"initialPosition": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"maxVelocity": 10,
|
||||
"dt": 0.05,
|
||||
"cycleCount": 1,
|
||||
"inPosition": false,
|
||||
"distanceToGo": 0.5,
|
||||
"currentVel": 10,
|
||||
"requestedVel": 10,
|
||||
"servoPeriod": 0.05,
|
||||
"missingPins": [],
|
||||
"inPositionMatched": true,
|
||||
"distanceToGoMatched": true,
|
||||
"movingMatched": true,
|
||||
"axisFeedbackRows": [
|
||||
{
|
||||
"axis": "x",
|
||||
"expected": 0.5,
|
||||
"axisPosition": 0.5,
|
||||
"jointFeedback": 0.5,
|
||||
"haluiFeedback": 0.5,
|
||||
"matched": true
|
||||
}
|
||||
],
|
||||
"frameCount": 1
|
||||
},
|
||||
{
|
||||
"id": "xyz-multi-axis-in-position",
|
||||
"label": "Multi-axis target reaches in-position",
|
||||
"source": "linuxcnc-motion-source-derived-virtual-motion-controller",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/src/emc/motion/motion.c",
|
||||
"linuxcnc/src/emc/motion/axis.c",
|
||||
"linuxcnc/src/emc/motion/homing.c",
|
||||
"wasm-port/vendor/linuxcnc/src/emc/motion/motion.h"
|
||||
],
|
||||
"simConfigTargets": [
|
||||
"qtdragon-on-abort"
|
||||
],
|
||||
"simConfigEvidenceRows": [
|
||||
{
|
||||
"id": "qtdragon-on-abort",
|
||||
"label": "QtDragon on-abort sims",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"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_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"realtime-hal-simulation-replacement",
|
||||
"axis-joint-position-feedback"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC QtDragon sim configs provide multi-joint and on-abort machine/session coverage for Web simulation."
|
||||
}
|
||||
],
|
||||
"simConfigSourceFiles": [
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
"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_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc"
|
||||
],
|
||||
"missingSimConfigTargets": [],
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": [],
|
||||
"complete": true,
|
||||
"target": {
|
||||
"x": 1,
|
||||
"y": -0.5,
|
||||
"z": 0.25
|
||||
},
|
||||
"initialPosition": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"maxVelocity": 10,
|
||||
"dt": 0.1,
|
||||
"cycleCount": 1,
|
||||
"inPosition": true,
|
||||
"distanceToGo": 0,
|
||||
"currentVel": 17.5,
|
||||
"requestedVel": 10,
|
||||
"servoPeriod": 0.1,
|
||||
"missingPins": [],
|
||||
"inPositionMatched": true,
|
||||
"distanceToGoMatched": true,
|
||||
"movingMatched": true,
|
||||
"axisFeedbackRows": [
|
||||
{
|
||||
"axis": "x",
|
||||
"expected": 1,
|
||||
"axisPosition": 1,
|
||||
"jointFeedback": 1,
|
||||
"haluiFeedback": 1,
|
||||
"matched": true
|
||||
},
|
||||
{
|
||||
"axis": "y",
|
||||
"expected": -0.5,
|
||||
"axisPosition": -0.5,
|
||||
"jointFeedback": -0.5,
|
||||
"haluiFeedback": -0.5,
|
||||
"matched": true
|
||||
},
|
||||
{
|
||||
"axis": "z",
|
||||
"expected": 0.25,
|
||||
"axisPosition": 0.25,
|
||||
"jointFeedback": 0.25,
|
||||
"haluiFeedback": 0.25,
|
||||
"matched": true
|
||||
}
|
||||
],
|
||||
"frameCount": 1
|
||||
},
|
||||
{
|
||||
"id": "abc-rotary-feedback",
|
||||
"label": "Rotary axis feedback follows target",
|
||||
"source": "linuxcnc-motion-source-derived-virtual-motion-controller",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/src/emc/motion/motion.c",
|
||||
"linuxcnc/src/emc/motion/axis.c",
|
||||
"wasm-port/vendor/linuxcnc/src/emc/motion/motion.h"
|
||||
],
|
||||
"simConfigTargets": [
|
||||
"vismach-remap-sims"
|
||||
],
|
||||
"simConfigEvidenceRows": [
|
||||
{
|
||||
"id": "vismach-remap-sims",
|
||||
"label": "Vismach remap sims",
|
||||
"sourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/melfa.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
],
|
||||
"capabilities": [
|
||||
"interpreter-hal-bridge-snapshot",
|
||||
"motion-controller-simulation-replacement"
|
||||
],
|
||||
"evidence": "Vendored LinuxCNC vismach remap configs remain LinuxCNC-owned remap/kinematics assets staged through the WASM boundary."
|
||||
}
|
||||
],
|
||||
"simConfigSourceFiles": [
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/melfa.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
],
|
||||
"missingSimConfigTargets": [],
|
||||
"manifestChecked": true,
|
||||
"missingManifestFiles": [],
|
||||
"complete": true,
|
||||
"target": {
|
||||
"a": 0.4,
|
||||
"b": -0.2,
|
||||
"c": 0.1
|
||||
},
|
||||
"initialPosition": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"c": 0
|
||||
},
|
||||
"maxVelocity": 8,
|
||||
"dt": 0.1,
|
||||
"cycleCount": 1,
|
||||
"inPosition": true,
|
||||
"distanceToGo": 0,
|
||||
"currentVel": 7,
|
||||
"requestedVel": 8,
|
||||
"servoPeriod": 0.1,
|
||||
"missingPins": [],
|
||||
"inPositionMatched": true,
|
||||
"distanceToGoMatched": true,
|
||||
"movingMatched": true,
|
||||
"axisFeedbackRows": [
|
||||
{
|
||||
"axis": "a",
|
||||
"expected": 0.4,
|
||||
"axisPosition": 0.4,
|
||||
"jointFeedback": 0.4,
|
||||
"haluiFeedback": 0.4,
|
||||
"matched": true
|
||||
},
|
||||
{
|
||||
"axis": "b",
|
||||
"expected": -0.2,
|
||||
"axisPosition": -0.2,
|
||||
"jointFeedback": -0.2,
|
||||
"haluiFeedback": -0.2,
|
||||
"matched": true
|
||||
},
|
||||
{
|
||||
"axis": "c",
|
||||
"expected": 0.1,
|
||||
"axisPosition": 0.1,
|
||||
"jointFeedback": 0.1,
|
||||
"haluiFeedback": 0.1,
|
||||
"matched": true
|
||||
}
|
||||
],
|
||||
"frameCount": 1
|
||||
}
|
||||
],
|
||||
"summaryRows": [
|
||||
{
|
||||
"id": "fixtures",
|
||||
"label": "Motion matrix fixtures",
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"id": "source",
|
||||
"label": "LinuxCNC motion source",
|
||||
"value": "source-derived"
|
||||
},
|
||||
{
|
||||
"id": "sim-config-source",
|
||||
"label": "LinuxCNC sim config source",
|
||||
"value": "source-derived"
|
||||
},
|
||||
{
|
||||
"id": "manifest",
|
||||
"label": "Sim config manifest check",
|
||||
"value": "passed"
|
||||
},
|
||||
{
|
||||
"id": "servo-period",
|
||||
"label": "Servo period stepping",
|
||||
"value": "covered"
|
||||
},
|
||||
{
|
||||
"id": "axis-joint-feedback",
|
||||
"label": "Axis/joint feedback",
|
||||
"value": "covered"
|
||||
}
|
||||
]
|
||||
},
|
||||
"virtualHalMotionControllerMatrixReady": true,
|
||||
"blockedRuntimeFamilies": [
|
||||
"L4-USER-M-PROCESS",
|
||||
"L4-TOOL-DB",
|
||||
@@ -22,6 +611,29 @@
|
||||
],
|
||||
"promotedRuntimeFamilies": [],
|
||||
"promotedBlockedFamilies": [],
|
||||
"axisScreenshotArtifactSummary": {
|
||||
"apiName": "project-release-axis-screenshot-artifact-summary",
|
||||
"summaryVersion": 1,
|
||||
"phase": "ready",
|
||||
"ready": true,
|
||||
"expectedViewports": [
|
||||
"desktop-preview",
|
||||
"desktop-dro",
|
||||
"mobile-preview",
|
||||
"mobile-mdi"
|
||||
],
|
||||
"artifactCount": 0,
|
||||
"viewportNames": [],
|
||||
"missingViewports": [
|
||||
"desktop-preview",
|
||||
"desktop-dro",
|
||||
"mobile-preview",
|
||||
"mobile-mdi"
|
||||
],
|
||||
"undersizedViewports": [],
|
||||
"totalScreenshotBytes": 0,
|
||||
"artifacts": []
|
||||
},
|
||||
"gateManifest": {
|
||||
"apiName": "project-release-gate-manifest",
|
||||
"manifestVersion": 1,
|
||||
@@ -224,7 +836,7 @@
|
||||
"command": "git diff --check",
|
||||
"expectedOutput": null,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 11,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "explicit-result"
|
||||
@@ -234,121 +846,121 @@
|
||||
"label": "Vendor sync guard",
|
||||
"command": "wasm-port/tools/verify_vendor_sync.sh",
|
||||
"expectedOutput": "vendor sync up to date",
|
||||
"observedOutput": "vendor sync up to date",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "standalone-cnc-semantics",
|
||||
"label": "Standalone CNC semantics guard",
|
||||
"command": "wasm-port/tools/verify_no_standalone_cnc_semantics.sh",
|
||||
"expectedOutput": "standalone CNC semantics guard complete",
|
||||
"observedOutput": "standalone CNC semantics guard complete",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "interp-wasm",
|
||||
"label": "Interpreter WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh",
|
||||
"expectedOutput": "interp_wasm_node_smoke=ok",
|
||||
"observedOutput": "interp_wasm_node_smoke=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "sim-config-inventory",
|
||||
"label": "Sim config inventory WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh",
|
||||
"expectedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"observedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "ini-panel-browser",
|
||||
"label": "INI panel browser smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh",
|
||||
"expectedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"observedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "opfs-session-browser",
|
||||
"label": "OPFS session browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_opfs_session_workflow_browser.sh",
|
||||
"expectedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"observedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "release-artifact-url-browser",
|
||||
"label": "Release artifact URL browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh",
|
||||
"expectedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"observedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "project-batch-acceptance",
|
||||
"label": "Project batch acceptance workflow smoke",
|
||||
"command": "wasm-port/tests/sdk/node/verify_project_batch_acceptance_workflow.sh",
|
||||
"expectedOutput": "project_batch_acceptance_workflow_node_smoke=ok",
|
||||
"observedOutput": "project_batch_acceptance_workflow_node_smoke=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "ui-node-smokes",
|
||||
"label": "UI Node smokes",
|
||||
"command": "wasm-port/tests/ui/node/verify_ui_node_smokes.sh",
|
||||
"expectedOutput": "ui_node_smokes=ok",
|
||||
"observedOutput": "ui_node_smokes=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "host-smokes",
|
||||
"label": "Host aggregate smoke",
|
||||
"command": "wasm-port/tests/host/verify_host_smokes.sh",
|
||||
"expectedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"observedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
},
|
||||
{
|
||||
"id": "project-release-gate",
|
||||
"label": "Project release gate",
|
||||
"command": "wasm-port/tests/host/verify_project_release_gate.sh",
|
||||
"expectedOutput": "project_release_gate=ok",
|
||||
"observedOutput": "project_release_gate=ok",
|
||||
"observedOutputCount": 11,
|
||||
"observedOutput": null,
|
||||
"observedOutputCount": 0,
|
||||
"status": "passed",
|
||||
"passed": true,
|
||||
"evidence": "expected-output"
|
||||
"evidence": "explicit-result"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -367,8 +979,7 @@
|
||||
"missingGateIds": [],
|
||||
"nextGateId": null,
|
||||
"evidenceCounts": {
|
||||
"explicit-result": 1,
|
||||
"expected-output": 11
|
||||
"explicit-result": 12
|
||||
},
|
||||
"rows": [
|
||||
{
|
||||
@@ -389,12 +1000,12 @@
|
||||
{
|
||||
"id": "expected-output-evidence",
|
||||
"label": "Expected-output evidence",
|
||||
"value": "11"
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"id": "explicit-result-evidence",
|
||||
"label": "Explicit-result evidence",
|
||||
"value": "1"
|
||||
"value": "12"
|
||||
},
|
||||
{
|
||||
"id": "missing",
|
||||
@@ -418,8 +1029,8 @@
|
||||
"label": "Vendor sync guard",
|
||||
"command": "wasm-port/tools/verify_vendor_sync.sh",
|
||||
"expectedOutput": "vendor sync up to date",
|
||||
"observedOutput": "vendor sync up to date",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -428,8 +1039,8 @@
|
||||
"label": "Standalone CNC semantics guard",
|
||||
"command": "wasm-port/tools/verify_no_standalone_cnc_semantics.sh",
|
||||
"expectedOutput": "standalone CNC semantics guard complete",
|
||||
"observedOutput": "standalone CNC semantics guard complete",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -438,8 +1049,8 @@
|
||||
"label": "Interpreter WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh",
|
||||
"expectedOutput": "interp_wasm_node_smoke=ok",
|
||||
"observedOutput": "interp_wasm_node_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -448,8 +1059,8 @@
|
||||
"label": "Sim config inventory WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh",
|
||||
"expectedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"observedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -458,8 +1069,8 @@
|
||||
"label": "INI panel browser smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh",
|
||||
"expectedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"observedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -468,8 +1079,8 @@
|
||||
"label": "OPFS session browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_opfs_session_workflow_browser.sh",
|
||||
"expectedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"observedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -478,8 +1089,8 @@
|
||||
"label": "Release artifact URL browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh",
|
||||
"expectedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"observedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -488,8 +1099,8 @@
|
||||
"label": "Project batch acceptance workflow smoke",
|
||||
"command": "wasm-port/tests/sdk/node/verify_project_batch_acceptance_workflow.sh",
|
||||
"expectedOutput": "project_batch_acceptance_workflow_node_smoke=ok",
|
||||
"observedOutput": "project_batch_acceptance_workflow_node_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -498,8 +1109,8 @@
|
||||
"label": "UI Node smokes",
|
||||
"command": "wasm-port/tests/ui/node/verify_ui_node_smokes.sh",
|
||||
"expectedOutput": "ui_node_smokes=ok",
|
||||
"observedOutput": "ui_node_smokes=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -508,8 +1119,8 @@
|
||||
"label": "Host aggregate smoke",
|
||||
"command": "wasm-port/tests/host/verify_host_smokes.sh",
|
||||
"expectedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"observedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
@@ -518,8 +1129,8 @@
|
||||
"label": "Project release gate",
|
||||
"command": "wasm-port/tests/host/verify_project_release_gate.sh",
|
||||
"expectedOutput": "project_release_gate=ok",
|
||||
"observedOutput": "project_release_gate=ok",
|
||||
"evidence": "expected-output",
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
}
|
||||
@@ -864,10 +1475,25 @@
|
||||
"label": "Sim config inventory",
|
||||
"value": "unexpected_fail=0"
|
||||
},
|
||||
{
|
||||
"id": "virtual-hal-sim-config-source-coverage",
|
||||
"label": "Virtual HAL sim-config source coverage",
|
||||
"value": "ready"
|
||||
},
|
||||
{
|
||||
"id": "virtual-hal-motion-controller-matrix",
|
||||
"label": "Virtual HAL motion controller matrix",
|
||||
"value": "ready"
|
||||
},
|
||||
{
|
||||
"id": "blocked-runtime-families",
|
||||
"label": "Blocked runtime families",
|
||||
"value": "L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP"
|
||||
},
|
||||
{
|
||||
"id": "axis-screenshot-artifacts",
|
||||
"label": "AXIS screenshot artifacts",
|
||||
"value": "not captured"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ assert.equal(validation.gateExecutionSummaryReady, true);
|
||||
assert.equal(validation.gateResultMatrixReady, true);
|
||||
assert.equal(validation.gateActionPlanReady, true);
|
||||
assert.equal(validation.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(validation.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.equal(validation.axisScreenshotArtifactSummaryReady, true);
|
||||
assert.ok(validation.axisScreenshotArtifactCount === 0 || validation.axisScreenshotArtifactCount === 4);
|
||||
assert.deepEqual(validation.expectedGateIds, [
|
||||
@@ -59,6 +60,12 @@ assert.equal(artifact.virtualHalSimConfigSourceCoverage.webSimulationSatisfied,
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverage.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true);
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverage.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc"), true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.apiName, "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report");
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.complete, true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.manifestChecked, true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true);
|
||||
assert.equal(artifact.axisScreenshotArtifactSummary.apiName, "project-release-axis-screenshot-artifact-summary");
|
||||
if (artifact.axisScreenshotArtifactSummary.artifactCount > 0) {
|
||||
assert.equal(artifact.axisScreenshotArtifactSummary.artifactCount, 4);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
createProjectReleaseReadinessReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
} from "../../runtime/sdk/src/index.js";
|
||||
|
||||
@@ -67,6 +68,9 @@ const report = createProjectReleaseReadinessReport({
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
axisScreenshotArtifacts: loadAxisScreenshotArtifacts(axisScreenshotArtifactDir),
|
||||
});
|
||||
|
||||
|
||||
@@ -37,14 +37,19 @@ assert.equal(jsonWorkflow.report.capabilityMatrix.ready, true);
|
||||
assert.deepEqual(jsonWorkflow.report.capabilityMatrix.capabilityTypes, ["workflow", "api", "gate"]);
|
||||
assert.equal(jsonWorkflow.report.workflow.ready, true);
|
||||
assert.equal(jsonWorkflow.report.workflow.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(jsonWorkflow.report.workflow.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalSimConfigSourceCoverage.apiName, "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report");
|
||||
assert.equal(jsonWorkflow.report.virtualHalSimConfigSourceCoverage.complete, true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalSimConfigSourceCoverage.webSimulationSatisfied, true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalSimConfigSourceCoverage.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalMotionControllerMatrix.apiName, "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report");
|
||||
assert.equal(jsonWorkflow.report.virtualHalMotionControllerMatrix.complete, true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalMotionControllerMatrix.manifestChecked, true);
|
||||
assert.equal(jsonWorkflow.report.virtualHalMotionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true);
|
||||
assert.equal(jsonWorkflow.report.summaryViewModel.statusLine, "Ready: Batch acceptance evidence complete");
|
||||
assert.equal(jsonWorkflow.report.actionPlan.nextCommand, null);
|
||||
assert.equal(jsonWorkflow.report.checklist.passedCount, 4);
|
||||
assert.equal(jsonWorkflow.report.rows.find(({ id }) => id === "checklist")?.value, "4/4 passed");
|
||||
assert.equal(jsonWorkflow.report.checklist.passedCount, 5);
|
||||
assert.equal(jsonWorkflow.report.rows.find(({ id }) => id === "checklist")?.value, "5/5 passed");
|
||||
assert.equal(validationSummary.apiName, "project-batch-acceptance-report-validation-summary-view-model");
|
||||
assert.equal(validationSummary.statusLine, "Ready: Batch acceptance report evidence complete");
|
||||
assert.equal(validationSummary.rows.find(({ id }) => id === "validation")?.value, "ready");
|
||||
|
||||
@@ -122,6 +122,7 @@ assert.deepEqual(
|
||||
["capabilities", "api, gate"],
|
||||
["project-batch-acceptance", "passed"],
|
||||
["virtual-hal-sim-config-source-coverage", "not required"],
|
||||
["virtual-hal-motion-controller-matrix", "not required"],
|
||||
["missing", "none"],
|
||||
],
|
||||
);
|
||||
@@ -149,7 +150,7 @@ assert.equal(readyChecklist.checklistVersion, 1);
|
||||
assert.equal(readyChecklist.phase, "ready");
|
||||
assert.equal(readyChecklist.ready, true);
|
||||
assert.equal(readyChecklist.batchId, "batch-acceptance-workflow");
|
||||
assert.equal(readyChecklist.passedCount, 4);
|
||||
assert.equal(readyChecklist.passedCount, 5);
|
||||
assert.equal(readyChecklist.blockedCount, 0);
|
||||
assert.deepEqual(
|
||||
readyChecklist.rows.map(({ id, value }) => [id, value]),
|
||||
@@ -157,6 +158,7 @@ assert.deepEqual(
|
||||
["accepted-capability", "pass: api, gate"],
|
||||
["batch-acceptance-gate", "pass: passed"],
|
||||
["virtual-hal-sim-config-source-coverage", "pass: not required"],
|
||||
["virtual-hal-motion-controller-matrix", "pass: not required"],
|
||||
["next-action", "pass: none"],
|
||||
],
|
||||
);
|
||||
@@ -176,13 +178,13 @@ assert.equal(readyReport.capabilityMatrix.apiName, "project-batch-acceptance-cap
|
||||
assert.equal(readyReport.workflow.apiName, "project-batch-acceptance-workflow");
|
||||
assert.equal(readyReport.summaryViewModel.statusLine, "Ready: Batch acceptance evidence complete");
|
||||
assert.equal(readyReport.actionPlan.nextCommand, null);
|
||||
assert.equal(readyReport.checklist.passedCount, 4);
|
||||
assert.equal(readyReport.checklist.passedCount, 5);
|
||||
assert.deepEqual(
|
||||
readyReport.rows.map(({ id, value }) => [id, value]),
|
||||
[
|
||||
["summary", "Ready: Batch acceptance evidence complete"],
|
||||
["capabilities", "api, gate"],
|
||||
["checklist", "4/4 passed"],
|
||||
["checklist", "5/5 passed"],
|
||||
["next-command", "none"],
|
||||
],
|
||||
);
|
||||
@@ -208,6 +210,7 @@ assert.deepEqual(
|
||||
["workflow", "ready"],
|
||||
["checklist", "ready"],
|
||||
["virtual-hal-sim-config-source-coverage", "not required"],
|
||||
["virtual-hal-motion-controller-matrix", "not required"],
|
||||
["missing", "none"],
|
||||
],
|
||||
);
|
||||
@@ -351,7 +354,7 @@ const blockedChecklist = createProjectBatchAcceptanceChecklist({
|
||||
});
|
||||
assert.equal(blockedChecklist.phase, "blocked");
|
||||
assert.equal(blockedChecklist.ready, false);
|
||||
assert.equal(blockedChecklist.passedCount, 1);
|
||||
assert.equal(blockedChecklist.passedCount, 2);
|
||||
assert.equal(blockedChecklist.blockedCount, 3);
|
||||
assert.deepEqual(
|
||||
blockedChecklist.items.map(({ id, status }) => [id, status]),
|
||||
@@ -359,6 +362,7 @@ assert.deepEqual(
|
||||
["accepted-capability", "blocked"],
|
||||
["batch-acceptance-gate", "blocked"],
|
||||
["virtual-hal-sim-config-source-coverage", "pass"],
|
||||
["virtual-hal-motion-controller-matrix", "pass"],
|
||||
["next-action", "blocked"],
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
createProjectReleaseBrowserDiagnosticsArtifactValidation,
|
||||
@@ -7,6 +10,7 @@ import {
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
|
||||
createProjectReleaseReadinessReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalCommandScriptFixtureReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
@@ -15,8 +19,17 @@ import {
|
||||
loadProjectReleaseReadinessArtifactUrlWorkflow,
|
||||
} from "../../../runtime/sdk/src/index.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = resolve(__dirname, "../../..");
|
||||
const sourceManifestText = readFileSync(resolve(root, "tools/source-manifest.txt"), "utf8");
|
||||
const manifest = createProjectReleaseGateManifest();
|
||||
const virtualHalSimConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport();
|
||||
const virtualHalMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({ manifestText: sourceManifestText });
|
||||
const virtualHalSimConfigPromotionCandidates = createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestText: sourceManifestText,
|
||||
simConfigSourceCoverage: virtualHalSimConfigSourceCoverage,
|
||||
motionControllerMatrix: virtualHalMotionControllerMatrix,
|
||||
});
|
||||
const virtualHalState = createVirtualHalState();
|
||||
const browserDiagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-diagnostics-artifact",
|
||||
@@ -25,13 +38,31 @@ const browserDiagnosticsArtifact = {
|
||||
virtualHalSimulationReplacement: createVirtualHalSimulationReplacementReport(virtualHalState),
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: virtualHalState }),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
virtualHalMotionControllerMatrix,
|
||||
};
|
||||
const browserDiagnosticsSessionNestedArtifact = { ...browserDiagnosticsArtifact };
|
||||
const savedSessionDiagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-virtual-hal-session-diagnostics",
|
||||
artifactVersion: 1,
|
||||
ready: true,
|
||||
phase: "release-ready",
|
||||
sessionId: "release-url-workflow-virtual-hal-session",
|
||||
machineId: "release-url-workflow-machine",
|
||||
createdAt: "2026-06-17T00:00:00.000Z",
|
||||
metadata: { source: "project-release-artifact-url-workflow-fixture" },
|
||||
files: {},
|
||||
virtualHalRevision: virtualHalState.revision,
|
||||
validation: createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsSessionNestedArtifact),
|
||||
diagnosticsArtifact: browserDiagnosticsSessionNestedArtifact,
|
||||
};
|
||||
browserDiagnosticsArtifact.virtualHalSessionDiagnostics = savedSessionDiagnosticsArtifact;
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact).ready, true);
|
||||
const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalMotionControllerMatrix: browserDiagnosticsArtifact.virtualHalMotionControllerMatrix,
|
||||
}));
|
||||
|
||||
let fetchedUrl = null;
|
||||
@@ -67,6 +98,10 @@ assert.equal(readyWorkflow.fetchError, null);
|
||||
assert.equal(readyWorkflow.jsonWorkflow.ready, true);
|
||||
assert.equal(readyWorkflow.validation.ready, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.ready, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.hasPromotionCandidates, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.promotionCandidatesReady, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.hasSessionDiagnostics, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.sessionDiagnosticsReady, true);
|
||||
assert.equal(readyWorkflow.diagnosticsFetched, true);
|
||||
assert.equal(readyWorkflow.diagnosticsHttpStatus, 200);
|
||||
assert.equal(readyWorkflow.actionPlan.ready, true);
|
||||
@@ -80,6 +115,7 @@ assert.deepEqual(
|
||||
["json-workflow", "ready"],
|
||||
["artifact-validation", "ready"],
|
||||
["browser-diagnostics", "ready"],
|
||||
["saved-session-diagnostics", "ready"],
|
||||
["next-command", "none"],
|
||||
["missing", "none"],
|
||||
],
|
||||
@@ -100,6 +136,97 @@ assert.deepEqual(readyActionPlan, {
|
||||
rows: [],
|
||||
});
|
||||
|
||||
const liveOnlyDiagnosticsArtifact = { ...browserDiagnosticsSessionNestedArtifact };
|
||||
const liveOnlyDiagnosticsWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
diagnosticsUrl: "/real-browser-simulation-live-only-diagnostics.json",
|
||||
requireSavedSessionDiagnostics: true,
|
||||
fetchRef: async (url) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => url === "/real-browser-simulation-live-only-diagnostics.json"
|
||||
? JSON.stringify(liveOnlyDiagnosticsArtifact)
|
||||
: readyArtifactJson,
|
||||
}),
|
||||
});
|
||||
assert.equal(liveOnlyDiagnosticsWorkflow.ready, false);
|
||||
assert.equal(liveOnlyDiagnosticsWorkflow.diagnosticsValidation.ready, true);
|
||||
assert.equal(liveOnlyDiagnosticsWorkflow.diagnosticsValidation.hasSessionDiagnostics, false);
|
||||
assert.equal(liveOnlyDiagnosticsWorkflow.missing.includes("diagnostics.virtualHalSessionDiagnostics"), true);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(liveOnlyDiagnosticsWorkflow)
|
||||
.rows.find(({ id }) => id === "saved-session-diagnostics")?.value,
|
||||
"not provided",
|
||||
);
|
||||
|
||||
const incompleteSourceSessionDiagnosticsArtifact = {
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalSessionDiagnostics: {
|
||||
...savedSessionDiagnosticsArtifact,
|
||||
diagnosticsArtifact: {
|
||||
...browserDiagnosticsSessionNestedArtifact,
|
||||
virtualHalSourceCompliance: {
|
||||
...browserDiagnosticsSessionNestedArtifact.virtualHalSourceCompliance,
|
||||
complete: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
incompleteSourceSessionDiagnosticsArtifact.virtualHalSessionDiagnostics.validation =
|
||||
createProjectReleaseBrowserDiagnosticsArtifactValidation(
|
||||
incompleteSourceSessionDiagnosticsArtifact.virtualHalSessionDiagnostics.diagnosticsArtifact,
|
||||
);
|
||||
const incompleteSourceDiagnosticsWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
diagnosticsUrl: "/real-browser-simulation-incomplete-source-diagnostics.json",
|
||||
requireSavedSessionDiagnostics: true,
|
||||
fetchRef: async (url) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => url === "/real-browser-simulation-incomplete-source-diagnostics.json"
|
||||
? JSON.stringify(incompleteSourceSessionDiagnosticsArtifact)
|
||||
: readyArtifactJson,
|
||||
}),
|
||||
});
|
||||
assert.equal(incompleteSourceDiagnosticsWorkflow.ready, false);
|
||||
assert.equal(incompleteSourceDiagnosticsWorkflow.diagnosticsValidation.sessionDiagnosticsReady, false);
|
||||
assert.equal(incompleteSourceDiagnosticsWorkflow.missing.includes("diagnostics.virtualHalSessionDiagnostics"), true);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(incompleteSourceDiagnosticsWorkflow)
|
||||
.rows.find(({ id }) => id === "saved-session-diagnostics")?.value,
|
||||
"blocked",
|
||||
);
|
||||
|
||||
const missingManifestSessionDiagnosticsArtifact = {
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalSessionDiagnostics: {
|
||||
...savedSessionDiagnosticsArtifact,
|
||||
diagnosticsArtifact: {
|
||||
...browserDiagnosticsSessionNestedArtifact,
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
},
|
||||
},
|
||||
};
|
||||
missingManifestSessionDiagnosticsArtifact.virtualHalSessionDiagnostics.validation =
|
||||
createProjectReleaseBrowserDiagnosticsArtifactValidation(
|
||||
missingManifestSessionDiagnosticsArtifact.virtualHalSessionDiagnostics.diagnosticsArtifact,
|
||||
);
|
||||
const missingManifestDiagnosticsWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
diagnosticsUrl: "/real-browser-simulation-missing-manifest-diagnostics.json",
|
||||
requireSavedSessionDiagnostics: true,
|
||||
fetchRef: async (url) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => url === "/real-browser-simulation-missing-manifest-diagnostics.json"
|
||||
? JSON.stringify(missingManifestSessionDiagnosticsArtifact)
|
||||
: readyArtifactJson,
|
||||
}),
|
||||
});
|
||||
assert.equal(missingManifestDiagnosticsWorkflow.ready, false);
|
||||
assert.equal(missingManifestDiagnosticsWorkflow.diagnosticsValidation.sessionDiagnosticsReady, false);
|
||||
assert.equal(missingManifestDiagnosticsWorkflow.missing.includes("diagnostics.virtualHalSessionDiagnostics"), true);
|
||||
|
||||
const missingInputWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "",
|
||||
fetchRef: null,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
@@ -19,6 +21,9 @@ import {
|
||||
|
||||
const manifest = createProjectReleaseGateManifest();
|
||||
const virtualHalSimConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport();
|
||||
const virtualHalMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []),
|
||||
});
|
||||
|
||||
assert.equal(manifest.apiName, "project-release-gate-manifest");
|
||||
assert.equal(manifest.manifestVersion, 1);
|
||||
@@ -204,6 +209,7 @@ assert.match(partialActionPlan.shellScript, /wasm-port\/tests\/host\/verify_proj
|
||||
const report = createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalMotionControllerMatrix,
|
||||
});
|
||||
assert.deepEqual(report.gateManifest, manifest);
|
||||
assert.equal(report.gateExecutionManifest.apiName, "project-release-gate-execution-manifest");
|
||||
@@ -251,6 +257,11 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "blocked-runtime-families",
|
||||
label: "Blocked runtime families",
|
||||
@@ -270,12 +281,13 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
});
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport()).statusLine,
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage",
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage, virtual-hal-motion-controller-matrix",
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalMotionControllerMatrix,
|
||||
promotedRuntimeFamilies: ["L4-TOOL-DB"],
|
||||
})).rows.find(({ id }) => id === "blocked-runtime-families")?.value,
|
||||
"promoted: L4-TOOL-DB",
|
||||
@@ -318,6 +330,7 @@ assert.deepEqual(
|
||||
["gate-result-matrix", "ready"],
|
||||
["gate-action-plan", "ready"],
|
||||
["virtual-hal-sim-config-source-coverage", "ready"],
|
||||
["virtual-hal-motion-controller-matrix", "ready"],
|
||||
["missing", "none"],
|
||||
],
|
||||
);
|
||||
@@ -405,6 +418,7 @@ assert.deepEqual(
|
||||
["json-workflow", "ready"],
|
||||
["artifact-validation", "ready"],
|
||||
["browser-diagnostics", "not requested"],
|
||||
["saved-session-diagnostics", "not requested"],
|
||||
["next-command", "none"],
|
||||
["missing", "none"],
|
||||
],
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
VIRTUAL_HAL_COVERAGE_STATES,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
|
||||
VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS,
|
||||
@@ -89,6 +90,7 @@ import {
|
||||
createVirtualHalPinInventory,
|
||||
createVirtualHalPinRegistry,
|
||||
createVirtualHalProjectReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalState,
|
||||
@@ -239,6 +241,7 @@ const requiredExports = [
|
||||
["createVirtualHalPinInventory", createVirtualHalPinInventory],
|
||||
["createVirtualHalPinRegistry", createVirtualHalPinRegistry],
|
||||
["createVirtualHalProjectReport", createVirtualHalProjectReport],
|
||||
["createVirtualHalSimConfigPromotionCandidateReport", createVirtualHalSimConfigPromotionCandidateReport],
|
||||
["createVirtualHalSimConfigSourceCoverageReport", createVirtualHalSimConfigSourceCoverageReport],
|
||||
["createVirtualHalSimulationReplacementReport", createVirtualHalSimulationReplacementReport],
|
||||
["createVirtualHalSimulationRuntimeReport", createVirtualHalSimulationRuntimeReport],
|
||||
@@ -536,6 +539,10 @@ assert.match(sdkIndexText, /\bcreateVirtualHalSimulationReplacementReport\b/);
|
||||
assert.match(sdkReadmeText, /\bcreateVirtualHalSimulationReplacementReport\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSimConfigSourceCoverageReport\b/);
|
||||
assert.match(sdkReadmeText, /\bcreateVirtualHalSimConfigSourceCoverageReport\b/);
|
||||
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES\b/);
|
||||
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSimConfigPromotionCandidateReport\b/);
|
||||
assert.match(sdkReadmeText, /\bcreateVirtualHalSimConfigPromotionCandidateReport\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSourceComplianceReport\b/);
|
||||
assert.match(sdkReadmeText, /\bcreateVirtualHalSourceComplianceReport\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSystemCoverageReport\b/);
|
||||
@@ -668,10 +675,23 @@ assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcn
|
||||
assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true);
|
||||
assert.equal(motionControllerMatrixReport.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma.ini"), true);
|
||||
assert.equal(motionControllerMatrixReport.missingSimConfigTargets.length, 0);
|
||||
assert.equal(motionControllerMatrixReport.manifestChecked, false);
|
||||
assert.equal(motionControllerMatrixReport.missingManifestFiles.length, 0);
|
||||
assert.equal(motionControllerMatrixReport.rows.some(({ id, inPosition }) => id === "xyz-multi-axis-in-position" && inPosition === true), true);
|
||||
assert.equal(motionControllerMatrixReport.rows.some(({ id, simConfigTargets }) => id === "x-single-axis-servo-dtg" && simConfigTargets.includes("external-offsets")), true);
|
||||
assert.equal(motionControllerMatrixReport.rows.every(({ axisFeedbackRows }) => axisFeedbackRows.every(({ matched }) => matched)), true);
|
||||
assert.equal(virtualHalRuntime.getMotionControllerMatrixReport().complete, true);
|
||||
const manifestCheckedMotionControllerMatrixReport = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestText: sourceManifestText,
|
||||
});
|
||||
assert.equal(manifestCheckedMotionControllerMatrixReport.complete, true);
|
||||
assert.equal(manifestCheckedMotionControllerMatrixReport.manifestChecked, true);
|
||||
assert.equal(manifestCheckedMotionControllerMatrixReport.missingManifestFiles.length, 0);
|
||||
assert.equal(manifestCheckedMotionControllerMatrixReport.rows.every(({ manifestChecked }) => manifestChecked === true), true);
|
||||
assert.equal(
|
||||
manifestCheckedMotionControllerMatrixReport.rows.every(({ missingManifestFiles }) => missingManifestFiles.length === 0),
|
||||
true,
|
||||
);
|
||||
const steppedVirtualHal = stepVirtualHalMotion(virtualHalRuntime.getState(), {
|
||||
target: { x: 3 },
|
||||
maxVelocity: 10,
|
||||
@@ -729,6 +749,41 @@ assert.equal(simConfigSourceCoverageReport.sourceFiles.includes("linuxcnc/config
|
||||
assert.equal(simConfigSourceCoverageReport.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc"), 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);
|
||||
const simConfigPromotionCandidateReport = createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestText: sourceManifestText,
|
||||
simConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
});
|
||||
assert.equal(
|
||||
simConfigPromotionCandidateReport.apiName,
|
||||
"linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report",
|
||||
);
|
||||
assert.equal(simConfigPromotionCandidateReport.complete, true);
|
||||
assert.equal(simConfigPromotionCandidateReport.webSimulationSatisfied, true);
|
||||
assert.equal(simConfigPromotionCandidateReport.inventoryBaselineUnchanged, true);
|
||||
assert.equal(simConfigPromotionCandidateReport.manifestChecked, true);
|
||||
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,
|
||||
);
|
||||
assert.equal(simConfigPromotionCandidateReport.rows.every(({ blockedKind }) => blockedKind === "-"), true);
|
||||
assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
|
||||
manifestText: sourceManifestText,
|
||||
simConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
}).complete, true);
|
||||
const sourceComplianceReport = createVirtualHalSourceComplianceReport({ halState: virtualHalRuntime.getState() });
|
||||
assert.equal(sourceComplianceReport.apiName, "linuxcnc-wasm-virtual-hal-source-compliance-report");
|
||||
assert.equal(sourceComplianceReport.complete, true);
|
||||
@@ -768,25 +823,47 @@ assert.equal(
|
||||
restoreVirtualHalStateFromSessionSnapshot(virtualHalSessionSnapshot).hal.nets["x-pos"].includes("axis.x.pos-cmd"),
|
||||
true,
|
||||
);
|
||||
const browserDiagnosticsArtifactValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
const browserDiagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-diagnostics-artifact",
|
||||
virtualHal: virtualHalRuntime.getState(),
|
||||
virtualHalSimulationReplacement: replacementReport,
|
||||
virtualHalSourceCompliance: sourceComplianceReport,
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalCommandScriptFixtures: commandScriptFixtureReport,
|
||||
virtualHalMotionControllerMatrix: motionControllerMatrixReport,
|
||||
});
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
};
|
||||
const browserDiagnosticsSessionNestedArtifact = { ...browserDiagnosticsArtifact };
|
||||
browserDiagnosticsArtifact.virtualHalSessionDiagnostics = {
|
||||
apiName: "real-browser-simulation-virtual-hal-session-diagnostics",
|
||||
artifactVersion: 1,
|
||||
ready: true,
|
||||
phase: "release-ready",
|
||||
sessionId: virtualHalSessionSnapshot.sessionId,
|
||||
machineId: virtualHalSessionSnapshot.payload.machineId,
|
||||
createdAt: virtualHalSessionSnapshot.createdAt,
|
||||
metadata: { ...(virtualHalSessionSnapshot.metadata ?? {}) },
|
||||
files: { ...(virtualHalSessionSnapshot.payload.files ?? {}) },
|
||||
virtualHalRevision: virtualHalSessionPayload.state.revision,
|
||||
validation: createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact),
|
||||
diagnosticsArtifact: browserDiagnosticsSessionNestedArtifact,
|
||||
};
|
||||
const browserDiagnosticsArtifactValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsArtifact);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.apiName, "project-release-browser-diagnostics-artifact-validation");
|
||||
assert.equal(browserDiagnosticsArtifactValidation.ready, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidatesReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.hasPromotionCandidates, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.commandScriptFixturesReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.motionControllerMatrixReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.hasSessionDiagnostics, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sessionDiagnosticsReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/src/hal/utils/halcmd_commands.cc"), true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/src/emc/motion/axis.c"), true);
|
||||
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/axis/vismach/puma/puma.ini"), true);
|
||||
const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS });
|
||||
assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true);
|
||||
@@ -857,16 +934,20 @@ assert.equal(
|
||||
capabilities: batchAcceptanceWorkflow.capabilities,
|
||||
observedOutputs: ["project_batch_acceptance_workflow_node_smoke=ok"],
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
}).rows.find(({ id }) => id === "checklist")?.value,
|
||||
"4/4 passed",
|
||||
"5/5 passed",
|
||||
);
|
||||
const batchAcceptanceReport = createProjectBatchAcceptanceReport({
|
||||
batchId: "sdk-surface-batch",
|
||||
capabilities: batchAcceptanceWorkflow.capabilities,
|
||||
observedOutputs: ["project_batch_acceptance_workflow_node_smoke=ok"],
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
});
|
||||
assert.equal(batchAcceptanceReport.virtualHalSimConfigSourceCoverage.complete, true);
|
||||
assert.equal(batchAcceptanceReport.virtualHalMotionControllerMatrix.complete, true);
|
||||
assert.equal(batchAcceptanceReport.workflow.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.equal(createProjectBatchAcceptanceReportValidation(batchAcceptanceReport).ready, true);
|
||||
assert.equal(
|
||||
createProjectBatchAcceptanceReportValidationSummaryViewModel(
|
||||
@@ -920,7 +1001,11 @@ assert.equal(
|
||||
);
|
||||
assert.equal(releaseReadinessWaiting.apiName, "project-release-readiness-report");
|
||||
assert.equal(releaseReadinessWaiting.ready, false);
|
||||
assert.deepEqual(releaseReadinessWaiting.missing, ["project-release-gate", "virtual-hal-sim-config-source-coverage"]);
|
||||
assert.deepEqual(releaseReadinessWaiting.missing, [
|
||||
"project-release-gate",
|
||||
"virtual-hal-sim-config-source-coverage",
|
||||
"virtual-hal-motion-controller-matrix",
|
||||
]);
|
||||
assert.equal(releaseReadinessWaiting.simConfigInventory.unexpectedFail, 0);
|
||||
assert.deepEqual(releaseReadinessWaiting.promotedBlockedFamilies, []);
|
||||
assert.equal(releaseReadinessWaiting.gateActionPlan.apiName, "project-release-gate-action-plan");
|
||||
@@ -933,10 +1018,12 @@ assert.equal(
|
||||
const releaseReadinessReady = createProjectReleaseReadinessReport({
|
||||
observedOutputs: ["project_release_gate=ok"],
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
});
|
||||
assert.equal(releaseReadinessReady.ready, true);
|
||||
assert.equal(releaseReadinessReady.releaseGate.passed, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.deepEqual(releaseReadinessReady.gateManifest, createProjectReleaseGateManifest());
|
||||
assert.equal(releaseReadinessReady.gateResultMatrix.rows.length, createProjectReleaseGateManifest().gateCount);
|
||||
assert.equal(createProjectReleaseGateActionPlan({
|
||||
@@ -953,6 +1040,7 @@ assert.equal(
|
||||
const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
axisScreenshotArtifacts: ["desktop-preview", "desktop-dro", "mobile-preview", "mobile-mdi"].map((viewportName) => ({
|
||||
apiName: "real-browser-simulation-axis-screenshot-artifact",
|
||||
artifactVersion: 1,
|
||||
@@ -987,6 +1075,7 @@ assert.equal(
|
||||
const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
})));
|
||||
assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report");
|
||||
const releaseReadinessArtifactValidation = createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact);
|
||||
@@ -1007,6 +1096,7 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
gateResultMatrixReady: true,
|
||||
gateActionPlanReady: true,
|
||||
virtualHalSimConfigSourceCoverageReady: true,
|
||||
virtualHalMotionControllerMatrixReady: true,
|
||||
axisScreenshotArtifactSummaryReady: true,
|
||||
axisScreenshotArtifactCount: 0,
|
||||
blockedRuntimeFamilies: [
|
||||
@@ -1055,6 +1145,11 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "axis-screenshot-artifacts",
|
||||
label: "AXIS screenshot artifacts",
|
||||
@@ -1152,6 +1247,7 @@ assert.deepEqual(
|
||||
"simConfigInventory.skipped",
|
||||
"simConfigInventory.unexpectedFail",
|
||||
"virtualHalSimConfigSourceCoverage",
|
||||
"virtualHalMotionControllerMatrix",
|
||||
"blockedRuntimeFamilies",
|
||||
"gateManifest",
|
||||
"gateExecutionManifest",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
createProjectBatchAcceptanceReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
} from "../../../runtime/sdk/src/index.js";
|
||||
|
||||
@@ -29,6 +30,13 @@ const report = createProjectBatchAcceptanceReport({
|
||||
evidence: "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report",
|
||||
command: "wasm-port/tests/sdk/node/verify_sdk_surface.sh",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
type: "api",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
evidence: "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report",
|
||||
command: "wasm-port/tests/sdk/node/verify_sdk_surface.sh",
|
||||
},
|
||||
{
|
||||
id: "project-batch-acceptance-workflow-gate",
|
||||
type: "gate",
|
||||
@@ -41,6 +49,9 @@ const report = createProjectBatchAcceptanceReport({
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
});
|
||||
|
||||
mkdirSync(dirname(outputPath), { recursive: true });
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
createProjectReleaseBrowserDiagnosticsArtifactValidation,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseReadinessReport,
|
||||
} from "../../../runtime/sdk/src/project-release-readiness.js";
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
createVirtualHalCommandScriptFixtureReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createVirtualHalSimulationReplacementReport,
|
||||
createVirtualHalSourceComplianceReport,
|
||||
createVirtualHalState,
|
||||
} from "../../../runtime/sdk/src/linuxcnc-hal.js";
|
||||
|
||||
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []);
|
||||
|
||||
import {
|
||||
INI_PANEL_ENTRIES,
|
||||
controlPageStatusText,
|
||||
@@ -1356,21 +1362,54 @@ assert.equal(workflowDomMountResult.ready, false);
|
||||
assert.equal(workflowDomMountResult.renderResult.rowCount, 8);
|
||||
assert.equal(workflowDomMountResult.renderResult.dataset.handoffScope, "workflow");
|
||||
assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), shellViewModel.shellWorkflowOverviewContract);
|
||||
const releaseReadinessMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
});
|
||||
const releaseReadinessArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalMotionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
}));
|
||||
const browserDiagnosticsVirtualHalState = createVirtualHalState();
|
||||
const browserDiagnosticsArtifactJson = JSON.stringify({
|
||||
const browserDiagnosticsArtifact = {
|
||||
apiName: "real-browser-simulation-diagnostics-artifact",
|
||||
artifactVersion: 1,
|
||||
virtualHal: browserDiagnosticsVirtualHalState,
|
||||
virtualHalSimulationReplacement: createVirtualHalSimulationReplacementReport(browserDiagnosticsVirtualHalState),
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: browserDiagnosticsVirtualHalState }),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"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_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
],
|
||||
motionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
}),
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: browserDiagnosticsVirtualHalState }),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
});
|
||||
virtualHalMotionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
};
|
||||
const browserDiagnosticsSessionNestedArtifact = { ...browserDiagnosticsArtifact };
|
||||
browserDiagnosticsArtifact.virtualHalSessionDiagnostics = {
|
||||
apiName: "real-browser-simulation-virtual-hal-session-diagnostics",
|
||||
artifactVersion: 1,
|
||||
ready: true,
|
||||
phase: "release-ready",
|
||||
sessionId: "ini-panel-ui-shell-virtual-hal-session",
|
||||
machineId: "ini-panel-ui-shell-machine",
|
||||
createdAt: "2026-06-17T00:00:00.000Z",
|
||||
metadata: { source: "ini-panel-ui-shell-url-fixture" },
|
||||
files: {},
|
||||
virtualHalRevision: browserDiagnosticsVirtualHalState.revision,
|
||||
validation: createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDiagnosticsSessionNestedArtifact),
|
||||
diagnosticsArtifact: browserDiagnosticsSessionNestedArtifact,
|
||||
};
|
||||
const browserDiagnosticsArtifactJson = JSON.stringify(browserDiagnosticsArtifact);
|
||||
const releaseArtifactValidation = validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(
|
||||
releaseReadinessArtifactJson,
|
||||
);
|
||||
@@ -1675,7 +1714,7 @@ const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseRead
|
||||
rowsNode: releaseArtifactRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 10);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
|
||||
@@ -1697,8 +1736,12 @@ assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("virtual-hal-sim-config-source-coverage"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("virtual-hal-motion-controller-matrix"),
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactMountResult.ready, true);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 10);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 11);
|
||||
assert.deepEqual(
|
||||
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
|
||||
["artifact-json"],
|
||||
@@ -1745,13 +1788,17 @@ assert.equal(releaseArtifactUrlWorkflow.httpStatus, 200);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsHttpStatus, 200);
|
||||
assert.equal(releaseArtifactUrlWorkflow.validation.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsValidation.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsValidation.hasPromotionCandidates, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsValidation.promotionCandidatesReady, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsValidation.hasSessionDiagnostics, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.diagnosticsValidation.sessionDiagnosticsReady, true);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflow.validationSummaryViewModel.statusLine,
|
||||
"Ready: Artifact evidence complete",
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflow.renderState.statusLine, "Ready: No blocking reasons");
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 10);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 11);
|
||||
const releaseArtifactUrlWorkflowSummary =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
releaseArtifactUrlWorkflow,
|
||||
@@ -1776,6 +1823,10 @@ assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "browser-diagnostics")?.value,
|
||||
"ready",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "saved-session-diagnostics")?.value,
|
||||
"ready",
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflow.actionPlan.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.actionPlan.nextCommand, null);
|
||||
assert.equal(
|
||||
@@ -1841,17 +1892,21 @@ const releaseArtifactUrlWorkflowMountResult =
|
||||
rowsNode: releaseArtifactUrlWorkflowRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 12);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("saved-session-diagnostics"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"),
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 12);
|
||||
const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
fetchRef: async () => ({
|
||||
|
||||
Reference in New Issue
Block a user