agentic-qe 3.5.0 → 3.5.2
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.
- package/.claude/agents/n8n/n8n-base-agent.md +3 -3
- package/.claude/agents/n8n/n8n-bdd-scenario-tester.md +2 -2
- package/.claude/agents/n8n/n8n-chaos-tester.md +2 -2
- package/.claude/agents/n8n/n8n-ci-orchestrator.md +2 -2
- package/.claude/agents/n8n/n8n-compliance-validator.md +2 -2
- package/.claude/agents/n8n/n8n-expression-validator.md +2 -2
- package/.claude/agents/n8n/n8n-integration-test.md +2 -2
- package/.claude/agents/n8n/n8n-monitoring-validator.md +2 -2
- package/.claude/agents/n8n/n8n-node-validator.md +2 -2
- package/.claude/agents/n8n/n8n-performance-tester.md +2 -2
- package/.claude/agents/n8n/n8n-security-auditor.md +2 -2
- package/.claude/agents/n8n/n8n-trigger-test.md +2 -2
- package/.claude/agents/n8n/n8n-unit-tester.md +2 -2
- package/.claude/agents/n8n/n8n-version-comparator.md +2 -2
- package/.claude/agents/n8n/n8n-workflow-executor.md +2 -2
- package/.claude/agents/subagents/qe-code-reviewer.md +2 -2
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +2 -2
- package/.claude/agents/subagents/qe-data-generator.md +2 -2
- package/.claude/agents/subagents/qe-flaky-investigator.md +2 -2
- package/.claude/agents/subagents/qe-integration-tester.md +2 -2
- package/.claude/agents/subagents/qe-performance-validator.md +2 -2
- package/.claude/agents/subagents/qe-security-auditor.md +2 -2
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +2 -2
- package/.claude/agents/subagents/qe-test-implementer.md +2 -2
- package/.claude/agents/subagents/qe-test-refactorer.md +2 -2
- package/.claude/agents/subagents/qe-test-writer.md +2 -2
- package/.claude/agents/v3/qe-accessibility-auditor.md +3 -3
- package/.claude/agents/v3/qe-bdd-generator.md +4 -4
- package/.claude/agents/v3/qe-chaos-engineer.md +3 -3
- package/.claude/agents/v3/qe-code-complexity.md +3 -3
- package/.claude/agents/v3/qe-code-intelligence.md +3 -3
- package/.claude/agents/v3/qe-contract-validator.md +3 -3
- package/.claude/agents/v3/qe-coverage-specialist.md +4 -4
- package/.claude/agents/v3/qe-defect-predictor.md +4 -4
- package/.claude/agents/v3/qe-dependency-mapper.md +3 -3
- package/.claude/agents/v3/qe-deployment-advisor.md +3 -3
- package/.claude/agents/v3/qe-flaky-hunter.md +3 -3
- package/.claude/agents/v3/qe-fleet-commander.md +3 -3
- package/.claude/agents/v3/qe-gap-detector.md +4 -4
- package/.claude/agents/v3/qe-graphql-tester.md +3 -3
- package/.claude/agents/v3/qe-impact-analyzer.md +3 -3
- package/.claude/agents/v3/qe-integration-architect.md +2 -2
- package/.claude/agents/v3/qe-integration-tester.md +3 -3
- package/.claude/agents/v3/qe-kg-builder.md +3 -3
- package/.claude/agents/v3/qe-learning-coordinator.md +24 -15
- package/.claude/agents/v3/qe-load-tester.md +3 -3
- package/.claude/agents/v3/qe-metrics-optimizer.md +3 -3
- package/.claude/agents/v3/qe-mutation-tester.md +3 -3
- package/.claude/agents/v3/qe-parallel-executor.md +4 -4
- package/.claude/agents/v3/qe-pattern-learner.md +16 -12
- package/.claude/agents/v3/qe-performance-tester.md +3 -3
- package/.claude/agents/v3/qe-product-factors-assessor.md +4 -4
- package/.claude/agents/v3/qe-property-tester.md +3 -3
- package/.claude/agents/v3/qe-quality-criteria-recommender.md +4 -4
- package/.claude/agents/v3/qe-quality-gate.md +4 -4
- package/.claude/agents/v3/qe-qx-partner.md +3 -3
- package/.claude/agents/v3/qe-regression-analyzer.md +3 -3
- package/.claude/agents/v3/qe-requirements-validator.md +4 -4
- package/.claude/agents/v3/qe-responsive-tester.md +3 -3
- package/.claude/agents/v3/qe-retry-handler.md +3 -3
- package/.claude/agents/v3/qe-risk-assessor.md +4 -4
- package/.claude/agents/v3/qe-root-cause-analyzer.md +3 -3
- package/.claude/agents/v3/qe-security-auditor.md +3 -3
- package/.claude/agents/v3/qe-security-scanner.md +3 -3
- package/.claude/agents/v3/qe-tdd-specialist.md +4 -4
- package/.claude/agents/v3/qe-test-architect.md +4 -4
- package/.claude/agents/v3/qe-test-idea-rewriter.md +3 -3
- package/.claude/agents/v3/qe-transfer-specialist.md +3 -3
- package/.claude/agents/v3/qe-visual-tester.md +3 -3
- package/.claude/agents/v3/reasoningbank-learner.md +4 -4
- package/.claude/agents/v3/subagents/qe-code-reviewer.md +3 -3
- package/.claude/agents/v3/subagents/qe-integration-reviewer.md +3 -3
- package/.claude/agents/v3/subagents/qe-performance-reviewer.md +3 -3
- package/.claude/agents/v3/subagents/qe-security-reviewer.md +3 -3
- package/.claude/agents/v3/subagents/qe-tdd-green.md +3 -3
- package/.claude/agents/v3/subagents/qe-tdd-red.md +3 -3
- package/.claude/agents/v3/subagents/qe-tdd-refactor.md +3 -3
- package/.claude/helpers/daemon-manager.sh +10 -10
- package/.claude/helpers/github-safe.js +10 -10
- package/.claude/helpers/statusline-v3.cjs +9 -3
- package/.claude/helpers/statusline.cjs +891 -59
- package/.claude/skills/agentic-quality-engineering/SKILL.md +6 -6
- package/.claude/skills/qcsd-cicd-swarm/SKILL.md +14 -14
- package/.claude/skills/qcsd-development-swarm/SKILL.md +14 -14
- package/.claude/skills/qcsd-ideation-swarm/SKILL.md +21 -21
- package/.claude/skills/qcsd-refinement-swarm/SKILL.md +22 -22
- package/.claude/skills/qe-iterative-loop/SKILL.md +4 -4
- package/.claude/skills/skills-manifest.json +17 -9
- package/.claude/skills/verification-quality/SKILL.md +0 -6
- package/CHANGELOG.md +52 -0
- package/README.md +22 -10
- package/package.json +5 -3
- package/v3/CHANGELOG.md +51 -3
- package/v3/README.md +9 -9
- package/v3/assets/agents/v3/qe-accessibility-auditor.md +12 -8
- package/v3/assets/agents/v3/qe-bdd-generator.md +13 -9
- package/v3/assets/agents/v3/qe-chaos-engineer.md +12 -8
- package/v3/assets/agents/v3/qe-code-complexity.md +12 -8
- package/v3/assets/agents/v3/qe-code-intelligence.md +12 -8
- package/v3/assets/agents/v3/qe-contract-validator.md +12 -8
- package/v3/assets/agents/v3/qe-coverage-specialist.md +13 -9
- package/v3/assets/agents/v3/qe-defect-predictor.md +13 -9
- package/v3/assets/agents/v3/qe-dependency-mapper.md +12 -8
- package/v3/assets/agents/v3/qe-deployment-advisor.md +12 -8
- package/v3/assets/agents/v3/qe-flaky-hunter.md +12 -8
- package/v3/assets/agents/v3/qe-fleet-commander.md +12 -8
- package/v3/assets/agents/v3/qe-gap-detector.md +13 -9
- package/v3/assets/agents/v3/qe-graphql-tester.md +12 -8
- package/v3/assets/agents/v3/qe-impact-analyzer.md +12 -8
- package/v3/assets/agents/v3/qe-integration-architect.md +2 -2
- package/v3/assets/agents/v3/qe-integration-tester.md +3 -3
- package/v3/assets/agents/v3/qe-kg-builder.md +12 -8
- package/v3/assets/agents/v3/qe-learning-coordinator.md +24 -15
- package/v3/assets/agents/v3/qe-load-tester.md +12 -8
- package/v3/assets/agents/v3/qe-metrics-optimizer.md +12 -8
- package/v3/assets/agents/v3/qe-mutation-tester.md +12 -8
- package/v3/assets/agents/v3/qe-parallel-executor.md +4 -4
- package/v3/assets/agents/v3/qe-pattern-learner.md +16 -12
- package/v3/assets/agents/v3/qe-performance-tester.md +12 -8
- package/v3/assets/agents/v3/qe-product-factors-assessor.md +4 -4
- package/v3/assets/agents/v3/qe-property-tester.md +12 -8
- package/v3/assets/agents/v3/qe-quality-criteria-recommender.md +4 -4
- package/v3/assets/agents/v3/qe-quality-gate.md +4 -4
- package/v3/assets/agents/v3/qe-qx-partner.md +12 -8
- package/v3/assets/agents/v3/qe-regression-analyzer.md +12 -8
- package/v3/assets/agents/v3/qe-requirements-validator.md +13 -9
- package/v3/assets/agents/v3/qe-responsive-tester.md +12 -8
- package/v3/assets/agents/v3/qe-retry-handler.md +12 -8
- package/v3/assets/agents/v3/qe-risk-assessor.md +13 -9
- package/v3/assets/agents/v3/qe-root-cause-analyzer.md +12 -8
- package/v3/assets/agents/v3/qe-security-auditor.md +12 -8
- package/v3/assets/agents/v3/qe-security-scanner.md +12 -8
- package/v3/assets/agents/v3/qe-tdd-specialist.md +4 -4
- package/v3/assets/agents/v3/qe-test-architect.md +13 -9
- package/v3/assets/agents/v3/qe-test-idea-rewriter.md +3 -3
- package/v3/assets/agents/v3/qe-transfer-specialist.md +12 -8
- package/v3/assets/agents/v3/qe-visual-tester.md +3 -3
- package/v3/assets/agents/v3/subagents/qe-code-reviewer.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-integration-reviewer.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-performance-reviewer.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-security-reviewer.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-tdd-green.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-tdd-red.md +12 -8
- package/v3/assets/agents/v3/subagents/qe-tdd-refactor.md +12 -8
- package/v3/assets/skills/agentic-quality-engineering/SKILL.md +6 -6
- package/v3/assets/skills/qcsd-ideation-swarm/SKILL.md +21 -21
- package/v3/assets/skills/qe-iterative-loop/SKILL.md +4 -4
- package/v3/dist/cli/bundle.js +2508 -816
- package/v3/dist/cli/commands/hooks.d.ts.map +1 -1
- package/v3/dist/cli/commands/hooks.js +34 -21
- package/v3/dist/cli/commands/hooks.js.map +1 -1
- package/v3/dist/cli/commands/learning.d.ts +23 -0
- package/v3/dist/cli/commands/learning.d.ts.map +1 -0
- package/v3/dist/cli/commands/learning.js +1448 -0
- package/v3/dist/cli/commands/learning.js.map +1 -0
- package/v3/dist/cli/index.js +2 -0
- package/v3/dist/cli/index.js.map +1 -1
- package/v3/dist/init/init-wizard.d.ts +2 -1
- package/v3/dist/init/init-wizard.d.ts.map +1 -1
- package/v3/dist/init/init-wizard.js +25 -23
- package/v3/dist/init/init-wizard.js.map +1 -1
- package/v3/dist/init/phases/07-hooks.d.ts +3 -0
- package/v3/dist/init/phases/07-hooks.d.ts.map +1 -1
- package/v3/dist/init/phases/07-hooks.js +12 -9
- package/v3/dist/init/phases/07-hooks.js.map +1 -1
- package/v3/dist/kernel/unified-memory.d.ts +8 -3
- package/v3/dist/kernel/unified-memory.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory.js +39 -9
- package/v3/dist/kernel/unified-memory.js.map +1 -1
- package/v3/dist/learning/aqe-learning-engine.d.ts +26 -0
- package/v3/dist/learning/aqe-learning-engine.d.ts.map +1 -1
- package/v3/dist/learning/aqe-learning-engine.js +116 -2
- package/v3/dist/learning/aqe-learning-engine.js.map +1 -1
- package/v3/dist/learning/index.d.ts +4 -0
- package/v3/dist/learning/index.d.ts.map +1 -1
- package/v3/dist/learning/index.js +8 -0
- package/v3/dist/learning/index.js.map +1 -1
- package/v3/dist/learning/metrics-tracker.d.ts +133 -0
- package/v3/dist/learning/metrics-tracker.d.ts.map +1 -0
- package/v3/dist/learning/metrics-tracker.js +396 -0
- package/v3/dist/learning/metrics-tracker.js.map +1 -0
- package/v3/dist/learning/pattern-lifecycle.d.ts +203 -0
- package/v3/dist/learning/pattern-lifecycle.d.ts.map +1 -0
- package/v3/dist/learning/pattern-lifecycle.js +614 -0
- package/v3/dist/learning/pattern-lifecycle.js.map +1 -0
- package/v3/dist/learning/sqlite-persistence.d.ts +30 -0
- package/v3/dist/learning/sqlite-persistence.d.ts.map +1 -1
- package/v3/dist/learning/sqlite-persistence.js +137 -0
- package/v3/dist/learning/sqlite-persistence.js.map +1 -1
- package/v3/dist/mcp/bundle.js +104568 -102038
- package/v3/dist/mcp/handlers/handler-factory.d.ts +5 -0
- package/v3/dist/mcp/handlers/handler-factory.d.ts.map +1 -1
- package/v3/dist/mcp/handlers/handler-factory.js +84 -0
- package/v3/dist/mcp/handlers/handler-factory.js.map +1 -1
- package/v3/dist/mcp/services/task-router.d.ts +32 -0
- package/v3/dist/mcp/services/task-router.d.ts.map +1 -1
- package/v3/dist/mcp/services/task-router.js +28 -0
- package/v3/dist/mcp/services/task-router.js.map +1 -1
- package/v3/dist/workers/workers/learning-consolidation.d.ts +29 -0
- package/v3/dist/workers/workers/learning-consolidation.d.ts.map +1 -1
- package/v3/dist/workers/workers/learning-consolidation.js +294 -3
- package/v3/dist/workers/workers/learning-consolidation.js.map +1 -1
- package/v3/package.json +3 -2
|
@@ -24,7 +24,7 @@ const CONFIG = {
|
|
|
24
24
|
showPerformance: true,
|
|
25
25
|
refreshInterval: 5000,
|
|
26
26
|
maxAgents: 15,
|
|
27
|
-
topology: 'hierarchical
|
|
27
|
+
topology: 'hierarchical',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
// ANSI colors
|
|
@@ -51,7 +51,7 @@ const c = {
|
|
|
51
51
|
function getUserInfo() {
|
|
52
52
|
let name = 'user';
|
|
53
53
|
let gitBranch = '';
|
|
54
|
-
let modelName = '
|
|
54
|
+
let modelName = '🤖 Claude Code';
|
|
55
55
|
|
|
56
56
|
try {
|
|
57
57
|
name = execSync('git config user.name 2>/dev/null || echo "user"', { encoding: 'utf-8' }).trim();
|
|
@@ -60,16 +60,86 @@ function getUserInfo() {
|
|
|
60
60
|
// Ignore errors
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// Auto-detect model from Claude Code's config
|
|
64
|
+
try {
|
|
65
|
+
const homedir = require('os').homedir();
|
|
66
|
+
const claudeConfigPath = path.join(homedir, '.claude.json');
|
|
67
|
+
if (fs.existsSync(claudeConfigPath)) {
|
|
68
|
+
const claudeConfig = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf-8'));
|
|
69
|
+
// Try to find lastModelUsage - check current dir and parent dirs
|
|
70
|
+
let lastModelUsage = null;
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
if (claudeConfig.projects) {
|
|
73
|
+
// Try exact match first, then check if cwd starts with any project path
|
|
74
|
+
for (const [projectPath, projectConfig] of Object.entries(claudeConfig.projects)) {
|
|
75
|
+
if (cwd === projectPath || cwd.startsWith(projectPath + '/')) {
|
|
76
|
+
lastModelUsage = projectConfig.lastModelUsage;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (lastModelUsage) {
|
|
82
|
+
const modelIds = Object.keys(lastModelUsage);
|
|
83
|
+
if (modelIds.length > 0) {
|
|
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
|
+
let modelId = modelIds[modelIds.length - 1];
|
|
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;
|
|
96
|
+
modelId = id;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Parse model ID to human-readable name
|
|
102
|
+
if (modelId.includes('opus')) modelName = 'Opus 4.5';
|
|
103
|
+
else if (modelId.includes('sonnet')) modelName = 'Sonnet 4';
|
|
104
|
+
else if (modelId.includes('haiku')) modelName = 'Haiku 4.5';
|
|
105
|
+
else modelName = modelId.split('-').slice(1, 3).join(' ');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (e) {
|
|
110
|
+
// Fallback to Unknown if can't read config
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Fallback: check project's .claude/settings.json for model
|
|
114
|
+
if (modelName === 'Unknown') {
|
|
115
|
+
try {
|
|
116
|
+
const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
|
|
117
|
+
if (fs.existsSync(settingsPath)) {
|
|
118
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
119
|
+
if (settings.model) {
|
|
120
|
+
if (settings.model.includes('opus')) modelName = 'Opus 4.5';
|
|
121
|
+
else if (settings.model.includes('sonnet')) modelName = 'Sonnet 4';
|
|
122
|
+
else if (settings.model.includes('haiku')) modelName = 'Haiku 4.5';
|
|
123
|
+
else modelName = settings.model.split('-').slice(1, 3).join(' ');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
// Keep Unknown
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
63
131
|
return { name, gitBranch, modelName };
|
|
64
132
|
}
|
|
65
133
|
|
|
66
134
|
// Get learning stats from memory database
|
|
67
135
|
function getLearningStats() {
|
|
68
136
|
const memoryPaths = [
|
|
69
|
-
path.join(process.cwd(), '.agentic-qe', 'memory.db'), // AQE v3 primary location
|
|
70
137
|
path.join(process.cwd(), '.swarm', 'memory.db'),
|
|
138
|
+
path.join(process.cwd(), '.claude-flow', 'memory.db'),
|
|
71
139
|
path.join(process.cwd(), '.claude', 'memory.db'),
|
|
72
140
|
path.join(process.cwd(), 'data', 'memory.db'),
|
|
141
|
+
path.join(process.cwd(), 'memory.db'),
|
|
142
|
+
path.join(process.cwd(), '.agentdb', 'memory.db'),
|
|
73
143
|
];
|
|
74
144
|
|
|
75
145
|
let patterns = 0;
|
|
@@ -112,6 +182,31 @@ function getLearningStats() {
|
|
|
112
182
|
function getV3Progress() {
|
|
113
183
|
const learning = getLearningStats();
|
|
114
184
|
|
|
185
|
+
// Check for metrics file first (created by init)
|
|
186
|
+
const metricsPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'v3-progress.json');
|
|
187
|
+
if (fs.existsSync(metricsPath)) {
|
|
188
|
+
try {
|
|
189
|
+
const data = JSON.parse(fs.readFileSync(metricsPath, 'utf-8'));
|
|
190
|
+
if (data.domains) {
|
|
191
|
+
const domainsCompleted = data.domains.completed || 0;
|
|
192
|
+
const totalDomains = data.domains.total || 5;
|
|
193
|
+
// Use ddd.progress if provided and > 0, otherwise calculate from domains
|
|
194
|
+
const dddProgress = (data.ddd?.progress > 0)
|
|
195
|
+
? data.ddd.progress
|
|
196
|
+
: Math.min(100, Math.floor((domainsCompleted / totalDomains) * 100));
|
|
197
|
+
return {
|
|
198
|
+
domainsCompleted,
|
|
199
|
+
totalDomains,
|
|
200
|
+
dddProgress,
|
|
201
|
+
patternsLearned: data.learning?.patternsLearned || learning.patterns,
|
|
202
|
+
sessionsCompleted: data.learning?.sessionsCompleted || learning.sessions
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
} catch (e) {
|
|
206
|
+
// Fall through to pattern-based calculation
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
115
210
|
// DDD progress based on actual learned patterns
|
|
116
211
|
// New install: 0 patterns = 0/5 domains, 0% DDD
|
|
117
212
|
// As patterns grow: 10+ patterns = 1 domain, 50+ = 2, 100+ = 3, 200+ = 4, 500+ = 5
|
|
@@ -134,45 +229,46 @@ function getV3Progress() {
|
|
|
134
229
|
};
|
|
135
230
|
}
|
|
136
231
|
|
|
137
|
-
// Get security status based on actual scans
|
|
232
|
+
// Get security status based on actual scans
|
|
138
233
|
function getSecurityStatus() {
|
|
139
234
|
const totalCves = 3;
|
|
140
235
|
let cvesFixed = 0;
|
|
141
236
|
|
|
142
|
-
//
|
|
143
|
-
const
|
|
144
|
-
if (fs.existsSync(
|
|
237
|
+
// Check audit-status.json first (created by init)
|
|
238
|
+
const auditStatusPath = path.join(process.cwd(), '.claude-flow', 'security', 'audit-status.json');
|
|
239
|
+
if (fs.existsSync(auditStatusPath)) {
|
|
145
240
|
try {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
241
|
+
const data = JSON.parse(fs.readFileSync(auditStatusPath, 'utf-8'));
|
|
242
|
+
return {
|
|
243
|
+
status: data.status || 'PENDING',
|
|
244
|
+
cvesFixed: data.cvesFixed || 0,
|
|
245
|
+
totalCves: data.totalCves || 3,
|
|
246
|
+
};
|
|
150
247
|
} catch (e) {
|
|
151
|
-
//
|
|
248
|
+
// Fall through to scan directory check
|
|
152
249
|
}
|
|
153
250
|
}
|
|
154
251
|
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
252
|
+
// Check for security scan results in memory
|
|
253
|
+
const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
|
|
254
|
+
if (fs.existsSync(scanResultsPath)) {
|
|
255
|
+
try {
|
|
256
|
+
const scans = fs.readdirSync(scanResultsPath).filter(f => f.endsWith('.json'));
|
|
257
|
+
// Each successful scan file = 1 CVE addressed
|
|
258
|
+
cvesFixed = Math.min(totalCves, scans.length);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
// Ignore
|
|
165
261
|
}
|
|
262
|
+
}
|
|
166
263
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
264
|
+
// Also check .swarm/security for audit results
|
|
265
|
+
const swarmAuditPath = path.join(process.cwd(), '.swarm', 'security');
|
|
266
|
+
if (fs.existsSync(swarmAuditPath)) {
|
|
267
|
+
try {
|
|
268
|
+
const audits = fs.readdirSync(swarmAuditPath).filter(f => f.includes('audit'));
|
|
269
|
+
cvesFixed = Math.min(totalCves, Math.max(cvesFixed, audits.length));
|
|
270
|
+
} catch (e) {
|
|
271
|
+
// Ignore
|
|
176
272
|
}
|
|
177
273
|
}
|
|
178
274
|
|
|
@@ -185,17 +281,69 @@ function getSecurityStatus() {
|
|
|
185
281
|
};
|
|
186
282
|
}
|
|
187
283
|
|
|
188
|
-
// Get swarm status
|
|
284
|
+
// Get swarm status (cross-platform)
|
|
189
285
|
function getSwarmStatus() {
|
|
190
286
|
let activeAgents = 0;
|
|
191
287
|
let coordinationActive = false;
|
|
192
288
|
|
|
289
|
+
// Check swarm-activity.json first (works on all platforms)
|
|
290
|
+
const activityPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'swarm-activity.json');
|
|
291
|
+
if (fs.existsSync(activityPath)) {
|
|
292
|
+
try {
|
|
293
|
+
const data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
|
|
294
|
+
if (data.swarm) {
|
|
295
|
+
return {
|
|
296
|
+
activeAgents: data.swarm.agent_count || 0,
|
|
297
|
+
maxAgents: CONFIG.maxAgents,
|
|
298
|
+
coordinationActive: data.swarm.coordination_active || data.swarm.active || false,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
} catch (e) {
|
|
302
|
+
// Fall through to v3-progress.json check
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Also check v3-progress.json for swarm data (secondary source)
|
|
307
|
+
const progressPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'v3-progress.json');
|
|
308
|
+
if (fs.existsSync(progressPath)) {
|
|
309
|
+
try {
|
|
310
|
+
const data = JSON.parse(fs.readFileSync(progressPath, 'utf-8'));
|
|
311
|
+
if (data.swarm) {
|
|
312
|
+
return {
|
|
313
|
+
activeAgents: data.swarm.activeAgents || data.swarm.agent_count || 0,
|
|
314
|
+
maxAgents: data.swarm.totalAgents || CONFIG.maxAgents,
|
|
315
|
+
coordinationActive: data.swarm.active || (data.swarm.activeAgents > 0),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
} catch (e) {
|
|
319
|
+
// Fall through to process detection
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Platform-specific process detection (fallback)
|
|
324
|
+
const isWindows = process.platform === 'win32';
|
|
193
325
|
try {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
326
|
+
if (isWindows) {
|
|
327
|
+
// Windows: use tasklist
|
|
328
|
+
const ps = execSync('tasklist /FI "IMAGENAME eq node.exe" /NH 2>nul || echo ""', { encoding: 'utf-8' });
|
|
329
|
+
const nodeProcesses = (ps.match(/node\.exe/gi) || []).length;
|
|
330
|
+
activeAgents = Math.max(0, Math.floor(nodeProcesses / 3)); // Heuristic
|
|
331
|
+
coordinationActive = nodeProcesses > 0;
|
|
332
|
+
} else {
|
|
333
|
+
// Unix: use ps - check for various agent process patterns
|
|
334
|
+
try {
|
|
335
|
+
const ps = execSync('ps aux 2>/dev/null | grep -E "(agentic-flow|claude-flow|mcp.*server)" | grep -v grep | wc -l', { encoding: 'utf-8' });
|
|
336
|
+
activeAgents = Math.max(0, parseInt(ps.trim()));
|
|
337
|
+
coordinationActive = activeAgents > 0;
|
|
338
|
+
} catch (e) {
|
|
339
|
+
// Fallback to simple agentic-flow check
|
|
340
|
+
const ps = execSync('ps aux 2>/dev/null | grep -c agentic-flow || echo "0"', { encoding: 'utf-8' });
|
|
341
|
+
activeAgents = Math.max(0, parseInt(ps.trim()) - 1);
|
|
342
|
+
coordinationActive = activeAgents > 0;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
197
345
|
} catch (e) {
|
|
198
|
-
// Ignore errors
|
|
346
|
+
// Ignore errors - return defaults
|
|
199
347
|
}
|
|
200
348
|
|
|
201
349
|
return {
|
|
@@ -205,34 +353,160 @@ function getSwarmStatus() {
|
|
|
205
353
|
};
|
|
206
354
|
}
|
|
207
355
|
|
|
208
|
-
// Get system metrics (
|
|
356
|
+
// Get system metrics (cross-platform)
|
|
209
357
|
function getSystemMetrics() {
|
|
210
358
|
let memoryMB = 0;
|
|
211
359
|
let subAgents = 0;
|
|
212
360
|
|
|
361
|
+
// Check learning.json first (works on all platforms)
|
|
362
|
+
const learningMetricsPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'learning.json');
|
|
363
|
+
let intelligenceFromFile = null;
|
|
364
|
+
let contextFromFile = null;
|
|
365
|
+
if (fs.existsSync(learningMetricsPath)) {
|
|
366
|
+
try {
|
|
367
|
+
const data = JSON.parse(fs.readFileSync(learningMetricsPath, 'utf-8'));
|
|
368
|
+
if (data.routing?.accuracy !== undefined) {
|
|
369
|
+
intelligenceFromFile = Math.min(100, Math.floor(data.routing.accuracy));
|
|
370
|
+
}
|
|
371
|
+
if (data.sessions?.total !== undefined) {
|
|
372
|
+
contextFromFile = Math.min(100, data.sessions.total * 5);
|
|
373
|
+
}
|
|
374
|
+
} catch (e) {
|
|
375
|
+
// Fall through
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Platform-specific memory detection
|
|
380
|
+
const isWindows = process.platform === 'win32';
|
|
213
381
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
382
|
+
if (isWindows) {
|
|
383
|
+
// Windows: use process.memoryUsage() (most reliable cross-platform)
|
|
384
|
+
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
385
|
+
} else {
|
|
386
|
+
// Unix: try ps command, fallback to process.memoryUsage()
|
|
387
|
+
try {
|
|
388
|
+
const mem = execSync('ps aux | grep -E "(node|agentic|claude)" | grep -v grep | awk \'{sum += \$6} END {print int(sum/1024)}\'', { encoding: 'utf-8' });
|
|
389
|
+
memoryMB = parseInt(mem.trim()) || 0;
|
|
390
|
+
} catch (e) {
|
|
391
|
+
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
216
394
|
} catch (e) {
|
|
217
|
-
// Fallback
|
|
395
|
+
// Fallback to Node.js memory API
|
|
218
396
|
memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
219
397
|
}
|
|
220
398
|
|
|
221
399
|
// Get learning stats for intelligence %
|
|
222
400
|
const learning = getLearningStats();
|
|
223
401
|
|
|
224
|
-
//
|
|
225
|
-
const
|
|
402
|
+
// Also get AgentDB stats for fallback intelligence calculation
|
|
403
|
+
const agentdbStats = getAgentDBStats();
|
|
404
|
+
|
|
405
|
+
// Intelligence % based on learned patterns, vectors, or project maturity
|
|
406
|
+
// Calculate all sources and take the maximum
|
|
407
|
+
let intelligencePct = 0;
|
|
408
|
+
|
|
409
|
+
if (intelligenceFromFile !== null) {
|
|
410
|
+
intelligencePct = intelligenceFromFile;
|
|
411
|
+
} else {
|
|
412
|
+
// Calculate from multiple sources and take the best
|
|
413
|
+
const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 10)) : 0;
|
|
414
|
+
const fromVectors = agentdbStats.vectorCount > 0 ? Math.min(100, Math.floor(agentdbStats.vectorCount / 100)) : 0;
|
|
415
|
+
|
|
416
|
+
intelligencePct = Math.max(fromPatterns, fromVectors);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// If still 0, use project maturity fallback
|
|
420
|
+
if (intelligencePct === 0) {
|
|
421
|
+
// Final fallback: estimate from project maturity indicators
|
|
422
|
+
let maturityScore = 0;
|
|
423
|
+
|
|
424
|
+
// Check git commit count (proxy for project development)
|
|
425
|
+
try {
|
|
426
|
+
const commitCount = parseInt(execSync('git rev-list --count HEAD 2>/dev/null || echo "0"', { encoding: 'utf-8' }).trim());
|
|
427
|
+
maturityScore += Math.min(30, Math.floor(commitCount / 10)); // Max 30% from commits
|
|
428
|
+
} catch (e) { /* ignore */ }
|
|
429
|
+
|
|
430
|
+
// Check for Claude session history
|
|
431
|
+
const sessionPaths = [
|
|
432
|
+
path.join(process.cwd(), '.claude', 'sessions'),
|
|
433
|
+
path.join(process.cwd(), '.claude-flow', 'sessions'),
|
|
434
|
+
];
|
|
435
|
+
for (const sessPath of sessionPaths) {
|
|
436
|
+
if (fs.existsSync(sessPath)) {
|
|
437
|
+
try {
|
|
438
|
+
const sessions = fs.readdirSync(sessPath).filter(f => f.endsWith('.json')).length;
|
|
439
|
+
maturityScore += Math.min(20, sessions * 2); // Max 20% from sessions
|
|
440
|
+
break;
|
|
441
|
+
} catch (e) { /* ignore */ }
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Check for source files (indicates codebase size)
|
|
446
|
+
try {
|
|
447
|
+
const srcDirs = ['src', 'lib', 'app', 'packages'];
|
|
448
|
+
for (const dir of srcDirs) {
|
|
449
|
+
const dirPath = path.join(process.cwd(), dir);
|
|
450
|
+
if (fs.existsSync(dirPath)) {
|
|
451
|
+
maturityScore += 15; // Base score for having source dir
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
} catch (e) { /* ignore */ }
|
|
456
|
+
|
|
457
|
+
// Check for test files
|
|
458
|
+
try {
|
|
459
|
+
const testDirs = ['tests', 'test', '__tests__', 'spec'];
|
|
460
|
+
for (const dir of testDirs) {
|
|
461
|
+
const dirPath = path.join(process.cwd(), dir);
|
|
462
|
+
if (fs.existsSync(dirPath)) {
|
|
463
|
+
maturityScore += 10; // Bonus for having tests
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
} catch (e) { /* ignore */ }
|
|
468
|
+
|
|
469
|
+
// Check for .claude directory (Claude Code usage)
|
|
470
|
+
if (fs.existsSync(path.join(process.cwd(), '.claude'))) {
|
|
471
|
+
maturityScore += 15; // Bonus for Claude Code integration
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Check for config files (project maturity)
|
|
475
|
+
const configFiles = ['package.json', 'tsconfig.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'];
|
|
476
|
+
for (const cfg of configFiles) {
|
|
477
|
+
if (fs.existsSync(path.join(process.cwd(), cfg))) {
|
|
478
|
+
maturityScore += 5;
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
intelligencePct = Math.min(100, maturityScore);
|
|
484
|
+
}
|
|
226
485
|
|
|
227
486
|
// Context % based on session history (0 sessions = 0%, grows with usage)
|
|
228
|
-
const contextPct =
|
|
487
|
+
const contextPct = contextFromFile !== null
|
|
488
|
+
? contextFromFile
|
|
489
|
+
: Math.min(100, Math.floor(learning.sessions * 5));
|
|
229
490
|
|
|
230
|
-
// Count active sub-agents
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
491
|
+
// Count active sub-agents (cross-platform via metrics file)
|
|
492
|
+
const activityPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'swarm-activity.json');
|
|
493
|
+
if (fs.existsSync(activityPath)) {
|
|
494
|
+
try {
|
|
495
|
+
const data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
|
|
496
|
+
subAgents = data.processes?.estimated_agents || 0;
|
|
497
|
+
} catch (e) {
|
|
498
|
+
// Ignore
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Fallback to process detection on Unix only
|
|
503
|
+
if (subAgents === 0 && !isWindows) {
|
|
504
|
+
try {
|
|
505
|
+
const agents = execSync('ps aux 2>/dev/null | grep -c "claude-flow.*agent" || echo "0"', { encoding: 'utf-8' });
|
|
506
|
+
subAgents = Math.max(0, parseInt(agents.trim()) - 1);
|
|
507
|
+
} catch (e) {
|
|
508
|
+
// Ignore
|
|
509
|
+
}
|
|
236
510
|
}
|
|
237
511
|
|
|
238
512
|
return {
|
|
@@ -243,6 +517,474 @@ function getSystemMetrics() {
|
|
|
243
517
|
};
|
|
244
518
|
}
|
|
245
519
|
|
|
520
|
+
// Get ADR (Architecture Decision Records) status
|
|
521
|
+
function getADRStatus() {
|
|
522
|
+
const adrPaths = [
|
|
523
|
+
path.join(process.cwd(), 'docs', 'adrs'),
|
|
524
|
+
path.join(process.cwd(), 'docs', 'adr'),
|
|
525
|
+
path.join(process.cwd(), 'adr'),
|
|
526
|
+
path.join(process.cwd(), 'ADR'),
|
|
527
|
+
path.join(process.cwd(), '.claude-flow', 'adrs'),
|
|
528
|
+
path.join(process.cwd(), 'v3', 'implementation', 'adrs'),
|
|
529
|
+
path.join(process.cwd(), 'implementation', 'adrs'),
|
|
530
|
+
];
|
|
531
|
+
|
|
532
|
+
let count = 0;
|
|
533
|
+
let implemented = 0;
|
|
534
|
+
|
|
535
|
+
for (const adrPath of adrPaths) {
|
|
536
|
+
if (fs.existsSync(adrPath)) {
|
|
537
|
+
try {
|
|
538
|
+
const files = fs.readdirSync(adrPath).filter(f =>
|
|
539
|
+
f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\d{4}-/.test(f))
|
|
540
|
+
);
|
|
541
|
+
count = files.length;
|
|
542
|
+
|
|
543
|
+
// Check for implemented status in ADR files
|
|
544
|
+
for (const file of files) {
|
|
545
|
+
try {
|
|
546
|
+
const content = fs.readFileSync(path.join(adrPath, file), 'utf-8');
|
|
547
|
+
if (content.includes('Status: Implemented') || content.includes('status: implemented') ||
|
|
548
|
+
content.includes('Status: Accepted') || content.includes('status: accepted')) {
|
|
549
|
+
implemented++;
|
|
550
|
+
}
|
|
551
|
+
} catch (e) {
|
|
552
|
+
// Skip unreadable files
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
break;
|
|
556
|
+
} catch (e) {
|
|
557
|
+
// Ignore
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return { count, implemented };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Get hooks status (enabled/registered hooks)
|
|
566
|
+
function getHooksStatus() {
|
|
567
|
+
let enabled = 0;
|
|
568
|
+
let total = 17; // V3 has 17 hook types
|
|
569
|
+
|
|
570
|
+
// Check .claude/settings.json for hooks config
|
|
571
|
+
const settingsPaths = [
|
|
572
|
+
path.join(process.cwd(), '.claude', 'settings.json'),
|
|
573
|
+
path.join(process.cwd(), '.claude', 'settings.local.json'),
|
|
574
|
+
];
|
|
575
|
+
|
|
576
|
+
for (const settingsPath of settingsPaths) {
|
|
577
|
+
if (fs.existsSync(settingsPath)) {
|
|
578
|
+
try {
|
|
579
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
580
|
+
if (settings.hooks) {
|
|
581
|
+
// Claude Code native hooks format: PreToolUse, PostToolUse, SessionStart, etc.
|
|
582
|
+
const hookCategories = Object.keys(settings.hooks);
|
|
583
|
+
for (const category of hookCategories) {
|
|
584
|
+
const categoryHooks = settings.hooks[category];
|
|
585
|
+
if (Array.isArray(categoryHooks) && categoryHooks.length > 0) {
|
|
586
|
+
// Count categories with at least one hook defined
|
|
587
|
+
enabled++;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
break;
|
|
592
|
+
} catch (e) {
|
|
593
|
+
// Ignore parse errors
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Also check for hook files in .claude/hooks
|
|
599
|
+
const hooksDir = path.join(process.cwd(), '.claude', 'hooks');
|
|
600
|
+
if (fs.existsSync(hooksDir)) {
|
|
601
|
+
try {
|
|
602
|
+
const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh'));
|
|
603
|
+
enabled = Math.max(enabled, hookFiles.length);
|
|
604
|
+
} catch (e) {
|
|
605
|
+
// Ignore
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return { enabled, total };
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Get AgentDB memory stats
|
|
613
|
+
function getAgentDBStats() {
|
|
614
|
+
let vectorCount = 0;
|
|
615
|
+
let dbSizeKB = 0;
|
|
616
|
+
let namespaces = 0;
|
|
617
|
+
let hasHnsw = false;
|
|
618
|
+
|
|
619
|
+
// Check for database directories
|
|
620
|
+
const dbDirPaths = [
|
|
621
|
+
path.join(process.cwd(), '.claude-flow', 'agentdb'),
|
|
622
|
+
path.join(process.cwd(), '.swarm', 'agentdb'),
|
|
623
|
+
path.join(process.cwd(), 'data', 'agentdb'),
|
|
624
|
+
path.join(process.cwd(), '.claude', 'memory'),
|
|
625
|
+
path.join(process.cwd(), '.agentdb'),
|
|
626
|
+
];
|
|
627
|
+
|
|
628
|
+
// Check for direct database files (memory.db, etc.)
|
|
629
|
+
const dbFilePaths = [
|
|
630
|
+
path.join(process.cwd(), '.swarm', 'memory.db'),
|
|
631
|
+
path.join(process.cwd(), '.claude-flow', 'memory.db'),
|
|
632
|
+
path.join(process.cwd(), '.claude', 'memory.db'),
|
|
633
|
+
path.join(process.cwd(), 'data', 'memory.db'),
|
|
634
|
+
path.join(process.cwd(), 'memory.db'),
|
|
635
|
+
];
|
|
636
|
+
|
|
637
|
+
// Check for HNSW index files
|
|
638
|
+
const hnswPaths = [
|
|
639
|
+
path.join(process.cwd(), '.swarm', 'hnsw.index'),
|
|
640
|
+
path.join(process.cwd(), '.claude-flow', 'hnsw.index'),
|
|
641
|
+
path.join(process.cwd(), 'data', 'hnsw.index'),
|
|
642
|
+
];
|
|
643
|
+
|
|
644
|
+
// Check direct database files first
|
|
645
|
+
for (const dbFile of dbFilePaths) {
|
|
646
|
+
if (fs.existsSync(dbFile)) {
|
|
647
|
+
try {
|
|
648
|
+
const stats = fs.statSync(dbFile);
|
|
649
|
+
dbSizeKB = stats.size / 1024;
|
|
650
|
+
// Estimate vectors: ~2KB per vector for SQLite with embeddings
|
|
651
|
+
vectorCount = Math.floor(dbSizeKB / 2);
|
|
652
|
+
namespaces = 1;
|
|
653
|
+
break;
|
|
654
|
+
} catch (e) {
|
|
655
|
+
// Ignore
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Check database directories if no direct file found
|
|
661
|
+
if (vectorCount === 0) {
|
|
662
|
+
for (const dbPath of dbDirPaths) {
|
|
663
|
+
if (fs.existsSync(dbPath)) {
|
|
664
|
+
try {
|
|
665
|
+
const stats = fs.statSync(dbPath);
|
|
666
|
+
if (stats.isDirectory()) {
|
|
667
|
+
const files = fs.readdirSync(dbPath);
|
|
668
|
+
namespaces = files.filter(f => f.endsWith('.db') || f.endsWith('.sqlite')).length;
|
|
669
|
+
|
|
670
|
+
for (const file of files) {
|
|
671
|
+
const filePath = path.join(dbPath, file);
|
|
672
|
+
const fileStat = fs.statSync(filePath);
|
|
673
|
+
if (fileStat.isFile()) {
|
|
674
|
+
dbSizeKB += fileStat.size / 1024;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
vectorCount = Math.floor(dbSizeKB / 2);
|
|
679
|
+
}
|
|
680
|
+
break;
|
|
681
|
+
} catch (e) {
|
|
682
|
+
// Ignore
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Check for HNSW index (indicates vector search capability)
|
|
689
|
+
for (const hnswPath of hnswPaths) {
|
|
690
|
+
if (fs.existsSync(hnswPath)) {
|
|
691
|
+
hasHnsw = true;
|
|
692
|
+
try {
|
|
693
|
+
const stats = fs.statSync(hnswPath);
|
|
694
|
+
// HNSW index: ~0.5KB per vector
|
|
695
|
+
const hnswVectors = Math.floor(stats.size / 1024 / 0.5);
|
|
696
|
+
vectorCount = Math.max(vectorCount, hnswVectors);
|
|
697
|
+
} catch (e) {
|
|
698
|
+
// Ignore
|
|
699
|
+
}
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Also check for vectors.json (simple vector store)
|
|
705
|
+
const vectorsPath = path.join(process.cwd(), '.claude-flow', 'vectors.json');
|
|
706
|
+
if (fs.existsSync(vectorsPath) && vectorCount === 0) {
|
|
707
|
+
try {
|
|
708
|
+
const data = JSON.parse(fs.readFileSync(vectorsPath, 'utf-8'));
|
|
709
|
+
if (Array.isArray(data)) {
|
|
710
|
+
vectorCount = data.length;
|
|
711
|
+
} else if (data.vectors) {
|
|
712
|
+
vectorCount = Object.keys(data.vectors).length;
|
|
713
|
+
}
|
|
714
|
+
} catch (e) {
|
|
715
|
+
// Ignore
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces, hasHnsw };
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Get test statistics
|
|
723
|
+
function getTestStats() {
|
|
724
|
+
let testFiles = 0;
|
|
725
|
+
let testCases = 0;
|
|
726
|
+
|
|
727
|
+
const testDirs = [
|
|
728
|
+
path.join(process.cwd(), 'tests'),
|
|
729
|
+
path.join(process.cwd(), 'test'),
|
|
730
|
+
path.join(process.cwd(), '__tests__'),
|
|
731
|
+
path.join(process.cwd(), 'src', '__tests__'),
|
|
732
|
+
path.join(process.cwd(), 'v3', '__tests__'),
|
|
733
|
+
];
|
|
734
|
+
|
|
735
|
+
// Recursively count test files
|
|
736
|
+
function countTestFiles(dir, depth = 0) {
|
|
737
|
+
if (depth > 3) return; // Limit recursion
|
|
738
|
+
if (!fs.existsSync(dir)) return;
|
|
739
|
+
|
|
740
|
+
try {
|
|
741
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
742
|
+
for (const entry of entries) {
|
|
743
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
744
|
+
countTestFiles(path.join(dir, entry.name), depth + 1);
|
|
745
|
+
} else if (entry.isFile()) {
|
|
746
|
+
const name = entry.name;
|
|
747
|
+
if (name.includes('.test.') || name.includes('.spec.') ||
|
|
748
|
+
name.includes('_test.') || name.includes('_spec.') ||
|
|
749
|
+
name.startsWith('test_') || name.startsWith('spec_')) {
|
|
750
|
+
testFiles++;
|
|
751
|
+
|
|
752
|
+
// Try to estimate test cases from file
|
|
753
|
+
try {
|
|
754
|
+
const content = fs.readFileSync(path.join(dir, name), 'utf-8');
|
|
755
|
+
// Count it(), test(), describe() patterns
|
|
756
|
+
const itMatches = (content.match(/\bit\s*\(/g) || []).length;
|
|
757
|
+
const testMatches = (content.match(/\btest\s*\(/g) || []).length;
|
|
758
|
+
testCases += itMatches + testMatches;
|
|
759
|
+
} catch (e) {
|
|
760
|
+
// Estimate 3 tests per file if can't read
|
|
761
|
+
testCases += 3;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
} catch (e) {
|
|
767
|
+
// Ignore
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
for (const dir of testDirs) {
|
|
772
|
+
countTestFiles(dir);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Also check src directory for colocated tests
|
|
776
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
777
|
+
if (fs.existsSync(srcDir)) {
|
|
778
|
+
countTestFiles(srcDir);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
return { testFiles, testCases };
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// Get integration status (MCP servers, external connections)
|
|
785
|
+
function getIntegrationStatus() {
|
|
786
|
+
let mcpServers = { total: 0, enabled: 0, names: [] };
|
|
787
|
+
let hasDatabase = false;
|
|
788
|
+
let hasCache = false;
|
|
789
|
+
let hasApi = false;
|
|
790
|
+
|
|
791
|
+
// Check for MCP servers in settings
|
|
792
|
+
const settingsPaths = [
|
|
793
|
+
path.join(process.cwd(), '.claude', 'settings.json'),
|
|
794
|
+
path.join(process.cwd(), '.claude', 'settings.local.json'),
|
|
795
|
+
];
|
|
796
|
+
|
|
797
|
+
for (const settingsPath of settingsPaths) {
|
|
798
|
+
if (fs.existsSync(settingsPath)) {
|
|
799
|
+
try {
|
|
800
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
801
|
+
|
|
802
|
+
// Check mcpServers object
|
|
803
|
+
if (settings.mcpServers && typeof settings.mcpServers === 'object') {
|
|
804
|
+
const servers = Object.keys(settings.mcpServers);
|
|
805
|
+
mcpServers.total = servers.length;
|
|
806
|
+
mcpServers.names = servers;
|
|
807
|
+
|
|
808
|
+
// Check enabledMcpjsonServers for enabled count
|
|
809
|
+
if (settings.enabledMcpjsonServers && Array.isArray(settings.enabledMcpjsonServers)) {
|
|
810
|
+
mcpServers.enabled = settings.enabledMcpjsonServers.filter(s => servers.includes(s)).length;
|
|
811
|
+
} else {
|
|
812
|
+
mcpServers.enabled = mcpServers.total; // Assume all enabled if not specified
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
break;
|
|
816
|
+
} catch (e) { /* ignore */ }
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Also check .mcp.json or mcp.json
|
|
821
|
+
const mcpConfigPaths = [
|
|
822
|
+
path.join(process.cwd(), '.mcp.json'),
|
|
823
|
+
path.join(process.cwd(), 'mcp.json'),
|
|
824
|
+
path.join(require('os').homedir(), '.claude', 'mcp.json'),
|
|
825
|
+
];
|
|
826
|
+
|
|
827
|
+
for (const mcpPath of mcpConfigPaths) {
|
|
828
|
+
if (fs.existsSync(mcpPath) && mcpServers.total === 0) {
|
|
829
|
+
try {
|
|
830
|
+
const config = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
|
|
831
|
+
if (config.mcpServers) {
|
|
832
|
+
const servers = Object.keys(config.mcpServers);
|
|
833
|
+
mcpServers.total = servers.length;
|
|
834
|
+
mcpServers.names = servers;
|
|
835
|
+
mcpServers.enabled = servers.length;
|
|
836
|
+
}
|
|
837
|
+
} catch (e) { /* ignore */ }
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// Check for database (AgentDB, SQLite, etc.)
|
|
842
|
+
const dbPaths = [
|
|
843
|
+
path.join(process.cwd(), '.swarm', 'memory.db'),
|
|
844
|
+
path.join(process.cwd(), '.claude-flow', 'memory.db'),
|
|
845
|
+
path.join(process.cwd(), 'data', 'memory.db'),
|
|
846
|
+
];
|
|
847
|
+
hasDatabase = dbPaths.some(p => fs.existsSync(p));
|
|
848
|
+
|
|
849
|
+
// Check for cache
|
|
850
|
+
const cachePaths = [
|
|
851
|
+
path.join(process.cwd(), '.claude-flow', 'cache'),
|
|
852
|
+
path.join(process.cwd(), '.cache'),
|
|
853
|
+
path.join(process.cwd(), 'node_modules', '.cache'),
|
|
854
|
+
];
|
|
855
|
+
hasCache = cachePaths.some(p => fs.existsSync(p));
|
|
856
|
+
|
|
857
|
+
// Check for API configuration (env vars or config)
|
|
858
|
+
try {
|
|
859
|
+
hasApi = !!(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY);
|
|
860
|
+
} catch (e) { /* ignore */ }
|
|
861
|
+
|
|
862
|
+
return { mcpServers, hasDatabase, hasCache, hasApi };
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// Get git status (uncommitted changes, untracked files) - cross-platform
|
|
866
|
+
function getGitStatus() {
|
|
867
|
+
let modified = 0;
|
|
868
|
+
let untracked = 0;
|
|
869
|
+
let staged = 0;
|
|
870
|
+
let ahead = 0;
|
|
871
|
+
let behind = 0;
|
|
872
|
+
const isWindows = process.platform === 'win32';
|
|
873
|
+
|
|
874
|
+
try {
|
|
875
|
+
// Get modified and staged counts - works on all platforms
|
|
876
|
+
const status = execSync('git status --porcelain', {
|
|
877
|
+
encoding: 'utf-8',
|
|
878
|
+
stdio: ['pipe', 'pipe', 'pipe'], // Suppress stderr
|
|
879
|
+
timeout: 5000,
|
|
880
|
+
});
|
|
881
|
+
const lines = status.trim().split('\n').filter(l => l);
|
|
882
|
+
for (const line of lines) {
|
|
883
|
+
const code = line.substring(0, 2);
|
|
884
|
+
if (code.includes('M') || code.includes('D') || code.includes('R')) {
|
|
885
|
+
if (code[0] !== ' ') staged++;
|
|
886
|
+
if (code[1] !== ' ') modified++;
|
|
887
|
+
}
|
|
888
|
+
if (code.includes('?')) untracked++;
|
|
889
|
+
if (code.includes('A')) staged++;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Get ahead/behind - may fail if no upstream
|
|
893
|
+
try {
|
|
894
|
+
const abStatus = execSync('git rev-list --left-right --count HEAD...@{upstream}', {
|
|
895
|
+
encoding: 'utf-8',
|
|
896
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
897
|
+
timeout: 5000,
|
|
898
|
+
});
|
|
899
|
+
const parts = abStatus.trim().split(/\s+/);
|
|
900
|
+
ahead = parseInt(parts[0]) || 0;
|
|
901
|
+
behind = parseInt(parts[1]) || 0;
|
|
902
|
+
} catch (e) { /* no upstream or error - that's ok */ }
|
|
903
|
+
|
|
904
|
+
} catch (e) {
|
|
905
|
+
// Not a git repo or git not installed - return zeros
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
return { modified, untracked, staged, ahead, behind };
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// Get session statistics
|
|
912
|
+
function getSessionStats() {
|
|
913
|
+
let sessionStart = null;
|
|
914
|
+
let duration = '';
|
|
915
|
+
let lastActivity = '';
|
|
916
|
+
let operationsCount = 0;
|
|
917
|
+
|
|
918
|
+
// Check for session file
|
|
919
|
+
const sessionPaths = [
|
|
920
|
+
path.join(process.cwd(), '.claude-flow', 'session.json'),
|
|
921
|
+
path.join(process.cwd(), '.claude', 'session.json'),
|
|
922
|
+
];
|
|
923
|
+
|
|
924
|
+
for (const sessPath of sessionPaths) {
|
|
925
|
+
if (fs.existsSync(sessPath)) {
|
|
926
|
+
try {
|
|
927
|
+
const data = JSON.parse(fs.readFileSync(sessPath, 'utf-8'));
|
|
928
|
+
if (data.startTime) {
|
|
929
|
+
sessionStart = new Date(data.startTime);
|
|
930
|
+
const now = new Date();
|
|
931
|
+
const diffMs = now.getTime() - sessionStart.getTime();
|
|
932
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
933
|
+
if (diffMins < 60) {
|
|
934
|
+
duration = `${diffMins}m`;
|
|
935
|
+
} else {
|
|
936
|
+
const hours = Math.floor(diffMins / 60);
|
|
937
|
+
const mins = diffMins % 60;
|
|
938
|
+
duration = `${hours}h${mins}m`;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
if (data.lastActivity) {
|
|
942
|
+
const last = new Date(data.lastActivity);
|
|
943
|
+
const now = new Date();
|
|
944
|
+
const diffMs = now.getTime() - last.getTime();
|
|
945
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
946
|
+
if (diffMins < 1) lastActivity = 'now';
|
|
947
|
+
else if (diffMins < 60) lastActivity = `${diffMins}m ago`;
|
|
948
|
+
else lastActivity = `${Math.floor(diffMins / 60)}h ago`;
|
|
949
|
+
}
|
|
950
|
+
operationsCount = data.operationsCount || data.commandCount || 0;
|
|
951
|
+
break;
|
|
952
|
+
} catch (e) { /* ignore */ }
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// Fallback: check metrics for activity
|
|
957
|
+
if (!duration) {
|
|
958
|
+
const metricsPath = path.join(process.cwd(), '.claude-flow', 'metrics', 'activity.json');
|
|
959
|
+
if (fs.existsSync(metricsPath)) {
|
|
960
|
+
try {
|
|
961
|
+
const data = JSON.parse(fs.readFileSync(metricsPath, 'utf-8'));
|
|
962
|
+
operationsCount = data.totalOperations || 0;
|
|
963
|
+
} catch (e) { /* ignore */ }
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
return { duration, lastActivity, operationsCount };
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// Get trend indicator based on change
|
|
971
|
+
function getTrend(current, previous) {
|
|
972
|
+
if (previous === null || previous === undefined) return '';
|
|
973
|
+
if (current > previous) return `${c.brightGreen}↑${c.reset}`;
|
|
974
|
+
if (current < previous) return `${c.brightRed}↓${c.reset}`;
|
|
975
|
+
return `${c.dim}→${c.reset}`;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// Store previous values for trends (persisted between calls)
|
|
979
|
+
let prevIntelligence = null;
|
|
980
|
+
try {
|
|
981
|
+
const trendPath = path.join(process.cwd(), '.claude-flow', '.trend-cache.json');
|
|
982
|
+
if (fs.existsSync(trendPath)) {
|
|
983
|
+
const data = JSON.parse(fs.readFileSync(trendPath, 'utf-8'));
|
|
984
|
+
prevIntelligence = data.intelligence;
|
|
985
|
+
}
|
|
986
|
+
} catch (e) { /* ignore */ }
|
|
987
|
+
|
|
246
988
|
// Generate progress bar
|
|
247
989
|
function progressBar(current, total) {
|
|
248
990
|
const width = 5;
|
|
@@ -258,51 +1000,137 @@ function generateStatusline() {
|
|
|
258
1000
|
const security = getSecurityStatus();
|
|
259
1001
|
const swarm = getSwarmStatus();
|
|
260
1002
|
const system = getSystemMetrics();
|
|
1003
|
+
const adrs = getADRStatus();
|
|
1004
|
+
const hooks = getHooksStatus();
|
|
1005
|
+
const agentdb = getAgentDBStats();
|
|
1006
|
+
const tests = getTestStats();
|
|
1007
|
+
const git = getGitStatus();
|
|
1008
|
+
const session = getSessionStats();
|
|
1009
|
+
const integration = getIntegrationStatus();
|
|
261
1010
|
const lines = [];
|
|
262
1011
|
|
|
263
|
-
//
|
|
1012
|
+
// Calculate intelligence trend
|
|
1013
|
+
const intellTrend = getTrend(system.intelligencePct, prevIntelligence);
|
|
1014
|
+
|
|
1015
|
+
// Save current values for next trend calculation
|
|
1016
|
+
try {
|
|
1017
|
+
const trendPath = path.join(process.cwd(), '.claude-flow', '.trend-cache.json');
|
|
1018
|
+
const trendDir = path.dirname(trendPath);
|
|
1019
|
+
if (!fs.existsSync(trendDir)) fs.mkdirSync(trendDir, { recursive: true });
|
|
1020
|
+
fs.writeFileSync(trendPath, JSON.stringify({ intelligence: system.intelligencePct, timestamp: Date.now() }));
|
|
1021
|
+
} catch (e) { /* ignore */ }
|
|
1022
|
+
|
|
1023
|
+
// Header Line with git changes indicator
|
|
264
1024
|
let header = `${c.bold}${c.brightPurple}▊ Claude Flow V3 ${c.reset}`;
|
|
265
1025
|
header += `${swarm.coordinationActive ? c.brightCyan : c.dim}● ${c.brightCyan}${user.name}${c.reset}`;
|
|
266
1026
|
if (user.gitBranch) {
|
|
267
1027
|
header += ` ${c.dim}│${c.reset} ${c.brightBlue}⎇ ${user.gitBranch}${c.reset}`;
|
|
1028
|
+
// Add git changes indicator
|
|
1029
|
+
const gitChanges = git.modified + git.staged + git.untracked;
|
|
1030
|
+
if (gitChanges > 0) {
|
|
1031
|
+
let gitIndicator = '';
|
|
1032
|
+
if (git.staged > 0) gitIndicator += `${c.brightGreen}+${git.staged}${c.reset}`;
|
|
1033
|
+
if (git.modified > 0) gitIndicator += `${c.brightYellow}~${git.modified}${c.reset}`;
|
|
1034
|
+
if (git.untracked > 0) gitIndicator += `${c.dim}?${git.untracked}${c.reset}`;
|
|
1035
|
+
header += ` ${gitIndicator}`;
|
|
1036
|
+
}
|
|
1037
|
+
// Add ahead/behind indicator
|
|
1038
|
+
if (git.ahead > 0 || git.behind > 0) {
|
|
1039
|
+
if (git.ahead > 0) header += ` ${c.brightGreen}↑${git.ahead}${c.reset}`;
|
|
1040
|
+
if (git.behind > 0) header += ` ${c.brightRed}↓${git.behind}${c.reset}`;
|
|
1041
|
+
}
|
|
268
1042
|
}
|
|
269
1043
|
header += ` ${c.dim}│${c.reset} ${c.purple}${user.modelName}${c.reset}`;
|
|
1044
|
+
// Add session duration if available
|
|
1045
|
+
if (session.duration) {
|
|
1046
|
+
header += ` ${c.dim}│${c.reset} ${c.cyan}⏱ ${session.duration}${c.reset}`;
|
|
1047
|
+
}
|
|
270
1048
|
lines.push(header);
|
|
271
1049
|
|
|
272
1050
|
// Separator
|
|
273
1051
|
lines.push(`${c.dim}─────────────────────────────────────────────────────${c.reset}`);
|
|
274
1052
|
|
|
275
|
-
// Line 1: DDD Domain Progress
|
|
1053
|
+
// Line 1: DDD Domain Progress with dynamic performance indicator
|
|
276
1054
|
const domainsColor = progress.domainsCompleted >= 3 ? c.brightGreen : progress.domainsCompleted > 0 ? c.yellow : c.red;
|
|
1055
|
+
// Show HNSW speedup if enabled, otherwise show patterns learned
|
|
1056
|
+
let perfIndicator = '';
|
|
1057
|
+
if (agentdb.hasHnsw && agentdb.vectorCount > 0) {
|
|
1058
|
+
// HNSW enabled: show estimated speedup (150x-12500x based on vector count)
|
|
1059
|
+
const speedup = agentdb.vectorCount > 10000 ? '12500x' : agentdb.vectorCount > 1000 ? '150x' : '10x';
|
|
1060
|
+
perfIndicator = `${c.brightGreen}⚡ HNSW ${speedup}${c.reset}`;
|
|
1061
|
+
} else if (progress.patternsLearned > 0) {
|
|
1062
|
+
// Show patterns learned
|
|
1063
|
+
const patternsK = progress.patternsLearned >= 1000
|
|
1064
|
+
? `${(progress.patternsLearned / 1000).toFixed(1)}k`
|
|
1065
|
+
: String(progress.patternsLearned);
|
|
1066
|
+
perfIndicator = `${c.brightYellow}📚 ${patternsK} patterns${c.reset}`;
|
|
1067
|
+
} else {
|
|
1068
|
+
// New project: show target
|
|
1069
|
+
perfIndicator = `${c.dim}⚡ target: 150x-12500x${c.reset}`;
|
|
1070
|
+
}
|
|
277
1071
|
lines.push(
|
|
278
1072
|
`${c.brightCyan}🏗️ DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
|
|
279
1073
|
`${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ` +
|
|
280
|
-
|
|
1074
|
+
perfIndicator
|
|
281
1075
|
);
|
|
282
1076
|
|
|
283
|
-
// Line 2: Swarm + CVE + Memory + Context + Intelligence
|
|
1077
|
+
// Line 2: Swarm + Hooks + CVE + Memory + Context + Intelligence
|
|
284
1078
|
const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
|
|
285
1079
|
const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
|
|
286
1080
|
let securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
|
|
287
1081
|
let securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
|
|
1082
|
+
const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
|
|
288
1083
|
|
|
289
1084
|
lines.push(
|
|
290
1085
|
`${c.brightYellow}🤖 Swarm${c.reset} ${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
|
|
291
1086
|
`${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
|
|
1087
|
+
`${c.brightBlue}🪝 ${hooksColor}${hooks.enabled}${c.reset}/${c.brightWhite}${hooks.total}${c.reset} ` +
|
|
292
1088
|
`${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
|
|
293
1089
|
`${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
|
|
294
|
-
`${c.brightGreen}
|
|
295
|
-
`${c.dim}🧠 ${String(system.intelligencePct).padStart(3)}%${c.reset}`
|
|
1090
|
+
`${system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim}🧠 ${String(system.intelligencePct).padStart(3)}%${intellTrend}${c.reset}`
|
|
296
1091
|
);
|
|
297
1092
|
|
|
298
|
-
// Line 3: Architecture status
|
|
1093
|
+
// Line 3: Architecture status with ADRs, AgentDB, Tests
|
|
299
1094
|
const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
|
|
1095
|
+
const adrColor = adrs.count > 0 ? (adrs.implemented === adrs.count ? c.brightGreen : c.yellow) : c.dim;
|
|
1096
|
+
const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
|
|
1097
|
+
const testColor = tests.testFiles > 0 ? c.brightGreen : c.dim;
|
|
1098
|
+
|
|
300
1099
|
lines.push(
|
|
301
1100
|
`${c.brightPurple}🔧 Architecture${c.reset} ` +
|
|
1101
|
+
`${c.cyan}ADRs${c.reset} ${adrColor}●${adrs.implemented}/${adrs.count}${c.reset} ${c.dim}│${c.reset} ` +
|
|
302
1102
|
`${c.cyan}DDD${c.reset} ${dddColor}●${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}│${c.reset} ` +
|
|
303
|
-
`${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset}
|
|
304
|
-
|
|
305
|
-
|
|
1103
|
+
`${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset}`
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1106
|
+
// Line 4: Memory, Vectors, Tests
|
|
1107
|
+
const hnswIndicator = agentdb.hasHnsw ? `${c.brightGreen}⚡${c.reset}` : '';
|
|
1108
|
+
const sizeDisplay = agentdb.dbSizeKB >= 1024
|
|
1109
|
+
? `${(agentdb.dbSizeKB / 1024).toFixed(1)}MB`
|
|
1110
|
+
: `${agentdb.dbSizeKB}KB`;
|
|
1111
|
+
// Build integration status string
|
|
1112
|
+
let integrationStr = '';
|
|
1113
|
+
if (integration.mcpServers.total > 0) {
|
|
1114
|
+
const mcpColor = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen :
|
|
1115
|
+
integration.mcpServers.enabled > 0 ? c.brightYellow : c.red;
|
|
1116
|
+
integrationStr += `${c.cyan}MCP${c.reset} ${mcpColor}●${integration.mcpServers.enabled}/${integration.mcpServers.total}${c.reset}`;
|
|
1117
|
+
}
|
|
1118
|
+
if (integration.hasDatabase) {
|
|
1119
|
+
integrationStr += (integrationStr ? ' ' : '') + `${c.brightGreen}◆${c.reset}DB`;
|
|
1120
|
+
}
|
|
1121
|
+
if (integration.hasApi) {
|
|
1122
|
+
integrationStr += (integrationStr ? ' ' : '') + `${c.brightGreen}◆${c.reset}API`;
|
|
1123
|
+
}
|
|
1124
|
+
if (!integrationStr) {
|
|
1125
|
+
integrationStr = `${c.dim}●none${c.reset}`;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
lines.push(
|
|
1129
|
+
`${c.brightCyan}📊 AgentDB${c.reset} ` +
|
|
1130
|
+
`${c.cyan}Vectors${c.reset} ${vectorColor}●${agentdb.vectorCount}${hnswIndicator}${c.reset} ${c.dim}│${c.reset} ` +
|
|
1131
|
+
`${c.cyan}Size${c.reset} ${c.brightWhite}${sizeDisplay}${c.reset} ${c.dim}│${c.reset} ` +
|
|
1132
|
+
`${c.cyan}Tests${c.reset} ${testColor}●${tests.testFiles}${c.reset} ${c.dim}(${tests.testCases} cases)${c.reset} ${c.dim}│${c.reset} ` +
|
|
1133
|
+
integrationStr
|
|
306
1134
|
);
|
|
307
1135
|
|
|
308
1136
|
return lines.join('\n');
|
|
@@ -316,6 +1144,10 @@ function generateJSON() {
|
|
|
316
1144
|
security: getSecurityStatus(),
|
|
317
1145
|
swarm: getSwarmStatus(),
|
|
318
1146
|
system: getSystemMetrics(),
|
|
1147
|
+
adrs: getADRStatus(),
|
|
1148
|
+
hooks: getHooksStatus(),
|
|
1149
|
+
agentdb: getAgentDBStats(),
|
|
1150
|
+
tests: getTestStats(),
|
|
319
1151
|
performance: {
|
|
320
1152
|
flashAttentionTarget: '2.49x-7.47x',
|
|
321
1153
|
searchImprovement: '150x-12,500x',
|