superlocalmemory 3.3.2__tar.gz → 3.3.6__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 (220) hide show
  1. {superlocalmemory-3.3.2/src/superlocalmemory.egg-info → superlocalmemory-3.3.6}/PKG-INFO +3 -2
  2. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/README.md +2 -1
  3. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/pyproject.toml +5 -1
  4. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/commands.py +150 -13
  5. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/main.py +25 -0
  6. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/config.py +12 -9
  7. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/maintenance.py +111 -5
  8. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/store_pipeline.py +24 -0
  9. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/worker_pool.py +9 -2
  10. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/cognitive_consolidator.py +19 -1
  11. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/emotional.py +5 -2
  12. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/entity_resolver.py +1 -1
  13. superlocalmemory-3.3.6/src/superlocalmemory/hooks/claude_code_hooks.py +404 -0
  14. superlocalmemory-3.3.6/src/superlocalmemory/hooks/hook_handlers.py +394 -0
  15. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/polar_quant.py +3 -1
  16. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/engine.py +36 -8
  17. superlocalmemory-3.3.6/src/superlocalmemory/retrieval/reranker.py +332 -0
  18. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/embedding_migrator.py +4 -3
  19. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6/src/superlocalmemory.egg-info}/PKG-INFO +3 -2
  20. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory.egg-info/SOURCES.txt +3 -0
  21. superlocalmemory-3.3.6/tests/test_claude_hooks.py +792 -0
  22. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_cli_v33.py +3 -2
  23. superlocalmemory-3.3.6/tests/test_hook_handlers.py +991 -0
  24. superlocalmemory-3.3.2/src/superlocalmemory/hooks/claude_code_hooks.py +0 -175
  25. superlocalmemory-3.3.2/src/superlocalmemory/retrieval/reranker.py +0 -255
  26. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/AUTHORS.md +0 -0
  27. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/LICENSE +0 -0
  28. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/NOTICE +0 -0
  29. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/setup.cfg +0 -0
  30. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/__init__.py +0 -0
  31. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/attribution/__init__.py +0 -0
  32. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/attribution/mathematical_dna.py +0 -0
  33. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/attribution/signer.py +0 -0
  34. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/attribution/watermark.py +0 -0
  35. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/__init__.py +0 -0
  36. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/json_output.py +0 -0
  37. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/migrate_cmd.py +0 -0
  38. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/post_install.py +0 -0
  39. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/cli/setup_wizard.py +0 -0
  40. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/__init__.py +0 -0
  41. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/abac.py +0 -0
  42. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/audit.py +0 -0
  43. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/eu_ai_act.py +0 -0
  44. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/gdpr.py +0 -0
  45. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/lifecycle.py +0 -0
  46. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/retention.py +0 -0
  47. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/compliance/scheduler.py +0 -0
  48. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/__init__.py +0 -0
  49. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/consolidation_engine.py +0 -0
  50. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/embedding_worker.py +0 -0
  51. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/embeddings.py +0 -0
  52. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/engine.py +0 -0
  53. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/engine_wiring.py +0 -0
  54. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/graph_analyzer.py +0 -0
  55. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/hooks.py +0 -0
  56. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/modes.py +0 -0
  57. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/ollama_embedder.py +0 -0
  58. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/profiles.py +0 -0
  59. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/recall_pipeline.py +0 -0
  60. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/recall_worker.py +0 -0
  61. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/registry.py +0 -0
  62. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/core/summarizer.py +0 -0
  63. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/dynamics/__init__.py +0 -0
  64. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -0
  65. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/dynamics/eap_scheduler.py +0 -0
  66. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -0
  67. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -0
  68. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/__init__.py +0 -0
  69. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/auto_linker.py +0 -0
  70. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/consolidator.py +0 -0
  71. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/context_generator.py +0 -0
  72. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/entropy_gate.py +0 -0
  73. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/fact_extractor.py +0 -0
  74. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/foresight.py +0 -0
  75. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/graph_builder.py +0 -0
  76. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/observation_builder.py +0 -0
  77. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/scene_builder.py +0 -0
  78. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/signal_inference.py +0 -0
  79. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/temporal_parser.py +0 -0
  80. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/temporal_validator.py +0 -0
  81. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/encoding/type_router.py +0 -0
  82. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/__init__.py +0 -0
  83. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/auto_capture.py +0 -0
  84. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/auto_invoker.py +0 -0
  85. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/auto_parameterize.py +0 -0
  86. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/auto_recall.py +0 -0
  87. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/ide_connector.py +0 -0
  88. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/hooks/rules_engine.py +0 -0
  89. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/__init__.py +0 -0
  90. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/auth_middleware.py +0 -0
  91. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/backup.py +0 -0
  92. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/cache_manager.py +0 -0
  93. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/event_bus.py +0 -0
  94. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/heartbeat_monitor.py +0 -0
  95. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/pid_manager.py +0 -0
  96. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/process_reaper.py +0 -0
  97. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/rate_limiter.py +0 -0
  98. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/infra/webhook_dispatcher.py +0 -0
  99. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/__init__.py +0 -0
  100. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/adaptive.py +0 -0
  101. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/behavioral.py +0 -0
  102. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/behavioral_listener.py +0 -0
  103. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/bootstrap.py +0 -0
  104. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -0
  105. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/consolidation_worker.py +0 -0
  106. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/cross_project.py +0 -0
  107. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/database.py +0 -0
  108. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/engagement.py +0 -0
  109. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/features.py +0 -0
  110. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/feedback.py +0 -0
  111. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/forgetting_scheduler.py +0 -0
  112. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/outcomes.py +0 -0
  113. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/project_context.py +0 -0
  114. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/quantization_scheduler.py +0 -0
  115. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/ranker.py +0 -0
  116. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/signals.py +0 -0
  117. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/source_quality.py +0 -0
  118. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/learning/workflows.py +0 -0
  119. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/llm/__init__.py +0 -0
  120. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/llm/backbone.py +0 -0
  121. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/__init__.py +0 -0
  122. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/ebbinghaus.py +0 -0
  123. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/fisher.py +0 -0
  124. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/fisher_quantized.py +0 -0
  125. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/hopfield.py +0 -0
  126. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/langevin.py +0 -0
  127. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/qjl.py +0 -0
  128. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/math/sheaf.py +0 -0
  129. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/__init__.py +0 -0
  130. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/resources.py +0 -0
  131. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/server.py +0 -0
  132. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools.py +0 -0
  133. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools_active.py +0 -0
  134. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools_core.py +0 -0
  135. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools_v28.py +0 -0
  136. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools_v3.py +0 -0
  137. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/mcp/tools_v33.py +0 -0
  138. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/__init__.py +0 -0
  139. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/pattern_extractor.py +0 -0
  140. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/pii_filter.py +0 -0
  141. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/prompt_injector.py +0 -0
  142. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -0
  143. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -0
  144. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/__init__.py +0 -0
  145. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/agentic.py +0 -0
  146. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/ann_index.py +0 -0
  147. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/bm25_channel.py +0 -0
  148. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/bridge_discovery.py +0 -0
  149. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/channel_registry.py +0 -0
  150. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/entity_channel.py +0 -0
  151. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/forgetting_filter.py +0 -0
  152. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/fusion.py +0 -0
  153. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/hopfield_channel.py +0 -0
  154. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/profile_channel.py +0 -0
  155. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -0
  156. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/semantic_channel.py +0 -0
  157. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/spreading_activation.py +0 -0
  158. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/strategy.py +0 -0
  159. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/temporal_channel.py +0 -0
  160. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/retrieval/vector_store.py +0 -0
  161. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/__init__.py +0 -0
  162. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/api.py +0 -0
  163. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/__init__.py +0 -0
  164. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/agents.py +0 -0
  165. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/backup.py +0 -0
  166. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/behavioral.py +0 -0
  167. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/compliance.py +0 -0
  168. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/data_io.py +0 -0
  169. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/events.py +0 -0
  170. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/helpers.py +0 -0
  171. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/learning.py +0 -0
  172. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/lifecycle.py +0 -0
  173. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/memories.py +0 -0
  174. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/profiles.py +0 -0
  175. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/stats.py +0 -0
  176. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/v3_api.py +0 -0
  177. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/routes/ws.py +0 -0
  178. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/security_middleware.py +0 -0
  179. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/server/ui.py +0 -0
  180. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/__init__.py +0 -0
  181. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/access_control.py +0 -0
  182. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/access_log.py +0 -0
  183. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/database.py +0 -0
  184. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/migration_v33.py +0 -0
  185. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/migrations.py +0 -0
  186. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/models.py +0 -0
  187. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/quantized_store.py +0 -0
  188. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/schema.py +0 -0
  189. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/schema_v32.py +0 -0
  190. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/storage/v2_migrator.py +0 -0
  191. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/trust/__init__.py +0 -0
  192. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/trust/gate.py +0 -0
  193. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/trust/provenance.py +0 -0
  194. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/trust/scorer.py +0 -0
  195. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory/trust/signals.py +0 -0
  196. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory.egg-info/dependency_links.txt +0 -0
  197. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory.egg-info/entry_points.txt +0 -0
  198. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory.egg-info/requires.txt +0 -0
  199. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/src/superlocalmemory.egg-info/top_level.txt +0 -0
  200. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_auto_hooks.py +0 -0
  201. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_behavioral_full.py +0 -0
  202. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_cli.py +0 -0
  203. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_cli_json.py +0 -0
  204. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_compliance_full.py +0 -0
  205. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_config_system.py +0 -0
  206. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_engine_hooks.py +0 -0
  207. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_event_bus.py +0 -0
  208. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_features.py +0 -0
  209. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_final_locomo_mini.py +0 -0
  210. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_ide_connector.py +0 -0
  211. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_infra.py +0 -0
  212. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_learning_advanced.py +0 -0
  213. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_learning_collectors.py +0 -0
  214. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_llm_provider.py +0 -0
  215. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_mcp_server.py +0 -0
  216. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_migration.py +0 -0
  217. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_post_install.py +0 -0
  218. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_ranker.py +0 -0
  219. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_trust_full.py +0 -0
  220. {superlocalmemory-3.3.2 → superlocalmemory-3.3.6}/tests/test_v3_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: superlocalmemory
