superlocalmemory 4.1.5 → 4.1.7

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 (56) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +3 -3
  4. package/package.json +3 -1
  5. package/plugin/.claude-plugin/plugin.json +1 -1
  6. package/plugin/CLAUDE.md +3 -3
  7. package/plugin/agents/slm-governance-advisor.md +1 -1
  8. package/plugin/agents/slm-loop-runner.md +1 -1
  9. package/plugin/agents/slm-memory-advisor.md +1 -1
  10. package/plugin/agents/slm-optimize-advisor.md +1 -1
  11. package/plugin/requirements.txt +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 +1 -1
  24. package/plugin-src/agents/slm-memory-advisor.md +49 -0
  25. package/plugin-src/agents/slm-optimize-advisor.md +44 -0
  26. package/plugin-src/rules/AGENTS.md +1 -1
  27. package/plugin-src/skills/slm-cache/SKILL.md +1 -1
  28. package/plugin-src/skills/slm-compress/SKILL.md +1 -1
  29. package/plugin-src/skills/slm-governance/SKILL.md +1 -1
  30. package/plugin-src/skills/slm-graph/SKILL.md +1 -1
  31. package/plugin-src/skills/slm-loop/SKILL.md +1 -1
  32. package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
  33. package/plugin-src/skills/slm-profile/SKILL.md +1 -1
  34. package/plugin-src/skills/slm-recall/SKILL.md +1 -1
  35. package/plugin-src/skills/slm-remember/SKILL.md +1 -1
  36. package/plugin-src/skills/slm-scope/SKILL.md +1 -1
  37. package/plugin-src/skills/slm-session/SKILL.md +1 -1
  38. package/plugin-src/skills/slm-status/SKILL.md +1 -1
  39. package/pyproject.toml +5 -1
  40. package/src/superlocalmemory/__init__.py +1 -1
  41. package/src/superlocalmemory/cli/host_upgrades.py +21 -7
  42. package/src/superlocalmemory/core/engine.py +7 -1
  43. package/src/superlocalmemory/core/maintenance_scheduler.py +36 -0
  44. package/src/superlocalmemory/core/recall_pipeline.py +13 -6
  45. package/src/superlocalmemory/core/session_identity.py +14 -1
  46. package/src/superlocalmemory/encoding/fact_extractor.py +7 -3
  47. package/src/superlocalmemory/hooks/codex_assets.py +165 -45
  48. package/src/superlocalmemory/learning/bandit.py +22 -2
  49. package/src/superlocalmemory/learning/engagement_features.py +279 -0
  50. package/src/superlocalmemory/learning/outcome_queue.py +14 -0
  51. package/src/superlocalmemory/learning/propensity.py +131 -0
  52. package/src/superlocalmemory/learning/reward.py +42 -16
  53. package/src/superlocalmemory/learning/reward_model.py +144 -0
  54. package/src/superlocalmemory/learning/reward_proxy.py +148 -22
  55. package/src/superlocalmemory/mcp/session_binding.py +7 -1
  56. package/src/superlocalmemory/server/routes/v3_api.py +4 -3
@@ -21,7 +21,7 @@
21
21
  "license": "AGPL-3.0-or-later",
22
22
  "name": "superlocalmemory",
23
23
  "source": "./plugin",
24
- "version": "4.1.5"
24
+ "version": "4.1.7"
25
25
  },
26
26
  {
27
27
  "author": {
@@ -39,7 +39,7 @@
39
39
  "license": "AGPL-3.0-or-later",
40
40
  "name": "superlocalmemory-codex",
41
41
  "source": "./codex-plugin",
42
- "version": "4.1.5"
42
+ "version": "4.1.7"
43
43
  }
44
44
  ]
45
45
  }
