claude-recall 0.20.0 → 0.20.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.
@@ -8,10 +8,14 @@ source: claude-recall
8
8
 
9
9
  # Corrections
10
10
 
11
- Auto-generated from 5 memories. Last updated: 2026-04-02.
11
+ Auto-generated from 9 memories. Last updated: 2026-04-02.
12
12
 
13
13
  ## Rules
14
14
 
15
+ - CORRECTION: Memory with complex metadata
16
+ - CORRECTION: Memory with complex metadata
17
+ - CORRECTION: Memory with complex metadata
18
+ - CORRECTION: Memory with complex metadata
15
19
  - CORRECTION: Memory with complex metadata
16
20
  - CORRECTION: Memory with complex metadata
17
21
  - CORRECTION: Memory with complex metadata
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "topicId": "corrections",
3
- "sourceHash": "a88187b382c2104a20922fd98e9de60d9ef6434a0a5e25f03a011998b491290f",
4
- "memoryCount": 5,
5
- "generatedAt": "2026-04-02T19:49:59.553Z",
3
+ "sourceHash": "bc99031d99dbd5f9baeff51cd1b1d609f0a231dc120f5559a98080419ba54be6",
4
+ "memoryCount": 9,
5
+ "generatedAt": "2026-04-02T22:34:33.293Z",
6
6
  "memoryKeys": [
7
+ "memory_1775169273281_4fod7ku6f",
8
+ "memory_1775169256118_y7kc07y6y",
9
+ "memory_1775169244673_d6d0uc33a",
10
+ "memory_1775160781806_vnqf355e9",
7
11
  "memory_1775159399542_awfryrxp3",
8
12
  "memory_1775157082825_8uvrul28i",
9
13
  "memory_1775156381094_dr1nihes8",
@@ -8,10 +8,32 @@ source: claude-recall
8
8
 
9
9
  # Preferences
10
10
 
11
- Auto-generated from 17 memories. Last updated: 2026-04-02.
11
+ Auto-generated from 39 memories. Last updated: 2026-04-02.
12
12
 
13
13
  ## Rules
14
14
 
15
+ - Session test preference 1775169273366
16
+ - Test preference 1775169273296-2
17
+ - Test preference 1775169273296-1
18
+ - Test preference 1775169273296-0
19
+ - Test memory content
20
+ - Session test preference 1775169256189
21
+ - Test preference 1775169256133-2
22
+ - Test preference 1775169256133-1
23
+ - Test preference 1775169256133-0
24
+ - Test memory content
25
+ - Session test preference 1775169244752
26
+ - Test preference 1775169244686-2
27
+ - Test preference 1775169244686-1
28
+ - Test preference 1775169244686-0
29
+ - Test memory content
30
+ - Markdown documentation files should be named with the convention YYYYMMDD_<filename>.md (e.g., 20260402_nemoclaw_integration.md). Use underscores, not hyphens, in the date-prefixed filenames.
31
+ - Never commit to git unless the user explicitly approves. Always show the commit message and wait for a clear "yes", "go ahead", "commit", or similar confirmation before running git commit.
32
+ - Session test preference 1775160781884
33
+ - Test preference 1775160781820-2
34
+ - Test preference 1775160781820-1
35
+ - Test preference 1775160781820-0
36
+ - Test memory content
15
37
  - Session test preference 1775159399698
16
38
  - Test preference 1775159399559-2
17
39
  - Test preference 1775159399559-1
@@ -1,9 +1,31 @@
1
1
  {
2
2
  "topicId": "preferences",
3
- "sourceHash": "13276d13523c8f8ec13ae9948cfa0e2cdd8ca5cd0fd6453b544307ae47d91df5",
4
- "memoryCount": 17,
5
- "generatedAt": "2026-04-02T19:49:59.727Z",
3
+ "sourceHash": "d609433b68eba6dbfaea5244e666c564e76ad1be0f75373c555fdd83405390cd",
4
+ "memoryCount": 39,
5
+ "generatedAt": "2026-04-02T22:34:33.383Z",
6
6
  "memoryKeys": [
7
+ "memory_1775169273368_c1e5jdl9r",
8
+ "memory_1775169273337_wozxe12k3",
9
+ "memory_1775169273319_3o1ww90na",
10
+ "memory_1775169273297_oqmyxziav",
11
+ "memory_1775169273232_eoymf3ezj",
12
+ "memory_1775169256190_681x8frvt",
13
+ "memory_1775169256164_kqderurux",
14
+ "memory_1775169256150_0nqbk7tx9",
15
+ "memory_1775169256134_ftj0m44bb",
16
+ "memory_1775169256069_dywd646f7",
17
+ "memory_1775169244754_sjfarlk41",
18
+ "memory_1775169244722_mavida9fg",
19
+ "memory_1775169244707_nmmu0s0lu",
20
+ "memory_1775169244688_03q4mmcky",
21
+ "memory_1775169244628_7kuhf5met",
22
+ "memory_1775168901303_o8o0i4952",
23
+ "memory_1775162828137_l6uw5swdn",
24
+ "memory_1775160781885_fkbnc0s85",
25
+ "memory_1775160781857_gj5y299dr",
26
+ "memory_1775160781842_0xmv146n5",
27
+ "memory_1775160781821_o9ipt8nsc",
28
+ "memory_1775160781747_70e5gbp7j",
7
29
  "memory_1775159399702_yg6ynd05n",
8
30
  "memory_1775159399631_fmy4s2vhr",
9
31
  "memory_1775159399606_xymkvcjfv",
@@ -467,9 +467,8 @@ class MemoryTools {
467
467
  }
468
468
  }
469
469
  exports.MemoryTools = MemoryTools;
470
- MemoryTools.LOAD_RULES_DIRECTIVE = 'INSTRUCTION: Before your FIRST Write, Edit, or Bash action, you MUST output an\n' +
471
- '"Applying memories:" section listing which rules below apply to the current task.\n' +
472
- 'If none apply, say so. Do NOT skip this step — the user expects visible confirmation\n' +
473
- 'that you checked your memories before acting.\n' +
474
- 'As you work, cite each applied rule inline: (applied from memory: <rule summary>)\n' +
470
+ MemoryTools.LOAD_RULES_DIRECTIVE = 'Before your FIRST action, briefly state which rules below you will apply to this task.\n' +
471
+ 'As you work, cite each rule at the point where it influences your action:\n' +
472
+ '(applied from memory: <short rule name>)\n' +
473
+ 'Place citations next to the action they influenced — not at the end of unrelated text.\n' +
475
474
  'If a rule conflicts with your plan, follow the rule — it reflects a user decision.';
@@ -14,10 +14,10 @@ const config_1 = require("../services/config");
14
14
  const outcome_storage_1 = require("../services/outcome-storage");
15
15
  const logging_1 = require("../services/logging");
16
16
  const event_processors_1 = require("../shared/event-processors");
17
- const LOAD_RULES_DIRECTIVE = 'INSTRUCTION: Before your FIRST edit or bash action, you MUST output an\n' +
18
- '"Applying memories:" section listing which rules below apply to the current task.\n' +
19
- 'If none apply, say so. Do NOT skip this step.\n' +
20
- 'As you work, cite each applied rule inline: (applied from memory: <rule summary>)\n' +
17
+ const LOAD_RULES_DIRECTIVE = 'Before your FIRST action, briefly state which rules below you will apply to this task.\n' +
18
+ 'As you work, cite each rule at the point where it influences your action:\n' +
19
+ '(applied from memory: <short rule name>)\n' +
20
+ 'Place citations next to the action they influenced not at the end of unrelated text.\n' +
21
21
  'If a rule conflicts with your plan, follow the rule — it reflects a user decision.';
22
22
  /** Format a memory value for display. */
23
23
  function extractVal(value) {
@@ -62,6 +62,7 @@ function default_1(pi) {
62
62
  projectId = ctx.cwd.split('/').pop() || 'unknown';
63
63
  rulesLoaded = false;
64
64
  collectedUserTexts.length = 0;
65
+ (0, event_processors_1.resetPendingFailures)();
65
66
  try {
66
67
  config_1.ConfigService.getInstance().updateConfig({
67
68
  project: { rootDir: ctx.cwd },
@@ -41,17 +41,72 @@ var __importStar = (this && this.__importStar) || (function () {
41
41
  })();
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
43
  exports.setLogFunction = setLogFunction;
44
+ exports.resetPendingFailures = resetPendingFailures;
44
45
  exports.processToolOutcome = processToolOutcome;
45
46
  exports.processUserInput = processUserInput;
46
47
  exports.processSessionEnd = processSessionEnd;
47
48
  exports.processPreCompact = processPreCompact;
48
49
  const shared_1 = require("../hooks/shared");
50
+ const memory_1 = require("../services/memory");
49
51
  const outcome_storage_1 = require("../services/outcome-storage");
50
52
  let logFn = () => { }; // silent by default
51
53
  /** Set the log function (hookLog for CC hooks, console for Pi, etc.) */
52
54
  function setLogFunction(fn) {
53
55
  logFn = fn;
54
56
  }
57
+ const MAX_PENDING = 10;
58
+ const FIX_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
59
+ const FIX_SIMILARITY_THRESHOLD = 0.3;
60
+ let pendingFailures = [];
61
+ /** Reset pending failures (e.g. on session start). */
62
+ function resetPendingFailures() {
63
+ pendingFailures = [];
64
+ }
65
+ /** Extract an identifier string from tool input for similarity comparison. */
66
+ function getToolIdentifier(toolName, toolInput) {
67
+ if ((toolName === 'Bash' || toolName === 'bash') && toolInput?.command) {
68
+ return toolInput.command;
69
+ }
70
+ if (toolInput?.file_path) {
71
+ return `${toolName}:${toolInput.file_path}`;
72
+ }
73
+ return toolName;
74
+ }
75
+ /**
76
+ * Check if a successful tool result matches a recent failure and pair the fix.
77
+ * Returns true if a fix was paired.
78
+ */
79
+ function tryPairFix(toolName, toolInput, output) {
80
+ if (pendingFailures.length === 0)
81
+ return false;
82
+ const now = Date.now();
83
+ const identifier = getToolIdentifier(toolName, toolInput);
84
+ let matched = false;
85
+ const remaining = [];
86
+ for (const pf of pendingFailures) {
87
+ if (now - pf.timestamp > FIX_WINDOW_MS)
88
+ continue; // expired
89
+ if (!matched && pf.toolName === toolName &&
90
+ (0, shared_1.jaccardSimilarity)(pf.identifier, identifier) >= FIX_SIMILARITY_THRESHOLD) {
91
+ try {
92
+ memory_1.MemoryService.getInstance().update(pf.memoryKey, {
93
+ value: { what_should_do: `Fix: ${truncate(identifier, 200)}` },
94
+ });
95
+ logFn('event-processor', `Paired fix: "${truncate(identifier, 60)}" → ${pf.memoryKey}`);
96
+ matched = true;
97
+ // Don't add to remaining — consumed
98
+ }
99
+ catch {
100
+ remaining.push(pf); // keep if update fails
101
+ }
102
+ }
103
+ else {
104
+ remaining.push(pf);
105
+ }
106
+ }
107
+ pendingFailures = remaining;
108
+ return matched;
109
+ }
55
110
  // --- Tool Outcome Processing ---
56
111
  /** Error patterns for Edit/Write tools */
57
112
  const WRITE_ERROR_PATTERNS = [
@@ -81,6 +136,7 @@ function firstLine(s) {
81
136
  }
82
137
  /**
83
138
  * Process a tool outcome — capture failures as memories, record outcome events.
139
+ * When a tool succeeds after a similar recent failure, pairs the fix.
84
140
  * Works for any tool type (Bash, Edit, Write, MCP, generic).
85
141
  */
86
142
  function processToolOutcome(toolName, toolInput, toolOutput, isError, sessionId) {
@@ -89,9 +145,14 @@ function processToolOutcome(toolName, toolInput, toolOutput, isError, sessionId)
89
145
  if (toolName.includes('claude-recall') || toolName.includes('claude_recall') ||
90
146
  toolName.startsWith('recall_'))
91
147
  return;
92
- if (isError || isToolFailureOutput(toolName, toolOutput)) {
148
+ const isFail = isError || isToolFailureOutput(toolName, toolOutput);
149
+ if (isFail) {
93
150
  storeToolFailure(toolName, toolInput, toolOutput, sessionId);
94
151
  }
152
+ else {
153
+ // Success — check if this fixes a recent failure
154
+ tryPairFix(toolName, toolInput, toolOutput);
155
+ }
95
156
  // Record outcome event for all tools
96
157
  recordOutcomeEvent(toolName, toolInput, toolOutput);
97
158
  }
@@ -136,7 +197,19 @@ function storeToolFailure(toolName, toolInput, output, sessionId) {
136
197
  context: `${toolName} error`,
137
198
  preventative_checks: ['Verify inputs are correct', 'Check preconditions'],
138
199
  };
139
- (0, shared_1.storeMemory)(JSON.stringify(failureContent), 'failure', undefined, 0.75);
200
+ const key = `hook_failure_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
201
+ memory_1.MemoryService.getInstance().store({
202
+ key,
203
+ value: failureContent,
204
+ type: 'failure',
205
+ context: { timestamp: Date.now() },
206
+ relevanceScore: 0.75,
207
+ });
208
+ // Track for fix pairing — when a similar tool succeeds, we update this memory
209
+ const identifier = getToolIdentifier(toolName, toolInput);
210
+ pendingFailures.push({ toolName, identifier, memoryKey: key, timestamp: Date.now() });
211
+ while (pendingFailures.length > MAX_PENDING)
212
+ pendingFailures.shift();
140
213
  logFn('event-processor', `Stored failure: ${truncate(whatFailed, 60)}`);
141
214
  }
142
215
  function recordOutcomeEvent(toolName, toolInput, output) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-recall",
3
- "version": "0.20.0",
3
+ "version": "0.20.2",
4
4
  "description": "Persistent memory for Claude Code and Pi with native Skills integration, automatic capture, failure learning, and project scoping",
5
5
  "main": "dist/index.js",
6
6
  "bin": {