# Sim Config Coverage Promotion Analysis

This analysis records how the completed virtual HAL changes the next
`linuxcnc/configs/sim` coverage-promotion work. It is intentionally an analysis
document only: it does not promote rows, change inventory counts, or relax any
blocked runtime family.

## Current Baseline

Current machine-readable inventory remains:

```text
sim_configs_wasm_node_inventory_executed=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
```

The current generated inventory has no skipped main-program row whose hard
block is already empty. That matters: virtual HAL maturity should not be used
as a blanket reason to reduce the skip baseline. The next useful promotions are
case promotions from Node inventory or representative coverage into browser,
diagnostics, and release evidence.

## 2026-06-20 Remaining Skip Promotion Audit

The generated audit for the remaining 77 skipped rows is:

```text
build/wasm/sim-configs-inventory/remaining-skip-main-program-promotion-audit.tsv
```

It contains only two skipped rows whose class is `main`:

| Path | Skip kind | Native status | Promotion allowed | Decision |
| --- | --- | --- | ---: | --- |
| `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc` | `UPSTREAM-DEMO` | `FAIL` with `upstream-demo-missing-motion-gcode` | 0 | Preserve as an upstream demo edge; do not force into PASS. |
| `axis/vismach/millturn/example.ngc` | `L4-USER-M-PROCESS` | `PASS` | 0 | Web virtual HAL proof exists for M428/M429 to M128/M129 transition state, but arbitrary external user-M process execution remains disabled and is not an inventory promotion proof. |

The remaining skipped rows are not direct main-program promotion targets:

```text
ASSET-ONLY=65
NON_MAIN_CLASS=10
```

The 2026-06-20 audit conclusion is therefore explicit:

```text
remaining_skip_count=77
remaining_skipped_main_program_rows=2
remaining_skipped_main_program_promotion_allowed=0
direct_inventory_promotion_rows=0
baseline_change_allowed=no
```

Future work should add browser diagnostics and release evidence for already
passing Node inventory or representative rows. It should not change the
inventory baseline unless a later patch supplies LinuxCNC-owned native proof,
Node/WASM proof, browser proof, and a manual promotion-lock update for the row
being promoted.

## What Virtual HAL Unlocks

The virtual HAL is now a source-derived Web simulation replacement for these
runtime surfaces:

- LinuxCNC realtime HAL simulation replacement;
- `halcmd` simulation replacement;
- motion controller simulation replacement;
- HAL pin/signal/param store;
- `setp`, `sets`, `net`, `show`, `getp`, `gets`, `loadrt`, `loadusr`, `addf`,
  `start`, and `stop` command workflow;
- servo-period motion stepping;
- axis/joint position feedback;
- source-compliance, sim-config source coverage, command fixture, and motion
  matrix reports;
- OPFS/session persistence and release diagnostics evidence.

That means Web coverage can now promote additional cases when their remaining
dependency is HAL, HALUI, deterministic virtual `halcmd`, machine state, or
motion feedback. It does not unlock rows whose defining behavior is Python
remap runtime, tool database process protocol, external user-M process state,
or upstream-invalid demo code.

## Web Simulation Improvements From Virtual HAL

Using the completed virtual HAL evidence improves the Web CNC simulation in
these concrete ways:

- Browser and Node simulation no longer need host `halcmd`, `halrun`, or a
  native motion-controller process for HAL-level diagnostics.
- UI workflows can inspect and update HAL pins, signals, and params through a
  shared source-derived registry instead of private page state.
- Simulation pages can run deterministic `halcmd`-style command fixtures such
  as `setp`, `sets`, `newsig`, `net`, `show`, `getp`, `gets`, `loadrt`,
  `loadusr`, `addf`, `start`, and `stop`.
- Motion feedback can advance through servo-period stepping so dashboards can
  display axis/joint target and feedback state without host realtime services.
- Browser diagnostics artifacts can carry source compliance, sim-config source
  coverage, command fixture, promotion candidate, macro/load fixture, and
  manifest-backed motion matrix evidence in one release surface.
- Release URL workflows can show the promotion candidate summary, including
  8 diagnostics-ready candidates across 3 families and 17 source files.
- OPFS/session workflows can persist and reload virtual HAL-backed diagnostics
  evidence for repeatable browser validation.

