tlc-claude-code 1.2.29 → 1.4.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/dashboard/dist/components/AuditPane.d.ts +30 -0
- package/dashboard/dist/components/AuditPane.js +127 -0
- package/dashboard/dist/components/AuditPane.test.d.ts +1 -0
- package/dashboard/dist/components/AuditPane.test.js +339 -0
- package/dashboard/dist/components/CompliancePane.d.ts +39 -0
- package/dashboard/dist/components/CompliancePane.js +96 -0
- package/dashboard/dist/components/CompliancePane.test.d.ts +1 -0
- package/dashboard/dist/components/CompliancePane.test.js +183 -0
- package/dashboard/dist/components/SSOPane.d.ts +36 -0
- package/dashboard/dist/components/SSOPane.js +71 -0
- package/dashboard/dist/components/SSOPane.test.d.ts +1 -0
- package/dashboard/dist/components/SSOPane.test.js +155 -0
- package/dashboard/dist/components/UsagePane.d.ts +13 -0
- package/dashboard/dist/components/UsagePane.js +51 -0
- package/dashboard/dist/components/UsagePane.test.d.ts +1 -0
- package/dashboard/dist/components/UsagePane.test.js +142 -0
- package/dashboard/dist/components/WorkspaceDocsPane.d.ts +19 -0
- package/dashboard/dist/components/WorkspaceDocsPane.js +130 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.js +242 -0
- package/dashboard/dist/components/WorkspacePane.d.ts +18 -0
- package/dashboard/dist/components/WorkspacePane.js +17 -0
- package/dashboard/dist/components/WorkspacePane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspacePane.test.js +84 -0
- package/dashboard/dist/components/ZeroRetentionPane.d.ts +44 -0
- package/dashboard/dist/components/ZeroRetentionPane.js +83 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.d.ts +1 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.js +160 -0
- package/package.json +1 -1
- package/server/lib/access-control-doc.js +541 -0
- package/server/lib/access-control-doc.test.js +672 -0
- package/server/lib/adr-generator.js +423 -0
- package/server/lib/adr-generator.test.js +586 -0
- package/server/lib/agent-progress-monitor.js +223 -0
- package/server/lib/agent-progress-monitor.test.js +202 -0
- package/server/lib/architecture-command.js +450 -0
- package/server/lib/architecture-command.test.js +754 -0
- package/server/lib/ast-analyzer.js +324 -0
- package/server/lib/ast-analyzer.test.js +437 -0
- package/server/lib/audit-attribution.js +191 -0
- package/server/lib/audit-attribution.test.js +359 -0
- package/server/lib/audit-classifier.js +202 -0
- package/server/lib/audit-classifier.test.js +209 -0
- package/server/lib/audit-command.js +275 -0
- package/server/lib/audit-command.test.js +325 -0
- package/server/lib/audit-exporter.js +380 -0
- package/server/lib/audit-exporter.test.js +464 -0
- package/server/lib/audit-logger.js +236 -0
- package/server/lib/audit-logger.test.js +364 -0
- package/server/lib/audit-query.js +257 -0
- package/server/lib/audit-query.test.js +352 -0
- package/server/lib/audit-storage.js +269 -0
- package/server/lib/audit-storage.test.js +272 -0
- package/server/lib/auth-system.test.js +4 -1
- package/server/lib/boundary-detector.js +427 -0
- package/server/lib/boundary-detector.test.js +320 -0
- package/server/lib/budget-alerts.js +138 -0
- package/server/lib/budget-alerts.test.js +235 -0
- package/server/lib/bulk-repo-init.js +342 -0
- package/server/lib/bulk-repo-init.test.js +388 -0
- package/server/lib/candidates-tracker.js +210 -0
- package/server/lib/candidates-tracker.test.js +300 -0
- package/server/lib/checkpoint-manager.js +251 -0
- package/server/lib/checkpoint-manager.test.js +474 -0
- package/server/lib/circular-detector.js +337 -0
- package/server/lib/circular-detector.test.js +353 -0
- package/server/lib/cohesion-analyzer.js +310 -0
- package/server/lib/cohesion-analyzer.test.js +447 -0
- package/server/lib/compliance-checklist.js +866 -0
- package/server/lib/compliance-checklist.test.js +476 -0
- package/server/lib/compliance-command.js +616 -0
- package/server/lib/compliance-command.test.js +551 -0
- package/server/lib/compliance-reporter.js +692 -0
- package/server/lib/compliance-reporter.test.js +707 -0
- package/server/lib/contract-testing.js +625 -0
- package/server/lib/contract-testing.test.js +342 -0
- package/server/lib/conversion-planner.js +469 -0
- package/server/lib/conversion-planner.test.js +361 -0
- package/server/lib/convert-command.js +351 -0
- package/server/lib/convert-command.test.js +608 -0
- package/server/lib/coupling-calculator.js +189 -0
- package/server/lib/coupling-calculator.test.js +509 -0
- package/server/lib/data-flow-doc.js +665 -0
- package/server/lib/data-flow-doc.test.js +659 -0
- package/server/lib/dependency-graph.js +367 -0
- package/server/lib/dependency-graph.test.js +516 -0
- package/server/lib/duplication-detector.js +349 -0
- package/server/lib/duplication-detector.test.js +401 -0
- package/server/lib/ephemeral-storage.js +249 -0
- package/server/lib/ephemeral-storage.test.js +254 -0
- package/server/lib/evidence-collector.js +627 -0
- package/server/lib/evidence-collector.test.js +901 -0
- package/server/lib/example-service.js +616 -0
- package/server/lib/example-service.test.js +397 -0
- package/server/lib/flow-diagram-generator.js +474 -0
- package/server/lib/flow-diagram-generator.test.js +446 -0
- package/server/lib/idp-manager.js +626 -0
- package/server/lib/idp-manager.test.js +587 -0
- package/server/lib/impact-scorer.js +184 -0
- package/server/lib/impact-scorer.test.js +211 -0
- package/server/lib/memory-exclusion.js +326 -0
- package/server/lib/memory-exclusion.test.js +241 -0
- package/server/lib/mermaid-generator.js +358 -0
- package/server/lib/mermaid-generator.test.js +301 -0
- package/server/lib/messaging-patterns.js +750 -0
- package/server/lib/messaging-patterns.test.js +213 -0
- package/server/lib/mfa-handler.js +452 -0
- package/server/lib/mfa-handler.test.js +490 -0
- package/server/lib/microservice-template.js +386 -0
- package/server/lib/microservice-template.test.js +325 -0
- package/server/lib/new-project-microservice.js +450 -0
- package/server/lib/new-project-microservice.test.js +600 -0
- package/server/lib/oauth-flow.js +375 -0
- package/server/lib/oauth-flow.test.js +487 -0
- package/server/lib/oauth-registry.js +190 -0
- package/server/lib/oauth-registry.test.js +306 -0
- package/server/lib/readme-generator.js +490 -0
- package/server/lib/readme-generator.test.js +493 -0
- package/server/lib/refactor-command.js +326 -0
- package/server/lib/refactor-command.test.js +528 -0
- package/server/lib/refactor-executor.js +254 -0
- package/server/lib/refactor-executor.test.js +305 -0
- package/server/lib/refactor-observer.js +292 -0
- package/server/lib/refactor-observer.test.js +422 -0
- package/server/lib/refactor-progress.js +193 -0
- package/server/lib/refactor-progress.test.js +251 -0
- package/server/lib/refactor-reporter.js +237 -0
- package/server/lib/refactor-reporter.test.js +247 -0
- package/server/lib/repo-dependency-tracker.js +261 -0
- package/server/lib/repo-dependency-tracker.test.js +350 -0
- package/server/lib/retention-policy.js +281 -0
- package/server/lib/retention-policy.test.js +486 -0
- package/server/lib/role-mapper.js +236 -0
- package/server/lib/role-mapper.test.js +395 -0
- package/server/lib/saml-provider.js +765 -0
- package/server/lib/saml-provider.test.js +643 -0
- package/server/lib/security-policy-generator.js +682 -0
- package/server/lib/security-policy-generator.test.js +544 -0
- package/server/lib/semantic-analyzer.js +198 -0
- package/server/lib/semantic-analyzer.test.js +474 -0
- package/server/lib/sensitive-detector.js +112 -0
- package/server/lib/sensitive-detector.test.js +209 -0
- package/server/lib/service-interaction-diagram.js +700 -0
- package/server/lib/service-interaction-diagram.test.js +638 -0
- package/server/lib/service-scaffold.js +486 -0
- package/server/lib/service-scaffold.test.js +373 -0
- package/server/lib/service-summary.js +553 -0
- package/server/lib/service-summary.test.js +619 -0
- package/server/lib/session-purge.js +460 -0
- package/server/lib/session-purge.test.js +312 -0
- package/server/lib/shared-kernel.js +578 -0
- package/server/lib/shared-kernel.test.js +255 -0
- package/server/lib/sso-command.js +544 -0
- package/server/lib/sso-command.test.js +552 -0
- package/server/lib/sso-session.js +492 -0
- package/server/lib/sso-session.test.js +670 -0
- package/server/lib/traefik-config.js +282 -0
- package/server/lib/traefik-config.test.js +312 -0
- package/server/lib/usage-command.js +218 -0
- package/server/lib/usage-command.test.js +391 -0
- package/server/lib/usage-formatter.js +192 -0
- package/server/lib/usage-formatter.test.js +267 -0
- package/server/lib/usage-history.js +122 -0
- package/server/lib/usage-history.test.js +206 -0
- package/server/lib/workspace-command.js +249 -0
- package/server/lib/workspace-command.test.js +264 -0
- package/server/lib/workspace-config.js +270 -0
- package/server/lib/workspace-config.test.js +312 -0
- package/server/lib/workspace-docs-command.js +547 -0
- package/server/lib/workspace-docs-command.test.js +692 -0
- package/server/lib/workspace-memory.js +451 -0
- package/server/lib/workspace-memory.test.js +403 -0
- package/server/lib/workspace-scanner.js +452 -0
- package/server/lib/workspace-scanner.test.js +677 -0
- package/server/lib/workspace-test-runner.js +315 -0
- package/server/lib/workspace-test-runner.test.js +294 -0
- package/server/lib/zero-retention-command.js +439 -0
- package/server/lib/zero-retention-command.test.js +448 -0
- package/server/lib/zero-retention.js +322 -0
- package/server/lib/zero-retention.test.js +258 -0
- package/server/package-lock.json +14 -0
- package/server/package.json +1 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture Command
|
|
3
|
+
* Main orchestrator for /tlc:architecture skill
|
|
4
|
+
* Analyzes codebase architecture: dependencies, boundaries, coupling, cohesion, cycles
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { DependencyGraph } = require('./dependency-graph.js');
|
|
9
|
+
const { MermaidGenerator } = require('./mermaid-generator.js');
|
|
10
|
+
const { BoundaryDetector } = require('./boundary-detector.js');
|
|
11
|
+
const { CouplingCalculator } = require('./coupling-calculator.js');
|
|
12
|
+
const { CohesionAnalyzer } = require('./cohesion-analyzer.js');
|
|
13
|
+
const { CircularDetector } = require('./circular-detector.js');
|
|
14
|
+
|
|
15
|
+
class ArchitectureCommand {
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.basePath = options.basePath || process.cwd();
|
|
19
|
+
|
|
20
|
+
// Dependency injection for all modules
|
|
21
|
+
this.dependencyGraph = options.dependencyGraph || new DependencyGraph({
|
|
22
|
+
basePath: this.basePath,
|
|
23
|
+
...options.graphOptions,
|
|
24
|
+
});
|
|
25
|
+
this.mermaidGenerator = options.mermaidGenerator || new MermaidGenerator(options.mermaidOptions);
|
|
26
|
+
this.boundaryDetector = options.boundaryDetector || new BoundaryDetector(options.boundaryOptions);
|
|
27
|
+
this.couplingCalculator = options.couplingCalculator || null; // Created after graph built
|
|
28
|
+
this.cohesionAnalyzer = options.cohesionAnalyzer || new CohesionAnalyzer({
|
|
29
|
+
basePath: this.basePath,
|
|
30
|
+
...options.cohesionOptions,
|
|
31
|
+
});
|
|
32
|
+
this.circularDetector = options.circularDetector || new CircularDetector({
|
|
33
|
+
basePath: this.basePath,
|
|
34
|
+
...options.circularOptions,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Callbacks for progress reporting
|
|
38
|
+
this.onProgress = options.onProgress || (() => {});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Run the architecture command
|
|
43
|
+
* @param {Object} options - Command options
|
|
44
|
+
* @returns {Object} Analysis results
|
|
45
|
+
*/
|
|
46
|
+
async run(options = {}) {
|
|
47
|
+
const {
|
|
48
|
+
analyze = false, // --analyze: full analysis
|
|
49
|
+
boundaries = false, // --boundaries: service boundaries
|
|
50
|
+
diagram = false, // --diagram: Mermaid output
|
|
51
|
+
metrics = false, // --metrics: coupling/cohesion scores
|
|
52
|
+
circular = false, // --circular: dependency cycles
|
|
53
|
+
targetPath = null, // Path targeting for specific modules
|
|
54
|
+
format = 'text', // Output format: 'text', 'json', 'markdown'
|
|
55
|
+
} = options;
|
|
56
|
+
|
|
57
|
+
const result = {
|
|
58
|
+
success: true,
|
|
59
|
+
targetPath,
|
|
60
|
+
graph: null,
|
|
61
|
+
analysis: null,
|
|
62
|
+
boundaries: null,
|
|
63
|
+
diagram: null,
|
|
64
|
+
metrics: null,
|
|
65
|
+
circular: null,
|
|
66
|
+
report: null,
|
|
67
|
+
error: null,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
// Step 1: Build dependency graph
|
|
72
|
+
this.onProgress({ phase: 'building-graph', message: 'Building dependency graph...' });
|
|
73
|
+
|
|
74
|
+
const scanPath = targetPath
|
|
75
|
+
? path.resolve(this.basePath, targetPath)
|
|
76
|
+
: this.basePath;
|
|
77
|
+
|
|
78
|
+
await this.dependencyGraph.buildFromDirectory(scanPath);
|
|
79
|
+
result.graph = this.dependencyGraph.getGraph();
|
|
80
|
+
|
|
81
|
+
// Create coupling calculator now that graph is built
|
|
82
|
+
if (!this.couplingCalculator) {
|
|
83
|
+
this.couplingCalculator = new CouplingCalculator(this.dependencyGraph);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Step 2: Run requested analyses
|
|
87
|
+
if (analyze || (!boundaries && !diagram && !metrics && !circular)) {
|
|
88
|
+
// Full analysis (default if no specific flags)
|
|
89
|
+
result.analysis = await this.runFullAnalysis(result.graph);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (boundaries || analyze) {
|
|
93
|
+
this.onProgress({ phase: 'analyzing-boundaries', message: 'Detecting service boundaries...' });
|
|
94
|
+
result.boundaries = this.analyzeBoundaries(result.graph);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (diagram || analyze) {
|
|
98
|
+
this.onProgress({ phase: 'generating-diagram', message: 'Generating Mermaid diagram...' });
|
|
99
|
+
result.diagram = this.generateDiagram(result.graph, options);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (metrics || analyze) {
|
|
103
|
+
this.onProgress({ phase: 'calculating-metrics', message: 'Calculating coupling and cohesion metrics...' });
|
|
104
|
+
result.metrics = this.calculateMetrics(result.graph);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (circular || analyze) {
|
|
108
|
+
this.onProgress({ phase: 'detecting-cycles', message: 'Detecting circular dependencies...' });
|
|
109
|
+
result.circular = this.detectCircular(result.graph);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Step 3: Generate report
|
|
113
|
+
result.report = this.generateReport(result, format);
|
|
114
|
+
|
|
115
|
+
this.onProgress({ phase: 'complete', message: 'Analysis complete' });
|
|
116
|
+
|
|
117
|
+
} catch (error) {
|
|
118
|
+
result.success = false;
|
|
119
|
+
result.error = error.message;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Run full architecture analysis
|
|
127
|
+
*/
|
|
128
|
+
async runFullAnalysis(graph) {
|
|
129
|
+
const boundaries = this.analyzeBoundaries(graph);
|
|
130
|
+
const metrics = this.calculateMetrics(graph);
|
|
131
|
+
const circular = this.detectCircular(graph);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
summary: {
|
|
135
|
+
totalFiles: graph.stats.totalFiles,
|
|
136
|
+
totalDependencies: graph.stats.totalEdges,
|
|
137
|
+
externalDependencies: graph.stats.externalDeps,
|
|
138
|
+
suggestedServices: boundaries.services?.length || 0,
|
|
139
|
+
cyclesFound: circular.cycleCount || 0,
|
|
140
|
+
averageCohesion: metrics.cohesion?.summary?.averageCohesion || 0,
|
|
141
|
+
},
|
|
142
|
+
boundaries,
|
|
143
|
+
metrics,
|
|
144
|
+
circular,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Analyze service boundaries
|
|
150
|
+
*/
|
|
151
|
+
analyzeBoundaries(graph) {
|
|
152
|
+
const couplingData = {
|
|
153
|
+
modules: this.couplingCalculator.getAllMetrics().map(m => ({
|
|
154
|
+
name: path.dirname(path.relative(this.basePath, m.file)) || '(root)',
|
|
155
|
+
afferent: m.afferentCoupling,
|
|
156
|
+
efferent: m.efferentCoupling,
|
|
157
|
+
instability: m.instability,
|
|
158
|
+
})),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const cohesionData = this.cohesionAnalyzer.analyze(this.dependencyGraph);
|
|
162
|
+
|
|
163
|
+
return this.boundaryDetector.detect(graph, couplingData, cohesionData);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Generate Mermaid diagram
|
|
168
|
+
*/
|
|
169
|
+
generateDiagram(graph, options = {}) {
|
|
170
|
+
const { targetPath, diagramType = 'flowchart' } = options;
|
|
171
|
+
|
|
172
|
+
// If targeting specific module, generate filtered diagram
|
|
173
|
+
if (targetPath) {
|
|
174
|
+
return this.mermaidGenerator.generateModuleDiagram(graph, targetPath, {
|
|
175
|
+
direction: 'LR',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check for cycles to highlight
|
|
180
|
+
const circularResult = this.circularDetector.detect(this.dependencyGraph);
|
|
181
|
+
const cycles = circularResult.hasCycles
|
|
182
|
+
? circularResult.cycles.map(c => c.pathNames)
|
|
183
|
+
: [];
|
|
184
|
+
|
|
185
|
+
return this.mermaidGenerator.generateFlowchart(graph, {
|
|
186
|
+
cycles,
|
|
187
|
+
highlightCycles: cycles.length > 0,
|
|
188
|
+
groupByDirectory: true,
|
|
189
|
+
maxNodes: options.maxNodes || 50,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Calculate coupling and cohesion metrics
|
|
195
|
+
*/
|
|
196
|
+
calculateMetrics(graph) {
|
|
197
|
+
// Coupling metrics
|
|
198
|
+
const allCoupling = this.couplingCalculator.getAllMetrics();
|
|
199
|
+
const hubFiles = this.couplingCalculator.getHubFiles({ threshold: 3 });
|
|
200
|
+
const dependentFiles = this.couplingCalculator.getDependentFiles({ threshold: 3 });
|
|
201
|
+
const isolatedFiles = this.couplingCalculator.getIsolatedFiles();
|
|
202
|
+
const highlyCoupled = this.couplingCalculator.getHighlyCoupledModules({ threshold: 5 });
|
|
203
|
+
|
|
204
|
+
// Cohesion metrics
|
|
205
|
+
const cohesion = this.cohesionAnalyzer.analyze(this.dependencyGraph);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
coupling: {
|
|
209
|
+
files: allCoupling.map(m => ({
|
|
210
|
+
file: path.relative(this.basePath, m.file),
|
|
211
|
+
afferentCoupling: m.afferentCoupling,
|
|
212
|
+
efferentCoupling: m.efferentCoupling,
|
|
213
|
+
instability: Math.round(m.instability * 100) / 100,
|
|
214
|
+
})),
|
|
215
|
+
hubs: hubFiles.map(h => ({
|
|
216
|
+
file: path.relative(this.basePath, h.file),
|
|
217
|
+
dependents: h.afferentCoupling,
|
|
218
|
+
})),
|
|
219
|
+
dependent: dependentFiles.map(d => ({
|
|
220
|
+
file: path.relative(this.basePath, d.file),
|
|
221
|
+
dependencies: d.efferentCoupling,
|
|
222
|
+
})),
|
|
223
|
+
isolated: isolatedFiles.map(f => path.relative(this.basePath, f)),
|
|
224
|
+
highlyCoupled: highlyCoupled.map(h => ({
|
|
225
|
+
file: path.relative(this.basePath, h.file),
|
|
226
|
+
total: h.totalCoupling,
|
|
227
|
+
afferent: h.afferentCoupling,
|
|
228
|
+
efferent: h.efferentCoupling,
|
|
229
|
+
})),
|
|
230
|
+
summary: {
|
|
231
|
+
totalFiles: allCoupling.length,
|
|
232
|
+
hubCount: hubFiles.length,
|
|
233
|
+
isolatedCount: isolatedFiles.length,
|
|
234
|
+
highlyCoupledCount: highlyCoupled.length,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
cohesion,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Detect circular dependencies
|
|
243
|
+
*/
|
|
244
|
+
detectCircular(graph) {
|
|
245
|
+
return this.circularDetector.detect(this.dependencyGraph);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Generate formatted report
|
|
250
|
+
*/
|
|
251
|
+
generateReport(result, format) {
|
|
252
|
+
switch (format) {
|
|
253
|
+
case 'json':
|
|
254
|
+
return this.generateJsonReport(result);
|
|
255
|
+
case 'markdown':
|
|
256
|
+
return this.generateMarkdownReport(result);
|
|
257
|
+
case 'text':
|
|
258
|
+
default:
|
|
259
|
+
return this.generateTextReport(result);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Generate JSON report
|
|
265
|
+
*/
|
|
266
|
+
generateJsonReport(result) {
|
|
267
|
+
return JSON.stringify({
|
|
268
|
+
success: result.success,
|
|
269
|
+
targetPath: result.targetPath,
|
|
270
|
+
stats: result.graph?.stats,
|
|
271
|
+
analysis: result.analysis,
|
|
272
|
+
boundaries: result.boundaries,
|
|
273
|
+
metrics: result.metrics,
|
|
274
|
+
circular: result.circular,
|
|
275
|
+
diagram: result.diagram,
|
|
276
|
+
error: result.error,
|
|
277
|
+
}, null, 2);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Generate Markdown report
|
|
282
|
+
*/
|
|
283
|
+
generateMarkdownReport(result) {
|
|
284
|
+
const lines = ['# Architecture Analysis Report\n'];
|
|
285
|
+
|
|
286
|
+
// Summary
|
|
287
|
+
if (result.analysis?.summary) {
|
|
288
|
+
const s = result.analysis.summary;
|
|
289
|
+
lines.push('## Summary\n');
|
|
290
|
+
lines.push(`| Metric | Value |`);
|
|
291
|
+
lines.push(`|--------|-------|`);
|
|
292
|
+
lines.push(`| Total Files | ${s.totalFiles} |`);
|
|
293
|
+
lines.push(`| Total Dependencies | ${s.totalDependencies} |`);
|
|
294
|
+
lines.push(`| External Dependencies | ${s.externalDependencies} |`);
|
|
295
|
+
lines.push(`| Suggested Services | ${s.suggestedServices} |`);
|
|
296
|
+
lines.push(`| Circular Dependencies | ${s.cyclesFound} |`);
|
|
297
|
+
lines.push(`| Average Cohesion | ${(s.averageCohesion * 100).toFixed(1)}% |`);
|
|
298
|
+
lines.push('');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Boundaries
|
|
302
|
+
if (result.boundaries?.services) {
|
|
303
|
+
lines.push('## Service Boundaries\n');
|
|
304
|
+
lines.push('### Detected Services\n');
|
|
305
|
+
for (const service of result.boundaries.services.slice(0, 10)) {
|
|
306
|
+
lines.push(`- **${service.name}** (${service.fileCount} files, quality: ${service.quality}/100)`);
|
|
307
|
+
if (service.dependencies.length > 0) {
|
|
308
|
+
lines.push(` - Depends on: ${service.dependencies.join(', ')}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
lines.push('');
|
|
312
|
+
|
|
313
|
+
if (result.boundaries.suggestions?.length > 0) {
|
|
314
|
+
lines.push('### Suggestions\n');
|
|
315
|
+
for (const suggestion of result.boundaries.suggestions.slice(0, 5)) {
|
|
316
|
+
lines.push(`- ${suggestion.message}`);
|
|
317
|
+
}
|
|
318
|
+
lines.push('');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Metrics
|
|
323
|
+
if (result.metrics) {
|
|
324
|
+
lines.push('## Coupling Metrics\n');
|
|
325
|
+
|
|
326
|
+
if (result.metrics.coupling.hubs.length > 0) {
|
|
327
|
+
lines.push('### Hub Files (Most Depended Upon)\n');
|
|
328
|
+
lines.push('| File | Dependents |');
|
|
329
|
+
lines.push('|------|------------|');
|
|
330
|
+
for (const hub of result.metrics.coupling.hubs.slice(0, 10)) {
|
|
331
|
+
lines.push(`| ${hub.file} | ${hub.dependents} |`);
|
|
332
|
+
}
|
|
333
|
+
lines.push('');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (result.metrics.coupling.highlyCoupled.length > 0) {
|
|
337
|
+
lines.push('### Highly Coupled Files\n');
|
|
338
|
+
lines.push('| File | Total | In | Out |');
|
|
339
|
+
lines.push('|------|-------|-----|-----|');
|
|
340
|
+
for (const file of result.metrics.coupling.highlyCoupled.slice(0, 10)) {
|
|
341
|
+
lines.push(`| ${file.file} | ${file.total} | ${file.afferent} | ${file.efferent} |`);
|
|
342
|
+
}
|
|
343
|
+
lines.push('');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
lines.push('## Cohesion Metrics\n');
|
|
347
|
+
if (result.metrics.cohesion?.lowCohesion?.length > 0) {
|
|
348
|
+
lines.push('### Low Cohesion Modules\n');
|
|
349
|
+
lines.push('| Module | Cohesion | Internal | External |');
|
|
350
|
+
lines.push('|--------|----------|----------|----------|');
|
|
351
|
+
for (const mod of result.metrics.cohesion.lowCohesion.slice(0, 10)) {
|
|
352
|
+
lines.push(`| ${mod.module} | ${(mod.cohesion * 100).toFixed(1)}% | ${mod.internalDeps} | ${mod.externalDeps} |`);
|
|
353
|
+
}
|
|
354
|
+
lines.push('');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Circular dependencies
|
|
359
|
+
if (result.circular?.hasCycles) {
|
|
360
|
+
lines.push('## Circular Dependencies\n');
|
|
361
|
+
lines.push(`Found ${result.circular.cycleCount} cycle(s):\n`);
|
|
362
|
+
for (let i = 0; i < Math.min(result.circular.cycles.length, 5); i++) {
|
|
363
|
+
const cycle = result.circular.cycles[i];
|
|
364
|
+
lines.push(`### Cycle ${i + 1}`);
|
|
365
|
+
lines.push('```');
|
|
366
|
+
lines.push(cycle.pathNames.join(' -> ') + ' -> ' + cycle.pathNames[0]);
|
|
367
|
+
lines.push('```');
|
|
368
|
+
if (result.circular.suggestions?.[i]) {
|
|
369
|
+
lines.push(`**Suggestion:** ${result.circular.suggestions[i].reason}`);
|
|
370
|
+
}
|
|
371
|
+
lines.push('');
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Diagram
|
|
376
|
+
if (result.diagram) {
|
|
377
|
+
lines.push('## Dependency Diagram\n');
|
|
378
|
+
lines.push('```mermaid');
|
|
379
|
+
lines.push(result.diagram);
|
|
380
|
+
lines.push('```');
|
|
381
|
+
lines.push('');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return lines.join('\n');
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Generate plain text report
|
|
389
|
+
*/
|
|
390
|
+
generateTextReport(result) {
|
|
391
|
+
const lines = ['ARCHITECTURE ANALYSIS REPORT', '='.repeat(50), ''];
|
|
392
|
+
|
|
393
|
+
// Summary
|
|
394
|
+
if (result.analysis?.summary) {
|
|
395
|
+
const s = result.analysis.summary;
|
|
396
|
+
lines.push('SUMMARY');
|
|
397
|
+
lines.push('-'.repeat(30));
|
|
398
|
+
lines.push(`Total Files: ${s.totalFiles}`);
|
|
399
|
+
lines.push(`Total Dependencies: ${s.totalDependencies}`);
|
|
400
|
+
lines.push(`External Dependencies: ${s.externalDependencies}`);
|
|
401
|
+
lines.push(`Suggested Services: ${s.suggestedServices}`);
|
|
402
|
+
lines.push(`Circular Dependencies: ${s.cyclesFound}`);
|
|
403
|
+
lines.push(`Average Cohesion: ${(s.averageCohesion * 100).toFixed(1)}%`);
|
|
404
|
+
lines.push('');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Boundaries
|
|
408
|
+
if (result.boundaries?.services) {
|
|
409
|
+
lines.push('SERVICE BOUNDARIES');
|
|
410
|
+
lines.push('-'.repeat(30));
|
|
411
|
+
for (const service of result.boundaries.services.slice(0, 10)) {
|
|
412
|
+
lines.push(` ${service.name} (${service.fileCount} files, quality: ${service.quality}/100)`);
|
|
413
|
+
}
|
|
414
|
+
lines.push('');
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Cycles
|
|
418
|
+
if (result.circular?.hasCycles) {
|
|
419
|
+
lines.push('CIRCULAR DEPENDENCIES');
|
|
420
|
+
lines.push('-'.repeat(30));
|
|
421
|
+
lines.push(`Found ${result.circular.cycleCount} cycle(s)`);
|
|
422
|
+
for (const cycle of result.circular.cycles.slice(0, 5)) {
|
|
423
|
+
lines.push(` ${cycle.pathNames.join(' -> ')} -> ${cycle.pathNames[0]}`);
|
|
424
|
+
}
|
|
425
|
+
lines.push('');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Metrics summary
|
|
429
|
+
if (result.metrics?.coupling?.summary) {
|
|
430
|
+
const s = result.metrics.coupling.summary;
|
|
431
|
+
lines.push('COUPLING SUMMARY');
|
|
432
|
+
lines.push('-'.repeat(30));
|
|
433
|
+
lines.push(`Hub Files: ${s.hubCount}`);
|
|
434
|
+
lines.push(`Isolated Files: ${s.isolatedCount}`);
|
|
435
|
+
lines.push(`Highly Coupled: ${s.highlyCoupledCount}`);
|
|
436
|
+
lines.push('');
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Diagram placeholder
|
|
440
|
+
if (result.diagram) {
|
|
441
|
+
lines.push('MERMAID DIAGRAM');
|
|
442
|
+
lines.push('-'.repeat(30));
|
|
443
|
+
lines.push(result.diagram);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return lines.join('\n');
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
module.exports = { ArchitectureCommand };
|