superlocalmemory 3.4.5 → 3.4.8

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 (232) hide show
  1. package/ide/hooks/tool-event-hook.sh +46 -0
  2. package/package.json +1 -1
  3. package/pyproject.toml +1 -1
  4. package/src/superlocalmemory/attribution/mathematical_dna.py +1 -1
  5. package/src/superlocalmemory/attribution/signer.py +1 -1
  6. package/src/superlocalmemory/attribution/watermark.py +1 -1
  7. package/src/superlocalmemory/cli/__init__.py +1 -1
  8. package/src/superlocalmemory/cli/commands.py +9 -1
  9. package/src/superlocalmemory/cli/daemon.py +57 -27
  10. package/src/superlocalmemory/cli/ingest_cmd.py +261 -0
  11. package/src/superlocalmemory/cli/json_output.py +1 -1
  12. package/src/superlocalmemory/cli/main.py +21 -1
  13. package/src/superlocalmemory/cli/migrate_cmd.py +1 -1
  14. package/src/superlocalmemory/cli/pending_store.py +1 -1
  15. package/src/superlocalmemory/cli/post_install.py +1 -1
  16. package/src/superlocalmemory/cli/service_installer.py +1 -1
  17. package/src/superlocalmemory/cli/setup_wizard.py +1 -1
  18. package/src/superlocalmemory/code_graph/__init__.py +1 -1
  19. package/src/superlocalmemory/code_graph/blast_radius.py +1 -1
  20. package/src/superlocalmemory/code_graph/bridge/__init__.py +1 -1
  21. package/src/superlocalmemory/code_graph/bridge/entity_resolver.py +1 -1
  22. package/src/superlocalmemory/code_graph/bridge/event_listeners.py +1 -1
  23. package/src/superlocalmemory/code_graph/bridge/fact_enricher.py +1 -1
  24. package/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +1 -1
  25. package/src/superlocalmemory/code_graph/bridge/temporal_checker.py +1 -1
  26. package/src/superlocalmemory/code_graph/changes.py +1 -1
  27. package/src/superlocalmemory/code_graph/communities.py +1 -1
  28. package/src/superlocalmemory/code_graph/config.py +1 -1
  29. package/src/superlocalmemory/code_graph/database.py +1 -1
  30. package/src/superlocalmemory/code_graph/extractors/__init__.py +1 -1
  31. package/src/superlocalmemory/code_graph/extractors/python.py +1 -1
  32. package/src/superlocalmemory/code_graph/extractors/typescript.py +1 -1
  33. package/src/superlocalmemory/code_graph/flows.py +1 -1
  34. package/src/superlocalmemory/code_graph/git_hooks.py +1 -1
  35. package/src/superlocalmemory/code_graph/graph_engine.py +1 -1
  36. package/src/superlocalmemory/code_graph/graph_store.py +1 -1
  37. package/src/superlocalmemory/code_graph/incremental.py +1 -1
  38. package/src/superlocalmemory/code_graph/models.py +1 -1
  39. package/src/superlocalmemory/code_graph/parser.py +1 -1
  40. package/src/superlocalmemory/code_graph/resolver.py +1 -1
  41. package/src/superlocalmemory/code_graph/search.py +1 -1
  42. package/src/superlocalmemory/code_graph/service.py +1 -1
  43. package/src/superlocalmemory/code_graph/watcher.py +1 -1
  44. package/src/superlocalmemory/compliance/abac.py +1 -1
  45. package/src/superlocalmemory/compliance/audit.py +1 -1
  46. package/src/superlocalmemory/compliance/eu_ai_act.py +1 -1
  47. package/src/superlocalmemory/compliance/gdpr.py +1 -1
  48. package/src/superlocalmemory/compliance/lifecycle.py +1 -1
  49. package/src/superlocalmemory/compliance/retention.py +1 -1
  50. package/src/superlocalmemory/compliance/scheduler.py +1 -1
  51. package/src/superlocalmemory/core/config.py +1 -1
  52. package/src/superlocalmemory/core/consolidation_engine.py +52 -1
  53. package/src/superlocalmemory/core/embedding_worker.py +1 -1
  54. package/src/superlocalmemory/core/embeddings.py +1 -1
  55. package/src/superlocalmemory/core/engine.py +17 -1
  56. package/src/superlocalmemory/core/engine_wiring.py +21 -1
  57. package/src/superlocalmemory/core/graph_analyzer.py +15 -1
  58. package/src/superlocalmemory/core/health_monitor.py +1 -1
  59. package/src/superlocalmemory/core/hooks.py +1 -1
  60. package/src/superlocalmemory/core/maintenance.py +1 -1
  61. package/src/superlocalmemory/core/maintenance_scheduler.py +1 -1
  62. package/src/superlocalmemory/core/modes.py +1 -1
  63. package/src/superlocalmemory/core/ollama_embedder.py +1 -1
  64. package/src/superlocalmemory/core/profiles.py +1 -1
  65. package/src/superlocalmemory/core/recall_pipeline.py +16 -3
  66. package/src/superlocalmemory/core/recall_worker.py +1 -1
  67. package/src/superlocalmemory/core/registry.py +1 -1
  68. package/src/superlocalmemory/core/reranker_worker.py +1 -1
  69. package/src/superlocalmemory/core/store_pipeline.py +1 -1
  70. package/src/superlocalmemory/core/summarizer.py +1 -1
  71. package/src/superlocalmemory/core/worker_pool.py +1 -1
  72. package/src/superlocalmemory/dynamics/activation_guided_quantization.py +1 -1
  73. package/src/superlocalmemory/dynamics/eap_scheduler.py +1 -1
  74. package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +1 -1
  75. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +1 -1
  76. package/src/superlocalmemory/encoding/auto_linker.py +1 -1
  77. package/src/superlocalmemory/encoding/cognitive_consolidator.py +1 -1
  78. package/src/superlocalmemory/encoding/consolidator.py +1 -1
  79. package/src/superlocalmemory/encoding/context_generator.py +1 -1
  80. package/src/superlocalmemory/encoding/emotional.py +1 -1
  81. package/src/superlocalmemory/encoding/entity_resolver.py +45 -6
  82. package/src/superlocalmemory/encoding/entropy_gate.py +1 -1
  83. package/src/superlocalmemory/encoding/fact_extractor.py +1 -1
  84. package/src/superlocalmemory/encoding/foresight.py +1 -1
  85. package/src/superlocalmemory/encoding/graph_builder.py +1 -1
  86. package/src/superlocalmemory/encoding/observation_builder.py +1 -1
  87. package/src/superlocalmemory/encoding/scene_builder.py +1 -1
  88. package/src/superlocalmemory/encoding/signal_inference.py +1 -1
  89. package/src/superlocalmemory/encoding/temporal_parser.py +1 -1
  90. package/src/superlocalmemory/encoding/temporal_validator.py +1 -1
  91. package/src/superlocalmemory/encoding/type_router.py +1 -1
  92. package/src/superlocalmemory/hooks/__init__.py +1 -1
  93. package/src/superlocalmemory/hooks/auto_capture.py +1 -1
  94. package/src/superlocalmemory/hooks/auto_invoker.py +1 -1
  95. package/src/superlocalmemory/hooks/auto_parameterize.py +1 -1
  96. package/src/superlocalmemory/hooks/auto_recall.py +1 -1
  97. package/src/superlocalmemory/hooks/claude_code_hooks.py +1 -1
  98. package/src/superlocalmemory/hooks/hook_handlers.py +1 -1
  99. package/src/superlocalmemory/hooks/ide_connector.py +1 -1
  100. package/src/superlocalmemory/hooks/rules_engine.py +1 -1
  101. package/src/superlocalmemory/infra/__init__.py +1 -1
  102. package/src/superlocalmemory/infra/auth_middleware.py +1 -1
  103. package/src/superlocalmemory/infra/backup.py +1 -1
  104. package/src/superlocalmemory/infra/cache_manager.py +1 -1
  105. package/src/superlocalmemory/infra/event_bus.py +1 -1
  106. package/src/superlocalmemory/infra/heartbeat_monitor.py +1 -1
  107. package/src/superlocalmemory/infra/pid_manager.py +1 -1
  108. package/src/superlocalmemory/infra/process_reaper.py +1 -1
  109. package/src/superlocalmemory/infra/rate_limiter.py +1 -1
  110. package/src/superlocalmemory/infra/webhook_dispatcher.py +1 -1
  111. package/src/superlocalmemory/ingestion/__init__.py +1 -1
  112. package/src/superlocalmemory/ingestion/adapter_manager.py +1 -1
  113. package/src/superlocalmemory/ingestion/base_adapter.py +1 -1
  114. package/src/superlocalmemory/ingestion/calendar_adapter.py +1 -1
  115. package/src/superlocalmemory/ingestion/credentials.py +1 -1
  116. package/src/superlocalmemory/ingestion/gmail_adapter.py +1 -1
  117. package/src/superlocalmemory/ingestion/parsers.py +1 -1
  118. package/src/superlocalmemory/ingestion/transcript_adapter.py +1 -1
  119. package/src/superlocalmemory/learning/adaptive.py +1 -1
  120. package/src/superlocalmemory/learning/assertion_miner.py +403 -0
  121. package/src/superlocalmemory/learning/behavioral.py +1 -1
  122. package/src/superlocalmemory/learning/behavioral_listener.py +1 -1
  123. package/src/superlocalmemory/learning/bootstrap.py +1 -1
  124. package/src/superlocalmemory/learning/consolidation_quantization_worker.py +1 -1
  125. package/src/superlocalmemory/learning/consolidation_worker.py +25 -9
  126. package/src/superlocalmemory/learning/cross_project.py +1 -1
  127. package/src/superlocalmemory/learning/database.py +1 -1
  128. package/src/superlocalmemory/learning/engagement.py +2 -3
  129. package/src/superlocalmemory/learning/entity_compiler.py +1 -1
  130. package/src/superlocalmemory/learning/features.py +1 -1
  131. package/src/superlocalmemory/learning/forgetting_scheduler.py +1 -1
  132. package/src/superlocalmemory/learning/outcomes.py +1 -1
  133. package/src/superlocalmemory/learning/project_context.py +1 -1
  134. package/src/superlocalmemory/learning/quantization_scheduler.py +1 -1
  135. package/src/superlocalmemory/learning/ranker.py +1 -1
  136. package/src/superlocalmemory/learning/signals.py +1 -1
  137. package/src/superlocalmemory/learning/workflows.py +1 -1
  138. package/src/superlocalmemory/llm/backbone.py +1 -1
  139. package/src/superlocalmemory/math/ebbinghaus.py +1 -1
  140. package/src/superlocalmemory/math/fisher.py +1 -1
  141. package/src/superlocalmemory/math/fisher_quantized.py +1 -1
  142. package/src/superlocalmemory/math/hopfield.py +1 -1
  143. package/src/superlocalmemory/math/langevin.py +1 -1
  144. package/src/superlocalmemory/math/polar_quant.py +1 -1
  145. package/src/superlocalmemory/math/qjl.py +1 -1
  146. package/src/superlocalmemory/math/sheaf.py +1 -1
  147. package/src/superlocalmemory/math/turbo_quant.py +1 -1
  148. package/src/superlocalmemory/mcp/resources.py +1 -1
  149. package/src/superlocalmemory/mcp/server.py +17 -2
  150. package/src/superlocalmemory/mcp/shared.py +1 -1
  151. package/src/superlocalmemory/mcp/tools.py +1 -1
  152. package/src/superlocalmemory/mcp/tools_active.py +1 -1
  153. package/src/superlocalmemory/mcp/tools_code_graph.py +1 -1
  154. package/src/superlocalmemory/mcp/tools_core.py +1 -1
  155. package/src/superlocalmemory/mcp/tools_learning.py +221 -0
  156. package/src/superlocalmemory/mcp/tools_mesh.py +55 -12
  157. package/src/superlocalmemory/mcp/tools_v28.py +23 -1
  158. package/src/superlocalmemory/mcp/tools_v3.py +1 -1
  159. package/src/superlocalmemory/mcp/tools_v33.py +1 -1
  160. package/src/superlocalmemory/mesh/__init__.py +1 -1
  161. package/src/superlocalmemory/mesh/broker.py +194 -38
  162. package/src/superlocalmemory/parameterization/__init__.py +1 -1
  163. package/src/superlocalmemory/parameterization/pattern_extractor.py +35 -1
  164. package/src/superlocalmemory/parameterization/pii_filter.py +1 -1
  165. package/src/superlocalmemory/parameterization/prompt_injector.py +3 -2
  166. package/src/superlocalmemory/parameterization/prompt_lifecycle.py +1 -1
  167. package/src/superlocalmemory/parameterization/soft_prompt_generator.py +7 -1
  168. package/src/superlocalmemory/retrieval/agentic.py +1 -1
  169. package/src/superlocalmemory/retrieval/ann_index.py +1 -1
  170. package/src/superlocalmemory/retrieval/bm25_channel.py +1 -1
  171. package/src/superlocalmemory/retrieval/bridge_discovery.py +1 -1
  172. package/src/superlocalmemory/retrieval/channel_registry.py +1 -1
  173. package/src/superlocalmemory/retrieval/engine.py +1 -1
  174. package/src/superlocalmemory/retrieval/entity_channel.py +1 -1
  175. package/src/superlocalmemory/retrieval/forgetting_filter.py +1 -1
  176. package/src/superlocalmemory/retrieval/fusion.py +1 -1
  177. package/src/superlocalmemory/retrieval/hopfield_channel.py +1 -1
  178. package/src/superlocalmemory/retrieval/profile_channel.py +1 -1
  179. package/src/superlocalmemory/retrieval/quantization_aware_search.py +1 -1
  180. package/src/superlocalmemory/retrieval/reranker.py +1 -1
  181. package/src/superlocalmemory/retrieval/semantic_channel.py +1 -1
  182. package/src/superlocalmemory/retrieval/spreading_activation.py +1 -1
  183. package/src/superlocalmemory/retrieval/strategy.py +1 -1
  184. package/src/superlocalmemory/retrieval/temporal_channel.py +1 -1
  185. package/src/superlocalmemory/retrieval/vector_store.py +1 -1
  186. package/src/superlocalmemory/server/api.py +1 -1
  187. package/src/superlocalmemory/server/routes/__init__.py +1 -1
  188. package/src/superlocalmemory/server/routes/adapters.py +1 -1
  189. package/src/superlocalmemory/server/routes/agents.py +2 -2
  190. package/src/superlocalmemory/server/routes/backup.py +2 -2
  191. package/src/superlocalmemory/server/routes/behavioral.py +129 -2
  192. package/src/superlocalmemory/server/routes/compliance.py +2 -2
  193. package/src/superlocalmemory/server/routes/data_io.py +2 -2
  194. package/src/superlocalmemory/server/routes/entity.py +1 -1
  195. package/src/superlocalmemory/server/routes/events.py +2 -2
  196. package/src/superlocalmemory/server/routes/helpers.py +2 -2
  197. package/src/superlocalmemory/server/routes/ingest.py +1 -1
  198. package/src/superlocalmemory/server/routes/learning.py +22 -5
  199. package/src/superlocalmemory/server/routes/lifecycle.py +2 -2
  200. package/src/superlocalmemory/server/routes/memories.py +2 -2
  201. package/src/superlocalmemory/server/routes/mesh.py +25 -7
  202. package/src/superlocalmemory/server/routes/profiles.py +2 -2
  203. package/src/superlocalmemory/server/routes/stats.py +26 -7
  204. package/src/superlocalmemory/server/routes/v3_api.py +1 -1
  205. package/src/superlocalmemory/server/routes/ws.py +2 -2
  206. package/src/superlocalmemory/server/ui.py +1 -1
  207. package/src/superlocalmemory/server/unified_daemon.py +42 -1
  208. package/src/superlocalmemory/storage/access_control.py +1 -1
  209. package/src/superlocalmemory/storage/access_log.py +1 -1
  210. package/src/superlocalmemory/storage/database.py +1 -1
  211. package/src/superlocalmemory/storage/embedding_migrator.py +1 -1
  212. package/src/superlocalmemory/storage/migration_v33.py +1 -1
  213. package/src/superlocalmemory/storage/migrations.py +1 -1
  214. package/src/superlocalmemory/storage/models.py +1 -1
  215. package/src/superlocalmemory/storage/quantized_store.py +1 -1
  216. package/src/superlocalmemory/storage/schema.py +1 -1
  217. package/src/superlocalmemory/storage/schema_code_graph.py +1 -1
  218. package/src/superlocalmemory/storage/schema_v32.py +1 -1
  219. package/src/superlocalmemory/storage/schema_v343.py +75 -1
  220. package/src/superlocalmemory/storage/schema_v347.py +136 -0
  221. package/src/superlocalmemory/storage/v2_migrator.py +1 -1
  222. package/src/superlocalmemory/trust/gate.py +1 -1
  223. package/src/superlocalmemory/trust/provenance.py +1 -1
  224. package/src/superlocalmemory/trust/scorer.py +1 -1
  225. package/src/superlocalmemory/trust/signals.py +1 -1
  226. package/src/superlocalmemory/ui/js/behavioral.js +174 -3
  227. package/src/superlocalmemory.egg-info/PKG-INFO +0 -601
  228. package/src/superlocalmemory.egg-info/SOURCES.txt +0 -313
  229. package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
  230. package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
  231. package/src/superlocalmemory.egg-info/requires.txt +0 -55
  232. package/src/superlocalmemory.egg-info/top_level.txt +0 -1
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ # SuperLocalMemory V3.4.7 — Tool Event Learning Hook
3
+ # Copyright (c) 2026 Varun Pratap Bhardwaj
4
+ # Licensed under AGPL-3.0-or-later
5
+ #
6
+ # PostToolUse hook that logs tool events to SLM for behavioral learning.
7
+ # Fires after every tool call. Lightweight — no LLM calls, just HTTP POST.
8
+ # All data stays 100% local.
9
+ #
10
+ # Installation: slm init (auto-registers) or manually add to settings.json:
11
+ # { "type": "PostToolUse", "matcher": "*",
12
+ # "command": "bash /path/to/tool-event-hook.sh",
13
+ # "timeout": 5000 }
14
+
15
+ set -euo pipefail
16
+
17
+ # Read stdin (Claude Code passes JSON with tool_name, input, output)
18
+ INPUT=$(cat)
19
+
20
+ # Extract tool name and event info
21
+ TOOL_NAME=$(echo "$INPUT" | python3 -c "
22
+ import sys, json
23
+ try:
24
+ d = json.load(sys.stdin)
25
+ print(d.get('tool_name', d.get('tool', 'unknown')))
26
+ except:
27
+ print('unknown')
28
+ " 2>/dev/null || echo "unknown")
29
+
30
+ # Skip logging for our own tools (avoid recursion)
31
+ case "$TOOL_NAME" in
32
+ log_tool_event|get_assertions|reinforce_assertion|contradict_assertion)
33
+ exit 0
34
+ ;;
35
+ esac
36
+
37
+ # Get daemon port
38
+ PORT=8765
39
+ PORT_FILE="$HOME/.superlocalmemory/daemon.port"
40
+ [ -f "$PORT_FILE" ] && PORT=$(cat "$PORT_FILE" 2>/dev/null || echo 8765)
41
+
42
+ # Log event to SLM daemon (fire and forget, 2s timeout)
43
+ curl -s -m 2 -X POST "http://127.0.0.1:${PORT}/api/v3/tool-event" \
44
+ -H "Content-Type: application/json" \
45
+ -d "{\"tool_name\": \"${TOOL_NAME}\", \"event_type\": \"complete\"}" \
46
+ >/dev/null 2>&1 || true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlocalmemory",
3
- "version": "3.4.5",
3
+ "version": "3.4.8",
4
4
  "description": "Information-geometric agent memory with mathematical guarantees. 4-channel retrieval, Fisher-Rao similarity, zero-LLM mode, EU AI Act compliant. Works with Claude, Cursor, Windsurf, and 17+ AI tools.",
