claude-flow 3.7.0-alpha.18 → 3.7.0-alpha.20

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.
@@ -0,0 +1 @@
1
+ {"sessionId":"e8acbe6b-1513-4c00-ac30-2b486317c5b1","pid":7565,"procStart":"Sat May 9 13:35:07 2026","acquiredAt":1778338395740}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.7.0-alpha.18",
3
+ "version": "3.7.0-alpha.20",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -39,9 +39,22 @@ console.log = (...args) => {
39
39
  // Conditions:
40
40
  // 1. stdin is being piped AND no CLI arguments provided (auto-detect)
41
41
  // 2. stdin is being piped AND args are "mcp start" (explicit, e.g. npx claude-flow@alpha mcp start)
42
+ // 3. EXCEPT — if the user explicitly passed --transport <non-stdio>
43
+ // (e.g. -t http), defer to the parser. Without this, every smoke
44
+ // test or non-TTY caller of `mcp start -t http` got force-routed
45
+ // into stdio mode and never hit the HTTP server (#1874 follow-up).
42
46
  const cliArgs = process.argv.slice(2);
43
47
  const isExplicitMCP = cliArgs.length >= 1 && cliArgs[0] === 'mcp' && (cliArgs.length === 1 || cliArgs[1] === 'start');
44
- const isMCPMode = !process.stdin.isTTY && (process.argv.length === 2 || isExplicitMCP);
48
+ const explicitNonStdioTransport = cliArgs.some((a, i) => {
49
+ // -t <value> | --transport <value>
50
+ if ((a === '-t' || a === '--transport') && cliArgs[i + 1] && cliArgs[i + 1] !== 'stdio') return true;
51
+ // --transport=<value>
52
+ if (/^--transport=/.test(a) && !/^--transport=stdio$/.test(a)) return true;
53
+ return false;
54
+ });
55
+ const isMCPMode = !process.stdin.isTTY
56
+ && !explicitNonStdioTransport
57
+ && (process.argv.length === 2 || isExplicitMCP);
45
58
 
46
59
  if (isMCPMode) {
47
60
  // Run MCP server mode
@@ -254,6 +254,49 @@ async function checkAIDefence() {
254
254
  };
255
255
  }
256
256
  }
257
+ /**
258
+ * ADR-097 Phase 4: federation peer-state surface for doctor.
259
+ *
260
+ * Probes the federation plugin loadability + asserts the breaker entity
261
+ * layer is present in the installed version. Without the plugin
262
+ * installed this is a "not configured" pass — federation is opt-in.
263
+ *
264
+ * Live coordinator state (per-peer counts) requires a running MCP server
265
+ * with `federation_init` called; operators inspect that via the
266
+ * `federation_breaker_status` MCP tool, not the doctor (which is a
267
+ * one-shot CLI process with no coordinator session).
268
+ */
269
+ async function checkFederationBreaker() {
270
+ try {
271
+ // Optional plugin — not a hard dep of @claude-flow/cli. Build the
272
+ // module specifier dynamically so TypeScript cannot statically
273
+ // resolve it (which would emit TS2307); at runtime the import
274
+ // either resolves (plugin installed) or throws (handled below).
275
+ const specifier = ['@claude-flow', 'plugin-agent-federation'].join('/');
276
+ const mod = await import(specifier);
277
+ if (!mod.FederationNodeState) {
278
+ return {
279
+ name: 'Federation Breaker',
280
+ status: 'warn',
281
+ message: '@claude-flow/plugin-agent-federation loaded but FederationNodeState export missing — version older than ADR-097 Phase 2',
282
+ fix: 'Upgrade: npm install @claude-flow/plugin-agent-federation@alpha',
283
+ };
284
+ }
285
+ return {
286
+ name: 'Federation Breaker',
287
+ status: 'pass',
288
+ message: 'ADR-097 breaker loadable — federation_breaker_status / federation_evict / federation_reactivate MCP tools available',
289
+ };
290
+ }
291
+ catch {
292
+ return {
293
+ name: 'Federation Breaker',
294
+ status: 'pass',
295
+ message: 'Federation plugin not installed (optional) — install only if you need cross-installation peering',
296
+ fix: 'npm install --save @claude-flow/plugin-agent-federation@alpha',
297
+ };
298
+ }
299
+ }
257
300
  // Check MCP servers
