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 ||
|
|
251
|
+
totalCves: auditData.totalCves || 0,
|
|
246
252
|
};
|
|
247
253
|
}
|
|
248
254
|
|
|
249
|
-
let
|
|
255
|
+
let scanCount = 0;
|
|
250
256
|
try {
|
|
251
257
|
const scanDir = path.join(CWD, '.claude', 'security-scans');
|
|
252
258
|
if (fs.existsSync(scanDir)) {
|
|
253
|
-
|
|
259
|
+
scanCount = fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length;
|
|
254
260
|
}
|
|
255
261
|
} catch { /* ignore */ }
|
|
256
262
|
|
|
257
263
|
return {
|
|
258
|
-
status:
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
302
|
-
const
|
|
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
|
-
|
|
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
|
-
//
|
|
359
|
-
|
|
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
|
-
|
|
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
|
|
378
|
-
if (Array.isArray(
|
|
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
|
|
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
|
|
411
|
-
|
|
412
|
-
namespaces = 1;
|
|
413
|
-
break;
|
|
446
|
+
dbSizeKB += stat.size / 1024;
|
|
447
|
+
namespaces++;
|
|
414
448
|
}
|
|
415
449
|
}
|
|
416
450
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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 >
|
|
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
|
-
|
|
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.
|
|
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 ||
|
|
273
|
+
totalCves: auditData.totalCves || 0,
|
|
269
274
|
};
|
|
270
275
|
}
|
|
271
276
|
|
|
272
|
-
let
|
|
277
|
+
let scanCount = 0;
|
|
273
278
|
try {
|
|
274
279
|
const scanDir = path.join(CWD, '.claude', 'security-scans');
|
|
275
280
|
if (fs.existsSync(scanDir)) {
|
|
276
|
-
|
|
281
|
+
scanCount = fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length;
|
|
277
282
|
}
|
|
278
283
|
} catch { /* ignore */ }
|
|
279
284
|
|
|
280
285
|
return {
|
|
281
|
-
status:
|
|
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
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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 /
|
|
325
|
-
const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount /
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
400
|
-
if (Array.isArray(
|
|
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
|
|
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
|
|
433
|
-
|
|
434
|
-
namespaces = 1;
|
|
435
|
-
break;
|
|
464
|
+
dbSizeKB += stat.size / 1024;
|
|
465
|
+
namespaces++;
|
|
436
466
|
}
|
|
437
467
|
}
|
|
438
468
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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 >
|
|
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
|
|
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.
|
|
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",
|