claude-flow 3.5.29 → 3.5.31

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.
@@ -236,49 +236,68 @@ function getV3Progress() {
236
236
 
237
237
  // Security status (pure file reads)
238
238
  function getSecurityStatus() {
239
- const totalCves = 3;
240
239
  const auditData = readJSON(path.join(CWD, '.claude-flow', 'security', 'audit-status.json'));
241
240
  if (auditData) {
241
+ const auditDate = auditData.lastAudit || auditData.lastScan;
242
+ if (!auditDate) {
243
+ // No audit has ever run — show as pending, not stale
244
+ return { status: 'PENDING', cvesFixed: 0, totalCves: 0 };
245
+ }
246
+ const auditAge = Date.now() - new Date(auditDate).getTime();
247
+ const isStale = auditAge > 7 * 24 * 60 * 60 * 1000;
242
248
  return {
243
- status: auditData.status || 'PENDING',
249
+ status: isStale ? 'STALE' : (auditData.status || 'PENDING'),
244
250
  cvesFixed: auditData.cvesFixed || 0,
245
- totalCves: auditData.totalCves || 3,
251
+ totalCves: auditData.totalCves || 0,
246
252
  };
247
253
  }
248
254
 
249
- let cvesFixed = 0;
255
+ let scanCount = 0;
250
256
  try {
251
257
  const scanDir = path.join(CWD, '.claude', 'security-scans');
252
258
  if (fs.existsSync(scanDir)) {
253
- cvesFixed = Math.min(totalCves, fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length);
259
+ scanCount = fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length;
254
260
  }
255
261
  } catch { /* ignore */ }
256
262
 
257
263
  return {
258
- status: cvesFixed >= totalCves ? 'CLEAN' : cvesFixed > 0 ? 'IN_PROGRESS' : 'PENDING',
259
- cvesFixed,
260
- totalCves,
264
+ status: scanCount > 0 ? 'SCANNED' : 'NONE',
265
+ cvesFixed: 0,
266
+ totalCves: 0,
261
267
  };
262
268
  }
263
269
 
264
270
  // Swarm status (pure file reads, NO ps aux)
265
271
  function getSwarmStatus() {
266
- const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
267
- if (activityData?.swarm) {
268
- return {
269
- activeAgents: activityData.swarm.agent_count || 0,
270
- maxAgents: CONFIG.maxAgents,
271
- coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
272
- };
272
+ // Check swarm state file — only trust if recently updated (within 5 min)
273
+ const staleThresholdMs = 5 * 60 * 1000;
274
+ const now = Date.now();
275
+
276
+ const swarmStatePath = path.join(CWD, '.claude-flow', 'swarm', 'swarm-state.json');
277
+ const swarmState = readJSON(swarmStatePath);
278
+ if (swarmState) {
279
+ const updatedAt = swarmState.updatedAt || swarmState.startedAt;
280
+ const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
281
+ if (age < staleThresholdMs) {
282
+ return {
283
+ activeAgents: swarmState.agents?.length || swarmState.agentCount || 0,
284
+ maxAgents: swarmState.maxAgents || CONFIG.maxAgents,
285
+ coordinationActive: true,
286
+ };
287
+ }
273
288
  }
274
289
 
275
- const progressData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'v3-progress.json'));
276
- if (progressData?.swarm) {
277
- return {
278
- activeAgents: progressData.swarm.activeAgents || progressData.swarm.agent_count || 0,
279
- maxAgents: progressData.swarm.totalAgents || CONFIG.maxAgents,
280
- coordinationActive: progressData.swarm.active || (progressData.swarm.activeAgents > 0),
281
- };
290
+ const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
291
+ if (activityData?.swarm) {
292
+ const updatedAt = activityData.timestamp || activityData.swarm.timestamp;
293
+ const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
294
+ if (age < staleThresholdMs) {
295
+ return {
296
+ activeAgents: activityData.swarm.agent_count || 0,
297
+ maxAgents: CONFIG.maxAgents,
298
+ coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
299
+ };
300
+ }
282
301
  }
283
302
 
284
303
  return { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false };
@@ -298,8 +317,9 @@ function getSystemMetrics() {
298
317
  if (learningData?.intelligence?.score !== undefined) {
299
318
  intelligencePct = Math.min(100, Math.floor(learningData.intelligence.score));
300
319
  } else {
301
- const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 10)) : 0;
302
- const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount / 100)) : 0;
320
+ // Use actual vector/entry counts 2000 entries = 100%
321
+ const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 20)) : 0;
322
+ const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount / 20)) : 0;
303
323
  intelligencePct = Math.max(fromPatterns, fromVectors);
