superlocalmemory 3.4.0__tar.gz → 3.4.1__tar.gz

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 (291) hide show
  1. {superlocalmemory-3.4.0/src/superlocalmemory.egg-info → superlocalmemory-3.4.1}/PKG-INFO +8 -9
  2. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/README.md +7 -8
  3. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/pyproject.toml +1 -1
  4. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/engine_wiring.py +5 -1
  5. superlocalmemory-3.4.1/src/superlocalmemory/core/graph_analyzer.py +441 -0
  6. superlocalmemory-3.4.1/src/superlocalmemory/learning/consolidation_worker.py +477 -0
  7. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/entity_channel.py +135 -4
  8. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/spreading_activation.py +45 -0
  9. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/api.py +9 -1
  10. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/behavioral.py +8 -4
  11. superlocalmemory-3.4.1/src/superlocalmemory/server/routes/chat.py +320 -0
  12. superlocalmemory-3.4.1/src/superlocalmemory/server/routes/insights.py +368 -0
  13. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/learning.py +106 -6
  14. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/memories.py +20 -9
  15. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/stats.py +25 -3
  16. superlocalmemory-3.4.1/src/superlocalmemory/server/routes/timeline.py +252 -0
  17. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/v3_api.py +161 -0
  18. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/ui.py +8 -0
  19. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/index.html +168 -58
  20. superlocalmemory-3.4.1/src/superlocalmemory/ui/js/graph-event-bus.js +83 -0
  21. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/graph-filters.js +1 -1
  22. superlocalmemory-3.4.1/src/superlocalmemory/ui/js/knowledge-graph.js +942 -0
  23. superlocalmemory-3.4.1/src/superlocalmemory/ui/js/memory-chat.js +344 -0
  24. superlocalmemory-3.4.1/src/superlocalmemory/ui/js/memory-timeline.js +265 -0
  25. superlocalmemory-3.4.1/src/superlocalmemory/ui/js/quick-actions.js +334 -0
  26. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1/src/superlocalmemory.egg-info}/PKG-INFO +8 -9
  27. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory.egg-info/SOURCES.txt +8 -0
  28. superlocalmemory-3.4.0/src/superlocalmemory/core/graph_analyzer.py +0 -199
  29. superlocalmemory-3.4.0/src/superlocalmemory/learning/consolidation_worker.py +0 -289
  30. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/AUTHORS.md +0 -0
  31. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/LICENSE +0 -0
  32. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/NOTICE +0 -0
  33. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/setup.cfg +0 -0
  34. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/__init__.py +0 -0
  35. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/attribution/__init__.py +0 -0
  36. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/attribution/mathematical_dna.py +0 -0
  37. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/attribution/signer.py +0 -0
  38. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/attribution/watermark.py +0 -0
  39. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/__init__.py +0 -0
  40. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/commands.py +0 -0
  41. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/daemon.py +0 -0
  42. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/json_output.py +0 -0
  43. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/main.py +0 -0
  44. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/migrate_cmd.py +0 -0
  45. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/pending_store.py +0 -0
  46. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/post_install.py +0 -0
  47. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/cli/setup_wizard.py +0 -0
  48. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/__init__.py +0 -0
  49. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/blast_radius.py +0 -0
  50. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/__init__.py +0 -0
  51. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/entity_resolver.py +0 -0
  52. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/event_listeners.py +0 -0
  53. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/fact_enricher.py +0 -0
  54. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +0 -0
  55. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/bridge/temporal_checker.py +0 -0
  56. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/changes.py +0 -0
  57. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/communities.py +0 -0
  58. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/config.py +0 -0
  59. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/database.py +0 -0
  60. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/extractors/__init__.py +0 -0
  61. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/extractors/python.py +0 -0
  62. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/extractors/typescript.py +0 -0
  63. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/flows.py +0 -0
  64. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/git_hooks.py +0 -0
  65. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/graph_engine.py +0 -0
  66. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/graph_store.py +0 -0
  67. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/incremental.py +0 -0
  68. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/models.py +0 -0
  69. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/parser.py +0 -0
  70. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/resolver.py +0 -0
  71. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/search.py +0 -0
  72. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/service.py +0 -0
  73. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/code_graph/watcher.py +0 -0
  74. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/__init__.py +0 -0
  75. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/abac.py +0 -0
  76. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/audit.py +0 -0
  77. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/eu_ai_act.py +0 -0
  78. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/gdpr.py +0 -0
  79. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/lifecycle.py +0 -0
  80. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/retention.py +0 -0
  81. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/compliance/scheduler.py +0 -0
  82. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/__init__.py +0 -0
  83. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/config.py +0 -0
  84. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/consolidation_engine.py +0 -0
  85. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/embedding_worker.py +0 -0
  86. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/embeddings.py +0 -0
  87. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/engine.py +0 -0
  88. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/hooks.py +0 -0
  89. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/maintenance.py +0 -0
  90. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/maintenance_scheduler.py +0 -0
  91. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/modes.py +0 -0
  92. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/ollama_embedder.py +0 -0
  93. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/profiles.py +0 -0
  94. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/recall_pipeline.py +0 -0
  95. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/recall_worker.py +0 -0
  96. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/registry.py +0 -0
  97. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/reranker_worker.py +0 -0
  98. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/store_pipeline.py +0 -0
  99. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/summarizer.py +0 -0
  100. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/core/worker_pool.py +0 -0
  101. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/dynamics/__init__.py +0 -0
  102. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -0
  103. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/dynamics/eap_scheduler.py +0 -0
  104. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -0
  105. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -0
  106. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/__init__.py +0 -0
  107. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/auto_linker.py +0 -0
  108. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/cognitive_consolidator.py +0 -0
  109. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/consolidator.py +0 -0
  110. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/context_generator.py +0 -0
  111. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/emotional.py +0 -0
  112. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/entity_resolver.py +0 -0
  113. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/entropy_gate.py +0 -0
  114. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/fact_extractor.py +0 -0
  115. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/foresight.py +0 -0
  116. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/graph_builder.py +0 -0
  117. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/observation_builder.py +0 -0
  118. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/scene_builder.py +0 -0
  119. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/signal_inference.py +0 -0
  120. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/temporal_parser.py +0 -0
  121. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/temporal_validator.py +0 -0
  122. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/encoding/type_router.py +0 -0
  123. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/__init__.py +0 -0
  124. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/auto_capture.py +0 -0
  125. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/auto_invoker.py +0 -0
  126. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/auto_parameterize.py +0 -0
  127. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/auto_recall.py +0 -0
  128. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/claude_code_hooks.py +0 -0
  129. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/hook_handlers.py +0 -0
  130. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/ide_connector.py +0 -0
  131. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/hooks/rules_engine.py +0 -0
  132. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/__init__.py +0 -0
  133. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/auth_middleware.py +0 -0
  134. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/backup.py +0 -0
  135. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/cache_manager.py +0 -0
  136. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/event_bus.py +0 -0
  137. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/heartbeat_monitor.py +0 -0
  138. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/pid_manager.py +0 -0
  139. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/process_reaper.py +0 -0
  140. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/rate_limiter.py +0 -0
  141. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/infra/webhook_dispatcher.py +0 -0
  142. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/__init__.py +0 -0
  143. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/adaptive.py +0 -0
  144. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/behavioral.py +0 -0
  145. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/behavioral_listener.py +0 -0
  146. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/bootstrap.py +0 -0
  147. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -0
  148. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/cross_project.py +0 -0
  149. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/database.py +0 -0
  150. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/engagement.py +0 -0
  151. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/features.py +0 -0
  152. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/feedback.py +0 -0
  153. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/forgetting_scheduler.py +0 -0
  154. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/outcomes.py +0 -0
  155. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/project_context.py +0 -0
  156. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/quantization_scheduler.py +0 -0
  157. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/ranker.py +0 -0
  158. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/signals.py +0 -0
  159. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/source_quality.py +0 -0
  160. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/learning/workflows.py +0 -0
  161. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/llm/__init__.py +0 -0
  162. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/llm/backbone.py +0 -0
  163. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/__init__.py +0 -0
  164. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/ebbinghaus.py +0 -0
  165. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/fisher.py +0 -0
  166. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/fisher_quantized.py +0 -0
  167. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/hopfield.py +0 -0
  168. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/langevin.py +0 -0
  169. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/polar_quant.py +0 -0
  170. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/qjl.py +0 -0
  171. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/sheaf.py +0 -0
  172. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/math/turbo_quant.py +0 -0
  173. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/__init__.py +0 -0
  174. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/resources.py +0 -0
  175. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/server.py +0 -0
  176. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/shared.py +0 -0
  177. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools.py +0 -0
  178. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_active.py +0 -0
  179. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_code_graph.py +0 -0
  180. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_core.py +0 -0
  181. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_v28.py +0 -0
  182. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_v3.py +0 -0
  183. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/mcp/tools_v33.py +0 -0
  184. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/__init__.py +0 -0
  185. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/pattern_extractor.py +0 -0
  186. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/pii_filter.py +0 -0
  187. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/prompt_injector.py +0 -0
  188. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -0
  189. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -0
  190. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/__init__.py +0 -0
  191. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/agentic.py +0 -0
  192. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/ann_index.py +0 -0
  193. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/bm25_channel.py +0 -0
  194. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/bridge_discovery.py +0 -0
  195. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/channel_registry.py +0 -0
  196. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/engine.py +0 -0
  197. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/forgetting_filter.py +0 -0
  198. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/fusion.py +0 -0
  199. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/hopfield_channel.py +0 -0
  200. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/profile_channel.py +0 -0
  201. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -0
  202. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/reranker.py +0 -0
  203. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/semantic_channel.py +0 -0
  204. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/strategy.py +0 -0
  205. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/temporal_channel.py +0 -0
  206. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/retrieval/vector_store.py +0 -0
  207. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/__init__.py +0 -0
  208. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/__init__.py +0 -0
  209. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/agents.py +0 -0
  210. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/backup.py +0 -0
  211. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/compliance.py +0 -0
  212. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/data_io.py +0 -0
  213. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/events.py +0 -0
  214. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/helpers.py +0 -0
  215. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/lifecycle.py +0 -0
  216. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/profiles.py +0 -0
  217. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/routes/ws.py +0 -0
  218. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/server/security_middleware.py +0 -0
  219. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/__init__.py +0 -0
  220. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/access_control.py +0 -0
  221. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/access_log.py +0 -0
  222. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/database.py +0 -0
  223. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/embedding_migrator.py +0 -0
  224. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/migration_v33.py +0 -0
  225. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/migrations.py +0 -0
  226. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/models.py +0 -0
  227. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/quantized_store.py +0 -0
  228. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/schema.py +0 -0
  229. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/schema_code_graph.py +0 -0
  230. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/schema_v32.py +0 -0
  231. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/storage/v2_migrator.py +0 -0
  232. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/trust/__init__.py +0 -0
  233. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/trust/gate.py +0 -0
  234. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/trust/provenance.py +0 -0
  235. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/trust/scorer.py +0 -0
  236. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/trust/signals.py +0 -0
  237. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/agents.js +0 -0
  238. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/auto-settings.js +0 -0
  239. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/behavioral.js +0 -0
  240. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/clusters.js +0 -0
  241. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/compliance.js +0 -0
  242. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/core.js +0 -0
  243. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/dashboard.js +0 -0
  244. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/events.js +0 -0
  245. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/fact-detail.js +0 -0
  246. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/feedback.js +0 -0
  247. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/graph-core.js +0 -0
  248. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/graph-interactions.js +0 -0
  249. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/graph-ui.js +0 -0
  250. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/ide-status.js +0 -0
  251. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/init.js +0 -0
  252. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/learning.js +0 -0
  253. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/lifecycle.js +0 -0
  254. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/math-health.js +0 -0
  255. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/memories.js +0 -0
  256. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/modal.js +0 -0
  257. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/patterns.js +0 -0
  258. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/profiles.js +0 -0
  259. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/recall-lab.js +0 -0
  260. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/search.js +0 -0
  261. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/settings.js +0 -0
  262. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/timeline.js +0 -0
  263. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory/ui/js/trust-dashboard.js +0 -0
  264. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory.egg-info/dependency_links.txt +0 -0
  265. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory.egg-info/entry_points.txt +0 -0
  266. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory.egg-info/requires.txt +0 -0
  267. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/src/superlocalmemory.egg-info/top_level.txt +0 -0
  268. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_auto_hooks.py +0 -0
  269. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_behavioral_full.py +0 -0
  270. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_claude_hooks.py +0 -0
  271. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_cli.py +0 -0
  272. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_cli_json.py +0 -0
  273. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_cli_v33.py +0 -0
  274. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_compliance_full.py +0 -0
  275. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_config_system.py +0 -0
  276. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_engine_hooks.py +0 -0
  277. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_event_bus.py +0 -0
  278. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_features.py +0 -0
  279. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_final_locomo_mini.py +0 -0
  280. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_hook_handlers.py +0 -0
  281. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_ide_connector.py +0 -0
  282. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_infra.py +0 -0
  283. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_learning_advanced.py +0 -0
  284. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_learning_collectors.py +0 -0
  285. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_llm_provider.py +0 -0
  286. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_mcp_server.py +0 -0
  287. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_migration.py +0 -0
  288. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_post_install.py +0 -0
  289. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_ranker.py +0 -0
  290. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_trust_full.py +0 -0
  291. {superlocalmemory-3.4.0 → superlocalmemory-3.4.1}/tests/test_v3_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: superlocalmemory