3
- Version: 3.3.2
3
+ Version: 3.3.6
4
4
  Summary: Information-geometric agent memory with mathematical guarantees
5
5
  Author-email: Varun Pratap Bhardwaj <admin@superlocalmemory.com>
6
6
  License: MIT
@@ -72,7 +72,8 @@ Dynamic: license-file
72
72
  </p>
73
73
 
74
74
  <h1 align="center">SuperLocalMemory V3.3</h1>
75
- <p align="center"><strong>The first local-only AI memory to break 74% retrieval on LoCoMo.<br/>No cloud. No APIs. No data leaves your machine.</strong></p>
75
+ <p align="center"><strong>Every other AI forgets. Yours won't.</strong><br/><em>Infinite memory for Claude Code, Cursor, Windsurf & 17+ AI tools.</em></p>
76
+ <p align="center"><code>v3.3.6</code> — Install once. Every session remembers the last. Automatically.</p>
76
77
 
77
78
  <p align="center">
78
79
  <code>+16pp vs Mem0 (zero cloud)</code> &nbsp;·&nbsp; <code>85% Open-Domain (best of any system)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
@@ -3,7 +3,8 @@
3
3
  </p>
4
4
 
5
5
  <h1 align="center">SuperLocalMemory V3.3</h1>
6
- <p align="center"><strong>The first local-only AI memory to break 74% retrieval on LoCoMo.<br/>No cloud. No APIs. No data leaves your machine.</strong></p>
6
+ <p align="center"><strong>Every other AI forgets. Yours won't.</strong><br/><em>Infinite memory for Claude Code, Cursor, Windsurf & 17+ AI tools.</em></p>
7
+ <p align="center"><code>v3.3.6</code> — Install once. Every session remembers the last. Automatically.</p>
7
8
 
