superlocalmemory 2.8.6 → 3.0.1

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 (431) hide show
  1. package/LICENSE +9 -1
  2. package/NOTICE +63 -0
  3. package/README.md +165 -480
  4. package/bin/slm +17 -449
  5. package/bin/slm-npm +62 -48
  6. package/conftest.py +5 -0
  7. package/docs/api-reference.md +284 -0
  8. package/docs/architecture.md +149 -0
  9. package/docs/auto-memory.md +150 -0
  10. package/docs/cli-reference.md +276 -0
  11. package/docs/compliance.md +191 -0
  12. package/docs/configuration.md +182 -0
  13. package/docs/getting-started.md +102 -0
  14. package/docs/ide-setup.md +261 -0
  15. package/docs/mcp-tools.md +220 -0
  16. package/docs/migration-from-v2.md +170 -0
  17. package/docs/profiles.md +173 -0
  18. package/docs/troubleshooting.md +310 -0
  19. package/{configs → ide/configs}/antigravity-mcp.json +3 -3
  20. package/ide/configs/chatgpt-desktop-mcp.json +16 -0
  21. package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
  22. package/{configs → ide/configs}/codex-mcp.toml +4 -4
  23. package/{configs → ide/configs}/continue-mcp.yaml +4 -3
  24. package/{configs → ide/configs}/continue-skills.yaml +6 -6
  25. package/ide/configs/cursor-mcp.json +15 -0
  26. package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
  27. package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
  28. package/{configs → ide/configs}/opencode-mcp.json +2 -2
  29. package/{configs → ide/configs}/perplexity-mcp.json +2 -2
  30. package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
  31. package/{configs → ide/configs}/windsurf-mcp.json +3 -3
  32. package/{configs → ide/configs}/zed-mcp.json +2 -2
  33. package/{hooks → ide/hooks}/context-hook.js +9 -20
  34. package/ide/hooks/memory-list-skill.js +70 -0
  35. package/ide/hooks/memory-profile-skill.js +101 -0
  36. package/ide/hooks/memory-recall-skill.js +62 -0
  37. package/ide/hooks/memory-remember-skill.js +68 -0
  38. package/ide/hooks/memory-reset-skill.js +160 -0
  39. package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
  40. package/ide/integrations/langchain/README.md +106 -0
  41. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
  42. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
  43. package/ide/integrations/langchain/pyproject.toml +38 -0
  44. package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
  45. package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
  46. package/ide/integrations/langchain/tests/test_security.py +117 -0
  47. package/ide/integrations/llamaindex/README.md +81 -0
  48. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
  49. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
  50. package/ide/integrations/llamaindex/pyproject.toml +43 -0
  51. package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
  52. package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
  53. package/ide/integrations/llamaindex/tests/test_security.py +241 -0
  54. package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
  55. package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
  56. package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
  57. package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
  58. package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
  59. package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
  60. package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
  61. package/package.json +13 -22
  62. package/pyproject.toml +85 -0
  63. package/scripts/build-dmg.sh +417 -0
  64. package/scripts/install-skills.ps1 +334 -0
  65. package/scripts/postinstall.js +2 -2
  66. package/scripts/start-dashboard.ps1 +52 -0
  67. package/scripts/start-dashboard.sh +41 -0
  68. package/scripts/sync-wiki.ps1 +127 -0
  69. package/scripts/sync-wiki.sh +82 -0
  70. package/scripts/test-dmg.sh +161 -0
  71. package/scripts/test-npm-package.ps1 +252 -0
  72. package/scripts/test-npm-package.sh +207 -0
  73. package/scripts/verify-install.ps1 +294 -0
  74. package/scripts/verify-install.sh +266 -0
  75. package/src/superlocalmemory/__init__.py +0 -0
  76. package/src/superlocalmemory/attribution/__init__.py +9 -0
  77. package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
  78. package/src/superlocalmemory/attribution/signer.py +153 -0
  79. package/src/superlocalmemory/attribution/watermark.py +189 -0
  80. package/src/superlocalmemory/cli/__init__.py +5 -0
  81. package/src/superlocalmemory/cli/commands.py +245 -0
  82. package/src/superlocalmemory/cli/main.py +89 -0
  83. package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
  84. package/src/superlocalmemory/cli/post_install.py +99 -0
  85. package/src/superlocalmemory/cli/setup_wizard.py +129 -0
  86. package/src/superlocalmemory/compliance/__init__.py +0 -0
  87. package/src/superlocalmemory/compliance/abac.py +204 -0
  88. package/src/superlocalmemory/compliance/audit.py +314 -0
  89. package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
  90. package/src/superlocalmemory/compliance/gdpr.py +294 -0
  91. package/src/superlocalmemory/compliance/lifecycle.py +158 -0
  92. package/src/superlocalmemory/compliance/retention.py +232 -0
  93. package/src/superlocalmemory/compliance/scheduler.py +148 -0
  94. package/src/superlocalmemory/core/__init__.py +0 -0
  95. package/src/superlocalmemory/core/config.py +391 -0
  96. package/src/superlocalmemory/core/embeddings.py +293 -0
  97. package/src/superlocalmemory/core/engine.py +701 -0
  98. package/src/superlocalmemory/core/hooks.py +65 -0
  99. package/src/superlocalmemory/core/maintenance.py +172 -0
  100. package/src/superlocalmemory/core/modes.py +140 -0
  101. package/src/superlocalmemory/core/profiles.py +234 -0
  102. package/src/superlocalmemory/core/registry.py +117 -0
  103. package/src/superlocalmemory/dynamics/__init__.py +0 -0
  104. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
  105. package/src/superlocalmemory/encoding/__init__.py +0 -0
  106. package/src/superlocalmemory/encoding/consolidator.py +485 -0
  107. package/src/superlocalmemory/encoding/emotional.py +125 -0
  108. package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
  109. package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
  110. package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
  111. package/src/superlocalmemory/encoding/foresight.py +91 -0
  112. package/src/superlocalmemory/encoding/graph_builder.py +302 -0
  113. package/src/superlocalmemory/encoding/observation_builder.py +160 -0
  114. package/src/superlocalmemory/encoding/scene_builder.py +183 -0
  115. package/src/superlocalmemory/encoding/signal_inference.py +90 -0
  116. package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
  117. package/src/superlocalmemory/encoding/type_router.py +235 -0
  118. package/src/superlocalmemory/hooks/__init__.py +3 -0
  119. package/src/superlocalmemory/hooks/auto_capture.py +111 -0
  120. package/src/superlocalmemory/hooks/auto_recall.py +93 -0
  121. package/src/superlocalmemory/hooks/ide_connector.py +204 -0
  122. package/src/superlocalmemory/hooks/rules_engine.py +99 -0
  123. package/src/superlocalmemory/infra/__init__.py +3 -0
  124. package/src/superlocalmemory/infra/auth_middleware.py +82 -0
  125. package/src/superlocalmemory/infra/backup.py +317 -0
  126. package/src/superlocalmemory/infra/cache_manager.py +267 -0
  127. package/src/superlocalmemory/infra/event_bus.py +381 -0
  128. package/src/superlocalmemory/infra/rate_limiter.py +135 -0
  129. package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
  130. package/src/superlocalmemory/learning/__init__.py +0 -0
  131. package/src/superlocalmemory/learning/adaptive.py +172 -0
  132. package/src/superlocalmemory/learning/behavioral.py +490 -0
  133. package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
  134. package/src/superlocalmemory/learning/bootstrap.py +298 -0
  135. package/src/superlocalmemory/learning/cross_project.py +399 -0
  136. package/src/superlocalmemory/learning/database.py +376 -0
  137. package/src/superlocalmemory/learning/engagement.py +323 -0
  138. package/src/superlocalmemory/learning/features.py +138 -0
  139. package/src/superlocalmemory/learning/feedback.py +316 -0
  140. package/src/superlocalmemory/learning/outcomes.py +255 -0
  141. package/src/superlocalmemory/learning/project_context.py +366 -0
  142. package/src/superlocalmemory/learning/ranker.py +155 -0
  143. package/src/superlocalmemory/learning/source_quality.py +303 -0
  144. package/src/superlocalmemory/learning/workflows.py +309 -0
  145. package/src/superlocalmemory/llm/__init__.py +0 -0
  146. package/src/superlocalmemory/llm/backbone.py +316 -0
  147. package/src/superlocalmemory/math/__init__.py +0 -0
  148. package/src/superlocalmemory/math/fisher.py +356 -0
  149. package/src/superlocalmemory/math/langevin.py +398 -0
  150. package/src/superlocalmemory/math/sheaf.py +257 -0
  151. package/src/superlocalmemory/mcp/__init__.py +0 -0
  152. package/src/superlocalmemory/mcp/resources.py +245 -0
  153. package/src/superlocalmemory/mcp/server.py +61 -0
  154. package/src/superlocalmemory/mcp/tools.py +18 -0
  155. package/src/superlocalmemory/mcp/tools_core.py +305 -0
  156. package/src/superlocalmemory/mcp/tools_v28.py +223 -0
  157. package/src/superlocalmemory/mcp/tools_v3.py +286 -0
  158. package/src/superlocalmemory/retrieval/__init__.py +0 -0
  159. package/src/superlocalmemory/retrieval/agentic.py +295 -0
  160. package/src/superlocalmemory/retrieval/ann_index.py +223 -0
  161. package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
  162. package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
  163. package/src/superlocalmemory/retrieval/engine.py +390 -0
  164. package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
  165. package/src/superlocalmemory/retrieval/fusion.py +78 -0
  166. package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
  167. package/src/superlocalmemory/retrieval/reranker.py +154 -0
  168. package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
  169. package/src/superlocalmemory/retrieval/strategy.py +96 -0
  170. package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
  171. package/src/superlocalmemory/server/__init__.py +1 -0
  172. package/src/superlocalmemory/server/api.py +248 -0
  173. package/src/superlocalmemory/server/routes/__init__.py +4 -0
  174. package/src/superlocalmemory/server/routes/agents.py +107 -0
  175. package/src/superlocalmemory/server/routes/backup.py +91 -0
  176. package/src/superlocalmemory/server/routes/behavioral.py +127 -0
  177. package/src/superlocalmemory/server/routes/compliance.py +160 -0
  178. package/src/superlocalmemory/server/routes/data_io.py +188 -0
  179. package/src/superlocalmemory/server/routes/events.py +183 -0
  180. package/src/superlocalmemory/server/routes/helpers.py +85 -0
  181. package/src/superlocalmemory/server/routes/learning.py +273 -0
  182. package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
  183. package/src/superlocalmemory/server/routes/memories.py +399 -0
  184. package/src/superlocalmemory/server/routes/profiles.py +219 -0
  185. package/src/superlocalmemory/server/routes/stats.py +346 -0
  186. package/src/superlocalmemory/server/routes/v3_api.py +365 -0
  187. package/src/superlocalmemory/server/routes/ws.py +82 -0
  188. package/src/superlocalmemory/server/security_middleware.py +57 -0
  189. package/src/superlocalmemory/server/ui.py +245 -0
  190. package/src/superlocalmemory/storage/__init__.py +0 -0
  191. package/src/superlocalmemory/storage/access_control.py +182 -0
  192. package/src/superlocalmemory/storage/database.py +594 -0
  193. package/src/superlocalmemory/storage/migrations.py +303 -0
  194. package/src/superlocalmemory/storage/models.py +406 -0
  195. package/src/superlocalmemory/storage/schema.py +726 -0
  196. package/src/superlocalmemory/storage/v2_migrator.py +317 -0
  197. package/src/superlocalmemory/trust/__init__.py +0 -0
  198. package/src/superlocalmemory/trust/gate.py +130 -0
  199. package/src/superlocalmemory/trust/provenance.py +124 -0
  200. package/src/superlocalmemory/trust/scorer.py +347 -0
  201. package/src/superlocalmemory/trust/signals.py +153 -0
  202. package/ui/index.html +278 -5
  203. package/ui/js/auto-settings.js +70 -0
  204. package/ui/js/dashboard.js +90 -0
  205. package/ui/js/fact-detail.js +92 -0
  206. package/ui/js/feedback.js +2 -2
  207. package/ui/js/ide-status.js +102 -0
  208. package/ui/js/math-health.js +98 -0
  209. package/ui/js/recall-lab.js +127 -0
  210. package/ui/js/settings.js +2 -2
  211. package/ui/js/trust-dashboard.js +73 -0
  212. package/api_server.py +0 -724
  213. package/bin/aider-smart +0 -72
  214. package/bin/superlocalmemoryv2-learning +0 -4
  215. package/bin/superlocalmemoryv2-list +0 -3
  216. package/bin/superlocalmemoryv2-patterns +0 -4
  217. package/bin/superlocalmemoryv2-profile +0 -3
  218. package/bin/superlocalmemoryv2-recall +0 -3
  219. package/bin/superlocalmemoryv2-remember +0 -3
  220. package/bin/superlocalmemoryv2-reset +0 -3
  221. package/bin/superlocalmemoryv2-status +0 -3
  222. package/configs/chatgpt-desktop-mcp.json +0 -16
  223. package/configs/cursor-mcp.json +0 -15
  224. package/hooks/memory-list-skill.js +0 -139
  225. package/hooks/memory-profile-skill.js +0 -273
  226. package/hooks/memory-recall-skill.js +0 -114
  227. package/hooks/memory-remember-skill.js +0 -127
  228. package/hooks/memory-reset-skill.js +0 -274
  229. package/mcp_server.py +0 -1808
  230. package/requirements-core.txt +0 -22
  231. package/requirements-learning.txt +0 -12
  232. package/requirements.txt +0 -12
  233. package/src/agent_registry.py +0 -411
  234. package/src/auth_middleware.py +0 -61
  235. package/src/auto_backup.py +0 -459
  236. package/src/behavioral/__init__.py +0 -49
  237. package/src/behavioral/behavioral_listener.py +0 -203
  238. package/src/behavioral/behavioral_patterns.py +0 -275
  239. package/src/behavioral/cross_project_transfer.py +0 -206
  240. package/src/behavioral/outcome_inference.py +0 -194
  241. package/src/behavioral/outcome_tracker.py +0 -193
  242. package/src/behavioral/tests/__init__.py +0 -4
  243. package/src/behavioral/tests/test_behavioral_integration.py +0 -108
  244. package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
  245. package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
  246. package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
  247. package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
  248. package/src/behavioral/tests/test_outcome_inference.py +0 -107
  249. package/src/behavioral/tests/test_outcome_tracker.py +0 -96
  250. package/src/cache_manager.py +0 -518
  251. package/src/compliance/__init__.py +0 -48
  252. package/src/compliance/abac_engine.py +0 -149
  253. package/src/compliance/abac_middleware.py +0 -116
  254. package/src/compliance/audit_db.py +0 -215
  255. package/src/compliance/audit_logger.py +0 -148
  256. package/src/compliance/retention_manager.py +0 -289
  257. package/src/compliance/retention_scheduler.py +0 -186
  258. package/src/compliance/tests/__init__.py +0 -4
  259. package/src/compliance/tests/test_abac_enforcement.py +0 -95
  260. package/src/compliance/tests/test_abac_engine.py +0 -124
  261. package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
  262. package/src/compliance/tests/test_audit_db.py +0 -123
  263. package/src/compliance/tests/test_audit_logger.py +0 -98
  264. package/src/compliance/tests/test_mcp_audit.py +0 -128
  265. package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
  266. package/src/compliance/tests/test_retention_manager.py +0 -131
  267. package/src/compliance/tests/test_retention_scheduler.py +0 -99
  268. package/src/compression/__init__.py +0 -25
  269. package/src/compression/cli.py +0 -150
  270. package/src/compression/cold_storage.py +0 -217
  271. package/src/compression/config.py +0 -72
  272. package/src/compression/orchestrator.py +0 -133
  273. package/src/compression/tier2_compressor.py +0 -228
  274. package/src/compression/tier3_compressor.py +0 -153
  275. package/src/compression/tier_classifier.py +0 -148
  276. package/src/db_connection_manager.py +0 -536
  277. package/src/embedding_engine.py +0 -63
  278. package/src/embeddings/__init__.py +0 -47
  279. package/src/embeddings/cache.py +0 -70
  280. package/src/embeddings/cli.py +0 -113
  281. package/src/embeddings/constants.py +0 -47
  282. package/src/embeddings/database.py +0 -91
  283. package/src/embeddings/engine.py +0 -247
  284. package/src/embeddings/model_loader.py +0 -145
  285. package/src/event_bus.py +0 -562
  286. package/src/graph/__init__.py +0 -36
  287. package/src/graph/build_helpers.py +0 -74
  288. package/src/graph/cli.py +0 -87
  289. package/src/graph/cluster_builder.py +0 -188
  290. package/src/graph/cluster_summary.py +0 -148
  291. package/src/graph/constants.py +0 -47
  292. package/src/graph/edge_builder.py +0 -162
  293. package/src/graph/entity_extractor.py +0 -95
  294. package/src/graph/graph_core.py +0 -226
  295. package/src/graph/graph_search.py +0 -231
  296. package/src/graph/hierarchical.py +0 -207
  297. package/src/graph/schema.py +0 -99
  298. package/src/graph_engine.py +0 -52
  299. package/src/hnsw_index.py +0 -628
  300. package/src/hybrid_search.py +0 -46
  301. package/src/learning/__init__.py +0 -217
  302. package/src/learning/adaptive_ranker.py +0 -682
  303. package/src/learning/bootstrap/__init__.py +0 -69
  304. package/src/learning/bootstrap/constants.py +0 -93
  305. package/src/learning/bootstrap/db_queries.py +0 -316
  306. package/src/learning/bootstrap/sampling.py +0 -82
  307. package/src/learning/bootstrap/text_utils.py +0 -71
  308. package/src/learning/cross_project_aggregator.py +0 -857
  309. package/src/learning/db/__init__.py +0 -40
  310. package/src/learning/db/constants.py +0 -44
  311. package/src/learning/db/schema.py +0 -279
  312. package/src/learning/engagement_tracker.py +0 -628
  313. package/src/learning/feature_extractor.py +0 -708
  314. package/src/learning/feedback_collector.py +0 -806
  315. package/src/learning/learning_db.py +0 -915
  316. package/src/learning/project_context_manager.py +0 -572
  317. package/src/learning/ranking/__init__.py +0 -33
  318. package/src/learning/ranking/constants.py +0 -84
  319. package/src/learning/ranking/helpers.py +0 -278
  320. package/src/learning/source_quality_scorer.py +0 -676
  321. package/src/learning/synthetic_bootstrap.py +0 -755
  322. package/src/learning/tests/test_adaptive_ranker.py +0 -325
  323. package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
  324. package/src/learning/tests/test_aggregator.py +0 -306
  325. package/src/learning/tests/test_auto_retrain_v28.py +0 -35
  326. package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
  327. package/src/learning/tests/test_feature_extractor_v28.py +0 -93
  328. package/src/learning/tests/test_feedback_collector.py +0 -294
  329. package/src/learning/tests/test_learning_db.py +0 -602
  330. package/src/learning/tests/test_learning_db_v28.py +0 -110
  331. package/src/learning/tests/test_learning_init_v28.py +0 -48
  332. package/src/learning/tests/test_outcome_signals.py +0 -48
  333. package/src/learning/tests/test_project_context.py +0 -292
  334. package/src/learning/tests/test_schema_migration.py +0 -319
  335. package/src/learning/tests/test_signal_inference.py +0 -397
  336. package/src/learning/tests/test_source_quality.py +0 -351
  337. package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
  338. package/src/learning/tests/test_workflow_miner.py +0 -318
  339. package/src/learning/workflow_pattern_miner.py +0 -655
  340. package/src/lifecycle/__init__.py +0 -54
  341. package/src/lifecycle/bounded_growth.py +0 -239
  342. package/src/lifecycle/compaction_engine.py +0 -226
  343. package/src/lifecycle/lifecycle_engine.py +0 -355
  344. package/src/lifecycle/lifecycle_evaluator.py +0 -257
  345. package/src/lifecycle/lifecycle_scheduler.py +0 -130
  346. package/src/lifecycle/retention_policy.py +0 -285
  347. package/src/lifecycle/tests/test_bounded_growth.py +0 -193
  348. package/src/lifecycle/tests/test_compaction.py +0 -179
  349. package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
  350. package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
  351. package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
  352. package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
  353. package/src/lifecycle/tests/test_mcp_compact.py +0 -149
  354. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
  355. package/src/lifecycle/tests/test_retention_policy.py +0 -162
  356. package/src/mcp_tools_v28.py +0 -281
  357. package/src/memory/__init__.py +0 -36
  358. package/src/memory/cli.py +0 -205
  359. package/src/memory/constants.py +0 -39
  360. package/src/memory/helpers.py +0 -28
  361. package/src/memory/schema.py +0 -166
  362. package/src/memory-profiles.py +0 -595
  363. package/src/memory-reset.py +0 -491
  364. package/src/memory_compression.py +0 -989
  365. package/src/memory_store_v2.py +0 -1155
  366. package/src/migrate_v1_to_v2.py +0 -629
  367. package/src/pattern_learner.py +0 -34
  368. package/src/patterns/__init__.py +0 -24
  369. package/src/patterns/analyzers.py +0 -251
  370. package/src/patterns/learner.py +0 -271
  371. package/src/patterns/scoring.py +0 -171
  372. package/src/patterns/store.py +0 -225
  373. package/src/patterns/terminology.py +0 -140
  374. package/src/provenance_tracker.py +0 -312
  375. package/src/qualixar_attribution.py +0 -139
  376. package/src/qualixar_watermark.py +0 -78
  377. package/src/query_optimizer.py +0 -511
  378. package/src/rate_limiter.py +0 -83
  379. package/src/search/__init__.py +0 -20
  380. package/src/search/cli.py +0 -77
  381. package/src/search/constants.py +0 -26
  382. package/src/search/engine.py +0 -241
  383. package/src/search/fusion.py +0 -122
  384. package/src/search/index_loader.py +0 -114
  385. package/src/search/methods.py +0 -162
  386. package/src/search_engine_v2.py +0 -401
  387. package/src/setup_validator.py +0 -482
  388. package/src/subscription_manager.py +0 -391
  389. package/src/tree/__init__.py +0 -59
  390. package/src/tree/builder.py +0 -185
  391. package/src/tree/nodes.py +0 -202
  392. package/src/tree/queries.py +0 -257
  393. package/src/tree/schema.py +0 -80
  394. package/src/tree_manager.py +0 -19
  395. package/src/trust/__init__.py +0 -45
  396. package/src/trust/constants.py +0 -66
  397. package/src/trust/queries.py +0 -157
  398. package/src/trust/schema.py +0 -95
  399. package/src/trust/scorer.py +0 -299
  400. package/src/trust/signals.py +0 -95
  401. package/src/trust_scorer.py +0 -44
  402. package/ui/app.js +0 -1588
  403. package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
  404. package/ui/js/graph-cytoscape.js +0 -1168
  405. package/ui/js/graph-d3-backup.js +0 -32
  406. package/ui/js/graph.js +0 -32
  407. package/ui_server.py +0 -286
  408. /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
  409. /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
  410. /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
  411. /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
  412. /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
  413. /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
  414. /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
  415. /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
  416. /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
  417. /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
  418. /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
  419. /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
  420. /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
  421. /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
  422. /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
  423. /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
  424. /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
  425. /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
  426. /package/{completions → ide/completions}/slm.bash +0 -0
  427. /package/{completions → ide/completions}/slm.zsh +0 -0
  428. /package/{configs → ide/configs}/cody-commands.json +0 -0
  429. /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
  430. /package/{install.ps1 → scripts/install.ps1} +0 -0
  431. /package/{install.sh → scripts/install.sh} +0 -0
