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 # 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. 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. turn-by-turn continuation notes and next-batch execution records.
## Current Status ## Current Status
- Active continuation file: `text16.txt` - Active continuation file: `text32.txt`
- Latest completed batch: AXIS run summary - Latest completed batch: evidence expansion filter query/hash preset
- Latest relevant commit: use `git log -1 --oneline` after each committed batch - Latest relevant commit: use `git log -1 --oneline` after each committed batch
- Working tree at tracker creation: clean - Working tree at tracker creation: clean
- Required policy: LinuxCNC remains the only CNC semantic source - 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. - Host/runtime blocked families are explicitly documented and not falsely promoted.
- All required gates pass. - All required gates pass.
- Documentation explains what is supported, blocked, and how to verify it. - 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 ## 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. | | 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. | | 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`. | | 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 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`. | | 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. | | 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, case promotions from Node inventory or representative coverage into browser,
diagnostics, and release evidence. 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 ## What Virtual HAL Unlocks
The virtual HAL is now a source-derived Web simulation replacement for these 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 `promotion-candidates.tsv`, and do not change the inventory baseline or any
hard-block lock. 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 ## Boundary Statement
This analysis relies on the improved virtual HAL only for Web simulation 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 browser simulation state now includes a source-derived virtual HAL proof for
the `M429 -> M129` turn and `M428 -> M128` mill state transitions. The TWP the `M429 -> M129` turn and `M428 -> M128` mill state transitions. The TWP
`incremental_repetition_g533.ngc` row remains preserved upstream demo evidence. `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 SDK and workflow-overview release URL summaries expose the current
`evidence-ready` layer as dashboard fields: `evidence-ready-candidate-rows=8`, `evidence-ready` layer as dashboard fields: `evidence-ready-candidate-rows=8`,

View File

@@ -61,6 +61,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomContract, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlanDomReadiness,
@@ -707,6 +718,20 @@ for external browser shells:
`renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()`, `renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()`,
and `mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()` and `mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState()`
let callers render the URL workflow status into their own DOM. 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()` `createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationActionPlan()`
exposes the direct artifact-validation next-command plan when callers already exposes the direct artifact-validation next-command plan when callers already
have parsed or validated artifact JSON. have parsed or validated artifact JSON.

View File

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

View File

