superlocalmemory 3.7.0 → 3.7.1

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 (35) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -2
  3. package/package.json +2 -2
  4. package/plugin/.claude-plugin/plugin.json +1 -1
  5. package/plugin/requirements.txt +1 -1
  6. package/plugin-src/.mcp.json +12 -0
  7. package/plugin-src/agents/slm-memory-advisor.md +44 -0
  8. package/plugin-src/agents/slm-optimize-advisor.md +38 -0
  9. package/plugin-src/hooks/.gitkeep +0 -0
  10. package/plugin-src/hooks/hooks.json +23 -0
  11. package/plugin-src/manifest.json +25 -0
  12. package/plugin-src/requirements.txt +1 -0
  13. package/plugin-src/rules/CLAUDE.md.fragment +44 -0
  14. package/plugin-src/scripts/ensure-venv.bat +122 -0
  15. package/plugin-src/scripts/ensure-venv.sh +105 -0
  16. package/plugin-src/scripts/slm-launch +15 -0
  17. package/plugin-src/scripts/slm-launch.bat +17 -0
  18. package/plugin-src/settings.json +16 -0
  19. package/plugin-src/skills/slm-cache/SKILL.md +140 -0
  20. package/plugin-src/skills/slm-compress/SKILL.md +143 -0
  21. package/plugin-src/skills/slm-graph/SKILL.md +300 -0
  22. package/plugin-src/skills/slm-recall/SKILL.md +204 -0
  23. package/plugin-src/skills/slm-remember/SKILL.md +194 -0
  24. package/plugin-src/skills/slm-session/SKILL.md +207 -0
  25. package/plugin-src/skills/slm-status/SKILL.md +149 -0
  26. package/pyproject.toml +1 -1
  27. package/src/superlocalmemory/__init__.py +1 -1
  28. package/src/superlocalmemory/cli/_lazy_init.py +4 -2
  29. package/src/superlocalmemory/core/engine_wiring.py +30 -23
  30. package/src/superlocalmemory/hooks/claude_code_hooks.py +1 -1
  31. package/src/superlocalmemory/hooks/context_payload.py +1 -1
  32. package/src/superlocalmemory/mcp/http_transport.py +1 -1
  33. package/src/superlocalmemory/mcp/tools_core.py +2 -2
  34. package/src/superlocalmemory/optimize/proxy/server.py +1 -1
  35. package/src/superlocalmemory/server/routes/brain.py +1 -1
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: slm-status
3
+ description: Health and optimization stats for SuperLocalMemory — call slm_optimize_stats() for live compression and cache counters (compress_runs, tokens_saved_compress, cache_proxy_hits, cache_proxy_misses, cache_kv_hits, cache_kv_misses); run slm status [--json] for system state (mode, profile, DB size, fact/entity/edge counts) and slm doctor [--json] for preflight including the "Optimize (Surface B)" health line; use together to confirm optimization is actually saving tokens.
4
+ when_to_use: "check slm status, health check, is slm working, optimize stats, tokens saved, cache hits, compress runs, slm doctor, preflight, db size, slm info, diagnose slm"
5
+ allowed-tools: slm_optimize_stats, Bash
6
+ ---
7
+
8
+ # slm-status — Health and Optimize Stats
9
+
10
+ ## Purpose
11
+
12
+ Use this skill to answer: "Is SLM healthy?", "Is compression/caching actually saving tokens?", and "What does the system look like right now?" It covers three surfaces: the MCP stats tool, the `slm status` CLI, and the `slm doctor` preflight.
13
+
14
+ ## Primary MCP Tool: slm_optimize_stats
15
+
16
+ ```
17
+ slm_optimize_stats() -> dict
18
+ ```
19
+
20
+ No arguments. Returns counters from the current daemon and MCP process session.
21
+
22
+ ### Return dict (all keys always present)
23
+
24
+ | Key | Type | Meaning |
25
+ |-----|------|---------|
26
+ | `ok` | bool | `True` on success; `False` on internal error |
27
+ | `compress_runs` | int | Total compress calls recorded by the daemon (persisted across restarts) |
28
+ | `tokens_saved_compress` | int | Cumulative tokens saved by compression (daemon-persisted) |
29
+ | `cache_proxy_hits` | int | Proxy-layer cache hits (daemon-persisted) |
30
+ | `cache_proxy_misses` | int | Proxy-layer cache misses (daemon-persisted) |
31
+ | `cache_kv_hits` | int | MCP KV cache hits — **this MCP process session only**, resets on restart |
32
+ | `cache_kv_misses` | int | MCP KV cache misses — **this MCP process session only**, resets on restart |
33
+ | `ccr_note` | str \| None | Note about CCR entry count (not tracked per-session; see daemon `/api/v1/metrics`) |
34
+ | `note` | str \| None | Scope clarification or error detail |
35
+
36
+ ### Important scope distinction
37
+
38
+ `compress_runs`, `tokens_saved_compress`, `cache_proxy_hits`, and `cache_proxy_misses` are **daemon-persisted** — they survive MCP restarts and accumulate over the full install lifetime.
39
+
40
+ `cache_kv_hits` and `cache_kv_misses` are **in-process counters** — they reset to 0 each time the MCP server starts. Use them to gauge cache effectiveness within the current session only.
41
+
42
+ ### Reading whether optimization is saving tokens
43
+
44
+ ```python
45
+ stats = await slm_optimize_stats()
46
+ if stats["ok"]:
47
+ savings = stats["tokens_saved_compress"]
48
+ kv_hit_rate = (
49
+ stats["cache_kv_hits"] / max(stats["cache_kv_hits"] + stats["cache_kv_misses"], 1)
50
+ )
51
+ # savings > 0 and kv_hit_rate > 0.5 means Surface B is actively reducing costs
52
+ ```
53
+
54
+ If `compress_runs` is 0 after several sessions, compression is not being triggered — check daemon config and whether `slm_compress` is being called.
55
+
56
+ If `cache_kv_hits` is 0 after repeated work, verify key naming consistency (the same key string must be used for set and get).
57
+
58
+ ## Secondary CLI: slm status
59
+
60
+ ```bash
61
+ slm status [--json] [--verbose]
62
+ ```
63
+
64
+ Reports system-level state — not optimization counters. Canonical fields (WP-02):
65
+
66
+ - **mode** — active operation mode (e.g. `local`)
67
+ - **profile** — current memory profile name
68
+ - **DB size** — database file size on disk
69
+ - **fact count** — number of stored memory facts
70
+ - **entity count** — entity graph node count
71
+ - **edge count** — entity graph edge count
72
+
73
+ `--verbose` / `-v` adds: migration log, daemon port, disabled marker, last version.
74
+
75
+ `--json` outputs a machine-readable dict with the same fields — preferred for agent consumption.
76
+
77
+ Example agent-native invocation:
78
+
79
+ ```bash
80
+ slm status --json
81
+ ```
82
+
83
+ Typical JSON shape (exact field names depend on runtime; use `--json` and read what arrives):
84
+
85
+ ```json
86
+ {
87
+ "mode": "local",
88
+ "profile": "code",
89
+ "db_size_mb": 12.4,
90
+ "facts": 384,
91
+ "entities": 201,
92
+ "edges": 519
93
+ }
94
+ ```
95
+
96
+ Do not rely on the human-readable format for parsing — always use `--json` when the output feeds another tool.
97
+
98
+ ## Secondary CLI: slm doctor
99
+
100
+ ```bash
101
+ slm doctor [--json] [--quick]
102
+ ```
103
+
104
+ Preflight check covering dependencies, embedding worker, daemon connectivity, and Surface B health. The **"Optimize (Surface B)"** line (WP-03) confirms whether the compression and cache subsystem initialised correctly.
105
+
106
+ `--quick` skips the daemon and embedding probes — runs only dependency and config checks; faster but incomplete.
107
+
108
+ `--json` outputs structured results per check — use this in automated health pipelines.
109
+
110
+ A passing doctor output confirms:
111
+ - Python deps present
112
+ - Embedding worker reachable
113
+ - Daemon responding
114
+ - Surface B (Optimize) initialised
115
+
116
+ A failing "Optimize (Surface B)" line means `slm_compress`, `slm_cache_set`, and `slm_cache_get` may not function correctly — investigate daemon config before relying on those tools.
117
+
118
+ ## Secondary CLI: slm optimize status
119
+
120
+ ```bash
121
+ slm optimize status [--json]
122
+ ```
123
+
124
+ Shows whether the Optimize module (cache + compress) is currently enabled or disabled at the daemon level. Available subcommands also include `optimize on`, `optimize off`, and `optimize savings`.
125
+
126
+ The `optimize savings` subcommand accepts:
127
+
128
+ ```bash
129
+ slm optimize savings [--since <days>] [--provider anthropic|openai|gemini] [--json]
130
+ ```
131
+
132
+ `--since` defaults to 7 days. `--provider` filters by the target AI provider.
133
+
134
+ Note: the `slm optimize` subcommands have known pre-existing parse-test failures — if a subcommand errors, use `slm_optimize_stats()` via MCP as the authoritative source.
135
+
136
+ ## Recommended Health Workflow
137
+
138
+ 1. Run `slm doctor --json` at session start to confirm all subsystems are up.
139
+ 2. Call `slm_optimize_stats()` after a batch of work to check token savings.
140
+ 3. Run `slm status --json` when you need DB size or memory counts.
141
+ 4. If `ok: false` on any MCP tool — check `note` field, then run `slm doctor` to isolate the failure.
142
+
143
+ ## Fail-Open
144
+
145
+ `slm_optimize_stats()` never raises. On internal error it returns `ok: false` with all counters at 0. Continue the session — stats unavailability does not affect compression or caching operations.
146
+
147
+ ---
148
+
149
+ SuperLocalMemory v3.6.18 · Qualixar · AGPL-3.0-or-later
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "3.7.0"
3
+ version = "3.7.1"
4
4
  description = "Local-first agent memory with auditable hybrid retrieval"
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-or-later"
@@ -32,7 +32,7 @@ if "OMP_NUM_THREADS" not in os.environ:
32
32
  os.environ["OMP_NUM_THREADS"] = "2"
