superlocalmemory 2.8.6 → 3.0.0

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 +1 -1
  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
@@ -1,397 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """SuperLocalMemory V2 - Signal Inference Engine Tests (v2.7.4)
5
-
6
- Tests for the implicit feedback signal inference system.
7
- """
8
- import time
9
- import threading
10
- import pytest
11
- import sys
12
- from pathlib import Path
13
-
14
- # Ensure mcp_server module is importable for RecallBuffer
15
- sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
16
-
17
-
18
- class TestRecallBuffer:
19
- """Test the _RecallBuffer class from mcp_server."""
20
-
21
- def _make_buffer(self):
22
- """Create a fresh RecallBuffer for testing."""
23
- # Import directly to avoid starting MCP server
24
- from importlib import import_module
25
- import types
26
-
27
- # Create a minimal RecallBuffer instance by duplicating the class logic
28
- # without importing the full mcp_server (which requires MCP deps)
29
- sys.path.insert(0, str(Path(__file__).parent.parent.parent))
30
-
31
- class RecallBuffer:
32
- def __init__(self):
33
- self._lock = threading.Lock()
34
- self._last_recall = {}
35
- self._global_last = None
36
- self._signal_timestamps = {}
37
- self._recent_result_ids = set()
38
- self._recall_count = 0
39
- self._positive_threshold = 300.0
40
- self._inter_recall_times = []
41
-
42
- def record_recall(self, query, result_ids, agent_id="mcp-client"):
43
- now = time.time()
44
- signals = []
45
- with self._lock:
46
- self._recall_count += 1
47
- result_id_set = set(result_ids)
48
- self._recent_result_ids = result_id_set
49
- current = {
50
- "query": query, "result_ids": result_ids,
51
- "result_id_set": result_id_set, "timestamp": now,
52
- "agent_id": agent_id,
53
- }
54
- prev = self._last_recall.get(agent_id)
55
- if prev:
56
- time_gap = now - prev["timestamp"]
57
- self._inter_recall_times.append(time_gap)
58
- if len(self._inter_recall_times) > 100:
59
- self._inter_recall_times = self._inter_recall_times[-100:]
60
- if len(self._inter_recall_times) >= 10:
61
- sorted_times = sorted(self._inter_recall_times)
62
- median = sorted_times[len(sorted_times) // 2]
63
- self._positive_threshold = max(60.0, min(median * 0.8, 1800.0))
64
- if time_gap < 30.0 and query != prev["query"]:
65
- for mid in prev["result_ids"][:5]:
66
- signals.append({
67
- "memory_id": mid,
68
- "signal_type": "implicit_negative_requick",
69
- "query": prev["query"],
70
- "rank_position": prev["result_ids"].index(mid) + 1,
71
- })
72
- elif time_gap > self._positive_threshold:
73
- for mid in prev["result_ids"][:3]:
74
- signals.append({
75
- "memory_id": mid,
76
- "signal_type": "implicit_positive_timegap",
77
- "query": prev["query"],
78
- "rank_position": prev["result_ids"].index(mid) + 1,
79
- })
80
- overlap = result_id_set & prev["result_id_set"]
81
- for mid in overlap:
82
- signals.append({
83
- "memory_id": mid,
84
- "signal_type": "implicit_positive_reaccess",
85
- "query": query,
86
- })
87
- global_prev = self._global_last
88
- if global_prev and global_prev["agent_id"] != agent_id:
89
- cross_overlap = result_id_set & global_prev["result_id_set"]
90
- for mid in cross_overlap:
91
- signals.append({
92
- "memory_id": mid,
93
- "signal_type": "implicit_positive_cross_tool",
94
- "query": query,
95
- })
96
- self._last_recall[agent_id] = current
97
- self._global_last = current
98
- return signals
99
-
100
- def check_post_action(self, memory_id, action):
101
- with self._lock:
102
- if memory_id not in self._recent_result_ids:
103
- return None
104
- if action == "update":
105
- return {"memory_id": memory_id, "signal_type": "implicit_positive_post_update",
106
- "query": self._global_last["query"] if self._global_last else ""}
107
- elif action == "delete":
108
- return {"memory_id": memory_id, "signal_type": "implicit_negative_post_delete",
109
- "query": self._global_last["query"] if self._global_last else ""}
110
- return None
111
-
112
- def check_rate_limit(self, agent_id, max_per_minute=5):
113
- now = time.time()
114
- with self._lock:
115
- if agent_id not in self._signal_timestamps:
116
- self._signal_timestamps[agent_id] = []
117
- self._signal_timestamps[agent_id] = [
118
- ts for ts in self._signal_timestamps[agent_id] if now - ts < 60.0
119
- ]
120
- if len(self._signal_timestamps[agent_id]) >= max_per_minute:
121
- return False
122
- self._signal_timestamps[agent_id].append(now)
123
- return True
124
-
125
- def get_recall_count(self):
126
- with self._lock:
127
- return self._recall_count
128
-
129
- def get_stats(self):
130
- with self._lock:
131
- return {
132
- "recall_count": self._recall_count,
133
- "tracked_agents": len(self._last_recall),
134
- "positive_threshold_s": round(self._positive_threshold, 1),
135
- "recent_results_count": len(self._recent_result_ids),
136
- }
137
-
138
- return RecallBuffer()
139
-
140
- def test_first_recall_no_signals(self):
141
- """First recall should produce no signals (nothing to compare with)."""
142
- buf = self._make_buffer()
143
- signals = buf.record_recall("test query", [1, 2, 3])
144
- assert signals == []
145
- assert buf.get_recall_count() == 1
146
-
147
- def test_quick_requery_negative_signals(self):
148
- """Quick re-query with different query should produce negative signals."""
149
- buf = self._make_buffer()
150
- buf.record_recall("first query", [10, 20, 30])
151
- # Simulate quick re-query (no sleep needed — time gap is ~0)
152
- signals = buf.record_recall("different query", [40, 50])
153
- negative_signals = [s for s in signals if s["signal_type"] == "implicit_negative_requick"]
154
- assert len(negative_signals) > 0
155
- # Should target previous results (10, 20, 30)
156
- neg_ids = {s["memory_id"] for s in negative_signals}
157
- assert neg_ids.issubset({10, 20, 30})
158
-
159
- def test_same_query_no_negative(self):
160
- """Same exact query repeated quickly should NOT produce negative signals."""
161
- buf = self._make_buffer()
162
- buf.record_recall("same query", [10, 20])
163
- signals = buf.record_recall("same query", [10, 20])
164
- negative_signals = [s for s in signals if s["signal_type"] == "implicit_negative_requick"]
165
- assert len(negative_signals) == 0
166
-
167
- def test_reaccess_positive_signals(self):
168
- """Same memory appearing in consecutive recalls = positive."""
169
- buf = self._make_buffer()
170
- buf.record_recall("query a", [10, 20, 30])
171
- signals = buf.record_recall("query b", [20, 40, 50])
172
- reaccess = [s for s in signals if s["signal_type"] == "implicit_positive_reaccess"]
173
- assert len(reaccess) == 1
174
- assert reaccess[0]["memory_id"] == 20
175
-
176
- def test_cross_tool_positive_signals(self):
177
- """Same memory recalled by different agents = cross-tool positive."""
178
- buf = self._make_buffer()
179
- buf.record_recall("query", [10, 20], agent_id="claude")
180
- signals = buf.record_recall("query", [20, 30], agent_id="cursor")
181
- cross_tool = [s for s in signals if s["signal_type"] == "implicit_positive_cross_tool"]
182
- assert len(cross_tool) == 1
183
- assert cross_tool[0]["memory_id"] == 20
184
-
185
- def test_post_action_update_tracked(self):
186
- """Update after recall should generate positive signal."""
187
- buf = self._make_buffer()
188
- buf.record_recall("query", [10, 20, 30])
189
- signal = buf.check_post_action(20, "update")
190
- assert signal is not None
191
- assert signal["signal_type"] == "implicit_positive_post_update"
192
- assert signal["memory_id"] == 20
193
-
194
- def test_post_action_delete_tracked(self):
195
- """Delete after recall should generate negative signal."""
196
- buf = self._make_buffer()
197
- buf.record_recall("query", [10, 20, 30])
198
- signal = buf.check_post_action(10, "delete")
199
- assert signal is not None
200
- assert signal["signal_type"] == "implicit_negative_post_delete"
201
-
202
- def test_post_action_unrelated_memory_ignored(self):
203
- """Action on memory NOT in recent results should be ignored."""
204
- buf = self._make_buffer()
205
- buf.record_recall("query", [10, 20, 30])
206
- signal = buf.check_post_action(999, "update")
207
- assert signal is None
208
-
209
- def test_rate_limiting(self):
210
- """Rate limiter should cap signals per agent per minute."""
211
- buf = self._make_buffer()
212
- agent = "test-agent"
213
- # First 5 should be allowed
214
- for i in range(5):
215
- assert buf.check_rate_limit(agent) is True
216
- # 6th should be blocked
217
- assert buf.check_rate_limit(agent) is False
218
-
219
- def test_rate_limiting_different_agents(self):
220
- """Different agents should have independent rate limits."""
221
- buf = self._make_buffer()
222
- for i in range(5):
223
- assert buf.check_rate_limit("agent1") is True
224
- assert buf.check_rate_limit("agent1") is False
225
- # Agent2 should still be allowed
226
- assert buf.check_rate_limit("agent2") is True
227
-
228
- def test_recall_count_increments(self):
229
- """Recall count should increment with each recall."""
230
- buf = self._make_buffer()
231
- assert buf.get_recall_count() == 0
232
- buf.record_recall("q1", [1])
233
- assert buf.get_recall_count() == 1
234
- buf.record_recall("q2", [2])
235
- assert buf.get_recall_count() == 2
236
-
237
- def test_negative_signals_cap_at_5(self):
238
- """Negative signals should only target top 5 results."""
239
- buf = self._make_buffer()
240
- buf.record_recall("first", list(range(1, 11))) # 10 results
241
- signals = buf.record_recall("different", [99])
242
- negative = [s for s in signals if s["signal_type"] == "implicit_negative_requick"]
243
- assert len(negative) <= 5
244
-
245
- def test_stats_output(self):
246
- """Stats should report correct values."""
247
- buf = self._make_buffer()
248
- buf.record_recall("q", [1, 2, 3])
249
- stats = buf.get_stats()
250
- assert stats["recall_count"] == 1
251
- assert stats["tracked_agents"] == 1
252
- assert stats["recent_results_count"] == 3
253
- assert stats["positive_threshold_s"] == 300.0
254
-
255
- def test_thread_safety(self):
256
- """Buffer should handle concurrent access without errors."""
257
- buf = self._make_buffer()
258
- errors = []
259
-
260
- def worker(agent_id):
261
- try:
262
- for i in range(20):
263
- buf.record_recall(f"query_{i}", [i, i+1], agent_id=agent_id)
264
- buf.check_rate_limit(agent_id)
265
- except Exception as e:
266
- errors.append(e)
267
-
268
- threads = [threading.Thread(target=worker, args=(f"agent_{i}",)) for i in range(5)]
269
- for t in threads:
270
- t.start()
271
- for t in threads:
272
- t.join(timeout=10)
273
-
274
- assert errors == [], f"Thread safety errors: {errors}"
275
- assert buf.get_recall_count() == 100 # 5 agents x 20 recalls
276
-
277
-
278
- class TestFeedbackCollectorImplicit:
279
- """Test the new implicit signal methods in FeedbackCollector."""
280
-
281
- def test_record_implicit_signal_valid(self):
282
- """Valid implicit signal should be stored."""
283
- sys.path.insert(0, str(Path(__file__).parent.parent))
284
- from feedback_collector import FeedbackCollector
285
- fc = FeedbackCollector()
286
- result = fc.record_implicit_signal(
287
- memory_id=42,
288
- query="test query",
289
- signal_type="implicit_positive_timegap",
290
- )
291
- # Should return row ID or None (depends on DB availability)
292
- # Just verify it doesn't crash
293
- assert result is None or isinstance(result, int)
294
-
295
- def test_record_implicit_signal_invalid_type(self):
296
- """Invalid signal type should return None."""
297
- sys.path.insert(0, str(Path(__file__).parent.parent))
298
- from feedback_collector import FeedbackCollector
299
- fc = FeedbackCollector()
300
- result = fc.record_implicit_signal(
301
- memory_id=42,
302
- query="test",
303
- signal_type="totally_fake_type",
304
- )
305
- assert result is None
306
-
307
- def test_record_dashboard_feedback_valid(self):
308
- """Valid dashboard feedback should be stored."""
309
- sys.path.insert(0, str(Path(__file__).parent.parent))
310
- from feedback_collector import FeedbackCollector
311
- fc = FeedbackCollector()
312
- result = fc.record_dashboard_feedback(
313
- memory_id=42,
314
- query="test query",
315
- feedback_type="thumbs_up",
316
- )
317
- assert result is None or isinstance(result, int)
318
-
319
- def test_record_dashboard_feedback_invalid_type(self):
320
- """Invalid feedback type should return None."""
321
- sys.path.insert(0, str(Path(__file__).parent.parent))
322
- from feedback_collector import FeedbackCollector
323
- fc = FeedbackCollector()
324
- result = fc.record_dashboard_feedback(
325
- memory_id=42,
326
- query="test",
327
- feedback_type="invalid_type",
328
- )
329
- assert result is None
330
-
331
- def test_signal_values_complete(self):
332
- """All declared signal types should have numeric values."""
333
- sys.path.insert(0, str(Path(__file__).parent.parent))
334
- from feedback_collector import FeedbackCollector
335
- fc = FeedbackCollector()
336
- for signal_type, value in fc.SIGNAL_VALUES.items():
337
- assert isinstance(value, (int, float)), f"{signal_type} has non-numeric value"
338
- assert 0.0 <= value <= 1.0, f"{signal_type} value {value} out of range"
339
-
340
-
341
- class TestFeatureExpansion:
342
- """Test the 10→12→20 feature vector expansion."""
343
-
344
- def test_feature_count_is_20(self):
345
- """Feature vector should have 20 dimensions (v2.8)."""
346
- sys.path.insert(0, str(Path(__file__).parent.parent))
347
- from feature_extractor import FEATURE_NAMES, NUM_FEATURES
348
- assert NUM_FEATURES == 20
349
- assert len(FEATURE_NAMES) == 20
350
-
351
- def test_new_features_present(self):
352
- """signal_count and avg_signal_value should be in feature names."""
353
- sys.path.insert(0, str(Path(__file__).parent.parent))
354
- from feature_extractor import FEATURE_NAMES
355
- assert 'signal_count' in FEATURE_NAMES
356
- assert 'avg_signal_value' in FEATURE_NAMES
357
- assert FEATURE_NAMES.index('signal_count') == 10
358
- assert FEATURE_NAMES.index('avg_signal_value') == 11
359
-
360
- def test_extract_features_returns_20(self):
361
- """Extract should return 20-element vector (v2.8)."""
362
- sys.path.insert(0, str(Path(__file__).parent.parent))
363
- from feature_extractor import FeatureExtractor
364
- fe = FeatureExtractor()
365
- features = fe.extract_features(
366
- {'id': 1, 'content': 'test', 'importance': 5},
367
- 'test'
368
- )
369
- assert len(features) == 20
370
-
371
- def test_signal_features_with_stats(self):
372
- """Signal features should use provided stats."""
373
- sys.path.insert(0, str(Path(__file__).parent.parent))
374
- from feature_extractor import FeatureExtractor
375
- fe = FeatureExtractor()
376
- fe.set_context(signal_stats={
377
- '42': {'count': 8, 'avg_value': 0.9},
378
- })
379
- features = fe.extract_features(
380
- {'id': 42, 'content': 'test', 'importance': 5},
381
- 'test'
382
- )
383
- assert features[10] == 0.8 # count=8, 8/10=0.8
384
- assert features[11] == 0.9 # avg_value=0.9
385
-
386
- def test_signal_features_without_stats(self):
387
- """Signal features should default safely without stats."""
388
- sys.path.insert(0, str(Path(__file__).parent.parent))
389
- from feature_extractor import FeatureExtractor
390
- fe = FeatureExtractor()
391
- # No set_context call — signal_stats empty
392
- features = fe.extract_features(
393
- {'id': 99, 'content': 'test', 'importance': 5},
394
- 'test'
395
- )
396
- assert features[10] == 0.0 # No stats → 0.0
397
- assert features[11] == 0.5 # No stats → neutral 0.5