claude-flow 3.21.1 → 3.23.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.
Files changed (40) hide show
  1. package/.claude/helpers/.helpers-version +1 -0
  2. package/.claude/helpers/auto-memory-hook.mjs +59 -274
  3. package/.claude/helpers/helpers.manifest.json +12 -0
  4. package/.claude/helpers/hook-handler.cjs +132 -112
  5. package/.claude/helpers/intelligence.cjs +992 -196
  6. package/package.json +1 -1
  7. package/v3/@claude-flow/cli/dist/src/commands/daemon.js +23 -2
  8. package/v3/@claude-flow/cli/dist/src/commands/memory-backup.d.ts +11 -0
  9. package/v3/@claude-flow/cli/dist/src/commands/memory-backup.js +46 -0
  10. package/v3/@claude-flow/cli/dist/src/commands/memory-distill.d.ts +27 -0
  11. package/v3/@claude-flow/cli/dist/src/commands/memory-distill.js +374 -0
  12. package/v3/@claude-flow/cli/dist/src/commands/memory.js +5 -2
  13. package/v3/@claude-flow/cli/dist/src/index.d.ts +1 -1
  14. package/v3/@claude-flow/cli/dist/src/index.js +22 -1
  15. package/v3/@claude-flow/cli/dist/src/init/executor.js +20 -0
  16. package/v3/@claude-flow/cli/dist/src/init/helper-refresh.d.ts +19 -0
  17. package/v3/@claude-flow/cli/dist/src/init/helper-refresh.js +175 -0
  18. package/v3/@claude-flow/cli/dist/src/init/helper-signing.d.ts +30 -0
  19. package/v3/@claude-flow/cli/dist/src/init/helper-signing.js +60 -0
  20. package/v3/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +16 -0
  21. package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +63 -6
  22. package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +18 -7
  23. package/v3/@claude-flow/cli/dist/src/mcp-client.js +13 -0
  24. package/v3/@claude-flow/cli/dist/src/mcp-tools/agenticow-speculate-tools.js +9 -2
  25. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-intent-tools.d.ts +162 -0
  26. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-intent-tools.js +548 -0
  27. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.d.ts +9 -1
  28. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +4 -1
  29. package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +67 -47
  30. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +71 -0
  31. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +330 -2
  32. package/v3/@claude-flow/cli/dist/src/services/distill-tuning.d.ts +111 -0
  33. package/v3/@claude-flow/cli/dist/src/services/distill-tuning.js +510 -0
  34. package/v3/@claude-flow/cli/dist/src/services/memory-backup.d.ts +24 -0
  35. package/v3/@claude-flow/cli/dist/src/services/memory-backup.js +94 -0
  36. package/v3/@claude-flow/cli/dist/src/services/memory-distillation.d.ts +41 -0
  37. package/v3/@claude-flow/cli/dist/src/services/memory-distillation.js +277 -0
  38. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +31 -2
  39. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +159 -6
  40. package/v3/@claude-flow/cli/package.json +5 -2
@@ -0,0 +1 @@
1
+ 3.22.0
@@ -27,16 +27,29 @@ const CYAN = '\x1b[0;36m';
27
27
  const DIM = '\x1b[2m';
28
28
  const RESET = '\x1b[0m';
29
29
 
30
+ const YELLOW = '\x1b[0;33m';
30
31
  const log = (msg) => console.log(`${CYAN}[AutoMemory] ${msg}${RESET}`);
31
32
  const success = (msg) => console.log(`${GREEN}[AutoMemory] ✓ ${msg}${RESET}`);
32
33
  const dim = (msg) => console.log(` ${DIM}${msg}${RESET}`);
33
34
 
35
+ // #2545: fail LOUD instead of a silent dim skip. When @claude-flow/memory cannot
36
+ // be resolved, self-learning imports are a no-op — the user must see this and be
37
+ // told exactly how to fix it (on both stdout, so it shows in the Claude Code hook
38
+ // transcript, and stderr, per the issue's requested channel).
39
+ function warnMemoryUnavailable() {
40
+ const line1 = `[AutoMemory] @claude-flow/memory not resolvable from ${PROJECT_ROOT} — self-learning imports are DISABLED.`;
41
+ const line2 = ' Fix: npm i -D @claude-flow/memory (or re-run: npx ruflo@latest init, then npx ruflo@latest doctor --fix)';
42
+ console.log(`${YELLOW}${line1}${RESET}`);
43
+ console.log(`${YELLOW}${line2}${RESET}`);
44
+ process.stderr.write(`${line1}\n${line2}\n`);
45
+ }
46
+
34
47
  const DEBUG = !!(process.env.RUFLO_DEBUG || process.env.DEBUG);
