@claude-flow/cli 3.56.10 → 3.57.1

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 (73) hide show
  1. package/.claude/helpers/.helpers-version +1 -1
  2. package/.claude/helpers/helpers.manifest.json +2 -2
  3. package/README.md +12 -3
  4. package/catalog-manifest.json +2 -2
  5. package/dist/src/commands/daemon.js +8 -2
  6. package/dist/src/commands/doctor.js +95 -18
  7. package/dist/src/commands/policy.js +6 -1
  8. package/dist/src/index.js +5 -5
  9. package/dist/src/init/settings-generator.js +4 -58
  10. package/dist/src/mcp-tools/memory-tools.d.ts +1 -1
  11. package/dist/src/mcp-tools/memory-tools.js +30 -5
  12. package/dist/src/mcp-tools/metaharness-tools.js +1 -1
  13. package/dist/src/mcp-tools/neural-tools.js +20 -50
  14. package/dist/src/mcp-tools/policy-tools.js +5 -3
  15. package/dist/src/memory/intelligence.js +80 -33
  16. package/dist/src/memory/stats-file-lock.d.ts +7 -0
  17. package/dist/src/memory/stats-file-lock.js +53 -0
  18. package/dist/src/missions/schemas.d.ts +113 -113
  19. package/dist/src/mods/command-registry/schema.d.ts +193 -193
  20. package/dist/src/services/distill-oracle.d.ts +1 -1
  21. package/dist/src/services/distill-oracle.js +2 -2
  22. package/dist/src/services/policy-anchor-log.d.ts +13 -0
  23. package/dist/src/services/policy-anchor-log.js +242 -0
  24. package/dist/src/services/policy-archive-scan.d.ts +7 -0
  25. package/dist/src/services/policy-archive-scan.js +50 -0
  26. package/dist/src/services/policy-ledger-anchor.d.ts +14 -8
  27. package/dist/src/services/policy-ledger-anchor.js +356 -40
  28. package/dist/src/services/policy-ledger-audit.d.ts +22 -0
  29. package/dist/src/services/policy-ledger-audit.js +260 -0
  30. package/dist/src/services/policy-ledger-record.d.ts +3 -0
  31. package/dist/src/services/policy-ledger-record.js +22 -0
  32. package/dist/src/services/policy-runtime.d.ts +1 -0
  33. package/dist/src/services/policy-runtime.js +261 -40
  34. package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
  35. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  36. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
  37. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts +17 -1
  38. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts.map +1 -1
  39. package/node_modules/@claude-flow/security/dist/policy/engine.js +99 -24
  40. package/node_modules/@claude-flow/security/dist/policy/engine.js.map +1 -1
  41. package/node_modules/@claude-flow/security/dist/policy/types.d.ts +14 -1
  42. package/node_modules/@claude-flow/security/dist/policy/types.d.ts.map +1 -1
  43. package/node_modules/@claude-flow/security/dist/policy/types.js +3 -1
  44. package/node_modules/@claude-flow/security/dist/policy/types.js.map +1 -1
  45. package/package.json +3 -3
  46. package/plugins/ruflo-console/dist/tui.mjs +153 -153
  47. package/plugins/ruflo-metaharness/hooks/screen.ts +7 -1
  48. package/plugins/ruflo-metaharness/scripts/_darwin.mjs +4 -4
  49. package/plugins/ruflo-metaharness/.claude-flow/daemon-state.json +0 -179
  50. package/plugins/ruflo-metaharness/.claude-flow/daemon.pid +0 -1
  51. package/plugins/ruflo-metaharness/.claude-flow/logs/daemon.log +0 -32
  52. package/plugins/ruflo-metaharness/.claude-flow/metrics/backup.json +0 -23
  53. package/plugins/ruflo-metaharness/.claude-flow/metrics/codebase-map.json +0 -11
  54. package/plugins/ruflo-metaharness/.claude-flow/metrics/consolidation.json +0 -16
  55. package/plugins/ruflo-metaharness/.claude-flow/metrics/harness-loop.json +0 -91
  56. package/plugins/ruflo-metaharness/.claude-flow/metrics/performance.json +0 -17
  57. package/plugins/ruflo-metaharness/.claude-flow/metrics/security-audit.json +0 -12
  58. package/plugins/ruflo-metaharness/.claude-flow/metrics/test-gaps.json +0 -8
  59. package/plugins/ruflo-metaharness/.claude-flow/neural/patterns.json +0 -2809
  60. package/plugins/ruflo-metaharness/.claude-flow/neural/stats.json +0 -6
  61. package/plugins/ruflo-metaharness/.claude-flow/policy/state.json +0 -11
  62. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db +0 -0
  63. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-shm +0 -0
  64. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-wal +0 -0
  65. package/plugins/ruflo-metaharness/.swarm/backups/memory-2026-10-14T16-09-38-164Z.db +0 -0
  66. package/plugins/ruflo-metaharness/.swarm/backups/store-agentdb-memory.db-2026-10-14T16-09-38-166Z.db +0 -0
  67. package/plugins/ruflo-metaharness/.swarm/ewc-fisher.json +0 -397
  68. package/plugins/ruflo-metaharness/.swarm/memory.db +0 -0
  69. package/plugins/ruflo-metaharness/.swarm/memory.db-shm +0 -0
  70. package/plugins/ruflo-metaharness/.swarm/memory.db-wal +0 -0
  71. package/plugins/ruflo-metaharness/agentdb.rvf +0 -0
  72. package/plugins/ruflo-metaharness/agentdb.rvf.lock +0 -0
  73. package/plugins/ruflo-metaharness/ruvector.db +0 -0