3
- Version: 3.4.0
3
+ Version: 3.4.1
4
4
  Summary: Information-geometric agent memory with mathematical guarantees
5
5
  Author-email: Varun Pratap Bhardwaj <admin@superlocalmemory.com>
6
6
  License: AGPL-3.0-or-later
@@ -413,20 +413,19 @@ slm dashboard # Opens at http://localhost:8765
413
413
 
414
414
  <details open>
415
415
  <summary><strong>Dashboard Screenshots</strong> (click to collapse)</summary>
416
- <p align="center"><img src="docs/screenshots/01-dashboard-main.png" alt="Dashboard" width="600"/></p>
416
+ <p align="center"><img src="docs/screenshots/01-dashboard-main.png" alt="Dashboard Overview — 3,100+ memories, 430K connections" width="600"/></p>
417
417
  <p align="center">
418
- <img src="docs/screenshots/02-knowledge-graph.png" alt="Graph" width="190"/>
419
- <img src="docs/screenshots/03-math-health.png" alt="Math" width="190"/>
420
- <img src="docs/screenshots/05-trust-dashboard.png" alt="Trust" width="190"/>
418
+ <img src="docs/screenshots/02-knowledge-graph.png" alt="Knowledge Graph — Sigma.js WebGL with community detection, chat, quick actions, timeline" width="290"/>
419
+ <img src="docs/screenshots/06-graph-communities.png" alt="Graph Communities — Louvain clustering with colored nodes" width="290"/>
421
420
  </p>
