enigma-memory 0.1.18 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/README.md +76 -24
  2. package/apps/cli/bin/enigma-desktop.mjs +140 -0
  3. package/apps/cli/bin/enigma-terminal.mjs +78 -0
  4. package/apps/cli/bin/enigma.mjs +1923 -285
  5. package/apps/desktop/electron-main.cjs +217 -0
  6. package/apps/desktop/package.json +12 -0
  7. package/apps/desktop/src/app.js +264 -7
  8. package/apps/desktop/src/index.html +3514 -1373
  9. package/apps/desktop/src/launch-electron.mjs +51 -0
  10. package/apps/desktop/src/server.mjs +2914 -0
  11. package/apps/desktop/src/styles.css +2972 -260
  12. package/apps/desktop/src/zk-browser-prove.mjs +53 -0
  13. package/apps/desktop/src/zk-state.mjs +1789 -0
  14. package/apps/gateway/bin/enigma-gateway.mjs +102 -5
  15. package/apps/gateway/src/server.mjs +271 -8
  16. package/apps/ios/EnigmaCore/Package.swift +12 -0
  17. package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
  18. package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
  19. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
  20. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
  21. package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
  22. package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
  23. package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
  24. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
  25. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
  26. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
  27. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
  28. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
  29. package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
  30. package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
  31. package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
  32. package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
  33. package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
  34. package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
  35. package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
  36. package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
  37. package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
  38. package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
  39. package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
  40. package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
  41. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
  42. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
  43. package/apps/native-host/README.md +19 -8
  44. package/apps/native-host/bin/enigma-native-host.mjs +229 -13
  45. package/apps/relay/bin/enigma-relay.mjs +103 -5
  46. package/apps/relay/src/federation-runtime.mjs +618 -0
  47. package/apps/relay/src/server.mjs +310 -9
  48. package/apps/verifier/bin/enigma-verify.mjs +327 -11
  49. package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
  50. package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
  51. package/cortex-v3/circuits/build/vk_bytes.json +32 -0
  52. package/cortex-v3/proving-assets.json +64 -0
  53. package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
  54. package/cortex-v3/zk/action-transition-vk.json +119 -0
  55. package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
  56. package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
  57. package/cortex-v3/zk/intent-witness.mjs +365 -0
  58. package/cortex-v3/zk/intent-witness.test.mjs +485 -0
  59. package/cortex-v3/zk/proving-assets.mjs +203 -0
  60. package/cortex-v3/zk/sale-witness.mjs +783 -0
  61. package/cortex-v3/zk/sale-witness.test.mjs +784 -0
  62. package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
  63. package/cortex-v3/zk/settlement-evidence.mjs +722 -0
  64. package/cortex-v3/zk/setup-intent.mjs +688 -0
  65. package/cortex-v3/zk/setup-sale.mjs +666 -0
  66. package/cortex-v3/zk/setup.mjs +594 -0
  67. package/cortex-v3/zk/witness.mjs +184 -0
  68. package/cortex-v3/zk/zk-codec.mjs +232 -0
  69. package/cortex-v3/zk/zk-codec.test.mjs +293 -0
  70. package/cortex-v3/zk/zk-settle.mjs +370 -0
  71. package/cortex-v3/zk/zk-tree.mjs +256 -0
  72. package/cortex-v3/zk/zk-tree.test.mjs +419 -0
  73. package/deploy/docker-compose.local-production-simulation.yml +36 -0
  74. package/docs/browser-extension-install.md +8 -6
  75. package/docs/client-connectors.md +15 -11
  76. package/docs/developer-ecosystem.md +15 -13
  77. package/docs/enigma-memory-ready-conformance.md +11 -9
  78. package/docs/install-anywhere.md +61 -28
  79. package/docs/installers-and-desktop.md +8 -7
  80. package/docs/novelty-invention-candidates.md +161 -161
  81. package/docs/proof-network-claim-boundaries.md +320 -318
  82. package/examples/01-quickstart-agent/index.mjs +49 -0
  83. package/examples/01_agent_memory_quickstart.mjs +57 -0
  84. package/examples/02-multi-agent-swarm/index.mjs +57 -0
  85. package/examples/02_cross_model_passport.mjs +64 -0
  86. package/examples/03-langchain-memory/index.mjs +41 -0
  87. package/examples/03_poseidon_commitment_verification.mjs +71 -0
  88. package/examples/04-python-trading-agent/trader.py +49 -0
  89. package/examples/README.md +27 -0
  90. package/examples/ci/github-actions.yml +7 -2
  91. package/package.json +142 -11
  92. package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
  93. package/packages/connectors/src/index.js +196 -4
  94. package/packages/connectors/swarm-router.mjs +168 -0
  95. package/packages/core/src/index.js +248 -1
  96. package/packages/core/src/version.mjs +7 -0
  97. package/packages/dev-tools/package.json +19 -0
  98. package/packages/dev-tools/src/index.js +4 -0
  99. package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
  100. package/packages/dev-tools/src/swarm-simulator.js +101 -0
  101. package/packages/dev-tools/src/vault-inspector.js +114 -0
  102. package/packages/dev-tools/src/vector-benchmark.js +100 -0
  103. package/packages/developer-platform/src/access-credentials.js +341 -0
  104. package/packages/developer-platform/src/http.js +132 -0
  105. package/packages/developer-platform/src/index.js +4 -0
  106. package/packages/developer-platform/src/usage-http.js +60 -0
  107. package/packages/developer-platform/src/usage.js +295 -0
  108. package/packages/enclave-runtime/attestation.mjs +159 -0
  109. package/packages/enclave-runtime/index.mjs +47 -0
  110. package/packages/enclave-runtime/session-manager.mjs +253 -0
  111. package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
  112. package/packages/enigma-reflex/package.json +14 -0
  113. package/packages/enigma-reflex/src/index.js +204 -0
  114. package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
  115. package/packages/enigma-reflex/training/requirements.txt +8 -0
  116. package/packages/enigma-reflex/training/train.py +314 -0
  117. package/packages/enigma-weave/LICENSE +22 -0
  118. package/packages/enigma-weave/UPSTREAM.json +21 -0
  119. package/packages/enigma-weave/package.json +14 -0
  120. package/packages/enigma-weave/src/index.js +286 -0
  121. package/packages/hosted-cloud/src/index.js +80 -5
  122. package/packages/importers/src/index.js +432 -0
  123. package/packages/inference-runtime/src/browser.js +401 -0
  124. package/packages/inference-runtime/src/chat.js +265 -0
  125. package/packages/inference-runtime/src/code.js +407 -0
  126. package/packages/inference-runtime/src/contracts.js +162 -0
  127. package/packages/inference-runtime/src/http.js +232 -0
  128. package/packages/inference-runtime/src/image.js +186 -0
  129. package/packages/inference-runtime/src/index.js +10 -0
  130. package/packages/inference-runtime/src/model-router.js +320 -0
  131. package/packages/inference-runtime/src/platform.js +125 -0
  132. package/packages/inference-runtime/src/privacy.js +400 -0
  133. package/packages/inference-runtime/src/video.js +253 -0
  134. package/packages/mcp-server/README.md +22 -6
  135. package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
  136. package/packages/mcp-server/src/index.js +1418 -105
  137. package/packages/mcp-server/src/oauth.js +561 -0
  138. package/packages/mcp-server/src/private-handoff.js +84 -0
  139. package/packages/mcp-server/src/remote-http.js +273 -0
  140. package/packages/mcp-server/src/remote-policy.js +72 -0
  141. package/packages/mcp-server/swarm-bridge.mjs +361 -0
  142. package/packages/mesh/index.d.ts +283 -0
  143. package/packages/mesh/package.json +23 -0
  144. package/packages/mesh/src/crypto.js +189 -0
  145. package/packages/mesh/src/federation-packets.js +353 -0
  146. package/packages/mesh/src/gossip.js +311 -0
  147. package/packages/mesh/src/index.js +6 -0
  148. package/packages/mesh/src/protocol.js +255 -0
  149. package/packages/mesh/src/router.js +279 -0
  150. package/packages/mesh/src/transport.js +306 -0
  151. package/packages/passport/src/index.js +426 -1
  152. package/packages/private-economy/src/credits-http.js +100 -0
  153. package/packages/private-economy/src/credits.js +447 -0
  154. package/packages/private-economy/src/index.js +5 -0
  155. package/packages/private-economy/src/payments-http.js +120 -0
  156. package/packages/private-economy/src/payments.js +509 -0
  157. package/packages/private-economy/src/x402.js +346 -0
  158. package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
  159. package/packages/rag/index.d.ts +182 -0
  160. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
  161. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
  162. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
  163. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
  164. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
  165. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
  166. package/packages/rag/package.json +27 -0
  167. package/packages/rag/src/blinded-search.js +109 -0
  168. package/packages/rag/src/bm25.js +169 -0
  169. package/packages/rag/src/embeddings.js +459 -0
  170. package/packages/rag/src/hybrid.js +76 -0
  171. package/packages/rag/src/index.js +38 -0
  172. package/packages/rag/src/reranker.js +61 -0
  173. package/packages/rag/src/research.js +107 -0
  174. package/packages/rag/src/vector-store.js +430 -0
  175. package/packages/rag/src/verify-model-artifacts.mjs +4 -0
  176. package/packages/sdk/index.d.ts +760 -0
  177. package/packages/sdk/package.json +33 -0
  178. package/packages/sdk/python/README.md +24 -0
  179. package/packages/sdk/python/enigma_sdk.py +250 -0
  180. package/packages/sdk/python/pyproject.toml +34 -0
  181. package/packages/sdk/python/requirements.txt +1 -0
  182. package/packages/sdk/python/setup.py +20 -0
  183. package/packages/sdk/src/federation/capability-grant.js +389 -0
  184. package/packages/sdk/src/federation/federation-router.js +360 -0
  185. package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
  186. package/packages/sdk/src/federation/index.js +3 -0
  187. package/packages/sdk/src/index.js +1796 -0
  188. package/packages/sdk/src/intelligence/contradiction.js +337 -0
  189. package/packages/sdk/src/intelligence/decision-engine.js +155 -0
  190. package/packages/sdk/src/intelligence/index.js +4 -0
  191. package/packages/sdk/src/intelligence/ontology.js +122 -0
  192. package/packages/sdk/src/intelligence/temporal.js +123 -0
  193. package/packages/sdk/src/market-client.js +142 -0
  194. package/packages/sdk/src/mesh-client.js +110 -0
  195. package/packages/sdk/src/middleware/index.js +3 -0
  196. package/packages/sdk/src/middleware/langchain.js +159 -0
  197. package/packages/sdk/src/middleware/llamaindex.js +101 -0
  198. package/packages/sdk/src/middleware/vercel-ai.js +112 -0
  199. package/packages/sdk/src/rag-client.js +85 -0
  200. package/packages/sdk/src/swarm-orchestrator.js +260 -0
  201. package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
  202. package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
  203. package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
  204. package/packages/snapcompact/index.d.ts +284 -0
  205. package/packages/snapcompact/package.json +25 -0
  206. package/packages/snapcompact/src/index.js +716 -0
  207. package/packages/storage/PACKAGE_CONTRACT.md +1 -1
  208. package/packages/terminal-console/animations.mjs +240 -0
  209. package/packages/terminal-console/auto-anchor.mjs +220 -0
  210. package/packages/terminal-console/banner.mjs +91 -0
  211. package/packages/terminal-console/commands.mjs +459 -0
  212. package/packages/terminal-console/delegation.mjs +152 -0
  213. package/packages/terminal-console/index.mjs +5 -0
  214. package/packages/terminal-console/outbox.mjs +143 -0
  215. package/packages/terminal-console/phantom-bridge.mjs +637 -0
  216. package/packages/terminal-console/repl.mjs +136 -0
  217. package/packages/terminal-console/signer-store.mjs +130 -0
  218. package/packages/terminal-console/solana-rpc.mjs +214 -0
  219. package/packages/terminal-console/solana-transport.mjs +189 -0
  220. package/packages/terminal-tui/dashboard.mjs +214 -0
  221. package/packages/terminal-tui/index.mjs +28 -0
  222. package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
  223. package/packages/terminal-tui/telemetry-hud.mjs +137 -0
  224. package/packages/vault/index.d.ts +449 -0
  225. package/packages/vault/package.json +27 -0
  226. package/packages/vault/src/e2ee.mjs +393 -0
  227. package/packages/vault/src/enclave.js +481 -0
  228. package/packages/vault/src/erasure.js +207 -0
  229. package/packages/vault/src/index.js +1018 -155
  230. package/packages/vault/src/persistence.js +307 -0
  231. package/packages/vault/src/poseidon.js +354 -0
  232. package/packages/vault/src/receipt.js +459 -0
  233. package/scripts/benchmark-optical-context.mjs +166 -0
  234. package/scripts/bootstrap-enigma.mjs +502 -0
  235. package/scripts/build-edge-backend-workers.mjs +20 -5
  236. package/scripts/build-goal-completion-audit.mjs +72 -25
  237. package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
  238. package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
  239. package/scripts/build-hosted-probe-worker.mjs +19 -4
  240. package/scripts/build-installer-assets.mjs +41 -21
  241. package/scripts/build-operator-evidence-starter.mjs +59 -1
  242. package/scripts/build-production-backend-env-kit.mjs +2 -0
  243. package/scripts/build-production-unblocker.mjs +3 -0
  244. package/scripts/check.mjs +17 -3
  245. package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
  246. package/scripts/install-enigma-local.mjs +18 -5
  247. package/scripts/release-audit.mjs +65 -109
  248. package/scripts/release-provenance.mjs +6 -0
  249. package/scripts/run-backend-readiness-smoke.mjs +112 -10
  250. package/scripts/scan-secrets.mjs +1 -0
  251. package/scripts/simulate-production-env.mjs +7 -2
  252. package/scripts/validate-hosted-backend-live.mjs +112 -1
  253. package/specs/antibody-pack-v1.schema.json +95 -0
  254. package/specs/antigen-envelope-v1.schema.json +81 -0
  255. package/specs/boundary-manifest-v1.schema.json +35 -35
  256. package/specs/capsule-v1.schema.json +55 -55
  257. package/specs/claim-boundary-manifest-v1.schema.json +22 -22
  258. package/specs/claim-ledger-v1.schema.json +291 -0
  259. package/specs/context-passport-v1.schema.json +59 -0
  260. package/specs/deletion-tombstone-v1.schema.json +26 -26
  261. package/specs/evidence-packet-v1.schema.json +177 -0
  262. package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
  263. package/specs/immune-scan-report-v1.schema.json +112 -0
  264. package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
  265. package/specs/memory-atom-v1.schema.json +59 -0
  266. package/specs/memory-event-v1.schema.json +42 -42
  267. package/specs/passport-v1.schema.json +50 -50
  268. package/specs/proof-of-non-use-v1.schema.json +65 -0
  269. package/specs/quarantine-record-v1.schema.json +126 -0
  270. package/specs/receipt-v1.schema.json +61 -61
  271. package/specs/state-checkpoint-v1.schema.json +37 -37
  272. package/specs/trust-bundle-v1.schema.json +56 -56
  273. package/specs/trust-card-v1.schema.json +119 -0
  274. package/docs/proof-network-launch-plan.md +0 -421
  275. package/packages/metering/PACKAGE_CONTRACT.md +0 -20
  276. package/scripts/build-ai-orchestration-plan.mjs +0 -248
