claude-mem-lite 3.39.1 → 3.39.2

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.
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "claude-mem-lite",
13
- "version": "3.39.1",
13
+ "version": "3.39.2",
14
14
  "source": "./",
15
15
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark)."
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "3.39.1",
3
+ "version": "3.39.2",
4
4
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/commands/bug.md CHANGED
@@ -43,13 +43,16 @@ Map severity to importance:
43
43
  Build the body as `<description>\n\nRepro:\n<repro-steps>` (or just
44
44
  `<description>` if `--repro` is absent).
45
45
 
46
- Run via Bash — the body is the positional content; the description goes in
47
- `--lesson` so it lands in the high-weight `lesson_learned` field:
46
+ Run via Bash — the full body is the positional content; a distilled description
47
+ goes in `--lesson` so it lands in the high-weight `lesson_learned` field.
48
+ `--lesson` is capped at 500 chars (longer values are rejected), so keep the full
49
+ body in the positional content and trim `--lesson` to the core description if
50
+ longer:
48
51
 
49
52
  node ${CLAUDE_PLUGIN_ROOT}/cli.mjs save "<body>" \
50
53
  --type bugfix \
51
54
  --title "<first 60 chars of description>" \
52
- --lesson "<description>" \
55
+ --lesson "<description, ≤500 chars>" \
53
56
  [--files f1,f2,...] \
54
57
  --importance <1|2|3>
55
58
 
@@ -36,13 +36,16 @@ Don't use for trivial fixes (typos, renames), for rules that belong in memdir
36
36
 
37
37
  ## Execution
38
38
 
39
- Run via Bash — pass the lesson text as the positional content and repeat it in
40
- `--lesson` so it lands in the high-weight `lesson_learned` field:
39
+ Run via Bash — pass the full lesson text as the positional content, and a
40
+ distilled version in `--lesson` so it lands in the high-weight `lesson_learned`
41
+ field. `--lesson` is capped at 500 chars (longer values are rejected), so for a
42
+ long lesson keep the full text in the positional content and trim `--lesson` to
43
+ the core insight:
41
44
 
42
45
  node ${CLAUDE_PLUGIN_ROOT}/cli.mjs save "<full text>" \
43
46
  --type discovery \
44
47
  --title "<first 60 chars of text>" \
45
- --lesson "<full text>" \
48
+ --lesson "<core insight, ≤500 chars>" \
46
49
  [--files f1,f2,...] \
47
50
  --importance <1|2|3>
48
51
 
package/hook-optimize.mjs CHANGED
@@ -171,6 +171,10 @@ Give 3-6 aliases: words a user might search for the SAME concept but that are NO
171
171
  const safe = scrubRecord('observations', { text: appendedText, search_aliases: searchAliases });
172
172
  db.prepare(`UPDATE observations SET search_aliases = ?, text = ? WHERE id = ?`)
173
173
  .run(safe.search_aliases, safe.text, cand.id);
174
+ // Refresh the TF-IDF vector from the just-updated FTS text so the new
175
+ // aliases reach the vector arm too — the narrow/wide branch rebuilds, this
176
+ // one must as well. No-ops when the vector arm is off / vocab unbuilt.
177
+ rebuildVector(db, cand.id, [safe.text]);
174
178
  processed++;
175
179
  continue;
176
180
  }
package/lib/activity.mjs CHANGED
@@ -131,10 +131,12 @@ export function recentEvents(db, { project, type = null, limit = 20 } = {}) {
131
131
  * importance>=minImportance) into searchable observations. mem_search / passive
132
132
  * injection never read the events table, so explicit /bug /lesson history and
133
133
  * high-value auto-captured events were unfindable. Each promoted event is marked
134
- * (superseded_at_epoch + superseded_by_id the new obs id) so re-runs are
135
- * idempotent. The source event row is kept (activity log intact), just retired.
134
+ * with superseded_at_epoch ONLY (superseded_by_id is a self-FK events(id), so an
135
+ * observation id there fails the FK on the real DB the marker alone gives
136
+ * idempotency) so re-runs skip it. The source event row is kept (activity log
137
+ * intact), just retired.
136
138
  *
137
- * @returns {{eligible:number, promoted:number, deduped:number}}
139
+ * @returns {{eligible:number, promoted:number, deduped:number, skipped:number}}
138
140
  */
139
141
  export function promoteInsightEvents(db, { project = null, minImportance = 2, execute = false, limit = 5000 } = {}) {
140
142
  const projClause = project ? 'AND project = ?' : '';
@@ -128,8 +128,11 @@ const ACTIVITY_SAVE_LESSON_RE = /activity\s+save\s+--type\s+(lesson|bugfix)\b/;
128
128
  // P2(a): /bug and /lesson were redirected from `activity save` (events) to
129
129
  // `cli.mjs save … --lesson` (searchable observations). Recognize that shape too,
130
130
  // or the unsaved-bugfix nudge over-fires after an explicit save. Anchored on the
131
- // mem CLI + the --lesson flag both skills always pass.
132
- const OBS_INSIGHT_SAVE_RE = /(?:cli\.mjs|claude-mem-lite)['"]?\s+save\b[^\n]*--lesson(?:-learned)?\b/;
131
+ // mem CLI + the --lesson flag both skills always pass. Uses `[\s\S]*?` (not
132
+ // `[^\n]*`) because the skill templates document a multi-line, backslash-
133
+ // continued command — after JSON.parse the command carries real newlines, so the
134
+ // gap between `save` and `--lesson` must be allowed to span them (lazy → nearest).
135
+ const OBS_INSIGHT_SAVE_RE = /(?:cli\.mjs|claude-mem-lite)['"]?\s+save\b[\s\S]*?--lesson(?:-learned)?\b/;
133
136
  const MEM_SAVE_TOOL_NAMES = new Set([
134
137
  'mem_save',
135
138
  'mcp__claude_mem_lite__mem_save',
@@ -113,7 +113,10 @@ export function saveObservation(db, params) {
113
113
  });
114
114
 
115
115
  insertObservationFiles(db, savedId, files);
116
- insertObservationVector(db, savedId, safeTitle + ' ' + safeContent);
116
+ // Vector text mirrors the FTS-indexed content (title + content + lesson) so a
117
+ // lesson-only term isn't invisible to the vector arm (finding #8). Reuses the
118
+ // same indexText the FTS `text` field is built from.
119
+ insertObservationVector(db, savedId, indexText);
117
120
 
118
121
  return savedId;
119
122
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "3.39.1",
3
+ "version": "3.39.2",
4
4
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",