422
421
  <p align="center">
423
- <img src="docs/screenshots/04-recall-lab.png" alt="Recall" width="190"/>
424
- <img src="docs/screenshots/06-settings.png" alt="Settings" width="190"/>
425
- <img src="docs/screenshots/07-memories-blurred.png" alt="Memories" width="190"/>
422
+ <img src="docs/screenshots/03-patterns-learning.png" alt="Patterns — 50 learned behavioral patterns with confidence bars" width="190"/>
423
+ <img src="docs/screenshots/04-learning-dashboard.png" alt="Learning — 722 signals, ML Model phase, tech preferences" width="190"/>
424
+ <img src="docs/screenshots/05-behavioral-analysis.png" alt="Behavioral — pattern analysis with confidence distribution" width="190"/>
426
425
  </p>
427
426
  </details>
428
427
 
429
- 23 tabs: Dashboard, Recall Lab, Knowledge Graph, Memories, Trust Scores, Math Health, Compliance, Learning, IDE Connections, Settings, Memory Lifecycle, Compression, Patterns, and more. Runs locally — no data leaves your machine.
428
+ **v3.4.1 Visual Intelligence:** Sigma.js WebGL knowledge graph with community detection (Louvain/Leiden), 5 quick insight actions, D3 memory timeline, graph-enhanced retrieval (PageRank bias + community boost + contradiction suppression), and 56 auto-mined behavioral patterns. 23+ tabs. Runs locally — no data leaves your machine.
430
429
 
