@girardelli/architect 2.2.0 → 5.0.0
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/README.md +105 -116
- package/architect-run.sh +431 -0
- package/assets/banner-v3.html +561 -0
- package/dist/agent-generator/context-enricher.d.ts +58 -0
- package/dist/agent-generator/context-enricher.d.ts.map +1 -0
- package/dist/agent-generator/context-enricher.js +613 -0
- package/dist/agent-generator/context-enricher.js.map +1 -0
- package/dist/agent-generator/domain-inferrer.d.ts +52 -0
- package/dist/agent-generator/domain-inferrer.d.ts.map +1 -0
- package/dist/agent-generator/domain-inferrer.js +585 -0
- package/dist/agent-generator/domain-inferrer.js.map +1 -0
- package/dist/agent-generator/framework-detector.d.ts +40 -0
- package/dist/agent-generator/framework-detector.d.ts.map +1 -0
- package/dist/agent-generator/framework-detector.js +611 -0
- package/dist/agent-generator/framework-detector.js.map +1 -0
- package/dist/agent-generator/index.d.ts +47 -0
- package/dist/agent-generator/index.d.ts.map +1 -0
- package/dist/agent-generator/index.js +545 -0
- package/dist/agent-generator/index.js.map +1 -0
- package/dist/agent-generator/stack-detector.d.ts +14 -0
- package/dist/agent-generator/stack-detector.d.ts.map +1 -0
- package/dist/agent-generator/stack-detector.js +124 -0
- package/dist/agent-generator/stack-detector.js.map +1 -0
- package/dist/agent-generator/templates/core/agents.d.ts +17 -0
- package/dist/agent-generator/templates/core/agents.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/agents.js +1256 -0
- package/dist/agent-generator/templates/core/agents.js.map +1 -0
- package/dist/agent-generator/templates/core/architecture-rules.d.ts +7 -0
- package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/architecture-rules.js +274 -0
- package/dist/agent-generator/templates/core/architecture-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/general-rules.d.ts +8 -0
- package/dist/agent-generator/templates/core/general-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/general-rules.js +301 -0
- package/dist/agent-generator/templates/core/general-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/hooks-generator.d.ts +21 -0
- package/dist/agent-generator/templates/core/hooks-generator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/hooks-generator.js +233 -0
- package/dist/agent-generator/templates/core/hooks-generator.js.map +1 -0
- package/dist/agent-generator/templates/core/index-md.d.ts +7 -0
- package/dist/agent-generator/templates/core/index-md.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/index-md.js +246 -0
- package/dist/agent-generator/templates/core/index-md.js.map +1 -0
- package/dist/agent-generator/templates/core/orchestrator.d.ts +8 -0
- package/dist/agent-generator/templates/core/orchestrator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/orchestrator.js +422 -0
- package/dist/agent-generator/templates/core/orchestrator.js.map +1 -0
- package/dist/agent-generator/templates/core/preflight.d.ts +8 -0
- package/dist/agent-generator/templates/core/preflight.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/preflight.js +213 -0
- package/dist/agent-generator/templates/core/preflight.js.map +1 -0
- package/dist/agent-generator/templates/core/quality-gates.d.ts +11 -0
- package/dist/agent-generator/templates/core/quality-gates.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/quality-gates.js +254 -0
- package/dist/agent-generator/templates/core/quality-gates.js.map +1 -0
- package/dist/agent-generator/templates/core/security-rules.d.ts +7 -0
- package/dist/agent-generator/templates/core/security-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/security-rules.js +528 -0
- package/dist/agent-generator/templates/core/security-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/skills-generator.d.ts +19 -0
- package/dist/agent-generator/templates/core/skills-generator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/skills-generator.js +546 -0
- package/dist/agent-generator/templates/core/skills-generator.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +7 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.js +237 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +8 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.js +321 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-review.d.ts +7 -0
- package/dist/agent-generator/templates/core/workflow-review.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-review.js +104 -0
- package/dist/agent-generator/templates/core/workflow-review.js.map +1 -0
- package/dist/agent-generator/templates/domain/index.d.ts +22 -0
- package/dist/agent-generator/templates/domain/index.d.ts.map +1 -0
- package/dist/agent-generator/templates/domain/index.js +1176 -0
- package/dist/agent-generator/templates/domain/index.js.map +1 -0
- package/dist/agent-generator/templates/stack/index.d.ts +8 -0
- package/dist/agent-generator/templates/stack/index.d.ts.map +1 -0
- package/dist/agent-generator/templates/stack/index.js +695 -0
- package/dist/agent-generator/templates/stack/index.js.map +1 -0
- package/dist/agent-generator/templates/template-helpers.d.ts +75 -0
- package/dist/agent-generator/templates/template-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/template-helpers.js +726 -0
- package/dist/agent-generator/templates/template-helpers.js.map +1 -0
- package/dist/agent-generator/types.d.ts +196 -0
- package/dist/agent-generator/types.d.ts.map +1 -0
- package/dist/agent-generator/types.js +27 -0
- package/dist/agent-generator/types.js.map +1 -0
- package/dist/analyzer.d.ts +5 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +46 -5
- package/dist/analyzer.js.map +1 -1
- package/dist/analyzers/forecast.d.ts +85 -0
- package/dist/analyzers/forecast.d.ts.map +1 -0
- package/dist/analyzers/forecast.js +337 -0
- package/dist/analyzers/forecast.js.map +1 -0
- package/dist/analyzers/git-cache.d.ts +7 -0
- package/dist/analyzers/git-cache.d.ts.map +1 -0
- package/dist/analyzers/git-cache.js +41 -0
- package/dist/analyzers/git-cache.js.map +1 -0
- package/dist/analyzers/git-history.d.ts +113 -0
- package/dist/analyzers/git-history.d.ts.map +1 -0
- package/dist/analyzers/git-history.js +333 -0
- package/dist/analyzers/git-history.js.map +1 -0
- package/dist/analyzers/index.d.ts +10 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +7 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/temporal-scorer.d.ts +72 -0
- package/dist/analyzers/temporal-scorer.d.ts.map +1 -0
- package/dist/analyzers/temporal-scorer.js +140 -0
- package/dist/analyzers/temporal-scorer.js.map +1 -0
- package/dist/anti-patterns.d.ts +7 -0
- package/dist/anti-patterns.d.ts.map +1 -1
- package/dist/anti-patterns.js +25 -6
- package/dist/anti-patterns.js.map +1 -1
- package/dist/cli.d.ts +2 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +275 -113
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +48 -11
- package/dist/config.js.map +1 -1
- package/dist/html-reporter.d.ts +3 -1
- package/dist/html-reporter.d.ts.map +1 -1
- package/dist/html-reporter.js +248 -12
- package/dist/html-reporter.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -4
- package/dist/index.js.map +1 -1
- package/dist/project-summarizer.d.ts +38 -0
- package/dist/project-summarizer.d.ts.map +1 -0
- package/dist/project-summarizer.js +463 -0
- package/dist/project-summarizer.js.map +1 -0
- package/dist/refactor-reporter.js +1 -1
- package/dist/scanner.d.ts +8 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +153 -113
- package/dist/scanner.js.map +1 -1
- package/dist/scorer.d.ts.map +1 -1
- package/dist/scorer.js +24 -11
- package/dist/scorer.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -3
- package/src/agent-generator/context-enricher.ts +672 -0
- package/src/agent-generator/domain-inferrer.ts +635 -0
- package/src/agent-generator/framework-detector.ts +669 -0
- package/src/agent-generator/index.ts +634 -0
- package/src/agent-generator/stack-detector.ts +115 -0
- package/src/agent-generator/templates/core/agents.ts +1296 -0
- package/src/agent-generator/templates/core/architecture-rules.ts +287 -0
- package/src/agent-generator/templates/core/general-rules.ts +306 -0
- package/src/agent-generator/templates/core/hooks-generator.ts +242 -0
- package/src/agent-generator/templates/core/index-md.ts +260 -0
- package/src/agent-generator/templates/core/orchestrator.ts +459 -0
- package/src/agent-generator/templates/core/preflight.ts +215 -0
- package/src/agent-generator/templates/core/quality-gates.ts +256 -0
- package/src/agent-generator/templates/core/security-rules.ts +543 -0
- package/src/agent-generator/templates/core/skills-generator.ts +585 -0
- package/src/agent-generator/templates/core/workflow-fix-bug.ts +239 -0
- package/src/agent-generator/templates/core/workflow-new-feature.ts +323 -0
- package/src/agent-generator/templates/core/workflow-review.ts +106 -0
- package/src/agent-generator/templates/domain/index.ts +1201 -0
- package/src/agent-generator/templates/stack/index.ts +705 -0
- package/src/agent-generator/templates/template-helpers.ts +776 -0
- package/src/agent-generator/types.ts +232 -0
- package/src/analyzer.ts +51 -5
- package/src/analyzers/forecast.ts +496 -0
- package/src/analyzers/git-cache.ts +52 -0
- package/src/analyzers/git-history.ts +488 -0
- package/src/analyzers/index.ts +33 -0
- package/src/analyzers/temporal-scorer.ts +227 -0
- package/src/anti-patterns.ts +29 -6
- package/src/cli.ts +316 -117
- package/src/config.ts +52 -11
- package/src/html-reporter.ts +263 -13
- package/src/index.ts +93 -10
- package/src/project-summarizer.ts +521 -0
- package/src/refactor-reporter.ts +1 -1
- package/src/scanner.ts +136 -90
- package/src/scorer.ts +26 -11
- package/src/types.ts +27 -0
- package/tests/agent-generator.test.ts +427 -0
- package/tests/analyzers-integration.test.ts +174 -0
- package/tests/architect-adapter-enrichment.test.ts +9 -0
- package/tests/context-enricher.test.ts +971 -0
- package/tests/fixtures/monorepo/package.json +6 -0
- package/tests/fixtures/monorepo/packages/app/package.json +12 -0
- package/tests/fixtures/monorepo/packages/app/src/index.ts +6 -0
- package/tests/fixtures/monorepo/packages/core/package.json +7 -0
- package/tests/fixtures/monorepo/packages/core/src/index.ts +7 -0
- package/tests/forecast.test.ts +509 -0
- package/tests/framework-detector.test.ts +1172 -0
- package/tests/git-history.test.ts +254 -0
- package/tests/monorepo-scan.test.ts +170 -0
- package/tests/scanner.test.ts +7 -8
- package/tests/scorer.test.ts +594 -0
- package/tests/stack-detector.test.ts +241 -0
- package/tests/template-generation.test.ts +706 -0
- package/tests/template-helpers.test.ts +1152 -0
- package/tests/temporal-scorer.test.ts +307 -0
- package/dist/agent-generator.d.ts +0 -106
- package/dist/agent-generator.d.ts.map +0 -1
- package/dist/agent-generator.js +0 -1398
- package/dist/agent-generator.js.map +0 -1
- package/src/agent-generator.ts +0 -1526
package/src/cli.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Architect CLI
|
|
5
|
-
*
|
|
4
|
+
* Architect CLI v3.1
|
|
5
|
+
* Enterprise Architecture Analysis — @girardelli/architect
|
|
6
6
|
*
|
|
7
7
|
* Uso:
|
|
8
8
|
* npx architect analyze ./src
|
|
@@ -10,10 +10,9 @@
|
|
|
10
10
|
* npx architect diagram ./src
|
|
11
11
|
* npx architect score ./src
|
|
12
12
|
* npx architect anti-patterns ./src
|
|
13
|
-
* npx architect layers ./src
|
|
14
13
|
*/
|
|
15
14
|
|
|
16
|
-
import { architect } from './index.js';
|
|
15
|
+
import { architect, ProgressEvent } from './index.js';
|
|
17
16
|
import { ReportGenerator } from './reporter.js';
|
|
18
17
|
import { HtmlReportGenerator } from './html-reporter.js';
|
|
19
18
|
import { RefactorReportGenerator } from './refactor-reporter.js';
|
|
@@ -29,45 +28,242 @@ interface CliOptions {
|
|
|
29
28
|
output?: string;
|
|
30
29
|
}
|
|
31
30
|
|
|
31
|
+
// ── ANSI Colors & Styles ──
|
|
32
|
+
const c = {
|
|
33
|
+
reset: '\x1b[0m',
|
|
34
|
+
bold: '\x1b[1m',
|
|
35
|
+
dim: '\x1b[2m',
|
|
36
|
+
italic: '\x1b[3m',
|
|
37
|
+
// Colors
|
|
38
|
+
red: '\x1b[38;5;196m',
|
|
39
|
+
green: '\x1b[38;5;46m',
|
|
40
|
+
blue: '\x1b[38;5;33m',
|
|
41
|
+
cyan: '\x1b[38;5;51m',
|
|
42
|
+
yellow: '\x1b[38;5;220m',
|
|
43
|
+
magenta: '\x1b[38;5;201m',
|
|
44
|
+
orange: '\x1b[38;5;208m',
|
|
45
|
+
white: '\x1b[38;5;255m',
|
|
46
|
+
gray: '\x1b[38;5;240m',
|
|
47
|
+
darkGray: '\x1b[38;5;236m',
|
|
48
|
+
// Bg
|
|
49
|
+
bgBlue: '\x1b[48;5;17m',
|
|
50
|
+
bgGreen: '\x1b[48;5;22m',
|
|
51
|
+
bgRed: '\x1b[48;5;52m',
|
|
52
|
+
bgCyan: '\x1b[48;5;23m',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// ── Phase config ──
|
|
56
|
+
interface PhaseConfig {
|
|
57
|
+
icon: string;
|
|
58
|
+
label: string;
|
|
59
|
+
verb: string;
|
|
60
|
+
color: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const PHASES: Record<string, PhaseConfig> = {
|
|
64
|
+
scan: { icon: '◉', label: 'FILE SCANNER', verb: 'Scanning filesystem', color: c.cyan },
|
|
65
|
+
dependencies: { icon: '◉', label: 'DEPENDENCY MAPPER', verb: 'Mapping import graph', color: c.blue },
|
|
66
|
+
layers: { icon: '◉', label: 'LAYER DETECTOR', verb: 'Classifying architecture', color: c.magenta },
|
|
67
|
+
antipatterns: { icon: '◉', label: 'PATTERN ANALYZER', verb: 'Detecting anti-patterns', color: c.orange },
|
|
68
|
+
scoring: { icon: '◉', label: 'QUALITY ENGINE', verb: 'Computing quality metrics', color: c.yellow },
|
|
69
|
+
normalize: { icon: '◉', label: 'PATH NORMALIZER', verb: 'Normalizing paths', color: c.gray },
|
|
70
|
+
summarize: { icon: '◉', label: 'AI SUMMARIZER', verb: 'Generating project summary', color: c.green },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const PHASE_ORDER = ['scan', 'dependencies', 'layers', 'antipatterns', 'scoring', 'normalize', 'summarize'];
|
|
74
|
+
|
|
32
75
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
76
|
+
* Enterprise-Grade Progress Reporter
|
|
77
|
+
* Real-time phase tracking with visual feedback
|
|
35
78
|
*/
|
|
36
|
-
class
|
|
79
|
+
class ProgressReporter {
|
|
37
80
|
private startTime: number;
|
|
38
|
-
private
|
|
39
|
-
private
|
|
81
|
+
private phaseStart: number = 0;
|
|
82
|
+
private completedPhases: string[] = [];
|
|
83
|
+
private totalPhases: number;
|
|
84
|
+
private scanMetrics: Record<string, number | string> = {};
|
|
40
85
|
|
|
41
86
|
constructor() {
|
|
42
87
|
this.startTime = Date.now();
|
|
43
|
-
this.
|
|
88
|
+
this.totalPhases = PHASE_ORDER.length;
|
|
44
89
|
}
|
|
45
90
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
91
|
+
/** Print the stylized header */
|
|
92
|
+
printHeader(projectPath: string): void {
|
|
93
|
+
const name = basename(projectPath);
|
|
94
|
+
const w = process.stderr;
|
|
95
|
+
|
|
96
|
+
w.write('\n');
|
|
97
|
+
w.write(`${c.darkGray} ┌─────────────────────────────────────────────────────────────────┐${c.reset}\n`);
|
|
98
|
+
w.write(`${c.darkGray} │${c.reset} ${c.cyan}${c.bold}⚡ ARCHITECT v3.1${c.reset} ${c.dim}Enterprise Architecture Intelligence${c.reset} ${c.darkGray}│${c.reset}\n`);
|
|
99
|
+
w.write(`${c.darkGray} │${c.reset} ${c.dim}@girardelli/architect — powered by Girardelli Tecnologia${c.reset} ${c.darkGray}│${c.reset}\n`);
|
|
100
|
+
w.write(`${c.darkGray} └─────────────────────────────────────────────────────────────────┘${c.reset}\n`);
|
|
101
|
+
w.write('\n');
|
|
102
|
+
w.write(` ${c.dim}Target:${c.reset} ${c.white}${c.bold}${name}${c.reset}\n`);
|
|
103
|
+
w.write(` ${c.dim}Path:${c.reset} ${c.gray}${projectPath}${c.reset}\n`);
|
|
104
|
+
w.write('\n');
|
|
105
|
+
w.write(` ${c.dim}──── Analysis Pipeline ────────────────────────────────────────${c.reset}\n`);
|
|
106
|
+
w.write('\n');
|
|
51
107
|
}
|
|
52
108
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
109
|
+
/** Handle a progress event from the analyzer */
|
|
110
|
+
onProgress(event: ProgressEvent): void {
|
|
111
|
+
const phase = PHASES[event.phase];
|
|
112
|
+
if (!phase) return;
|
|
113
|
+
|
|
114
|
+
if (event.status === 'start') {
|
|
115
|
+
this.phaseStart = Date.now();
|
|
116
|
+
this.printPhaseStart(event.phase, phase);
|
|
117
|
+
} else if (event.status === 'complete') {
|
|
118
|
+
this.completedPhases.push(event.phase);
|
|
119
|
+
this.printPhaseComplete(event.phase, phase, event.metrics);
|
|
120
|
+
if (event.metrics) {
|
|
121
|
+
Object.assign(this.scanMetrics, event.metrics);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
58
124
|
}
|
|
59
125
|
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
126
|
+
private printPhaseStart(key: string, phase: PhaseConfig): void {
|
|
127
|
+
const idx = PHASE_ORDER.indexOf(key) + 1;
|
|
128
|
+
const bar = this.buildProgressBar(this.completedPhases.length, this.totalPhases);
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
` ${c.dim}[${idx}/${this.totalPhases}]${c.reset} ${phase.color}${phase.icon}${c.reset} ${c.bold}${phase.label}${c.reset} ${c.dim}— ${phase.verb}...${c.reset} ${bar}\n`
|
|
131
|
+
);
|
|
63
132
|
}
|
|
64
133
|
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
134
|
+
private printPhaseComplete(key: string, phase: PhaseConfig, metrics?: Record<string, number | string>): void {
|
|
135
|
+
const elapsed = Date.now() - this.phaseStart;
|
|
136
|
+
const metricStr = metrics ? this.formatMetrics(key, metrics) : '';
|
|
137
|
+
process.stderr.write(
|
|
138
|
+
` ${c.dim} └─${c.reset} ${c.green}✓${c.reset} ${c.dim}${this.formatTime(elapsed)}${c.reset}${metricStr}\n`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private formatMetrics(phase: string, m: Record<string, number | string>): string {
|
|
143
|
+
const parts: string[] = [];
|
|
144
|
+
switch (phase) {
|
|
145
|
+
case 'scan':
|
|
146
|
+
parts.push(`${c.white}${m.files}${c.reset}${c.dim} files${c.reset}`);
|
|
147
|
+
parts.push(`${c.white}${Number(m.lines).toLocaleString()}${c.reset}${c.dim} lines${c.reset}`);
|
|
148
|
+
parts.push(`${c.white}${m.languages}${c.reset}${c.dim} langs${c.reset}`);
|
|
149
|
+
break;
|
|
150
|
+
case 'dependencies':
|
|
151
|
+
parts.push(`${c.white}${m.edges}${c.reset}${c.dim} edges${c.reset}`);
|
|
152
|
+
parts.push(`${c.white}${m.modules}${c.reset}${c.dim} modules${c.reset}`);
|
|
153
|
+
break;
|
|
154
|
+
case 'layers':
|
|
155
|
+
parts.push(`${c.white}${m.layers}${c.reset}${c.dim} layers${c.reset}`);
|
|
156
|
+
parts.push(`${c.white}${m.classified}${c.reset}${c.dim} classified${c.reset}`);
|
|
157
|
+
break;
|
|
158
|
+
case 'antipatterns':
|
|
159
|
+
if (Number(m.total) === 0) {
|
|
160
|
+
parts.push(`${c.green}clean${c.reset}`);
|
|
161
|
+
} else {
|
|
162
|
+
parts.push(`${c.yellow}${m.total}${c.reset}${c.dim} found${c.reset}`);
|
|
163
|
+
if (Number(m.critical) > 0) parts.push(`${c.red}${m.critical} critical${c.reset}`);
|
|
164
|
+
if (Number(m.high) > 0) parts.push(`${c.orange}${m.high} high${c.reset}`);
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
case 'scoring': {
|
|
168
|
+
const overall = Number(m.overall);
|
|
169
|
+
const scoreColor = overall >= 80 ? c.green : overall >= 60 ? c.yellow : c.red;
|
|
170
|
+
parts.push(`${scoreColor}${c.bold}${overall}/100${c.reset}`);
|
|
171
|
+
parts.push(`${c.dim}M:${m.modularity} C:${m.coupling} Co:${m.cohesion} L:${m.layering}${c.reset}`);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
case 'summarize':
|
|
175
|
+
parts.push(`${c.white}${m.modules}${c.reset}${c.dim} modules${c.reset}`);
|
|
176
|
+
parts.push(`${c.white}${m.techStack}${c.reset}${c.dim} technologies${c.reset}`);
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
return parts.length ? ` ${c.dim}│${c.reset} ${parts.join(`${c.dim} · ${c.reset}`)}` : '';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private buildProgressBar(done: number, total: number): string {
|
|
183
|
+
const width = 20;
|
|
184
|
+
const filled = Math.round((done / total) * width);
|
|
185
|
+
const empty = width - filled;
|
|
186
|
+
const pct = Math.round((done / total) * 100);
|
|
187
|
+
const bar = `${c.cyan}${'█'.repeat(filled)}${c.darkGray}${'░'.repeat(empty)}${c.reset}`;
|
|
188
|
+
return `${c.dim}[${c.reset}${bar}${c.dim}]${c.reset} ${c.dim}${pct}%${c.reset}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private formatTime(ms: number): string {
|
|
192
|
+
if (ms < 1000) return `${ms}ms`;
|
|
193
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Print extra phase for refactor/agents/report generation */
|
|
197
|
+
printExtraPhase(label: string, verb: string, color: string = c.cyan): void {
|
|
198
|
+
this.phaseStart = Date.now();
|
|
199
|
+
const idx = this.completedPhases.length + 1;
|
|
200
|
+
process.stderr.write(
|
|
201
|
+
` ${c.dim}[${idx}/—]${c.reset} ${color}◉${c.reset} ${c.bold}${label}${c.reset} ${c.dim}— ${verb}...${c.reset}\n`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
printExtraComplete(detail: string): void {
|
|
206
|
+
const elapsed = Date.now() - this.phaseStart;
|
|
207
|
+
process.stderr.write(
|
|
208
|
+
` ${c.dim} └─${c.reset} ${c.green}✓${c.reset} ${c.dim}${this.formatTime(elapsed)}${c.reset} ${detail}\n`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Final summary with score visualization */
|
|
213
|
+
printSummary(score: number, breakdown: Record<string, number>, stats: {
|
|
214
|
+
files: number; lines: number; antiPatterns: number;
|
|
215
|
+
refactorSteps?: number; refactorOps?: number; agents?: number;
|
|
216
|
+
}): void {
|
|
217
|
+
const totalTime = Date.now() - this.startTime;
|
|
218
|
+
const w = process.stderr;
|
|
219
|
+
|
|
220
|
+
w.write('\n');
|
|
221
|
+
w.write(` ${c.dim}──── Results ──────────────────────────────────────────────────${c.reset}\n`);
|
|
222
|
+
w.write('\n');
|
|
223
|
+
|
|
224
|
+
// Score meter
|
|
225
|
+
const scoreColor = score >= 80 ? c.green : score >= 60 ? c.yellow : c.red;
|
|
226
|
+
const meterWidth = 40;
|
|
227
|
+
const filled = Math.round((score / 100) * meterWidth);
|
|
228
|
+
const meter = `${scoreColor}${'━'.repeat(filled)}${c.darkGray}${'━'.repeat(meterWidth - filled)}${c.reset}`;
|
|
229
|
+
const grade = score >= 90 ? 'A+' : score >= 80 ? 'A' : score >= 70 ? 'B' : score >= 60 ? 'C' : score >= 50 ? 'D' : 'F';
|
|
230
|
+
|
|
231
|
+
w.write(` ${c.bold} ARCHITECTURE SCORE${c.reset}\n`);
|
|
232
|
+
w.write(` ${meter} ${scoreColor}${c.bold}${score}/100${c.reset} ${c.dim}(${grade})${c.reset}\n`);
|
|
233
|
+
w.write('\n');
|
|
234
|
+
w.write(` ${c.dim} Modularity${c.reset} ${this.miniBar(breakdown.modularity)} ${c.white}${breakdown.modularity}${c.reset}\n`);
|
|
235
|
+
w.write(` ${c.dim} Coupling${c.reset} ${this.miniBar(breakdown.coupling)} ${c.white}${breakdown.coupling}${c.reset}\n`);
|
|
236
|
+
w.write(` ${c.dim} Cohesion${c.reset} ${this.miniBar(breakdown.cohesion)} ${c.white}${breakdown.cohesion}${c.reset}\n`);
|
|
237
|
+
w.write(` ${c.dim} Layering${c.reset} ${this.miniBar(breakdown.layering)} ${c.white}${breakdown.layering}${c.reset}\n`);
|
|
238
|
+
w.write('\n');
|
|
239
|
+
|
|
240
|
+
// Stats line
|
|
241
|
+
w.write(` ${c.cyan}📁${c.reset} ${c.white}${stats.files}${c.reset}${c.dim} files${c.reset}`);
|
|
242
|
+
w.write(` ${c.cyan}📝${c.reset} ${c.white}${stats.lines.toLocaleString()}${c.reset}${c.dim} lines${c.reset}`);
|
|
243
|
+
w.write(` ${c.cyan}⚠️${c.reset} ${c.white}${stats.antiPatterns}${c.reset}${c.dim} anti-patterns${c.reset}`);
|
|
244
|
+
if (stats.refactorSteps !== undefined) {
|
|
245
|
+
w.write(` ${c.cyan}🔧${c.reset} ${c.white}${stats.refactorSteps}${c.reset}${c.dim} steps${c.reset}`);
|
|
246
|
+
}
|
|
247
|
+
if (stats.agents !== undefined) {
|
|
248
|
+
w.write(` ${c.cyan}🤖${c.reset} ${c.white}${stats.agents}${c.reset}${c.dim} agents${c.reset}`);
|
|
249
|
+
}
|
|
250
|
+
w.write('\n');
|
|
251
|
+
|
|
252
|
+
// Timing
|
|
253
|
+
w.write(`\n ${c.dim}⏱ Completed in ${this.formatTime(totalTime)}${c.reset}\n`);
|
|
254
|
+
w.write('\n');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private miniBar(value: number): string {
|
|
258
|
+
const w = 15;
|
|
259
|
+
const f = Math.round((value / 100) * w);
|
|
260
|
+
const color = value >= 80 ? c.green : value >= 60 ? c.yellow : c.red;
|
|
261
|
+
return `${color}${'▓'.repeat(f)}${c.darkGray}${'░'.repeat(w - f)}${c.reset}`;
|
|
69
262
|
}
|
|
70
263
|
}
|
|
264
|
+
|
|
265
|
+
// ── CLI Parsing ──
|
|
266
|
+
|
|
71
267
|
function parseArgs(args: string[]): CliOptions {
|
|
72
268
|
const command = args[0] || 'analyze';
|
|
73
269
|
const pathArg = args.find((a) => !a.startsWith('--') && a !== command) || '.';
|
|
@@ -81,30 +277,31 @@ function parseArgs(args: string[]): CliOptions {
|
|
|
81
277
|
|
|
82
278
|
function printUsage(): void {
|
|
83
279
|
console.log(`
|
|
84
|
-
|
|
280
|
+
${c.cyan}${c.bold}⚡ Architect v3.1${c.reset} — Enterprise Architecture Intelligence
|
|
85
281
|
|
|
86
|
-
Usage
|
|
282
|
+
${c.bold}Usage:${c.reset}
|
|
87
283
|
architect <command> [path] [options]
|
|
88
284
|
|
|
89
|
-
Commands
|
|
90
|
-
analyze Full architecture analysis (default)
|
|
91
|
-
refactor Generate refactoring plan with actionable steps
|
|
92
|
-
agents Generate/audit .agent/ directory with AI agents
|
|
93
|
-
diagram Generate architecture diagram only
|
|
94
|
-
score Calculate quality score only
|
|
95
|
-
anti-patterns Detect anti-patterns only
|
|
96
|
-
layers Analyze layer structure only
|
|
285
|
+
${c.bold}Commands:${c.reset}
|
|
286
|
+
${c.cyan}analyze${c.reset} Full architecture analysis (default)
|
|
287
|
+
${c.cyan}refactor${c.reset} Generate refactoring plan with actionable steps
|
|
288
|
+
${c.cyan}agents${c.reset} Generate/audit .agent/ directory with AI agents
|
|
289
|
+
${c.cyan}diagram${c.reset} Generate architecture diagram only
|
|
290
|
+
${c.cyan}score${c.reset} Calculate quality score only
|
|
291
|
+
${c.cyan}anti-patterns${c.reset} Detect anti-patterns only
|
|
292
|
+
${c.cyan}layers${c.reset} Analyze layer structure only
|
|
97
293
|
|
|
98
|
-
Options
|
|
294
|
+
${c.bold}Options:${c.reset}
|
|
99
295
|
--format <type> Output format: html, json, markdown (default: html)
|
|
100
|
-
--output <file> Output file path
|
|
296
|
+
--output <file> Output file path
|
|
101
297
|
--help Show this help message
|
|
102
298
|
|
|
103
|
-
Examples
|
|
104
|
-
architect analyze ./src
|
|
105
|
-
architect analyze ./src --format html --output report.html
|
|
106
|
-
architect score ./src --format json
|
|
107
|
-
|
|
299
|
+
${c.bold}Examples:${c.reset}
|
|
300
|
+
${c.dim}$${c.reset} architect analyze ./src
|
|
301
|
+
${c.dim}$${c.reset} architect analyze ./src --format html --output report.html
|
|
302
|
+
${c.dim}$${c.reset} architect score ./src --format json
|
|
303
|
+
|
|
304
|
+
${c.dim}@girardelli/architect — Girardelli Tecnologia${c.reset}
|
|
108
305
|
`);
|
|
109
306
|
}
|
|
110
307
|
|
|
@@ -118,113 +315,113 @@ async function main(): Promise<void> {
|
|
|
118
315
|
|
|
119
316
|
const options = parseArgs(args);
|
|
120
317
|
|
|
121
|
-
console.log('🏗️ Architect — Architecture Analysis');
|
|
122
|
-
console.log(`📂 Path: ${options.path}`);
|
|
123
|
-
console.log(`📋 Command: ${options.command}`);
|
|
124
|
-
console.log(`📄 Format: ${options.format}\n`);
|
|
125
|
-
|
|
126
318
|
try {
|
|
127
319
|
switch (options.command) {
|
|
128
320
|
case 'analyze': {
|
|
129
|
-
const progress = new
|
|
321
|
+
const progress = new ProgressReporter();
|
|
322
|
+
progress.printHeader(options.path);
|
|
130
323
|
|
|
131
|
-
|
|
132
|
-
const report = await architect.analyze(options.path);
|
|
133
|
-
progress.complete(`Scanned ${report.projectInfo.totalFiles} files (${report.projectInfo.totalLines.toLocaleString()} lines)`);
|
|
324
|
+
const report = await architect.analyze(options.path, (e) => progress.onProgress(e));
|
|
134
325
|
|
|
135
|
-
|
|
326
|
+
// Refactoring
|
|
327
|
+
progress.printExtraPhase('REFACTOR ENGINE', 'Building refactoring plan', c.orange);
|
|
136
328
|
const plan = architect.refactor(report, options.path);
|
|
137
|
-
progress.
|
|
329
|
+
progress.printExtraComplete(
|
|
330
|
+
`${c.white}${plan.steps.length}${c.reset}${c.dim} steps · ${c.reset}${c.white}${plan.totalOperations}${c.reset}${c.dim} operations · est. +${plan.estimatedScoreAfter.overall - plan.currentScore.overall} pts${c.reset}`
|
|
331
|
+
);
|
|
138
332
|
|
|
139
|
-
|
|
333
|
+
// Agent suggestion
|
|
334
|
+
progress.printExtraPhase('AGENT SYSTEM', 'Analyzing agent requirements', c.magenta);
|
|
140
335
|
const agentSuggestion = architect.suggestAgents(report, plan, options.path);
|
|
141
|
-
progress.
|
|
336
|
+
progress.printExtraComplete(
|
|
337
|
+
`${c.white}${agentSuggestion.suggestedAgents.length}${c.reset}${c.dim} agents suggested${agentSuggestion.hasExistingAgents ? ' (existing .agent/ audited)' : ''}${c.reset}`
|
|
338
|
+
);
|
|
142
339
|
|
|
143
340
|
const projectName = report.projectInfo.name || basename(options.path);
|
|
144
341
|
|
|
342
|
+
// Report generation
|
|
145
343
|
if (options.format === 'html') {
|
|
146
|
-
progress.
|
|
344
|
+
progress.printExtraPhase('REPORT BUILDER', 'Generating interactive HTML report', c.cyan);
|
|
147
345
|
const htmlGenerator = new HtmlReportGenerator();
|
|
148
346
|
const html = htmlGenerator.generateHtml(report, plan, agentSuggestion);
|
|
149
347
|
const outputPath = options.output || `architect-report-${projectName}.html`;
|
|
150
348
|
writeFileSync(outputPath, html);
|
|
151
|
-
progress.
|
|
349
|
+
progress.printExtraComplete(`${c.green}${outputPath}${c.reset}`);
|
|
152
350
|
} else if (options.format === 'markdown') {
|
|
153
|
-
progress.
|
|
351
|
+
progress.printExtraPhase('REPORT BUILDER', 'Generating Markdown report', c.cyan);
|
|
154
352
|
const mdGenerator = new ReportGenerator();
|
|
155
353
|
const markdown = mdGenerator.generateMarkdownReport(report);
|
|
156
354
|
const outputPath = options.output || `architect-report-${projectName}.md`;
|
|
157
355
|
writeFileSync(outputPath, markdown);
|
|
158
|
-
progress.
|
|
356
|
+
progress.printExtraComplete(`${c.green}${outputPath}${c.reset}`);
|
|
159
357
|
} else {
|
|
160
|
-
progress.
|
|
358
|
+
progress.printExtraPhase('REPORT BUILDER', 'Generating JSON report', c.cyan);
|
|
161
359
|
const outputPath = options.output || `architect-report-${projectName}.json`;
|
|
162
360
|
writeFileSync(outputPath, JSON.stringify({ report, plan, agentSuggestion }, null, 2));
|
|
163
|
-
progress.
|
|
361
|
+
progress.printExtraComplete(`${c.green}${outputPath}${c.reset}`);
|
|
164
362
|
}
|
|
165
363
|
|
|
166
|
-
//
|
|
167
|
-
progress.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
`└─ Layering: ${report.score.breakdown.layering}`,
|
|
176
|
-
``,
|
|
177
|
-
`📁 Files: ${report.projectInfo.totalFiles} | 📝 Lines: ${report.projectInfo.totalLines.toLocaleString()}`,
|
|
178
|
-
`⚠️ Anti-patterns: ${report.antiPatterns.length}`,
|
|
179
|
-
`🔧 Refactoring: ${plan.steps.length} steps (${plan.totalOperations} ops)`,
|
|
180
|
-
`🤖 Agents: ${agentSuggestion.suggestedAgents.length} suggested`,
|
|
181
|
-
]);
|
|
364
|
+
// Summary
|
|
365
|
+
progress.printSummary(report.score.overall, report.score.breakdown, {
|
|
366
|
+
files: report.projectInfo.totalFiles,
|
|
367
|
+
lines: report.projectInfo.totalLines,
|
|
368
|
+
antiPatterns: report.antiPatterns.length,
|
|
369
|
+
refactorSteps: plan.steps.length,
|
|
370
|
+
refactorOps: plan.totalOperations,
|
|
371
|
+
agents: agentSuggestion.suggestedAgents.length,
|
|
372
|
+
});
|
|
182
373
|
break;
|
|
183
374
|
}
|
|
184
375
|
|
|
185
376
|
case 'refactor': {
|
|
186
|
-
const
|
|
377
|
+
const progress = new ProgressReporter();
|
|
378
|
+
progress.printHeader(options.path);
|
|
379
|
+
|
|
380
|
+
const report = await architect.analyze(options.path, (e) => progress.onProgress(e));
|
|
381
|
+
|
|
382
|
+
progress.printExtraPhase('REFACTOR ENGINE', 'Building refactoring plan', c.orange);
|
|
187
383
|
const plan = architect.refactor(report, options.path);
|
|
188
384
|
const projectName = report.projectInfo.name || basename(options.path);
|
|
189
385
|
|
|
190
386
|
if (options.format === 'json') {
|
|
191
387
|
const outputPath = options.output || `refactor-plan-${projectName}.json`;
|
|
192
388
|
writeFileSync(outputPath, JSON.stringify(plan, null, 2));
|
|
193
|
-
|
|
389
|
+
progress.printExtraComplete(`${c.green}${outputPath}${c.reset}`);
|
|
194
390
|
} else {
|
|
195
391
|
const refactorReporter = new RefactorReportGenerator();
|
|
196
392
|
const html = refactorReporter.generateHtml(plan);
|
|
197
393
|
const outputPath = options.output || `refactor-plan-${projectName}.html`;
|
|
198
394
|
writeFileSync(outputPath, html);
|
|
199
|
-
|
|
395
|
+
progress.printExtraComplete(`${c.green}${outputPath}${c.reset}`);
|
|
200
396
|
}
|
|
201
397
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
console.log(`├─ Steps: ${plan.steps.length}`);
|
|
206
|
-
console.log(`├─ Operations: ${plan.totalOperations}`);
|
|
207
|
-
console.log(`├─ Tier 1: ${plan.tier1Steps} (rule-based)`);
|
|
208
|
-
console.log(`├─ Tier 2: ${plan.tier2Steps} (AST-based)`);
|
|
209
|
-
console.log(`├─ Current: ${plan.currentScore.overall}/100`);
|
|
210
|
-
console.log(`└─ Estimated: ${plan.estimatedScoreAfter.overall}/100 (+${plan.estimatedScoreAfter.overall - plan.currentScore.overall})`);
|
|
398
|
+
process.stderr.write(`\n ${c.bold}REFACTORING PLAN${c.reset}\n`);
|
|
399
|
+
process.stderr.write(` ${c.dim}Steps:${c.reset} ${c.white}${plan.steps.length}${c.reset} ${c.dim}Ops:${c.reset} ${c.white}${plan.totalOperations}${c.reset} ${c.dim}Tier1:${c.reset} ${c.white}${plan.tier1Steps}${c.reset} ${c.dim}Tier2:${c.reset} ${c.white}${plan.tier2Steps}${c.reset}\n`);
|
|
400
|
+
process.stderr.write(` ${c.dim}Score:${c.reset} ${c.white}${plan.currentScore.overall}${c.reset}${c.dim} → ${c.reset}${c.green}${plan.estimatedScoreAfter.overall}${c.reset} ${c.dim}(+${plan.estimatedScoreAfter.overall - plan.currentScore.overall})${c.reset}\n\n`);
|
|
211
401
|
break;
|
|
212
402
|
}
|
|
213
403
|
|
|
214
404
|
case 'agents': {
|
|
215
|
-
const
|
|
405
|
+
const progress = new ProgressReporter();
|
|
406
|
+
progress.printHeader(options.path);
|
|
407
|
+
|
|
408
|
+
const report = await architect.analyze(options.path, (e) => progress.onProgress(e));
|
|
409
|
+
|
|
410
|
+
progress.printExtraPhase('REFACTOR ENGINE', 'Building refactoring plan', c.orange);
|
|
216
411
|
const plan = architect.refactor(report, options.path);
|
|
412
|
+
progress.printExtraComplete(`${c.white}${plan.steps.length}${c.reset}${c.dim} steps${c.reset}`);
|
|
413
|
+
|
|
414
|
+
progress.printExtraPhase('AGENT GENERATOR', 'Generating .agent/ framework', c.magenta);
|
|
217
415
|
const outputDir = options.output || undefined;
|
|
218
416
|
const result = architect.agents(report, plan, options.path, outputDir);
|
|
417
|
+
progress.printExtraComplete(`${c.white}${result.generated.length}${c.reset}${c.dim} files generated${c.reset}`);
|
|
219
418
|
|
|
220
|
-
|
|
221
|
-
console.log(` 🤖 AGENT SYSTEM`);
|
|
222
|
-
console.log(`═══════════════════════════════════════`);
|
|
419
|
+
process.stderr.write(`\n ${c.bold}🤖 AGENT SYSTEM${c.reset}\n\n`);
|
|
223
420
|
|
|
224
421
|
if (result.generated.length > 0) {
|
|
225
|
-
|
|
422
|
+
process.stderr.write(` ${c.green}Generated:${c.reset}\n`);
|
|
226
423
|
for (const file of result.generated) {
|
|
227
|
-
|
|
424
|
+
process.stderr.write(` ${c.dim} 📄${c.reset} ${file}\n`);
|
|
228
425
|
}
|
|
229
426
|
}
|
|
230
427
|
|
|
@@ -233,25 +430,20 @@ async function main(): Promise<void> {
|
|
|
233
430
|
const improvements = result.audit.filter(f => f.type === 'IMPROVEMENT');
|
|
234
431
|
const ok = result.audit.filter(f => f.type === 'OK');
|
|
235
432
|
|
|
236
|
-
if (ok.length > 0) {
|
|
237
|
-
console.log(`\n✅ ${ok.length} checks passed`);
|
|
238
|
-
}
|
|
433
|
+
if (ok.length > 0) process.stderr.write(`\n ${c.green}✓ ${ok.length} checks passed${c.reset}\n`);
|
|
239
434
|
if (missing.length > 0) {
|
|
240
|
-
|
|
241
|
-
for (const f of missing) {
|
|
242
|
-
console.log(` 📄 ${f.file} — ${f.description}`);
|
|
243
|
-
}
|
|
435
|
+
process.stderr.write(`\n ${c.red}✗ ${missing.length} missing (auto-generated):${c.reset}\n`);
|
|
436
|
+
for (const f of missing) process.stderr.write(` ${c.dim}📄${c.reset} ${f.file} — ${f.description}\n`);
|
|
244
437
|
}
|
|
245
438
|
if (improvements.length > 0) {
|
|
246
|
-
|
|
439
|
+
process.stderr.write(`\n ${c.yellow}💡 ${improvements.length} improvements:${c.reset}\n`);
|
|
247
440
|
for (const f of improvements) {
|
|
248
|
-
|
|
249
|
-
if (f.suggestion)
|
|
441
|
+
process.stderr.write(` ${c.dim}⚡${c.reset} ${f.description}\n`);
|
|
442
|
+
if (f.suggestion) process.stderr.write(` ${c.dim}→ ${f.suggestion}${c.reset}\n`);
|
|
250
443
|
}
|
|
251
444
|
}
|
|
252
445
|
}
|
|
253
|
-
|
|
254
|
-
console.log(`\n📊 Score: ${report.score.overall}/100`);
|
|
446
|
+
process.stderr.write(`\n ${c.dim}Score: ${report.score.overall}/100${c.reset}\n\n`);
|
|
255
447
|
break;
|
|
256
448
|
}
|
|
257
449
|
|
|
@@ -259,7 +451,7 @@ async function main(): Promise<void> {
|
|
|
259
451
|
const diagram = await architect.diagram(options.path);
|
|
260
452
|
if (options.output) {
|
|
261
453
|
writeFileSync(options.output, diagram);
|
|
262
|
-
|
|
454
|
+
process.stderr.write(` ${c.green}✓${c.reset} Diagram saved: ${options.output}\n`);
|
|
263
455
|
} else {
|
|
264
456
|
console.log(diagram);
|
|
265
457
|
}
|
|
@@ -271,10 +463,13 @@ async function main(): Promise<void> {
|
|
|
271
463
|
if (options.format === 'json') {
|
|
272
464
|
console.log(JSON.stringify(score, null, 2));
|
|
273
465
|
} else {
|
|
274
|
-
|
|
466
|
+
const scoreColor = score.overall >= 80 ? c.green : score.overall >= 60 ? c.yellow : c.red;
|
|
467
|
+
process.stderr.write(`\n ${c.bold}ARCHITECTURE SCORE${c.reset}\n`);
|
|
468
|
+
process.stderr.write(` ${scoreColor}${c.bold}${score.overall}/100${c.reset}\n\n`);
|
|
275
469
|
for (const [name, value] of Object.entries(score.breakdown)) {
|
|
276
|
-
|
|
470
|
+
process.stderr.write(` ${c.dim}${name}:${c.reset} ${c.white}${value}${c.reset}\n`);
|
|
277
471
|
}
|
|
472
|
+
process.stderr.write('\n');
|
|
278
473
|
}
|
|
279
474
|
break;
|
|
280
475
|
}
|
|
@@ -284,10 +479,12 @@ async function main(): Promise<void> {
|
|
|
284
479
|
if (options.format === 'json') {
|
|
285
480
|
console.log(JSON.stringify(patterns, null, 2));
|
|
286
481
|
} else {
|
|
287
|
-
|
|
482
|
+
process.stderr.write(`\n ${c.bold}ANTI-PATTERNS${c.reset} — ${patterns.length} found\n\n`);
|
|
288
483
|
for (const p of patterns) {
|
|
289
|
-
|
|
484
|
+
const sevColor = p.severity === 'CRITICAL' ? c.red : p.severity === 'HIGH' ? c.orange : c.yellow;
|
|
485
|
+
process.stderr.write(` ${sevColor}[${p.severity}]${c.reset} ${c.bold}${p.name}${c.reset}: ${p.description}\n`);
|
|
290
486
|
}
|
|
487
|
+
process.stderr.write('\n');
|
|
291
488
|
}
|
|
292
489
|
break;
|
|
293
490
|
}
|
|
@@ -297,20 +494,22 @@ async function main(): Promise<void> {
|
|
|
297
494
|
if (options.format === 'json') {
|
|
298
495
|
console.log(JSON.stringify(layers, null, 2));
|
|
299
496
|
} else {
|
|
497
|
+
process.stderr.write(`\n ${c.bold}ARCHITECTURE LAYERS${c.reset}\n\n`);
|
|
300
498
|
for (const l of layers) {
|
|
301
|
-
|
|
499
|
+
process.stderr.write(` ${c.cyan}${l.name}${c.reset}: ${c.white}${l.files.length}${c.reset} files\n`);
|
|
302
500
|
}
|
|
501
|
+
process.stderr.write('\n');
|
|
303
502
|
}
|
|
304
503
|
break;
|
|
305
504
|
}
|
|
306
505
|
|
|
307
506
|
default:
|
|
308
|
-
console.error(
|
|
507
|
+
console.error(`${c.red}✗${c.reset} Unknown command: ${options.command}`);
|
|
309
508
|
printUsage();
|
|
310
509
|
process.exit(1);
|
|
311
510
|
}
|
|
312
511
|
} catch (error) {
|
|
313
|
-
|
|
512
|
+
process.stderr.write(`\n ${c.red}${c.bold}✗ ERROR${c.reset}: ${error instanceof Error ? error.message : error}\n\n`);
|
|
314
513
|
process.exit(1);
|
|
315
514
|
}
|
|
316
515
|
}
|