304
324
  }
305
325
 
@@ -334,15 +354,7 @@ function getSystemMetrics() {
334
354
 
335
355
  // ADR status (count files only — don't read contents)
336
356
  function getADRStatus() {
337
- const complianceData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'adr-compliance.json'));
338
- if (complianceData) {
339
- const checks = complianceData.checks || {};
340
- const total = Object.keys(checks).length;
341
- const impl = Object.values(checks).filter(c => c.compliant).length;
342
- return { count: total, implemented: impl, compliance: complianceData.compliance || 0 };
343
- }
344
-
345
- // Fallback: just count ADR files (don't read them)
357
+ // Count actual ADR files first compliance JSON may be stale
346
358
  const adrPaths = [
347
359
  path.join(CWD, 'v3', 'implementation', 'adrs'),
348
360
  path.join(CWD, 'docs', 'adrs'),
@@ -355,10 +367,8 @@ function getADRStatus() {
355
367
  const files = fs.readdirSync(adrPath).filter(f =>
356
368
  f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\d{4}-/.test(f))
357
369
  );
358
- // Estimate: ~70% implemented in mature projects
359
- const implemented = Math.floor(files.length * 0.7);
360
- const compliance = files.length > 0 ? Math.floor((implemented / files.length) * 100) : 0;
361
- return { count: files.length, implemented, compliance };
370
+ // Report actual count don't guess compliance without reading files
371
+ return { count: files.length, implemented: files.length, compliance: 0 };
362
372
  }
363
373
  } catch { /* ignore */ }
364
374
  }