package/CHANGELOG.md CHANGED
@@ -5,6 +5,61 @@ All notable changes to SuperLocalMemory will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.1.7] — Recall that improves with use
9
+
10
+ ### Added
11
+ - **Adaptive ranking is on by default.** Recall now learns which memories
12
+ actually helped and ranks accordingly. Set `SLM_RANKING=off` to opt out.
13
+
14
+ ### Fixed
15
+ - **Ranking never learned anything.** Recalls were not attributed to the
16
+ conversation they came from, so nothing could tell whether a memory had been
17
+ useful, and every result was scored the same regardless. Recalls are now
18
+ attributed correctly and scored from real use.
19
+ - **Unused results are no longer scored as average.** When there is no evidence
20
+ either way, a result is left unscored instead of being recorded as
21
+ middling — which had made the ranking progressively harder to change.
22
+ - **Frequently shown memories no longer reinforce themselves.** A memory that
23
+ was going to be shown regardless now counts for less than one that was not.
24
+ - **Codex subagents install complete.** Installing from a published package
25
+ produced one-line advisor definitions instead of the full ones.
26
+
27
+ ## [4.1.6] — A learning loop that never learns looks identical to one that works
28
+
29
+ ### Fixed
30
+ - **The engagement-learning loop settled every outcome at neutral, regardless of
31
+ real usage.** `SESSION_ENV_VARS` checked `SLM_SESSION_ID` and `CLAUDE_SESSION_ID`
32
+ but not `CLAUDE_CODE_SESSION_ID` — the variable Claude Code's own MCP subprocess
33
+ actually sets. Every recall from Claude Code fell through to the synthetic
34
+ `mcp:<agent_id>` id, which step 4 of the resolution ladder deliberately excludes
35
+ from ever matching a pending outcome, by design — a real session should never be
36
+ confused with a placeholder. The result: measured on a live store, 6,013 of 6,039
37
+ settled outcomes carried exactly `reward=0.5`, and all 414 bandit arms held
38
+ `alpha == beta` at every play count. Adding the missing name is what closes the
39
+ loop; two test files that had never isolated session resolution from the ambient
40
+ environment were also hardened, since a live Claude Code session now genuinely
41
+ satisfies the check they'd only ever run without.
42
+ - **Auto-captured facts could assert a date nothing in the source text contained.**
43
+ The fact-extraction system prompt taught relative-date resolution with a fixed
44
+ worked example — `'Yesterday' with session date 2024-01-15 becomes '2024-01-14'`
45
+ — sent identically on every extraction call. A smaller local model under
46
+ uncertainty would echo that literal example date back as if it were extracted
47
+ content, rather than resolving against the real conversation date already present
48
+ in the same prompt. Reproduced live and fixed by removing the concrete date from
49
+ the instruction entirely, teaching the same rule without anything to leak.
50
+ Several existing memories carrying this exact signature — including one date
51
+ claim accessed 28 times — were identified and quarantined.
52
+ - **A store that drifted from M048's classification rule stayed unready for up to a
53
+ full maintenance interval (6 hours) after every restart.** The migration itself
54
+ is idempotent and safe to replay — its own `verify()` docstring says so — but the
55
+ migration runner never replays a completed migration, and the periodic
56
+ maintenance cycle that's supposed to reconcile it only runs once every
57
+ `scheduler_interval_minutes`. A restart landing between cycles reported
58
+ `ready=false, migrations=false` with "automatic replay is disabled" and stayed
59
+ that way until the next scheduled tick. A third staggered one-shot startup timer,
60
+ matching the two that already exist for the same reason (cache GC, graph
61
+ metrics), now runs the same reconciliation pass within seconds of boot instead.
62
+
8
63
  ## [4.1.5] — Ask whether a feature is working, not whether it is present
9
64
 
10
65
  ### Added
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  </picture>
6
6
  </p>
7
7
 
8
- <h1 align="center">SuperLocalMemory V4.1.5</h1>
8
+ <h1 align="center">SuperLocalMemory V4.1.7</h1>
9
9
 
10
10
  <h2 align="center">Rent the LLM. Own the memory.</h2>
11
11
 
@@ -27,12 +27,12 @@ guarantee here is stated as a falsifiable invariant, tested under an adversarial
27
27
  negative control, and shipped with the harness that regenerates the evidence:
28
28
  <code>python benchmark/run_all.py --trials 200 --output-dir results/</code>. What each experiment
29
29
  does <em>not</em> exercise is stated too.</p>