These improvements make the Web simulation more complete and inspectable for
HAL/UI/machine-state cases. They are still evidence and simulation-surface
improvements only: they do not implement Linux kernel hard realtime, native HAL
module ABI loading, Python remap runtime, tool DB process protocol, external
user-M process execution, or new JavaScript-owned CNC semantics.

## Promotion Rules After Virtual HAL

A sim-config case can move forward only when all of these are true:

1. LinuxCNC source/config evidence owns the behavior.
2. Native or current Node inventory evidence already passes, or the row is a
   macro/load or subroutine class with an explicit non-main validation plan.
3. Dependencies are limited to virtual HAL, HALUI, deterministic UI process
   declarations, machine files, tool tables, remap subroutine assets, or
   motion/kinematics evidence already covered by LinuxCNC-backed runtime.
4. Browser evidence can export virtual HAL source compliance, sim-config
   source coverage, command fixtures, and manifest-backed motion matrix.
5. The row is not `L4-PYTHON-REMAP`, `L4-TOOL-DB`, `L4-USER-M-PROCESS`, or
   `UPSTREAM-DEMO`.
6. `verify_no_standalone_cnc_semantics.sh` remains green.

Promotion should mean a stronger evidence tier, not necessarily a lower skip
count. For example, a row may move from Node `INV` to browser diagnostics
evidence while the inventory baseline remains `executed=28`.

## Recommended Promotion Candidates

### Tier 1: Browser Evidence For Existing Node INV Rows

These rows already pass Node inventory and have no hard runtime block. Virtual
HAL makes them good candidates for browser diagnostics/release evidence rather
than only shared representative coverage.

