diff --git a/text12.txt b/text12.txt index 08d7a96..93e78c5 100644 --- a/text12.txt +++ b/text12.txt @@ -659,3 +659,73 @@ host_wasm_opfs_browser_smokes=ok 入口或 manifest,方便外部页面稳定发现 `readStatus()`、`loadSessionState()`、`refresh()` 和 `renderView()`;仍保持只描述 UI/host boundary facts,不在 JS 中解释 G-code、canonical events 或 CNC 运行语义。 + +七、2026-06-15 继续执行记录:INI panel readonly status API manifest + +本轮按“第一原则:加快实质性推进”继续推进 SDK/API surface,把 readonly status API 的 shape +写入轻量 manifest,方便外部页面稳定发现 `readStatus()`、`loadSessionState()`、`refresh()` 和 +`renderView()`。 + +完成内容: + +- `wasm-port/runtime/ui/ini-panel/readonly-status-api.js` 新增 + `createMachineSessionReadonlyStatusApiManifest()`; +- manifest 固定返回: + - `apiName` + - `methods.readStatus` + - `relatedControlPageMethods` + - `statusFields` +- `ui-shell.js` re-export `createMachineSessionReadonlyStatusApiManifest()`; +- `createIniPanelShellViewModel()` 的 `controlPage` 新增 `readonlyStatusApiManifest`; +- `verify_ini_panel_readonly_status_api.mjs` 覆盖 manifest shape; +- `verify_ini_panel_ui_shell.mjs` 覆盖 shell view-model 中的 manifest 暴露; +- `verify_ini_panel_entry_docs.mjs` 与 `docs/panel-entry.md` 同步记录 manifest 入口; +- 未新增控制按钮; +- 未解析 G-code; +- 未解释 canonical events; +- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或 + LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +wasm-port/tests/ui/node/verify_ini_panel_readonly_status_api.sh +wasm-port/tests/ui/node/verify_ini_panel_ui_shell.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_readonly_status_api_node_smoke=ok +ini_panel_ui_shell_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 +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 +browser_interp_smoke=ok +host_wasm_opfs_browser_smokes=ok +``` + +下一步建议: + +继续推进 SDK/API surface。下一批建议为 shell-facing API 增加一个 focused contract smoke, +直接校验 `createIniPanelShellViewModel().controlPage` 的所有方法名、manifest 字段和只读边界, +使外部页面接入前能运行一个快速 contract gate;仍保持只描述 UI/host boundary facts,不在 JS +中解释 G-code、canonical events 或 CNC 运行语义。 diff --git a/wasm-port/docs/panel-entry.md b/wasm-port/docs/panel-entry.md index 1129394..7e5ffcb 100644 --- a/wasm-port/docs/panel-entry.md +++ b/wasm-port/docs/panel-entry.md @@ -16,6 +16,7 @@ import { getVisibleIniPanelEntries, createMachineSessionControlPageController, createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, readMachineSessionReadonlyStatus, loadMachineSessionForControlPageWorkflow, createControlPageSessionLoadState, @@ -26,8 +27,8 @@ import { ``` `ui-shell.js` re-exports the entry manifest, the read-only control-page -controller, the unified read-only status API, and the control-view renderer. It -does not implement CNC behavior. +controller, the unified read-only status API, the readonly-status API manifest, +and the control-view renderer. It does not implement CNC behavior. ## Pages @@ -56,6 +57,9 @@ mounting the existing control-page controller, refresh workflow, and renderer. Use `controlPage.readStatus` or `readMachineSessionReadonlyStatus()` when an outer shell needs one stable read of `stateBundle`, `workflowStatus`, `overview`, `controlView`, `session`, `runReadiness`, and `run`. +Use `createMachineSessionReadonlyStatusApiManifest()` or +`controlPage.readonlyStatusApiManifest` when you only need the API shape and +method names. The control-page refresh workflow lives in `runtime/ui/ini-panel/control-page-refresh-workflow.js`. Use diff --git a/wasm-port/runtime/ui/ini-panel/readonly-status-api.js b/wasm-port/runtime/ui/ini-panel/readonly-status-api.js index 2404d5a..9b2e831 100644 --- a/wasm-port/runtime/ui/ini-panel/readonly-status-api.js +++ b/wasm-port/runtime/ui/ini-panel/readonly-status-api.js @@ -21,6 +21,35 @@ export function createMachineSessionReadonlyStatus({ }; } +export function createMachineSessionReadonlyStatusApiManifest() { + return { + apiName: "machine-session-readonly-status", + methods: { + readStatus: { + input: "{ getPanelApi, getControlView }", + output: "readonly machine-session status snapshot", + }, + }, + relatedControlPageMethods: [ + "loadSessionState", + "readStatus", + "refresh", + "renderView", + ], + statusFields: [ + "stateBundle", + "workflowStatus", + "overview", + "controlView", + "report", + "runReadiness", + "run", + "session", + "status", + ], + }; +} + export function readMachineSessionReadonlyStatus({ getPanelApi, getControlView } = {}) { if (typeof getPanelApi !== "function") { throw new Error("A panel API getter is required."); diff --git a/wasm-port/runtime/ui/ini-panel/ui-shell.js b/wasm-port/runtime/ui/ini-panel/ui-shell.js index 0177dad..1a1d85f 100644 --- a/wasm-port/runtime/ui/ini-panel/ui-shell.js +++ b/wasm-port/runtime/ui/ini-panel/ui-shell.js @@ -20,6 +20,7 @@ import { } from "./control-page-session-workflow.js"; import { createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, readMachineSessionReadonlyStatus, } from "./readonly-status-api.js"; export { @@ -33,6 +34,7 @@ export { } from "./control-page-session-workflow.js"; export { createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, readMachineSessionReadonlyStatus, } from "./readonly-status-api.js"; export { @@ -70,6 +72,7 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries controlPage: { createController: createMachineSessionControlPageController, loadSessionState: loadMachineSessionForControlPageWorkflow, + readonlyStatusApiManifest: createMachineSessionReadonlyStatusApiManifest(), readStatus: readMachineSessionReadonlyStatus, refresh: refreshMachineSessionControlPage, renderView: renderMachineSessionControlView, 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 fbaf2b8..3e206ba 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 @@ -10,6 +10,7 @@ import { createIniPanelLauncherLinkViewModel, createIniPanelShellViewModel, createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, loadMachineSessionForControlPageWorkflow, readMachineSessionReadonlyStatus, refreshMachineSessionControlPage, @@ -39,6 +40,7 @@ const requiredShellExports = [ "getVisibleIniPanelEntries", "createMachineSessionControlPageController", "createMachineSessionReadonlyStatus", + "createMachineSessionReadonlyStatusApiManifest", "loadMachineSessionForControlPageWorkflow", "readMachineSessionReadonlyStatus", "refreshMachineSessionControlPage", @@ -101,7 +103,13 @@ assert.deepEqual(createControlPageSessionLoadState({ phase: "waiting-panel" }), }); assert.equal(typeof createIniPanelShellViewModel().controlPage.createController, "function"); assert.equal(typeof createMachineSessionReadonlyStatus, "function"); +assert.equal(typeof createMachineSessionReadonlyStatusApiManifest, "function"); assert.equal(createIniPanelShellViewModel().controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow); +assert.equal(createIniPanelShellViewModel().controlPage.readonlyStatusApiManifest.apiName, "machine-session-readonly-status"); +assert.deepEqual( + createIniPanelShellViewModel().controlPage.readonlyStatusApiManifest, + createMachineSessionReadonlyStatusApiManifest(), +); assert.equal(createIniPanelShellViewModel().controlPage.readStatus, readMachineSessionReadonlyStatus); assert.equal(createIniPanelShellViewModel().controlPage.refresh, refreshMachineSessionControlPage); assert.equal(typeof createIniPanelShellViewModel().controlPage.renderView, "function"); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_readonly_status_api.mjs b/wasm-port/tests/ui/node/verify_ini_panel_readonly_status_api.mjs index 35397e9..db88678 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_readonly_status_api.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_readonly_status_api.mjs @@ -2,6 +2,7 @@ import assert from "node:assert/strict"; import { createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, readMachineSessionReadonlyStatus, } from "../../../runtime/ui/ini-panel/readonly-status-api.js"; @@ -82,6 +83,33 @@ assert.deepEqual(createMachineSessionReadonlyStatus(), { }, }); +assert.deepEqual(createMachineSessionReadonlyStatusApiManifest(), { + apiName: "machine-session-readonly-status", + methods: { + readStatus: { + input: "{ getPanelApi, getControlView }", + output: "readonly machine-session status snapshot", + }, + }, + relatedControlPageMethods: [ + "loadSessionState", + "readStatus", + "refresh", + "renderView", + ], + statusFields: [ + "stateBundle", + "workflowStatus", + "overview", + "controlView", + "report", + "runReadiness", + "run", + "session", + "status", + ], +}); + const panelApi = { getMachineSessionStateBundle: () => stateBundle, getMachineSessionWorkflowStatus: () => workflowStatus, 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 3d739b6..17bddfa 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 @@ -6,6 +6,7 @@ import { createIniPanelLauncherLinkViewModel, createIniPanelShellViewModel, createMachineSessionReadonlyStatus, + createMachineSessionReadonlyStatusApiManifest, createControlPageRefreshState, createControlPageSessionLoadState, createMachineSessionControlPageController, @@ -41,6 +42,7 @@ assert.deepEqual(createControlPageSessionLoadState({ phase: "waiting-panel" }), assert.equal(getIniPanelEntryByHref("./index.html")?.id, "edit-run"); assert.equal(typeof createMachineSessionControlPageController, "function"); assert.equal(typeof createMachineSessionReadonlyStatus, "function"); +assert.equal(typeof createMachineSessionReadonlyStatusApiManifest, "function"); assert.equal(typeof loadMachineSessionForControlPageWorkflow, "function"); assert.equal(typeof readMachineSessionReadonlyStatus, "function"); assert.equal(typeof refreshMachineSessionControlPage, "function"); @@ -83,6 +85,8 @@ assert.deepEqual(shellViewModel.pages, [ assert.deepEqual(shellViewModel.launcherLinks, createIniPanelLauncherLinkViewModel()); assert.equal(shellViewModel.controlPage.createController, createMachineSessionControlPageController); assert.equal(shellViewModel.controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow); +assert.equal(shellViewModel.controlPage.readonlyStatusApiManifest.apiName, "machine-session-readonly-status"); +assert.deepEqual(shellViewModel.controlPage.readonlyStatusApiManifest, createMachineSessionReadonlyStatusApiManifest()); assert.equal(shellViewModel.controlPage.readStatus, readMachineSessionReadonlyStatus); assert.equal(shellViewModel.controlPage.refresh, refreshMachineSessionControlPage); assert.equal(shellViewModel.controlPage.renderView, renderMachineSessionControlView);