claude-recall 0.20.6 → 0.20.7

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,7 +8,7 @@ source: claude-recall
8
8
 
9
9
  # Corrections
10
10
 
11
- Auto-generated from 14 memories. Last updated: 2026-04-06.
11
+ Auto-generated from 15 memories. Last updated: 2026-04-06.
12
12
 
13
13
  ## Rules
14
14
 
@@ -24,6 +24,7 @@ Auto-generated from 14 memories. Last updated: 2026-04-06.
24
24
  - CORRECTION: Memory with complex metadata
25
25
  - CORRECTION: Memory with complex metadata
26
26
  - CORRECTION: Memory with complex metadata
27
+ - CORRECTION: Memory with complex metadata
27
28
  - CORRECTION: License copyright should include user's name instead of 'Claude Recall Contributors'
28
29
  - CORRECTION: License copyright should list your name instead of 'Claude Recall Contributors'
29
30
 
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "topicId": "corrections",
3
- "sourceHash": "c77b49a2f99b869465aeb4705a4c3de1f922381d5b49ed8d78c661477f8668fa",
4
- "memoryCount": 14,
5
- "generatedAt": "2026-04-06T16:14:29.343Z",
3
+ "sourceHash": "6bede026828253771f48ae5c05e80878ab69beb584dfc06f416814840016ad6c",
4
+ "memoryCount": 15,
5
+ "generatedAt": "2026-04-06T16:51:19.054Z",
6
6
  "memoryKeys": [
7
+ "memory_1775494279035_j6uj5lzxo",
7
8
  "memory_1775492069326_vksvzmt3f",
8
9
  "memory_1775491767369_sepsjmg8y",
9
10
  "memory_1775169786543_43p8to1hu",
@@ -8,10 +8,15 @@ source: claude-recall
8
8
 
9
9
  # Preferences
10
10
 
11
- Auto-generated from 69 memories. Last updated: 2026-04-06.
11
+ Auto-generated from 74 memories. Last updated: 2026-04-06.
12
12
 
13
13
  ## Rules
14
14
 
15
+ - Session test preference 1775494279149
16
+ - Test preference 1775494279061-2
17
+ - Test preference 1775494279061-1
18
+ - Test preference 1775494279061-0
19
+ - Test memory content
15
20
  - Session test preference 1775492069465
16
21
  - Test preference 1775492069353-2
17
22
  - Test preference 1775492069353-1
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "topicId": "preferences",
3
- "sourceHash": "84b3e678b896e5e6761dcfc6d49ee47c0027d4c7808f6ef6f8f3e00aa39ee76c",
4
- "memoryCount": 69,
5
- "generatedAt": "2026-04-06T16:14:29.485Z",
3
+ "sourceHash": "77d6964d46ea058e3de341d9d43c79901bc596a18b5a03fa8e402368ba20b412",
4
+ "memoryCount": 74,
5
+ "generatedAt": "2026-04-06T16:51:19.174Z",
6
6
  "memoryKeys": [
7
+ "memory_1775494279150_n4pq7zy11",
8
+ "memory_1775494279108_6hbe8qoit",
9
+ "memory_1775494279088_nv8hjdm7s",
10
+ "memory_1775494279062_jx4wrwn6s",
11
+ "memory_1775494278982_fsc491z41",
7
12
  "memory_1775492069467_5cturlg0a",
8
13
  "memory_1775492069400_icg4tjivf",
9
14
  "memory_1775492069377_goix7nu9v",
@@ -693,8 +693,20 @@ async function main() {
693
693
  // This avoids registry lookups on every hook invocation.
694
694
  const cliScript = path.join(packageDir, 'dist', 'cli', 'claude-recall-cli.js');
695
695
  const hookCmd = `node ${cliScript} hook run`;
696
- settings.hooksVersion = '10.0.0'; // v10 = add PostToolUseFailure for explicit error capture
696
+ settings.hooksVersion = '11.0.0'; // v11 = add SessionStart(compact) for post-compaction rule reload
697
697
  settings.hooks = {
698
+ SessionStart: [
699
+ {
700
+ matcher: "compact",
701
+ hooks: [
702
+ {
703
+ type: "command",
704
+ command: `${hookCmd} post-compact-reload`,
705
+ timeout: 10
706
+ }
707
+ ]
708
+ }
709
+ ],
698
710
  PostToolUse: [
699
711
  {
700
712
  hooks: [
@@ -85,6 +85,11 @@ class HookCommands {
85
85
  await handleToolFailure(input);
86
86
  break;
87
87
  }
88
+ case 'post-compact-reload': {
89
+ const { handlePostCompactReload } = await Promise.resolve().then(() => __importStar(require('../../hooks/post-compact-reload')));
90
+ await handlePostCompactReload(input);
91
+ break;
92
+ }
88
93
  case 'bash-failure-watcher': {
89
94
  // Backward compat alias — routes to tool-outcome-watcher
90
95
  const { handleBashFailureWatcher } = await Promise.resolve().then(() => __importStar(require('../../hooks/tool-outcome-watcher')));
@@ -114,6 +114,21 @@ async function handleMemoryStop(input) {
114
114
  const sessionEntries = (0, shared_1.readTranscriptTail)(transcriptPath, 50);
115
115
  if (sessionEntries.length >= 10) {
116
116
  const conversationEntries = buildConversationEntries(sessionEntries);
117
+ // Record failed subagent outcomes
118
+ for (const entry of conversationEntries) {
119
+ if (entry.toolName === 'Agent' && entry.isError) {
120
+ try {
121
+ outcomeStorage.createOutcomeEvent({
122
+ event_type: 'agent_failure',
123
+ actor: 'tool',
124
+ action_summary: entry.text,
125
+ next_state_summary: entry.text,
126
+ tags: ['agent', 'subagent'],
127
+ });
128
+ }
129
+ catch { /* non-critical */ }
130
+ }
131
+ }
117
132
  const extracted = await (0, event_processors_1.extractSessionLearnings)(conversationEntries, input?.session_id ?? '', projectId, 5);
118
133
  if (extracted > 0) {
119
134
  (0, shared_1.hookLog)('memory-stop', `Session extraction: stored ${extracted} learnings`);
@@ -417,7 +432,21 @@ function buildConversationEntries(entries) {
417
432
  else {
418
433
  const text = (0, shared_1.extractTextFromEntry)(entry);
419
434
  if (text && text.length > 5) {
420
- result.push({ role: 'assistant', text: text.substring(0, 300) });
435
+ // Detect subagent task notifications
436
+ const notifMatch = text.match(/<task-notification>[\s\S]*?<\/task-notification>/);
437
+ if (notifMatch) {
438
+ const status = notifMatch[0].match(/<status>(.*?)<\/status>/)?.[1] ?? 'unknown';
439
+ const summary = notifMatch[0].match(/<summary>(.*?)<\/summary>/)?.[1] ?? '';
440
+ result.push({
441
+ role: 'tool_result',
442
+ text: `Agent ${status}: ${summary}`.substring(0, 300),
443
+ toolName: 'Agent',
444
+ isError: status === 'failed' || status === 'killed',
445
+ });
446
+ }
447
+ else {
448
+ result.push({ role: 'assistant', text: text.substring(0, 300) });
449
+ }
421
450
  }
422
451
  }
423
452
  }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * post-compact-reload hook — fires on SessionStart with source "compact".
4
+ *
5
+ * After context compaction, recall rules loaded earlier in the session are
6
+ * gone from the model's context. This hook re-injects them by outputting
7
+ * the active rules to stdout, which CC injects as a system message.
8
+ *
9
+ * Input: { session_id, hook_event_name: "SessionStart", source: "compact" }
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.handlePostCompactReload = handlePostCompactReload;
13
+ const shared_1 = require("./shared");
14
+ const memory_1 = require("../services/memory");
15
+ const config_1 = require("../services/config");
16
+ const DIRECTIVE = 'These rules were re-loaded after context compaction.\n' +
17
+ 'Continue applying them. Cite at the point of application: (applied from memory: <rule>)';
18
+ function extractVal(value) {
19
+ if (typeof value === 'string')
20
+ return value;
21
+ if (typeof value === 'object' && value !== null) {
22
+ return value.content || value.value || JSON.stringify(value);
23
+ }
24
+ return String(value ?? '');
25
+ }
26
+ function formatRules(rules) {
27
+ const sections = [];
28
+ if (rules.preferences.length > 0) {
29
+ sections.push('## Preferences\n' + rules.preferences.map(m => `- ${extractVal(m.value)}`).join('\n'));
30
+ }
31
+ if (rules.corrections.length > 0) {
32
+ sections.push('## Corrections\n' + rules.corrections.map(m => `- ${extractVal(m.value)}`).join('\n'));
33
+ }
34
+ if (rules.failures.length > 0) {
35
+ sections.push('## Failures\n' + rules.failures.map(m => `- ${extractVal(m.value)}`).join('\n'));
36
+ }
37
+ if (rules.devops.length > 0) {
38
+ sections.push('## DevOps Rules\n' + rules.devops.map(m => `- ${extractVal(m.value)}`).join('\n'));
39
+ }
40
+ return sections.join('\n\n');
41
+ }
42
+ async function handlePostCompactReload(input) {
43
+ try {
44
+ const projectId = config_1.ConfigService.getInstance().getProjectId();
45
+ const rules = memory_1.MemoryService.getInstance().loadActiveRules(projectId);
46
+ const totalRules = rules.preferences.length + rules.corrections.length +
47
+ rules.failures.length + rules.devops.length;
48
+ if (totalRules === 0)
49
+ return;
50
+ const body = formatRules(rules);
51
+ console.log(`${DIRECTIVE}\n\n---\n\n${body}`);
52
+ (0, shared_1.hookLog)('post-compact-reload', `Re-injected ${totalRules} rules after compaction`);
53
+ }
54
+ catch (err) {
55
+ (0, shared_1.hookLog)('post-compact-reload', `Error: ${err.message}`);
56
+ }
57
+ }
@@ -0,0 +1,114 @@
1
+ # Claude Code Agent Harness — Architecture Reference
2
+
3
+ Reference notes on Claude Code's internal agent harness architecture, based on source code analysis (v1.0.x, March 2026). Useful for understanding integration points and designing Claude Recall features.
4
+
5
+ ## Core Orchestration
6
+
7
+ **Query loop** — main while-loop that calls the API, executes tools, handles continuations, retries, and abort. Key behaviors:
8
+ - Infinite loop with explicit terminal conditions (end_turn, max_tokens, budget exceeded, turn limit)
9
+ - Pre-API hooks, post-sampling hooks, stop hooks at each stage
10
+ - Memory prefetch started non-blocking before API call
11
+ - Skill discovery prefetch in parallel with streaming
12
+
13
+ **Tool execution pipeline** — partitions tool calls into batches:
14
+ - Read-only tools (Read, Grep, Glob) run concurrently (max 10)
15
+ - Write tools (Bash, Edit, Write) run serially
16
+ - Each tool goes through: permission check → execute → yield result → apply context modifiers
17
+ - Tool result size budget enforced per turn
18
+
19
+ ## Permission System
20
+
21
+ Three modes: `default` (interactive), `auto` (ML classifier), `bypass`.
22
+
23
+ Pipeline per tool call:
24
+ 1. Rules-based check (always-allow/deny/ask lists)
25
+ 2. Bash classifier (ML, 2s timeout for speculative decisions)
26
+ 3. Hook execution (PreToolUse hooks)
27
+ 4. Interactive UI prompt (if needed)
28
+ 5. Decision persisted to ToolPermissionContext
29
+
30
+ Risk classification: LOW/MEDIUM/HIGH per tool action. Denial tracking state for threshold-based fallback.
31
+
32
+ ## Multi-Agent
33
+
34
+ **Coordinator mode** — multi-agent orchestration with parallel worker phases and shared scratchpad.
35
+
36
+ **Agent tool** — forks subagents with inherited context:
37
+ - Child shares parent's prompt cache (byte-identical prefix = free context)
38
+ - Hard turn limit per agent
39
+ - Task notifications via XML: `<task-notification><status>completed</status>...</task-notification>`
40
+ - Agent types: worker (async), teammate (in-process, visible UI), fork (implicit context inheritance)
41
+
42
+ **Worker constraints:**
43
+ - SIMPLE mode: Bash, Read, Edit only
44
+ - Normal mode: full tool list including MCP
45
+
46
+ ## State Management
47
+
48
+ **AppState** (Zustand store, 200+ fields):
49
+ - messages, tasks, agents, permissions, MCP clients, models, plugins, settings
50
+ - Observable via selectors
51
+ - Task registry: `{ [taskId]: TaskState }` with status tracking
52
+
53
+ **Task types:** local_bash, local_agent, remote_agent, in_process_teammate, local_workflow, monitor_mcp, dream
54
+
55
+ **Session persistence:** transcript JSONL written per session, resumable.
56
+
57
+ ## Context Management / Compaction
58
+
59
+ Four compaction strategies (in order of aggressiveness):
60
+ 1. **Microcompact** — cache-editing on every turn (efficient, preserves cache)
61
+ 2. **Snip compact** — truncate oldest history (feature-gated)
62
+ 3. **Context collapse** — deduplicate/compress (feature-gated)
63
+ 4. **Autocompact** — full summarization when token threshold crossed
64
+
65
+ Token tracking: per-message estimates, cache creation/read tokens, danger zone threshold, cumulative budget.
66
+
67
+ Pre/post compact hooks fire at each stage.
68
+
69
+ ## Safety & Guardrails
70
+
71
+ - Cyber risk instruction (defensive security, CTF rules)
72
+ - Secret scanner (gitleaks patterns, credential redaction)
73
+ - Path traversal prevention
74
+ - Command injection protection (fixed in security audit)
75
+ - Crypto: `crypto.randomUUID()` / `crypto.randomBytes()` throughout (no weak RNG)
76
+
77
+ ## Memory System
78
+
79
+ **extractMemories** — forked sub-agent after each query loop:
80
+ - Reads last ~N messages, decides what to extract
81
+ - 5-turn budget, read-then-write strategy
82
+ - Mutual exclusivity: skips if main agent already wrote to memory
83
+ - Shares parent's prompt cache
84
+
85
+ **autoDream** — background consolidation:
86
+ - Three-gate trigger: 24h since last + 5 sessions + no parallel consolidation
87
+ - Four phases: orient → gather → consolidate → prune
88
+ - PID-based locking, 1h stale window
89
+
90
+ **Memory retrieval** — Sonnet sidequery selects up to 5 relevant memories per query from the memory directory.
91
+
92
+ ## Integration Points for Claude Recall
93
+
94
+ ### Currently Used
95
+ - PostToolUse / PostToolUseFailure hooks (tool outcome capture)
96
+ - UserPromptSubmit hook (correction detection)
97
+ - Stop hook (session-end processing)
98
+ - PreCompact hook (pre-compaction capture)
99
+ - MCP server (tool registration)
100
+ - Skills directory (behavioral guidance)
101
+
102
+ ### Available but Unused
103
+ - Permission decision hooks (observe denied tools as learning signals)
104
+ - Task notification parsing (multi-agent session outcomes)
105
+ - Agent fork interception (inject memory context into subagents)
106
+ - Compaction triggers (pre-compact hooks with message access)
107
+ - Memory prefetch integration (inject recall results alongside native memory)
108
+
109
+ ### Architectural Constraints
110
+ - Hooks run as external processes (no shared memory, no prompt cache)
111
+ - MCP tools are request-response (no streaming, no multi-turn)
112
+ - Cannot fork sub-agents from hooks
113
+ - Cannot modify the query loop or tool pipeline directly
114
+ - Feature flags (GrowthBook `tengu_*`) control many code paths — not accessible externally
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-recall",
3
- "version": "0.20.6",
3
+ "version": "0.20.7",
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": {