claude-mem-lite 2.34.1 → 2.34.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": "2.34.1",
13
+ "version": "2.34.2",
14
14
  "source": "./",
15
15
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall"
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.34.1",
3
+ "version": "2.34.2",
4
4
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/mem-cli.mjs CHANGED
@@ -742,8 +742,11 @@ function cmdTimeline(db, args) {
742
742
  return;
743
743
  }
744
744
 
745
- const projectFilter = project ? 'AND project = ?' : '';
746
- const baseParams = project ? [project] : [];
745
+ // Auto-scope to anchor's project when --project not explicitly given: users asking
746
+ // "what happened around #N" expect same-project context, not cross-project time-bleed.
747
+ const effectiveProject = project || anchorRow.project;
748
+ const projectFilter = effectiveProject ? 'AND project = ?' : '';
749
+ const baseParams = effectiveProject ? [effectiveProject] : [];
747
750
 
748
751
  // Before anchor
749
752
  const beforeRows = db.prepare(`
@@ -1721,17 +1724,26 @@ function cmdMaintain(db, args) {
1721
1724
  }
1722
1725
 
1723
1726
  if (ops.includes('dedup') && flags['merge-ids']) {
1724
- // Parse merge-ids: "keepId:removeId1:removeId2,keepId2:removeId3" format
1727
+ // Parse merge-ids: "keepId:removeId1:removeId2,keepId2:removeId3" format.
1728
+ // Surface malformed segments (non-numeric tokens, single-element pairs) instead of
1729
+ // silently dropping them, so typos like "abc:def" don't hide behind "Merged 0".
1725
1730
  let totalMerged = 0;
1731
+ const invalidSegments = [];
1726
1732
  const mergeStmt = db.prepare('UPDATE observations SET compressed_into = ? WHERE id = ? AND COALESCE(compressed_into, 0) = 0');
1727
- const groups = flags['merge-ids'].split(',').map(g => g.trim().split(':').map(Number).filter(n => !isNaN(n)));
1728
- for (const group of groups) {
1729
- if (group.length < 2) continue;
1730
- const [keepId, ...removeIds] = group;
1733
+ const rawSegments = flags['merge-ids'].split(',').map(s => s.trim()).filter(Boolean);
1734
+ for (const seg of rawSegments) {
1735
+ const parts = seg.split(':').map(s => s.trim());
1736
+ const nums = parts.map(p => Number(p));
1737
+ const badToken = parts.length < 2 || nums.some(n => !Number.isFinite(n) || n <= 0);
1738
+ if (badToken) { invalidSegments.push(seg); continue; }
1739
+ const [keepId, ...removeIds] = nums;
1731
1740
  for (const removeId of removeIds) {
1732
1741
  totalMerged += mergeStmt.run(keepId, removeId).changes;
1733
1742
  }
1734
1743
  }
1744
+ if (invalidSegments.length) {
1745
+ results.push(`Warning: ignored ${invalidSegments.length} malformed --merge-ids segment(s): ${invalidSegments.join(', ')} (expected keepId:removeId[:removeId...] with positive integers)`);
1746
+ }
1735
1747
  results.push(`Merged ${totalMerged} duplicate observations`);
1736
1748
  }
1737
1749
 
@@ -2070,6 +2082,16 @@ Commands:
2070
2082
  --project P Filter by project
2071
2083
  --retain-days N For purge_stale: keep last N days (default 30)
2072
2084
 
2085
+ optimize LLM-powered memory optimization (preview by default)
2086
+ --run Execute (default: preview gates)
2087
+ --run-all Execute bypassing gates
2088
+ --task T Comma-separated: re-enrich,normalize,cluster-merge,smart-compress
2089
+ --max N Max items per task (1-100, default 15)
2090
+ --scope S re-enrich scope: narrow (default) or wide
2091
+
2092
+ doctor Environment diagnostics and benchmarks
2093
+ --benchmark Run perf benchmark and emit JSON
2094
+
2073
2095
  fts-check <check|rebuild> FTS5 index check or rebuild
2074
2096
 
2075
2097
  stats Show memory statistics
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.34.1",
3
+ "version": "2.34.2",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {
@@ -188,15 +188,19 @@ try {
188
188
  const lines = [];
189
189
  if (allRows.length > 0) {
190
190
  lines.push(`[mem] Lessons for ${fname}:`);
191
+ // R3-UX: raised from 120 → 240 after measuring 97% of lessons exceed 120 chars
192
+ // (p50=218, avg=247). Previous limit truncated the actionable "Fix:" tail in 80%
193
+ // of lessons containing it. 3 × 240 ≈ 180 tokens/Edit — negligible context cost.
194
+ const LESSON_MAX = 240;
191
195
  for (const r of allRows) {
192
196
  if (r.lesson_learned) {
193
- const lesson = r.lesson_learned.length > 120
194
- ? r.lesson_learned.slice(0, 117) + '...'
197
+ const lesson = r.lesson_learned.length > LESSON_MAX
198
+ ? r.lesson_learned.slice(0, LESSON_MAX - 3) + '...'
195
199
  : r.lesson_learned;
196
200
  lines.push(` #${r.id} [${r.type}] ${lesson}`);
197
201
  } else {
198
- const title = (r.title || '').length > 120
199
- ? r.title.slice(0, 117) + '...'
202
+ const title = (r.title || '').length > LESSON_MAX
203
+ ? r.title.slice(0, LESSON_MAX - 3) + '...'
200
204
  : (r.title || '');
201
205
  lines.push(` #${r.id} [${r.type}] ${title}`);
202
206
  }
package/server.mjs CHANGED
@@ -789,8 +789,11 @@ server.registerTool(
789
789
  db.prepare('UPDATE observations SET access_count = COALESCE(access_count, 0) + 1, last_accessed_at = ? WHERE id = ?').run(Date.now(), anchorId);
790
790
  } catch { /* non-critical: FTS5 trigger may fail on corrupted index */ }
791
791
 
792
- const projectFilter = args.project ? 'AND project = ?' : '';
793
- const baseParams = args.project ? [args.project] : [];
792
+ // Auto-scope to anchor's project when caller didn't pass one: "timeline around #N"
793
+ // means same-project context by default; cross-project bleed breaks user mental model.
794
+ const effectiveProject = args.project || anchorRow.project;
795
+ const projectFilter = effectiveProject ? 'AND project = ?' : '';
796
+ const baseParams = effectiveProject ? [effectiveProject] : [];
794
797
 
795
798
  // Before anchor
796
799
  const beforeRows = db.prepare(`