Compare commits

...

4 Commits

Author SHA1 Message Date
a6eda3fbff 按text32继续推进evidence expansion过滤预设
结论:已完成 evidence expansion family/source filter 的 summary/action-plan、query/hash 预选、UI/API/SDK/浏览器验证覆盖,并保持 sim-config inventory baseline=82/82/77/0。
2026-06-20 12:18:08 +08:00
8a1c4699b1 按接续文件text31持续推进
结论:已将五项evidence expansion从API/smoke推进到real simulation diagnostics panel和release URL/INI workflow完整列表可见面;baseline保持82/82/77/0,promotionAllowed保持false。
2026-06-20 08:26:55 +08:00
fab42a8bdb 按接续文件text31持续推进
结论:已将五轴TRT的boat-xyzac与xyzac_switchkins加入browser diagnostics evidence expansion,candidateCount提升到5且全部ready;inventory baseline继续保持82/82/77/0,promotionAllowed仍为false。
2026-06-20 08:16:29 +08:00
c2e07518d3 接续上一轮,按接续文件持续推进
结论:已完成剩余77个SKIP的promotion复核;仅2个main SKIP且promotion_allowed均为0,当前baseline保持82/82/77/0,并新增文档与docs smoke防止误promotion。
2026-06-20 08:07:06 +08:00
19 changed files with 2895 additions and 18 deletions

View File

@@ -1,15 +1,15 @@
# Project Completion Tracker
Last updated: 2026-06-16 CST
Last updated: 2026-06-20 CST
This file tracks the overall completion state of the LinuxCNC WASM/browser port.
Use it for project-level status and acceptance tracking. Use `text16.txt` for
Use it for project-level status and acceptance tracking. Use `text32.txt` for
turn-by-turn continuation notes and next-batch execution records.
## Current Status
- Active continuation file: `text16.txt`
- Latest completed batch: AXIS run summary
- Active continuation file: `text32.txt`
- Latest completed batch: evidence expansion filter query/hash preset
- Latest relevant commit: use `git log -1 --oneline` after each committed batch
- Working tree at tracker creation: clean
- Required policy: LinuxCNC remains the only CNC semantic source
@@ -32,7 +32,7 @@ The project is complete for the current scope when all of the following are true
- Host/runtime blocked families are explicitly documented and not falsely promoted.
- All required gates pass.
- Documentation explains what is supported, blocked, and how to verify it.
- `text16.txt` contains the current continuation record and the working tree is clean.
- `text32.txt` contains the current continuation record and the working tree is clean.
## Area Status
@@ -45,7 +45,7 @@ The project is complete for the current scope when all of the following are true
| Simulation test program library | Active | Built-in browser simulation programs live in `wasm-port/runtime/ui/simulation/programs/`, one module per program, exported through `programs/index.js`; `verify_real_simulation_programs.sh` checks directory-backed inventory, IDs, defaults, and playback contracts. |
| Vendor/source guard | Stable | `verify_vendor_sync.sh` and standalone semantic guard are required every batch. |
| Interpreter WASM smoke | Stable | `interp_wasm_node_smoke=ok`. |
| Sim config inventory | Stable with skips | `executed=28`, `passed=28`, `skipped=131`, `unexpected_fail=0`; `docs/sim-configs-coverage-handoff.md` records the release-gate baseline. |
| Sim config inventory | Stable with skips | `executed=82`, `passed=82`, `skipped=77`, `unexpected_fail=0`; `docs/sim-configs-coverage-handoff.md` records the release-gate baseline. The 2026-06-20 remaining-skip audit found 2 skipped main-program rows and 0 rows with `promotion_allowed=1`, so the baseline must not change without new LinuxCNC-owned native/Node/browser proof. Browser diagnostics evidence expansion now includes eleven ready source-derived REP candidates, including the full current TRT table-rotary-tilting batch, all with `promotionAllowed=false`; the real simulation diagnostics panel and release URL workflow summaries expose the eleven-row full candidate/G-code lists plus three-family/source-count drilldown, and the INI workflow overview now has a separate evidence-expansion family/source filter with summary/action-plan helpers plus query/hash UI-state presets for external shell reads. |
| Native nc_files baseline | Stable | Last recorded Layer 1: `total 107`, `pass 101`, `expected_fail 6`, `unexpected_fail 0`. |
| Native sim configs baseline | Stable | Last recorded Layer 2: `total 159`, `pass 151`, `expected_fail 8`, `unexpected_fail 0`. |
| OPFS/session persistence | Stable for current scope | Browser smoke passes, SDK re-exports OPFS/session helpers including `readMachineSessionReadiness()` and `createMachineSessionPersistenceSummary()`, the UI exposes `getMachineSessionPersistenceSummary()`, and `docs/opfs-session-persistence.md` defines the project-level release gate. |

751
text32.txt Normal file
View File

