暴露 workflow overview 发布 artifact 校验 API

This commit is contained in:
2026-06-16 09:46:29 +08:00
parent 7177a29fc6
commit 23f337834b
15 changed files with 300 additions and 2 deletions

View File

@@ -63,6 +63,7 @@ import {
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -149,6 +150,12 @@ status, and handoff readiness rows. The launch page exposes the same helper as
`linuxCncIniPanelLaunchApi.getMachineSessionPersistenceSummary()`, and the
workflow overview page exposes it as
`linuxCncIniPanelWorkflowOverviewApi.getWorkflowOverviewPersistenceSummary()`.
Use `validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson()` or
`linuxCncIniPanelWorkflowOverviewApi.validateWorkflowOverviewReleaseReadinessArtifactJson()`
when an outer shell needs to validate a project release readiness artifact JSON
through the same read-only workflow overview surface. It parses the artifact,
returns stable validation rows, and does not execute release gates or CNC
behavior.
Use `createMachineSessionPersistenceDisplayViewModel()` and
`createMachineSessionPersistenceRenderState()` when that summary needs stable
display text, rows, status line, and dataset fields for caller-owned DOM.

View File

@@ -44,6 +44,9 @@ continuation records are in `../text14.txt`.
validates it with `verify_project_release_readiness_artifact.sh`. External
tools can load that artifact with `parseProjectReleaseReadinessArtifactJson()`
and validate it with `createProjectReleaseReadinessArtifactValidation()`.
Browser shells can also pass the JSON to
`linuxCncIniPanelWorkflowOverviewApi.validateWorkflowOverviewReleaseReadinessArtifactJson()`
through the workflow overview iframe and receive stable validation rows.
- OPFS/session callers can use `createMachineSessionPersistenceSummary()` or
`linuxCncIniPanelApi.getMachineSessionPersistenceSummary()` to inspect
machine files, session snapshot, session readiness, session load, readonly

View File

@@ -82,6 +82,7 @@ import {
saveTextFile,
sessionSnapshotPath,
toolTablePath,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
validateSessionSnapshot,
} from "./src/index.js";
```
@@ -263,6 +264,9 @@ for external browser shells:
read-only `persistence-summary` row.
- `createIniPanelShellWorkflowOverviewContract()` for discovering the workflow
overview iframe API contract.
- `validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson()` for the
read-only workflow overview artifact validation wrapper exposed by
`workflow-overview.html`.
- `createIniPanelShellApiSurfaceInventory()` for a machine-readable inventory
of launch, control-page, workflow overview, persistence, and session
readiness report API counts, including persistence summary row counts.

View File

@@ -113,4 +113,5 @@ export {
renderIniPanelShellSessionHandoffMountState,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
renderIniPanelShellWorkflowOverviewEmbeddingState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
} from "../../ui/ini-panel/ui-shell.js";

View File

@@ -31,6 +31,10 @@ import {
import {
createMachineSessionPersistenceSummary,
} from "./panel-state-summary.js";
import {
createProjectReleaseReadinessArtifactValidation,
parseProjectReleaseReadinessArtifactJson,
} from "../../sdk/src/project-release-readiness.js";
export {
controlPageStatusText,
createControlPageRefreshState,
@@ -72,6 +76,10 @@ export {
createMachineSessionWorkflowOverview,
createMachineSessionWorkflowStatus,
} from "./panel-state-summary.js";
export {
createProjectReleaseReadinessArtifactValidation,
parseProjectReleaseReadinessArtifactJson,
} from "../../sdk/src/project-release-readiness.js";
export function getVisibleIniPanelEntries() {
return getIniPanelEntryManifest();
@@ -1865,6 +1873,7 @@ export function createIniPanelShellWorkflowOverviewContract() {
"getWorkflowOverviewSessionReadinessReport",
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -1874,6 +1883,46 @@ export function createIniPanelShellWorkflowOverviewContract() {
};
}
export function validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(artifactJson) {
try {
const artifact = parseProjectReleaseReadinessArtifactJson(artifactJson);
const validation = createProjectReleaseReadinessArtifactValidation(artifact);
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
validationVersion: 1,
phase: validation.ready ? "ready" : "blocked",
ready: validation.ready,
missing: [...validation.missing],
error: null,
artifactApiName: validation.artifactApiName,
artifactVersion: validation.artifactVersion,
gateCount: validation.gateCount,
validation,
rows: [...validation.rows],
};
} catch (error) {
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
validationVersion: 1,
phase: "blocked",
ready: false,
missing: ["artifact-json"],
error: error?.message ?? "Unable to parse release readiness artifact JSON",
artifactApiName: null,
artifactVersion: null,
gateCount: 0,
validation: null,
rows: [
{
id: "artifact-json",
label: "Readiness artifact JSON",
value: "blocked",
},
],
};
}
}
export function createIniPanelShellWorkflowOverviewReadiness({
overviewApi = null,
contract = createIniPanelShellWorkflowOverviewContract(),

View File

@@ -105,6 +105,7 @@
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
} from "./ui-shell.js";
@@ -133,6 +134,9 @@
getWorkflowOverviewPersistenceSummary: (options) => (
createMachineSessionPersistenceSummary(options)
),
validateWorkflowOverviewReleaseReadinessArtifactJson: (artifactJson) => (
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(artifactJson)
),
getWorkflowOverviewDomContract: (options) => (
createIniPanelShellSessionHandoffWorkflowDomContract(options)
),

View File

@@ -309,6 +309,39 @@ TOOL_TABLE = browser-shell-tool.tbl
const workflowOverviewReadiness = launchApi.getWorkflowOverviewReadiness({
overviewApi: workflowOverviewApi,
});
const workflowOverviewReleaseArtifactValidation = workflowOverviewApi
.validateWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify({
apiName: "project-release-readiness-report",
reportVersion: 1,
phase: "ready",
ready: true,
missing: [],
releaseGate: {
command: "wasm-port/tests/host/verify_project_release_gate.sh",
passed: true,
expectedOutput: "project_release_gate=ok",
},
simConfigInventory: {
executed: 28,
passed: 28,
skipped: 131,
unexpectedFail: 0,
},
blockedRuntimeFamilies: [
"L4-USER-M-PROCESS",
"L4-TOOL-DB",
"L4-PYTHON-REMAP",
],
promotedBlockedFamilies: [],
gates: Array.from({ length: 9 }, (_, index) => ({ id: `gate-${index}`, passed: true })),
rows: [
{
id: "project-release-gate",
label: "Project release gate",
value: "passed",
},
],
}));
const workflowOverviewEmbedding = launchApi.mountWorkflowOverviewEmbedding({
overviewApi: workflowOverviewApi,
});
@@ -370,6 +403,16 @@ TOOL_TABLE = browser-shell-tool.tbl
});
assertEqual(workflowOverviewReadiness.ready, true, "shell workflow overview iframe readiness");
assertEqual(workflowOverviewReadiness.missing.join(","), "", "shell workflow overview iframe missing methods");
assertEqual(
workflowOverviewReleaseArtifactValidation.apiName,
"ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
"shell workflow overview release artifact validation API",
);
assertEqual(
workflowOverviewReleaseArtifactValidation.ready,
true,
"shell workflow overview release artifact validation readiness",
);
assertEqual(workflowOverviewEmbedding.apiName, "ini-panel-shell-workflow-overview-embedding", "shell workflow overview embedding API");
assertEqual(workflowOverviewEmbedding.renderState.dataset.handoffScope, "workflow", "shell workflow overview embedding scope");
assertEqual(workflowOverviewEmbedding.mountResult.renderResult.rowCount, 8, "shell workflow overview embedding rows");

View File

@@ -34,6 +34,7 @@
!workflowApi?.getWorkflowOverviewSessionReadinessReport ||
!workflowApi?.getWorkflowOverviewApiSurfaceInventory ||
!workflowApi?.getWorkflowOverviewPersistenceSummary ||
!workflowApi?.validateWorkflowOverviewReleaseReadinessArtifactJson ||
!workflowApi?.getWorkflowOverviewDomContract ||
!workflowApi?.getWorkflowOverviewDomReadiness ||
!workflowApi?.renderWorkflowOverview ||
@@ -62,6 +63,38 @@
const sessionReadinessReport = workflowApi.getWorkflowOverviewSessionReadinessReport();
const apiSurfaceInventory = workflowApi.getWorkflowOverviewApiSurfaceInventory();
const persistenceSummary = workflowApi.getWorkflowOverviewPersistenceSummary();
const releaseArtifactValidation = workflowApi.validateWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify({
apiName: "project-release-readiness-report",
reportVersion: 1,
phase: "ready",
ready: true,
missing: [],
releaseGate: {
command: "wasm-port/tests/host/verify_project_release_gate.sh",
passed: true,
expectedOutput: "project_release_gate=ok",
},
simConfigInventory: {
executed: 28,
passed: 28,
skipped: 131,
unexpectedFail: 0,
},
blockedRuntimeFamilies: [
"L4-USER-M-PROCESS",
"L4-TOOL-DB",
"L4-PYTHON-REMAP",
],
promotedBlockedFamilies: [],
gates: Array.from({ length: 9 }, (_, index) => ({ id: `gate-${index}`, passed: true })),
rows: [
{
id: "project-release-gate",
label: "Project release gate",
value: "passed",
},
],
}));
const domContract = workflowApi.getWorkflowOverviewDomContract();
const domReadiness = workflowApi.getWorkflowOverviewDomReadiness();
const renderResult = workflowApi.renderWorkflowOverview();
@@ -107,6 +140,13 @@
"workflow overview persistence summary API name",
);
assertEqual(persistenceSummary.rows.length, 7, "workflow overview persistence summary rows");
assertEqual(
releaseArtifactValidation.apiName,
"ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
"workflow overview release artifact validation API name",
);
assertEqual(releaseArtifactValidation.ready, true, "workflow overview release artifact validation readiness");
assertEqual(releaseArtifactValidation.gateCount, 9, "workflow overview release artifact validation gates");
assertEqual(displayViewModel.title, "Shell handoff workflow", "workflow overview display title");
assertEqual(renderState.renderStateVersion, 1, "workflow overview render-state version");
assertEqual(renderState.dataset.handoffScope, "workflow", "workflow overview render-state scope");

View File

@@ -34,6 +34,7 @@ for (const phrase of [
"createProjectReleaseReadinessReport()",
"parseProjectReleaseReadinessArtifactJson()",
"createProjectReleaseReadinessArtifactValidation()",
"validateWorkflowOverviewReleaseReadinessArtifactJson()",
"createIniPanelShellApiSurfaceInventory()",
"createIniPanelShellSessionReadinessWorkflowReport()",
"workflow overview embedding mount DOM",

View File

@@ -63,6 +63,7 @@ import {
saveTextFile,
sessionSnapshotPath,
toolTablePath,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
validateSessionSnapshot,
} from "../../../runtime/sdk/src/index.js";
@@ -78,6 +79,10 @@ const requiredExports = [
["createProjectReleaseReadinessArtifactValidation", createProjectReleaseReadinessArtifactValidation],
["createProjectReleaseReadinessReport", createProjectReleaseReadinessReport],
["parseProjectReleaseReadinessArtifactJson", parseProjectReleaseReadinessArtifactJson],
[
"validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson",
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
],
["planIniFileContextStaging", planIniFileContextStaging],
["planSimConfigStaging", planSimConfigStaging],
["analyzeIniRuntimeBoundaries", analyzeIniRuntimeBoundaries],
@@ -241,6 +246,10 @@ assert.deepEqual(
"rows.project-release-gate",
],
);
assert.equal(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)).ready,
true,
);
assert.equal(
createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],

View File

@@ -53,6 +53,7 @@ import {
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -154,6 +155,7 @@ const requiredShellExports = [
"createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness",
"renderIniPanelShellWorkflowOverviewEmbeddingMountState",
"mountIniPanelShellWorkflowOverviewEmbeddingMountState",
"validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson",
"renderIniPanelShellSessionHandoffWorkflowState",
"mountIniPanelShellSessionHandoffWorkflow",
"renderIniPanelShellSessionHandoffMountState",

View File

@@ -51,6 +51,7 @@ import {
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
createIniPanelShellSessionHandoffPackageReport,
@@ -780,6 +781,7 @@ assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), {
"getWorkflowOverviewSessionReadinessReport",
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -817,6 +819,11 @@ assert.equal(typeof createIniPanelShellWorkflowOverviewEmbeddingMountDomContract
assert.equal(typeof createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness, "function");
assert.equal(typeof renderIniPanelShellWorkflowOverviewEmbeddingMountState, "function");
assert.equal(typeof mountIniPanelShellWorkflowOverviewEmbeddingMountState, "function");
assert.equal(typeof validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson, "function");
assert.equal(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{}").apiName,
"ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
);
assert.deepEqual(
createIniPanelShellWorkflowOverviewReadiness({
overviewApi: {
@@ -829,6 +836,7 @@ assert.deepEqual(
"getWorkflowOverviewDisplayViewModel",
"getWorkflowOverviewSummary",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",

View File

@@ -51,6 +51,7 @@ import {
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -674,6 +675,7 @@ assert.deepEqual(shellViewModel.shellWorkflowOverviewContract, {
"getWorkflowOverviewSessionReadinessReport",
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -1269,6 +1271,52 @@ assert.equal(workflowDomMountResult.ready, false);
assert.equal(workflowDomMountResult.renderResult.rowCount, 8);
assert.equal(workflowDomMountResult.renderResult.dataset.handoffScope, "workflow");
assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), shellViewModel.shellWorkflowOverviewContract);
const releaseReadinessArtifactJson = JSON.stringify({
apiName: "project-release-readiness-report",
reportVersion: 1,
phase: "ready",
ready: true,
missing: [],
releaseGate: {
command: "wasm-port/tests/host/verify_project_release_gate.sh",
passed: true,
expectedOutput: "project_release_gate=ok",
},
simConfigInventory: {
executed: 28,
passed: 28,
skipped: 131,
unexpectedFail: 0,
},
blockedRuntimeFamilies: [
"L4-USER-M-PROCESS",
"L4-TOOL-DB",
"L4-PYTHON-REMAP",
],
promotedBlockedFamilies: [],
gates: Array.from({ length: 9 }, (_, index) => ({ id: `gate-${index}`, passed: true })),
rows: [
{
id: "project-release-gate",
label: "Project release gate",
value: "passed",
},
],
});
const releaseArtifactValidation = validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(
releaseReadinessArtifactJson,
);
assert.equal(
releaseArtifactValidation.apiName,
"ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
);
assert.equal(releaseArtifactValidation.ready, true);
assert.equal(releaseArtifactValidation.validation.ready, true);
assert.equal(releaseArtifactValidation.gateCount, 9);
assert.deepEqual(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
["artifact-json"],
);
assert.deepEqual(createIniPanelShellWorkflowOverviewReadiness(), {
apiName: "ini-panel-shell-workflow-overview-readiness",
readinessVersion: 1,
@@ -1284,6 +1332,7 @@ const workflowOverviewApi = {
getWorkflowOverviewSessionReadinessReport: () => sessionReadinessWorkflowReport,
getWorkflowOverviewApiSurfaceInventory: () => shellViewModel.shellApiSurfaceInventory,
getWorkflowOverviewPersistenceSummary: () => shellViewModel.shellPersistenceSummary,
validateWorkflowOverviewReleaseReadinessArtifactJson: () => ({ ready: true }),
getWorkflowOverviewDomContract: createIniPanelShellSessionHandoffWorkflowDomContract,
getWorkflowOverviewDomReadiness: createIniPanelShellSessionHandoffWorkflowDomReadiness,
renderWorkflowOverview: renderIniPanelShellSessionHandoffWorkflowState,