新增 release gate execution summary API
This commit is contained in:
56
text15.txt
56
text15.txt
@@ -416,3 +416,59 @@ project_release_gate=ok
|
||||
- 新增内容只验证 host OPFS/session persistence、WASM staging、SDK/browser workflow 和 release gate
|
||||
evidence;
|
||||
- blocked runtime families 仍不 promotion。
|
||||
|
||||
五十九、2026-06-16 继续执行记录:release gate execution summary view-model SDK API
|
||||
|
||||
本批继续按“每批必须产出可调用 API、可验证 workflow、可执行 gate、或真实 UI/browser 能力”
|
||||
推进,选择 release gate execution evidence 的 UI/CI 展示能力。
|
||||
|
||||
本批新增实质能力:
|
||||
|
||||
- 新增 SDK API:`createProjectReleaseGateExecutionSummaryViewModel()`;
|
||||
- 该 API 复用 `createProjectReleaseGateExecutionManifest()` 输出,生成稳定 dashboard/view-model:
|
||||
- `statusLine`;
|
||||
- `passedCount`、`unknownCount`、`gateCount`;
|
||||
- `nextGateId`;
|
||||
- `evidenceCounts`;
|
||||
- summary rows;
|
||||
- normalized per-gate `gateRows`。
|
||||
- `createProjectReleaseReadinessReport()` 现在嵌入 `gateExecutionSummaryViewModel`;
|
||||
- `createProjectReleaseReadinessArtifactValidation()` 现在要求 artifact 包含 ready
|
||||
`gateExecutionSummaryViewModel`,并暴露 `gateExecutionSummaryReady`;
|
||||
- release artifact validation summary/render rows 增加 `gate-execution-summary` evidence 行;
|
||||
- SDK README 与 project release handoff docs 记录该 summary view-model;
|
||||
- ready fixture 与 host artifact writer/validator 同步新 artifact schema。
|
||||
|
||||
本批新增/更新可执行验证:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/sdk/node/verify_project_release_gate_manifest.sh
|
||||
wasm-port/tests/sdk/node/verify_sdk_surface.sh
|
||||
wasm-port/tests/docs/node/verify_project_release_handoff_docs.sh
|
||||
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
|
||||
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh
|
||||
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||
wasm-port/tests/host/verify_project_release_gate.sh
|
||||
```
|
||||
|
||||
关键通过输出:
|
||||
|
||||
```text
|
||||
project_release_gate_manifest_node_smoke=ok
|
||||
sdk_surface_node_smoke=ok
|
||||
project_release_handoff_docs_node_smoke=ok
|
||||
ui_node_smokes=ok
|
||||
browser_release_artifact_url_workflow_smoke=ok
|
||||
browser_ini_shell_integration_workflow_smoke=ok
|
||||
browser_opfs_session_workflow_smoke=ok
|
||||
project_release_readiness_artifact_node_smoke=ok
|
||||
project_release_gate=ok
|
||||
```
|
||||
|
||||
本批仍保持 LinuxCNC 语义边界:
|
||||
|
||||
- 未修改 vendored LinuxCNC 源码;
|
||||
- 未在 JS/browser 中实现 G-code、tool、parameter、planner、kinematics、remap 或 canonical motion
|
||||
语义;
|
||||
- 新增内容只包装 release gate evidence 与 artifact validation display rows;
|
||||
- blocked runtime families 仍不 promotion。
|
||||
|
||||
@@ -41,7 +41,10 @@ continuation records are in `../text15.txt`.
|
||||
`createProjectReleaseGateActionPlan()` to derive pending gate commands, the
|
||||
next command, display rows, and a shell script from that matrix,
|
||||
`createProjectReleaseGateExecutionManifest()` to package each gate command,
|
||||
expected output, observed-output evidence, and passed/unknown status, and
|
||||
expected output, observed-output evidence, and passed/unknown status,
|
||||
`createProjectReleaseGateExecutionSummaryViewModel()` to expose dashboard
|
||||
status text, evidence counts, next missing gate, and normalized per-gate rows,
|
||||
and
|
||||
`createProjectReleaseReadinessReport()` for a machine-readable release
|
||||
readiness report covering the same manifest, execution manifest, result
|
||||
matrix, action plan, sim-config inventory baseline, and blocked runtime
|
||||
|
||||
@@ -55,6 +55,7 @@ import {
|
||||
createMachineSessionSnapshotPayload,
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
createProjectReleaseGateExecutionSummaryViewModel,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseGateResultMatrix,
|
||||
createProjectReleaseReadinessArtifactJsonWorkflow,
|
||||
@@ -214,12 +215,15 @@ with caller-provided explicit results and observed output evidence. Each row
|
||||
includes the command, expected output, matched observed output when present,
|
||||
evidence kind, and `passed`/`unknown` status so CI or browser dashboards can
|
||||
render release-gate execution state without scraping shell scripts.
|
||||
`createProjectReleaseGateExecutionSummaryViewModel()` turns that execution
|
||||
manifest into stable dashboard status text, evidence counts, next missing gate,
|
||||
summary rows, and normalized per-gate rows.
|
||||
`createProjectReleaseReadinessReport()` returns a machine-readable release
|
||||
readiness report that embeds the same manifest, result matrix, and action plan
|
||||
beside the gate execution manifest, sim-config inventory baseline, and blocked
|
||||
runtime families. It is evidence driven: the default report is `ready: false`
|
||||
until the caller supplies observed gate output such as `project_release_gate=ok`
|
||||
or explicit gate results.
|
||||
readiness report that embeds the same manifest, result matrix, action plan,
|
||||
gate execution manifest, gate execution summary view-model, sim-config
|
||||
inventory baseline, and blocked runtime families. It is evidence driven: the
|
||||
default report is `ready: false` until the caller supplies observed gate output
|
||||
such as `project_release_gate=ok` or explicit gate results.
|
||||
`createProjectReleaseReadinessSummaryViewModel()` turns the report into stable
|
||||
status text, a status line, and display rows for dashboards without executing
|
||||
any gate.
|
||||
@@ -238,8 +242,9 @@ it with `createProjectReleaseReadinessArtifactValidation()` without copying the
|
||||
host test assertions. The validation result includes `expectedGateCount` and
|
||||
`expectedGateIds` so external callers can compare an artifact against the
|
||||
current manifest, plus `gateManifestReady`, `gateExecutionManifestReady`,
|
||||
`gateResultMatrixReady`, and `gateActionPlanReady` so stale artifacts that omit
|
||||
the embedded gate evidence chain fail the same executable gate.
|
||||
`gateExecutionSummaryReady`, `gateResultMatrixReady`, and
|
||||
`gateActionPlanReady` so stale artifacts that omit the embedded gate evidence
|
||||
chain fail the same executable gate.
|
||||
`createProjectReleaseReadinessArtifactValidationSummaryViewModel()` turns that
|
||||
validation result into stable status text and display rows for dashboards or
|
||||
browser shells without reinterpreting the artifact fields.
|
||||
|
||||
@@ -3,6 +3,7 @@ export { createLinuxCncInterpSdk } from "./linuxcnc-interp.js";
|
||||
export {
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
createProjectReleaseGateExecutionSummaryViewModel,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseGateResultMatrix,
|
||||
createProjectReleaseReadinessArtifactJsonWorkflow,
|
||||
|
||||
@@ -176,6 +176,81 @@ export function createProjectReleaseGateExecutionManifest({
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectReleaseGateExecutionSummaryViewModel(
|
||||
executionManifest = createProjectReleaseGateExecutionManifest(),
|
||||
) {
|
||||
const rows = arrayOrEmpty(executionManifest?.rows);
|
||||
const ready = executionManifest?.ready === true;
|
||||
const missingGateIds = arrayOrEmpty(executionManifest?.missingGateIds);
|
||||
const statusText = ready ? "Ready" : "Waiting";
|
||||
const detailText = ready
|
||||
? "All release gate evidence present"
|
||||
: (missingGateIds.length > 0 ? missingGateIds.join(", ") : "release gate evidence missing");
|
||||
const evidenceCounts = rows.reduce((counts, row) => ({
|
||||
...counts,
|
||||
[row.evidence ?? "missing"]: (counts[row.evidence ?? "missing"] ?? 0) + 1,
|
||||
}), {});
|
||||
|
||||
return {
|
||||
apiName: "project-release-gate-execution-summary-view-model",
|
||||
viewModelVersion: 1,
|
||||
phase: ready ? "ready" : "waiting",
|
||||
ready,
|
||||
title: "Project release gate execution",
|
||||
statusText,
|
||||
detailText,
|
||||
statusLine: `${statusText}: ${detailText}`,
|
||||
gateCount: executionManifest?.gateCount ?? rows.length,
|
||||
passedCount: executionManifest?.passedCount ?? rows.filter(({ passed }) => passed === true).length,
|
||||
unknownCount: executionManifest?.unknownCount ?? rows.filter(({ passed }) => passed !== true).length,
|
||||
missingGateIds,
|
||||
nextGateId: missingGateIds[0] ?? null,
|
||||
evidenceCounts,
|
||||
rows: [
|
||||
{
|
||||
id: "gate-results",
|
||||
label: "Release gate evidence",
|
||||
value: `${executionManifest?.passedCount ?? 0}/${executionManifest?.gateCount ?? rows.length} passed`,
|
||||
},
|
||||
{
|
||||
id: "unknown-gates",
|
||||
label: "Unknown gates",
|
||||
value: `${executionManifest?.unknownCount ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "next-gate",
|
||||
label: "Next gate",
|
||||
value: missingGateIds[0] ?? "none",
|
||||
},
|
||||
{
|
||||
id: "expected-output-evidence",
|
||||
label: "Expected-output evidence",
|
||||
value: `${evidenceCounts["expected-output"] ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "explicit-result-evidence",
|
||||
label: "Explicit-result evidence",
|
||||
value: `${evidenceCounts["explicit-result"] ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing gate evidence",
|
||||
value: missingGateIds.length > 0 ? missingGateIds.join(", ") : "none",
|
||||
},
|
||||
],
|
||||
gateRows: rows.map((row) => ({
|
||||
id: row.id,
|
||||
label: row.label,
|
||||
command: row.command,
|
||||
expectedOutput: row.expectedOutput ?? null,
|
||||
observedOutput: row.observedOutput ?? null,
|
||||
evidence: row.evidence ?? "missing",
|
||||
status: row.status ?? (row.passed === true ? "passed" : "unknown"),
|
||||
passed: row.passed === true,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectReleaseGateResultMatrix({
|
||||
gateResults = {},
|
||||
observedOutputs = [],
|
||||
@@ -274,6 +349,9 @@ export function createProjectReleaseReadinessReport({
|
||||
observedOutputs,
|
||||
manifest: gateManifest,
|
||||
});
|
||||
const gateExecutionSummaryViewModel = createProjectReleaseGateExecutionSummaryViewModel(
|
||||
gateExecutionManifest,
|
||||
);
|
||||
const gateResultMatrix = createProjectReleaseGateResultMatrix({
|
||||
gateResults,
|
||||
observedOutputs,
|
||||
@@ -318,6 +396,7 @@ export function createProjectReleaseReadinessReport({
|
||||
promotedBlockedFamilies,
|
||||
gateManifest,
|
||||
gateExecutionManifest,
|
||||
gateExecutionSummaryViewModel,
|
||||
gateResultMatrix,
|
||||
gateActionPlan,
|
||||
gates: gateRows,
|
||||
@@ -432,6 +511,11 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
label: "Gate execution manifest",
|
||||
value: validation?.gateExecutionManifestReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-execution-summary",
|
||||
label: "Gate execution summary",
|
||||
value: validation?.gateExecutionSummaryReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-result-matrix",
|
||||
label: "Gate result matrix",
|
||||
@@ -889,6 +973,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const simConfigInventory = objectOrEmpty(artifactObject.simConfigInventory);
|
||||
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
|
||||
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
|
||||
const gateExecutionSummaryViewModel = objectOrEmpty(artifactObject.gateExecutionSummaryViewModel);
|
||||
const gateResultMatrix = objectOrEmpty(artifactObject.gateResultMatrix);
|
||||
const gateActionPlan = objectOrEmpty(artifactObject.gateActionPlan);
|
||||
const gates = arrayOrEmpty(artifactObject.gates);
|
||||
@@ -917,6 +1002,13 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
&& gateExecutionManifest.unknownCount === 0
|
||||
&& executionRows.length === REQUIRED_RELEASE_GATES.length
|
||||
&& executionRows.every(({ command, status }) => typeof command === "string" && status === "passed");
|
||||
const executionSummaryReady = gateExecutionSummaryViewModel.apiName === "project-release-gate-execution-summary-view-model"
|
||||
&& gateExecutionSummaryViewModel.viewModelVersion === 1
|
||||
&& gateExecutionSummaryViewModel.ready === true
|
||||
&& gateExecutionSummaryViewModel.passedCount === REQUIRED_RELEASE_GATES.length
|
||||
&& gateExecutionSummaryViewModel.unknownCount === 0
|
||||
&& gateExecutionSummaryViewModel.nextGateId === null
|
||||
&& arrayOrEmpty(gateExecutionSummaryViewModel.gateRows).length === REQUIRED_RELEASE_GATES.length;
|
||||
const actionPlanReady = gateActionPlan.apiName === "project-release-gate-action-plan"
|
||||
&& gateActionPlan.planVersion === 1
|
||||
&& gateActionPlan.ready === true
|
||||
@@ -942,6 +1034,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
...(arrayOrEmpty(artifactObject.promotedBlockedFamilies).length === 0 ? [] : ["promotedBlockedFamilies"]),
|
||||
...(manifestReady ? [] : ["gateManifest"]),
|
||||
...(executionManifestReady ? [] : ["gateExecutionManifest"]),
|
||||
...(executionSummaryReady ? [] : ["gateExecutionSummaryViewModel"]),
|
||||
...(matrixReady ? [] : ["gateResultMatrix"]),
|
||||
...(actionPlanReady ? [] : ["gateActionPlan"]),
|
||||
...(gateCountReady ? [] : ["gates.length"]),
|
||||
@@ -964,6 +1057,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
expectedGateIds,
|
||||
gateManifestReady: manifestReady,
|
||||
gateExecutionManifestReady: executionManifestReady,
|
||||
gateExecutionSummaryReady: executionSummaryReady,
|
||||
gateResultMatrixReady: matrixReady,
|
||||
gateActionPlanReady: actionPlanReady,
|
||||
blockedRuntimeFamilies: arrayOrEmpty(artifactObject.blockedRuntimeFamilies),
|
||||
@@ -988,6 +1082,11 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
label: "Gate execution manifest",
|
||||
value: executionManifestReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-execution-summary",
|
||||
label: "Gate execution summary",
|
||||
value: executionSummaryReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-result-matrix",
|
||||
label: "Gate result matrix",
|
||||
|
||||
@@ -469,7 +469,7 @@ TOOL_TABLE = browser-shell-tool.tbl
|
||||
);
|
||||
assertEqual(
|
||||
workflowOverviewReleaseArtifactRenderResult.rowCount,
|
||||
7,
|
||||
8,
|
||||
"shell workflow overview release artifact render rows",
|
||||
);
|
||||
assertEqual(
|
||||
@@ -477,6 +477,11 @@ TOOL_TABLE = browser-shell-tool.tbl
|
||||
true,
|
||||
"shell workflow overview release artifact execution manifest row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowOverviewReleaseArtifactRenderResult.rowIds.includes("gate-execution-summary"),
|
||||
true,
|
||||
"shell workflow overview release artifact execution summary row",
|
||||
);
|
||||
assertEqual(
|
||||
workflowOverviewReleaseArtifactMountResult.ready,
|
||||
true,
|
||||
|
||||
@@ -262,14 +262,19 @@
|
||||
.getWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(releaseArtifactUrlWorkflow);
|
||||
assertEqual(releaseArtifactDomReadinessReady.ready, true, "workflow overview release artifact DOM readiness");
|
||||
assertEqual(releaseArtifactRenderResult.rendered, true, "workflow overview release artifact render result");
|
||||
assertEqual(releaseArtifactRenderResult.rowCount, 7, "workflow overview release artifact render row count");
|
||||
assertEqual(releaseArtifactRenderResult.rowCount, 8, "workflow overview release artifact render row count");
|
||||
assertEqual(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
|
||||
true,
|
||||
"workflow overview release artifact execution manifest row",
|
||||
);
|
||||
assertEqual(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-summary"),
|
||||
true,
|
||||
"workflow overview release artifact execution summary row",
|
||||
);
|
||||
assertEqual(releaseArtifactMountResult.ready, true, "workflow overview release artifact mount readiness");
|
||||
assertEqual(releaseArtifactMountResult.renderResult.rowCount, 7, "workflow overview release artifact mount rows");
|
||||
assertEqual(releaseArtifactMountResult.renderResult.rowCount, 8, "workflow overview release artifact mount rows");
|
||||
assertEqual(releaseArtifactUrlWorkflow.ready, true, "workflow overview release artifact URL workflow readiness");
|
||||
assertEqual(releaseArtifactUrlWorkflow.httpStatus, 200, "workflow overview release artifact URL workflow status");
|
||||
assertEqual(
|
||||
|
||||
@@ -35,6 +35,7 @@ for (const phrase of [
|
||||
"createProjectReleaseGateResultMatrix()",
|
||||
"createProjectReleaseGateActionPlan()",
|
||||
"createProjectReleaseGateExecutionManifest()",
|
||||
"createProjectReleaseGateExecutionSummaryViewModel()",
|
||||
"createProjectReleaseReadinessReport()",
|
||||
"createProjectReleaseReadinessSummaryViewModel()",
|
||||
"parseProjectReleaseReadinessArtifactJson()",
|
||||
@@ -118,6 +119,7 @@ for (const phrase of [
|
||||
"createProjectReleaseGateManifest()",
|
||||
"createProjectReleaseGateResultMatrix()",
|
||||
"createProjectReleaseGateActionPlan()",
|
||||
"createProjectReleaseGateExecutionSummaryViewModel()",
|
||||
"createProjectReleaseReadinessReport()",
|
||||
"createProjectReleaseReadinessSummaryViewModel()",
|
||||
"parseProjectReleaseReadinessArtifactJson()",
|
||||
@@ -127,6 +129,7 @@ for (const phrase of [
|
||||
"createProjectReleaseReadinessArtifactValidationSummaryViewModel()",
|
||||
"gateManifestReady",
|
||||
"gateExecutionManifestReady",
|
||||
"gateExecutionSummaryReady",
|
||||
"gateResultMatrixReady",
|
||||
"gateActionPlanReady",
|
||||
"loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl()",
|
||||
|
||||
@@ -327,6 +327,169 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"gateExecutionSummaryViewModel": {
|
||||
"apiName": "project-release-gate-execution-summary-view-model",
|
||||
"viewModelVersion": 1,
|
||||
"phase": "ready",
|
||||
"ready": true,
|
||||
"title": "Project release gate execution",
|
||||
"statusText": "Ready",
|
||||
"detailText": "All release gate evidence present",
|
||||
"statusLine": "Ready: All release gate evidence present",
|
||||
"gateCount": 11,
|
||||
"passedCount": 11,
|
||||
"unknownCount": 0,
|
||||
"missingGateIds": [],
|
||||
"nextGateId": null,
|
||||
"evidenceCounts": {
|
||||
"explicit-result": 1,
|
||||
"expected-output": 10
|
||||
},
|
||||
"rows": [
|
||||
{
|
||||
"id": "gate-results",
|
||||
"label": "Release gate evidence",
|
||||
"value": "11/11 passed"
|
||||
},
|
||||
{
|
||||
"id": "unknown-gates",
|
||||
"label": "Unknown gates",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"id": "next-gate",
|
||||
"label": "Next gate",
|
||||
"value": "none"
|
||||
},
|
||||
{
|
||||
"id": "expected-output-evidence",
|
||||
"label": "Expected-output evidence",
|
||||
"value": "10"
|
||||
},
|
||||
{
|
||||
"id": "explicit-result-evidence",
|
||||
"label": "Explicit-result evidence",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"id": "missing",
|
||||
"label": "Missing gate evidence",
|
||||
"value": "none"
|
||||
}
|
||||
],
|
||||
"gateRows": [
|
||||
{
|
||||
"id": "diff-check",
|
||||
"label": "Git diff check",
|
||||
"command": "git diff --check",
|
||||
"expectedOutput": null,
|
||||
"observedOutput": null,
|
||||
"evidence": "explicit-result",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "vendor-sync",
|
||||
"label": "Vendor sync guard",
|
||||
"command": "wasm-port/tools/verify_vendor_sync.sh",
|
||||
"expectedOutput": "vendor sync up to date",
|
||||
"observedOutput": "vendor sync up to date",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "standalone-cnc-semantics",
|
||||
"label": "Standalone CNC semantics guard",
|
||||
"command": "wasm-port/tools/verify_no_standalone_cnc_semantics.sh",
|
||||
"expectedOutput": "standalone CNC semantics guard complete",
|
||||
"observedOutput": "standalone CNC semantics guard complete",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "interp-wasm",
|
||||
"label": "Interpreter WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh",
|
||||
"expectedOutput": "interp_wasm_node_smoke=ok",
|
||||
"observedOutput": "interp_wasm_node_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "sim-config-inventory",
|
||||
"label": "Sim config inventory WASM Node smoke",
|
||||
"command": "SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh",
|
||||
"expectedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"observedOutput": "sim_configs_wasm_node_inventory_unexpected_fail=0",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "ini-panel-browser",
|
||||
"label": "INI panel browser smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh",
|
||||
"expectedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"observedOutput": "browser_ini_shell_integration_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "opfs-session-browser",
|
||||
"label": "OPFS session browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_opfs_session_workflow_browser.sh",
|
||||
"expectedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"observedOutput": "browser_opfs_session_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "release-artifact-url-browser",
|
||||
"label": "Release artifact URL browser workflow smoke",
|
||||
"command": "SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_release_artifact_url_workflow_browser.sh",
|
||||
"expectedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"observedOutput": "browser_release_artifact_url_workflow_smoke=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "ui-node-smokes",
|
||||
"label": "UI Node smokes",
|
||||
"command": "wasm-port/tests/ui/node/verify_ui_node_smokes.sh",
|
||||
"expectedOutput": "ui_node_smokes=ok",
|
||||
"observedOutput": "ui_node_smokes=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "host-smokes",
|
||||
"label": "Host aggregate smoke",
|
||||
"command": "wasm-port/tests/host/verify_host_smokes.sh",
|
||||
"expectedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"observedOutput": "host_wasm_opfs_browser_smokes=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"id": "project-release-gate",
|
||||
"label": "Project release gate",
|
||||
"command": "wasm-port/tests/host/verify_project_release_gate.sh",
|
||||
"expectedOutput": "project_release_gate=ok",
|
||||
"observedOutput": "project_release_gate=ok",
|
||||
"evidence": "expected-output",
|
||||
"status": "passed",
|
||||
"passed": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"gateResultMatrix": {
|
||||
"apiName": "project-release-gate-result-matrix",
|
||||
"matrixVersion": 1,
|
||||
|
||||
@@ -24,6 +24,7 @@ assert.equal(validation.gateCount, 11);
|
||||
assert.equal(validation.expectedGateCount, 11);
|
||||
assert.equal(validation.gateManifestReady, true);
|
||||
assert.equal(validation.gateExecutionManifestReady, true);
|
||||
assert.equal(validation.gateExecutionSummaryReady, true);
|
||||
assert.equal(validation.gateResultMatrixReady, true);
|
||||
assert.equal(validation.gateActionPlanReady, true);
|
||||
assert.deepEqual(validation.expectedGateIds, [
|
||||
@@ -42,6 +43,8 @@ assert.deepEqual(validation.expectedGateIds, [
|
||||
assert.equal(artifact.gateManifest.apiName, "project-release-gate-manifest");
|
||||
assert.equal(artifact.gateExecutionManifest.apiName, "project-release-gate-execution-manifest");
|
||||
assert.equal(artifact.gateExecutionManifest.passedCount, 11);
|
||||
assert.equal(artifact.gateExecutionSummaryViewModel.apiName, "project-release-gate-execution-summary-view-model");
|
||||
assert.equal(artifact.gateExecutionSummaryViewModel.rows[0].value, "11/11 passed");
|
||||
assert.equal(artifact.gateResultMatrix.apiName, "project-release-gate-result-matrix");
|
||||
assert.equal(artifact.gateActionPlan.apiName, "project-release-gate-action-plan");
|
||||
assert.equal(artifact.gateActionPlan.pendingCount, 0);
|
||||
|
||||
@@ -3,6 +3,7 @@ import assert from "node:assert/strict";
|
||||
import {
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
createProjectReleaseGateExecutionSummaryViewModel,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseGateResultMatrix,
|
||||
createProjectReleaseReadinessArtifactJsonWorkflow,
|
||||
@@ -126,6 +127,37 @@ assert.equal(
|
||||
partialExecutionManifest.rows.find(({ id }) => id === "standalone-cnc-semantics")?.observedOutput,
|
||||
null,
|
||||
);
|
||||
const partialExecutionSummary = createProjectReleaseGateExecutionSummaryViewModel(partialExecutionManifest);
|
||||
assert.equal(partialExecutionSummary.apiName, "project-release-gate-execution-summary-view-model");
|
||||
assert.equal(partialExecutionSummary.viewModelVersion, 1);
|
||||
assert.equal(partialExecutionSummary.phase, "waiting");
|
||||
assert.equal(partialExecutionSummary.ready, false);
|
||||
assert.equal(partialExecutionSummary.statusLine, "Waiting: standalone-cnc-semantics, interp-wasm, sim-config-inventory, ini-panel-browser, opfs-session-browser, ui-node-smokes, host-smokes, project-release-gate");
|
||||
assert.equal(partialExecutionSummary.gateCount, 11);
|
||||
assert.equal(partialExecutionSummary.passedCount, 3);
|
||||
assert.equal(partialExecutionSummary.unknownCount, 8);
|
||||
assert.equal(partialExecutionSummary.nextGateId, "standalone-cnc-semantics");
|
||||
assert.deepEqual(partialExecutionSummary.evidenceCounts, {
|
||||
"explicit-result": 1,
|
||||
"expected-output": 2,
|
||||
missing: 8,
|
||||
});
|
||||
assert.deepEqual(
|
||||
partialExecutionSummary.rows.map(({ id, value }) => [id, value]),
|
||||
[
|
||||
["gate-results", "3/11 passed"],
|
||||
["unknown-gates", "8"],
|
||||
["next-gate", "standalone-cnc-semantics"],
|
||||
["expected-output-evidence", "2"],
|
||||
["explicit-result-evidence", "1"],
|
||||
["missing", "standalone-cnc-semantics, interp-wasm, sim-config-inventory, ini-panel-browser, opfs-session-browser, ui-node-smokes, host-smokes, project-release-gate"],
|
||||
],
|
||||
);
|
||||
assert.equal(partialExecutionSummary.gateRows.length, manifest.gateCount);
|
||||
assert.equal(
|
||||
partialExecutionSummary.gateRows.find(({ id }) => id === "vendor-sync")?.evidence,
|
||||
"expected-output",
|
||||
);
|
||||
|
||||
const partialActionPlan = createProjectReleaseGateActionPlan({ gateResultMatrix: partialMatrix });
|
||||
assert.equal(partialActionPlan.apiName, "project-release-gate-action-plan");
|
||||
@@ -166,6 +198,10 @@ assert.deepEqual(report.gateManifest, manifest);
|
||||
assert.equal(report.gateExecutionManifest.apiName, "project-release-gate-execution-manifest");
|
||||
assert.equal(report.gateExecutionManifest.ready, true);
|
||||
assert.equal(report.gateExecutionManifest.passedCount, manifest.gateCount);
|
||||
assert.equal(report.gateExecutionSummaryViewModel.apiName, "project-release-gate-execution-summary-view-model");
|
||||
assert.equal(report.gateExecutionSummaryViewModel.statusLine, "Ready: All release gate evidence present");
|
||||
assert.equal(report.gateExecutionSummaryViewModel.rows[0].value, "11/11 passed");
|
||||
assert.equal(report.gateExecutionSummaryViewModel.nextGateId, null);
|
||||
assert.equal(report.gateResultMatrix.ready, true);
|
||||
assert.equal(report.gateResultMatrix.passedCount, manifest.gateCount);
|
||||
assert.equal(report.gateActionPlan.ready, true);
|
||||
@@ -256,6 +292,7 @@ assert.deepEqual(
|
||||
["gate-count", "11/11"],
|
||||
["gate-manifest", "ready"],
|
||||
["gate-execution-manifest", "ready"],
|
||||
["gate-execution-summary", "ready"],
|
||||
["gate-result-matrix", "ready"],
|
||||
["gate-action-plan", "ready"],
|
||||
["missing", "none"],
|
||||
@@ -383,6 +420,10 @@ assert.equal(
|
||||
staleArtifactValidationSummary.rows.find(({ id }) => id === "gate-execution-manifest")?.value,
|
||||
"missing",
|
||||
);
|
||||
assert.equal(
|
||||
staleArtifactValidationSummary.rows.find(({ id }) => id === "gate-execution-summary")?.value,
|
||||
"missing",
|
||||
);
|
||||
assert.equal(staleArtifactValidationActionPlan.phase, "blocked");
|
||||
assert.equal(staleArtifactValidationActionPlan.ready, false);
|
||||
assert.equal(staleArtifactValidationActionPlan.missingCount, staleArtifactValidation.missing.length);
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
createMachineSessionPersistenceSummary,
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
createProjectReleaseGateExecutionSummaryViewModel,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseGateResultMatrix,
|
||||
createProjectReleaseReadinessArtifactJsonWorkflow,
|
||||
@@ -98,6 +99,7 @@ const requiredExports = [
|
||||
["createLinuxCncInterpSdk", createLinuxCncInterpSdk],
|
||||
["createProjectReleaseGateActionPlan", createProjectReleaseGateActionPlan],
|
||||
["createProjectReleaseGateExecutionManifest", createProjectReleaseGateExecutionManifest],
|
||||
["createProjectReleaseGateExecutionSummaryViewModel", createProjectReleaseGateExecutionSummaryViewModel],
|
||||
["createProjectReleaseGateManifest", createProjectReleaseGateManifest],
|
||||
["createProjectReleaseGateResultMatrix", createProjectReleaseGateResultMatrix],
|
||||
["createProjectReleaseReadinessArtifactJsonWorkflow", createProjectReleaseReadinessArtifactJsonWorkflow],
|
||||
@@ -294,6 +296,7 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
expectedGateIds: createProjectReleaseGateManifest().gateIds,
|
||||
gateManifestReady: true,
|
||||
gateExecutionManifestReady: true,
|
||||
gateExecutionSummaryReady: true,
|
||||
gateResultMatrixReady: true,
|
||||
gateActionPlanReady: true,
|
||||
blockedRuntimeFamilies: [
|
||||
@@ -322,6 +325,11 @@ assert.deepEqual(releaseReadinessArtifactValidation, {
|
||||
label: "Gate execution manifest",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "gate-execution-summary",
|
||||
label: "Gate execution summary",
|
||||
value: "ready",
|
||||
},
|
||||
{
|
||||
id: "gate-result-matrix",
|
||||
label: "Gate result matrix",
|
||||
@@ -426,6 +434,7 @@ assert.deepEqual(
|
||||
"blockedRuntimeFamilies",
|
||||
"gateManifest",
|
||||
"gateExecutionManifest",
|
||||
"gateExecutionSummaryViewModel",
|
||||
"gateResultMatrix",
|
||||
"gateActionPlan",
|
||||
"gates.length",
|
||||
|
||||
@@ -1366,18 +1366,22 @@ const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseRead
|
||||
rowsNode: releaseArtifactRowsNode,
|
||||
});
|
||||
assert.equal(releaseArtifactRenderResult.rendered, true);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 7);
|
||||
assert.equal(releaseArtifactRenderResult.rowCount, 8);
|
||||
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-manifest"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-execution-summary"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
releaseArtifactRenderResult.rowIds.includes("gate-action-plan"),
|
||||
true,
|
||||
);
|
||||
assert.equal(releaseArtifactMountResult.ready, true);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 7);
|
||||
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 8);
|
||||
assert.deepEqual(
|
||||
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
|
||||
["artifact-json"],
|
||||
@@ -1418,7 +1422,7 @@ assert.equal(
|
||||
);
|
||||
assert.equal(releaseArtifactUrlWorkflow.renderState.statusLine, "Ready: No blocking reasons");
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.ready, true);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 7);
|
||||
assert.equal(releaseArtifactUrlWorkflow.mountResult.renderResult.rowCount, 8);
|
||||
const releaseArtifactUrlWorkflowSummary =
|
||||
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrlWorkflowSummaryViewModel(
|
||||
releaseArtifactUrlWorkflow,
|
||||
|
||||
Reference in New Issue
Block a user