claude-flow 3.54.1 → 3.55.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 (68) hide show
  1. package/.claude/.proven-config-version +1 -0
  2. package/.claude/proven-config.json +42 -0
  3. package/node_modules/@claude-flow/mcp/dist/connection-pool.d.ts.map +1 -1
  4. package/node_modules/@claude-flow/mcp/dist/connection-pool.js +5 -2
  5. package/node_modules/@claude-flow/mcp/dist/connection-pool.js.map +1 -1
  6. package/node_modules/@claude-flow/mcp/dist/transport/http.d.ts +7 -1
  7. package/node_modules/@claude-flow/mcp/dist/transport/http.d.ts.map +1 -1
  8. package/node_modules/@claude-flow/mcp/dist/transport/http.js +60 -47
  9. package/node_modules/@claude-flow/mcp/dist/transport/http.js.map +1 -1
  10. package/node_modules/@claude-flow/mcp/package.json +1 -1
  11. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js +1 -1
  12. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js.map +1 -1
  13. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  14. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts +3 -0
  15. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts.map +1 -1
  16. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js +4 -1
  17. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js.map +1 -1
  18. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.d.ts.map +1 -1
  19. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js +1 -0
  20. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js.map +1 -1
  21. package/node_modules/@claude-flow/plugin-agent-federation/package.json +1 -1
  22. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts +11 -1
  23. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts.map +1 -1
  24. package/node_modules/@claude-flow/security/dist/policy/engine.js +19 -3
  25. package/node_modules/@claude-flow/security/dist/policy/engine.js.map +1 -1
  26. package/node_modules/@claude-flow/security/dist/policy/types.d.ts +4 -2
  27. package/node_modules/@claude-flow/security/dist/policy/types.d.ts.map +1 -1
  28. package/node_modules/@claude-flow/security/package.json +1 -1
  29. package/package.json +5 -5
  30. package/v3/@claude-flow/cli/bin/cli.js +1 -1
  31. package/v3/@claude-flow/cli/bin/mcp-server.js +1 -1
  32. package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
  33. package/v3/@claude-flow/cli/dist/src/commands/autopilot.js +2 -2
  34. package/v3/@claude-flow/cli/dist/src/commands/daemon.js +21 -1
  35. package/v3/@claude-flow/cli/dist/src/commands/hive-mind.js +7 -0
  36. package/v3/@claude-flow/cli/dist/src/commands/mcp.js +35 -1
  37. package/v3/@claude-flow/cli/dist/src/commands/policy.js +10 -2
  38. package/v3/@claude-flow/cli/dist/src/mcp-server.d.ts +33 -0
  39. package/v3/@claude-flow/cli/dist/src/mcp-server.js +96 -4
  40. package/v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.d.ts +2 -4
  41. package/v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.js +214 -40
  42. package/v3/@claude-flow/cli/dist/src/missions/schemas.d.ts +125 -125
  43. package/v3/@claude-flow/cli/dist/src/mods/command-registry/schema.d.ts +199 -199
  44. package/v3/@claude-flow/cli/dist/src/parser.d.ts +3 -0
  45. package/v3/@claude-flow/cli/dist/src/parser.js +64 -13
  46. package/v3/@claude-flow/cli/dist/src/production/retry.js +1 -1
  47. package/v3/@claude-flow/cli/dist/src/services/bounded-worker-pool.js +3 -0
  48. package/v3/@claude-flow/cli/dist/src/services/config-file-manager.d.ts +3 -0
  49. package/v3/@claude-flow/cli/dist/src/services/config-file-manager.js +24 -7
  50. package/v3/@claude-flow/cli/dist/src/services/policy-ledger-anchor.d.ts +42 -0
  51. package/v3/@claude-flow/cli/dist/src/services/policy-ledger-anchor.js +163 -0
  52. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.d.ts +11 -5
  53. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.js +70 -15
  54. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +1 -0
  55. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +12 -0
  56. package/v3/@claude-flow/cli/dist/src/services/worker-queue.js +11 -2
  57. package/v3/@claude-flow/cli/package.json +7 -7
  58. package/v3/@claude-flow/shared/dist/events/event-store-pagination.test.d.ts +2 -0
  59. package/v3/@claude-flow/shared/dist/events/event-store-pagination.test.js +32 -0
  60. package/v3/@claude-flow/shared/dist/events/event-store.js +6 -2
  61. package/v3/@claude-flow/shared/dist/mcp/connection-pool.js +5 -2
  62. package/v3/@claude-flow/shared/dist/resilience/bulkhead-sync-throw.test.d.ts +2 -0
  63. package/v3/@claude-flow/shared/dist/resilience/bulkhead-sync-throw.test.js +33 -0
  64. package/v3/@claude-flow/shared/dist/resilience/bulkhead.js +2 -1
  65. package/v3/@claude-flow/shared/dist/resilience/retry-timeout-cleanup.test.d.ts +2 -0
  66. package/v3/@claude-flow/shared/dist/resilience/retry-timeout-cleanup.test.js +38 -0
  67. package/v3/@claude-flow/shared/dist/resilience/retry.js +9 -2
  68. package/v3/@claude-flow/shared/package.json +1 -1