@@ -0,0 +1,751 @@
项目接续文件:剩余 77 个 SKIP promotion 复核完成
生成时间2026-06-20 CST
一、本轮完成内容
按上一轮 `text31.txt` 的要求,已重新生成并复核当前 sim-config
inventory artifact
```bash
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
```
当前结果:
```text
sim_configs_wasm_node_inventory_executed=82
sim_configs_wasm_node_inventory_passed=82
sim_configs_wasm_node_inventory_skipped=77
sim_configs_wasm_node_inventory_unexpected_fail=0
sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65
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
sim_configs_wasm_node_inventory=ok
```
二、77 个 SKIP 复核结论
`remaining-skip-main-program-promotion-audit.tsv` 中只有 2 个 class=main
的 SKIP
```text
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc
skip_kind=UPSTREAM-DEMO
native_status=FAIL
native_expected_failure=upstream-demo-missing-motion-gcode
promotion_allowed=0
conclusion=保留 upstream demo edge不强行 PASS
axis/vismach/millturn/example.ngc
skip_kind=L4-USER-M-PROCESS
native_status=PASS
simulation_proof_status=ready_disabled_by_default:native=0:node=0:browser=0
promotion_allowed=0
conclusion=Web virtual HAL 已有 M428/M429 -> M128/M129 状态 proof
但 external user-M arbitrary process execution 仍 disabled
不能作为 inventory promotion proof
```
其余 SKIP
```text
ASSET-ONLY=65
NON_MAIN_CLASS=10
```
这些不是 standalone browser main-program promotion 对象。
本轮最终结论:
```text
remaining_skip_count=77
remaining_skipped_main_program_rows=2
remaining_skipped_main_program_promotion_allowed=0
direct_inventory_promotion_rows=0
baseline_change_allowed=no
```
三、本轮代码/文档改动
已更新:
```text
PROJECT_COMPLETION_TRACKER.md
wasm-port/docs/sim-config-coverage-promotion-analysis.md
wasm-port/docs/sim-configs-coverage-handoff.md
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.mjs
text32.txt
```
新增 docs smoke 断言:
```text
1. skip-summary.tsv 仍是 ASSET-ONLY=65 / L4-USER-M-PROCESS=1 /
NON_MAIN_CLASS=10 / UPSTREAM-DEMO=1
2. remaining-skip-main-program-promotion-audit.tsv 只有 2 行;
3. 两行均 class=main
4. 两行均 promotion_allowed=0 且 promotion_ready=0
5. 路径必须是 millturn/example.ngc 和 incremental_repetition_g533.ngc。
```
四、已运行验证
```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
wasm-port/tests/ui/node/verify_real_simulation_programs.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
wasm-port/tools/verify_no_standalone_cnc_semantics.sh
```
结果:
```text
sim_configs_coverage_docs_node_smoke=ok
sim_configs_wasm_node_inventory=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
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
standalone CNC semantics guard complete
```
五、下一步工作计划
不要继续尝试把 77 个 SKIP 直接改 PASS。当前没有可直接 promotion 的
remaining SKIP main-program row。
下一批应推进已经 PASS 的 row 的 browser diagnostics / release evidence
不改 inventory baseline。优先顺序
```text
1. 读取 evidence-expansion-candidates.tsv
2. 从已 PASS 且 matrix_layer4_browser=REP 的五轴/vismach row 中选一组;
3. 优先建议:
- axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc
- axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc
- axis/vismach/melfa-sim/example.ngc
- axis/vismach/puma/puma_cube.ngc
4. 为首个候选补 browser diagnostics evidence不新增 JS CNC 语义;
5. 让 release artifact / real simulation diagnostics DOM 能显示该 evidence
6. 补 Node/browser smoke
7. 保持 inventory baseline=82/82/77/0。
```
推荐下一轮验证命令:
```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
wasm-port/tools/verify_no_standalone_cnc_semantics.sh
```
六、本轮接续推进:五轴 TRT browser diagnostics evidence expansion
执行时间2026-06-20 CST
已按上面的下一步计划推进,不改 inventory baseline不把 77 个 SKIP
强行 promotion。
新增 browser diagnostics evidence expansion 候选:
```text
trt-boat-xyzac
gcode=linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc
ini=linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini
remap_subs=428remap.ngc,429remap.ngc,430remap.ngc
currentNodeInventoryStatus=PASS
currentMatrixBrowserStatus=REP
targetBrowserEvidence=browser-diagnostics-expansion
promotionAllowed=false
trt-xyzac-switchkins
gcode=linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc
ini=linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini
remap_subs=428remap.ngc,429remap.ngc,430remap.ngc
currentNodeInventoryStatus=PASS
currentMatrixBrowserStatus=REP
targetBrowserEvidence=browser-diagnostics-expansion
promotionAllowed=false
```
当前 evidence expansion report
```text
candidateCount=11
readyCandidateCount=11
inventoryBaselineUnchanged=true
promotionAllowed=false
```
覆盖面:
```text
woodpecker-on-abort
puma-cube
melfa-example
trt-boat-xyzac
trt-xyzac-switchkins
```
已更新:
```text
PROJECT_COMPLETION_TRACKER.md
wasm-port/runtime/sdk/src/linuxcnc-hal.js
wasm-port/runtime/sdk/src/project-release-readiness.js
wasm-port/runtime/ui/simulation diagnostics artifact smoke
wasm-port/tests/browser/ini_panel_workflow_overview_smoke.html
wasm-port/tests/browser/real_simulation_page_smoke.html
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.mjs
wasm-port/tests/sdk/node/verify_sdk_surface.mjs
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs
wasm-port/docs/sim-config-coverage-promotion-analysis.md
```
已运行验证:
```text
git diff --check
wasm-port/tests/sdk/node/verify_sdk_surface.sh
wasm-port/tests/sdk/node/verify_project_release_artifact_url_workflow.sh
wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
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/tools/verify_no_standalone_cnc_semantics.sh
```
结果:
```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
ini_panel_ui_shell_node_smoke=ok
browser_real_simulation_page_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
browser_release_artifact_url_workflow_smoke=ok
sim_configs_coverage_docs_node_smoke=ok
sim_configs_wasm_node_inventory=ok
standalone CNC semantics guard complete
```
七、下一步工作计划
继续沿 browser diagnostics / release evidence 方向推进,不改变
`82/82/77/0` inventory baseline。
优先建议:
```text
1. 把 evidence expansion 从“候选 report/API/smoke”推进到更可见的 UI
surface
- real simulation diagnostics panel 显示 evidence expansion ready count
- INI workflow overview URL summary 显示 5 个 ready candidates 的完整列表
或 drilldown
- 保持 summary preview 的前三项兼容现有 UI。
2. 继续扩展五轴 TRT family 的 browser diagnostics evidence
- boat-xyzbc.ngc
- impeller-7bl-xyzac.ngc
- xyzac_switchkins_test_1.ngc
- xyzac_switchkins_test_2.ngc
- xyzac_switchkins_test_3.ngc
- xyzbc_switchkins.ngc
3. 每新增一批都必须满足:
- currentNodeInventoryStatus=PASS
- currentMatrixBrowserStatus=REP
- targetBrowserEvidence=browser-diagnostics-expansion
- promotionAllowed=false
- inventoryBaselineUnchanged=true
- real browser diagnostics artifact smoke 覆盖。
```
八、本轮接续推进evidence expansion UI surface
执行时间2026-06-20 CST
已完成第七节优先建议中的 UI 可见性推进:
```text
1. real simulation diagnostics panel 显示 evidence expansion ready count
2. real simulation diagnostics panel 显示完整 ready candidates
3. release artifact URL workflow summary 暴露完整 candidate / G-code list
4. INI workflow overview URL summary 暴露完整 candidate / G-code list
5. 保留原有 preview 的前三项,兼容既有 UI 和测试。
```
新增可见/API 字段:
```text
real-browser-simulation-evidence-expansion-summary
data-evidence-expansion-summary-value="candidate-count" => 11/11 ready
data-evidence-expansion-summary-value="candidate-list" =>
woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins
evidence-expansion-full-candidate-list
evidence-expansion-full-gcode-list
```
边界仍保持:
```text
inventoryBaselineUnchanged=true
promotionAllowed=false
inventory baseline=82/82/77/0
```
本轮已运行验证:
```text
wasm-port/tests/sdk/node/verify_project_release_artifact_url_workflow.sh
wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh
wasm-port/tests/sdk/node/verify_sdk_surface.sh
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
```
结果:
```text
project_release_artifact_url_workflow_node_smoke=ok
project_release_gate_manifest_node_smoke=ok
sdk_surface_node_smoke=ok
ini_panel_ui_shell_node_smoke=ok
browser_real_simulation_page_smoke=ok
browser_ini_workflow_overview_smoke=ok
browser_ini_shell_integration_workflow_smoke=ok
browser_release_artifact_url_workflow_smoke=ok
```
九、下一步工作计划
本轮已把计划中的六个五轴 TRT row 加入 browser diagnostics evidence
expansion当前完整 ready candidates 为:
```text
woodpecker-on-abort
puma-cube
melfa-example
trt-boat-xyzac
trt-xyzac-switchkins
trt-boat-xyzbc
trt-impeller-7bl-xyzac
trt-xyzac-switchkins-test-1
trt-xyzac-switchkins-test-2
trt-xyzac-switchkins-test-3
trt-xyzbc-switchkins
```
下一步建议不要继续堆同一 TRT family改为做“evidence expansion
source drilldown / family grouping”让 UI 按 family 或 source kind 查看
11 个 candidates
```text
1. 在 real simulation diagnostics panel 增加 evidence-expansion family rows
2. 在 release URL / INI workflow summary 增加 source-count 或 family-count
drilldown
3. 保持 preview 三项兼容;
4. inventory baseline 仍保持 82/82/77/0
5. promotionAllowed 仍保持 false。
```
十、本轮接续推进evidence expansion family/source drilldown
执行时间2026-06-20 CST
已完成第九节建议的 family/source drilldown不改变
`82/82/77/0` inventory baseline也不允许 evidence expansion 触发
inventory promotion。
新增/确认的 diagnostics/API/UI 字段:
```text
virtualHalSimConfigEvidenceExpansion.familyRows
evidence-expansion-family-count
evidence-expansion-family-summary
evidence-expansion-family-source-count-list
evidence-expansion-family-woodpecker
evidence-expansion-family-vismach-remap-sims
evidence-expansion-family-five-axis-trt
data-evidence-expansion-summary-value="family-count"
data-evidence-expansion-summary-value="family-summary"
data-evidence-expansion-summary-value="family-source-count-list"
```
当前 family drilldown
```text
woodpecker: 1/1 ready; sources=3
vismach-remap-sims: 2/2 ready; sources=6
five-axis-trt: 8/8 ready; sources=12
```
边界仍保持:
```text
candidateCount=11
readyCandidateCount=11
inventoryBaselineUnchanged=true
promotionAllowed=false
inventory baseline=82/82/77/0
```
本轮已运行验证:
```text
wasm-port/tests/sdk/node/verify_sdk_surface.sh
wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh
wasm-port/tests/sdk/node/verify_project_release_artifact_url_workflow.sh
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
```
结果:
```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
ini_panel_ui_shell_node_smoke=ok
browser_real_simulation_page_smoke=ok
browser_ini_workflow_overview_smoke=ok
browser_ini_shell_integration_workflow_smoke=ok
browser_release_artifact_url_workflow_smoke=ok
```
十一、下一步工作计划
不要继续扩大同一个 TRT evidence expansion 列表,也不要改 inventory
baseline。下一批建议转向“drilldown 可用性/过滤”:
```text
1. 在 INI workflow overview 增加 evidence-expansion family/source filter
render-state类似现有 promotion family source filter
2. 支持按 family 查看 candidateIds / gcodePaths / sourceFiles
3. real simulation diagnostics panel 保持 summary 简洁,只暴露 family rows
4. release URL workflow summary 保留 preview 三项和 full list 兼容;
5. 继续保持 promotionAllowed=false、baseline=82/82/77/0。
```
十二、本轮接续推进evidence expansion family/source filter
执行时间2026-06-20 CST
已完成第十一节建议的 evidence-expansion family/source filter。该 filter
独立于 promotion family source filter避免把 promotion candidates 与
evidence expansion diagnostics rows 混在同一 API/DOM contract 中。
新增 API / DOM surface
```text
getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState
getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan
handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange
bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState
data-workflow-overview-evidence-expansion-family-source-filter
data-workflow-overview-evidence-expansion-family-source-filter-controls
data-workflow-overview-evidence-expansion-family-source-filter-rows
```
当前 filter 覆盖:
```text
families=3
sourceFiles=21
candidates=11
sourceKinds=ini/gcode/remap-subroutine/source
evidence-expansion-family-five-axis-trt + gcode => 8 source files / 8 candidates
```
边界仍保持:
```text
promotionAllowed=false
inventoryBaselineUnchanged=true
inventory baseline=82/82/77/0
```
本轮已运行验证:
```text
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
wasm-port/tests/sdk/node/verify_sdk_surface.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
```
结果:
```text
ini_panel_ui_shell_node_smoke=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
browser_ini_workflow_overview_smoke=ok
browser_ini_shell_integration_workflow_smoke=ok
```
十三、下一步工作计划
不要改 inventory baseline也不要扩大同一 TRT family。下一批建议做
filter 状态的可复用输出/深链:
```text
1. 为 evidence-expansion family/source filter 增加 summary/action-plan
helper输出 selectedFamilyId / selectedSourceKind / filtered counts
2. 在 workflow overview URL workflow result 中保留当前 filter selection
的 structured summary方便外部 shell 读取;
3. 可选:支持 query/hash 参数预选 family/sourceKind
4. 继续保持 promotionAllowed=false、baseline=82/82/77/0
5. 验证仍以 Node UI smoke、INI browser smoke、SDK surface、docs smoke 为主。
```
十四、本轮接续推进evidence expansion filter summary/action-plan
执行时间2026-06-20 CST
已完成第十三节建议中的可复用输出层,不改变 inventory baseline也不扩大
TRT family 候选集合。
新增 API / SDK / 页面 surface
```text
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary
getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan
```
当前 structured summary/action-plan 覆盖:
```text
selectedFamilyId
selectedSourceKind
filteredSourceFileCount
scopedSourceFileCount
totalSourceFileCount
filteredCandidateCount
totalCandidateCount
familyIds
sourceKinds
candidateIds
gcodePaths
sourceFiles
promotionAllowed=false
baselineChanging=false
```
页面侧 `workflow-overview.html` 现在会在 fixed release artifact URL workflow
执行后保留当前 evidence-expansion filter selection 的 structured summary
和 action-plan并通过 workflow overview API 暴露给外部 shell。默认状态
```text
all / all => 21/21 source files selected
five-axis-trt / gcode => 8/21 source files selected, 8 candidates
```
边界仍保持:
```text
promotionAllowed=false
baselineChanging=false
inventoryBaselineUnchanged=true
inventory baseline=82/82/77/0
```
本轮已运行验证:
```text
git diff --check
wasm-port/tests/sdk/node/verify_sdk_surface.sh
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
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/tools/verify_no_standalone_cnc_semantics.sh
```
结果:
```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
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
browser_release_artifact_url_workflow_smoke=ok
browser_real_simulation_page_smoke=ok
sim_configs_coverage_docs_node_smoke=ok
sim_configs_wasm_node_inventory=ok
standalone CNC semantics guard complete
```
inventory 验证结果仍为:
```text
sim_configs_wasm_node_inventory_executed=82
sim_configs_wasm_node_inventory_passed=82
sim_configs_wasm_node_inventory_skipped=77
sim_configs_wasm_node_inventory_unexpected_fail=0
sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65
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也不要继续扩大同一个 TRT evidence list。
下一批建议做可选的 filter 深链预选,但要保持为 UI 状态恢复能力,不影响
release evidence 或 promotion 结论:
```text
1. 支持 workflow overview 的 query/hash 参数预选:
- evidenceExpansionFamily=evidence-expansion-family-five-axis-trt
- evidenceExpansionSourceKind=gcode
2. 预选只驱动 filter view-model 初始状态,不写入 inventory/report artifact
3. browser smoke 覆盖预选后 body dataset / DOM selectedFamilyId /
selectedSourceKind / filtered count
4. SDK summary/action-plan 保持 promotionAllowed=false、baselineChanging=false
5. baseline 继续保持 82/82/77/0。
```
十六、本轮接续推进evidence expansion filter query/hash 预选
执行时间2026-06-20 CST
已完成第十五节建议的 workflow overview filter 深链预选。该能力只影响
`workflow-overview.html` 中 evidence-expansion family/source filter 的初始
UI 状态,不写入 release artifact、不写入 diagnostics artifact、不改变
inventory/report 结论。
新增行为:
```text
workflow-overview.html?evidenceExpansionFamily=evidence-expansion-family-five-axis-trt&evidenceExpansionSourceKind=gcode
workflow-overview.html#evidenceExpansionFamily=evidence-expansion-family-five-axis-trt&evidenceExpansionSourceKind=gcode
```
当前预选结果:
```text
selectedFamilyId=evidence-expansion-family-five-axis-trt
selectedSourceKind=gcode
filteredSourceFileCount=8
filteredCandidateCount=8
baselineChanging=false
promotionAllowed=false
```
实现边界:
```text
1. 预选只通过 URL query/hash 读取;
2. 只传入 createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel
3. 不改 SDK helper 的纯函数输入/输出;
4. 不改 diagnostics artifact 或 release readiness artifact
5. 不改 inventory baseline。
```
本轮已运行验证:
```text
git diff --check
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh
wasm-port/tests/sdk/node/verify_sdk_surface.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
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/tools/verify_no_standalone_cnc_semantics.sh
```
结果:
```text
ini_panel_ui_shell_node_smoke=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
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_release_artifact_url_workflow_smoke=ok
browser_real_simulation_page_smoke=ok
sim_configs_coverage_docs_node_smoke=ok
sim_configs_wasm_node_inventory=ok
standalone CNC semantics guard complete
```
inventory 验证结果仍为:
```text
sim_configs_wasm_node_inventory_executed=82
sim_configs_wasm_node_inventory_passed=82
sim_configs_wasm_node_inventory_skipped=77
sim_configs_wasm_node_inventory_unexpected_fail=0
sim_configs_wasm_node_inventory_skip_ASSET_ONLY=65
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也不要把 evidence-expansion filter 状态写入
artifact。下一批建议转向真实浏览器模拟页面的 operator-facing 可用性:
```text
1. 在 real simulation page diagnostics 区增加 evidence-expansion family
drilldown 的紧凑 operator view
2. 只展示 family/count/source-kind summary不新增 CNC 语义;
3. 保持 release artifact URL workflow 和 INI workflow overview 现有 API 兼容;
4. browser smoke 覆盖 real simulation page 的 family drilldown 可见状态;
5. baseline 继续保持 82/82/77/0。
```

View File

@@ -26,6 +26,44 @@ as a blanket reason to reduce the skip baseline. The next useful promotions are
case promotions from Node inventory or representative coverage into browser,
diagnostics, and release evidence.
## 2026-06-20 Remaining Skip Promotion Audit
The generated audit for the remaining 77 skipped rows is:
```text
build/wasm/sim-configs-inventory/remaining-skip-main-program-promotion-audit.tsv
```
It contains only two skipped rows whose class is `main`:
| Path | Skip kind | Native status | Promotion allowed | Decision |
| --- | --- | --- | ---: | --- |
| `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc` | `UPSTREAM-DEMO` | `FAIL` with `upstream-demo-missing-motion-gcode` | 0 | Preserve as an upstream demo edge; do not force into PASS. |
| `axis/vismach/millturn/example.ngc` | `L4-USER-M-PROCESS` | `PASS` | 0 | Web virtual HAL proof exists for M428/M429 to M128/M129 transition state, but arbitrary external user-M process execution remains disabled and is not an inventory promotion proof. |
The remaining skipped rows are not direct main-program promotion targets:
```text
ASSET-ONLY=65
NON_MAIN_CLASS=10
```
The 2026-06-20 audit conclusion is therefore explicit:
```text
remaining_skip_count=77
remaining_skipped_main_program_rows=2
remaining_skipped_main_program_promotion_allowed=0
direct_inventory_promotion_rows=0
baseline_change_allowed=no
```
Future work should add browser diagnostics and release evidence for already
passing Node inventory or representative rows. It should not change the
inventory baseline unless a later patch supplies LinuxCNC-owned native proof,
Node/WASM proof, browser proof, and a manual promotion-lock update for the row
being promoted.
## What Virtual HAL Unlocks
The virtual HAL is now a source-derived Web simulation replacement for these
@@ -655,6 +693,118 @@ surfaces. They do not add virtual HAL runtime capability, do not alter
`promotion-candidates.tsv`, and do not change the inventory baseline or any
hard-block lock.
## 2026-06-20 Five-Axis TRT Evidence Expansion
After the remaining 77 SKIP audit confirmed there are no directly promotable
skipped main-program rows, the next evidence batch expanded browser diagnostics
coverage for already passing representative rows instead of changing the
inventory baseline.
The virtual HAL sim-config evidence expansion report now requires these
five-axis TRT rows:
```text
trt-boat-xyzac
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc
trt-xyzac-switchkins
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc
trt-boat-xyzbc
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc
trt-impeller-7bl-xyzac
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc
trt-xyzac-switchkins-test-1
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc
trt-xyzac-switchkins-test-2
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc
trt-xyzac-switchkins-test-3
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc
trt-xyzbc-switchkins
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc
```
Both rows use the LinuxCNC-owned `xyzac-trt.ini` machine context and the
vendored `428remap.ngc`, `429remap.ngc`, and `430remap.ngc` remap
subroutines. They remain:
```text
currentNodeInventoryStatus=PASS
currentMatrixBrowserStatus=REP
targetBrowserEvidence=browser-diagnostics-expansion
promotionAllowed=false
inventoryBaselineUnchanged=true
```
The real browser simulation diagnostics artifact now validates that the
evidence expansion report has `candidateCount=11` and `readyCandidateCount=11`,
including the TRT rows above. The inventory baseline remains
`executed=82 passed=82 skipped=77 unexpected_fail=0`.
## 2026-06-20 Evidence Expansion UI Surface
The evidence expansion data is now visible outside the raw diagnostics JSON:
```text
real-browser-simulation-evidence-expansion-summary
evidence-expansion-full-candidate-list
evidence-expansion-full-gcode-list
evidence-expansion-family-count
evidence-expansion-family-summary
evidence-expansion-family-source-count-list
```
The real simulation diagnostics panel renders `11/11 ready`, the full eleven-row
candidate list, source-file count, promotion lock state, and unchanged
inventory state. The project release URL workflow summary and INI workflow
overview keep their existing three-row preview fields for compatibility, and
also expose the full candidate and G-code lists so shell callers can inspect
all eleven ready evidence-expansion rows without opening the raw artifact.
The same diagnostics and release URL summaries now group the eleven
evidence-expansion rows into three browser diagnostics families:
```text
woodpecker: 1/1 ready; sources=3
vismach-remap-sims: 2/2 ready; sources=6
five-axis-trt: 8/8 ready; sources=12
```
This family drilldown is source/evidence visibility only. It does not alter the
separate promotion candidate summary of 8 diagnostics-ready candidates across
3 families and 17 source files, and it does not change the inventory baseline.
## 2026-06-20 Evidence Expansion Source Filter
The INI workflow overview now exposes a separate evidence-expansion family
source filter, distinct from the promotion-family source filter:
```text
getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState
getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState
```
The filter supports selecting `all`, `ini`, `gcode`, `remap-subroutine`, or
`source` rows within the evidence-expansion families, and it keeps candidate
rows separate from source rows. The current ready filter surface covers:
```text
21 source files
11 evidence-expansion candidate rows
evidence-expansion-family-five-axis-trt / gcode => 8 source files, 8 candidates
```
All rows remain diagnostics evidence only: `promotionAllowed=false`,
`inventoryBaselineUnchanged=true`, and the inventory baseline remains
`82/82/77/0`.
## Boundary Statement
This analysis relies on the improved virtual HAL only for Web simulation