33
33
  # ---------------------------------------------------------------------------
34
34
 
35
- __version__ = "3.7.0"
35
+ __version__ = "3.7.1"
36
36
 
37
37
  _REQUIRED_VERSIONS = {
38
38
  "sentence_transformers": "5.3.0",
@@ -4,7 +4,7 @@
4
4
 
5
5
  """WP-07 — Lazy first-run initialisation (pip cross-install).
6
6
 
7
- stdlib-only — zero heavy imports, STDOUT-SILENT.
7
+ Lightweight import only — zero heavy imports, STDOUT-SILENT.
8
8
 
9
9
  Public API
10
10
  ----------
@@ -25,6 +25,8 @@ import json
25
25
  import os
26
26
  from pathlib import Path
27
27
 
28
+ from superlocalmemory import __version__ as _RUNTIME_VERSION
29
+
28
30
 
29
31
  # ---------------------------------------------------------------------------
30
32
  # Public: home resolution
@@ -55,7 +57,7 @@ def slm_home() -> Path:
55
57
  # Only mode + base_dir; everything else uses SLMConfig defaults.
56
58
  _MINIMAL_CONFIG: dict = {
57
59
  "mode": "a",
58
- "version": "3.6.14",
60
+ "version": _RUNTIME_VERSION,
59
61
  }
60
62
 
61
63
 
@@ -22,6 +22,30 @@ if TYPE_CHECKING:
22
22
  logger = logging.getLogger(__name__)
23
23
 
24
24
 
25
+ def _log_reranker_warmup_status(reranker: Any) -> None:
26
+ """Record non-blocking reranker warmup state without alarming first-run users."""
27
+ ready = reranker.warmup_sync(timeout=180)
28
+ if ready:
29
+ logger.info("Cross-encoder reranker warm and ready")
30
+ return
31
+ try:
32
+ from superlocalmemory.retrieval.reranker import _is_reranker_worker_alive
33
+
34
+ if _is_reranker_worker_alive():
35
+ logger.info(
36
+ "Cross-encoder reranker worker held by another process "
37
+ "(machine-wide singleton — usually the unified daemon); "
38
+ "this process will route reranking through that worker"
39
+ )
40
+ return
41
+ except Exception:
42
+ pass
43
+ logger.info(
44
+ "Cross-encoder reranker did not become ready during background warmup; "
45
+ "recalls use fallback scoring. Run 'slm doctor' for diagnostics."
46
+ )
47
+
48
+
25
49
  # ---------------------------------------------------------------------------
26
50
  # init_embedder (was MemoryEngine._init_embedder + helpers)
27
51
  # ---------------------------------------------------------------------------
@@ -552,29 +576,12 @@ def init_retrieval(
552
576
  # trust in slm health / slm doctor output.
553
577
  if reranker is not None:
554
578
  import threading
555
- def _log_warmup_status() -> None:
556
- ready = reranker.warmup_sync(timeout=180)
557
- if ready:
558
- logger.info("Cross-encoder reranker warm and ready")
559
- return
560
- # warmup_sync returned False. Could be (a) singleton held by
561
- # another process (benign), or (b) actual model load failure.
562
- # Disambiguate by probing the singleton PID file.
563
- try:
564
- from superlocalmemory.retrieval.reranker import _is_reranker_worker_alive
565
- if _is_reranker_worker_alive():
566
- logger.info(
567
- "Cross-encoder reranker worker held by another process "
568
- "(machine-wide singleton — usually the unified daemon); "
569
- "this process will route reranking through that worker"
570
- )
571
- return
572
- except Exception:
573
- pass
574
- logger.warning(
575
- "Cross-encoder reranker warmup failed — recalls will use fallback scoring"
576
- )
577
- t = threading.Thread(target=_log_warmup_status, daemon=True, name="ce-init-warmup")
579
+ t = threading.Thread(
580
+ target=_log_reranker_warmup_status,
581
+ args=(reranker,),
582
+ daemon=True,
583
+ name="ce-init-warmup",
584
+ )
578
585
  t.start()
579
586
 
580
587
  # Phase A: Register forgetting filter into the channel registry
@@ -40,7 +40,7 @@ _DEFAULT_DISABLED_FILE = _DEFAULT_VERSION_DIR / ".hooks-disabled"
40
40
  VERSION_DIR = _DEFAULT_VERSION_DIR
41
41
  VERSION_FILE = _DEFAULT_VERSION_FILE
42
42
  DISABLED_FILE = _DEFAULT_DISABLED_FILE
43
- HOOKS_VERSION = "3.7.0"
43
+ HOOKS_VERSION = "3.7.1"
44
44
 
45
45
  # Cross-platform temp dir and backwards-compatible marker overrides. Runtime
46
46
  # defaults are root-namespaced and resolved when hook definitions are built.
@@ -22,7 +22,7 @@ from typing import Callable, Iterable
22
22
  from superlocalmemory.core.security_primitives import redact_secrets
23
23
 
24
24
 
25
- VERSION = "3.7.0"
25
+ VERSION = "3.7.1"
26
26
  DEFAULT_TOP_K = 10
27
27
  DEFAULT_DECISIONS_K = 5
28
28
  DEFAULT_MEMORIES_K = 10
@@ -40,7 +40,7 @@ def install_streamable_http_resource_guard() -> None:
40
40
  class SLMFastMCP(FastMCP):
41
41
  """FastMCP with SLM release identity and deterministic SSE cleanup."""
42
42
 
43
- def __init__(self, *args, product_version: str = "3.7.0", **kwargs) -> None:
43
+ def __init__(self, *args, product_version: str = "3.7.1", **kwargs) -> None:
44
44
  super().__init__(*args, **kwargs)
45
45
  # FastMCP delegates the initialize response to the low-level MCP
46
46
  # server. Without an explicit value it reports the installed ``mcp``
@@ -111,7 +111,7 @@ def register_core_tools(server, get_engine: Callable) -> None:
111
111
  """Store content to memory with intelligent indexing.
112
112
 
113
113
  Extracts atomic facts, resolves entities, builds graph edges,
114
- and indexes for 4-channel retrieval.
114
+ and indexes for hybrid retrieval with graph-aware enhancement.
115
115
 
116
116
  Multi-scope: ``scope`` sets visibility (personal/shared/global).
117
117
  ``shared_with`` is a comma-separated list of profile_ids for
@@ -246,7 +246,7 @@ def register_core_tools(server, get_engine: Callable) -> None:
246
246
  include_global: bool | None = None,
247
247
  include_shared: bool | None = None,
248
248
  ) -> dict:
