superlocalmemory 2.8.5 → 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 (434) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +9 -1
  3. package/NOTICE +63 -0
  4. package/README.md +165 -480
  5. package/bin/slm +17 -449
  6. package/bin/slm-npm +2 -2
  7. package/bin/slm.bat +4 -2
  8. package/conftest.py +5 -0
  9. package/docs/api-reference.md +284 -0
  10. package/docs/architecture.md +149 -0
  11. package/docs/auto-memory.md +150 -0
  12. package/docs/cli-reference.md +276 -0
  13. package/docs/compliance.md +191 -0
  14. package/docs/configuration.md +182 -0
  15. package/docs/getting-started.md +102 -0
  16. package/docs/ide-setup.md +261 -0
  17. package/docs/mcp-tools.md +220 -0
  18. package/docs/migration-from-v2.md +170 -0
  19. package/docs/profiles.md +173 -0
  20. package/docs/troubleshooting.md +310 -0
  21. package/{configs → ide/configs}/antigravity-mcp.json +3 -3
  22. package/ide/configs/chatgpt-desktop-mcp.json +16 -0
  23. package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
  24. package/{configs → ide/configs}/codex-mcp.toml +4 -4
  25. package/{configs → ide/configs}/continue-mcp.yaml +4 -3
  26. package/{configs → ide/configs}/continue-skills.yaml +6 -6
  27. package/ide/configs/cursor-mcp.json +15 -0
  28. package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
  29. package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
  30. package/{configs → ide/configs}/opencode-mcp.json +2 -2
  31. package/{configs → ide/configs}/perplexity-mcp.json +2 -2
  32. package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
  33. package/{configs → ide/configs}/windsurf-mcp.json +3 -3
  34. package/{configs → ide/configs}/zed-mcp.json +2 -2
  35. package/{hooks → ide/hooks}/context-hook.js +9 -20
  36. package/ide/hooks/memory-list-skill.js +70 -0
  37. package/ide/hooks/memory-profile-skill.js +101 -0
  38. package/ide/hooks/memory-recall-skill.js +62 -0
  39. package/ide/hooks/memory-remember-skill.js +68 -0
  40. package/ide/hooks/memory-reset-skill.js +160 -0
  41. package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
  42. package/ide/integrations/langchain/README.md +106 -0
  43. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
  44. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
  45. package/ide/integrations/langchain/pyproject.toml +38 -0
  46. package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
  47. package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
  48. package/ide/integrations/langchain/tests/test_security.py +117 -0
  49. package/ide/integrations/llamaindex/README.md +81 -0
  50. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
  51. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
  52. package/ide/integrations/llamaindex/pyproject.toml +43 -0
  53. package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
  54. package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
  55. package/ide/integrations/llamaindex/tests/test_security.py +241 -0
  56. package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
  57. package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
  58. package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
  59. package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
  60. package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
  61. package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
  62. package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
  63. package/package.json +13 -22
  64. package/pyproject.toml +85 -0
  65. package/scripts/build-dmg.sh +417 -0
  66. package/scripts/install-skills.ps1 +334 -0
  67. package/{install.ps1 → scripts/install.ps1} +36 -4
  68. package/{install.sh → scripts/install.sh} +14 -13
  69. package/scripts/postinstall.js +2 -2
  70. package/scripts/start-dashboard.ps1 +52 -0
  71. package/scripts/start-dashboard.sh +41 -0
  72. package/scripts/sync-wiki.ps1 +127 -0
  73. package/scripts/sync-wiki.sh +82 -0
  74. package/scripts/test-dmg.sh +161 -0
  75. package/scripts/test-npm-package.ps1 +252 -0
  76. package/scripts/test-npm-package.sh +207 -0
  77. package/scripts/verify-install.ps1 +294 -0
  78. package/scripts/verify-install.sh +266 -0
  79. package/src/superlocalmemory/__init__.py +0 -0
  80. package/src/superlocalmemory/attribution/__init__.py +9 -0
  81. package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
  82. package/src/superlocalmemory/attribution/signer.py +153 -0
  83. package/src/superlocalmemory/attribution/watermark.py +189 -0
  84. package/src/superlocalmemory/cli/__init__.py +5 -0
  85. package/src/superlocalmemory/cli/commands.py +245 -0
  86. package/src/superlocalmemory/cli/main.py +89 -0
  87. package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
  88. package/src/superlocalmemory/cli/post_install.py +99 -0
  89. package/src/superlocalmemory/cli/setup_wizard.py +129 -0
  90. package/src/superlocalmemory/compliance/__init__.py +0 -0
  91. package/src/superlocalmemory/compliance/abac.py +204 -0
  92. package/src/superlocalmemory/compliance/audit.py +314 -0
  93. package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
  94. package/src/superlocalmemory/compliance/gdpr.py +294 -0
  95. package/src/superlocalmemory/compliance/lifecycle.py +158 -0
  96. package/src/superlocalmemory/compliance/retention.py +232 -0
  97. package/src/superlocalmemory/compliance/scheduler.py +148 -0
  98. package/src/superlocalmemory/core/__init__.py +0 -0
  99. package/src/superlocalmemory/core/config.py +391 -0
  100. package/src/superlocalmemory/core/embeddings.py +293 -0
  101. package/src/superlocalmemory/core/engine.py +701 -0
  102. package/src/superlocalmemory/core/hooks.py +65 -0
  103. package/src/superlocalmemory/core/maintenance.py +172 -0
  104. package/src/superlocalmemory/core/modes.py +140 -0
  105. package/src/superlocalmemory/core/profiles.py +234 -0
  106. package/src/superlocalmemory/core/registry.py +117 -0
  107. package/src/superlocalmemory/dynamics/__init__.py +0 -0
  108. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
  109. package/src/superlocalmemory/encoding/__init__.py +0 -0
  110. package/src/superlocalmemory/encoding/consolidator.py +485 -0
  111. package/src/superlocalmemory/encoding/emotional.py +125 -0
  112. package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
  113. package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
  114. package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
  115. package/src/superlocalmemory/encoding/foresight.py +91 -0
  116. package/src/superlocalmemory/encoding/graph_builder.py +302 -0
  117. package/src/superlocalmemory/encoding/observation_builder.py +160 -0
  118. package/src/superlocalmemory/encoding/scene_builder.py +183 -0
  119. package/src/superlocalmemory/encoding/signal_inference.py +90 -0
  120. package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
  121. package/src/superlocalmemory/encoding/type_router.py +235 -0
  122. package/src/superlocalmemory/hooks/__init__.py +3 -0
  123. package/src/superlocalmemory/hooks/auto_capture.py +111 -0
  124. package/src/superlocalmemory/hooks/auto_recall.py +93 -0
  125. package/src/superlocalmemory/hooks/ide_connector.py +204 -0
  126. package/src/superlocalmemory/hooks/rules_engine.py +99 -0
  127. package/src/superlocalmemory/infra/__init__.py +3 -0
  128. package/src/superlocalmemory/infra/auth_middleware.py +82 -0
  129. package/src/superlocalmemory/infra/backup.py +317 -0
  130. package/src/superlocalmemory/infra/cache_manager.py +267 -0
  131. package/src/superlocalmemory/infra/event_bus.py +381 -0
  132. package/src/superlocalmemory/infra/rate_limiter.py +135 -0
  133. package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
  134. package/src/superlocalmemory/learning/__init__.py +0 -0
  135. package/src/superlocalmemory/learning/adaptive.py +172 -0
  136. package/src/superlocalmemory/learning/behavioral.py +490 -0
  137. package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
  138. package/src/superlocalmemory/learning/bootstrap.py +298 -0
  139. package/src/superlocalmemory/learning/cross_project.py +399 -0
  140. package/src/superlocalmemory/learning/database.py +376 -0
  141. package/src/superlocalmemory/learning/engagement.py +323 -0
  142. package/src/superlocalmemory/learning/features.py +138 -0
  143. package/src/superlocalmemory/learning/feedback.py +316 -0
  144. package/src/superlocalmemory/learning/outcomes.py +255 -0
  145. package/src/superlocalmemory/learning/project_context.py +366 -0
  146. package/src/superlocalmemory/learning/ranker.py +155 -0
  147. package/src/superlocalmemory/learning/source_quality.py +303 -0
  148. package/src/superlocalmemory/learning/workflows.py +309 -0
  149. package/src/superlocalmemory/llm/__init__.py +0 -0
  150. package/src/superlocalmemory/llm/backbone.py +316 -0
  151. package/src/superlocalmemory/math/__init__.py +0 -0
  152. package/src/superlocalmemory/math/fisher.py +356 -0
  153. package/src/superlocalmemory/math/langevin.py +398 -0
  154. package/src/superlocalmemory/math/sheaf.py +257 -0
  155. package/src/superlocalmemory/mcp/__init__.py +0 -0
  156. package/src/superlocalmemory/mcp/resources.py +245 -0
  157. package/src/superlocalmemory/mcp/server.py +61 -0
  158. package/src/superlocalmemory/mcp/tools.py +18 -0
  159. package/src/superlocalmemory/mcp/tools_core.py +305 -0
  160. package/src/superlocalmemory/mcp/tools_v28.py +223 -0
  161. package/src/superlocalmemory/mcp/tools_v3.py +286 -0
  162. package/src/superlocalmemory/retrieval/__init__.py +0 -0
  163. package/src/superlocalmemory/retrieval/agentic.py +295 -0
  164. package/src/superlocalmemory/retrieval/ann_index.py +223 -0
  165. package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
  166. package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
  167. package/src/superlocalmemory/retrieval/engine.py +390 -0
  168. package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
  169. package/src/superlocalmemory/retrieval/fusion.py +78 -0
  170. package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
  171. package/src/superlocalmemory/retrieval/reranker.py +154 -0
  172. package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
  173. package/src/superlocalmemory/retrieval/strategy.py +96 -0
  174. package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
  175. package/src/superlocalmemory/server/__init__.py +1 -0
  176. package/src/superlocalmemory/server/api.py +248 -0
  177. package/src/superlocalmemory/server/routes/__init__.py +4 -0
  178. package/src/superlocalmemory/server/routes/agents.py +107 -0
  179. package/src/superlocalmemory/server/routes/backup.py +91 -0
  180. package/src/superlocalmemory/server/routes/behavioral.py +127 -0
  181. package/src/superlocalmemory/server/routes/compliance.py +160 -0
  182. package/src/superlocalmemory/server/routes/data_io.py +188 -0
  183. package/src/superlocalmemory/server/routes/events.py +183 -0
  184. package/src/superlocalmemory/server/routes/helpers.py +85 -0
  185. package/src/superlocalmemory/server/routes/learning.py +273 -0
  186. package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
  187. package/src/superlocalmemory/server/routes/memories.py +399 -0
  188. package/src/superlocalmemory/server/routes/profiles.py +219 -0
  189. package/src/superlocalmemory/server/routes/stats.py +346 -0
  190. package/src/superlocalmemory/server/routes/v3_api.py +365 -0
  191. package/src/superlocalmemory/server/routes/ws.py +82 -0
  192. package/src/superlocalmemory/server/security_middleware.py +57 -0
  193. package/src/superlocalmemory/server/ui.py +245 -0
  194. package/src/superlocalmemory/storage/__init__.py +0 -0
  195. package/src/superlocalmemory/storage/access_control.py +182 -0
  196. package/src/superlocalmemory/storage/database.py +594 -0
  197. package/src/superlocalmemory/storage/migrations.py +303 -0
  198. package/src/superlocalmemory/storage/models.py +406 -0
  199. package/src/superlocalmemory/storage/schema.py +726 -0
  200. package/src/superlocalmemory/storage/v2_migrator.py +317 -0
  201. package/src/superlocalmemory/trust/__init__.py +0 -0
  202. package/src/superlocalmemory/trust/gate.py +130 -0
  203. package/src/superlocalmemory/trust/provenance.py +124 -0
  204. package/src/superlocalmemory/trust/scorer.py +347 -0
  205. package/src/superlocalmemory/trust/signals.py +153 -0
  206. package/ui/index.html +278 -5
  207. package/ui/js/auto-settings.js +70 -0
  208. package/ui/js/dashboard.js +90 -0
  209. package/ui/js/fact-detail.js +92 -0
  210. package/ui/js/feedback.js +2 -2
  211. package/ui/js/ide-status.js +102 -0
  212. package/ui/js/math-health.js +98 -0
  213. package/ui/js/recall-lab.js +127 -0
  214. package/ui/js/settings.js +2 -2
  215. package/ui/js/trust-dashboard.js +73 -0
  216. package/api_server.py +0 -724
  217. package/bin/aider-smart +0 -72
  218. package/bin/superlocalmemoryv2-learning +0 -4
  219. package/bin/superlocalmemoryv2-list +0 -3
  220. package/bin/superlocalmemoryv2-patterns +0 -4
  221. package/bin/superlocalmemoryv2-profile +0 -3
  222. package/bin/superlocalmemoryv2-recall +0 -3
  223. package/bin/superlocalmemoryv2-remember +0 -3
  224. package/bin/superlocalmemoryv2-reset +0 -3
  225. package/bin/superlocalmemoryv2-status +0 -3
  226. package/configs/chatgpt-desktop-mcp.json +0 -16
  227. package/configs/cursor-mcp.json +0 -15
  228. package/docs/SECURITY-QUICK-REFERENCE.md +0 -214
  229. package/hooks/memory-list-skill.js +0 -139
  230. package/hooks/memory-profile-skill.js +0 -273
  231. package/hooks/memory-recall-skill.js +0 -114
  232. package/hooks/memory-remember-skill.js +0 -127
  233. package/hooks/memory-reset-skill.js +0 -274
  234. package/mcp_server.py +0 -1800
  235. package/requirements-core.txt +0 -22
  236. package/requirements-learning.txt +0 -12
  237. package/requirements.txt +0 -12
  238. package/src/agent_registry.py +0 -411
  239. package/src/auth_middleware.py +0 -61
  240. package/src/auto_backup.py +0 -459
  241. package/src/behavioral/__init__.py +0 -49
  242. package/src/behavioral/behavioral_listener.py +0 -203
  243. package/src/behavioral/behavioral_patterns.py +0 -275
  244. package/src/behavioral/cross_project_transfer.py +0 -206
  245. package/src/behavioral/outcome_inference.py +0 -194
  246. package/src/behavioral/outcome_tracker.py +0 -193
  247. package/src/behavioral/tests/__init__.py +0 -4
  248. package/src/behavioral/tests/test_behavioral_integration.py +0 -108
  249. package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
  250. package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
  251. package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
  252. package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
  253. package/src/behavioral/tests/test_outcome_inference.py +0 -107
  254. package/src/behavioral/tests/test_outcome_tracker.py +0 -96
  255. package/src/cache_manager.py +0 -518
  256. package/src/compliance/__init__.py +0 -48
  257. package/src/compliance/abac_engine.py +0 -149
  258. package/src/compliance/abac_middleware.py +0 -116
  259. package/src/compliance/audit_db.py +0 -215
  260. package/src/compliance/audit_logger.py +0 -148
  261. package/src/compliance/retention_manager.py +0 -289
  262. package/src/compliance/retention_scheduler.py +0 -186
  263. package/src/compliance/tests/__init__.py +0 -4
  264. package/src/compliance/tests/test_abac_enforcement.py +0 -95
  265. package/src/compliance/tests/test_abac_engine.py +0 -124
  266. package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
  267. package/src/compliance/tests/test_audit_db.py +0 -123
  268. package/src/compliance/tests/test_audit_logger.py +0 -98
  269. package/src/compliance/tests/test_mcp_audit.py +0 -128
  270. package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
  271. package/src/compliance/tests/test_retention_manager.py +0 -131
  272. package/src/compliance/tests/test_retention_scheduler.py +0 -99
  273. package/src/compression/__init__.py +0 -25
  274. package/src/compression/cli.py +0 -150
  275. package/src/compression/cold_storage.py +0 -217
  276. package/src/compression/config.py +0 -72
  277. package/src/compression/orchestrator.py +0 -133
  278. package/src/compression/tier2_compressor.py +0 -228
  279. package/src/compression/tier3_compressor.py +0 -153
  280. package/src/compression/tier_classifier.py +0 -148
  281. package/src/db_connection_manager.py +0 -536
  282. package/src/embedding_engine.py +0 -63
  283. package/src/embeddings/__init__.py +0 -47
  284. package/src/embeddings/cache.py +0 -70
  285. package/src/embeddings/cli.py +0 -113
  286. package/src/embeddings/constants.py +0 -47
  287. package/src/embeddings/database.py +0 -91
  288. package/src/embeddings/engine.py +0 -247
  289. package/src/embeddings/model_loader.py +0 -145
  290. package/src/event_bus.py +0 -562
  291. package/src/graph/__init__.py +0 -36
  292. package/src/graph/build_helpers.py +0 -74
  293. package/src/graph/cli.py +0 -87
  294. package/src/graph/cluster_builder.py +0 -188
  295. package/src/graph/cluster_summary.py +0 -148
  296. package/src/graph/constants.py +0 -47
  297. package/src/graph/edge_builder.py +0 -162
  298. package/src/graph/entity_extractor.py +0 -95
  299. package/src/graph/graph_core.py +0 -226
  300. package/src/graph/graph_search.py +0 -231
  301. package/src/graph/hierarchical.py +0 -207
  302. package/src/graph/schema.py +0 -99
  303. package/src/graph_engine.py +0 -52
  304. package/src/hnsw_index.py +0 -628
  305. package/src/hybrid_search.py +0 -46
  306. package/src/learning/__init__.py +0 -217
  307. package/src/learning/adaptive_ranker.py +0 -682
  308. package/src/learning/bootstrap/__init__.py +0 -69
  309. package/src/learning/bootstrap/constants.py +0 -93
  310. package/src/learning/bootstrap/db_queries.py +0 -316
  311. package/src/learning/bootstrap/sampling.py +0 -82
  312. package/src/learning/bootstrap/text_utils.py +0 -71
  313. package/src/learning/cross_project_aggregator.py +0 -857
  314. package/src/learning/db/__init__.py +0 -40
  315. package/src/learning/db/constants.py +0 -44
  316. package/src/learning/db/schema.py +0 -279
  317. package/src/learning/engagement_tracker.py +0 -628
  318. package/src/learning/feature_extractor.py +0 -708
  319. package/src/learning/feedback_collector.py +0 -806
  320. package/src/learning/learning_db.py +0 -915
  321. package/src/learning/project_context_manager.py +0 -572
  322. package/src/learning/ranking/__init__.py +0 -33
  323. package/src/learning/ranking/constants.py +0 -84
  324. package/src/learning/ranking/helpers.py +0 -278
  325. package/src/learning/source_quality_scorer.py +0 -676
  326. package/src/learning/synthetic_bootstrap.py +0 -755
  327. package/src/learning/tests/test_adaptive_ranker.py +0 -325
  328. package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
  329. package/src/learning/tests/test_aggregator.py +0 -306
  330. package/src/learning/tests/test_auto_retrain_v28.py +0 -35
  331. package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
  332. package/src/learning/tests/test_feature_extractor_v28.py +0 -93
  333. package/src/learning/tests/test_feedback_collector.py +0 -294
  334. package/src/learning/tests/test_learning_db.py +0 -602
  335. package/src/learning/tests/test_learning_db_v28.py +0 -110
  336. package/src/learning/tests/test_learning_init_v28.py +0 -48
  337. package/src/learning/tests/test_outcome_signals.py +0 -48
  338. package/src/learning/tests/test_project_context.py +0 -292
  339. package/src/learning/tests/test_schema_migration.py +0 -319
  340. package/src/learning/tests/test_signal_inference.py +0 -397
  341. package/src/learning/tests/test_source_quality.py +0 -351
  342. package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
  343. package/src/learning/tests/test_workflow_miner.py +0 -318
  344. package/src/learning/workflow_pattern_miner.py +0 -655
  345. package/src/lifecycle/__init__.py +0 -54
  346. package/src/lifecycle/bounded_growth.py +0 -239
  347. package/src/lifecycle/compaction_engine.py +0 -226
  348. package/src/lifecycle/lifecycle_engine.py +0 -355
  349. package/src/lifecycle/lifecycle_evaluator.py +0 -257
  350. package/src/lifecycle/lifecycle_scheduler.py +0 -130
  351. package/src/lifecycle/retention_policy.py +0 -285
  352. package/src/lifecycle/tests/test_bounded_growth.py +0 -193
  353. package/src/lifecycle/tests/test_compaction.py +0 -179
  354. package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
  355. package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
  356. package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
  357. package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
  358. package/src/lifecycle/tests/test_mcp_compact.py +0 -149
  359. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
  360. package/src/lifecycle/tests/test_retention_policy.py +0 -162
  361. package/src/mcp_tools_v28.py +0 -281
  362. package/src/memory/__init__.py +0 -36
  363. package/src/memory/cli.py +0 -205
  364. package/src/memory/constants.py +0 -39
  365. package/src/memory/helpers.py +0 -28
  366. package/src/memory/schema.py +0 -166
  367. package/src/memory-profiles.py +0 -595
  368. package/src/memory-reset.py +0 -491
  369. package/src/memory_compression.py +0 -989
  370. package/src/memory_store_v2.py +0 -1155
  371. package/src/migrate_v1_to_v2.py +0 -629
  372. package/src/pattern_learner.py +0 -34
  373. package/src/patterns/__init__.py +0 -24
  374. package/src/patterns/analyzers.py +0 -251
  375. package/src/patterns/learner.py +0 -271
  376. package/src/patterns/scoring.py +0 -171
  377. package/src/patterns/store.py +0 -225
  378. package/src/patterns/terminology.py +0 -140
  379. package/src/provenance_tracker.py +0 -312
  380. package/src/qualixar_attribution.py +0 -139
  381. package/src/qualixar_watermark.py +0 -78
  382. package/src/query_optimizer.py +0 -511
  383. package/src/rate_limiter.py +0 -83
  384. package/src/search/__init__.py +0 -20
  385. package/src/search/cli.py +0 -77
  386. package/src/search/constants.py +0 -26
  387. package/src/search/engine.py +0 -241
  388. package/src/search/fusion.py +0 -122
  389. package/src/search/index_loader.py +0 -114
  390. package/src/search/methods.py +0 -162
  391. package/src/search_engine_v2.py +0 -401
  392. package/src/setup_validator.py +0 -482
  393. package/src/subscription_manager.py +0 -391
  394. package/src/tree/__init__.py +0 -59
  395. package/src/tree/builder.py +0 -185
  396. package/src/tree/nodes.py +0 -202
  397. package/src/tree/queries.py +0 -257
  398. package/src/tree/schema.py +0 -80
  399. package/src/tree_manager.py +0 -19
  400. package/src/trust/__init__.py +0 -45
  401. package/src/trust/constants.py +0 -66
  402. package/src/trust/queries.py +0 -157
  403. package/src/trust/schema.py +0 -95
  404. package/src/trust/scorer.py +0 -299
  405. package/src/trust/signals.py +0 -95
  406. package/src/trust_scorer.py +0 -44
  407. package/ui/app.js +0 -1588
  408. package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
  409. package/ui/js/graph-cytoscape.js +0 -1168
  410. package/ui/js/graph-d3-backup.js +0 -32
  411. package/ui/js/graph.js +0 -32
  412. package/ui_server.py +0 -266
  413. /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
  414. /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
  415. /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
  416. /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
  417. /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
  418. /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
  419. /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
  420. /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
  421. /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
  422. /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
  423. /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
  424. /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
  425. /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
  426. /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
  427. /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
  428. /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
  429. /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
  430. /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
  431. /package/{completions → ide/completions}/slm.bash +0 -0
  432. /package/{completions → ide/completions}/slm.zsh +0 -0
  433. /package/{configs → ide/configs}/cody-commands.json +0 -0
  434. /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
