推进 workflow overview 发布 artifact DOM workflow

This commit is contained in:
2026-06-16 10:03:23 +08:00
parent 23f337834b
commit b63669588c
15 changed files with 644 additions and 4 deletions

View File

@@ -64,6 +64,12 @@ import {
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -156,6 +162,15 @@ 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 `createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness()`,
`renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState()`, or
`mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState()` when that
validation needs to be rendered into caller-owned DOM. The workflow overview
page exposes equivalent methods with the `getWorkflowOverview...`,
`renderWorkflowOverview...`, and `mountWorkflowOverview...` prefixes.
Use `createMachineSessionPersistenceDisplayViewModel()` and
`createMachineSessionPersistenceRenderState()` when that summary needs stable
display text, rows, status line, and dataset fields for caller-owned DOM.

View File

@@ -46,7 +46,10 @@ continuation records are in `../text14.txt`.
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.
through the workflow overview iframe and receive stable validation rows. When
the outer shell needs DOM output, the workflow overview iframe also exposes
display, render-state, DOM readiness, renderer, and mount helpers for the
same release readiness artifact validation.
- OPFS/session callers can use `createMachineSessionPersistenceSummary()` or
`linuxCncIniPanelApi.getMachineSessionPersistenceSummary()` to inspect
machine files, session snapshot, session readiness, session load, readonly

View File

@@ -41,6 +41,10 @@ import {
createIniPanelShellWorkflowOverviewContract,
createIniPanelShellWorkflowOverviewEmbeddingMountDomContract,
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createLinuxCncIniSdk,
createLinuxCncInterpSdk,
createMachineSessionPersistenceDisplayViewModel,
@@ -68,6 +72,7 @@ import {
machineFilePaths,
machineIniPath,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
normalizeOpfsPath,
parameterFilePath,
parseProjectReleaseReadinessArtifactJson,
@@ -75,6 +80,7 @@ import {
planSimConfigStaging,
readMachineSessionReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
restoreMachineParametersFromOpfs,
saveMachineSessionSnapshot,
saveMachineTextFiles,
@@ -266,7 +272,14 @@ for external browser shells:
overview iframe API contract.
- `validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson()` for the
read-only workflow overview artifact validation wrapper exposed by
`workflow-overview.html`.
`workflow-overview.html`. Use
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract()`,
`createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness()`,
`renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState()`, and
`mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState()` when an
outer shell needs to render that validation into caller-owned DOM.
- `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

@@ -97,6 +97,10 @@ export {
createIniPanelShellWorkflowOverviewEmbeddingMountRenderState,
createIniPanelShellWorkflowOverviewEmbeddingRenderState,
createIniPanelShellWorkflowOverviewEmbeddingReport,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReadiness,
getIniPanelEntryByHref,
getIniPanelEntryManifest,
@@ -111,7 +115,9 @@ export {
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingState,
renderIniPanelShellSessionHandoffMountState,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
renderIniPanelShellWorkflowOverviewEmbeddingState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
} from "../../ui/ini-panel/ui-shell.js";

View File

@@ -1874,6 +1874,12 @@ export function createIniPanelShellWorkflowOverviewContract() {
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
"getWorkflowOverviewReleaseReadinessArtifactRenderState",
"getWorkflowOverviewReleaseReadinessArtifactDomContract",
"getWorkflowOverviewReleaseReadinessArtifactDomReadiness",
"renderWorkflowOverviewReleaseReadinessArtifactState",
"mountWorkflowOverviewReleaseReadinessArtifactState",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -1923,6 +1929,240 @@ export function validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJso
}
}
export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(
validation = validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{}"),
) {
const missing = Array.isArray(validation?.missing) ? validation.missing : [];
const rows = Array.isArray(validation?.rows)
? validation.rows.map(({ id, label, value }) => ({
id,
label,
value: value == null ? "" : String(value),
}))
: [];
return {
phase: validation?.phase === "ready" ? "ready" : "blocked",
title: "Release readiness artifact",
statusText: validation?.ready ? "Ready" : "Blocked",
detailText: validation?.ready
? "No blocking reasons"
: (missing.length > 0 ? missing.join(", ") : validation?.error ?? "artifact validation blocked"),
rows,
};
}
export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(
displayViewModel = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(),
) {
const rows = Array.isArray(displayViewModel?.rows)
? displayViewModel.rows.map(({ id, label, value }) => ({
id,
label,
value: value == null ? "" : String(value),
}))
: [];
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Blocked");
const detailText = displayViewModel?.detailText ?? "No blocking reasons";
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-render-state",
renderStateVersion: 1,
phase: ready ? "ready" : "blocked",
ready,
title: displayViewModel?.title ?? "Release readiness artifact",
statusText,
detailText,
statusLine: `${statusText}: ${detailText}`,
rows,
dataset: {
handoffPhase: ready ? "ready" : "blocked",
handoffReady: ready ? "true" : "false",
handoffScope: "workflow-overview-release-readiness-artifact",
},
};
}
export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract({
rowDatasetPrefix = "workflowOverviewReleaseReadinessArtifact",
selectors = {},
} = {}) {
const mountSelector = selectors.mount ?? "[data-workflow-overview-release-readiness-artifact]";
const statusSelector = selectors.status ?? "[data-workflow-overview-release-readiness-artifact-status]";
const rowsSelector = selectors.rows ?? "[data-workflow-overview-release-readiness-artifact-rows]";
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-dom-contract",
contractVersion: 1,
requiredNodeIds: ["mount", "status", "rows"],
selectors: {
mount: mountSelector,
status: statusSelector,
rows: rowsSelector,
},
mountDatasetKeys: ["handoffPhase", "handoffReady", "handoffScope"],
rowDatasetPrefix,
rowDatasetKeys: {
term: [`${rowDatasetPrefix}Row`, `${rowDatasetPrefix}Status`],
detail: [`${rowDatasetPrefix}Value`, `${rowDatasetPrefix}Status`],
},
renderResultFields: ["rendered", "statusLine", "rowCount", "rowIds", "dataset"],
};
}
export function createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness({
rowDatasetPrefix = "workflowOverviewReleaseReadinessArtifact",
contract = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {}) {
const checks = {
document: Boolean(documentRef?.createElement),
mount: Boolean(mountNode),
status: Boolean(statusNode),
rows: Boolean(rowsNode),
rowDatasetPrefix: Boolean(contract.rowDatasetPrefix),
};
const missing = Object.entries(checks)
.filter(([, passed]) => !passed)
.map(([name]) => name);
const ready = missing.length === 0;
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-dom-readiness",
readinessVersion: 1,
phase: ready ? "ready" : "blocked",
ready,
missing,
checks,
contract,
};
}
export function renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState(
renderState = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(),
{
rowDatasetPrefix = "workflowOverviewReleaseReadinessArtifact",
contract = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {},
) {
const readiness = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness({
contract,
documentRef,
mountNode,
statusNode,
rowsNode,
});
if (!readiness.ready) {
throw new Error(
`Workflow overview release readiness artifact DOM is not ready: ${readiness.missing.join(", ")}`,
);
}
mountNode.dataset.handoffPhase = renderState?.dataset?.handoffPhase ?? "blocked";
mountNode.dataset.handoffReady = renderState?.dataset?.handoffReady ?? "false";
mountNode.dataset.handoffScope = renderState?.dataset?.handoffScope
?? "workflow-overview-release-readiness-artifact";
statusNode.textContent = renderState?.statusLine ?? "Blocked: No release readiness artifact render state";
rowsNode.replaceChildren();
const rows = Array.isArray(renderState?.rows) ? renderState.rows : [];
const effectiveRowDatasetPrefix = contract.rowDatasetPrefix;
for (const row of rows) {
const term = documentRef.createElement("dt");
term.dataset[`${effectiveRowDatasetPrefix}Row`] = row.id;
term.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
term.textContent = row.label;
const detail = documentRef.createElement("dd");
detail.dataset[`${effectiveRowDatasetPrefix}Value`] = row.id;
detail.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
detail.textContent = row.value;
rowsNode.append(term, detail);
}
return {
rendered: true,
statusLine: statusNode.textContent,
rowCount: rows.length,
rowIds: rows.map(({ id }) => id),
dataset: {
handoffPhase: mountNode.dataset.handoffPhase,
handoffReady: mountNode.dataset.handoffReady,
handoffScope: mountNode.dataset.handoffScope,
},
};
}
export function mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState({
renderState = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(),
rowDatasetPrefix = "workflowOverviewReleaseReadinessArtifact",
contract = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract({ rowDatasetPrefix }),
documentRef = globalThis.document,
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
statusNode = documentRef?.querySelector?.(contract.selectors.status),
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
} = {}) {
const domReadiness = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness({
contract,
documentRef,
mountNode,
statusNode,
rowsNode,
});
if (!domReadiness.ready) {
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-dom-mount",
workflowVersion: 1,
phase: "blocked",
ready: false,
statusLine: `Blocked: ${domReadiness.missing.join(", ")}`,
contract,
domReadiness,
renderState,
renderResult: null,
error: null,
};
}
try {
const renderResult = renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState(renderState, {
contract,
documentRef,
mountNode,
statusNode,
rowsNode,
});
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-dom-mount",
workflowVersion: 1,
phase: renderState?.phase === "ready" ? "ready" : "blocked",
ready: renderState?.ready === true,
statusLine: renderResult.statusLine,
contract,
domReadiness,
renderState,
renderResult,
error: null,
};
} catch (error) {
return {
apiName: "ini-panel-shell-workflow-overview-release-readiness-artifact-dom-mount",
workflowVersion: 1,
phase: "blocked",
ready: false,
statusLine: `Blocked: ${error?.message ?? "release readiness artifact DOM mount error"}`,
contract,
domReadiness,
renderState,
renderResult: null,
error: error?.message ?? String(error),
};
}
}
export function createIniPanelShellWorkflowOverviewReadiness({
overviewApi = null,
contract = createIniPanelShellWorkflowOverviewContract(),

View File

@@ -106,6 +106,12 @@
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
} from "./ui-shell.js";
@@ -137,6 +143,24 @@
validateWorkflowOverviewReleaseReadinessArtifactJson: (artifactJson) => (
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(artifactJson)
),
getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel: (validation) => (
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(validation)
),
getWorkflowOverviewReleaseReadinessArtifactRenderState: (displayViewModel) => (
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(displayViewModel)
),
getWorkflowOverviewReleaseReadinessArtifactDomContract: (options) => (
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract(options)
),
getWorkflowOverviewReleaseReadinessArtifactDomReadiness: (options) => (
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness(options ?? { documentRef: document })
),
renderWorkflowOverviewReleaseReadinessArtifactState: (renderState, options) => (
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState(renderState, options ?? { documentRef: document })
),
mountWorkflowOverviewReleaseReadinessArtifactState: (options) => (
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState(options ?? { documentRef: document })
),
getWorkflowOverviewDomContract: (options) => (
createIniPanelShellSessionHandoffWorkflowDomContract(options)
),

View File

@@ -18,6 +18,10 @@
<p data-external-overview-embedding-status>waiting</p>
<dl data-external-overview-embedding-rows></dl>
</section>
<section data-external-release-artifact>
<p data-external-release-artifact-status>waiting</p>
<dl data-external-release-artifact-rows></dl>
</section>
<script type="module">
function assertEqual(actual, expected, label) {
if (actual !== expected) {
@@ -342,6 +346,38 @@ TOOL_TABLE = browser-shell-tool.tbl
},
],
}));
const workflowOverviewReleaseArtifactDisplay = workflowOverviewApi
.getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(workflowOverviewReleaseArtifactValidation);
const workflowOverviewReleaseArtifactRenderState = workflowOverviewApi
.getWorkflowOverviewReleaseReadinessArtifactRenderState(workflowOverviewReleaseArtifactDisplay);
const workflowOverviewReleaseArtifactDomContract = workflowOverviewApi
.getWorkflowOverviewReleaseReadinessArtifactDomContract({
rowDatasetPrefix: "externalReleaseArtifact",
selectors: {
mount: "[data-external-release-artifact]",
status: "[data-external-release-artifact-status]",
rows: "[data-external-release-artifact-rows]",
},
});
const workflowOverviewReleaseArtifactDomReadiness = workflowOverviewApi
.getWorkflowOverviewReleaseReadinessArtifactDomReadiness({
contract: workflowOverviewReleaseArtifactDomContract,
documentRef: document,
});
const workflowOverviewReleaseArtifactRenderResult = workflowOverviewApi
.renderWorkflowOverviewReleaseReadinessArtifactState(
workflowOverviewReleaseArtifactRenderState,
{
contract: workflowOverviewReleaseArtifactDomContract,
documentRef: document,
},
);
const workflowOverviewReleaseArtifactMountResult = workflowOverviewApi
.mountWorkflowOverviewReleaseReadinessArtifactState({
renderState: workflowOverviewReleaseArtifactRenderState,
contract: workflowOverviewReleaseArtifactDomContract,
documentRef: document,
});
const workflowOverviewEmbedding = launchApi.mountWorkflowOverviewEmbedding({
overviewApi: workflowOverviewApi,
});
@@ -413,6 +449,26 @@ TOOL_TABLE = browser-shell-tool.tbl
true,
"shell workflow overview release artifact validation readiness",
);
assertEqual(
workflowOverviewReleaseArtifactDomReadiness.ready,
true,
"shell workflow overview release artifact DOM readiness",
);
assertEqual(
workflowOverviewReleaseArtifactRenderResult.rowCount,
3,
"shell workflow overview release artifact render rows",
);
assertEqual(
workflowOverviewReleaseArtifactMountResult.ready,
true,
"shell workflow overview release artifact mount readiness",
);
assertEqual(
document.querySelector("[data-external-release-artifact-status]").textContent,
"Ready: No blocking reasons",
"shell workflow overview release artifact rendered status",
);
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