@@ -0,0 +1,99 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """Rules engine for configurable auto-capture and auto-recall behavior."""
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import logging
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ DEFAULT_RULES = {
17
+ "auto_recall": {
18
+ "enabled": True,
19
+ "on_session_start": True,
20
+ "on_every_prompt": False,
21
+ "max_memories_injected": 10,
22
+ "relevance_threshold": 0.3,
23
+ },
24
+ "auto_capture": {
25
+ "enabled": True,
26
+ "capture_decisions": True,
27
+ "capture_bugs": True,
28
+ "capture_preferences": True,
29
+ "capture_session_summary": True,
30
+ "min_confidence": 0.5,
31
+ },
32
+ }
33
+
34
+
35
+ class RulesEngine:
36
+ """Manage configurable rules for auto-capture and auto-recall."""
37
+
38
+ def __init__(self, config: dict | None = None, config_path: Path | None = None):
39
+ if config:
40
+ self._rules = {**DEFAULT_RULES, **config}
41
+ elif config_path and config_path.exists():
42
+ data = json.loads(config_path.read_text())
43
+ self._rules = {**DEFAULT_RULES, **data.get("rules", {})}
44
+ else:
45
+ self._rules = dict(DEFAULT_RULES)
46
+
47
+ def should_capture(self, category: str, confidence: float) -> bool:
48
+ """Check if a category should be captured based on rules."""
49
+ capture_rules = self._rules.get("auto_capture", {})
50
+ if not capture_rules.get("enabled", True):
51
+ return False
52
+
53
+ category_key = f"capture_{category}s" if not category.endswith("s") else f"capture_{category}"
54
+ if not capture_rules.get(category_key, True):
55
+ return False
56
+
57
+ min_conf = capture_rules.get("min_confidence", 0.5)
58
+ return confidence >= min_conf
59
+
60
+ def should_recall(self, trigger: str) -> bool:
61
+ """Check if auto-recall should fire for a trigger."""
62
+ recall_rules = self._rules.get("auto_recall", {})
63
+ if not recall_rules.get("enabled", True):
64
+ return False
65
+
66
+ if trigger == "session_start":
67
+ return recall_rules.get("on_session_start", True)
68
+ if trigger == "every_prompt":
69
+ return recall_rules.get("on_every_prompt", False)
70
+
71
+ return True
72
+
73
+ def get_recall_config(self) -> dict:
74
+ """Get auto-recall configuration."""
75
+ return dict(self._rules.get("auto_recall", DEFAULT_RULES["auto_recall"]))
76
+
77
+ def get_capture_config(self) -> dict:
78
+ """Get auto-capture configuration."""
79
+ return dict(self._rules.get("auto_capture", DEFAULT_RULES["auto_capture"]))
80
+
81
+ def update_rule(self, section: str, key: str, value: Any) -> None:
82
+ """Update a specific rule."""
83
+ if section not in self._rules:
84
+ self._rules[section] = {}
85
+ self._rules[section][key] = value
86
+
87
+ def save(self, config_path: Path) -> None:
88
+ """Save rules to config file."""
89
+ if config_path.exists():
90
+ data = json.loads(config_path.read_text())
91
+ else:
92
+ data = {}
93
+ data["rules"] = self._rules
94
+ config_path.parent.mkdir(parents=True, exist_ok=True)
95
+ config_path.write_text(json.dumps(data, indent=2))
96
+
97
+ def to_dict(self) -> dict:
98
+ """Export rules as dict."""
99
+ return dict(self._rules)
@@ -0,0 +1,3 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
@@ -0,0 +1,82 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ """Opt-in API-key authentication middleware.
5
+
6
+ When ``~/.superlocalmemory/api_key`` exists, write endpoints require the
7
+ ``X-SLM-API-Key`` header. Read endpoints remain open for backward
8
+ compatibility. If the key file is absent auth is completely disabled --
9
+ all requests pass.
10
+
11
+ V3 change: base directory moved from ``~/.claude-memory/`` to
12
+ ``~/.superlocalmemory/``.
13
+ """
14
+
15
+ import hashlib
16
+ import logging
17
+ from pathlib import Path
18
+ from typing import Optional
19
+
20
+ logger = logging.getLogger("superlocalmemory.auth")
21
+
22
+ # V3 base directory
23
+ MEMORY_DIR = Path.home() / ".superlocalmemory"
24
+ API_KEY_FILE = MEMORY_DIR / "api_key"
25
+
26
+
27
+ def _load_api_key_hash(key_file: Optional[Path] = None) -> Optional[str]:
28
+ """Load and hash the API key from disk.
29
+
30
+ Args:
31
+ key_file: Override path (useful for testing).
32
+
33
+ Returns:
34
+ SHA-256 hex digest of the stored key, or ``None`` when auth is
35
+ not configured.
36
+ """
37
+ path = key_file or API_KEY_FILE
38
+ if not path.exists():
39
+ return None
40
+ try:
41
+ key = path.read_text().strip()
42
+ if not key:
43
+ return None
44
+ return hashlib.sha256(key.encode()).hexdigest()
45
+ except Exception as exc:
46
+ logger.warning("Failed to load API key: %s", exc)
47
+ return None
48
+
49
+
50
+ def check_api_key(
51
+ request_headers: dict,
52
+ is_write: bool = False,
53
+ key_file: Optional[Path] = None,
54
+ ) -> bool:
55
+ """Authorize a request against the stored API key.
56
+
57
+ Returns ``True`` when:
58
+ * No key file exists (auth not configured -- backward compatible).
59
+ * The request is a read operation (reads always allowed).
60
+ * The ``X-SLM-API-Key`` header matches the stored key.
61
+
62
+ Args:
63
+ request_headers: Mapping of HTTP header names to values.
64
+ is_write: ``True`` for mutating operations that require auth.
65
+ key_file: Override key-file path (testing).
66
+ """
67
+ key_hash = _load_api_key_hash(key_file)
68
+
69
+ # No key file = auth disabled
70
+ if key_hash is None:
71
+ return True
72
+
73
+ # Reads are always permitted
74
+ if not is_write:
75
+ return True
76
+
77
+ # Writes require a matching key
78
+ provided = request_headers.get("x-slm-api-key", "")
79
+ if not provided:
80
+ return False
81
+
82
+ return hashlib.sha256(provided.encode()).hexdigest() == key_hash
@@ -0,0 +1,317 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+ """Automated backup manager for SuperLocalMemory V3.
5
+
6
+ Provides:
7
+ * Configurable interval (daily / weekly)
8
+ * Timestamped SQLite-safe backups via the ``sqlite3.backup()`` API
9
+ * Retention policy (keeps last *N* backups)
10
+ * Restore with automatic pre-restore safety snapshot
11
+
12
+ V3 change: base directory is ``~/.superlocalmemory/`` (was ``~/.claude-memory/``).
13
+ """
14
+
15
+ import json
16
+ import logging
17
+ import sqlite3
18
+ from datetime import datetime, timedelta
19
+ from pathlib import Path
20
+ from typing import Dict, List, Optional
21
+
22
+ logger = logging.getLogger("superlocalmemory.backup")
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # V3 paths
26
+ # ---------------------------------------------------------------------------
27
+ MEMORY_DIR = Path.home() / ".superlocalmemory"
28
+ DB_PATH = MEMORY_DIR / "memory.db"
29
+ BACKUP_DIR = MEMORY_DIR / "backups"
30
+ CONFIG_FILE = MEMORY_DIR / "backup_config.json"
31
+
32
+ # Defaults
33
+ DEFAULT_INTERVAL_HOURS = 168 # 7 days
34
+ DEFAULT_MAX_BACKUPS = 10
35
+ MIN_INTERVAL_HOURS = 1
36
+
37
+
38
+ class BackupManager:
39
+ """Automated backup manager for SuperLocalMemory V3.
40
+
41
+ Args:
42
+ db_path: Path to the primary database file.
43
+ backup_dir: Directory where backup files are stored.
44
+ base_dir: Base SLM directory (used for config file + learning DB).
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ db_path: Optional[Path] = None,
50
+ backup_dir: Optional[Path] = None,
51
+ base_dir: Optional[Path] = None,
52
+ ) -> None:
53
+ self.base_dir = base_dir or MEMORY_DIR
54
+ self.db_path = db_path or (self.base_dir / "memory.db")
55
+ self.backup_dir = backup_dir or (self.base_dir / "backups")
56
+ self._config_file = self.base_dir / "backup_config.json"
57
+ self.config = self._load_config()
58
+ self._ensure_backup_dir()
59
+
60
+ # ------------------------------------------------------------------
61
+ # Config management
62
+ # ------------------------------------------------------------------
63
+
64
+ def _ensure_backup_dir(self) -> None:
65
+ self.backup_dir.mkdir(parents=True, exist_ok=True)
66
+
67
+ def _load_config(self) -> Dict:
68
+ if self._config_file.exists():
69
+ try:
70
+ raw = json.loads(self._config_file.read_text())
71
+ defaults = self._default_config()
72
+ for k in defaults:
73
+ raw.setdefault(k, defaults[k])
74
+ return raw
75
+ except (json.JSONDecodeError, IOError):
76
+ pass
77
+ return self._default_config()
78
+
79
+ @staticmethod
80
+ def _default_config() -> Dict:
81
+ return {
82
+ "enabled": True,
83
+ "interval_hours": DEFAULT_INTERVAL_HOURS,
84
+ "max_backups": DEFAULT_MAX_BACKUPS,
85
+ "last_backup": None,
86
+ "last_backup_file": None,
87
+ }
88
+
89
+ def _save_config(self) -> None:
90
+ try:
91
+ self._config_file.parent.mkdir(parents=True, exist_ok=True)
92
+ self._config_file.write_text(json.dumps(self.config, indent=2))
93
+ except IOError as exc:
94
+ logger.error("Failed to save backup config: %s", exc)
95
+
96
+ def configure(
97
+ self,
98
+ interval_hours: Optional[int] = None,
99
+ max_backups: Optional[int] = None,
100
+ enabled: Optional[bool] = None,
101
+ ) -> Dict:
102
+ """Update backup configuration and return current status."""
103
+ if interval_hours is not None:
104
+ self.config["interval_hours"] = max(MIN_INTERVAL_HOURS, interval_hours)
105
+ if max_backups is not None:
106
+ self.config["max_backups"] = max(1, max_backups)
107
+ if enabled is not None:
108
+ self.config["enabled"] = enabled
109
+ self._save_config()
110
+ return self.get_status()
111
+
112
+ # ------------------------------------------------------------------
113
+ # Scheduling helpers
114
+ # ------------------------------------------------------------------
115
+
116
+ def is_backup_due(self) -> bool:
117
+ """Return ``True`` when a backup should be taken."""
118
+ if not self.config.get("enabled", True):
119
+ return False
120
+ last = self.config.get("last_backup")
121
+ if not last:
122
+ return True
123
+ try:
124
+ last_dt = datetime.fromisoformat(last)
125
+ interval = timedelta(hours=self.config.get("interval_hours", DEFAULT_INTERVAL_HOURS))
126
+ return datetime.now() >= last_dt + interval
127
+ except (ValueError, TypeError):
128
+ return True
129
+
130
+ def check_and_backup(self) -> Optional[str]:
131
+ """Create a backup only when one is due. Returns filename or ``None``."""
132
+ if not self.is_backup_due():
133
+ return None
134
+ return self.create_backup()
135
+
136
+ # ------------------------------------------------------------------
137
+ # Core backup / restore
138
+ # ------------------------------------------------------------------
139
+
140
+ def create_backup(self, label: Optional[str] = None) -> str:
141
+ """Create a timestamped backup via the SQLite online-backup API.
142
+
143
+ Returns:
144
+ Backup filename on success, empty string on failure.
145
+ """
146
+ if not self.db_path.exists():
147
+ logger.warning("No database to backup at %s", self.db_path)
148
+ return ""
149
+
150
+ self._ensure_backup_dir()
151
+
152
+ timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
153
+ suffix = f"-{label}" if label else ""
154
+ backup_name = f"memory-{timestamp}{suffix}.db"
155
+ backup_path = self.backup_dir / backup_name
156
+
157
+ try:
158
+ source = sqlite3.connect(str(self.db_path))
159
+ dest = sqlite3.connect(str(backup_path))
160
+ try:
161
+ source.backup(dest)
162
+ finally:
163
+ dest.close()
164
+ source.close()
165
+
166
+ size_mb = backup_path.stat().st_size / (1024 * 1024)
167
+ self.config["last_backup"] = datetime.now().isoformat()
168
+ self.config["last_backup_file"] = backup_name
169
+ self._save_config()
170
+ logger.info("Backup created: %s (%.1f MB)", backup_name, size_mb)
171
+
172
+ # Also backup learning.db if present
173
+ self._backup_learning_db(timestamp, suffix)
174
+
175
+ self._enforce_retention()
176
+ return backup_name
177
+
178
+ except Exception as exc:
179
+ logger.error("Backup failed: %s", exc)
180
+ if backup_path.exists():
181
+ backup_path.unlink()
182
+ return ""
183
+
184
+ def _backup_learning_db(self, timestamp: str, suffix: str) -> None:
185
+ """Best-effort backup of ``learning.db`` alongside the main DB."""
186
+ learning_db = self.db_path.parent / "learning.db"
187
+ if not learning_db.exists():
188
+ return
189
+ try:
190
+ name = f"learning-{timestamp}{suffix}.db"
191
+ path = self.backup_dir / name
192
+ src = sqlite3.connect(str(learning_db))
193
+ dst = sqlite3.connect(str(path))
194
+ try:
195
+ src.backup(dst)
196
+ finally:
197
+ dst.close()
198
+ src.close()
199
+ logger.info("Learning backup: %s (%.1f MB)", name, path.stat().st_size / (1024 * 1024))
200
+ except Exception as exc:
201
+ logger.warning("Learning DB backup failed (non-critical): %s", exc)
202
+
203
+ def _enforce_retention(self) -> None:
204
+ """Remove old backups exceeding the configured max."""
205
+ max_backups = self.config.get("max_backups", DEFAULT_MAX_BACKUPS)
206
+ for pattern in ("memory-*.db", "learning-*.db"):
207
+ backups = sorted(
208
+ self.backup_dir.glob(pattern),
209
+ key=lambda f: f.stat().st_mtime,
210
+ )
211
+ while len(backups) > max_backups:
212
+ oldest = backups.pop(0)
213
+ try:
214
+ oldest.unlink()
215
+ logger.info("Removed old backup: %s", oldest.name)
216
+ except OSError as exc:
217
+ logger.error("Failed to remove backup %s: %s", oldest.name, exc)
218
+
219
+ def restore_backup(self, filename: str) -> bool:
220
+ """Restore the database from *filename*.
221
+
222
+ A safety snapshot of the current state is taken first.
223
+ """
224
+ backup_path = self.backup_dir / filename
225
+ if not backup_path.exists():
226
+ logger.error("Backup not found: %s", filename)
227
+ return False
228
+
229
+ try:
230
+ self.create_backup(label="pre-restore")
231
+
232
+ target = (
233
+ self.db_path.parent / "learning.db"
234
+ if filename.startswith("learning-")
235
+ else self.db_path
236
+ )
237
+
238
+ src = sqlite3.connect(str(backup_path))
239
+ dst = sqlite3.connect(str(target))
240
+ try:
241
+ src.backup(dst)
242
+ finally:
243
+ dst.close()
244
+ src.close()
245
+
246
+ logger.info("Restored: %s -> %s", filename, target.name)
247
+ return True
248
+
249
+ except Exception as exc:
250
+ logger.error("Restore failed: %s", exc)
251
+ return False
252
+
253
+ # ------------------------------------------------------------------
254
+ # Listing / status
255
+ # ------------------------------------------------------------------
256
+
257
+ def list_backups(self) -> List[Dict]:
258
+ """Return metadata for all available backups (newest first)."""
259
+ if not self.backup_dir.exists():
260
+ return []
261
+
262
+ result: List[Dict] = []
263
+ for pattern in ("memory-*.db", "learning-*.db"):
264
+ for f in sorted(self.backup_dir.glob(pattern), key=lambda p: p.stat().st_mtime, reverse=True):
265
+ st = f.stat()
266
+ db_type = "learning" if f.name.startswith("learning-") else "memory"
267
+ result.append({
268
+ "filename": f.name,
269
+ "path": str(f),
270
+ "size_mb": round(st.st_size / (1024 * 1024), 2),
271
+ "created": datetime.fromtimestamp(st.st_mtime).isoformat(),
272
+ "age_hours": round(
273
+ (datetime.now() - datetime.fromtimestamp(st.st_mtime)).total_seconds() / 3600, 1
274
+ ),
275
+ "type": db_type,
276
+ })
277
+ result.sort(key=lambda b: b["created"], reverse=True)
278
+ return result
279
+
280
+ def get_status(self) -> Dict:
281
+ """Return a status summary of the backup system."""
282
+ backups = self.list_backups()
283
+ next_backup = None
284
+
285
+ if self.config.get("enabled") and self.config.get("last_backup"):
286
+ try:
287
+ last_dt = datetime.fromisoformat(self.config["last_backup"])
288
+ interval = timedelta(hours=self.config.get("interval_hours", DEFAULT_INTERVAL_HOURS))
289
+ nxt = last_dt + interval
290
+ next_backup = nxt.isoformat() if nxt > datetime.now() else "overdue"
291
+ except (ValueError, TypeError):
292
+ next_backup = "unknown"
293
+
294
+ hours = self.config.get("interval_hours", DEFAULT_INTERVAL_HOURS)
295
+ if hours >= 168:
296
+ display = f"{hours // 168} week(s)"
297
+ elif hours >= 24:
298
+ display = f"{hours // 24} day(s)"
299
+ else:
300
+ display = f"{hours} hour(s)"
301
+
302
+ mem_bk = [b for b in backups if b.get("type") == "memory"]
303
+ learn_bk = [b for b in backups if b.get("type") == "learning"]
304
+
305
+ return {
306
+ "enabled": self.config.get("enabled", True),
307
+ "interval_hours": hours,
308
+ "interval_display": display,
309
+ "max_backups": self.config.get("max_backups", DEFAULT_MAX_BACKUPS),
310
+ "last_backup": self.config.get("last_backup"),
311
+ "last_backup_file": self.config.get("last_backup_file"),
312
+ "next_backup": next_backup,
313
+ "backup_count": len(mem_bk),
314
+ "learning_backup_count": len(learn_bk),
315
+ "total_size_mb": round(sum(b["size_mb"] for b in backups), 2),
316
+ "backups": backups,
317
+ }