收束promotion候选证据

结论:按text22铁律完成promotion-candidates双层证据管理,baseline保持28/28/131/0,Python remap、tool DB、external user-M hard block继续locked。
This commit is contained in:
2026-06-18 19:32:28 +08:00
parent f2cc1e4c57
commit 00af30c074
18 changed files with 1129 additions and 5 deletions

View File

@@ -981,9 +981,24 @@ TOOL_TABLE = browser-shell-tool.tbl
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowRenderResult.rowCount,
10,
16,
"shell workflow overview release artifact URL workflow render rows",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"shell workflow overview release artifact URL workflow candidate layers",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-allowed")?.value,
"0",
"shell workflow overview release artifact URL workflow promotion allowed count",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
"shell workflow overview release artifact URL workflow evidence expansion count",
);
assertEqual(
workflowOverviewReleaseArtifactUrlWorkflowRenderResult.rowIds.includes("hard-block-runtime-lock"),
true,

View File

@@ -597,7 +597,7 @@
);
assertEqual(
releaseArtifactUrlWorkflowRenderResult.rowCount,
23,
29,
"workflow overview release artifact URL workflow render rows",
);
assertEqual(
@@ -610,6 +610,41 @@
true,
"workflow overview release artifact URL workflow candidate summary row",
);
assertEqual(
releaseArtifactUrlWorkflowRenderResult.rowIds.includes("promotion-candidate-layers"),
true,
"workflow overview release artifact URL workflow candidate layer row",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
"workflow overview release artifact URL workflow candidate artifact",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
"workflow overview release artifact URL workflow candidate layers",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-total")?.value,
"28",
"workflow overview release artifact URL workflow candidate total",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
"workflow overview release artifact URL workflow evidence expansion count",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
"workflow overview release artifact URL workflow evidence expansion artifact",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "promotion-candidate-allowed")?.value,
"0",
"workflow overview release artifact URL workflow promotion allowed count",
);
assertEqual(
releaseArtifactUrlWorkflowSummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate")?.value,
"qtdragon-multi-joint-on-abort",
@@ -776,6 +811,21 @@
"8/8 ready",
"workflow overview fixed URL workflow form candidate count row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="promotion-candidate-layers"]').textContent,
"evidence-ready=8 inventory-ready=20",
"workflow overview fixed URL workflow form candidate layer row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="promotion-candidate-allowed"]').textContent,
"0",
"workflow overview fixed URL workflow form candidate allowed row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="evidence-expansion-candidates"]').textContent,
"13",
"workflow overview fixed URL workflow form evidence expansion count row",
);
assertEqual(
workflowDoc.querySelector('[data-workflow-overview-release-readiness-artifact-url-workflow-value="virtual-hal-promotion-source-file-count"]').textContent,
"17 source files",

View File

@@ -712,6 +712,45 @@
"ready": true
}
],
"promotionCandidateArtifactSummary": {
"apiName": "project-release-promotion-candidate-artifact-summary",
"summaryVersion": 1,
"phase": "ready",
"ready": true,
"artifactPath": "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
"evidenceExpansionArtifactPath": "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
"layerCount": 2,
"evidenceReadyCount": 8,
"inventoryReadyCount": 20,
"evidenceExpansionCandidateCount": 13,
"totalCandidateCount": 28,
"promotionAllowedCount": 0,
"hardBlockRuntimeLock": "locked (3 families)",
"inventoryBaseline": "executed=28 passed=28 skipped=131 unexpected_fail=0",
"layers": [
{
"id": "evidence-ready",
"candidateCount": 8,
"promotionAllowedCount": 0,
"virtualHalEvidenceReady": true,
"baselineChanging": false
},
{
"id": "inventory-ready",
"candidateCount": 20,
"promotionAllowedCount": 0,
"virtualHalEvidenceReady": false,
"baselineChanging": false
}
],
"evidenceExpansion": {
"id": "browser-diagnostics-expansion",
"candidateCount": 13,
"promotionAllowedCount": 0,
"baselineChanging": false,
"nextEvidence": "browser-diagnostics-binding"
}
},
"virtualHalSimConfigMacroLoadFixtures": {
"apiName": "linuxcnc-wasm-virtual-hal-sim-config-macro-load-fixture-report",
"reportVersion": 1,
@@ -2288,6 +2327,36 @@
"label": "Virtual HAL sim-config promotion candidates",
"value": "ready"
},
{
"id": "promotion-candidate-artifact",
"label": "Promotion candidate artifact",
"value": "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"
},
{
"id": "promotion-candidate-layers",
"label": "Promotion candidate layers",
"value": "evidence-ready=8 inventory-ready=20"
},
{
"id": "promotion-candidate-total",
"label": "Promotion candidate total",
"value": "28"
},
{
"id": "evidence-expansion-candidates",
"label": "Evidence expansion candidates",
"value": "13"
},
{
"id": "evidence-expansion-artifact",
"label": "Evidence expansion artifact",
"value": "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"
},
{
"id": "promotion-candidate-allowed",
"label": "Promotion candidates allowed",
"value": "0"
},
{
"id": "virtual-hal-promotion-families",
"label": "Virtual HAL promotion families",

View File

@@ -175,6 +175,25 @@ assert.equal(artifact.virtualHalMotionControllerMatrix.manifestChecked, true);
assert.equal(artifact.virtualHalMotionControllerMatrixReady, true);
assert.equal(artifact.virtualHalMotionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"), true);
assert.equal(artifact.virtualHalMotionControllerMatrix.simConfigSourceFiles.includes("linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini"), true);
assert.equal(artifact.promotionCandidateArtifactSummary.apiName, "project-release-promotion-candidate-artifact-summary");
assert.equal(
artifact.promotionCandidateArtifactSummary.artifactPath,
"wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
);
assert.equal(
artifact.promotionCandidateArtifactSummary.evidenceExpansionArtifactPath,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceReadyCount, 8);
assert.equal(artifact.promotionCandidateArtifactSummary.inventoryReadyCount, 20);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceExpansionCandidateCount, 13);
assert.equal(artifact.promotionCandidateArtifactSummary.totalCandidateCount, 28);
assert.equal(artifact.promotionCandidateArtifactSummary.promotionAllowedCount, 0);
assert.equal(artifact.promotionCandidateArtifactSummary.evidenceExpansion.promotionAllowedCount, 0);
assert.equal(
artifact.promotionCandidateArtifactSummary.inventoryBaseline,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
);
assert.equal(artifact.axisScreenshotArtifactSummary.apiName, "project-release-axis-screenshot-artifact-summary");
if (artifact.axisScreenshotArtifactSummary.artifactCount > 0) {
assert.equal(artifact.axisScreenshotArtifactSummary.artifactCount, 4);

View File

@@ -14,6 +14,7 @@ import {
createVirtualHalSimConfigMacroLoadFixtureReport,
createVirtualHalCommandScriptFixtureReport,
createVirtualHalMotionControllerMatrixReport,
createVirtualHalSimConfigEvidenceExpansionReport,
createVirtualHalSimulationReplacementReport,
createVirtualHalSourceComplianceReport,
createVirtualHalState,
@@ -31,6 +32,11 @@ const virtualHalSimConfigPromotionCandidates = createVirtualHalSimConfigPromotio
simConfigSourceCoverage: virtualHalSimConfigSourceCoverage,
motionControllerMatrix: virtualHalMotionControllerMatrix,
});
const virtualHalSimConfigEvidenceExpansion = createVirtualHalSimConfigEvidenceExpansionReport({
manifestText: sourceManifestText,
simConfigSourceCoverage: virtualHalSimConfigSourceCoverage,
motionControllerMatrix: virtualHalMotionControllerMatrix,
});
const virtualHalSimConfigMacroLoadFixtures = createVirtualHalSimConfigMacroLoadFixtureReport({
manifestText: sourceManifestText,
});
@@ -43,6 +49,7 @@ const browserDiagnosticsArtifact = {
virtualHalSourceCompliance: createVirtualHalSourceComplianceReport({ halState: virtualHalState }),
virtualHalSimConfigSourceCoverage,
virtualHalSimConfigPromotionCandidates,
virtualHalSimConfigEvidenceExpansion,
virtualHalPromotionCandidateSummary: {
apiName: "real-browser-simulation-promotion-candidate-summary",
summaryVersion: 1,
@@ -84,6 +91,7 @@ const readyArtifactJson = JSON.stringify(createProjectReleaseReadinessReport({
gateResults: Object.fromEntries(manifest.gateIds.map((id) => [id, true])),
virtualHalSimConfigSourceCoverage,
virtualHalSimConfigPromotionCandidates,
virtualHalSimConfigEvidenceExpansion,
virtualHalSimConfigMacroLoadFixtures,
virtualHalMotionControllerMatrix: browserDiagnosticsArtifact.virtualHalMotionControllerMatrix,
}));
@@ -178,6 +186,30 @@ assert.equal(
readySummary.rows.find(({ id }) => id === "virtual-hal-promotion-candidate-baseline")?.value,
"executed=28 passed=28 skipped=131 unexpected_fail=0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-total")?.value,
"28",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-candidates")?.value,
"13",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "evidence-expansion-artifact")?.value,
"wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "promotion-candidate-allowed")?.value,
"0",
);
assert.equal(
readySummary.rows.find(({ id }) => id === "hard-block-runtime-lock")?.value,
"locked (3 families)",
@@ -203,6 +235,12 @@ assert.deepEqual(
["json-workflow", "ready"],
["artifact-validation", "ready"],
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
...expectedPromotionFamilyRows,
["browser-diagnostics", "ready"],
["virtual-hal-promotion-candidate-summary", "ready"],

View File

@@ -271,6 +271,21 @@ assert.deepEqual(createProjectReleaseReadinessSummaryViewModel(report), {
label: "Virtual HAL sim-config promotion candidates",
value: "ready",
},
{
id: "promotion-candidate-layers",
label: "Promotion candidate layers",
value: "evidence-ready=8 inventory-ready=20",
},
{
id: "promotion-candidate-allowed",
label: "Promotion candidates allowed",
value: "0",
},
{
id: "evidence-expansion-candidates",
label: "Evidence expansion candidates",
value: "13",
},
{
id: "virtual-hal-sim-config-macro-load-fixtures",
label: "Virtual HAL sim-config macro/load fixtures",
@@ -369,6 +384,12 @@ assert.deepEqual(
["gate-action-plan", "ready"],
["virtual-hal-sim-config-source-coverage", "ready"],
["virtual-hal-sim-config-promotion-candidates", "ready"],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
...expectedPromotionFamilyRows,
["virtual-hal-sim-config-macro-load-fixtures", "ready"],
@@ -460,6 +481,12 @@ assert.deepEqual(
["json-workflow", "ready"],
["artifact-validation", "ready"],
["virtual-hal-promotion-families", expectedPromotionFamilySummary],
["promotion-candidate-artifact", "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv"],
["promotion-candidate-layers", "evidence-ready=8 inventory-ready=20"],
["promotion-candidate-total", "28"],
["evidence-expansion-candidates", "13"],
["evidence-expansion-artifact", "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv"],
["promotion-candidate-allowed", "0"],
...expectedPromotionFamilyRows,
["browser-diagnostics", "not requested"],
["virtual-hal-promotion-candidate-summary", "not requested"],

View File

@@ -39,6 +39,7 @@ import {
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_EVIDENCE_EXPANSION_CANDIDATES,
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES,
VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE,
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES,
@@ -95,6 +96,7 @@ import {
createVirtualHalPinInventory,
createVirtualHalPinRegistry,
createVirtualHalProjectReport,
createVirtualHalSimConfigEvidenceExpansionReport,
createVirtualHalSimConfigMacroLoadFixtureReport,
createVirtualHalSimConfigPromotionCandidateReport,
createVirtualHalSimConfigSourceCoverageReport,
@@ -188,6 +190,45 @@ const expectedPromotionFamilyRows = [
["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 expectedPromotionCandidateArtifactSummary = {
apiName: "project-release-promotion-candidate-artifact-summary",
summaryVersion: 1,
phase: "ready",
ready: true,
artifactPath: "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
evidenceExpansionArtifactPath: "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
layerCount: 2,
evidenceReadyCount: 8,
inventoryReadyCount: 20,
evidenceExpansionCandidateCount: 13,
totalCandidateCount: 28,
promotionAllowedCount: 0,
hardBlockRuntimeLock: "locked (3 families)",
inventoryBaseline: "executed=28 passed=28 skipped=131 unexpected_fail=0",
layers: [
{
id: "evidence-ready",
candidateCount: 8,
promotionAllowedCount: 0,
virtualHalEvidenceReady: true,
baselineChanging: false,
},
{
id: "inventory-ready",
candidateCount: 20,
promotionAllowedCount: 0,
virtualHalEvidenceReady: false,
baselineChanging: false,
},
],
evidenceExpansion: {
id: "browser-diagnostics-expansion",
candidateCount: 13,
promotionAllowedCount: 0,
baselineChanging: false,
nextEvidence: "browser-diagnostics-binding",
},
};
const hasFreshBoundaryArtifactHashes = (boundaryEvidence) =>
Object.entries(VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES)
.every(([artifactPath, expectedHash]) => boundaryEvidence?.sourceArtifactHashes?.[artifactPath] === expectedHash);
@@ -257,6 +298,7 @@ const requiredExports = [
["createVirtualHalPinInventory", createVirtualHalPinInventory],
["createVirtualHalPinRegistry", createVirtualHalPinRegistry],
["createVirtualHalProjectReport", createVirtualHalProjectReport],
["createVirtualHalSimConfigEvidenceExpansionReport", createVirtualHalSimConfigEvidenceExpansionReport],
["createVirtualHalSimConfigMacroLoadFixtureReport", createVirtualHalSimConfigMacroLoadFixtureReport],
["createVirtualHalSimConfigPromotionCandidateReport", createVirtualHalSimConfigPromotionCandidateReport],
["createVirtualHalSimConfigSourceCoverageReport", createVirtualHalSimConfigSourceCoverageReport],
@@ -896,6 +938,33 @@ assert.equal(virtualHalRuntime.getSimConfigPromotionCandidateReport({
simConfigSourceCoverage: simConfigSourceCoverageReport,
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
}).complete, true);
assert.equal(VIRTUAL_HAL_SIM_CONFIG_EVIDENCE_EXPANSION_CANDIDATES.length, 3);
const simConfigEvidenceExpansionReport = createVirtualHalSimConfigEvidenceExpansionReport({
manifestText: sourceManifestText,
simConfigSourceCoverage: simConfigSourceCoverageReport,
motionControllerMatrix: manifestCheckedMotionControllerMatrixReport,
});
assert.equal(
simConfigEvidenceExpansionReport.apiName,
"linuxcnc-wasm-virtual-hal-sim-config-evidence-expansion-report",
);
assert.equal(simConfigEvidenceExpansionReport.complete, true);
assert.equal(simConfigEvidenceExpansionReport.webSimulationSatisfied, true);
assert.equal(simConfigEvidenceExpansionReport.inventoryBaselineUnchanged, true);
assert.equal(simConfigEvidenceExpansionReport.promotionAllowed, false);
assert.equal(simConfigEvidenceExpansionReport.candidateCount, 3);
assert.equal(simConfigEvidenceExpansionReport.readyCandidateCount, 3);
assert.equal(simConfigEvidenceExpansionReport.promotionAllowedViolations.length, 0);
assert.equal(
simConfigEvidenceExpansionReport.rows.some((row) =>
row.id === "woodpecker-on-abort" &&
row.currentMatrixBrowserStatus === "REP" &&
row.targetBrowserEvidence === "browser-diagnostics-expansion" &&
row.promotionAllowed === false &&
row.sourceFiles.includes("linuxcnc/configs/sim/woodpecker/on_abort.ngc")
),
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);
@@ -1204,6 +1273,7 @@ assert.equal(virtualHalSessionPayload.state.hal.signals["x-pos"].value, 1.25);
assert.equal(virtualHalSessionPayload.sourceCompliance.complete, true);
assert.equal(virtualHalSessionPayload.simConfigSourceCoverage.complete, true);
assert.equal(virtualHalSessionPayload.simConfigPromotionCandidates.complete, true);
assert.equal(virtualHalSessionPayload.simConfigEvidenceExpansion.complete, true);
assert.equal(virtualHalSessionPayload.simConfigMacroLoadFixtures.complete, true);
assert.equal(virtualHalSessionPayload.commandScriptFixtures.complete, true);
assert.equal(virtualHalSessionPayload.motionControllerMatrix.complete, true);
@@ -1226,6 +1296,7 @@ const browserDiagnosticsArtifact = {
virtualHalSourceCompliance: sourceComplianceReport,
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
virtualHalSimConfigPromotionCandidates: simConfigPromotionCandidateReport,
virtualHalSimConfigEvidenceExpansion: simConfigEvidenceExpansionReport,
virtualHalPromotionCandidateSummary: {
apiName: "real-browser-simulation-promotion-candidate-summary",
summaryVersion: 1,
@@ -1268,6 +1339,8 @@ assert.equal(browserDiagnosticsArtifactValidation.sourceComplianceReady, true);
assert.equal(browserDiagnosticsArtifactValidation.simConfigSourceCoverageReady, true);
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidatesReady, true);
assert.equal(browserDiagnosticsArtifactValidation.hasPromotionCandidates, true);
assert.equal(browserDiagnosticsArtifactValidation.evidenceExpansionReady, true);
assert.equal(browserDiagnosticsArtifactValidation.hasEvidenceExpansion, true);
assert.equal(browserDiagnosticsArtifactValidation.promotionCandidateSummaryReady, true);
assert.equal(browserDiagnosticsArtifactValidation.hasPromotionCandidateSummary, true);
assert.equal(browserDiagnosticsArtifactValidation.macroLoadFixturesReady, true);
@@ -1494,6 +1567,10 @@ assert.equal(releaseReadinessReady.releaseGate.passed, true);
assert.equal(releaseReadinessReady.virtualHalSimConfigSourceCoverageReady, true);
assert.equal(releaseReadinessReady.virtualHalSimConfigPromotionCandidatesReady, true);
assert.equal(releaseReadinessReady.virtualHalPromotionFamilySummary, expectedPromotionFamilySummary);
assert.deepEqual(
releaseReadinessReady.promotionCandidateArtifactSummary,
expectedPromotionCandidateArtifactSummary,
);
assert.deepEqual(
releaseReadinessReady.virtualHalPromotionFamilyRows.map(({ id, value }) => [
`virtual-hal-promotion-family-${id}`,
@@ -1516,6 +1593,10 @@ assert.equal(
createProjectReleaseReadinessSummaryViewModel(releaseReadinessReady).rows.find(({ id }) => id === "axis-screenshot-artifacts")?.value,
"not captured",
);
assert.equal(
createProjectReleaseReadinessSummaryViewModel(releaseReadinessReady).rows.find(({ id }) => id === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
);
const releaseReadinessWithScreenshots = createProjectReleaseReadinessReport({
gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])),
virtualHalSimConfigSourceCoverage: simConfigSourceCoverageReport,
@@ -1582,6 +1663,8 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
virtualHalSimConfigPromotionCandidatesReady: true,
virtualHalPromotionFamilySummary: expectedPromotionFamilySummary,
virtualHalPromotionFamilyRows: releaseReadinessReady.virtualHalPromotionFamilyRows,
promotionCandidateArtifactSummary: expectedPromotionCandidateArtifactSummary,
promotionCandidateArtifactSummaryReady: true,
virtualHalSimConfigMacroLoadFixturesReady: true,
virtualHalMotionControllerMatrixReady: true,
axisScreenshotArtifactSummaryReady: true,
@@ -1637,6 +1720,36 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
label: "Virtual HAL sim-config promotion candidates",
value: "ready",
},
{
id: "promotion-candidate-artifact",
label: "Promotion candidate artifact",
value: "wasm-port/build/wasm/sim-configs-inventory/promotion-candidates.tsv",
},
{
id: "promotion-candidate-layers",
label: "Promotion candidate layers",
value: "evidence-ready=8 inventory-ready=20",
},
{
id: "promotion-candidate-total",
label: "Promotion candidate total",
value: "28",
},
{
id: "evidence-expansion-candidates",
label: "Evidence expansion candidates",
value: "13",
},
{
id: "evidence-expansion-artifact",
label: "Evidence expansion artifact",
value: "wasm-port/build/wasm/sim-configs-inventory/evidence-expansion-candidates.tsv",
},
{
id: "promotion-candidate-allowed",
label: "Promotion candidates allowed",
value: "0",
},
{
id: "virtual-hal-promotion-families",
label: "Virtual HAL promotion families",
@@ -1763,6 +1876,32 @@ assert.equal(
).rows.find(({ id }) => id === "virtual-hal-promotion-families")?.value,
expectedPromotionFamilySummary,
);
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 === "promotion-candidate-layers")?.value,
"evidence-ready=8 inventory-ready=20",
);
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 === "evidence-expansion-candidates")?.value,
"13",
);
assert.deepEqual(
createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
await loadProjectReleaseReadinessArtifactUrlWorkflow({
@@ -1815,6 +1954,7 @@ assert.deepEqual(
"simConfigInventory.unexpectedFail",
"virtualHalSimConfigSourceCoverage",
"virtualHalSimConfigPromotionCandidates",
"promotionCandidateArtifactSummary",
"virtualHalSimConfigMacroLoadFixtures",
"virtualHalMotionControllerMatrix",
"blockedRuntimeFamilies",

View File

@@ -1797,7 +1797,7 @@ const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseRead
rowsNode: releaseArtifactRowsNode,
});
assert.equal(releaseArtifactRenderResult.rendered, true);
assert.equal(releaseArtifactRenderResult.rowCount, 20);
assert.equal(releaseArtifactRenderResult.rowCount, 26);
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
assert.equal(
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
@@ -1811,6 +1811,18 @@ assert.equal(
releaseArtifactRenderResult.rowIds.includes("virtual-hal-promotion-families"),
true,
);
assert.equal(
releaseArtifactRenderResult.rowIds.includes("promotion-candidate-layers"),
true,
);
assert.equal(
releaseArtifactRenderResult.rowIds.includes("promotion-candidate-allowed"),
true,
);
assert.equal(
releaseArtifactRenderResult.rowIds.includes("evidence-expansion-candidates"),
true,
);
assert.equal(
releaseArtifactRenderResult.rowIds.includes("gate-action-plan"),
true,
@@ -1828,7 +1840,7 @@ assert.equal(
true,
);
assert.equal(releaseArtifactMountResult.ready, true);
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 20);
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 26);
assert.deepEqual(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
["artifact-json"],
@@ -1887,7 +1899,7 @@ assert.equal(
);
assert.equal(releaseArtifactUrlWorkflow.renderState.statusLine, "Ready: No blocking reasons");
assert.equal(releaseArtifactUrlWorkflow.mountResult.ready, true);
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 20);
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 26);
const releaseArtifactUrlWorkflowSummary =
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
releaseArtifactUrlWorkflow,

View File

@@ -102,6 +102,7 @@ const runtimeProbeGateAlignmentPath = resolve(buildDir, "runtime-probe-gate-alig
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 evidenceExpansionCandidatesPath = resolve(buildDir, "evidence-expansion-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");
@@ -12055,6 +12056,127 @@ function promotionCandidateRows({
return [...evidenceReadyRows, ...inventoryReadyRows];
}
function evidenceExpansionCandidateRows({
summaryRows,
boundaryRows,
trackedMatrixByPath,
}) {
const promotedEvidencePaths = new Set(
VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES.map((candidate) =>
sourcePathToInventoryPath(candidate.gcodePath)
),
);
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
return summaryRows
.map((row) => {
const [
path,
inventoryStatus,
reason,
className,
nativeStatus,
nativeExpectedFailure,
] = row.split("\t");
return {
path,
inventoryStatus,
reason,
className,
nativeStatus,
nativeExpectedFailure,
};
})
.filter((row) =>
row.inventoryStatus === "PASS" &&
row.reason === "-" &&
row.className === "main" &&
row.nativeStatus === "PASS" &&
!promotedEvidencePaths.has(row.path) &&
(boundaryByPath.get(row.path)?.blocked ?? "-") === "-"
)
.sort((left, right) => left.path.localeCompare(right.path))
.map((row) => {
const boundary = boundaryByPath.get(row.path);
const matrix = trackedMatrixByPath.get(row.path);
return [
"browser-diagnostics-expansion",
row.path,
boundary?.ini ?? "-",
row.inventoryStatus,
row.reason,
matrix?.layer4Node ?? "-",
matrix?.layer4Browser ?? "-",
row.className,
row.nativeStatus,
row.nativeExpectedFailure,
matrix?.blocked ?? boundary?.blocked ?? "-",
boundary?.dependencies ?? "-",
"0",
"needs_browser_diagnostics_binding_no_inventory_baseline_change",
"wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh && wasm-port/tests/browser/verify_ini_panel_browser.sh",
].map(tsvValue).join("\t");
});
}
function verifyEvidenceExpansionCandidateRows(rows, summaryRows, boundaryRows, trackedMatrixByPath) {
const expectedHeaders = [
"candidate_kind",
"path",
"ini",
"current_status",
"skip_kind",
"matrix_layer4_node",
"matrix_layer4_browser",
"class",
"native_status",
"native_expected_failure",
"blocked_kind",
"dependency_class",
"promotion_allowed",
"block_reason",
"recommended_next_command",
];
const parsedRows = parseTsv(
`${expectedHeaders.join("\t")}\n${rows.join("\n")}\n`,
expectedHeaders,
);
const boundaryByPath = new Map(boundaryRows.map((row) => [row.path, row]));
const expectedPaths = evidenceExpansionCandidateRows({
summaryRows,
boundaryRows,
trackedMatrixByPath,
}).map((row) => row.split("\t")[1]).sort();
assert.deepEqual(
parsedRows.map((row) => row.path).sort(),
expectedPaths,
"evidence expansion candidates must cover every non-hard-block PASS main candidate outside evidence-ready",
);
assert.equal(parsedRows.length, 13, "current evidence expansion candidate count drift");
for (const row of parsedRows) {
const boundary = boundaryByPath.get(row.path);
assert.ok(boundary, `${row.path}: evidence expansion candidate lacks boundary evidence`);
assert.equal(row.candidate_kind, "browser-diagnostics-expansion", `${row.path}: candidate kind drift`);
assert.equal(row.current_status, "PASS", `${row.path}: expansion candidate must be PASS`);
assert.equal(row.skip_kind, "-", `${row.path}: expansion candidate must not have a skip kind`);
assert.equal(row.class, "main", `${row.path}: expansion candidate must be main class`);
assert.equal(row.native_status, "PASS", `${row.path}: expansion candidate must have native PASS`);
assert.equal(row.blocked_kind, "-", `${row.path}: expansion candidate must not be blocked`);
assert.equal(row.promotion_allowed, "0", `${row.path}: expansion candidate must not claim baseline promotion`);
assert.equal(
row.block_reason,
"needs_browser_diagnostics_binding_no_inventory_baseline_change",
`${row.path}: expansion candidate block reason drift`,
);
assert.ok(
row.recommended_next_command.includes("verify_release_artifact_url_workflow_browser.sh"),
`${row.path}: expansion candidate lacks browser diagnostics command`,
);
}
return parsedRows;
}
function verifyPromotionCandidateRows(rows, summaryRows, boundaryRows) {
const expectedHeaders = [
"candidate_kind",
@@ -12633,6 +12755,17 @@ verifyPromotionCandidateRows(
summaryRows,
boundarySummaryRecords,
);
const evidenceExpansionCandidateRowsGenerated = evidenceExpansionCandidateRows({
summaryRows,
boundaryRows: boundarySummaryRecords,
trackedMatrixByPath,
});
verifyEvidenceExpansionCandidateRows(
evidenceExpansionCandidateRowsGenerated,
summaryRows,
boundarySummaryRecords,
trackedMatrixByPath,
);
writeFileSync(
promotionCandidatesPath,
`${[
@@ -12659,6 +12792,30 @@ writeFileSync(
].join("\n")}\n`,
);
writeFileSync(
evidenceExpansionCandidatesPath,
`${[
[
"candidate_kind",
"path",
"ini",
"current_status",
"skip_kind",
"matrix_layer4_node",
"matrix_layer4_browser",
"class",
"native_status",
"native_expected_failure",
"blocked_kind",
"dependency_class",
"promotion_allowed",
"block_reason",
"recommended_next_command",
].join("\t"),
...evidenceExpansionCandidateRowsGenerated,
].join("\n")}\n`,
);
writeFileSync(
boundarySummaryPath,
`${[