431
430
  ---
432
431
 
@@ -341,20 +341,19 @@ slm dashboard # Opens at http://localhost:8765
341
341
 
342
342
  <details open>
343
343
  <summary><strong>Dashboard Screenshots</strong> (click to collapse)</summary>
344
- <p align="center"><img src="docs/screenshots/01-dashboard-main.png" alt="Dashboard" width="600"/></p>
344
+ <p align="center"><img src="docs/screenshots/01-dashboard-main.png" alt="Dashboard Overview — 3,100+ memories, 430K connections" width="600"/></p>
345
345
  <p align="center">
346
- <img src="docs/screenshots/02-knowledge-graph.png" alt="Graph" width="190"/>
347
- <img src="docs/screenshots/03-math-health.png" alt="Math" width="190"/>
348
- <img src="docs/screenshots/05-trust-dashboard.png" alt="Trust" width="190"/>
346
+ <img src="docs/screenshots/02-knowledge-graph.png" alt="Knowledge Graph — Sigma.js WebGL with community detection, chat, quick actions, timeline" width="290"/>
347
+ <img src="docs/screenshots/06-graph-communities.png" alt="Graph Communities — Louvain clustering with colored nodes" width="290"/>
349
348
  </p>
350
349
  <p align="center">
351
- <img src="docs/screenshots/04-recall-lab.png" alt="Recall" width="190"/>
352
- <img src="docs/screenshots/06-settings.png" alt="Settings" width="190"/>
353
- <img src="docs/screenshots/07-memories-blurred.png" alt="Memories" width="190"/>
350
+ <img src="docs/screenshots/03-patterns-learning.png" alt="Patterns — 50 learned behavioral patterns with confidence bars" width="190"/>
351
+ <img src="docs/screenshots/04-learning-dashboard.png" alt="Learning — 722 signals, ML Model phase, tech preferences" width="190"/>
352
+ <img src="docs/screenshots/05-behavioral-analysis.png" alt="Behavioral — pattern analysis with confidence distribution" width="190"/>
354
353
  </p>
355
354
  </details>
356
355
 
