import assert from "node:assert/strict"; import { existsSync, readFileSync, readdirSync, statSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join, resolve } from "node:path"; import { after, before, test } from "node:test"; import { createServer } from "vite"; const testRoot = dirname(fileURLToPath(import.meta.url)); const controlStationRoot = resolve(testRoot, ".."); const repositoryRoot = resolve(controlStationRoot, "../.."); const coreSourceRoot = join(controlStationRoot, "src"); const pluginFrontendRoot = join(repositoryRoot, "plugins/xgrids-k1/frontend/src"); const legacyPluginRoot = join(coreSourceRoot, "device-plugins/xgrids-k1"); function sourceFiles(root) { return readdirSync(root).flatMap((entry) => { const path = join(root, entry); if (statSync(path).isDirectory()) return sourceFiles(path); return /\.(?:css|ts|tsx)$/.test(entry) ? [path] : []; }); } let server; let createDevicePluginRegistry; before(async () => { server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true }, }); ({ createDevicePluginRegistry } = await server.ssrLoadModule( "/src/core/device-plugins/registry.ts", )); }); after(async () => { await server?.close(); }); function syntheticPlugin({ pluginId, modelId, componentKey, connectionView, spatialControlsView, }) { return { manifest: { apiVersion: "missioncore.nodedc/v1alpha2", kind: "DevicePlugin", metadata: { id: pluginId, version: "1.0.0", displayName: pluginId }, spec: { hostApiRange: "v1alpha2", runtime: { backendEntrypoint: `${pluginId}:build`, isolation: "transitional-in-process" }, permissions: ["device.read"], actions: [{ id: "state.read", mutating: false, secretFields: [] }], compatibilityProfiles: [{ profileId: `${modelId}.profile.v1`, path: `profiles/${modelId}.json`, modelId, }], models: [{ id: modelId, vendor: pluginId, displayName: modelId, category: "Sensor", description: "Synthetic frontend contribution", verified: true, capabilities: [{ id: "device.read", label: "Read" }], ui: { slot: "device.connection", componentKey }, }], }, }, RuntimeProvider: ({ children }) => children, connectionViews: { [componentKey]: connectionView }, ...(spatialControlsView ? { SpatialControlsView: spatialControlsView } : {}), }; } test("each device plugin contributes its own connection pipeline component", () => { const alphaConnection = () => null; const betaConnection = () => null; const registry = createDevicePluginRegistry([ syntheticPlugin({ pluginId: "synthetic.alpha", modelId: "synthetic.alpha.sensor", componentKey: "alpha.connection", connectionView: alphaConnection, }), syntheticPlugin({ pluginId: "synthetic.beta", modelId: "synthetic.beta.sensor", componentKey: "beta.connection", connectionView: betaConnection, }), ]); assert.equal(registry.resolveModel("synthetic.alpha.sensor").ConnectionView, alphaConnection); assert.equal(registry.resolveModel("synthetic.beta.sensor").ConnectionView, betaConnection); assert.notEqual( registry.resolveModel("synthetic.alpha.sensor").ConnectionView, registry.resolveModel("synthetic.beta.sensor").ConnectionView, ); }); test("selected-model shell leaves the model name to the connection heading", () => { const workspace = readFileSync( join(coreSourceRoot, "workspaces/DeviceWorkspace.tsx"), "utf8", ); const app = readFileSync(join(coreSourceRoot, "App.tsx"), "utf8"); const selectedSlot = workspace.slice(workspace.indexOf("const ConnectionView =")); assert.match(workspace, /

\{model\.displayName\}<\/h3>/); assert.match(selectedSlot, /СЦЕНАРИЙ ПОДКЛЮЧЕНИЯ/); assert.match(selectedSlot, /Модель выбрана<\/strong>/); assert.doesNotMatch(selectedSlot, /selection\.model\.displayName/); assert.doesNotMatch( selectedSlot, /selection\.plugin\.manifest\.metadata\.displayName/, ); const localContour = app.slice( app.indexOf('id: "local-contour"'), app.indexOf("items={rootWorkspaces", app.indexOf('id: "local-contour"')), ); assert.match( localContour, /description: selection \? "Подключение" : "Модель не выбрана"/, ); assert.doesNotMatch(localContour, /activeDevice\?\.endpointLabel/); assert.doesNotMatch(localContour, /selection\?\.model\.displayName/); }); test("registry exposes an optional model-scoped spatial controls contribution", () => { const connectionView = () => null; const spatialControlsView = () => null; const registry = createDevicePluginRegistry([ syntheticPlugin({ pluginId: "synthetic.spatial", modelId: "synthetic.spatial.sensor", componentKey: "spatial.connection", connectionView, spatialControlsView, }), syntheticPlugin({ pluginId: "synthetic.connection-only", modelId: "synthetic.connection-only.sensor", componentKey: "connection-only.connection", connectionView, }), ]); assert.equal( registry.resolveModel("synthetic.spatial.sensor").SpatialControlsView, spatialControlsView, ); assert.equal( registry.resolveModel("synthetic.connection-only.sensor").SpatialControlsView, undefined, ); }); test("XGRIDS frontend is physically plugin-owned and split by operator pipeline", () => { if (existsSync(legacyPluginRoot)) { assert.deepEqual(readdirSync(legacyPluginRoot), []); } for (const relativePath of [ "plugin.ts", "runtimeContext.tsx", "styles.css", "components/K1ProvisioningPipeline.tsx", "components/K1AcquisitionPipeline.tsx", "components/K1SpatialControls.tsx", "components/K1Diagnostics.tsx", "physicalCommandConfirmation.ts", "projectName.ts", ]) { assert.equal(existsSync(join(pluginFrontendRoot, relativePath)), true, relativePath); } const spatialControls = readFileSync( join(pluginFrontendRoot, "components/K1SpatialControls.tsx"), "utf8", ); assert.match(spatialControls, /shouldRenderSpatialControls\(state\)/); assert.match(spatialControls, /cleanup_pending/); assert.match(spatialControls, /spatialActionFailure/); assert.match(spatialControls, /role="alert"/); assert.doesNotMatch(spatialControls, /Повторить остановку/); assert.match(spatialControls, /stopLocalReceiver/); assert.match(spatialControls, / { const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const lifecycle = readFileSync(join(pluginFrontendRoot, "lifecycle.ts"), "utf8"); const submitPrerequisites = lifecycle.slice( lifecycle.indexOf("export function canSubmitProvisioningMutation"), lifecycle.indexOf("export function canAdmitProvisioningConnection"), ); assert.match(provisioning, /bridge:\s*\{/); assert.match( provisioning, /compatibility_attestation: profileSelectionForConnectionMode\([\s\S]*attemptedConnectionMode/, ); assert.match(provisioning, /scanSecondsRemaining/); assert.match(provisioning, /setInterval\(updateCountdown, 250\)/); assert.match(provisioning, /Поиск Bluetooth · до \{scanSecondsRemaining \?\? BLE_DISCOVERY_TIMEOUT_SECONDS\} с/); assert.match(provisioning, /scanWithResult\(\{[^}]*durationSeconds:\s*BLE_DISCOVERY_TIMEOUT_SECONDS/); assert.doesNotMatch(provisioning, /K1 уже доступен|Сетевой адрес K1 доступен/); assert.doesNotMatch( provisioning, /automaticRecovery|automaticDiscovery|reconnectFallbackAction/, ); assert.match(provisioning, /Переподключиться/); assert.match(provisioning, /Подключить новый K1/); assert.doesNotMatch(provisioning, /Вернуть прежний K1 и проверить/); assert.match(provisioning, /explicitProvisioningDraftMatches/); assert.doesNotMatch( provisioning, /powerConfirmed|powerConfirmationEpoch|resetPowerConfirmation|Питание включено|title="Питание"/, ); assert.doesNotMatch(submitPrerequisites, /power|питани/i); assert.match(provisioning, /ПОДКЛЮЧЕНИЕ · ШАГИ 01–02/); assert.match( provisioning, /number="01"[\s\S]*?title="Подключение"/, ); assert.match(provisioning, /number="02"[\s\S]*?title="Сеть"/); assert.doesNotMatch(provisioning, /number="03"|showDeviceStep/); assert.match( provisioning, /const backendScanAllowed = scanAllowedByPolicy\s*&& !isBusy\s*&& !networkRecoveryRequired/, ); assert.match(provisioning, /const showNetworkStep = Boolean\([\s\S]*explicitProvisioningDraftRetained/); assert.match( provisioning, /if \(result\.networkIntentCompleted\)[\s\S]*setExplicitProvisioningDraft\(null\)/, ); assert.equal( (provisioning.match(/buttonLabel:\s*"Применить"/g) ?? []).length, 3, ); assert.doesNotMatch(provisioning, /<(?:button|input|select|textarea)\b/); assert.doesNotMatch(provisioning, /allow_host_wifi_switch/); assert.doesNotMatch(provisioning, /(?:color|background(?:-color)?):\s*(?:#[0-9a-f]{3,8}|rgba?\()/i); for (const sharedControl of ["Button", "IconButton", "TextField", "ActivityIndicator", "StatusBadge"]) { const password = readFileSync(join(pluginFrontendRoot, "components/K1WifiPasswordField.tsx"), "utf8"); assert.match(provisioning + password, new RegExp(`<${sharedControl}\\b`), sharedControl); } assert.doesNotMatch( provisioning, /Подключиться к сохранённому|Исходный K1|Проверить связь с K1|Проверить прежнее подключение/, ); }); test("K1 click-owned actions are fenced without hidden frontend continuations", () => { const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const search = provisioning.slice( provisioning.indexOf("const repeatDeviceScan"), provisioning.indexOf("const submitConnect"), ); const apply = provisioning.slice( provisioning.indexOf("const submitConnect"), provisioning.indexOf("const verifyAppliedNetwork"), ); assert.equal((search.match(/scanWithResult\(/g) ?? []).length, 1); assert.match(search, /durationSeconds:\s*BLE_DISCOVERY_TIMEOUT_SECONDS/); assert.equal((apply.match(/await connect\(/g) ?? []).length, 1); assert.doesNotMatch( apply, /scanWithResult\(|verifyConnection\(|candidateRefresh|void submitConnect/, ); assert.match(runtime, /class SnapshotRuntimeActionArbiter/); assert.match(runtime, /runtimeActionArbiter\.current\.isCurrent\(actionToken\)/); assert.match(runtime, /runtimeActionArbiter\.current\.settle\(actionToken\)/); }); test("connected presentation uses canonical process copy", () => { const connection = readFileSync( join(pluginFrontendRoot, "XgridsK1Connection.tsx"), "utf8", ); assert.match( connection, /connectionTopology\?\.status === "active"\s*\? "Подключение установлено"/, ); assert.match(connection, /"Готово к новой сессии\."/); assert.match(connection, /

Подключение \{model\.displayName\}<\/h2>/); assert.match( connection, /const operationalPanelsVisible = shouldRenderK1OperationalPanels\(\s*state,\s*controller\.pendingAction,\s*\)/, ); assert.match( connection, /operationalPanelsVisible \? : null/, ); assert.match( connection, / { const app = readFileSync(join(coreSourceRoot, "App.tsx"), "utf8"); const shellPresentation = readFileSync( join(coreSourceRoot, "presentation.ts"), "utf8", ); const connection = readFileSync( join(pluginFrontendRoot, "XgridsK1Connection.tsx"), "utf8", ); const operatorError = readFileSync( join(pluginFrontendRoot, "components/K1OperatorError.tsx"), "utf8", ); const acquisition = readFileSync( join(pluginFrontendRoot, "components/K1AcquisitionPipeline.tsx"), "utf8", ); const metrics = readFileSync( join(pluginFrontendRoot, "components/K1Metrics.tsx"), "utf8", ); assert.match(connection, /

Подключение \{model\.displayName\}<\/h2>/); assert.doesNotMatch(connection, /:\s*message\}/); assert.match( operatorError, /Подключение не завершено\. Автоматического повтора не было/, ); const deviceHeader = app.slice( app.indexOf('activeDefinition.kind === "device" ? ('), app.indexOf('activeDefinition.kind === "spatial"', app.indexOf('activeDefinition.kind === "device" ? (')), ); assert.match(deviceHeader, /localConnectionPhaseLabel\(runtime\.state\?\.phase\)/); assert.doesNotMatch(deviceHeader, /phaseLabel\(runtime\.state\?\.phase\)/); assert.match( shellPresentation, /phase === "configuring"\) return "Подключение"/, ); assert.match( shellPresentation, /phase === "connected"\) return "Подключение установлено"/, ); assert.match(shellPresentation, /configuring: "Настройка устройства"/); assert.match(shellPresentation, /connected: "Устройство подключено"/); assert.match(acquisition, /hint="Локальный файл записи"/); assert.match(acquisition, /Состояние сканирования остаётся неизвестным/); assert.doesNotMatch( acquisition, /Локальный файл исходных данных|Физическое состояние сканера/, ); assert.match(metrics, /Данные потока при этом сохраняются/); assert.doesNotMatch(metrics, /Исходные данные при этом сохраняются/); }); test("K1 START renders an in-button spinner for the complete live orchestration", () => { const acquisition = readFileSync( join(pluginFrontendRoot, "components/K1AcquisitionPipeline.tsx"), "utf8", ); assert.match(acquisition, /pendingAction === "live"[\s\S]* { const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const exactReady = runtime.slice( runtime.indexOf("function hasExactConnectionReady"), runtime.indexOf("async function waitForPhysicalReconciliationProof"), ); const connectFlow = runtime.slice( runtime.indexOf("const connect = useCallback"), runtime.indexOf("const verifyConnection = useCallback"), ); const appliedProof = runtime.slice( runtime.indexOf("export function exactAppliedNetworkIntentCompleted"), runtime.indexOf("function requireExactReadOnlyVerificationOutcome"), ); assert.match(exactReady, /state\.desired_connection_mode === connectionMode/); assert.match(exactReady, /state\.active_connection_mode === connectionMode/); assert.match(exactReady, /application_control_session\?\.state === "connection-ready"/); assert.match(exactReady, /currentAppliedConnectionTopology\(state, connectionMode\)\?\.status === "active"/); assert.doesNotMatch(connectFlow, /openApplicationControlSession|waitForControlPhase/); assert.doesNotMatch(connectFlow, /verifyConnection\(|scanWithResult\(/); assert.doesNotMatch(connectFlow, /startAcquisition|startPreparedAcquisition|START acquisition/); assert.match(connectFlow, /networkIntentCompleted/); assert.match(appliedProof, /attempt\.phase === "network_applied"/); assert.match(appliedProof, /operation\.status === "succeeded"/); assert.match(appliedProof, /operationPhase === "network_applied"/); assert.match(appliedProof, /ledger\.resolution === "target-observed"/); assert.match(appliedProof, /deviceNetwork\?\.state === "applied"/); assert.doesNotMatch(appliedProof, /control_state/); assert.match( connectFlow, /const exactNetworkIntentCompleted = exactAppliedNetworkIntentCompleted\([\s\S]*?if \(\s*!exactNetworkIntentCompleted\s*&& !hasExactConnectionReady\([\s\S]*?return requireExactConnectionReady\([\s\S]*?nextState = acceptSuccessfulConnectState\(nextState\)/, ); assert.match(provisioning, /Подключение установлено/); assert.doesNotMatch( provisioning, /Подключиться к сохранённому|Проверить связь с K1|Проверить прежнее подключение/, ); assert.match(provisioning, /Переподключиться/); assert.match(provisioning, /Подключить новый K1/); assert.match(provisioning, /expected_mode_revision: modeAuthority\.desiredModeRevision/); assert.match( provisioning, /expected_discovery_generation: modeAuthority\.discoveryGeneration/, ); assert.doesNotMatch(provisioning, /Настройки сети применены/); }); test("K1 mode reset is explicit while Scan and Apply keep exact backend CAS", () => { const api = readFileSync(join(pluginFrontendRoot, "api.ts"), "utf8"); const manifest = readFileSync(join(pluginFrontendRoot, "manifest.ts"), "utf8"); const connection = readFileSync(join(pluginFrontendRoot, "XgridsK1Connection.tsx"), "utf8"); const runtime = readFileSync(join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8"); const acquisition = readFileSync( join(pluginFrontendRoot, "components/K1AcquisitionPipeline.tsx"), "utf8", ); const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); assert.match(manifest, /connectionModeSelect:[\s\S]*"connection\.mode\.select"/); assert.match(api, /interface SelectConnectionModeRequest/); assert.match(api, /expected_revision: number/); assert.match(api, /reset_scenario\?: true/); assert.match(api, /reset_id\?: string/); assert.match(api, /expected_mode_revision: number/); assert.match(api, /expected_discovery_generation: number/); const localModeHandler = connection.slice( connection.indexOf("const updateDesiredConnectionMode"), connection.indexOf("const sourceTone"), ); assert.match(localModeHandler, /setDesiredConnectionMode\(mode\)/); assert.doesNotMatch(localModeHandler, /await|selectConnectionMode\(|refresh\(|connect\(/); assert.match(provisioning, /const commitDesiredModeForExplicitAction = useCallback\(async/); assert.match(provisioning, /await selectConnectionMode\(\{/); assert.match(provisioning, /expected_revision: expectedRevision as number/); assert.match(provisioning, /reset_scenario: true/); assert.match(provisioning, /const resetId = newOperationId\(\)/); assert.match(provisioning, /reset_id: resetId/); assert.match(provisioning, /Подключить новый K1/); const configurationAnchor = provisioning.slice( provisioning.indexOf('
'), provisioning.indexOf('
'), ); assert.doesNotMatch(configurationAnchor, /Подключить новый K1/); assert.match(provisioning, /value=\{connectionMode\}/); assert.doesNotMatch( provisioning, /disabled=\{\s*isBusy\s*\|\|\s*networkRecoveryRequired\s*\|\|\s*physicalRecoveryRequired\s*\|\|\s*connectionRecoveryRequired/, ); assert.match(runtime, /catch \(selectionError\)[\s\S]*xgridsK1Api\.getState\(\)/); assert.match(acquisition, /state\?\.active_connection_mode/); assert.match(acquisition, /desiredSelectionCommitted/); assert.match(acquisition, /configuredConnectionMode !== desiredConnectionMode/); assert.doesNotMatch(acquisition, /Выбран другой способ связи/); }); test("top-right device utility is an explicit pending-aware K1 scenario reset", async () => { const { deviceRuntimeUtilityAction } = await server.ssrLoadModule( "/src/components/useApplicationPanelActions.ts", ); let resetCalls = 0; let refreshCalls = 0; const reset = deviceRuntimeUtilityAction({ refreshRuntime: () => { refreshCalls += 1; }, resetConnectionScenario: async () => { resetCalls += 1; return true; }, connectionScenarioResetting: false, }); assert.equal(reset.label, "Сбросить подключение"); assert.equal(reset.icon, "refresh"); assert.equal(reset.disabled, undefined); reset.onClick(); await Promise.resolve(); assert.equal(resetCalls, 1); assert.equal(refreshCalls, 0); const pending = deviceRuntimeUtilityAction({ refreshRuntime: () => { refreshCalls += 1; }, resetConnectionScenario: async () => true, connectionScenarioResetting: true, }); assert.equal(pending.label, "Сбрасываем подключение"); assert.equal(pending.icon, "activity"); assert.equal(pending.disabled, true); pending.onClick(); await Promise.resolve(); assert.equal(resetCalls, 1); assert.equal(refreshCalls, 0); const app = readFileSync(join(coreSourceRoot, "App.tsx"), "utf8"); const contracts = readFileSync( join(coreSourceRoot, "core/runtime/contracts.ts"), "utf8", ); const runtimeContext = readFileSync( join(pluginFrontendRoot, "runtimeContext.tsx"), "utf8", ); const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const connection = readFileSync( join(pluginFrontendRoot, "XgridsK1Connection.tsx"), "utf8", ); assert.match(contracts, /resetConnectionScenario\?: \(\) => Promise/); assert.match(app, /resetConnectionScenario: runtime\.resetConnectionScenario/); assert.match(app, /connectionScenarioResetting: runtime\.pendingAction === "mode"/); assert.match( runtimeContext, /resetConnectionScenario: controller\.resetConnectionScenario/, ); const resetStart = runtime.indexOf("const resetConnectionScenario"); const resetEnd = runtime.indexOf( "const prepareConnectionReconfigurationWithResult", resetStart, ); assert.notEqual(resetStart, -1); assert.notEqual(resetEnd, -1); const resetFlow = runtime.slice(resetStart, resetEnd); assert.equal((resetFlow.match(/selectConnectionMode\(/g) ?? []).length, 1); assert.match(resetFlow, /connection_mode: DEFAULT_CONNECTION_MODE/); assert.match(resetFlow, /expected_revision: expectedRevision as number/); assert.match(resetFlow, /reset_scenario: true/); assert.match(resetFlow, /reset_id: newOperationId\(\)/); assert.doesNotMatch( resetFlow, /refresh\(|getState\(|scan|verify|connect\(|prepare|start|stop|camera/i, ); const selectStart = runtime.indexOf("const selectConnectionMode"); const selectEnd = runtime.indexOf("const resetConnectionScenario", selectStart); const selectFlow = runtime.slice(selectStart, selectEnd); assert.match(selectFlow, /expected_snapshot_runtime_id: expectedSnapshotRuntimeId\(\)/); assert.match(selectFlow, /supersedePending: request\.reset_scenario === true/); const runStart = runtime.indexOf("const run = useCallback"); const runEnd = runtime.indexOf("const scanWithResult", runStart); const runFlow = runtime.slice(runStart, runEnd); assert.match(runFlow, /setPendingAction\(action\)/); assert.match(runFlow, /setPresentedErrorCorrelation\(null\)/); assert.match(runFlow, /setError\(null\)/); assert.match(runFlow, /setErrorDiagnostic\(null\)/); assert.match(runFlow, /setPendingAction\(null\)/); const draftFenceStart = provisioning.indexOf("const nextFence = localProvisioningDraftFenceKey"); assert.notEqual(draftFenceStart, -1); const draftFence = provisioning.slice(draftFenceStart, draftFenceStart + 2_700); assert.match(draftFence, /reconfigurationRevision/); assert.match(draftFence, /setSelectedDeviceId\(""\)/); assert.match(draftFence, /setSelectedDeviceSnapshot\(null\)/); assert.match(draftFence, /setExplicitProvisioningDraft\(null\)/); assert.match(draftFence, /setSsid\(""\)/); assert.match(draftFence, /setPassword\(""\)/); assert.match(draftFence, /setCandidateUnavailableMessage\(null\)/); assert.match(draftFence, /resetSearchPresentation\(\)/); assert.match( provisioning, /const hydratedScenarioResetPresentationKey = useRef\(null\)/, ); assert.match( provisioning, /hydratedScenarioResetPresentationKey\.current = scenarioResetPresentationKey/, ); assert.match(provisioning, /setConnectionAttemptPresentation\(null\)/); assert.match( provisioning, /const modeResetInFlight = pendingAction === "mode" \|\| modeResetPending !== null/, ); assert.match(provisioning, /if \(modeResetInFlight\) return/); assert.equal((provisioning.match(/disabled=\{modeResetInFlight\}/g) ?? []).length, 1); assert.match(provisioning, /disabled=\{isBusy \|\| modeResetInFlight\}/); assert.match(connection, /const hydratedScenarioResetKey = useRef\(null\)/); assert.match( connection, /scenarioReset\.revision === state\?\.desired_connection_mode_revision/, ); assert.match(connection, /scenarioReset\.desired_mode === backendDesiredMode/); assert.match(connection, /desiredModeLocallyDirty\.current = false/); assert.match(connection, /setDesiredConnectionMode\(backendDesiredMode\)/); }); test("background polling stays read-only while backend state reconciliation retires terminal control", () => { const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const refreshFlow = runtime.slice( runtime.indexOf("const refresh = useCallback"), runtime.indexOf("const run = useCallback"), ); assert.match(runtime, /refresh\(false\)/); assert.match(runtime, /refresh\(true\)/); assert.doesNotMatch(runtime, /terminalControlCleanupInFlight/); assert.doesNotMatch( refreshFlow, /closeApplicationControlSession|startAcquisition|stopAcquisition|networkProvision/, ); assert.match(refreshFlow, /xgridsK1Api\.getState\(\)/); }); test("automatic K1 live start opens the selected delivered camera despite an older saved layout", () => { const app = readFileSync(join(coreSourceRoot, "App.tsx"), "utf8"); const layout = readFileSync( join(coreSourceRoot, "core/observation/useObservationLayout.ts"), "utf8", ); assert.match(app, /observationLayout\.activateAutomaticDefaults\(\)/); assert.match(layout, /const activateAutomaticDefaults = useCallback/); assert.match(layout, /restoredLayoutAuthorityRef\.current = false/); assert.match(layout, /sources\.filter\(canOpenByDefault\)/); assert.match(layout, /source\.capabilities\.overlay/); }); test("K1 connect errors preserve the result and expose explicit recovery", () => { const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const connectStart = runtime.indexOf("const connect = useCallback("); const connectEnd = runtime.indexOf("const verifyConnection = useCallback(", connectStart); assert.notEqual(connectStart, -1); assert.notEqual(connectEnd, -1); const connectFlow = runtime.slice(connectStart, connectEnd); assert.match(connectFlow, /observeProvisioningRequest\(/); assert.match(connectFlow, /operation\?\.status !== "succeeded"/); assert.match(connectFlow, /networkProvisionFailureMessage\(/); assert.doesNotMatch( connectFlow, /требует ручной проверки|измените параметры только после проверки устройства|Сохранён тот же ключ/, ); const networkFlow = readFileSync(join(pluginFrontendRoot, "networkProvisioning.ts"), "utf8"); assert.match(networkFlow, /Проверьте состояние K1 через «Переподключиться»/); assert.match(networkFlow, /новое подключение через поиск Bluetooth/); assert.equal((networkFlow.match(/await context\.send\(/g) ?? []).length, 1); const verifyStart = runtime.indexOf("const verifyConnection = useCallback("); const verifyEnd = runtime.indexOf("const probeConfiguredEndpoint = useCallback(", verifyStart); const verifyFlow = runtime.slice(verifyStart, verifyEnd); assert.match(verifyFlow, /failedOperation\?\.status === "succeeded"/); assert.doesNotMatch(verifyFlow, /xgridsK1Api\.verifyConnection\([^)]*\)[\s\S]*xgridsK1Api\.verifyConnection/); assert.doesNotMatch(runtime, /automatic.?retry\s*:\s*true/); }); test("K1 provisioning keeps the operator draft separate from the backend lease", () => { const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const selection = provisioning.slice( provisioning.indexOf("const selectFreshDevice"), provisioning.indexOf("const chooseAnother"), ); const apply = provisioning.slice( provisioning.indexOf("const submitConnect"), provisioning.indexOf("const verifyAppliedNetwork"), ); assert.match(provisioning, /explicitProvisioningDraftRetained/); assert.match(provisioning, /localProvisioningDraftFenceKey/); assert.match(provisioning, /provisioningIntentKey\(null\)/); assert.match(provisioning, /const \[selectedDeviceSnapshot, setSelectedDeviceSnapshot\]/); assert.doesNotMatch(selection, /await|scanWithResult\(|verifyConnection\(|connect\(/); assert.match(selection, /requestExplicitProvisioning\(device\.device_id/); assert.equal((apply.match(/await connect\(/g) ?? []).length, 1); assert.doesNotMatch(apply, /scanWithResult\(|verifyConnection\(|candidateRefresh/); assert.match(provisioning, /scanWithResult\(\{ durationSeconds: BLE_DISCOVERY_TIMEOUT_SECONDS \}\)/); assert.match( provisioning, / { const styles = readFileSync(join(pluginFrontendRoot, "styles.css"), "utf8"); const baseGrid = styles.slice( styles.indexOf(".device-workspace__grid"), styles.indexOf(".device-workspace__side"), ); const splitThreshold = styles.match( /@container xgrids-k1 \(min-width:\s*([0-9.]+)rem\)/, ); const splitColumns = styles.match( /grid-template-columns:\s*minmax\(([0-9.]+)rem,\s*0\.8fr\)\s*minmax\(([0-9.]+)rem,\s*1\.2fr\)/, ); assert.match(styles, /container:\s*xgrids-k1\s*\/\s*inline-size/); assert.match(styles, /container:\s*k1-connection-panel\s*\/\s*inline-size/); assert.match(styles, /container:\s*k1-session-panel\s*\/\s*inline-size/); assert.match(styles, /@container xgrids-k1 \(min-width:\s*78rem\)/); assert.match( styles, /grid-template-columns:\s*minmax\(32rem,\s*0\.8fr\)\s*minmax\(38rem,\s*1\.2fr\)/, ); assert.match(styles, /@container k1-connection-panel \(max-width:\s*48rem\)/); assert.match(styles, /@container k1-session-panel \(max-width:\s*48rem\)/); assert.match(styles, /@container xgrids-k1 \(max-width:\s*48rem\)/); assert.match(styles, /overflow-wrap:\s*anywhere/); assert.match(baseGrid, /grid-template-columns:\s*minmax\(0,\s*1fr\)/); assert.ok(splitThreshold); assert.ok(splitColumns); const splitThresholdPixels = Number(splitThreshold[1]) * 16; const minimumSplitPixels = (Number(splitColumns[1]) + Number(splitColumns[2]) + 0.85) * 16; assert.equal(splitThresholdPixels, 1248); assert.ok(minimumSplitPixels < splitThresholdPixels); assert.ok(390 < splitThresholdPixels); assert.ok(760 < splitThresholdPixels); assert.ok(1280 > splitThresholdPixels); assert.match( styles, /\.wizard-list,[\s\S]*?\.wizard-step,[\s\S]*?\.session-form,[\s\S]*?\.device-row,[\s\S]*?\.detail-list\s*\{[^}]*min-width:\s*0[^}]*max-width:\s*100%/, ); assert.match( styles, /> \*\s*\{[^}]*min-width:\s*0[^}]*max-width:\s*100%/, ); assert.match( styles, /\.metrics-grid > \*,[\s\S]*?\.device-workspace__grid > \*,[\s\S]*?\.diagnostics-grid > \*\s*\{[^}]*min-width:\s*0[^}]*max-width:\s*100%/, ); assert.match( styles, /\.device-row code,[\s\S]*?\.detail-row code\s*\{[^}]*overflow-wrap:\s*anywhere[^}]*white-space:\s*normal/, ); assert.match( styles, /\.detail-row dd\s*\{[^}]*overflow-wrap:\s*anywhere[^}]*text-overflow:\s*clip[^}]*white-space:\s*normal/, ); assert.match( styles, /\.error-banner__actions > \.nodedc-button\s*\{[^}]*min-width:\s*0[^}]*max-width:\s*100%[^}]*overflow-wrap:\s*anywhere/, ); assert.doesNotMatch( styles, /\.connection-panel,[\s\S]*?\.session-panel\s*\{[^}]*overflow:\s*(?:clip|hidden)/, ); assert.match( styles, /@container k1-connection-panel \(max-width:\s*48rem\)[\s\S]*?\.wizard-step__content > header[^}]*flex-wrap:\s*wrap/, ); assert.match( styles, /@container k1-connection-panel \(max-width:\s*48rem\)[\s\S]*?\.retained-recovery-target > div[^}]*flex-direction:\s*column/, ); assert.match( styles, /@container k1-session-panel \(max-width:\s*48rem\)[\s\S]*?\.panel-heading[^}]*flex-wrap:\s*wrap/, ); assert.match( styles, /\.connection-summary__value > \.nodedc-status,[\s\S]*?white-space:\s*normal/, ); assert.doesNotMatch(styles, /\.nodedc-checker(?:__copy|__label)?\s*\{/); assert.match( styles, /\.workspace-lead__status > span,[\s\S]*?\.nodedc-field__description,[\s\S]*?\.retained-recovery-target small,[\s\S]*?\.session-footer p\s*\{[^}]*overflow-wrap:\s*anywhere/, ); assert.match( styles, /@container xgrids-k1 \(max-width:\s*32rem\)[\s\S]*?\.error-banner__actions\s*\{[^}]*align-items:\s*stretch[^}]*flex-direction:\s*column/, ); assert.doesNotMatch(styles, /@media \(max-width:\s*(?:1280|1480)px\)/); assert.doesNotMatch(styles, /device-recovery-choice/); }); test("Mission Core shell protects the device workspace before the shared mobile breakpoint", () => { const responsive = readFileSync(join(coreSourceRoot, "styles/responsive.css"), "utf8"); assert.match( responsive, /@media \(min-width:\s*761px\) and \(max-width:\s*929px\)/, ); assert.match( responsive, /\.nodedc-app-shell__navigation,\s*\.nodedc-app-shell__content\s*\{[^}]*left:\s*var\(--nodedc-app-page-pad\)[^}]*width:\s*auto/s, ); assert.match( responsive, /\[data-content-open="true"\] \.nodedc-app-shell__navigation\s*\{[^}]*opacity:\s*0[^}]*pointer-events:\s*none/s, ); assert.match( responsive, /@media \(max-width:\s*760px\)[\s\S]*?\.nodedc-application-panel__head,\s*\.nodedc-application-panel__body\s*\{[^}]*width:\s*auto[^}]*min-width:\s*0[^}]*max-width:\s*100%/, ); assert.match( responsive, /\.nodedc-application-panel__head\s*\{[^}]*grid-template-columns:\s*minmax\(0,\s*1fr\)\s*auto/, ); }); test("K1 frontend state models durable mutation and connection supervision facts", () => { const api = readFileSync(join(pluginFrontendRoot, "api.ts"), "utf8"); const lifecycle = readFileSync(join(pluginFrontendRoot, "lifecycle.ts"), "utf8"); assert.match(api, /interface XgridsNetworkMutationLedger/); assert.match(api, /scope:\s*"durable-ledger"/); assert.match(api, /network_mutation_ledger\?: XgridsNetworkMutationLedger \| null/); assert.match(api, /handle_retained\?: boolean/); assert.match(api, /gatt_validated_recently\?: boolean/); assert.match(api, /interface XgridsConnectionSupervisor/); assert.match(api, /interface XgridsConnectionSupervisorDeviceNetwork/); assert.match(api, /device_network: XgridsConnectionSupervisorDeviceNetwork/); assert.match(api, /missioncore\.k1-connection-supervisor\/v1/); assert.match(api, /connection_supervisor\?: XgridsConnectionSupervisor \| null/); assert.match(api, /interface XgridsConnectionPolicy/); assert.match(api, /missioncore\.xgrids-k1-connection-policy\/v1/); assert.match(api, /connection_policy\?: XgridsConnectionPolicy \| null/); assert.match(api, /interface XgridsSemanticTopologyStore/); assert.match(api, /configured_offline_evidence: boolean/); assert.match(api, /live_connection_authority: false/); assert.match(api, /semantic_topology_store\?: XgridsSemanticTopologyStore \| null/); const reconciliation = lifecycle.slice( lifecycle.indexOf("export function readOnlyVerificationClearedReconciliation"), lifecycle.indexOf("export function provisioningCandidateById"), ); assert.match(reconciliation, /nextState\?\.network_mutation_ledger/); assert.match(reconciliation, /nextLedger\.status === "resolved"/); assert.match(reconciliation, /nextLedger\.operation_id === previousOperationId/); assert.doesNotMatch(reconciliation, /snapshot_runtime_id/); }); test("Bridge device and network reconfiguration stays backend-owned and CAS-fenced", () => { const api = readFileSync(join(pluginFrontendRoot, "api.ts"), "utf8"); const manifest = readFileSync(join(pluginFrontendRoot, "manifest.ts"), "utf8"); const lifecycle = readFileSync(join(pluginFrontendRoot, "lifecycle.ts"), "utf8"); const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const prepare = provisioning.slice( provisioning.indexOf("const prepareReconfiguration"), provisioning.indexOf("const changeDesiredConnectionMode"), ); const selection = provisioning.slice( provisioning.indexOf("const selectFreshDevice"), provisioning.indexOf("const chooseAnother"), ); assert.match(manifest, /connectionReconfigurePrepare:[\s\S]*"connection\.reconfigure\.prepare"/); assert.match(api, /expected_reconfiguration_revision: number/); assert.match(api, /expected_reconfiguration_intent_id/); assert.match(prepare, /prepareConnectionReconfigurationWithResult\(\{/); assert.doesNotMatch(prepare, /scanWithResult\(|verifyConnection\(|connect\(/); assert.doesNotMatch(selection, /await|scanWithResult\(|verifyConnection\(|connect\(/); assert.match(provisioning, /showNetworkStep = Boolean\([\s\S]*changeNetworkDialogue/); assert.match(provisioning, /localProvisioningDraftFenceKey/); assert.match(lifecycle, /reconfigurationAllowsFreshDevice/); assert.match(runtime, /prepareConnectionReconfiguration/); }); test("shared runtime exposes only a reachable K1 endpoint as active", () => { const runtimeContext = readFileSync( join(pluginFrontendRoot, "runtimeContext.tsx"), "utf8", ); assert.match( runtimeContext, /endpointLabel: activeConnectionEndpointLabel\(state\)/, ); assert.doesNotMatch(runtimeContext, /endpointLabel: state\.k1_ip/); }); test("every K1 connection and acquisition action is fenced to the accepted backend runtime", () => { const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); assert.match(runtime, /latestState\.current\?\.snapshot_runtime_id/); assert.equal( [...runtime.matchAll( /expected_snapshot_runtime_id: expectedSnapshotRuntimeId\(\)/g, )].length, 14, ); assert.match( runtime, /mode:\s*"graceful",[\s\S]*?expected_snapshot_runtime_id: checkpoint\.snapshotRuntimeId/, ); assert.match( runtime, /xgridsK1Api\.scanBle\([\s\S]*?expected_snapshot_runtime_id/, ); assert.match( runtime, /xgridsK1Api\.verifyConnection\([\s\S]*?expected_snapshot_runtime_id/, ); assert.match( runtime, /xgridsK1Api\.connect\([\s\S]*?expected_snapshot_runtime_id/, ); assert.match( runtime, /xgridsK1Api\.retireUnavailablePhysicalCommand\([\s\S]*?expected_snapshot_runtime_id:\s*exactSnapshotRuntimeId/, ); assert.match( runtime, /run\("retire",[\s\S]*?surfaceErrors: false[\s\S]*?await refresh\(false\)/, ); assert.match( runtime, /const exactSnapshotRuntimeId = actionSnapshotRuntimeId\.trim\(\)[\s\S]*?isSnapshotRuntimeCurrent\(exactSnapshotRuntimeId\)[\s\S]*?xgridsK1Api\.reopenRetiredPhysicalReconciliation\([\s\S]*?expected_snapshot_runtime_id: exactSnapshotRuntimeId/, ); for (const action of [ "openApplicationControlSession", "enterApplicationWorkspace", "closeApplicationControlSession", "prepareAcquisition", "startAcquisition", "abortAcquisition", "reconcilePhysicalCommand", ]) { assert.match( runtime, new RegExp(`xgridsK1Api\\.${action}\\([\\s\\S]*?expected_snapshot_runtime_id`), action, ); } assert.equal( [...runtime.matchAll( /expected_snapshot_runtime_id: actionSnapshotRuntimeId/g, )].length, 4, ); assert.match( runtime, /stopSessionCompatibility\(\{[\s\S]*?expected_snapshot_runtime_id/, ); assert.match( runtime, /run\([\s\S]*?"reopen"[\s\S]*?surfaceErrors: false, supersedePending: true[\s\S]*?await refresh\(false\)/, ); assert.match( runtime, /const actionSnapshotRuntimeId =\s*options\.expectedSnapshotRuntimeId\?\.trim\(\) \|\| null[\s\S]*?expected_snapshot_runtime_id:\s*actionSnapshotRuntimeId \?\? expectedSnapshotRuntimeId\(\)/, ); }); test("fresh Scan treats an exact prior K1 as one local Select action", () => { const provisioning = readFileSync( join(pluginFrontendRoot, "components/K1ProvisioningPipeline.tsx"), "utf8", ); const lifecycle = readFileSync(join(pluginFrontendRoot, "lifecycle.ts"), "utf8"); const runtime = readFileSync( join(pluginFrontendRoot, "useXgridsK1Runtime.ts"), "utf8", ); const selection = provisioning.slice( provisioning.indexOf("const selectFreshDevice"), provisioning.indexOf("const chooseAnother"), ); const apply = provisioning.slice( provisioning.indexOf("const submitConnect"), provisioning.indexOf("const verifyAppliedNetwork"), ); assert.match(selection, /requestExplicitProvisioning\(device\.device_id/); assert.match(selection, /const actionableDevices = devices\.filter\(candidateSelectionAllowed\)/); assert.doesNotMatch( selection, /physicallyRetired|retiredPhysical|await|verifyConnection\(|retireUnavailable|reopenRetired/, ); const resultRows = provisioning.slice( provisioning.indexOf('
'), provisioning.indexOf('
'), ); assert.match(resultRows, /actionLabel="Выбрать"/); assert.match(resultRows, /onSelect=\{\(\) => selectCandidate\(device\)\}/); assert.doesNotMatch(resultRows, /Переподключиться|reopen|verifyConnection/); assert.doesNotMatch(provisioning, /recoverRetiredPhysicalCandidate/); assert.doesNotMatch(apply, /verifyConnection\(|retireUnavailable|reopenRetired/); assert.match(provisioning, /Переподключиться/); assert.match(provisioning, /Подключить новый K1/); assert.doesNotMatch(provisioning, /Вернуть прежний K1 и проверить/); assert.match(runtime, /reopenRetiredPhysicalReconciliation/); assert.match(runtime, /retireUnavailablePhysicalCommand/); assert.match(lifecycle, /retiredPhysicalReopenAuthority/); }); test("K1 orchestration accepts backend recovery but still requires exact topology before physical START", () => { const acquisition = readFileSync( join(pluginFrontendRoot, "components/K1AcquisitionPipeline.tsx"), "utf8", ); const diagnostics = readFileSync( join(pluginFrontendRoot, "components/K1Diagnostics.tsx"), "utf8", ); assert.match(acquisition, /currentAppliedConnectionTopology\(state\)/); assert.ok( [...acquisition.matchAll(/!connectionConfigured/g)].length >= 2, "handler and button must both reject absent or configured-offline topology", ); assert.match(acquisition, /desiredModeMatchesActive/); assert.match(acquisition, /modeSwitchRequired/); assert.doesNotMatch(acquisition, /Выбран другой способ связи/); assert.match(acquisition, /prepareCanonicalAcquisition/); assert.match(acquisition, /startPreparedAcquisition/); assert.match(acquisition, /operatorActionPhysicalAcceptance\(\)/); assert.doesNotMatch(acquisition, /K1PhysicalCommandConfirmation/); assert.match(acquisition, /connectionPolicyAllows\(state, "start-acquisition"\)/); assert.match(acquisition, /canIssueCanonicalStop\(state, physicalStopIntentSpent\)/); assert.match(acquisition, /physicalStopInFlight \|\| physicalStopExecutable/); assert.match(acquisition, /connectionPolicyAllows\(state, "stop-local-receiver"\)/); assert.match(acquisition, /if \(finalStartTarget\)/); assert.match(acquisition, /if \(physicalStopExecutable\)/); assert.match(acquisition, /if \(!physicalStartAllowed\) return;/); assert.doesNotMatch(acquisition, /physicalStopAllowed/); const replaySubmit = acquisition.slice( acquisition.indexOf("const submitReplay ="), acquisition.indexOf("return (", acquisition.indexOf("const submitReplay =")), ); assert.doesNotMatch( replaySubmit, /connectionPolicyAllows|physicalStartAllowed|physicalStopExecutable/, ); assert.match(acquisition, /void stopLocalReceiver\(\);/); assert.match(acquisition, /onClick=\{\(\) => void abort\(\)\}/); assert.doesNotMatch(acquisition, /acknowledge-data-loss/); assert.doesNotMatch(acquisition, /PHYSICAL_ACCEPTANCE/); assert.doesNotMatch(acquisition, /!state\?\.k1_ip/); assert.match(diagnostics, /activeConnectionEndpointLabel\(state\)/); assert.match(diagnostics, /Адрес конфигурации/); assert.match(diagnostics, /связь не подтверждена/); assert.doesNotMatch(diagnostics, /state\?\.k1_ip/); }); test("one explicit K1 action performs START or STOP without a redundant checklist modal", () => { const acquisition = readFileSync( join(pluginFrontendRoot, "components/K1AcquisitionPipeline.tsx"), "utf8", ); const spatial = readFileSync( join(pluginFrontendRoot, "components/K1SpatialControls.tsx"), "utf8", ); const confirmation = readFileSync( join(pluginFrontendRoot, "physicalCommandConfirmation.ts"), "utf8", ); const styles = readFileSync(join(pluginFrontendRoot, "styles.css"), "utf8"); assert.equal( existsSync(join(pluginFrontendRoot, "components/K1PhysicalCommandConfirmation.tsx")), false, ); assert.doesNotMatch(acquisition, /K1PhysicalCommandConfirmation|ConfirmationModal/); assert.doesNotMatch(spatial, /K1PhysicalCommandConfirmation|ConfirmationModal/); assert.match(acquisition, /operatorActionPhysicalAcceptance\(\)/); assert.match(acquisition, /await submitFinalStart\(\)/); assert.match(spatial, /stop\(operatorActionPhysicalAcceptance\(\)\)/); assert.match(spatial, /physicalStopExecutable/); assert.match(spatial, /canIssueCanonicalStop\(state, physicalStopIntentSpent\)/); assert.match(spatial, /physicalStopInFlight \|\| physicalStopExecutable/); assert.match(spatial, /connectionPolicyAllows\(state, "stop-local-receiver"\)/); assert.doesNotMatch(spatial, /Физическая остановка K1 недоступна/); assert.match(spatial, /onClick=\{\(\) => void stopLocalReceiver\(\)\}/); assert.match(spatial, /Завершить локальный приём/); assert.doesNotMatch(spatial, /Повторить остановку/); assert.match(acquisition, /canIssueCanonicalStop\(state, physicalStopIntentSpent\)/); assert.match(acquisition, /stopLocalReceiver/); assert.match(acquisition, /Повторная команда устройству не отправляется/); assert.doesNotMatch(spatial, /acknowledge-data-loss/); assert.match(confirmation, /operatorActionPhysicalAcceptance/); assert.match(confirmation, /operator_present:\s*true/); assert.match(confirmation, /acquisition\.state !== "prepared"/); assert.match(confirmation, /control\.state !== "project-ready"/); assert.match(confirmation, /latest_device_session_state/); assert.match(confirmation, /acquisition_start_allowed !== true/); assert.doesNotMatch(styles, /xgrids-k1-physical-confirmation/); }); test("generic Control Station has one composition import and no K1 implementation knowledge", () => { const compositionPath = join(coreSourceRoot, "composition/devicePlugins.ts"); const composition = readFileSync(compositionPath, "utf8"); assert.match(composition, /from "@xgrids-k1\/frontend\/plugin"/); for (const path of sourceFiles(coreSourceRoot)) { if (path === compositionPath) continue; const source = readFileSync(path, "utf8"); assert.doesNotMatch(source, /xgrids|lixel|\bk1\b/i, path); } for (const path of sourceFiles(pluginFrontendRoot)) { const source = readFileSync(path, "utf8"); assert.doesNotMatch(source, /apps\/control-station|\.\.\/\.\.\/core|\.\.\/\.\.\/components/, path); } });