| Candidate | Current coverage | Why it is now promotable |
| --- | --- | --- |
| `qtdragon/qtdragon_multi_joint/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Requires HAL/UI declarations and multi-joint machine context; virtual HAL motion matrix already maps `qtdragon-on-abort` and `qtdragon_xyyz.ini`. |
| `qtdragon/qtdragon_xyz/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Same on-abort family, already part of virtual HAL sim-config source coverage evidence. |
| `qtdragon/qtdragon_xyz45/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Adds rotary-axis machine context without requiring Python remap or external process runtime. |
| `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | Deterministic UI/HAL family, suitable for browser diagnostics artifact evidence. |
| `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | HAL/UI machine state case; should be promoted only with explicit source evidence for the z-compensation INI. |
| `qtvcp_screens/qtdragon/on_abort.ngc` | Node `INV`, browser delegated to `woodpecker` | QTVCP on-abort surface, no Python-remap hard block in inventory. |
| `axis/vismach/puma/puma_seam_weld.ngc` | Node `INV`, browser represented by `puma_cube.ngc` | Same vendored PUMA machine context; virtual HAL motion matrix already includes `vismach-remap-sims` and `puma.ini`. |
| `axis/rose_engine/rcone_demo.ngc` | Node `INV` | HAL process only, no hard block; useful as a non-Qt/non-vismach browser diagnostics candidate. |

Expected next artifact shape:

- extend a source-derived candidate list in SDK or docs;
- add browser diagnostics fixture rows, not a JS CNC interpretation path;
- assert virtual HAL source compliance, sim-config source coverage, command
  fixtures, and motion matrix remain complete;
- update matrix notes from delegated browser representative to explicit browser
  evidence only after the browser gate exists.

### Tier 2: Existing REP Rows Worth Splitting Into More Cases

These are already promoted as representative coverage. The next work is not to
prove the class exists; it is to split representative buckets into more
specific cases now that virtual HAL can carry machine state evidence.

| Candidate | Current coverage | Promotion goal |
| --- | --- | --- |
| `axis/vismach/5axis/bridgemill/5axisgui.ngc` | Node/browser `REP` | Add explicit HALUI MDI and W-axis diagnostics evidence. |
| `axis/vismach/5axis/table-dual-rotary/demos/xyzab-tdr-demo.ngc` | Node/browser `REP` | Add dual-rotary ABC/AB feedback evidence in motion matrix rows. |
| `axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc` | Node/browser `REP` | Add TRT machine-family diagnostics evidence separate from generic 5-axis class. |
| `axis/vismach/melfa-sim/example.ngc` | Node/browser `REP` | Add robot/Genser remap-machine evidence with source files and session diagnostics. |
| `axis/vismach/puma/puma_cube.ngc` | Node/browser `REP` | Keep as PUMA representative but pair with `puma_seam_weld.ngc` Node `INV` evidence. |

### Tier 3: Macro/Load Rows With No Hard Runtime Block

These rows are not standalone main-program targets, so they should not be
promoted by executing them as browser main programs. They can move forward as
explicit macro/load fixtures if the gate names them as non-main class evidence.

| Candidate | Current status | Promotion goal |
| --- | --- | --- |
| `axis/external_offsets/queuebuster.ngc` | `NON_MAIN_CLASS` | Add external-offset macro/load source fixture next to `circles.ngc`. |
| `axis/lathe-fanucy/toolchange.ngc` | `NON_MAIN_CLASS` | Add macro/load fixture if the lathe-fanucy INI/tool context is vendored. |
| `axis/rose_engine/rcone.ngc` | inventory-only macro/load | Pair with `rcone_demo.ngc` to prove rose-engine support assets load. |
| `gscreen/industrial_lathe_wear/toolchange.ngc` | inventory-only macro/load | Candidate only if kept as macro/load evidence, not UI process emulation. |
| `gscreen/silverdragon/macros/*.ngc` | inventory-only macro/load | Candidate for a small macro fixture subset, not all macros at once. |
| `qtvcp_screens/industrial_lathe_wear/toolchange.ngc` | inventory-only macro/load | Candidate only as non-main fixture evidence. |

## Rows Still Not Promotable

Virtual HAL does not change these blocked decisions:

- `L4-PYTHON-REMAP`: still requires LinuxCNC-owned Python remap runtime proof.
  Examples include laser, many `axis/remap/*`, gmoccapy macro families, and
  table-rotary-spindle-nutating TWP demos.
- `L4-TOOL-DB`: `axis/db_demo/base.ngc` still requires tool database process
  protocol proof, not only HAL state.
- `L4-USER-M-PROCESS`: `axis/vismach/millturn/example.ngc` still requires
  external `USER_M_PATH` process state proof for `M128`/`M129`.
- `UPSTREAM-DEMO`: `incremental_repetition_g533.ngc` remains a preserved
  upstream demo edge and must not be forced to pass by standalone semantics.
- `ASSET-ONLY`: remap subroutines remain validated by parse/remap or owning
  main-program context, not standalone browser execution.

## Proposed Next Batch

The next implementation batch should avoid changing the inventory baseline.
It should add a promotion-candidate report and one or two browser evidence
fixtures.

Recommended first slice:

1. Add a machine-readable candidate report for Tier 1 rows:
   `qtdragon-on-abort`, `puma-seam-weld`, and `rose-engine`.
2. Require every row to name LinuxCNC source files, INI files, G-code files,
   dependency class, current Node status, and target browser evidence.
3. Add Node gate assertions that no candidate is in `L4-PYTHON-REMAP`,
   `L4-TOOL-DB`, `L4-USER-M-PROCESS`, `UPSTREAM-DEMO`, or `ASSET-ONLY`.
4. Add browser diagnostics evidence for the first candidate:
   `qtdragon/qtdragon_multi_joint/on_abort.ngc`.
5. Keep `sim_configs_wasm_node_inventory_executed=82`,
   `sim_configs_wasm_node_inventory_passed=82`, and
   `sim_configs_wasm_node_inventory_skipped=77` unchanged until a deliberate
   inventory-promotion patch is made.

Recommended gates:

```bash
git diff --check
wasm-port/tests/docs/node/verify_sim_configs_coverage_docs.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
wasm-port/tests/sdk/node/verify_sdk_surface.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
```

## 2026-06-18 QtDragon Family Promotion Evidence

The first promotion-candidate gate has now been extended from a single
`qtdragon/qtdragon_multi_joint/on_abort.ngc` row to the full QtDragon
on-abort family:

- `qtdragon/qtdragon_multi_joint/on_abort.ngc`
- `qtdragon/qtdragon_xyz/on_abort.ngc`
- `qtdragon/qtdragon_xyz45/on_abort.ngc`
- `qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc`
- `qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc`
- `qtvcp_screens/qtdragon/on_abort.ngc`

The implementation remains a diagnostics/evidence promotion, not an inventory
baseline change. The rows still report Node inventory `PASS` with matrix
`INV`, but the virtual HAL promotion candidate report and real browser
diagnostics artifact now require every QtDragon candidate to be complete, to
name its LinuxCNC INI and G-code source files, to keep `currentNodeInventoryStatus
=== "PASS"`, and to target `explicit-browser-diagnostics`.

The virtual HAL sim-config source coverage target also includes the previously
missing QtDragon `qtdragon_xyz45` and `qtdragon_hd_z_compensation` INI/program
source files. This keeps the report source-derived from vendored LinuxCNC
machine files rather than browser-owned CNC behavior.

Inventory baseline remains:

```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
```

## 2026-06-18 Non-Qt Promotion Evidence

The promotion-candidate release gate has now been extended beyond QtDragon to
the two Tier 1 non-Qt candidates:

- `axis/vismach/puma/puma_seam_weld.ngc`
- `axis/rose_engine/rcone_demo.ngc`

The required candidate set now covers all eight source-derived Tier 1 rows:
the six QtDragon on-abort candidates, PUMA seam weld, and rose-engine cone
demo. Release diagnostics validation requires the PUMA row to include
`puma.ini`, `puma_seam_weld.ngc`, and the LinuxCNC remap subroutine source
`remap_subs/428remap.ngc`. It also requires the rose-engine row to include
`rose_engine.ini` and `rcone_demo.ngc`.

This still does not change inventory promotion counts. Both rows remain Node
inventory `PASS` with matrix `INV`; the added value is explicit browser
diagnostics evidence and release-gate enforcement that the virtual HAL reports
are complete for non-Qt sim-config families.

## 2026-06-18 Macro/Load Non-Main Fixture Evidence

The virtual HAL diagnostics evidence now includes an explicit macro/load
fixture report:

- `VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES`
- `createVirtualHalSimConfigMacroLoadFixtureReport()`

The first required non-main fixtures are:

- `axis/rose_engine/rcone.ngc`
- `axis/external_offsets/queuebuster.ngc`

The rose-engine fixture is paired with `rcone_demo.ngc` and keeps `rcone.ngc`
as a non-main macro/load asset. The external-offsets fixture records
`queuebuster.ngc` as a declared `NGCGUI_SUBFILE` through `eoffsets.ini`; the
fixture path is preserved for diagnostics, while the manifest-backed source
evidence is the owning INI and paired LinuxCNC program source. This avoids
pretending that `queuebuster.ngc` is a standalone browser main program.

Release diagnostics validation now requires
`virtualHalSimConfigMacroLoadFixtures` to be present and ready. The report must
keep `inventoryBaselineUnchanged === true`, every row must have
`nonMainFixture === true`, and `standaloneMainViolations` must stay empty.

## 2026-06-18 Macro/Load Blocked Fixture Lock

The macro/load report now also carries a blocked-fixture lock. This is a
negative evidence gate: it proves selected macro/load paths are not included in
positive virtual HAL fixtures when their owner boundary is still unavailable or
outside the virtual HAL scope.

The first blocked fixture rows are:

- `gscreen/silverdragon/macros/tool_sensor.ngc`
- `gmoccapy/macros/on_abort.ngc`

`tool_sensor.ngc` is intentionally not promoted because the owning
`gscreen/silverdragon/silverdragon.ini` machine file is not available in the
vendored manifest, and promoting it would require a Python UI/process boundary
proof rather than virtual HAL diagnostics alone. `gmoccapy/macros/on_abort.ngc`
remains locked behind `L4-PYTHON-REMAP` and LinuxCNC-owned Python
remap/prolog/epilog runtime proof.

Release diagnostics validation now requires
`blockedFixturePromotionViolations` to stay empty and requires both blocked
rows to be excluded from positive macro/load fixtures. This prevents virtual
HAL from accidentally unlocking Python UI or Python remap families.

The next practical slice is to add a machine-readable candidate audit for other
UI-family macro/load rows before promoting any new positive fixture.

## 2026-06-18 UI-Family Macro/Load Candidate Audit

The macro/load report now carries audit rows for UI-family fixture candidates
that are not ready for positive promotion:

- `gscreen/industrial_lathe_wear/toolchange.ngc`
- `qtvcp_screens/industrial_lathe_wear/toolchange.ngc`

Both rows are recorded as `blocked-missing-owning-ini` audit candidates with
`promotionAllowed === false`. They must remain excluded from positive
macro/load fixtures until the owning INI, machine files, tool table, and
UI/process declaration have LinuxCNC source evidence that does not require
Python UI process emulation.

Release diagnostics validation now requires `auditPromotionViolations` to stay
empty and requires both audit rows to be present as negative evidence. This is
an audit gate, not a coverage promotion: inventory baseline remains unchanged.

## 2026-06-18 UI-Family Audit Boundary Evidence

The UI-family audit rows now carry machine-readable source evidence from the
generated inventory boundary artifacts:

- `wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv`
- `wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv`

For both industrial-lathe `toolchange.ngc` rows, the audit evidence requires
`recommendedBlocked === "UNAVAILABLE"` and a `missing_vendored_ini:*`
dependency for the owning INI. The INI-level row must also report
`vendored === 0` and `reportAvailable === 0`.

The macro/load fixture report now exposes:

- `missingAuditRows`
- `auditBoundaryEvidenceViolations`
- `auditPromotionAllowedViolations`

Release diagnostics validation requires all of those lists to stay empty. This
adds negative coverage for three failure modes: audit rows missing, audit rows
accidentally promoted into positive fixtures, and `promotionAllowed === true`
without generated boundary/source proof.

## 2026-06-18 SilverDragon Blocked Boundary Evidence

The blocked macro/load fixture rows now use the same generated boundary
evidence contract. `gscreen/silverdragon/macros/tool_sensor.ngc` carries
evidence from `boundary-summary.tsv` and `ini-boundary-summary.tsv` showing
that the owning `gscreen/silverdragon/silverdragon.ini` is unavailable in the
vendored inventory.

The report now exposes `blockedBoundaryEvidenceViolations`, and release
diagnostics validation requires it to stay empty. This keeps the SilverDragon
row as a blocked negative fixture with source-derived evidence, not a virtual
HAL promotion path.

## 2026-06-18 Queuebuster Declaration Evidence

The declared-only `axis/external_offsets/queuebuster.ngc` fixture now carries
declaration-level evidence from `eoffsets.ini`. The fixture report requires the
owning INI to expose:

- section: `DISPLAY`
- key: `NGCGUI_SUBFILE`
- value: `queuebuster.ngc`
- source line: `NGCGUI_SUBFILE = queuebuster.ngc`

This keeps `queuebuster.ngc` as a non-main fixture path declared by LinuxCNC
configuration, not a standalone browser main program. Release diagnostics
validation now requires `declarationEvidenceViolations` to stay empty.

## 2026-06-18 Rose Engine Declaration Evidence

The positive `axis/rose_engine/rcone.ngc` non-main fixture now carries the same
declaration-level evidence contract as queuebuster. `rose_engine.ini` declares
the fixture with `NGCGUI_SUBFILE = rcone.ngc`, and the macro/load report now
requires every positive fixture with a `declarationSource` to carry matching
source evidence.

This keeps `rcone.ngc` as a LinuxCNC-declared macro/load support asset paired
with `rcone_demo.ngc`, not a standalone browser main program. The evidence is
limited to the owning INI declaration and does not add browser-owned G-code,
interpreter, planner, or remap behavior.

## 2026-06-18 Boundary Evidence Freshness Gate

Generated boundary evidence for blocked and audit-only macro/load rows now
carries an inventory `baselineSummary`. The macro/load report requires that
summary to match the current generated inventory baseline:

```text
executed=82
passed=82
skipped=77
unexpectedFail=0
```

This makes `boundary-summary.tsv` and `ini-boundary-summary.tsv` evidence
explicitly tied to the current inventory baseline. A stale baseline now fails
the blocked/audit boundary evidence gate instead of silently passing release
diagnostics.

## 2026-06-18 Promotion Family URL Workflow Summary

The release readiness validation and URL workflow summaries now surface the
promotion candidate `familyRows` as a user-visible summary. Ready artifacts
show:

```text
qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready
```

The ini-panel workflow overview URL summary reuses this value, so the
QtDragon, PUMA, and rose-engine promotion families are visible without opening
the raw diagnostics JSON. This is a presentation/reporting change only; it
does not change inventory counts or CNC semantics.

## 2026-06-18 Structured Promotion Family Rows

The promotion family summary is now also exposed as structured rows. Each row
records the family id, candidate count, complete count, source file count, and
explicit browser diagnostics readiness. Current rows are:

```text
qtdragon-on-abort: 6/6 ready; sources=12; diagnostics=ready
vismach-remap-sims: 1/1 ready; sources=3; diagnostics=ready
rose-engine-rcone-demo: 1/1 ready; sources=2; diagnostics=ready
```

The release readiness artifact, validation summary, URL workflow summary, and
ini-panel workflow overview all expose these rows. This keeps the summary
machine-readable while preserving the existing single-line text summary.

## 2026-06-18 Boundary Evidence Artifact Hash Gate

Generated boundary evidence now includes SHA-256 hashes for the two source TSV
artifacts used by blocked and audit macro/load evidence:

```text
boundary-summary.tsv de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9
ini-boundary-summary.tsv b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae
```

The macro/load report and release validation require those hashes to match.
This extends the freshness gate beyond inventory counts and makes stale or
substituted boundary TSV evidence fail the release diagnostics gate.

## 2026-06-18 Browser Promotion Family DOM Rows

The real browser simulation page now renders the structured promotion family
rows in the diagnostics panel. The visible browser DOM exposes:

```text
qtdragon-on-abort: 6/6 ready; sources=12
vismach-remap-sims: 1/1 ready; sources=3
rose-engine-rcone-demo: 1/1 ready; sources=2
```

The browser API also exposes `getVirtualHalPromotionFamilyRows()`, and the real
simulation browser smoke asserts that the DOM rows, readiness dataset, and
candidate report agree. This moves the existing source-derived promotion
evidence from view-model/report data into a visible browser diagnostics surface.
It does not change inventory counts or add CNC semantics.

## 2026-06-18 Fast Follow: Hash Tool And INI Panel Promotion DOM

The boundary TSV hash freshness gate now has an update/check helper:

```bash
wasm-port/tools/update_sim_config_boundary_hashes.sh --check
wasm-port/tools/update_sim_config_boundary_hashes.sh --write
```

The script computes SHA-256 for `boundary-summary.tsv` and
`ini-boundary-summary.tsv`, then checks or updates the SDK/release validation
constants. This removes the manual hash-update step after generated inventory
artifacts change.

The ini-panel workflow overview now also has a dedicated promotion family DOM
surface. It can render and mount the three structured promotion rows from the
release URL workflow summary into `[data-workflow-overview-promotion-family-rows]`.
The UI shell smoke verifies the rows mount as ready with the expected QtDragon,
PUMA, and rose-engine values.

## 2026-06-18 Promotion Family Source Drilldown

Promotion family rows now carry their LinuxCNC source file lists through the
release readiness report, validation summary, URL workflow summary, and
ini-panel workflow overview render state. The ini-panel promotion family DOM
mount renders the three family rows plus per-family source-file drilldown rows.

Current drilldown count is 17 source files:

```text
qtdragon-on-abort: 12 source files
vismach-remap-sims: 3 source files
rose-engine-rcone-demo: 2 source files
```

This makes the browser/ini-panel evidence inspectable without opening the raw
JSON artifact, while keeping the underlying behavior LinuxCNC-source-derived.

## 2026-06-18 Promotion Family Source Status

Each ini-panel promotion family source drilldown row now carries source status
metadata:

- `ini` for LinuxCNC INI machine files;
- `gcode` for `.ngc` main/on-abort programs;
- `remap-subroutine` for files under `remap_subs` or `nc_subroutines`;
- `manifest-backed` for rows already carried by the source-derived promotion
  evidence.

The DOM render adds dataset fields for source kind, manifest-backed state, and
source status, so the UI can distinguish machine config, G-code, and remap
support evidence without changing any CNC semantics.

## 2026-06-18 Promotion Family Source Kind Counts

The ini-panel promotion family render state now aggregates source-kind counts
per family and exposes them in the family row DOM dataset. Current counts are:

```text
qtdragon-on-abort: ini=6 gcode=6
vismach-remap-sims: ini=1 gcode=1 remap-subroutine=1
rose-engine-rcone-demo: ini=1 gcode=1
```

The family row display includes this summary, while the per-source drilldown
rows still expose individual source kind and manifest-backed status.

## 2026-06-18 Promotion Family Source Filter View Model

The ini-panel workflow overview now exposes a promotion family source filter
view-model. It can filter the existing source drilldown by `all`, `ini`,
`gcode`, `remap-subroutine`, or `source`, while preserving family grouping and
source-kind counts.

Current filter totals are:

```text
all=17
ini=8
gcode=8
remap-subroutine=1
```

The `remap-subroutine` filter currently resolves to the PUMA remap evidence
row:

```text
linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc
```

This is a browser/UI evidence navigation helper only. It does not change the
promotion candidate set, inventory baseline, or CNC runtime semantics.

## 2026-06-18 Promotion Family Source Family Filter

The source filter view-model now supports a second selector: `familyId`. This
allows UI callers to scope source evidence by promotion family and then filter
within that family by source kind.

Current family filter totals are:

```text
all=17
qtdragon-on-abort=12
vismach-remap-sims=3
rose-engine-rcone-demo=2
```

For example, selecting `virtual-hal-promotion-family-qtdragon-on-abort` with
`gcode` returns 6 QtDragon `.ngc` source rows from the 12-file family scope.
The selector is a view-model feature only; it does not promote additional sim
config rows or relax any blocked runtime family.

## 2026-06-18 Promotion Family Source Filter DOM Surface

The source filter view-model now has a dedicated DOM contract, readiness check,
render helper, and mount helper. The DOM surface renders:

- family filter rows;
- source-kind filter rows;
- filtered source evidence rows;
- selected family/source-kind dataset fields on the mount node.

The QtDragon + `gcode` combination currently renders 13 DOM rows: 7 filter
rows and 6 filtered source rows. This moves the combined evidence filter from a
view-model-only helper into a mountable ini-panel workflow overview surface.
It still only displays existing LinuxCNC-source-derived evidence.

## 2026-06-18 Promotion Family Source Filter Selector Controls

The source filter DOM surface now renders two selector controls in addition to
the diagnostic rows:

- a family selector backed by `familyFilters`;
- a source-kind selector backed by `sourceKindFilters`.

For the QtDragon + `gcode` example, the controls expose the selected family
`virtual-hal-promotion-family-qtdragon-on-abort` and selected source kind
`gcode`, with the `gcode` option carrying count `6`. The selectors currently
render selection state and option metadata for browser integration; they do not
change the underlying promotion evidence or add CNC semantics.

## 2026-06-18 Promotion Family Source Filter Selection Workflow

The selector controls now have an action-plan and selection-change workflow.
The workflow reads the current family/source-kind selector values, derives the
next source filter view-model, and can optionally re-render the source filter
DOM surface.

The current smoke path changes from QtDragon + `gcode` to
`virtual-hal-promotion-family-rose-engine-rcone-demo` + `all`. That produces a
new view-model with 2 filtered source files from a 2-file family scope and
re-renders the DOM rows to include rose-engine source evidence. This is still a
host/UI workflow over existing source-derived evidence only.

## 2026-06-18 Promotion Family Source Filter Event Binding

The selector controls now have a reusable event binding helper. It binds the
family and source-kind `<select>` elements to the selection-change workflow,
tracks the last change result, and can unbind both controls.

The current Node smoke binds two selector controls, changes the family selector
to `virtual-hal-promotion-family-rose-engine-rcone-demo`, dispatches a `change`
event, and verifies that the source filter DOM re-renders with 2 rose-engine
source rows. This keeps the browser integration path explicit without changing
promotion status or CNC semantics.

## 2026-06-18 Release URL Promotion Summary Counts

The release artifact URL workflow summary now exposes the promotion candidate
summary counts as first-class rows:

```text
virtual-hal-promotion-family-count=3 families
virtual-hal-promotion-source-file-count=17 source files
virtual-hal-promotion-browser-diagnostics-count=8 diagnostics-ready
```

These rows are read from the existing browser diagnostics
`virtualHalPromotionCandidateSummary`. They make the current evidence-ready
promotion set easier to inspect from SDK, ini-panel, and browser workflow
surfaces. They do not add virtual HAL runtime capability, do not alter
`promotion-candidates.tsv`, and do not change the inventory baseline or any
hard-block lock.

## 2026-06-20 Five-Axis TRT Evidence Expansion

After the remaining 77 SKIP audit confirmed there are no directly promotable
skipped main-program rows, the next evidence batch expanded browser diagnostics
coverage for already passing representative rows instead of changing the
inventory baseline.

The virtual HAL sim-config evidence expansion report now requires these
five-axis TRT rows:

```text
trt-boat-xyzac
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzac.ngc

trt-xyzac-switchkins
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins.ngc

trt-boat-xyzbc
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc

trt-impeller-7bl-xyzac
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/impeller-7bl-xyzac.ngc

trt-xyzac-switchkins-test-1
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc

trt-xyzac-switchkins-test-2
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_2.ngc

trt-xyzac-switchkins-test-3
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc

trt-xyzbc-switchkins
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc
```

Both rows use the LinuxCNC-owned `xyzac-trt.ini` machine context and the
vendored `428remap.ngc`, `429remap.ngc`, and `430remap.ngc` remap
subroutines. They remain:

```text
currentNodeInventoryStatus=PASS
currentMatrixBrowserStatus=REP
targetBrowserEvidence=browser-diagnostics-expansion
promotionAllowed=false
inventoryBaselineUnchanged=true
```

The real browser simulation diagnostics artifact now validates that the
evidence expansion report has `candidateCount=11` and `readyCandidateCount=11`,
including the TRT rows above. The inventory baseline remains
`executed=82 passed=82 skipped=77 unexpected_fail=0`.

## 2026-06-20 Evidence Expansion UI Surface

The evidence expansion data is now visible outside the raw diagnostics JSON:

```text
real-browser-simulation-evidence-expansion-summary
evidence-expansion-full-candidate-list
evidence-expansion-full-gcode-list
evidence-expansion-family-count
evidence-expansion-family-summary
evidence-expansion-family-source-count-list
```

The real simulation diagnostics panel renders `11/11 ready`, the full eleven-row
candidate list, source-file count, promotion lock state, and unchanged
inventory state. The project release URL workflow summary and INI workflow
overview keep their existing three-row preview fields for compatibility, and
also expose the full candidate and G-code lists so shell callers can inspect
all eleven ready evidence-expansion rows without opening the raw artifact.

The same diagnostics and release URL summaries now group the eleven
evidence-expansion rows into three browser diagnostics families:

```text
woodpecker: 1/1 ready; sources=3
vismach-remap-sims: 2/2 ready; sources=6
five-axis-trt: 8/8 ready; sources=12
```

This family drilldown is source/evidence visibility only. It does not alter the
separate promotion candidate summary of 8 diagnostics-ready candidates across
3 families and 17 source files, and it does not change the inventory baseline.

## 2026-06-20 Evidence Expansion Source Filter

The INI workflow overview now exposes a separate evidence-expansion family
source filter, distinct from the promotion-family source filter:

```text
getWorkflowOverviewEvidenceExpansionFamilyRowsRenderState
getWorkflowOverviewEvidenceExpansionFamilySourceFilterViewModel
renderWorkflowOverviewEvidenceExpansionFamilySourceFilterState
mountWorkflowOverviewEvidenceExpansionFamilySourceFilterState
```

The filter supports selecting `all`, `ini`, `gcode`, `remap-subroutine`, or
`source` rows within the evidence-expansion families, and it keeps candidate
rows separate from source rows. The current ready filter surface covers:

```text
21 source files
11 evidence-expansion candidate rows
evidence-expansion-family-five-axis-trt / gcode => 8 source files, 8 candidates
```

All rows remain diagnostics evidence only: `promotionAllowed=false`,
`inventoryBaselineUnchanged=true`, and the inventory baseline remains
`82/82/77/0`.

## Boundary Statement

This analysis relies on the improved virtual HAL only for Web simulation
runtime surfaces. It does not claim Linux kernel hard-realtime ABI support,
external hardware driver ABI support, native HAL module ABI support, Python UI
process emulation, tool database process emulation, or external user-M process
execution. G-code, interpreter, planner, kinematics, canonical motion, machine
INI, tool table, parameter, and remap semantics remain LinuxCNC-backed.