@@ -193,6 +193,7 @@ export class WorkerDaemon extends EventEmitter {
193
193
  ?? fileConfig.aiWorkersEnabled
194
194
  ?? (process.env.RUFLO_DAEMON_AI_WORKERS === '1'),
195
195
  workers: config?.workers ?? DEFAULT_WORKERS,
196
+ enabledWorkers: config?.enabledWorkers,
196
197
  };
197
198
  // #2935 — deferred from readDaemonConfigFromFile(): this.config (and
198
199
  // therefore this.config.logDir) doesn't exist until the assignment
@@ -700,6 +701,17 @@ export class WorkerDaemon extends EventEmitter {
700
701
  // Ignore parse errors, start fresh
701
702
  }
702
703
  }
704
+ // #3547 (#1968 follow-up): an explicit `--workers` selection wins over
705
+ // both DEFAULT_WORKERS and whatever daemon-state.json just restored
706
+ // above — otherwise `daemon start --workers map,audit` always ran the
707
+ // full default set (or a stale saved selection) because nothing ever
708
+ // applied the requested list to `enabled`.
709
+ if (this.config.enabledWorkers) {
710
+ const selected = new Set(this.config.enabledWorkers);
711
+ for (const workerConfig of this.config.workers) {
712
+ workerConfig.enabled = selected.has(workerConfig.type);
713
+ }
714
+ }
703
715
  // Initialize any missing workers
704
716
  for (const workerConfig of this.config.workers) {
705
717
  if (!this.workers.has(workerConfig.type)) {
@@ -233,8 +233,9 @@ export class WorkerQueue extends EventEmitter {
233
233
  // Check queues in priority order
234
234
  for (const workerType of workerTypes) {
235
235
  const queueName = this.getQueueName(workerType);
236
- const taskId = this.store.popFromQueue(queueName);
237
- if (taskId) {
236
+ let taskId;
237
+ // Cancelled or otherwise stale entries do not exhaust this worker type.
238
+ while ((taskId = this.store.popFromQueue(queueName)) !== null) {
238
239
  const task = this.store.getTask(taskId);
239
240
  if (task && task.status === 'pending') {
240
241
  task.status = 'processing';
@@ -258,6 +259,10 @@ export class WorkerQueue extends EventEmitter {
258
259
  this.emit('warning', { message: `Task ${taskId} not found for completion` });
259
260
  return;
260
261
  }
262
+ // Late or duplicate outcomes must not rewrite a settled task.
263
+ if (['completed', 'failed', 'timeout', 'cancelled'].includes(task.status)) {
264
+ return;
265
+ }
261
266
  task.status = 'completed';
262
267
  task.completedAt = new Date();
263
268
  task.result = result;
@@ -276,6 +281,10 @@ export class WorkerQueue extends EventEmitter {
276
281
  this.emit('warning', { message: `Task ${taskId} not found for failure` });
277
282
  return;
278
283
  }
284
+ // Late or duplicate outcomes must not rewrite a settled task.
285
+ if (['completed', 'failed', 'timeout', 'cancelled'].includes(task.status)) {
286
+ return;
287
+ }
279
288
  this.processingTasks.delete(taskId);
280
289
  // Check if we should retry
281
290
  if (retryable && task.retryCount < task.maxRetries) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.54.1",
3
+ "version": "3.55.0",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -100,11 +100,11 @@
100
100
  "dependencies": {
101
101
  "@claude-flow/cli-core": "3.7.0",
102
102
  "@claude-flow/codex": "3.0.3",
103
- "@claude-flow/mcp": "3.0.0",
103
+ "@claude-flow/mcp": "3.1.0",
104
104
  "@claude-flow/neural": "3.0.0",
105
- "@claude-flow/plugin-agent-federation": "1.0.0",
106
- "@claude-flow/security": "3.0.1",
107
- "@claude-flow/shared": "3.0.1",
105
+ "@claude-flow/plugin-agent-federation": "1.0.1",
106
+ "@claude-flow/security": "3.0.2",
107
+ "@claude-flow/shared": "3.0.2",
108
108
  "@iarna/toml": "^2.2.5",
109
109
  "@noble/ed25519": "2.3.0",
110
110
  "@ruvector/rabitq-wasm": "0.1.0",
@@ -125,11 +125,11 @@
125
125
  "ws": "^8.21.0",
126
126
  "yaml": "^2.8.0",
127
127
  "zod": "^3.22.0",
128
- "@claude-flow/memory": "3.0.0"
128
+ "@claude-flow/memory": "3.0.1"
129
129
  },
130
130
  "optionalDependencies": {
131
131
  "@agntcy/slim-bindings": "2.0.0-alpha.5",
132
- "@claude-flow/memory": "3.0.0",
132
+ "@claude-flow/memory": "3.0.1",
133
133
  "@metaharness/darwin": "~0.10.2",
134
134
  "@metaharness/flywheel": "~0.1.10",
135
135
  "@metaharness/radio": "~0.1.0",
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-store-pagination.test.d.ts.map
@@ -0,0 +1,32 @@
1
+ import { beforeEach, afterEach, describe, it, expect } from 'vitest';
2
+ import { EventStore } from './event-store.js';
3
+ import { createAgentSpawnedEvent } from './domain-events.js';
4
+ describe('SQLite event query pagination', () => {
5
+ let store;
6
+ beforeEach(async () => {
7
+ store = new EventStore({
8
+ databasePath: ':memory:',
9
+ autoPersistInterval: 0,
10
+ });
11
+ await store.initialize();
12
+ for (let i = 0; i < 3; i++) {
13
+ const event = createAgentSpawnedEvent(`agent-${i}`, 'coder', 'core', []);
14
+ event.timestamp = 100 + i;
15
+ await store.append(event);
16
+ }
17
+ });
18
+ afterEach(async () => {
19
+ await store.shutdown();
20
+ });
21
+ it('supports offsets without a caller-specified limit', async () => {
22
+ expect((await store.query({ offset: 1 })).map((event) => event.aggregateId)).toEqual(['agent-1', 'agent-2']);
23
+ });
24
+ it('returns no rows for an explicit zero limit', async () => {
25
+ expect(await store.query({ limit: 0 })).toEqual([]);
26
+ expect(await store.query({ limit: 0, offset: 1 })).toEqual([]);
27
+ });
28
+ it('retains bounded page ordering', async () => {
29
+ expect((await store.query({ limit: 1, offset: 1 })).map((event) => event.aggregateId)).toEqual(['agent-1']);
30
+ });
31
+ });
32
+ //# sourceMappingURL=event-store-pagination.test.js.map
@@ -225,11 +225,15 @@ export class EventStore extends EventEmitter {
225
225
  // Order by timestamp
226
226
  sql += ' ORDER BY timestamp ASC';
227
227
  // Pagination
228
- if (filter.limit) {
228
+ if (filter.limit !== undefined) {
229
229
  sql += ' LIMIT ?';
230
230
  params.push(filter.limit);
231
231
  }
232
- if (filter.offset) {
232
+ else if (filter.offset !== undefined) {
233
+ // SQLite requires LIMIT before OFFSET; -1 means no upper bound.
234
+ sql += ' LIMIT -1';
235
+ }
236
+ if (filter.offset !== undefined) {
233
237
  sql += ' OFFSET ?';
234
238
  params.push(filter.offset);
235
239
  }
@@ -119,9 +119,12 @@ export class ConnectionPool extends EventEmitter {
119
119
  /**
120
120
  * Create a new connection
121
121
  */
122
- async createConnection() {
122
+ async createConnection(reserved = false) {
123
123
  const id = `conn-${++this.connectionCounter}-${Date.now()}`;
124
124
  const connection = new ManagedConnection(id, this.transportType);
125
+ // Reserve before exposing it in the map or yielding to another acquirer.
126
+ if (reserved)
127
+ connection.state = 'busy';
125
128
  this.connections.set(id, connection);
126
129
  this.stats.totalCreated++;
127
130
  this.emit('pool:connection:created', { connectionId: id });
@@ -149,7 +152,7 @@ export class ConnectionPool extends EventEmitter {
149
152
  }
150
153
  // Create new connection if under limit
151
154
  if (this.connections.size < this.config.maxConnections) {
152
- const connection = await this.createConnection();
155
+ const connection = await this.createConnection(true);
153
156
  connection.acquire();
154
157
  this.stats.totalAcquired++;
155
158
  this.recordAcquireTime(startTime);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bulkhead-sync-throw.test.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { Bulkhead } from './bulkhead.js';
3
+ describe('queued bulkhead failures', () => {
4
+ it('rejects the throwing task and preserves the previous result and remaining capacity', async () => {
5
+ const bulkhead = new Bulkhead({
6
+ name: 'test',
7
+ maxConcurrent: 1,
8
+ maxQueue: 2,
9
+ queueTimeout: 100,
10
+ });
11
+ let release;
12
+ const first = bulkhead.execute(() => new Promise((resolve) => {
13
+ release = resolve;
14
+ }));
15
+ const failure = new Error('synchronous callback failure');
16
+ const second = bulkhead.execute(() => {
17
+ throw failure;
18
+ });
19
+ const secondResult = second.catch((error) => error);
20
+ const third = bulkhead.execute(async () => 'third');
21
+ release('first');
22
+ await expect(first).resolves.toBe('first');
23
+ expect(await secondResult).toBe(failure);
24
+ await expect(third).resolves.toBe('third');
25
+ await Promise.resolve();
26
+ expect(bulkhead.getStats()).toMatchObject({
27
+ active: 0,
28
+ queued: 0,
29
+ completed: 2,
30
+ });
31
+ });
32
+ });
33
+ //# sourceMappingURL=bulkhead-sync-throw.test.js.map
@@ -158,7 +158,8 @@ export class Bulkhead extends EventEmitter {
158
158
  // Execute the queued function
159
159
  this.active++;
160
160
  this.emit('acquire');
161
- item.fn()
161
+ Promise.resolve()
162
+ .then(() => item.fn())
162
163
  .then((result) => {
163
164
  this.completed++;
164
165
  item.resolve(result);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=retry-timeout-cleanup.test.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { afterEach, describe, it, expect, vi } from 'vitest';
2
+ import { retry } from './retry.js';
3
+ afterEach(() => vi.useRealTimers());
4
+ describe('retry timeout lifetime', () => {
5
+ it('does not keep a success timer alive after an attempt settles', async () => {
6
+ vi.useFakeTimers();
7
+ const result = await retry(async () => 42, {
8
+ maxAttempts: 1,
9
+ timeout: 30000,
10
+ });
11
+ expect(result.success).toBe(true);
12
+ expect(result.result).toBe(42);
13
+ expect(vi.getTimerCount()).toBe(0);
14
+ });
15
+ it('releases timers for rejected attempts without suppressing their errors', async () => {
16
+ vi.useFakeTimers();
17
+ const err = new Error('no');
18
+ const result = await retry(async () => {
19
+ throw err;
20
+ }, { maxAttempts: 1 });
21
+ expect(result.success).toBe(false);
22
+ expect(result.errors).toEqual([err]);
23
+ expect(vi.getTimerCount()).toBe(0);
24
+ });
25
+ it('still bounds a pending operation and reports the timeout', async () => {
26
+ vi.useFakeTimers();
27
+ const promise = retry(() => new Promise(() => { }), {
28
+ maxAttempts: 1,
29
+ timeout: 10,
30
+ });
31
+ await vi.advanceTimersByTimeAsync(10);
32
+ const result = await promise;
33
+ expect(result.success).toBe(false);
34
+ expect(result.errors[0].message).toContain('timed out');
35
+ expect(vi.getTimerCount()).toBe(0);
36
+ });
37
+ });
38
+ //# sourceMappingURL=retry-timeout-cleanup.test.js.map
@@ -117,12 +117,19 @@ export function withRetry(fn, options = {}) {
117
117
  * Execute with timeout
118
118
  */
119
119
  async function withTimeout(promise, timeout, attempt) {
120
+ let timer;
120
121
  const timeoutPromise = new Promise((_, reject) => {
121
- setTimeout(() => {
122
+ timer = setTimeout(() => {
122
123
  reject(new Error(`Attempt ${attempt} timed out after ${timeout}ms`));
123
124
  }, timeout);
124
125
  });
125
- return Promise.race([promise, timeoutPromise]);
126
+ try {
127
+ return await Promise.race([promise, timeoutPromise]);
128
+ }
129
+ finally {
130
+ if (timer !== undefined)
131
+ clearTimeout(timer);
132
+ }
126
133
  }
127
134
  /**
128
135
  * Sleep for specified milliseconds
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/shared",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "type": "module",
5
5
  "description": "Shared module - common types, events, utilities, core interfaces",
6
6
  "main": "dist/index.js",