@@ -0,0 +1,217 @@
1
+ // Enigma Sovereign Terminal — Dedicated Electron Desktop Application Window
2
+ // Owns the dynamic localhost server and the enigma:// private-session protocol.
3
+
4
+ const { app, BrowserWindow, shell, safeStorage } = require('electron');
5
+ const path = require('node:path');
6
+ const { pathToFileURL } = require('node:url');
7
+
8
+ const PROTOCOL_SCHEME = 'enigma';
9
+ const TEST_MODE = process.env.ENIGMA_ELECTRON_HANDOFF_TEST === '1';
10
+ const HANDOFF_MODULE_URL = pathToFileURL(
11
+ path.join(__dirname, '..', '..', 'packages', 'mcp-server', 'src', 'private-handoff.js')
12
+ ).href;
13
+
14
+ let mainWindow = null;
15
+ let desktopServerInstance = null;
16
+ let desktopServerInfo = null;
17
+ let pendingHandoffUrl = process.env.ENIGMA_ELECTRON_HANDOFF_TEST_URL || findHandoffArgument(process.argv);
18
+ let protocolRegistered = false;
19
+
20
+ function findHandoffArgument(argv) {
21
+ return Array.isArray(argv)
22
+ ? argv.find((value) => typeof value === 'string' && value.toLowerCase().startsWith('enigma://private')) || null
23
+ : null;
24
+ }
25
+
26
+ function registerPrivateProtocol() {
27
+ if (process.defaultApp && process.argv[1]) {
28
+ protocolRegistered = app.setAsDefaultProtocolClient(
29
+ PROTOCOL_SCHEME,
30
+ process.execPath,
31
+ [path.resolve(process.argv[1])]
32
+ );
33
+ } else {
34
+ protocolRegistered = app.setAsDefaultProtocolClient(PROTOCOL_SCHEME);
35
+ }
36
+ }
37
+
38
+ async function closeDesktopServer() {
39
+ const instance = desktopServerInstance;
40
+ desktopServerInstance = null;
41
+ desktopServerInfo = null;
42
+ if (instance) await instance.close();
43
+ }
44
+
45
+ async function workspaceUrlForHandoff(protocolUrl) {
46
+ if (!desktopServerInfo) throw new Error('Enigma desktop server is not ready.');
47
+ const { createWorkspaceUrlFromProtocol } = await import(HANDOFF_MODULE_URL);
48
+ return createWorkspaceUrlFromProtocol(protocolUrl, desktopServerInfo.url);
49
+ }
50
+
51
+ async function openPrivateHandoff(protocolUrl) {
52
+ if (!protocolUrl) return;
53
+ pendingHandoffUrl = protocolUrl;
54
+ if (!app.isReady()) return;
55
+ if (!mainWindow || mainWindow.isDestroyed() || !desktopServerInfo) {
56
+ await createMainWindow();
57
+ return;
58
+ }
59
+ const target = await workspaceUrlForHandoff(protocolUrl);
60
+ pendingHandoffUrl = null;
61
+ await mainWindow.loadURL(target);
62
+ if (mainWindow.isMinimized()) mainWindow.restore();
63
+ mainWindow.show();
64
+ mainWindow.focus();
65
+ }
66
+
67
+ async function verifyElectronHandoff() {
68
+ const state = await mainWindow.webContents.executeJavaScript(`
69
+ new Promise((resolve, reject) => {
70
+ const startedAt = Date.now();
71
+ const inspect = () => {
72
+ const route = document.querySelector('#workspaceRouteSelect');
73
+ const active = document.querySelector('.workspace-view.active');
74
+ if (active?.dataset.workspaceView === 'chat' && route && !route.disabled && route.value) {
75
+ resolve({
76
+ href: location.href,
77
+ activeTab: document.querySelector('.nav-tab-btn.active')?.id || null,
78
+ activeView: active.dataset.workspaceView,
79
+ selectedRoute: route.selectedOptions[0]?.textContent || null,
80
+ externalScripts: Array.from(document.scripts).map((script) => script.src).filter(Boolean),
81
+ sessionStorageEntries: sessionStorage.length
82
+ });
83
+ return;
84
+ }
85
+ if (Date.now() - startedAt > 8000) {
86
+ reject(new Error('Workspace route did not become ready.'));
87
+ return;
88
+ }
89
+ setTimeout(inspect, 50);
90
+ };
91
+ inspect();
92
+ })
93
+ `);
94
+ console.log('ENIGMA_ELECTRON_HANDOFF ' + JSON.stringify({
95
+ ...state,
96
+ dynamicPort: desktopServerInfo.port,
97
+ protocolRegistered,
98
+ }));
99
+ await closeDesktopServer();
100
+ if (mainWindow && !mainWindow.isDestroyed()) mainWindow.destroy();
101
+ app.exit(0);
102
+ }
103
+
104
+ async function createMainWindow() {
105
+ if (mainWindow && !mainWindow.isDestroyed()) return mainWindow;
106
+ const { createDesktopServer } = await import('./src/server.mjs');
107
+ const defaultUserDataBundle = process.env.ENIGMA_BUNDLE_PATH
108
+ || path.join(app.getPath('userData'), 'vault', 'bundle.json');
109
+
110
+ let serverOptions;
111
+ if (TEST_MODE) {
112
+ serverOptions = {
113
+ port: 0,
114
+ inMemoryOnly: true,
115
+ modelAdapters: [{
116
+ id: 'electron-handoff-fixture',
117
+ provider: 'Enigma Electron',
118
+ models: ['enigma-code'],
119
+ async invoke(input) {
120
+ return { text: `Electron handoff fixture: ${input.prompt}` };
121
+ },
122
+ }],
123
+ };
124
+ } else {
125
+ if (!safeStorage.isEncryptionAvailable()) {
126
+ throw new Error('OS secure storage unavailable; refusing to start with weak host-bound key custody.');
127
+ }
128
+ serverOptions = {
129
+ port: 0,
130
+ bundlePath: defaultUserDataBundle,
131
+ safeStorage,
132
+ };
133
+ }
134
+
135
+ desktopServerInstance = createDesktopServer(serverOptions);
136
+ desktopServerInfo = await desktopServerInstance.listen();
137
+ mainWindow = new BrowserWindow({
138
+ width: 1240,
139
+ height: 780,
140
+ minWidth: 900,
141
+ minHeight: 600,
142
+ show: !TEST_MODE,
143
+ backgroundColor: '#07090e',
144
+ title: 'Enigma Sovereign AI Memory Terminal',
145
+ autoHideMenuBar: true,
146
+ webPreferences: {
147
+ nodeIntegration: false,
148
+ contextIsolation: true,
149
+ sandbox: true,
150
+ },
151
+ });
152
+
153
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
154
+ if (url.toLowerCase().startsWith('enigma://private')) {
155
+ openPrivateHandoff(url).catch(() => {});
156
+ } else {
157
+ shell.openExternal(url);
158
+ }
159
+ return { action: 'deny' };
160
+ });
161
+
162
+ const target = pendingHandoffUrl
163
+ ? await workspaceUrlForHandoff(pendingHandoffUrl)
164
+ : desktopServerInfo.url;
165
+ pendingHandoffUrl = null;
166
+ await mainWindow.loadURL(target);
167
+
168
+ mainWindow.on('closed', async () => {
169
+ mainWindow = null;
170
+ await closeDesktopServer();
171
+ });
172
+
173
+ if (TEST_MODE) await verifyElectronHandoff();
174
+ return mainWindow;
175
+ }
176
+
177
+ if (!TEST_MODE) registerPrivateProtocol();
178
+ const hasSingleInstanceLock = app.requestSingleInstanceLock();
179
+ if (!hasSingleInstanceLock) {
180
+ app.quit();
181
+ } else {
182
+ app.on('second-instance', (_event, argv) => {
183
+ const handoffUrl = findHandoffArgument(argv);
184
+ if (handoffUrl) {
185
+ openPrivateHandoff(handoffUrl).catch(() => {});
186
+ } else if (mainWindow && !mainWindow.isDestroyed()) {
187
+ if (mainWindow.isMinimized()) mainWindow.restore();
188
+ mainWindow.show();
189
+ mainWindow.focus();
190
+ }
191
+ });
192
+
193
+ app.on('open-url', (event, url) => {
194
+ event.preventDefault();
195
+ if (typeof url === 'string' && url.toLowerCase().startsWith('enigma://private')) {
196
+ openPrivateHandoff(url).catch(() => {});
197
+ }
198
+ });
199
+
200
+ app.whenReady()
201
+ .then(() => createMainWindow())
202
+ .catch((error) => {
203
+ console.error(`Enigma desktop startup failed: ${error.message}`);
204
+ app.exit(1);
205
+ });
206
+
207
+ app.on('activate', () => {
208
+ if (BrowserWindow.getAllWindows().length === 0) {
209
+ createMainWindow().catch(() => {});
210
+ }
211
+ });
212
+ }
213
+
214
+ app.on('window-all-closed', async () => {
215
+ await closeDesktopServer();
216
+ if (process.platform !== 'darwin') app.quit();
217
+ });
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "enigma-desktop-app",
3
+ "version": "0.1.22",
4
+ "description": "Enigma Sovereign AI Memory Terminal Dedicated Desktop Application",
5
+ "type": "module",
6
+ "main": "electron-main.cjs",
7
+ "private": true,
8
+ "scripts": {
9
+ "start": "electron electron-main.cjs",
10
+ "build": "node src/launch-electron.mjs"
11
+ }
12
+ }
@@ -17,6 +17,7 @@ export const DESKTOP_SCREENS = Object.freeze([
17
17
  const CLIENT_TEMPLATES = Object.freeze([
18
18
  Object.freeze({ id: 'claude-desktop', name: 'Claude Desktop', kind: 'mcp-client' }),
19
19
  Object.freeze({ id: 'cursor', name: 'Cursor', kind: 'mcp-client' }),
20
+ Object.freeze({ id: 'kimi-k3', name: 'Kimi K3', kind: 'mcp-client' }),
20
21
  Object.freeze({ id: 'vscode', name: 'VS Code', kind: 'mcp-client' }),
21
22
  Object.freeze({ id: 'browser-bridge', name: 'Browser bridge', kind: 'extension' })
22
23
  ]);
@@ -76,6 +77,21 @@ export function createDesktopState(options = {}) {
76
77
  clients: [],
77
78
  memories: [],
78
79
  search: { query: '', results: [] },
80
+ agentTurn: {
81
+ status: 'idle',
82
+ adapters: [],
83
+ adapter_id: '',
84
+ provider: '',
85
+ model: '',
86
+ context_refs: [],
87
+ receipt_refs: [],
88
+ memory_id: '',
89
+ result_preview: '',
90
+ error_code: '',
91
+ error_message: '',
92
+ completed_at: '',
93
+ note: 'Agent turns execute only through an explicitly configured provider/model adapter.'
94
+ },
79
95
  verifier: {
80
96
  status: 'idle',
81
97
  evidence: [],
@@ -95,6 +111,17 @@ export function createDesktopState(options = {}) {
95
111
  peers: 0,
96
112
  relays: 0,
97
113
  last_witness_at: '',
114
+ federation: {
115
+ started: false,
116
+ scope: '',
117
+ destination_hex: '',
118
+ transport_id: '',
119
+ listen_port: null,
120
+ registered_peers: 0,
121
+ active_grants: 0,
122
+ pending_queries: 0,
123
+ persisted: false
124
+ },
98
125
  note: 'Mesh status is local telemetry until matched to witness receipts.'
99
126
  },
100
127
  enterprise: {
@@ -141,8 +168,18 @@ export function desktopReducer(state = createDesktopState(), action = {}) {
141
168
  return importBundleState(state, action);
142
169
  case 'bundle/export':
143
170
  return exportBundleState(state, action);
171
+ case 'agent/adapters':
172
+ return setAgentAdaptersState(state, action);
173
+ case 'agent/turn-started':
174
+ return startAgentTurnState(state, action);
175
+ case 'agent/turn-completed':
176
+ return completeAgentTurnState(state, action);
177
+ case 'agent/turn-failed':
178
+ return failAgentTurnState(state, action);
144
179
  case 'mesh/update':
145
180
  return updateMeshState(state, action);
181
+ case 'mesh/federation-update':
182
+ return updateFederationState(state, action);
146
183
  case 'enterprise/update':
147
184
  return updateEnterpriseState(state, action);
148
185
  case 'draft/set':
@@ -167,6 +204,7 @@ export function renderDesktopModel(state = createDesktopState()) {
167
204
  vault: state.vault.status,
168
205
  mcp: state.mcp.status,
169
206
  clients: connectedClients.length,
207
+ agentTurn: state.agentTurn.status,
170
208
  memories: activeMemories.length,
171
209
  deleted: deletedMemories.length,
172
210
  verifier: verifierOk ? 'shape-clean' : state.verifier.status,
@@ -187,6 +225,28 @@ export function renderDesktopModel(state = createDesktopState()) {
187
225
  ],
188
226
  memories: state.memories.map(renderMemoryRow)
189
227
  },
228
+ agentTurn: {
229
+ title: 'Operational agent turn',
230
+ status: state.agentTurn.status,
231
+ adapters: state.agentTurn.adapters.map((adapter) => ({
232
+ ...adapter,
233
+ models: adapter.models.slice()
234
+ })),
235
+ selection: {
236
+ adapter_id: state.agentTurn.adapter_id,
237
+ provider: state.agentTurn.provider,
238
+ model: state.agentTurn.model
239
+ },
240
+ context_refs: state.agentTurn.context_refs.map((ref) => ({ ...ref })),
241
+ receipt_refs: state.agentTurn.receipt_refs.map((ref) => ({ ...ref })),
242
+ memory_id: state.agentTurn.memory_id,
243
+ result_preview: state.agentTurn.result_preview,
244
+ error: state.agentTurn.error_code
245
+ ? { code: state.agentTurn.error_code, message: state.agentTurn.error_message }
246
+ : null,
247
+ completed_at: state.agentTurn.completed_at,
248
+ note: state.agentTurn.note
249
+ },
190
250
  mcp: {
191
251
  title: 'MCP server status',
192
252
  status: state.mcp.status,
@@ -230,6 +290,7 @@ export function renderDesktopModel(state = createDesktopState()) {
230
290
  peers: state.mesh.peers,
231
291
  relays: state.mesh.relays,
232
292
  last_witness_at: state.mesh.last_witness_at,
293
+ federation: { ...state.mesh.federation },
233
294
  note: state.mesh.note
234
295
  },
235
296
  enterprise: {
@@ -268,6 +329,22 @@ export function searchMemories(query, options = {}) {
268
329
  return { ...options, query, type: 'memory/search' };
269
330
  }
270
331
 
332
+ export function setAgentAdapters(adapters = []) {
333
+ return { adapters, type: 'agent/adapters' };
334
+ }
335
+
336
+ export function startAgentTurn(selection = {}, options = {}) {
337
+ return { ...options, selection, type: 'agent/turn-started' };
338
+ }
339
+
340
+ export function completeAgentTurn(turn = {}, options = {}) {
341
+ return { ...options, turn, type: 'agent/turn-completed' };
342
+ }
343
+
344
+ export function failAgentTurn(error = {}, options = {}) {
345
+ return { ...options, error, type: 'agent/turn-failed' };
346
+ }
347
+
271
348
  export function verifyReceipts(input = {}, options = {}) {
272
349
  return { ...options, input, type: 'receipts/verify' };
273
350
  }
@@ -292,6 +369,10 @@ export function updateMeshStatus(mesh = {}, options = {}) {
292
369
  return { ...options, mesh, type: 'mesh/update' };
293
370
  }
294
371
 
372
+ export function updateFederationStatus(federation = {}, options = {}) {
373
+ return { ...options, federation, type: 'mesh/federation-update' };
374
+ }
375
+
295
376
  export function updateEnterpriseStatus(enterprise = {}, options = {}) {
296
377
  return { ...options, enterprise, type: 'enterprise/update' };
297
378
  }
@@ -316,6 +397,10 @@ export const desktopActions = Object.freeze({
316
397
  removeMemory: deleteMemory,
317
398
  searchMemories,
318
399
  searchMemory: searchMemories,
400
+ setAgentAdapters,
401
+ startAgentTurn,
402
+ completeAgentTurn,
403
+ failAgentTurn,
319
404
  verifyReceipts,
320
405
  verifyReceiptOutput: verifyReceipts,
321
406
  connectClient,
@@ -326,6 +411,7 @@ export const desktopActions = Object.freeze({
326
411
  exportBundle,
327
412
  exportDesktopBundle: exportBundle,
328
413
  updateMeshStatus,
414
+ updateFederationStatus,
329
415
  updateEnterpriseStatus,
330
416
  selectDesktopScreen,
331
417
  setDesktopDraft
@@ -360,6 +446,10 @@ export const desktopApi = Object.freeze({
360
446
  removeMemory,
361
447
  searchMemories,
362
448
  searchMemory,
449
+ setAgentAdapters,
450
+ startAgentTurn,
451
+ completeAgentTurn,
452
+ failAgentTurn,
363
453
  verifyReceipts,
364
454
  verifyReceiptOutput,
365
455
  connectClient,
@@ -368,7 +458,10 @@ export const desktopApi = Object.freeze({
368
458
  importBundle,
369
459
  importDesktopBundle,
370
460
  exportBundle,
371
- exportDesktopBundle
461
+ exportDesktopBundle,
462
+ updateMeshStatus,
463
+ updateFederationStatus,
464
+ updateEnterpriseStatus
372
465
  });
373
466
 
374
467
  if (typeof globalThis !== 'undefined') {
@@ -605,6 +698,7 @@ function importBundleState(state, action) {
605
698
  evidence: state.verifier.evidence.concat(importedVerifierEvidence),
606
699
  errors: state.verifier.errors.concat(importedVerifierEvidence.flatMap((item) => item.errors.map((error) => `${item.receipt_id || `receipt[${item.index}]`}: ${error}`)))
607
700
  } : state.verifier,
701
+
608
702
  importExport: { ...state.importExport, import_status: 'imported', import_errors: [] },
609
703
  vault: {
610
704
  ...state.vault,
@@ -616,6 +710,136 @@ function importBundleState(state, action) {
616
710
  }
617
711
  });
618
712
  }
713
+ function setAgentAdaptersState(state, action) {
714
+ const adapters = Array.isArray(action.adapters)
715
+ ? action.adapters
716
+ .map((adapter) => ({
717
+ id: cleanString(adapter?.id),
718
+ provider: cleanString(adapter?.provider),
719
+ models: normalizeStringList(adapter?.models)
720
+ }))
721
+ .filter((adapter) => adapter.id && adapter.provider && adapter.models.length > 0)
722
+ : [];
723
+ return bump({
724
+ ...state,
725
+ agentTurn: {
726
+ ...state.agentTurn,
727
+ adapters
728
+ },
729
+ notice: adapters.length > 0
730
+ ? `${adapters.length} configured model adapter${adapters.length === 1 ? '' : 's'} available.`
731
+ : 'No provider/model adapter is configured; agent turns fail closed.'
732
+ });
733
+ }
734
+
735
+ function startAgentTurnState(state, action) {
736
+ const selection = action.selection && typeof action.selection === 'object'
737
+ ? action.selection
738
+ : {};
739
+ return bump({
740
+ ...state,
741
+ activeScreen: 'vault',
742
+ agentTurn: {
743
+ ...state.agentTurn,
744
+ status: 'running',
745
+ adapter_id: cleanString(selection.adapterId ?? selection.adapter_id),
746
+ provider: cleanString(selection.provider),
747
+ model: cleanString(selection.model),
748
+ context_refs: [],
749
+ receipt_refs: [],
750
+ memory_id: '',
751
+ result_preview: '',
752
+ error_code: '',
753
+ error_message: '',
754
+ completed_at: ''
755
+ },
756
+ notice: 'Executing authenticated retrieval → provider invocation → encrypted persistence.'
757
+ });
758
+ }
759
+
760
+ function completeAgentTurnState(state, action) {
761
+ const turn = action.turn && typeof action.turn === 'object' ? action.turn : {};
762
+ const adapter = turn.adapter && typeof turn.adapter === 'object' ? turn.adapter : {};
763
+ const contextRefs = Array.isArray(turn.context?.refs)
764
+ ? turn.context.refs.map((ref) => ({ ...ref }))
765
+ : [];
766
+ const receiptRefs = Array.isArray(turn.receiptRefs)
767
+ ? turn.receiptRefs.map((ref) => ({ ...ref }))
768
+ : [];
769
+ const completedAt = cleanString(action.now) || INITIAL_NOW;
770
+ return bump({
771
+ ...state,
772
+ activeScreen: 'vault',
773
+ agentTurn: {
774
+ ...state.agentTurn,
775
+ status: 'completed',
776
+ adapter_id: cleanString(adapter.id) || state.agentTurn.adapter_id,
777
+ provider: cleanString(adapter.provider) || state.agentTurn.provider,
778
+ model: cleanString(adapter.model) || state.agentTurn.model,
779
+ context_refs: contextRefs,
780
+ receipt_refs: receiptRefs,
781
+ memory_id: cleanString(turn.memory?.id),
782
+ result_preview: clamp(modelResultText(turn.result), 240),
783
+ error_code: '',
784
+ error_message: '',
785
+ completed_at: completedAt
786
+ },
787
+ notice: `Agent turn completed with ${contextRefs.length} context ref${contextRefs.length === 1 ? '' : 's'} and ${receiptRefs.length} receipt ref${receiptRefs.length === 1 ? '' : 's'}.`
788
+ });
789
+ }
790
+
791
+ function failAgentTurnState(state, action) {
792
+ const error = action.error && typeof action.error === 'object' ? action.error : {};
793
+ return bump({
794
+ ...state,
795
+ activeScreen: 'vault',
796
+ agentTurn: {
797
+ ...state.agentTurn,
798
+ status: 'failed',
799
+ error_code: cleanString(error.code) || 'AGENT_TURN_FAILED',
800
+ error_message: cleanString(error.message) || 'Agent turn failed',
801
+ completed_at: cleanString(action.now) || INITIAL_NOW
802
+ },
803
+ notice: cleanString(error.message) || 'Agent turn failed closed.'
804
+ });
805
+ }
806
+
807
+ function updateFederationState(state, action) {
808
+ const federation = action.federation && typeof action.federation === 'object'
809
+ ? action.federation
810
+ : {};
811
+ const endpoint = federation.endpoint && typeof federation.endpoint === 'object'
812
+ ? federation.endpoint
813
+ : {};
814
+ const transport = federation.transport && typeof federation.transport === 'object'
815
+ ? federation.transport
816
+ : {};
817
+ return bump({
818
+ ...state,
819
+ activeScreen: 'mesh',
820
+ mesh: {
821
+ ...state.mesh,
822
+ federation: {
823
+ started: federation.started === true,
824
+ scope: cleanString(federation.scope),
825
+ destination_hex: cleanString(endpoint.destinationHex),
826
+ transport_id: cleanString(transport.id),
827
+ listen_port: normalizePort(transport.listenPort),
828
+ registered_peers: Array.isArray(federation.registeredPeers)
829
+ ? federation.registeredPeers.length
830
+ : 0,
831
+ active_grants: Array.isArray(federation.activeGrantIds)
832
+ ? federation.activeGrantIds.length
833
+ : 0,
834
+ pending_queries: normalizeNonNegativeInteger(federation.pendingQueries, 0),
835
+ persisted: federation.persisted === true
836
+ }
837
+ },
838
+ notice: federation.started === true
839
+ ? 'Encrypted, signed GhostMesh federation bridge is running.'
840
+ : 'GhostMesh federation bridge is configured but stopped.'
841
+ });
842
+ }
619
843
 
620
844
  function exportBundleState(state, action) {
621
845
  const now = cleanString(action.now) || INITIAL_NOW;
@@ -1012,6 +1236,21 @@ function screenLabel(screen) {
1012
1236
  case 'enterprise': return 'Enterprise';
1013
1237
  default: return screen;
1014
1238
  }
1239
+
1240
+ }
1241
+ function modelResultText(result) {
1242
+ if (typeof result === 'string') return result;
1243
+ if (!result || typeof result !== 'object') return '';
1244
+ for (const key of ['text', 'outputText', 'output_text', 'content']) {
1245
+ if (typeof result[key] === 'string') return result[key];
1246
+ }
1247
+ if (Array.isArray(result.content)) {
1248
+ return result.content
1249
+ .map((part) => typeof part === 'string' ? part : part?.text)
1250
+ .filter((part) => typeof part === 'string')
1251
+ .join('');
1252
+ }
1253
+ return '';
1015
1254
  }
1016
1255
 
1017
1256
  function cleanString(value) {
@@ -1102,13 +1341,14 @@ function renderHtml(model, state) {
1102
1341
  ${renderMetric('MCP', model.summary.mcp)}
1103
1342
  ${renderMetric('Clients', model.summary.clients)}
1104
1343
  ${renderMetric('Receipt inspector', model.summary.verifier)}
1344
+ ${renderMetric('Agent turn', model.summary.agentTurn)}
1105
1345
  </dl>
1106
1346
  </header>
1107
1347
  <nav class="screen-nav" aria-label="Desktop screens">
1108
1348
  ${model.navigation.map((item) => `<button class="screen-tab${item.active ? ' is-active' : ''}" type="button" data-screen="${escapeHtml(item.id)}">${escapeHtml(item.label)}</button>`).join('')}
1109
1349
  </nav>
1110
1350
  <main>
1111
- ${renderVaultScreen(model.screens.vault, state)}
1351
+ ${renderVaultScreen(model.screens.vault, model.screens.agentTurn, state)}
1112
1352
  ${renderMcpScreen(model.screens.mcp)}
1113
1353
  ${renderClientsScreen(model.screens.clients)}
1114
1354
  ${renderImportExportScreen(model.screens.importExport, state)}
@@ -1127,13 +1367,19 @@ function renderScreen(id, title, body) {
1127
1367
  return `<section class="screen-card" id="screen-${escapeHtml(id)}"><div class="screen-heading"><p>${escapeHtml(screenLabel(id))}</p><h2>${escapeHtml(title)}</h2></div>${body}</section>`;
1128
1368
  }
1129
1369
 
1130
- function renderVaultScreen(screen, state) {
1370
+ function renderVaultScreen(screen, agentTurn, state) {
1131
1371
  const memories = screen.memories.length ? screen.memories.map((memory) => `
1132
1372
  <li class="memory-row${memory.deleted ? ' is-deleted' : ''}">
1133
1373
  <div><strong>${escapeHtml(memory.descriptor)}</strong><span>${escapeHtml(memory.address)}</span></div>
1134
1374
  <code>${escapeHtml(memory.body_fingerprint)}</code>
1135
1375
  <button type="button" data-delete-memory="${escapeHtml(memory.address)}" ${memory.deleted ? 'disabled' : ''}>Delete + prove</button>
1136
1376
  </li>`).join('') : '<li class="empty-row">No memory descriptors yet.</li>';
1377
+ const contextRefs = agentTurn.context_refs.length
1378
+ ? escapeHtml(JSON.stringify(agentTurn.context_refs, null, 2))
1379
+ : 'No context refs observed.';
1380
+ const receiptRefs = agentTurn.receipt_refs.length
1381
+ ? escapeHtml(JSON.stringify(agentTurn.receipt_refs, null, 2))
1382
+ : 'No receipt refs observed.';
1137
1383
 
1138
1384
  return renderScreen('vault', screen.title, `
1139
1385
  <div class="two-column">
@@ -1155,6 +1401,19 @@ function renderVaultScreen(screen, state) {
1155
1401
  <button type="submit">Remember descriptor</button>
1156
1402
  </form>
1157
1403
  </div>
1404
+ <div class="panel status-panel">
1405
+ <span class="status-pill">${escapeHtml(agentTurn.status)}</span>
1406
+ <h3>${escapeHtml(agentTurn.title)}</h3>
1407
+ <p>${escapeHtml(agentTurn.note)}</p>
1408
+ <dl class="detail-list">
1409
+ ${renderMetric('Adapter', agentTurn.selection.adapter_id || 'not configured')}
1410
+ ${renderMetric('Provider', agentTurn.selection.provider || 'not configured')}
1411
+ ${renderMetric('Model', agentTurn.selection.model || 'not configured')}
1412
+ ${renderMetric('Persisted memory', agentTurn.memory_id || 'not observed')}
1413
+ </dl>
1414
+ <h4>Context refs</h4><pre>${contextRefs}</pre>
1415
+ <h4>Receipt refs</h4><pre>${receiptRefs}</pre>
1416
+ </div>
1158
1417
  <form class="inline-form" data-form="search">
1159
1418
  <label>Search descriptors <input name="query" value="${escapeHtml(state.search.query)}" placeholder="tag, address, fingerprint"></label>
1160
1419
  <button type="submit">Search</button>
@@ -1224,7 +1483,8 @@ function renderDeleteProveScreen(screen) {
1224
1483
  }
1225
1484
 
1226
1485
  function renderMeshScreen(screen) {
1227
- return renderScreen('mesh', screen.title, `<div class="panel status-panel"><span class="status-pill">${escapeHtml(screen.status)}</span><p>${escapeHtml(screen.note)}</p><dl class="detail-list">${renderMetric('Peers', screen.peers)}${renderMetric('Relays', screen.relays)}${renderMetric('Last witness', screen.last_witness_at || 'not observed')}</dl><button type="button" data-action="mesh-online">Mark local mesh online</button></div>`);
1486
+ const federation = screen.federation;
1487
+ return renderScreen('mesh', screen.title, `<div class="panel status-panel"><span class="status-pill">${escapeHtml(screen.status)}</span><p>${escapeHtml(screen.note)}</p><dl class="detail-list">${renderMetric('Peers', screen.peers)}${renderMetric('Relays', screen.relays)}${renderMetric('Last witness', screen.last_witness_at || 'not observed')}${renderMetric('Federation bridge', federation.started ? 'running' : 'stopped')}${renderMetric('Federation scope', federation.scope || 'not initialized')}${renderMetric('Local bridge port', federation.listen_port || 'not listening')}${renderMetric('Registered federation peers', federation.registered_peers)}${renderMetric('Active grants', federation.active_grants)}${renderMetric('Pending queries', federation.pending_queries)}${renderMetric('Encrypted state', federation.persisted ? 'persistent' : 'ephemeral')}</dl></div>`);
1228
1488
  }
1229
1489
 
1230
1490
  function renderEnterpriseScreen(screen) {
@@ -1249,9 +1509,6 @@ function wireDesktopEvents(root, state, dispatch) {
1249
1509
  case 'stop-mcp':
1250
1510
  dispatch(stopMcp({ now }));
1251
1511
  break;
1252
- case 'mesh-online':
1253
- dispatch(updateMeshStatus({ status: 'online', peers: 3, relays: 1, last_witness_at: now }, { now }));
1254
- break;
1255
1512
  case 'enterprise-demo':
1256
1513
  dispatch(updateEnterpriseStatus({ status: 'configured', tenant_id: 'tenant_local', policy_id: 'policy_desktop', siem: 'ready' }, { now }));
1257
1514
  break;