superlocalmemory 4.0.8 → 4.0.10

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 (147) hide show
  1. package/CHANGELOG.md +221 -1
  2. package/README.md +6 -6
  3. package/package.json +1 -1
  4. package/plugin/.claude-plugin/plugin.json +1 -1
  5. package/plugin/CLAUDE.md +3 -3
  6. package/plugin/agents/slm-governance-advisor.md +1 -1
  7. package/plugin/agents/slm-loop-runner.md +1 -1
  8. package/plugin/agents/slm-memory-advisor.md +1 -1
  9. package/plugin/agents/slm-optimize-advisor.md +1 -1
  10. package/plugin/requirements.txt +1 -1
  11. package/plugin/scripts/ensure-venv.sh +1 -1
  12. package/plugin/skills/slm-cache/SKILL.md +1 -1
  13. package/plugin/skills/slm-compress/SKILL.md +1 -1
  14. package/plugin/skills/slm-governance/SKILL.md +1 -1
  15. package/plugin/skills/slm-graph/SKILL.md +1 -1
  16. package/plugin/skills/slm-loop/SKILL.md +1 -1
  17. package/plugin/skills/slm-mesh/SKILL.md +1 -1
  18. package/plugin/skills/slm-profile/SKILL.md +1 -1
  19. package/plugin/skills/slm-recall/SKILL.md +1 -1
  20. package/plugin/skills/slm-remember/SKILL.md +1 -1
  21. package/plugin/skills/slm-scope/SKILL.md +1 -1
  22. package/plugin/skills/slm-session/SKILL.md +1 -1
  23. package/plugin/skills/slm-status/SKILL.md +3 -3
  24. package/plugin-src/rules/AGENTS.md +1 -1
  25. package/plugin-src/skills/slm-status/SKILL.md +2 -2
  26. package/pyproject.toml +1 -1
  27. package/scripts/postinstall.js +4 -0
  28. package/src/superlocalmemory/__init__.py +1 -1
  29. package/src/superlocalmemory/cli/_lazy_init.py +1 -1
  30. package/src/superlocalmemory/cli/commands.py +164 -11
  31. package/src/superlocalmemory/cli/db_migrate.py +0 -2
  32. package/src/superlocalmemory/cli/gdpr_io.py +1 -1
  33. package/src/superlocalmemory/cli/main.py +7 -7
  34. package/src/superlocalmemory/cli/service_installer.py +2 -1
  35. package/src/superlocalmemory/cli/setup_wizard.py +1 -1
  36. package/src/superlocalmemory/code_graph/bridge/maintenance.py +8 -0
  37. package/src/superlocalmemory/core/config.py +41 -7
  38. package/src/superlocalmemory/core/context_cache.py +0 -2
  39. package/src/superlocalmemory/core/engine.py +371 -63
  40. package/src/superlocalmemory/core/evidence_bundle.py +3 -1
  41. package/src/superlocalmemory/core/fact_consolidator.py +316 -125
  42. package/src/superlocalmemory/core/install_detector.py +131 -0
  43. package/src/superlocalmemory/core/maintenance.py +44 -6
  44. package/src/superlocalmemory/core/memory_health.py +266 -0
  45. package/src/superlocalmemory/core/operation_policy_registry.py +1 -1
  46. package/src/superlocalmemory/core/operation_request.py +1 -1
  47. package/src/superlocalmemory/core/ops_remediation.py +2 -2
  48. package/src/superlocalmemory/core/progressive_abstraction.py +1 -1
  49. package/src/superlocalmemory/core/security_primitives.py +3 -6
  50. package/src/superlocalmemory/core/store_pipeline.py +172 -29
  51. package/src/superlocalmemory/core/topic_signature.py +0 -2
  52. package/src/superlocalmemory/core/transactions/concrete_owners.py +15 -8
  53. package/src/superlocalmemory/dynamics/eap_scheduler.py +17 -6
  54. package/src/superlocalmemory/encoding/cognitive_consolidator.py +15 -1
  55. package/src/superlocalmemory/encoding/graph_builder.py +2 -2
  56. package/src/superlocalmemory/encoding/scene_builder.py +8 -2
  57. package/src/superlocalmemory/hooks/adapter_base.py +0 -2
  58. package/src/superlocalmemory/hooks/context_payload.py +0 -2
  59. package/src/superlocalmemory/hooks/portable_kit.py +8 -8
  60. package/src/superlocalmemory/hooks/post_tool_async_hook.py +0 -2
  61. package/src/superlocalmemory/hooks/prewarm_auth.py +0 -2
  62. package/src/superlocalmemory/hooks/user_prompt_hook.py +0 -2
  63. package/src/superlocalmemory/infra/backup.py +44 -8
  64. package/src/superlocalmemory/integrations/bounded_loops_mcp.py +24 -7
  65. package/src/superlocalmemory/learning/arm_catalog.py +0 -2
  66. package/src/superlocalmemory/learning/bandit.py +0 -2
  67. package/src/superlocalmemory/learning/bandit_cache.py +0 -2
  68. package/src/superlocalmemory/learning/dedup_hnsw.py +11 -11
  69. package/src/superlocalmemory/learning/ensemble.py +0 -2
  70. package/src/superlocalmemory/learning/labeler.py +0 -2
  71. package/src/superlocalmemory/learning/legacy_migration.py +0 -2
  72. package/src/superlocalmemory/learning/model_cache.py +0 -2
  73. package/src/superlocalmemory/learning/ranker.py +0 -2
  74. package/src/superlocalmemory/learning/reward_archive.py +6 -1
  75. package/src/superlocalmemory/learning/reward_proxy.py +0 -2
  76. package/src/superlocalmemory/learning/signal_worker.py +0 -2
  77. package/src/superlocalmemory/math/fisher.py +1 -1
  78. package/src/superlocalmemory/math/hopfield.py +4 -1
  79. package/src/superlocalmemory/math/langevin.py +1 -1
  80. package/src/superlocalmemory/math/sheaf.py +7 -3
  81. package/src/superlocalmemory/mcp/cli_fallback.py +1 -1
  82. package/src/superlocalmemory/mcp/profiles.py +1 -1
  83. package/src/superlocalmemory/mcp/server.py +2 -2
  84. package/src/superlocalmemory/mcp/session_binding.py +92 -0
  85. package/src/superlocalmemory/mcp/tools_active.py +56 -0
  86. package/src/superlocalmemory/mcp/tools_core.py +41 -40
  87. package/src/superlocalmemory/mcp/tools_ops.py +2 -2
  88. package/src/superlocalmemory/optimize/cache/manager.py +2 -2
  89. package/src/superlocalmemory/optimize/compress/ccr.py +1 -1
  90. package/src/superlocalmemory/optimize/compress/router.py +1 -1
  91. package/src/superlocalmemory/optimize/proxy/_helpers.py +2 -2
  92. package/src/superlocalmemory/optimize/proxy/server.py +1 -1
  93. package/src/superlocalmemory/optimize/proxy/vertex_surface.py +2 -2
  94. package/src/superlocalmemory/optimize/storage/db.py +2 -2
  95. package/src/superlocalmemory/retrieval/agentic.py +1 -1
  96. package/src/superlocalmemory/retrieval/ann_index.py +9 -2
  97. package/src/superlocalmemory/retrieval/bm25_channel.py +6 -10
  98. package/src/superlocalmemory/retrieval/bridge_discovery.py +2 -2
  99. package/src/superlocalmemory/retrieval/engine.py +272 -43
  100. package/src/superlocalmemory/retrieval/entity_channel.py +8 -2
  101. package/src/superlocalmemory/retrieval/hopfield_channel.py +8 -2
  102. package/src/superlocalmemory/retrieval/profile_channel.py +1 -1
  103. package/src/superlocalmemory/retrieval/quantization_aware_search.py +1 -1
  104. package/src/superlocalmemory/retrieval/remote_reranker.py +2 -2
  105. package/src/superlocalmemory/retrieval/reranker.py +3 -3
  106. package/src/superlocalmemory/retrieval/scope_policy.py +22 -1
  107. package/src/superlocalmemory/retrieval/semantic_channel.py +3 -3
  108. package/src/superlocalmemory/retrieval/spreading_activation.py +8 -8
  109. package/src/superlocalmemory/retrieval/strategy.py +94 -0
  110. package/src/superlocalmemory/retrieval/temporal_channel.py +179 -10
  111. package/src/superlocalmemory/retrieval/temporal_validity_filter.py +1 -1
  112. package/src/superlocalmemory/retrieval/vector_store.py +151 -10
  113. package/src/superlocalmemory/server/api.py +6 -1
  114. package/src/superlocalmemory/server/asset_versions.py +171 -0
  115. package/src/superlocalmemory/server/recall_serializer.py +10 -0
  116. package/src/superlocalmemory/server/routes/abstraction.py +201 -0
  117. package/src/superlocalmemory/server/routes/brain.py +2 -2
  118. package/src/superlocalmemory/server/routes/data_io.py +29 -1
  119. package/src/superlocalmemory/server/routes/entity.py +13 -1
  120. package/src/superlocalmemory/server/routes/mesh.py +1 -1
  121. package/src/superlocalmemory/server/routes/prewarm.py +4 -4
  122. package/src/superlocalmemory/server/routes/v3_api.py +2 -2
  123. package/src/superlocalmemory/server/ui.py +8 -1
  124. package/src/superlocalmemory/server/unified_daemon.py +570 -16
  125. package/src/superlocalmemory/storage/_migration_internals.py +4 -0
  126. package/src/superlocalmemory/storage/_schema_version.py +46 -3
  127. package/src/superlocalmemory/storage/backup.py +531 -0
  128. package/src/superlocalmemory/storage/database.py +139 -34
  129. package/src/superlocalmemory/storage/embedding_codec.py +129 -0
  130. package/src/superlocalmemory/storage/embedding_migrator.py +5 -3
  131. package/src/superlocalmemory/storage/migration_runner.py +153 -2
  132. package/src/superlocalmemory/storage/migrations/M043_quarantine_display_summaries.py +488 -0
  133. package/src/superlocalmemory/storage/migrations/__init__.py +1 -1
  134. package/src/superlocalmemory/storage/migrations.py +15 -1
  135. package/src/superlocalmemory/storage/models.py +7 -0
  136. package/src/superlocalmemory/storage/quantized_store.py +4 -2
  137. package/src/superlocalmemory/storage/schema.py +98 -0
  138. package/src/superlocalmemory/summaries/base.py +1 -1
  139. package/src/superlocalmemory/summaries/non_answer.py +223 -0
  140. package/src/superlocalmemory/summaries/session_summary.py +1 -1
  141. package/src/superlocalmemory/ui/css/legacy-dashboard.css +1 -1
  142. package/src/superlocalmemory/ui/css/neural-glass.css +1 -1
  143. package/src/superlocalmemory/ui/index.html +1 -1
  144. package/src/superlocalmemory/ui/js/core.js +1 -1
  145. package/src/superlocalmemory/ui/js/od-brain.js +1 -1
  146. package/src/superlocalmemory/ui/js/od-memories.js +190 -1
  147. package/src/superlocalmemory/ui/js/od-ops-health.js +1 -1
