import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { INI_PANEL_ENTRIES, analyzeIniRuntimeBoundaries, createControlPageBrowserApiManifest, createControlPageBrowserApiMethods, createControlPageBrowserApiSchema, createIniPanelLaunchApiManifest, createIniPanelLauncherLinkViewModel, createIniPanelShellApiSurfaceInventory, createIniPanelShellControlPageContract, createIniPanelShellIntegrationManifest, createIniPanelShellIntegrationReadiness, createIniPanelShellIntegrationSchema, createIniPanelShellIntegrationWorkflowPlan, createIniPanelShellSessionReadinessWorkflowReport, createIniPanelShellViewModel, createIniPanelShellWorkflowOverviewContract, createIniPanelShellWorkflowOverviewEmbeddingMountDomContract, createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness, createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState, createLinuxCncIniSdk, createLinuxCncInterpSdk, createMachineSessionSnapshotPayload, createMachineSessionPersistenceDisplayViewModel, createMachineSessionPersistenceRenderState, createMachineSessionPersistenceSummary, createProjectReleaseGateActionPlan, createProjectReleaseGateManifest, createProjectReleaseGateResultMatrix, createProjectReleaseReadinessArtifactValidation, createProjectReleaseReadinessArtifactValidationSummaryViewModel, createProjectReleaseReadinessReport, createProjectReleaseReadinessSummaryViewModel, parseProjectReleaseReadinessArtifactJson, createSessionSnapshot, defaultMachinePaths, gcodeFilenameFromProgramPath, gcodeProgramPath, getIniPanelEntryByHref, getIniPanelEntryManifest, getOpfsRoot, getVisibleIniPanelEntries, isSupportedIniPanelControlPageApiManifest, isSupportedIniPanelLaunchApiManifest, isSupportedIniPanelShellIntegrationManifest, loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl, loadMachineSessionFromOpfs, loadMachineSessionSnapshot, loadMachineTextFiles, loadMachineToolTableFromOpfs, loadTextFile, machineFilePaths, machineIniPath, mountIniPanelShellWorkflowOverviewEmbeddingMountState, mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, normalizeOpfsPath, parameterFilePath, planIniFileContextStaging, planSimConfigStaging, readMachineSessionReadiness, renderIniPanelShellWorkflowOverviewEmbeddingMountState, renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, restoreMachineParametersFromOpfs, saveMachineSessionSnapshot, saveMachineTextFiles, saveSessionSnapshot, saveTextFile, sessionSnapshotPath, toolTablePath, validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson, validateSessionSnapshot, } from "../../../runtime/sdk/src/index.js"; const __dirname = dirname(fileURLToPath(import.meta.url)); const root = resolve(__dirname, "../../.."); const sdkIndexText = readFileSync(resolve(root, "runtime/sdk/src/index.js"), "utf8"); const sdkReadmeText = readFileSync(resolve(root, "runtime/sdk/README.md"), "utf8"); const trackerText = readFileSync(resolve(root, "../PROJECT_COMPLETION_TRACKER.md"), "utf8"); const requiredExports = [ ["createLinuxCncIniSdk", createLinuxCncIniSdk], ["createLinuxCncInterpSdk", createLinuxCncInterpSdk], ["createProjectReleaseGateActionPlan", createProjectReleaseGateActionPlan], ["createProjectReleaseGateManifest", createProjectReleaseGateManifest], ["createProjectReleaseGateResultMatrix", createProjectReleaseGateResultMatrix], ["createProjectReleaseReadinessArtifactValidation", createProjectReleaseReadinessArtifactValidation], [ "createProjectReleaseReadinessArtifactValidationSummaryViewModel", createProjectReleaseReadinessArtifactValidationSummaryViewModel, ], ["createProjectReleaseReadinessReport", createProjectReleaseReadinessReport], ["createProjectReleaseReadinessSummaryViewModel", createProjectReleaseReadinessSummaryViewModel], ["parseProjectReleaseReadinessArtifactJson", parseProjectReleaseReadinessArtifactJson], [ "validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson", validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson, ], [ "loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl", loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl, ], ["planIniFileContextStaging", planIniFileContextStaging], ["planSimConfigStaging", planSimConfigStaging], ["analyzeIniRuntimeBoundaries", analyzeIniRuntimeBoundaries], ["getIniPanelEntryManifest", getIniPanelEntryManifest], ["getIniPanelEntryByHref", getIniPanelEntryByHref], ["getVisibleIniPanelEntries", getVisibleIniPanelEntries], ["createIniPanelLauncherLinkViewModel", createIniPanelLauncherLinkViewModel], ["createMachineSessionPersistenceDisplayViewModel", createMachineSessionPersistenceDisplayViewModel], ["createMachineSessionPersistenceRenderState", createMachineSessionPersistenceRenderState], ["createMachineSessionPersistenceSummary", createMachineSessionPersistenceSummary], ["getOpfsRoot", getOpfsRoot], ["saveTextFile", saveTextFile], ["loadTextFile", loadTextFile], ["machineIniPath", machineIniPath], ["toolTablePath", toolTablePath], ["parameterFilePath", parameterFilePath], ["gcodeProgramPath", gcodeProgramPath], ["sessionSnapshotPath", sessionSnapshotPath], ["defaultMachinePaths", defaultMachinePaths], ["normalizeOpfsPath", normalizeOpfsPath], ["createMachineSessionSnapshotPayload", createMachineSessionSnapshotPayload], ["createSessionSnapshot", createSessionSnapshot], ["saveSessionSnapshot", saveSessionSnapshot], ["saveMachineSessionSnapshot", saveMachineSessionSnapshot], ["loadMachineSessionSnapshot", loadMachineSessionSnapshot], ["validateSessionSnapshot", validateSessionSnapshot], ["machineFilePaths", machineFilePaths], ["saveMachineTextFiles", saveMachineTextFiles], ["loadMachineTextFiles", loadMachineTextFiles], ["gcodeFilenameFromProgramPath", gcodeFilenameFromProgramPath], ["restoreMachineParametersFromOpfs", restoreMachineParametersFromOpfs], ["loadMachineToolTableFromOpfs", loadMachineToolTableFromOpfs], ["loadMachineSessionFromOpfs", loadMachineSessionFromOpfs], ["readMachineSessionReadiness", readMachineSessionReadiness], ["createControlPageBrowserApiSchema", createControlPageBrowserApiSchema], ["createControlPageBrowserApiManifest", createControlPageBrowserApiManifest], ["createControlPageBrowserApiMethods", createControlPageBrowserApiMethods], ["createIniPanelShellControlPageContract", createIniPanelShellControlPageContract], ["isSupportedIniPanelControlPageApiManifest", isSupportedIniPanelControlPageApiManifest], ["createIniPanelLaunchApiManifest", createIniPanelLaunchApiManifest], ["isSupportedIniPanelLaunchApiManifest", isSupportedIniPanelLaunchApiManifest], ["createIniPanelShellIntegrationSchema", createIniPanelShellIntegrationSchema], ["createIniPanelShellIntegrationManifest", createIniPanelShellIntegrationManifest], ["createIniPanelShellIntegrationReadiness", createIniPanelShellIntegrationReadiness], ["createIniPanelShellIntegrationWorkflowPlan", createIniPanelShellIntegrationWorkflowPlan], ["isSupportedIniPanelShellIntegrationManifest", isSupportedIniPanelShellIntegrationManifest], ["createIniPanelShellViewModel", createIniPanelShellViewModel], ["createIniPanelShellApiSurfaceInventory", createIniPanelShellApiSurfaceInventory], ["createIniPanelShellSessionReadinessWorkflowReport", createIniPanelShellSessionReadinessWorkflowReport], ["createIniPanelShellWorkflowOverviewContract", createIniPanelShellWorkflowOverviewContract], [ "createIniPanelShellWorkflowOverviewEmbeddingMountDomContract", createIniPanelShellWorkflowOverviewEmbeddingMountDomContract, ], [ "createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness", createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness, ], [ "createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel", createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel, ], [ "createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState", createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState, ], [ "createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract", createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract, ], [ "createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness", createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness, ], [ "renderIniPanelShellWorkflowOverviewEmbeddingMountState", renderIniPanelShellWorkflowOverviewEmbeddingMountState, ], [ "renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState", renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, ], [ "mountIniPanelShellWorkflowOverviewEmbeddingMountState", mountIniPanelShellWorkflowOverviewEmbeddingMountState, ], [ "mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState", mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState, ], ]; for (const [name, value] of requiredExports) { assert.equal(typeof value, "function", `${name} SDK export drift`); assert.match(sdkIndexText, new RegExp(`\\b${name}\\b`)); assert.match(sdkReadmeText, new RegExp(`\\b${name}\\b`)); } assert.equal(machineIniPath("sdk-mill"), "linuxcnc/machines/sdk-mill/machine.ini"); assert.deepEqual(defaultMachinePaths("sdk-mill"), machineFilePaths("sdk-mill")); assert.equal(gcodeProgramPath("demo.ngc"), "linuxcnc/gcode/demo.ngc"); assert.equal(sessionSnapshotPath("sdk-session"), "linuxcnc/sessions/sdk-session/snapshot.json"); assert.equal(normalizeOpfsPath("linuxcnc/machines/sdk-mill/tool.tbl"), "linuxcnc/machines/sdk-mill/tool.tbl"); assert.equal(gcodeFilenameFromProgramPath("linuxcnc/gcode/demo.ngc"), "demo.ngc"); const releaseReadinessWaiting = createProjectReleaseReadinessReport(); assert.equal(releaseReadinessWaiting.apiName, "project-release-readiness-report"); assert.equal(releaseReadinessWaiting.ready, false); assert.deepEqual(releaseReadinessWaiting.missing, ["project-release-gate"]); assert.equal(releaseReadinessWaiting.simConfigInventory.unexpectedFail, 0); assert.deepEqual(releaseReadinessWaiting.promotedBlockedFamilies, []); assert.equal(releaseReadinessWaiting.gateActionPlan.apiName, "project-release-gate-action-plan"); assert.equal(releaseReadinessWaiting.gateActionPlan.pendingCount, 10); assert.equal(releaseReadinessWaiting.gateActionPlan.nextGateId, "diff-check"); assert.equal( releaseReadinessWaiting.rows.find(({ id }) => id === "blocked-runtime-families")?.value, "L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP", ); const releaseReadinessReady = createProjectReleaseReadinessReport({ observedOutputs: ["project_release_gate=ok"], }); assert.equal(releaseReadinessReady.ready, true); assert.equal(releaseReadinessReady.releaseGate.passed, true); assert.deepEqual(releaseReadinessReady.gateManifest, createProjectReleaseGateManifest()); assert.equal(releaseReadinessReady.gateResultMatrix.rows.length, 10); assert.equal(createProjectReleaseGateActionPlan({ gateResultMatrix: releaseReadinessReady.gateResultMatrix, }).ready, false); assert.equal(createProjectReleaseGateActionPlan({ gateResults: Object.fromEntries(createProjectReleaseGateManifest().gateIds.map((id) => [id, true])), }).shellScript, "# Project release gates are already marked passed.\n"); assert.equal(createProjectReleaseReadinessSummaryViewModel(releaseReadinessReady).statusLine, "Ready: No blocking reasons"); assert.equal( createProjectReleaseGateResultMatrix({ observedOutputs: ["project_release_gate=ok"], }).rows.find(({ id }) => id === "project-release-gate")?.passed, true, ); const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.stringify(createProjectReleaseReadinessReport({ gateResults: { "diff-check": true, "vendor-sync": true, "standalone-cnc-semantics": true, "interp-wasm": true, "sim-config-inventory": true, "ini-panel-browser": true, "release-artifact-url-browser": true, "ui-node-smokes": true, "host-smokes": true, "project-release-gate": true, }, }))); assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report"); const releaseReadinessArtifactValidation = createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact); assert.deepEqual(releaseReadinessArtifactValidation, { apiName: "project-release-readiness-artifact-validation", validationVersion: 1, phase: "ready", ready: true, missing: [], artifactApiName: "project-release-readiness-report", artifactVersion: 1, gateCount: 10, expectedGateCount: 10, expectedGateIds: createProjectReleaseGateManifest().gateIds, gateManifestReady: true, gateResultMatrixReady: true, gateActionPlanReady: true, blockedRuntimeFamilies: [ "L4-USER-M-PROCESS", "L4-TOOL-DB", "L4-PYTHON-REMAP", ], rows: [ { id: "artifact", label: "Readiness artifact", value: "project-release-readiness-report", }, { id: "project-release-gate", label: "Project release gate", value: "passed", }, { id: "gate-manifest", label: "Gate manifest", value: "ready", }, { id: "gate-result-matrix", label: "Gate result matrix", value: "ready", }, { id: "gate-action-plan", label: "Gate action plan", value: "ready", }, { id: "validation", label: "Artifact validation", value: "ready", }, ], }); assert.equal( createProjectReleaseReadinessArtifactValidationSummaryViewModel( releaseReadinessArtifactValidation, ).statusLine, "Ready: Artifact evidence complete", ); assert.deepEqual( createProjectReleaseReadinessArtifactValidation({}).missing, [ "apiName", "reportVersion", "phase", "ready", "missing", "releaseGate.command", "releaseGate.passed", "releaseGate.expectedOutput", "simConfigInventory.executed", "simConfigInventory.passed", "simConfigInventory.skipped", "simConfigInventory.unexpectedFail", "blockedRuntimeFamilies", "gateManifest", "gateResultMatrix", "gateActionPlan", "gates.length", "gates.passed", "rows.project-release-gate", ], ); assert.equal( validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)).ready, true, ); assert.equal( (await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({ artifactUrl: "/project-release-readiness.json", fetchRef: async () => ({ ok: true, status: 200, text: async () => 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"], promotedRuntimeFamilies: ["L4-TOOL-DB"], }).missing.includes("blocked-runtime-families"), true, ); assert.deepEqual(getIniPanelEntryManifest(), INI_PANEL_ENTRIES); assert.deepEqual(getVisibleIniPanelEntries(), INI_PANEL_ENTRIES); assert.deepEqual(getIniPanelEntryByHref("./control-page.html"), { id: "control-view", title: "Open read-only control view", href: "./control-page.html", }); assert.deepEqual(createIniPanelLauncherLinkViewModel(), [ { entryId: "edit-run", href: "./index.html", label: "Open edit and run panel", }, { entryId: "control-view", href: "./control-page.html", label: "Open read-only control view", }, { entryId: "workflow-overview", href: "./workflow-overview.html", label: "Open shell handoff overview", }, ]); assert.equal( createMachineSessionPersistenceSummary({ state: { badges: { opfs: "OPFS: ready" }, fields: { sessionSnapshot: "sdk-session/snapshot.json", sessionIni: "/work/session-machine.ini" }, sessionLoad: { iniWasmPath: "/work/session-machine.ini" }, sessionReadiness: { phase: "ready", ready: true, missing: [] }, }, }).rows.find(({ id }) => id === "session-load")?.value, "loaded: /work/session-machine.ini", ); assert.equal( createMachineSessionPersistenceRenderState( createMachineSessionPersistenceDisplayViewModel(createMachineSessionPersistenceSummary()), ).apiName, "machine-session-persistence-render-state", ); const controlPageApiSchema = createControlPageBrowserApiSchema(); const controlPageApiManifest = createControlPageBrowserApiManifest(); assert.equal(controlPageApiSchema.apiName, "ini-panel-control-page"); assert.equal(isSupportedIniPanelControlPageApiManifest(controlPageApiManifest), true); assert.deepEqual(controlPageApiManifest.methods, createControlPageBrowserApiMethods()); assert.equal( createIniPanelShellControlPageContract().readonlyStatusApiManifest.apiName, "machine-session-readonly-status", ); const launchManifest = createIniPanelLaunchApiManifest(); assert.equal(isSupportedIniPanelLaunchApiManifest(launchManifest), true); assert.equal( launchManifest.methods.includes("mountWorkflowOverviewEmbeddingMountState"), true, ); assert.deepEqual( launchManifest.visibleEntries, getVisibleIniPanelEntries().map(({ id, href, title }) => ({ id, href, title })), ); const shellIntegrationManifest = createIniPanelShellIntegrationManifest(); assert.equal(createIniPanelShellIntegrationSchema().apiName, "ini-panel-shell-integration"); assert.equal(isSupportedIniPanelShellIntegrationManifest(shellIntegrationManifest), true); assert.equal(createIniPanelShellIntegrationReadiness(shellIntegrationManifest).ready, true); assert.equal(createIniPanelShellIntegrationWorkflowPlan({ manifest: shellIntegrationManifest, }).ready, true); assert.equal( createIniPanelShellWorkflowOverviewContract().methodNames.includes("getWorkflowOverviewApiSurfaceInventory"), true, ); const shellViewModel = createIniPanelShellViewModel(); assert.equal( shellViewModel.launchApiManifest.methods.includes("mountWorkflowOverviewEmbeddingMountState"), true, ); assert.equal( shellViewModel.launchApiManifest.methods.includes("getShellSessionReadinessWorkflowReport"), true, ); assert.equal( createIniPanelShellSessionReadinessWorkflowReport().apiName, "ini-panel-shell-session-readiness-workflow-report", ); assert.equal( createIniPanelShellApiSurfaceInventory().apiName, "ini-panel-shell-api-surface-inventory", ); assert.equal(shellViewModel.shellApiSurfaceInventory.ready, true); assert.equal( shellViewModel.shellSessionHandoffWorkflowSummary.rows.find( ({ id }) => id === "persistence-summary", )?.value, "waiting: 5 missing", ); assert.equal( shellViewModel.shellSessionHandoffWorkflowSummary.rows.find( ({ id }) => id === "api-surface-inventory", )?.value, "ready: 6 rows", ); assert.equal( shellViewModel.mountWorkflowOverviewEmbeddingMountState, mountIniPanelShellWorkflowOverviewEmbeddingMountState, ); const blockedMount = mountIniPanelShellWorkflowOverviewEmbeddingMountState({ documentRef: null }); assert.equal(blockedMount.apiName, "ini-panel-shell-workflow-overview-embedding-mount-dom-mount"); assert.equal(blockedMount.ready, false); assert.deepEqual(blockedMount.domReadiness.missing, ["document", "mount", "status", "rows"]); assert.match(sdkReadmeText, /OPFS\/session persistence/); assert.match(sdkReadmeText, /INI panel shell handoff/); assert.match(sdkReadmeText, /workflow overview embedding/); assert.match(trackerText, /SDK\/API surface/); console.log("sdk_surface_node_smoke=ok");