View File

@@ -63,6 +63,19 @@ incomplete user-M process native/inventory promotion proof, even though the
browser simulation state now includes a source-derived virtual HAL proof for
the `M429 -> M129` turn and `M428 -> M128` mill state transitions. The TWP
`incremental_repetition_g533.ngc` row remains preserved upstream demo evidence.
The 2026-06-20 re-audit confirmed that there are no directly promotable
remaining skipped main-program rows:
```text
remaining_skip_count=77
remaining_skipped_main_program_rows=2
remaining_skipped_main_program_promotion_allowed=0
direct_inventory_promotion_rows=0
baseline_change_allowed=no
```
The 65 `ASSET-ONLY` rows and 10 `NON_MAIN_CLASS` rows remain non-main evidence
targets, not standalone browser main programs.
SDK and workflow-overview release URL summaries expose the current
`evidence-ready` layer as dashboard fields: `evidence-ready-candidate-rows=8`,

View File

@@ -61,6 +61,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomReadiness,
@@ -707,6 +718,20 @@ for external browser shells:
`renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()`,
and `mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()`
let callers render the URL workflow status into their own DOM.
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState()`,
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel()`,
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary()`,
and `createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan()`
expose the current evidence-expansion family/source selection for external
shells without enabling inventory promotion.
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract()`,
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness()`,
`createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan()`,
`handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange()`,
`bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls()`,
`renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState()`,
and `mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState()`
let callers render and bind that evidence-expansion filter in caller-owned DOM.
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan()`
exposes the direct artifact-validation next-command plan when callers already
have parsed or validated artifact JSON.

View File