30
- <p align="center"><code>v4.1.5</code> — one control plane: <strong>SLM-Mesh</strong> peer coordination · multi-scope memory (personal / shared / global) · profiles · Cache · Compress · 7-layer retrieval · code graph · Entity Explorer · skill evolution · Modes A/B/C · GDPR retention &amp; audit chain · bounded loops — across CLI, MCP, dashboard, the <strong>Claude plugin</strong>, the <strong>Codex add-on</strong>, and documented IDE integrations.<br/>
30
+ <p align="center"><code>v4.1.7</code> — one control plane: <strong>SLM-Mesh</strong> peer coordination · multi-scope memory (personal / shared / global) · profiles · Cache · Compress · 7-layer retrieval · code graph · Entity Explorer · skill evolution · Modes A/B/C · GDPR retention &amp; audit chain · bounded loops — across CLI, MCP, dashboard, the <strong>Claude plugin</strong>, the <strong>Codex add-on</strong>, and documented IDE integrations.<br/>
31
31
  Proxy: <code>slm wrap claude</code> &nbsp;·&nbsp; MCP: add <code>slm_compress</code> to your config &nbsp;·&nbsp; Skill: zero-config</p>
32
32
  <p align="center"><strong>Four public arXiv preprints</strong> · V4: <a href="https://arxiv.org/abs/2608.08253">arXiv:2608.08253</a> · companion archive: <a href="https://zenodo.org/records/21853302">Zenodo 21853302</a> (<a href="https://doi.org/10.5281/zenodo.21853302">DOI 10.5281/zenodo.21853302</a>) · prior preprints: <a href="https://arxiv.org/abs/2603.02240">2603.02240</a> · <a href="https://arxiv.org/abs/2603.14588">2603.14588</a> · <a href="https://arxiv.org/abs/2604.04514">2604.04514</a>.</p>
33
33
 
34
34
  <p align="center">
35
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/v4.1.5-Current_Release-2ea44f?style=for-the-badge&logo=checkmarx&logoColor=white" alt="v4.1.5 — Current Release"/></a>
35
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/v4.1.7-Current_Release-2ea44f?style=for-the-badge&logo=checkmarx&logoColor=white" alt="v4.1.7 — Current Release"/></a>
36
36
  <a href="https://arxiv.org/abs/2608.08253"><img src="https://img.shields.io/badge/arXiv-2608.08253-b31b1b?style=for-the-badge&logo=arxiv&logoColor=white" alt="SuperLocalMemory 4.0 paper on arXiv:2608.08253"/></a>
37
37
  <a href="https://zenodo.org/records/21853302"><img src="https://img.shields.io/badge/Zenodo-10.5281%2Fzenodo.21853302-1682D4?style=for-the-badge&logo=zenodo&logoColor=white" alt="V4 paper on Zenodo: 10.5281/zenodo.21853302"/></a>
38
38
  <a href="https://arxiv.org/abs/2603.14588"><img src="https://img.shields.io/badge/arXiv-2603.14588-b31b1b?style=for-the-badge&logo=arxiv&logoColor=white" alt="arXiv Paper"/></a>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlocalmemory",
3
- "version": "4.1.5",
3
+ "version": "4.1.7",
4
4
  "description": "Local-first agent memory with MCP and an agent-native CLI. Documented clients include Claude Code, Cursor, and Windsurf.",
5
5
  "keywords": [
6
6
  "ai-memory",
@@ -96,6 +96,8 @@
96
96
  "plugin-src/skills/slm-scope/SKILL.md",
97
97
  "plugin-src/skills/slm-session/SKILL.md",
98
98
  "plugin-src/skills/slm-status/SKILL.md",
99
+ "plugin-src/agents/slm-memory-advisor.md",
100
+ "plugin-src/agents/slm-optimize-advisor.md",
99
101
  "plugin-src/rules/AGENTS.md",
100
102
  "docs/pi-dev-integration.md",
101
103
  "pyproject.toml",
@@ -15,5 +15,5 @@
15
15
  "mcpServers": "./.mcp.json",
16
16
  "name": "superlocalmemory",
17
17
  "repository": "https://github.com/qualixar/superlocalmemory",
18
- "version": "4.1.5"
18
+ "version": "4.1.7"
19
19
  }
package/plugin/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- <!-- BEGIN SuperLocalMemory v4.1.5 -->
1
+ <!-- BEGIN SuperLocalMemory v4.1.7 -->
2
2
 
3
3
  ## SuperLocalMemory (SLM) — Agent Rules
4
4
 
@@ -39,6 +39,6 @@ slm-recall · slm-remember · slm-session · slm-status · slm-cache · slm-comp
39
39
  ### Subagents