8
9
  <p align="center">
9
10
  <code>+16pp vs Mem0 (zero cloud)</code> &nbsp;·&nbsp; <code>85% Open-Domain (best of any system)</code> &nbsp;·&nbsp; <code>EU AI Act Ready</code>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.3.2"
3
+ version = "3.3.6"
4
4
  description = "Information-geometric agent memory with mathematical guarantees"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -98,6 +98,10 @@ testpaths = ["tests"]
98
98
  pythonpath = ["src"]
99
99
  markers = [
100
100
  "slow: marks tests as slow (deselect with '-m \"not slow\"')",
101
+ "ollama: marks tests that require a running Ollama instance",
102
+ ]
103
+ filterwarnings = [
104
+ "ignore::DeprecationWarning:vaderSentiment",
101
105
  ]
102
106
 
103
107
  [tool.coverage.run]
@@ -18,7 +18,16 @@ from argparse import Namespace
18
18
 
19
19
  def dispatch(args: Namespace) -> None:
20
20
  """Route CLI command to the appropriate handler."""
21
+ # Auto-install/upgrade hooks on version change (single file read, ~0.1ms)
22
+ if args.command not in ("hooks", "init", "mcp"):
23
+ try:
24
+ from superlocalmemory.hooks.claude_code_hooks import auto_install_if_needed
25
+ auto_install_if_needed()
26
+ except Exception:
27
+ pass
28
+
21
29
  handlers = {
30
+ "init": cmd_init,
22
31
  "setup": cmd_setup,
23
32
  "mode": cmd_mode,
24
33
  "provider": cmd_provider,
@@ -113,6 +122,10 @@ def cmd_mode(args: Namespace) -> None:
113
122
  if (config.embedding.provider != updated.embedding.provider
114
123
  or config.embedding.model_name != updated.embedding.model_name):
115
124
  print(" ⚠ Embedding model changed. Re-indexing will run on next recall.")
125
+
126
+ # V3.3.4: Warn if Mode C lacks cloud API key
127
+ if args.value == "c" and not updated.llm.api_key:
128
+ print(" ⚠ Mode C requires a cloud API key. Run: slm provider set")
116
129
  else:
117
130
  print(f"Current mode: {config.mode.value.upper()}")
118
131
 
@@ -356,12 +369,20 @@ def cmd_forget(args: Namespace) -> None:
356
369
  sys.exit(1)
357
370
  raise
358
371
 
372
+ dry_run = getattr(args, 'dry_run', False)
373
+
359
374
  if use_json:
360
375
  from superlocalmemory.cli.json_output import json_print
361
376
  if not matches:
362
377
  json_print("forget", data={"matched_count": 0, "deleted_count": 0, "matches": []})
363
378
  return
364
379
  match_items = [{"fact_id": f.fact_id, "content": f.content[:120]} for f in matches[:20]]
380
+ if dry_run:
381
+ json_print("forget", data={
382
+ "matched_count": len(matches), "deleted_count": 0,
383
+ "dry_run": True, "matches": match_items,
384
+ })
385
+ return
365
386
  if getattr(args, 'yes', False):
366
387
  for f in matches:
367
388
  engine._db.delete_fact(f.fact_id)
@@ -387,6 +408,9 @@ def cmd_forget(args: Namespace) -> None:
387
408
  print(f"Found {len(matches)} matching memories:")
388
409
  for f in matches[:10]:
389
410
  print(f" - {f.fact_id[:8]}... {f.content[:80]}")
411
+ if dry_run:
412
+ print(f"(dry run — {len(matches)} would be deleted)")
413
+ return
390
414
  if getattr(args, 'yes', False):
391
415
  for f in matches:
392
416
  engine._db.delete_fact(f.fact_id)
@@ -861,7 +885,8 @@ def cmd_trace(args: Namespace) -> None:
861
885
  try:
862
886
  config = SLMConfig.load()
863
887
  engine = MemoryEngine(config)
864
- response = engine.recall(args.query, limit=5)
888
+ limit = getattr(args, 'limit', 10)
889
+ response = engine.recall(args.query, limit=limit)
865
890
  except Exception as exc:
866
891
  if use_json:
867
892
  from superlocalmemory.cli.json_output import json_print
@@ -907,6 +932,14 @@ def cmd_trace(args: Namespace) -> None:
907
932
 
908
933
  def cmd_mcp(_args: Namespace) -> None:
909
934
  """Start the V3 MCP server (stdio transport for IDE integration)."""
935
+ # Auto-install hooks on MCP startup (fast path: ~0.1ms if already current)
936
+ # CRITICAL: No stdout — MCP uses stdio transport, any print corrupts protocol
937
+ try:
938
+ from superlocalmemory.hooks.claude_code_hooks import auto_install_if_needed
939
+ auto_install_if_needed()
940
+ except Exception:
941
+ pass
942
+
910
943
  from superlocalmemory.mcp.server import server
911
944
 
912
945
  server.run(transport="stdio")
@@ -1126,6 +1159,99 @@ def cmd_profile(args: Namespace) -> None:
1126
1159
  # -- Active Memory commands (V3.1) ------------------------------------------
1127
1160
 
1128
1161
 
1162
+ def cmd_init(args: Namespace) -> None:
1163
+ """One-command setup: mode + hooks + IDE connect + warmup."""
1164
+ from pathlib import Path
1165
+ from superlocalmemory.core.config import SLMConfig
1166
+
1167
+ force = getattr(args, "force", False)
1168
+
1169
+ config_exists = (Path.home() / ".superlocalmemory" / "config.json").exists()
1170
+
1171
+ print()
1172
+ print("SuperLocalMemory — One-Time Setup")
1173
+ print("=" * 40)
1174
+
1175
+ # Step 1: Mode selection (interactive)
1176
+ if force or not config_exists:
1177
+ print()
1178
+ from superlocalmemory.cli.setup_wizard import run_wizard
1179
+ run_wizard()
1180
+ else:
1181
+ config = SLMConfig.load()
1182
+ print(f"\n Already configured: Mode {config.mode.value.upper()}")
1183
+ print(f" Profile: {config.active_profile}")
1184
+
1185
+ # Step 2: Install hooks (gate always OFF by default)
1186
+ print()
1187
+ print("Installing Claude Code hooks...")
1188
+ from superlocalmemory.hooks.claude_code_hooks import install_hooks, check_status
1189
+
1190
+ status = check_status()
1191
+
1192
+ if status["installed"] and not force:
1193
+ if status["needs_upgrade"]:
1194
+ from superlocalmemory.hooks.claude_code_hooks import upgrade_hooks
1195
+ result = upgrade_hooks()
1196
+ if result.get("upgraded"):
1197
+ print(f" Hooks upgraded: {result['from_version']} -> {result['to_version']}")
1198
+ else:
1199
+ print(f" Upgrade issue: {result.get('reason', result.get('errors', ''))}")
1200
+ else:
1201
+ print(f" Hooks already installed (v{status['version']})")
1202
+ else:
1203
+ result = install_hooks(include_gate=False)
1204
+ if result["success"]:
1205
+ print(f" Hooks installed: {', '.join(result['hooks_added'])}")
1206
+ print(" SLM: Hooks installed into Claude Code (slm hooks remove to undo)")
1207
+ else:
1208
+ print(f" Hook install failed: {result['errors']}")
1209
+
1210
+ # Step 3: IDE connection
1211
+ print()
1212
+ print("Detecting IDEs...")
1213
+ try:
1214
+ from superlocalmemory.hooks.ide_connector import IDEConnector
1215
+ connector = IDEConnector()
1216
+ results = connector.connect_all()
1217
+ for ide_id, ide_status in results.items():
1218
+ print(f" {ide_id}: {ide_status}")
1219
+ except Exception as exc:
1220
+ print(f" IDE detection skipped: {exc}")
1221
+
1222
+ # Step 4: Warmup (embedding model)
1223
+ print()
1224
+ print("Checking embedding model...")
1225
+ try:
1226
+ from superlocalmemory.core.config import SLMConfig as _Cfg
1227
+ cfg = _Cfg.load()
1228
+ model_name = cfg.embedding.model_name
1229
+ print(f" Model: {model_name}")
1230
+ # Quick check: try creating embedding service (auto-downloads if needed)
1231
+ from superlocalmemory.core.embeddings import EmbeddingService
1232
+ svc = EmbeddingService(cfg.embedding)
1233
+ test_result = svc.embed_text("test")
1234
+ if test_result is not None and len(test_result) > 0:
1235
+ print(" Status: ready")
1236
+ else:
1237
+ print(" Status: model not available (run: slm warmup)")
1238
+ except Exception as exc:
1239
+ print(f" Warmup skipped: {exc}")
1240
+ print(" Run 'slm warmup' later to download the embedding model.")
1241
+
1242
+ # Done
1243
+ print()
1244
+ print("=" * 40)
1245
+ print("SLM is active. Your AI now remembers you.")
1246
+ print()
1247
+ print("What happens next:")
1248
+ print(" - Open Claude Code in any project")
1249
+ print(" - SLM auto-injects your memory context")
1250
+ print(" - Decisions, bugs, preferences are captured automatically")
1251
+ print(" - Session summaries saved when you close")
1252
+ print()
1253
+
1254
+
1129
1255
  def cmd_hooks(args: Namespace) -> None:
1130
1256
  """Manage Claude Code hooks for invisible memory injection."""
1131
1257
  from superlocalmemory.hooks.claude_code_hooks import (
@@ -1133,28 +1259,38 @@ def cmd_hooks(args: Namespace) -> None:
1133
1259
  )
1134
1260
 
1135
1261
  action = getattr(args, "action", "status")
1262
+ # Gate is OFF by default. --gate opts in (for brave users).
1263
+ include_gate = getattr(args, "gate", False)
1264
+
1136
1265
  if action == "install":
1137
- result = install_hooks()
1138
- if result["scripts"] and result["settings"]:
1266
+ result = install_hooks(include_gate=include_gate)
1267
+ if result["success"]:
1139
1268
  print("SLM hooks installed in Claude Code.")
1140
- print("Memory context will auto-inject on every new session.")
1269
+ print(f" Hook types: {', '.join(result['hooks_added'])}")
1270
+ if include_gate:
1271
+ print(" Gate: ON (enforces session_init — experimental)")
1272
+ print(" SLM: Hooks installed into Claude Code (slm hooks remove to undo)")
1141
1273
  else:
1142
- print(f"Installation incomplete: {result['errors']}")
1274
+ print(f"Installation failed: {result['errors']}")
1143
1275
  elif action == "remove":
1144
1276
  result = remove_hooks()
1145
- if result["scripts"] and result["settings"]:
1277
+ if result["success"]:
1146
1278
  print("SLM hooks removed from Claude Code.")
1147
1279
  else:
1148
- print(f"Removal incomplete: {result['errors']}")
1280
+ print(f"Removal failed: {result['errors']}")
1149
1281
  else:
1150
1282
  result = check_status()
1151
1283
  if result["installed"]:
1152
- print("SLM hooks: INSTALLED")
1153
- print(f" Scripts: {result['hooks_dir']}")
1154
- print(" Claude Code settings: configured")
1284
+ print(f"SLM hooks: INSTALLED (v{result['version']})")
1285
+ print(f" Hook types: {', '.join(result['hook_types'])}")
1286
+ print(f" Gate: {'ON' if result['gate_enabled'] else 'OFF'}")
1287
+ if result["needs_upgrade"]:
1288
+ print(f" Update available: {result['version']} -> {result['latest_version']}")
1289
+ print(" Run: slm hooks install")
1155
1290
  else:
1156
1291
  print("SLM hooks: NOT INSTALLED")
1157
1292
  print(" Run: slm hooks install")
1293
+ print(" Or: slm init (full setup)")
1158
1294
 
1159
1295
 
1160
1296
  def cmd_session_context(args: Namespace) -> None:
@@ -1435,6 +1571,7 @@ def cmd_consolidate(args: Namespace) -> None:
1435
1571
 
1436
1572
  use_json = getattr(args, "json", False)
1437
1573
  cognitive = getattr(args, "cognitive", False)
1574
+ dry_run = getattr(args, "dry_run", False)
1438
1575
  profile = getattr(args, "profile", "")
1439
1576
 
1440
1577
  if not cognitive:
@@ -1460,7 +1597,7 @@ def cmd_consolidate(args: Namespace) -> None:
1460
1597
  )