@@ -471,6 +471,174 @@ export const VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES = Object.freez
blockedKind: "-", blockedKind: "-",
evidence: "MELFA example has current representative coverage and can receive explicit browser diagnostics evidence without unlocking any hard runtime family.", 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([ 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 blockedCandidateIds = rows.filter((row) => row.blockedKind !== "-").map((row) => row.id);
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))]; const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
const missingRequiredReports = [...new Set(rows.flatMap((row) => row.missingRequiredReports))]; 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 && const complete = rows.length > 0 &&
missingCandidates.length === 0 && missingCandidates.length === 0 &&
promotionAllowedViolations.length === 0 && promotionAllowedViolations.length === 0 &&
@@ -3355,10 +3547,12 @@ export function createVirtualHalSimConfigEvidenceExpansionReport(options = {}) {
blockedCandidateIds, blockedCandidateIds,
missingManifestFiles, missingManifestFiles,
missingRequiredReports, missingRequiredReports,
familyRows,
rows, rows,
summaryRows: [ summaryRows: [
{ id: "candidates", label: "Expansion candidates", value: `${rows.length}` }, { id: "candidates", label: "Expansion candidates", value: `${rows.length}` },
{ id: "ready-candidates", label: "Ready candidates", value: `${rows.filter((row) => row.complete).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: "promotion-allowed", label: "Promotion allowed", value: "0" },
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" }, { 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({ function createPromotionCandidateArtifactSummary({
candidateReport = {}, candidateReport = {},
evidenceExpansionReport = {}, evidenceExpansionReport = {},
@@ -161,6 +190,8 @@ function createPromotionCandidateArtifactSummary({
const artifactInventoryReadyRows = candidateArtifactRows const artifactInventoryReadyRows = candidateArtifactRows
.filter((row) => row.candidate_kind === "inventory-ready"); .filter((row) => row.candidate_kind === "inventory-ready");
const artifactEvidenceReadyCount = artifactEvidenceReadyRows.length; const artifactEvidenceReadyCount = artifactEvidenceReadyRows.length;
const evidenceExpansionFamilyRows = createEvidenceExpansionFamilySummaryRows(evidenceExpansionReport);
const evidenceExpansionFamilySummary = createEvidenceExpansionFamilySummaryText(evidenceExpansionReport);
const inventoryReadyCount = artifactInventoryReadyRows.length > 0 const inventoryReadyCount = artifactInventoryReadyRows.length > 0
? artifactInventoryReadyRows.length ? artifactInventoryReadyRows.length
: 2; : 2;
@@ -269,6 +300,9 @@ function createPromotionCandidateArtifactSummary({
promotionAllowedCount: 0, promotionAllowedCount: 0,
baselineChanging: false, baselineChanging: false,
nextEvidence: "browser-diagnostics-binding", 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", "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 = [ const REQUIRED_MACRO_LOAD_FIXTURES = [
@@ -664,8 +778,8 @@ function isVirtualHalSimConfigEvidenceExpansionReportReady(report) {
expansionReport.webSimulationSatisfied === true && expansionReport.webSimulationSatisfied === true &&
expansionReport.inventoryBaselineUnchanged === true && expansionReport.inventoryBaselineUnchanged === true &&
expansionReport.promotionAllowed === false && expansionReport.promotionAllowed === false &&
expansionReport.candidateCount === 3 && expansionReport.candidateCount === REQUIRED_EVIDENCE_EXPANSION_CANDIDATES.length &&
expansionReport.readyCandidateCount === 3 && expansionReport.readyCandidateCount === REQUIRED_EVIDENCE_EXPANSION_CANDIDATES.length &&
arrayOrEmpty(expansionReport.missingCandidates).length === 0 && arrayOrEmpty(expansionReport.missingCandidates).length === 0 &&
arrayOrEmpty(expansionReport.promotionAllowedViolations).length === 0 && arrayOrEmpty(expansionReport.promotionAllowedViolations).length === 0 &&
arrayOrEmpty(expansionReport.blockedCandidateIds).length === 0 && arrayOrEmpty(expansionReport.blockedCandidateIds).length === 0 &&
@@ -3203,8 +3317,13 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
const evidenceExpansionRows = arrayOrEmpty( const evidenceExpansionRows = arrayOrEmpty(
workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows, workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows,
); );
const evidenceExpansionFamilyRows = arrayOrEmpty(
promotionCandidateArtifactSummary.evidenceExpansion?.familyRows
?? workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows,
);
const preferredEvidenceExpansion = evidenceExpansionRows[0] ?? {}; const preferredEvidenceExpansion = evidenceExpansionRows[0] ?? {};
const evidenceExpansionPreviewRows = evidenceExpansionRows.slice(0, 3); const evidenceExpansionPreviewRows = evidenceExpansionRows.slice(0, 3);
const evidenceExpansionFullRows = evidenceExpansionRows;
const ready = workflow?.ready === true; const ready = workflow?.ready === true;
const statusText = ready ? "Ready" : "Blocked"; const statusText = ready ? "Ready" : "Blocked";
const detailText = ready const detailText = ready
@@ -3366,6 +3485,48 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
).join(", ") ).join(", ")
: "not provided", : "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", id: "evidence-expansion-artifact",
label: "Evidence expansion artifact", label: "Evidence expansion artifact",

View File

@@ -219,6 +219,17 @@ export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntr
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState", "getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel", "getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract", "getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness", "getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -1942,6 +1953,17 @@ export function createIniPanelShellWorkflowOverviewContract() {
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState", "getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel", "getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract", "getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness", "getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -2600,12 +2622,21 @@ export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWo
?? workflow?.urlWorkflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows ?? workflow?.urlWorkflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.rows
?? [] ?? []
); );
const evidenceExpansionFamilyRows = (
promotionCandidateArtifactSummary.evidenceExpansion?.familyRows
?? workflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows
?? workflow?.urlWorkflow?.diagnosticsArtifact?.virtualHalSimConfigEvidenceExpansion?.familyRows
?? []
);
const preferredEvidenceExpansion = Array.isArray(evidenceExpansionRows) const preferredEvidenceExpansion = Array.isArray(evidenceExpansionRows)
? (evidenceExpansionRows[0] ?? {}) ? (evidenceExpansionRows[0] ?? {})
: {}; : {};
const evidenceExpansionPreviewRows = Array.isArray(evidenceExpansionRows) const evidenceExpansionPreviewRows = Array.isArray(evidenceExpansionRows)
? evidenceExpansionRows.slice(0, 3) ? evidenceExpansionRows.slice(0, 3)
: []; : [];
const evidenceExpansionFullRows = Array.isArray(evidenceExpansionRows)
? evidenceExpansionRows
: [];
const ready = workflow?.ready === true; const ready = workflow?.ready === true;
const promotionFamilyRows = ( const promotionFamilyRows = (
workflow?.validation?.virtualHalPromotionFamilyRows workflow?.validation?.virtualHalPromotionFamilyRows
@@ -2800,6 +2831,54 @@ export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWo
).join(", ") ).join(", ")
: "not provided", : "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", id: "hard-block-runtime-lock",
label: "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( export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(), renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
{ sourceKind = "all", familyId = "all" } = {}, { 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({ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract({
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter", rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter",
selectors = {}, 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({ export function createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness({
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter", rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter",
contract = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract({ rowDatasetPrefix }), 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( function readPromotionFamilySourceFilterControlValue(
controlsNode, controlsNode,
rowDatasetPrefix, 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({ export function handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange({
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(), renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState), 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({ export function bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls({
renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(), renderState = createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(),
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState), viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState),
@@ -3703,6 +4063,98 @@ export function bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSele
return binding; 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( export function renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(), 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({ export function mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState({
viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(), viewModel = createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(),
rowDatasetPrefix = "workflowOverviewPromotionFamilySourceFilter", 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({ export function createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract({
rowDatasetPrefix = "workflowOverviewPromotionFamily", rowDatasetPrefix = "workflowOverviewPromotionFamily",
selectors = {}, selectors = {},
@@ -6835,6 +7383,28 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
createWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState: createWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState:
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createWorkflowOverviewEvidenceExpansionFamilyRowsRenderState:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan:
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange:
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls:
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState:
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState:
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createWorkflowOverviewPromotionFamilyRowsRenderState: createWorkflowOverviewPromotionFamilyRowsRenderState:
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState, createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createWorkflowOverviewPromotionFamilySourceFilterViewModel: createWorkflowOverviewPromotionFamilySourceFilterViewModel:

View File

@@ -162,6 +162,11 @@
<div class="source-filter-controls" data-workflow-overview-promotion-family-source-filter-controls></div> <div class="source-filter-controls" data-workflow-overview-promotion-family-source-filter-controls></div>
<dl data-workflow-overview-promotion-family-source-filter-rows></dl> <dl data-workflow-overview-promotion-family-source-filter-rows></dl>
</section> </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> </section>
</main> </main>
<script type="module"> <script type="module">
@@ -205,6 +210,17 @@
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState, renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState, mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState, createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel, createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract, createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
@@ -256,6 +272,20 @@
const browserDiagnosticsUrlInput = document.querySelector("[data-browser-diagnostics-url-input]"); const browserDiagnosticsUrlInput = document.querySelector("[data-browser-diagnostics-url-input]");
const releaseArtifactUrlWorkflowForm = document.querySelector("[data-release-artifact-url-workflow-form]"); 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 = {}) { async function runWorkflowOverviewReleaseReadinessArtifactUrlForm(options = {}) {
const artifactUrl = String(options.artifactUrl ?? releaseArtifactUrlInput?.value ?? "").trim(); const artifactUrl = String(options.artifactUrl ?? releaseArtifactUrlInput?.value ?? "").trim();
const diagnosticsUrl = String(options.diagnosticsUrl ?? browserDiagnosticsUrlInput?.value ?? "").trim(); const diagnosticsUrl = String(options.diagnosticsUrl ?? browserDiagnosticsUrlInput?.value ?? "").trim();
@@ -326,7 +356,45 @@
document.body.dataset.promotionFamilySourceFilterSourceKind = document.body.dataset.promotionFamilySourceFilterSourceKind =
changeResult.selectedSourceKind; changeResult.selectedSourceKind;
document.body.dataset.promotionFamilySourceFilterCount = 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); String(changeResult.actionPlan.filteredSourceFileCount);
document.body.dataset.evidenceExpansionFamilySourceFilterSummary =
changeResult.actionPlan.statusLine;
}, },
}); });
document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase; document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase;
@@ -337,6 +405,16 @@
promotionFamilySourceFilter.ready ? "true" : "false"; promotionFamilySourceFilter.ready ? "true" : "false";
document.body.dataset.promotionFamilySourceFilterCount = document.body.dataset.promotionFamilySourceFilterCount =
String(promotionFamilySourceFilter.filteredSourceFileCount); 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 { return {
workflow, workflow,
summary, summary,
@@ -355,6 +433,12 @@
promotionFamilySourceFilter, promotionFamilySourceFilter,
promotionFamilySourceFilterMountResult, promotionFamilySourceFilterMountResult,
promotionFamilySourceFilterBinding, promotionFamilySourceFilterBinding,
evidenceExpansionFamilyRowsRenderState,
evidenceExpansionFamilySourceFilter,
evidenceExpansionFamilySourceFilterSummary,
evidenceExpansionFamilySourceFilterActionPlan,
evidenceExpansionFamilySourceFilterMountResult,
evidenceExpansionFamilySourceFilterBinding,
}; };
} }
@@ -459,6 +543,50 @@
getWorkflowOverviewPromotionFamilyRowsRenderState: (summaryViewModel) => ( getWorkflowOverviewPromotionFamilyRowsRenderState: (summaryViewModel) => (
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(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) => ( getWorkflowOverviewPromotionFamilySourceFilterViewModel: (renderState, options) => (
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState, options) createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState, options)
), ),

View File

@@ -1757,6 +1757,7 @@ M2
<div><span>Shortcut</span><strong data-diagnostics="shortcut">-</strong></div> <div><span>Shortcut</span><strong data-diagnostics="shortcut">-</strong></div>
<div class="promotion-family-panel" data-promotion-family-rows></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-promotion-candidate-summary></div>
<div class="promotion-candidate-panel" data-evidence-expansion-summary></div>
<div class="tool-table-mini" data-axis-shell="tool-table"> <div class="tool-table-mini" data-axis-shell="tool-table">
<table aria-label="Loaded tool table"> <table aria-label="Loaded tool table">
<thead> <thead>
@@ -2788,6 +2789,86 @@ M2
return summary; 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) { function renderMachineStatusDom(machineStatus) {
const statusMap = { const statusMap = {
"spindle-state": machineStatus.spindle.state, "spindle-state": machineStatus.spindle.state,
@@ -2828,8 +2909,10 @@ M2
renderLimitsHomeState(createVirtualHalLimitsHomeState()); renderLimitsHomeState(createVirtualHalLimitsHomeState());
renderMillturnUserMProcessState(); renderMillturnUserMProcessState();
const promotionCandidateReport = createVirtualHalSimConfigPromotionCandidateReport(); const promotionCandidateReport = createVirtualHalSimConfigPromotionCandidateReport();
const evidenceExpansionReport = createVirtualHalSimConfigEvidenceExpansionReport();
renderPromotionFamilyRows(promotionCandidateReport); renderPromotionFamilyRows(promotionCandidateReport);
renderPromotionCandidateSummary(createVirtualHalPromotionCandidateSummary(promotionCandidateReport)); renderPromotionCandidateSummary(createVirtualHalPromotionCandidateSummary(promotionCandidateReport));
renderEvidenceExpansionSummary(createVirtualHalEvidenceExpansionSummary(evidenceExpansionReport));
document.querySelector("[data-axis-machine-control-state]")?.setAttribute("data-state", "ready"); document.querySelector("[data-axis-machine-control-state]")?.setAttribute("data-state", "ready");
return cloneVirtualHalState(); return cloneVirtualHalState();
} }
@@ -4333,6 +4416,7 @@ M2
getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(), getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(),
getVirtualHalSimConfigPromotionCandidateReport: () => createVirtualHalSimConfigPromotionCandidateReport(), getVirtualHalSimConfigPromotionCandidateReport: () => createVirtualHalSimConfigPromotionCandidateReport(),
getVirtualHalSimConfigEvidenceExpansionReport: () => createVirtualHalSimConfigEvidenceExpansionReport(), getVirtualHalSimConfigEvidenceExpansionReport: () => createVirtualHalSimConfigEvidenceExpansionReport(),
getVirtualHalEvidenceExpansionSummary: () => renderEvidenceExpansionSummary(),
getVirtualHalPromotionCandidateSummary: () => renderPromotionCandidateSummary(), getVirtualHalPromotionCandidateSummary: () => renderPromotionCandidateSummary(),
getVirtualHalPromotionFamilyRows: () => renderPromotionFamilyRows(), getVirtualHalPromotionFamilyRows: () => renderPromotionFamilyRows(),
getVirtualHalSimConfigMacroLoadFixtureReport: () => createVirtualHalSimConfigMacroLoadFixtureReport(), getVirtualHalSimConfigMacroLoadFixtureReport: () => createVirtualHalSimConfigMacroLoadFixtureReport(),

View File

@@ -244,7 +244,7 @@ TOOL_TABLE = browser-shell-tool.tbl
"shell handoff action-plan next steps", "shell handoff action-plan next steps",
); );
assertEqual(handoffChecklist.ready, true, "shell handoff checklist readiness"); 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( assertEqual(
handoffChecklist.checks.map(({ status }) => status).join(","), handoffChecklist.checks.map(({ status }) => status).join(","),
"pass,pass,pass,pass,pass", "pass,pass,pass,pass,pass",
@@ -1039,6 +1039,31 @@ TOOL_TABLE = browser-shell-tool.tbl
"3, 3, 3", "3, 3, 3",
"shell workflow overview release artifact URL workflow evidence expansion source count list", "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( assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowRenderResult.rowIds.includes("hard-block-runtime-lock"), workflowOverviewReleaseArtifactUrlWorkflowRenderResult.rowIds.includes("hard-block-runtime-lock"),
true, true,

View File

@@ -9,6 +9,7 @@
<script type="module"> <script type="module">
import { import {
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS, VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMillturnUserMProcessBoundaryReport, createVirtualHalMillturnUserMProcessBoundaryReport,
createVirtualHalMotionControllerMatrixReport, createVirtualHalMotionControllerMatrixReport,
@@ -23,6 +24,8 @@
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES = const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []); 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) { function assertEqual(actual, expected, label) {
if (actual !== expected) { 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"); const frame = document.createElement("iframe");
frame.src = "../../runtime/ui/ini-panel/workflow-overview.html"; frame.src = src;
document.body.appendChild(frame); document.body.appendChild(frame);
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
frame.addEventListener("load", resolve, { once: true }); frame.addEventListener("load", resolve, { once: true });
@@ -69,6 +74,17 @@
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState || !workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState || !workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
!workflowApi?.getWorkflowOverviewPromotionFamilyRowsRenderState || !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?.getWorkflowOverviewPromotionFamilySourceFilterViewModel ||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomContract || !workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomContract ||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomReadiness || !workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomReadiness ||
@@ -395,7 +411,7 @@
const diagnosticsEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({ const diagnosticsEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({
manifestEntries: [ manifestEntries: [
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES, ...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ini", ...VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES,
], ],
motionControllerMatrix: diagnosticsMotionControllerMatrix, motionControllerMatrix: diagnosticsMotionControllerMatrix,
}); });
@@ -736,6 +752,16 @@
"3, 3, 3", "3, 3, 3",
"workflow overview release artifact URL workflow evidence expansion source count list", "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( assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value, releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
@@ -1027,6 +1053,31 @@
"3, 3, 3", "3, 3, 3",
"workflow overview fixed URL workflow form evidence expansion source count list row", "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( assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-source-file-count"]').textContent, workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-source-file-count"]').textContent,
"17 source files", "17 source files",
@@ -1175,6 +1226,142 @@
"0", "0",
"workflow overview source filter changed rose engine promotion allowed", "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( assertEqual(
releaseArtifactJsonWorkflow.statusLine, releaseArtifactJsonWorkflow.statusLine,
"Ready: Artifact JSON workflow complete", "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/qtdragon_xyz45/qtdragon_xyza.ini") ||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini") || !diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini") ||
diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.complete !== true || diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.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?.ready !== true ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.preferredCandidateId !== "qtdragon-multi-joint-on-abort" || diagnosticsArtifact.virtualHalPromotionCandidateSummary?.preferredCandidateId !== "qtdragon-multi-joint-on-abort" ||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.candidateCount !== 8 || diagnosticsArtifact.virtualHalPromotionCandidateSummary?.candidateCount !== 8 ||
@@ -678,6 +698,18 @@
promotionCandidateSummary.preferredIniPath !== "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" || promotionCandidateSummary.preferredIniPath !== "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" ||
doc.body.dataset.promotionCandidateReady !== "true" || doc.body.dataset.promotionCandidateReady !== "true" ||
doc.body.dataset.promotionCandidatePreferred !== "qtdragon-multi-joint-on-abort" || 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="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="candidate-layers"]')?.textContent !== "evidence-ready=8 inventory-ready=2" ||
doc.querySelector('[data-promotion-candidate-summary-value="inventory-baseline"]')?.textContent !== "82/82 pass; 77 skip" || 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", "sim_configs_wasm_node_inventory_skip_UPSTREAM_DEMO=1",
"build/wasm/sim-configs-inventory/skip-summary.tsv", "build/wasm/sim-configs-inventory/skip-summary.tsv",
"build/wasm/sim-configs-inventory/blocked-dependency-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_no_standalone_cnc_semantics.sh",
"verify_sim_configs_coverage_docs.sh", "verify_sim_configs_coverage_docs.sh",
"L4-PYTHON-REMAP", "L4-PYTHON-REMAP",
@@ -65,6 +70,40 @@ for (const phrase of [
"axis/rose_engine/rcone_demo.ngc", "axis/rose_engine/rcone_demo.ngc",
"axis/external_offsets/queuebuster.ngc", "axis/external_offsets/queuebuster.ngc",
"Web Simulation Improvements From Virtual HAL", "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", "Browser and Node simulation no longer need host `halcmd`, `halrun`, or a",
"servo-period stepping", "servo-period stepping",
"8 diagnostics-ready candidates across 3 families and 17 source files", "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"); 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, readySummary.rows.find(({ id }) => id === "evidence-expansion-source-count-list")?.value,
"3, 3, 3", "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( assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value, readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv", "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-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-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-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"], ["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"], ["promotion-candidate-allowed", "0"],
["hard-block-runtime-locked-rows", "1"], ["hard-block-runtime-locked-rows", "1"],

View File

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

View File

@@ -154,6 +154,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState, renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState, mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryRenderState, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomContract, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactGateExecutionSummaryDomReadiness,
@@ -299,6 +310,9 @@ const expectedPromotionCandidateArtifactSummary = {
promotionAllowedCount: 0, promotionAllowedCount: 0,
baselineChanging: false, baselineChanging: false,
nextEvidence: "browser-diagnostics-binding", nextEvidence: "browser-diagnostics-binding",
familyCount: 0,
familySummary: "not provided",
familyRows: [],
}, },
}; };
const hasFreshBoundaryArtifactHashes = (boundaryEvidence) => const hasFreshBoundaryArtifactHashes = (boundaryEvidence) =>
@@ -580,6 +594,50 @@ const requiredExports = [
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan", "createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
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",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactValidationSummaryViewModel,
@@ -1084,7 +1142,7 @@ assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
simConfigSourceCoverage: simConfigSourceCoverageReport, simConfigSourceCoverage: simConfigSourceCoverageReport,
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport, motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
}).complete, true); }).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({ const simConfigEvidenceExpansionReport = createVirtualHalSimConfigEvidenceExpansionReport({
manifestText: sourceManifestText, manifestText: sourceManifestText,
simConfigSourceCoverage: simConfigSourceCoverageReport, simConfigSourceCoverage: simConfigSourceCoverageReport,
@@ -1098,8 +1156,22 @@ assert.equal(simConfigEvidenceExpansionReport.complete, true);
assert.equal(simConfigEvidenceExpansionReport.webSimulationSatisfied, true); assert.equal(simConfigEvidenceExpansionReport.webSimulationSatisfied, true);
assert.equal(simConfigEvidenceExpansionReport.inventoryBaselineUnchanged, true); assert.equal(simConfigEvidenceExpansionReport.inventoryBaselineUnchanged, true);
assert.equal(simConfigEvidenceExpansionReport.promotionAllowed, false); assert.equal(simConfigEvidenceExpansionReport.promotionAllowed, false);
assert.equal(simConfigEvidenceExpansionReport.candidateCount, 3); assert.equal(simConfigEvidenceExpansionReport.candidateCount, 11);
assert.equal(simConfigEvidenceExpansionReport.readyCandidateCount, 3); 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.promotionAllowedViolations.length, 0);
assert.equal( assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) => simConfigEvidenceExpansionReport.rows.some((row) =>
@@ -1111,6 +1183,49 @@ assert.equal(
), ),
true, 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_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_BLOCKED_FIXTURES.length >= 2, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES.length >= 2, true); assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES.length >= 2, true);

View File

@@ -9,6 +9,7 @@ import {
createProjectReleaseReadinessReport, createProjectReleaseReadinessReport,
} from "../../../runtime/sdk/src/project-release-readiness.js"; } from "../../../runtime/sdk/src/project-release-readiness.js";
import { import {
VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS, VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
createVirtualHalCommandScriptFixtureReport, createVirtualHalCommandScriptFixtureReport,
createVirtualHalMillturnUserMProcessBoundaryReport, createVirtualHalMillturnUserMProcessBoundaryReport,
@@ -86,6 +87,17 @@ import {
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan,
createIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan,
handleIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange,
bindIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls,
renderIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
mountIniPanelShellWorkflowOverviewEvidenceExpansionFamilySourceFilterState,
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState, createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel, createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract, createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
@@ -164,6 +176,8 @@ import {
const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES = const VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES =
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []); 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 __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, "../../.."); const root = resolve(__dirname, "../../..");
@@ -790,6 +804,17 @@ assert.deepEqual(shellViewModel.shellWorkflowOverviewContract, {
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState", "getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
"getWorkflowOverviewPromotionFamilyRowsRenderState", "getWorkflowOverviewPromotionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomContract",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterDomReadiness",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSummary",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterActionPlan",
"getWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionActionPlan",
"handleWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionChange",
"bindWorkflowOverviewEvidenceExpansionFamilySourceFilterSelectionControls",
"renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState",
"getWorkflowOverviewPromotionFamilySourceFilterViewModel", "getWorkflowOverviewPromotionFamilySourceFilterViewModel",
"getWorkflowOverviewPromotionFamilySourceFilterDomContract", "getWorkflowOverviewPromotionFamilySourceFilterDomContract",
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness", "getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
@@ -1460,7 +1485,7 @@ const releaseReadinessPromotionCandidates = createVirtualHalSimConfigPromotionCa
const releaseReadinessEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({ const releaseReadinessEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({
manifestEntries: [ manifestEntries: [
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES, ...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
"linuxcnc/configs/sim/axis/vismach/puma/puma_cube.ini", ...VIRTUAL_HAL_EVIDENCE_EXPANSION_MANIFEST_ENTRIES,
], ],
motionControllerMatrix: releaseReadinessMotionControllerMatrix, motionControllerMatrix: releaseReadinessMotionControllerMatrix,
}); });
@@ -2107,6 +2132,30 @@ assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-source-count-list")?.value, releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-source-count-list")?.value,
"3, 3, 3", "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( assert.equal(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value, releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=82 passed=82 skipped=77 unexpected_fail=0", "executed=82 passed=82 skipped=77 unexpected_fail=0",
@@ -2683,6 +2732,263 @@ assert.equal(
), ),
true, 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( assert.equal(
promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) => promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) =>
sourceKind === "ini" && sourceKind === "ini" &&
@@ -2855,7 +3161,7 @@ const releaseArtifactUrlWorkflowMountResult =
rowsNode: releaseArtifactUrlWorkflowRowsNode, rowsNode: releaseArtifactUrlWorkflowRowsNode,
}); });
assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true); assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true);
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 53); assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 61);
assert.equal( assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"), releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"),
true, true,
@@ -2900,12 +3206,20 @@ assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("evidence-expansion-source-count-list"), releaseArtifactUrlWorkflowRenderResult.rowIds.includes("evidence-expansion-source-count-list"),
true, 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( assert.equal(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"), releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"),
true, true,
); );
assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true); assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true);
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 53); assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 61);
const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({ const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
artifactUrl: "/project-release-readiness.json", artifactUrl: "/project-release-readiness.json",
fetchRef: async () => ({ fetchRef: async () => ({
@@ -2965,6 +3279,34 @@ const workflowOverviewApi = {
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan: () => releaseArtifactUrlWorkflow.actionPlan, getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan: () => releaseArtifactUrlWorkflow.actionPlan,
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState: () => releaseArtifactUrlWorkflowRenderState, getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState: () => releaseArtifactUrlWorkflowRenderState,
getWorkflowOverviewPromotionFamilyRowsRenderState: () => promotionFamilyRowsRenderState, 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, getWorkflowOverviewPromotionFamilySourceFilterViewModel: () => promotionFamilySourceFilterViewModel,
getWorkflowOverviewPromotionFamilySourceFilterDomContract: getWorkflowOverviewPromotionFamilySourceFilterDomContract:
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract, createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,