40
40
  slm-memory-advisor (memory decisions, session hygiene, scope/profile guidance) · slm-optimize-advisor (context compression + KV cache) · slm-governance-advisor (scope/roles/compliance/GDPR)
41
41
 
42
- <!-- END SuperLocalMemory v4.1.5 -->
42
+ <!-- END SuperLocalMemory v4.1.7 -->
43
43
 
44
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
44
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -77,4 +77,4 @@ slm-scope · slm-governance · slm-profile · slm-remember · slm-recall
77
77
  # What NOT to do
78
78
  Never session_init twice; never forget without dry-run preview; never store secrets; never bypass role checks; never claim an erasure succeeded without verifying via recall.
79
79
 
80
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
80
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -68,4 +68,4 @@ assessment. The gate is the authority.
68
68
 
69
69
  ---
70
70
 
71
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
71
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -46,4 +46,4 @@ slm-recall · slm-remember · slm-session · slm-scope · slm-profile · slm-gov
46
46
  # What NOT to do
47
47
  Never session_init twice; never forget dry_run=False without reporting preview; never dump a whole file into remember; never invent a memory; never claim "saved" without success:true / clean CLI exit; never bypass scope or governance restrictions.
48
48
 
49
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
49
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -41,4 +41,4 @@ slm-compress · slm-cache · slm-status · slm-profile
41
41
  # What NOT to do
42
42
  Never compress code-for-edit/JSON-to-parse/<500 chars; never store secrets/ccr_ids; never let optimize failure block/alter the task; never claim a specific savings %; never carry ccr_ids across profile switches.
43
43
 
44
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
44
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -1 +1 @@
1
- superlocalmemory==4.1.5
1
+ superlocalmemory==4.1.7
@@ -145,4 +145,4 @@ These subcommands control daemon-level cache settings. They do not read or write
145
145
 
146
146
  ---
147
147
 
148
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
148
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -147,4 +147,4 @@ Content over 1 MB (1 000 000 bytes UTF-8) is processed but `reversible` is force
147
147
 
148
148
  ---
149
149
 
150
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
150
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -245,4 +245,4 @@ Before running any destructive operation (`forget`, `compact_memories`):
245
245
 
246
246
  ---
247
247
 
248
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
248
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -312,4 +312,4 @@ profile. See `slm-profile` for the full profile switching workflow.
312
312
 
313
313
  ---
314
314
 
315
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
315
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -96,4 +96,4 @@ paused, name the approval needed; when errored, quote the short detail.
96
96
 
97
97
  ---
98
98
 
99
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
99
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -279,4 +279,4 @@ mesh availability.
279
279
 
280
280
  ---
281
281
 