@@ -12,7 +12,7 @@ import gzip
12
12
  import hashlib
13
13
  import json
14
14
  import logging
15
- from typing import Optional
15
+ from typing import Any, Optional
16
16
  from datetime import datetime, timezone
17
17
 
18
18
  from fastapi import APIRouter, HTTPException, Query, Request, UploadFile, File
@@ -78,7 +78,22 @@ async def export_memories(
78
78
  use_v3 = False
79
79
 
80
80
  if use_v3:
81
+ # Withheld summaries are excluded, and this is about IMPORT, not
82
+ # tidiness. Import re-ingests every record through the normal
83
+ # pipeline, which mints a fresh memory with quarantined = 0 — so an
84
+ # export taken here and imported anywhere would resurrect all 1,195
85
+ # model-written rows as though the owner had written them, on a
86
+ # machine where nothing had gone wrong. The repair would then have
87
+ # to run again there.
88
+ #
89
+ # Nothing the owner wrote is lost: these are derived artefacts, the
90
+ # consolidator regenerates them from the facts that ARE exported,
91
+ # and their text is kept in consolidated_summaries. (That table is
92
+ # not in this export either — it is a view, not a memory. Worth
93
+ # revisiting when export covers derived state.)
81
94
  query = "SELECT * FROM atomic_facts WHERE profile_id = ?"
95
+ if _has_column(cursor, "atomic_facts", "quarantined"):
96
+ query += " AND COALESCE(quarantined, 0) = 0"
82
97
  params = [active_profile]
83
98
  if category:
84
99
  query += " AND fact_type = ?"
@@ -154,6 +169,19 @@ async def export_memories(
154
169
  raise _internal_error("Export error")
155
170
 
156
171
 
172
+ def _has_column(cursor: Any, table: str, column: str) -> bool:
173
+ """Whether ``table`` carries ``column`` in this database.
174
+
175
+ Presence-guarded because ``quarantined`` arrives with a migration and this
176
+ route must keep working on a store the engine has not opened.
177
+ """
178
+ try:
179
+ cursor.execute(f"PRAGMA table_info({table})")
180
+ return any(row[1] == column for row in cursor.fetchall())
181
+ except Exception: # noqa: BLE001 -- an export must not fail over a probe
182
+ return False
183
+
184
+
157
185
  @router.post("/api/import")
158
186
  async def import_memories(request: Request, file: UploadFile = File(...)):
159
187
  """Import memories from JSON file using V3 engine."""
@@ -84,7 +84,19 @@ def list_entities(
84
84
 
85
85
  conn = get_read_connection(engine._config.db_path)
86
86
  try:
87
- where = ["ce.profile_id = ?"]
87
+ # Hide the placeholder that dated facts with no recognised entity
88
+ # attach their temporal events to (core/store_pipeline.py,
89
+ # _ensure_unresolved_entity). It is a hook for a foreign key, not a
90
+ # concept, and it would otherwise appear here as a nameless entity and
91
+ # be counted in the total the owner reads as "entities I have".
92
+ #
93
+ # Only the presentation layer needs this. The other readers of
94
+ # canonical_entities are unaffected on inspection: graph_pruner uses
95
+ # `NOT IN (SELECT entity_id ...)` to find orphaned edges, where
96
+ # including it is correct; community_summary builds from graph edges and
97
+ # the placeholder has none; scale_engine counts for backend sync, not
98
+ # for display.
99
+ where = ["ce.profile_id = ?", "ce.entity_type != 'unresolved'"]
88
100
  params: list[object] = [profile]
89
101
  if entity_type and entity_type.lower() != "all":
90
102
  where.append("ce.entity_type = ? COLLATE NOCASE")
@@ -408,7 +408,7 @@ def send(req: SendRequest, request: Request):
408
408
  if sig_err is not None:
409
409
  raise HTTPException(401, detail=sig_err.get("error", "signature error"))
410
410
 
411
- # Admission gate parity (closes Wave-1 P1 bypass for inbound remote send).
411
+ # Admission gate parity (closes the P1 bypass for inbound remote send).
412
412
  try:
413
413
  from superlocalmemory.core.admission import (
414
414
  AdmissionDenied,
@@ -4,10 +4,10 @@
4
4
 
5
5
  """POST /internal/prewarm — populates the context cache for a session.
6
6
 
7
- S8-SK-02 fix: Wave 2A shipped ``hooks/prewarm_auth.authorize`` (gates
8
- loopback → origin → install-token → body-size) and unit-tested it, but
9
- no FastAPI route mounted it. The hot-path ``post_tool_async_hook`` POSTs
10
- to ``/internal/prewarm`` after every tool call to refresh the
7
+ Bug fix: ``hooks/prewarm_auth.authorize`` (which gates loopback →
8
+ origin → install-token → body-size) was implemented and unit-tested,
9
+ but no FastAPI route mounted it. The hot-path ``post_tool_async_hook``
10
+ POSTs to ``/internal/prewarm`` after every tool call to refresh the
11
11
  ``active_brain_cache`` row for the current session/topic. Without a
12
12
  route registered here, those POSTs 404'd silently, the cache never
13
13
  populated, and every ``UserPromptSubmit`` ended up a structural miss.
@@ -266,7 +266,7 @@ def apply_settings_update(config: "SLMConfig", payload: dict) -> "SLMConfig":
266
266
  This is the SINGLE authoritative place where incoming dashboard save payloads
267
267
  are merged onto the stored config. The POST /api/v3/mode/set handler calls
268
268
  this function after its HTTP-layer concerns (SSRF guard, auth) are settled,
269
- so the acceptance gate (test_wave2_acceptance.py::P3) tests real product
269
+ so the test suite (test_acceptance_core.py::P3) tests real product
270
270
  behaviour — not a reimplementation.
271
271
 
272
272
  SEC-L-01 PRESERVED:
@@ -444,7 +444,7 @@ async def set_full_config(request: Request):
444
444
  # Resolve the effective endpoint value before SSRF validation.
445
445
  # Only the Ollama default injection happens here; the fallback to the
446
446
  # stored URL (and redacted-echo detection) live inside
447
- # apply_settings_update so that the P3 acceptance gate exercises
447
+ # apply_settings_update so that the P3 test exercises
448
448
  # the same code path as the HTTP handler — not a reimplementation.
449
449
  _raw_ep: str = "" if clear_base_url else (base_url_input or endpoint_input or "")
450
450
  if (
@@ -231,7 +231,14 @@ def create_app() -> FastAPI:
231
231
  "<p><a href='/api/docs'>API Documentation</a></p>"
232
232
  "</body></html>"
233
233
  )
234
- return index_path.read_text()
234
+ from superlocalmemory.server.asset_versions import render_index
235
+ from superlocalmemory import __version__ as _v
236
+
237
+ # __SLM_VERSION__ was substituted only by the unified daemon, so the
238
+ # dashboard's upgrade detector did nothing when served from here.
239
+ return render_index(
240
+ index_path, UI_DIR, substitutions={"__SLM_VERSION__": _v},
241
+ )
235
242
 
236
243
  @application.get("/favicon.ico", include_in_schema=False)
237
244
  async def favicon():