@@ -234,6 +234,17 @@ export {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,

View File

@@ -471,6 +471,174 @@ export const VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES = Object.freez
blockedKind: "-",
evidence: "MELFA example has current representative coverage and can receive explicit browser diagnostics evidence without unlocking any hard runtime family.",
}),
Object.freeze({
id: "trt-boat-xyzac",
label: "TRT boat XYZAC",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC table-rotary-tilting boat XYZAC demo is already covered as a five-axis representative; this row adds explicit browser diagnostics evidence without changing inventory counts.",
}),
Object.freeze({
id: "trt-xyzac-switchkins",
label: "TRT XYZAC switchkins",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC table-rotary-tilting XYZAC switchkins demo is already a browser representative row; this evidence expansion binds it into release diagnostics only.",
}),
Object.freeze({
id: "trt-boat-xyzbc",
label: "TRT boat XYZBC",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC table-rotary-tilting boat XYZBC demo is already a five-axis representative row and is added as browser diagnostics evidence only.",
}),
Object.freeze({
id: "trt-impeller-7bl-xyzac",
label: "TRT impeller 7 blade XYZAC",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC table-rotary-tilting impeller demo expands the TRT representative diagnostics set without changing inventory promotion state.",
}),
Object.freeze({
id: "trt-xyzac-switchkins-test-1",
label: "TRT XYZAC switchkins test 1",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC XYZAC switchkins test 1 row is already representative coverage and is exposed as browser diagnostics evidence only.",
}),
Object.freeze({
id: "trt-xyzac-switchkins-test-2",
label: "TRT XYZAC switchkins test 2",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC XYZAC switchkins test 2 row is already representative coverage and is exposed as browser diagnostics evidence only.",
}),
Object.freeze({
id: "trt-xyzac-switchkins-test-3",
label: "TRT XYZAC switchkins test 3",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC XYZAC switchkins test 3 row is already representative coverage and is exposed as browser diagnostics evidence only.",
}),
Object.freeze({
id: "trt-xyzbc-switchkins",
label: "TRT XYZBC switchkins",
simConfigTarget: "five-axis-trt",
sourceFiles: Object.freeze([
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
]),
iniPath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
gcodePath: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
currentNodeInventoryStatus: "PASS",
currentMatrixBrowserStatus: "REP",
dependencyClass: "hal_process,halui_mdi_process,ui_process",
targetBrowserEvidence: "browser-diagnostics-expansion",
promotionAllowed: false,
blockedKind: "-",
evidence: "The LinuxCNC XYZBC switchkins demo completes the current TRT representative diagnostics batch without changing inventory promotion state.",
}),
]);
export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
@@ -3329,6 +3497,30 @@ export function createVirtualHalSimConfigEvidenceExpansionReport(options = {}) {
const blockedCandidateIds = rows.filter((row) => row.blockedKind !== "-").map((row) => row.id);
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
const missingRequiredReports = [...new Set(rows.flatMap((row) => row.missingRequiredReports))];
const familyRows = [...new Set(rows.map((row) => row.simConfigTarget ?? row.id))].map((familyId) => {
const familyCandidates = rows.filter((row) => (row.simConfigTarget ?? row.id) === familyId);
const completeCount = familyCandidates.filter((row) => row.complete).length;
const readyBrowserDiagnosticsCount = familyCandidates
.filter((row) => row.targetBrowserEvidence === "browser-diagnostics-expansion").length;
const promotionAllowedCount = familyCandidates.filter((row) => row.promotionAllowed).length;
const sourceFiles = [...new Set(familyCandidates.flatMap((row) => row.sourceFiles))];
const gcodePaths = [...new Set(familyCandidates.map((row) => row.gcodePath).filter(Boolean))];
const iniPaths = [...new Set(familyCandidates.map((row) => row.iniPath).filter(Boolean))];
return {
id: familyId,
candidateIds: familyCandidates.map((row) => row.id),
candidateCount: familyCandidates.length,
completeCount,
readyBrowserDiagnosticsCount,
browserDiagnosticsExpansionReady: readyBrowserDiagnosticsCount === familyCandidates.length,
promotionAllowedCount,
complete: completeCount === familyCandidates.length,
sourceFiles,
sourceFileCount: sourceFiles.length,
gcodePaths,
iniPaths,
};
});
const complete = rows.length > 0 &&
missingCandidates.length === 0 &&
promotionAllowedViolations.length === 0 &&
@@ -3355,10 +3547,12 @@ export function createVirtualHalSimConfigEvidenceExpansionReport(options = {}) {
blockedCandidateIds,
missingManifestFiles,
missingRequiredReports,
familyRows,
rows,
summaryRows: [
{ id: "candidates", label: "Expansion candidates", value: `${rows.length}` },
{ id: "ready-candidates", label: "Ready candidates", value: `${rows.filter((row) => row.complete).length}` },
{ id: "families", label: "Expansion families", value: `${familyRows.length}` },
{ id: "promotion-allowed", label: "Promotion allowed", value: "0" },
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" },
],

View File

@@ -138,6 +138,35 @@ function createPromotionFamilySummaryRows(candidateReport = {}) {
});
}
function createEvidenceExpansionFamilySummaryRows(evidenceExpansionReport = {}) {
return arrayOrEmpty(objectOrEmpty(evidenceExpansionReport).familyRows).map((family) => {
const candidateCount = family.candidateCount ?? 0;
const completeCount = family.completeCount ?? 0;
const sourceFileCount = family.sourceFileCount ?? arrayOrEmpty(family.sourceFiles).length;
const ready = family.complete === true && family.browserDiagnosticsExpansionReady === true;
return {
id: family.id ?? "unknown",
label: family.id ?? "Unknown evidence expansion family",
value: `${completeCount}/${candidateCount} ready; sources=${sourceFileCount}; diagnostics=${ready ? "ready" : "blocked"}`,
candidateIds: arrayOrEmpty(family.candidateIds),
sourceFiles: arrayOrEmpty(family.sourceFiles),
gcodePaths: arrayOrEmpty(family.gcodePaths),
iniPaths: arrayOrEmpty(family.iniPaths),
candidateCount,
completeCount,
sourceFileCount,
ready,
};
});
}
function createEvidenceExpansionFamilySummaryText(evidenceExpansionReport = {}) {
const rows = createEvidenceExpansionFamilySummaryRows(evidenceExpansionReport);
return rows.length > 0
? rows.map((row) => `${row.id}: ${row.completeCount}/${row.candidateCount} ${row.ready ? "ready" : "blocked"}`).join("; ")
: "not provided";
}
function createPromotionCandidateArtifactSummary({
candidateReport = {},
evidenceExpansionReport = {},
@@ -161,6 +190,8 @@ function createPromotionCandidateArtifactSummary({
const artifactInventoryReadyRows = candidateArtifactRows
.filter((row) => row.candidate_kind === "inventory-ready");
const artifactEvidenceReadyCount = artifactEvidenceReadyRows.length;
const evidenceExpansionFamilyRows = createEvidenceExpansionFamilySummaryRows(evidenceExpansionReport);
const evidenceExpansionFamilySummary = createEvidenceExpansionFamilySummaryText(evidenceExpansionReport);
const inventoryReadyCount = artifactInventoryReadyRows.length > 0
? artifactInventoryReadyRows.length
: 2;
@@ -269,6 +300,9 @@ function createPromotionCandidateArtifactSummary({
promotionAllowedCount: 0,
baselineChanging: false,
nextEvidence: "browser-diagnostics-binding",
familyCount: evidenceExpansionFamilyRows.length,
familySummary: evidenceExpansionFamilySummary,
familyRows: evidenceExpansionFamilyRows,
},
};
}
@@ -462,6 +496,86 @@ const REQUIRED_EVIDENCE_EXPANSION_CANDIDATES = [
"linuxcnc/configs/sim/axis/vismach/melfa-sim/remap_subs/428remap.ngc",
],
},
{
id: "trt-boat-xyzac",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-xyzac-switchkins",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-boat-xyzbc",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-impeller-7bl-xyzac",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-xyzac-switchkins-test-1",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-xyzac-switchkins-test-2",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-xyzac-switchkins-test-3",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
{
id: "trt-xyzbc-switchkins",
sourceFiles: [
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
],
},
];
const REQUIRED_MACRO_LOAD_FIXTURES = [
@@ -664,8 +778,8 @@ function isVirtualHalSimConfigEvidenceExpansionReportReady(report) {
expansionReport.webSimulationSatisfied === true &&
expansionReport.inventoryBaselineUnchanged === true &&
expansionReport.promotionAllowed === false &&
expansionReport.candidateCount === 3 &&
expansionReport.readyCandidateCount === 3 &&
expansionReport.candidateCount === REQUIRED_EVIDENCE_EXPANSION_CANDIDATES.length &&
expansionReport.readyCandidateCount === REQUIRED_EVIDENCE_EXPANSION_CANDIDATES.length &&
arrayOrEmpty(expansionReport.missingCandidates).length === 0 &&
arrayOrEmpty(expansionReport.promotionAllowedViolations).length === 0 &&
arrayOrEmpty(expansionReport.blockedCandidateIds).length === 0 &&
@@ -3203,8 +3317,13 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
const evidenceExpansionRows = arrayOrEmpty(
workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows,
);
const evidenceExpansionFamilyRows = arrayOrEmpty(
promotionCandidateArtifactSummary.evidenceExpansion?.familyRows
?? workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows,
);
const preferredEvidenceExpansion = evidenceExpansionRows[0] ?? {};
const evidenceExpansionPreviewRows = evidenceExpansionRows.slice(0, 3);
const evidenceExpansionFullRows = evidenceExpansionRows;
const ready = workflow?.ready === true;
const statusText = ready ? "Ready" : "Blocked";
const detailText = ready
@@ -3366,6 +3485,48 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
).join(", ")
: "not provided",
},
{
id: "evidence-expansion-full-candidate-list",
label: "Evidence expansion full candidate list",
value: evidenceExpansionFullRows.length > 0
? evidenceExpansionFullRows.map((row) => row.id).join(", ")
: "not provided",
},
{
id: "evidence-expansion-full-gcode-list",
label: "Evidence expansion full G-code list",
value: evidenceExpansionFullRows.length > 0
? evidenceExpansionFullRows.map((row) => row.gcodePath).join(", ")
: "not provided",
},
{
id: "evidence-expansion-family-count",
label: "Evidence expansion family count",
value: evidenceExpansionFamilyRows.length > 0
? `${evidenceExpansionFamilyRows.length} families`
: "not provided",
},
{
id: "evidence-expansion-family-summary",
label: "Evidence expansion family summary",
value: promotionCandidateArtifactSummary.evidenceExpansion?.familySummary
?? createEvidenceExpansionFamilySummaryText(workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion),
},
{
id: "evidence-expansion-family-source-count-list",
label: "Evidence expansion family source counts",
value: evidenceExpansionFamilyRows.length > 0
? evidenceExpansionFamilyRows.map((row) => `${row.id}:${row.sourceFileCount ?? arrayOrEmpty(row.sourceFiles).length}`).join(", ")
: "not provided",
},
...evidenceExpansionFamilyRows.map((row) => ({
id: `evidence-expansion-family-${row.id}`,
label: `Evidence expansion family ${row.label ?? row.id}`,
value: row.value ?? `${row.completeCount ?? 0}/${row.candidateCount ?? 0} ready; sources=${row.sourceFileCount ?? arrayOrEmpty(row.sourceFiles).length}`,
candidateIds: arrayOrEmpty(row.candidateIds),
sourceFiles: arrayOrEmpty(row.sourceFiles),
gcodePaths: arrayOrEmpty(row.gcodePaths),
})),
{
id: "evidence-expansion-artifact",
label: "Evidence expansion artifact",

View File

@@ -219,6 +219,17 @@ export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntr
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -1942,6 +1953,17 @@ export function createIniPanelShellWorkflowOverviewContract() {
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -2600,12 +2622,21 @@ export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWo
?? workflow?.urlWorkflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows
?? []
);
const evidenceExpansionFamilyRows = (
promotionCandidateArtifactSummary.evidenceExpansion?.familyRows
?? workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows
?? workflow?.urlWorkflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows
?? []
);
const preferredEvidenceExpansion = Array.isArray(evidenceExpansionRows)
? (evidenceExpansionRows[0] ?? {})
: {};
const evidenceExpansionPreviewRows = Array.isArray(evidenceExpansionRows)
? evidenceExpansionRows.slice(0, 3)
: [];
const evidenceExpansionFullRows = Array.isArray(evidenceExpansionRows)
? evidenceExpansionRows
: [];
const ready = workflow?.ready === true;
const promotionFamilyRows = (
workflow?.validation?.virtualHalPromotionFamilyRows
@@ -2800,6 +2831,54 @@ export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWo
).join(", ")
: "not provided",
},
{
id: "evidence-expansion-full-candidate-list",
label: "Evidence expansion full candidate list",
value: evidenceExpansionFullRows.length > 0
? evidenceExpansionFullRows.map((row) => row.id).join(", ")
: "not provided",
},
{
id: "evidence-expansion-full-gcode-list",
label: "Evidence expansion full G-code list",
value: evidenceExpansionFullRows.length > 0
? evidenceExpansionFullRows.map((row) => row.gcodePath).join(", ")
: "not provided",
},
{
id: "evidence-expansion-family-count",
label: "Evidence expansion family count",
value: Array.isArray(evidenceExpansionFamilyRows) && evidenceExpansionFamilyRows.length > 0
? `${evidenceExpansionFamilyRows.length} families`
: "not provided",
},
{
id: "evidence-expansion-family-summary",
label: "Evidence expansion family summary",
value: evidenceExpansion.familySummary ?? (Array.isArray(evidenceExpansionFamilyRows) && evidenceExpansionFamilyRows.length > 0
? evidenceExpansionFamilyRows.map((row) => {
const ready = row.ready === true || (row.complete === true && row.browserDiagnosticsExpansionReady === true);
return `${row.id}: ${row.completeCount ?? 0}/${row.candidateCount ?? 0} ${ready ? "ready" : "blocked"}`;
}).join("; ")
: "not provided"),
},
{
id: "evidence-expansion-family-source-count-list",
label: "Evidence expansion family source counts",
value: Array.isArray(evidenceExpansionFamilyRows) && evidenceExpansionFamilyRows.length > 0
? evidenceExpansionFamilyRows.map((row) =>
`${row.id}:${row.sourceFileCount ?? (Array.isArray(row.sourceFiles) ? row.sourceFiles.length : 0)}`
).join(", ")
: "not provided",
},
...(Array.isArray(evidenceExpansionFamilyRows) ? evidenceExpansionFamilyRows.map((row) => ({
id: `evidence-expansion-family-${row.id}`,
label: `Evidence expansion family ${row.label ?? row.id}`,
value: row.value ?? `${row.completeCount ?? 0}/${row.candidateCount ?? 0} ready; sources=${row.sourceFileCount ?? (Array.isArray(row.sourceFiles) ? row.sourceFiles.length : 0)}`,
candidateIds: Array.isArray(row.candidateIds) ? row.candidateIds : [],
sourceFiles: Array.isArray(row.sourceFiles) ? row.sourceFiles : [],
gcodePaths: Array.isArray(row.gcodePaths) ? row.gcodePaths : [],
})) : []),
{
id: "hard-block-runtime-lock",
label: "Hard-block runtime lock",
@@ -3343,6 +3422,77 @@ export function createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderStat
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(
summaryViewModel = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(),
) {
const summaryRows = Array.isArray(summaryViewModel?.rows) ? summaryViewModel.rows : [];
const rows = summaryRows
.filter(({ id }) => String(id).startsWith("evidence-expansion-family-"))
.filter(({ sourceFiles, gcodePaths }) => Array.isArray(sourceFiles) && Array.isArray(gcodePaths))
.map(({ id, label, value, sourceFiles, gcodePaths, candidateIds }) => {
const familySourceFiles = Array.isArray(sourceFiles) ? sourceFiles : [];
const familyGcodePaths = Array.isArray(gcodePaths) ? gcodePaths : [];
const familyCandidateIds = Array.isArray(candidateIds) ? candidateIds : [];
const sourceKindCounts = countPromotionFamilySourceKinds(familySourceFiles);
const sourceKindSummary = formatPromotionFamilySourceKindCounts(sourceKindCounts);
return {
id,
label,
value: value == null ? "" : String(value),
sourceFiles: familySourceFiles,
gcodePaths: familyGcodePaths,
candidateIds: familyCandidateIds,
sourceKindCounts,
sourceKindSummary,
};
});
const sourceRows = rows.flatMap((row) =>
row.sourceFiles.map((sourceFile, index) => ({
id: `${row.id}-source-${index + 1}`,
familyId: row.id,
label: `Source ${index + 1}`,
value: sourceFile,
sourceKind: classifyPromotionFamilySource(sourceFile),
manifestBacked: true,
status: "evidence-expansion-source",
}))
);
const candidateRows = rows.flatMap((row) =>
row.gcodePaths.map((gcodePath, index) => ({
id: `${row.id}-candidate-${index + 1}`,
familyId: row.id,
label: row.candidateIds[index] ?? `Candidate ${index + 1}`,
value: gcodePath,
candidateStatus: "evidence-expansion-ready",
promotionAllowed: false,
baselineChanging: false,
sourceKind: "gcode",
manifestBacked: true,
}))
);
const ready = rows.length > 0 && rows.every(({ value }) => String(value).includes("diagnostics=ready"));
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-rows-render-state",
renderStateVersion: 1,
phase: ready ? "ready" : "blocked",
ready,
title: "Evidence expansion family diagnostics",
statusText: ready ? "Ready" : "Blocked",
detailText: ready ? `${rows.length} evidence expansion families ready` : "evidence expansion family rows missing",
statusLine: `${ready ? "Ready" : "Blocked"}: ${ready ? `${rows.length} evidence expansion families ready` : "evidence expansion family rows missing"}`,
rows,
sourceRows,
candidateRows,
sourceFileCount: sourceRows.length,
candidateCount: candidateRows.length,
dataset: {
handoffPhase: ready ? "ready" : "blocked",
handoffReady: ready ? "true" : "false",
handoffScope: "workflow-overview-evidence-expansion-family-rows",
},
};
}
export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
{ sourceKind = "all", familyId = "all" } = {},
@@ -3437,6 +3587,88 @@ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterVi
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(
renderState = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(),
{ sourceKind = "all", familyId = "all" } = {},
) {
const viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
renderState,
{ sourceKind, familyId },
);
return {
...viewModel,
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-view-model",
detailText: viewModel.ready
? `${viewModel.filteredSourceFileCount}/${viewModel.totalSourceFileCount} source files selected`
: "evidence expansion source rows missing",
statusLine: `${viewModel.ready ? "Ready" : "Blocked"}: ${viewModel.ready ? `${viewModel.filteredSourceFileCount}/${viewModel.totalSourceFileCount} source files selected` : "evidence expansion source rows missing"}`,
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary(
viewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(),
) {
const familyRows = Array.isArray(viewModel?.familyRows) ? viewModel.familyRows : [];
const sourceRows = Array.isArray(viewModel?.sourceRows) ? viewModel.sourceRows : [];
const candidateRows = Array.isArray(viewModel?.candidateRows) ? viewModel.candidateRows : [];
const selectedFamilyId = viewModel?.selectedFamilyId ?? "all";
const selectedSourceKind = viewModel?.selectedSourceKind ?? "all";
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-summary",
summaryVersion: 1,
phase: viewModel?.ready === true ? "ready" : "blocked",
ready: viewModel?.ready === true,
selectedFamilyId,
selectedSourceKind,
filteredSourceFileCount: viewModel?.filteredSourceFileCount ?? sourceRows.length,
scopedSourceFileCount: viewModel?.scopedSourceFileCount ?? sourceRows.length,
totalSourceFileCount: viewModel?.totalSourceFileCount ?? sourceRows.length,
filteredCandidateCount: viewModel?.filteredCandidateCount ?? candidateRows.length,
totalCandidateCount: viewModel?.totalCandidateCount ?? candidateRows.length,
familyCount: familyRows.length,
sourceKinds: [...new Set(sourceRows.map((row) => row.sourceKind).filter(Boolean))],
familyIds: familyRows.map((row) => row.id),
candidateIds: candidateRows.map((row) => row.label ?? row.id),
gcodePaths: candidateRows.map((row) => row.value).filter(Boolean),
sourceFiles: sourceRows.map((row) => row.value).filter(Boolean),
statusLine: viewModel?.ready === true
? `Ready: ${selectedFamilyId} / ${selectedSourceKind} selects ${viewModel?.filteredSourceFileCount ?? sourceRows.length}/${viewModel?.totalSourceFileCount ?? sourceRows.length} source files`
: "Blocked: evidence expansion source filter summary missing",
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan(
summary = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary(),
) {
const ready = summary?.ready === true;
const selectedFamilyId = summary?.selectedFamilyId ?? "all";
const selectedSourceKind = summary?.selectedSourceKind ?? "all";
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-action-plan",
actionPlanVersion: 1,
phase: ready ? "ready" : "blocked",
ready,
selectedFamilyId,
selectedSourceKind,
filteredSourceFileCount: summary?.filteredSourceFileCount ?? 0,
filteredCandidateCount: summary?.filteredCandidateCount ?? 0,
promotionAllowed: false,
baselineChanging: false,
nextCommand: ready ? null : "mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
nextSteps: ready
? []
: [
"Load a release readiness artifact URL workflow summary.",
"Create evidence expansion family rows render state.",
"Mount the evidence expansion family/source filter DOM.",
],
statusLine: ready
? `Ready: evidence expansion filter ${selectedFamilyId} / ${selectedSourceKind} is externally readable`
: "Blocked: evidence expansion filter summary is not ready",
summary,
};
}
export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract({
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter",
selectors = {},
@@ -3479,6 +3711,21 @@ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDo
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
selectors = {},
} = {}) {
return createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract({
rowDatasetPrefix,
selectors: {
mount: selectors.mount ?? "[data-workflow-overview-evidence-expansion-family-source-filter]",
status: selectors.status ?? "[data-workflow-overview-evidence-expansion-family-source-filter-status]",
controls: selectors.controls ?? "[data-workflow-overview-evidence-expansion-family-source-filter-controls]",
rows: selectors.rows ?? "[data-workflow-overview-evidence-expansion-family-source-filter-rows]",
},
});
}
export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness({
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract({ rowDatasetPrefix }),
@@ -3511,6 +3758,30 @@ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDo
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness({
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
controlsNode = documentRef?.querySelector?.(contract.selectors.controls),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {}) {
const readiness = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness({
rowDatasetPrefix,
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
});
return {
...readiness,
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-dom-readiness",
};
}
function readPromotionFamilySourceFilterControlValue(
controlsNode,
rowDatasetPrefix,
@@ -3555,6 +3826,39 @@ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSe
};
}
export function createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan(
renderState = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(),
{
familyId = "all",
sourceKind = "all",
previousViewModel = null,
} = {},
) {
const nextViewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(
renderState,
{ familyId, sourceKind },
);
const changed = previousViewModel === null ||
previousViewModel.selectedFamilyId !== nextViewModel.selectedFamilyId ||
previousViewModel.selectedSourceKind !== nextViewModel.selectedSourceKind;
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-selection-action-plan",
actionPlanVersion: 1,
phase: nextViewModel.ready ? "ready" : "blocked",
ready: nextViewModel.ready,
changed,
selectedFamilyId: nextViewModel.selectedFamilyId,
selectedSourceKind: nextViewModel.selectedSourceKind,
filteredSourceFileCount: nextViewModel.filteredSourceFileCount,
scopedSourceFileCount: nextViewModel.scopedSourceFileCount,
totalSourceFileCount: nextViewModel.totalSourceFileCount,
statusLine: changed
? `Ready: evidence expansion source filter changed to ${nextViewModel.selectedFamilyId} / ${nextViewModel.selectedSourceKind}`
: "Ready: evidence expansion source filter unchanged",
nextViewModel,
};
}
export function handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange({
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState),
@@ -3611,6 +3915,62 @@ export function handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSe
};
}
export function handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange({
renderState = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(renderState),
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
controlsNode = documentRef?.querySelector?.(contract.selectors.controls),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
render = false,
} = {}) {
const selectedFamilyId = readPromotionFamilySourceFilterControlValue(
controlsNode,
contract.rowDatasetPrefix,
"family",
viewModel?.selectedFamilyId ?? "all",
);
const selectedSourceKind = readPromotionFamilySourceFilterControlValue(
controlsNode,
contract.rowDatasetPrefix,
"source-kind",
viewModel?.selectedSourceKind ?? "all",
);
const actionPlan = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan(
renderState,
{
familyId: selectedFamilyId,
sourceKind: selectedSourceKind,
previousViewModel: viewModel,
},
);
const renderResult = render
? renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(actionPlan.nextViewModel, {
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
})
: null;
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-selection-change",
workflowVersion: 1,
phase: actionPlan.phase,
ready: actionPlan.ready,
statusLine: actionPlan.statusLine,
selectedFamilyId: actionPlan.selectedFamilyId,
selectedSourceKind: actionPlan.selectedSourceKind,
actionPlan,
viewModel: actionPlan.nextViewModel,
renderResult,
};
}
export function bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls({
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState),
@@ -3703,6 +4063,98 @@ export function bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSele
return binding;
}
export function bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls({
renderState = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(renderState),
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
controlsNode = documentRef?.querySelector?.(contract.selectors.controls),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
render = true,
onChange = null,
} = {}) {
const domReadiness = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness({
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
});
const selectNodes = Array.from(controlsNode?.children ?? [])
.filter((node) => typeof node?.dataset?.[`${contract.rowDatasetPrefix}Select`] === "string");
if (!domReadiness.ready || selectNodes.length === 0) {
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-selection-controls-binding",
bindingVersion: 1,
phase: "blocked",
ready: false,
statusLine: `Blocked: ${domReadiness.ready ? "selector controls missing" : domReadiness.missing.join(", ")}`,
boundControlCount: 0,
controlIds: [],
domReadiness,
lastChange: null,
triggerChange: () => null,
unbind: () => ({ unbound: 0 }),
};
}
const binding = {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-selection-controls-binding",
bindingVersion: 1,
phase: "ready",
ready: true,
statusLine: `Ready: ${selectNodes.length} selector controls bound`,
boundControlCount: selectNodes.length,
controlIds: selectNodes.map((node) => node.dataset[`${contract.rowDatasetPrefix}Select`]),
domReadiness,
lastChange: null,
triggerChange: null,
unbind: null,
};
const handleChange = () => {
const changeResult = handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange({
renderState,
viewModel,
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
render,
});
binding.lastChange = changeResult;
if (typeof onChange === "function") {
onChange(changeResult);
}
return changeResult;
};
const unbinders = selectNodes.map((node) => {
if (typeof node.addEventListener === "function") {
node.addEventListener("change", handleChange);
return () => node.removeEventListener?.("change", handleChange);
}
node.onchange = handleChange;
return () => {
if (node.onchange === handleChange) {
node.onchange = null;
}
};
});
binding.triggerChange = handleChange;
binding.unbind = () => {
for (const unbind of unbinders) {
unbind();
}
return { unbound: unbinders.length };
};
return binding;
}
export function renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(),
{
@@ -3875,6 +4327,32 @@ export function renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSt
};
}
export function renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(
viewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(),
{
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
controlsNode = documentRef?.querySelector?.(contract.selectors.controls),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {},
) {
const renderResult = renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(viewModel, {
rowDatasetPrefix,
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
});
mountNode.dataset.handoffScope = "workflow-overview-evidence-expansion-family-source-filter";
renderResult.dataset.handoffScope = mountNode.dataset.handoffScope;
return renderResult;
}
export function mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState({
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(),
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter",
@@ -3945,6 +4423,76 @@ export function mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSta
}
}
export function mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState({
viewModel = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(),
rowDatasetPrefix = "workflowOverviewEvidenceExpansionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
controlsNode = documentRef?.querySelector?.(contract.selectors.controls),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {}) {
const domReadiness = createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness({
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
});
if (!domReadiness.ready) {
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-dom-mount",
workflowVersion: 1,
phase: "blocked",
ready: false,
statusLine: `Blocked: ${domReadiness.missing.join(", ")}`,
contract,
domReadiness,
viewModel,
renderResult: null,
error: null,
};
}
try {
const renderResult = renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(viewModel, {
contract,
documentRef,
mountNode,
statusNode,
controlsNode,
rowsNode,
});
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-dom-mount",
workflowVersion: 1,
phase: viewModel?.phase === "ready" ? "ready" : "blocked",
ready: viewModel?.ready === true,
statusLine: renderResult.statusLine,
contract,
domReadiness,
viewModel,
renderResult,
error: null,
};
} catch (error) {
return {
apiName: "ini-panel-shell-workflow-overview-evidence-expansion-family-source-filter-dom-mount",
workflowVersion: 1,
phase: "blocked",
ready: false,
statusLine: `Blocked: ${error?.message ?? "evidence expansion source filter DOM mount error"}`,
contract,
domReadiness,
viewModel,
renderResult: null,
error: error?.message ?? String(error),
};
}
}
export function createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract({
rowDatasetPrefix = "workflowOverviewPromotionFamily",
selectors = {},
@@ -6835,6 +7383,28 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
createWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState:
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createWorkflowOverviewEvidenceExpansionFamilyRowsRenderState:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange:
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls:
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState:
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState:
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createWorkflowOverviewPromotionFamilyRowsRenderState:
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createWorkflowOverviewPromotionFamilySourceFilterViewModel:

View File

@@ -162,6 +162,11 @@
<div class="source-filter-controls" data-workflow-overview-promotion-family-source-filter-controls></div>
<dl data-workflow-overview-promotion-family-source-filter-rows></dl>
</section>
<section class="overview-status" aria-label="Evidence expansion family source filter" data-workflow-overview-evidence-expansion-family-source-filter>
<p data-workflow-overview-evidence-expansion-family-source-filter-status>Waiting for evidence expansion family source evidence.</p>
<div class="source-filter-controls" data-workflow-overview-evidence-expansion-family-source-filter-controls></div>
<dl data-workflow-overview-evidence-expansion-family-source-filter-rows></dl>
</section>
</section>
</main>
<script type="module">
@@ -205,6 +210,17 @@
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
@@ -256,6 +272,20 @@
const browserDiagnosticsUrlInput = document.querySelector("[data-browser-diagnostics-url-input]");
const releaseArtifactUrlWorkflowForm = document.querySelector("[data-release-artifact-url-workflow-form]");
function getWorkflowOverviewEvidenceExpansionFilterPreset(locationRef = window.location) {
const searchParams = new URLSearchParams(locationRef?.search ?? "");
const hashText = String(locationRef?.hash ?? "").replace(/^#/, "");
const hashParams = new URLSearchParams(hashText);
return {
familyId: searchParams.get("evidenceExpansionFamily") ??
hashParams.get("evidenceExpansionFamily") ??
"all",
sourceKind: searchParams.get("evidenceExpansionSourceKind") ??
hashParams.get("evidenceExpansionSourceKind") ??
"all",
};
}
async function runWorkflowOverviewReleaseReadinessArtifactUrlForm(options = {}) {
const artifactUrl = String(options.artifactUrl ?? releaseArtifactUrlInput?.value ?? "").trim();
const diagnosticsUrl = String(options.diagnosticsUrl ?? browserDiagnosticsUrlInput?.value ?? "").trim();
@@ -326,7 +356,45 @@
document.body.dataset.promotionFamilySourceFilterSourceKind =
changeResult.selectedSourceKind;
document.body.dataset.promotionFamilySourceFilterCount =
String(changeResult.actionPlan.filteredSourceFileCount);
},
});
const evidenceExpansionFamilyRowsRenderState =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(summary);
const evidenceExpansionFamilySourceFilter =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(
evidenceExpansionFamilyRowsRenderState,
options.evidenceExpansionFilterPreset ??
getWorkflowOverviewEvidenceExpansionFilterPreset(window.location),
);
const evidenceExpansionFamilySourceFilterSummary =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary(
evidenceExpansionFamilySourceFilter,
);
const evidenceExpansionFamilySourceFilterActionPlan =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan(
evidenceExpansionFamilySourceFilterSummary,
);
const evidenceExpansionFamilySourceFilterMountResult =
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState({
viewModel: evidenceExpansionFamilySourceFilter,
documentRef: document,
});
const evidenceExpansionFamilySourceFilterBinding =
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls({
renderState: evidenceExpansionFamilyRowsRenderState,
viewModel: evidenceExpansionFamilySourceFilter,
documentRef: document,
render: true,
onChange: (changeResult) => {
document.body.dataset.evidenceExpansionFamilySourceFilterFamily =
changeResult.selectedFamilyId;
document.body.dataset.evidenceExpansionFamilySourceFilterSourceKind =
changeResult.selectedSourceKind;
document.body.dataset.evidenceExpansionFamilySourceFilterCount =
String(changeResult.actionPlan.filteredSourceFileCount);
document.body.dataset.evidenceExpansionFamilySourceFilterSummary =
changeResult.actionPlan.statusLine;
},
});
document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase;
@@ -337,6 +405,16 @@
promotionFamilySourceFilter.ready ? "true" : "false";
document.body.dataset.promotionFamilySourceFilterCount =
String(promotionFamilySourceFilter.filteredSourceFileCount);
document.body.dataset.evidenceExpansionFamilySourceFilterReady =
evidenceExpansionFamilySourceFilter.ready ? "true" : "false";
document.body.dataset.evidenceExpansionFamilySourceFilterFamily =
evidenceExpansionFamilySourceFilter.selectedFamilyId;
document.body.dataset.evidenceExpansionFamilySourceFilterSourceKind =
evidenceExpansionFamilySourceFilter.selectedSourceKind;
document.body.dataset.evidenceExpansionFamilySourceFilterCount =
String(evidenceExpansionFamilySourceFilter.filteredSourceFileCount);
document.body.dataset.evidenceExpansionFamilySourceFilterSummary =
evidenceExpansionFamilySourceFilterActionPlan.statusLine;
return {
workflow,
summary,
@@ -355,6 +433,12 @@
promotionFamilySourceFilter,
promotionFamilySourceFilterMountResult,
promotionFamilySourceFilterBinding,
evidenceExpansionFamilyRowsRenderState,
evidenceExpansionFamilySourceFilter,
evidenceExpansionFamilySourceFilterSummary,
evidenceExpansionFamilySourceFilterActionPlan,
evidenceExpansionFamilySourceFilterMountResult,
evidenceExpansionFamilySourceFilterBinding,
};
}
@@ -459,6 +543,50 @@
getWorkflowOverviewPromotionFamilyRowsRenderState: (summaryViewModel) => (
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(summaryViewModel)
),
getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState: (summaryViewModel) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(summaryViewModel)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel: (renderState, options) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(renderState, options)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract: (options) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract(options)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness: (options) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness(
options ?? { documentRef: document },
)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary: (viewModel) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary(viewModel)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan: (summary) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan(summary)
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan: (renderState, options) => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan(renderState, options)
),
handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange: (options) => (
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange(
options ?? { documentRef: document },
)
),
bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls: (options) => (
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls(
options ?? { documentRef: document },
)
),
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState: (viewModel, options) => (
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(
viewModel,
options ?? { documentRef: document },
)
),
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState: (options) => (
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(
options ?? { documentRef: document },
)
),
getWorkflowOverviewPromotionFamilySourceFilterViewModel: (renderState, options) => (
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState, options)
),