@@ -369,13 +379,20 @@ function getADRStatus() {
369
379
  // Hooks status (shared settings cache)
370
380
  function getHooksStatus() {
371
381
  let enabled = 0;
372
- const total = 17;
382
+ let total = 0;
373
383
  const settings = getSettings();
374
384
 
375
385
  if (settings?.hooks) {
376
386
  for (const category of Object.keys(settings.hooks)) {
377
- const h = settings.hooks[category];
378
- if (Array.isArray(h) && h.length > 0) enabled++;
387
+ const matchers = settings.hooks[category];
388
+ if (!Array.isArray(matchers)) continue;
389
+ for (const matcher of matchers) {
390
+ const hooks = matcher?.hooks;
391
+ if (Array.isArray(hooks)) {
392
+ total += hooks.length;
393
+ enabled += hooks.length;
394
+ }
395
+ }
379
396
  }
380
397
  }
381
398
 
@@ -383,6 +400,7 @@ function getHooksStatus() {
383
400
  const hooksDir = path.join(CWD, '.claude', 'hooks');
384
401
  if (fs.existsSync(hooksDir)) {
385
402
  const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh')).length;
403
+ total = Math.max(total, hookFiles);
386
404
  enabled = Math.max(enabled, hookFiles);
387
405
  }
388
406
  } catch { /* ignore */ }
@@ -390,52 +408,52 @@ function getHooksStatus() {
390
408
  return { enabled, total };
391
409
  }
392
410
 
393
- // AgentDB stats (pure stat calls)
411
+ // AgentDB stats count real entries, not file-size heuristics
394
412
  function getAgentDBStats() {
395
413
  let vectorCount = 0;
396
414
  let dbSizeKB = 0;
397
415
  let namespaces = 0;
398
416
  let hasHnsw = false;
399
417
 
418
+ // 1. Count real entries from auto-memory-store.json
419
+ const storePath = path.join(CWD, '.claude-flow', 'data', 'auto-memory-store.json');
420
+ const storeStat = safeStat(storePath);
421
+ if (storeStat) {
422
+ dbSizeKB += storeStat.size / 1024;
423
+ try {
424
+ const store = JSON.parse(fs.readFileSync(storePath, 'utf-8'));
425
+ if (Array.isArray(store)) vectorCount += store.length;
426
+ else if (store?.entries) vectorCount += store.entries.length;
427
+ } catch { /* fall back to size estimate */ }
428
+ }
429
+
430
+ // 2. Count entries from ranked-context.json
431
+ const rankedPath = path.join(CWD, '.claude-flow', 'data', 'ranked-context.json');
432
+ try {
433
+ const ranked = readJSON(rankedPath);
434
+ if (ranked?.entries?.length > vectorCount) vectorCount = ranked.entries.length;
435
+ } catch { /* ignore */ }
436
+
437
+ // 3. Add DB file sizes
400
438
  const dbFiles = [
401
- path.join(CWD, '.swarm', 'memory.db'),
402
- path.join(CWD, '.claude-flow', 'memory.db'),
403
- path.join(CWD, '.claude', 'memory.db'),
404
439
  path.join(CWD, 'data', 'memory.db'),
440
+ path.join(CWD, '.claude-flow', 'memory.db'),
441
+ path.join(CWD, '.swarm', 'memory.db'),
405
442
  ];
406
-
407
443
  for (const f of dbFiles) {
408
444
  const stat = safeStat(f);
409
445
  if (stat) {
410
- dbSizeKB = stat.size / 1024;
411
- vectorCount = Math.floor(dbSizeKB / 2);
412
- namespaces = 1;
413
- break;
446
+ dbSizeKB += stat.size / 1024;
447
+ namespaces++;
414
448
  }
415
449
  }
416
450
 
417
- if (vectorCount === 0) {
418
- const dbDirs = [
419
- path.join(CWD, '.claude-flow', 'agentdb'),
420
- path.join(CWD, '.swarm', 'agentdb'),
421
- path.join(CWD, '.agentdb'),
422
- ];
423
- for (const dir of dbDirs) {
424
- try {
425
- if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
426
- const files = fs.readdirSync(dir);
427
- namespaces = files.filter(f => f.endsWith('.db') || f.endsWith('.sqlite')).length;
428
- for (const file of files) {
429
- const stat = safeStat(path.join(dir, file));
430
- if (stat?.isFile()) dbSizeKB += stat.size / 1024;
431
- }
432
- vectorCount = Math.floor(dbSizeKB / 2);
433
- break;
434
- }
435
- } catch { /* ignore */ }
436
- }
437
- }
451
+ // 4. Check for graph data
452
+ const graphPath = path.join(CWD, 'data', 'memory.graph');
453
+ const graphStat = safeStat(graphPath);
454
+ if (graphStat) dbSizeKB += graphStat.size / 1024;
438
455
 
456
+ // 5. HNSW index
439
457
  const hnswPaths = [
440
458
  path.join(CWD, '.swarm', 'hnsw.index'),
441
459
  path.join(CWD, '.claude-flow', 'hnsw.index'),
@@ -444,11 +462,21 @@ function getAgentDBStats() {
444
462
  const stat = safeStat(p);
445
463
  if (stat) {
446
464
  hasHnsw = true;
447
- vectorCount = Math.max(vectorCount, Math.floor(stat.size / 512));
448
465
  break;
449
466
  }
450
467
  }
451
468
 
469
+ // HNSW is available if memory package is present
470
+ if (!hasHnsw) {
471
+ const memPkgPaths = [
472
+ path.join(CWD, 'v3', '@claude-flow', 'memory', 'dist'),
473
+ path.join(CWD, 'node_modules', '@claude-flow', 'memory'),
474
+ ];
475
+ for (const p of memPkgPaths) {
476
+ if (fs.existsSync(p)) { hasHnsw = true; break; }
477
+ }
478
+ }
479
+
452
480
  return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces, hasHnsw };
453
481
  }
454
482
 
@@ -457,7 +485,7 @@ function getTestStats() {
457
485
  let testFiles = 0;
458
486
 
459
487
  function countTestFiles(dir, depth = 0) {
460
- if (depth > 2) return; // Shallower recursion limit
488
+ if (depth > 6) return;
461
489
  try {
462
490
  if (!fs.existsSync(dir)) return;
463
491
  const entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -474,10 +502,10 @@ function getTestStats() {
474
502
  } catch { /* ignore */ }
475
503
  }
476
504
 
477
- for (const d of ['tests', 'test', '__tests__', 'v3/__tests__']) {
505
+ // Scan all source directories
506
+ for (const d of ['tests', 'test', '__tests__', 'src', 'v3']) {
478
507
  countTestFiles(path.join(CWD, d));
479
508
  }
480
- countTestFiles(path.join(CWD, 'src'));
481
509
 
482
510
  // Estimate ~4 test cases per file (avoids reading every file)
483
511
  return { testFiles, testCases: testFiles * 4 };
@@ -658,8 +686,8 @@ function generateDashboard() {
658
686
  // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
659
687
  const swarmInd = swarm.coordinationActive ? `${c.brightGreen}\u25C9${c.reset}` : `${c.dim}\u25CB${c.reset}`;
660
688
  const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
661
- const secIcon = security.status === 'CLEAN' ? '\uD83D\uDFE2' : security.status === 'IN_PROGRESS' ? '\uD83D\uDFE1' : '\uD83D\uDD34';
662
- const secColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
689
+ const secIcon = security.status === 'CLEAN' ? '\uD83D\uDFE2' : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? '\uD83D\uDFE1' : '\uD83D\uDD34';
690
+ const secColor = security.status === 'CLEAN' ? c.brightGreen : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? c.brightYellow : c.brightRed;
663
691
  const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
664
692
  const intellColor = system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim;
665
693
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.5.29",
3
+ "version": "3.5.31",
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",
@@ -259,49 +259,66 @@ function getV3Progress() {
259
259
 
260
260
  // Security status (pure file reads)
261
261
  function getSecurityStatus() {
262
- const totalCves = 3;
263
262
  const auditData = readJSON(path.join(CWD, '.claude-flow', 'security', 'audit-status.json'));
264
263
  if (auditData) {
264
+ const auditDate = auditData.lastAudit || auditData.lastScan;
265
+ if (!auditDate) {
266
+ return { status: 'PENDING', cvesFixed: 0, totalCves: 0 };
267
+ }
268
+ const auditAge = Date.now() - new Date(auditDate).getTime();
269
+ const isStale = auditAge > 7 * 24 * 60 * 60 * 1000;
265
270
  return {
266
- status: auditData.status || 'PENDING',
271
+ status: isStale ? 'STALE' : (auditData.status || 'PENDING'),
267
272
  cvesFixed: auditData.cvesFixed || 0,
268
- totalCves: auditData.totalCves || 3,
273
+ totalCves: auditData.totalCves || 0,
269
274
  };
270
275
  }
271
276
 
272
- let cvesFixed = 0;
277
+ let scanCount = 0;
273
278
  try {
274
279
  const scanDir = path.join(CWD, '.claude', 'security-scans');
275
280
  if (fs.existsSync(scanDir)) {
276
- cvesFixed = Math.min(totalCves, fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length);
281
+ scanCount = fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length;
277
282
  }
278
283
  } catch { /* ignore */ }
279
284
 
280
285
  return {
281
- status: cvesFixed >= totalCves ? 'CLEAN' : cvesFixed > 0 ? 'IN_PROGRESS' : 'PENDING',
282
- cvesFixed,
283
- totalCves,
286
+ status: scanCount > 0 ? 'SCANNED' : 'NONE',
287
+ cvesFixed: 0,
288
+ totalCves: 0,
284
289
  };
285
290
  }
286
291
 
287
292
  // Swarm status (pure file reads, NO ps aux)
288
293
  function getSwarmStatus() {
289
- const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
290
- if (activityData && activityData.swarm) {
291
- return {
292
- activeAgents: activityData.swarm.agent_count || 0,
293
- maxAgents: CONFIG.maxAgents,
294
- coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
295
- };
294
+ const staleThresholdMs = 5 * 60 * 1000;
295
+ const now = Date.now();
296
+
297
+ const swarmStatePath = path.join(CWD, '.claude-flow', 'swarm', 'swarm-state.json');
298
+ const swarmState = readJSON(swarmStatePath);
299
+ if (swarmState) {
300
+ const updatedAt = swarmState.updatedAt || swarmState.startedAt;
301
+ const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
302
+ if (age < staleThresholdMs) {
303
+ return {
304
+ activeAgents: (swarmState.agents && swarmState.agents.length) || swarmState.agentCount || 0,
305
+ maxAgents: swarmState.maxAgents || CONFIG.maxAgents,
306
+ coordinationActive: true,
307
+ };
308
+ }
296
309
  }
297
310
 
298
- const progressData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'v3-progress.json'));
299
- if (progressData && progressData.swarm) {
300
- return {
301
- activeAgents: progressData.swarm.activeAgents || progressData.swarm.agent_count || 0,
302
- maxAgents: progressData.swarm.totalAgents || CONFIG.maxAgents,
303
- coordinationActive: progressData.swarm.active || (progressData.swarm.activeAgents > 0),
304
- };
311
+ const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
312
+ if (activityData && activityData.swarm) {
313
+ const updatedAt = activityData.timestamp || (activityData.swarm && activityData.swarm.timestamp);
314
+ const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
315
+ if (age < staleThresholdMs) {
316
+ return {
317
+ activeAgents: activityData.swarm.agent_count || 0,
318
+ maxAgents: CONFIG.maxAgents,
319
+ coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
320
+ };
321
+ }
305
322
  }
306
323
 
307
324
  return { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false };
@@ -321,8 +338,8 @@ function getSystemMetrics() {
321
338
  if (learningData && learningData.intelligence && learningData.intelligence.score !== undefined) {
322
339
  intelligencePct = Math.min(100, Math.floor(learningData.intelligence.score));
323
340
  } else {
324
- const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 10)) : 0;
325
- const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount / 100)) : 0;
341
+ const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 20)) : 0;
342
+ const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount / 20)) : 0;
326
343
  intelligencePct = Math.max(fromPatterns, fromVectors);
327
344
  }
