diff --git a/text12.txt b/text12.txt index bb4b3c2..58c383d 100644 --- a/text12.txt +++ b/text12.txt @@ -3024,3 +3024,78 @@ host_wasm_opfs_browser_smokes=ok `createIniPanelShellSessionHandoffWorkflowSummary()`),把 mount workflow、control-page mount workflow 和 readonly status result 合并成一个稳定 summary,方便外部 shell 一次展示 handoff end-to-end 状态; 仍保持只读,不新增控制按钮,不解析 G-code。 + +三十八、2026-06-15 继续执行记录:INI panel shell handoff workflow summary helper + +本轮按“第一原则:加快实质性推进”继续推进 SDK/API surface 与 browser/UI workflow,为 shell +handoff 增加 end-to-end workflow summary helper,把 mount workflow、control-page mount workflow +和 readonly status result 合并为一个稳定 summary,方便外部 shell 一次展示 handoff 总体状态。 + +完成内容: + +- `ui-shell.js` 新增 `createIniPanelShellSessionHandoffWorkflowSummary()`; +- 新 helper 返回 `apiName`、`summaryVersion`、`phase`、`ready`、`statusLine`、`mountWorkflow`、 + `controlPageMountWorkflow`、`readonlyStatusResult`、`blockingReasons` 与 display rows; +- summary helper 对 mount workflow、control-page mount workflow、readonly status result 做只读聚合, + 并把 blocked 原因稳定编码为 end-to-end `blockingReasons`; +- `createIniPanelShellViewModel()` 暴露 `createShellSessionHandoffWorkflowSummary`; +- `createIniPanelLaunchApiManifest().methods` 新增 `getShellSessionHandoffWorkflowSummary`, + launch method count 更新为 33; +- `launch.html` 的 `window.linuxCncIniPanelLaunchApi.getShellSessionHandoffWorkflowSummary()` 暴露 + 真实 browser API,并提供无副作用的默认 summary 输入; +- `ini_panel_shell_integration_workflow_smoke.html` 在真实 browser workflow 中通过 shared summary helper + 校验 ready、blocking reasons 与 end-to-end handoff 状态; +- Node smoke 覆盖 summary helper 的 blocked/ready 路径; +- 文档同步记录 summary helper 用法; +- 未新增控制按钮; +- 未解析 G-code; +- 未解释 canonical events; +- 未新增 JS CNC 语义; +- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或 + LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh +wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.sh +wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.sh +wasm-port/tests/ui/node/verify_ini_panel_entry_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_ini_panel_browser.sh +wasm-port/tools/verify_vendor_sync.sh +wasm-port/tools/verify_no_standalone_cnc_semantics.sh +SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh +SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh +wasm-port/tests/host/verify_host_smokes.sh +``` + +关键输出: + +```text +ini_panel_ui_shell_node_smoke=ok +ini_panel_launch_api_manifest_node_smoke=ok +ini_panel_shell_integration_manifest_node_smoke=ok +ini_panel_entry_docs_node_smoke=ok +ui_node_smokes=ok +browser_ini_opfs_smoke=ok +browser_ini_control_page_smoke=ok +browser_ini_launch_smoke=ok +browser_ini_shell_integration_workflow_smoke=ok +vendor sync up to date +standalone CNC semantics guard complete +interp_wasm_node_smoke=ok +sim_configs_wasm_node_inventory_executed=28 +sim_configs_wasm_node_inventory_passed=28 +sim_configs_wasm_node_inventory_skipped=131 +sim_configs_wasm_node_inventory_unexpected_fail=0 +host_wasm_opfs_browser_smokes=ok +``` + +下一步建议: + +继续推进 SDK/API surface。下一批建议增加 shell handoff workflow display-model helper(例如 +`createIniPanelShellSessionHandoffWorkflowDisplayViewModel()`),把 end-to-end summary 转成稳定 title、 +statusText、detailText 和 rows,方便外部 shell 直接渲染 handoff 总览;仍保持只读,不新增控制按钮, +不解析 G-code。 diff --git a/wasm-port/docs/panel-entry.md b/wasm-port/docs/panel-entry.md index cadbec0..91ce0f4 100644 --- a/wasm-port/docs/panel-entry.md +++ b/wasm-port/docs/panel-entry.md @@ -34,6 +34,7 @@ import { createIniPanelShellSessionHandoffMountDomReadiness, mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, + createIniPanelShellSessionHandoffWorkflowSummary, renderIniPanelShellSessionHandoffMountState, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, @@ -250,6 +251,11 @@ view-model, mount render-state, and DOM mount workflow result. Use `linuxCncIniPanelLaunchApi.readShellSessionHandoffStatusFromControlPage()` when an outer shell needs to read the control-page readonly status and verify the expected handoff status fields as a structured ready/blocked result. Use +`createIniPanelShellSessionHandoffWorkflowSummary()` or +`linuxCncIniPanelLaunchApi.getShellSessionHandoffWorkflowSummary()` when an +outer shell needs one stable end-to-end summary that combines mount workflow, +control-page mount workflow, readonly status result, and current blocking +reasons into display rows. Use `renderIniPanelShellSessionHandoffMountState()` or `linuxCncIniPanelLaunchApi.renderShellSessionHandoffMountState()` when an outer shell needs the shared read-only DOM renderer for those rows. The launch page diff --git a/wasm-port/runtime/ui/ini-panel/launch.html b/wasm-port/runtime/ui/ini-panel/launch.html index d97e409..5cfa523 100644 --- a/wasm-port/runtime/ui/ini-panel/launch.html +++ b/wasm-port/runtime/ui/ini-panel/launch.html @@ -111,6 +111,7 @@ mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, readIniPanelShellSessionHandoffStatusFromControlPage, + createIniPanelShellSessionHandoffWorkflowSummary, renderIniPanelShellSessionHandoffMountState, } from "./ui-shell.js"; @@ -214,6 +215,23 @@ ...(options ?? {}), }) ), + getShellSessionHandoffWorkflowSummary: (options) => ( + createIniPanelShellSessionHandoffWorkflowSummary(options ?? { + mountWorkflow: { + phase: shellViewModel.shellSessionHandoffPackageMountRenderState.phase, + ready: shellViewModel.shellSessionHandoffPackageMountRenderState.ready, + statusLine: shellViewModel.shellSessionHandoffPackageMountRenderState.statusLine, + }, + controlPageMountWorkflow: { + phase: shellViewModel.shellSessionHandoffPackageMountState.phase, + ready: shellViewModel.shellSessionHandoffPackageMountState.ready, + statusLine: shellViewModel.shellSessionHandoffPackageMountState.statusLine, + }, + readonlyStatusResult: shellViewModel.readShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + }), + }) + ), isSupportedShellSessionHandoffPackage: shellViewModel.isSupportedShellSessionHandoffPackage, getLauncherLinks: () => shellViewModel.launcherLinks, getControlPageApiMethods: () => shellViewModel.controlPage.browserApiMethods, diff --git a/wasm-port/runtime/ui/ini-panel/ui-shell.js b/wasm-port/runtime/ui/ini-panel/ui-shell.js index cce8ffc..cf6f56c 100644 --- a/wasm-port/runtime/ui/ini-panel/ui-shell.js +++ b/wasm-port/runtime/ui/ini-panel/ui-shell.js @@ -149,6 +149,7 @@ export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntr "mountShellSessionHandoff", "mountShellSessionHandoffFromControlPage", "readShellSessionHandoffStatusFromControlPage", + "getShellSessionHandoffWorkflowSummary", "isSupportedShellSessionHandoffPackage", "getLauncherLinks", "getControlPageApiMethods", @@ -1376,6 +1377,103 @@ export function readIniPanelShellSessionHandoffStatusFromControlPage({ }; } +export function createIniPanelShellSessionHandoffWorkflowSummary({ + mountWorkflow = { + phase: "blocked", + ready: false, + statusLine: "Blocked: mount workflow unavailable", + }, + controlPageMountWorkflow = { + phase: "blocked", + ready: false, + statusLine: "Blocked: control-page mount workflow unavailable", + }, + readonlyStatusResult = { + phase: "blocked", + ready: false, + statusLine: "Blocked: readonly status unavailable", + missingStatusFields: [], + }, +} = {}) { + const blockingReasons = []; + if (mountWorkflow?.ready !== true) { + blockingReasons.push(`mount:${mountWorkflow?.phase ?? "blocked"}`); + } + if (controlPageMountWorkflow?.ready !== true) { + blockingReasons.push(`control-page-mount:${controlPageMountWorkflow?.phase ?? "blocked"}`); + } + if (readonlyStatusResult?.ready !== true) { + const readonlyDetail = readonlyStatusResult?.readError + ?? ( + Array.isArray(readonlyStatusResult?.missingStatusFields) + && readonlyStatusResult.missingStatusFields.length > 0 + ? readonlyStatusResult.missingStatusFields.join(", ") + : readonlyStatusResult?.phase ?? "blocked" + ); + blockingReasons.push(`readonly-status:${readonlyDetail}`); + } + const ready = blockingReasons.length === 0; + + return { + apiName: "ini-panel-shell-session-handoff-workflow-summary", + summaryVersion: 1, + phase: ready ? "ready" : "blocked", + ready, + statusLine: ready + ? "Ready: shell handoff end-to-end workflow available" + : `Blocked: ${blockingReasons.join("; ")}`, + mountWorkflow: { + phase: mountWorkflow?.phase ?? "blocked", + ready: mountWorkflow?.ready === true, + statusLine: mountWorkflow?.statusLine ?? null, + }, + controlPageMountWorkflow: { + phase: controlPageMountWorkflow?.phase ?? "blocked", + ready: controlPageMountWorkflow?.ready === true, + statusLine: controlPageMountWorkflow?.statusLine ?? null, + }, + readonlyStatusResult: { + phase: readonlyStatusResult?.phase ?? "blocked", + ready: readonlyStatusResult?.ready === true, + statusLine: readonlyStatusResult?.statusLine ?? null, + missingStatusFields: Array.isArray(readonlyStatusResult?.missingStatusFields) + ? [...readonlyStatusResult.missingStatusFields] + : [], + }, + blockingReasons, + rows: [ + { + id: "mount-workflow", + label: "Mount workflow", + value: mountWorkflow?.statusLine ?? "missing", + }, + { + id: "control-page-mount-workflow", + label: "Control-page mount workflow", + value: controlPageMountWorkflow?.statusLine ?? "missing", + }, + { + id: "readonly-status-workflow", + label: "Readonly status workflow", + value: readonlyStatusResult?.statusLine ?? "missing", + }, + { + id: "readonly-status-missing-fields", + label: "Readonly missing fields", + value: Array.isArray(readonlyStatusResult?.missingStatusFields) + && readonlyStatusResult.missingStatusFields.length > 0 + ? readonlyStatusResult.missingStatusFields.join(", ") + : "none", + }, + { + id: "blocking-reasons", + label: "Blocking reasons", + value: blockingReasons.length > 0 ? blockingReasons.join("; ") : "none", + }, + ], + }; +} + export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries()) { const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries); const shellIntegrationReadiness = createIniPanelShellIntegrationReadiness(shellIntegrationManifest); @@ -1496,6 +1594,7 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries mountShellSessionHandoff: mountIniPanelShellSessionHandoff, mountShellSessionHandoffFromControlPage: mountIniPanelShellSessionHandoffFromControlPage, readShellSessionHandoffStatusFromControlPage: readIniPanelShellSessionHandoffStatusFromControlPage, + createShellSessionHandoffWorkflowSummary: createIniPanelShellSessionHandoffWorkflowSummary, isSupportedShellSessionHandoffPackage: isSupportedIniPanelShellSessionHandoffPackage, controlPage: { browserApiSchema: createControlPageBrowserApiSchema(), diff --git a/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html b/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html index 8f89e4a..b722085 100644 --- a/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html +++ b/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html @@ -91,6 +91,7 @@ TOOL_TABLE = browser-shell-tool.tbl !launchApi?.mountShellSessionHandoff || !launchApi?.mountShellSessionHandoffFromControlPage || !launchApi?.readShellSessionHandoffStatusFromControlPage || + !launchApi?.getShellSessionHandoffWorkflowSummary || !launchApi?.isSupportedShellSessionHandoffPackage ) { throw new Error("launch API namespace did not expose shell integration helpers"); @@ -357,6 +358,11 @@ TOOL_TABLE = browser-shell-tool.tbl const readonlyStatusResult = launchApi.readShellSessionHandoffStatusFromControlPage({ controlPageApi, }); + const workflowSummaryResult = launchApi.getShellSessionHandoffWorkflowSummary({ + mountWorkflow: readyMountWorkflow, + controlPageMountWorkflow: readyControlPageMountWorkflow, + readonlyStatusResult, + }); assertEqual(readonlyStatusResult.phase, "ready", "shell handoff readonly status result phase"); assertEqual(readonlyStatusResult.ready, true, "shell handoff readonly status result readiness"); assertEqual( @@ -364,6 +370,9 @@ TOOL_TABLE = browser-shell-tool.tbl "", "shell handoff readonly status missing fields", ); + assertEqual(workflowSummaryResult.phase, "ready", "shell handoff workflow summary phase"); + assertEqual(workflowSummaryResult.ready, true, "shell handoff workflow summary readiness"); + assertEqual(workflowSummaryResult.blockingReasons.join(","), "", "shell handoff workflow summary blocking reasons"); assertEqual( readonlyStatus.workflowStatus.lastAction, "load-session", diff --git a/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs b/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs index 92ffa77..e9fe8ee 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs @@ -32,6 +32,7 @@ import { mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, readIniPanelShellSessionHandoffStatusFromControlPage, + createIniPanelShellSessionHandoffWorkflowSummary, renderIniPanelShellSessionHandoffMountState, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, @@ -103,6 +104,7 @@ const requiredShellExports = [ "mountIniPanelShellSessionHandoff", "mountIniPanelShellSessionHandoffFromControlPage", "readIniPanelShellSessionHandoffStatusFromControlPage", + "createIniPanelShellSessionHandoffWorkflowSummary", "renderIniPanelShellSessionHandoffMountState", "createIniPanelShellSessionHandoffPackageReport", "createIniPanelShellSessionHandoffPackageRenderState", @@ -309,6 +311,10 @@ assert.equal( readIniPanelShellSessionHandoffStatusFromControlPage().phase, "blocked", ); +assert.equal( + createIniPanelShellSessionHandoffWorkflowSummary().phase, + "blocked", +); assert.equal(isSupportedIniPanelShellSessionHandoffPackage(createIniPanelShellViewModel().shellSessionHandoffPackage), true); assert.equal(isSupportedIniPanelShellIntegrationManifest(createIniPanelShellViewModel().shellIntegrationManifest), true); assert.deepEqual(createIniPanelShellViewModel().launchApiSchema, createIniPanelLaunchApiSchema()); @@ -471,6 +477,7 @@ assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellSessionHandoffMountD assert.match(docText, /\blinuxCncIniPanelLaunchApi\.mountShellSessionHandoff\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.mountShellSessionHandoffFromControlPage\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.readShellSessionHandoffStatusFromControlPage\b/); +assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellSessionHandoffWorkflowSummary\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getControlPageApiMethods\b/); assert.match(docText, /\bini_panel_shell_integration_workflow_smoke\.html\b/); assert.match(browserIniPanelText, /\bini_panel_shell_integration_workflow_smoke\.html\b/); @@ -492,6 +499,7 @@ assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellSessionHandoffMountDo assert.match(shellIntegrationWorkflowSmokeText, /\bmountShellSessionHandoff\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bmountShellSessionHandoffFromControlPage\b/); assert.match(shellIntegrationWorkflowSmokeText, /\breadShellSessionHandoffStatusFromControlPage\b/); +assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellSessionHandoffWorkflowSummary\b/); assert.match(shellIntegrationWorkflowSmokeText, /\brenderShellSessionHandoffMountState\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bdata-external-shell-mount\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bdata-external-mount-value\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs b/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs index a62c663..6073850 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs @@ -69,6 +69,7 @@ assert.deepEqual(manifest, { "mountShellSessionHandoff", "mountShellSessionHandoffFromControlPage", "readShellSessionHandoffStatusFromControlPage", + "getShellSessionHandoffWorkflowSummary", "isSupportedShellSessionHandoffPackage", "getLauncherLinks", "getControlPageApiMethods", @@ -193,6 +194,7 @@ assert.match(launchText, /\brenderShellSessionHandoffMountState\b/); assert.match(launchText, /\bmountShellSessionHandoff\b/); assert.match(launchText, /\bmountShellSessionHandoffFromControlPage\b/); assert.match(launchText, /\breadShellSessionHandoffStatusFromControlPage\b/); +assert.match(launchText, /\bgetShellSessionHandoffWorkflowSummary\b/); assert.match(launchText, /\bisSupportedShellSessionHandoffPackage\b/); assert.match(launchText, /\bdata-handoff-mount\b/); assert.match(launchText, /\bdata-handoff-mount-status\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs b/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs index e4e5277..e200b30 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs @@ -28,6 +28,7 @@ import { mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, readIniPanelShellSessionHandoffStatusFromControlPage, + createIniPanelShellSessionHandoffWorkflowSummary, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, createIniPanelShellSessionHandoffPackageSchema, @@ -154,7 +155,7 @@ assert.deepEqual(readiness, { counts: { pages: 2, launcherLinks: 2, - launchMethods: 32, + launchMethods: 33, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -216,7 +217,7 @@ assert.deepEqual(handoffSummary, { counts: { pages: 2, launcherLinks: 2, - launchMethods: 32, + launchMethods: 33, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -716,6 +717,10 @@ assert.equal( readIniPanelShellSessionHandoffStatusFromControlPage().readError, "Missing readControlPageStatus", ); +assert.equal( + createIniPanelShellSessionHandoffWorkflowSummary().phase, + "blocked", +); assert.deepEqual( createIniPanelShellSessionHandoffPackageMountState({ handoffPackage, @@ -1127,7 +1132,7 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), { counts: { pages: 2, launcherLinks: 2, - launchMethods: 32, + launchMethods: 33, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -1301,6 +1306,7 @@ assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffMoun assert.match(shellText, /\bexport function mountIniPanelShellSessionHandoff\b/); assert.match(shellText, /\bexport function mountIniPanelShellSessionHandoffFromControlPage\b/); assert.match(shellText, /\bexport function readIniPanelShellSessionHandoffStatusFromControlPage\b/); +assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffWorkflowSummary\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageReport\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageRenderState\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageSchema\b/); @@ -1331,6 +1337,7 @@ assert.match(docText, /\bcreateIniPanelShellSessionHandoffMountDomReadiness\b/); assert.match(docText, /\bmountIniPanelShellSessionHandoff\b/); assert.match(docText, /\bmountIniPanelShellSessionHandoffFromControlPage\b/); assert.match(docText, /\breadIniPanelShellSessionHandoffStatusFromControlPage\b/); +assert.match(docText, /\bcreateIniPanelShellSessionHandoffWorkflowSummary\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageReport\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageRenderState\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageSchema\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs b/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs index 58d3155..6fc019c 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs @@ -28,6 +28,7 @@ import { mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, readIniPanelShellSessionHandoffStatusFromControlPage, + createIniPanelShellSessionHandoffWorkflowSummary, renderIniPanelShellSessionHandoffMountState, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, @@ -104,6 +105,7 @@ assert.equal(typeof createIniPanelShellSessionHandoffMountDomReadiness, "functio assert.equal(typeof mountIniPanelShellSessionHandoff, "function"); assert.equal(typeof mountIniPanelShellSessionHandoffFromControlPage, "function"); assert.equal(typeof readIniPanelShellSessionHandoffStatusFromControlPage, "function"); +assert.equal(typeof createIniPanelShellSessionHandoffWorkflowSummary, "function"); assert.equal(typeof renderIniPanelShellSessionHandoffMountState, "function"); assert.equal(typeof createIniPanelShellSessionHandoffPackageReport, "function"); assert.equal(typeof createIniPanelShellSessionHandoffPackageRenderState, "function"); @@ -714,6 +716,10 @@ assert.equal( shellViewModel.readShellSessionHandoffStatusFromControlPage, readIniPanelShellSessionHandoffStatusFromControlPage, ); +assert.equal( + shellViewModel.createShellSessionHandoffWorkflowSummary, + createIniPanelShellSessionHandoffWorkflowSummary, +); assert.equal(shellViewModel.createShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageReport); assert.equal(shellViewModel.createShellSessionHandoffPackageSchema, createIniPanelShellSessionHandoffPackageSchema); assert.equal(shellViewModel.isSupportedShellSessionHandoffPackage, isSupportedIniPanelShellSessionHandoffPackage); @@ -937,6 +943,29 @@ assert.equal( }).readError, "Missing readControlPageStatus", ); +const workflowSummaryResult = createIniPanelShellSessionHandoffWorkflowSummary({ + mountWorkflow: mountWorkflowResult, + controlPageMountWorkflow, + readonlyStatusResult, +}); +assert.equal(workflowSummaryResult.apiName, "ini-panel-shell-session-handoff-workflow-summary"); +assert.equal(workflowSummaryResult.summaryVersion, 1); +assert.equal(workflowSummaryResult.phase, "blocked"); +assert.equal(workflowSummaryResult.ready, false); +assert.equal(workflowSummaryResult.rows.length, 5); +assert.equal(workflowSummaryResult.blockingReasons[0], "mount:blocked"); +const readyWorkflowSummaryResult = createIniPanelShellSessionHandoffWorkflowSummary({ + mountWorkflow: { + phase: "ready", + ready: true, + statusLine: "Ready: mount workflow available", + }, + controlPageMountWorkflow, + readonlyStatusResult, +}); +assert.equal(readyWorkflowSummaryResult.phase, "ready"); +assert.equal(readyWorkflowSummaryResult.ready, true); +assert.equal(readyWorkflowSummaryResult.blockingReasons.length, 0); assert.deepEqual( mountIniPanelShellSessionHandoff({ documentRef: mountDocument }).renderResult, null,