diff --git a/text17.txt b/text17.txt index 438599f..865e896 100644 --- a/text17.txt +++ b/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 文档,形成发布交接可读说明。 diff --git a/text18.txt b/text18.txt new file mode 100644 index 0000000..af56770 --- /dev/null +++ b/text18.txt @@ -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 案例。 diff --git a/wasm-port/docs/sim-config-coverage-promotion-analysis.md b/wasm-port/docs/sim-config-coverage-promotion-analysis.md new file mode 100644 index 0000000..e97b4ed --- /dev/null +++ b/wasm-port/docs/sim-config-coverage-promotion-analysis.md @@ -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. diff --git a/wasm-port/runtime/sdk/README.md b/wasm-port/runtime/sdk/README.md index ddb7e9f..6f74cd0 100644 --- a/wasm-port/runtime/sdk/README.md +++ b/wasm-port/runtime/sdk/README.md @@ -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()`, diff --git a/wasm-port/runtime/sdk/src/index.js b/wasm-port/runtime/sdk/src/index.js index 72b91a9..486056a 100644 --- a/wasm-port/runtime/sdk/src/index.js +++ b/wasm-port/runtime/sdk/src/index.js @@ -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, diff --git a/wasm-port/runtime/sdk/src/linuxcnc-hal.js b/wasm-port/runtime/sdk/src/linuxcnc-hal.js index e5143a5..6e8a876 100644 --- a/wasm-port/runtime/sdk/src/linuxcnc-hal.js +++ b/wasm-port/runtime/sdk/src/linuxcnc-hal.js @@ -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 }); }, diff --git a/wasm-port/runtime/sdk/src/project-release-readiness.js b/wasm-port/runtime/sdk/src/project-release-readiness.js index ea4a127..63f7264 100644 --- a/wasm-port/runtime/sdk/src/project-release-readiness.js +++ b/wasm-port/runtime/sdk/src/project-release-readiness.js @@ -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", diff --git a/wasm-port/runtime/ui/ini-panel/ui-shell.js b/wasm-port/runtime/ui/ini-panel/ui-shell.js index 8a46649..467d514 100644 --- a/wasm-port/runtime/ui/ini-panel/ui-shell.js +++ b/wasm-port/runtime/ui/ini-panel/ui-shell.js @@ -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", diff --git a/wasm-port/runtime/ui/ini-panel/workflow-overview.html b/wasm-port/runtime/ui/ini-panel/workflow-overview.html index 6d5bb18..8b99c8e 100644 --- a/wasm-port/runtime/ui/ini-panel/workflow-overview.html +++ b/wasm-port/runtime/ui/ini-panel/workflow-overview.html @@ -127,6 +127,14 @@

Waiting for release artifact URL workflow.

+
+

Waiting for URL workflow action plan.

+
+
+
+

Waiting for URL workflow gate evidence.

+
+