357
- 23 tabs: Dashboard, Recall Lab, Knowledge Graph, Memories, Trust Scores, Math Health, Compliance, Learning, IDE Connections, Settings, Memory Lifecycle, Compression, Patterns, and more. Runs locally — no data leaves your machine.
356
+ **v3.4.1 Visual Intelligence:** Sigma.js WebGL knowledge graph with community detection (Louvain/Leiden), 5 quick insight actions, D3 memory timeline, graph-enhanced retrieval (PageRank bias + community boost + contradiction suppression), and 56 auto-mined behavioral patterns. 23+ tabs. Runs locally — no data leaves your machine.
358
357
 
359
358
  ---
360
359
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.4.0"
3
+ version = "3.4.1"
4
4
  description = "Information-geometric agent memory with mathematical guarantees"
5
5
  readme = "README.md"
6
6
  license = {text = "AGPL-3.0-or-later"}
@@ -364,7 +364,11 @@ def _init_spreading_activation(
364
364
  SpreadingActivation,
365
365
  SpreadingActivationConfig,
366
366
  )
367
- sa_config = SpreadingActivationConfig(enabled=True)
367
+ sa_config = SpreadingActivationConfig(
368
+ enabled=True,
369
+ use_pagerank_bias=True, # v3.4.1: PageRank-weighted propagation
370
+ community_boost=0.15, # v3.4.1: 15% boost for same-community nodes
371
+ )
368
372
  return SpreadingActivation(
369
373
  db=db, vector_store=vector_store, config=sa_config,
370
374
  )