@@ -1 +1 @@
1
- 3.56.9
1
+ 3.57.0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest": {
3
- "version": "3.56.10",
3
+ "version": "3.57.1",
4
4
  "files": {
5
5
  "auto-memory-hook.mjs": "631fac9d518835e2852a406888316bbbddddb49e7ed8e406d2e971f46833df9a",
6
6
  "hook-handler.cjs": "bc12b3cae92d5a7c8deef699fa00d0ef07b57625c18dbeac4387f15725b8e09f",
@@ -9,6 +9,6 @@
9
9
  "router.cjs": "16648b3c0d73b6681ac2d8d13def6a68286c57f5a11004de5b19a0fa088c833d"
10
10
  }
11
11
  },
12
- "signature": "hZ0iy15VIKpZOjC2iG2fPsV68csqXrMhn2mifCIvzsjngaB/wmP0P4iMF38nAo57MeANEM6wW1nhK7YvteUXCg==",
12
+ "signature": "4QJCbq039ufiBQ0tz2aVw1refajyDbptNNS+xaHszCNADeMKOzqL3pT3dh4k+hZgMn+zKYh1V0FOmF9GyXJhAA==",
13
13
  "algorithm": "ed25519"
14
14
  }
package/README.md CHANGED
@@ -10,10 +10,11 @@
10
10
  [![Star on GitHub](https://img.shields.io/github/stars/ruvnet/claude-flow?style=for-the-badge&logo=github&color=gold)](https://github.com/ruvnet/claude-flow)
11
11
 
12
12
  <p align="center">
13
- <a href="data/npm-downloads.latest.json"><img src="docs/assets/readme/badges/downloads.svg?v=mobile-readable-3" width="300" alt="Ecosystem npm downloads: 12.52M over 12 months through October 4, 2026"></a>
13
+ <a href="docs/harness-origins.md"><img src="https://raw.githubusercontent.com/ruvnet/ruflo/e69e4b95aa08d65ea0f7715489bbf8e62a83a0d2/docs/assets/readme/badges/first-commit.svg" width="300" height="76" alt="Claude Flow lineage: first commit June 2, 2025 by rUv; inspect the evidence"></a>
14
+ <a href="data/npm-downloads.latest.json"><img src="https://raw.githubusercontent.com/ruvnet/ruflo/275aff65a198af758923669acff36f03d1f41623/docs/assets/readme/badges/downloads.svg" width="300" height="76" alt="Illustrative download counter starts at 98,000,000 and adds varied amounts each second in a 30 second loop. Verified dataset: 97,022,120 download events."></a>
14
15
  <br>
15
- <a href="https://github.com/ruvnet/claude-flow"><img src="docs/assets/readme/badges/claude.svg?v=mobile-readable-3" width="300" alt="Claude Code"></a>
16
- <a href="https://www.npmjs.com/package/@claude-flow/codex"><img src="docs/assets/readme/badges/codex.svg?v=mobile-readable-3" width="300" alt="Codex Plugin"></a>
16
+ <a href="https://github.com/ruvnet/claude-flow"><img src="https://raw.githubusercontent.com/ruvnet/ruflo/d1e80400bdefe01d3b13e70395f88fffab76bb18/docs/assets/readme/badges/claude.svg" width="300" height="76" alt="Claude Code plugin"></a>
17
+ <a href="https://www.npmjs.com/package/@claude-flow/codex"><img src="https://raw.githubusercontent.com/ruvnet/ruflo/d1e80400bdefe01d3b13e70395f88fffab76bb18/docs/assets/readme/badges/codex.svg" width="300" height="76" alt="Codex plugin"></a>
17
18
  </p>
18
19
 
19
20
  </div>
@@ -109,6 +110,14 @@ User → Ruflo (CLI/MCP) → Router → Swarm → Agents → Memory → LLM prov
109
110
 
110
111
  > **New to Ruflo?** You don't need to learn 314 MCP tools or 26 CLI commands. After `init`, just use Claude Code normally — the hooks system automatically routes tasks, learns from successful patterns, and coordinates agents in the background.
111
112
 
113
+ ### An origin you can inspect
114
+
115
+ [![Claude Flow to Ruflo: founding idea on June 2, 2025, orchestration source on June 10, and the continuing Ruflo lineage.](docs/assets/readme/harness-origins.svg)](docs/harness-origins.md)
116
+
117
+ **Built by [Reuven Cohen (rUv)](https://github.com/ruvnet), originally as Claude Flow.** The [first commit, June 2, 2025](https://github.com/ruvnet/ruflo/commit/7c1f9402d70e7af56c01a879073cbac92564dc4e), describes a code orchestration layer for recursive agent cycles: Claude writes, edits, tests and improves. The [June 10 source snapshot](https://github.com/ruvnet/ruflo/tree/dba545f012ea92a2375a26332bbf3797495e93c9) adds orchestration, task scheduling, memory and terminal modules.
118
+
119
+ A harness is the workbench around the model: it organizes tasks, carries context between steps and helps check results. **This establishes Ruflo's lineage, not a universal first across every Claude Code tool.** [See the illustrated explainer, exact commits and earlier ecosystem context](docs/harness-origins.md).
120
+
112
121
  <details>
113
122
  <summary><strong>📖 Background — where the name comes from</strong></summary>
114
123
 
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 7,
4
- "generatedAt": "2026-10-14T16:22:09.483Z",
5
- "gitSha": "1882006a",
4
+ "generatedAt": "2026-10-19T16:47:16.220Z",
5
+ "gitSha": "aedd3d53",
6
6
  "catalog": {
7
7
  "agents": 176,
8
8
  "tools": 423,
@@ -1247,12 +1247,18 @@ const statusCommand = {
1247
1247
  // its real consent state into daemon-state.json — prefer that when it
1248
1248
  // is the one running.
1249
1249
  let aiWorkersEnabled = status.config.aiWorkersEnabled;
1250
+ // #4238: same for the TTL — a daemon started with `--ttl 0` must not be
1251
+ // reported with this process's 12h default.
1252
+ let ttlMs = status.config.ttlMs;
1250
1253
  if (bgRunning) {
1251
1254
  try {
1252
1255
  const st = JSON.parse(fs.readFileSync(join(projectRoot, '.claude-flow', 'daemon-state.json'), 'utf-8'));
1253
1256
  if (typeof st?.config?.aiWorkersEnabled === 'boolean') {
1254
1257
  aiWorkersEnabled = st.config.aiWorkersEnabled;
1255
1258
  }
1259
+ if (typeof st?.config?.ttlMs === 'number' && Number.isFinite(st.config.ttlMs)) {
1260
+ ttlMs = st.config.ttlMs;
1261
+ }
1256
1262
  }
1257
1263
  catch { /* no/partial state — fall back to in-process config */ }
1258
1264
  }
@@ -1265,8 +1271,8 @@ const statusCommand = {
1265
1271
  `Status: ${statusIcon} ${statusText}${mode}`,
1266
1272
  `PID: ${displayPid}`,
1267
1273
  status.startedAt ? `Started: ${status.startedAt.toISOString()}` : '',
1268
- status.config.ttlMs > 0
1269
- ? `TTL: ${Math.round(status.config.ttlMs / 3600000)}h (self-shutdown)`
1274
+ ttlMs > 0
1275
+ ? `TTL: ${Math.round(ttlMs / 3600000)}h (self-shutdown)`
1270
1276
  : `TTL: ${output.dim('off (runs until stopped)')}`,
1271
1277
  // #2661: surface the AI-consent gate so "why is audit local-only?"
1272
1278
  // is answerable from `daemon status` alone.
@@ -2515,6 +2515,12 @@ export const doctorCommand = {
2515
2515
  name: 'doctor',
2516
2516
  description: 'System diagnostics and health checks',
2517
2517
  options: [
2518
+ {
2519
+ name: 'json',
2520
+ description: 'Emit versioned JSON health checks (cannot be combined with repair flags)',
2521
+ type: 'boolean',
2522
+ default: false
2523
+ },
2518
2524
  {
2519
2525
  name: 'fix',
2520
2526
  short: 'f',
@@ -2561,6 +2567,7 @@ export const doctorCommand = {
2561
2567
  }
2562
2568
  ],
2563
2569
  examples: [
2570
+ { command: 'claude-flow doctor --json -c node', description: 'Emit machine-readable health checks' },
2564
2571
  { command: 'claude-flow doctor', description: 'Run full health check' },
2565
2572
  { command: 'claude-flow doctor --fix', description: 'Print suggested fix commands (does not auto-apply)' },
2566
2573
  { command: 'claude-flow doctor --install', description: 'Auto-install missing dependencies' },
@@ -2575,6 +2582,21 @@ export const doctorCommand = {
2575
2582
  const verbose = ctx.flags.verbose;
2576
2583
  // Parser camelCases kebab-case flag names — read via `fixHandles`, not `['fix-handles']`.
2577
2584
  const fixHandles = ctx.flags.fixHandles;
2585
+ const json = ctx.flags.json;
2586
+ const reportError = (message) => {
2587
+ if (json)
2588
+ output.writeln(JSON.stringify({ schemaVersion: 1, checks: [], error: message }));
2589
+ else
2590
+ output.printError(message);
2591
+ return { success: false, exitCode: 1, message };
2592
+ };
2593
+ if (json && (showFix || autoInstall || fixHandles)) {
2594
+ return reportError('--json cannot be combined with --fix, --install, or --fix-handles');
2595
+ }
2596
+ // Reuse the same callable for anonymous checks so their IDs do not depend
2597
+ // on display names or on whether the full or component suite was selected.
2598
+ const helperCheck = () => checkHelperIntegrity();
2599
+ const nativeAddonCheck = () => checkNativeAddonHeaders();
2578
2600
  // #2677: `--component memory` now runs the whole memory-health suite,
2579
2601
  // not just the existence check. Values can be a single check or an
2580
2602
  // array — expanded at execution time. Stuinfla's report showed the
@@ -2592,7 +2614,7 @@ export const doctorCommand = {
2592
2614
  'browser': checkAgentBrowserVersion,
2593
2615
  'config': checkConfigFile,
2594
2616
  'stale-settings': checkStaleSettingsNpx, // #2448
2595
- 'helpers': () => checkHelperIntegrity(), // #3565
2617
+ 'helpers': helperCheck, // #3565
2596
2618
  'daemon': checkDaemonStatus,
2597
2619
  get memory() {
2598
2620
  return [
@@ -2608,7 +2630,7 @@ export const doctorCommand = {
2608
2630
  ];
2609
2631
  },
2610
2632
  'memory-package': checkMemoryPackageVersion, // #3392
2611
- 'native-addon': () => checkNativeAddonHeaders(), // #4055
2633
+ 'native-addon': nativeAddonCheck, // #4055
2612
2634
  'learning': checkLearningBridge, // #2545
2613
2635
  'learning-bridge': checkLearningBridge, // #2545
2614
2636
  'api': checkApiKeys,
@@ -2634,8 +2656,7 @@ export const doctorCommand = {
2634
2656
  };
2635
2657
  if (component !== undefined && !Object.hasOwn(componentMap, component)) {
2636
2658
  const message = `Unknown doctor component: ${JSON.stringify(component)}. Valid components: ${Object.keys(componentMap).join(', ')}`;
2637
- output.printError(message);
2638
- return { success: false, exitCode: 1, message };
2659
+ return reportError(message);
2639
2660
  }
2640
2661
  // Early-return short-circuit: `--fix-handles` is a targeted mitigation, not
2641
2662
  // part of the health-check flow. Runs, reports, exits.
@@ -2699,12 +2720,15 @@ export const doctorCommand = {
2699
2720
  output.writeln(output.dim('Upstream tracking: https://github.com/anthropics/claude-code/issues/67888'));
2700
2721
  return { success: true };
2701
2722
  }
2702
- output.writeln();
2703
- output.writeln(output.bold('RuFlo Doctor'));
2704
- output.writeln(output.dim('System diagnostics and health check'));
2705
- output.writeln(output.dim('─'.repeat(50)));
2706
- output.writeln();
2707
- const nativeAgentDbChecks = (await existingNativeAgentDbPaths())
2723
+ if (!json) {
2724
+ output.writeln();
2725
+ output.writeln(output.bold('RuFlo Doctor'));
2726
+ output.writeln(output.dim('System diagnostics and health check'));
2727
+ output.writeln(output.dim('─'.repeat(50)));
2728
+ output.writeln();
2729
+ }
2730
+ const nativeAgentDbPaths = await existingNativeAgentDbPaths();
2731
+ const nativeAgentDbChecks = nativeAgentDbPaths
2708
2732
  .map((dbPath) => () => checkNativeAgentDbStructuralIntegrity(dbPath));
2709
2733
  const allChecks = [
2710
2734
  checkVersionFreshness,
@@ -2716,7 +2740,7 @@ export const doctorCommand = {
2716
2740
  checkGitRepo,
2717
2741
  checkConfigFile,
2718
2742
  checkStaleSettingsNpx, // #2448/#2677 — runaway `npx @latest` in settings
2719
- () => checkHelperIntegrity(), // #3565 — installed signed helpers vs manifest
2743
+ helperCheck, // #3565 — installed signed helpers vs manifest
2720
2744
  checkDaemonStatus,
2721
2745
  checkMemoryDatabase,
2722
2746
  checkMemoryStructuralIntegrity, // #2737 — bounded, native quick_check on every default run
@@ -2724,7 +2748,7 @@ export const doctorCommand = {
2724
2748
  checkMemoryPersistenceDriver, // #2968/#3321 — read-only native capability probe
2725
2749
  checkLearningBridge, // #2545 — can the auto-memory hook actually load @claude-flow/memory?
2726
2750
  checkMemoryPackageVersion, // #3392 — loaded @claude-flow/memory must satisfy the CLI's declared range
2727
- () => checkNativeAddonHeaders(), // #4055 — better-sqlite3 built against Node 24.19+ headers on 24.19-24.21
2751
+ nativeAddonCheck, // #4055 — better-sqlite3 built against Node 24.19+ headers on 24.19-24.21
2728
2752
  checkApiKeys,
2729
2753
  checkMcpServers,
2730
2754
  checkMcpSchemaOverhead, // #2726 — fixed tools/list prompt cost
@@ -2747,21 +2771,59 @@ export const doctorCommand = {
2747
2771
  const entry = componentMap[component];
2748
2772
  checksToRun = Array.isArray(entry) ? entry : [entry];
2749
2773
  }
2774
+ // These are API identifiers: keep them stable even when user-facing names
2775
+ // change. Grouped components have a distinct ID for each individual check.
2776
+ const checkIds = new Map([
2777
+ [checkVersionFreshness, 'version'], [checkNodeVersion, 'node'],
2778
+ [checkNpmVersion, 'npm'], [checkClaudeCode, 'claude'],
2779
+ [checkAgentBrowserVersion, 'browser'], [checkGit, 'git'],
2780
+ [checkGitRepo, 'git-repo'], [checkConfigFile, 'config'],
2781
+ [checkStaleSettingsNpx, 'stale-settings'], [helperCheck, 'helpers'],
2782
+ [checkDaemonStatus, 'daemon'], [checkMemoryDatabase, 'memory-presence'],
2783
+ [checkMemoryStructuralIntegrity, 'memory-structural'],
2784
+ [checkMemoryIntegrity, 'memory-integrity'],
2785
+ [checkMemoryPersistenceDriver, 'memory-driver'],
2786
+ [checkMemoryPackageVersion, 'memory-package'],
2787
+ [checkMemoryContent, 'memory-content'],
2788
+ [checkMemoryEmbeddingCoverage, 'memory-embeddings'],
2789
+ [checkMemoryReflexionCoverage, 'memory-reflexion'],
2790
+ [checkMemoryCritiqueCoverage, 'memory-critique'],
2791
+ [checkLearningBridge, 'learning'], [nativeAddonCheck, 'native-addon'],
2792
+ [checkApiKeys, 'api'], [checkMcpServers, 'mcp'],
2793
+ [checkMcpSchemaOverhead, 'mcp-overhead'], [checkAIDefence, 'aidefence'],
2794
+ [checkDiskSpace, 'disk'], [checkBuildTools, 'typescript'],
2795
+ [checkAgenticFlow, 'agentic-flow'], [checkEncryptionAtRest, 'encryption'],
2796
+ [checkFederationBreaker, 'federation'], [checkMetaharness, 'metaharness'],
2797
+ [checkMetaharnessDeclaredPackages, 'metaharness-packages'],
2798
+ [checkMetaharnessIntegration, 'metaharness-integration'],
2799
+ [checkFunnel, 'funnel'], [checkProxySponsoredConsent, 'proxy-consent'],
2800
+ [checkProxyBinary, 'proxy-binary'], [checkProxyProcess, 'proxy-process'],
2801
+ [checkProxyBindAddress, 'proxy-bind'], [checkAuth, 'auth'],
2802
+ [checkTypesafeRouter, 'typesafe'], [checkMods, 'mods'],
2803
+ ]);
2804
+ nativeAgentDbChecks.forEach((check, index) => {
2805
+ // The path distinguishes simultaneous authority files; normalize separators.
2806
+ checkIds.set(check, `memory-native:${nativeAgentDbPaths[index].replace(/\\/g, '/')}`);
2807
+ });
2808
+ if (json && checksToRun.some(check => !checkIds.has(check))) {
2809
+ return reportError('Doctor check is missing a stable JSON ID');
2810
+ }
2750
2811
  const results = [];
2751
2812
  const fixes = [];
2752
2813
  // OPTIMIZATION: Run all checks in parallel for 3-5x faster execution
2753
- const spinner = output.createSpinner({ text: 'Running health checks in parallel...', spinner: 'dots' });
2754
- spinner.start();
2814
+ const spinner = json ? undefined : output.createSpinner({ text: 'Running health checks in parallel...', spinner: 'dots' });
2815
+ spinner?.start();
2755
2816
  try {
2756
2817
  // Execute all checks concurrently
2757
2818
  const checkResults = await Promise.allSettled(checksToRun.map(check => check()));
2758
- spinner.stop();
2819
+ spinner?.stop();
2759
2820
  // Process results in order
2760
2821
  for (const settledResult of checkResults) {
2761
2822
  if (settledResult.status === 'fulfilled') {
2762
2823
  const result = settledResult.value;
2763
2824
  results.push(result);
2764
- output.writeln(formatCheck(result));
2825
+ if (!json)
2826
+ output.writeln(formatCheck(result));
2765
2827
  if (result.fix && (result.status === 'fail' || result.status === 'warn')) {
2766
2828
  fixes.push(`${result.name}: ${result.fix}`);
2767
2829
  }
@@ -2773,12 +2835,15 @@ export const doctorCommand = {
2773
2835
  message: settledResult.reason?.message || 'Unknown error'
2774
2836
  };
2775
2837
  results.push(errorResult);
2776
- output.writeln(formatCheck(errorResult));
2838
+ if (!json)
2839
+ output.writeln(formatCheck(errorResult));
2777
2840
  }
2778
2841
  }
2779
2842
  }
2780
2843
  catch (error) {
2781
- spinner.stop();
2844
+ spinner?.stop();
2845
+ if (json)
2846
+ return reportError(`Failed to run health checks: ${error instanceof Error ? error.message : String(error)}`);
2782
2847
  output.writeln(output.error('Failed to run health checks'));
2783
2848
  }
2784
2849
  // #2545: --fix / --install can actually repair the Learning Bridge by
@@ -2827,6 +2892,18 @@ export const doctorCommand = {
2827
2892
  const passed = results.filter(r => r.status === 'pass').length;
2828
2893
  const warnings = results.filter(r => r.status === 'warn').length;
2829
2894
  const failed = results.filter(r => r.status === 'fail').length;
2895
+ if (json) {
2896
+ const checks = results.map((result, index) => ({
2897
+ id: checkIds.get(checksToRun[index]),
2898
+ status: result.status,
2899
+ name: result.name,
2900
+ detail: result.message,
2901
+ ...(result.fix ? { fix: result.fix } : {}),
2902
+ }));
2903
+ const data = { schemaVersion: 1, checks };
2904
+ output.writeln(JSON.stringify(data));
2905
+ return { success: failed === 0, exitCode: failed > 0 ? 1 : 0, data };
2906
+ }
2830
2907
  output.writeln();
2831
2908
  output.writeln(output.dim('─'.repeat(50)));
2832
2909
  output.writeln();
@@ -30,6 +30,7 @@ export const policyCommand = {
30
30
  { name: 'mode', type: 'string', description: 'Policy mode: legacy | observe | enforce' },
31
31
  { name: 'project-root', type: 'string', description: 'Project root containing .claude-flow/policy' },
32
32
  { name: 'establish-anchor', type: 'boolean', description: 'verify: explicitly anchor a ledger that has receipts but no anchor (interactive, logged with user and time)' },
33
+ { name: 'full', type: 'boolean', description: 'verify: additionally replay the archived receipts (receipts.ledger.jsonl) to verify the complete historical chain, not just the retained hot tail' },
33
34
  ],
34
35
  async action(context) {
35
36
  const args = context.args ?? [];
@@ -93,9 +94,13 @@ export const policyCommand = {
93
94
  }
94
95
  if (operation === 'verify') {
95
96
  const establishAnchor = flags['establish-anchor'] === true || flags.establishAnchor === true;
97
+ const full = flags.full === true;
96
98
  if (establishAnchor)
97
99
  requireInteractiveAdministrator();
98
- const ledger = await verifyPolicyLedger(root, { establishAnchor });
100
+ const ledger = await verifyPolicyLedger(root, { establishAnchor, full });
101
+ if (ledger.error === 'receipt-key-id-mismatch') {
102
+ output.printError('Restore the original CLAUDE_FLOW_POLICY_KEY_ID for this ledger; do not rewrite or re-sign historical receipts.');
103
+ }
99
104
  const result = print({ ...ledger, anchors: anchorPosture(root), scope: LEDGER_TRUST_SCOPE });
100
105
  return ledger.valid ? result : { ...result, success: false, exitCode: 1 };
101
106
  }
package/dist/src/index.js CHANGED
@@ -92,13 +92,13 @@ export class CLI {
92
92
  const parseResult = this.parser.parse(args);
93
93
  const { command: commandPath, flags, positional } = parseResult;
94
94
  // Handle global flags
95
+ if (flags.noColor || flags.color === false) {
96
+ this.output.setColorEnabled(false);
97
+ }
95
98
  if (flags.version || flags.V) {
96
99
  this.showVersion();
97
100
  return;
98
101
  }
99
- if (flags.noColor) {
100
- this.output.setColorEnabled(false);
101
- }
102
102
  // Set verbosity level based on flags
103
103
  if (flags.quiet) {
104
104
  this.output.setVerbosity('quiet');
@@ -114,7 +114,7 @@ export class CLI {
114
114
  this.output.printDebug(`CWD: ${process.cwd()}`);
115
115
  }
116
116
  // Run startup update check (non-blocking, silent on skip)
117
- if (!flags.noUpdate && commandPath[0] !== 'update') {
117
+ if (!flags.noUpdate && flags.update !== false && commandPath[0] !== 'update' && !(commandPath[0] === 'doctor' && flags.json)) {
118
118
  this.checkForUpdatesOnStartup().catch(() => { });
119
119
  }
120
120
  // Version-stamped helper auto-refresh — propagate hook fixes to an already
@@ -536,7 +536,7 @@ export class CLI {
536
536
  catch (error) {
537
537
  // Config loading is optional - don't fail if it doesn't exist
538
538
  if (process.env.DEBUG) {
539
- this.output.writeln(this.output.dim(`Config loading failed: ${error.message}`));
539
+ this.output.writeErrorln(this.output.dim(`Config loading failed: ${error.message}`));
540
540
  }
541
541
  return undefined;
542
542
  }
@@ -27,7 +27,6 @@ export function generateSettings(options) {
27
27
  allow: [
28
28
  'Bash(npx @claude-flow*)',
29
29
  'Bash(npx claude-flow*)',
30
- 'Bash(node .claude/*)',
31
30
  'mcp__claude-flow__*',
32
31
  ],
33
32
  deny: [
@@ -201,7 +200,7 @@ function generateHooksConfig(config, scope) {
201
200
  const hooks = {};
202
201
  // Node.js scripts handle errors internally via try/catch.
203
202
  // No shell-level error suppression needed (2>/dev/null || true breaks Windows).
204
- // PreToolUse — validate commands and edits before execution
203
+ // PreToolUse — validate shell commands before execution
205
204
  if (config.preToolUse) {
206
205
  hooks.PreToolUse = [
207
206
  {
@@ -214,19 +213,9 @@ function generateHooksConfig(config, scope) {
214
213
  },
215
214
  ],
216
215
  },
217
- {
218
- matcher: 'Write|Edit|MultiEdit',
219
- hooks: [
220
- {
221
- type: 'command',
222
- command: hookHandlerCmd('pre-edit', scope),
223
- timeout: config.timeout,
224
- },
225
- ],
226
- },
227
216
  ];
228
217
  }
229
- // PostToolUse — record edits and commands for session metrics / learning
218
+ // PostToolUse — record edits for session metrics / learning
230
219
  if (config.postToolUse) {
231
220
  hooks.PostToolUse = [
232
221
  {
@@ -239,16 +228,6 @@ function generateHooksConfig(config, scope) {
239
228
  },
240
229
  ],
241
230
  },
242
- {
243
- matcher: 'Bash',
244
- hooks: [
245
- {
246
- type: 'command',
247
- command: hookHandlerCmd('post-bash', scope),
248
- timeout: config.timeout,
249
- },
250
- ],
251
- },
252
231
  ];
253
232
  }
254
233
  // UserPromptSubmit — intelligent task routing
@@ -312,16 +291,13 @@ function generateHooksConfig(config, scope) {
312
291
  },
313
292
  ];
314
293
  }
315
- // PreCompact — preserve context before compaction
294
+ // PreCompact — end the current session before compaction. The handler has no
295
+ // manual/automatic compaction-specific command, so don't wire no-op hooks.
316
296
  if (config.preCompact) {
317
297
  hooks.PreCompact = [
318
298
  {
319
299
  matcher: 'manual',
320
300
  hooks: [
321
- {
322
- type: 'command',
323
- command: hookHandlerCmd('compact-manual', scope),
324
- },
325
301
  {
326
302
  type: 'command',
327
303
  command: hookHandlerCmd('session-end', scope),
@@ -332,10 +308,6 @@ function generateHooksConfig(config, scope) {
332
308
  {
333
309
  matcher: 'auto',
334
310
  hooks: [
335
- {
336
- type: 'command',
337
- command: hookHandlerCmd('compact-auto', scope),
338
- },
339
311
  {
340
312
  type: 'command',
341
313
  command: hookHandlerCmd('session-end', scope),
@@ -345,18 +317,6 @@ function generateHooksConfig(config, scope) {
345
317
  },
346
318
  ];
347
319
  }
348
- // SubagentStart — status update when a sub-agent is spawned
349
- hooks.SubagentStart = [
350
- {
351
- hooks: [
352
- {
353
- type: 'command',
354
- command: hookHandlerCmd('status', scope),
355
- timeout: 3000,
356
- },
357
- ],
358
- },
359
- ];
360
320
  // SubagentStop — track agent completion for metrics
361
321
  // NOTE: The valid event is "SubagentStop" (not "SubagentEnd")
362
322
  hooks.SubagentStop = [
@@ -370,20 +330,6 @@ function generateHooksConfig(config, scope) {
370
330
  ],
371
331
  },
372
332
  ];
373
- // Notification — capture Claude Code notifications for logging
374
- if (config.notification) {
375
- hooks.Notification = [
376
- {
377
- hooks: [
378
- {
379
- type: 'command',
380
- command: hookHandlerCmd('notify', scope),
381
- timeout: 3000,
382
- },
383
- ],
384
- },
385
- ];
386
- }
387
333
  // NOTE: TeammateIdle, TaskCompleted, and PostCompact are NOT accepted by
388
334
  // Claude Code's settings.json validator (rejected as "Invalid key in record").
389
335
  // Agent Teams coordination lives in claudeFlow.agentTeams.hooks instead.
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @module v3/cli/mcp-tools/memory-tools
11
11
  */
12
- import type { MCPTool } from './types.js';
12
+ import { type MCPTool } from './types.js';
13
13
  export declare const DANGEROUS_KEY_PATTERN: RegExp;
14
14
  /**
15
15
  * #3570: the one key rule for every memory write path (MCP store, CLI store,
@@ -11,8 +11,10 @@
11
11
  */
12
12
  import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from 'fs';
13
13
  import { homedir } from 'os';
14
- import { join, resolve } from 'path';
14
+ import { basename, dirname, join, resolve } from 'path';
15
+ import { execFileSync } from 'node:child_process';
15
16
  import { createHash } from 'crypto';
17
+ import { getProjectCwd } from './types.js';
16
18
  import { validateIdentifier } from './validate-input.js';
17
19
  import { DEFAULT_SEARCH_THRESHOLD, nearMisses } from '../memory/search-defaults.js';
18
20
  // #1604: Align with memory-initializer.ts — single source of truth is .swarm/memory.db
@@ -146,7 +148,24 @@ function resolveProjectMemoryDir(claudeProjectsDir, projectPathOverride) {
146
148
  sources.push(projectPathOverride);
147
149
  }
148
150
  else {
149
- sources.push(process.cwd());
151
+ const project = getProjectCwd();
152
+ sources.push(project);
153
+ // Claude Code shares auto-memory across linked Git worktrees under the
154
+ // main checkout's project slug. Preserve the direct-path match first,
155
+ // then try the common Git directory's parent. Explicit overrides above
156
+ // remain authoritative, and non-Git projects need no Git dependency.
157
+ try {
158
+ const commonDir = execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {
159
+ cwd: project,
160
+ encoding: 'utf-8',
161
+ timeout: 1000,
162
+ windowsHide: true,
163
+ stdio: ['ignore', 'pipe', 'ignore'],
164
+ }).trim();
165
+ if (basename(commonDir) === '.git')
166
+ sources.push(dirname(resolve(project, commonDir)));
167
+ }
168
+ catch { /* Git unavailable or not a repository: use the project path */ }
150
169
  }
151
170
  for (const source of sources) {
152
171
  // Candidate 1: legacy POSIX hash — what shipped before #1883
@@ -1066,6 +1085,7 @@ export const memoryTools = [
1066
1085
  }
1067
1086
  let imported = 0;
1068
1087
  let skipped = 0;
1088
+ const importErrors = [];
1069
1089
  // #1791.8 — Claude Code's `~/.claude/projects/` accumulates historical
1070
1090
  // project_id directories (truncated forms, sandbox cwds, renamed
1071
1091
  // workspaces) that all contain copies of the same memory files. The
@@ -1105,7 +1125,7 @@ export const memoryTools = [
1105
1125
  // #1884 — sanitize key so memory_delete can later remove it. Without
1106
1126
  // this, dangerous chars from frontmatter `name` strand the key.
1107
1127
  const key = sanitizeMemoryKey(`claude:${memFile.project}:${name}`);
1108
- const stored = await storeEntry({ key, value: body, namespace: ns, generateEmbeddingFlag: true });
1128
+ const stored = await storeEntry({ key, value: body, namespace: ns, generateEmbeddingFlag: true, upsert: true });
1109
1129
  if (!stored.success)
1110
1130
  throw new Error(stored.error || `Failed to store ${key}`);
1111
1131
  imported++;
@@ -1120,15 +1140,19 @@ export const memoryTools = [
1120
1140
  // #1884 — sanitize so any dangerous chars in the heading don't
1121
1141
  // produce keys memory_delete will reject.
1122
1142
  const key = sanitizeMemoryKey(`claude:${memFile.project}:${name}:${sectionTitle.slice(0, 50)}`);
1123
- const stored = await storeEntry({ key, value: sectionBody, namespace: ns, generateEmbeddingFlag: true });
1143
+ const stored = await storeEntry({ key, value: sectionBody, namespace: ns, generateEmbeddingFlag: true, upsert: true });
1124
1144
  if (!stored.success)
1125
1145
  throw new Error(stored.error || `Failed to store ${key}`);
1126
1146
  imported++;
1127
1147
  }
1128
1148
  }
1129
1149
  }
1130
- catch {
1150
+ catch (err) {
1131
1151
  skipped++;
1152
+ // Say why a file was skipped instead of returning a bare failure (#4197).
1153
+ if (importErrors.length < 5) {
1154
+ importErrors.push(`${memFile.path}: ${err instanceof Error ? err.message : String(err)}`);
1155
+ }
1132
1156
  }
1133
1157
  }
1134
1158
  // AUDIT #3: report the embedding backend truthfully — a hash-fallback
@@ -1147,6 +1171,7 @@ export const memoryTools = [
1147
1171
  skipped,
1148
1172
  duplicatesSkipped,
1149
1173
  excludedByPattern,
1174
+ ...(importErrors.length > 0 ? { errors: importErrors } : {}),
1150
1175
  files: memoryFiles.length,
1151
1176
  projects: projects.size,
1152
1177
  namespace: ns,
@@ -399,7 +399,7 @@ export const metaharnessTools = [
399
399
  },
400
400
  // ───────────────────────────────────────────────────────────────────────
401
401
  // ADR-153 — @metaharness/darwin integration (3 tools).
402
- // Backed by the separate `@metaharness/darwin@~0.10.2` npm package, NOT
402
+ // Backed by the separate `@metaharness/darwin@~0.12.0` npm package, NOT
403
403
  // the umbrella `metaharness`. Plugin scripts shell out via _darwin.mjs.
404
404
  // Same {success, data, degraded, exitCode} contract.
405
405
  // ───────────────────────────────────────────────────────────────────────