258
301
  async function checkMcpServers() {
259
302
  const home = process.env.HOME || process.env.USERPROFILE || '';
@@ -702,6 +745,7 @@ export const doctorCommand = {
702
745
  checkBuildTools,
703
746
  checkAgenticFlow,
704
747
  checkEncryptionAtRest, // ADR-096 Phase 5
748
+ checkFederationBreaker, // ADR-097 Phase 4
705
749
  ];
706
750
  const componentMap = {
707
751
  'version': checkVersionFreshness,
@@ -720,6 +764,7 @@ export const doctorCommand = {
720
764
  'typescript': checkBuildTools,
721
765
  'agentic-flow': checkAgenticFlow,
722
766
  'encryption': checkEncryptionAtRest, // ADR-096 Phase 5
767
+ 'federation': checkFederationBreaker, // ADR-097 Phase 4
723
768
  };
724
769
  let checksToRun = allChecks;
725
770
  if (component && componentMap[component]) {
@@ -137,6 +137,9 @@ export class SONAOptimizer {
137
137
  if (this.sonaEngine !== undefined)
138
138
  return; // already attempted
139
139
  try {
140
+ // @ts-ignore — @ruvector/sona is in optionalDependencies and ships
141
+ // no .d.ts. Runtime is gated by try/catch; TS errors here on hosts
142
+ // without the module resolved (e.g. CI before postinstall).
140
143
  const sona = await import('@ruvector/sona');
141
144
  const EngineCtor = sona.SonaEngine || sona.default?.SonaEngine;
142
145
  if (EngineCtor) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.7.0-alpha.18",
3
+ "version": "3.7.0-alpha.20",
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",
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { EventEmitter } from 'node:events';
18
18
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
19
+ import { createRequire } from 'node:module';
19
20
  import initSqlJs from 'sql.js';
20
21
  const DEFAULT_CONFIG = {
21
22
  databasePath: ':memory:',
@@ -45,11 +46,21 @@ export class EventStore extends EventEmitter {
45
46
  if (this.initialized)
46
47
  return;
47
48
  // Load sql.js WASM
48
- this.SQL = await initSqlJs({
49
- locateFile: this.config.wasmPath
50
- ? () => this.config.wasmPath
51
- : (file) => `https://sql.js.org/dist/${file}`,
52
- });
49
+ let wasmLocator;
50
+ if (this.config.wasmPath) {
51
+ wasmLocator = () => this.config.wasmPath;
52
+ }
53
+ else {
54
+ try {
55
+ const req = createRequire(import.meta.url);
56
+ const sqlJsPath = req.resolve('sql.js/dist/sql-wasm.wasm');
57
+ wasmLocator = () => sqlJsPath;
58
+ }
59
+ catch {
60
+ wasmLocator = (file) => `https://sql.js.org/dist/${file}`;
61
+ }
62
+ }
63
+ this.SQL = await initSqlJs({ locateFile: wasmLocator });
53
64
  // Load existing database if exists
54
65
  if (this.config.databasePath !== ':memory:' && existsSync(this.config.databasePath)) {
55
66
  const buffer = readFileSync(this.config.databasePath);
@@ -237,7 +248,7 @@ export class EventStore extends EventEmitter {
237
248
  */
238
249
  async *replay(fromVersion = 0) {
239
250
  this.ensureInitialized();
240
- const stmt = this.db.prepare('SELECT * FROM events WHERE version >= ? ORDER BY version ASC');
251
+ const stmt = this.db.prepare('SELECT * FROM events WHERE rowid >= ? ORDER BY rowid ASC');
241
252
  stmt.bind([fromVersion]);
242
253
  while (stmt.step()) {
243
254
  const row = stmt.getAsObject();
@@ -290,7 +301,7 @@ export class EventStore extends EventEmitter {
290
301
  this.ensureInitialized();
291
302
  // Total events
292
303
  const totalStmt = this.db.prepare('SELECT COUNT(*) as count FROM events');
293
- const totalRow = totalStmt.getAsObject();
304
+ const totalRow = totalStmt.getAsObject([]);
294
305
  totalStmt.free();
295
306
  const totalEvents = totalRow.count || 0;
296
307
  // Events by type
@@ -311,11 +322,11 @@ export class EventStore extends EventEmitter {
311
322
  aggStmt.free();
312
323
  // Timestamp range
313
324
  const rangeStmt = this.db.prepare('SELECT MIN(timestamp) as oldest, MAX(timestamp) as newest FROM events');
314
- const rangeRow = rangeStmt.getAsObject();
325
+ const rangeRow = rangeStmt.getAsObject([]);
315
326
  rangeStmt.free();
316
327
  // Snapshot count
317
328
  const snapshotStmt = this.db.prepare('SELECT COUNT(*) as count FROM snapshots');
318
- const snapshotRow = snapshotStmt.getAsObject();
329
+ const snapshotRow = snapshotStmt.getAsObject([]);
319
330
  snapshotStmt.free();
320
331
  return {
321
332
  totalEvents,
@@ -205,6 +205,8 @@ export class HookExecutor {
205
205
  const results = [];
206
206
  let currentContext = { ...initialContext };
207
207
  let totalExecutionTime = 0;
208
+ let totalHooksExecuted = 0;
209
+ let totalHooksFailed = 0;
208
210
  let aborted = false;
209
211
  for (const event of events) {
210
212
  if (aborted) {
@@ -213,6 +215,8 @@ export class HookExecutor {
213
215
  const result = await this.execute(event, currentContext, options);
214
216
  results.push(...result.results);
215
217
  totalExecutionTime += result.totalExecutionTime;
218
+ totalHooksExecuted += result.hooksExecuted;
219
+ totalHooksFailed += result.hooksFailed;
216
220
  // Merge context for next event
217
221
  if (result.finalContext) {
218
222
  currentContext = { ...currentContext, ...result.finalContext };
@@ -222,13 +226,12 @@ export class HookExecutor {
222
226
  break;
223
227
  }
224
228
  }
225
- const hooksFailed = results.filter(r => !r.success).length;
226
229
  return {
227
- success: hooksFailed === 0 && !aborted,
230
+ success: totalHooksFailed === 0 && !aborted,
228
231
  results: options.collectResults ? results : [],
229
232
  totalExecutionTime,
230
- hooksExecuted: results.length,
231
- hooksFailed,
233
+ hooksExecuted: totalHooksExecuted,
234
+ hooksFailed: totalHooksFailed,
232
235
  aborted,
233
236
  finalContext: currentContext,
234
237
  };
@@ -22,8 +22,8 @@ describe('Hooks Module Exports', () => {
22
22
  it('should export types (type-only imports)', () => {
23
23
  expect(true).toBe(true);
24
24
  });
25
- it('should create instances from exported factories', () => {
26
- const { createHookRegistry, createHookExecutor } = require('./index.js');
25
+ it('should create instances from exported factories', async () => {
26
+ const { createHookRegistry, createHookExecutor } = await import('./index.js');
27
27
  const registry = createHookRegistry();
28
28
  expect(registry).toBeDefined();
29
29
  expect(typeof registry.register).toBe('function');
@@ -32,8 +32,8 @@ describe('Hooks Module Exports', () => {
32
32
  expect(executor).toBeDefined();
33
33
  expect(typeof executor.execute).toBe('function');
34
34
  });
35
- it('should have all 26 hook events defined', () => {
36
- const { HookEvent } = require('./index.js');
35
+ it('should have all 26 hook events defined', async () => {
36
+ const { HookEvent } = await import('./index.js');
37
37
  const expectedEvents = [
38
38
  'PreToolUse',
39
39
  'PostToolUse',
@@ -68,8 +68,8 @@ describe('Hooks Module Exports', () => {
68
68
  expect(HookEvent[event]).toBeDefined();
69
69
  }
70
70
  });
71
- it('should have all 5 priority levels defined', () => {
72
- const { HookPriority } = require('./index.js');
71
+ it('should have all 5 priority levels defined', async () => {
72
+ const { HookPriority } = await import('./index.js');
73
73
  expect(HookPriority.Critical).toBe(1000);
74
74
  expect(HookPriority.High).toBe(500);
75
75
  expect(HookPriority.Normal).toBe(0);
@@ -59,12 +59,9 @@ export class MCPServer extends EventEmitter {
59
59
  name: 'Claude-Flow MCP Server V3',
60
60
  version: '3.0.0',
61
61
  };
62
- // Protocol version
63
- protocolVersion = {
64
- major: 2024,
65
- minor: 11,
66
- patch: 5,
67
- };
62
+ // MCP protocol version — spec-required YYYY-MM-DD date string (#1874).
63
+ // Claude Code's Zod validator rejects any other shape.
64
+ protocolVersion = '2024-11-05';
68
65
  // Server capabilities
69
66
  capabilities = {
70
67
  logging: { level: 'info' },
@@ -17,13 +17,11 @@
17
17
  */
18
18
  export type JsonRpcVersion = '2.0';
19
19
  /**
20
- * MCP Protocol Version
20
+ * MCP Protocol Version. Per the [MCP spec](https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization)
21
+ * this must be a `YYYY-MM-DD` date string (e.g. `'2024-11-05'`, `'2025-06-18'`).
22
+ * Claude Code's Zod validator rejects any other shape (#1874).
21
23
  */
22
- export interface MCPProtocolVersion {
23
- major: number;
24
- minor: number;
25
- patch: number;
26
- }
24
+ export type MCPProtocolVersion = string;
27
25
  /**
28
26
  * MCP Request ID (can be string, number, or null)
29
27
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/shared",
3
- "version": "3.0.0-alpha.7",
3
+ "version": "3.0.0-alpha.8",
4
4
  "type": "module",
5
5
  "description": "Shared module - common types, events, utilities, core interfaces",
6
6
  "main": "dist/index.js",