@@ -0,0 +1,441 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the Elastic License 2.0 - see LICENSE file
3
+ # Part of SuperLocalMemory V3
4
+
5
+ """Graph structural analysis -- PageRank, community detection, centrality.
6
+
7
+ Reads BOTH graph_edges and association_edges for the full graph picture.
8
+ Stores results in fact_importance table.
9
+ Called during consolidation (Phase 5), not at query time.
10
+
11
+ v3.4.1: Added Leiden community detection (optional), TF-IDF community labels,
12
+ bridge score detection. Frontend uses Louvain; backend uses Leiden/LP.
13
+
14
+ Part of Qualixar | Author: Varun Pratap Bhardwaj
15
+ License: AGPL-3.0-or-later
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import logging
22
+ from collections import Counter, defaultdict
23
+ from math import log
24
+ from typing import Any
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class GraphAnalyzer:
30
+ """Compute structural importance metrics for the memory graph.
31
+
32
+ - PageRank: global structural importance via networkx
33
+ - Community detection: Label Propagation via networkx
34
+ - Degree centrality: connection count normalization
35
+
36
+ Reads BOTH graph_edges and association_edges (Rule 13).
37
+ Stores results in fact_importance table.
38
+ """
39
+
40
+ def __init__(self, db: Any) -> None:
41
+ self._db = db
42
+
43
+ def compute_and_store(self, profile_id: str) -> dict[str, Any]:
44
+ """Run all analyses and persist to fact_importance.
45
+
46
+ v3.4.1: Now uses Leiden (falls back to Label Propagation),
47
+ generates TF-IDF community labels, computes bridge scores.
48
+
49
+ Returns summary dict with node_count, community_count, top_5_nodes,
50
+ bridge_count, top_bridge_nodes, community_labels.
51
+ """
52
+ try:
53
+ graph = self._build_networkx_graph(profile_id)
54
+ if graph.number_of_nodes() == 0:
55
+ return {
56
+ "node_count": 0,
57
+ "edge_count": 0,
58
+ "community_count": 0,
59
+ "top_5_nodes": [],
60
+ }
61
+
62
+ pagerank = self.compute_pagerank(graph)
63
+ communities = self.detect_communities_leiden(graph, profile_id)
64
+ centrality = self._compute_degree_centrality(graph)
65
+ bridge_scores = self.compute_bridge_scores(graph)
66
+ labels = self.compute_community_labels(profile_id, communities)
67
+
68
+ # v3.4.1: Ensure bridge_score column exists (idempotent migration)
69
+ try:
70
+ columns = self._db.execute(
71
+ "PRAGMA table_info(fact_importance)", (),
72
+ )
73
+ has_bridge = any(
74
+ dict(c).get("name") == "bridge_score" for c in columns
75
+ )
76
+ if not has_bridge:
77
+ self._db.execute(
78
+ "ALTER TABLE fact_importance "
79
+ "ADD COLUMN bridge_score REAL DEFAULT 0.0",
80
+ (),
81
+ )
82
+ except Exception:
83
+ pass
84
+
85
+ # Persist to fact_importance (with bridge_score)
86
+ for node_id in graph.nodes():
87
+ pr_score = pagerank.get(node_id, 0.0)
88
+ comm_id = communities.get(node_id)
89
+ deg_cent = centrality.get(node_id, 0.0)
90
+ br_score = bridge_scores.get(node_id, 0.0)
91
+ try:
92
+ self._db.execute(
93
+ "INSERT OR REPLACE INTO fact_importance "
94
+ "(fact_id, profile_id, pagerank_score, community_id, "
95
+ " degree_centrality, bridge_score, computed_at) "
96
+ "VALUES (?, ?, ?, ?, ?, ?, datetime('now'))",
97
+ (node_id, profile_id, round(pr_score, 6),
98
+ comm_id, round(deg_cent, 4),
99
+ round(br_score, 6)),
100
+ )
101
+ except Exception:
102
+ # Fallback without bridge_score if column doesn't exist
103
+ self._db.execute(
104
+ "INSERT OR REPLACE INTO fact_importance "
105
+ "(fact_id, profile_id, pagerank_score, community_id, "
106
+ " degree_centrality, computed_at) "
107
+ "VALUES (?, ?, ?, ?, ?, datetime('now'))",
108
+ (node_id, profile_id, round(pr_score, 6),
109
+ comm_id, round(deg_cent, 4)),
110
+ )
111
+
112
+ # v3.4.1: Persist community labels to JSON sidecar
113
+ try:
114
+ from pathlib import Path as _Path
115
+ labels_dir = _Path.home() / ".superlocalmemory"
116
+ labels_dir.mkdir(parents=True, exist_ok=True)
117
+ labels_path = labels_dir / f"{profile_id}_community_labels.json"
118
+ labels_path.write_text(json.dumps(labels, indent=2))
119
+ except Exception:
120
+ pass
121
+
122
+ top_5 = sorted(
123
+ pagerank.items(), key=lambda x: x[1], reverse=True,
124
+ )[:5]
125
+ unique_communities = len(
126
+ set(c for c in communities.values() if c is not None),
127
+ )
128
+
129
+ bridge_count = len(
130
+ [s for s in bridge_scores.values() if s > 0.1],
131
+ )
132
+ top_bridges = sorted(
133
+ bridge_scores.items(), key=lambda x: -x[1],
134
+ )[:5]
135
+
136
+ logger.info(
137
+ "GraphAnalyzer: %d nodes, %d communities, %d bridges, "
138
+ "labels=%s",
139
+ graph.number_of_nodes(), unique_communities,
140
+ bridge_count, labels,
141
+ )
142
+
143
+ return {
144
+ "node_count": graph.number_of_nodes(),
145
+ "edge_count": graph.number_of_edges(),
146
+ "community_count": unique_communities,
147
+ "top_5_nodes": [
148
+ (nid, round(score, 4)) for nid, score in top_5
149
+ ],
150
+ "bridge_count": bridge_count,
151
+ "top_bridge_nodes": [
152
+ (nid, round(s, 4)) for nid, s in top_bridges
153
+ ],
154
+ "community_labels": labels,
155
+ }
156
+ except Exception as exc:
157
+ logger.debug("GraphAnalyzer.compute_and_store failed: %s", exc)
158
+ return {
159
+ "node_count": 0,
160
+ "edge_count": 0,
161
+ "community_count": 0,
162
+ "top_5_nodes": [],
163
+ }
164
+
165
+ def compute_pagerank(
166
+ self,
167
+ graph: Any = None,
168
+ profile_id: str = "",
169
+ alpha: float = 0.85,
170
+ ) -> dict[str, float]:
171
+ """Compute PageRank using networkx.
172
+
173
+ alpha = damping factor (0.85 is standard).
174
+ """
175
+ import networkx as nx
176
+
177
+ if graph is None:
178
+ graph = self._build_networkx_graph(profile_id)
179
+ if graph.number_of_nodes() == 0:
180
+ return {}
181
+ try:
182
+ return nx.pagerank(graph, alpha=alpha, weight="weight")
183
+ except nx.PowerIterationFailedConvergence:
184
+ return nx.pagerank(graph, alpha=alpha, weight=None)
185
+
186
+ def detect_communities(
187
+ self,
188
+ graph: Any = None,
189
+ profile_id: str = "",
190
+ ) -> dict[str, int]:
191
+ """Detect communities via Label Propagation.
192
+
193
+ O(m) where m = edges (fast), no parameter tuning needed.
194
+ """
195
+ import networkx as nx
196
+ from networkx.algorithms.community import (
197
+ label_propagation_communities,
198
+ )
199
+
200
+ if graph is None:
201
+ graph = self._build_networkx_graph(profile_id)
202
+ if graph.number_of_nodes() == 0:
203
+ return {}
204
+
205
+ # Label propagation needs undirected graph
206
+ undirected = graph.to_undirected()
207
+ communities_gen = label_propagation_communities(undirected)
208
+ result: dict[str, int] = {}
209
+ for comm_id, community in enumerate(communities_gen):
210
+ for node in community:
211
+ result[node] = comm_id
212
+ return result
213
+
214
+ # ── v3.4.1: Leiden Community Detection ────────────────────────
215
+
216
+ def detect_communities_leiden(
217
+ self,
218
+ graph: Any = None,
219
+ profile_id: str = "",
220
+ resolution: float = 1.0,
221
+ ) -> dict[str, int]:
222
+ """Leiden community detection (higher quality than Label Propagation).
223
+
224
+ Falls back to detect_communities() (Label Propagation) if
225
+ leidenalg or igraph are not installed.
226
+ """
227
+ if graph is None:
228
+ graph = self._build_networkx_graph(profile_id)
229
+ if graph.number_of_nodes() == 0:
230
+ return {}
231
+
232
+ try:
233
+ import leidenalg
234
+ import igraph
235
+ except ImportError:
236
+ logger.info(
237
+ "leidenalg not installed, using Label Propagation fallback",
238
+ )
239
+ return self.detect_communities(graph, profile_id)
240
+
241
+ # Convert DiGraph -> undirected -> igraph
242
+ undirected = graph.to_undirected()
243
+ node_list = list(undirected.nodes())
244
+ node_index = {n: i for i, n in enumerate(node_list)}
245
+
246
+ ig = igraph.Graph(n=len(node_list), directed=False)
247
+ edges = []
248
+ weights = []
249
+ for u, v in undirected.edges():
250
+ if u in node_index and v in node_index:
251
+ edges.append((node_index[u], node_index[v]))
252
+ weights.append(undirected[u][v].get("weight", 1.0))
253
+
254
+ ig.add_edges(edges)
255
+ ig.es["weight"] = weights
256
+ ig.simplify(combine_edges={"weight": "max"})
257
+
258
+ partition = leidenalg.find_partition(
259
+ ig,
260
+ leidenalg.RBConfigurationVertexPartition,
261
+ resolution_parameter=resolution,
262
+ weights="weight",
263
+ )
264
+
265
+ result: dict[str, int] = {}
266
+ for idx, comm_id in enumerate(partition.membership):
267
+ result[node_list[idx]] = comm_id
268
+
269
+ logger.info(
270
+ "Leiden detected %d communities (resolution=%.1f)",
271
+ len(set(result.values())), resolution,
272
+ )
273
+ return result
274
+
275
+ # ── v3.4.1: TF-IDF Community Labels ─────────────────────────
276
+
277
+ def compute_community_labels(
278
+ self,
279
+ profile_id: str,
280
+ communities: dict[str, int],
281
+ ) -> dict[int, str]:
282
+ """Generate human-readable labels via TF-IDF on fact content.
283
+
284
+ Returns dict mapping community_id to label string.
285
+ Labels stored in config table for API access.
286
+ """
287
+ if not communities:
288
+ return {}
289
+
290
+ # Group fact_ids by community
291
+ comm_facts: dict[int, list[str]] = defaultdict(list)
292
+ for fact_id, comm_id in communities.items():
293
+ comm_facts[comm_id].append(fact_id)
294
+
295
+ stopwords = frozenset({
296
+ "the", "a", "an", "is", "was", "were", "are", "be", "been",
297
+ "being", "have", "has", "had", "do", "does", "did", "will",
298
+ "would", "could", "should", "may", "might", "shall", "can",
299
+ "to", "of", "in", "for", "on", "with", "at", "by", "from",
300
+ "as", "into", "through", "during", "before", "after", "above",
301
+ "below", "between", "and", "but", "or", "not", "no", "nor",
302
+ "so", "yet", "both", "either", "neither", "this", "that",
303
+ "these", "those", "it", "its", "they", "them", "their",
304
+ "he", "she", "his", "her", "we", "our", "you", "your",
305
+ "i", "my", "me",
306
+ })
307
+
308
+ # Fetch content for each community
309
+ tf_per_comm: dict[int, Counter] = {}
310
+ for comm_id, fact_ids in comm_facts.items():
311
+ placeholders = ",".join("?" * len(fact_ids))
312
+ sql = (
313
+ "SELECT content FROM atomic_facts WHERE fact_id IN ("
314
+ + placeholders
315
+ + ") AND profile_id = ?"
316
+ )
317
+ try:
318
+ rows = self._db.execute(sql, (*fact_ids, profile_id))
319
+ texts = [dict(r).get("content", "") for r in rows]
320
+ except Exception:
321
+ texts = []
322
+
323
+ tokens: list[str] = []
324
+ for text in texts:
325
+ for word in text.lower().split():
326
+ w = word.strip(".,;:!?\"'()[]{}")
327
+ if len(w) > 2 and w not in stopwords:
328
+ tokens.append(w)
329
+ tf_per_comm[comm_id] = Counter(tokens)
330
+
331
+ num_communities = len(comm_facts)
332
+ labels: dict[int, str] = {}
333
+
334
+ if num_communities == 1:
335
+ # Single community: use raw term frequency
336
+ for comm_id, tf in tf_per_comm.items():
337
+ top = [w for w, _ in tf.most_common(3)]
338
+ labels[comm_id] = ", ".join(top) if top else f"Community {comm_id}"
339
+ else:
340
+ # Compute IDF across communities
341
+ doc_freq: Counter = Counter()
342
+ for tf in tf_per_comm.values():
343
+ for term in tf:
344
+ doc_freq[term] += 1
345
+
346
+ for comm_id, tf in tf_per_comm.items():
347
+ scored = []
348
+ for term, count in tf.items():
349
+ idf = log(1 + num_communities / (1 + doc_freq[term]))
350
+ scored.append((term, count * idf))
351
+ scored.sort(key=lambda x: x[1], reverse=True)
352
+ top = [w for w, _ in scored[:3]]
353
+ labels[comm_id] = ", ".join(top) if top else f"Community {comm_id}"
354
+
355
+ # Store in config table
356
+ try:
357
+ key = "community_labels_" + profile_id
358
+ value = json.dumps(labels)
359
+ self._db.execute(
360
+ "INSERT OR REPLACE INTO config (key, value, updated_at) "
361
+ "VALUES (?, ?, datetime('now'))",
362
+ (key, value),
363
+ )
364
+ except Exception as exc:
365
+ logger.warning("Failed to store community labels: %s", exc)
366
+
367
+ return labels
368
+
369
+ # ── v3.4.1: Bridge Score Detection ───────────────────────────
370
+
371
+ def compute_bridge_scores(self, graph: Any) -> dict[str, float]:
372
+ """Identify bridge nodes via betweenness centrality.
373
+
374
+ Returns dict mapping node_id to bridge_score (0.0 to 1.0).
375
+ NOT persisted to DB (no column exists) -- used in summary only.
376
+ """
377
+ import networkx as nx
378
+
379
+ if graph.number_of_nodes() <= 2:
380
+ return {}
381
+ return nx.betweenness_centrality(
382
+ graph, weight="weight", normalized=True,
383
+ )
384
+
385
+ def _compute_degree_centrality(
386
+ self, graph: Any,
387
+ ) -> dict[str, float]:
388
+ """Degree centrality: fraction of nodes each node connects to."""
389
+ import networkx as nx
390
+
391
+ if graph.number_of_nodes() <= 1:
392
+ return {n: 0.0 for n in graph.nodes()}
393
+ return nx.degree_centrality(graph)
394
+
395
+ def _build_networkx_graph(self, profile_id: str) -> Any:
396
+ """Build networkx DiGraph from BOTH graph_edges + association_edges."""
397
+ import networkx as nx
398
+
399
+ g = nx.DiGraph()
400
+
401
+ # graph_edges
402
+ try:
403
+ rows = self._db.execute(
404
+ "SELECT source_id, target_id, weight, edge_type "
405
+ "FROM graph_edges WHERE profile_id = ?",
406
+ (profile_id,),
407
+ )
408
+ for row in rows:
409
+ d = dict(row)
410
+ g.add_edge(
411
+ d["source_id"], d["target_id"],
412
+ weight=d["weight"], edge_type=d["edge_type"],
413
+ )
414
+ except Exception as exc:
415
+ logger.debug("graph_edges read failed: %s", exc)
416
+
417
+ # association_edges
418
+ try:
419
+ rows = self._db.execute(
420
+ "SELECT source_fact_id, target_fact_id, weight, "
421
+ " association_type "
422
+ "FROM association_edges WHERE profile_id = ?",
423
+ (profile_id,),
424
+ )
425
+ for row in rows:
426
+ d = dict(row)
427
+ src, tgt = d["source_fact_id"], d["target_fact_id"]
428
+ if g.has_edge(src, tgt):
429
+ existing_w = g[src][tgt].get("weight", 0)
430
+ if d["weight"] > existing_w:
431
+ g[src][tgt]["weight"] = d["weight"]
432
+ else:
433
+ g.add_edge(
434
+ src, tgt,
435
+ weight=d["weight"],
436
+ edge_type=d["association_type"],
437
+ )
438
+ except Exception as exc:
439
+ logger.debug("association_edges read failed: %s", exc)
440
+
441
+ return g