按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:
@@ -66,6 +66,15 @@
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness ||
|
||||
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
|
||||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState ||
|
||||
!workflowApi?.getWorkflowOverviewPromotionFamilyRowsRenderState ||
|
||||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterViewModel ||
|
||||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomContract ||
|
||||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterDomReadiness ||
|
||||
!workflowApi?.getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan ||
|
||||
!workflowApi?.handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange ||
|
||||
!workflowApi?.bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls ||
|
||||
!workflowApi?.renderWorkflowOverviewPromotionFamilySourceFilterState ||
|
||||
!workflowApi?.mountWorkflowOverviewPromotionFamilySourceFilterState ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanRenderState ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomContract ||
|
||||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlanDomReadiness ||
|
||||
@@ -381,6 +390,22 @@
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
}),
|
||||
}),
|
||||
virtualHalPromotionCandidateSummary: {
|
||||
apiName: "real-browser-simulation-promotion-candidate-summary",
|
||||
summaryVersion: 1,
|
||||
phase: "ready",
|
||||
ready: true,
|
||||
candidateCount: 8,
|
||||
readyCandidateCount: 8,
|
||||
familyCount: 3,
|
||||
sourceFileCount: 17,
|
||||
preferredCandidateId: "qtdragon-multi-joint-on-abort",
|
||||
preferredIniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
blockedCandidateIds: [],
|
||||
explicitBrowserDiagnosticsCount: 8,
|
||||
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
},
|
||||
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
@@ -543,6 +568,11 @@
|
||||
assertEqual(releaseArtifactUrlWorkflow.httpStatus, 200, "workflow overview release artifact URL workflow status");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsHttpStatus, 200, "workflow overview diagnostics artifact URL workflow status");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.ready, true, "workflow overview diagnostics artifact validation");
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflow.diagnosticsArtifact.virtualHalPromotionCandidateSummary.ready,
|
||||
true,
|
||||
"workflow overview diagnostics promotion candidate summary",
|
||||
);
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.hasSessionDiagnostics, true, "workflow overview diagnostics saved-session presence");
|
||||
assertEqual(releaseArtifactUrlWorkflow.diagnosticsValidation.sessionDiagnosticsReady, true, "workflow overview diagnostics saved-session validation");
|
||||
assertEqual(
|
||||
@@ -567,7 +597,7 @@
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowCount,
|
||||
12,
|
||||
18,
|
||||
"workflow overview release artifact URL workflow render rows",
|
||||
);
|
||||
assertEqual(
|
||||
@@ -575,6 +605,36 @@
|
||||
true,
|
||||
"workflow overview release artifact URL workflow diagnostics row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("virtual-hal-promotion-candidate-summary"),
|
||||
true,
|
||||
"workflow overview release artifact URL workflow candidate summary row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate")?.value,
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
"workflow overview release artifact URL workflow candidate id",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-ini")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
"workflow overview release artifact URL workflow candidate INI",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-gcode")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
"workflow overview release artifact URL workflow candidate G-code",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-count")?.value,
|
||||
"8/8 ready",
|
||||
"workflow overview release artifact URL workflow candidate count",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
|
||||
"executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
"workflow overview release artifact URL workflow candidate baseline",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("saved-session-diagnostics"),
|
||||
true,
|
||||
@@ -626,16 +686,71 @@
|
||||
true,
|
||||
"workflow overview fixed URL workflow gate execution summary row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilyRowsRenderState.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow promotion family rows ready",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilyRowsRenderState.sourceFileCount,
|
||||
17,
|
||||
"workflow overview fixed URL workflow promotion family source count",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilySourceFilter.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow source filter readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilySourceFilter.filteredSourceFileCount,
|
||||
17,
|
||||
"workflow overview fixed URL workflow source filter default count",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilySourceFilterMountResult.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow source filter mount readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilySourceFilterBinding.ready,
|
||||
true,
|
||||
"workflow overview fixed URL workflow source filter binding readiness",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactUrlFormResult.promotionFamilySourceFilterBinding.boundControlCount,
|
||||
2,
|
||||
"workflow overview fixed URL workflow source filter bound controls",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.releaseArtifactUrlWorkflowReady,
|
||||
"true",
|
||||
"workflow overview fixed URL workflow form body ready",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.promotionFamilySourceFilterReady,
|
||||
"true",
|
||||
"workflow overview fixed URL workflow source filter body ready",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.promotionFamilySourceFilterCount,
|
||||
"17",
|
||||
"workflow overview fixed URL workflow source filter body default count",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="browser-diagnostics"]').textContent,
|
||||
"ready",
|
||||
"workflow overview fixed URL workflow form browser diagnostics row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-candidate"]').textContent,
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
"workflow overview fixed URL workflow form candidate row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-candidate-count"]').textContent,
|
||||
"8/8 ready",
|
||||
"workflow overview fixed URL workflow form candidate count row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-action-plan-value="next-command"]').textContent,
|
||||
"none",
|
||||
@@ -646,6 +761,59 @@
|
||||
true,
|
||||
"workflow overview fixed URL workflow gate execution summary DOM row",
|
||||
);
|
||||
const sourceFilterMount = workflowDoc.querySelector("[data-workflow-overview-promotion-family-source-filter]");
|
||||
const sourceFilterFamilySelect = workflowDoc.querySelector(
|
||||
'[data-workflow-overview-promotion-family-source-filter-select="family"]',
|
||||
);
|
||||
const sourceFilterKindSelect = workflowDoc.querySelector(
|
||||
'[data-workflow-overview-promotion-family-source-filter-select="source-kind"]',
|
||||
);
|
||||
assertEqual(
|
||||
sourceFilterMount.dataset.selectedFamilyId,
|
||||
"all",
|
||||
"workflow overview source filter default family",
|
||||
);
|
||||
assertEqual(
|
||||
sourceFilterFamilySelect?.value,
|
||||
"all",
|
||||
"workflow overview source filter family select default",
|
||||
);
|
||||
assertEqual(
|
||||
sourceFilterKindSelect?.value,
|
||||
"all",
|
||||
"workflow overview source filter kind select default",
|
||||
);
|
||||
sourceFilterFamilySelect.value = "virtual-hal-promotion-family-rose-engine-rcone-demo";
|
||||
sourceFilterFamilySelect.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.promotionFamilySourceFilterFamily,
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
"workflow overview source filter change body family",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.body.dataset.promotionFamilySourceFilterCount,
|
||||
"2",
|
||||
"workflow overview source filter change source count",
|
||||
);
|
||||
assertEqual(
|
||||
sourceFilterMount.dataset.selectedFamilyId,
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
"workflow overview source filter changed mount family",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelectorAll(
|
||||
'[data-workflow-overview-promotion-family-source-filter-type="source-row"]',
|
||||
).length,
|
||||
4,
|
||||
"workflow overview source filter changed source DOM nodes",
|
||||
);
|
||||
assertEqual(
|
||||
workflowDoc.querySelector(
|
||||
'[data-workflow-overview-promotion-family-source-filter-value="linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc"]',
|
||||
)?.textContent,
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
"workflow overview source filter changed rose engine source row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactJsonWorkflow.statusLine,
|
||||
"Ready: Artifact JSON workflow complete",
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
"native-runtime-probe-summary.tsv",
|
||||
"next-boundary-recommendations.tsv",
|
||||
"next-boundary-worklist.tsv",
|
||||
"promotion-candidates.tsv",
|
||||
"python-remap-boundary-summary.tsv",
|
||||
"python-remap-family-summary.tsv",
|
||||
"python-remap-native-runtime-alignment.tsv",
|
||||
@@ -150,7 +151,7 @@
|
||||
"build/native/source-probes.tsv",
|
||||
];
|
||||
|
||||
if (wasmArtifactNames.length !== 54 || new Set(wasmArtifactNames).size !== wasmArtifactNames.length) {
|
||||
if (wasmArtifactNames.length !== 55 || new Set(wasmArtifactNames).size !== wasmArtifactNames.length) {
|
||||
throw new Error("browser_generated_artifact_documentation_coverage: WASM artifact list drift");
|
||||
}
|
||||
if (nativeArtifactTokens.length !== 8 || new Set(nativeArtifactTokens).size !== nativeArtifactTokens.length) {
|
||||
|
||||
@@ -244,6 +244,8 @@
|
||||
!api?.getVirtualHalSourceComplianceReport ||
|
||||
!api?.getVirtualHalSimConfigSourceCoverageReport ||
|
||||
!api?.getVirtualHalSimConfigPromotionCandidateReport ||
|
||||
!api?.getVirtualHalPromotionCandidateSummary ||
|
||||
!api?.getVirtualHalPromotionFamilyRows ||
|
||||
!api?.getVirtualHalSimConfigMacroLoadFixtureReport ||
|
||||
!api?.getVirtualHalCommandScriptFixtureReport ||
|
||||
!api?.getVirtualHalMotionControllerMatrixReport ||
|
||||
@@ -409,6 +411,7 @@
|
||||
throw new Error(`simulation virtual HAL registry/integrity drift: ${JSON.stringify(initialVirtualHalRegistry)}`);
|
||||
}
|
||||
const diagnosticsArtifact = api.exportDiagnosticsArtifact();
|
||||
const promotionCandidateSummary = api.getVirtualHalPromotionCandidateSummary();
|
||||
const expectedPromotionCandidates = [
|
||||
[
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
@@ -458,6 +461,9 @@
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
false,
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"rcone.ngc",
|
||||
34,
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
],
|
||||
@@ -466,6 +472,9 @@
|
||||
"linuxcnc/configs/sim/axis/external_offsets/queuebuster.ngc",
|
||||
true,
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"queuebuster.ngc",
|
||||
40,
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
],
|
||||
];
|
||||
@@ -481,6 +490,18 @@
|
||||
"L4-PYTHON-REMAP",
|
||||
],
|
||||
];
|
||||
const expectedMacroLoadAuditCandidates = [
|
||||
[
|
||||
"gscreen-industrial-lathe-wear-toolchange-audit",
|
||||
"linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
|
||||
"blocked-missing-owning-ini",
|
||||
],
|
||||
[
|
||||
"qtvcp-industrial-lathe-wear-toolchange-audit",
|
||||
"linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
|
||||
"blocked-missing-owning-ini",
|
||||
],
|
||||
];
|
||||
if (
|
||||
diagnosticsArtifact.apiName !== "real-browser-simulation-diagnostics-artifact" ||
|
||||
diagnosticsArtifact.statusHistory.length === 0 ||
|
||||
@@ -495,18 +516,41 @@
|
||||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini") ||
|
||||
!diagnosticsArtifact.virtualHalSimConfigSourceCoverage?.sourceFiles?.includes("linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini") ||
|
||||
diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.complete !== true ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.ready !== true ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.preferredCandidateId !== "qtdragon-multi-joint-on-abort" ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.candidateCount !== 8 ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.readyCandidateCount !== 8 ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.sourceFileCount !== 17 ||
|
||||
diagnosticsArtifact.virtualHalPromotionCandidateSummary?.inventoryBaseline !== "executed=28 passed=28 skipped=131 unexpected_fail=0" ||
|
||||
promotionCandidateSummary.ready !== true ||
|
||||
promotionCandidateSummary.preferredIniPath !== "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" ||
|
||||
doc.body.dataset.promotionCandidateReady !== "true" ||
|
||||
doc.body.dataset.promotionCandidatePreferred !== "qtdragon-multi-joint-on-abort" ||
|
||||
doc.querySelector('[data-promotion-candidate-summary-value="preferred-candidate"]')?.textContent !== "qtdragon-multi-joint-on-abort" ||
|
||||
doc.querySelector('[data-promotion-candidate-summary-value="inventory-baseline"]')?.textContent !== "28/28 pass; 131 skip unchanged" ||
|
||||
!diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.familyRows?.some((row) =>
|
||||
row.id === "qtdragon-on-abort" &&
|
||||
row.candidateCount === 6 &&
|
||||
row.completeCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsReady === true &&
|
||||
row.complete === true
|
||||
) ||
|
||||
!expectedPromotionCandidates.every(([id, ...sourceFiles]) =>
|
||||
diagnosticsArtifact.virtualHalSimConfigPromotionCandidates?.rows?.some((row) =>
|
||||
row.id === id &&
|
||||
row.complete === true &&
|
||||
row.currentNodeInventoryStatus === "PASS" &&
|
||||
row.currentMatrixBrowserStatus === "explicit-browser-diagnostics" &&
|
||||
row.targetBrowserEvidence === "explicit-browser-diagnostics" &&
|
||||
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
|
||||
)
|
||||
) ||
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.complete !== true ||
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.blockedFixturePromotionViolations?.length !== 0 ||
|
||||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, ...sourceFiles]) =>
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.blockedBoundaryEvidenceViolations?.length !== 0 ||
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.auditPromotionViolations?.length !== 0 ||
|
||||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, declarationSourceFile, declarationValue, declarationLine, ...sourceFiles]) =>
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.rows?.some((row) =>
|
||||
row.id === id &&
|
||||
row.complete === true &&
|
||||
@@ -514,6 +558,12 @@
|
||||
row.targetBrowserEvidence === "non-main-fixture-diagnostics" &&
|
||||
row.fixturePath === fixturePath &&
|
||||
row.declaredOnly === declaredOnly &&
|
||||
row.requiresDeclarationEvidence === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence?.sourceFile === declarationSourceFile &&
|
||||
row.declarationEvidence?.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence?.value === declarationValue &&
|
||||
row.declarationEvidence?.line === declarationLine &&
|
||||
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
|
||||
)
|
||||
) ||
|
||||
@@ -523,6 +573,38 @@
|
||||
row.fixturePath === fixturePath &&
|
||||
row.blockedKind === blockedKind &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence?.baselineSummary?.executed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.passed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.skipped === 131 &&
|
||||
row.boundaryEvidence?.baselineSummary?.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence?.boundarySummary?.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence?.boundarySummary?.dependencies?.includes("missing_vendored_ini:") &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.vendored === 0 &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
) ||
|
||||
!expectedMacroLoadAuditCandidates.every(([id, fixturePath, auditStatus]) =>
|
||||
diagnosticsArtifact.virtualHalSimConfigMacroLoadFixtures?.auditRows?.some((row) =>
|
||||
row.id === id &&
|
||||
row.fixturePath === fixturePath &&
|
||||
row.auditStatus === auditStatus &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence?.baselineSummary?.executed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.passed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.skipped === 131 &&
|
||||
row.boundaryEvidence?.baselineSummary?.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence?.boundarySummary?.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence?.boundarySummary?.dependencies?.includes("missing_vendored_ini:") &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.vendored === 0 &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
) ||
|
||||
@@ -946,6 +1028,7 @@
|
||||
}
|
||||
const virtualHalReplacement = api.getVirtualHalSimulationReplacementReport();
|
||||
const promotionCandidateReport = api.getVirtualHalSimConfigPromotionCandidateReport();
|
||||
const promotionFamilyRows = api.getVirtualHalPromotionFamilyRows();
|
||||
const macroLoadFixtureReport = api.getVirtualHalSimConfigMacroLoadFixtureReport();
|
||||
if (
|
||||
virtualHalReplacement.apiName !== "linuxcnc-wasm-virtual-hal-simulation-replacement-report" ||
|
||||
@@ -966,6 +1049,17 @@
|
||||
!api.getVirtualHalSimConfigSourceCoverageReport().sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc") ||
|
||||
promotionCandidateReport.complete !== true ||
|
||||
promotionCandidateReport.inventoryBaselineUnchanged !== true ||
|
||||
doc.body.dataset.promotionFamilyReady !== "true" ||
|
||||
doc.body.dataset.promotionFamilyCount !== "3" ||
|
||||
promotionFamilyRows.length !== 3 ||
|
||||
![
|
||||
["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"],
|
||||
].every(([id, value]) =>
|
||||
doc.querySelector(`[data-promotion-family-row="${id}"]`)?.dataset.promotionFamilyReady === "true" &&
|
||||
doc.querySelector(`[data-promotion-family-value="${id}"]`)?.textContent === value
|
||||
) ||
|
||||
!expectedPromotionCandidates.every(([id, ...sourceFiles]) =>
|
||||
promotionCandidateReport.rows.some((row) =>
|
||||
row.id === id &&
|
||||
@@ -978,13 +1072,21 @@
|
||||
macroLoadFixtureReport.inventoryBaselineUnchanged !== true ||
|
||||
macroLoadFixtureReport.standaloneMainViolations.length !== 0 ||
|
||||
macroLoadFixtureReport.blockedFixturePromotionViolations.length !== 0 ||
|
||||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, ...sourceFiles]) =>
|
||||
macroLoadFixtureReport.blockedBoundaryEvidenceViolations.length !== 0 ||
|
||||
macroLoadFixtureReport.auditPromotionViolations.length !== 0 ||
|
||||
!expectedMacroLoadFixtures.every(([id, fixturePath, declaredOnly, declarationSourceFile, declarationValue, declarationLine, ...sourceFiles]) =>
|
||||
macroLoadFixtureReport.rows.some((row) =>
|
||||
row.id === id &&
|
||||
row.complete === true &&
|
||||
row.nonMainFixture === true &&
|
||||
row.fixturePath === fixturePath &&
|
||||
row.declaredOnly === declaredOnly &&
|
||||
row.requiresDeclarationEvidence === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence?.sourceFile === declarationSourceFile &&
|
||||
row.declarationEvidence?.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence?.value === declarationValue &&
|
||||
row.declarationEvidence?.line === declarationLine &&
|
||||
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
|
||||
)
|
||||
) ||
|
||||
@@ -994,6 +1096,38 @@
|
||||
row.fixturePath === fixturePath &&
|
||||
row.blockedKind === blockedKind &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence?.baselineSummary?.executed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.passed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.skipped === 131 &&
|
||||
row.boundaryEvidence?.baselineSummary?.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence?.boundarySummary?.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence?.boundarySummary?.dependencies?.includes("missing_vendored_ini:") &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.vendored === 0 &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
) ||
|
||||
!expectedMacroLoadAuditCandidates.every(([id, fixturePath, auditStatus]) =>
|
||||
macroLoadFixtureReport.auditRows.some((row) =>
|
||||
row.id === id &&
|
||||
row.fixturePath === fixturePath &&
|
||||
row.auditStatus === auditStatus &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence?.baselineSummary?.executed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.passed === 28 &&
|
||||
row.boundaryEvidence?.baselineSummary?.skipped === 131 &&
|
||||
row.boundaryEvidence?.baselineSummary?.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence?.sourceArtifactHashes?.["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence?.boundarySummary?.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence?.boundarySummary?.dependencies?.includes("missing_vendored_ini:") &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.vendored === 0 &&
|
||||
row.boundaryEvidence?.iniBoundarySummary?.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
)
|
||||
) ||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,8 @@ assert.equal(validation.gateExecutionSummaryReady, true);
|
||||
assert.equal(validation.gateResultMatrixReady, true);
|
||||
assert.equal(validation.gateActionPlanReady, true);
|
||||
assert.equal(validation.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(validation.virtualHalSimConfigPromotionCandidatesReady, true);
|
||||
assert.equal(validation.virtualHalSimConfigMacroLoadFixturesReady, true);
|
||||
assert.equal(validation.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.equal(validation.axisScreenshotArtifactSummaryReady, true);
|
||||
assert.ok(validation.axisScreenshotArtifactCount === 0 || validation.axisScreenshotArtifactCount === 4);
|
||||
@@ -60,6 +62,105 @@ assert.equal(artifact.virtualHalSimConfigSourceCoverage.webSimulationSatisfied,
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverage.sourceFiles.includes("linuxcnc/configs/sim/axis/foam/axis_foam.ini"), true);
|
||||
assert.equal(artifact.virtualHalSimConfigSourceCoverage.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_xyz/on_abort.ngc"), true);
|
||||
assert.equal(artifact.virtualHalSimConfigPromotionCandidates.apiName, "linuxcnc-wasm-virtual-hal-sim-config-promotion-candidate-report");
|
||||
assert.equal(artifact.virtualHalSimConfigPromotionCandidates.complete, true);
|
||||
assert.equal(artifact.virtualHalSimConfigPromotionCandidatesReady, true);
|
||||
assert.equal(
|
||||
artifact.virtualHalPromotionFamilySummary,
|
||||
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready",
|
||||
);
|
||||
assert.deepEqual(
|
||||
artifact.virtualHalPromotionFamilyRows.map(({ id, value }) => [id, value]),
|
||||
[
|
||||
["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"],
|
||||
],
|
||||
);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigPromotionCandidates.familyRows.some((row) =>
|
||||
row.id === "qtdragon-on-abort" &&
|
||||
row.candidateCount === 6 &&
|
||||
row.completeCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsReady === true &&
|
||||
row.complete === true
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigPromotionCandidates.rows.some((row) =>
|
||||
row.id === "rose-engine-rcone-demo" &&
|
||||
row.currentMatrixBrowserStatus === "explicit-browser-diagnostics" &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc")
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.apiName, "linuxcnc-wasm-virtual-hal-sim-config-macro-load-fixture-report");
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.complete, true);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixturesReady, true);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.declarationEvidenceViolations.length, 0);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.missingAuditRows.length, 0);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.blockedBoundaryEvidenceViolations.length, 0);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.auditPromotionViolations.length, 0);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.auditBoundaryEvidenceViolations.length, 0);
|
||||
assert.equal(artifact.virtualHalSimConfigMacroLoadFixtures.auditPromotionAllowedViolations.length, 0);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigMacroLoadFixtures.rows.some((row) =>
|
||||
row.id === "rose-engine-rcone-macro-load" &&
|
||||
row.requiresDeclarationEvidence === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence.sourceFile === "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini" &&
|
||||
row.declarationEvidence.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence.value === "rcone.ngc" &&
|
||||
row.declarationEvidence.line === 34
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigMacroLoadFixtures.rows.some((row) =>
|
||||
row.id === "external-offsets-queuebuster-macro-load" &&
|
||||
row.requiresDeclarationEvidence === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence.sourceFile === "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini" &&
|
||||
row.declarationEvidence.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence.value === "queuebuster.ngc" &&
|
||||
row.declarationEvidence.line === 40
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigMacroLoadFixtures.auditRows.some((row) =>
|
||||
row.id === "gscreen-industrial-lathe-wear-toolchange-audit" &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence.baselineSummary.executed === 28 &&
|
||||
row.boundaryEvidence.baselineSummary.passed === 28 &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === 131 &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini") &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
artifact.virtualHalSimConfigMacroLoadFixtures.blockedRows.some((row) =>
|
||||
row.id === "silverdragon-tool-sensor-python-ui-boundary" &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
row.boundaryEvidence.baselineSummary.executed === 28 &&
|
||||
row.boundaryEvidence.baselineSummary.passed === 28 &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === 131 &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === 0 &&
|
||||
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv"] === "de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9" &&
|
||||
row.boundaryEvidence.sourceArtifactHashes["wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv"] === "b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae" &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini") &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.apiName, "linuxcnc-wasm-virtual-hal-motion-controller-matrix-report");
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.complete, true);
|
||||
assert.equal(artifact.virtualHalMotionControllerMatrix.manifestChecked, true);
|
||||
|
||||
@@ -5,6 +5,8 @@ import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
createProjectReleaseReadinessReport,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigMacroLoadFixtureReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
} from "../../runtime/sdk/src/index.js";
|
||||
|
||||
@@ -31,6 +33,13 @@ const passedGateResults = {
|
||||
"project-release-gate": true,
|
||||
};
|
||||
|
||||
const virtualHalSimConfigSourceCoverage = createVirtualHalSimConfigSourceCoverageReport({
|
||||
manifestText: sourceManifestText,
|
||||
});
|
||||
const virtualHalMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestText: sourceManifestText,
|
||||
});
|
||||
|
||||
function loadAxisScreenshotArtifacts(directory) {
|
||||
if (!directory || !existsSync(directory)) {
|
||||
return [];
|
||||
@@ -65,12 +74,16 @@ const report = createProjectReleaseReadinessReport({
|
||||
"host_wasm_opfs_browser_smokes=ok",
|
||||
"project_release_gate=ok",
|
||||
],
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
virtualHalMotionControllerMatrix: createVirtualHalMotionControllerMatrixReport({
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestText: sourceManifestText,
|
||||
simConfigSourceCoverage: virtualHalSimConfigSourceCoverage,
|
||||
motionControllerMatrix: virtualHalMotionControllerMatrix,
|
||||
}),
|
||||
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
}),
|
||||
virtualHalMotionControllerMatrix,
|
||||
axisScreenshotArtifacts: loadAxisScreenshotArtifacts(axisScreenshotArtifactDir),
|
||||
});
|
||||
|
||||
|
||||
@@ -43,6 +43,22 @@ const browserDiagnosticsArtifact = {
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: virtualHalState }),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalPromotionCandidateSummary: {
|
||||
apiName: "real-browser-simulation-promotion-candidate-summary",
|
||||
summaryVersion: 1,
|
||||
phase: "ready",
|
||||
ready: true,
|
||||
candidateCount: 8,
|
||||
readyCandidateCount: 8,
|
||||
familyCount: 3,
|
||||
sourceFileCount: 17,
|
||||
preferredCandidateId: "qtdragon-multi-joint-on-abort",
|
||||
preferredIniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
blockedCandidateIds: [],
|
||||
explicitBrowserDiagnosticsCount: 8,
|
||||
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
},
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: virtualHalState }),
|
||||
virtualHalMotionControllerMatrix,
|
||||
@@ -67,6 +83,8 @@ assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation(browserDia
|
||||
const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix: browserDiagnosticsArtifact.virtualHalMotionControllerMatrix,
|
||||
}));
|
||||
|
||||
@@ -92,6 +110,13 @@ const readyWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
});
|
||||
const readySummary = createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(readyWorkflow);
|
||||
const readyActionPlan = createProjectReleaseReadinessArtifactUrlWorkflowActionPlan(readyWorkflow);
|
||||
const expectedPromotionFamilySummary =
|
||||
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready";
|
||||
const expectedPromotionFamilyRows = [
|
||||
["virtual-hal-promotion-family-qtdragon-on-abort", "6/6 ready; sources=12; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-vismach-remap-sims", "1/1 ready; sources=3; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-rose-engine-rcone-demo", "1/1 ready; sources=2; diagnostics=ready"],
|
||||
];
|
||||
|
||||
assert.equal(fetchedUrl, "/real-browser-simulation-diagnostics.json");
|
||||
assert.equal(readyWorkflow.apiName, "project-release-readiness-artifact-url-workflow");
|
||||
@@ -103,14 +128,50 @@ assert.equal(readyWorkflow.fetchError, null);
|
||||
assert.equal(readyWorkflow.jsonWorkflow.ready, true);
|
||||
assert.equal(readyWorkflow.validation.ready, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.ready, true);
|
||||
assert.equal(readyWorkflow.diagnosticsArtifact.virtualHalPromotionCandidateSummary.ready, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.hasPromotionCandidates, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.promotionCandidatesReady, true);
|
||||
assert.equal(readyWorkflow.validation.virtualHalPromotionFamilySummary, expectedPromotionFamilySummary);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.hasMacroLoadFixtures, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.macroLoadFixturesReady, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.hasSessionDiagnostics, true);
|
||||
assert.equal(readyWorkflow.diagnosticsValidation.sessionDiagnosticsReady, true);
|
||||
assert.equal(readyWorkflow.diagnosticsFetched, true);
|
||||
assert.equal(readyWorkflow.diagnosticsHttpStatus, 200);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-families")?.value,
|
||||
expectedPromotionFamilySummary,
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-summary")?.value,
|
||||
"ready",
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate")?.value,
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-ini")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-gcode")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-count")?.value,
|
||||
"8/8 ready",
|
||||
);
|
||||
assert.equal(
|
||||
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
|
||||
"executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
);
|
||||
assert.deepEqual(
|
||||
readySummary.rows
|
||||
.filter(({ id }) => id.startsWith("virtual-hal-promotion-family-"))
|
||||
.map(({ id, value }) => [id, value]),
|
||||
expectedPromotionFamilyRows,
|
||||
);
|
||||
assert.equal(readyWorkflow.actionPlan.ready, true);
|
||||
assert.equal(readySummary.apiName, "project-release-readiness-artifact-url-workflow-summary-view-model");
|
||||
assert.equal(readySummary.statusLine, "Ready: Artifact URL workflow complete");
|
||||
@@ -121,7 +182,15 @@ assert.deepEqual(
|
||||
["fetch", "ready (200)"],
|
||||
["json-workflow", "ready"],
|
||||
["artifact-validation", "ready"],
|
||||
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
|
||||
...expectedPromotionFamilyRows,
|
||||
["browser-diagnostics", "ready"],
|
||||
["virtual-hal-promotion-candidate-summary", "ready"],
|
||||
["virtual-hal-promotion-candidate", "qtdragon-multi-joint-on-abort"],
|
||||
["virtual-hal-promotion-candidate-ini", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"],
|
||||
["virtual-hal-promotion-candidate-gcode", "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"],
|
||||
["virtual-hal-promotion-candidate-count", "8/8 ready"],
|
||||
["virtual-hal-promotion-candidate-baseline", "executed=28 passed=28 skipped=131 unexpected_fail=0"],
|
||||
["saved-session-diagnostics", "ready"],
|
||||
["next-command", "none"],
|
||||
["missing", "none"],
|
||||
@@ -143,6 +212,33 @@ assert.deepEqual(readyActionPlan, {
|
||||
rows: [],
|
||||
});
|
||||
|
||||
const missingPromotionCandidateSummaryArtifact = { ...browserDiagnosticsArtifact };
|
||||
delete missingPromotionCandidateSummaryArtifact.virtualHalPromotionCandidateSummary;
|
||||
const missingPromotionCandidateSummaryWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
diagnosticsUrl: "/real-browser-simulation-missing-promotion-candidate-summary.json",
|
||||
fetchRef: async (url) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => url === "/real-browser-simulation-missing-promotion-candidate-summary.json"
|
||||
? JSON.stringify(missingPromotionCandidateSummaryArtifact)
|
||||
: readyArtifactJson,
|
||||
}),
|
||||
});
|
||||
assert.equal(missingPromotionCandidateSummaryWorkflow.ready, false);
|
||||
assert.equal(missingPromotionCandidateSummaryWorkflow.diagnosticsValidation.ready, false);
|
||||
assert.equal(missingPromotionCandidateSummaryWorkflow.diagnosticsValidation.hasPromotionCandidateSummary, false);
|
||||
assert.equal(missingPromotionCandidateSummaryWorkflow.diagnosticsValidation.promotionCandidateSummaryReady, false);
|
||||
assert.equal(
|
||||
missingPromotionCandidateSummaryWorkflow.missing.includes("diagnostics.virtualHalPromotionCandidateSummary"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(missingPromotionCandidateSummaryWorkflow)
|
||||
.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-summary")?.value,
|
||||
"not provided",
|
||||
);
|
||||
|
||||
const liveOnlyDiagnosticsArtifact = { ...browserDiagnosticsSessionNestedArtifact };
|
||||
const liveOnlyDiagnosticsWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
|
||||
@@ -3,6 +3,8 @@ import assert from "node:assert/strict";
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS,
|
||||
createVirtualHalMotionControllerMatrixReport,
|
||||
createVirtualHalSimConfigMacroLoadFixtureReport,
|
||||
createVirtualHalSimConfigPromotionCandidateReport,
|
||||
createVirtualHalSimConfigSourceCoverageReport,
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
@@ -24,6 +26,11 @@ const virtualHalSimConfigSourceCoverage = createVirtualHalSimConfigSourceCoverag
|
||||
const virtualHalMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS.flatMap((target) => target.sourceFiles ?? []),
|
||||
});
|
||||
const virtualHalSimConfigPromotionCandidates = createVirtualHalSimConfigPromotionCandidateReport({
|
||||
simConfigSourceCoverage: virtualHalSimConfigSourceCoverage,
|
||||
motionControllerMatrix: virtualHalMotionControllerMatrix,
|
||||
});
|
||||
const virtualHalSimConfigMacroLoadFixtures = createVirtualHalSimConfigMacroLoadFixtureReport();
|
||||
|
||||
assert.equal(manifest.apiName, "project-release-gate-manifest");
|
||||
assert.equal(manifest.manifestVersion, 1);
|
||||
@@ -209,6 +216,8 @@ assert.match(partialActionPlan.shellScript, /wasm-port\/tests\/host\/verify_proj
|
||||
const report = createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix,
|
||||
});
|
||||
assert.deepEqual(report.gateManifest, manifest);
|
||||
@@ -257,6 +266,16 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
@@ -281,12 +300,14 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
|
||||
});
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport()).statusLine,
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage, virtual-hal-motion-controller-matrix",
|
||||
"Waiting: project-release-gate, virtual-hal-sim-config-source-coverage, virtual-hal-sim-config-promotion-candidates, virtual-hal-sim-config-macro-load-fixtures, virtual-hal-motion-controller-matrix",
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessSummaryViewModel(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage,
|
||||
virtualHalSimConfigPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix,
|
||||
promotedRuntimeFamilies: ["L4-TOOL-DB"],
|
||||
})).rows.find(({ id }) => id === "blocked-runtime-families")?.value,
|
||||
@@ -313,6 +334,13 @@ const artifactUrlWorkflow = await loadProjectReleaseReadinessArtifactUrlWorkflow
|
||||
const artifactUrlWorkflowSummary = createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
artifactUrlWorkflow,
|
||||
);
|
||||
const expectedPromotionFamilySummary =
|
||||
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready";
|
||||
const expectedPromotionFamilyRows = [
|
||||
["virtual-hal-promotion-family-qtdragon-on-abort", "6/6 ready; sources=12; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-vismach-remap-sims", "1/1 ready; sources=3; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-rose-engine-rcone-demo", "1/1 ready; sources=2; diagnostics=ready"],
|
||||
];
|
||||
assert.equal(
|
||||
artifactValidationSummary.apiName,
|
||||
"project-release-readiness-artifact-validation-summary-view-model",
|
||||
@@ -330,6 +358,10 @@ assert.deepEqual(
|
||||
["gate-result-matrix", "ready"],
|
||||
["gate-action-plan", "ready"],
|
||||
["virtual-hal-sim-config-source-coverage", "ready"],
|
||||
["virtual-hal-sim-config-promotion-candidates", "ready"],
|
||||
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
|
||||
...expectedPromotionFamilyRows,
|
||||
["virtual-hal-sim-config-macro-load-fixtures", "ready"],
|
||||
["virtual-hal-motion-controller-matrix", "ready"],
|
||||
["missing", "none"],
|
||||
],
|
||||
@@ -417,7 +449,15 @@ assert.deepEqual(
|
||||
["fetch", "ready (200)"],
|
||||
["json-workflow", "ready"],
|
||||
["artifact-validation", "ready"],
|
||||
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
|
||||
...expectedPromotionFamilyRows,
|
||||
["browser-diagnostics", "not requested"],
|
||||
["virtual-hal-promotion-candidate-summary", "not requested"],
|
||||
["virtual-hal-promotion-candidate", "not provided"],
|
||||
["virtual-hal-promotion-candidate-ini", "not provided"],
|
||||
["virtual-hal-promotion-candidate-gcode", "not provided"],
|
||||
["virtual-hal-promotion-candidate-count", "not provided"],
|
||||
["virtual-hal-promotion-candidate-baseline", "not provided"],
|
||||
["saved-session-diagnostics", "not requested"],
|
||||
["next-command", "none"],
|
||||
["missing", "none"],
|
||||
|
||||
@@ -36,8 +36,11 @@ import {
|
||||
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,
|
||||
@@ -178,6 +181,16 @@ const sdkIndexText = readFileSync(resolve(root, "runtime/sdk/src/index.js"), "ut
|
||||
const sdkReadmeText = readFileSync(resolve(root, "runtime/sdk/README.md"), "utf8");
|
||||
const sourceManifestText = readFileSync(resolve(root, "tools/source-manifest.txt"), "utf8");
|
||||
const trackerText = readFileSync(resolve(root, "../PROJECT_COMPLETION_TRACKER.md"), "utf8");
|
||||
const expectedPromotionFamilySummary =
|
||||
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready";
|
||||
const expectedPromotionFamilyRows = [
|
||||
["virtual-hal-promotion-family-qtdragon-on-abort", "6/6 ready; sources=12; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-vismach-remap-sims", "1/1 ready; sources=3; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-rose-engine-rcone-demo", "1/1 ready; sources=2; diagnostics=ready"],
|
||||
];
|
||||
const hasFreshBoundaryArtifactHashes = (boundaryEvidence) =>
|
||||
Object.entries(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
|
||||
.every(([artifactPath, expectedHash]) => boundaryEvidence?.sourceArtifactHashes?.[artifactPath] === expectedHash);
|
||||
|
||||
const requiredExports = [
|
||||
["createLinuxCncIniSdk", createLinuxCncIniSdk],
|
||||
@@ -551,6 +564,10 @@ assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES\b/);
|
||||
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES\b/);
|
||||
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES\b/);
|
||||
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES\b/);
|
||||
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES\b/);
|
||||
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES\b/);
|
||||
assert.match(sdkIndexText, /\bVIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE\b/);
|
||||
assert.match(sdkReadmeText, /\bVIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSimConfigMacroLoadFixtureReport\b/);
|
||||
assert.match(sdkReadmeText, /\bcreateVirtualHalSimConfigMacroLoadFixtureReport\b/);
|
||||
assert.match(sdkIndexText, /\bcreateVirtualHalSourceComplianceReport\b/);
|
||||
@@ -784,6 +801,39 @@ assert.equal(simConfigPromotionCandidateReport.missingCandidates.length, 0);
|
||||
assert.equal(simConfigPromotionCandidateReport.blockedCandidateIds.length, 0);
|
||||
assert.equal(simConfigPromotionCandidateReport.missingManifestFiles.length, 0);
|
||||
assert.equal(simConfigPromotionCandidateReport.missingRequiredReports.length, 0);
|
||||
assert.equal(
|
||||
simConfigPromotionCandidateReport.familyRows.some((row) =>
|
||||
row.id === "qtdragon-on-abort" &&
|
||||
row.candidateCount === 6 &&
|
||||
row.completeCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsCount === 6 &&
|
||||
row.explicitBrowserDiagnosticsReady === true &&
|
||||
row.complete === true &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini") &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/qtvcp_screens/qtdragon/on_abort.ngc")
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
simConfigPromotionCandidateReport.familyRows.some((row) =>
|
||||
row.id === "vismach-remap-sims" &&
|
||||
row.candidateCount === 1 &&
|
||||
row.complete === true &&
|
||||
row.explicitBrowserDiagnosticsReady === true &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc")
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
simConfigPromotionCandidateReport.familyRows.some((row) =>
|
||||
row.id === "rose-engine-rcone-demo" &&
|
||||
row.candidateCount === 1 &&
|
||||
row.complete === true &&
|
||||
row.explicitBrowserDiagnosticsReady === true &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc")
|
||||
),
|
||||
true,
|
||||
);
|
||||
const expectedPromotionCandidates = [
|
||||
[
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
@@ -833,6 +883,7 @@ for (const [id, ...sourceFiles] of expectedPromotionCandidates) {
|
||||
row.id === id &&
|
||||
row.complete === true &&
|
||||
row.currentNodeInventoryStatus === "PASS" &&
|
||||
row.currentMatrixBrowserStatus === "explicit-browser-diagnostics" &&
|
||||
row.targetBrowserEvidence === "explicit-browser-diagnostics" &&
|
||||
sourceFiles.every((sourceFile) => row.sourceFiles.includes(sourceFile))
|
||||
),
|
||||
@@ -847,6 +898,19 @@ assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
|
||||
}).complete, true);
|
||||
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.length >= 2, true);
|
||||
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.length >= 2, true);
|
||||
assert.equal(VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_AUDIT_CANDIDATES.length >= 2, true);
|
||||
assert.deepEqual(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE, {
|
||||
executed: 28,
|
||||
passed: 28,
|
||||
skipped: 131,
|
||||
unexpectedFail: 0,
|
||||
});
|
||||
assert.deepEqual(VIRTUAL_HAL_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",
|
||||
});
|
||||
const simConfigMacroLoadFixtureReport = createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
});
|
||||
@@ -862,7 +926,13 @@ assert.equal(simConfigMacroLoadFixtureReport.missingFixtures.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.blockedFixtureIds.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.standaloneMainViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.blockedFixturePromotionViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.blockedBoundaryEvidenceViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.missingAuditRows.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.auditPromotionViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.auditBoundaryEvidenceViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.auditPromotionAllowedViolations.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.missingManifestFiles.length, 0);
|
||||
assert.equal(simConfigMacroLoadFixtureReport.declarationEvidenceViolations.length, 0);
|
||||
assert.equal(
|
||||
simConfigMacroLoadFixtureReport.rows.some((row) =>
|
||||
row.id === "rose-engine-rcone-macro-load" &&
|
||||
@@ -870,6 +940,12 @@ assert.equal(
|
||||
row.nonMainFixture === true &&
|
||||
row.targetBrowserEvidence === "non-main-fixture-diagnostics" &&
|
||||
row.fixturePath === "linuxcnc/configs/sim/axis/rose_engine/rcone.ngc" &&
|
||||
row.requiresDeclarationEvidence === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence.sourceFile === "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini" &&
|
||||
row.declarationEvidence.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence.value === "rcone.ngc" &&
|
||||
row.declarationEvidence.line === 34 &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/rose_engine/rcone.ngc") &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc")
|
||||
),
|
||||
@@ -881,18 +957,50 @@ assert.equal(
|
||||
row.complete === true &&
|
||||
row.nonMainFixture === true &&
|
||||
row.declaredOnly === true &&
|
||||
row.declarationEvidenceReady === true &&
|
||||
row.declarationEvidence.sourceFile === "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini" &&
|
||||
row.declarationEvidence.key === "NGCGUI_SUBFILE" &&
|
||||
row.declarationEvidence.value === "queuebuster.ngc" &&
|
||||
row.declarationEvidence.line === 40 &&
|
||||
row.fixturePath === "linuxcnc/configs/sim/axis/external_offsets/queuebuster.ngc" &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini") &&
|
||||
row.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc")
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
fixtures: [
|
||||
{
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.find(({ id }) => id === "external-offsets-queuebuster-macro-load"),
|
||||
declarationEvidence: null,
|
||||
},
|
||||
],
|
||||
}).declarationEvidenceViolations.includes("external-offsets-queuebuster-macro-load"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
fixtures: [
|
||||
{
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES.find(({ id }) => id === "rose-engine-rcone-macro-load"),
|
||||
declarationEvidence: null,
|
||||
},
|
||||
],
|
||||
}).declarationEvidenceViolations.includes("rose-engine-rcone-macro-load"), true);
|
||||
assert.equal(
|
||||
simConfigMacroLoadFixtureReport.blockedRows.some((row) =>
|
||||
row.id === "silverdragon-tool-sensor-python-ui-boundary" &&
|
||||
row.fixturePath === "linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc" &&
|
||||
row.blockedKind === "PYTHON-UI-PROCESS" &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
hasFreshBoundaryArtifactHashes(row.boundaryEvidence) &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/silverdragon/silverdragon.ini") &&
|
||||
row.boundaryEvidence.baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
row.boundaryEvidence.baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0 &&
|
||||
row.boundaryEvidence.iniBoundarySummary.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
),
|
||||
true,
|
||||
@@ -903,10 +1011,170 @@ assert.equal(
|
||||
row.fixturePath === "linuxcnc/configs/sim/gmoccapy/macros/on_abort.ngc" &&
|
||||
row.blockedKind === "L4-PYTHON-REMAP" &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
hasFreshBoundaryArtifactHashes(row.boundaryEvidence) &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gmoccapy/6_axis.ini") &&
|
||||
row.boundaryEvidence.baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
row.boundaryEvidence.baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0 &&
|
||||
row.boundaryEvidence.iniBoundarySummary.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
simConfigMacroLoadFixtureReport.auditRows.some((row) =>
|
||||
row.id === "gscreen-industrial-lathe-wear-toolchange-audit" &&
|
||||
row.fixturePath === "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc" &&
|
||||
row.auditStatus === "blocked-missing-owning-ini" &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
hasFreshBoundaryArtifactHashes(row.boundaryEvidence) &&
|
||||
row.boundaryEvidence.boundarySummary.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini") &&
|
||||
row.boundaryEvidence.baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
row.boundaryEvidence.baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0 &&
|
||||
row.boundaryEvidence.iniBoundarySummary.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
simConfigMacroLoadFixtureReport.auditRows.some((row) =>
|
||||
row.id === "qtvcp-industrial-lathe-wear-toolchange-audit" &&
|
||||
row.fixturePath === "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc" &&
|
||||
row.auditStatus === "blocked-missing-owning-ini" &&
|
||||
row.promotionAllowed === false &&
|
||||
row.excludedFromPositiveFixtures === true &&
|
||||
row.boundaryEvidenceReady === true &&
|
||||
hasFreshBoundaryArtifactHashes(row.boundaryEvidence) &&
|
||||
row.boundaryEvidence.boundarySummary.recommendedBlocked === "UNAVAILABLE" &&
|
||||
row.boundaryEvidence.boundarySummary.dependencies.includes("missing_vendored_ini:configs/sim/qtvcp_screens/industrial_lathe_wear/industrial_lathe_wear.ini") &&
|
||||
row.boundaryEvidence.baselineSummary.executed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.executed &&
|
||||
row.boundaryEvidence.baselineSummary.passed === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.passed &&
|
||||
row.boundaryEvidence.baselineSummary.skipped === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
|
||||
row.boundaryEvidence.baselineSummary.unexpectedFail === VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
|
||||
row.boundaryEvidence.iniBoundarySummary.vendored === 0 &&
|
||||
row.boundaryEvidence.iniBoundarySummary.reportAvailable === 0 &&
|
||||
row.complete === true
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
auditCandidates: [],
|
||||
}).complete, true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
blockedFixtures: [
|
||||
{
|
||||
id: "bad-blocked-boundary-evidence",
|
||||
fixturePath: "linuxcnc/configs/sim/gscreen/silverdragon/macros/tool_sensor.ngc",
|
||||
owningIniPath: "linuxcnc/configs/sim/gscreen/silverdragon/silverdragon.ini",
|
||||
blockedKind: "PYTHON-UI-PROCESS",
|
||||
dependencyClass: "macro-load-python-ui-boundary",
|
||||
reason: "negative fixture: blocked row missing generated boundary evidence must fail",
|
||||
},
|
||||
],
|
||||
}).blockedBoundaryEvidenceViolations.includes("bad-blocked-boundary-evidence"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
blockedFixtures: [
|
||||
{
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.find(
|
||||
({ id }) => id === "silverdragon-tool-sensor-python-ui-boundary",
|
||||
),
|
||||
id: "stale-blocked-boundary-evidence",
|
||||
boundaryEvidence: {
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.find(
|
||||
({ id }) => id === "silverdragon-tool-sensor-python-ui-boundary",
|
||||
).boundaryEvidence,
|
||||
baselineSummary: {
|
||||
...VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
|
||||
skipped: 130,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}).blockedBoundaryEvidenceViolations.includes("stale-blocked-boundary-evidence"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
blockedFixtures: [
|
||||
{
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.find(
|
||||
({ id }) => id === "silverdragon-tool-sensor-python-ui-boundary",
|
||||
),
|
||||
id: "stale-hash-blocked-boundary-evidence",
|
||||
boundaryEvidence: {
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_BLOCKED_FIXTURES.find(
|
||||
({ id }) => id === "silverdragon-tool-sensor-python-ui-boundary",
|
||||
).boundaryEvidence,
|
||||
sourceArtifactHashes: {
|
||||
...VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
|
||||
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv": "stale",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}).blockedBoundaryEvidenceViolations.includes("stale-hash-blocked-boundary-evidence"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
fixtures: [
|
||||
...VIRTUAL_HAL_SIM_CONFIG_MACRO_LOAD_FIXTURES,
|
||||
{
|
||||
id: "bad-positive-industrial-lathe-audit",
|
||||
label: "Bad positive industrial lathe audit fixture",
|
||||
fixturePath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
|
||||
sourceFiles: [
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
],
|
||||
owningIniPath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/industrial_lathe_wear.ini",
|
||||
pairedMainProgram: "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
declarationSource: "NGCGUI_SUBFILE",
|
||||
currentNodeInventoryStatus: "PASS",
|
||||
dependencyClass: "macro-load-ui-family-audit",
|
||||
targetBrowserEvidence: "non-main-fixture-diagnostics",
|
||||
blockedKind: "-",
|
||||
nonMainFixture: true,
|
||||
declaredOnly: false,
|
||||
evidence: "negative fixture: audit candidate must not be promoted as a positive fixture",
|
||||
},
|
||||
],
|
||||
}).auditPromotionViolations.includes("gscreen-industrial-lathe-wear-toolchange-audit"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
auditCandidates: [
|
||||
{
|
||||
id: "bad-audit-boundary-evidence",
|
||||
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,
|
||||
reason: "negative fixture: missing generated boundary evidence must fail",
|
||||
},
|
||||
],
|
||||
}).auditBoundaryEvidenceViolations.includes("bad-audit-boundary-evidence"), true);
|
||||
assert.equal(createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
auditCandidates: [
|
||||
{
|
||||
id: "bad-audit-promotion-allowed",
|
||||
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: true,
|
||||
reason: "negative fixture: promotionAllowed true without boundary/source proof must fail",
|
||||
},
|
||||
],
|
||||
}).auditPromotionAllowedViolations.includes("bad-audit-promotion-allowed"), true);
|
||||
assert.equal(virtualHalRuntime.getSimConfigMacroLoadFixtureReport({
|
||||
manifestText: sourceManifestText,
|
||||
}).complete, true);
|
||||
@@ -958,6 +1226,22 @@ const browserDiagnosticsArtifact = {
|
||||
virtualHalSourceCompliance: sourceComplianceReport,
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalPromotionCandidateSummary: {
|
||||
apiName: "real-browser-simulation-promotion-candidate-summary",
|
||||
summaryVersion: 1,
|
||||
phase: "ready",
|
||||
ready: true,
|
||||
candidateCount: 8,
|
||||
readyCandidateCount: 8,
|
||||
familyCount: 3,
|
||||
sourceFileCount: 17,
|
||||
preferredCandidateId: "qtdragon-multi-joint-on-abort",
|
||||
preferredIniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
blockedCandidateIds: [],
|
||||
explicitBrowserDiagnosticsCount: 8,
|
||||
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
},
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalCommandScriptFixtures: commandScriptFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
@@ -984,6 +1268,8 @@ assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidatesReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.hasPromotionCandidates, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidateSummaryReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.hasPromotionCandidateSummary, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.macroLoadFixturesReady, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.hasMacroLoadFixtures, true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.commandScriptFixturesReady, true);
|
||||
@@ -1004,6 +1290,38 @@ assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/rose_engine/rcone.ngc"), true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini"), true);
|
||||
assert.equal(browserDiagnosticsArtifactValidation.sourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc"), true);
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalPromotionCandidateSummary: undefined,
|
||||
}).missing.includes("virtualHalPromotionCandidateSummary"), true);
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalPromotionCandidateSummary: {
|
||||
...browserDiagnosticsArtifact.virtualHalPromotionCandidateSummary,
|
||||
readyCandidateCount: 7,
|
||||
},
|
||||
}).promotionCandidateSummaryReady, false);
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalSimConfigMacroLoadFixtures: {
|
||||
...simConfigMacroLoadFixtureReport,
|
||||
auditRows: [],
|
||||
},
|
||||
}).macroLoadFixturesReady, false);
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalSimConfigMacroLoadFixtures: {
|
||||
...simConfigMacroLoadFixtureReport,
|
||||
auditBoundaryEvidenceViolations: ["gscreen-industrial-lathe-wear-toolchange-audit"],
|
||||
},
|
||||
}).missing.includes("virtualHalSimConfigMacroLoadFixtures"), true);
|
||||
assert.equal(createProjectReleaseBrowserDiagnosticsArtifactValidation({
|
||||
...browserDiagnosticsArtifact,
|
||||
virtualHalSimConfigMacroLoadFixtures: {
|
||||
...simConfigMacroLoadFixtureReport,
|
||||
auditPromotionAllowedViolations: ["qtvcp-industrial-lathe-wear-toolchange-audit"],
|
||||
},
|
||||
}).ready, false);
|
||||
const runtimeProjectReport = virtualHalRuntime.getProjectReport({ availableFunctions: VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS });
|
||||
assert.equal(runtimeProjectReport.simulationRuntime.replacesHostRuntimeForSimulation, true);
|
||||
assert.equal(runtimeProjectReport.systemCoverage.unclassifiedSnapshotPins.length, 0);
|
||||
@@ -1143,6 +1461,8 @@ assert.equal(releaseReadinessWaiting.ready, false);
|
||||
assert.deepEqual(releaseReadinessWaiting.missing, [
|
||||
"project-release-gate",
|
||||
"virtual-hal-sim-config-source-coverage",
|
||||
"virtual-hal-sim-config-promotion-candidates",
|
||||
"virtual-hal-sim-config-macro-load-fixtures",
|
||||
"virtual-hal-motion-controller-matrix",
|
||||
]);
|
||||
assert.equal(releaseReadinessWaiting.simConfigInventory.unexpectedFail, 0);
|
||||
@@ -1157,11 +1477,23 @@ assert.equal(
|
||||
const releaseReadinessReady = createProjectReleaseReadinessReport({
|
||||
observedOutputs: ["project_release_gate=ok"],
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
});
|
||||
assert.equal(releaseReadinessReady.ready, true);
|
||||
assert.equal(releaseReadinessReady.releaseGate.passed, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalSimConfigSourceCoverageReady, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalSimConfigPromotionCandidatesReady, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalPromotionFamilySummary, expectedPromotionFamilySummary);
|
||||
assert.deepEqual(
|
||||
releaseReadinessReady.virtualHalPromotionFamilyRows.map(({ id, value }) => [
|
||||
`virtual-hal-promotion-family-${id}`,
|
||||
value,
|
||||
]),
|
||||
expectedPromotionFamilyRows,
|
||||
);
|
||||
assert.equal(releaseReadinessReady.virtualHalSimConfigMacroLoadFixturesReady, true);
|
||||
assert.equal(releaseReadinessReady.virtualHalMotionControllerMatrixReady, true);
|
||||
assert.deepEqual(releaseReadinessReady.gateManifest, createProjectReleaseGateManifest());
|
||||
assert.equal(releaseReadinessReady.gateResultMatrix.rows.length, createProjectReleaseGateManifest().gateCount);
|
||||
@@ -1179,6 +1511,8 @@ assert.equal(
|
||||
const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
axisScreenshotArtifacts: ["desktop-preview", "desktop-dro", "mobile-preview", "mobile-mdi"].map((viewportName) => ({
|
||||
apiName: "real-browser-simulation-axis-screenshot-artifact",
|
||||
@@ -1214,6 +1548,8 @@ assert.equal(
|
||||
const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
|
||||
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
|
||||
virtualHalSimConfigMacroLoadFixtures: simConfigMacroLoadFixtureReport,
|
||||
virtualHalMotionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
|
||||
})));
|
||||
assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report");
|
||||
@@ -1235,6 +1571,10 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
gateResultMatrixReady: true,
|
||||
gateActionPlanReady: true,
|
||||
virtualHalSimConfigSourceCoverageReady: true,
|
||||
virtualHalSimConfigPromotionCandidatesReady: true,
|
||||
virtualHalPromotionFamilySummary: expectedPromotionFamilySummary,
|
||||
virtualHalPromotionFamilyRows: releaseReadinessReady.virtualHalPromotionFamilyRows,
|
||||
virtualHalSimConfigMacroLoadFixturesReady: true,
|
||||
virtualHalMotionControllerMatrixReady: true,
|
||||
axisScreenshotArtifactSummaryReady: true,
|
||||
axisScreenshotArtifactCount: 0,
|
||||
@@ -1284,6 +1624,29 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
label: "Virtual HAL sim-config source coverage",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-sim-config-promotion-candidates",
|
||||
label: "Virtual HAL sim-config promotion candidates",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-promotion-families",
|
||||
label: "Virtual HAL promotion families",
|
||||
value: expectedPromotionFamilySummary,
|
||||
},
|
||||
...expectedPromotionFamilyRows.map(([id, value]) => ({
|
||||
id,
|
||||
label: `Promotion family ${id.replace("virtual-hal-promotion-family-", "")}`,
|
||||
value,
|
||||
sourceFiles: releaseReadinessReady.virtualHalPromotionFamilyRows.find((row) =>
|
||||
`virtual-hal-promotion-family-${row.id}` === id
|
||||
)?.sourceFiles ?? [],
|
||||
})),
|
||||
{
|
||||
id: "virtual-hal-sim-config-macro-load-fixtures",
|
||||
label: "Virtual HAL sim-config macro/load fixtures",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "virtual-hal-motion-controller-matrix",
|
||||
label: "Virtual HAL motion controller matrix",
|
||||
@@ -1307,6 +1670,20 @@ assert.equal(
|
||||
).statusLine,
|
||||
"Ready: Artifact evidence complete",
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
releaseReadinessArtifactValidation,
|
||||
).rows.find(({ id }) => id === "virtual-hal-promotion-families")?.value,
|
||||
expectedPromotionFamilySummary,
|
||||
);
|
||||
assert.deepEqual(
|
||||
createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
releaseReadinessArtifactValidation,
|
||||
).rows
|
||||
.filter(({ id }) => id.startsWith("virtual-hal-promotion-family-"))
|
||||
.map(({ id, value }) => [id, value]),
|
||||
expectedPromotionFamilyRows,
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactValidationActionPlan(releaseReadinessArtifactValidation).shellScript,
|
||||
"# Project release readiness artifact validation is already ready.\n",
|
||||
@@ -1350,6 +1727,34 @@ assert.equal(
|
||||
).statusLine,
|
||||
"Ready: Artifact URL workflow complete",
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
fetchRef: async () => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify(releaseReadinessArtifact),
|
||||
}),
|
||||
}),
|
||||
).rows.find(({ id }) => id === "virtual-hal-promotion-families")?.value,
|
||||
expectedPromotionFamilySummary,
|
||||
);
|
||||
assert.deepEqual(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
fetchRef: async () => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify(releaseReadinessArtifact),
|
||||
}),
|
||||
}),
|
||||
).rows
|
||||
.filter(({ id }) => id.startsWith("virtual-hal-promotion-family-"))
|
||||
.map(({ id, value }) => [id, value]),
|
||||
expectedPromotionFamilyRows,
|
||||
);
|
||||
assert.equal(
|
||||
createProjectReleaseReadinessArtifactUrlWorkflowActionPlan(
|
||||
await loadProjectReleaseReadinessArtifactUrlWorkflow({
|
||||
@@ -1386,6 +1791,8 @@ assert.deepEqual(
|
||||
"simConfigInventory.skipped",
|
||||
"simConfigInventory.unexpectedFail",
|
||||
"virtualHalSimConfigSourceCoverage",
|
||||
"virtualHalSimConfigPromotionCandidates",
|
||||
"virtualHalSimConfigMacroLoadFixtures",
|
||||
"virtualHalMotionControllerMatrix",
|
||||
"blockedRuntimeFamilies",
|
||||
"gateManifest",
|
||||
|
||||
@@ -84,6 +84,25 @@ import {
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan,
|
||||
handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange,
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls,
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilyRowsState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilyRowsState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomContract,
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract,
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness,
|
||||
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState,
|
||||
@@ -744,6 +763,19 @@ assert.deepEqual(shellViewModel.shellWorkflowOverviewContract, {
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsRenderState",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterViewModel",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomContract",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterDomReadiness",
|
||||
"getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan",
|
||||
"handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange",
|
||||
"bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls",
|
||||
"renderWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"mountWorkflowOverviewPromotionFamilySourceFilterState",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomContract",
|
||||
"getWorkflowOverviewPromotionFamilyRowsDomReadiness",
|
||||
"renderWorkflowOverviewPromotionFamilyRowsState",
|
||||
"mountWorkflowOverviewPromotionFamilyRowsState",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract",
|
||||
"getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness",
|
||||
"renderWorkflowOverviewReleaseReadinessArtifactUrlWorkflowState",
|
||||
@@ -1044,7 +1076,27 @@ const mountRowsNode = {
|
||||
const mountNode = { dataset: {} };
|
||||
const mountStatusNode = { textContent: "" };
|
||||
const mountDocument = {
|
||||
createElement: (tagName) => ({ tagName, dataset: {}, textContent: "" }),
|
||||
createElement: (tagName) => ({
|
||||
tagName,
|
||||
dataset: {},
|
||||
textContent: "",
|
||||
children: [],
|
||||
listeners: {},
|
||||
append(...nodes) {
|
||||
this.children.push(...nodes);
|
||||
},
|
||||
addEventListener(eventName, handler) {
|
||||
this.listeners[eventName] = handler;
|
||||
},
|
||||
removeEventListener(eventName, handler) {
|
||||
if (this.listeners[eventName] === handler) {
|
||||
delete this.listeners[eventName];
|
||||
}
|
||||
},
|
||||
dispatchEvent(eventName) {
|
||||
return this.listeners[eventName]?.();
|
||||
},
|
||||
}),
|
||||
};
|
||||
assert.deepEqual(
|
||||
createIniPanelShellSessionHandoffMountDomReadiness({
|
||||
@@ -1366,9 +1418,34 @@ assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), shellViewModel.s
|
||||
const releaseReadinessMotionControllerMatrix = createVirtualHalMotionControllerMatrixReport({
|
||||
manifestEntries: VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
});
|
||||
const releaseReadinessPromotionCandidates = createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
],
|
||||
motionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
});
|
||||
const releaseReadinessMacroLoadFixtures = createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
],
|
||||
});
|
||||
const releaseReadinessArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
|
||||
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: releaseReadinessPromotionCandidates,
|
||||
virtualHalSimConfigMacroLoadFixtures: releaseReadinessMacroLoadFixtures,
|
||||
virtualHalMotionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
}));
|
||||
const browserDiagnosticsVirtualHalState = createVirtualHalState();
|
||||
@@ -1379,29 +1456,24 @@ const browserDiagnosticsArtifact = {
|
||||
virtualHalSimulationReplacement: createVirtualHalSimulationReplacementReport(browserDiagnosticsVirtualHalState),
|
||||
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: browserDiagnosticsVirtualHalState }),
|
||||
virtualHalSimConfigSourceCoverage: createVirtualHalSimConfigSourceCoverageReport(),
|
||||
virtualHalSimConfigPromotionCandidates: createVirtualHalSimConfigPromotionCandidateReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/qtdragon_xyza.ini",
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_xyz45/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/qtdragon_hd_z_compensation.ini",
|
||||
"linuxcnc/configs/sim/qtdragon_hd/qtdragon_hd_z_compensation/on_abort.ngc",
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/puma_seam_weld.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
],
|
||||
motionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
}),
|
||||
virtualHalSimConfigMacroLoadFixtures: createVirtualHalSimConfigMacroLoadFixtureReport({
|
||||
manifestEntries: [
|
||||
...VIRTUAL_HAL_MOTION_MATRIX_MANIFEST_ENTRIES,
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
|
||||
"linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
|
||||
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
|
||||
],
|
||||
}),
|
||||
virtualHalSimConfigPromotionCandidates: releaseReadinessPromotionCandidates,
|
||||
virtualHalPromotionCandidateSummary: {
|
||||
apiName: "real-browser-simulation-promotion-candidate-summary",
|
||||
summaryVersion: 1,
|
||||
phase: "ready",
|
||||
ready: true,
|
||||
candidateCount: 8,
|
||||
readyCandidateCount: 8,
|
||||
familyCount: 3,
|
||||
sourceFileCount: 17,
|
||||
preferredCandidateId: "qtdragon-multi-joint-on-abort",
|
||||
preferredIniPath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
preferredGcodePath: "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
blockedCandidateIds: [],
|
||||
explicitBrowserDiagnosticsCount: 8,
|
||||
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
},
|
||||
virtualHalSimConfigMacroLoadFixtures: releaseReadinessMacroLoadFixtures,
|
||||
virtualHalCommandScriptFixtures: createVirtualHalCommandScriptFixtureReport({ halState: browserDiagnosticsVirtualHalState }),
|
||||
virtualHalMotionControllerMatrix: releaseReadinessMotionControllerMatrix,
|
||||
};
|
||||
@@ -1725,7 +1797,7 @@ const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseRead
|
||||
rowsNode: releaseArtifactRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 17);
|
||||
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
|
||||
@@ -1735,6 +1807,10 @@ assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-summary"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("virtual-hal-promotion-families"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-action-plan"),
|
||||
true,
|
||||
@@ -1752,7 +1828,7 @@ assert.equal(
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactMountResult.ready, true);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 17);
|
||||
assert.deepEqual(
|
||||
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
|
||||
["artifact-json"],
|
||||
@@ -1811,11 +1887,18 @@ assert.equal(
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflow.renderState.statusLine, "Ready: No blocking reasons");
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 11);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 17);
|
||||
const releaseArtifactUrlWorkflowSummary =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
releaseArtifactUrlWorkflow,
|
||||
);
|
||||
const expectedPromotionFamilySummary =
|
||||
"qtdragon-on-abort: 6/6 ready; vismach-remap-sims: 1/1 ready; rose-engine-rcone-demo: 1/1 ready";
|
||||
const expectedPromotionFamilyRows = [
|
||||
["virtual-hal-promotion-family-qtdragon-on-abort", "6/6 ready; sources=12; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-vismach-remap-sims", "1/1 ready; sources=3; diagnostics=ready"],
|
||||
["virtual-hal-promotion-family-rose-engine-rcone-demo", "1/1 ready; sources=2; diagnostics=ready"],
|
||||
];
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.statusLine,
|
||||
"Ready: Artifact URL workflow complete",
|
||||
@@ -1836,6 +1919,583 @@ assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "browser-diagnostics")?.value,
|
||||
"ready",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-summary")?.value,
|
||||
"ready",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate")?.value,
|
||||
"qtdragon-multi-joint-on-abort",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-ini")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-gcode")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-count")?.value,
|
||||
"8/8 ready",
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
|
||||
"executed=28 passed=28 skipped=131 unexpected_fail=0",
|
||||
);
|
||||
const promotionCandidateDrilldownViewModel =
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownViewModel(
|
||||
releaseArtifactUrlWorkflowSummary,
|
||||
{ diagnosticsArtifact: releaseArtifactUrlWorkflow.diagnosticsArtifact },
|
||||
);
|
||||
const promotionCandidateDrilldownRenderState =
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownRenderState(
|
||||
promotionCandidateDrilldownViewModel,
|
||||
);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.ready, true);
|
||||
assert.equal(
|
||||
promotionCandidateDrilldownViewModel.statusLine,
|
||||
"Ready: qtdragon-multi-joint-on-abort source-derived browser evidence ready",
|
||||
);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.candidateId, "qtdragon-multi-joint-on-abort");
|
||||
assert.equal(promotionCandidateDrilldownViewModel.blockedFamilyExcluded, true);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.nodeInventoryReady, true);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.browserEvidenceReady, true);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.virtualHalReportsReady, true);
|
||||
assert.deepEqual(promotionCandidateDrilldownViewModel.requiredReports, [
|
||||
"source-compliance",
|
||||
"sim-config-source-coverage",
|
||||
"command-script-fixtures",
|
||||
"manifest-backed-motion-matrix",
|
||||
]);
|
||||
assert.equal(
|
||||
promotionCandidateDrilldownViewModel.rows.find(({ id }) => id === "ini")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini",
|
||||
);
|
||||
assert.equal(
|
||||
promotionCandidateDrilldownViewModel.rows.find(({ id }) => id === "gcode")?.value,
|
||||
"linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc",
|
||||
);
|
||||
assert.equal(
|
||||
promotionCandidateDrilldownViewModel.rows.find(({ id }) => id === "blocked-family-exclusion")?.value,
|
||||
"passed",
|
||||
);
|
||||
assert.equal(promotionCandidateDrilldownViewModel.sourceFileCount, 2);
|
||||
assert.deepEqual(
|
||||
promotionCandidateDrilldownViewModel.sourceRows.map(({ value, sourceKind, manifestBacked }) => [
|
||||
value,
|
||||
sourceKind,
|
||||
manifestBacked,
|
||||
]),
|
||||
[
|
||||
["linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini", "ini", true],
|
||||
["linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc", "gcode", true],
|
||||
],
|
||||
);
|
||||
assert.equal(promotionCandidateDrilldownRenderState.ready, true);
|
||||
assert.equal(promotionCandidateDrilldownRenderState.rowCount, 11);
|
||||
assert.equal(promotionCandidateDrilldownRenderState.sourceFileCount, 2);
|
||||
assert.equal(
|
||||
createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomContract().selectors.mount,
|
||||
"[data-workflow-overview-promotion-candidate-drilldown]",
|
||||
);
|
||||
assert.equal(createIniPanelShellWorkflowOverviewPromotionCandidateDrilldownDomReadiness().ready, false);
|
||||
const promotionCandidateDrilldownMountNode = mountDocument.createElement("section");
|
||||
promotionCandidateDrilldownMountNode.dataset.workflowOverviewPromotionCandidateDrilldown = "";
|
||||
const promotionCandidateDrilldownStatusNode = mountDocument.createElement("p");
|
||||
promotionCandidateDrilldownStatusNode.dataset.workflowOverviewPromotionCandidateDrilldownStatus = "";
|
||||
const promotionCandidateDrilldownRowsNode = {
|
||||
children: [],
|
||||
dataset: {},
|
||||
append(...nodes) {
|
||||
this.children.push(...nodes);
|
||||
},
|
||||
replaceChildren(...nodes) {
|
||||
this.children = [...nodes];
|
||||
},
|
||||
};
|
||||
promotionCandidateDrilldownRowsNode.dataset.workflowOverviewPromotionCandidateDrilldownRows = "";
|
||||
const promotionCandidateDrilldownRenderResult =
|
||||
renderIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState(
|
||||
promotionCandidateDrilldownRenderState,
|
||||
{
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionCandidateDrilldownMountNode,
|
||||
statusNode: promotionCandidateDrilldownStatusNode,
|
||||
rowsNode: promotionCandidateDrilldownRowsNode,
|
||||
},
|
||||
);
|
||||
const promotionCandidateDrilldownMountResult =
|
||||
mountIniPanelShellWorkflowOverviewPromotionCandidateDrilldownState({
|
||||
renderState: promotionCandidateDrilldownRenderState,
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionCandidateDrilldownMountNode,
|
||||
statusNode: promotionCandidateDrilldownStatusNode,
|
||||
rowsNode: promotionCandidateDrilldownRowsNode,
|
||||
});
|
||||
assert.equal(promotionCandidateDrilldownRenderResult.rendered, true);
|
||||
assert.equal(promotionCandidateDrilldownRenderResult.rowCount, 11);
|
||||
assert.deepEqual(promotionCandidateDrilldownRenderResult.dataset, {
|
||||
handoffPhase: "ready",
|
||||
handoffReady: "true",
|
||||
handoffScope: "workflow-overview-promotion-candidate-drilldown",
|
||||
candidateId: "qtdragon-multi-joint-on-abort",
|
||||
});
|
||||
assert.equal(promotionCandidateDrilldownRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionCandidateDrilldownValue === "blocked-family-exclusion" &&
|
||||
node.textContent === "passed"
|
||||
), true);
|
||||
assert.equal(promotionCandidateDrilldownRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionCandidateDrilldownSourceKind === "gcode" &&
|
||||
node.dataset?.workflowOverviewPromotionCandidateDrilldownManifestBacked === "true" &&
|
||||
node.textContent === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"
|
||||
), true);
|
||||
assert.equal(promotionCandidateDrilldownMountResult.ready, true);
|
||||
assert.equal(promotionCandidateDrilldownMountResult.renderResult.sourceFileCount, 2);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-families")?.value,
|
||||
expectedPromotionFamilySummary,
|
||||
);
|
||||
assert.deepEqual(
|
||||
releaseArtifactUrlWorkflowSummary.rows
|
||||
.filter(({ id }) => id.startsWith("virtual-hal-promotion-family-"))
|
||||
.map(({ id, value }) => [id, value]),
|
||||
expectedPromotionFamilyRows,
|
||||
);
|
||||
const promotionFamilyRowsRenderState =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsRenderState(
|
||||
releaseArtifactUrlWorkflowSummary,
|
||||
);
|
||||
const promotionFamilySourceFilterViewModel =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
|
||||
promotionFamilyRowsRenderState,
|
||||
);
|
||||
const promotionFamilyRemapSourceFilterViewModel =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
|
||||
promotionFamilyRowsRenderState,
|
||||
{ sourceKind: "remap-subroutine" },
|
||||
);
|
||||
const promotionFamilyQtDragonGcodeFilterViewModel =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterViewModel(
|
||||
promotionFamilyRowsRenderState,
|
||||
{
|
||||
familyId: "virtual-hal-promotion-family-qtdragon-on-abort",
|
||||
sourceKind: "gcode",
|
||||
},
|
||||
);
|
||||
assert.equal(promotionFamilyRowsRenderState.ready, true);
|
||||
assert.equal(promotionFamilyRowsRenderState.statusLine, "Ready: 3 promotion families ready");
|
||||
assert.equal(promotionFamilyRowsRenderState.rows.length, 3);
|
||||
assert.equal(promotionFamilyRowsRenderState.sourceFileCount, 17);
|
||||
assert.equal(promotionFamilyRowsRenderState.sourceRows.length, 17);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.rows.find(({ id }) => id === "virtual-hal-promotion-family-qtdragon-on-abort")
|
||||
?.sourceKindSummary,
|
||||
"ini=6 gcode=6",
|
||||
);
|
||||
assert.deepEqual(
|
||||
promotionFamilyRowsRenderState.rows.find(({ id }) => id === "virtual-hal-promotion-family-vismach-remap-sims")
|
||||
?.sourceKindCounts,
|
||||
{ ini: 1, gcode: 1, "remap-subroutine": 1 },
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.rows.find(({ id }) => id === "virtual-hal-promotion-family-rose-engine-rcone-demo")
|
||||
?.sourceKindSummary,
|
||||
"ini=1 gcode=1",
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterViewModel.ready, true);
|
||||
assert.equal(promotionFamilySourceFilterViewModel.statusLine, "Ready: 17/17 source files selected");
|
||||
assert.equal(promotionFamilySourceFilterViewModel.filteredSourceFileCount, 17);
|
||||
assert.equal(promotionFamilySourceFilterViewModel.totalSourceFileCount, 17);
|
||||
assert.deepEqual(
|
||||
promotionFamilySourceFilterViewModel.familyFilters.map(({ id, count, selected }) => [id, count, selected]),
|
||||
[
|
||||
["all", 17, true],
|
||||
["virtual-hal-promotion-family-qtdragon-on-abort", 12, false],
|
||||
["virtual-hal-promotion-family-vismach-remap-sims", 3, false],
|
||||
["virtual-hal-promotion-family-rose-engine-rcone-demo", 2, false],
|
||||
],
|
||||
);
|
||||
assert.deepEqual(
|
||||
promotionFamilySourceFilterViewModel.sourceKindFilters.map(({ id, count, selected }) => [id, count, selected]),
|
||||
[
|
||||
["all", 17, true],
|
||||
["ini", 8, false],
|
||||
["gcode", 8, false],
|
||||
["remap-subroutine", 1, false],
|
||||
],
|
||||
);
|
||||
assert.equal(promotionFamilyRemapSourceFilterViewModel.selectedSourceKind, "remap-subroutine");
|
||||
assert.equal(promotionFamilyRemapSourceFilterViewModel.statusLine, "Ready: 1/17 source files selected");
|
||||
assert.equal(promotionFamilyRemapSourceFilterViewModel.familyRows.length, 1);
|
||||
assert.equal(
|
||||
promotionFamilyRemapSourceFilterViewModel.familyRows[0]?.id,
|
||||
"virtual-hal-promotion-family-vismach-remap-sims",
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRemapSourceFilterViewModel.sourceRows[0]?.value,
|
||||
"linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc",
|
||||
);
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.selectedFamilyId, "virtual-hal-promotion-family-qtdragon-on-abort");
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.selectedSourceKind, "gcode");
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.statusLine, "Ready: 6/17 source files selected");
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.scopedSourceFileCount, 12);
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.filteredSourceFileCount, 6);
|
||||
assert.equal(promotionFamilyQtDragonGcodeFilterViewModel.familyRows.length, 1);
|
||||
assert.equal(
|
||||
promotionFamilyQtDragonGcodeFilterViewModel.familyRows[0]?.sourceKindSummary,
|
||||
"gcode=6",
|
||||
);
|
||||
assert.deepEqual(
|
||||
promotionFamilyQtDragonGcodeFilterViewModel.sourceKindFilters.map(({ id, count, selected }) => [id, count, selected]),
|
||||
[
|
||||
["all", 12, false],
|
||||
["ini", 6, false],
|
||||
["gcode", 6, true],
|
||||
],
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyQtDragonGcodeFilterViewModel.sourceRows.every(({ familyId, sourceKind }) =>
|
||||
familyId === "virtual-hal-promotion-family-qtdragon-on-abort" &&
|
||||
sourceKind === "gcode"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract().selectors.mount,
|
||||
"[data-workflow-overview-promotion-family-source-filter]",
|
||||
);
|
||||
assert.equal(createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness().ready, false);
|
||||
const promotionFamilySourceFilterMountNode = mountDocument.createElement("section");
|
||||
promotionFamilySourceFilterMountNode.dataset.workflowOverviewPromotionFamilySourceFilter = "";
|
||||
const promotionFamilySourceFilterStatusNode = mountDocument.createElement("p");
|
||||
promotionFamilySourceFilterStatusNode.dataset.workflowOverviewPromotionFamilySourceFilterStatus = "";
|
||||
const promotionFamilySourceFilterControlsNode = {
|
||||
...mountDocument.createElement("div"),
|
||||
children: [],
|
||||
replaceChildren() {
|
||||
this.children = [];
|
||||
},
|
||||
append(...nodes) {
|
||||
this.children.push(...nodes);
|
||||
},
|
||||
};
|
||||
promotionFamilySourceFilterControlsNode.dataset.workflowOverviewPromotionFamilySourceFilterControls = "";
|
||||
const promotionFamilySourceFilterRowsNode = {
|
||||
...mountDocument.createElement("dl"),
|
||||
children: [],
|
||||
replaceChildren() {
|
||||
this.children = [];
|
||||
},
|
||||
append(...nodes) {
|
||||
this.children.push(...nodes);
|
||||
},
|
||||
};
|
||||
promotionFamilySourceFilterRowsNode.dataset.workflowOverviewPromotionFamilySourceFilterRows = "";
|
||||
const promotionFamilySourceFilterRenderResult =
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
|
||||
promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
{
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
},
|
||||
);
|
||||
const promotionFamilySourceFilterMountResult =
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState({
|
||||
viewModel: promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
});
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.rendered, true);
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.statusLine, "Ready: 6/17 source files selected");
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.controlCount, 2);
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.filterRowCount, 7);
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.sourceFileCount, 6);
|
||||
assert.equal(promotionFamilySourceFilterRenderResult.rowCount, 13);
|
||||
assert.deepEqual(promotionFamilySourceFilterRenderResult.dataset, {
|
||||
handoffPhase: "ready",
|
||||
handoffReady: "true",
|
||||
handoffScope: "workflow-overview-promotion-family-source-filter",
|
||||
selectedFamilyId: "virtual-hal-promotion-family-qtdragon-on-abort",
|
||||
selectedSourceKind: "gcode",
|
||||
});
|
||||
assert.equal(promotionFamilySourceFilterControlsNode.children.length, 4);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterControlsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterControl === "family" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterControlValue ===
|
||||
"virtual-hal-promotion-family-qtdragon-on-abort" &&
|
||||
node.textContent === "Family"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterControlsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelect === "source-kind" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterValue === "gcode" &&
|
||||
node.value === "gcode" &&
|
||||
node.children.some((option) =>
|
||||
option.value === "gcode" &&
|
||||
option.selected === true &&
|
||||
option.dataset?.workflowOverviewPromotionFamilySourceFilterCount === "6"
|
||||
)
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterValue ===
|
||||
"virtual-hal-promotion-family-qtdragon-on-abort" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterType === "family-filter" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelected === "true" &&
|
||||
node.textContent === "virtual-hal-promotion-family-qtdragon-on-abort: 12 selected"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterValue === "gcode" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterType === "source-kind-filter" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelected === "true" &&
|
||||
node.textContent === "gcode: 6 selected"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterType === "source-row" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterFamily ===
|
||||
"virtual-hal-promotion-family-qtdragon-on-abort" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSourceKind === "gcode" &&
|
||||
node.textContent === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterMountResult.ready, true);
|
||||
assert.equal(promotionFamilySourceFilterMountResult.renderResult.rowCount, 13);
|
||||
const promotionFamilySourceFilterSelectionActionPlan =
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan(
|
||||
promotionFamilyRowsRenderState,
|
||||
{
|
||||
familyId: "virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
sourceKind: "all",
|
||||
previousViewModel: promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
},
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterSelectionActionPlan.ready, true);
|
||||
assert.equal(promotionFamilySourceFilterSelectionActionPlan.changed, true);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterSelectionActionPlan.statusLine,
|
||||
"Ready: source filter changed to virtual-hal-promotion-family-rose-engine-rcone-demo / all",
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterSelectionActionPlan.nextViewModel.statusLine,
|
||||
"Ready: 2/17 source files selected",
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterSelectionActionPlan.nextViewModel.filteredSourceFileCount, 2);
|
||||
assert.equal(promotionFamilySourceFilterSelectionActionPlan.nextViewModel.scopedSourceFileCount, 2);
|
||||
const sourceFilterFamilySelect = promotionFamilySourceFilterControlsNode.children.find((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelect === "family"
|
||||
);
|
||||
const sourceFilterKindSelect = promotionFamilySourceFilterControlsNode.children.find((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelect === "source-kind"
|
||||
);
|
||||
sourceFilterFamilySelect.value = "virtual-hal-promotion-family-rose-engine-rcone-demo";
|
||||
sourceFilterKindSelect.value = "all";
|
||||
const promotionFamilySourceFilterSelectionChange =
|
||||
handleIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionChange({
|
||||
renderState: promotionFamilyRowsRenderState,
|
||||
viewModel: promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
render: true,
|
||||
});
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.ready, true);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterSelectionChange.selectedFamilyId,
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.selectedSourceKind, "all");
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.actionPlan.changed, true);
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.viewModel.filteredSourceFileCount, 2);
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.renderResult.sourceFileCount, 2);
|
||||
assert.equal(promotionFamilySourceFilterSelectionChange.renderResult.dataset.selectedSourceKind, "all");
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterType === "source-row" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterFamily ===
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo" &&
|
||||
node.textContent === "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilySourceFilterState(
|
||||
promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
{
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
},
|
||||
);
|
||||
let promotionFamilySourceFilterBindingLastChange = null;
|
||||
const promotionFamilySourceFilterSelectionBinding =
|
||||
bindIniPanelShellWorkflowOverviewPromotionFamilySourceFilterSelectionControls({
|
||||
renderState: promotionFamilyRowsRenderState,
|
||||
viewModel: promotionFamilyQtDragonGcodeFilterViewModel,
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
render: true,
|
||||
onChange: (changeResult) => {
|
||||
promotionFamilySourceFilterBindingLastChange = changeResult;
|
||||
},
|
||||
});
|
||||
assert.equal(promotionFamilySourceFilterSelectionBinding.ready, true);
|
||||
assert.equal(promotionFamilySourceFilterSelectionBinding.boundControlCount, 2);
|
||||
assert.deepEqual(promotionFamilySourceFilterSelectionBinding.controlIds, ["family", "source-kind"]);
|
||||
const boundSourceFilterFamilySelect = promotionFamilySourceFilterControlsNode.children.find((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelect === "family"
|
||||
);
|
||||
const boundSourceFilterKindSelect = promotionFamilySourceFilterControlsNode.children.find((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceFilterSelect === "source-kind"
|
||||
);
|
||||
boundSourceFilterFamilySelect.value = "virtual-hal-promotion-family-rose-engine-rcone-demo";
|
||||
boundSourceFilterKindSelect.value = "all";
|
||||
const promotionFamilySourceFilterBoundChange = boundSourceFilterFamilySelect.dispatchEvent("change");
|
||||
assert.equal(promotionFamilySourceFilterBoundChange.ready, true);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterBoundChange.selectedFamilyId,
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterBoundChange.renderResult.sourceFileCount, 2);
|
||||
assert.equal(
|
||||
promotionFamilySourceFilterBindingLastChange.selectedFamilyId,
|
||||
"virtual-hal-promotion-family-rose-engine-rcone-demo",
|
||||
);
|
||||
assert.equal(promotionFamilySourceFilterSelectionBinding.lastChange.selectedSourceKind, "all");
|
||||
assert.deepEqual(promotionFamilySourceFilterSelectionBinding.unbind(), { unbound: 2 });
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ value }) =>
|
||||
value === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) =>
|
||||
sourceKind === "ini" &&
|
||||
manifestBacked === true &&
|
||||
status === "manifest-backed" &&
|
||||
value === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) =>
|
||||
sourceKind === "gcode" &&
|
||||
manifestBacked === true &&
|
||||
status === "manifest-backed" &&
|
||||
value === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ value }) =>
|
||||
value === "linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ sourceKind, manifestBacked, status, value }) =>
|
||||
sourceKind === "remap-subroutine" &&
|
||||
manifestBacked === true &&
|
||||
status === "manifest-backed" &&
|
||||
value === "linuxcnc/configs/sim/axis/vismach/puma/remap_subs/428remap.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsRenderState.sourceRows.some(({ value }) =>
|
||||
value === "linuxcnc/configs/sim/axis/rose_engine/rcone_demo.ngc"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract().selectors.mount,
|
||||
"[data-workflow-overview-promotion-family-rows]",
|
||||
);
|
||||
assert.equal(createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomReadiness().ready, false);
|
||||
const promotionFamilyRowsMountNode = mountDocument.createElement("section");
|
||||
promotionFamilyRowsMountNode.dataset.workflowOverviewPromotionFamilyRows = "";
|
||||
const promotionFamilyRowsStatusNode = mountDocument.createElement("p");
|
||||
promotionFamilyRowsStatusNode.dataset.workflowOverviewPromotionFamilyRowsStatus = "";
|
||||
const promotionFamilyRowsNode = {
|
||||
...mountDocument.createElement("dl"),
|
||||
children: [],
|
||||
replaceChildren() {
|
||||
this.children = [];
|
||||
},
|
||||
append(...nodes) {
|
||||
this.children.push(...nodes);
|
||||
},
|
||||
};
|
||||
promotionFamilyRowsNode.dataset.workflowOverviewPromotionFamilyRowList = "";
|
||||
const promotionFamilyRowsRenderResult =
|
||||
renderIniPanelShellWorkflowOverviewPromotionFamilyRowsState(
|
||||
promotionFamilyRowsRenderState,
|
||||
{
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilyRowsMountNode,
|
||||
statusNode: promotionFamilyRowsStatusNode,
|
||||
rowsNode: promotionFamilyRowsNode,
|
||||
},
|
||||
);
|
||||
const promotionFamilyRowsMountResult =
|
||||
mountIniPanelShellWorkflowOverviewPromotionFamilyRowsState({
|
||||
renderState: promotionFamilyRowsRenderState,
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilyRowsMountNode,
|
||||
statusNode: promotionFamilyRowsStatusNode,
|
||||
rowsNode: promotionFamilyRowsNode,
|
||||
});
|
||||
assert.equal(promotionFamilyRowsRenderResult.rendered, true);
|
||||
assert.equal(promotionFamilyRowsRenderResult.rowCount, 20);
|
||||
assert.deepEqual(promotionFamilyRowsRenderResult.rowIds, expectedPromotionFamilyRows.map(([id]) => id));
|
||||
assert.equal(promotionFamilyRowsRenderResult.sourceFileCount, 17);
|
||||
assert.equal(
|
||||
promotionFamilyRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilyValue ===
|
||||
"virtual-hal-promotion-family-qtdragon-on-abort" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceKindCounts === "ini=6 gcode=6" &&
|
||||
node.textContent === "6/6 ready; sources=12; diagnostics=ready; ini=6 gcode=6"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
promotionFamilyRowsNode.children.some((node) =>
|
||||
node.dataset?.workflowOverviewPromotionFamilyValue ===
|
||||
"virtual-hal-promotion-family-qtdragon-on-abort-source-1" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceKind === "ini" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilyManifestBacked === "true" &&
|
||||
node.dataset?.workflowOverviewPromotionFamilySourceStatus === "manifest-backed" &&
|
||||
node.textContent === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(promotionFamilyRowsMountResult.ready, true);
|
||||
assert.equal(promotionFamilyRowsMountResult.renderResult.rowCount, 20);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "saved-session-diagnostics")?.value,
|
||||
"ready",
|
||||
@@ -1905,7 +2565,7 @@ const releaseArtifactUrlWorkflowMountResult =
|
||||
rowsNode: releaseArtifactUrlWorkflowRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 12);
|
||||
assert.equal(releaseArtifactUrlWorkflowRenderResult.rowCount, 22);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("browser-diagnostics"),
|
||||
true,
|
||||
@@ -1914,12 +2574,16 @@ assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("saved-session-diagnostics"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("virtual-hal-promotion-families"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("mount-result"),
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 12);
|
||||
assert.equal(releaseArtifactUrlWorkflowMountResult.renderResult.rowCount, 22);
|
||||
const releaseArtifactUrlWorkflowMissingDom = await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
|
||||
artifactUrl: "/project-release-readiness.json",
|
||||
fetchRef: async () => ({
|
||||
@@ -1978,6 +2642,39 @@ const workflowOverviewApi = {
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel: () => releaseArtifactUrlWorkflowSummary,
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowActionPlan: () => releaseArtifactUrlWorkflow.actionPlan,
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowRenderState: () => releaseArtifactUrlWorkflowRenderState,
|
||||
getWorkflowOverviewPromotionFamilyRowsRenderState: () => promotionFamilyRowsRenderState,
|
||||
getWorkflowOverviewPromotionFamilySourceFilterViewModel: () => promotionFamilySourceFilterViewModel,
|
||||
getWorkflowOverviewPromotionFamilySourceFilterDomContract:
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomContract,
|
||||
getWorkflowOverviewPromotionFamilySourceFilterDomReadiness: () => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilySourceFilterDomReadiness({
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilySourceFilterMountNode,
|
||||
statusNode: promotionFamilySourceFilterStatusNode,
|
||||
controlsNode: promotionFamilySourceFilterControlsNode,
|
||||
rowsNode: promotionFamilySourceFilterRowsNode,
|
||||
})
|
||||
),
|
||||
getWorkflowOverviewPromotionFamilySourceFilterSelectionActionPlan: () =>
|
||||
promotionFamilySourceFilterSelectionActionPlan,
|
||||
handleWorkflowOverviewPromotionFamilySourceFilterSelectionChange: () =>
|
||||
promotionFamilySourceFilterSelectionChange,
|
||||
bindWorkflowOverviewPromotionFamilySourceFilterSelectionControls: () =>
|
||||
promotionFamilySourceFilterSelectionBinding,
|
||||
renderWorkflowOverviewPromotionFamilySourceFilterState: () => promotionFamilySourceFilterRenderResult,
|
||||
mountWorkflowOverviewPromotionFamilySourceFilterState: () => promotionFamilySourceFilterMountResult,
|
||||
getWorkflowOverviewPromotionFamilyRowsDomContract:
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomContract,
|
||||
getWorkflowOverviewPromotionFamilyRowsDomReadiness: () => (
|
||||
createIniPanelShellWorkflowOverviewPromotionFamilyRowsDomReadiness({
|
||||
documentRef: mountDocument,
|
||||
mountNode: promotionFamilyRowsMountNode,
|
||||
statusNode: promotionFamilyRowsStatusNode,
|
||||
rowsNode: promotionFamilyRowsNode,
|
||||
})
|
||||
),
|
||||
renderWorkflowOverviewPromotionFamilyRowsState: () => promotionFamilyRowsRenderResult,
|
||||
mountWorkflowOverviewPromotionFamilyRowsState: () => promotionFamilyRowsMountResult,
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract:
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomContract,
|
||||
getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowDomReadiness: () => (
|
||||
|
||||
@@ -4,6 +4,7 @@ import { basename, dirname, posix, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
|
||||
analyzeIniRuntimeBoundaries,
|
||||
createLinuxCncInterpSdk,
|
||||
planSimConfigStaging,
|
||||
@@ -100,6 +101,7 @@ const runtimeBoundaryNativeAlignmentSummaryPath = resolve(buildDir, "runtime-bou
|
||||
const runtimeProbeGateAlignmentPath = resolve(buildDir, "runtime-probe-gate-alignment.tsv");
|
||||
const nativeRuntimeProbeExecutionPlanPath = resolve(buildDir, "native-runtime-probe-execution-plan.tsv");
|
||||
const nativeRuntimeProbePassEvidenceContractPath = resolve(buildDir, "native-runtime-probe-pass-evidence-contract.tsv");
|
||||
const promotionCandidatesPath = resolve(buildDir, "promotion-candidates.tsv");
|
||||
const blockedRuntimePromotionLockPath = resolve(buildDir, "blocked-runtime-promotion-lock.tsv");
|
||||
const runtimeBoundaryPromotionReadinessPath = resolve(buildDir, "runtime-boundary-promotion-readiness.tsv");
|
||||
const runtimeBoundaryPromotionBlockersPath = resolve(buildDir, "runtime-boundary-promotion-blockers.tsv");
|
||||
@@ -155,6 +157,7 @@ const generatedSimConfigInventoryArtifactPaths = [
|
||||
runtimeProbeGateAlignmentPath,
|
||||
nativeRuntimeProbeExecutionPlanPath,
|
||||
nativeRuntimeProbePassEvidenceContractPath,
|
||||
promotionCandidatesPath,
|
||||
blockedRuntimePromotionLockPath,
|
||||
runtimeBoundaryPromotionReadinessPath,
|
||||
runtimeBoundaryPromotionBlockersPath,
|
||||
@@ -6087,7 +6090,7 @@ function verifyBoundaryPhaseCompletionSummaryRows(rows) {
|
||||
const rowByCriterion = new Map(parsedRows.map((row) => [row.criterion, row]));
|
||||
assert.equal(
|
||||
rowByCriterion.get("wasm_inventory_artifact_documentation_coverage")?.count,
|
||||
"54",
|
||||
"55",
|
||||
"WASM artifact documentation completion count must match generated artifact baseline",
|
||||
);
|
||||
assert.equal(
|
||||
@@ -8609,7 +8612,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
);
|
||||
assert.equal(
|
||||
artifactNames.length,
|
||||
54,
|
||||
55,
|
||||
"generated sim-config inventory artifact list count drift",
|
||||
);
|
||||
assert.deepEqual(
|
||||
@@ -8628,6 +8631,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
"native-runtime-probe-summary.tsv",
|
||||
"next-boundary-recommendations.tsv",
|
||||
"next-boundary-worklist.tsv",
|
||||
"promotion-candidates.tsv",
|
||||
"python-remap-boundary-summary.tsv",
|
||||
"python-remap-family-summary.tsv",
|
||||
"python-remap-native-runtime-alignment.tsv",
|
||||
@@ -8703,7 +8707,7 @@ function verifyGeneratedArtifactDocumentationCoverage({
|
||||
"generated sim-config inventory artifacts must be listed in browser smoke",
|
||||
);
|
||||
assert.ok(
|
||||
browserSmokeText.includes("wasmArtifactNames.length !== 54"),
|
||||
browserSmokeText.includes("wasmArtifactNames.length !== 55"),
|
||||
"browser smoke must keep generated WASM artifact fixed-count guard",
|
||||
);
|
||||
assert.ok(
|
||||
@@ -11946,6 +11950,198 @@ function verifyHardBlockedInventorySkips(rows, pathMatrixByPath) {
|
||||
}
|
||||
}
|
||||
|
||||
function sourcePathToInventoryPath(sourcePath) {
|
||||
const prefix = "linuxcnc/configs/sim/";
|
||||
return sourcePath.startsWith(prefix) ? sourcePath.slice(prefix.length) : "";
|
||||
}
|
||||
|
||||
function promotionCandidateRows({
|
||||
summaryRows,
|
||||
boundaryRows,
|
||||
nextBoundaryRecords,
|
||||
trackedMatrixByPath,
|
||||
nativeByPath,
|
||||
}) {
|
||||
const summaryByPath = new Map(summaryRows.map((row) => {
|
||||
const [
|
||||
path,
|
||||
inventoryStatus,
|
||||
reason,
|
||||
className,
|
||||
nativeStatus,
|
||||
nativeExpectedFailure,
|
||||
] = row.split("\t");
|
||||
return [path, {
|
||||
path,
|
||||
inventoryStatus,
|
||||
reason,
|
||||
className,
|
||||
nativeStatus,
|
||||
nativeExpectedFailure,
|
||||
}];
|
||||
}));
|
||||
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
|
||||
const nextBoundaryByBlocked = new Map(nextBoundaryRecords.map((row) => [row.blocked, row]));
|
||||
|
||||
const evidenceReadyRows = VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES.map((candidate) => {
|
||||
const inventoryPath = sourcePathToInventoryPath(candidate.gcodePath);
|
||||
const summary = summaryByPath.get(inventoryPath);
|
||||
const matrix = trackedMatrixByPath.get(inventoryPath);
|
||||
const native = nativeByPath.get(inventoryPath);
|
||||
const boundary = boundaryByPath.get(inventoryPath);
|
||||
const virtualHalEvidenceReady = candidate.currentNodeInventoryStatus === "PASS" &&
|
||||
candidate.currentMatrixBrowserStatus === "explicit-browser-diagnostics" &&
|
||||
candidate.targetBrowserEvidence === "explicit-browser-diagnostics" &&
|
||||
candidate.blockedKind === "-" &&
|
||||
summary?.inventoryStatus === "PASS";
|
||||
return [
|
||||
"evidence-ready",
|
||||
candidate.id,
|
||||
inventoryPath,
|
||||
sourcePathToInventoryPath(candidate.iniPath),
|
||||
summary?.inventoryStatus ?? "-",
|
||||
summary?.reason ?? "-",
|
||||
matrix?.layer4Node ?? "-",
|
||||
matrix?.layer4Browser ?? "-",
|
||||
summary?.className ?? native?.class ?? "-",
|
||||
summary?.nativeStatus ?? native?.status ?? "-",
|
||||
summary?.nativeExpectedFailure ?? native?.expected_failure ?? "-",
|
||||
matrix?.blocked ?? candidate.blockedKind ?? "-",
|
||||
candidate.dependencyClass,
|
||||
flagValue(virtualHalEvidenceReady),
|
||||
"0",
|
||||
virtualHalEvidenceReady ? "browser_release_evidence_ready_inventory_baseline_unchanged" : "virtual_hal_evidence_incomplete",
|
||||
"wasm-port/tests/sdk/node/verify_sdk_surface.sh && wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh",
|
||||
].map(tsvValue).join("\t");
|
||||
});
|
||||
|
||||
const inventoryReadyRows = [...summaryByPath.values()]
|
||||
.filter((row) => row.className === "main" && row.inventoryStatus === "SKIP")
|
||||
.sort((left, right) => left.path.localeCompare(right.path))
|
||||
.map((row) => {
|
||||
const boundary = boundaryByPath.get(row.path);
|
||||
const matrix = trackedMatrixByPath.get(row.path);
|
||||
const boundaryWork = nextBoundaryByBlocked.get(row.reason);
|
||||
const promotionAllowed = row.reason === "-" &&
|
||||
boundary?.recommended_blocked === "-" &&
|
||||
row.nativeStatus === "PASS";
|
||||
const blockReason = promotionAllowed
|
||||
? "-"
|
||||
: (boundaryWork?.next_action ?? `blocked_by_${row.reason}`);
|
||||
const recommendedNextCommand = promotionAllowed
|
||||
? "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh"
|
||||
: (boundaryWork?.required_native_proof ?? "no_direct_baseline_promotion_candidate");
|
||||
return [
|
||||
"inventory-ready",
|
||||
row.path,
|
||||
row.path,
|
||||
boundary?.ini ?? "-",
|
||||
row.inventoryStatus,
|
||||
row.reason,
|
||||
matrix?.layer4Node ?? "-",
|
||||
matrix?.layer4Browser ?? "-",
|
||||
row.className,
|
||||
row.nativeStatus,
|
||||
row.nativeExpectedFailure,
|
||||
matrix?.blocked ?? row.reason,
|
||||
boundary?.dependencies ?? "-",
|
||||
"0",
|
||||
flagValue(promotionAllowed),
|
||||
blockReason,
|
||||
recommendedNextCommand,
|
||||
].map(tsvValue).join("\t");
|
||||
});
|
||||
|
||||
return [...evidenceReadyRows, ...inventoryReadyRows];
|
||||
}
|
||||
|
||||
function verifyPromotionCandidateRows(rows, summaryRows, boundaryRows) {
|
||||
const expectedHeaders = [
|
||||
"candidate_kind",
|
||||
"candidate_id",
|
||||
"path",
|
||||
"ini",
|
||||
"current_status",
|
||||
"skip_kind",
|
||||
"matrix_layer4_node",
|
||||
"matrix_layer4_browser",
|
||||
"class",
|
||||
"native_status",
|
||||
"native_expected_failure",
|
||||
"blocked_kind",
|
||||
"dependency_class",
|
||||
"virtual_hal_evidence_ready",
|
||||
"promotion_allowed",
|
||||
"block_reason",
|
||||
"recommended_next_command",
|
||||
];
|
||||
const parsedRows = parseTsv(
|
||||
`${expectedHeaders.join("\t")}\n${rows.join("\n")}\n`,
|
||||
expectedHeaders,
|
||||
);
|
||||
const expectedSkippedMain = summaryRows
|
||||
.map((row) => {
|
||||
const [path, inventoryStatus, reason, className] = row.split("\t");
|
||||
return { path, inventoryStatus, reason, className };
|
||||
})
|
||||
.filter((row) => row.inventoryStatus === "SKIP" && row.className === "main")
|
||||
.map((row) => row.path)
|
||||
.sort();
|
||||
const evidenceReadyPaths = VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES
|
||||
.map((candidate) => sourcePathToInventoryPath(candidate.gcodePath))
|
||||
.sort();
|
||||
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
|
||||
const parsedEvidenceReady = parsedRows.filter((row) => row.candidate_kind === "evidence-ready");
|
||||
const parsedInventoryReady = parsedRows.filter((row) => row.candidate_kind === "inventory-ready");
|
||||
|
||||
assert.deepEqual(
|
||||
parsedEvidenceReady.map((row) => row.path).sort(),
|
||||
evidenceReadyPaths,
|
||||
"promotion-candidates must cover virtual HAL evidence-ready rows",
|
||||
);
|
||||
assert.deepEqual(
|
||||
parsedInventoryReady.map((row) => row.path).sort(),
|
||||
expectedSkippedMain,
|
||||
"promotion-candidates must cover every skipped main inventory candidate row",
|
||||
);
|
||||
assert.equal(
|
||||
parsedInventoryReady.filter((row) => row.promotion_allowed === "1").length,
|
||||
0,
|
||||
"current baseline has no direct skipped-main inventory promotion candidate",
|
||||
);
|
||||
for (const row of parsedEvidenceReady) {
|
||||
assert.equal(row.current_status, "PASS", `${row.path}: evidence-ready row must be a current inventory PASS`);
|
||||
assert.equal(row.skip_kind, "-", `${row.path}: evidence-ready row must not have a skip kind`);
|
||||
assert.equal(row.blocked_kind, "-", `${row.path}: evidence-ready row must not be hard-blocked`);
|
||||
assert.equal(row.virtual_hal_evidence_ready, "1", `${row.path}: evidence-ready row lacks virtual HAL evidence`);
|
||||
assert.equal(row.promotion_allowed, "0", `${row.path}: evidence-ready row must not claim inventory promotion`);
|
||||
assert.equal(row.matrix_layer4_node, "INV", `${row.path}: evidence-ready row should remain Node INV`);
|
||||
assert.equal(row.matrix_layer4_browser, "-", `${row.path}: evidence-ready row should record explicit diagnostics outside matrix browser REP`);
|
||||
assert.equal(row.block_reason, "browser_release_evidence_ready_inventory_baseline_unchanged");
|
||||
assert.ok(
|
||||
row.recommended_next_command.includes("verify_sdk_surface.sh"),
|
||||
`${row.path}: evidence-ready row lacks virtual HAL gate command`,
|
||||
);
|
||||
}
|
||||
for (const row of parsedInventoryReady) {
|
||||
assert.equal(row.current_status, "SKIP", `${row.path}: promotion candidate status drift`);
|
||||
assert.equal(row.class, "main", `${row.path}: promotion candidate must be main class`);
|
||||
assert.equal(row.blocked_kind, row.skip_kind, `${row.path}: skipped inventory blocked kind drift`);
|
||||
assert.equal(row.virtual_hal_evidence_ready, "0", `${row.path}: skipped inventory row must not claim virtual HAL evidence ready`);
|
||||
assert.ok(
|
||||
["L4-PYTHON-REMAP", "L4-TOOL-DB", "L4-USER-M-PROCESS", "UPSTREAM-DEMO"].includes(row.skip_kind),
|
||||
`${row.path}: direct promotion candidate must remain hard-blocked or upstream-demo`,
|
||||
);
|
||||
const boundary = boundaryByPath.get(row.path);
|
||||
assert.ok(boundary, `${row.path}: promotion candidate lacks boundary evidence`);
|
||||
if (row.skip_kind.startsWith("L4-")) {
|
||||
assert.notEqual(row.recommended_next_command, "-", `${row.path}: blocked row lacks next proof command`);
|
||||
assert.notEqual(row.block_reason, "-", `${row.path}: blocked row lacks block reason`);
|
||||
}
|
||||
}
|
||||
return parsedRows;
|
||||
}
|
||||
|
||||
for (const record of nativeRecords) {
|
||||
const skipReason = blockedKind(record, pathMatrixByPath);
|
||||
if (skipReason) {
|
||||
@@ -12425,6 +12621,44 @@ writeFileSync(
|
||||
].join("\n")}\n`,
|
||||
);
|
||||
|
||||
const promotionCandidateRowsGenerated = promotionCandidateRows({
|
||||
summaryRows,
|
||||
boundaryRows: boundarySummaryRecords,
|
||||
nextBoundaryRecords,
|
||||
trackedMatrixByPath,
|
||||
nativeByPath: new Map(nativeRecords.map((record) => [record.path, record])),
|
||||
});
|
||||
verifyPromotionCandidateRows(
|
||||
promotionCandidateRowsGenerated,
|
||||
summaryRows,
|
||||
boundarySummaryRecords,
|
||||
);
|
||||
writeFileSync(
|
||||
promotionCandidatesPath,
|
||||
`${[
|
||||
[
|
||||
"candidate_kind",
|
||||
"candidate_id",
|
||||
"path",
|
||||
"ini",
|
||||
"current_status",
|
||||
"skip_kind",
|
||||
"matrix_layer4_node",
|
||||
"matrix_layer4_browser",
|
||||
"class",
|
||||
"native_status",
|
||||
"native_expected_failure",
|
||||
"blocked_kind",
|
||||
"dependency_class",
|
||||
"virtual_hal_evidence_ready",
|
||||
"promotion_allowed",
|
||||
"block_reason",
|
||||
"recommended_next_command",
|
||||
].join("\t"),
|
||||
...promotionCandidateRowsGenerated,
|
||||
].join("\n")}\n`,
|
||||
);
|
||||
|
||||
writeFileSync(
|
||||
boundarySummaryPath,
|
||||
`${[
|
||||
|
||||
Reference in New Issue
Block a user