按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:
2026-06-18 17:20:29 +08:00
parent 014081f1f9
commit 1c94ea4527
29 changed files with 8500 additions and 121 deletions

View File

@@ -79,6 +79,59 @@ const DEFAULT_SIM_CONFIG_INVENTORY_BASELINE = {
unexpectedFail: 0,
};
const DEFAULT_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = {
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
"de6cf57b7c07182e3bcb32e22dbdf202b618cabc14620d6dff1ef815587950b9",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
"b0afe27224e97a82fbecbbd75a7c86233c98fe957d9c1ba20f0656f8745a5eae",
};
function isBoundaryEvidenceBaselineFresh(boundaryEvidence = {}) {
const baseline = objectOrEmpty(boundaryEvidence.baselineSummary);
const hashes = objectOrEmpty(boundaryEvidence.sourceArtifactHashes);
return baseline.executed === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.executed &&
baseline.passed === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.passed &&
baseline.skipped === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.skipped &&
baseline.unexpectedFail === DEFAULT_SIM_CONFIG_INVENTORY_BASELINE.unexpectedFail &&
Object.entries(DEFAULT_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
.every(([artifactPath, expectedHash]) => hashes[artifactPath] === expectedHash);
}
function createPromotionFamilySummaryText(candidateReport = {}) {
const families = arrayOrEmpty(objectOrEmpty(candidateReport).familyRows);
if (families.length === 0) {
return "not provided";
}
return families.map((family) => {
const label = family.id ?? "unknown";
const completeCount = family.completeCount ?? 0;
const candidateCount = family.candidateCount ?? 0;
const state = family.complete === true && family.explicitBrowserDiagnosticsReady === true ? "ready" : "blocked";
return `${label}: ${completeCount}/${candidateCount} ${state}`;
}).join("; ");
}
function createPromotionFamilySummaryRows(candidateReport = {}) {
return arrayOrEmpty(objectOrEmpty(candidateReport).familyRows).map((family) => {
const sourceFileCount = arrayOrEmpty(family.sourceFiles).length;
const candidateCount = family.candidateCount ?? 0;
const completeCount = family.completeCount ?? 0;
const explicitBrowserDiagnosticsReady = family.explicitBrowserDiagnosticsReady === true;
const ready = family.complete === true && explicitBrowserDiagnosticsReady;
return {
id: family.id ?? "unknown",
label: family.id ?? "Unknown promotion family",
value: `${completeCount}/${candidateCount} ${ready ? "ready" : "blocked"}; sources=${sourceFileCount}; diagnostics=${explicitBrowserDiagnosticsReady ? "ready" : "blocked"}`,
sourceFiles: arrayOrEmpty(family.sourceFiles),
candidateCount,
completeCount,
sourceFileCount,
explicitBrowserDiagnosticsReady,
ready,
};
});
}
const BLOCKED_RUNTIME_FAMILIES = [
"L4-USER-M-PROCESS",
"L4-TOOL-DB",
@@ -152,6 +205,12 @@ const REQUIRED_MACRO_LOAD_FIXTURES = [
{
id: "rose-engine-rcone-macro-load",
fixturePath: "linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
declarationEvidence: {
sourceFile: "linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
key: "NGCGUI_SUBFILE",
value: "rcone.ngc",
line: 34,
},
sourceFiles: [
"linuxcnc/configs/sim/axis/rose_engine/rose_engine.ini",
"linuxcnc/configs/sim/axis/rose_engine/rcone.ngc",
@@ -161,6 +220,12 @@ const REQUIRED_MACRO_LOAD_FIXTURES = [
{
id: "external-offsets-queuebuster-macro-load",
fixturePath: "linuxcnc/configs/sim/axis/external_offsets/queuebuster.ngc",
declarationEvidence: {
sourceFile: "linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
key: "NGCGUI_SUBFILE",
value: "queuebuster.ngc",
line: 40,
},
sourceFiles: [
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ini",
"linuxcnc/configs/sim/axis/external_offsets/eoffsets.ngc",
@@ -181,6 +246,19 @@ const REQUIRED_BLOCKED_MACRO_LOAD_FIXTURES = [
},
];
const REQUIRED_MACRO_LOAD_AUDIT_CANDIDATES = [
{
id: "gscreen-industrial-lathe-wear-toolchange-audit",
fixturePath: "linuxcnc/configs/sim/gscreen/industrial_lathe_wear/toolchange.ngc",
auditStatus: "blocked-missing-owning-ini",
},
{
id: "qtvcp-industrial-lathe-wear-toolchange-audit",
fixturePath: "linuxcnc/configs/sim/qtvcp_screens/industrial_lathe_wear/toolchange.ngc",
auditStatus: "blocked-missing-owning-ini",
},
];
function isVirtualHalSimConfigSourceCoverageReady(report) {
const coverage = objectOrEmpty(report);
return coverage.apiName === "linuxcnc-wasm-virtual-hal-sim-config-source-coverage-report" &&
@@ -218,8 +296,14 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
fixtureReport.inventoryBaselineUnchanged === true &&
arrayOrEmpty(fixtureReport.missingFixtures).length === 0 &&
arrayOrEmpty(fixtureReport.blockedFixtureIds).length === 0 &&
arrayOrEmpty(fixtureReport.declarationEvidenceViolations).length === 0 &&
arrayOrEmpty(fixtureReport.standaloneMainViolations).length === 0 &&
arrayOrEmpty(fixtureReport.blockedFixturePromotionViolations).length === 0 &&
arrayOrEmpty(fixtureReport.blockedBoundaryEvidenceViolations).length === 0 &&
arrayOrEmpty(fixtureReport.missingAuditRows).length === 0 &&
arrayOrEmpty(fixtureReport.auditPromotionViolations).length === 0 &&
arrayOrEmpty(fixtureReport.auditBoundaryEvidenceViolations).length === 0 &&
arrayOrEmpty(fixtureReport.auditPromotionAllowedViolations).length === 0 &&
arrayOrEmpty(fixtureReport.missingManifestFiles).length === 0 &&
REQUIRED_MACRO_LOAD_FIXTURES.every((fixture) =>
rows.some((row) =>
@@ -228,6 +312,16 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
row.nonMainFixture === true &&
row.targetBrowserEvidence === "non-main-fixture-diagnostics" &&
row.fixturePath === fixture.fixturePath &&
(
!fixture.declarationEvidence ||
(
row.declarationEvidenceReady === true &&
objectOrEmpty(row.declarationEvidence).sourceFile === fixture.declarationEvidence.sourceFile &&
objectOrEmpty(row.declarationEvidence).key === fixture.declarationEvidence.key &&
objectOrEmpty(row.declarationEvidence).value === fixture.declarationEvidence.value &&
objectOrEmpty(row.declarationEvidence).line === fixture.declarationEvidence.line
)
) &&
fixture.sourceFiles.every((file) => arrayOrEmpty(row.sourceFiles).includes(file))
)
) &&
@@ -237,6 +331,28 @@ function isVirtualHalSimConfigMacroLoadFixtureReportReady(report) {
row.fixturePath === fixture.fixturePath &&
row.blockedKind === fixture.blockedKind &&
row.excludedFromPositiveFixtures === true &&
row.boundaryEvidenceReady === true &&
isBoundaryEvidenceBaselineFresh(row.boundaryEvidence) &&
objectOrEmpty(row.boundaryEvidence?.boundarySummary).recommendedBlocked === "UNAVAILABLE" &&
String(objectOrEmpty(row.boundaryEvidence?.boundarySummary).dependencies ?? "").includes("missing_vendored_ini:") &&
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).vendored === 0 &&
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).reportAvailable === 0 &&
row.complete === true
)
) &&
REQUIRED_MACRO_LOAD_AUDIT_CANDIDATES.every((candidate) =>
arrayOrEmpty(fixtureReport.auditRows).some((row) =>
row.id === candidate.id &&
row.fixturePath === candidate.fixturePath &&
row.auditStatus === candidate.auditStatus &&
row.promotionAllowed === false &&
row.excludedFromPositiveFixtures === true &&
row.boundaryEvidenceReady === true &&
isBoundaryEvidenceBaselineFresh(row.boundaryEvidence) &&
objectOrEmpty(row.boundaryEvidence?.boundarySummary).recommendedBlocked === "UNAVAILABLE" &&
String(objectOrEmpty(row.boundaryEvidence?.boundarySummary).dependencies ?? "").includes("missing_vendored_ini:") &&
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).vendored === 0 &&
objectOrEmpty(row.boundaryEvidence?.iniBoundarySummary).reportAvailable === 0 &&
row.complete === true
)
);
@@ -277,6 +393,23 @@ function isVirtualHalSimConfigPromotionCandidateReportReady(report) {
hasRequiredPromotionCandidates(rows);
}
function isVirtualHalPromotionCandidateSummaryReady(summary) {
const summaryObject = objectOrEmpty(summary);
return summaryObject.apiName === "real-browser-simulation-promotion-candidate-summary" &&
summaryObject.ready === true &&
summaryObject.phase === "ready" &&
summaryObject.candidateCount === 8 &&
summaryObject.readyCandidateCount === 8 &&
summaryObject.familyCount === 3 &&
summaryObject.sourceFileCount === 17 &&
summaryObject.preferredCandidateId === "qtdragon-multi-joint-on-abort" &&
summaryObject.preferredIniPath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" &&
summaryObject.preferredGcodePath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc" &&
summaryObject.explicitBrowserDiagnosticsCount === 8 &&
summaryObject.inventoryBaseline === "executed=28 passed=28 skipped=131 unexpected_fail=0" &&
arrayOrEmpty(summaryObject.blockedCandidateIds).length === 0;
}
export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifact = {}) {
const artifactObject = objectOrEmpty(artifact);
const sourceCompliance = objectOrEmpty(artifactObject.virtualHalSourceCompliance);
@@ -284,6 +417,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
const commandScriptFixtures = objectOrEmpty(artifactObject.virtualHalCommandScriptFixtures);
const motionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
const promotionCandidates = objectOrEmpty(artifactObject.virtualHalSimConfigPromotionCandidates);
const promotionCandidateSummary = objectOrEmpty(artifactObject.virtualHalPromotionCandidateSummary);
const macroLoadFixtures = objectOrEmpty(artifactObject.virtualHalSimConfigMacroLoadFixtures);
const sessionDiagnostics = objectOrEmpty(artifactObject.virtualHalSessionDiagnostics);
const replacement = objectOrEmpty(artifactObject.virtualHalSimulationReplacement);
@@ -301,6 +435,9 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
const hasPromotionCandidates = artifactObject.virtualHalSimConfigPromotionCandidates !== undefined;
const promotionCandidatesReady = !hasPromotionCandidates ||
isVirtualHalSimConfigPromotionCandidateReportReady(promotionCandidates);
const hasPromotionCandidateSummary = artifactObject.virtualHalPromotionCandidateSummary !== undefined;
const promotionCandidateSummaryReady = hasPromotionCandidateSummary &&
isVirtualHalPromotionCandidateSummaryReady(promotionCandidateSummary);
const hasMacroLoadFixtures = artifactObject.virtualHalSimConfigMacroLoadFixtures !== undefined;
const macroLoadFixturesReady = hasMacroLoadFixtures &&
isVirtualHalSimConfigMacroLoadFixtureReportReady(macroLoadFixtures);
@@ -326,6 +463,7 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
...(sourceComplianceReady ? [] : ["virtualHalSourceCompliance"]),
...(simConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
...(promotionCandidatesReady ? [] : ["virtualHalSimConfigPromotionCandidates"]),
...(promotionCandidateSummaryReady ? [] : ["virtualHalPromotionCandidateSummary"]),
...(macroLoadFixturesReady ? [] : ["virtualHalSimConfigMacroLoadFixtures"]),
...(commandScriptFixturesReady ? [] : ["virtualHalCommandScriptFixtures"]),
...(motionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
@@ -344,6 +482,8 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
simConfigSourceCoverageReady,
promotionCandidatesReady,
hasPromotionCandidates,
promotionCandidateSummaryReady,
hasPromotionCandidateSummary,
macroLoadFixturesReady,
hasMacroLoadFixtures,
commandScriptFixturesReady,
@@ -385,6 +525,11 @@ export function createProjectReleaseBrowserDiagnosticsArtifactValidation(artifac
label: "Virtual HAL sim-config promotion candidates",
value: hasPromotionCandidates ? (promotionCandidatesReady ? "ready" : "missing") : "not provided",
},
{
id: "promotion-candidate-summary",
label: "Virtual HAL promotion candidate summary",
value: hasPromotionCandidateSummary ? (promotionCandidateSummaryReady ? "ready" : "missing") : "not provided",
},
{
id: "sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
@@ -1659,6 +1804,8 @@ export function createProjectReleaseReadinessReport({
observedOutputs = [],
simConfigInventory = DEFAULT_SIM_CONFIG_INVENTORY_BASELINE,
virtualHalSimConfigSourceCoverage = null,
virtualHalSimConfigPromotionCandidates = null,
virtualHalSimConfigMacroLoadFixtures = null,
virtualHalMotionControllerMatrix = null,
blockedRuntimeFamilies = BLOCKED_RUNTIME_FAMILIES,
promotedRuntimeFamilies = [],
@@ -1695,6 +1842,14 @@ export function createProjectReleaseReadinessReport({
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
virtualHalSimConfigSourceCoverage,
);
const virtualHalSimConfigPromotionCandidatesReady = isVirtualHalSimConfigPromotionCandidateReportReady(
virtualHalSimConfigPromotionCandidates,
);
const virtualHalPromotionFamilySummary = createPromotionFamilySummaryText(virtualHalSimConfigPromotionCandidates);
const virtualHalPromotionFamilyRows = createPromotionFamilySummaryRows(virtualHalSimConfigPromotionCandidates);
const virtualHalSimConfigMacroLoadFixturesReady = isVirtualHalSimConfigMacroLoadFixtureReportReady(
virtualHalSimConfigMacroLoadFixtures,
);
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
virtualHalMotionControllerMatrix,
);
@@ -1704,6 +1859,8 @@ export function createProjectReleaseReadinessReport({
const ready = releaseGatePassed &&
inventoryReady &&
virtualHalSimConfigSourceCoverageReady &&
virtualHalSimConfigPromotionCandidatesReady &&
virtualHalSimConfigMacroLoadFixturesReady &&
virtualHalMotionControllerMatrixReady &&
blockedRuntimeReady &&
axisScreenshotArtifactsReady;
@@ -1711,6 +1868,8 @@ export function createProjectReleaseReadinessReport({
...(releaseGatePassed ? [] : ["project-release-gate"]),
...(inventoryReady ? [] : ["sim-config-inventory"]),
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtual-hal-sim-config-source-coverage"]),
...(virtualHalSimConfigPromotionCandidatesReady ? [] : ["virtual-hal-sim-config-promotion-candidates"]),
...(virtualHalSimConfigMacroLoadFixturesReady ? [] : ["virtual-hal-sim-config-macro-load-fixtures"]),
...(virtualHalMotionControllerMatrixReady ? [] : ["virtual-hal-motion-controller-matrix"]),
...(blockedRuntimeReady ? [] : ["blocked-runtime-families"]),
...(axisScreenshotArtifactsReady ? [] : ["axis-screenshot-artifacts"]),
@@ -1730,6 +1889,12 @@ export function createProjectReleaseReadinessReport({
simConfigInventory: inventory,
virtualHalSimConfigSourceCoverage,
virtualHalSimConfigSourceCoverageReady,
virtualHalSimConfigPromotionCandidates,
virtualHalSimConfigPromotionCandidatesReady,
virtualHalPromotionFamilySummary,
virtualHalPromotionFamilyRows,
virtualHalSimConfigMacroLoadFixtures,
virtualHalSimConfigMacroLoadFixturesReady,
virtualHalMotionControllerMatrix,
virtualHalMotionControllerMatrixReady,
blockedRuntimeFamilies: blockedFamilies,
@@ -1758,6 +1923,27 @@ export function createProjectReleaseReadinessReport({
label: "Virtual HAL sim-config source coverage",
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
},
{
id: "virtual-hal-sim-config-promotion-candidates",
label: "Virtual HAL sim-config promotion candidates",
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
},
{
id: "virtual-hal-promotion-families",
label: "Virtual HAL promotion families",
value: virtualHalPromotionFamilySummary,
},
...virtualHalPromotionFamilyRows.map((row) => ({
id: `virtual-hal-promotion-family-${row.id}`,
label: `Promotion family ${row.label}`,
value: row.value,
sourceFiles: row.sourceFiles,
})),
{
id: "virtual-hal-sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
},
{
id: "virtual-hal-motion-controller-matrix",
label: "Virtual HAL motion controller matrix",
@@ -1786,6 +1972,8 @@ export function createProjectReleaseReadinessSummaryViewModel(
const gateResultMatrix = objectOrEmpty(report?.gateResultMatrix);
const simConfigInventory = objectOrEmpty(report?.simConfigInventory);
const virtualHalSimConfigSourceCoverageReady = report?.virtualHalSimConfigSourceCoverageReady === true;
const virtualHalSimConfigPromotionCandidatesReady = report?.virtualHalSimConfigPromotionCandidatesReady === true;
const virtualHalSimConfigMacroLoadFixturesReady = report?.virtualHalSimConfigMacroLoadFixturesReady === true;
const virtualHalMotionControllerMatrixReady = report?.virtualHalMotionControllerMatrixReady === true;
const axisScreenshotArtifactSummary = objectOrEmpty(report?.axisScreenshotArtifactSummary);
const blockedRuntimeFamilies = arrayOrEmpty(report?.blockedRuntimeFamilies);
@@ -1823,6 +2011,16 @@ export function createProjectReleaseReadinessSummaryViewModel(
label: "Virtual HAL sim-config source coverage",
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
},
{
id: "virtual-hal-sim-config-promotion-candidates",
label: "Virtual HAL sim-config promotion candidates",
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
},
{
id: "virtual-hal-sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
},
{
id: "virtual-hal-motion-controller-matrix",
label: "Virtual HAL motion controller matrix",
@@ -1910,6 +2108,27 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
label: "Virtual HAL sim-config source coverage",
value: validation?.virtualHalSimConfigSourceCoverageReady === true ? "ready" : "missing",
},
{
id: "virtual-hal-sim-config-promotion-candidates",
label: "Virtual HAL sim-config promotion candidates",
value: validation?.virtualHalSimConfigPromotionCandidatesReady === true ? "ready" : "missing",
},
{
id: "virtual-hal-promotion-families",
label: "Virtual HAL promotion families",
value: validation?.virtualHalPromotionFamilySummary ?? "not provided",
},
...arrayOrEmpty(validation?.virtualHalPromotionFamilyRows).map((row) => ({
id: `virtual-hal-promotion-family-${row.id}`,
label: `Promotion family ${row.label}`,
value: row.value,
sourceFiles: row.sourceFiles,
})),
{
id: "virtual-hal-sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
value: validation?.virtualHalSimConfigMacroLoadFixturesReady === true ? "ready" : "missing",
},
{
id: "virtual-hal-motion-controller-matrix",
label: "Virtual HAL motion controller matrix",
@@ -2179,6 +2398,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
let diagnosticsHttpStatus = null;
let diagnosticsFetchError = null;
let diagnosticsValidation = null;
let diagnosticsArtifact = null;
const diagnosticsMissing = [];
if (diagnosticsUrl) {
try {
@@ -2190,7 +2410,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
diagnosticsValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation({});
} else {
diagnosticsFetched = true;
const diagnosticsArtifact = JSON.parse(await diagnosticsResponse.text());
diagnosticsArtifact = JSON.parse(await diagnosticsResponse.text());
diagnosticsValidation = createProjectReleaseBrowserDiagnosticsArtifactValidation(diagnosticsArtifact);
diagnosticsMissing.push(...diagnosticsValidation.missing.map((item) => `diagnostics.${item}`));
if (requireSavedSessionDiagnostics && diagnosticsValidation.hasSessionDiagnostics !== true) {
@@ -2226,6 +2446,7 @@ export async function loadProjectReleaseReadinessArtifactUrlWorkflow({
jsonWorkflow,
validation: jsonWorkflow.validation,
diagnosticsValidation,
diagnosticsArtifact,
summaryViewModel: jsonWorkflow.summaryViewModel,
actionPlan: jsonWorkflow.actionPlan,
missing,
@@ -2305,6 +2526,8 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
workflow = {},
) {
const missing = arrayOrEmpty(workflow?.missing);
const promotionCandidateSummary = objectOrEmpty(workflow?.diagnosticsArtifact?.virtualHalPromotionCandidateSummary);
const promotionCandidateSummaryReady = promotionCandidateSummary.ready === true;
const ready = workflow?.ready === true;
const statusText = ready ? "Ready" : "Blocked";
const detailText = ready
@@ -2340,6 +2563,17 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
label: "Artifact validation",
value: workflow?.validation?.ready === true ? "ready" : "blocked",
},
{
id: "virtual-hal-promotion-families",
label: "Virtual HAL promotion families",
value: workflow?.validation?.virtualHalPromotionFamilySummary ?? "not provided",
},
...arrayOrEmpty(workflow?.validation?.virtualHalPromotionFamilyRows).map((row) => ({
id: `virtual-hal-promotion-family-${row.id}`,
label: `Promotion family ${row.label}`,
value: row.value,
sourceFiles: row.sourceFiles,
})),
{
id: "browser-diagnostics",
label: "Browser diagnostics",
@@ -2347,6 +2581,41 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
? (workflow?.diagnosticsValidation?.ready === true ? "ready" : "blocked")
: "not requested",
},
{
id: "virtual-hal-promotion-candidate-summary",
label: "Virtual HAL promotion candidate summary",
value: workflow?.diagnosticsUrl
? (promotionCandidateSummaryReady ? "ready" : "not provided")
: "not requested",
},
{
id: "virtual-hal-promotion-candidate",
label: "Virtual HAL promotion candidate",
value: promotionCandidateSummary.preferredCandidateId ?? "not provided",
},
{
id: "virtual-hal-promotion-candidate-ini",
label: "Candidate INI",
value: promotionCandidateSummary.preferredIniPath ?? "not provided",
},
{
id: "virtual-hal-promotion-candidate-gcode",
label: "Candidate G-code",
value: promotionCandidateSummary.preferredGcodePath ?? "not provided",
},
{
id: "virtual-hal-promotion-candidate-count",
label: "Candidate readiness",
value: Number.isFinite(promotionCandidateSummary.readyCandidateCount) &&
Number.isFinite(promotionCandidateSummary.candidateCount)
? `${promotionCandidateSummary.readyCandidateCount}/${promotionCandidateSummary.candidateCount} ready`
: "not provided",
},
{
id: "virtual-hal-promotion-candidate-baseline",
label: "Candidate inventory baseline",
value: promotionCandidateSummary.inventoryBaseline ?? "not provided",
},
{
id: "saved-session-diagnostics",
label: "Saved-session diagnostics",
@@ -2466,6 +2735,8 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
const releaseGate = objectOrEmpty(artifactObject.releaseGate);
const simConfigInventory = objectOrEmpty(artifactObject.simConfigInventory);
const virtualHalSimConfigSourceCoverage = objectOrEmpty(artifactObject.virtualHalSimConfigSourceCoverage);
const virtualHalSimConfigPromotionCandidates = objectOrEmpty(artifactObject.virtualHalSimConfigPromotionCandidates);
const virtualHalSimConfigMacroLoadFixtures = objectOrEmpty(artifactObject.virtualHalSimConfigMacroLoadFixtures);
const virtualHalMotionControllerMatrix = objectOrEmpty(artifactObject.virtualHalMotionControllerMatrix);
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
@@ -2515,6 +2786,14 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
const virtualHalSimConfigSourceCoverageReady = isVirtualHalSimConfigSourceCoverageReady(
virtualHalSimConfigSourceCoverage,
) && artifactObject.virtualHalSimConfigSourceCoverageReady === true;
const virtualHalSimConfigPromotionCandidatesReady = isVirtualHalSimConfigPromotionCandidateReportReady(
virtualHalSimConfigPromotionCandidates,
) && artifactObject.virtualHalSimConfigPromotionCandidatesReady === true;
const virtualHalPromotionFamilySummary = createPromotionFamilySummaryText(virtualHalSimConfigPromotionCandidates);
const virtualHalPromotionFamilyRows = createPromotionFamilySummaryRows(virtualHalSimConfigPromotionCandidates);
const virtualHalSimConfigMacroLoadFixturesReady = isVirtualHalSimConfigMacroLoadFixtureReportReady(
virtualHalSimConfigMacroLoadFixtures,
) && artifactObject.virtualHalSimConfigMacroLoadFixturesReady === true;
const virtualHalMotionControllerMatrixReady = isVirtualHalMotionControllerMatrixReady(
virtualHalMotionControllerMatrix,
) && artifactObject.virtualHalMotionControllerMatrixReady === true;
@@ -2556,6 +2835,8 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
...(simConfigInventory.skipped === 131 ? [] : ["simConfigInventory.skipped"]),
...(simConfigInventory.unexpectedFail === 0 ? [] : ["simConfigInventory.unexpectedFail"]),
...(virtualHalSimConfigSourceCoverageReady ? [] : ["virtualHalSimConfigSourceCoverage"]),
...(virtualHalSimConfigPromotionCandidatesReady ? [] : ["virtualHalSimConfigPromotionCandidates"]),
...(virtualHalSimConfigMacroLoadFixturesReady ? [] : ["virtualHalSimConfigMacroLoadFixtures"]),
...(virtualHalMotionControllerMatrixReady ? [] : ["virtualHalMotionControllerMatrix"]),
...(arrayOrEmpty(artifactObject.blockedRuntimeFamilies).join(",") === BLOCKED_RUNTIME_FAMILIES.join(",")
? []
@@ -2591,6 +2872,10 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
gateResultMatrixReady: matrixReady,
gateActionPlanReady: actionPlanReady,
virtualHalSimConfigSourceCoverageReady,
virtualHalSimConfigPromotionCandidatesReady,
virtualHalPromotionFamilySummary,
virtualHalPromotionFamilyRows,
virtualHalSimConfigMacroLoadFixturesReady,
virtualHalMotionControllerMatrixReady,
axisScreenshotArtifactSummaryReady: axisScreenshotSummaryReady,
axisScreenshotArtifactCount: axisScreenshotArtifacts.length,
@@ -2636,6 +2921,27 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
label: "Virtual HAL sim-config source coverage",
value: virtualHalSimConfigSourceCoverageReady ? "ready" : "missing",
},
{
id: "virtual-hal-sim-config-promotion-candidates",
label: "Virtual HAL sim-config promotion candidates",
value: virtualHalSimConfigPromotionCandidatesReady ? "ready" : "missing",
},
{
id: "virtual-hal-promotion-families",
label: "Virtual HAL promotion families",
value: virtualHalPromotionFamilySummary,
},
...virtualHalPromotionFamilyRows.map((row) => ({
id: `virtual-hal-promotion-family-${row.id}`,
label: `Promotion family ${row.label}`,
value: row.value,
sourceFiles: row.sourceFiles,
})),
{
id: "virtual-hal-sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
value: virtualHalSimConfigMacroLoadFixturesReady ? "ready" : "missing",
},
{
id: "virtual-hal-motion-controller-matrix",
label: "Virtual HAL motion controller matrix",