superlocalmemory 4.1.5 → 4.1.6

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +36 -0
  3. package/README.md +3 -3
  4. package/package.json +1 -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/rules/AGENTS.md +1 -1
  25. package/plugin-src/skills/slm-cache/SKILL.md +1 -1
  26. package/plugin-src/skills/slm-compress/SKILL.md +1 -1
  27. package/plugin-src/skills/slm-governance/SKILL.md +1 -1
  28. package/plugin-src/skills/slm-graph/SKILL.md +1 -1
  29. package/plugin-src/skills/slm-loop/SKILL.md +1 -1
  30. package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
  31. package/plugin-src/skills/slm-profile/SKILL.md +1 -1
  32. package/plugin-src/skills/slm-recall/SKILL.md +1 -1
  33. package/plugin-src/skills/slm-remember/SKILL.md +1 -1
  34. package/plugin-src/skills/slm-scope/SKILL.md +1 -1
  35. package/plugin-src/skills/slm-session/SKILL.md +1 -1
  36. package/plugin-src/skills/slm-status/SKILL.md +1 -1
  37. package/pyproject.toml +1 -1
  38. package/src/superlocalmemory/__init__.py +1 -1
  39. package/src/superlocalmemory/core/maintenance_scheduler.py +36 -0
  40. package/src/superlocalmemory/encoding/fact_extractor.py +7 -3
  41. package/src/superlocalmemory/mcp/session_binding.py +7 -1
@@ -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.6"
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.6"
43
43
  }
44
44
  ]
45
45
  }
package/CHANGELOG.md CHANGED
@@ -5,6 +5,42 @@ 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.6] — A learning loop that never learns looks identical to one that works
9
+
10
+ ### Fixed
11
+ - **The engagement-learning loop settled every outcome at neutral, regardless of
12
+ real usage.** `SESSION_ENV_VARS` checked `SLM_SESSION_ID` and `CLAUDE_SESSION_ID`
13
+ but not `CLAUDE_CODE_SESSION_ID` — the variable Claude Code's own MCP subprocess
14
+ actually sets. Every recall from Claude Code fell through to the synthetic
15
+ `mcp:<agent_id>` id, which step 4 of the resolution ladder deliberately excludes
16
+ from ever matching a pending outcome, by design — a real session should never be
17
+ confused with a placeholder. The result: measured on a live store, 6,013 of 6,039
18
+ settled outcomes carried exactly `reward=0.5`, and all 414 bandit arms held
19
+ `alpha == beta` at every play count. Adding the missing name is what closes the
20
+ loop; two test files that had never isolated session resolution from the ambient
21
+ environment were also hardened, since a live Claude Code session now genuinely
22
+ satisfies the check they'd only ever run without.
23
+ - **Auto-captured facts could assert a date nothing in the source text contained.**
24
+ The fact-extraction system prompt taught relative-date resolution with a fixed
25
+ worked example — `'Yesterday' with session date 2024-01-15 becomes '2024-01-14'`
26
+ — sent identically on every extraction call. A smaller local model under
27
+ uncertainty would echo that literal example date back as if it were extracted
28
+ content, rather than resolving against the real conversation date already present
29
+ in the same prompt. Reproduced live and fixed by removing the concrete date from
30
+ the instruction entirely, teaching the same rule without anything to leak.
31
+ Several existing memories carrying this exact signature — including one date
32
+ claim accessed 28 times — were identified and quarantined.
33
+ - **A store that drifted from M048's classification rule stayed unready for up to a
34
+ full maintenance interval (6 hours) after every restart.** The migration itself
35
+ is idempotent and safe to replay — its own `verify()` docstring says so — but the
36
+ migration runner never replays a completed migration, and the periodic
37
+ maintenance cycle that's supposed to reconcile it only runs once every
38
+ `scheduler_interval_minutes`. A restart landing between cycles reported
39
+ `ready=false, migrations=false` with "automatic replay is disabled" and stayed
40
+ that way until the next scheduled tick. A third staggered one-shot startup timer,
41
+ matching the two that already exist for the same reason (cache GC, graph
42
+ metrics), now runs the same reconciliation pass within seconds of boot instead.
43
+
8
44
  ## [4.1.5] — Ask whether a feature is working, not whether it is present
9
45
 
10
46
  ### 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.6</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.6</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.6-Current_Release-2ea44f?style=for-the-badge&logo=checkmarx&logoColor=white" alt="v4.1.6 — 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.6",
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",
@@ -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.6"
19
19
  }
package/plugin/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- <!-- BEGIN SuperLocalMemory v4.1.5 -->
1
+ <!-- BEGIN SuperLocalMemory v4.1.6 -->
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.6 -->
43
43
 
44
- SuperLocalMemory v4.1.5 · Qualixar · AGPL-3.0-or-later
44
+ SuperLocalMemory v4.1.6 · 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.6 · 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.6 · 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.6 · 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.6 · Qualixar · AGPL-3.0-or-later
@@ -1 +1 @@
1
- superlocalmemory==4.1.5
1
+ superlocalmemory==4.1.6
@@ -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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6 · 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.6"
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__ = "4.1.5"
35
+ __version__ = "4.1.6"
36
36
 
37
37
  _REQUIRED_VERSIONS = {
38
38
  "sentence_transformers": "5.3.0",
@@ -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:
@@ -134,9 +134,13 @@ _SYSTEM_PROMPT = (
134
134
  "must name the subject explicitly.\n"
135
135
  "2. Each fact must be a COMPLETE, STANDALONE statement understandable "
136
136
  "without the original conversation.\n"
137
- "3. Convert ALL relative time to ABSOLUTE dates when possible. "
138
- "'Yesterday' with session date 2024-01-15 becomes '2024-01-14'. "
139
- "'Next month' becomes the actual month and year.\n"
137
+ "3. Convert ALL relative time to ABSOLUTE dates when possible, using "
138
+ "ONLY the conversation date given in the user message below as your "
139
+ "reference point never invent or assume a date. 'Yesterday' resolves "
140
+ "to one calendar day before that conversation date; 'next month' "
141
+ "resolves to the following calendar month of that same date. If no "
142
+ "conversation date is given, leave the date unresolved rather than "
143
+ "guessing one.\n"
140
144
  "4. Resolve ALL coreferences. 'He went there' must become "
141
145
  "'[Person name] went to [Place name]'.\n"
142
146
  "5. Extract relationships between people when mentioned.\n"
@@ -34,7 +34,13 @@ __all__ = ["resolve_session_id", "SESSION_ENV_VARS"]
34
34
 
35
35
  #: Checked in order. Hosts set one or the other; SLM's own takes precedence so a
36
36
  #: user can override a host that sets its variable to something unhelpful.
37
- SESSION_ENV_VARS = ("SLM_SESSION_ID", "CLAUDE_SESSION_ID")
37
+ #: ``CLAUDE_CODE_SESSION_ID`` is the actual variable Claude Code's MCP
38
+ #: subprocess environment carries — verified on a live daemon 2026-08-24,
39
+ #: this pipeline settled 6013/6039 outcomes at the neutral 0.5 fallback
40
+ #: because the old two-name list never matched it, and every recall fell
41
+ #: through to the synthetic ``mcp:<agent_id>`` id that step 4 deliberately
42
+ #: excludes from matching.
43
+ SESSION_ENV_VARS = ("SLM_SESSION_ID", "CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID")
38
44
 
39
45
 
40
46
  def resolve_session_id(