vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642
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 +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics and Trends Generator for Analysis Reports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generate comprehensive statistics and trend analysis
|
|
7
|
+
*/
|
|
8
|
+
class StatisticsGenerator {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.trendData = new Map();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate comprehensive statistics
|
|
15
|
+
* @param {Object} analysisData - Complete analysis data
|
|
16
|
+
* @returns {Object} Statistics object
|
|
17
|
+
*/
|
|
18
|
+
generateStatistics(analysisData) {
|
|
19
|
+
const files = analysisData.files || [];
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
overview: this.generateOverviewStats(files),
|
|
23
|
+
sizeDistribution: this.generateSizeDistribution(files),
|
|
24
|
+
complexityDistribution: this.generateComplexityDistribution(files),
|
|
25
|
+
complianceMetrics: this.generateComplianceMetrics(files),
|
|
26
|
+
packageMetrics: this.generatePackageMetrics(files),
|
|
27
|
+
violationMetrics: this.generateViolationMetrics(files),
|
|
28
|
+
riskMetrics: this.generateRiskMetrics(files),
|
|
29
|
+
effortEstimates: this.generateEffortEstimates(files)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Generate overview statistics
|
|
35
|
+
* @param {Array} files - Files to analyze
|
|
36
|
+
* @returns {Object} Overview statistics
|
|
37
|
+
*/
|
|
38
|
+
generateOverviewStats(files) {
|
|
39
|
+
const totalFiles = files.length;
|
|
40
|
+
const totalLines = files.reduce((sum, f) => sum + f.lineCount, 0);
|
|
41
|
+
const averageLines = totalFiles > 0 ? Math.round(totalLines / totalFiles) : 0;
|
|
42
|
+
|
|
43
|
+
const filesNeedingRefactoring = files.filter(f => f.needsRefactoring).length;
|
|
44
|
+
const urgentFiles = files.filter(f => f.urgentRefactoring).length;
|
|
45
|
+
const complianceRate = totalFiles > 0 ? Math.round(((totalFiles - filesNeedingRefactoring) / totalFiles) * 100) : 0;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
totalFiles,
|
|
49
|
+
totalLines,
|
|
50
|
+
averageLines,
|
|
51
|
+
filesNeedingRefactoring,
|
|
52
|
+
urgentFiles,
|
|
53
|
+
complianceRate,
|
|
54
|
+
status: this.getOverallStatus(complianceRate, urgentFiles)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Generate size distribution statistics
|
|
60
|
+
* @param {Array} files - Files to analyze
|
|
61
|
+
* @returns {Object} Size distribution
|
|
62
|
+
*/
|
|
63
|
+
generateSizeDistribution(files) {
|
|
64
|
+
const distribution = {
|
|
65
|
+
SMALL: { count: 0, lines: 0, percentage: 0 },
|
|
66
|
+
MEDIUM: { count: 0, lines: 0, percentage: 0 },
|
|
67
|
+
LARGE: { count: 0, lines: 0, percentage: 0 },
|
|
68
|
+
XLARGE: { count: 0, lines: 0, percentage: 0 }
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
for (const file of files) {
|
|
72
|
+
const category = file.sizeCategory || 'UNKNOWN';
|
|
73
|
+
if (distribution[category]) {
|
|
74
|
+
distribution[category].count += 1;
|
|
75
|
+
distribution[category].lines += file.lineCount;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Calculate percentages
|
|
80
|
+
const totalFiles = files.length;
|
|
81
|
+
for (const category of Object.keys(distribution)) {
|
|
82
|
+
distribution[category].percentage = totalFiles > 0
|
|
83
|
+
? Math.round((distribution[category].count / totalFiles) * 100)
|
|
84
|
+
: 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return distribution;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generate complexity distribution statistics
|
|
92
|
+
* @param {Array} files - Files to analyze
|
|
93
|
+
* @returns {Object} Complexity distribution
|
|
94
|
+
*/
|
|
95
|
+
generateComplexityDistribution(files) {
|
|
96
|
+
const scores = files
|
|
97
|
+
.map(f => f.getComplexityScore ? f.getComplexityScore() : 0)
|
|
98
|
+
.filter(score => score > 0);
|
|
99
|
+
|
|
100
|
+
if (scores.length === 0) {
|
|
101
|
+
return {
|
|
102
|
+
average: 0,
|
|
103
|
+
median: 0,
|
|
104
|
+
min: 0,
|
|
105
|
+
max: 0,
|
|
106
|
+
distribution: {
|
|
107
|
+
LOW: 0,
|
|
108
|
+
MEDIUM: 0,
|
|
109
|
+
HIGH: 0,
|
|
110
|
+
VERY_HIGH: 0
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
scores.sort((a, b) => a - b);
|
|
116
|
+
|
|
117
|
+
const average = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length);
|
|
118
|
+
const median = scores[Math.floor(scores.length / 2)];
|
|
119
|
+
const min = scores[0];
|
|
120
|
+
const max = scores[scores.length - 1];
|
|
121
|
+
|
|
122
|
+
const distribution = {
|
|
123
|
+
LOW: scores.filter(s => s <= 25).length,
|
|
124
|
+
MEDIUM: scores.filter(s => s > 25 && s <= 50).length,
|
|
125
|
+
HIGH: scores.filter(s => s > 50 && s <= 75).length,
|
|
126
|
+
VERY_HIGH: scores.filter(s => s > 75).length
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
average,
|
|
131
|
+
median,
|
|
132
|
+
min,
|
|
133
|
+
max,
|
|
134
|
+
distribution,
|
|
135
|
+
totalFiles: scores.length
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Generate compliance metrics
|
|
141
|
+
* @param {Array} files - Files to analyze
|
|
142
|
+
* @returns {Object} Compliance metrics
|
|
143
|
+
*/
|
|
144
|
+
generateComplianceMetrics(files) {
|
|
145
|
+
const totalFiles = files.length;
|
|
146
|
+
const compliantFiles = files.filter(f => !f.needsRefactoring).length;
|
|
147
|
+
const nonCompliantFiles = totalFiles - compliantFiles;
|
|
148
|
+
|
|
149
|
+
const complianceRate = totalFiles > 0 ? Math.round((compliantFiles / totalFiles) * 100) : 0;
|
|
150
|
+
|
|
151
|
+
// Compliance by size category
|
|
152
|
+
const complianceBySize = {};
|
|
153
|
+
const sizeCategories = ['SMALL', 'MEDIUM', 'LARGE', 'XLARGE'];
|
|
154
|
+
|
|
155
|
+
for (const category of sizeCategories) {
|
|
156
|
+
const categoryFiles = files.filter(f => f.sizeCategory === category);
|
|
157
|
+
const categoryCompliant = categoryFiles.filter(f => !f.needsRefactoring).length;
|
|
158
|
+
const categoryTotal = categoryFiles.length;
|
|
159
|
+
|
|
160
|
+
complianceBySize[category] = {
|
|
161
|
+
total: categoryTotal,
|
|
162
|
+
compliant: categoryCompliant,
|
|
163
|
+
nonCompliant: categoryTotal - categoryCompliant,
|
|
164
|
+
complianceRate: categoryTotal > 0 ? Math.round((categoryCompliant / categoryTotal) * 100) : 0
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
totalFiles,
|
|
170
|
+
compliantFiles,
|
|
171
|
+
nonCompliantFiles,
|
|
172
|
+
complianceRate,
|
|
173
|
+
complianceBySize,
|
|
174
|
+
status: this.getComplianceStatus(complianceRate)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Generate package metrics
|
|
180
|
+
* @param {Array} files - Files to analyze
|
|
181
|
+
* @returns {Object} Package metrics
|
|
182
|
+
*/
|
|
183
|
+
generatePackageMetrics(files) {
|
|
184
|
+
const packageMap = new Map();
|
|
185
|
+
|
|
186
|
+
// Group files by package
|
|
187
|
+
for (const file of files) {
|
|
188
|
+
const packageName = this.extractPackageName(file.filePath);
|
|
189
|
+
|
|
190
|
+
if (!packageMap.has(packageName)) {
|
|
191
|
+
packageMap.set(packageName, {
|
|
192
|
+
packageName,
|
|
193
|
+
totalFiles: 0,
|
|
194
|
+
totalLines: 0,
|
|
195
|
+
compliantFiles: 0,
|
|
196
|
+
urgentFiles: 0,
|
|
197
|
+
averageComplexity: 0,
|
|
198
|
+
complexityScores: []
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const packageData = packageMap.get(packageName);
|
|
203
|
+
packageData.totalFiles += 1;
|
|
204
|
+
packageData.totalLines += file.lineCount;
|
|
205
|
+
|
|
206
|
+
if (!file.needsRefactoring) {
|
|
207
|
+
packageData.compliantFiles += 1;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (file.urgentRefactoring) {
|
|
211
|
+
packageData.urgentFiles += 1;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (file.getComplexityScore) {
|
|
215
|
+
packageData.complexityScores.push(file.getComplexityScore());
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Calculate package metrics
|
|
220
|
+
const packages = {};
|
|
221
|
+
for (const [packageName, data] of packageMap) {
|
|
222
|
+
data.complianceRate = data.totalFiles > 0 ? Math.round((data.compliantFiles / data.totalFiles) * 100) : 0;
|
|
223
|
+
data.averageComplexity = data.complexityScores.length > 0
|
|
224
|
+
? Math.round(data.complexityScores.reduce((sum, score) => sum + score, 0) / data.complexityScores.length)
|
|
225
|
+
: 0;
|
|
226
|
+
data.status = this.getPackageStatus(data.complianceRate, data.urgentFiles);
|
|
227
|
+
|
|
228
|
+
packages[packageName] = data;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
totalPackages: Object.keys(packages).length,
|
|
233
|
+
packages,
|
|
234
|
+
ranking: this.getPackageRanking(packages)
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Generate violation metrics
|
|
240
|
+
* @param {Array} files - Files to analyze
|
|
241
|
+
* @returns {Object} Violation metrics
|
|
242
|
+
*/
|
|
243
|
+
generateViolationMetrics(files) {
|
|
244
|
+
const allViolations = [];
|
|
245
|
+
const violationTypes = new Map();
|
|
246
|
+
const violationSeverity = new Map();
|
|
247
|
+
|
|
248
|
+
for (const file of files) {
|
|
249
|
+
if (file.violations) {
|
|
250
|
+
for (const violation of file.violations) {
|
|
251
|
+
allViolations.push(violation);
|
|
252
|
+
|
|
253
|
+
// Count by type
|
|
254
|
+
const type = violation.type || 'UNKNOWN';
|
|
255
|
+
violationTypes.set(type, (violationTypes.get(type) || 0) + 1);
|
|
256
|
+
|
|
257
|
+
// Count by severity
|
|
258
|
+
const severity = violation.severity || 'LOW';
|
|
259
|
+
violationSeverity.set(severity, (violationSeverity.get(severity) || 0) + 1);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
totalViolations: allViolations.length,
|
|
266
|
+
filesWithViolations: files.filter(f => f.violations && f.violations.length > 0).length,
|
|
267
|
+
violationTypes: Object.fromEntries(violationTypes),
|
|
268
|
+
violationSeverity: Object.fromEntries(violationSeverity),
|
|
269
|
+
averageViolationsPerFile: files.length > 0 ? Math.round((allViolations.length / files.length) * 10) / 10 : 0
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Generate risk metrics
|
|
275
|
+
* @param {Array} files - Files to analyze
|
|
276
|
+
* @returns {Object} Risk metrics
|
|
277
|
+
*/
|
|
278
|
+
generateRiskMetrics(files) {
|
|
279
|
+
const riskScores = files.map(f => this.calculateFileRiskScore(f));
|
|
280
|
+
|
|
281
|
+
const totalRisk = riskScores.reduce((sum, score) => sum + score, 0);
|
|
282
|
+
const averageRisk = files.length > 0 ? Math.round(totalRisk / files.length) : 0;
|
|
283
|
+
|
|
284
|
+
const riskDistribution = {
|
|
285
|
+
LOW: riskScores.filter(s => s <= 25).length,
|
|
286
|
+
MEDIUM: riskScores.filter(s => s > 25 && s <= 50).length,
|
|
287
|
+
HIGH: riskScores.filter(s => s > 50 && s <= 75).length,
|
|
288
|
+
CRITICAL: riskScores.filter(s => s > 75).length
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const highRiskFiles = files.filter(f => this.calculateFileRiskScore(f) > 50);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
totalRisk,
|
|
295
|
+
averageRisk,
|
|
296
|
+
riskDistribution,
|
|
297
|
+
highRiskFiles: highRiskFiles.length,
|
|
298
|
+
riskLevel: this.getOverallRiskLevel(averageRisk)
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Generate effort estimates
|
|
304
|
+
* @param {Array} files - Files to analyze
|
|
305
|
+
* @returns {Object} Effort estimates
|
|
306
|
+
*/
|
|
307
|
+
generateEffortEstimates(files) {
|
|
308
|
+
const filesNeedingRefactoring = files.filter(f => f.needsRefactoring);
|
|
309
|
+
const totalLines = filesNeedingRefactoring.reduce((sum, f) => sum + f.lineCount, 0);
|
|
310
|
+
|
|
311
|
+
// Estimate effort in person-hours (rough estimate: 1 hour per 50 lines)
|
|
312
|
+
const baseHours = Math.round(totalLines / 50);
|
|
313
|
+
|
|
314
|
+
// Adjust for complexity
|
|
315
|
+
const complexityMultiplier = 1.5; // Complex files take longer
|
|
316
|
+
|
|
317
|
+
// Adjust for dependencies
|
|
318
|
+
const dependencyMultiplier = 1.2; // Files with many dependencies take longer
|
|
319
|
+
|
|
320
|
+
const adjustedHours = Math.round(baseHours * complexityMultiplier * dependencyMultiplier);
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
totalFiles: filesNeedingRefactoring.length,
|
|
324
|
+
totalLines,
|
|
325
|
+
estimatedHours: adjustedHours,
|
|
326
|
+
estimatedDays: Math.round(adjustedHours / 8), // Assuming 8-hour work days
|
|
327
|
+
effortLevel: this.getEffortLevel(adjustedHours),
|
|
328
|
+
breakdown: this.getEffortBreakdown(filesNeedingRefactoring)
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Extract package name from file path
|
|
334
|
+
* @param {string} filePath - File path
|
|
335
|
+
* @returns {string} Package name
|
|
336
|
+
*/
|
|
337
|
+
extractPackageName(filePath) {
|
|
338
|
+
const parts = filePath.split('/');
|
|
339
|
+
const packagesIndex = parts.findIndex(part => part === 'packages');
|
|
340
|
+
|
|
341
|
+
if (packagesIndex !== -1 && parts.length > packagesIndex + 1) {
|
|
342
|
+
return parts[packagesIndex + 1];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return 'unknown';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Get overall status
|
|
350
|
+
* @param {number} complianceRate - Compliance rate
|
|
351
|
+
* @param {number} urgentFiles - Number of urgent files
|
|
352
|
+
* @returns {string} Overall status
|
|
353
|
+
*/
|
|
354
|
+
getOverallStatus(complianceRate, urgentFiles) {
|
|
355
|
+
if (complianceRate === 100 && urgentFiles === 0) {
|
|
356
|
+
return 'COMPLIANT';
|
|
357
|
+
} else if (urgentFiles > 0) {
|
|
358
|
+
return 'URGENT_ATTENTION';
|
|
359
|
+
} else if (complianceRate >= 90) {
|
|
360
|
+
return 'MOSTLY_COMPLIANT';
|
|
361
|
+
} else if (complianceRate >= 70) {
|
|
362
|
+
return 'PARTIALLY_COMPLIANT';
|
|
363
|
+
} else {
|
|
364
|
+
return 'NON_COMPLIANT';
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get compliance status
|
|
370
|
+
* @param {number} complianceRate - Compliance rate
|
|
371
|
+
* @returns {string} Compliance status
|
|
372
|
+
*/
|
|
373
|
+
getComplianceStatus(complianceRate) {
|
|
374
|
+
if (complianceRate === 100) return 'COMPLIANT';
|
|
375
|
+
if (complianceRate >= 90) return 'MOSTLY_COMPLIANT';
|
|
376
|
+
if (complianceRate >= 70) return 'PARTIALLY_COMPLIANT';
|
|
377
|
+
return 'NON_COMPLIANT';
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get package status
|
|
382
|
+
* @param {number} complianceRate - Compliance rate
|
|
383
|
+
* @param {number} urgentFiles - Number of urgent files
|
|
384
|
+
* @returns {string} Package status
|
|
385
|
+
*/
|
|
386
|
+
getPackageStatus(complianceRate, urgentFiles) {
|
|
387
|
+
if (complianceRate === 100 && urgentFiles === 0) {
|
|
388
|
+
return 'COMPLIANT';
|
|
389
|
+
} else if (urgentFiles > 0) {
|
|
390
|
+
return 'URGENT_ATTENTION';
|
|
391
|
+
} else if (complianceRate >= 90) {
|
|
392
|
+
return 'MOSTLY_COMPLIANT';
|
|
393
|
+
} else if (complianceRate >= 70) {
|
|
394
|
+
return 'PARTIALLY_COMPLIANT';
|
|
395
|
+
} else {
|
|
396
|
+
return 'NON_COMPLIANT';
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Get package ranking by priority
|
|
402
|
+
* @param {Object} packages - Package metrics
|
|
403
|
+
* @returns {Array} Sorted packages
|
|
404
|
+
*/
|
|
405
|
+
getPackageRanking(packages) {
|
|
406
|
+
return Object.entries(packages)
|
|
407
|
+
.map(([name, data]) => ({
|
|
408
|
+
name,
|
|
409
|
+
...data,
|
|
410
|
+
priority: this.calculatePackagePriority(data)
|
|
411
|
+
}))
|
|
412
|
+
.sort((a, b) => b.priority - a.priority);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Calculate package priority
|
|
417
|
+
* @param {Object} packageData - Package data
|
|
418
|
+
* @returns {number} Priority score
|
|
419
|
+
*/
|
|
420
|
+
calculatePackagePriority(packageData) {
|
|
421
|
+
let priority = 0;
|
|
422
|
+
|
|
423
|
+
// Priority from urgent files
|
|
424
|
+
priority += packageData.urgentFiles * 50;
|
|
425
|
+
|
|
426
|
+
// Priority from non-compliance
|
|
427
|
+
priority += (100 - packageData.complianceRate) * 2;
|
|
428
|
+
|
|
429
|
+
// Priority from complexity
|
|
430
|
+
priority += packageData.averageComplexity * 0.5;
|
|
431
|
+
|
|
432
|
+
// Priority from size
|
|
433
|
+
priority += Math.log(packageData.totalLines + 1) * 0.1;
|
|
434
|
+
|
|
435
|
+
return Math.round(priority);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Calculate file risk score
|
|
440
|
+
* @param {Object} file - File analysis
|
|
441
|
+
* @returns {number} Risk score (0-100)
|
|
442
|
+
*/
|
|
443
|
+
calculateFileRiskScore(file) {
|
|
444
|
+
let riskScore = 0;
|
|
445
|
+
|
|
446
|
+
// Risk from size
|
|
447
|
+
if (file.sizeCategory === 'XLARGE') riskScore += 40;
|
|
448
|
+
else if (file.sizeCategory === 'LARGE') riskScore += 20;
|
|
449
|
+
|
|
450
|
+
// Risk from urgency
|
|
451
|
+
if (file.urgentRefactoring) riskScore += 30;
|
|
452
|
+
|
|
453
|
+
// Risk from complexity
|
|
454
|
+
const complexity = file.getComplexityScore ? file.getComplexityScore() : 0;
|
|
455
|
+
riskScore += Math.min(complexity * 0.5, 30);
|
|
456
|
+
|
|
457
|
+
// Risk from violations
|
|
458
|
+
if (file.violations) {
|
|
459
|
+
riskScore += Math.min(file.violations.length * 5, 25);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return Math.min(100, Math.round(riskScore));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Get overall risk level
|
|
467
|
+
* @param {number} averageRisk - Average risk score
|
|
468
|
+
* @returns {string} Risk level
|
|
469
|
+
*/
|
|
470
|
+
getOverallRiskLevel(averageRisk) {
|
|
471
|
+
if (averageRisk <= 25) return 'LOW';
|
|
472
|
+
if (averageRisk <= 50) return 'MEDIUM';
|
|
473
|
+
if (averageRisk <= 75) return 'HIGH';
|
|
474
|
+
return 'CRITICAL';
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Get effort level
|
|
479
|
+
* @param {number} hours - Estimated hours
|
|
480
|
+
* @returns {string} Effort level
|
|
481
|
+
*/
|
|
482
|
+
getEffortLevel(hours) {
|
|
483
|
+
if (hours <= 8) return 'LOW';
|
|
484
|
+
if (hours <= 40) return 'MEDIUM';
|
|
485
|
+
if (hours <= 160) return 'HIGH';
|
|
486
|
+
return 'VERY_HIGH';
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Get effort breakdown
|
|
491
|
+
* @param {Array} files - Files needing refactoring
|
|
492
|
+
* @returns {Object} Effort breakdown
|
|
493
|
+
*/
|
|
494
|
+
getEffortBreakdown(files) {
|
|
495
|
+
const breakdown = {
|
|
496
|
+
SMALL: { files: 0, lines: 0, hours: 0 },
|
|
497
|
+
MEDIUM: { files: 0, lines: 0, hours: 0 },
|
|
498
|
+
LARGE: { files: 0, lines: 0, hours: 0 },
|
|
499
|
+
XLARGE: { files: 0, lines: 0, hours: 0 }
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
for (const file of files) {
|
|
503
|
+
const category = file.sizeCategory || 'UNKNOWN';
|
|
504
|
+
if (breakdown[category]) {
|
|
505
|
+
breakdown[category].files += 1;
|
|
506
|
+
breakdown[category].lines += file.lineCount;
|
|
507
|
+
breakdown[category].hours += Math.round(file.lineCount / 50);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return breakdown;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
module.exports = StatisticsGenerator;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analysis Report Model
|
|
3
|
+
*
|
|
4
|
+
* Data model for analysis reports with metadata, summary, and file analysis.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const RefactoringConfig = require('../../config/refactoring-config');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Analysis report class
|
|
11
|
+
*/
|
|
12
|
+
class AnalysisReport {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.metadata = {
|
|
15
|
+
generatedAt: new Date().toISOString(),
|
|
16
|
+
version: '1.0.0',
|
|
17
|
+
analysisScope: 'full_codebase',
|
|
18
|
+
config: RefactoringConfig.limits
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
this.summary = {
|
|
22
|
+
totalFiles: 0,
|
|
23
|
+
totalLines: 0,
|
|
24
|
+
filesNeedingRefactoring: 0,
|
|
25
|
+
urgentRefactoring: 0,
|
|
26
|
+
complianceRate: 0,
|
|
27
|
+
averageComplexity: 0
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
this.fileAnalysis = [];
|
|
31
|
+
this.packageAnalysis = {};
|
|
32
|
+
this.recommendations = [];
|
|
33
|
+
this.strategies = [];
|
|
34
|
+
this.statistics = {};
|
|
35
|
+
this.violations = [];
|
|
36
|
+
this.trends = {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
addFileAnalysis(analysis) {
|
|
40
|
+
this.fileAnalysis.push(analysis);
|
|
41
|
+
this.updateSummary();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateSummary() {
|
|
45
|
+
this.summary.totalFiles = this.fileAnalysis.length;
|
|
46
|
+
this.summary.totalLines = this.fileAnalysis.reduce((sum, f) => sum + f.lineCount, 0);
|
|
47
|
+
this.summary.filesNeedingRefactoring = this.fileAnalysis.filter(f => f.needsRefactoring).length;
|
|
48
|
+
this.summary.urgentRefactoring = this.fileAnalysis.filter(f => f.priority === 'urgent').length;
|
|
49
|
+
this.summary.complianceRate = this.summary.totalFiles > 0 ?
|
|
50
|
+
((this.summary.totalFiles - this.summary.filesNeedingRefactoring) / this.summary.totalFiles * 100).toFixed(2) : 100;
|
|
51
|
+
this.summary.averageComplexity = this.calculateAverageComplexity();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
calculateAverageComplexity() {
|
|
55
|
+
if (this.fileAnalysis.length === 0) return 0;
|
|
56
|
+
const totalComplexity = this.fileAnalysis.reduce((sum, f) => {
|
|
57
|
+
return sum + (f.getComplexityScore ? f.getComplexityScore() : 0);
|
|
58
|
+
}, 0);
|
|
59
|
+
return (totalComplexity / this.fileAnalysis.length).toFixed(2);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
addPackageAnalysis(packageName, analysis) {
|
|
63
|
+
this.packageAnalysis[packageName] = analysis;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
addRecommendation(recommendation) {
|
|
67
|
+
this.recommendations.push(recommendation);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
addStrategy(strategy) {
|
|
71
|
+
this.strategies.push(strategy);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
addViolation(violation) {
|
|
75
|
+
this.violations.push(violation);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setStatistics(stats) {
|
|
79
|
+
this.statistics = stats;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setTrends(trends) {
|
|
83
|
+
this.trends = trends;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
toJSON() {
|
|
87
|
+
return {
|
|
88
|
+
metadata: this.metadata,
|
|
89
|
+
summary: this.summary,
|
|
90
|
+
fileAnalysis: this.fileAnalysis,
|
|
91
|
+
packageAnalysis: this.packageAnalysis,
|
|
92
|
+
recommendations: this.recommendations,
|
|
93
|
+
strategies: this.strategies,
|
|
94
|
+
statistics: this.statistics,
|
|
95
|
+
violations: this.violations,
|
|
96
|
+
trends: this.trends
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = AnalysisReport;
|