View File

@@ -1757,6 +1757,7 @@ M2
<div><span>Shortcut</span><strong data-diagnostics="shortcut">-</strong></div>
<div class="promotion-family-panel" data-promotion-family-rows></div>
<div class="promotion-candidate-panel" data-promotion-candidate-summary></div>
<div class="promotion-candidate-panel" data-evidence-expansion-summary></div>
<div class="tool-table-mini" data-axis-shell="tool-table">
<table aria-label="Loaded tool table">
<thead>
@@ -2788,6 +2789,86 @@ M2
return summary;
}
function createVirtualHalEvidenceExpansionSummary(
report = createVirtualHalSimConfigEvidenceExpansionReport(),
) {
const rows = Array.isArray(report.rows) ? report.rows : [];
const familyRows = Array.isArray(report.familyRows) ? report.familyRows : [];
const readyRows = rows.filter((row) => row.complete === true);
const blockedRows = rows.filter((row) => row.complete !== true);
const promotionAllowedRows = rows.filter((row) => row.promotionAllowed === true);
const preferredRow = rows[0] ?? null;
const familySummary = familyRows.length > 0
? familyRows.map((row) => {
const readyFamily = row.complete === true && row.browserDiagnosticsExpansionReady === true;
return `${row.id}: ${row.completeCount ?? 0}/${row.candidateCount ?? 0} ${readyFamily ? "ready" : "blocked"}`;
}).join("; ")
: "missing";
const ready = report.complete === true &&
report.inventoryBaselineUnchanged === true &&
report.promotionAllowed === false &&
readyRows.length === rows.length &&
blockedRows.length === 0 &&
promotionAllowedRows.length === 0;
return {
apiName: "real-browser-simulation-evidence-expansion-summary",
summaryVersion: 1,
phase: ready ? "ready" : "blocked",
ready,
candidateCount: rows.length,
readyCandidateCount: readyRows.length,
preferredCandidateId: preferredRow?.id ?? null,
candidateIds: rows.map((row) => row.id),
gcodePaths: rows.map((row) => row.gcodePath),
familyRows,
familyCount: familyRows.length,
familySummary,
sourceFileCount: new Set(rows.flatMap((row) => row.sourceFiles ?? [])).size,
promotionAllowedCount: promotionAllowedRows.length,
inventoryBaselineUnchanged: report.inventoryBaselineUnchanged === true,
rows: [
{ id: "candidate-count", label: "Expansion", value: `${readyRows.length}/${rows.length} ready` },
{ id: "preferred-candidate", label: "First case", value: preferredRow?.id ?? "missing" },
{ id: "candidate-list", label: "Cases", value: rows.map((row) => row.id).join(", ") || "missing" },
{ id: "family-count", label: "Families", value: `${familyRows.length}` },
{ id: "family-summary", label: "Family summary", value: familySummary },
{
id: "family-source-count-list",
label: "Family source counts",
value: familyRows.length > 0
? familyRows.map((row) => `${row.id}:${row.sourceFileCount ?? row.sourceFiles?.length ?? 0}`).join(", ")
: "missing",
},
{ id: "source-files", label: "Source files", value: `${new Set(rows.flatMap((row) => row.sourceFiles ?? [])).size}` },
{ id: "promotion-allowed", label: "Allowed", value: `${promotionAllowedRows.length} baseline changes` },
{ id: "inventory-baseline", label: "Inventory", value: report.inventoryBaselineUnchanged === true ? "unchanged" : "changing" },
],
};
}
function renderEvidenceExpansionSummary(summary = createVirtualHalEvidenceExpansionSummary()) {
const container = document.querySelector("[data-evidence-expansion-summary]");
if (!container) {
return summary;
}
container.textContent = "";
document.body.dataset.evidenceExpansionReady = summary.ready ? "true" : "false";
document.body.dataset.evidenceExpansionCount = String(summary.candidateCount);
document.body.dataset.evidenceExpansionReadyCount = String(summary.readyCandidateCount);
for (const row of summary.rows) {
const item = document.createElement("div");
item.dataset.evidenceExpansionSummaryRow = row.id;
const label = document.createElement("span");
label.textContent = row.label;
const value = document.createElement("strong");
value.dataset.evidenceExpansionSummaryValue = row.id;
value.textContent = row.value;
item.append(label, value);
container.append(item);
}
return summary;
}
function renderMachineStatusDom(machineStatus) {
const statusMap = {
"spindle-state": machineStatus.spindle.state,
@@ -2828,8 +2909,10 @@ M2
renderLimitsHomeState(createVirtualHalLimitsHomeState());
renderMillturnUserMProcessState();
const promotionCandidateReport = createVirtualHalSimConfigPromotionCandidateReport();
const evidenceExpansionReport = createVirtualHalSimConfigEvidenceExpansionReport();
renderPromotionFamilyRows(promotionCandidateReport);
renderPromotionCandidateSummary(createVirtualHalPromotionCandidateSummary(promotionCandidateReport));
renderEvidenceExpansionSummary(createVirtualHalEvidenceExpansionSummary(evidenceExpansionReport));
document.querySelector("[data-axis-machine-control-state]")?.setAttribute("data-state", "ready");
return cloneVirtualHalState();
}
@@ -4333,6 +4416,7 @@ M2
getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(),
getVirtualHalSimConfigPromotionCandidateReport: () => createVirtualHalSimConfigPromotionCandidateReport(),
getVirtualHalSimConfigEvidenceExpansionReport: () => createVirtualHalSimConfigEvidenceExpansionReport(),
getVirtualHalEvidenceExpansionSummary: () => renderEvidenceExpansionSummary(),
getVirtualHalPromotionCandidateSummary: () => renderPromotionCandidateSummary(),
getVirtualHalPromotionFamilyRows: () => renderPromotionFamilyRows(),
getVirtualHalSimConfigMacroLoadFixtureReport: () => createVirtualHalSimConfigMacroLoadFixtureReport(),

View File

@@ -244,7 +244,7 @@ TOOL_TABLE = browser-shell-tool.tbl
"shell handoff action-plan next steps",
);
assertEqual(handoffChecklist.ready, true, "shell handoff checklist readiness");
assertEqual(handoffChecklist.checks.length, 5, "shell handoff checklist checks");
assertEqual(handoffChecklist.checks.length, 11, "shell handoff checklist checks");
assertEqual(
handoffChecklist.checks.map(({ status }) => status).join(","),
"pass,pass,pass,pass,pass",
@@ -1039,6 +1039,31 @@ TOOL_TABLE = browser-shell-tool.tbl
"3, 3, 3",
"shell workflow overview release artifact URL workflow evidence expansion source count list",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-candidate-list")?.value,
"woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins",
"shell workflow overview release artifact URL workflow evidence expansion full candidate list",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-gcode-list")?.value,
"linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"shell workflow overview release artifact URL workflow evidence expansion full gcode list",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-count")?.value,
"3 families",
"shell workflow overview release artifact URL workflow evidence expansion family count",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-summary")?.value,
"woodpecker: 1/1 ready; vismach-remap-sims: 2/2 ready; five-axis-trt: 8/8 ready",
"shell workflow overview release artifact URL workflow evidence expansion family summary",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-source-count-list")?.value,
"woodpecker:3, vismach-remap-sims:6, five-axis-trt:12",
"shell workflow overview release artifact URL workflow evidence expansion family source count",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowRenderResult.rowIds.includes("hard-block-runtime-lock"),
true,