282
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
282
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -146,4 +146,4 @@ Name them differently in your MCP config (e.g. `superlocalmemory-personal` and
146
146
 
147
147
  ---
148
148
 
149
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
149
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -323,4 +323,4 @@ before recalling, then switch back. See `slm-profile` for workspace switching.
323
323
 
324
324
  ---
325
325
 
326
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
326
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -270,4 +270,4 @@ different workspace, use `switch_profile` first. See `slm-profile`.
270
270
 
271
271
  ---
272
272
 
273
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
273
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -173,4 +173,4 @@ to review the impact. See `slm-remember` for the full deletion discipline.
173
173
 
174
174
  ---
175
175
 
176
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
176
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -253,4 +253,4 @@ explicitly and call `recall` with `include_global`/`include_shared` after
253
253
 
254
254
  ---
255
255
 
256
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
256
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -163,4 +163,4 @@ multi-profile setup. To switch the active profile, see `slm-profile`.
163
163
 
164
164
  ---
165
165
 
166
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
166
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: slm-memory-advisor
3
+ description: >
4
+ Advises the main agent on using SuperLocalMemory well — when to call
5
+ session_init, remember, recall, and search; how to phrase queries; and how
6
+ to keep memory clean. Delegate here for any "should I save/recall this?"
7
+ decision or when memory results look wrong.
8
+ tools: session_init, recall, search, remember, update_memory, forget, list_recent, Read
9
+ model: inherit
10
+ ---
11
+
12
+ # Role
13
+ You are the SuperLocalMemory (SLM) memory advisor. You help the main agent use the local-first memory system correctly across a session. You do not do the user's primary task — you make memory usage disciplined: the right thing saved, the right thing recalled, nothing duplicated, nothing lost between sessions. Core memory tools run against the configured local data root; optional providers, connectors, backup, and downloads have separate network behavior.
14
+
15
+ # When to act
16
+ When the main agent: starts a session and hasn't loaded project context; is about to or just made a decision worth persisting; asks "what did we decide about X"; gets recall results that look irrelevant/empty; needs advice on scope, profile, or governance.
17
+
18
+ # Tools you may use (real SLM MCP tools, core profile)
19
+ - `session_init(project_path, query, max_results, max_age_days)` — ONCE at session start; returns recent decisions + relevant memories.
20
+ - `recall(query, limit, session_id, fast, include_global, include_shared)` — multi-channel semantic + keyword + temporal + contextual retrieval (default limit 10). Leave `include_global`/`include_shared` unset — recall is private-by-default (v3.6.15). Returns fast local results (~1–2s, no server-side LLM round) plus confidence signals: if `no_confident_match` is true or `answer_confidence` is low, advise the main agent to rewrite into 1–3 sharper sub-queries and recall again rather than treating the memory as absent.
21
+ - `search(query, limit, profile_id)` — exact keyword / FTS5 BM25.
22
+ - `remember(content, tags, project, importance, session_id, scope, shared_with)` — store atomic fact; importance 1-10. Leave `scope` unset (defaults to `personal`/private).
23
+ - `update_memory(fact_id, content)` — correct by exact id.
24
+ - `forget(profile_id, dry_run)` — decay cycle; ALWAYS dry_run=True first, report, never apply blind.
25
+ - `list_recent(limit)` — newest first.
26
+ - `Read` — inspect a file before deciding what to remember.
27
+
28
+ # Decision rules
29
+ 1. SESSION_INIT FIRST — once, before any recall/remember in a fresh session. Never skip; never twice.
30
+ 2. RECALL BEFORE REMEMBER — if it exists, update_memory instead of duplicating.
31
+ 3. REMEMBER ATOMIC DURABLE FACTS ONLY — decisions/conventions/constraints/gotchas/stable prefs; one per call; add tags+project; importance 7-10 for blockers/security/architecture.
32
+ 4. QUERY PHRASING — concept phrases not vague words; pass session_id when available.
33
+ 5. recall vs search — recall for conceptual; search for literal keyword.
34
+ 6. EMPTY/LOW results → broaden, try search, or list_recent; never fabricate.
35
+ 7. SESSION END — close_session(session_id) when work meaningfully complete.
36
+ 8. SCOPE IS OPT-IN (v3.6.15) — every memory is `personal` (private to this profile) by default, and recall returns only this profile's facts. Do NOT set `scope="shared"/"global"` or `include_global`/`include_shared` on your own. Use them ONLY when the user EXPLICITLY asks to share memories across local profiles or to read other profiles' shared/global facts. Default behaviour is identical to single-profile SLM. See slm-scope for the complete sharing model.
37
+ 9. PROFILE CONTEXT (v3.8.0) — session_init and all memory ops use the active profile. If the user needs to work in a different workspace, direct them to switch_profile (requires code/full/power profile). See slm-profile.
38
+ 10. GOVERNANCE — in a governed workspace (admin/member/viewer roles), respect role restrictions: viewers must not write, members must not write global scope without authorization. See slm-governance.
39
+
40
+ # CLI fallback (MCP unavailable)
41
+ recall→`slm recall "<q>" --limit N` (add `--include-global`/`--include-shared` only on explicit user request) · search→`slm search "<q>"` · remember→`slm remember "<c>" --tags a,b` (project/importance are MCP-only, NOT CLI flags; `--scope shared --shared-with a,b` only when the user asks to share) · list→`slm list --limit N` · forget→`slm forget` (preview first) · status→`slm status`. session_init/close_session are daemon-implicit (no CLI verb) — skip on MCP-down.
42
+
43
+ # Related skills
44
+ slm-recall · slm-remember · slm-session · slm-scope · slm-profile · slm-governance
45
+
46
+ # What NOT to do
47
+ Never session_init twice; never forget dry_run=False without reporting preview; never dump a whole file into remember; never invent a memory; never claim "saved" without success:true / clean CLI exit; never bypass scope or governance restrictions.
48
+
49
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: slm-optimize-advisor
3
+ description: >
4
+ Applies SuperLocalMemory's context-optimization rules — reversible
5
+ compression of large tool output and KV-caching of repeated reads/searches —
6
+ to stretch the context window with no proxy. Delegate here when context is
7
+ filling up or the same files/searches are read repeatedly. Strictly advisory
8
+ and fail-open: optimization must never block the primary task.
9
+ tools: slm_compress, slm_retrieve, slm_cache_set, slm_cache_get, slm_optimize_stats, Read, Bash
10
+ model: inherit
11
+ ---
12
+
13
+ # Role
14
+ You are the SLM optimize advisor. You reduce context-window pressure using Surface-B tools: reversible compression (CCR) and a per-agent KV cache. No proxy; full 1M window preserved on any plan. You apply the same rules as the slm-compress and slm-cache skills. You cannot cache the primary Claude turn (needs a proxy) — only content the agent routes through SLM.
15
+
16
+ # When to act
17
+ Tool/file read >~2000 chars; same file or bash/web search about to be re-read; user asks how much context saved; context tight with large outputs sitting in window.
18
+
19
+ # Tools (real SLM MCP tools, core profile)
20
+ slm_compress(content,mode,reversible,ttl_seconds)→compressed,lossy,ccr_id (mode normalize|auto|aggressive); slm_retrieve(ccr_id); slm_cache_set(key,value,ttl_seconds); slm_cache_get(key)→hit,value; slm_optimize_stats(); Read/Bash to fetch content.
21
+
22
+ # Decision rules (the 8 — apply automatically)
23
+ 1. CLAUDE.md >3000 chars → slm_compress(mode="normalize", reversible=False), use compressed IN CONTEXT ONLY; never modify the file.
24
+ 2. Tool output >2000 chars → slm_compress(mode="auto", reversible=True); work from compressed; keep ccr_id if lossy.
25
+ 3. Repeated file reads → slm_cache_get("file:<path>") first; on miss Read then slm_cache_set("file:<path>", ttl 1800); invalidate on Edit/Write.
26
+ 4. Repeated bash/web → slm_cache_set("bash:<cmd[:64]>", ttl 600); web ttl 3600.
27
+ 5. Retrieve original only when byte-identical needed.
28
+ 6. NEVER compress/cache: code for Edit/Write; JSON to parse; secrets/keys/tokens; ccr_ids; <500 chars.
29
+ 7. Stats → slm_optimize_stats() (KV this-session; proxy/compress daemon-persisted).
30
+ 8. FAIL-OPEN: ok:false → continue with original, no retry, don't surface unless asked. Never block the task.
31
+
32
+ # Profile context (v3.8.0)
33
+ Cache entries are namespaced per active profile — if the user switches profiles via switch_profile, the cache is effectively fresh for the new profile. Do not carry ccr_id values across profile switches.
34
+
35
+ # CLI fallback
36
+ stats→`slm optimize status`/`savings` · compress→`slm compress` · cache→`slm cache ...`. If CLI also fails, drop optimization silently (rule 8).
37
+
38
+ # Related skills
39
+ slm-compress · slm-cache · slm-status · slm-profile
40
+
41
+ # What NOT to do
42
+ Never compress code-for-edit/JSON-to-parse/<500 chars; never store secrets/ccr_ids; never let optimize failure block/alter the task; never claim a specific savings %; never carry ccr_ids across profile switches.
43
+
44
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -137,4 +137,4 @@ When the SLM MCP server is unavailable, use these CLI equivalents:
137
137
  - **slm-optimize-advisor** — context compression and KV cache
138
138
  - **slm-governance-advisor** — scope/role compliance, retention policies, GDPR
139
139
 
140
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
140
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -145,4 +145,4 @@ These subcommands control daemon-level cache settings. They do not read or write
145
145
 
146
146
  ---
147
147
 
148
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
148
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -147,4 +147,4 @@ Content over 1 MB (1 000 000 bytes UTF-8) is processed but `reversible` is force
147
147
 
148
148
  ---
149
149
 
150
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
150
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -245,4 +245,4 @@ Before running any destructive operation (`forget`, `compact_memories`):
245
245
 
246
246
  ---
247
247
 
248
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
248
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -312,4 +312,4 @@ profile. See `slm-profile` for the full profile switching workflow.
312
312
 
313
313
  ---
314
314
 
315
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
315
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -96,4 +96,4 @@ paused, name the approval needed; when errored, quote the short detail.
96
96
 
97
97
  ---
98
98
 
99
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
99
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
@@ -279,4 +279,4 @@ mesh availability.
279
279
 
280
280
  ---
281
281
 
282
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
282
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -146,4 +146,4 @@ Name them differently in your MCP config (e.g. `superlocalmemory-personal` and
146
146
 
147
147
  ---
148
148
 
149
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
149
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -323,4 +323,4 @@ before recalling, then switch back. See `slm-profile` for workspace switching.
323
323
 
324
324
  ---
325
325
 
326
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
326
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -270,4 +270,4 @@ different workspace, use `switch_profile` first. See `slm-profile`.
270
270
 
271
271
  ---
272
272
 
273
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
273
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -173,4 +173,4 @@ to review the impact. See `slm-remember` for the full deletion discipline.
173
173
 
174
174
  ---
175
175
 
176
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
176
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -253,4 +253,4 @@ explicitly and call `recall` with `include_global`/`include_shared` after
253
253
 
254
254
  ---
255
255
 
256
- *SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later*
256
+ *SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later*
@@ -163,4 +163,4 @@ multi-profile setup. To switch the active profile, see `slm-profile`.
163
163
 
164
164
  ---
165
165
 
166
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
166
+ SuperLocalMemory v4.1.7 · Qualixar · AGPL-3.0-or-later
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "superlocalmemory"
3
- version = "4.1.5"
3
+ version = "4.1.7"
4
4
  description = "Local-first agent memory with auditable hybrid retrieval"
5
5
  readme = "README.md"
6
6
  license = "AGPL-3.0-or-later"
@@ -186,6 +186,10 @@ superlocalmemory = ["ui/**/*", "optimize/NOTICE", "contracts/schemas/*.json"]
186
186
  "share/superlocalmemory/codex/skills/slm-scope" = ["plugin-src/skills/slm-scope/SKILL.md"]
187
187
  "share/superlocalmemory/codex/skills/slm-session" = ["plugin-src/skills/slm-session/SKILL.md"]
188
188
  "share/superlocalmemory/codex/skills/slm-status" = ["plugin-src/skills/slm-status/SKILL.md"]
189
+ "share/superlocalmemory/codex/agents" = [
190
+ "plugin-src/agents/slm-memory-advisor.md",
191
+ "plugin-src/agents/slm-optimize-advisor.md",
192
+ ]
189
193
  "share/superlocalmemory/portable-kit/rules" = ["plugin-src/rules/AGENTS.md"]
190
194
 
191
195
  [tool.pytest.ini_options]
@@ -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__ = "4.1.5"
35
+ __version__ = "4.1.7"
36
36
 
37
37
  _REQUIRED_VERSIONS = {
38
38
  "sentence_transformers": "5.3.0",
@@ -145,13 +145,27 @@ def _upgrade_host(host: str, *, apply: bool, already_integrated: bool) -> dict[s
145
145
  if not assets.get("success") or not hooks.get("success"):
146
146
  return {"status": "blocked", "detail": "could not refresh SLM-owned Codex assets"}
147
147
  action = "would refresh" if not apply else "refreshed"
148
- return {
149
- "status": "updated" if apply else "preview",
150
- "detail": (
151
- f"{action} SLM-owned Codex skills, agents, and hooks; "
152
- "MCP block preserved"
153
- ),
154
- }
148
+ # Name what is actually written. Saying "refreshed skills" while the
149
+ # copies under ~/.agents/skills are not what this Codex reads turns a
150
+ # no-op into a success report.
151
+ written = assets.get("skills_written") or []
152
+ agents_written = assets.get("agents_written") or []
153
+ preserved = assets.get("agents_preserved") or []
154
+ elsewhere = assets.get("skills_read_elsewhere") or []
155
+
156
+ detail = f"{action} {len(written)} skill file(s) and {len(agents_written)} subagent file(s)"
157
+ if written:
158
+ detail += f" under {Path(written[0]).parent.parent}"
159
+ detail += "; hooks refreshed; MCP block preserved"
160
+ if preserved:
161
+ names = ", ".join(Path(x).name for x in preserved)
162
+ detail += f"; preserved {len(preserved)} subagent file(s) not written by SLM ({names})"
163
+ if elsewhere:
164
+ detail += (
165
+ f"; {len(elsewhere)} skill path(s) under ~/.codex/skills resolve outside "
166
+ f"the written location and were NOT refreshed ({Path(elsewhere[0]).parent})"
167
+ )
168
+ return {"status": "updated" if apply else "preview", "detail": detail}
155
169
 
156
170
  if already_integrated:
157
171
  return {
@@ -24,6 +24,7 @@ import time
24
24
  from pathlib import Path
25
25
  from typing import Any
26
26
 
27
+ from superlocalmemory.core.session_identity import synthetic_session_id
27
28
  from superlocalmemory.core.config import CANONICAL_RECALL_LIMIT, SLMConfig
28
29
  from superlocalmemory.core.engine_capabilities import Capabilities, CapabilityError
29
30
  from superlocalmemory.core.modes import get_capabilities
@@ -138,7 +139,12 @@ class MemoryEngine:
138
139
  # one is dropped by the queue, which is how 34 of 35 recall paths came
139
140
  # to leave no record at all.
140
141
  self._last_session_id: str = ""
141
- self._ambient_session_id: str = f"engine:{os.getpid()}"
142
+ # Minted through the shared helper so this id is registered as
143
+ # invented rather than received; continuity and the reward pipeline
144
+ # both ask session_identity, and a hand-built prefix is invisible to it.
145
+ self._ambient_session_id: str = synthetic_session_id(
146
+ "engine", str(os.getpid()),
147
+ )
142
148
  self._initialized = False
143
149
 
144
150
  self._db = None
@@ -77,11 +77,43 @@ class MaintenanceScheduler:
77
77
  )
78
78
  self._initial_metrics_timer.daemon = True
79
79
  self._initial_metrics_timer.start()
80
+ # M048's re-read pass is idempotent and safe to replay (see its
81
+ # verify() docstring), but the migration runner never replays a
82
+ # completed migration and the cycle above only reaches it every
83
+ # ``scheduler_interval_minutes`` (360 by default). A store that
84
+ # drifted since the last cycle stays blocking — ready=false,
85
+ # migrations=false — for up to that whole interval after every
86
+ # restart, not because the fix is slow, but because nothing asks
87
+ # for it sooner. Staggered behind the other two so none of the
88
+ # three one-shots contend for the write lock.
89
+ self._initial_reclassify_timer = threading.Timer(
90
+ 210.0, self._initial_reclassify_upcoming,
91
+ )
92
+ self._initial_reclassify_timer.daemon = True
93
+ self._initial_reclassify_timer.start()
80
94
  logger.info(
81
95
  "Maintenance scheduler started (interval=%dm)",
82
96
  self._config.forgetting.scheduler_interval_minutes,
83
97
  )
84
98
 
99
+ def _initial_reclassify_upcoming(self) -> None:
100
+ """Best-effort one-shot M048 re-read shortly after boot.
101
+
102
+ Runs the same pass the periodic cycle already runs (see below) so a
103
+ store that drifted before this restart converges within seconds
104
+ instead of waiting up to a full maintenance interval with the
105
+ daemon reporting itself not ready.
106
+ """
107
+ if not self._running:
108
+ return
109
+ try:
110
+ from superlocalmemory.storage.migrations import (
111
+ M048_upcoming_holds_only_what_is_upcoming as _reclassify,
112
+ )
113
+ _reclassify.apply(open_connection=self._db.raw_connection)
114
+ except Exception as exc:
115
+ logger.debug("Startup plan re-read skipped: %s", exc)
116
+
85
117
  def _initial_cache_gc(self) -> None:
86
118
  """Best-effort one-shot activation-cache GC shortly after boot."""
87
119
  if not self._running:
@@ -133,6 +165,10 @@ class MaintenanceScheduler:
133
165
  if _metrics_timer is not None:
134
166
  _metrics_timer.cancel()
135
167
  self._initial_metrics_timer = None
168
+ _reclassify_timer = getattr(self, "_initial_reclassify_timer", None)
169
+ if _reclassify_timer is not None:
170
+ _reclassify_timer.cancel()
171
+ self._initial_reclassify_timer = None
136
172
  logger.info("Maintenance scheduler stopped")
137
173
 
138
174
  def _schedule_next(self) -> None: