claude-mem-lite 2.33.3 → 2.33.5

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.33.3",
13
+ "version": "2.33.5",
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.33.3",
3
+ "version": "2.33.5",
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.mjs CHANGED
@@ -109,10 +109,15 @@ if (!event) process.exit(0);
109
109
 
110
110
  // ─── Episode Flush ──────────────────────────────────────────────────────────
111
111
 
112
- // hookEventName defaults to 'PostToolUse' since that's the most common caller.
113
- // Stop / SessionStart callers MUST pass their own event name — CC rejects
114
- // hook output whose hookEventName doesn't match the triggering event
115
- // (regression introduced in v2.33.1's structured receipt, fixed in v2.33.3).
112
+ // hookEventName serves two roles: it is written into the emitted receipt JSON
113
+ // AND it gates emission via RECEIPT_EVENTS. Callers MUST pass their triggering
114
+ // event name so both work Stop falls outside the allowlist, so its receipt
115
+ // is skipped entirely (CC's Stop schema rejects hookSpecificOutput at the root,
116
+ // not just on event-name mismatch). The episode still flushes to DB and
117
+ // spawns llm-episode background enrichment; only the stdout receipt is gated.
118
+ // Regression chain: v2.33.1 introduced the receipt; v2.33.3 misdiagnosed the
119
+ // Stop rejection as event-name mismatch; v2.33.4 is the root-cause fix.
120
+ const RECEIPT_EVENTS = new Set(['PostToolUse', 'SessionStart', 'UserPromptSubmit']);
116
121
  function flushEpisode(episode, hookEventName = 'PostToolUse') {
117
122
  if (!episode || episode.entries.length === 0) return;
118
123
 
@@ -157,32 +162,35 @@ function flushEpisode(episode, hookEventName = 'PostToolUse') {
157
162
  // and the legacy error→fix nudge consolidates here. PostToolUse JSON with
158
163
  // hookSpecificOutput.additionalContext reliably renders across CC variants;
159
164
  // the old plain-text stdout write was invisible on some variants.
160
- try {
161
- const entries = episode.entries || [];
162
- const hasError = entries.some(e => e.isError);
163
- const hasEdit = entries.some(e => EDIT_TOOLS.has(e.tool));
164
- const toolCounts = {};
165
- for (const e of entries) toolCounts[e.tool] = (toolCounts[e.tool] || 0) + 1;
166
- const toolSummary = Object.entries(toolCounts)
167
- .sort((a, b) => b[1] - a[1])
168
- .slice(0, 3)
169
- .map(([t, n]) => `${t}×${n}`)
170
- .join(', ');
171
- const lines = [`[mem] episode flushed: ${entries.length} entries (${toolSummary})`];
172
- if (hasError && hasEdit && entries.length >= 3) {
173
- const editFiles = entries.filter(e => EDIT_TOOLS.has(e.tool)).flatMap(e => e.files || []);
174
- const uniqueFiles = [...new Set(editFiles)].slice(0, 3);
175
- const filesHint = uniqueFiles.length > 0 ? ` (${uniqueFiles.join(', ')})` : '';
176
- lines.push(`[mem] 💡 error→fix pattern${filesHint} — consider: mem_save(type="bugfix", lesson_learned="<root cause + fix>")`);
177
- }
178
- process.stdout.write(JSON.stringify({
179
- suppressOutput: true,
180
- hookSpecificOutput: {
181
- hookEventName,
182
- additionalContext: lines.join('\n'),
183
- },
184
- }));
185
- } catch { /* never block on receipt */ }
165
+ // v2.33.4: Stop event rejects hookSpecificOutput entirely — skip receipt.
166
+ if (RECEIPT_EVENTS.has(hookEventName)) {
167
+ try {
168
+ const entries = episode.entries || [];
169
+ const hasError = entries.some(e => e.isError);
170
+ const hasEdit = entries.some(e => EDIT_TOOLS.has(e.tool));
171
+ const toolCounts = {};
172
+ for (const e of entries) toolCounts[e.tool] = (toolCounts[e.tool] || 0) + 1;
173
+ const toolSummary = Object.entries(toolCounts)
174
+ .sort((a, b) => b[1] - a[1])
175
+ .slice(0, 3)
176
+ .map(([t, n]) => `${t}×${n}`)
177
+ .join(', ');
178
+ const lines = [`[mem] episode flushed: ${entries.length} entries (${toolSummary})`];
179
+ if (hasError && hasEdit && entries.length >= 3) {
180
+ const editFiles = entries.filter(e => EDIT_TOOLS.has(e.tool)).flatMap(e => e.files || []);
181
+ const uniqueFiles = [...new Set(editFiles)].slice(0, 3);
182
+ const filesHint = uniqueFiles.length > 0 ? ` (${uniqueFiles.join(', ')})` : '';
183
+ lines.push(`[mem] 💡 error→fix pattern${filesHint} — consider: mem_save(type="bugfix", lesson_learned="<root cause + fix>")`);
184
+ }
185
+ process.stdout.write(JSON.stringify({
186
+ suppressOutput: true,
187
+ hookSpecificOutput: {
188
+ hookEventName,
189
+ additionalContext: lines.join('\n'),
190
+ },
191
+ }));
192
+ } catch { /* never block on receipt */ }
193
+ }
186
194
  } else {
187
195
  try { unlinkSync(flushFile); } catch {}
188
196
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.33.3",
3
+ "version": "2.33.5",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {