claude-mem-lite 2.53.2 → 2.54.0

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.53.2",
13
+ "version": "2.54.0",
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.53.2",
3
+ "version": "2.54.0",
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/hook-llm.mjs CHANGED
@@ -677,9 +677,13 @@ search_aliases: 2-6 alternative search terms someone might use to find this memo
677
677
  files: episode.files,
678
678
  filesRead: episode.filesRead || [],
679
679
  // v2.33.1: when lesson is low-signal, don't trust Haiku's importance
680
- // inflation for noise-prone types. rule-based floor still applies so
681
- // error-in-test (→3) / config-change (→2) keep their floor.
682
- importance: isLessonLowSignal && (parsed.type === 'change' || parsed.type === 'discovery')
680
+ // inflation. v2.54.0: extended from {change, discovery} to all types
681
+ // except `decision` after audit (2026-04-30) showed bugfix lesson
682
+ // coverage 11.2% / refactor hit-rate 18.1% Haiku marks bugfix/refactor
683
+ // imp=2-3 even when lesson is null after retry. Keep `decision` exempt:
684
+ // it's rare (39 obs / 94.9% hit-rate) and the retry path already gave
685
+ // it a second chance; a no-lesson decision is still a worthwhile signal.
686
+ importance: isLessonLowSignal && parsed.type !== 'decision'
683
687
  ? Math.min(ruleImportance, 1)
684
688
  : Math.max(ruleImportance, clampImportance(parsed.importance)),
685
689
  lessonLearned,
package/hook-optimize.mjs CHANGED
@@ -709,7 +709,14 @@ export async function handleLLMOptimize() {
709
709
  }
710
710
 
711
711
  try {
712
- const results = await optimizeRun(db);
712
+ // v2.54.0: auto-maintain default scope is 'wide'. Narrow scope (the prior
713
+ // default) only matches fully-degraded rows (no concepts AND no facts AND
714
+ // no lesson AND no aliases) — production diagnostic 2026-04-30 found only
715
+ // 56 obs ever optimized after months of daily auto-maintain runs. Wide
716
+ // targets bugfix/refactor/feature/decision rows with substantive narrative
717
+ // but missing lesson_learned, which is exactly the audit's 11.2% coverage
718
+ // gap. CLI `mem optimize` keeps narrow as default for explicit invocations.
719
+ const results = await optimizeRun(db, { reenrichScope: 'wide' });
713
720
  const parts = [];
714
721
  if (results.reenrich?.processed) parts.push(`re-enriched: ${results.reenrich.processed}`);
715
722
  if (results.normalize?.processed) parts.push(`normalized: ${results.normalize.processed}`);
@@ -155,19 +155,26 @@ export function isNoiseObservation(obs, env = process.env) {
155
155
  const lesson = obs.lessonLearned ?? obs.lesson_learned;
156
156
  if (lesson && String(lesson).trim() && String(lesson).trim().toLowerCase() !== 'none') return false;
157
157
 
158
- if ((obs.importance ?? 1) >= 2) return false;
159
-
160
- if (Array.isArray(obs.facts) &&
161
- obs.facts.filter(f => typeof f === 'string' && f.trim().length > 0).length >= 1) {
162
- return false;
163
- }
158
+ const hasFacts = Array.isArray(obs.facts) &&
159
+ obs.facts.filter(f => typeof f === 'string' && f.trim().length > 0).length >= 1;
160
+ if (hasFacts) return false;
164
161
 
165
162
  const narrative = (obs.narrative || '').trim();
166
- if (narrative.length >= 40 &&
167
- !/^Error[: ]/i.test(narrative) &&
168
- !_isLikelyToolOutputPassthrough(narrative)) {
169
- return false;
170
- }
163
+ const isPassthrough = _isLikelyToolOutputPassthrough(narrative);
164
+ const isStderrShape = /^Error[: ]/i.test(narrative);
165
+
166
+ // v2.54.0: raw tool-output passthrough is always noise regardless of importance.
167
+ // Rule-based importance (computeRuleImportance) can hit 2-3 from filename
168
+ // heuristics (test/schema/migration) even when narrative is just
169
+ // "cmd → ERROR: stderr" — 30d audit found 64 'Error: X' titles surviving via
170
+ // imp=2 escape with raw stderr narratives. Per #8152 paired-gate model: this
171
+ // is the drop counterpart to capNoiseImportance's demote — both must check
172
+ // the same passthrough signal.
173
+ if (isPassthrough || isStderrShape) return true;
174
+
175
+ if ((obs.importance ?? 1) >= 2) return false;
176
+
177
+ if (narrative.length >= 40) return false;
171
178
 
172
179
  return true;
173
180
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.53.2",
3
+ "version": "2.54.0",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {