@claude-flow/cli 3.56.8 → 3.56.10

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 (120) hide show
  1. package/.claude/helpers/.helpers-version +1 -1
  2. package/.claude/helpers/helpers.manifest.json +4 -4
  3. package/.claude/helpers/hook-handler.cjs +109 -23
  4. package/.claude/helpers/intelligence.cjs +51 -9
  5. package/.claude/helpers/router.cjs +0 -0
  6. package/.claude/skills/verification-quality/SKILL.md +14 -11
  7. package/README.md +1 -1
  8. package/catalog-manifest.json +2 -2
  9. package/dist/src/autopilot-state.d.ts +2 -0
  10. package/dist/src/autopilot-state.js +36 -8
  11. package/dist/src/command-resolution.d.ts +15 -0
  12. package/dist/src/command-resolution.js +25 -0
  13. package/dist/src/commands/agent.js +17 -17
  14. package/dist/src/commands/analyze.js +40 -29
  15. package/dist/src/commands/claims.js +6 -8
  16. package/dist/src/commands/daemon.js +86 -31
  17. package/dist/src/commands/memory.js +14 -2
  18. package/dist/src/commands/security-code-patterns.d.ts +2 -2
  19. package/dist/src/commands/security-code-patterns.js +61 -3
  20. package/dist/src/commands/security.d.ts +24 -0
  21. package/dist/src/commands/security.js +81 -35
  22. package/dist/src/commands/tui.d.ts +9 -0
  23. package/dist/src/commands/tui.js +29 -3
  24. package/dist/src/config/proven-config-refresh.d.ts +9 -0
  25. package/dist/src/config/proven-config-refresh.js +24 -3
  26. package/dist/src/funnel/local-signals.js +2 -1
  27. package/dist/src/index.js +6 -42
  28. package/dist/src/init/helpers-generator.js +109 -23
  29. package/dist/src/init/types.js +1 -1
  30. package/dist/src/mcp-tools/agent-execute-core.d.ts +2 -0
  31. package/dist/src/mcp-tools/agent-execute-core.js +15 -0
  32. package/dist/src/mcp-tools/agent-health-metrics.d.ts +22 -0
  33. package/dist/src/mcp-tools/agent-health-metrics.js +33 -0
  34. package/dist/src/mcp-tools/agent-tools.js +45 -22
  35. package/dist/src/mcp-tools/agentbbs-federation.d.ts +1 -1
  36. package/dist/src/mcp-tools/agentbbs-federation.js +7 -2
  37. package/dist/src/mcp-tools/agentdb-tools.js +25 -2
  38. package/dist/src/mcp-tools/aidefence-known-misses.d.ts +22 -0
  39. package/dist/src/mcp-tools/aidefence-known-misses.js +57 -0
  40. package/dist/src/mcp-tools/analyze-tools.js +10 -11
  41. package/dist/src/mcp-tools/autopilot-tools.js +2 -2
  42. package/dist/src/mcp-tools/browser-intent-tools.js +6 -2
  43. package/dist/src/mcp-tools/embeddings-tools.js +29 -7
  44. package/dist/src/mcp-tools/hooks-tools.js +4 -0
  45. package/dist/src/mcp-tools/memory-tools.js +70 -20
  46. package/dist/src/mcp-tools/neural-tools.js +28 -4
  47. package/dist/src/mcp-tools/ruvllm-tools.js +6 -0
  48. package/dist/src/mcp-tools/security-tools.js +55 -17
  49. package/dist/src/mcp-tools/workflow-tools.js +66 -17
  50. package/dist/src/memory/intelligence.d.ts +5 -1
  51. package/dist/src/memory/intelligence.js +105 -29
  52. package/dist/src/memory/memory-bridge.js +10 -3
  53. package/dist/src/memory/memory-initializer.js +2 -1
  54. package/dist/src/memory/search-defaults.d.ts +54 -0
  55. package/dist/src/memory/search-defaults.js +37 -0
  56. package/dist/src/memory/sona-optimizer.d.ts +28 -0
  57. package/dist/src/memory/sona-optimizer.js +59 -2
  58. package/dist/src/mods/command-registry/schema.d.ts +24 -24
  59. package/dist/src/parser.js +32 -22
  60. package/dist/src/production/monitoring.d.ts +1 -0
  61. package/dist/src/production/monitoring.js +19 -6
  62. package/dist/src/production/rate-limiter.js +5 -4
  63. package/dist/src/production/retry.js +3 -0
  64. package/dist/src/ruvector/agent-wasm.d.ts +10 -0
  65. package/dist/src/ruvector/agent-wasm.js +27 -1
  66. package/dist/src/ruvector/diff-classifier.d.ts +2 -4
  67. package/dist/src/ruvector/diff-classifier.js +202 -69
  68. package/dist/src/ruvector/ruvllm-wasm.d.ts +4 -0
  69. package/dist/src/ruvector/ruvllm-wasm.js +12 -1
  70. package/dist/src/services/config-file-manager.js +3 -3
  71. package/dist/src/services/policy-runtime.d.ts +1 -1
  72. package/dist/src/services/policy-runtime.js +7 -1
  73. package/dist/src/services/worker-daemon.d.ts +11 -0
  74. package/dist/src/services/worker-daemon.js +37 -0
  75. package/dist/src/transfer/store/discovery.js +16 -17
  76. package/dist/src/transfer/store/types.d.ts +4 -0
  77. package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
  78. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts +1 -0
  79. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts.map +1 -1
  80. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js +3 -1
  81. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js.map +1 -1
  82. package/node_modules/@claude-flow/codex/dist/index.d.ts +3 -3
  83. package/node_modules/@claude-flow/codex/dist/index.js +1 -1
  84. package/node_modules/@claude-flow/codex/package.json +1 -1
  85. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  86. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
  87. package/node_modules/@claude-flow/security/dist/policy/envelope.js +6 -6
  88. package/node_modules/@claude-flow/security/dist/policy/envelope.js.map +1 -1
  89. package/node_modules/@claude-flow/security/package.json +1 -1
  90. package/package.json +7 -7
  91. package/plugins/ruflo-console/dist/tui.mjs +162 -160
  92. package/plugins/ruflo-metaharness/.claude-flow/daemon-state.json +179 -0
  93. package/plugins/ruflo-metaharness/.claude-flow/daemon.pid +1 -0
  94. package/plugins/ruflo-metaharness/.claude-flow/logs/daemon.log +32 -0
  95. package/plugins/ruflo-metaharness/.claude-flow/metrics/backup.json +23 -0
  96. package/plugins/ruflo-metaharness/.claude-flow/metrics/codebase-map.json +11 -0
  97. package/plugins/ruflo-metaharness/.claude-flow/metrics/consolidation.json +16 -0
  98. package/plugins/ruflo-metaharness/.claude-flow/metrics/harness-loop.json +91 -0
  99. package/plugins/ruflo-metaharness/.claude-flow/metrics/performance.json +17 -0
  100. package/plugins/ruflo-metaharness/.claude-flow/metrics/security-audit.json +12 -0
  101. package/plugins/ruflo-metaharness/.claude-flow/metrics/test-gaps.json +8 -0
  102. package/plugins/ruflo-metaharness/.claude-flow/neural/patterns.json +2809 -0
  103. package/plugins/ruflo-metaharness/.claude-flow/neural/stats.json +6 -0
  104. package/plugins/ruflo-metaharness/.claude-flow/policy/state.json +11 -0
  105. package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +1 -1
  106. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db +0 -0
  107. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-shm +0 -0
  108. package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-wal +0 -0
  109. package/plugins/ruflo-metaharness/.swarm/backups/memory-2026-10-14T16-09-38-164Z.db +0 -0
  110. package/plugins/ruflo-metaharness/.swarm/backups/store-agentdb-memory.db-2026-10-14T16-09-38-166Z.db +0 -0
  111. package/plugins/ruflo-metaharness/.swarm/ewc-fisher.json +397 -0
  112. package/plugins/ruflo-metaharness/.swarm/memory.db +0 -0
  113. package/plugins/ruflo-metaharness/.swarm/memory.db-shm +0 -0
  114. package/plugins/ruflo-metaharness/.swarm/memory.db-wal +0 -0
  115. package/plugins/ruflo-metaharness/CHANGELOG.md +3 -0
  116. package/plugins/ruflo-metaharness/agentdb.rvf +0 -0
  117. package/plugins/ruflo-metaharness/agentdb.rvf.lock +0 -0
  118. package/plugins/ruflo-metaharness/hooks/screen.ts +10 -3
  119. package/plugins/ruflo-metaharness/ruvector.db +0 -0
  120. package/plugins/ruflo-metaharness/scripts/smoke.sh +4 -4