1461
1598
 
1462
1599
  consolidator = CognitiveConsolidator(db=engine._db)
1463
- result = consolidator.run_pipeline(pid)
1600
+ result = consolidator.run_pipeline(pid, dry_run=dry_run)
1464
1601
  except Exception as exc:
1465
1602
  if use_json:
1466
1603
  from superlocalmemory.cli.json_output import json_print
@@ -1473,7 +1610,7 @@ def cmd_consolidate(args: Namespace) -> None:
1473
1610
  if use_json:
1474
1611
  from superlocalmemory.cli.json_output import json_print
1475
1612
  json_print("consolidate", data={
1476
- "clusters_found": result.clusters_found,
1613
+ "clusters_processed": result.clusters_processed,
1477
1614
  "blocks_created": result.blocks_created,
1478
1615
  "facts_archived": result.facts_archived,
1479
1616
  "compression_ratio": round(result.compression_ratio, 3),
@@ -1484,7 +1621,7 @@ def cmd_consolidate(args: Namespace) -> None:
1484
1621
  return
1485
1622
 
1486
1623
  print("CCQ Cognitive Consolidation")
1487
- print(f" Clusters found: {result.clusters_found}")
1624
+ print(f" Clusters processed: {result.clusters_processed}")
1488
1625
  print(f" Blocks created: {result.blocks_created}")
1489
1626
  print(f" Facts archived: {result.facts_archived}")
1490
1627
  print(f" Compression ratio: {result.compression_ratio:.3f}")
@@ -70,6 +70,12 @@ documentation:
70
70
 
71
71
  def main() -> None:
72
72
  """Parse CLI arguments and dispatch to command handlers."""
73
+ # Fast path: hook invocations bypass argparse entirely (stdlib only, ~30ms)
74
+ if len(sys.argv) >= 3 and sys.argv[1] == "hook":
75
+ from superlocalmemory.hooks.hook_handlers import handle_hook
76
+ handle_hook(sys.argv[2])
77
+ return
78
+
73
79
  from superlocalmemory.cli.json_output import _get_version
74
80
  _ver = _get_version()
75
81
 
@@ -85,6 +91,15 @@ def main() -> None:
85
91
  sub = parser.add_subparsers(dest="command", title="commands")
86
92
 
87
93
  # -- Setup & Config ------------------------------------------------
94
+ init_p = sub.add_parser("init", help="One-command setup: mode + hooks + IDE + warmup")
95
+ init_p.add_argument(
96
+ "--force", action="store_true", help="Re-run full setup even if already configured",
97
+ )
98
+ init_p.add_argument(
99
+ "--gate", action="store_true",
100
+ help="Enable PreToolUse gate (experimental — blocks tools until session_init)",
101
+ )
102
+
88
103
  sub.add_parser("setup", help="Interactive first-time setup wizard")
89
104
 
90
105
  mode_p = sub.add_parser("mode", help="Get or set operating mode (a/b/c)")
@@ -123,6 +138,7 @@ def main() -> None:
123
138
 
124
139
  forget_p = sub.add_parser("forget", help="Delete memories matching a query (fuzzy)")
125
140
  forget_p.add_argument("query", help="Query to match for deletion")
141
+ forget_p.add_argument("--dry-run", action="store_true", default=False, help="Preview matches without deleting")
126
142
  forget_p.add_argument("--yes", "-y", action="store_true", help="Skip confirmation prompt")
127
143
  forget_p.add_argument("--json", action="store_true", help="Output structured JSON (agent-native)")
128
144
 
@@ -151,6 +167,7 @@ def main() -> None:
151
167
 
152
168
  trace_p = sub.add_parser("trace", help="Recall with per-channel score breakdown")
153
169
  trace_p.add_argument("query", help="Search query")
170
+ trace_p.add_argument("--limit", type=int, default=10, help="Max results (default 10)")
154
171
  trace_p.add_argument("--json", action="store_true", help="Output structured JSON (agent-native)")
155
172
 
156
173
  # -- Diagnostics (continued) ----------------------------------------
@@ -180,6 +197,10 @@ def main() -> None:
180
197
  "action", nargs="?", default="status",
181
198
  choices=["install", "remove", "status"], help="Action (default: status)",
182
199
  )
200
+ hooks_p.add_argument(
201
+ "--gate", action="store_true",
202
+ help="Enable PreToolUse gate (experimental — blocks tools until session_init)",
203
+ )
183
204
 
184
205
  ctx_p = sub.add_parser("session-context", help="Print session context (for hooks)")
185
206
  ctx_p.add_argument("query", nargs="?", default="", help="Optional context query")
@@ -217,6 +238,10 @@ def main() -> None:
217
238
  "--cognitive", action="store_true",
218
239
  help="Run CCQ cognitive consolidation",
219
240
  )