328
345
 
@@ -357,15 +374,7 @@ function getSystemMetrics() {
357
374
 
358
375
  // ADR status (count files only — don't read contents)
359
376
  function getADRStatus() {
360
- const complianceData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'adr-compliance.json'));
361
- if (complianceData) {
362
- const checks = complianceData.checks || {};
363
- const total = Object.keys(checks).length;
364
- const impl = Object.values(checks).filter(c => c.compliant).length;
365
- return { count: total, implemented: impl, compliance: complianceData.compliance || 0 };
366
- }
367
-
368
- // Fallback: just count ADR files (don't read them)
377
+ // Count actual ADR files first compliance JSON may be stale
369
378
  const adrPaths = [
370
379
  path.join(CWD, 'v3', 'implementation', 'adrs'),
371
380
  path.join(CWD, 'docs', 'adrs'),
@@ -378,9 +387,7 @@ function getADRStatus() {
378
387
  const files = fs.readdirSync(adrPath).filter(f =>
379
388
  f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\\d{4}-/.test(f))
380
389
  );
381
- const implemented = Math.floor(files.length * 0.7);
382
- const compliance = files.length > 0 ? Math.floor((implemented / files.length) * 100) : 0;
383
- return { count: files.length, implemented, compliance };
390
+ return { count: files.length, implemented: files.length, compliance: 0 };
384
391
  }