35
48
 
36
49
  // ── Graceful shutdown (FIX 3) ───────────────────────────────────────────────
37
- // Track the backend currently in use so a SIGTERM/SIGINT mid-run can still
38
- // flush it (the JSON backend persists, a SQLite-backed one closes/flushes WAL)
39
- // instead of leaving a half-written store or a stale lock behind.
50
+ // Track the backend in use so a SIGTERM/SIGINT mid-run can still flush it
51
+ // (the JSON backend persists; a SQLite-backed one closes/flushes WAL) instead
52
+ // of leaving a half-written store or a stale lock behind.
40
53
  let activeBackend = null;
41
54
  let shuttingDown = false;
42
55
  function trackBackend(b) { activeBackend = b; return b; }
@@ -151,77 +164,31 @@ class JsonFileBackend {
151
164
  // Resolve memory package path (local dev or npm installed)
152
165
  // ============================================================================
153
166
 
154
- /**
155
- * Resolve a bundled package file (`<pkg>/<relativeFile>`) by trying, in order:
156
- * 1. PROJECT_ROOT/v3/<pkg>/<relativeFile> (monorepo dev layout)
157
- * 2. CWD/node_modules/<pkg>/<relativeFile> (user's project deps)
158
- * 3. node_modules walk-up from PROJECT_ROOT
159
- * 4. node_modules walk-up from CWD
160
- * 5. Global npm prefix — checks the ruflo / claude-flow / @claude-flow/cli
161
- * bundles, AND the package installed globally on its own
162
- *
163
- * Returns the resolved absolute path, or null. See issue #2285.
164
- */
165
- async function resolveBundledFile(pkg, relativeFile) {
166
- const monorepo = join(PROJECT_ROOT, 'v3', pkg, relativeFile);
167
- if (existsSync(monorepo)) return monorepo;
168
-
169
- const cwd = process.env.CLAUDE_FLOW_CWD || process.cwd();
170
- const inCwd = join(cwd, 'node_modules', pkg, relativeFile);
171
- if (existsSync(inCwd)) return inCwd;
172
-
173
- const walkUp = (start) => {
174
- let dir = start;
175
- while (dir && dir !== dirname(dir)) {
176
- const candidate = join(dir, 'node_modules', pkg, relativeFile);
177
- if (existsSync(candidate)) return candidate;
178
- dir = dirname(dir);
179
- }
180
- return null;
181
- };
182
-
183
- const fromProject = walkUp(PROJECT_ROOT);
184
- if (fromProject) return fromProject;
185
-
186
- const fromCwd = walkUp(cwd);
187
- if (fromCwd) return fromCwd;
188
-
189
- // Global npm prefix fallback — handles `npm i -g ruflo` and friends, where
190
- // the marketplace clone (PROJECT_ROOT) has no access to the bundled deps.
167
+ async function loadMemoryPackage() {
168
+ // Strategy 0 (#2545): sidecar recorded by `init` / `doctor --fix`. On the
169
+ // documented `npx ruflo` path @claude-flow/memory (an optionalDependency of
170
+ // the CLI) lands in the npx cache, which is NOT on the walk-up path from the
171
+ // project so init resolves it from the CLI's own context and records the
172
+ // absolute path here. This is the only strategy that works on that install.
191
173
  try {
192
- const { execSync } = await import('child_process');
193
- const npmPrefix = execSync('npm prefix -g', {
194
- encoding: 'utf-8',
195
- stdio: ['ignore', 'pipe', 'ignore'],
196
- }).trim();
197
- if (npmPrefix) {
198
- // Both Unix (<prefix>/lib/node_modules) and Windows (<prefix>/node_modules)
199
- const roots = [join(npmPrefix, 'lib', 'node_modules'), join(npmPrefix, 'node_modules')];
200
- const wrappers = ['ruflo', 'claude-flow', join('@claude-flow', 'cli')];
201
- for (const root of roots) {
202
- for (const wrapper of wrappers) {
203
- const candidate = join(root, wrapper, 'node_modules', pkg, relativeFile);
204
- if (existsSync(candidate)) return candidate;
205
- }
206
- const direct = join(root, pkg, relativeFile);
207
- if (existsSync(direct)) return direct;
174
+ const sidecar = join(PROJECT_ROOT, '.claude-flow', 'memory-package.json');
175
+ if (existsSync(sidecar)) {
176
+ const rec = JSON.parse(readFileSync(sidecar, 'utf-8'));
177
+ if (rec?.distPath && existsSync(rec.distPath)) {
178
+ return await import(`file://${rec.distPath}`);
208
179
  }
209
180
  }
210
- } catch { /* npm not on PATH or no global install */ }
211
-
212
- return null;
213
- }
181
+ } catch { /* fall through */ }
214
182
 
215
- async function loadMemoryPackage() {
216
- // Strategy 1-5: locate dist/index.js across dev/installed/global layouts
217
- const resolved = await resolveBundledFile('@claude-flow/memory', 'dist/index.js');
218
- if (resolved) {
183
+ // Strategy 1: Local dev (built dist)
184
+ const localDist = join(PROJECT_ROOT, 'v3/@claude-flow/memory/dist/index.js');
185
+ if (existsSync(localDist)) {
219
186
  try {
220
- return await import(`file://${resolved}`);
187
+ return await import(`file://${localDist}`);
221
188
  } catch { /* fall through */ }
222
189
  }
223
190
 
224
- // Strategy 6: Use createRequire for CJS-style resolution (handles nested node_modules
191
+ // Strategy 2: Use createRequire for CJS-style resolution (handles nested node_modules
225
192
  // when installed as a transitive dependency via npx ruflo / npx claude-flow)
226
193
  try {
227
194
  const { createRequire } = await import('module');
@@ -229,11 +196,24 @@ async function loadMemoryPackage() {
229
196
  return require('@claude-flow/memory');
230
197
  } catch { /* fall through */ }
231
198
 
232
- // Strategy 7: ESM import (works when @claude-flow/memory is a direct dependency)
199
+ // Strategy 3: ESM import (works when @claude-flow/memory is a direct dependency)
233
200
  try {
234
201
  return await import('@claude-flow/memory');
235
202
  } catch { /* fall through */ }
236
203
 
204
+ // Strategy 4: Walk up from PROJECT_ROOT looking for @claude-flow/memory in any node_modules
205
+ let searchDir = PROJECT_ROOT;
206
+ const { parse } = await import('path');
207
+ while (searchDir !== parse(searchDir).root) {
208
+ const candidate = join(searchDir, 'node_modules', '@claude-flow', 'memory', 'dist', 'index.js');
209
+ if (existsSync(candidate)) {
210
+ try {
211
+ return await import(`file://${candidate}`);
212
+ } catch { /* fall through */ }
213
+ }
214
+ searchDir = dirname(searchDir);
215
+ }
216
+
237
217
  return null;
238
218
  }
239
219
 
@@ -283,7 +263,7 @@ async function doImport() {
283
263
 
284
264
  const memPkg = await loadMemoryPackage();
285
265
  if (!memPkg || !memPkg.AutoMemoryBridge) {
286
- dim('Memory package not available — skipping auto memory import');
266
+ warnMemoryUnavailable();
287
267
  return;
288
268
  }
289
269
 
@@ -292,10 +272,7 @@ async function doImport() {
292
272
  await backend.initialize();
293
273
 
294
274
  const bridgeConfig = {
295
- // Use Claude Code's invocation cwd (the user's project), not PROJECT_ROOT
296
- // — PROJECT_ROOT resolves to the plugin clone when this hook runs from
297
- // ~/.claude/plugins/marketplaces/ruflo/. See issue #2284.
298
- workingDir: process.env.CLAUDE_FLOW_CWD || process.cwd(),
275
+ workingDir: PROJECT_ROOT,
299
276
  syncMode: 'on-session-end',
300
277
  };
301
278
 
@@ -327,36 +304,6 @@ async function doImport() {
327
304
  dim(`├─ Learning: ${config.learningBridge.enabled ? 'active' : 'disabled'}`);
328
305
  dim(`├─ Graph: ${config.memoryGraph.enabled ? 'active' : 'disabled'}`);
329
306
  dim(`└─ Agent scopes: ${config.agentScopes.enabled ? 'active' : 'disabled'}`);
330
-
331
- // Bridge to AgentDB: store entries with ONNX vector embeddings for semantic search
332
- let vectorized = 0;
333
- try {
334
- const cliDistPath = await resolveBundledFile('@claude-flow/cli', 'dist/src/memory/memory-initializer.js');
335
- if (cliDistPath) {
336
- const memInit = await import(`file://${cliDistPath}`);
337
- await memInit.initializeMemoryDatabase({ force: false, verbose: false });
338
-
339
- const entries = await backend.query({});
340
- for (const entry of entries) {
341
- if (!entry.content || entry.content.length < 10) continue;
342
- try {
343
- await memInit.storeEntry({
344
- key: entry.key || entry.id,
345
- value: entry.content,
346
- namespace: entry.namespace || 'auto-memory',
347
- generateEmbeddingFlag: true,
348
- });
349
- vectorized++;
350
- } catch { /* skip entries that fail to embed */ }
351
- }
352
-
353
- if (vectorized > 0) {
354
- success(`Vectorized ${vectorized} entries into AgentDB (ONNX 384-dim)`);
355
- }
356
- }
357
- } catch (vecErr) {
358
- dim(`AgentDB vectorization skipped: ${vecErr.message?.slice(0, 60)}`);
359
- }
360
307
  } catch (err) {
361
308
  dim(`Import failed (non-critical): ${err.message}`);
362
309
  }
@@ -369,7 +316,7 @@ async function doSync() {
369
316
 
370
317
  const memPkg = await loadMemoryPackage();
371
318
  if (!memPkg || !memPkg.AutoMemoryBridge) {
372
- dim('Memory package not available — skipping sync');
319
+ warnMemoryUnavailable();
373
320
  return;
374
321
  }
375
322
 
@@ -385,8 +332,7 @@ async function doSync() {
385
332
  }
386
333
 
387
334
  const bridgeConfig = {
388
- // See doImport — must reflect the user's project, not PROJECT_ROOT (#2284)
389
- workingDir: process.env.CLAUDE_FLOW_CWD || process.cwd(),
335
+ workingDir: PROJECT_ROOT,
390
336
  syncMode: 'on-session-end',
391
337
  };
392
338
 
@@ -416,21 +362,6 @@ async function doSync() {
416
362
  // Curate MEMORY.md index with graph-aware ordering
417
363
  await bridge.curateIndex();
418
364
  success('Curated MEMORY.md index');
419
-
420
- // Flush intelligence patterns to disk (SONA + ReasoningBank)
421
- try {
422
- const intPath = await resolveBundledFile('@claude-flow/cli', 'dist/src/memory/intelligence.js');
423
- if (intPath) {
424
- const intelligence = await import(`file://${intPath}`);
425
- if (intelligence.flushPatterns) {
426
- intelligence.flushPatterns();
427
- const stats = intelligence.getIntelligenceStats?.();
428
- if (stats && stats.patternsLearned > 0) {
429
- success(`Flushed ${stats.patternsLearned} learned patterns to disk`);
430
- }
431
- }
432
- }
433
- } catch { /* non-critical */ }
434
365
  } catch (err) {
435
366
  dim(`Sync failed (non-critical): ${err.message}`);
436
367
  }
@@ -443,8 +374,12 @@ async function doStatus() {
443
374
  const memPkg = await loadMemoryPackage();
444
375
  const config = readConfig();
445
376
 
377
+ const sidecar = join(PROJECT_ROOT, '.claude-flow', 'memory-package.json');
378
+ const hasSidecar = existsSync(sidecar);
379
+
446
380
  console.log('\n=== Auto Memory Bridge Status ===\n');
447
- console.log(` Package: ${memPkg ? '✅ Available' : '❌ Not found'}`);
381
+ console.log(` Package: ${memPkg ? '✅ Available' : '❌ Not found — self-learning DISABLED (fix: npm i -D @claude-flow/memory)'}`);
382
+ console.log(` Resolver: ${hasSidecar ? '✅ .claude-flow/memory-package.json' : '⏸ no sidecar (run: npx ruflo@latest doctor --fix)'}`);
448
383
  console.log(` Store: ${existsSync(STORE_PATH) ? '✅ ' + STORE_PATH : '⏸ Not initialized'}`);
449
384
  console.log(` LearningBridge: ${config.learningBridge.enabled ? '✅ Enabled' : '⏸ Disabled'}`);
450
385
  console.log(` MemoryGraph: ${config.memoryGraph.enabled ? '✅ Enabled' : '⏸ Disabled'}`);
@@ -457,158 +392,9 @@ async function doStatus() {
457
392
  } catch { /* ignore */ }
458
393
  }
459
394
 
460
- // AgentDB vector status
461
- try {
462
- const dbPath = join(PROJECT_ROOT, '.claude-flow', 'memory', 'memory.db');
463
- const swarmDbPath = join(PROJECT_ROOT, '.swarm', 'memory.db');
464
- const hasDb = existsSync(dbPath) || existsSync(swarmDbPath);
465
- console.log(` AgentDB: ${hasDb ? '✅ sql.js database exists' : '⏸ Not initialized'}`);
466
-
467
- const intPath = await resolveBundledFile('@claude-flow/cli', 'dist/src/memory/intelligence.js');
468
- if (intPath) {
469
- const intelligence = await import(`file://${intPath}`);
470
- const stats = intelligence.getIntelligenceStats?.();
471
- if (stats) {
472
- console.log(` SONA: ${stats.sonaEnabled ? '✅ Active' : '⏸ Not initialized'}`);
473
- console.log(` Patterns: ${stats.patternsLearned} learned`);
474
- console.log(` Trajectories: ${stats.trajectoriesRecorded} recorded`);
475
- }
476
- }
477
- } catch { /* ignore */ }
478
-
479
395
  console.log('');
480
396
  }
481
397
 
482
- // ============================================================================
483
- // Import ALL Claude Code memories from all projects into AgentDB
484
- // ============================================================================
485
-
486
- async function doImportAll() {
487
- log('Importing ALL Claude Code memories into AgentDB...');
488
-
489
- const { homedir } = await import('os');
490
- const { readdirSync } = await import('fs');
491
- const claudeProjectsDir = join(homedir(), '.claude', 'projects');
492
-
493
- if (!existsSync(claudeProjectsDir)) {
494
- dim('No Claude Code projects found at ' + claudeProjectsDir);
495
- return;
496
- }
497
-
498
- // Find all memory files across all projects
499
- const memoryFiles = [];
500
- try {
501
- const projects = readdirSync(claudeProjectsDir, { withFileTypes: true });
502
- for (const project of projects) {
503
- if (!project.isDirectory()) continue;
504
- const memDir = join(claudeProjectsDir, project.name, 'memory');
505
- if (!existsSync(memDir)) continue;
506
- const files = readdirSync(memDir).filter(f => f.endsWith('.md'));
507
- for (const file of files) {
508
- memoryFiles.push({
509
- path: join(memDir, file),
510
- project: project.name,
511
- file,
512
- });
513
- }
514
- }
515
- } catch (err) {
516
- dim('Error scanning projects: ' + err.message);
517
- return;
518
- }
519
-
520
- if (memoryFiles.length === 0) {
521
- dim('No memory files found');
522
- return;
523
- }
524
-
525
- log(`Found ${memoryFiles.length} memory files across ${new Set(memoryFiles.map(f => f.project)).size} projects`);
526
-
527
- // Load memory-initializer for vectorized storage
528
- let memInit = null;
529
- try {
530
- const cliDistPath = await resolveBundledFile('@claude-flow/cli', 'dist/src/memory/memory-initializer.js');
531
- if (cliDistPath) {
532
- memInit = await import(`file://${cliDistPath}`);
533
- await memInit.initializeMemoryDatabase({ force: false, verbose: false });
534
- }
535
- } catch (err) {
536
- dim('Memory initializer not available: ' + err.message?.slice(0, 60));
537
- }
538
-
539
- if (!memInit) {
540
- dim('Cannot vectorize without memory-initializer. Run: cd v3/@claude-flow/cli && npm run build');
541
- return;
542
- }
543
-
544
- let imported = 0;
545
- let skipped = 0;
546
-
547
- for (const memFile of memoryFiles) {
548
- try {
549
- const content = readFileSync(memFile.path, 'utf-8');
550
-
551
- // Parse YAML frontmatter + body
552
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
553
- let name = memFile.file.replace('.md', '');
554
- let description = '';
555
- let type = 'auto-memory';
556
- let body = content;
557
-
558
- if (frontmatterMatch) {
559
- const yaml = frontmatterMatch[1];
560
- body = frontmatterMatch[2].trim();
561
- const nameMatch = yaml.match(/^name:\s*(.+)$/m);
562
- const descMatch = yaml.match(/^description:\s*(.+)$/m);
563
- const typeMatch = yaml.match(/^type:\s*(.+)$/m);
564
- if (nameMatch) name = nameMatch[1].trim();
565
- if (descMatch) description = descMatch[1].trim();
566
- if (typeMatch) type = typeMatch[1].trim();
567
- }
568
-
569
- // Split body into sections (## headers) for granular entries
570
- const sections = body.split(/^(?=## )/m).filter(s => s.trim().length > 20);
571
-
572
- if (sections.length === 0) {
573
- // Store whole file as one entry
574
- if (body.length > 10) {
575
- await memInit.storeEntry({
576
- key: `claude-memory:${memFile.project}:${name}`,
577
- value: body.slice(0, 4096),
578
- namespace: 'claude-memories',
579
- generateEmbeddingFlag: true,
580
- });
581
- imported++;
582
- }
583
- } else {
584
- // Store each section separately for better search granularity
585
- for (const section of sections) {
586
- const titleMatch = section.match(/^##\s+(.+)/);
587
- const sectionTitle = titleMatch ? titleMatch[1].trim() : name;
588
- const sectionBody = section.replace(/^##\s+.+\n/, '').trim();
589
- if (sectionBody.length < 10) continue;
590
-
591
- await memInit.storeEntry({
592
- key: `claude-memory:${memFile.project}:${name}:${sectionTitle.slice(0, 50)}`,
593
- value: sectionBody.slice(0, 4096),
594
- namespace: 'claude-memories',
595
- generateEmbeddingFlag: true,
596
- });
597
- imported++;
598
- }
599
- }
600
-
601
- dim(` ✓ ${memFile.project}/${memFile.file} (${sections.length || 1} entries)`);
602
- } catch (err) {
603
- dim(` ✗ ${memFile.project}/${memFile.file}: ${err.message?.slice(0, 60)}`);
604
- skipped++;
605
- }
606
- }
607
-
608
- success(`Imported ${imported} entries from ${memoryFiles.length} files (${skipped} skipped)`);
609
- success('All Claude Code memories now searchable via AgentDB vector search');
610
- }
611
-
612
398
  // ============================================================================
613
399
  // Main
614
400
  // ============================================================================
@@ -630,16 +416,15 @@ process.on('unhandledRejection', (reason) => {
630
416
  try {
631
417
  switch (command) {
632
418
  case 'import': await doImport(); break;
633
- case 'import-all': await doImportAll(); break;
634
419
  case 'sync': await doSync(); break;
635
420
  case 'status': await doStatus(); break;
636
421
  default:
637
422
  console.log('Usage: auto-memory-hook.mjs <import|sync|status>');
638
- process.exit(1);
423
+ break;
639
424
  }
640
425
  } catch (err) {
641
426
  // Hooks must never crash Claude Code - fail silently
642
- dim(`Error (non-critical): ${err.message}`);
427
+ try { dim(`Error (non-critical): ${err.message}`); } catch (_) {}
643
428
  }
644
- // Ensure clean exit for Claude Code hooks (exit 0 = success, no stderr = no error)
429
+ // Force clean exit process.exitCode alone isn't enough if async errors override it
645
430
  process.exit(0);
@@ -0,0 +1,12 @@
1
+ {
2
+ "manifest": {
3
+ "version": "3.22.0",
4
+ "files": {
5
+ "auto-memory-hook.mjs": "68be7e9a9eba7bf9c4e8a230db7bf61a243b965639f8504842799d6c6ca28762",
6
+ "hook-handler.cjs": "bc4d2d26823d49b3ab1dded2946b66369f1f67bd76b4c30dca9f3b6df3cca8f0",
7
+ "intelligence.cjs": "760cb82ed2000031abc1ac1fa90a014e7d91d93966e3aa4741b07ab7aff8d066"
8
+ }
9
+ },
10
+ "signature": "sTqZ2JNEoWfS0LKrQVESAqJ+yfNB6/YExxxn5mmsZ/kPuH8u9uURt8J+RPICG1/qwNIOkkDEYJtQtGzpVW0jAw==",
11
+ "algorithm": "ed25519"
12
+ }