241
+ consolidate_p.add_argument(
242
+ "--dry-run", action="store_true", default=False,
243
+ help="Preview without applying",
244
+ )
220
245
  consolidate_p.add_argument("--profile", default="", help="Target profile")
221
246
  consolidate_p.add_argument("--json", action="store_true", help="Output structured JSON (agent-native)")
222
247
 
@@ -612,15 +612,15 @@ class SLMConfig:
612
612
 
613
613
  rt = data.get("retrieval", {})
614
614
  if rt:
615
- # V3.3.2 migration: auto-enable ONNX cross-encoder.
616
- # Pre-3.3.2 configs had use_cross_encoder=False because the
617
- # PyTorch cross-encoder used ~1.5GB RAM. With ONNX backend
618
- # (~200MB), it's now safe for all modes. Detect old configs
619
- # by the absence of cross_encoder_backend field.
615
+ # V3.3.2 migration: add ONNX cross-encoder backend field.
616
+ # Pre-3.3.2 configs lacked cross_encoder_backend. Add it,
617
+ # but NEVER override an explicit use_cross_encoder setting.
618
+ # The user's explicit choice always wins.
620
619
  if "cross_encoder_backend" not in rt:
621
- rt["use_cross_encoder"] = True
622
- rt["cross_encoder_model"] = "cross-encoder/ms-marco-MiniLM-L-6-v2"
620
+ rt.setdefault("cross_encoder_model", "cross-encoder/ms-marco-MiniLM-L-6-v2")
623
621
  rt["cross_encoder_backend"] = "onnx"
