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