@@ -1,251 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Pattern Analyzers - Frequency and Context Analysis
6
-
7
- Technology preference detection via frequency counting,
8
- and coding style pattern detection from context.
9
- """
10
-
11
- import sqlite3
12
- import re
13
- import logging
14
- from typing import Dict, List, Any
15
- from collections import Counter
16
- from pathlib import Path
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
-
21
- class FrequencyAnalyzer:
22
- """Analyzes technology and tool preferences via frequency counting."""
23
-
24
- def __init__(self, db_path: Path):
25
- self.db_path = db_path
26
-
27
- # Predefined technology categories
28
- self.tech_categories = {
29
- 'frontend_framework': ['react', 'nextjs', 'next.js', 'vue', 'angular', 'svelte', 'solid'],
30
- 'backend_framework': ['express', 'fastapi', 'django', 'flask', 'nestjs', 'spring', 'rails'],
31
- 'database': ['postgres', 'postgresql', 'mysql', 'mongodb', 'redis', 'dynamodb', 'sqlite'],
32
- 'state_management': ['redux', 'context', 'zustand', 'mobx', 'recoil', 'jotai'],
33
- 'styling': ['tailwind', 'css modules', 'styled-components', 'emotion', 'sass', 'less'],
34
- 'language': ['python', 'javascript', 'typescript', 'go', 'rust', 'java', 'c++'],
35
- 'deployment': ['docker', 'kubernetes', 'vercel', 'netlify', 'aws', 'gcp', 'azure'],
36
- 'testing': ['jest', 'pytest', 'vitest', 'mocha', 'cypress', 'playwright'],
37
- }
38
-
39
- def analyze_preferences(self, memory_ids: List[int]) -> Dict[str, Dict[str, Any]]:
40
- """Analyze technology preferences across memories."""
41
- patterns = {}
42
-
43
- conn = sqlite3.connect(self.db_path)
44
- try:
45
- cursor = conn.cursor()
46
-
47
- for category, keywords in self.tech_categories.items():
48
- keyword_counts = Counter()
49
- evidence_memories = {} # {keyword: [memory_ids]}
50
-
51
- for memory_id in memory_ids:
52
- cursor.execute('SELECT content FROM memories WHERE id = ?', (memory_id,))
53
- row = cursor.fetchone()
54
-
55
- if not row:
56
- continue
57
-
58
- content = row[0].lower()
59
-
60
- for keyword in keywords:
61
- # Count occurrences with word boundaries
62
- pattern = r'\b' + re.escape(keyword.replace('.', r'\.')) + r'\b'
63
- matches = re.findall(pattern, content, re.IGNORECASE)
64
- count = len(matches)
65
-
66
- if count > 0:
67
- keyword_counts[keyword] += count
68
-
69
- if keyword not in evidence_memories:
70
- evidence_memories[keyword] = []
71
- evidence_memories[keyword].append(memory_id)
72
-
73
- # Determine preference (most mentioned)
74
- if keyword_counts:
75
- top_keyword = keyword_counts.most_common(1)[0][0]
76
- total_mentions = sum(keyword_counts.values())
77
- top_count = keyword_counts[top_keyword]
78
-
79
- # Calculate confidence (% of mentions)
80
- confidence = top_count / total_mentions if total_mentions > 0 else 0
81
-
82
- # Only create pattern if confidence > 0.6 and at least 3 mentions
83
- if confidence > 0.6 and top_count >= 3:
84
- value = self._format_preference(top_keyword, keyword_counts)
85
- evidence_list = list(set(evidence_memories.get(top_keyword, [])))
86
-
87
- patterns[category] = {
88
- 'pattern_type': 'preference',
89
- 'key': category,
90
- 'value': value,
91
- 'confidence': round(confidence, 2),
92
- 'evidence_count': len(evidence_list),
93
- 'memory_ids': evidence_list,
94
- 'category': self._categorize_pattern(category)
95
- }
96
-
97
- finally:
98
- conn.close()
99
- return patterns
100
-
101
- def _format_preference(self, top_keyword: str, all_counts: Counter) -> str:
102
- """Format preference value (e.g., 'Next.js over React')."""
103
- # Normalize keyword for display
104
- display_map = {
105
- 'nextjs': 'Next.js',
106
- 'next.js': 'Next.js',
107
- 'postgres': 'PostgreSQL',
108
- 'postgresql': 'PostgreSQL',
109
- 'fastapi': 'FastAPI',
110
- 'nestjs': 'NestJS',
111
- 'mongodb': 'MongoDB',
112
- 'redis': 'Redis',
113
- 'dynamodb': 'DynamoDB',
114
- 'tailwind': 'Tailwind CSS',
115
- }
116
-
117
- top_display = display_map.get(top_keyword.lower(), top_keyword.title())
118
-
119
- if len(all_counts) > 1:
120
- second = all_counts.most_common(2)[1]
121
- second_keyword = second[0]
122
- second_display = display_map.get(second_keyword.lower(), second_keyword.title())
123
-
124
- # Only show comparison if second choice has significant mentions
125
- if second[1] / all_counts[top_keyword] > 0.3:
126
- return f"{top_display} over {second_display}"
127
-
128
- return top_display
129
-
130
- def _categorize_pattern(self, tech_category: str) -> str:
131
- """Map tech category to high-level category."""
132
- category_map = {
133
- 'frontend_framework': 'frontend',
134
- 'state_management': 'frontend',
135
- 'styling': 'frontend',
136
- 'backend_framework': 'backend',
137
- 'database': 'backend',
138
- 'language': 'general',
139
- 'deployment': 'devops',
140
- 'testing': 'general',
141
- }
142
- return category_map.get(tech_category, 'general')
143
-
144
-
145
- class ContextAnalyzer:
146
- """Analyzes coding style patterns from context."""
147
-
148
- def __init__(self, db_path: Path):
149
- self.db_path = db_path
150
-
151
- # Style pattern detection rules
152
- self.style_indicators = {
153
- 'optimization_priority': {
154
- 'performance': ['optimize', 'faster', 'performance', 'speed', 'latency', 'efficient', 'cache'],
155
- 'readability': ['readable', 'clean', 'maintainable', 'clear', 'simple', 'understandable']
156
- },
157
- 'error_handling': {
158
- 'explicit': ['error boundary', 'explicit', 'throw', 'handle error', 'try catch', 'error handling'],
159
- 'permissive': ['ignore', 'suppress', 'skip error', 'optional']
160
- },
161
- 'testing_approach': {
162
- 'comprehensive': ['test coverage', 'unit test', 'integration test', 'e2e test', 'test suite'],
163
- 'minimal': ['manual test', 'skip test', 'no tests']
164
- },
165
- 'code_organization': {
166
- 'modular': ['separate', 'module', 'component', 'split', 'refactor', 'extract'],
167
- 'monolithic': ['single file', 'one place', 'combined']
168
- }
169
- }
170
-
171
- def analyze_style(self, memory_ids: List[int]) -> Dict[str, Dict[str, Any]]:
172
- """Detect stylistic patterns from context."""
173
- patterns = {}
174
-
175
- conn = sqlite3.connect(self.db_path)
176
- try:
177
- cursor = conn.cursor()
178
-
179
- for pattern_key, indicators in self.style_indicators.items():
180
- indicator_counts = Counter()
181
- evidence_memories = {} # {style_type: [memory_ids]}
182
-
183
- for memory_id in memory_ids:
184
- cursor.execute('SELECT content FROM memories WHERE id = ?', (memory_id,))
185
- row = cursor.fetchone()
186
-
187
- if not row:
188
- continue
189
-
190
- content = row[0].lower()
191
-
192
- for style_type, keywords in indicators.items():
193
- for keyword in keywords:
194
- if keyword in content:
195
- indicator_counts[style_type] += 1
196
-
197
- if style_type not in evidence_memories:
198
- evidence_memories[style_type] = []
199
- evidence_memories[style_type].append(memory_id)
200
-
201
- # Determine dominant style
202
- if indicator_counts:
203
- top_style = indicator_counts.most_common(1)[0][0]
204
- total = sum(indicator_counts.values())
205
- top_count = indicator_counts[top_style]
206
- confidence = top_count / total if total > 0 else 0
207
-
208
- # Only create pattern if confidence > 0.65 and at least 3 mentions
209
- if confidence > 0.65 and top_count >= 3:
210
- value = self._format_style_value(pattern_key, top_style, indicator_counts)
211
- evidence_list = list(set(evidence_memories.get(top_style, [])))
212
-
213
- patterns[pattern_key] = {
214
- 'pattern_type': 'style',
215
- 'key': pattern_key,
216
- 'value': value,
217
- 'confidence': round(confidence, 2),
218
- 'evidence_count': len(evidence_list),
219
- 'memory_ids': evidence_list,
220
- 'category': 'general'
221
- }
222
-
223
- finally:
224
- conn.close()
225
- return patterns
226
-
227
- def _format_style_value(self, pattern_key: str, top_style: str, all_counts: Counter) -> str:
228
- """Format style value as comparison or preference."""
229
- style_formats = {
230
- 'optimization_priority': {
231
- 'performance': 'Performance over readability',
232
- 'readability': 'Readability over performance'
233
- },
234
- 'error_handling': {
235
- 'explicit': 'Explicit error boundaries',
236
- 'permissive': 'Permissive error handling'
237
- },
238
- 'testing_approach': {
239
- 'comprehensive': 'Comprehensive testing',
240
- 'minimal': 'Minimal testing'
241
- },
242
- 'code_organization': {
243
- 'modular': 'Modular organization',
244
- 'monolithic': 'Monolithic organization'
245
- }
246
- }
247
-
248
- if pattern_key in style_formats and top_style in style_formats[pattern_key]:
249
- return style_formats[pattern_key][top_style]
250
-
251
- return top_style.replace('_', ' ').title()
@@ -1,271 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Pattern Learner - Main orchestrator and CLI.
6
-
7
- Coordinates frequency analysis, context analysis, terminology learning,
8
- confidence scoring, and pattern storage into a unified learning pipeline.
9
- """
10
-
11
- import sqlite3
12
- import json
13
- import logging
14
- from datetime import datetime
15
- from pathlib import Path
16
- from typing import Dict, List, Any
17
- from collections import Counter
18
-
19
- from .analyzers import FrequencyAnalyzer, ContextAnalyzer
20
- from .terminology import TerminologyLearner
21
- from .scoring import ConfidenceScorer
22
- from .store import PatternStore
23
-
24
- logger = logging.getLogger(__name__)
25
-
26
- # Local NLP tools (no external APIs)
27
- try:
28
- from sklearn.feature_extraction.text import TfidfVectorizer
29
- from sklearn.metrics.pairwise import cosine_similarity
30
- import numpy as np
31
- SKLEARN_AVAILABLE = True
32
- except ImportError:
33
- SKLEARN_AVAILABLE = False
34
-
35
- MEMORY_DIR = Path.home() / ".claude-memory"
36
- DB_PATH = MEMORY_DIR / "memory.db"
37
-
38
-
39
- class PatternLearner:
40
- """Main pattern learning orchestrator."""
41
-
42
- def __init__(self, db_path: Path = DB_PATH):
43
- self.db_path = db_path
44
- self.frequency_analyzer = FrequencyAnalyzer(db_path)
45
- self.context_analyzer = ContextAnalyzer(db_path)
46
- self.terminology_learner = TerminologyLearner(db_path)
47
- self.confidence_scorer = ConfidenceScorer(db_path)
48
- self.pattern_store = PatternStore(db_path)
49
-
50
- def _get_active_profile(self) -> str:
51
- """Get the currently active profile name from config."""
52
- config_file = MEMORY_DIR / "profiles.json"
53
- if config_file.exists():
54
- try:
55
- with open(config_file, 'r') as f:
56
- config = json.load(f)
57
- return config.get('active_profile', 'default')
58
- except (json.JSONDecodeError, IOError):
59
- pass
60
- return 'default'
61
-
62
- def weekly_pattern_update(self) -> Dict[str, int]:
63
- """Full pattern analysis of all memories for active profile. Run this weekly."""
64
- active_profile = self._get_active_profile()
65
- print(f"Starting weekly pattern update for profile: {active_profile}...")
66
-
67
- # Get memory IDs for active profile only
68
- conn = sqlite3.connect(self.db_path)
69
- try:
70
- cursor = conn.cursor()
71
- cursor.execute('SELECT id FROM memories WHERE profile = ? ORDER BY created_at',
72
- (active_profile,))
73
- all_memory_ids = [row[0] for row in cursor.fetchall()]
74
- total_memories = len(all_memory_ids)
75
- finally:
76
- conn.close()
77
-
78
- if total_memories == 0:
79
- print(f"No memories found for profile '{active_profile}'. Add memories first.")
80
- return {'preferences': 0, 'styles': 0, 'terminology': 0}
81
-
82
- print(f"Analyzing {total_memories} memories for profile '{active_profile}'...")
83
-
84
- # Run all analyzers
85
- preferences = self.frequency_analyzer.analyze_preferences(all_memory_ids)
86
- print(f" Found {len(preferences)} preference patterns")
87
-
88
- styles = self.context_analyzer.analyze_style(all_memory_ids)
89
- print(f" Found {len(styles)} style patterns")
90
-
91
- terms = self.terminology_learner.learn_terminology(all_memory_ids)
92
- print(f" Found {len(terms)} terminology patterns")
93
-
94
- # Recalculate confidence scores and save all patterns (tagged with profile)
95
- counts = {'preferences': 0, 'styles': 0, 'terminology': 0}
96
-
97
- for pattern in preferences.values():
98
- confidence = self.confidence_scorer.calculate_confidence(
99
- pattern['pattern_type'],
100
- pattern['key'],
101
- pattern['value'],
102
- pattern['memory_ids'],
103
- total_memories
104
- )
105
- pattern['confidence'] = round(confidence, 2)
106
- pattern['profile'] = active_profile
107
- self.pattern_store.save_pattern(pattern)
108
- counts['preferences'] += 1
109
-
110
- for pattern in styles.values():
111
- confidence = self.confidence_scorer.calculate_confidence(
112
- pattern['pattern_type'],
113
- pattern['key'],
114
- pattern['value'],
115
- pattern['memory_ids'],
116
- total_memories
117
- )
118
- pattern['confidence'] = round(confidence, 2)
119
- pattern['profile'] = active_profile
120
- self.pattern_store.save_pattern(pattern)
121
- counts['styles'] += 1
122
-
123
- for pattern in terms.values():
124
- confidence = self.confidence_scorer.calculate_confidence(
125
- pattern['pattern_type'],
126
- pattern['key'],
127
- pattern['value'],
128
- pattern['memory_ids'],
129
- total_memories
130
- )
131
- pattern['confidence'] = round(confidence, 2)
132
- pattern['profile'] = active_profile
133
- self.pattern_store.save_pattern(pattern)
134
- counts['terminology'] += 1
135
-
136
- print(f"\nPattern update complete:")
137
- print(f" {counts['preferences']} preferences")
138
- print(f" {counts['styles']} styles")
139
- print(f" {counts['terminology']} terminology")
140
-
141
- return counts
142
-
143
- def on_new_memory(self, memory_id: int):
144
- """Incremental update when new memory is added."""
145
- active_profile = self._get_active_profile()
146
- conn = sqlite3.connect(self.db_path)
147
- try:
148
- cursor = conn.cursor()
149
- cursor.execute('SELECT COUNT(*) FROM memories WHERE profile = ?',
150
- (active_profile,))
151
- total = cursor.fetchone()[0]
152
- finally:
153
- conn.close()
154
-
155
- # Only do incremental updates if we have many memories (>50)
156
- if total > 50:
157
- # Deferred to batch update for efficiency (see weekly_pattern_update)
158
- pass
159
- else:
160
- # For small memory counts, just do full update
161
- self.weekly_pattern_update()
162
-
163
- def get_patterns(self, min_confidence: float = 0.7) -> List[Dict[str, Any]]:
164
- """Query patterns above confidence threshold for active profile."""
165
- active_profile = self._get_active_profile()
166
- return self.pattern_store.get_patterns(min_confidence, profile=active_profile)
167
-
168
- def get_identity_context(self, min_confidence: float = 0.7) -> str:
169
- """Format patterns for Claude context injection."""
170
- patterns = self.get_patterns(min_confidence)
171
-
172
- if not patterns:
173
- return "## Working with User - Learned Patterns\n\nNo patterns learned yet. Add more memories to build your profile."
174
-
175
- # Group by pattern type
176
- sections = {
177
- 'preference': [],
178
- 'style': [],
179
- 'terminology': []
180
- }
181
-
182
- for p in patterns:
183
- sections[p['pattern_type']].append(
184
- f"- **{p['key'].replace('_', ' ').title()}:** {p['value']} "
185
- f"(confidence: {p['confidence']:.0%}, {p['evidence_count']} examples)"
186
- )
187
-
188
- output = "## Working with User - Learned Patterns\n\n"
189
-
190
- if sections['preference']:
191
- output += "**Technology Preferences:**\n" + '\n'.join(sections['preference']) + '\n\n'
192
-
193
- if sections['style']:
194
- output += "**Coding Style:**\n" + '\n'.join(sections['style']) + '\n\n'
195
-
196
- if sections['terminology']:
197
- output += "**Terminology:**\n" + '\n'.join(sections['terminology']) + '\n'
198
-
199
- return output
200
-
201
-
202
- # CLI Interface
203
- if __name__ == "__main__":
204
- import sys
205
-
206
- learner = PatternLearner()
207
-
208
- if len(sys.argv) < 2:
209
- print("Pattern Learner - Identity Profile Extraction")
210
- print("\nUsage:")
211
- print(" python pattern_learner.py update # Full pattern update (weekly)")
212
- print(" python pattern_learner.py list [min_conf] # List learned patterns (default: 0.7)")
213
- print(" python pattern_learner.py context [min] # Get context for Claude")
214
- print(" python pattern_learner.py stats # Pattern statistics")
215
- sys.exit(0)
216
-
217
- command = sys.argv[1]
218
-
219
- if command == "update":
220
- counts = learner.weekly_pattern_update()
221
- print(f"\nTotal patterns learned: {sum(counts.values())}")
222
-
223
- elif command == "list":
224
- min_conf = float(sys.argv[2]) if len(sys.argv) > 2 else 0.7
225
- patterns = learner.get_patterns(min_conf)
226
-
227
- if not patterns:
228
- print(f"No patterns found with confidence >= {min_conf:.0%}")
229
- else:
230
- print(f"\n{'Type':<15} {'Category':<12} {'Pattern':<30} {'Confidence':<12} {'Evidence':<10}")
231
- print("-" * 95)
232
-
233
- for p in patterns:
234
- pattern_display = f"{p['key'].replace('_', ' ').title()}: {p['value']}"
235
- if len(pattern_display) > 28:
236
- pattern_display = pattern_display[:28] + "..."
237
-
238
- print(f"{p['pattern_type']:<15} {p['category']:<12} {pattern_display:<30} "
239
- f"{p['confidence']:>6.0%} {p['evidence_count']:<10}")
240
-
241
- elif command == "context":
242
- min_conf = float(sys.argv[2]) if len(sys.argv) > 2 else 0.7
243
- context = learner.get_identity_context(min_conf)
244
- print(context)
245
-
246
- elif command == "stats":
247
- patterns = learner.get_patterns(0.5) # Include all patterns
248
-
249
- if not patterns:
250
- print("No patterns learned yet.")
251
- else:
252
- by_type = Counter([p['pattern_type'] for p in patterns])
253
- by_category = Counter([p['category'] for p in patterns])
254
-
255
- avg_confidence = sum(p['confidence'] for p in patterns) / len(patterns)
256
- high_conf = len([p for p in patterns if p['confidence'] >= 0.8])
257
-
258
- print(f"\nPattern Statistics:")
259
- print(f" Total patterns: {len(patterns)}")
260
- print(f" Average confidence: {avg_confidence:.0%}")
261
- print(f" High confidence (>=80%): {high_conf}")
262
- print(f"\nBy Type:")
263
- for ptype, count in by_type.most_common():
264
- print(f" {ptype}: {count}")
265
- print(f"\nBy Category:")
266
- for cat, count in by_category.most_common():
267
- print(f" {cat}: {count}")
268
-
269
- else:
270
- print(f"Unknown command: {command}")
271
- sys.exit(1)
@@ -1,171 +0,0 @@
1
- #!/usr/bin/env python3
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
4
- """
5
- Confidence Scoring - Bayesian pattern confidence calculation.
6
-
7
- Uses Beta-Binomial posterior with log-scaled competition,
8
- recency bonuses, and temporal distribution factors.
9
- """
10
-
11
- import sqlite3
12
- import logging
13
- from datetime import datetime, timedelta
14
- from typing import List
15
- from pathlib import Path
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
-
20
- class ConfidenceScorer:
21
- """Calculates and tracks pattern confidence scores."""
22
-
23
- def __init__(self, db_path: Path):
24
- self.db_path = db_path
25
-
26
- def calculate_confidence(
27
- self,
28
- pattern_type: str,
29
- key: str,
30
- value: str,
31
- evidence_memory_ids: List[int],
32
- total_memories: int
33
- ) -> float:
34
- """
35
- Calculate confidence using Beta-Binomial Bayesian posterior.
36
-
37
- Based on MACLA (arXiv:2512.18950, Forouzandeh et al., Dec 2025):
38
- posterior_mean = (alpha + evidence) / (alpha + beta + evidence + competition)
39
-
40
- Adaptation: MACLA's Beta-Binomial uses pairwise interaction counts.
41
- Our corpus has sparse signals (most memories are irrelevant to any
42
- single pattern). We use log-scaled competition instead of raw total
43
- to avoid over-dilution: competition = log2(total_memories).
44
-
45
- Pattern-specific priors (alpha, beta):
46
- - preference (1, 4): prior mean 0.20, ~8 items to reach 0.5
47
- - style (1, 5): prior mean 0.17, subtler signals need more evidence
48
- - terminology (2, 3): prior mean 0.40, direct usage signal
49
- """
50
- if total_memories == 0 or not evidence_memory_ids:
51
- return 0.0
52
-
53
- import math
54
- evidence_count = len(evidence_memory_ids)
55
-
56
- # Pattern-specific Beta priors (alpha, beta)
57
- PRIORS = {
58
- 'preference': (1.0, 4.0),
59
- 'style': (1.0, 5.0),
60
- 'terminology': (2.0, 3.0),
61
- }
62
- alpha, beta = PRIORS.get(pattern_type, (1.0, 4.0))
63
-
64
- # Log-scaled competition: grows slowly with corpus size
65
- # 10 memories -> 3.3, 60 -> 5.9, 500 -> 9.0, 5000 -> 12.3
66
- competition = math.log2(max(2, total_memories))
67
-
68
- # MACLA-inspired Beta posterior with log competition
69
- posterior_mean = (alpha + evidence_count) / (alpha + beta + evidence_count + competition)
70
-
71
- # Recency adjustment (mild: 1.0 to 1.15)
72
- recency_bonus = self._calculate_recency_bonus(evidence_memory_ids)
73
- recency_factor = 1.0 + min(0.15, 0.075 * (recency_bonus - 1.0) / 0.2) if recency_bonus > 1.0 else 1.0
74
-
75
- # Temporal spread adjustment (0.9 to 1.1)
76
- distribution_factor = self._calculate_distribution_factor(evidence_memory_ids)
77
-
78
- # Final confidence
79
- confidence = posterior_mean * recency_factor * distribution_factor
80
-
81
- return min(0.95, round(confidence, 3))
82
-
83
- def _calculate_recency_bonus(self, memory_ids: List[int]) -> float:
84
- """Give bonus to patterns with recent evidence."""
85
- conn = sqlite3.connect(self.db_path)
86
- try:
87
- cursor = conn.cursor()
88
-
89
- # Get timestamps
90
- placeholders = ','.join('?' * len(memory_ids))
91
- cursor.execute(f'''
92
- SELECT created_at FROM memories
93
- WHERE id IN ({placeholders})
94
- ORDER BY created_at DESC
95
- ''', memory_ids)
96
-
97
- timestamps = cursor.fetchall()
98
- finally:
99
- conn.close()
100
-
101
- if not timestamps:
102
- return 1.0
103
-
104
- # Check if any memories are from last 30 days
105
- recent_count = 0
106
- cutoff = datetime.now() - timedelta(days=30)
107
-
108
- for ts_tuple in timestamps:
109
- ts_str = ts_tuple[0]
110
- try:
111
- ts = datetime.fromisoformat(ts_str.replace(' ', 'T'))
112
- if ts > cutoff:
113
- recent_count += 1
114
- except (ValueError, AttributeError):
115
- pass
116
-
117
- # Bonus if >50% are recent
118
- if len(timestamps) > 0 and recent_count / len(timestamps) > 0.5:
119
- return 1.2
120
- else:
121
- return 1.0
122
-
123
- def _calculate_distribution_factor(self, memory_ids: List[int]) -> float:
124
- """Better confidence if memories are distributed over time, not just one session."""
125
- if len(memory_ids) < 3:
126
- return 0.8 # Penalize low sample size
127
-
128
- conn = sqlite3.connect(self.db_path)
129
- try:
130
- cursor = conn.cursor()
131
-
132
- placeholders = ','.join('?' * len(memory_ids))
133
- cursor.execute(f'''
134
- SELECT created_at FROM memories
135
- WHERE id IN ({placeholders})
136
- ORDER BY created_at
137
- ''', memory_ids)
138
-
139
- timestamps = [row[0] for row in cursor.fetchall()]
140
- finally:
141
- conn.close()
142
-
143
- if len(timestamps) < 2:
144
- return 0.8
145
-
146
- try:
147
- # Parse timestamps
148
- dates = []
149
- for ts_str in timestamps:
150
- try:
151
- ts = datetime.fromisoformat(ts_str.replace(' ', 'T'))
152
- dates.append(ts)
153
- except (ValueError, AttributeError):
154
- pass
155
-
156
- if len(dates) < 2:
157
- return 0.8
158
-
159
- # Calculate time span
160
- time_span = (dates[-1] - dates[0]).days
161
-
162
- # If memories span multiple days, higher confidence
163
- if time_span > 7:
164
- return 1.1
165
- elif time_span > 1:
166
- return 1.0
167
- else:
168
- return 0.9 # All on same day = might be one-off
169
-
170
- except Exception:
171
- return 1.0