@@ -35,6 +35,12 @@
!workflowApi?.getWorkflowOverviewApiSurfaceInventory ||
!workflowApi?.getWorkflowOverviewPersistenceSummary ||
!workflowApi?.validateWorkflowOverviewReleaseReadinessArtifactJson ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactRenderState ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactDomContract ||
!workflowApi?.getWorkflowOverviewReleaseReadinessArtifactDomReadiness ||
!workflowApi?.renderWorkflowOverviewReleaseReadinessArtifactState ||
!workflowApi?.mountWorkflowOverviewReleaseReadinessArtifactState ||
!workflowApi?.getWorkflowOverviewDomContract ||
!workflowApi?.getWorkflowOverviewDomReadiness ||
!workflowApi?.renderWorkflowOverview ||
@@ -95,6 +101,14 @@
},
],
}));
const releaseArtifactDisplay = workflowApi.getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(
releaseArtifactValidation,
);
const releaseArtifactRenderState = workflowApi.getWorkflowOverviewReleaseReadinessArtifactRenderState(
releaseArtifactDisplay,
);
const releaseArtifactDomContract = workflowApi.getWorkflowOverviewReleaseReadinessArtifactDomContract();
const releaseArtifactDomReadinessMissing = workflowApi.getWorkflowOverviewReleaseReadinessArtifactDomReadiness();
const domContract = workflowApi.getWorkflowOverviewDomContract();
const domReadiness = workflowApi.getWorkflowOverviewDomReadiness();
const renderResult = workflowApi.renderWorkflowOverview();
@@ -147,6 +161,19 @@
);
assertEqual(releaseArtifactValidation.ready, true, "workflow overview release artifact validation readiness");
assertEqual(releaseArtifactValidation.gateCount, 9, "workflow overview release artifact validation gates");
assertEqual(releaseArtifactDisplay.statusText, "Ready", "workflow overview release artifact display status");
assertEqual(releaseArtifactRenderState.statusLine, "Ready: No blocking reasons", "workflow overview release artifact render status");
assertEqual(
releaseArtifactRenderState.dataset.handoffScope,
"workflow-overview-release-readiness-artifact",
"workflow overview release artifact render scope",
);
assertEqual(
releaseArtifactDomContract.selectors.mount,
"[data-workflow-overview-release-readiness-artifact]",
"workflow overview release artifact DOM mount selector",
);
assertEqual(releaseArtifactDomReadinessMissing.ready, false, "workflow overview release artifact missing DOM readiness");
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");
@@ -229,6 +256,27 @@
assertEqual(embeddingMountDomMount.renderResult.rowCount, 7, "workflow overview embedding mount DOM mount row count");
assertEqual(embeddingMountDomMount.error, null, "workflow overview embedding mount DOM mount error");
assertEqual(embeddingMountStatus.textContent, embeddingMountRenderState.statusLine, "workflow overview embedding mount rendered status");
const releaseArtifactNode = workflowDoc.createElement("section");
releaseArtifactNode.dataset.workflowOverviewReleaseReadinessArtifact = "";
const releaseArtifactStatus = workflowDoc.createElement("p");
releaseArtifactStatus.dataset.workflowOverviewReleaseReadinessArtifactStatus = "";
const releaseArtifactRows = workflowDoc.createElement("dl");
releaseArtifactRows.dataset.workflowOverviewReleaseReadinessArtifactRows = "";
releaseArtifactNode.append(releaseArtifactStatus, releaseArtifactRows);
workflowDoc.body.append(releaseArtifactNode);
const releaseArtifactDomReadinessReady = workflowApi.getWorkflowOverviewReleaseReadinessArtifactDomReadiness();
const releaseArtifactRenderResult = workflowApi.renderWorkflowOverviewReleaseReadinessArtifactState(
releaseArtifactRenderState,
);
const releaseArtifactMountResult = workflowApi.mountWorkflowOverviewReleaseReadinessArtifactState({
renderState: releaseArtifactRenderState,
});
assertEqual(releaseArtifactDomReadinessReady.ready, true, "workflow overview release artifact DOM readiness");
assertEqual(releaseArtifactRenderResult.rendered, true, "workflow overview release artifact render result");
assertEqual(releaseArtifactRenderResult.rowCount, 3, "workflow overview release artifact render row count");
assertEqual(releaseArtifactMountResult.ready, true, "workflow overview release artifact mount readiness");
assertEqual(releaseArtifactMountResult.renderResult.rowCount, 3, "workflow overview release artifact mount rows");
assertEqual(releaseArtifactStatus.textContent, releaseArtifactRenderState.statusLine, "workflow overview release artifact rendered status");
assertEqual(
workflowDoc.querySelector("[data-handoff-workflow]").dataset.handoffScope,
"workflow",

View File

@@ -35,6 +35,8 @@ for (const phrase of [
"parseProjectReleaseReadinessArtifactJson()",
"createProjectReleaseReadinessArtifactValidation()",
"validateWorkflowOverviewReleaseReadinessArtifactJson()",
"render-state",
"DOM readiness",
"createIniPanelShellApiSurfaceInventory()",
"createIniPanelShellSessionReadinessWorkflowReport()",
"workflow overview embedding mount DOM",

View File

@@ -22,6 +22,10 @@ import {
createIniPanelShellWorkflowOverviewContract,
createIniPanelShellWorkflowOverviewEmbeddingMountDomContract,
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createLinuxCncIniSdk,
createLinuxCncInterpSdk,
createMachineSessionSnapshotPayload,
@@ -50,12 +54,14 @@ import {
machineFilePaths,
machineIniPath,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
normalizeOpfsPath,
parameterFilePath,
planIniFileContextStaging,
planSimConfigStaging,
readMachineSessionReadiness,
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
restoreMachineParametersFromOpfs,
saveMachineSessionSnapshot,
saveMachineTextFiles,
@@ -141,14 +147,38 @@ const requiredExports = [
"createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness",
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
],
[
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
],
[
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
],
[
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
],
[
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness",
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
],
[
"renderIniPanelShellWorkflowOverviewEmbeddingMountState",
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
],
[
"renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
],
[
"mountIniPanelShellWorkflowOverviewEmbeddingMountState",
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
],
[
"mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
],
];
for (const [name, value] of requiredExports) {
@@ -250,6 +280,19 @@ assert.equal(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)).ready,
true,
);
assert.equal(
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)),
),
).dataset.handoffScope,
"workflow-overview-release-readiness-artifact",
);
assert.equal(
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract().selectors.rows,
"[data-workflow-overview-release-readiness-artifact-rows]",
);
assert.equal(createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness().ready, false);
assert.equal(
createProjectReleaseReadinessReport({
observedOutputs: ["project_release_gate=ok"],

View File

@@ -54,6 +54,12 @@ import {
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -156,6 +162,12 @@ const requiredShellExports = [
"renderIniPanelShellWorkflowOverviewEmbeddingMountState",
"mountIniPanelShellWorkflowOverviewEmbeddingMountState",
"validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson",
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState",
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract",
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness",
"renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
"mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
"renderIniPanelShellSessionHandoffWorkflowState",
"mountIniPanelShellSessionHandoffWorkflow",
"renderIniPanelShellSessionHandoffMountState",

View File

@@ -52,6 +52,12 @@ import {
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
createIniPanelShellSessionHandoffPackageReport,
@@ -782,6 +788,12 @@ assert.deepEqual(createIniPanelShellWorkflowOverviewContract(), {
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
"getWorkflowOverviewReleaseReadinessArtifactRenderState",
"getWorkflowOverviewReleaseReadinessArtifactDomContract",
"getWorkflowOverviewReleaseReadinessArtifactDomReadiness",
"renderWorkflowOverviewReleaseReadinessArtifactState",
"mountWorkflowOverviewReleaseReadinessArtifactState",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -820,6 +832,12 @@ assert.equal(typeof createIniPanelShellWorkflowOverviewEmbeddingMountDomReadines
assert.equal(typeof renderIniPanelShellWorkflowOverviewEmbeddingMountState, "function");
assert.equal(typeof mountIniPanelShellWorkflowOverviewEmbeddingMountState, "function");
assert.equal(typeof validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson, "function");
assert.equal(typeof createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel, "function");
assert.equal(typeof createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState, "function");
assert.equal(typeof createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract, "function");
assert.equal(typeof createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness, "function");
assert.equal(typeof renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, "function");
assert.equal(typeof mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, "function");
assert.equal(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{}").apiName,
"ini-panel-shell-workflow-overview-release-readiness-artifact-validation",
@@ -837,6 +855,12 @@ assert.deepEqual(
"getWorkflowOverviewSummary",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
"getWorkflowOverviewReleaseReadinessArtifactRenderState",
"getWorkflowOverviewReleaseReadinessArtifactDomContract",
"getWorkflowOverviewReleaseReadinessArtifactDomReadiness",
"renderWorkflowOverviewReleaseReadinessArtifactState",
"mountWorkflowOverviewReleaseReadinessArtifactState",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",

View File

@@ -52,6 +52,12 @@ import {
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
renderIniPanelShellSessionHandoffWorkflowState,
mountIniPanelShellSessionHandoffWorkflow,
renderIniPanelShellSessionHandoffMountState,
@@ -676,6 +682,12 @@ assert.deepEqual(shellViewModel.shellWorkflowOverviewContract, {
"getWorkflowOverviewApiSurfaceInventory",
"getWorkflowOverviewPersistenceSummary",
"validateWorkflowOverviewReleaseReadinessArtifactJson",
"getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
"getWorkflowOverviewReleaseReadinessArtifactRenderState",
"getWorkflowOverviewReleaseReadinessArtifactDomContract",
"getWorkflowOverviewReleaseReadinessArtifactDomReadiness",
"renderWorkflowOverviewReleaseReadinessArtifactState",
"mountWorkflowOverviewReleaseReadinessArtifactState",
"getWorkflowOverviewDomContract",
"getWorkflowOverviewDomReadiness",
"renderWorkflowOverview",
@@ -1313,6 +1325,56 @@ assert.equal(
assert.equal(releaseArtifactValidation.ready, true);
assert.equal(releaseArtifactValidation.validation.ready, true);
assert.equal(releaseArtifactValidation.gateCount, 9);
const releaseArtifactDisplay = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(
releaseArtifactValidation,
);
const releaseArtifactRenderState = createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(
releaseArtifactDisplay,
);
assert.equal(releaseArtifactDisplay.statusText, "Ready");
assert.equal(releaseArtifactRenderState.statusLine, "Ready: No blocking reasons");
assert.equal(releaseArtifactRenderState.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
assert.equal(
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract().selectors.mount,
"[data-workflow-overview-release-readiness-artifact]",
);
assert.equal(createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness().ready, false);
const releaseArtifactMountNode = mountDocument.createElement("section");
releaseArtifactMountNode.dataset.workflowOverviewReleaseReadinessArtifact = "";
const releaseArtifactStatusNode = mountDocument.createElement("p");
releaseArtifactStatusNode.dataset.workflowOverviewReleaseReadinessArtifactStatus = "";
const releaseArtifactRowsNode = {
...mountDocument.createElement("dl"),
children: [],
replaceChildren() {
this.children = [];
},
append(...nodes) {
this.children.push(...nodes);
},
};
releaseArtifactRowsNode.dataset.workflowOverviewReleaseReadinessArtifactRows = "";
const releaseArtifactRenderResult = renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState(
releaseArtifactRenderState,
{
documentRef: mountDocument,
mountNode: releaseArtifactMountNode,
statusNode: releaseArtifactStatusNode,
rowsNode: releaseArtifactRowsNode,
},
);
const releaseArtifactMountResult = mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState({
renderState: releaseArtifactRenderState,
documentRef: mountDocument,
mountNode: releaseArtifactMountNode,
statusNode: releaseArtifactStatusNode,
rowsNode: releaseArtifactRowsNode,
});
assert.equal(releaseArtifactRenderResult.rendered, true);
assert.equal(releaseArtifactRenderResult.rowCount, 3);
assert.equal(releaseArtifactRenderResult.dataset.handoffScope, "workflow-overview-release-readiness-artifact");
assert.equal(releaseArtifactMountResult.ready, true);
assert.equal(releaseArtifactMountResult.renderResult.rowCount, 3);
assert.deepEqual(
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson("{").missing,
["artifact-json"],
@@ -1333,6 +1395,12 @@ const workflowOverviewApi = {
getWorkflowOverviewApiSurfaceInventory: () => shellViewModel.shellApiSurfaceInventory,
getWorkflowOverviewPersistenceSummary: () => shellViewModel.shellPersistenceSummary,
validateWorkflowOverviewReleaseReadinessArtifactJson: () => ({ ready: true }),
getWorkflowOverviewReleaseReadinessArtifactDisplayViewModel: () => releaseArtifactDisplay,
getWorkflowOverviewReleaseReadinessArtifactRenderState: () => releaseArtifactRenderState,
getWorkflowOverviewReleaseReadinessArtifactDomContract: createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
getWorkflowOverviewReleaseReadinessArtifactDomReadiness: createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
renderWorkflowOverviewReleaseReadinessArtifactState: renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
mountWorkflowOverviewReleaseReadinessArtifactState: mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
getWorkflowOverviewDomContract: createIniPanelShellSessionHandoffWorkflowDomContract,
getWorkflowOverviewDomReadiness: createIniPanelShellSessionHandoffWorkflowDomReadiness,
renderWorkflowOverview: renderIniPanelShellSessionHandoffWorkflowState,