@@ -63,19 +63,19 @@ export declare const commandDefinitionSchema: z.ZodEffects<z.ZodObject<{
63
63
  path: z.ZodString;
64
64
  }, "strict", z.ZodTypeAny, {
65
65
  path: string;
66
- commit: string;
67
66
  repository: string;
67
+ commit: string;
68
68
  }, {
69
69
  path: string;
70
- commit: string;
71
70
  repository: string;
71
+ commit: string;
72
72
  }>;
73
73
  }, "strict", z.ZodTypeAny, {
74
74
  id: string;
75
75
  source: {
76
76
  path: string;
77
- commit: string;
78
77
  repository: string;
78
+ commit: string;
79
79
  };
80
80
  schemaVersion: 1;
81
81
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -100,8 +100,8 @@ export declare const commandDefinitionSchema: z.ZodEffects<z.ZodObject<{
100
100
  id: string;
101
101
  source: {
102
102
  path: string;
103
- commit: string;
104
103
  repository: string;
104
+ commit: string;
105
105
  };
106
106
  schemaVersion: 1;
107
107
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -126,8 +126,8 @@ export declare const commandDefinitionSchema: z.ZodEffects<z.ZodObject<{
126
126
  id: string;
127
127
  source: {
128
128
  path: string;
129
- commit: string;
130
129
  repository: string;
130
+ commit: string;
131
131
  };
132
132
  schemaVersion: 1;
133
133
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -152,8 +152,8 @@ export declare const commandDefinitionSchema: z.ZodEffects<z.ZodObject<{
152
152
  id: string;
153
153
  source: {
154
154
  path: string;
155
- commit: string;
156
155
  repository: string;
156
+ commit: string;
157
157
  };
158
158
  schemaVersion: 1;
159
159
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -244,19 +244,19 @@ export declare const catalogEntrySchema: z.ZodObject<{
244
244
  path: z.ZodString;
245
245
  }, "strict", z.ZodTypeAny, {
246
246
  path: string;
247
- commit: string;
248
247
  repository: string;
248
+ commit: string;
249
249
  }, {
250
250
  path: string;
251
- commit: string;
252
251
  repository: string;
252
+ commit: string;
253
253
  }>;
254
254
  }, "strict", z.ZodTypeAny, {
255
255
  id: string;
256
256
  source: {
257
257
  path: string;
258
- commit: string;
259
258
  repository: string;
259
+ commit: string;
260
260
  };
261
261
  schemaVersion: 1;
262
262
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -281,8 +281,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
281
281
  id: string;
282
282
  source: {
283
283
  path: string;
284
- commit: string;
285
284
  repository: string;
285
+ commit: string;
286
286
  };
287
287
  schemaVersion: 1;
288
288
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -307,8 +307,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
307
307
  id: string;
308
308
  source: {
309
309
  path: string;
310
- commit: string;
311
310
  repository: string;
311
+ commit: string;
312
312
  };
313
313
  schemaVersion: 1;
314
314
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -333,8 +333,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
333
333
  id: string;
334
334
  source: {
335
335
  path: string;
336
- commit: string;
337
336
  repository: string;
337
+ commit: string;
338
338
  };
339
339
  schemaVersion: 1;
340
340
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -404,8 +404,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
404
404
  id: string;
405
405
  source: {
406
406
  path: string;
407
- commit: string;
408
407
  repository: string;
408
+ commit: string;
409
409
  };
410
410
  schemaVersion: 1;
411
411
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -445,8 +445,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
445
445
  id: string;
446
446
  source: {
447
447
  path: string;
448
- commit: string;
449
448
  repository: string;
449
+ commit: string;
450
450
  };
451
451
  schemaVersion: 1;
452
452
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -510,19 +510,19 @@ export declare const commandCatalogSchema: z.ZodObject<{
510
510
  path: z.ZodString;
511
511
  }, "strict", z.ZodTypeAny, {
512
512
  path: string;
513
- commit: string;
514
513
  repository: string;
514
+ commit: string;
515
515
  }, {
516
516
  path: string;
517
- commit: string;
518
517
  repository: string;
518
+ commit: string;
519
519
  }>;
520
520
  }, "strict", z.ZodTypeAny, {
521
521
  id: string;
522
522
  source: {
523
523
  path: string;
524
- commit: string;
525
524
  repository: string;
525
+ commit: string;
526
526
  };
527
527
  schemaVersion: 1;
528
528
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -547,8 +547,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
547
547
  id: string;
548
548
  source: {
549
549
  path: string;
550
- commit: string;
551
550
  repository: string;
551
+ commit: string;
552
552
  };
553
553
  schemaVersion: 1;
554
554
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -573,8 +573,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
573
573
  id: string;
574
574
  source: {
575
575
  path: string;
576
- commit: string;
577
576
  repository: string;
577
+ commit: string;
578
578
  };
579
579
  schemaVersion: 1;
580
580
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -599,8 +599,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
599
599
  id: string;
600
600
  source: {
601
601
  path: string;
602
- commit: string;
603
602
  repository: string;
603
+ commit: string;
604
604
  };
605
605
  schemaVersion: 1;
606
606
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -670,8 +670,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
670
670
  id: string;
671
671
  source: {
672
672
  path: string;
673
- commit: string;
674
673
  repository: string;
674
+ commit: string;
675
675
  };
676
676
  schemaVersion: 1;
677
677
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -711,8 +711,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
711
711
  id: string;
712
712
  source: {
713
713
  path: string;
714
- commit: string;
715
714
  repository: string;
715
+ commit: string;
716
716
  };
717
717
  schemaVersion: 1;
718
718
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -754,8 +754,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
754
754
  id: string;
755
755
  source: {
756
756
  path: string;
757
- commit: string;
758
757
  repository: string;
758
+ commit: string;
759
759
  };
760
760
  schemaVersion: 1;
761
761
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -800,8 +800,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
800
800
  id: string;
801
801
  source: {
802
802
  path: string;
803
- commit: string;
804
803
  repository: string;
804
+ commit: string;
805
805
  };
806
806
  schemaVersion: 1;
807
807
  kind: "help" | "query" | "prompt" | "workflow" | "mutation";
@@ -134,7 +134,6 @@ export class CommandParser {
134
134
  // command, because that's what caused `daemon start` to resolve as `start`
135
135
  // with `daemon` left as a positional.
136
136
  let resolvedCmd;
137
- let resolvedSub;
138
137
  const resolvedCommands = [];
139
138
  let sawFirstPositional = false;
140
139
  for (let index = 0; index < args.length; index++) {
@@ -173,16 +172,16 @@ export class CommandParser {
173
172
  const child = parent.subcommands.find(sc => sc.name === arg || sc.aliases?.includes(arg));
174
173
  if (child) {
175
174
  resolvedCommands.push(child);
176
- resolvedSub ??= child;
177
175
  continue;
178
176
  }
179
177
  }
180
178
  // A positional that is not the next subcommand ends the command path.
181
179
  break;
182
180
  }
183
- const { aliases, booleanFlags, stringFlags } = this.getFlagScope(resolvedCommands);
181
+ const { aliases, booleanFlags, stringFlags, arrayFlags } = this.getFlagScope(resolvedCommands);
184
182
  let i = 0;
185
183
  let parsingFlags = true;
184
+ let commandSlotAvailable = true;
186
185
  while (i < args.length) {
187
186
  const arg = args[i];
188
187
  // Check for end of flags marker
@@ -194,8 +193,17 @@ export class CommandParser {
194
193
  // Handle flags
195
194
  if (parsingFlags && arg.startsWith('-')) {
196
195
  const parseResult = this.parseFlag(args, i, aliases, booleanFlags, stringFlags);
196
+ // Array declarations retain text and accumulate repeated occurrences.
197
+ for (const key of arrayFlags) {
198
+ const value = parseResult.flags[key];
199
+ if (value !== undefined && value !== true && value !== false) {
200
+ const previous = result.flags[key];
201
+ parseResult.flags[key] = [...(Array.isArray(previous) ? previous : []), String(value)];
202
+ }
203
+ }
197
204
  // Apply to result flags
198
- Object.assign(result.flags, parseResult.flags);
205
+ const { _: ignoredPositionals, ...parsedFlags } = parseResult.flags;
206
+ Object.assign(result.flags, parsedFlags);
199
207
  i = parseResult.nextIndex;
200
208
  continue;
201
209
  }
@@ -203,7 +211,9 @@ export class CommandParser {
203
211
  // Fix for #1596: treat lazy command names as commands here too so that
204
212
  // downstream dispatch sees `commandPath = ['daemon', 'start']` instead of
205
213
  // `commandPath = ['start'], positional = ['daemon']`.
206
- if (result.command.length === 0 && this.isKnownCommandName(arg)) {
214
+ const isCommandSlot = commandSlotAvailable && parsingFlags;
215
+ commandSlotAvailable = false;
216
+ if (isCommandSlot && this.isKnownCommandName(arg)) {
207
217
  // This is a command
208
218
  result.command.push(arg);
209
219
  // Check for subcommand (level 1) — only possible for sync commands
@@ -248,7 +258,7 @@ export class CommandParser {
248
258
  // `default: true` silently dropped and reached the action handler as
249
259
  // `undefined`. That trapped `memory store --upsert` and every other
250
260
  // subcommand that leaned on a per-flag default.
251
- this.applyDefaults(result.flags, resolvedCmd, resolvedSub);
261
+ this.applyDefaults(result.flags, resolvedCommands);
252
262
  return result;
253
263
  }
254
264
  parseFlag(args, index, aliases, booleanFlags, stringFlags) {
@@ -472,11 +482,18 @@ export class CommandParser {
472
482
  aliases[option.short] = option.name;
473
483
  }
474
484
  }
485
+ const arrayFlags = new Set((this.options.arrayFlags ?? []).map(flag => this.normalizeKey(flag)));
486
+ for (const flag of arrayFlags)
487
+ stringFlags.add(flag);
475
488
  const layers = [this.globalOptions, ...commands.map(command => command.options ?? [])];
476
489
  for (const options of layers) {
477
490
  for (const option of options) {
478
491
  const key = this.normalizeKey(option.name);
479
- if (option.type === 'string')
492
+ if (option.type === 'array')
493
+ arrayFlags.add(key);
494
+ else if (option.type)
495
+ arrayFlags.delete(key);
496
+ if (option.type === 'string' || option.type === 'array')
480
497
  stringFlags.add(key);
481
498
  else if (option.type)
482
499
  stringFlags.delete(key);
@@ -488,7 +505,7 @@ export class CommandParser {
488
505
  }
489
506
  for (const flag of stringFlags)
490
507
  booleanFlags.delete(flag);
491
- return { aliases, booleanFlags, stringFlags };
508
+ return { aliases, booleanFlags, stringFlags, arrayFlags };
492
509
  }
493
510
  getBooleanFlags() {
494
511
  const flags = new Set();
@@ -526,23 +543,16 @@ export class CommandParser {
526
543
  }
527
544
  return flags;
528
545
  }
529
- applyDefaults(flags, command, subcommand) {
530
- // #2775: apply defaults from globals AND the resolved command/subcommand.
531
- // Subcommand > command > global (later writes lose to earlier — because
532
- // we only set when `undefined`, so the FIRST option definition that
533
- // supplies a default wins; walk narrow-to-broad so subcommand options
534
- // apply before broader ones do).
535
- const layers = [];
536
- if (subcommand?.options)
537
- layers.push(subcommand.options);
538
- if (command?.options)
539
- layers.push(command.options);
546
+ applyDefaults(flags, commands) {
547
+ // Walk every resolved command from narrow to broad so nested defaults
548
+ // have the same precedence as their declared flag types.
549
+ const layers = [...commands].reverse().map(command => command.options ?? []);
540
550
  layers.push(this.globalOptions);
541
551
  for (const layer of layers) {
542
552
  for (const opt of layer) {
543
553
  const key = this.normalizeKey(opt.name);
544
554
  if (flags[key] === undefined && opt.default !== undefined) {
545
- flags[key] = opt.default;
555
+ flags[key] = (Array.isArray(opt.default) ? [...opt.default] : opt.default);
546
556
  }
547
557
  }
548
558
  }
@@ -551,7 +561,7 @@ export class CommandParser {
551
561
  for (const [key, value] of Object.entries(this.options.defaults)) {
552
562
  const normalizedKey = this.normalizeKey(key);
553
563
  if (flags[normalizedKey] === undefined) {
554
- flags[normalizedKey] = value;
564
+ flags[normalizedKey] = (Array.isArray(value) ? [...value] : value);
555
565
  }
556
566
  }
557
567
  }
@@ -572,7 +582,7 @@ export class CommandParser {
572
582
  // followed by another flag) is parsed as boolean `true`. Commands then treat `true` as
573
583
  // the value: `hooks route --task` crashed with "task.trim is not a function" and
574
584
  // `memory retrieve --key` looked up the key "true". Report it instead.
575
- if ((opt.type === 'string' || opt.type === 'number') && flags[key] === true) {
585
+ if ((opt.type === 'string' || opt.type === 'number' || opt.type === 'array') && flags[key] === true) {
576
586
  errors.push(`Option --${opt.name} needs a value`);
577
587
  }
578
588
  // Check choices
@@ -71,6 +71,7 @@ export declare class MonitoringHooks {
71
71
  private healthStatus;
72
72
  private startTime;
73
73
  private activeRequests;
74
+ private requestGeneration;
74
75
  private requestCount;
75
76
  private errorCount;
76
77
  private healthChecks;
@@ -37,6 +37,7 @@ export class MonitoringHooks {
37
37
  healthStatus;
38
38
  startTime = Date.now();
39
39
  activeRequests = 0;
40
+ requestGeneration = 0;
40
41
  requestCount = 0;
41
42
  errorCount = 0;
42
43
  healthChecks = new Map();
@@ -101,9 +102,14 @@ export class MonitoringHooks {
101
102
  this.activeRequests++;
102
103
  this.requestCount++;
103
104
  const startTime = Date.now();
105
+ const generation = this.requestGeneration;
106
+ let completed = false;
104
107
  this.counter('request_started', 1, { requestId });
105
108
  // Return end function
106
109
  return () => {
110
+ if (completed || generation !== this.requestGeneration)
111
+ return;
112
+ completed = true;
107
113
  this.activeRequests--;
108
114
  const duration = Date.now() - startTime;
109
115
  this.responseTimes.push(duration);
@@ -156,7 +162,7 @@ export class MonitoringHooks {
156
162
  catch (error) {
157
163
  checks[name] = {
158
164
  status: 'unhealthy',
159
- message: error.message,
165
+ message: error instanceof Error ? error.message : String(error),
160
166
  lastCheck: Date.now(),
161
167
  responseTimeMs: Date.now() - startTime,
162
168
  };
@@ -168,13 +174,13 @@ export class MonitoringHooks {
168
174
  checks,
169
175
  timestamp: Date.now(),
170
176
  };
171
- return this.healthStatus;
177
+ return structuredClone(this.healthStatus);
172
178
  }
173
179
  /**
174
180
  * Get current health status
175
181
  */
176
182
  getHealthStatus() {
177
- return this.healthStatus;
183
+ return structuredClone(this.healthStatus);
178
184
  }
179
185
  // ============================================================================
180
186
  // Performance Metrics
@@ -217,7 +223,7 @@ export class MonitoringHooks {
217
223
  if (level) {
218
224
  filtered = filtered.filter(a => a.level === level);
219
225
  }
220
- return filtered;
226
+ return filtered.map(alert => ({ ...alert }));
221
227
  }
222
228
  /**
223
229
  * Acknowledge an alert
@@ -248,7 +254,7 @@ export class MonitoringHooks {
248
254
  if (since) {
249
255
  filtered = filtered.filter(m => m.timestamp >= since);
250
256
  }
251
- return filtered;
257
+ return filtered.map(metric => ({ ...metric, labels: { ...metric.labels } }));
252
258
  }
253
259
  /**
254
260
  * Get all metrics summary
@@ -278,6 +284,7 @@ export class MonitoringHooks {
278
284
  * Reset all metrics
279
285
  */
280
286
  reset() {
287
+ this.requestGeneration++;
281
288
  this.metrics = [];
282
289
  this.responseTimes = [];
283
290
  this.alerts = [];
@@ -308,7 +315,13 @@ export class MonitoringHooks {
308
315
  const recentAlert = this.alerts.find(a => a.metric === name &&
309
316
  !a.acknowledged &&
310
317
  Date.now() - a.timestamp < 60000);
311
- if (!recentAlert) {
318
+ if (recentAlert && level === 'critical' && recentAlert.level !== 'critical') {
319
+ Object.assign(recentAlert, {
320
+ level, value, threshold, timestamp: Date.now(),
321
+ message: `${name} exceeded ${level} threshold: ${value} >= ${threshold}`,
322
+ });
323
+ }
324
+ else if (!recentAlert) {
312
325
  this.alerts.push({
313
326
  id: `alert_${Date.now()}_${Math.random().toString(36).substring(7)}`,
314
327
  level,
@@ -90,6 +90,7 @@ export class RateLimiter {
90
90
  */
91
91
  getStatus(operation, userId) {
92
92
  const limits = this.getLimits(operation);
93
+ const capacity = Math.floor(limits.maxRequests * this.config.burstMultiplier);
93
94
  const bucketKey = userId && this.config.perUserLimits
94
95
  ? `${operation}:${userId}`
95
96
  : `global:${operation}`;
@@ -98,8 +99,8 @@ export class RateLimiter {
98
99
  if (!bucket) {
99
100
  return {
100
101
  current: 0,
101
- limit: limits.maxRequests,
102
- remaining: limits.maxRequests,
102
+ limit: capacity,
103
+ remaining: capacity,
103
104
  resetAt: now + limits.windowMs,
104
105
  };
105
106
  }
@@ -107,8 +108,8 @@ export class RateLimiter {
107
108
  const validRequests = bucket.requests.filter(t => t > now - limits.windowMs);
108
109
  return {
109
110
  current: validRequests.length,
110
- limit: limits.maxRequests,
111
- remaining: Math.max(0, limits.maxRequests - validRequests.length),
111
+ limit: capacity,
112
+ remaining: Math.max(0, capacity - validRequests.length),
112
113
  resetAt: validRequests.length > 0
113
114
  ? validRequests[0] + limits.windowMs
114
115
  : now + limits.windowMs,
@@ -74,6 +74,9 @@ function fibonacci(n) {
74
74
  * Check if an error should be retried
75
75
  */
76
76
  function shouldRetryError(error, attempt, config) {
77
+ // Exhaustion always takes precedence over custom retry policies.
78
+ if (attempt >= config.maxAttempts)
79
+ return false;
77
80
  // Check custom retry function
78
81
  if (config.shouldRetry) {
79
82
  return config.shouldRetry(error, attempt);
@@ -70,6 +70,16 @@ export interface ToolResult {
70
70
  success: boolean;
71
71
  output: string;
72
72
  }
73
+ /** Shown wherever the optional @ruvector/rvagent-wasm package cannot be loaded. */
74
+ export declare const AGENT_WASM_NOT_INSTALLED_MESSAGE: string;
75
+ /**
76
+ * True when err is the module-resolution failure for @ruvector/rvagent-wasm itself.
77
+ * Decided by the error code OR its text, because wrappers (loaders, test harnesses)
78
+ * can drop `code` while keeping the message.
79
+ */
80
+ export declare function isMissingAgentWasm(err: unknown): boolean;
81
+ /** The error initAgentWasm() throws for a load failure: "not installed" with the fix, or a genuine init failure. */
82
+ export declare function agentWasmLoadError(err: unknown): Error;
73
83
  /**
74
84
  * Check if @ruvector/rvagent-wasm is installed and loadable.
75
85
  */
@@ -14,6 +14,30 @@ import { readFileSync } from 'node:fs';
14
14
  import { createRequire } from 'node:module';
15
15
  // ── WASM Module Detection & Init ─────────────────────────────
16
16
  let _wasmReady = false;
17
+ /** Shown wherever the optional @ruvector/rvagent-wasm package cannot be loaded. */
18
+ export const AGENT_WASM_NOT_INSTALLED_MESSAGE = '@ruvector/rvagent-wasm is not installed.\n' +
19
+ 'Install it with: npm install @ruvector/rvagent-wasm (or npm install -g @ruvector/rvagent-wasm for a global ruflo)';
20
+ /**
21
+ * True when err is the module-resolution failure for @ruvector/rvagent-wasm itself.
22
+ * Decided by the error code OR its text, because wrappers (loaders, test harnesses)
23
+ * can drop `code` while keeping the message.
24
+ */
25
+ export function isMissingAgentWasm(err) {
26
+ const e = err;
27
+ const code = typeof e?.code === 'string' ? e.code : '';
28
+ const message = typeof e?.message === 'string' ? e.message : String(err);
29
+ if (!message.includes('@ruvector/rvagent-wasm'))
30
+ return false;
31
+ return (code === 'ERR_MODULE_NOT_FOUND' ||
32
+ code === 'MODULE_NOT_FOUND' ||
33
+ /ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND|Cannot find (package|module)/.test(message));
34
+ }
35
+ /** The error initAgentWasm() throws for a load failure: "not installed" with the fix, or a genuine init failure. */
36
+ export function agentWasmLoadError(err) {
37
+ return isMissingAgentWasm(err)
38
+ ? new Error(AGENT_WASM_NOT_INSTALLED_MESSAGE)
39
+ : new Error(`Failed to initialize @ruvector/rvagent-wasm: ${err}`);
40
+ }
17
41
  /**
18
42
  * Check if @ruvector/rvagent-wasm is installed and loadable.
19
43
  */
@@ -43,7 +67,9 @@ export async function initAgentWasm() {
43
67
  _wasmReady = true;
44
68
  }
45
69
  catch (err) {
46
- throw new Error(`Failed to initialize @ruvector/rvagent-wasm: ${err}`);
70
+ // #3979 item 1: a missing optional package is "not installed", with the fix,
71
+ // not a raw ERR_MODULE_NOT_FOUND trace dressed up as an initialization failure.
72
+ throw agentWasmLoadError(err);
47
73
  }
48
74
  }
49
75
  // ── Agent Registry ───────────────────────────────────────────
@@ -145,10 +145,8 @@ export declare function assessFileRisk(file: DiffFile): FileRisk;
145
145
  * Assess overall risk from files and file risks
146
146
  */
147
147
  export declare function assessOverallRisk(files: DiffFile[], fileRisks: FileRisk[]): OverallRisk;
148
- /**
149
- * Classify a diff based on files (uses singleton classifier)
150
- */
151
- export declare function classifyDiff(files: DiffFile[]): DiffClassification;
148
+ /** Classify file metadata with the actual patch and, for one-commit ranges, its subject. */
149
+ export declare function classifyDiff(files: DiffFile[], patch?: string, commitSubject?: string): DiffClassification;
152
150
  /**
153
151
  * Suggest reviewers based on files and risks
154
152
  */