622
+ # Only auto-enable if user didn't explicitly set the field
623
+ rt.setdefault("use_cross_encoder", True)
624
624
  config.retrieval = RetrievalConfig(**{
625
625
  k: v for k, v in rt.items()
626
626
  if k in RetrievalConfig.__dataclass_fields__
@@ -768,6 +768,9 @@ class SLMConfig:
768
768
  )
769
769
 
770
770
  # Mode C — FULL POWER, UNRESTRICTED
771
+ # Don't carry over local-only providers (ollama) to cloud mode
772
+ c_provider = llm_provider if llm_provider not in ("ollama", "") else "openrouter"
773
+ c_model = llm_model if llm_provider not in ("ollama", "") else "anthropic/claude-sonnet-4"
771
774
  return cls(
772
775
  mode=mode,
773
776
  base_dir=_base,
@@ -779,8 +782,8 @@ class SLMConfig:
779
782
  deployment_name=embedding_deployment,
780
783
  ),
781
784
  llm=LLMConfig(
782
- provider=llm_provider or "azure",
783
- model=llm_model or "gpt-4.1-mini",
785
+ provider=c_provider,
786
+ model=c_model,
784
787
  api_key=llm_api_key,
785
788
  api_base=llm_api_base,
786
789
  ),
@@ -6,6 +6,7 @@
6
6
 
7
7
  Periodic batch processing for mathematical layers:
8
8
  1. Langevin batch_step on all active facts (self-organization)
9
+ 1a. Backfill: seed uninitialized facts with metadata-aware positions (B+C)
9
10
  2. Sheaf batch consistency check on recent facts
10
11
  3. Fisher adaptive temperature recalculation
11
12
 
@@ -18,15 +19,72 @@ License: MIT
18
19
  from __future__ import annotations
19
20
 
20
21
  import logging
22
+ import math as _math
21
23
  from datetime import UTC, datetime, timedelta
22
24
  from typing import TYPE_CHECKING
23
25
 
26
+ import numpy as np
27
+
24
28
  if TYPE_CHECKING:
25
29
  from superlocalmemory.core.config import SLMConfig
26
30
  from superlocalmemory.storage.database import DatabaseManager
27
31
 
28
32
  logger = logging.getLogger(__name__)
29
33
 
34
+ # Backfill constants
35
+ _BACKFILL_BURN_IN_STEPS = 50
36
+ _LANGEVIN_DIM = 8
37
+ _MAX_NORM = 0.99
38
+
39
+
40
+ def _compute_equilibrium_radius(
41
+ access_count: int,
42
+ age_days: float,
43
+ importance: float,
44
+ temperature: float = 0.3,
45
+ dim: int = 8,
46
+ ) -> float:
47
+ """Compute metadata-aware equilibrium radius (Strategy B).
48
+
49
+ Uses the Langevin potential coefficients to estimate where a fact
50
+ would settle if it had been in the dynamics from the start.
51
+
52
+ r_eq ≈ sqrt(T * dim / (2 * effective_alpha))
53
+ """
54
+ alpha, beta, gamma, delta = 3.0, 0.8, 0.005, 0.5
55
+ effective_alpha = (
56
+ alpha
57
+ + beta * _math.log(access_count + 1) / 10.0
58
+ - gamma * min(age_days, 365.0) / 365.0
59
+ + delta * importance
60
+ )
61
+ effective_alpha = max(0.1, effective_alpha)
62
+ r_eq = _math.sqrt(temperature * dim / (2.0 * effective_alpha))
63
+ return min(r_eq, _MAX_NORM * 0.95)
64
+
65
+
66
+ def _seed_langevin_position(
67
+ access_count: int,
68
+ age_days: float,
69
+ importance: float,
70
+ temperature: float = 0.3,
71
+ dim: int = 8,
72
+ ) -> list[float]:
73
+ """Create a metadata-aware initial position (Strategy B).
74
+
75
+ Places the fact at the equilibrium radius with a random direction.
76
+ """
77
+ r_eq = _compute_equilibrium_radius(
78
+ access_count, age_days, importance, temperature, dim,
79
+ )
80
+ rng = np.random.default_rng()
81
+ direction = rng.standard_normal(dim)
82
+ norm = float(np.linalg.norm(direction))
83
+ if norm < 1e-8:
84
+ direction = np.ones(dim)
85
+ norm = float(np.linalg.norm(direction))
86
+ return (direction / norm * r_eq).tolist()
87
+
30
88
 
31
89
  def run_maintenance(
32
90
  db: DatabaseManager,
@@ -44,6 +102,7 @@ def run_maintenance(
44
102
  Dict of counts: langevin_updated, sheaf_checked, etc.
45
103
  """
46
104
  counts: dict[str, int] = {
105
+ "langevin_backfilled": 0,
47
106
  "langevin_updated": 0,
48
107
  "fisher_coupled": 0,
49
108
  "sheaf_checked": 0,
@@ -53,13 +112,60 @@ def run_maintenance(
53
112
  if not facts:
54
113
  return counts
55
114
 
56
- # 1. Langevin batch step
115
+ # 1a. Backfill: seed uninitialized facts with metadata-aware positions (B+C)
116
+ if config.math.langevin_persist_positions:
117
+ try:
118
+ from superlocalmemory.math.langevin import LangevinDynamics
119
+
120
+ ld = LangevinDynamics(
121
+ dim=_LANGEVIN_DIM,
122
+ dt=config.math.langevin_dt,
123
+ temperature=config.math.langevin_temperature,
124
+ )
125
+
126
+ backfilled = 0
127
+ for f in facts:
128
+ if f.langevin_position is not None:
129
+ continue
130
+ created = datetime.fromisoformat(
131
+ f.created_at.replace("Z", "+00:00")
132
+ ) if f.created_at else datetime.now(UTC)
133
+ age_days = max(
134
+ 0.0,
135
+ (datetime.now(UTC) - created).total_seconds() / 86400.0,
136
+ )
137
+ # Strategy B: metadata-aware seed position
138
+ position = _seed_langevin_position(
139
+ f.access_count, age_days, f.importance,
140
+ config.math.langevin_temperature, _LANGEVIN_DIM,
141
+ )
142
+ # Strategy C: burn-in from the seeded position
143
+ for step_i in range(_BACKFILL_BURN_IN_STEPS):
144
+ position, _ = ld.step(
145
+ position, f.access_count, age_days, f.importance,
146
+ )
147
+ weight = ld.compute_lifecycle_weight(position)
148
+ lifecycle = ld.get_lifecycle_state(weight).value
149
+ db.update_fact(f.fact_id, {
150
+ "langevin_position": position,
151
+ "lifecycle": lifecycle,
152
+ })
153
+ f.langevin_position = position # update in-memory for step 1b
154
+ backfilled += 1
155
+
156
+ counts["langevin_backfilled"] = backfilled
157
+ if backfilled:
158
+ logger.info("Langevin backfill: %d facts initialized", backfilled)
159
+ except Exception as exc:
160
+ logger.warning("Langevin backfill failed: %s", exc)
161
+
162
+ # 1b. Langevin batch step on all positioned facts
57
163
  if config.math.langevin_persist_positions:
58
164
  try:
59
165
  from superlocalmemory.math.langevin import LangevinDynamics
60
166
 
61
167
  ld = LangevinDynamics(
62
- dim=8,
168
+ dim=_LANGEVIN_DIM,
63
169
  dt=config.math.langevin_dt,
64
170
  temperature=config.math.langevin_temperature,
65
171
  )
@@ -165,8 +271,8 @@ def run_maintenance(
165
271
  logger.warning("Sheaf maintenance failed: %s", exc)
166
272
 
167
273
  logger.info(
168
- "Maintenance complete: %d Langevin, %d Fisher-coupled, %d Sheaf",
169
- counts["langevin_updated"], counts["fisher_coupled"],
170
- counts["sheaf_checked"],
274
+ "Maintenance complete: %d backfilled, %d Langevin, %d Fisher-coupled, %d Sheaf",
275
+ counts["langevin_backfilled"], counts["langevin_updated"],
276
+ counts["fisher_coupled"], counts["sheaf_checked"],
171
277
  )
172
278
  return counts
@@ -25,6 +25,25 @@ from superlocalmemory.storage.models import (
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
 
28
+ # Langevin initialization radius for new facts (ACTIVE zone < 0.3)
29
+ _INIT_LANGEVIN_RADIUS = 0.05
30
+
31
+
32
+ def _init_langevin_position(dim: int = 8) -> list[float]:
33
+ """Initialize Langevin position near origin for a new fact.
34
+
35
+ Small random perturbation ensures each fact gets a unique position
36
+ while staying deep in the ACTIVE zone (radius < 0.3).
37
+ """
38
+ import numpy as np
39
+ rng = np.random.default_rng()
40
+ direction = rng.standard_normal(dim)
41
+ norm = float(np.linalg.norm(direction))
42
+ if norm < 1e-8:
43
+ direction = np.ones(dim)
44
+ norm = float(np.linalg.norm(direction))
45
+ return (direction / norm * _INIT_LANGEVIN_RADIUS).tolist()
46
+
28
47
 
29
48
  # ---------------------------------------------------------------------------
30
49
  # enrich_fact (was MemoryEngine._enrich_fact)
@@ -59,6 +78,10 @@ def enrich_fact(
59
78
  emotion = tag_emotion(fact.content)
60
79
  signal = infer_signal(fact.content)
61
80
 
81
+ # Strategy A: initialize Langevin position near origin (ACTIVE zone).
82
+ # New facts start as ACTIVE; dynamics will evolve them based on access patterns.
83
+ langevin_pos = _init_langevin_position(dim=8)
84
+
62
85
  return AtomicFact(
63
86
  fact_id=fact.fact_id, memory_id=record.memory_id,
64
87
  profile_id=profile_id, content=fact.content,
@@ -73,6 +96,7 @@ def enrich_fact(
73
96
  evidence_count=fact.evidence_count,
74
97
  source_turn_ids=fact.source_turn_ids, session_id=record.session_id,
75
98
  embedding=embedding, fisher_mean=fisher_mean, fisher_variance=fisher_variance,
99
+ langevin_position=langevin_pos,
76
100
  emotional_valence=emotion.valence, emotional_arousal=emotion.arousal,
77
101
  signal_type=signal, created_at=fact.created_at,
78
102
  )
@@ -142,8 +142,15 @@ class WorkerPool:
142
142
  # ------------------------------------------------------------------
143
143
 
144
144
  def _send(self, request: dict) -> dict:
145
- """Send request to worker and get response. Thread-safe."""
146
- return self._send_with_timeout(request, timeout=_REQUEST_TIMEOUT)
145
+ """Send request to worker and get response. Thread-safe.
146
+
147
+ Auto-retries once on worker death (idle timeout, crash).
148
+ """
149
+ resp = self._send_with_timeout(request, timeout=_REQUEST_TIMEOUT)
150
+ if not resp.get("ok") and "Worker" in resp.get("error", ""):
151
+ logger.info("Auto-restarting worker after failure, retrying request")
152
+ resp = self._send_with_timeout(request, timeout=_REQUEST_TIMEOUT)
153
+ return resp
147
154
 
148
155
  def _send_with_timeout(self, request: dict, timeout: float) -> dict:
149
156
  """Send request with configurable timeout. Thread-safe."""