385
392
  } catch { /* ignore */ }
386
393
  }
@@ -391,13 +398,20 @@ function getADRStatus() {
391
398
  // Hooks status (shared settings cache)
392
399
  function getHooksStatus() {
393
400
  let enabled = 0;
394
- const total = 17;
401
+ let total = 0;
395
402
  const settings = getSettings();
396
403
 
397
404
  if (settings && settings.hooks) {
398
405
  for (const category of Object.keys(settings.hooks)) {
399
- const h = settings.hooks[category];
400
- if (Array.isArray(h) && h.length > 0) enabled++;
406
+ const matchers = settings.hooks[category];
407
+ if (!Array.isArray(matchers)) continue;
408
+ for (const matcher of matchers) {
409
+ const hooks = matcher && matcher.hooks;
410
+ if (Array.isArray(hooks)) {
411
+ total += hooks.length;
412
+ enabled += hooks.length;
413
+ }
414
+ }
401
415
  }
402
416
  }
403
417
 
@@ -405,6 +419,7 @@ function getHooksStatus() {
405
419
  const hooksDir = path.join(CWD, '.claude', 'hooks');
406
420
  if (fs.existsSync(hooksDir)) {
407
421
  const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh')).length;
422
+ total = Math.max(total, hookFiles);
408
423
  enabled = Math.max(enabled, hookFiles);
409
424
  }
410
425
  } catch { /* ignore */ }
@@ -412,62 +427,64 @@ function getHooksStatus() {
412
427
  return { enabled, total };
413
428
  }
414
429
 
415
- // AgentDB stats (pure stat calls)
430
+ // AgentDB stats count real entries, not file-size heuristics
416
431
  function getAgentDBStats() {
417
432
  let vectorCount = 0;
418
433
  let dbSizeKB = 0;
419
434
  let namespaces = 0;
420
435
  let hasHnsw = false;
421
436
 
437
+ // 1. Count real entries from auto-memory-store.json
438
+ const storePath = path.join(CWD, '.claude-flow', 'data', 'auto-memory-store.json');
439
+ const storeStat = safeStat(storePath);
440
+ if (storeStat) {
441
+ dbSizeKB += storeStat.size / 1024;
442
+ try {
443
+ const store = JSON.parse(fs.readFileSync(storePath, 'utf-8'));
444
+ if (Array.isArray(store)) vectorCount += store.length;
445
+ else if (store && store.entries) vectorCount += store.entries.length;
446
+ } catch { /* fall back */ }
447
+ }
448
+
449
+ // 2. Count entries from ranked-context.json
450
+ try {
451
+ const ranked = readJSON(path.join(CWD, '.claude-flow', 'data', 'ranked-context.json'));
452
+ if (ranked && ranked.entries && ranked.entries.length > vectorCount) vectorCount = ranked.entries.length;
453
+ } catch { /* ignore */ }
454
+
455
+ // 3. Add DB file sizes
422
456
  const dbFiles = [
423
- path.join(CWD, '.swarm', 'memory.db'),
424
- path.join(CWD, '.claude-flow', 'memory.db'),
425
- path.join(CWD, '.claude', 'memory.db'),
426
457
  path.join(CWD, 'data', 'memory.db'),
458
+ path.join(CWD, '.claude-flow', 'memory.db'),
459
+ path.join(CWD, '.swarm', 'memory.db'),
427
460
  ];
428
-
429
461
  for (const f of dbFiles) {
430
462
  const stat = safeStat(f);
431
463
  if (stat) {
432
- dbSizeKB = stat.size / 1024;
433
- vectorCount = Math.floor(dbSizeKB / 2);
434
- namespaces = 1;
435
- break;
464
+ dbSizeKB += stat.size / 1024;
465
+ namespaces++;
436
466
  }
437
467
  }
438
468
 
439
- if (vectorCount === 0) {
440
- const dbDirs = [
441
- path.join(CWD, '.claude-flow', 'agentdb'),
442
- path.join(CWD, '.swarm', 'agentdb'),
443
- path.join(CWD, '.agentdb'),
444
- ];
445
- for (const dir of dbDirs) {
446
- try {
447
- if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
448
- const files = fs.readdirSync(dir);
449
- namespaces = files.filter(f => f.endsWith('.db') || f.endsWith('.sqlite')).length;
450
- for (const file of files) {
451
- const stat = safeStat(path.join(dir, file));
452
- if (stat && stat.isFile()) dbSizeKB += stat.size / 1024;
453
- }
454
- vectorCount = Math.floor(dbSizeKB / 2);
455
- break;
456
- }
457
- } catch { /* ignore */ }
458
- }
459
- }
469
+ // 4. Graph data size
470
+ const graphStat = safeStat(path.join(CWD, 'data', 'memory.graph'));
471
+ if (graphStat) dbSizeKB += graphStat.size / 1024;
460
472
 
473
+ // 5. HNSW index or memory package
461
474
  const hnswPaths = [
462
475
  path.join(CWD, '.swarm', 'hnsw.index'),
463
476
  path.join(CWD, '.claude-flow', 'hnsw.index'),
464
477
  ];
465
478
  for (const p of hnswPaths) {
466
- const stat = safeStat(p);
467
- if (stat) {
468
- hasHnsw = true;
469
- vectorCount = Math.max(vectorCount, Math.floor(stat.size / 512));
470
- break;
479
+ if (safeStat(p)) { hasHnsw = true; break; }
480
+ }
481
+ if (!hasHnsw) {
482
+ const memPkgPaths = [
483
+ path.join(CWD, 'v3', '@claude-flow', 'memory', 'dist'),
484
+ path.join(CWD, 'node_modules', '@claude-flow', 'memory'),
485
+ ];
486
+ for (const p of memPkgPaths) {
487
+ if (fs.existsSync(p)) { hasHnsw = true; break; }
471
488
  }
472
489
  }
473
490
 
@@ -480,7 +497,7 @@ function getTestStats() {
480
497
 
481
498
  function countTestFiles(dir, depth) {
482
499
  if (depth === undefined) depth = 0;
483
- if (depth > 2) return;
500
+ if (depth > 6) return;
484
501
  try {
485
502
  if (!fs.existsSync(dir)) return;
486
503
  const entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -497,11 +514,10 @@ function getTestStats() {
497
514
  } catch { /* ignore */ }
498
515
  }
499
516
 
500
- var testDirNames = ['tests', 'test', '__tests__', 'v3/__tests__'];
517
+ var testDirNames = ['tests', 'test', '__tests__', 'src', 'v3'];
501
518
  for (var i = 0; i < testDirNames.length; i++) {
502
519
  countTestFiles(path.join(CWD, testDirNames[i]));
503
520
  }
504
- countTestFiles(path.join(CWD, 'src'));
505
521
 
506
522
  return { testFiles, testCases: testFiles * 4 };
507
523
  }
@@ -631,8 +647,8 @@ function generateStatusline() {
631
647
  // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
632
648
  const swarmInd = swarm.coordinationActive ? c.brightGreen + '\\u25C9' + c.reset : c.dim + '\\u25CB' + c.reset;
633
649
  const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
634
- const secIcon = security.status === 'CLEAN' ? '\\uD83D\\uDFE2' : security.status === 'IN_PROGRESS' ? '\\uD83D\\uDFE1' : '\\uD83D\\uDD34';
635
- const secColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
650
+ const secIcon = security.status === 'CLEAN' ? '\\uD83D\\uDFE2' : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? '\\uD83D\\uDFE1' : (security.status === 'NONE' ? '\\u26AA' : '\\uD83D\\uDD34');
651
+ const secColor = security.status === 'CLEAN' ? c.brightGreen : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? c.brightYellow : (security.status === 'NONE' ? c.dim : c.brightRed);
636
652
  const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
637
653
  const intellColor = system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim;
638
654
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.5.29",
3
+ "version": "3.5.31",
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",