249
- """Search memories by semantic query with 4-channel retrieval, RRF fusion, and reranking.
249
+ """Search memories through hybrid retrieval, RRF fusion, and reranking.
250
250
 
251
251
  S9-DASH-02: optional ``session_id`` threads through to the
252
252
  engine's outcome-queue so PostToolUse / Stop hooks can attach
@@ -17,7 +17,7 @@ from superlocalmemory.optimize.proxy.lifecycle import HookChain
17
17
 
18
18
  logger = logging.getLogger("slm.optimize.proxy")
19
19
 
20
- _PROXY_VERSION = "3.7.0"
20
+ _PROXY_VERSION = "3.7.1"
21
21
  _REQUEST_TIMEOUT_S = 300.0
22
22
  _CONNECT_TIMEOUT_S = 10.0
23
23
  _MAX_CONNECTIONS = 100
@@ -64,7 +64,7 @@ router = APIRouter(prefix="/api/v3", tags=["brain"])
64
64
  # LLD-03 v2 stratum space = 4 query types × 3 entity bins × 4 time buckets.
65
65
  _STRATA_TOTAL: int = 48
66
66
 
67
- _VERSION: str = "3.7.0"
67
+ _VERSION: str = "3.7.1"
68
68
 
69
69
  # Banned metric names (LLD-04 U4). Kept as a tuple for grep visibility;
70
70
  # the source-level test asserts we don't accidentally reintroduce them.