View File

@@ -9,6 +9,7 @@
<script type="module">
import {
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES,
createVirtualHalCommandScriptFixtureReport,
createVirtualHalMillturnUserMProcessBoundaryReport,
createVirtualHalMotionControllerMatrixReport,
@@ -23,6 +24,8 @@
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []);
const VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES.flatMap((candidate) => candidate.sourceFiles ?? []);
function assertEqual(actual, expected, label) {
if (actual !== expected) {
@@ -30,9 +33,11 @@
}
}
async function loadWorkflowOverviewFrame() {
async function loadWorkflowOverviewFrame(
src = "../../runtime/ui/ini-panel/workflow-overview.html",
) {
const frame = document.createElement("iframe");
frame.src = "../../runtime/ui/ini-panel/workflow-overview.html";
frame.src = src;
document.body.appendChild(frame);
await new Promise((resolve, reject) => {
frame.addEventListener("load", resolve, { once: true });
@@ -69,6 +74,17 @@
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.getWorkflowOverviewPromotionFamilyRowsRenderState ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan ||
!workflowApi?.getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan ||
!workflowApi?.handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange ||
!workflowApi?.bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls ||
!workflowApi?.renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState ||
!workflowApi?.mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState ||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterViewModel ||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomContract ||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomReadiness ||
@@ -395,7 +411,7 @@
const diagnosticsEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({
manifestEntries: [
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ini",
...VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES,
],
motionControllerMatrix: diagnosticsMotionControllerMatrix,
});
@@ -736,6 +752,16 @@
"3, 3, 3",
"workflow overview release artifact URL workflow evidence expansion source count list",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-candidate-list")?.value,
"woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins",
"workflow overview release artifact URL workflow evidence expansion full candidate list",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-gcode-list")?.value,
"linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"workflow overview release artifact URL workflow evidence expansion full gcode list",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
@@ -1027,6 +1053,31 @@
"3, 3, 3",
"workflow overview fixed URL workflow form evidence expansion source count list row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-full-candidate-list"]').textContent,
"woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins",
"workflow overview fixed URL workflow form evidence expansion full candidate list row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-full-gcode-list"]').textContent,
"linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"workflow overview fixed URL workflow form evidence expansion full gcode list row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-family-count"]').textContent,
"3 families",
"workflow overview fixed URL workflow form evidence expansion family count row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-family-summary"]').textContent,
"woodpecker: 1/1 ready; vismach-remap-sims: 2/2 ready; five-axis-trt: 8/8 ready",
"workflow overview fixed URL workflow form evidence expansion family summary row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-family-source-count-list"]').textContent,
"woodpecker:3, vismach-remap-sims:6, five-axis-trt:12",
"workflow overview fixed URL workflow form evidence expansion family source count row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-source-file-count"]').textContent,
"17 source files",
@@ -1175,6 +1226,142 @@
"0",
"workflow overview source filter changed rose engine promotion allowed",
);
const evidenceExpansionSourceFilterMount = workflowDoc.querySelector("[data-workflow-overview-evidence-expansion-family-source-filter]");
const evidenceExpansionSourceFilterFamilySelect = workflowDoc.querySelector(
'[data-workflow-overview-evidence-expansion-family-source-filter-select="family"]',
);
const evidenceExpansionSourceFilterKindSelect = workflowDoc.querySelector(
'[data-workflow-overview-evidence-expansion-family-source-filter-select="source-kind"]',
);
assertEqual(
evidenceExpansionSourceFilterMount.dataset.selectedFamilyId,
"all",
"workflow overview evidence expansion source filter default family",
);
assertEqual(
workflowDoc.body.dataset.evidenceExpansionFamilySourceFilterReady,
"true",
"workflow overview evidence expansion source filter ready",
);
assertEqual(
workflowDoc.body.dataset.evidenceExpansionFamilySourceFilterCount,
"21",
"workflow overview evidence expansion source filter default source count",
);
evidenceExpansionSourceFilterFamilySelect.value = "evidence-expansion-family-five-axis-trt";
evidenceExpansionSourceFilterKindSelect.value = "gcode";
evidenceExpansionSourceFilterFamilySelect.dispatchEvent(new Event("change", { bubbles: true }));
assertEqual(
workflowDoc.body.dataset.evidenceExpansionFamilySourceFilterFamily,
"evidence-expansion-family-five-axis-trt",
"workflow overview evidence expansion source filter change body family",
);
assertEqual(
workflowDoc.body.dataset.evidenceExpansionFamilySourceFilterSourceKind,
"gcode",
"workflow overview evidence expansion source filter change body source kind",
);
assertEqual(
workflowDoc.body.dataset.evidenceExpansionFamilySourceFilterCount,
"8",
"workflow overview evidence expansion source filter changed source count",
);
assertEqual(
evidenceExpansionSourceFilterMount.dataset.handoffScope,
"workflow-overview-evidence-expansion-family-source-filter",
"workflow overview evidence expansion source filter scope",
);
assertEqual(
workflowDoc.querySelectorAll(
'[data-workflow-overview-evidence-expansion-family-source-filter-type="source-row"]',
).length,
16,
"workflow overview evidence expansion source filter changed source DOM nodes",
);
assertEqual(
workflowDoc.querySelectorAll(
'[data-workflow-overview-evidence-expansion-family-source-filter-type="candidate-row"]',
).length,
16,
"workflow overview evidence expansion source filter changed candidate DOM nodes",
);
assertEqual(
workflowDoc.querySelector(
'[data-workflow-overview-evidence-expansion-family-source-filter-type="candidate-row"][data-workflow-overview-evidence-expansion-family-source-filter-value="linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc"]',
)?.dataset.workflowOverviewEvidenceExpansionFamilySourceFilterCandidateStatus,
"evidence-expansion-ready",
"workflow overview evidence expansion source filter TRT candidate status",
);
assertEqual(
workflowDoc.querySelector(
'[data-workflow-overview-evidence-expansion-family-source-filter-type="candidate-row"][data-workflow-overview-evidence-expansion-family-source-filter-value="linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc"]',
)?.dataset.workflowOverviewEvidenceExpansionFamilySourceFilterPromotionAllowed,
"0",
"workflow overview evidence expansion source filter promotion allowed",
);
const presetWorkflowDoc = await loadWorkflowOverviewFrame(
"../../runtime/ui/ini-panel/workflow-overview.html?evidenceExpansionFamily=evidence-expansion-family-five-axis-trt&evidenceExpansionSourceKind=gcode",
);
const presetWorkflowApi = presetWorkflowDoc.defaultView.linuxCncIniPanelWorkflowOverviewApi;
presetWorkflowDoc.querySelector("[data-release-artifact-url-input]").value =
"../../tests/fixtures/project-release-readiness-ready.json";
presetWorkflowDoc.querySelector("[data-browser-diagnostics-url-input]").value =
"../../tests/fixtures/real-browser-simulation-diagnostics-ready.json";
const presetReleaseArtifactUrlFormResult = await presetWorkflowApi.runWorkflowOverviewReleaseReadinessArtifactUrlForm({
fetchRef: async (url) => {
if (String(url).endsWith("real-browser-simulation-diagnostics-ready.json")) {
return {
ok: true,
status: 200,
text: async () => diagnosticsArtifactJson,
};
}
return fetch(url);
},
});
const presetEvidenceExpansionSourceFilterMount = presetWorkflowDoc.querySelector(
"[data-workflow-overview-evidence-expansion-family-source-filter]",
);
assertEqual(
presetWorkflowDoc.body.dataset.evidenceExpansionFamilySourceFilterFamily,
"evidence-expansion-family-five-axis-trt",
"workflow overview evidence expansion query preset body family",
);
assertEqual(
presetWorkflowDoc.body.dataset.evidenceExpansionFamilySourceFilterSourceKind,
"gcode",
"workflow overview evidence expansion query preset body source kind",
);
assertEqual(
presetWorkflowDoc.body.dataset.evidenceExpansionFamilySourceFilterCount,
"8",
"workflow overview evidence expansion query preset source count",
);
assertEqual(
presetWorkflowDoc.body.dataset.evidenceExpansionFamilySourceFilterSummary,
"Ready: evidence expansion filter evidence-expansion-family-five-axis-trt / gcode is externally readable",
"workflow overview evidence expansion query preset summary",
);
assertEqual(
presetEvidenceExpansionSourceFilterMount.dataset.selectedFamilyId,
"evidence-expansion-family-five-axis-trt",
"workflow overview evidence expansion query preset mount family",
);
assertEqual(
presetEvidenceExpansionSourceFilterMount.dataset.selectedSourceKind,
"gcode",
"workflow overview evidence expansion query preset mount source kind",
);
assertEqual(
presetReleaseArtifactUrlFormResult.evidenceExpansionFamilySourceFilterSummary.filteredSourceFileCount,
8,
"workflow overview evidence expansion query preset summary source count",
);
assertEqual(
presetReleaseArtifactUrlFormResult.evidenceExpansionFamilySourceFilterActionPlan.baselineChanging,
false,
"workflow overview evidence expansion query preset baseline unchanged",
);
assertEqual(
releaseArtifactJsonWorkflow.statusLine,
"Ready: Artifact JSON workflow complete",

View File

@@ -668,6 +668,26 @@
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini") ||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini") ||
diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.complete !== true ||
diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.complete !== true ||
diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.candidateCount !== 11 ||
diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.readyCandidateCount !== 11 ||
diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.promotionAllowed !== false ||
!diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.rows?.some((row) =>
row.id === "trt-boat-xyzac" &&
row.currentNodeInventoryStatus === "PASS" &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles?.includes("linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc")
) ||
!diagnosticsArtifact.virtualHalSimConfigEvidenceExpansion?.rows?.some((row) =>
row.id === "trt-xyzac-switchkins" &&
row.currentNodeInventoryStatus === "PASS" &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles?.includes("linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc")
) ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.ready !== true ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.preferredCandidateId !== "qtdragon-multi-joint-on-abort" ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.candidateCount !== 8 ||
@@ -678,6 +698,18 @@
promotionCandidateSummary.preferredIniPath !== "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" ||
doc.body.dataset.promotionCandidateReady !== "true" ||
doc.body.dataset.promotionCandidatePreferred !== "qtdragon-multi-joint-on-abort" ||
doc.body.dataset.evidenceExpansionReady !== "true" ||
doc.body.dataset.evidenceExpansionCount !== "11" ||
doc.body.dataset.evidenceExpansionReadyCount !== "11" ||
api.getVirtualHalEvidenceExpansionSummary?.().ready !== true ||
api.getVirtualHalEvidenceExpansionSummary?.().candidateIds?.join(", ") !== "woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins" ||
doc.querySelector('[data-evidence-expansion-summary-value="candidate-count"]')?.textContent !== "11/11 ready" ||
doc.querySelector('[data-evidence-expansion-summary-value="candidate-list"]')?.textContent !== "woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins" ||
doc.querySelector('[data-evidence-expansion-summary-value="family-count"]')?.textContent !== "3" ||
doc.querySelector('[data-evidence-expansion-summary-value="family-summary"]')?.textContent !== "woodpecker: 1/1 ready; vismach-remap-sims: 2/2 ready; five-axis-trt: 8/8 ready" ||
doc.querySelector('[data-evidence-expansion-summary-value="family-source-count-list"]')?.textContent !== "woodpecker:3, vismach-remap-sims:6, five-axis-trt:12" ||
doc.querySelector('[data-evidence-expansion-summary-value="promotion-allowed"]')?.textContent !== "0 baseline changes" ||
doc.querySelector('[data-evidence-expansion-summary-value="inventory-baseline"]')?.textContent !== "unchanged" ||
doc.querySelector('[data-promotion-candidate-summary-value="preferred-candidate"]')?.textContent !== "qtdragon-multi-joint-on-abort" ||
doc.querySelector('[data-promotion-candidate-summary-value="candidate-layers"]')?.textContent !== "evidence-ready=8 inventory-ready=2" ||
doc.querySelector('[data-promotion-candidate-summary-value="inventory-baseline"]')?.textContent !== "82/82 pass; 77 skip" ||

