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,337 @@
1
+ // Enigma Memory Intelligence: Contradiction & Supersession DAG.
2
+ // Automatically tracks state evolution, resolves conflicting factual assertions,
3
+ // and preserves immutable provenance links for superseded facts.
4
+ const CONTEXT_STOP_WORDS = new Set([
5
+ 'and', 'are', 'changed', 'favorite', 'from', 'into', 'instead', 'is', 'living',
6
+ 'lives', 'longer', 'moved', 'now', 'preference', 'prefer', 'prefers', 'stopped',
7
+ 'switched', 'the', 'their', 'they', 'this', 'to', 'using', 'uses', 'with',
8
+ ]);
9
+
10
+ function extractSubject(text, kind) {
11
+ const predicates = {
12
+ location: /^(.*?)\b(?:now\s+)?(?:lives?\s+in|living\s+in|moved\s+to)\b/i,
13
+ service: /^(.*?)\b(?:stopped\s+using|no\s+longer\s+uses?|switched\s+to|uses?|using)\b/i,
14
+ preference: /^(.*?)\b(?:changed\s+preference|now\s+prefers?|prefers?)\b/i,
15
+ };
16
+ const match = text.trim().match(predicates[kind]);
17
+ const subject = match?.[1]
18
+ ?.trim()
19
+ .replace(/\b(?:currently|is|was)\s*$/i, '')
20
+ .replace(/[^a-z0-9]+/gi, ' ')
21
+ .trim()
22
+ .toLowerCase();
23
+ return subject || null;
24
+ }
25
+
26
+ function contextTokens(text, subject) {
27
+ const subjectTokens = new Set((subject || '').split(/\s+/).filter(Boolean));
28
+ return new Set(
29
+ text.toLowerCase()
30
+ .split(/[^a-z0-9]+/)
31
+ .filter(token => token.length > 2 && !CONTEXT_STOP_WORDS.has(token) && !subjectTokens.has(token)),
32
+ );
33
+ }
34
+
35
+ function hasVerifiedSharedContext(newText, oldText, kind) {
36
+ const newSubject = extractSubject(newText, kind);
37
+ const oldSubject = extractSubject(oldText, kind);
38
+ if (newSubject && oldSubject) return newSubject === oldSubject;
39
+ const newTopics = contextTokens(newText, newSubject);
40
+ const oldTopics = contextTokens(oldText, oldSubject);
41
+ for (const topic of newTopics) {
42
+ if (oldTopics.has(topic)) return true;
43
+ }
44
+ return false;
45
+ }
46
+
47
+
48
+ export class ContradictionGraph {
49
+ constructor() {
50
+ /** @type {Map<string, { scope: string, supersedes: Set<string>, supersededBy: Set<string>, reasons: Map<string, string>, status: 'active'|'superseded', reason?: string }>} */
51
+ this.edges = new Map();
52
+ }
53
+
54
+ /**
55
+ * Registers a memory atom in the supersession graph.
56
+ * @param {string} id
57
+ * @param {{ scope?: string }} [meta]
58
+ */
59
+ registerNode(id, meta = {}) {
60
+ if (!id || typeof id !== 'string') {
61
+ throw new TypeError('Supersession node ID must be a non-empty string');
62
+ }
63
+ const scope = meta.scope || 'enigma.global';
64
+ const existing = this.edges.get(id);
65
+ if (existing) {
66
+ if (existing.scope !== scope) {
67
+ throw new Error(`Supersession node "${id}" is already registered in scope "${existing.scope}"`);
68
+ }
69
+ return;
70
+ }
71
+ this.edges.set(id, {
72
+ scope,
73
+ supersedes: new Set(),
74
+ supersededBy: new Set(),
75
+ reasons: new Map(),
76
+ status: 'active',
77
+ reason: undefined,
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Records that newAtomId supersedes priorAtomId.
83
+ * Both nodes must already exist in the same scope.
84
+ * @param {string} newAtomId
85
+ * @param {string} priorAtomId
86
+ * @param {string} [reason]
87
+ */
88
+ recordSupersession(newAtomId, priorAtomId, reason = 'state_update') {
89
+ if (newAtomId === priorAtomId) {
90
+ throw new Error('A memory atom cannot supersede itself');
91
+ }
92
+ const newEntry = this.edges.get(newAtomId);
93
+ const priorEntry = this.edges.get(priorAtomId);
94
+ if (!newEntry || !priorEntry) {
95
+ const missing = [!newEntry ? newAtomId : null, !priorEntry ? priorAtomId : null].filter(Boolean);
96
+ throw new Error(`Unknown supersession node${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}`);
97
+ }
98
+ if (newEntry.scope !== priorEntry.scope) {
99
+ throw new Error(`Cross-scope supersession is not allowed ("${newEntry.scope}" -> "${priorEntry.scope}")`);
100
+ }
101
+ if (newEntry.supersedes.has(priorAtomId)) {
102
+ newEntry.reasons.set(priorAtomId, reason);
103
+ priorEntry.reason = reason;
104
+ return;
105
+ }
106
+ if (this.#reaches(priorAtomId, newAtomId)) {
107
+ throw new Error(`Supersession edge "${newAtomId}" -> "${priorAtomId}" would create a cycle`);
108
+ }
109
+
110
+ newEntry.supersedes.add(priorAtomId);
111
+ newEntry.reasons.set(priorAtomId, reason);
112
+ priorEntry.supersededBy.add(newAtomId);
113
+ priorEntry.status = 'superseded';
114
+ priorEntry.reason = reason;
115
+ }
116
+
117
+ #reaches(startId, targetId) {
118
+ const pending = [startId];
119
+ const visited = new Set();
120
+ while (pending.length > 0) {
121
+ const id = pending.pop();
122
+ if (id === targetId) return true;
123
+ if (visited.has(id)) continue;
124
+ visited.add(id);
125
+ const entry = this.edges.get(id);
126
+ if (entry) pending.push(...entry.supersedes);
127
+ }
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Removes a node and all incident edges. Used to roll back failed writes.
133
+ * @param {string} id
134
+ */
135
+ removeNode(id) {
136
+ const entry = this.edges.get(id);
137
+ if (!entry) return false;
138
+ for (const priorId of entry.supersedes) {
139
+ const prior = this.edges.get(priorId);
140
+ if (!prior) continue;
141
+ prior.supersededBy.delete(id);
142
+ if (prior.supersededBy.size === 0) {
143
+ prior.status = 'active';
144
+ prior.reason = undefined;
145
+ } else {
146
+ const remainingNewerId = prior.supersededBy.values().next().value;
147
+ prior.reason = this.edges.get(remainingNewerId)?.reasons.get(priorId);
148
+ }
149
+ }
150
+ for (const newerId of entry.supersededBy) {
151
+ const newer = this.edges.get(newerId);
152
+ newer?.supersedes.delete(id);
153
+ newer?.reasons.delete(id);
154
+ }
155
+ return this.edges.delete(id);
156
+ }
157
+
158
+ /**
159
+ * Checks if an atom is superseded by any newer record.
160
+ * @param {string} id
161
+ * @returns {boolean}
162
+ */
163
+ isSuperseded(id) {
164
+ const entry = this.edges.get(id);
165
+ return Boolean(entry && entry.supersededBy.size > 0);
166
+ }
167
+
168
+ /**
169
+ * Returns supersession lineage for an atom.
170
+ * @param {string} id
171
+ */
172
+ getLineage(id) {
173
+ const entry = this.edges.get(id);
174
+ if (!entry) return { supersedes: [], supersededBy: [], status: 'active' };
175
+ return {
176
+ supersedes: Array.from(entry.supersedes),
177
+ supersededBy: Array.from(entry.supersededBy),
178
+ status: entry.status,
179
+ reason: entry.reason,
180
+ scope: entry.scope,
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Filters memory atoms to their current authoritative state.
186
+ * @param {Array<Object>} atoms
187
+ * @param {{ includeSuperseded?: boolean }} [options]
188
+ */
189
+ resolveActiveState(atoms, options = {}) {
190
+ const includeSuperseded = Boolean(options.includeSuperseded);
191
+ const result = [];
192
+ for (const atom of atoms) {
193
+ const isSup = this.isSuperseded(atom.id) || atom.metadata?.status === 'superseded';
194
+ if (!isSup || includeSuperseded) {
195
+ result.push({
196
+ ...atom,
197
+ _status: isSup ? 'superseded' : 'active',
198
+ _lineage: this.getLineage(atom.id),
199
+ });
200
+ }
201
+ }
202
+ return result;
203
+ }
204
+
205
+ /**
206
+ * Serializes the complete scoped DAG. Reverse edges and statuses are derived on import.
207
+ */
208
+ exportState() {
209
+ const nodes = Array.from(this.edges, ([id, entry]) => ({ id, scope: entry.scope }))
210
+ .sort((a, b) => a.id.localeCompare(b.id));
211
+ const edges = [];
212
+ for (const [from, entry] of this.edges) {
213
+ for (const to of entry.supersedes) {
214
+ edges.push({ from, to, reason: entry.reasons.get(to) || 'state_update' });
215
+ }
216
+ }
217
+ edges.sort((a, b) => a.from.localeCompare(b.from) || a.to.localeCompare(b.to));
218
+ return { schema: 'enigma.supersession_graph.v1', version: 1, nodes, edges };
219
+ }
220
+
221
+ /**
222
+ * Strictly imports and validates a serialized graph.
223
+ * @param {Object} state
224
+ * @param {Map<string, string>|Object<string, string>} [knownNodes]
225
+ */
226
+ importState(state, knownNodes) {
227
+ if (!state || state.schema !== 'enigma.supersession_graph.v1' || state.version !== 1
228
+ || !Array.isArray(state.nodes) || !Array.isArray(state.edges)) {
229
+ throw new Error('Invalid supersession graph state');
230
+ }
231
+ const expected = knownNodes instanceof Map
232
+ ? knownNodes
233
+ : new Map(Object.entries(knownNodes || {}));
234
+ const validateKnownNodes = knownNodes !== undefined;
235
+ const imported = new ContradictionGraph();
236
+ for (const node of state.nodes) {
237
+ if (!node || typeof node.id !== 'string' || !node.id || typeof node.scope !== 'string' || !node.scope) {
238
+ throw new Error('Invalid supersession graph node');
239
+ }
240
+ if (imported.edges.has(node.id)) {
241
+ throw new Error(`Duplicate supersession node "${node.id}"`);
242
+ }
243
+ if (validateKnownNodes) {
244
+ if (!expected.has(node.id)) throw new Error(`Unknown supersession node: ${node.id}`);
245
+ if (expected.get(node.id) !== node.scope) {
246
+ throw new Error(`Supersession node "${node.id}" has an invalid scope`);
247
+ }
248
+ }
249
+ imported.registerNode(node.id, { scope: node.scope });
250
+ }
251
+ if (validateKnownNodes) {
252
+ for (const [id, scope] of expected) {
253
+ if (!imported.edges.has(id)) imported.registerNode(id, { scope });
254
+ }
255
+ }
256
+ for (const edge of state.edges) {
257
+ if (!edge || typeof edge.from !== 'string' || !edge.from
258
+ || typeof edge.to !== 'string' || !edge.to
259
+ || (edge.reason !== undefined && typeof edge.reason !== 'string')) {
260
+ throw new Error('Invalid supersession graph edge');
261
+ }
262
+ imported.recordSupersession(edge.from, edge.to, edge.reason || 'state_update');
263
+ }
264
+ this.edges = imported.edges;
265
+ return this;
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Heuristic detector for state contradiction between existing memories and a newly proposed statement.
271
+ * Checks for subject-predicate updates like "lives in [X]" vs "lives in [Y]", "using [A]" vs "stopped using [A], now using [B]".
272
+ * @param {string} newText
273
+ * @param {Array<{ id: string, text: string }>} candidateMemories
274
+ * @returns {Array<{ priorId: string, confidence: number, reason: string }>}
275
+ */
276
+ export function detectContradictions(newText, candidateMemories = []) {
277
+ if (!newText || typeof newText !== 'string' || candidateMemories.length === 0) {
278
+ return [];
279
+ }
280
+
281
+ const conflicts = [];
282
+ const lowerNew = newText.toLowerCase();
283
+
284
+ for (const candidate of candidateMemories) {
285
+ const lowerOld = candidate.text.toLowerCase();
286
+
287
+ // 1. Relocation / Living location updates ("lives in X" -> "moved to Y")
288
+ if (
289
+ (lowerNew.includes('moved to ') || lowerNew.includes('now lives in ')) &&
290
+ (lowerOld.includes('lives in ') || lowerOld.includes('living in ')) &&
291
+ hasVerifiedSharedContext(newText, candidate.text, 'location')
292
+ ) {
293
+ conflicts.push({
294
+ priorId: candidate.id,
295
+ confidence: 0.95,
296
+ reason: 'location_relocation_detected',
297
+ });
298
+ continue;
299
+ }
300
+
301
+ // 2. Service / Tool cessation ("stopped using X" -> "using Y now")
302
+ if (
303
+ (lowerNew.includes('stopped using ') || lowerNew.includes('no longer use ') || lowerNew.includes('switched to ')) &&
304
+ (lowerOld.includes('favorite ') || lowerOld.includes('uses ') || lowerOld.includes('using ')) &&
305
+ hasVerifiedSharedContext(newText, candidate.text, 'service')
306
+ ) {
307
+ conflicts.push({
308
+ priorId: candidate.id,
309
+ confidence: 0.90,
310
+ reason: 'service_supersession_detected',
311
+ });
312
+ continue;
313
+ }
314
+
315
+ // 3. Preference changes ("changed preference to X", "prefers X instead of Y")
316
+ if (
317
+ (lowerNew.includes('changed preference') || lowerNew.includes('prefer ') || lowerNew.includes('now prefer ')) &&
318
+ (lowerOld.includes('prefer ') || lowerOld.includes('prefers ')) &&
319
+ hasVerifiedSharedContext(newText, candidate.text, 'preference')
320
+ ) {
321
+ // Check for token overlap to prevent false positives on distinct topics
322
+ const newTokens = new Set(lowerNew.split(/\W+/).filter(w => w.length > 3));
323
+ const oldTokens = lowerOld.split(/\W+/).filter(w => w.length > 3);
324
+ const overlap = oldTokens.filter(t => newTokens.has(t)).length;
325
+
326
+ if (overlap >= 2) {
327
+ conflicts.push({
328
+ priorId: candidate.id,
329
+ confidence: 0.85,
330
+ reason: 'preference_updated',
331
+ });
332
+ }
333
+ }
334
+ }
335
+
336
+ return conflicts;
337
+ }
@@ -0,0 +1,155 @@
1
+ // Enigma Memory Intelligence: Memory Decision & Consolidation Engine.
2
+ // Evaluates observation novelty, filters transient conversation noise,
3
+ // and consolidates redundant memory clusters.
4
+ import { inferMemoryType, DEFAULT_TYPE_WEIGHTS } from './ontology.js';
5
+ import { detectContradictions } from './contradiction.js';
6
+
7
+ const NOISE_WORDS = new Set([
8
+ 'ok', 'okay', 'got', 'it', 'thanks', 'thank', 'you', 'cool', 'yes', 'no',
9
+ 'sure', 'yep', 'nope', 'hi', 'hello', 'hey', 'bye', 'i', 'see', 'understood',
10
+ 'makes', 'sense', 'great', 'perfect', 'will', 'do', 'alright', 'k'
11
+ ]);
12
+
13
+ export function isTransientNoise(text) {
14
+ if (!text || typeof text !== 'string') return true;
15
+ const tokens = text.toLowerCase().replace(/[^a-z\s]/g, '').trim().split(/\s+/).filter(Boolean);
16
+ if (tokens.length === 0) return true;
17
+ if (tokens.length <= 5 && tokens.every(t => NOISE_WORDS.has(t))) {
18
+ return true;
19
+ }
20
+ return false;
21
+ }
22
+
23
+ export class MemoryDecisionEngine {
24
+ /**
25
+ * @param {Object} [options]
26
+ * @param {number} [options.minNoveltyThreshold=0.25]
27
+ * @param {number} [options.minImportanceThreshold=0.3]
28
+ */
29
+ constructor(options = {}) {
30
+ this.minNoveltyThreshold = options.minNoveltyThreshold ?? 0.25;
31
+ this.minImportanceThreshold = options.minImportanceThreshold ?? 0.3;
32
+ }
33
+
34
+ /**
35
+ * Evaluates an incoming observation to decide if it warrants sovereign vault persistence.
36
+ * @param {string} text
37
+ * @param {Object} [metadata={}]
38
+ * @param {Array<{ id: string, text: string }>} [existingMemories=[]]
39
+ * @returns {{ shouldRemember: boolean, novelty: number, importance: number, type: string, conflicts: Array<Object>, reason: string }}
40
+ */
41
+ evaluate(text, metadata = {}, existingMemories = []) {
42
+ if (!text || typeof text !== 'string' || text.trim().length === 0) {
43
+ return { shouldRemember: false, novelty: 0, importance: 0, type: 'semantic', conflicts: [], reason: 'empty_text' };
44
+ }
45
+
46
+ const trimmed = text.trim();
47
+
48
+ // 1. Transient noise filter
49
+ if (isTransientNoise(trimmed)) {
50
+ return {
51
+ shouldRemember: false,
52
+ novelty: 0.05,
53
+ importance: 0.05,
54
+ type: 'working',
55
+ conflicts: [],
56
+ reason: 'transient_chat_chatter_filtered',
57
+ };
58
+ }
59
+
60
+ // 2. Infer ontology type & base importance weight
61
+ const type = metadata.type || inferMemoryType(trimmed);
62
+ const typeMultiplier = DEFAULT_TYPE_WEIGHTS[type] || 1.0;
63
+ const explicitImportance = typeof metadata.importance === 'number' ? metadata.importance : 1.0;
64
+ const computedImportance = Math.min(2.5, explicitImportance * typeMultiplier);
65
+
66
+ // 3. Compute novelty against existing memory corpus
67
+ const novelty = this.computeNovelty(trimmed, existingMemories);
68
+
69
+ // 4. Detect contradictions / supersessions
70
+ const conflicts = detectContradictions(trimmed, existingMemories);
71
+
72
+ // 5. Decision logic: Policies and preferences are always remembered
73
+ const isCriticalType = type === 'policy' || type === 'preference' || type === 'identity';
74
+ const hasSufficientSignal = novelty >= this.minNoveltyThreshold && computedImportance >= this.minImportanceThreshold;
75
+ const shouldRemember = isCriticalType || hasSufficientSignal || conflicts.length > 0;
76
+
77
+ return {
78
+ shouldRemember,
79
+ novelty: Math.round(novelty * 100) / 100,
80
+ importance: Math.round(computedImportance * 100) / 100,
81
+ type,
82
+ conflicts,
83
+ reason: shouldRemember ? 'high_value_signal_accepted' : 'redundant_or_low_signal',
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Computes lexical novelty score (0.0 to 1.0) against existing memories.
89
+ * @param {string} text
90
+ * @param {Array<{ id: string, text: string }>} existing
91
+ * @returns {number}
92
+ */
93
+ computeNovelty(text, existing = []) {
94
+ if (existing.length === 0) return 1.0;
95
+
96
+ const newTokens = new Set(text.toLowerCase().split(/\W+/).filter(w => w.length > 2));
97
+ if (newTokens.size === 0) return 0.5;
98
+
99
+ let maxOverlapRatio = 0;
100
+
101
+ for (const item of existing) {
102
+ const oldTokens = new Set(item.text.toLowerCase().split(/\W+/).filter(w => w.length > 2));
103
+ if (oldTokens.size === 0) continue;
104
+
105
+ let overlapCount = 0;
106
+ for (const t of newTokens) {
107
+ if (oldTokens.has(t)) overlapCount++;
108
+ }
109
+
110
+ const ratio = overlapCount / Math.max(newTokens.size, oldTokens.size);
111
+ if (ratio > maxOverlapRatio) maxOverlapRatio = ratio;
112
+ }
113
+
114
+ return Math.max(0.0, 1.0 - maxOverlapRatio);
115
+ }
116
+
117
+ /**
118
+ * Consolidates redundant memory atoms into a concise summary record.
119
+ * @param {Array<{ id: string, text: string, type?: string, createdAt: number }>} memories
120
+ * @returns {Array<{ id: string, text: string, consolidatedFrom: string[], type: string }>}
121
+ */
122
+ consolidate(memories = []) {
123
+ if (memories.length <= 1) return memories;
124
+
125
+ // Group memories by category/topic
126
+ const clusters = new Map();
127
+ for (const mem of memories) {
128
+ const type = mem.type || 'semantic';
129
+ if (!clusters.has(type)) clusters.set(type, []);
130
+ clusters.get(type).push(mem);
131
+ }
132
+
133
+ const consolidated = [];
134
+ for (const [type, items] of clusters.entries()) {
135
+ if (items.length <= 3) {
136
+ consolidated.push(...items);
137
+ continue;
138
+ }
139
+
140
+ // Consolidate cluster into deduplicated items
141
+ const uniqueTexts = Array.from(new Set(items.map(i => i.text.trim())));
142
+ const sourceIds = items.map(i => i.id);
143
+
144
+ consolidated.push({
145
+ id: `consolidated_${type}_${Date.now()}`,
146
+ text: uniqueTexts.join('; '),
147
+ consolidatedFrom: sourceIds,
148
+ type,
149
+ createdAt: Date.now(),
150
+ });
151
+ }
152
+
153
+ return consolidated;
154
+ }
155
+ }
@@ -0,0 +1,4 @@
1
+ export * from './ontology.js';
2
+ export * from './temporal.js';
3
+ export * from './contradiction.js';
4
+ export * from './decision-engine.js';
@@ -0,0 +1,122 @@
1
+ // Enigma Memory Intelligence: Structured Memory Ontology & Taxonomy.
2
+ // Distinguishes episodic events, semantic facts, agent preferences,
3
+ // procedural workflows, security policies, and working context.
4
+
5
+ export const MEMORY_TYPES = Object.freeze({
6
+ EPISODIC: 'episodic', // Temporal events: "User executed trade #42 at 14:02"
7
+ SEMANTIC: 'semantic', // General facts: "Solana slot time is approximately 400ms"
8
+ PROCEDURAL: 'procedural', // Workflows / how-to: "To anchor a note tree, call settleIntent()"
9
+ PREFERENCE: 'preference', // Actor preferences: "User prefers max 0.5% slippage on Raydium"
10
+ POLICY: 'policy', // Governance & safety rules: "Never execute trades exceeding 10 SOL without 2FA"
11
+ IDENTITY: 'identity', // Persistent facts: "Agent pubkey is 42d8ea..."
12
+ GOAL: 'goal', // Future targets: "Reach 99.9% uptime on GhostMesh relay"
13
+ WORKING: 'working', // Ephemeral scratchpad / session context
14
+ });
15
+
16
+ export const VALID_MEMORY_TYPES = new Set(Object.values(MEMORY_TYPES));
17
+
18
+ export const DEFAULT_TYPE_WEIGHTS = Object.freeze({
19
+ [MEMORY_TYPES.POLICY]: 2.5, // Policies & safety rules have highest default retrieval priority
20
+ [MEMORY_TYPES.IDENTITY]: 2.0, // Core identity facts
21
+ [MEMORY_TYPES.PREFERENCE]: 1.8, // User preferences heavily shape responses
22
+ [MEMORY_TYPES.GOAL]: 1.5,
23
+ [MEMORY_TYPES.PROCEDURAL]: 1.3,
24
+ [MEMORY_TYPES.SEMANTIC]: 1.0,
25
+ [MEMORY_TYPES.EPISODIC]: 0.9,
26
+ [MEMORY_TYPES.WORKING]: 0.7,
27
+ });
28
+
29
+ /**
30
+ * Validates and normalizes memory type. Defaults to 'semantic' if omitted or unrecognized.
31
+ * @param {string} [type]
32
+ * @returns {string} Normalized memory type
33
+ */
34
+ export function normalizeMemoryType(type) {
35
+ if (!type || typeof type !== 'string') return MEMORY_TYPES.SEMANTIC;
36
+ const normalized = type.trim().toLowerCase();
37
+ return VALID_MEMORY_TYPES.has(normalized) ? normalized : MEMORY_TYPES.SEMANTIC;
38
+ }
39
+
40
+ /**
41
+ * Automatically infers memory ontology type from text patterns and keywords.
42
+ * @param {string} text
43
+ * @returns {string} Inferred memory type
44
+ */
45
+ export function inferMemoryType(text) {
46
+ if (!text || typeof text !== 'string') return MEMORY_TYPES.SEMANTIC;
47
+ const lower = text.toLowerCase();
48
+
49
+ // 1. Policy & Security Invariants
50
+ if (
51
+ lower.includes('never ') ||
52
+ lower.includes('must not') ||
53
+ lower.includes('prohibited') ||
54
+ lower.includes('always require') ||
55
+ lower.includes('policy:') ||
56
+ lower.includes('invariant:') ||
57
+ lower.includes('rule:') ||
58
+ lower.includes('security rule')
59
+ ) {
60
+ return MEMORY_TYPES.POLICY;
61
+ }
62
+
63
+ // 2. Preferences
64
+ if (
65
+ lower.includes('prefer') ||
66
+ lower.includes('likes') ||
67
+ lower.includes('dislikes') ||
68
+ lower.includes('favorite') ||
69
+ lower.includes('always use') ||
70
+ lower.includes('setting:') ||
71
+ lower.includes('preference:')
72
+ ) {
73
+ return MEMORY_TYPES.PREFERENCE;
74
+ }
75
+
76
+ // 3. Procedural / Workflows
77
+ if (
78
+ lower.includes('how to') ||
79
+ lower.includes('steps to') ||
80
+ lower.includes('procedure:') ||
81
+ lower.includes('workflow:') ||
82
+ lower.includes('first, ') && lower.includes('then, ')
83
+ ) {
84
+ return MEMORY_TYPES.PROCEDURAL;
85
+ }
86
+
87
+ // 4. Goals
88
+ if (
89
+ lower.includes('goal:') ||
90
+ lower.includes('target:') ||
91
+ lower.includes('objective:') ||
92
+ lower.includes('aim to') ||
93
+ lower.includes('milestone:')
94
+ ) {
95
+ return MEMORY_TYPES.GOAL;
96
+ }
97
+
98
+ // 5. Identity
99
+ if (
100
+ lower.includes('my name is') ||
101
+ lower.includes('i am an ai') ||
102
+ lower.includes('agent id') ||
103
+ lower.includes('public key') ||
104
+ lower.includes('pubkey')
105
+ ) {
106
+ return MEMORY_TYPES.IDENTITY;
107
+ }
108
+
109
+ // 6. Episodic (timestamps, events, actions)
110
+ if (
111
+ lower.includes('yesterday') ||
112
+ lower.includes('today at') ||
113
+ lower.includes('executed') ||
114
+ lower.includes('happened') ||
115
+ lower.includes('received signal') ||
116
+ /\b(20\d\d-\d\d-\d\d|\d{1,2}:\d{2})\b/.test(lower)
117
+ ) {
118
+ return MEMORY_TYPES.EPISODIC;
119
+ }
120
+
121
+ return MEMORY_TYPES.SEMANTIC;
122
+ }