5
5
  "keywords": [
6
6
  "ai-memory",
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.4.5"
3
+ version = "3.4.8"
4
4
  description = "Information-geometric agent memory with mathematical guarantees"
5
5
  readme = "README.md"
6
6
  license = {text = "AGPL-3.0-or-later"}
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Self-enforcing inter-layer parameter constraints.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Cryptographic signing for content attribution and tamper detection.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Steganographic watermarking using zero-width Unicode characters.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """SuperLocalMemory V3 — CLI package."""
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """CLI command implementations.
@@ -60,6 +60,8 @@ def dispatch(args: Namespace) -> None:
60
60
  "serve": cmd_serve,
61
61
  # V3.4.3 ingestion adapters
62
62
  "adapters": cmd_adapters,
63
+ # V3.4.8 external observation ingestion
64
+ "ingest": cmd_ingest,
63
65
  }
64
66
  handler = handlers.get(args.command)
65
67
  if handler:
@@ -144,6 +146,12 @@ def cmd_serve(args: Namespace) -> None:
144
146
  # -- Ingestion Adapters (V3.4.3) ------------------------------------------
145
147
 
146
148
 
149
+ def cmd_ingest(args: Namespace) -> None:
150
+ """Import external observations into SLM learning pipeline."""
151
+ from superlocalmemory.cli.ingest_cmd import cmd_ingest as _ingest
152
+ _ingest(args)
153
+
154
+
147
155
  def cmd_adapters(args: Namespace) -> None:
148
156
  """Manage ingestion adapters (Gmail, Calendar, Transcript).
149
157
 
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """SLM Daemon — client functions for communicating with the unified daemon.
@@ -16,7 +16,7 @@ This module contains CLIENT functions used by CLI commands:
16
16
  The actual daemon server code is in server/unified_daemon.py.
17
17
 
18
18
  Part of Qualixar | Author: Varun Pratap Bhardwaj
19
- License: Elastic-2.0
19
+ License: AGPL-3.0-or-later
20
20
  """
21
21
 
22
22
  from __future__ import annotations
@@ -232,39 +232,69 @@ def _wait_for_daemon(timeout: int = 60) -> bool:
232
232
 
233
233
 
234
234
  def stop_daemon() -> bool:
235
- """Stop the running daemon gracefully.
235
+ """Stop ALL SLM daemon processes and their workers.
236
236
 
237
- v3.4.3: Uses psutil for cross-platform process termination.
238
- Falls back to os.kill if psutil unavailable.
237
+ v3.4.7: Nuclear cleanup finds and kills ALL processes matching
238
+ superlocalmemory.server.unified_daemon, embedding_worker, recall_worker,
239
+ reranker_worker. Not just the PID file daemon. Multiple daemons can
240
+ accumulate from rapid restarts, MCP warmups, and concurrent sessions.
239
241
  """
240
- if not _PID_FILE.exists():
241
- return True
242
+ killed = 0
243
+
242
244
  try:
243
- pid = int(_PID_FILE.read_text().strip())
245
+ import psutil
246
+ my_pid = os.getpid()
247
+ targets = [
248
+ "superlocalmemory.server.unified_daemon",
249
+ "superlocalmemory.core.embedding_worker",
250
+ "superlocalmemory.core.recall_worker",
251
+ "superlocalmemory.core.reranker_worker",
252
+ ]
253
+
254
+ for proc in psutil.process_iter(["pid", "cmdline"]):
255
+ try:
256
+ if proc.pid == my_pid:
257
+ continue
258
+ cmdline = " ".join(proc.info.get("cmdline") or [])
259
+ if any(t in cmdline for t in targets):
260
+ # Kill children first, then process
261
+ for child in proc.children(recursive=True):
262
+ try:
263
+ child.kill()
264
+ killed += 1
265
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
266
+ pass
267
+ proc.kill()
268
+ killed += 1
269
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
270
+ pass
244
271
 
245
- # Cross-platform termination via psutil
272
+ except ImportError:
273
+ # Fallback: pkill by pattern
246
274
  try:
247
- import psutil
248
- proc = psutil.Process(pid)
249
- proc.terminate() # SIGTERM on Unix, TerminateProcess on Windows
250
- proc.wait(timeout=10)
251
- except ImportError:
252
- # Fallback: direct signal (works on Unix, may fail on Windows)
253
- os.kill(pid, signal.SIGTERM)
254
- for _ in range(20):
255
- time.sleep(0.5)
256
- try:
257
- os.kill(pid, 0)
258
- except ProcessLookupError:
259
- break
275
+ import subprocess as _sp
276
+ for pattern in [
277
+ "superlocalmemory.server.unified_daemon",
278
+ "superlocalmemory.core.embedding_worker",
279
+ "superlocalmemory.core.recall_worker",
280
+ "superlocalmemory.core.reranker_worker",
281
+ ]:
282
+ result = _sp.run(
283
+ ["pkill", "-9", "-f", pattern],
284
+ capture_output=True, timeout=5,
285
+ )
286
+ if result.returncode == 0:
287
+ killed += 1
260
288
  except Exception:
261
289
  pass
262
290
 
263
- _PID_FILE.unlink(missing_ok=True)
264
- _PORT_FILE.unlink(missing_ok=True)
265
- return True
266
- except Exception:
267
- return False
291
+ # Clean up PID/port files
292
+ _PID_FILE.unlink(missing_ok=True)
293
+ _PORT_FILE.unlink(missing_ok=True)
294
+
295
+ if killed:
296
+ logger.info("Stopped %d SLM processes", killed)
297
+ return True
268
298
 
269
299
 
270
300
  # ---------------------------------------------------------------------------
@@ -0,0 +1,261 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """CLI handler for `slm ingest` — import external observations into SLM.
6
+
7
+ Supported sources:
8
+ --source ecc Import ECC (Everything Claude Code) session summaries
9
+ --source jsonl Import generic JSONL observations
10
+
11
+ Each imported record becomes a tool_event in the behavioral learning pipeline,
12
+ so the AssertionMiner can learn from them.
13
+
14
+ Part of Qualixar | Author: Varun Pratap Bhardwaj
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ import logging
21
+ import sqlite3
22
+ import sys
23
+ from argparse import Namespace
24
+ from datetime import datetime, timezone
25
+ from pathlib import Path
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+ MEMORY_DIR = Path.home() / ".superlocalmemory"
30
+ MEMORY_DB = MEMORY_DIR / "memory.db"
31
+
32
+
33
+ def cmd_ingest(args: Namespace) -> None:
34
+ """Ingest external observations into SLM tool_events table."""
35
+ source = getattr(args, "source", "ecc")
36
+ file_path = getattr(args, "file", "")
37
+ use_json = getattr(args, "json", False)
38
+ dry_run = getattr(args, "dry_run", False)
39
+
40
+ if source == "ecc":
41
+ result = _ingest_ecc(file_path, dry_run=dry_run)
42
+ elif source == "jsonl":
43
+ if not file_path:
44
+ _error("--file required for jsonl source", use_json)
45
+ return
46
+ result = _ingest_jsonl(file_path, dry_run=dry_run)
47
+ else:
48
+ _error(f"Unknown source: {source}", use_json)
49
+ return
50
+
51
+ if use_json:
52
+ from superlocalmemory.cli.json_output import json_print
53
+ json_print("ingest", data=result, next_actions=[
54
+ {"command": "slm consolidate --cognitive", "description": "Run consolidation to mine assertions"},
55
+ ])
56
+ return
57
+
58
+ if result.get("error"):
59
+ print(f"Error: {result['error']}")
60
+ sys.exit(1)
61
+
62
+ print(f"Ingested: {result['ingested']} events from {source}")
63
+ if result.get("skipped"):
64
+ print(f"Skipped: {result['skipped']} (duplicates/invalid)")
65
+ if dry_run:
66
+ print("(dry run — no data written)")
67
+
68
+
69
+ def _error(msg: str, use_json: bool) -> None:
70
+ if use_json:
71
+ from superlocalmemory.cli.json_output import json_print
72
+ json_print("ingest", error={"code": "INGEST_ERROR", "message": msg})
73
+ else:
74
+ print(f"Error: {msg}")
75
+ sys.exit(1)
76
+
77
+
78
+ def _ingest_ecc(file_path: str, *, dry_run: bool = False) -> dict:
79
+ """Ingest ECC session summaries from transcript JSONL files.
80
+
81
+ Scans the Claude projects directory for session JSONL files and
82
+ extracts tool usage patterns from them.
83
+ """
84
+ result = {"source": "ecc", "ingested": 0, "skipped": 0, "dry_run": dry_run}
85
+
86
+ # Find ECC session files
87
+ if file_path:
88
+ files = [Path(file_path)]
89
+ else:
90
+ # Auto-discover: scan Claude project session files
91
+ claude_dir = Path.home() / ".claude" / "projects"
92
+ if not claude_dir.exists():
93
+ result["error"] = f"Claude projects dir not found: {claude_dir}"
94
+ return result
95
+ files = sorted(claude_dir.rglob("*.jsonl"), key=lambda p: p.stat().st_mtime, reverse=True)
96
+ # Limit to recent files (last 20)
97
+ files = files[:20]
98
+
99
+ if not files:
100
+ result["error"] = "No session files found"
101
+ return result
102
+
103
+ result["files_scanned"] = len(files)
104
+ events = []
105
+
106
+ for fpath in files:
107
+ try:
108
+ with open(fpath) as f:
109
+ for line in f:
110
+ line = line.strip()
111
+ if not line:
112
+ continue
113
+ try:
114
+ record = json.loads(line)
115
+ except json.JSONDecodeError:
116
+ result["skipped"] += 1
117
+ continue
118
+
119
+ # Extract tool usage from ECC session records
120
+ extracted = _extract_tool_events_from_record(record)
121
+ events.extend(extracted)
122
+ except (OSError, PermissionError):
123
+ result["skipped"] += 1
124
+ continue
125
+
126
+ if dry_run:
127
+ result["ingested"] = len(events)
128
+ result["sample"] = events[:5]
129
+ return result
130
+
131
+ # Write to tool_events table
132
+ if events:
133
+ ingested = _write_tool_events(events)
134
+ result["ingested"] = ingested
135
+ else:
136
+ result["ingested"] = 0
137
+
138
+ return result
139
+
140
+
141
+ def _extract_tool_events_from_record(record: dict) -> list[dict]:
142
+ """Extract tool events from a single ECC/Claude session JSONL record."""
143
+ events = []
144
+
145
+ # Handle ECC summary format
146
+ if "type" in record:
147
+ rtype = record.get("type", "")
148
+
149
+ # Tool use records
150
+ if rtype == "assistant" and "content" in record:
151
+ content = record.get("content", [])
152
+ if isinstance(content, list):
153
+ for block in content:
154
+ if isinstance(block, dict) and block.get("type") == "tool_use":
155
+ tool_name = block.get("name", "unknown")
156
+ events.append({
157
+ "tool_name": tool_name,
158
+ "event_type": "complete",
159
+ "session_id": record.get("session_id", "ecc_import"),
160
+ "created_at": record.get("timestamp", datetime.now(timezone.utc).isoformat()),
161
+ })
162
+
163
+ # Also extract from tool_use type directly
164
+ if isinstance(content, list):
165
+ for block in content:
166
+ if isinstance(block, dict) and block.get("type") == "tool_result":
167
+ tool_name = block.get("tool_use_id", "unknown")
168
+ is_error = block.get("is_error", False)
169
+ events.append({
170
+ "tool_name": tool_name,
171
+ "event_type": "error" if is_error else "complete",
172
+ "session_id": record.get("session_id", "ecc_import"),
173
+ "created_at": record.get("timestamp", datetime.now(timezone.utc).isoformat()),
174
+ })
175
+
176
+ # Handle direct tool event format (from hook output)
177
+ if "tool_name" in record and "event_type" in record:
178
+ events.append({
179
+ "tool_name": record["tool_name"],
180
+ "event_type": record.get("event_type", "complete"),
181
+ "session_id": record.get("session_id", "ecc_import"),
182
+ "created_at": record.get("created_at", datetime.now(timezone.utc).isoformat()),
183
+ })
184
+
185
+ return events
186
+
187
+
188
+ def _ingest_jsonl(file_path: str, *, dry_run: bool = False) -> dict:
189
+ """Ingest generic JSONL file with tool event records."""
190
+ result = {"source": "jsonl", "ingested": 0, "skipped": 0, "dry_run": dry_run}
191
+
192
+ fpath = Path(file_path)
193
+ if not fpath.exists():
194
+ result["error"] = f"File not found: {file_path}"
195
+ return result
196
+
197
+ events = []
198
+ with open(fpath) as f:
199
+ for line in f:
200
+ line = line.strip()
201
+ if not line:
202
+ continue
203
+ try:
204
+ record = json.loads(line)
205
+ except json.JSONDecodeError:
206
+ result["skipped"] += 1
207
+ continue
208
+
209
+ if "tool_name" not in record:
210
+ result["skipped"] += 1
211
+ continue
212
+
213
+ events.append({
214
+ "tool_name": record["tool_name"],
215
+ "event_type": record.get("event_type", "complete"),
216
+ "session_id": record.get("session_id", "jsonl_import"),
217
+ "created_at": record.get("created_at", datetime.now(timezone.utc).isoformat()),
218
+ })
219
+
220
+ if dry_run:
221
+ result["ingested"] = len(events)
222
+ return result
223
+
224
+ if events:
225
+ result["ingested"] = _write_tool_events(events)
226
+
227
+ return result
228
+
229
+
230
+ def _write_tool_events(events: list[dict]) -> int:
231
+ """Write tool events to SLM's memory.db tool_events table."""
232
+ db_path = MEMORY_DB
233
+ if not db_path.exists():
234
+ return 0
235
+
236
+ conn = sqlite3.connect(str(db_path), timeout=10)
237
+ count = 0
238
+
239
+ try:
240
+ for ev in events:
241
+ try:
242
+ conn.execute(
243
+ "INSERT INTO tool_events "
244
+ "(session_id, profile_id, project_path, tool_name, event_type, "
245
+ " input_summary, output_summary, duration_ms, metadata, created_at) "
246
+ "VALUES (?, 'default', '', ?, ?, '', '', 0, '{}', ?)",
247
+ (
248
+ ev.get("session_id", "import"),
249
+ ev["tool_name"],
250
+ ev.get("event_type", "complete"),
251
+ ev.get("created_at", datetime.now(timezone.utc).isoformat()),
252
+ ),
253
+ )
254
+ count += 1
255
+ except sqlite3.Error:
256
+ continue
257
+ conn.commit()
258
+ finally:
259
+ conn.close()
260
+
261
+ return count
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Shared JSON envelope for agent-native CLI output.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """SuperLocalMemory V3 — CLI entry point.
@@ -282,6 +282,26 @@ def main() -> None:
282
282
  help="Subcommand: list, enable, disable, start, stop, status [name]",
283
283
  )
284
284
 
285
+ # V3.4.8: External observation ingestion
286
+ ingest_p = sub.add_parser(
287
+ "ingest",
288
+ help="Import external observations (ECC, JSONL) into SLM learning",
289
+ )
290
+ ingest_p.add_argument(
291
+ "--source", default="ecc",
292
+ choices=["ecc", "jsonl"],
293
+ help="Source type: ecc (Claude Code sessions), jsonl (generic)",
294
+ )
295
+ ingest_p.add_argument(
296
+ "--file", default="",
297
+ help="Specific file to ingest (auto-discovers if not set)",
298
+ )
299
+ ingest_p.add_argument(
300
+ "--dry-run", action="store_true", default=False,
301
+ help="Preview without writing",
302
+ )
303
+ ingest_p.add_argument("--json", action="store_true", help="Output structured JSON")
304
+
285
305
  args = parser.parse_args()
286
306
 
287
307
  if not args.command:
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Migration CLI command implementation."""
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Pending memory store — zero-loss async remember (Option C).
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Post-install script for npm package.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """OS-level service installer — daemon survives reboots.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
4
 
5
5
  """Interactive setup wizard for first-time configuration.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Module
4
4
 
5
5
  """Code Knowledge Graph for SuperLocalMemory.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Module
4
4
 
5
5
  """BlastRadius — bidirectional BFS impact analysis.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Bridge between code_graph.db and SLM memory.db.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Entity Resolver — match SLM fact text against code graph nodes.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Event Listeners — bidirectional bridge between SLM events and code graph.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Fact Enricher — append code metadata to fact descriptions.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Hebbian Linker — code-aware association edge creation.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Bridge Module
4
4
 
5
5
  """Temporal Checker — invalidate memories about deleted/renamed code.
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under the Elastic License 2.0 - see LICENSE file
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
3
  # Part of SuperLocalMemory v3.4 — CodeGraph Module
4
4
 
5
5
  """ChangeAnalyzer — git diff to risk-scored change analysis.