View File

@@ -45,6 +45,11 @@ for (const phrase of [
"sim_configs_wasm_node_inventory_skip_UPSTREAM_DEMO=1",
"build/wasm/sim-configs-inventory/skip-summary.tsv",
"build/wasm/sim-configs-inventory/blocked-dependency-summary.tsv",
"remaining_skip_count=77",
"remaining_skipped_main_program_rows=2",
"remaining_skipped_main_program_promotion_allowed=0",
"direct_inventory_promotion_rows=0",
"baseline_change_allowed=no",
"verify_no_standalone_cnc_semantics.sh",
"verify_sim_configs_coverage_docs.sh",
"L4-PYTHON-REMAP",
@@ -65,6 +70,40 @@ for (const phrase of [
"axis/rose_engine/rcone_demo.ngc",
"axis/external_offsets/queuebuster.ngc",
"Web Simulation Improvements From Virtual HAL",
"2026-06-20 Remaining Skip Promotion Audit",
"2026-06-20 Five-Axis TRT Evidence Expansion",
"2026-06-20 Evidence Expansion UI Surface",
"remaining_skipped_main_program_promotion_allowed=0",
"direct_inventory_promotion_rows=0",
"axis/vismach/millturn/example.ngc",
"incremental_repetition_g533.ngc",
"trt-boat-xyzac",
"trt-xyzac-switchkins",
"trt-boat-xyzbc",
"trt-impeller-7bl-xyzac",
"trt-xyzac-switchkins-test-1",
"trt-xyzac-switchkins-test-2",
"trt-xyzac-switchkins-test-3",
"trt-xyzbc-switchkins",
"candidateCount=11",
"readyCandidateCount=11",
"real-browser-simulation-evidence-expansion-summary",
"evidence-expansion-full-candidate-list",
"evidence-expansion-full-gcode-list",
"evidence-expansion-family-count",
"evidence-expansion-family-summary",
"evidence-expansion-family-source-count-list",
"woodpecker: 1/1 ready; sources=3",
"vismach-remap-sims: 2/2 ready; sources=6",
"five-axis-trt: 8/8 ready; sources=12",
"2026-06-20 Evidence Expansion Source Filter",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"21 source files",
"11 evidence-expansion candidate rows",
"evidence-expansion-family-five-axis-trt / gcode => 8 source files, 8 candidates",
"Browser and Node simulation no longer need host `halcmd`, `halrun`, or a",
"servo-period stepping",
"8 diagnostics-ready candidates across 3 families and 17 source files",
@@ -109,4 +148,33 @@ if (existsSync(skipSummaryPath)) {
);
}
const remainingSkipAuditPath = resolve(
root,
"build/wasm/sim-configs-inventory/remaining-skip-main-program-promotion-audit.tsv",
);
if (existsSync(remainingSkipAuditPath)) {
const rows = parseTsv(readFileSync(remainingSkipAuditPath, "utf8"));
assert.equal(rows.length, 2);
assert.deepEqual(
rows.map((row) => row.path).sort(),
[
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc",
"axis/vismach/millturn/example.ngc",
],
);
assert.deepEqual(
Object.fromEntries(rows.map((row) => [row.path, row.skip_kind])),
{
"axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc":
"UPSTREAM-DEMO",
"axis/vismach/millturn/example.ngc": "L4-USER-M-PROCESS",
},
);
for (const row of rows) {
assert.equal(row.class, "main");
assert.equal(row.promotion_allowed, "0");
assert.equal(row.promotion_ready, "0");
}
}
console.log("sim_configs_coverage_docs_node_smoke=ok");

View File

@@ -300,6 +300,14 @@ assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-source-count-list")?.value,
"3, 3, 3",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-full-candidate-list")?.value,
"woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-full-gcode-list")?.value,
"linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
@@ -380,6 +388,14 @@ assert.deepEqual(
["evidence-expansion-candidate-list", "woodpecker-on-abort, puma-cube, melfa-example"],
["evidence-expansion-gcode-list", "linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc"],
["evidence-expansion-source-count-list", "3, 3, 3"],
["evidence-expansion-full-candidate-list", "woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins"],
["evidence-expansion-full-gcode-list", "linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc"],
["evidence-expansion-family-count", "3 families"],
["evidence-expansion-family-summary", "woodpecker: 1/1 ready; vismach-remap-sims: 2/2 ready; five-axis-trt: 8/8 ready"],
["evidence-expansion-family-source-count-list", "woodpecker:3, vismach-remap-sims:6, five-axis-trt:12"],
["evidence-expansion-family-woodpecker", "1/1 ready; sources=3; diagnostics=ready"],
["evidence-expansion-family-vismach-remap-sims", "2/2 ready; sources=6; diagnostics=ready"],
["evidence-expansion-family-five-axis-trt", "8/8 ready; sources=12; diagnostics=ready"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "1"],

View File

@@ -561,6 +561,11 @@ assert.deepEqual(
["evidence-expansion-candidate-list", "not provided"],
["evidence-expansion-gcode-list", "not provided"],
["evidence-expansion-source-count-list", "not provided"],
["evidence-expansion-full-candidate-list", "not provided"],
["evidence-expansion-full-gcode-list", "not provided"],
["evidence-expansion-family-count", "not provided"],
["evidence-expansion-family-summary", "not provided"],
["evidence-expansion-family-source-count-list", "not provided"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "0"],

View File

@@ -154,6 +154,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomReadiness,
@@ -299,6 +310,9 @@ const expectedPromotionCandidateArtifactSummary = {
promotionAllowedCount: 0,
baselineChanging: false,
nextEvidence: "browser-diagnostics-binding",
familyCount: 0,
familySummary: "not provided",
familyRows: [],
},
};
const hasFreshBoundaryArtifactHashes = (boundaryEvidence) =>
@@ -580,6 +594,50 @@ const requiredExports = [
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
],
[
"createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
],
[
"handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
],
[
"bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
],
[
"renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
],
[
"mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
],
[
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel,
@@ -1084,7 +1142,7 @@ assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
simConfigSourceCoverage: simConfigSourceCoverageReport,
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
}).complete, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES.length, 3);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES.length, 11);
const simConfigEvidenceExpansionReport = createVirtualHalSimConfigEvidenceExpansionReport({
manifestText: sourceManifestText,
simConfigSourceCoverage: simConfigSourceCoverageReport,
@@ -1098,8 +1156,22 @@ assert.equal(simConfigEvidenceExpansionReport.complete, true);
assert.equal(simConfigEvidenceExpansionReport.webSimulationSatisfied, true);
assert.equal(simConfigEvidenceExpansionReport.inventoryBaselineUnchanged, true);
assert.equal(simConfigEvidenceExpansionReport.promotionAllowed, false);
assert.equal(simConfigEvidenceExpansionReport.candidateCount, 3);
assert.equal(simConfigEvidenceExpansionReport.readyCandidateCount, 3);
assert.equal(simConfigEvidenceExpansionReport.candidateCount, 11);
assert.equal(simConfigEvidenceExpansionReport.readyCandidateCount, 11);
assert.deepEqual(
simConfigEvidenceExpansionReport.familyRows.map(({ id, candidateCount, completeCount, sourceFileCount, complete }) => [
id,
candidateCount,
completeCount,
sourceFileCount,
complete,
]),
[
["woodpecker", 1, 1, 3, true],
["vismach-remap-sims", 2, 2, 6, true],
["five-axis-trt", 8, 8, 12, true],
],
);
assert.equal(simConfigEvidenceExpansionReport.promotionAllowedViolations.length, 0);
assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) =>
@@ -1111,6 +1183,49 @@ assert.equal(
),
true,
);
assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) =>
row.id === "trt-boat-xyzac" &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles.includes(
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc",
)
),
true,
);
assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) =>
row.id === "trt-xyzac-switchkins" &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles.includes(
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc",
)
),
true,
);
for (const [id, gcodePath] of [
["trt-boat-xyzbc", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc"],
["trt-impeller-7bl-xyzac", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc"],
["trt-xyzac-switchkins-test-1", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc"],
["trt-xyzac-switchkins-test-2", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc"],
["trt-xyzac-switchkins-test-3", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc"],
["trt-xyzbc-switchkins", "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc"],
]) {
assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) =>
row.id === id &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles.includes(gcodePath)
),
true,
);
}
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES.length >= 2, true);

View File

@@ -9,6 +9,7 @@ import {
createProjectReleaseReadinessReport,
} from "../../../runtime/sdk/src/project-release-readiness.js";
import {
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
createVirtualHalCommandScriptFixtureReport,
createVirtualHalMillturnUserMProcessBoundaryReport,
@@ -86,6 +87,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
@@ -164,6 +176,8 @@ import {
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []);
const VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES.flatMap((candidate) => candidate.sourceFiles ?? []);
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, "../../..");
@@ -790,6 +804,17 @@ assert.deepEqual(shellViewModel.shellWorkflowOverviewContract, {
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -1460,7 +1485,7 @@ const releaseReadinessPromotionCandidates = createVirtualHalSimConfigPromotionCa
const releaseReadinessEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({
manifestEntries: [
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ini",
...VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES,
],
motionControllerMatrix: releaseReadinessMotionControllerMatrix,
});
@@ -2107,6 +2132,30 @@ assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-source-count-list")?.value,
"3, 3, 3",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-candidate-list")?.value,
"woodpecker-on-abort, puma-cube, melfa-example, trt-boat-xyzac, trt-xyzac-switchkins, trt-boat-xyzbc, trt-impeller-7bl-xyzac, trt-xyzac-switchkins-test-1, trt-xyzac-switchkins-test-2, trt-xyzac-switchkins-test-3, trt-xyzbc-switchkins",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-full-gcode-list")?.value,
"linuxcnc/configs/sim/woodpecker/on_abort.ngc, linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ngc, linuxcnc/configs/sim/axis/vismach/melfa-sim/example.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc, linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-count")?.value,
"3 families",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-summary")?.value,
"woodpecker: 1/1 ready; vismach-remap-sims: 2/2 ready; five-axis-trt: 8/8 ready",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-source-count-list")?.value,
"woodpecker:3, vismach-remap-sims:6, five-axis-trt:12",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-family-five-axis-trt")?.value,
"8/8 ready; sources=12; diagnostics=ready",
);
assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=82 passed=82 skipped=77 unexpected_fail=0",
@@ -2683,6 +2732,263 @@ assert.equal(
),
true,
);
const evidenceExpansionFamilyRowsRenderState =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState(releaseArtifactUrlWorkflowSummary);
const evidenceExpansionFamilySourceFilterViewModel =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(
evidenceExpansionFamilyRowsRenderState,
);
const evidenceExpansionTrtGcodeFilterViewModel =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel(
evidenceExpansionFamilyRowsRenderState,
{
familyId: "evidence-expansion-family-five-axis-trt",
sourceKind: "gcode",
},
);
const evidenceExpansionTrtGcodeFilterSummary =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary(
evidenceExpansionTrtGcodeFilterViewModel,
);
const evidenceExpansionTrtGcodeFilterActionPlan =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan(
evidenceExpansionTrtGcodeFilterSummary,
);
assert.equal(evidenceExpansionFamilyRowsRenderState.ready, true);
assert.equal(evidenceExpansionFamilyRowsRenderState.statusLine, "Ready: 3 evidence expansion families ready");
assert.equal(evidenceExpansionFamilyRowsRenderState.rows.length, 3);
assert.equal(evidenceExpansionFamilyRowsRenderState.sourceFileCount, 21);
assert.equal(evidenceExpansionFamilyRowsRenderState.candidateCount, 11);
assert.deepEqual(
evidenceExpansionFamilyRowsRenderState.rows.map(({ id, sourceKindSummary }) => [id, sourceKindSummary]),
[
["evidence-expansion-family-woodpecker", "ini=1 gcode=1 source=1"],
["evidence-expansion-family-vismach-remap-sims", "ini=2 gcode=2 remap-subroutine=2"],
["evidence-expansion-family-five-axis-trt", "ini=1 gcode=8 remap-subroutine=3"],
],
);
assert.equal(evidenceExpansionFamilySourceFilterViewModel.ready, true);
assert.equal(evidenceExpansionFamilySourceFilterViewModel.statusLine, "Ready: 21/21 source files selected");
assert.equal(evidenceExpansionFamilySourceFilterViewModel.filteredCandidateCount, 11);
assert.deepEqual(
evidenceExpansionFamilySourceFilterViewModel.familyFilters.map(({ id, count, selected }) => [id, count, selected]),
[
["all", 21, true],
["evidence-expansion-family-woodpecker", 3, false],
["evidence-expansion-family-vismach-remap-sims", 6, false],
["evidence-expansion-family-five-axis-trt", 12, false],
],
);
assert.deepEqual(
evidenceExpansionFamilySourceFilterViewModel.sourceKindFilters.map(({ id, count, selected }) => [id, count, selected]),
[
["all", 21, true],
["ini", 4, false],
["gcode", 11, false],
["remap-subroutine", 5, false],
["source", 1, false],
],
);
assert.equal(evidenceExpansionTrtGcodeFilterViewModel.statusLine, "Ready: 8/21 source files selected");
assert.equal(evidenceExpansionTrtGcodeFilterViewModel.scopedSourceFileCount, 12);
assert.equal(evidenceExpansionTrtGcodeFilterViewModel.filteredSourceFileCount, 8);
assert.equal(evidenceExpansionTrtGcodeFilterViewModel.filteredCandidateCount, 8);
assert.equal(evidenceExpansionTrtGcodeFilterViewModel.familyRows[0]?.sourceKindSummary, "gcode=8");
assert.deepEqual(
{
ready: evidenceExpansionTrtGcodeFilterSummary.ready,
selectedFamilyId: evidenceExpansionTrtGcodeFilterSummary.selectedFamilyId,
selectedSourceKind: evidenceExpansionTrtGcodeFilterSummary.selectedSourceKind,
filteredSourceFileCount: evidenceExpansionTrtGcodeFilterSummary.filteredSourceFileCount,
filteredCandidateCount: evidenceExpansionTrtGcodeFilterSummary.filteredCandidateCount,
totalSourceFileCount: evidenceExpansionTrtGcodeFilterSummary.totalSourceFileCount,
promotionAllowed: evidenceExpansionTrtGcodeFilterActionPlan.promotionAllowed,
baselineChanging: evidenceExpansionTrtGcodeFilterActionPlan.baselineChanging,
nextCommand: evidenceExpansionTrtGcodeFilterActionPlan.nextCommand,
},
{
ready: true,
selectedFamilyId: "evidence-expansion-family-five-axis-trt",
selectedSourceKind: "gcode",
filteredSourceFileCount: 8,
filteredCandidateCount: 8,
totalSourceFileCount: 21,
promotionAllowed: false,
baselineChanging: false,
nextCommand: null,
},
);
assert.equal(
evidenceExpansionTrtGcodeFilterSummary.statusLine,
"Ready: evidence-expansion-family-five-axis-trt / gcode selects 8/21 source files",
);
assert.equal(
evidenceExpansionTrtGcodeFilterActionPlan.statusLine,
"Ready: evidence expansion filter evidence-expansion-family-five-axis-trt / gcode is externally readable",
);
assert.equal(
evidenceExpansionTrtGcodeFilterViewModel.sourceRows.every(({ familyId, sourceKind }) =>
familyId === "evidence-expansion-family-five-axis-trt" &&
sourceKind === "gcode"
),
true,
);
assert.equal(
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract().selectors.mount,
"[data-workflow-overview-evidence-expansion-family-source-filter]",
);
assert.equal(createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness().ready, false);
const evidenceExpansionSourceFilterMountNode = mountDocument.createElement("section");
evidenceExpansionSourceFilterMountNode.dataset.workflowOverviewEvidenceExpansionFamilySourceFilter = "";
const evidenceExpansionSourceFilterStatusNode = mountDocument.createElement("p");
evidenceExpansionSourceFilterStatusNode.dataset.workflowOverviewEvidenceExpansionFamilySourceFilterStatus = "";
const evidenceExpansionSourceFilterControlsNode = {
...mountDocument.createElement("div"),
children: [],
replaceChildren() {
this.children = [];
},
append(...nodes) {
this.children.push(...nodes);
},
};
evidenceExpansionSourceFilterControlsNode.dataset.workflowOverviewEvidenceExpansionFamilySourceFilterControls = "";
const evidenceExpansionSourceFilterRowsNode = {
...mountDocument.createElement("dl"),
children: [],
replaceChildren() {
this.children = [];
},
append(...nodes) {
this.children.push(...nodes);
},
};
evidenceExpansionSourceFilterRowsNode.dataset.workflowOverviewEvidenceExpansionFamilySourceFilterRows = "";
const evidenceExpansionSourceFilterRenderResult =
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(
evidenceExpansionTrtGcodeFilterViewModel,
{
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
},
);
const evidenceExpansionSourceFilterMountResult =
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState({
viewModel: evidenceExpansionTrtGcodeFilterViewModel,
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
});
assert.equal(evidenceExpansionSourceFilterRenderResult.rendered, true);
assert.equal(evidenceExpansionSourceFilterRenderResult.statusLine, "Ready: 8/21 source files selected");
assert.equal(evidenceExpansionSourceFilterRenderResult.rowCount, 24);
assert.equal(evidenceExpansionSourceFilterRenderResult.sourceFileCount, 8);
assert.equal(evidenceExpansionSourceFilterRenderResult.candidateCount, 8);
assert.deepEqual(evidenceExpansionSourceFilterRenderResult.dataset, {
handoffPhase: "ready",
handoffReady: "true",
handoffScope: "workflow-overview-evidence-expansion-family-source-filter",
selectedFamilyId: "evidence-expansion-family-five-axis-trt",
selectedSourceKind: "gcode",
});
assert.equal(
evidenceExpansionSourceFilterRowsNode.children.some((node) =>
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterType === "candidate-row" &&
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterFamily ===
"evidence-expansion-family-five-axis-trt" &&
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterCandidateStatus ===
"evidence-expansion-ready" &&
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterPromotionAllowed === "0" &&
node.textContent === "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc"
),
true,
);
assert.equal(evidenceExpansionSourceFilterMountResult.ready, true);
assert.equal(evidenceExpansionSourceFilterMountResult.renderResult.rowCount, 24);
const evidenceExpansionSourceFilterSelectionActionPlan =
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan(
evidenceExpansionFamilyRowsRenderState,
{
familyId: "evidence-expansion-family-woodpecker",
sourceKind: "source",
previousViewModel: evidenceExpansionTrtGcodeFilterViewModel,
},
);
assert.equal(evidenceExpansionSourceFilterSelectionActionPlan.ready, true);
assert.equal(evidenceExpansionSourceFilterSelectionActionPlan.changed, true);
assert.equal(
evidenceExpansionSourceFilterSelectionActionPlan.statusLine,
"Ready: evidence expansion source filter changed to evidence-expansion-family-woodpecker / source",
);
assert.equal(evidenceExpansionSourceFilterSelectionActionPlan.nextViewModel.filteredSourceFileCount, 1);
const evidenceExpansionSourceFilterFamilySelect = evidenceExpansionSourceFilterControlsNode.children.find((node) =>
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterSelect === "family"
);
const evidenceExpansionSourceFilterKindSelect = evidenceExpansionSourceFilterControlsNode.children.find((node) =>
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterSelect === "source-kind"
);
evidenceExpansionSourceFilterFamilySelect.value = "evidence-expansion-family-woodpecker";
evidenceExpansionSourceFilterKindSelect.value = "source";
const evidenceExpansionSourceFilterSelectionChange =
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange({
renderState: evidenceExpansionFamilyRowsRenderState,
viewModel: evidenceExpansionTrtGcodeFilterViewModel,
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
render: true,
});
assert.equal(evidenceExpansionSourceFilterSelectionChange.ready, true);
assert.equal(evidenceExpansionSourceFilterSelectionChange.selectedFamilyId, "evidence-expansion-family-woodpecker");
assert.equal(evidenceExpansionSourceFilterSelectionChange.selectedSourceKind, "source");
assert.equal(evidenceExpansionSourceFilterSelectionChange.renderResult.sourceFileCount, 1);
let evidenceExpansionSourceFilterBindingLastChange = null;
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState(
evidenceExpansionTrtGcodeFilterViewModel,
{
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
},
);
const evidenceExpansionSourceFilterSelectionBinding =
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls({
renderState: evidenceExpansionFamilyRowsRenderState,
viewModel: evidenceExpansionTrtGcodeFilterViewModel,
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
render: true,
onChange: (changeResult) => {
evidenceExpansionSourceFilterBindingLastChange = changeResult;
},
});
assert.equal(evidenceExpansionSourceFilterSelectionBinding.ready, true);
assert.deepEqual(evidenceExpansionSourceFilterSelectionBinding.controlIds, ["family", "source-kind"]);
const boundEvidenceExpansionFamilySelect = evidenceExpansionSourceFilterControlsNode.children.find((node) =>
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterSelect === "family"
);
const boundEvidenceExpansionKindSelect = evidenceExpansionSourceFilterControlsNode.children.find((node) =>
node.dataset?.workflowOverviewEvidenceExpansionFamilySourceFilterSelect === "source-kind"
);
boundEvidenceExpansionFamilySelect.value = "evidence-expansion-family-woodpecker";
boundEvidenceExpansionKindSelect.value = "source";
const evidenceExpansionSourceFilterBoundChange = boundEvidenceExpansionFamilySelect.dispatchEvent("change");
assert.equal(evidenceExpansionSourceFilterBoundChange.ready, true);
assert.equal(evidenceExpansionSourceFilterBoundChange.selectedFamilyId, "evidence-expansion-family-woodpecker");
assert.equal(evidenceExpansionSourceFilterBindingLastChange.selectedSourceKind, "source");
assert.deepEqual(evidenceExpansionSourceFilterSelectionBinding.unbind(), { unbound: 2 });
assert.equal(
promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) =>
sourceKind === "ini" &&
@@ -2855,7 +3161,7 @@ const releaseArtifactUrlWorkflowMountResult =
rowsNode: releaseArtifactUrlWorkflowRowsNode,
});
assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true);
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 53);
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 61);
assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"),
true,
@@ -2900,12 +3206,20 @@ assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("evidence-expansion-source-count-list"),
true,
);
assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("evidence-expansion-full-candidate-list"),
true,
);
assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("evidence-expansion-full-gcode-list"),
true,
);
assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"),
true,
);
assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true);
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 53);
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 61);
const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
artifactUrl: "/project-release-readiness.json",
fetchRef: async () => ({
@@ -2965,6 +3279,34 @@ const workflowOverviewApi = {
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan: () => releaseArtifactUrlWorkflow.actionPlan,
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState: () => releaseArtifactUrlWorkflowRenderState,
getWorkflowOverviewPromotionFamilyRowsRenderState: () => promotionFamilyRowsRenderState,
getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState: () => evidenceExpansionFamilyRowsRenderState,
getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel: () =>
evidenceExpansionFamilySourceFilterViewModel,
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness: () => (
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness({
documentRef: mountDocument,
mountNode: evidenceExpansionSourceFilterMountNode,
statusNode: evidenceExpansionSourceFilterStatusNode,
controlsNode: evidenceExpansionSourceFilterControlsNode,
rowsNode: evidenceExpansionSourceFilterRowsNode,
})
),
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary: () =>
evidenceExpansionTrtGcodeFilterSummary,
getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan: () =>
evidenceExpansionTrtGcodeFilterActionPlan,
getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan: () =>
evidenceExpansionSourceFilterSelectionActionPlan,
handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange: () =>
evidenceExpansionSourceFilterSelectionChange,
bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls: () =>
evidenceExpansionSourceFilterSelectionBinding,
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState: () =>
evidenceExpansionSourceFilterRenderResult,
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState: () =>
evidenceExpansionSourceFilterMountResult,
getWorkflowOverviewPromotionFamilySourceFilterViewModel: () => promotionFamilySourceFilterViewModel,
getWorkflowOverviewPromotionFamilySourceFilterDomContract:
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,