@claude-flow/cli 3.0.0-alpha.128 → 3.0.0-alpha.129
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.
|
@@ -81,21 +81,23 @@ function getUserInfo() {
|
|
|
81
81
|
if (lastModelUsage) {
|
|
82
82
|
const modelIds = Object.keys(lastModelUsage);
|
|
83
83
|
if (modelIds.length > 0) {
|
|
84
|
-
//
|
|
85
|
-
//
|
|
84
|
+
// Find the most recently used model by checking lastUsedAt timestamps
|
|
85
|
+
// or fall back to the last key in the object (preserves insertion order in modern JS)
|
|
86
86
|
let modelId = modelIds[modelIds.length - 1];
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
let latestTimestamp = 0;
|
|
88
|
+
|
|
89
|
+
for (const id of modelIds) {
|
|
90
|
+
const usage = lastModelUsage[id];
|
|
91
|
+
// Check for lastUsedAt timestamp (if available)
|
|
92
|
+
if (usage.lastUsedAt) {
|
|
93
|
+
const ts = new Date(usage.lastUsedAt).getTime();
|
|
94
|
+
if (ts > latestTimestamp) {
|
|
95
|
+
latestTimestamp = ts;
|
|
95
96
|
modelId = id;
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
}
|
|
100
|
+
|
|
99
101
|
// Parse model ID to human-readable name
|
|
100
102
|
if (modelId.includes('opus')) modelName = 'Opus 4.5';
|
|
101
103
|
else if (modelId.includes('sonnet')) modelName = 'Sonnet 4';
|
|
@@ -159,6 +161,25 @@ function getLearningStats() {
|
|
|
159
161
|
function getV3Progress() {
|
|
160
162
|
const learning = getLearningStats();
|
|
161
163
|
|
|
164
|
+
// Check for metrics file first (created by init)
|
|
165
|
+
const metricsPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'v3-progress.json');
|
|
166
|
+
if (fs.existsSync(metricsPath)) {
|
|
167
|
+
try {
|
|
168
|
+
const data = JSON.parse(fs.readFileSync(metricsPath, 'utf-8'));
|
|
169
|
+
if (data.domains && data.ddd) {
|
|
170
|
+
return {
|
|
171
|
+
domainsCompleted: data.domains.completed || 0,
|
|
172
|
+
totalDomains: data.domains.total || 5,
|
|
173
|
+
dddProgress: data.ddd.progress || 0,
|
|
174
|
+
patternsLearned: data.learning?.patternsLearned || learning.patterns,
|
|
175
|
+
sessionsCompleted: data.learning?.sessionsCompleted || learning.sessions
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
} catch (e) {
|
|
179
|
+
// Fall through to pattern-based calculation
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
162
183
|
// DDD progress based on actual learned patterns
|
|
163
184
|
// New install: 0 patterns = 0/5 domains, 0% DDD
|
|
164
185
|
// As patterns grow: 10+ patterns = 1 domain, 50+ = 2, 100+ = 3, 200+ = 4, 500+ = 5
|
|
@@ -183,11 +204,26 @@ function getV3Progress() {
|
|
|
183
204
|
|
|
184
205
|
// Get security status based on actual scans
|
|
185
206
|
function getSecurityStatus() {
|
|
186
|
-
// Check for security scan results in memory
|
|
187
|
-
const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
|
|
188
|
-
let cvesFixed = 0;
|
|
189
207
|
const totalCves = 3;
|
|
208
|
+
let cvesFixed = 0;
|
|
209
|
+
|
|
210
|
+
// Check audit-status.json first (created by init)
|
|
211
|
+
const auditStatusPath = path.join(process.cwd(), '.claude-flow', 'security', 'audit-status.json');
|
|
212
|
+
if (fs.existsSync(auditStatusPath)) {
|
|
213
|
+
try {
|
|
214
|
+
const data = JSON.parse(fs.readFileSync(auditStatusPath, 'utf-8'));
|
|
215
|
+
return {
|
|
216
|
+
status: data.status || 'PENDING',
|
|
217
|
+
cvesFixed: data.cvesFixed || 0,
|
|
218
|
+
totalCves: data.totalCves || 3,
|
|
219
|
+
};
|
|
220
|
+
} catch (e) {
|
|
221
|
+
// Fall through to scan directory check
|
|
222
|
+
}
|
|
223
|
+
}
|
|
190
224
|
|
|
225
|
+
// Check for security scan results in memory
|
|
226
|
+
const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
|
|
191
227
|
if (fs.existsSync(scanResultsPath)) {
|
|
192
228
|
try {
|
|
193
229
|
const scans = fs.readdirSync(scanResultsPath).filter(f => f.endsWith('.json'));
|
|
@@ -199,10 +235,10 @@ function getSecurityStatus() {
|
|
|
199
235
|
}
|
|
200
236
|
|
|
201
237
|
// Also check .swarm/security for audit results
|
|
202
|
-
const
|
|
203
|
-
if (fs.existsSync(
|
|
238
|
+
const swarmAuditPath = path.join(process.cwd(), '.swarm', 'security');
|
|
239
|
+
if (fs.existsSync(swarmAuditPath)) {
|
|
204
240
|
try {
|
|
205
|
-
const audits = fs.readdirSync(
|
|
241
|
+
const audits = fs.readdirSync(swarmAuditPath).filter(f => f.includes('audit'));
|
|
206
242
|
cvesFixed = Math.min(totalCves, Math.max(cvesFixed, audits.length));
|
|
207
243
|
} catch (e) {
|
|
208
244
|
// Ignore
|
|
@@ -218,17 +254,45 @@ function getSecurityStatus() {
|
|
|
218
254
|
};
|
|
219
255
|
}
|
|
220
256
|
|
|
221
|
-
// Get swarm status
|
|
257
|
+
// Get swarm status (cross-platform)
|
|
222
258
|
function getSwarmStatus() {
|
|
223
259
|
let activeAgents = 0;
|
|
224
260
|
let coordinationActive = false;
|
|
225
261
|
|
|
262
|
+
// Check swarm-activity.json first (works on all platforms)
|
|
263
|
+
const activityPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'swarm-activity.json');
|
|
264
|
+
if (fs.existsSync(activityPath)) {
|
|
265
|
+
try {
|
|
266
|
+
const data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
|
|
267
|
+
if (data.swarm) {
|
|
268
|
+
return {
|
|
269
|
+
activeAgents: data.swarm.agent_count || 0,
|
|
270
|
+
maxAgents: CONFIG.maxAgents,
|
|
271
|
+
coordinationActive: data.swarm.coordination_active || false,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
} catch (e) {
|
|
275
|
+
// Fall through to process detection
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Platform-specific process detection
|
|
280
|
+
const isWindows = process.platform === 'win32';
|
|
226
281
|
try {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
282
|
+
if (isWindows) {
|
|
283
|
+
// Windows: use tasklist
|
|
284
|
+
const ps = execSync('tasklist /FI "IMAGENAME eq node.exe" /NH 2>nul || echo ""', { encoding: 'utf-8' });
|
|
285
|
+
const nodeProcesses = (ps.match(/node\.exe/gi) || []).length;
|
|
286
|
+
activeAgents = Math.max(0, Math.floor(nodeProcesses / 3)); // Heuristic
|
|
287
|
+
coordinationActive = nodeProcesses > 0;
|
|
288
|
+
} else {
|
|
289
|
+
// Unix: use ps
|
|
290
|
+
const ps = execSync('ps aux 2>/dev/null | grep -c agentic-flow || echo "0"', { encoding: 'utf-8' });
|
|
291
|
+
activeAgents = Math.max(0, parseInt(ps.trim()) - 1);
|
|
292
|
+
coordinationActive = activeAgents > 0;
|
|
293
|
+
}
|
|
230
294
|
} catch (e) {
|
|
231
|
-
// Ignore errors
|
|
295
|
+
// Ignore errors - return defaults
|
|
232
296
|
}
|
|
233
297
|
|
|
234
298
|
return {
|
|
@@ -238,16 +302,46 @@ function getSwarmStatus() {
|
|
|
238
302
|
};
|
|
239
303
|
}
|
|
240
304
|
|
|
241
|
-
// Get system metrics (
|
|
305
|
+
// Get system metrics (cross-platform)
|
|
242
306
|
function getSystemMetrics() {
|
|
243
307
|
let memoryMB = 0;
|
|
244
308
|
let subAgents = 0;
|
|
245
309
|
|
|
310
|
+
// Check learning.json first (works on all platforms)
|
|
311
|
+
const learningMetricsPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'learning.json');
|
|
312
|
+
let intelligenceFromFile = null;
|
|
313
|
+
let contextFromFile = null;
|
|
314
|
+
if (fs.existsSync(learningMetricsPath)) {
|
|
315
|
+
try {
|
|
316
|
+
const data = JSON.parse(fs.readFileSync(learningMetricsPath, 'utf-8'));
|
|
317
|
+
if (data.routing?.accuracy !== undefined) {
|
|
318
|
+
intelligenceFromFile = Math.min(100, Math.floor(data.routing.accuracy));
|
|
319
|
+
}
|
|
320
|
+
if (data.sessions?.total !== undefined) {
|
|
321
|
+
contextFromFile = Math.min(100, data.sessions.total * 5);
|
|
322
|
+
}
|
|
323
|
+
} catch (e) {
|
|
324
|
+
// Fall through
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Platform-specific memory detection
|
|
329
|
+
const isWindows = process.platform === 'win32';
|
|
246
330
|
try {
|
|
247
|
-
|
|
248
|
-
|
|
331
|
+
if (isWindows) {
|
|
332
|
+
// Windows: use process.memoryUsage() (most reliable cross-platform)
|
|
333
|
+
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
334
|
+
} else {
|
|
335
|
+
// Unix: try ps command, fallback to process.memoryUsage()
|
|
336
|
+
try {
|
|
337
|
+
const mem = execSync('ps aux | grep -E "(node|agentic|claude)" | grep -v grep | awk \'{sum += \$6} END {print int(sum/1024)}\'', { encoding: 'utf-8' });
|
|
338
|
+
memoryMB = parseInt(mem.trim()) || 0;
|
|
339
|
+
} catch (e) {
|
|
340
|
+
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
249
343
|
} catch (e) {
|
|
250
|
-
// Fallback
|
|
344
|
+
// Fallback to Node.js memory API
|
|
251
345
|
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
252
346
|
}
|
|
253
347
|
|
|
@@ -255,17 +349,34 @@ function getSystemMetrics() {
|
|
|
255
349
|
const learning = getLearningStats();
|
|
256
350
|
|
|
257
351
|
// Intelligence % based on learned patterns (0 patterns = 0%, 1000+ = 100%)
|
|
258
|
-
const intelligencePct =
|
|
352
|
+
const intelligencePct = intelligenceFromFile !== null
|
|
353
|
+
? intelligenceFromFile
|
|
354
|
+
: Math.min(100, Math.floor((learning.patterns / 10) * 1));
|
|
259
355
|
|
|
260
356
|
// Context % based on session history (0 sessions = 0%, grows with usage)
|
|
261
|
-
const contextPct =
|
|
357
|
+
const contextPct = contextFromFile !== null
|
|
358
|
+
? contextFromFile
|
|
359
|
+
: Math.min(100, Math.floor(learning.sessions * 5));
|
|
262
360
|
|
|
263
|
-
// Count active sub-agents
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
361
|
+
// Count active sub-agents (cross-platform via metrics file)
|
|
362
|
+
const activityPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'swarm-activity.json');
|
|
363
|
+
if (fs.existsSync(activityPath)) {
|
|
364
|
+
try {
|
|
365
|
+
const data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
|
|
366
|
+
subAgents = data.processes?.estimated_agents || 0;
|
|
367
|
+
} catch (e) {
|
|
368
|
+
// Ignore
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Fallback to process detection on Unix only
|
|
373
|
+
if (subAgents === 0 && !isWindows) {
|
|
374
|
+
try {
|
|
375
|
+
const agents = execSync('ps aux 2>/dev/null | grep -c "claude-flow.*agent" || echo "0"', { encoding: 'utf-8' });
|
|
376
|
+
subAgents = Math.max(0, parseInt(agents.trim()) - 1);
|
|
377
|
+
} catch (e) {
|
|
378
|
+
// Ignore
|
|
379
|
+
}
|
|
269
380
|
}
|
|
270
381
|
|
|
271
382
|
return {
|
|
@@ -276,6 +387,221 @@ function getSystemMetrics() {
|
|
|
276
387
|
};
|
|
277
388
|
}
|
|
278
389
|
|
|
390
|
+
// Get ADR (Architecture Decision Records) status
|
|
391
|
+
function getADRStatus() {
|
|
392
|
+
const adrPaths = [
|
|
393
|
+
path.join(process.cwd(), 'docs', 'adrs'),
|
|
394
|
+
path.join(process.cwd(), 'docs', 'adr'),
|
|
395
|
+
path.join(process.cwd(), 'adr'),
|
|
396
|
+
path.join(process.cwd(), 'ADR'),
|
|
397
|
+
path.join(process.cwd(), '.claude-flow', 'adrs'),
|
|
398
|
+
path.join(process.cwd(), 'v3', 'implementation', 'adrs'),
|
|
399
|
+
path.join(process.cwd(), 'implementation', 'adrs'),
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
let count = 0;
|
|
403
|
+
let implemented = 0;
|
|
404
|
+
|
|
405
|
+
for (const adrPath of adrPaths) {
|
|
406
|
+
if (fs.existsSync(adrPath)) {
|
|
407
|
+
try {
|
|
408
|
+
const files = fs.readdirSync(adrPath).filter(f =>
|
|
409
|
+
f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\d{4}-/.test(f))
|
|
410
|
+
);
|
|
411
|
+
count = files.length;
|
|
412
|
+
|
|
413
|
+
// Check for implemented status in ADR files
|
|
414
|
+
for (const file of files) {
|
|
415
|
+
try {
|
|
416
|
+
const content = fs.readFileSync(path.join(adrPath, file), 'utf-8');
|
|
417
|
+
if (content.includes('Status: Implemented') || content.includes('status: implemented') ||
|
|
418
|
+
content.includes('Status: Accepted') || content.includes('status: accepted')) {
|
|
419
|
+
implemented++;
|
|
420
|
+
}
|
|
421
|
+
} catch (e) {
|
|
422
|
+
// Skip unreadable files
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
break;
|
|
426
|
+
} catch (e) {
|
|
427
|
+
// Ignore
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return { count, implemented };
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Get hooks status (enabled/registered hooks)
|
|
436
|
+
function getHooksStatus() {
|
|
437
|
+
let enabled = 0;
|
|
438
|
+
let total = 17; // V3 has 17 hook types
|
|
439
|
+
|
|
440
|
+
// Check .claude/settings.json for hooks config
|
|
441
|
+
const settingsPaths = [
|
|
442
|
+
path.join(process.cwd(), '.claude', 'settings.json'),
|
|
443
|
+
path.join(process.cwd(), '.claude', 'settings.local.json'),
|
|
444
|
+
];
|
|
445
|
+
|
|
446
|
+
for (const settingsPath of settingsPaths) {
|
|
447
|
+
if (fs.existsSync(settingsPath)) {
|
|
448
|
+
try {
|
|
449
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
450
|
+
if (settings.hooks) {
|
|
451
|
+
// Count enabled hooks
|
|
452
|
+
const hookTypes = Object.keys(settings.hooks);
|
|
453
|
+
enabled = hookTypes.filter(h => {
|
|
454
|
+
const hook = settings.hooks[h];
|
|
455
|
+
return hook && (hook.enabled !== false) && (hook.command || hook.script);
|
|
456
|
+
}).length;
|
|
457
|
+
}
|
|
458
|
+
break;
|
|
459
|
+
} catch (e) {
|
|
460
|
+
// Ignore parse errors
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Also check for hook files in .claude/hooks
|
|
466
|
+
const hooksDir = path.join(process.cwd(), '.claude', 'hooks');
|
|
467
|
+
if (fs.existsSync(hooksDir)) {
|
|
468
|
+
try {
|
|
469
|
+
const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh'));
|
|
470
|
+
enabled = Math.max(enabled, hookFiles.length);
|
|
471
|
+
} catch (e) {
|
|
472
|
+
// Ignore
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return { enabled, total };
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Get AgentDB memory stats
|
|
480
|
+
function getAgentDBStats() {
|
|
481
|
+
let vectorCount = 0;
|
|
482
|
+
let dbSizeKB = 0;
|
|
483
|
+
let namespaces = 0;
|
|
484
|
+
|
|
485
|
+
const dbPaths = [
|
|
486
|
+
path.join(process.cwd(), '.claude-flow', 'agentdb'),
|
|
487
|
+
path.join(process.cwd(), '.swarm', 'agentdb'),
|
|
488
|
+
path.join(process.cwd(), 'data', 'agentdb'),
|
|
489
|
+
path.join(process.cwd(), '.claude', 'memory'),
|
|
490
|
+
];
|
|
491
|
+
|
|
492
|
+
for (const dbPath of dbPaths) {
|
|
493
|
+
if (fs.existsSync(dbPath)) {
|
|
494
|
+
try {
|
|
495
|
+
const stats = fs.statSync(dbPath);
|
|
496
|
+
if (stats.isDirectory()) {
|
|
497
|
+
// Count database files and estimate vectors
|
|
498
|
+
const files = fs.readdirSync(dbPath);
|
|
499
|
+
namespaces = files.filter(f => f.endsWith('.db') || f.endsWith('.sqlite')).length;
|
|
500
|
+
|
|
501
|
+
// Calculate total size
|
|
502
|
+
for (const file of files) {
|
|
503
|
+
const filePath = path.join(dbPath, file);
|
|
504
|
+
const fileStat = fs.statSync(filePath);
|
|
505
|
+
if (fileStat.isFile()) {
|
|
506
|
+
dbSizeKB += fileStat.size / 1024;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Estimate vector count (~0.5KB per vector on average)
|
|
511
|
+
vectorCount = Math.floor(dbSizeKB / 0.5);
|
|
512
|
+
} else {
|
|
513
|
+
// Single file database
|
|
514
|
+
dbSizeKB = stats.size / 1024;
|
|
515
|
+
vectorCount = Math.floor(dbSizeKB / 0.5);
|
|
516
|
+
namespaces = 1;
|
|
517
|
+
}
|
|
518
|
+
break;
|
|
519
|
+
} catch (e) {
|
|
520
|
+
// Ignore
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Also check for vectors.json (simple vector store)
|
|
526
|
+
const vectorsPath = path.join(process.cwd(), '.claude-flow', 'vectors.json');
|
|
527
|
+
if (fs.existsSync(vectorsPath) && vectorCount === 0) {
|
|
528
|
+
try {
|
|
529
|
+
const data = JSON.parse(fs.readFileSync(vectorsPath, 'utf-8'));
|
|
530
|
+
if (Array.isArray(data)) {
|
|
531
|
+
vectorCount = data.length;
|
|
532
|
+
} else if (data.vectors) {
|
|
533
|
+
vectorCount = Object.keys(data.vectors).length;
|
|
534
|
+
}
|
|
535
|
+
} catch (e) {
|
|
536
|
+
// Ignore
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces };
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Get test statistics
|
|
544
|
+
function getTestStats() {
|
|
545
|
+
let testFiles = 0;
|
|
546
|
+
let testCases = 0;
|
|
547
|
+
|
|
548
|
+
const testDirs = [
|
|
549
|
+
path.join(process.cwd(), 'tests'),
|
|
550
|
+
path.join(process.cwd(), 'test'),
|
|
551
|
+
path.join(process.cwd(), '__tests__'),
|
|
552
|
+
path.join(process.cwd(), 'src', '__tests__'),
|
|
553
|
+
path.join(process.cwd(), 'v3', '__tests__'),
|
|
554
|
+
];
|
|
555
|
+
|
|
556
|
+
// Recursively count test files
|
|
557
|
+
function countTestFiles(dir, depth = 0) {
|
|
558
|
+
if (depth > 3) return; // Limit recursion
|
|
559
|
+
if (!fs.existsSync(dir)) return;
|
|
560
|
+
|
|
561
|
+
try {
|
|
562
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
563
|
+
for (const entry of entries) {
|
|
564
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
565
|
+
countTestFiles(path.join(dir, entry.name), depth + 1);
|
|
566
|
+
} else if (entry.isFile()) {
|
|
567
|
+
const name = entry.name;
|
|
568
|
+
if (name.includes('.test.') || name.includes('.spec.') ||
|
|
569
|
+
name.includes('_test.') || name.includes('_spec.') ||
|
|
570
|
+
name.startsWith('test_') || name.startsWith('spec_')) {
|
|
571
|
+
testFiles++;
|
|
572
|
+
|
|
573
|
+
// Try to estimate test cases from file
|
|
574
|
+
try {
|
|
575
|
+
const content = fs.readFileSync(path.join(dir, name), 'utf-8');
|
|
576
|
+
// Count it(), test(), describe() patterns
|
|
577
|
+
const itMatches = (content.match(/\bit\s*\(/g) || []).length;
|
|
578
|
+
const testMatches = (content.match(/\btest\s*\(/g) || []).length;
|
|
579
|
+
testCases += itMatches + testMatches;
|
|
580
|
+
} catch (e) {
|
|
581
|
+
// Estimate 3 tests per file if can't read
|
|
582
|
+
testCases += 3;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
} catch (e) {
|
|
588
|
+
// Ignore
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
for (const dir of testDirs) {
|
|
593
|
+
countTestFiles(dir);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Also check src directory for colocated tests
|
|
597
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
598
|
+
if (fs.existsSync(srcDir)) {
|
|
599
|
+
countTestFiles(srcDir);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return { testFiles, testCases };
|
|
603
|
+
}
|
|
604
|
+
|
|
279
605
|
// Generate progress bar
|
|
280
606
|
function progressBar(current, total) {
|
|
281
607
|
const width = 5;
|
|
@@ -291,6 +617,10 @@ function generateStatusline() {
|
|
|
291
617
|
const security = getSecurityStatus();
|
|
292
618
|
const swarm = getSwarmStatus();
|
|
293
619
|
const system = getSystemMetrics();
|
|
620
|
+
const adrs = getADRStatus();
|
|
621
|
+
const hooks = getHooksStatus();
|
|
622
|
+
const agentdb = getAgentDBStats();
|
|
623
|
+
const tests = getTestStats();
|
|
294
624
|
const lines = [];
|
|
295
625
|
|
|
296
626
|
// Header Line
|
|
@@ -313,28 +643,41 @@ function generateStatusline() {
|
|
|
313
643
|
`${c.brightYellow}⚡ 1.0x${c.reset} ${c.dim}→${c.reset} ${c.brightYellow}2.49x-7.47x${c.reset}`
|
|
314
644
|
);
|
|
315
645
|
|
|
316
|
-
// Line 2: Swarm + CVE + Memory + Context + Intelligence
|
|
646
|
+
// Line 2: Swarm + Hooks + CVE + Memory + Context + Intelligence
|
|
317
647
|
const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
|
|
318
648
|
const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
|
|
319
649
|
let securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
|
|
320
650
|
let securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
|
|
651
|
+
const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
|
|
321
652
|
|
|
322
653
|
lines.push(
|
|
323
654
|
`${c.brightYellow}🤖 Swarm${c.reset} ${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
|
|
324
655
|
`${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
|
|
656
|
+
`${c.brightBlue}🪝 ${hooksColor}${hooks.enabled}${c.reset}/${c.brightWhite}${hooks.total}${c.reset} ` +
|
|
325
657
|
`${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
|
|
326
658
|
`${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
|
|
327
|
-
`${c.brightGreen}📂 ${String(system.contextPct).padStart(3)}%${c.reset} ` +
|
|
328
659
|
`${c.dim}🧠 ${String(system.intelligencePct).padStart(3)}%${c.reset}`
|
|
329
660
|
);
|
|
330
661
|
|
|
331
|
-
// Line 3: Architecture status
|
|
662
|
+
// Line 3: Architecture status with ADRs, AgentDB, Tests
|
|
332
663
|
const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
|
|
664
|
+
const adrColor = adrs.count > 0 ? (adrs.implemented === adrs.count ? c.brightGreen : c.yellow) : c.dim;
|
|
665
|
+
const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
|
|
666
|
+
const testColor = tests.testFiles > 0 ? c.brightGreen : c.dim;
|
|
667
|
+
|
|
333
668
|
lines.push(
|
|
334
669
|
`${c.brightPurple}🔧 Architecture${c.reset} ` +
|
|
670
|
+
`${c.cyan}ADRs${c.reset} ${adrColor}●${adrs.implemented}/${adrs.count}${c.reset} ${c.dim}│${c.reset} ` +
|
|
335
671
|
`${c.cyan}DDD${c.reset} ${dddColor}●${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}│${c.reset} ` +
|
|
336
|
-
`${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset}
|
|
337
|
-
|
|
672
|
+
`${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset}`
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
// Line 4: Memory, Vectors, Tests
|
|
676
|
+
lines.push(
|
|
677
|
+
`${c.brightCyan}📊 AgentDB${c.reset} ` +
|
|
678
|
+
`${c.cyan}Vectors${c.reset} ${vectorColor}●${agentdb.vectorCount}${c.reset} ${c.dim}│${c.reset} ` +
|
|
679
|
+
`${c.cyan}Size${c.reset} ${c.brightWhite}${agentdb.dbSizeKB}KB${c.reset} ${c.dim}│${c.reset} ` +
|
|
680
|
+
`${c.cyan}Tests${c.reset} ${testColor}●${tests.testFiles}${c.reset} ${c.dim}(${tests.testCases} cases)${c.reset} ${c.dim}│${c.reset} ` +
|
|
338
681
|
`${c.cyan}Integration${c.reset} ${swarm.coordinationActive ? c.brightCyan : c.dim}●${c.reset}`
|
|
339
682
|
);
|
|
340
683
|
|
|
@@ -349,6 +692,10 @@ function generateJSON() {
|
|
|
349
692
|
security: getSecurityStatus(),
|
|
350
693
|
swarm: getSwarmStatus(),
|
|
351
694
|
system: getSystemMetrics(),
|
|
695
|
+
adrs: getADRStatus(),
|
|
696
|
+
hooks: getHooksStatus(),
|
|
697
|
+
agentdb: getAgentDBStats(),
|
|
698
|
+
tests: getTestStats(),
|
|
352
699
|
performance: {
|
|
353
700
|
flashAttentionTarget: '2.49x-7.47x',
|
|
354
701
|
searchImprovement: '150x-12,500x',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusline-generator.d.ts","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAEhE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"statusline-generator.d.ts","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAEhE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAgtBrE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CA2BnE"}
|