按text22收束promotion证据
结论:完成 evidence-ready / inventory-ready 双层 promotion candidate 管理,release/SDK gate 已纳入 virtual HAL promotion summary,baseline 保持 28/28/131/0,Python remap、tool DB、external user-M hard block 继续 locked。
This commit is contained in:
@@ -70,6 +70,8 @@ import {
|
||||
VIRTUAL_HAL_COVERAGE_STATES,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
|
||||
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
|
||||
VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS,
|
||||
@@ -327,8 +329,9 @@ private page state.
|
||||
files, current Node `PASS` evidence, blocked-family exclusions, target
|
||||
browser diagnostics evidence, and the required virtual HAL reports for
|
||||
QtDragon on-abort, PUMA seam-weld, and rose-engine promotion planning.
|
||||
- `VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES` and
|
||||
`VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES` plus
|
||||
- `VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES`,
|
||||
`VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES`, and
|
||||
`VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES` plus
|
||||
`createVirtualHalSimConfigMacroLoadFixtureReport()` expose non-main
|
||||
macro/load fixture evidence for virtual HAL diagnostics. The report keeps
|
||||
`nonMainFixture === true`, separates fixture paths from manifest-backed
|
||||
@@ -336,7 +339,9 @@ private page state.
|
||||
`rcone.ngc` or external-offsets `queuebuster.ngc` from being promoted as
|
||||
standalone browser main programs. Blocked fixture rows such as SilverDragon
|
||||
`tool_sensor.ngc` remain excluded until their Python UI/process boundary is
|
||||
proven outside virtual HAL.
|
||||
proven outside virtual HAL. Audit candidates such as industrial-lathe
|
||||
`toolchange.ngc` rows stay machine-readable negative evidence until owning
|
||||
INI and UI/process source evidence is complete.
|
||||
- `createVirtualHalSourceComplianceReport()` is the machine-readable gate for
|
||||
the virtual HAL source rule. It maps replacement targets, runtime
|
||||
capabilities, and HAL pin families back to LinuxCNC source files such as
|
||||
|
||||
@@ -7,8 +7,11 @@ export {
|
||||
VIRTUAL_HAL_COVERAGE_STATES,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_PROJECT_PIN_GROUPS,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
VIRTUAL_HAL_SOURCE_DERIVED_CAPABILITIES,
|
||||
@@ -186,6 +189,25 @@ export {
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan,
|
||||
handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange,
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls,
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilyRowsState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilyRowsState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
|
||||
@@ -125,6 +125,20 @@ export const VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS = Object.freeze([
|
||||
}),
|
||||
]);
|
||||
|
||||
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE = Object.freeze({
|
||||
executed: 28,
|
||||
passed: 28,
|
||||
skipped: 131,
|
||||
unexpectedFail: 0,
|
||||
});
|
||||
|
||||
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = Object.freeze({
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
|
||||
"de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
|
||||
"b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae",
|
||||
});
|
||||
|
||||
export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
Object.freeze({
|
||||
id: "qtdragon-multi-joint-on-abort",
|
||||
@@ -137,7 +151,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-multi-joint",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -161,7 +175,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/qtdragon_inch.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -185,7 +199,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-rotary-axis",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -209,7 +223,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_vertical.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_xyz/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -233,7 +247,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-z-compensation",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -257,7 +271,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/qtdragon_mpg.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "delegated-to-woodpecker",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-ui-on-abort",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -282,7 +296,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/axis/vismach/puma/puma.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "represented-by-puma-cube",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "halui-vismach-remap",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -306,7 +320,7 @@ export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([
|
||||
iniPath: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
gcodePath: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
currentMatrixBrowserStatus: "not-promoted",
|
||||
currentMatrixBrowserStatus: "explicit-browser-diagnostics",
|
||||
dependencyClass: "hal-process-only",
|
||||
targetBrowserEvidence: "explicit-browser-diagnostics",
|
||||
requiredVirtualHalReports: Object.freeze([
|
||||
@@ -334,6 +348,14 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
|
||||
owningIniPath: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
pairedMainProgram: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
declarationSource: "NGCGUI_SUBFILE",
|
||||
declarationEvidence: Object.freeze({
|
||||
sourceFile: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
section: "DISPLAY",
|
||||
key: "NGCGUI_SUBFILE",
|
||||
value: "rcone.ngc",
|
||||
line: 34,
|
||||
sourceLine: "NGCGUI_SUBFILE = rcone.ngc",
|
||||
}),
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
dependencyClass: "macro-load-non-main",
|
||||
targetBrowserEvidence: "non-main-fixture-diagnostics",
|
||||
@@ -353,6 +375,14 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES = Object.freeze([
|
||||
owningIniPath: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
pairedMainProgram: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
declarationSource: "NGCGUI_SUBFILE",
|
||||
declarationEvidence: Object.freeze({
|
||||
sourceFile: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
section: "DISPLAY",
|
||||
key: "NGCGUI_SUBFILE",
|
||||
value: "queuebuster.ngc",
|
||||
line: 40,
|
||||
sourceLine: "NGCGUI_SUBFILE = queuebuster.ngc",
|
||||
}),
|
||||
currentNodeInventoryStatus: "NON_MAIN_CLASS",
|
||||
dependencyClass: "macro-load-non-main-declared-only",
|
||||
targetBrowserEvidence: "non-main-fixture-diagnostics",
|
||||
@@ -370,6 +400,27 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES = Object.freeze(
|
||||
owningIniPath: "linuxcnc/configs/sim/gscreen/silverdragon/silverdragon.ini",
|
||||
blockedKind: "PYTHON-UI-PROCESS",
|
||||
dependencyClass: "macro-load-python-ui-boundary",
|
||||
boundaryEvidence: Object.freeze({
|
||||
sourceArtifacts: Object.freeze([
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
|
||||
]),
|
||||
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
boundarySummary: Object.freeze({
|
||||
path: "gscreen/silverdragon/macros/tool_sensor.ngc",
|
||||
ini: "gscreen/silverdragon/silverdragon.ini",
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini",
|
||||
}),
|
||||
iniBoundarySummary: Object.freeze({
|
||||
ini: "gscreen/silverdragon/silverdragon.ini",
|
||||
vendored: 0,
|
||||
reportAvailable: 0,
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini",
|
||||
}),
|
||||
}),
|
||||
reason: "Owning SilverDragon UI machine file is not available in the vendored manifest; promotion would require Python UI process boundary proof outside virtual HAL.",
|
||||
}),
|
||||
Object.freeze({
|
||||
@@ -378,10 +429,94 @@ export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES = Object.freeze(
|
||||
owningIniPath: "linuxcnc/configs/sim/gmoccapy/6_axis.ini",
|
||||
blockedKind: "L4-PYTHON-REMAP",
|
||||
dependencyClass: "macro-load-python-remap-boundary",
|
||||
boundaryEvidence: Object.freeze({
|
||||
sourceArtifacts: Object.freeze([
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
|
||||
]),
|
||||
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
boundarySummary: Object.freeze({
|
||||
path: "gmoccapy/macros/on_abort.ngc",
|
||||
ini: "gmoccapy/6_axis.ini",
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gmoccapy/6_axis.ini",
|
||||
}),
|
||||
iniBoundarySummary: Object.freeze({
|
||||
ini: "gmoccapy/6_axis.ini",
|
||||
vendored: 0,
|
||||
reportAvailable: 0,
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gmoccapy/6_axis.ini",
|
||||
}),
|
||||
}),
|
||||
reason: "gmoccapy macro/load rows remain locked behind LinuxCNC-owned Python remap/prolog/epilog runtime proof.",
|
||||
}),
|
||||
]);
|
||||
|
||||
export const VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES = Object.freeze([
|
||||
Object.freeze({
|
||||
id: "gscreen-industrial-lathe-wear-toolchange-audit",
|
||||
fixturePath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
|
||||
owningIniPath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
dependencyClass: "macro-load-ui-family-audit",
|
||||
auditStatus: "blocked-missing-owning-ini",
|
||||
promotionAllowed: false,
|
||||
boundaryEvidence: Object.freeze({
|
||||
sourceArtifacts: Object.freeze([
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
|
||||
]),
|
||||
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
boundarySummary: Object.freeze({
|
||||
path: "gscreen/industrial_lathe_wear/toolchange.ngc",
|
||||
ini: "gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
}),
|
||||
iniBoundarySummary: Object.freeze({
|
||||
ini: "gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
vendored: 0,
|
||||
reportAvailable: 0,
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
}),
|
||||
}),
|
||||
reason: "Generated boundary evidence reports missing vendored owning INI for gscreen industrial_lathe_wear; keep as audit-only until machine files and UI/process declaration have LinuxCNC source evidence.",
|
||||
}),
|
||||
Object.freeze({
|
||||
id: "qtvcp-industrial-lathe-wear-toolchange-audit",
|
||||
fixturePath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
|
||||
owningIniPath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
dependencyClass: "macro-load-ui-family-audit",
|
||||
auditStatus: "blocked-missing-owning-ini",
|
||||
promotionAllowed: false,
|
||||
boundaryEvidence: Object.freeze({
|
||||
sourceArtifacts: Object.freeze([
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv",
|
||||
]),
|
||||
sourceArtifactHashes: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
baselineSummary: VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
boundarySummary: Object.freeze({
|
||||
path: "qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
|
||||
ini: "qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
}),
|
||||
iniBoundarySummary: Object.freeze({
|
||||
ini: "qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
vendored: 0,
|
||||
reportAvailable: 0,
|
||||
recommendedBlocked: "UNAVAILABLE",
|
||||
dependencies: "missing_vendored_ini:configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
}),
|
||||
}),
|
||||
reason: "Generated boundary evidence reports missing vendored owning INI for qtvcp_screens industrial_lathe_wear; keep as audit-only until machine files and UI/process declaration have LinuxCNC source evidence.",
|
||||
}),
|
||||
]);
|
||||
|
||||
export const VIRTUAL_HAL_COVERAGE_STATES = Object.freeze({
|
||||
simulated: "simulated",
|
||||
bridgeOnly: "bridge-only",
|
||||
@@ -2683,6 +2818,10 @@ function normalizeLinuxCncSourcePath(path) {
|
||||
return parts.join("/");
|
||||
}
|
||||
|
||||
function normalizeSimConfigInventoryPath(path) {
|
||||
return normalizeLinuxCncSourcePath(path).replace(/^configs\/sim\//, "");
|
||||
}
|
||||
|
||||
function sourceManifestSetFromText(manifestText = "") {
|
||||
return new Set(String(manifestText)
|
||||
.split("\n")
|
||||
@@ -2691,6 +2830,35 @@ function sourceManifestSetFromText(manifestText = "") {
|
||||
.map(normalizeLinuxCncSourcePath));
|
||||
}
|
||||
|
||||
function isGeneratedBoundaryEvidenceReady(boundaryEvidence = {}, fixturePath = "", owningIniPath = "") {
|
||||
const boundarySummary = boundaryEvidence.boundarySummary ?? {};
|
||||
const iniBoundarySummary = boundaryEvidence.iniBoundarySummary ?? {};
|
||||
const baselineSummary = boundaryEvidence.baselineSummary ?? {};
|
||||
const sourceArtifactHashes = boundaryEvidence.sourceArtifactHashes ?? {};
|
||||
const sourceArtifacts = [...(boundaryEvidence.sourceArtifacts ?? [])];
|
||||
const normalizedFixturePath = normalizeSimConfigInventoryPath(fixturePath);
|
||||
const normalizedOwningIniPath = normalizeSimConfigInventoryPath(owningIniPath);
|
||||
return sourceArtifacts.includes("wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv") &&
|
||||
sourceArtifacts.includes("wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv") &&
|
||||
Object.entries(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
|
||||
.every(([artifactPath, expectedHash]) => sourceArtifactHashes[artifactPath] === expectedHash) &&
|
||||
baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
normalizeSimConfigInventoryPath(boundarySummary.path) === normalizedFixturePath &&
|
||||
normalizeSimConfigInventoryPath(boundarySummary.ini) === normalizedOwningIniPath &&
|
||||
boundarySummary.recommendedBlocked === "UNAVAILABLE" &&
|
||||
typeof boundarySummary.dependencies === "string" &&
|
||||
boundarySummary.dependencies.includes("missing_vendored_ini:") &&
|
||||
normalizeSimConfigInventoryPath(iniBoundarySummary.ini) === normalizedOwningIniPath &&
|
||||
iniBoundarySummary.vendored === 0 &&
|
||||
iniBoundarySummary.reportAvailable === 0 &&
|
||||
iniBoundarySummary.recommendedBlocked === "UNAVAILABLE" &&
|
||||
typeof iniBoundarySummary.dependencies === "string" &&
|
||||
iniBoundarySummary.dependencies.includes("missing_vendored_ini:");
|
||||
}
|
||||
|
||||
export function createVirtualHalSimConfigSourceCoverageReport(options = {}) {
|
||||
const targets = options.targets ?? VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS;
|
||||
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
|
||||
@@ -2835,6 +3003,23 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
|
||||
const blockedCandidateIds = rows.filter((row) => !row.blockedKindExcluded).map((row) => row.id);
|
||||
const missingManifestFiles = [...new Set(rows.flatMap((row) => row.missingManifestFiles))];
|
||||
const missingRequiredReports = [...new Set(rows.flatMap((row) => row.missingRequiredReports))];
|
||||
const 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 explicitBrowserDiagnosticsCount = familyCandidates
|
||||
.filter((row) => row.targetBrowserEvidence === "explicit-browser-diagnostics").length;
|
||||
const sourceFiles = [...new Set(familyCandidates.flatMap((row) => row.sourceFiles))];
|
||||
return {
|
||||
id: familyId,
|
||||
candidateIds: familyCandidates.map((row) => row.id),
|
||||
candidateCount: familyCandidates.length,
|
||||
completeCount,
|
||||
explicitBrowserDiagnosticsCount,
|
||||
explicitBrowserDiagnosticsReady: explicitBrowserDiagnosticsCount === familyCandidates.length,
|
||||
complete: completeCount === familyCandidates.length,
|
||||
sourceFiles,
|
||||
};
|
||||
});
|
||||
const complete = rows.length > 0 &&
|
||||
missingCandidates.length === 0 &&
|
||||
blockedCandidateIds.length === 0 &&
|
||||
@@ -2858,9 +3043,11 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
|
||||
blockedCandidateIds,
|
||||
missingManifestFiles,
|
||||
missingRequiredReports,
|
||||
familyRows,
|
||||
rows,
|
||||
summaryRows: [
|
||||
{ id: "candidates", label: "Promotion candidates", value: `${rows.length}` },
|
||||
{ id: "families", label: "Promotion families", value: `${familyRows.length}` },
|
||||
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedCandidateIds.length === 0 ? "passed" : `blocked ${blockedCandidateIds.length}` },
|
||||
{ id: "reports", label: "Virtual HAL reports", value: missingRequiredReports.length === 0 ? "complete" : `missing ${missingRequiredReports.length}` },
|
||||
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
|
||||
@@ -2872,6 +3059,7 @@ export function createVirtualHalSimConfigPromotionCandidateReport(options = {})
|
||||
export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
const fixtures = options.fixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES;
|
||||
const blockedFixtures = options.blockedFixtures ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES;
|
||||
const auditCandidates = options.auditCandidates ?? VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES;
|
||||
const manifestProvided = typeof options.manifestText === "string" || Array.isArray(options.manifestEntries);
|
||||
const manifestSet = new Set([
|
||||
...sourceManifestSetFromText(options.manifestText ?? ""),
|
||||
@@ -2894,11 +3082,25 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
const statusReady = allowedStatuses.has(fixture.currentNodeInventoryStatus);
|
||||
const nonMainFixtureReady = fixture.nonMainFixture === true &&
|
||||
fixture.targetBrowserEvidence === "non-main-fixture-diagnostics";
|
||||
const declarationEvidence = fixture.declarationEvidence ?? null;
|
||||
const requiresDeclarationEvidence = typeof fixture.declarationSource === "string" &&
|
||||
fixture.declarationSource.length > 0;
|
||||
const declarationEvidenceReady = !requiresDeclarationEvidence || (
|
||||
declarationEvidence !== null &&
|
||||
declarationEvidence.sourceFile === fixture.owningIniPath &&
|
||||
declarationEvidence.key === fixture.declarationSource &&
|
||||
declarationEvidence.value === fixture.fixturePath.split("/").at(-1) &&
|
||||
Number.isInteger(declarationEvidence.line) &&
|
||||
declarationEvidence.line > 0 &&
|
||||
typeof declarationEvidence.sourceLine === "string" &&
|
||||
declarationEvidence.sourceLine.includes(`${declarationEvidence.key} = ${declarationEvidence.value}`)
|
||||
);
|
||||
const complete = sourceFiles.length > 0 &&
|
||||
missingManifestFiles.length === 0 &&
|
||||
blockedKindExcluded &&
|
||||
statusReady &&
|
||||
nonMainFixtureReady;
|
||||
nonMainFixtureReady &&
|
||||
declarationEvidenceReady;
|
||||
return {
|
||||
id: fixture.id,
|
||||
label: fixture.label,
|
||||
@@ -2908,6 +3110,9 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
owningIniPath: fixture.owningIniPath,
|
||||
pairedMainProgram: fixture.pairedMainProgram,
|
||||
declarationSource: fixture.declarationSource,
|
||||
declarationEvidence,
|
||||
declarationEvidenceReady,
|
||||
requiresDeclarationEvidence,
|
||||
currentNodeInventoryStatus: fixture.currentNodeInventoryStatus,
|
||||
dependencyClass: fixture.dependencyClass,
|
||||
targetBrowserEvidence: fixture.targetBrowserEvidence,
|
||||
@@ -2924,6 +3129,9 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
});
|
||||
const missingFixtures = rows.filter((row) => !row.complete).map((row) => row.id);
|
||||
const blockedFixtureIds = rows.filter((row) => !row.blockedKindExcluded).map((row) => row.id);
|
||||
const declarationEvidenceViolations = rows
|
||||
.filter((row) => row.requiresDeclarationEvidence === true && row.declarationEvidenceReady !== true)
|
||||
.map((row) => row.id);
|
||||
const standaloneMainViolations = rows
|
||||
.filter((row) => row.nonMainFixture !== true || row.targetBrowserEvidence !== "non-main-fixture-diagnostics")
|
||||
.map((row) => row.id);
|
||||
@@ -2931,6 +3139,8 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
const positiveFixturePaths = new Set(rows.map((row) => normalizeLinuxCncSourcePath(row.fixturePath)));
|
||||
const blockedRows = blockedFixtures.map((fixture) => {
|
||||
const excludedFromPositiveFixtures = !positiveFixturePaths.has(normalizeLinuxCncSourcePath(fixture.fixturePath));
|
||||
const boundaryEvidence = fixture.boundaryEvidence ?? {};
|
||||
const boundaryEvidenceReady = isGeneratedBoundaryEvidenceReady(boundaryEvidence, fixture.fixturePath, fixture.owningIniPath);
|
||||
return {
|
||||
id: fixture.id,
|
||||
source: "linuxcnc-configs-sim-source-derived-virtual-hal-macro-load-blocked-fixture",
|
||||
@@ -2939,19 +3149,61 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
blockedKind: fixture.blockedKind,
|
||||
dependencyClass: fixture.dependencyClass,
|
||||
excludedFromPositiveFixtures,
|
||||
boundaryEvidence,
|
||||
boundaryEvidenceReady,
|
||||
reason: fixture.reason,
|
||||
complete: excludedFromPositiveFixtures,
|
||||
complete: excludedFromPositiveFixtures && boundaryEvidenceReady,
|
||||
};
|
||||
});
|
||||
const blockedFixturePromotionViolations = blockedRows
|
||||
.filter((row) => row.excludedFromPositiveFixtures !== true)
|
||||
.map((row) => row.id);
|
||||
const blockedBoundaryEvidenceViolations = blockedRows
|
||||
.filter((row) => row.boundaryEvidenceReady !== true)
|
||||
.map((row) => row.id);
|
||||
const auditRows = auditCandidates.map((candidate) => {
|
||||
const excludedFromPositiveFixtures = !positiveFixturePaths.has(normalizeLinuxCncSourcePath(candidate.fixturePath));
|
||||
const boundaryEvidence = candidate.boundaryEvidence ?? {};
|
||||
const boundaryEvidenceReady = isGeneratedBoundaryEvidenceReady(boundaryEvidence, candidate.fixturePath, candidate.owningIniPath);
|
||||
return {
|
||||
id: candidate.id,
|
||||
source: "linuxcnc-configs-sim-source-derived-virtual-hal-macro-load-audit-candidate",
|
||||
fixturePath: candidate.fixturePath,
|
||||
owningIniPath: candidate.owningIniPath,
|
||||
dependencyClass: candidate.dependencyClass,
|
||||
auditStatus: candidate.auditStatus,
|
||||
promotionAllowed: candidate.promotionAllowed === true,
|
||||
excludedFromPositiveFixtures,
|
||||
boundaryEvidence,
|
||||
boundaryEvidenceReady,
|
||||
reason: candidate.reason,
|
||||
complete: excludedFromPositiveFixtures && candidate.promotionAllowed !== true && boundaryEvidenceReady,
|
||||
};
|
||||
});
|
||||
const missingAuditRows = auditRows
|
||||
.filter((row) => !row.complete)
|
||||
.map((row) => row.id);
|
||||
const auditPromotionViolations = auditRows
|
||||
.filter((row) => row.promotionAllowed !== true && row.excludedFromPositiveFixtures !== true)
|
||||
.map((row) => row.id);
|
||||
const auditBoundaryEvidenceViolations = auditRows
|
||||
.filter((row) => row.boundaryEvidenceReady !== true)
|
||||
.map((row) => row.id);
|
||||
const auditPromotionAllowedViolations = auditRows
|
||||
.filter((row) => row.promotionAllowed === true && row.boundaryEvidenceReady !== true)
|
||||
.map((row) => row.id);
|
||||
const complete = rows.length > 0 &&
|
||||
missingFixtures.length === 0 &&
|
||||
missingAuditRows.length === 0 &&
|
||||
blockedFixtureIds.length === 0 &&
|
||||
declarationEvidenceViolations.length === 0 &&
|
||||
standaloneMainViolations.length === 0 &&
|
||||
missingManifestFiles.length === 0 &&
|
||||
blockedFixturePromotionViolations.length === 0;
|
||||
blockedFixturePromotionViolations.length === 0 &&
|
||||
blockedBoundaryEvidenceViolations.length === 0 &&
|
||||
auditPromotionViolations.length === 0 &&
|
||||
auditBoundaryEvidenceViolations.length === 0 &&
|
||||
auditPromotionAllowedViolations.length === 0;
|
||||
return {
|
||||
apiName: "linuxcnc-wasm-virtual-hal-sim-config-macro-load-fixture-report",
|
||||
reportVersion: 1,
|
||||
@@ -2966,15 +3218,24 @@ export function createVirtualHalSimConfigMacroLoadFixtureReport(options = {}) {
|
||||
fixturePaths: rows.map((row) => row.fixturePath),
|
||||
missingFixtures,
|
||||
blockedFixtureIds,
|
||||
declarationEvidenceViolations,
|
||||
standaloneMainViolations,
|
||||
blockedFixturePromotionViolations,
|
||||
blockedBoundaryEvidenceViolations,
|
||||
missingAuditRows,
|
||||
auditPromotionViolations,
|
||||
auditBoundaryEvidenceViolations,
|
||||
auditPromotionAllowedViolations,
|
||||
missingManifestFiles,
|
||||
rows,
|
||||
blockedRows,
|
||||
auditRows,
|
||||
summaryRows: [
|
||||
{ id: "fixtures", label: "Macro/load fixtures", value: `${rows.length}` },
|
||||
{ id: "declarations", label: "Declaration evidence", value: declarationEvidenceViolations.length === 0 ? "passed" : `violations ${declarationEvidenceViolations.length}` },
|
||||
{ id: "non-main", label: "Non-main fixture gate", value: standaloneMainViolations.length === 0 ? "passed" : `violations ${standaloneMainViolations.length}` },
|
||||
{ id: "blocked-fixture-lock", label: "Blocked fixture lock", value: blockedFixturePromotionViolations.length === 0 ? "passed" : `violations ${blockedFixturePromotionViolations.length}` },
|
||||
{ id: "blocked-fixture-lock", label: "Blocked fixture lock", value: blockedFixturePromotionViolations.length === 0 && blockedBoundaryEvidenceViolations.length === 0 ? "passed" : "violations" },
|
||||
{ id: "ui-family-audit", label: "UI-family macro/load audit", value: missingAuditRows.length === 0 && auditPromotionViolations.length === 0 && auditBoundaryEvidenceViolations.length === 0 && auditPromotionAllowedViolations.length === 0 ? "passed" : "violations" },
|
||||
{ id: "blocked-family", label: "Blocked-family exclusion", value: blockedFixtureIds.length === 0 ? "passed" : `blocked ${blockedFixtureIds.length}` },
|
||||
{ id: "manifest", label: "Manifest check", value: manifestProvided ? (missingManifestFiles.length === 0 ? "passed" : "failed") : "not provided" },
|
||||
{ id: "inventory-baseline", label: "Inventory baseline", value: "unchanged" },
|
||||
|
||||
@@ -79,6 +79,59 @@ const DEFAULT_SIM_CONFIG_INVENTORY_BASELINE = {
|
||||
unexpectedFail: 0,
|
||||
};
|
||||
|
||||
const DEFAULT_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = {
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
|
||||
"de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9",
|
||||
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
|
||||
"b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae",
|
||||
};
|
||||
|
||||
function isBoundaryEvidenceBaselineFresh(boundaryEvidence = {}) {
|
||||
const baseline = objectOrEmpty(boundaryEvidence.baselineSummary);
|
||||
const hashes = objectOrEmpty(boundaryEvidence.sourceArtifactHashes);
|
||||
return baseline.executed === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
baseline.passed === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
baseline.skipped === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
baseline.unexpectedFail === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
Object.entries(DEFAULT_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
|
||||
.every(([artifactPath, expectedHash]) => hashes[artifactPath] === expectedHash);
|
||||
}
|
||||
|
||||
function createPromotionFamilySummaryText(candidateReport = {}) {
|
||||
const families = arrayOrEmpty(objectOrEmpty(candidateReport).familyRows);
|
||||
if (families.length === 0) {
|
||||
return "not provided";
|
||||
}
|
||||
return families.map((family) => {
|
||||
const label = family.id ?? "unknown";
|
||||
const completeCount = family.completeCount ?? 0;
|
||||
const candidateCount = family.candidateCount ?? 0;
|
||||
const state = family.complete === true && family.explicitBrowserDiagnosticsReady === true ? "ready" : "blocked";
|
||||
return `${label}: ${completeCount}/${candidateCount} ${state}`;
|
||||
}).join("; ");
|
||||
}
|
||||
|
||||
function createPromotionFamilySummaryRows(candidateReport = {}) {
|
||||
return arrayOrEmpty(objectOrEmpty(candidateReport).familyRows).map((family) => {
|
||||
const sourceFileCount = arrayOrEmpty(family.sourceFiles).length;
|
||||
const candidateCount = family.candidateCount ?? 0;
|
||||
const completeCount = family.completeCount ?? 0;
|
||||
const explicitBrowserDiagnosticsReady = family.explicitBrowserDiagnosticsReady === true;
|
||||
const ready = family.complete === true && explicitBrowserDiagnosticsReady;
|
||||
return {
|
||||
id: family.id ?? "unknown",
|
||||
label: family.id ?? "Unknown promotion family",
|
||||
value: `${completeCount}/${candidateCount} ${ready ? "ready" : "blocked"}; sources=${sourceFileCount}; diagnostics=${explicitBrowserDiagnosticsReady ? "ready" : "blocked"}`,
|
||||
sourceFiles: arrayOrEmpty(family.sourceFiles),
|
||||
candidateCount,
|
||||
completeCount,
|
||||
sourceFileCount,
|
||||
explicitBrowserDiagnosticsReady,
|
||||
ready,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const BLOCKED_RUNTIME_FAMILIES = [
|
||||
"L4-USER-M-PROCESS",
|
||||
"L4-TOOL-DB",
|
||||
@@ -152,6 +205,12 @@ const REQUIRED_MACRO_LOAD_FIXTURES = [
|
||||
{
|
||||
id: "rose-engine-rcone-macro-load",
|
||||
fixturePath: "linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
declarationEvidence: {
|
||||
sourceFile: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
key: "NGCGUI_SUBFILE",
|
||||
value: "rcone.ngc",
|
||||
line: 34,
|
||||
},
|
||||
sourceFiles: [
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
@@ -161,6 +220,12 @@ const REQUIRED_MACRO_LOAD_FIXTURES = [
|
||||
{
|
||||
id: "external-offsets-queuebuster-macro-load",
|
||||
fixturePath: "linuxcnc/configs/sim/axis/external_offsets/queuebuster.ngc",
|
||||
declarationEvidence: {
|
||||
sourceFile: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
key: "NGCGUI_SUBFILE",
|
||||
value: "queuebuster.ngc",
|
||||
line: 40,
|
||||
},
|
||||
sourceFiles: [
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
@@ -181,6 +246,19 @@ const REQUIRED_BLOCKED_MACRO_LOAD_FIXTURES = [
|
||||
},
|
||||
];
|
||||
|
||||
const REQUIRED_MACRO_LOAD_AUDIT_CANDIDATES = [
|
||||
{
|
||||
id: "gscreen-industrial-lathe-wear-toolchange-audit",
|
||||
fixturePath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
|
||||
auditStatus: "blocked-missing-owning-ini",
|
||||
},
|
||||
{
|
||||
id: "qtvcp-industrial-lathe-wear-toolchange-audit",
|
||||
fixturePath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
|
||||
auditStatus: "blocked-missing-owning-ini",
|
||||
},
|
||||
];
|
||||
|
||||
function isVirtualHalSimConfigSourceCoverageReady(report) {
|
||||
const coverage = objectOrEmpty(report);
|
||||
return coverage.apiName === "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report" &&
|
||||
@@ -218,8 +296,14 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
|
||||
fixtureReport.inventoryBaselineUnchanged === true &&
|
||||
arrayOrEmpty(fixtureReport.missingFixtures).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.blockedFixtureIds).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.declarationEvidenceViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.standaloneMainViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.blockedFixturePromotionViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.blockedBoundaryEvidenceViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.missingAuditRows).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.auditPromotionViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.auditBoundaryEvidenceViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.auditPromotionAllowedViolations).length === 0 &&
|
||||
arrayOrEmpty(fixtureReport.missingManifestFiles).length === 0 &&
|
||||
REQUIRED_MACRO_LOAD_FIXTURES.every((fixture) =>
|
||||
rows.some((row) =>
|
||||
@@ -228,6 +312,16 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
|
||||
row.nonMainFixture === true &&
|
||||
row.targetBrowserEvidence === "non-main-fixture-diagnostics" &&
|
||||
row.fixturePath === fixture.fixturePath &&
|
||||
(
|
||||
!fixture.declarationEvidence ||
|
||||
(
|
||||
row.declarationEvidenceReady === true &&
|
||||
objectOrEmpty(row.declarationEvidence).sourceFile === fixture.declarationEvidence.sourceFile &&
|
||||
objectOrEmpty(row.declarationEvidence).key === fixture.declarationEvidence.key &&
|
||||
objectOrEmpty(row.declarationEvidence).value === fixture.declarationEvidence.value &&
|
||||
objectOrEmpty(row.declarationEvidence).line === fixture.declarationEvidence.line
|
||||
)
|
||||
) &&
|
||||
fixture.sourceFiles.every((file) => arrayOrEmpty(row.sourceFiles).includes(file))
|
||||
)
|
||||
) &&
|
||||
@@ -237,6 +331,28 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
|
||||
row.fixturePath === fixture.fixturePath &&
|
||||
row.blockedKind === fixture.blockedKind &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
isBoundaryEvidenceBaselineFresh(row.boundaryEvidence) &&
|
||||
objectOrEmpty(row.boundaryEvidence?.boundarySummary).recommendedBlocked === "UNAVAILABLE" &&
|
||||
String(objectOrEmpty(row.boundaryEvidence?.boundarySummary).dependencies ?? "").includes("missing_vendored_ini:") &&
|
||||
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).vendored === 0 &&
|
||||
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
) &&
|
||||
REQUIRED_MACRO_LOAD_AUDIT_CANDIDATES.every((candidate) =>
|
||||
arrayOrEmpty(fixtureReport.auditRows).some((row) =>
|
||||
row.id === candidate.id &&
|
||||
row.fixturePath === candidate.fixturePath &&
|
||||
row.auditStatus === candidate.auditStatus &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
isBoundaryEvidenceBaselineFresh(row.boundaryEvidence) &&
|
||||
objectOrEmpty(row.boundaryEvidence?.boundarySummary).recommendedBlocked === "UNAVAILABLE" &&
|
||||
String(objectOrEmpty(row.boundaryEvidence?.boundarySummary).dependencies ?? "").includes("missing_vendored_ini:") &&
|
||||
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).vendored === 0 &&
|
||||
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
);
|
||||
@@ -277,6 +393,23 @@ function isVirtualHalSimConfigPromotionCandidateReportReady(report) {
|
||||
hasRequiredPromotionCandidates(rows);
|
||||
}
|
||||
|
||||
function isVirtualHalPromotionCandidateSummaryReady(summary) {
|
||||
const summaryObject = objectOrEmpty(summary);
|
||||
return summaryObject.apiName === "real-browser-simulation-promotion-candidate-summary" &&
|
||||
summaryObject.ready === true &&
|
||||
summaryObject.phase === "ready" &&
|
||||
summaryObject.candidateCount === 8 &&
|
||||
summaryObject.readyCandidateCount === 8 &&
|
||||
summaryObject.familyCount === 3 &&
|
||||
summaryObject.sourceFileCount === 17 &&
|
||||
summaryObject.preferredCandidateId === "qtdragon-multi-joint-on-abort" &&
|
||||
summaryObject.preferredIniPath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" &&
|
||||
summaryObject.preferredGcodePath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc" &&
|
||||
summaryObject.explicitBrowserDiagnosticsCount === 8 &&
|
||||
summaryObject.inventoryBaseline === "executed=28 passed=28 skipped=131 unexpected_fail=0" &&
|
||||
arrayOrEmpty(summaryObject.blockedCandidateIds).length === 0;
|
||||
}
|
||||
|
||||
export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifact = {}) {
|
||||
const artifactObject = objectOrEmpty(artifact);
|
||||
const sourceCompliance = objectOrEmpty(artifactObject.virtualHalSourceCompliance);
|
||||
@@ -284,6 +417,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
const commandScriptFixtures = objectOrEmpty(artifactObject.virtualHalCommandScriptFixtures);
|
||||
const motionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
|
||||
const promotionCandidates = objectOrEmpty(artifactObject.virtualHalSimConfigPromotionCandidates);
|
||||
const promotionCandidateSummary = objectOrEmpty(artifactObject.virtualHalPromotionCandidateSummary);
|
||||
const macroLoadFixtures = objectOrEmpty(artifactObject.virtualHalSimConfigMacroLoadFixtures);
|
||||
const sessionDiagnostics = objectOrEmpty(artifactObject.virtualHalSessionDiagnostics);
|
||||
const replacement = objectOrEmpty(artifactObject.virtualHalSimulationReplacement);
|
||||
@@ -301,6 +435,9 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
const hasPromotionCandidates = artifactObject.virtualHalSimConfigPromotionCandidates !== undefined;
|
||||
const promotionCandidatesReady = !hasPromotionCandidates ||
|
||||
isVirtualHalSimConfigPromotionCandidateReportReady(promotionCandidates);
|
||||
const hasPromotionCandidateSummary = artifactObject.virtualHalPromotionCandidateSummary !== undefined;
|
||||
const promotionCandidateSummaryReady = hasPromotionCandidateSummary &&
|
||||
isVirtualHalPromotionCandidateSummaryReady(promotionCandidateSummary);
|
||||
const hasMacroLoadFixtures = artifactObject.virtualHalSimConfigMacroLoadFixtures !== undefined;
|
||||
const macroLoadFixturesReady = hasMacroLoadFixtures &&
|
||||
isVirtualHalSimConfigMacroLoadFixtureReportReady(macroLoadFixtures);
|
||||
@@ -326,6 +463,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
...(sourceComplianceReady ? [] : ["virtualHalSourceCompliance"]),
|
||||
...(simConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
|
||||
...(promotionCandidatesReady ? [] : ["virtualHalSimConfigPromotionCandidates"]),
|
||||
...(promotionCandidateSummaryReady ? [] : ["virtualHalPromotionCandidateSummary"]),
|
||||
...(macroLoadFixturesReady ? [] : ["virtualHalSimConfigMacroLoadFixtures"]),
|
||||
...(commandScriptFixturesReady ? [] : ["virtualHalCommandScriptFixtures"]),
|
||||
...(motionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
|
||||
@@ -344,6 +482,8 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
simConfigSourceCoverageReady,
|
||||
promotionCandidatesReady,
|
||||
hasPromotionCandidates,
|
||||
promotionCandidateSummaryReady,
|
||||
hasPromotionCandidateSummary,
|
||||
macroLoadFixturesReady,
|
||||
hasMacroLoadFixtures,
|
||||
commandScriptFixturesReady,
|
||||
@@ -385,6 +525,11 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: hasPromotionCandidates ? (promotionCandidatesReady ? "ready" : "missing") : "not provided",
|
||||
},
|
||||
{
|
||||
id: "promotion-candidate-summary",
|
||||
label: "Virtual HAL promotion candidate summary",
|
||||
value: hasPromotionCandidateSummary ? (promotionCandidateSummaryReady ? "ready" : "missing") : "not provided",
|
||||
},
|
||||
{
|
||||
id: "sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
@@ -1659,6 +1804,8 @@ export function createProjectReleaseReadinessReport({
|
||||
observedOutputs = [],
|
||||
simConfigInventory = DEFAULT_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
virtualHalSimConfigSourceCoverage = null,
|
||||
virtualHalSimConfigPromotionCandidates = null,
|
||||
virtualHalSimConfigMacroLoadFixtures = null,
|
||||
virtualHalMotionControllerMatrix = null,
|
||||
blockedRuntimeFamilies = BLOCKED_RUNTIME_FAMILIES,
|
||||
promotedRuntimeFamilies = [],
|
||||
@@ -1695,6 +1842,14 @@ export function createProjectReleaseReadinessReport({
|
||||
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
);
|
||||
const virtualHalSimConfigPromotionCandidatesReady = isVirtualHalSimConfigPromotionCandidateReportReady(
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
);
|
||||
const virtualHalPromotionFamilySummary = createPromotionFamilySummaryText(virtualHalSimConfigPromotionCandidates);
|
||||
const virtualHalPromotionFamilyRows = createPromotionFamilySummaryRows(virtualHalSimConfigPromotionCandidates);
|
||||
const virtualHalSimConfigMacroLoadFixturesReady = isVirtualHalSimConfigMacroLoadFixtureReportReady(
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
);
|
||||
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
|
||||
virtualHalMotionControllerMatrix,
|
||||
);
|
||||
@@ -1704,6 +1859,8 @@ export function createProjectReleaseReadinessReport({
|
||||
const ready = releaseGatePassed &&
|
||||
inventoryReady &&
|
||||
virtualHalSimConfigSourceCoverageReady &&
|
||||
virtualHalSimConfigPromotionCandidatesReady &&
|
||||
virtualHalSimConfigMacroLoadFixturesReady &&
|
||||
virtualHalMotionControllerMatrixReady &&
|
||||
blockedRuntimeReady &&
|
||||
axisScreenshotArtifactsReady;
|
||||
@@ -1711,6 +1868,8 @@ export function createProjectReleaseReadinessReport({
|
||||
...(releaseGatePassed ? [] : ["project-release-gate"]),
|
||||
...(inventoryReady ? [] : ["sim-config-inventory"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtual-hal-sim-config-source-coverage"]),
|
||||
...(virtualHalSimConfigPromotionCandidatesReady ? [] : ["virtual-hal-sim-config-promotion-candidates"]),
|
||||
...(virtualHalSimConfigMacroLoadFixturesReady ? [] : ["virtual-hal-sim-config-macro-load-fixtures"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtual-hal-motion-controller-matrix"]),
|
||||
...(blockedRuntimeReady ? [] : ["blocked-runtime-families"]),
|
||||
...(axisScreenshotArtifactsReady ? [] : ["axis-screenshot-artifacts"]),
|
||||
@@ -1730,6 +1889,12 @@ export function createProjectReleaseReadinessReport({
|
||||
simConfigInventory: inventory,
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigPromotionCandidatesReady,
|
||||
virtualHalPromotionFamilySummary,
|
||||
virtualHalPromotionFamilyRows,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalSimConfigMacroLoadFixturesReady,
|
||||
virtualHalMotionControllerMatrix,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
blockedRuntimeFamilies: blockedFamilies,
|
||||
@@ -1758,6 +1923,27 @@ export function createProjectReleaseReadinessReport({
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-families",
|
||||
label: "Virtual HAL promotion families",
|
||||
value: virtualHalPromotionFamilySummary,
|
||||
},
|
||||
...virtualHalPromotionFamilyRows.map((row) => ({
|
||||
id: `virtual-hal-promotion-family-${row.id}`,
|
||||
label: `Promotion family ${row.label}`,
|
||||
value: row.value,
|
||||
sourceFiles: row.sourceFiles,
|
||||
})),
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
@@ -1786,6 +1972,8 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
const gateResultMatrix = objectOrEmpty(report?.gateResultMatrix);
|
||||
const simConfigInventory = objectOrEmpty(report?.simConfigInventory);
|
||||
const virtualHalSimConfigSourceCoverageReady = report?.virtualHalSimConfigSourceCoverageReady === true;
|
||||
const virtualHalSimConfigPromotionCandidatesReady = report?.virtualHalSimConfigPromotionCandidatesReady === true;
|
||||
const virtualHalSimConfigMacroLoadFixturesReady = report?.virtualHalSimConfigMacroLoadFixturesReady === true;
|
||||
const virtualHalMotionControllerMatrixReady = report?.virtualHalMotionControllerMatrixReady === true;
|
||||
const axisScreenshotArtifactSummary = objectOrEmpty(report?.axisScreenshotArtifactSummary);
|
||||
const blockedRuntimeFamilies = arrayOrEmpty(report?.blockedRuntimeFamilies);
|
||||
@@ -1823,6 +2011,16 @@ export function createProjectReleaseReadinessSummaryViewModel(
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
@@ -1910,6 +2108,27 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: validation?.virtualHalSimConfigSourceCoverageReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: validation?.virtualHalSimConfigPromotionCandidatesReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-families",
|
||||
label: "Virtual HAL promotion families",
|
||||
value: validation?.virtualHalPromotionFamilySummary ?? "not provided",
|
||||
},
|
||||
...arrayOrEmpty(validation?.virtualHalPromotionFamilyRows).map((row) => ({
|
||||
id: `virtual-hal-promotion-family-${row.id}`,
|
||||
label: `Promotion family ${row.label}`,
|
||||
value: row.value,
|
||||
sourceFiles: row.sourceFiles,
|
||||
})),
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: validation?.virtualHalSimConfigMacroLoadFixturesReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
@@ -2179,6 +2398,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
let diagnosticsHttpStatus = null;
|
||||
let diagnosticsFetchError = null;
|
||||
let diagnosticsValidation = null;
|
||||
let diagnosticsArtifact = null;
|
||||
const diagnosticsMissing = [];
|
||||
if (diagnosticsUrl) {
|
||||
try {
|
||||
@@ -2190,7 +2410,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
diagnosticsValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation({});
|
||||
} else {
|
||||
diagnosticsFetched = true;
|
||||
const diagnosticsArtifact = JSON.parse(await diagnosticsResponse.text());
|
||||
diagnosticsArtifact = JSON.parse(await diagnosticsResponse.text());
|
||||
diagnosticsValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation(diagnosticsArtifact);
|
||||
diagnosticsMissing.push(...diagnosticsValidation.missing.map((item) => `diagnostics.${item}`));
|
||||
if (requireSavedSessionDiagnostics && diagnosticsValidation.hasSessionDiagnostics !== true) {
|
||||
@@ -2226,6 +2446,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
jsonWorkflow,
|
||||
validation: jsonWorkflow.validation,
|
||||
diagnosticsValidation,
|
||||
diagnosticsArtifact,
|
||||
summaryViewModel: jsonWorkflow.summaryViewModel,
|
||||
actionPlan: jsonWorkflow.actionPlan,
|
||||
missing,
|
||||
@@ -2305,6 +2526,8 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
workflow = {},
|
||||
) {
|
||||
const missing = arrayOrEmpty(workflow?.missing);
|
||||
const promotionCandidateSummary = objectOrEmpty(workflow?.diagnosticsArtifact?.virtualHalPromotionCandidateSummary);
|
||||
const promotionCandidateSummaryReady = promotionCandidateSummary.ready === true;
|
||||
const ready = workflow?.ready === true;
|
||||
const statusText = ready ? "Ready" : "Blocked";
|
||||
const detailText = ready
|
||||
@@ -2340,6 +2563,17 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
label: "Artifact validation",
|
||||
value: workflow?.validation?.ready === true ? "ready" : "blocked",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-families",
|
||||
label: "Virtual HAL promotion families",
|
||||
value: workflow?.validation?.virtualHalPromotionFamilySummary ?? "not provided",
|
||||
},
|
||||
...arrayOrEmpty(workflow?.validation?.virtualHalPromotionFamilyRows).map((row) => ({
|
||||
id: `virtual-hal-promotion-family-${row.id}`,
|
||||
label: `Promotion family ${row.label}`,
|
||||
value: row.value,
|
||||
sourceFiles: row.sourceFiles,
|
||||
})),
|
||||
{
|
||||
id: "browser-diagnostics",
|
||||
label: "Browser diagnostics",
|
||||
@@ -2347,6 +2581,41 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
|
||||
? (workflow?.diagnosticsValidation?.ready === true ? "ready" : "blocked")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate-summary",
|
||||
label: "Virtual HAL promotion candidate summary",
|
||||
value: workflow?.diagnosticsUrl
|
||||
? (promotionCandidateSummaryReady ? "ready" : "not provided")
|
||||
: "not requested",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate",
|
||||
label: "Virtual HAL promotion candidate",
|
||||
value: promotionCandidateSummary.preferredCandidateId ?? "not provided",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate-ini",
|
||||
label: "Candidate INI",
|
||||
value: promotionCandidateSummary.preferredIniPath ?? "not provided",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate-gcode",
|
||||
label: "Candidate G-code",
|
||||
value: promotionCandidateSummary.preferredGcodePath ?? "not provided",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate-count",
|
||||
label: "Candidate readiness",
|
||||
value: Number.isFinite(promotionCandidateSummary.readyCandidateCount) &&
|
||||
Number.isFinite(promotionCandidateSummary.candidateCount)
|
||||
? `${promotionCandidateSummary.readyCandidateCount}/${promotionCandidateSummary.candidateCount} ready`
|
||||
: "not provided",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-candidate-baseline",
|
||||
label: "Candidate inventory baseline",
|
||||
value: promotionCandidateSummary.inventoryBaseline ?? "not provided",
|
||||
},
|
||||
{
|
||||
id: "saved-session-diagnostics",
|
||||
label: "Saved-session diagnostics",
|
||||
@@ -2466,6 +2735,8 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const releaseGate = objectOrEmpty(artifactObject.releaseGate);
|
||||
const simConfigInventory = objectOrEmpty(artifactObject.simConfigInventory);
|
||||
const virtualHalSimConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage);
|
||||
const virtualHalSimConfigPromotionCandidates = objectOrEmpty(artifactObject.virtualHalSimConfigPromotionCandidates);
|
||||
const virtualHalSimConfigMacroLoadFixtures = objectOrEmpty(artifactObject.virtualHalSimConfigMacroLoadFixtures);
|
||||
const virtualHalMotionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
|
||||
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
|
||||
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
|
||||
@@ -2515,6 +2786,14 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
) && artifactObject.virtualHalSimConfigSourceCoverageReady === true;
|
||||
const virtualHalSimConfigPromotionCandidatesReady = isVirtualHalSimConfigPromotionCandidateReportReady(
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
) && artifactObject.virtualHalSimConfigPromotionCandidatesReady === true;
|
||||
const virtualHalPromotionFamilySummary = createPromotionFamilySummaryText(virtualHalSimConfigPromotionCandidates);
|
||||
const virtualHalPromotionFamilyRows = createPromotionFamilySummaryRows(virtualHalSimConfigPromotionCandidates);
|
||||
const virtualHalSimConfigMacroLoadFixturesReady = isVirtualHalSimConfigMacroLoadFixtureReportReady(
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
) && artifactObject.virtualHalSimConfigMacroLoadFixturesReady === true;
|
||||
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
|
||||
virtualHalMotionControllerMatrix,
|
||||
) && artifactObject.virtualHalMotionControllerMatrixReady === true;
|
||||
@@ -2556,6 +2835,8 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
...(simConfigInventory.skipped === 131 ? [] : ["simConfigInventory.skipped"]),
|
||||
...(simConfigInventory.unexpectedFail === 0 ? [] : ["simConfigInventory.unexpectedFail"]),
|
||||
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
|
||||
...(virtualHalSimConfigPromotionCandidatesReady ? [] : ["virtualHalSimConfigPromotionCandidates"]),
|
||||
...(virtualHalSimConfigMacroLoadFixturesReady ? [] : ["virtualHalSimConfigMacroLoadFixtures"]),
|
||||
...(virtualHalMotionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
|
||||
...(arrayOrEmpty(artifactObject.blockedRuntimeFamilies).join(",") === BLOCKED_RUNTIME_FAMILIES.join(",")
|
||||
? []
|
||||
@@ -2591,6 +2872,10 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
gateResultMatrixReady: matrixReady,
|
||||
gateActionPlanReady: actionPlanReady,
|
||||
virtualHalSimConfigSourceCoverageReady,
|
||||
virtualHalSimConfigPromotionCandidatesReady,
|
||||
virtualHalPromotionFamilySummary,
|
||||
virtualHalPromotionFamilyRows,
|
||||
virtualHalSimConfigMacroLoadFixturesReady,
|
||||
virtualHalMotionControllerMatrixReady,
|
||||
axisScreenshotArtifactSummaryReady: axisScreenshotSummaryReady,
|
||||
axisScreenshotArtifactCount: axisScreenshotArtifacts.length,
|
||||
@@ -2636,6 +2921,27 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-families",
|
||||
label: "Virtual HAL promotion families",
|
||||
value: virtualHalPromotionFamilySummary,
|
||||
},
|
||||
...virtualHalPromotionFamilyRows.map((row) => ({
|
||||
id: `virtual-hal-promotion-family-${row.id}`,
|
||||
label: `Promotion family ${row.label}`,
|
||||
value: row.value,
|
||||
sourceFiles: row.sourceFiles,
|
||||
})),
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -101,6 +101,24 @@
|
||||
font: 13px/1.4 "Segoe UI", "Noto Sans", sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
.source-filter-controls {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
.source-filter-controls label {
|
||||
color: var(--muted);
|
||||
font: 12px/1.4 "Segoe UI", "Noto Sans", sans-serif;
|
||||
}
|
||||
.source-filter-controls select {
|
||||
width: 100%;
|
||||
min-height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
padding: 6px 8px;
|
||||
color: var(--text);
|
||||
font: 13px/1.4 "Segoe UI", "Noto Sans", sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -135,6 +153,15 @@
|
||||
<p data-workflow-overview-release-readiness-artifact-gate-execution-summary-status>Waiting for URL workflow gate evidence.</p>
|
||||
<dl data-workflow-overview-release-readiness-artifact-gate-execution-summary-rows></dl>
|
||||
</section>
|
||||
<section class="overview-status" aria-label="Promotion candidate drilldown" data-workflow-overview-promotion-candidate-drilldown>
|
||||
<p data-workflow-overview-promotion-candidate-drilldown-status>Waiting for promotion candidate evidence.</p>
|
||||
<dl data-workflow-overview-promotion-candidate-drilldown-rows></dl>
|
||||
</section>
|
||||
<section class="overview-status" aria-label="Promotion family source filter" data-workflow-overview-promotion-family-source-filter>
|
||||
<p data-workflow-overview-promotion-family-source-filter-status>Waiting for promotion family source evidence.</p>
|
||||
<div class="source-filter-controls" data-workflow-overview-promotion-family-source-filter-controls></div>
|
||||
<dl data-workflow-overview-promotion-family-source-filter-rows></dl>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script type="module">
|
||||
@@ -178,6 +205,21 @@
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan,
|
||||
handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange,
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls,
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness,
|
||||
@@ -248,8 +290,53 @@
|
||||
renderState: gateExecutionSummaryRenderState,
|
||||
documentRef: document,
|
||||
});
|
||||
const promotionCandidateDrilldown =
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel(summary, {
|
||||
diagnosticsArtifact: workflow.diagnosticsArtifact,
|
||||
});
|
||||
const promotionCandidateDrilldownRenderState =
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState(
|
||||
promotionCandidateDrilldown,
|
||||
);
|
||||
const promotionCandidateDrilldownMountResult =
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState({
|
||||
renderState: promotionCandidateDrilldownRenderState,
|
||||
documentRef: document,
|
||||
});
|
||||
const promotionFamilyRowsRenderState =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(summary);
|
||||
const promotionFamilySourceFilter =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
|
||||
promotionFamilyRowsRenderState,
|
||||
);
|
||||
const promotionFamilySourceFilterMountResult =
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState({
|
||||
viewModel: promotionFamilySourceFilter,
|
||||
documentRef: document,
|
||||
});
|
||||
const promotionFamilySourceFilterBinding =
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls({
|
||||
renderState: promotionFamilyRowsRenderState,
|
||||
viewModel: promotionFamilySourceFilter,
|
||||
documentRef: document,
|
||||
render: true,
|
||||
onChange: (changeResult) => {
|
||||
document.body.dataset.promotionFamilySourceFilterFamily =
|
||||
changeResult.selectedFamilyId;
|
||||
document.body.dataset.promotionFamilySourceFilterSourceKind =
|
||||
changeResult.selectedSourceKind;
|
||||
document.body.dataset.promotionFamilySourceFilterCount =
|
||||
String(changeResult.actionPlan.filteredSourceFileCount);
|
||||
},
|
||||
});
|
||||
document.body.dataset.releaseArtifactUrlWorkflowPhase = workflow.phase;
|
||||
document.body.dataset.releaseArtifactUrlWorkflowReady = workflow.ready ? "true" : "false";
|
||||
document.body.dataset.promotionCandidateDrilldownReady =
|
||||
promotionCandidateDrilldown.ready ? "true" : "false";
|
||||
document.body.dataset.promotionFamilySourceFilterReady =
|
||||
promotionFamilySourceFilter.ready ? "true" : "false";
|
||||
document.body.dataset.promotionFamilySourceFilterCount =
|
||||
String(promotionFamilySourceFilter.filteredSourceFileCount);
|
||||
return {
|
||||
workflow,
|
||||
summary,
|
||||
@@ -261,6 +348,13 @@
|
||||
gateExecutionSummary,
|
||||
gateExecutionSummaryRenderState,
|
||||
gateExecutionSummaryMountResult,
|
||||
promotionCandidateDrilldown,
|
||||
promotionCandidateDrilldownRenderState,
|
||||
promotionCandidateDrilldownMountResult,
|
||||
promotionFamilyRowsRenderState,
|
||||
promotionFamilySourceFilter,
|
||||
promotionFamilySourceFilterMountResult,
|
||||
promotionFamilySourceFilterBinding,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -362,6 +456,69 @@
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilyRowsRenderState: (summaryViewModel) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(summaryViewModel)
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilySourceFilterViewModel: (renderState, options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(renderState, options)
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilySourceFilterDomContract: (options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract(options)
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilySourceFilterDomReadiness: (options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan: (renderState, options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan(renderState, options)
|
||||
),
|
||||
handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange: (options) => (
|
||||
handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls: (options) => (
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
renderWorkflowOverviewPromotionFamilySourceFilterState: (viewModel, options) => (
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
|
||||
viewModel,
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
mountWorkflowOverviewPromotionFamilySourceFilterState: (options) => (
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewPromotionCandidateDrilldownViewModel: (summaryViewModel, options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel(summaryViewModel, options)
|
||||
),
|
||||
getWorkflowOverviewPromotionCandidateDrilldownRenderState: (viewModel) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState(viewModel)
|
||||
),
|
||||
getWorkflowOverviewPromotionCandidateDrilldownDomContract: (options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomContract(options)
|
||||
),
|
||||
getWorkflowOverviewPromotionCandidateDrilldownDomReadiness: (options) => (
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomReadiness(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
renderWorkflowOverviewPromotionCandidateDrilldownState: (renderState, options) => (
|
||||
renderIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState(
|
||||
renderState,
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
mountWorkflowOverviewPromotionCandidateDrilldownState: (options) => (
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState(
|
||||
options ?? { documentRef: document },
|
||||
)
|
||||
),
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState: (actionPlan) => (
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState(actionPlan)
|
||||
),
|
||||
|
||||
@@ -683,6 +683,40 @@
|
||||
font-weight: 700;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.promotion-family-panel {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 4px 7px;
|
||||
border-top: 1px solid #c4c9cc;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.promotion-family-panel div {
|
||||
border: 1px solid #b5bcc1;
|
||||
background: #f1f1f1;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
.promotion-candidate-panel {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 4px 7px;
|
||||
border-top: 1px solid #c4c9cc;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.promotion-candidate-panel div {
|
||||
min-height: 27px;
|
||||
border: 1px solid #b5bcc1;
|
||||
background: #f7f7f7;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
.promotion-candidate-panel strong {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--text);
|
||||
}
|
||||
.status-history {
|
||||
border-top: 1px solid var(--line);
|
||||
background: #f2f2f2;
|
||||
@@ -1709,6 +1743,8 @@ M2
|
||||
<div><span>Last error</span><strong data-diagnostics="last-error">none</strong></div>
|
||||
<div><span>Readiness</span><strong data-diagnostics="readiness">unchecked</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-candidate-panel" data-promotion-candidate-summary></div>
|
||||
<div class="tool-table-mini" data-axis-shell="tool-table">
|
||||
<table aria-label="Loaded tool table">
|
||||
<thead>
|
||||
@@ -2553,6 +2589,99 @@ M2
|
||||
});
|
||||
}
|
||||
|
||||
function renderPromotionFamilyRows(report = createVirtualHalSimConfigPromotionCandidateReport()) {
|
||||
const container = document.querySelector("[data-promotion-family-rows]");
|
||||
if (!container) {
|
||||
return [];
|
||||
}
|
||||
const rows = Array.isArray(report.familyRows) ? report.familyRows : [];
|
||||
container.textContent = "";
|
||||
document.body.dataset.promotionFamilyReady = rows.every((row) =>
|
||||
row.complete === true && row.explicitBrowserDiagnosticsReady === true
|
||||
) ? "true" : "false";
|
||||
document.body.dataset.promotionFamilyCount = String(rows.length);
|
||||
for (const row of rows) {
|
||||
const item = document.createElement("div");
|
||||
item.dataset.promotionFamilyRow = row.id ?? "unknown";
|
||||
item.dataset.promotionFamilyReady = row.complete === true && row.explicitBrowserDiagnosticsReady === true ? "true" : "false";
|
||||
const label = document.createElement("span");
|
||||
label.textContent = row.id ?? "unknown";
|
||||
const value = document.createElement("strong");
|
||||
value.dataset.promotionFamilyValue = row.id ?? "unknown";
|
||||
value.textContent = `${row.completeCount ?? 0}/${row.candidateCount ?? 0} ready; sources=${row.sourceFiles?.length ?? 0}`;
|
||||
item.append(label, value);
|
||||
container.append(item);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
function createVirtualHalPromotionCandidateSummary(
|
||||
report = createVirtualHalSimConfigPromotionCandidateReport(),
|
||||
) {
|
||||
const rows = Array.isArray(report.rows) ? report.rows : [];
|
||||
const familyRows = Array.isArray(report.familyRows) ? report.familyRows : [];
|
||||
const preferredCandidate = rows.find((row) => row.id === "qtdragon-multi-joint-on-abort") ?? rows[0] ?? null;
|
||||
const readyRows = rows.filter((row) => row.complete === true);
|
||||
const blockedRows = rows.filter((row) => row.blockedKind !== "-");
|
||||
const explicitBrowserRows = rows.filter((row) => row.targetBrowserEvidence === "explicit-browser-diagnostics");
|
||||
const sourceFiles = [...new Set(rows.flatMap((row) => row.sourceFiles ?? []))];
|
||||
const ready = report.complete === true &&
|
||||
readyRows.length === rows.length &&
|
||||
blockedRows.length === 0 &&
|
||||
explicitBrowserRows.length === rows.length &&
|
||||
report.inventoryBaselineUnchanged === true;
|
||||
return {
|
||||
apiName: "real-browser-simulation-promotion-candidate-summary",
|
||||
summaryVersion: 1,
|
||||
phase: ready ? "ready" : "blocked",
|
||||
ready,
|
||||
candidateCount: rows.length,
|
||||
readyCandidateCount: readyRows.length,
|
||||
familyCount: familyRows.length,
|
||||
sourceFileCount: sourceFiles.length,
|
||||
preferredCandidateId: preferredCandidate?.id ?? null,
|
||||
preferredIniPath: preferredCandidate?.iniPath ?? null,
|
||||
preferredGcodePath: preferredCandidate?.gcodePath ?? null,
|
||||
blockedCandidateIds: blockedRows.map((row) => row.id),
|
||||
explicitBrowserDiagnosticsCount: explicitBrowserRows.length,
|
||||
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
sourceFiles,
|
||||
rows: [
|
||||
{ id: "candidate-count", label: "Candidates", value: `${readyRows.length}/${rows.length} ready` },
|
||||
{ id: "family-count", label: "Families", value: `${familyRows.length}` },
|
||||
{ id: "preferred-candidate", label: "First case", value: preferredCandidate?.id ?? "missing" },
|
||||
{ id: "source-files", label: "Source files", value: `${sourceFiles.length}` },
|
||||
{ id: "inventory-baseline", label: "Inventory", value: "28/28 pass; 131 skip unchanged" },
|
||||
{ id: "blocked-candidates", label: "Hard blocks", value: blockedRows.length === 0 ? "excluded" : blockedRows.map((row) => row.id).join(", ") },
|
||||
{ id: "browser-evidence", label: "Browser evidence", value: `${explicitBrowserRows.length}/${rows.length} explicit` },
|
||||
{ id: "preferred-ini", label: "INI", value: preferredCandidate?.iniPath ?? "missing" },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function renderPromotionCandidateSummary(summary = createVirtualHalPromotionCandidateSummary()) {
|
||||
const container = document.querySelector("[data-promotion-candidate-summary]");
|
||||
if (!container) {
|
||||
return summary;
|
||||
}
|
||||
container.textContent = "";
|
||||
document.body.dataset.promotionCandidateReady = summary.ready ? "true" : "false";
|
||||
document.body.dataset.promotionCandidateCount = String(summary.candidateCount);
|
||||
document.body.dataset.promotionCandidatePreferred = summary.preferredCandidateId ?? "";
|
||||
for (const row of summary.rows) {
|
||||
const item = document.createElement("div");
|
||||
item.dataset.promotionCandidateSummaryRow = row.id;
|
||||
const label = document.createElement("span");
|
||||
label.textContent = row.label;
|
||||
const value = document.createElement("strong");
|
||||
value.dataset.promotionCandidateSummaryValue = row.id;
|
||||
value.textContent = row.value;
|
||||
item.append(label, value);
|
||||
container.append(item);
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
function renderMachineStatusDom(machineStatus) {
|
||||
const statusMap = {
|
||||
"spindle-state": machineStatus.spindle.state,
|
||||
@@ -2591,6 +2720,9 @@ M2
|
||||
renderVirtualHalDro();
|
||||
}
|
||||
renderLimitsHomeState(createVirtualHalLimitsHomeState());
|
||||
const promotionCandidateReport = createVirtualHalSimConfigPromotionCandidateReport();
|
||||
renderPromotionFamilyRows(promotionCandidateReport);
|
||||
renderPromotionCandidateSummary(createVirtualHalPromotionCandidateSummary(promotionCandidateReport));
|
||||
document.querySelector("[data-axis-machine-control-state]")?.setAttribute("data-state", "ready");
|
||||
return cloneVirtualHalState();
|
||||
}
|
||||
@@ -2642,6 +2774,7 @@ M2
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport(),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport(),
|
||||
virtualHalPromotionCandidateSummary: createVirtualHalPromotionCandidateSummary(),
|
||||
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport(),
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport(),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport(),
|
||||
@@ -4081,6 +4214,8 @@ M2
|
||||
getVirtualHalSourceComplianceReport: () => createVirtualHalSourceComplianceReport(),
|
||||
getVirtualHalSimConfigSourceCoverageReport: () => createVirtualHalSimConfigSourceCoverageReport(),
|
||||
getVirtualHalSimConfigPromotionCandidateReport: () => createVirtualHalSimConfigPromotionCandidateReport(),
|
||||
getVirtualHalPromotionCandidateSummary: () => renderPromotionCandidateSummary(),
|
||||
getVirtualHalPromotionFamilyRows: () => renderPromotionFamilyRows(),
|
||||
getVirtualHalSimConfigMacroLoadFixtureReport: () => createVirtualHalSimConfigMacroLoadFixtureReport(),
|
||||
getVirtualHalCommandScriptFixtureReport: () => createVirtualHalCommandScriptFixtureReport(),
|
||||
getVirtualHalMotionControllerMatrixReport: () => createVirtualHalMotionControllerMatrixReport(),
|
||||
|
||||
@@ -19,6 +19,7 @@ export {
|
||||
VIRTUAL_HAL_AXES,
|
||||
VIRTUAL_HAL_AXISUI_PINS,
|
||||
VIRTUAL_HAL_MOTION_CONTROLLER_MATRIX_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
|
||||
Reference in New Issue
Block a user