vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739
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,679 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates refactoring priorities based on multiple factors.
|
|
5
|
+
* Provides consistent, data-driven priority assessment.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const RefactoringConfig = require('../config/refactoring-config');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Priority levels
|
|
12
|
+
*/
|
|
13
|
+
const PRIORITY_LEVELS = {
|
|
14
|
+
CRITICAL: 'critical',
|
|
15
|
+
HIGH: 'high',
|
|
16
|
+
MEDIUM: 'medium',
|
|
17
|
+
LOW: 'low',
|
|
18
|
+
NONE: 'none'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Priority factors
|
|
23
|
+
*/
|
|
24
|
+
const PRIORITY_FACTORS = {
|
|
25
|
+
SIZE_VIOLATION: 'size_violation',
|
|
26
|
+
COMPLEXITY: 'complexity',
|
|
27
|
+
DEPENDENCY_COUNT: 'dependency_count',
|
|
28
|
+
CHANGE_FREQUENCY: 'change_frequency',
|
|
29
|
+
PACKAGE_IMPORTANCE: 'package_importance',
|
|
30
|
+
TEST_COVERAGE: 'test_coverage',
|
|
31
|
+
BUSINESS_IMPACT: 'business_impact'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Priority calculation result class
|
|
36
|
+
*/
|
|
37
|
+
class PriorityResult {
|
|
38
|
+
constructor(filePath) {
|
|
39
|
+
this.filePath = filePath;
|
|
40
|
+
this.priority = PRIORITY_LEVELS.NONE;
|
|
41
|
+
this.score = 0;
|
|
42
|
+
this.factors = {};
|
|
43
|
+
this.reasons = [];
|
|
44
|
+
this.recommendations = [];
|
|
45
|
+
this.metadata = {
|
|
46
|
+
calculatedAt: new Date().toISOString(),
|
|
47
|
+
version: '1.0.0'
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
addFactor(factorName, score, weight, details = {}) {
|
|
52
|
+
this.factors[factorName] = {
|
|
53
|
+
score,
|
|
54
|
+
weight,
|
|
55
|
+
weightedScore: score * weight,
|
|
56
|
+
details
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addReason(reason) {
|
|
61
|
+
this.reasons.push(reason);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
addRecommendation(recommendation) {
|
|
65
|
+
this.recommendations.push(recommendation);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
setPriority(priority, score) {
|
|
69
|
+
this.priority = priority;
|
|
70
|
+
this.score = score;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getFactorScore(factorName) {
|
|
74
|
+
return this.factors[factorName]?.weightedScore || 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getTotalWeightedScore() {
|
|
78
|
+
return Object.values(this.factors)
|
|
79
|
+
.reduce((sum, factor) => sum + factor.weightedScore, 0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Priority calculator class
|
|
85
|
+
*/
|
|
86
|
+
class PriorityCalculator {
|
|
87
|
+
constructor(config = RefactoringConfig) {
|
|
88
|
+
this.config = config;
|
|
89
|
+
this.weights = this.getDefaultWeights();
|
|
90
|
+
this.thresholds = this.getDefaultThresholds();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get default factor weights
|
|
95
|
+
*/
|
|
96
|
+
getDefaultWeights() {
|
|
97
|
+
return {
|
|
98
|
+
[PRIORITY_FACTORS.SIZE_VIOLATION]: 0.4,
|
|
99
|
+
[PRIORITY_FACTORS.COMPLEXITY]: 0.25,
|
|
100
|
+
[PRIORITY_FACTORS.DEPENDENCY_COUNT]: 0.15,
|
|
101
|
+
[PRIORITY_FACTORS.PACKAGE_IMPORTANCE]: 0.1,
|
|
102
|
+
[PRIORITY_FACTORS.CHANGE_FREQUENCY]: 0.05,
|
|
103
|
+
[PRIORITY_FACTORS.TEST_COVERAGE]: 0.03,
|
|
104
|
+
[PRIORITY_FACTORS.BUSINESS_IMPACT]: 0.02
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get default priority thresholds
|
|
110
|
+
*/
|
|
111
|
+
getDefaultThresholds() {
|
|
112
|
+
return {
|
|
113
|
+
[PRIORITY_LEVELS.CRITICAL]: 0.8,
|
|
114
|
+
[PRIORITY_LEVELS.HIGH]: 0.6,
|
|
115
|
+
[PRIORITY_LEVELS.MEDIUM]: 0.4,
|
|
116
|
+
[PRIORITY_LEVELS.LOW]: 0.2,
|
|
117
|
+
[PRIORITY_LEVELS.NONE]: 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Calculate priority for a file analysis
|
|
123
|
+
*/
|
|
124
|
+
calculatePriority(fileAnalysis) {
|
|
125
|
+
const result = new PriorityResult(fileAnalysis.filePath);
|
|
126
|
+
|
|
127
|
+
// Calculate each factor
|
|
128
|
+
this.calculateSizeViolationFactor(fileAnalysis, result);
|
|
129
|
+
this.calculateComplexityFactor(fileAnalysis, result);
|
|
130
|
+
this.calculateDependencyFactor(fileAnalysis, result);
|
|
131
|
+
this.calculatePackageImportanceFactor(fileAnalysis, result);
|
|
132
|
+
this.calculateChangeFrequencyFactor(fileAnalysis, result);
|
|
133
|
+
this.calculateTestCoverageFactor(fileAnalysis, result);
|
|
134
|
+
this.calculateBusinessImpactFactor(fileAnalysis, result);
|
|
135
|
+
|
|
136
|
+
// Calculate total weighted score
|
|
137
|
+
const totalScore = result.getTotalWeightedScore();
|
|
138
|
+
|
|
139
|
+
// Determine priority based on thresholds
|
|
140
|
+
const priority = this.determinePriority(totalScore);
|
|
141
|
+
|
|
142
|
+
result.setPriority(priority, totalScore);
|
|
143
|
+
this.generateReasonsAndRecommendations(fileAnalysis, result);
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Calculate size violation factor
|
|
150
|
+
*/
|
|
151
|
+
calculateSizeViolationFactor(fileAnalysis, result) {
|
|
152
|
+
const limits = this.config.limits;
|
|
153
|
+
let score = 0;
|
|
154
|
+
let details = {};
|
|
155
|
+
|
|
156
|
+
if (fileAnalysis.lineCount > limits.criticalThreshold) {
|
|
157
|
+
score = 1.0;
|
|
158
|
+
details.violation = 'critical';
|
|
159
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
160
|
+
details.severity = 'critical';
|
|
161
|
+
} else if (fileAnalysis.lineCount > limits.maxFileSize) {
|
|
162
|
+
score = 0.8;
|
|
163
|
+
details.violation = 'major';
|
|
164
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
165
|
+
details.severity = 'major';
|
|
166
|
+
} else if (fileAnalysis.lineCount > limits.warningThreshold) {
|
|
167
|
+
score = 0.6;
|
|
168
|
+
details.violation = 'minor';
|
|
169
|
+
details.excessLines = fileAnalysis.lineCount - limits.warningThreshold;
|
|
170
|
+
details.severity = 'minor';
|
|
171
|
+
} else if (fileAnalysis.lineCount > limits.mediumFileMax) {
|
|
172
|
+
score = 0.3;
|
|
173
|
+
details.violation = 'approaching';
|
|
174
|
+
details.excessLines = 0;
|
|
175
|
+
details.severity = 'low';
|
|
176
|
+
} else {
|
|
177
|
+
score = 0.0;
|
|
178
|
+
details.violation = 'none';
|
|
179
|
+
details.excessLines = 0;
|
|
180
|
+
details.severity = 'none';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
details.lineCount = fileAnalysis.lineCount;
|
|
184
|
+
details.limit = limits.maxFileSize;
|
|
185
|
+
details.warningThreshold = limits.warningThreshold;
|
|
186
|
+
|
|
187
|
+
result.addFactor(PRIORITY_FACTORS.SIZE_VIOLATION, score, this.weights[PRIORITY_FACTORS.SIZE_VIOLATION], details);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Calculate complexity factor
|
|
192
|
+
*/
|
|
193
|
+
calculateComplexityFactor(fileAnalysis, result) {
|
|
194
|
+
let score = 0;
|
|
195
|
+
let details = {};
|
|
196
|
+
|
|
197
|
+
// Use complexity score if available, otherwise calculate
|
|
198
|
+
const complexityScore = fileAnalysis.getComplexityScore ?
|
|
199
|
+
fileAnalysis.getComplexityScore() :
|
|
200
|
+
this.calculateComplexityScore(fileAnalysis);
|
|
201
|
+
|
|
202
|
+
if (complexityScore >= 80) {
|
|
203
|
+
score = 1.0;
|
|
204
|
+
details.level = 'very_high';
|
|
205
|
+
} else if (complexityScore >= 60) {
|
|
206
|
+
score = 0.8;
|
|
207
|
+
details.level = 'high';
|
|
208
|
+
} else if (complexityScore >= 40) {
|
|
209
|
+
score = 0.6;
|
|
210
|
+
details.level = 'medium';
|
|
211
|
+
} else if (complexityScore >= 20) {
|
|
212
|
+
score = 0.3;
|
|
213
|
+
details.level = 'low';
|
|
214
|
+
} else {
|
|
215
|
+
score = 0.0;
|
|
216
|
+
details.level = 'very_low';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
details.complexityScore = complexityScore;
|
|
220
|
+
details.cyclomaticComplexity = fileAnalysis.cyclomaticComplexity || 0;
|
|
221
|
+
details.nestingDepth = fileAnalysis.nestingDepth || 0;
|
|
222
|
+
details.functionCount = fileAnalysis.functionCount || 0;
|
|
223
|
+
details.classCount = fileAnalysis.classCount || 0;
|
|
224
|
+
|
|
225
|
+
result.addFactor(PRIORITY_FACTORS.COMPLEXITY, score, this.weights[PRIORITY_FACTORS.COMPLEXITY], details);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Calculate dependency factor
|
|
230
|
+
*/
|
|
231
|
+
calculateDependencyFactor(fileAnalysis, result) {
|
|
232
|
+
let score = 0;
|
|
233
|
+
let details = {};
|
|
234
|
+
|
|
235
|
+
const dependencyCount = fileAnalysis.dependencyCount || fileAnalysis.imports?.length || 0;
|
|
236
|
+
const dependentCount = fileAnalysis.dependents?.length || 0;
|
|
237
|
+
|
|
238
|
+
// Score based on total dependencies (incoming + outgoing)
|
|
239
|
+
const totalDependencies = dependencyCount + dependentCount;
|
|
240
|
+
|
|
241
|
+
if (totalDependencies > 20) {
|
|
242
|
+
score = 1.0;
|
|
243
|
+
details.level = 'very_high';
|
|
244
|
+
} else if (totalDependencies > 15) {
|
|
245
|
+
score = 0.8;
|
|
246
|
+
details.level = 'high';
|
|
247
|
+
} else if (totalDependencies > 10) {
|
|
248
|
+
score = 0.6;
|
|
249
|
+
details.level = 'medium';
|
|
250
|
+
} else if (totalDependencies > 5) {
|
|
251
|
+
score = 0.3;
|
|
252
|
+
details.level = 'low';
|
|
253
|
+
} else {
|
|
254
|
+
score = 0.0;
|
|
255
|
+
details.level = 'very_low';
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
details.dependencyCount = dependencyCount;
|
|
259
|
+
details.dependentCount = dependentCount;
|
|
260
|
+
details.totalDependencies = totalDependencies;
|
|
261
|
+
details.couplingRisk = this.assessCouplingRisk(totalDependencies);
|
|
262
|
+
|
|
263
|
+
result.addFactor(PRIORITY_FACTORS.DEPENDENCY_COUNT, score, this.weights[PRIORITY_FACTORS.DEPENDENCY_COUNT], details);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Calculate package importance factor
|
|
268
|
+
*/
|
|
269
|
+
calculatePackageImportanceFactor(fileAnalysis, result) {
|
|
270
|
+
let score = 0;
|
|
271
|
+
let details = {};
|
|
272
|
+
|
|
273
|
+
const packageName = fileAnalysis.package || 'root';
|
|
274
|
+
|
|
275
|
+
// Package importance scoring
|
|
276
|
+
const packageImportance = {
|
|
277
|
+
'core': 1.0,
|
|
278
|
+
'cli': 0.8,
|
|
279
|
+
'electron-app': 0.7,
|
|
280
|
+
'web': 0.6,
|
|
281
|
+
'api-server': 0.6,
|
|
282
|
+
'chrome-extension': 0.5,
|
|
283
|
+
'mobile': 0.5,
|
|
284
|
+
'vscode-extension': 0.4,
|
|
285
|
+
'admin': 0.3,
|
|
286
|
+
'root': 0.2
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
score = packageImportance[packageName] || 0.2;
|
|
290
|
+
|
|
291
|
+
details.packageName = packageName;
|
|
292
|
+
details.importance = score >= 0.8 ? 'critical' :
|
|
293
|
+
score >= 0.6 ? 'high' :
|
|
294
|
+
score >= 0.4 ? 'medium' : 'low';
|
|
295
|
+
details.isCorePackage = packageName === 'core';
|
|
296
|
+
|
|
297
|
+
result.addFactor(PRIORITY_FACTORS.PACKAGE_IMPORTANCE, score, this.weights[PRIORITY_FACTORS.PACKAGE_IMPORTANCE], details);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Calculate change frequency factor
|
|
302
|
+
*/
|
|
303
|
+
calculateChangeFrequencyFactor(fileAnalysis, result) {
|
|
304
|
+
let score = 0;
|
|
305
|
+
let details = {};
|
|
306
|
+
|
|
307
|
+
// For now, use a simple heuristic based on file type and location
|
|
308
|
+
// In a real implementation, this would use git history or other metrics
|
|
309
|
+
const filePath = fileAnalysis.filePath;
|
|
310
|
+
|
|
311
|
+
// Files that tend to change frequently
|
|
312
|
+
const highFrequencyPatterns = [
|
|
313
|
+
/config\//,
|
|
314
|
+
/\/bin\//,
|
|
315
|
+
/\/src\/main\//,
|
|
316
|
+
/package\.json$/,
|
|
317
|
+
/README\.md$/,
|
|
318
|
+
/\.config\./
|
|
319
|
+
];
|
|
320
|
+
|
|
321
|
+
const mediumFrequencyPatterns = [
|
|
322
|
+
/\/src\/utils\//,
|
|
323
|
+
/\/src\/helpers\//,
|
|
324
|
+
/\/src\/services\//
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
if (highFrequencyPatterns.some(pattern => pattern.test(filePath))) {
|
|
328
|
+
score = 0.8;
|
|
329
|
+
details.frequency = 'high';
|
|
330
|
+
} else if (mediumFrequencyPatterns.some(pattern => pattern.test(filePath))) {
|
|
331
|
+
score = 0.5;
|
|
332
|
+
details.frequency = 'medium';
|
|
333
|
+
} else {
|
|
334
|
+
score = 0.2;
|
|
335
|
+
details.frequency = 'low';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
details.filePath = filePath;
|
|
339
|
+
details.lastModified = fileAnalysis.lastModified;
|
|
340
|
+
|
|
341
|
+
// If we have last modified, use it to adjust score
|
|
342
|
+
if (fileAnalysis.lastModified) {
|
|
343
|
+
const daysSinceModified = (Date.now() - new Date(fileAnalysis.lastModified)) / (1000 * 60 * 60 * 24);
|
|
344
|
+
if (daysSinceModified < 7) {
|
|
345
|
+
score = Math.min(1.0, score + 0.2);
|
|
346
|
+
details.recentlyModified = true;
|
|
347
|
+
} else if (daysSinceModified < 30) {
|
|
348
|
+
score = Math.min(1.0, score + 0.1);
|
|
349
|
+
details.recentlyModified = false;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
result.addFactor(PRIORITY_FACTORS.CHANGE_FREQUENCY, score, this.weights[PRIORITY_FACTORS.CHANGE_FREQUENCY], details);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Calculate test coverage factor
|
|
358
|
+
*/
|
|
359
|
+
calculateTestCoverageFactor(fileAnalysis, result) {
|
|
360
|
+
let score = 0;
|
|
361
|
+
let details = {};
|
|
362
|
+
|
|
363
|
+
// Simple heuristic based on file type and naming
|
|
364
|
+
const filePath = fileAnalysis.filePath;
|
|
365
|
+
const isTestFile = fileAnalysis.isTestFile || /test|spec/.test(filePath);
|
|
366
|
+
|
|
367
|
+
if (isTestFile) {
|
|
368
|
+
score = 0.0; // Test files themselves don't need refactoring priority
|
|
369
|
+
details.coverage = 'test_file';
|
|
370
|
+
} else {
|
|
371
|
+
// Look for corresponding test files
|
|
372
|
+
const hasTestFile = this.hasCorrespondingTestFile(filePath);
|
|
373
|
+
|
|
374
|
+
if (hasTestFile) {
|
|
375
|
+
score = 0.2; // Lower priority if well tested
|
|
376
|
+
details.coverage = 'good';
|
|
377
|
+
details.testFile = this.findTestFile(filePath);
|
|
378
|
+
} else {
|
|
379
|
+
score = 0.6; // Higher priority if no tests
|
|
380
|
+
details.coverage = 'poor';
|
|
381
|
+
details.testFile = null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
details.filePath = filePath;
|
|
386
|
+
details.isTestFile = isTestFile;
|
|
387
|
+
details.impact = score > 0.4 ? 'high_risk' : 'low_risk';
|
|
388
|
+
|
|
389
|
+
result.addFactor(PRIORITY_FACTORS.TEST_COVERAGE, score, this.weights[PRIORITY_FACTORS.TEST_COVERAGE], details);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Calculate business impact factor
|
|
394
|
+
*/
|
|
395
|
+
calculateBusinessImpactFactor(fileAnalysis, result) {
|
|
396
|
+
let score = 0;
|
|
397
|
+
let details = {};
|
|
398
|
+
|
|
399
|
+
const filePath = fileAnalysis.filePath;
|
|
400
|
+
|
|
401
|
+
// Business critical file patterns
|
|
402
|
+
const criticalPatterns = [
|
|
403
|
+
/\/bin\//,
|
|
404
|
+
/\/src\/main\//,
|
|
405
|
+
/\/src\/app\//,
|
|
406
|
+
/\/src\/index\./,
|
|
407
|
+
/\/server\./,
|
|
408
|
+
/\/app\./
|
|
409
|
+
];
|
|
410
|
+
|
|
411
|
+
// Important but not critical patterns
|
|
412
|
+
const importantPatterns = [
|
|
413
|
+
/\/src\/api\//,
|
|
414
|
+
/\/src\/controllers\//,
|
|
415
|
+
/\/src\/services\//,
|
|
416
|
+
/\/src\/models\//
|
|
417
|
+
];
|
|
418
|
+
|
|
419
|
+
if (criticalPatterns.some(pattern => pattern.test(filePath))) {
|
|
420
|
+
score = 0.8;
|
|
421
|
+
details.impact = 'critical';
|
|
422
|
+
} else if (importantPatterns.some(pattern => pattern.test(filePath))) {
|
|
423
|
+
score = 0.5;
|
|
424
|
+
details.impact = 'important';
|
|
425
|
+
} else {
|
|
426
|
+
score = 0.2;
|
|
427
|
+
details.impact = 'standard';
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
details.filePath = filePath;
|
|
431
|
+
details.isBusinessCritical = score >= 0.8;
|
|
432
|
+
|
|
433
|
+
result.addFactor(PRIORITY_FACTORS.BUSINESS_IMPACT, score, this.weights[PRIORITY_FACTORS.BUSINESS_IMPACT], details);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Determine priority from score
|
|
438
|
+
*/
|
|
439
|
+
determinePriority(score) {
|
|
440
|
+
if (score >= this.thresholds[PRIORITY_LEVELS.CRITICAL]) {
|
|
441
|
+
return PRIORITY_LEVELS.CRITICAL;
|
|
442
|
+
} else if (score >= this.thresholds[PRIORITY_LEVELS.HIGH]) {
|
|
443
|
+
return PRIORITY_LEVELS.HIGH;
|
|
444
|
+
} else if (score >= this.thresholds[PRIORITY_LEVELS.MEDIUM]) {
|
|
445
|
+
return PRIORITY_LEVELS.MEDIUM;
|
|
446
|
+
} else if (score >= this.thresholds[PRIORITY_LEVELS.LOW]) {
|
|
447
|
+
return PRIORITY_LEVELS.LOW;
|
|
448
|
+
}
|
|
449
|
+
return PRIORITY_LEVELS.NONE;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Generate reasons and recommendations
|
|
454
|
+
*/
|
|
455
|
+
generateReasonsAndRecommendations(fileAnalysis, result) {
|
|
456
|
+
const reasons = [];
|
|
457
|
+
const recommendations = [];
|
|
458
|
+
|
|
459
|
+
// Size-related reasons
|
|
460
|
+
const sizeFactor = result.factors[PRIORITY_FACTORS.SIZE_VIOLATION];
|
|
461
|
+
if (sizeFactor && sizeFactor.score > 0.6) {
|
|
462
|
+
reasons.push(`File has ${sizeFactor.details.excessLines} excess lines beyond limit`);
|
|
463
|
+
recommendations.push('Consider splitting large functions or extracting modules');
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Complexity-related reasons
|
|
467
|
+
const complexityFactor = result.factors[PRIORITY_FACTORS.COMPLEXITY];
|
|
468
|
+
if (complexityFactor && complexityFactor.score > 0.6) {
|
|
469
|
+
reasons.push(`File has ${complexityFactor.details.level} complexity`);
|
|
470
|
+
recommendations.push('Reduce complexity through better organization and smaller functions');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Dependency-related reasons
|
|
474
|
+
const dependencyFactor = result.factors[PRIORITY_FACTORS.DEPENDENCY_COUNT];
|
|
475
|
+
if (dependencyFactor && dependencyFactor.score > 0.6) {
|
|
476
|
+
reasons.push(`File has ${dependencyFactor.details.totalDependencies} total dependencies`);
|
|
477
|
+
recommendations.push('Consider reducing dependencies through better separation of concerns');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Package importance reasons
|
|
481
|
+
const packageFactor = result.factors[PRIORITY_FACTORS.PACKAGE_IMPORTANCE];
|
|
482
|
+
if (packageFactor && packageFactor.score > 0.8) {
|
|
483
|
+
reasons.push(`File is in ${packageFactor.details.importance} package (${packageFactor.details.packageName})`);
|
|
484
|
+
recommendations.push('Ensure high code quality for critical package files');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Test coverage reasons
|
|
488
|
+
const testFactor = result.factors[PRIORITY_FACTORS.TEST_COVERAGE];
|
|
489
|
+
if (testFactor && testFactor.score > 0.4) {
|
|
490
|
+
reasons.push('File has poor or no test coverage');
|
|
491
|
+
recommendations.push('Add test coverage before refactoring to ensure safety');
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Business impact reasons
|
|
495
|
+
const businessFactor = result.factors[PRIORITY_FACTORS.BUSINESS_IMPACT];
|
|
496
|
+
if (businessFactor && businessFactor.score > 0.6) {
|
|
497
|
+
reasons.push(`File has ${businessFactor.details.impact} business impact`);
|
|
498
|
+
recommendations.push('Exercise extra caution when refactoring business-critical code');
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
result.reasons = reasons;
|
|
502
|
+
result.recommendations = recommendations;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Calculate complexity score for a file
|
|
507
|
+
*/
|
|
508
|
+
calculateComplexityScore(fileAnalysis) {
|
|
509
|
+
let score = 0;
|
|
510
|
+
|
|
511
|
+
// Line count contribution
|
|
512
|
+
if (fileAnalysis.lineCount > 1000) score += 30;
|
|
513
|
+
else if (fileAnalysis.lineCount > 555) score += 25;
|
|
514
|
+
else if (fileAnalysis.lineCount > 300) score += 15;
|
|
515
|
+
else if (fileAnalysis.lineCount > 100) score += 5;
|
|
516
|
+
|
|
517
|
+
// Function count contribution
|
|
518
|
+
const functionCount = fileAnalysis.functionCount || 0;
|
|
519
|
+
if (functionCount > 20) score += 20;
|
|
520
|
+
else if (functionCount > 10) score += 15;
|
|
521
|
+
else if (functionCount > 5) score += 10;
|
|
522
|
+
else if (functionCount > 2) score += 5;
|
|
523
|
+
|
|
524
|
+
// Class count contribution
|
|
525
|
+
const classCount = fileAnalysis.classCount || 0;
|
|
526
|
+
if (classCount > 5) score += 15;
|
|
527
|
+
else if (classCount > 3) score += 10;
|
|
528
|
+
else if (classCount > 1) score += 5;
|
|
529
|
+
|
|
530
|
+
// Nesting depth contribution
|
|
531
|
+
const nestingDepth = fileAnalysis.nestingDepth || 0;
|
|
532
|
+
if (nestingDepth > 8) score += 15;
|
|
533
|
+
else if (nestingDepth > 5) score += 10;
|
|
534
|
+
else if (nestingDepth > 3) score += 5;
|
|
535
|
+
|
|
536
|
+
// Dependency count contribution
|
|
537
|
+
const dependencyCount = fileAnalysis.dependencyCount || 0;
|
|
538
|
+
if (dependencyCount > 20) score += 20;
|
|
539
|
+
else if (dependencyCount > 10) score += 15;
|
|
540
|
+
else if (dependencyCount > 5) score += 10;
|
|
541
|
+
else if (dependencyCount > 2) score += 5;
|
|
542
|
+
|
|
543
|
+
return Math.min(score, 100);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Assess coupling risk
|
|
548
|
+
*/
|
|
549
|
+
assessCouplingRisk(dependencyCount) {
|
|
550
|
+
if (dependencyCount > 20) return 'very_high';
|
|
551
|
+
if (dependencyCount > 15) return 'high';
|
|
552
|
+
if (dependencyCount > 10) return 'medium';
|
|
553
|
+
if (dependencyCount > 5) return 'low';
|
|
554
|
+
return 'very_low';
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Check if file has corresponding test file
|
|
559
|
+
*/
|
|
560
|
+
hasCorrespondingTestFile(filePath) {
|
|
561
|
+
const testFile = this.findTestFile(filePath);
|
|
562
|
+
return testFile !== null;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Find test file for a given source file
|
|
567
|
+
*/
|
|
568
|
+
findTestFile(filePath) {
|
|
569
|
+
const fs = require('fs');
|
|
570
|
+
const path = require('path');
|
|
571
|
+
|
|
572
|
+
const dir = path.dirname(filePath);
|
|
573
|
+
const basename = path.basename(filePath, path.extname(filePath));
|
|
574
|
+
|
|
575
|
+
const testPatterns = [
|
|
576
|
+
path.join(dir, `${basename}.test.js`),
|
|
577
|
+
path.join(dir, `${basename}.spec.js`),
|
|
578
|
+
path.join(dir, `${basename}.test.ts`),
|
|
579
|
+
path.join(dir, `${basename}.spec.ts`),
|
|
580
|
+
path.join(dir, '__tests__', `${basename}.js`),
|
|
581
|
+
path.join(dir, '__tests__', `${basename}.ts`),
|
|
582
|
+
path.join(dir, 'test', `${basename}.js`),
|
|
583
|
+
path.join(dir, 'test', `${basename}.ts`),
|
|
584
|
+
path.join(dir, 'tests', `${basename}.js`),
|
|
585
|
+
path.join(dir, 'tests', `${basename}.ts`)
|
|
586
|
+
];
|
|
587
|
+
|
|
588
|
+
for (const testPath of testPatterns) {
|
|
589
|
+
if (fs.existsSync(testPath)) {
|
|
590
|
+
return testPath;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Calculate priorities for multiple files
|
|
599
|
+
*/
|
|
600
|
+
calculatePriorities(fileAnalyses) {
|
|
601
|
+
const results = [];
|
|
602
|
+
|
|
603
|
+
for (const fileAnalysis of fileAnalyses) {
|
|
604
|
+
const result = this.calculatePriority(fileAnalysis);
|
|
605
|
+
results.push(result);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return results;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Get priority summary
|
|
613
|
+
*/
|
|
614
|
+
getPrioritySummary(priorityResults) {
|
|
615
|
+
const summary = {
|
|
616
|
+
total: priorityResults.length,
|
|
617
|
+
byPriority: {
|
|
618
|
+
[PRIORITY_LEVELS.CRITICAL]: 0,
|
|
619
|
+
[PRIORITY_LEVELS.HIGH]: 0,
|
|
620
|
+
[PRIORITY_LEVELS.MEDIUM]: 0,
|
|
621
|
+
[PRIORITY_LEVELS.LOW]: 0,
|
|
622
|
+
[PRIORITY_LEVELS.NONE]: 0
|
|
623
|
+
},
|
|
624
|
+
averageScore: 0,
|
|
625
|
+
highestScore: 0,
|
|
626
|
+
lowestScore: 100
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
let totalScore = 0;
|
|
630
|
+
|
|
631
|
+
for (const result of priorityResults) {
|
|
632
|
+
summary.byPriority[result.priority]++;
|
|
633
|
+
totalScore += result.score;
|
|
634
|
+
summary.highestScore = Math.max(summary.highestScore, result.score);
|
|
635
|
+
summary.lowestScore = Math.min(summary.lowestScore, result.score);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
summary.averageScore = summary.total > 0 ? totalScore / summary.total : 0;
|
|
639
|
+
|
|
640
|
+
return summary;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Sort files by priority
|
|
645
|
+
*/
|
|
646
|
+
sortByPriority(priorityResults, descending = true) {
|
|
647
|
+
const priorityOrder = {
|
|
648
|
+
[PRIORITY_LEVELS.CRITICAL]: 0,
|
|
649
|
+
[PRIORITY_LEVELS.HIGH]: 1,
|
|
650
|
+
[PRIORITY_LEVELS.MEDIUM]: 2,
|
|
651
|
+
[PRIORITY_LEVELS.LOW]: 3,
|
|
652
|
+
[PRIORITY_LEVELS.NONE]: 4
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
return [...priorityResults].sort((a, b) => {
|
|
656
|
+
const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
|
|
657
|
+
if (priorityDiff !== 0) {
|
|
658
|
+
return priorityDiff;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// If same priority, sort by score
|
|
662
|
+
return descending ? b.score - a.score : a.score - b.score;
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Get files by priority level
|
|
668
|
+
*/
|
|
669
|
+
getFilesByPriority(priorityResults, priorityLevel) {
|
|
670
|
+
return priorityResults.filter(result => result.priority === priorityLevel);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
module.exports = {
|
|
675
|
+
PriorityCalculator,
|
|
676
|
+
PriorityResult,
|
|
677
|
+
PRIORITY_LEVELS,
|
|
678
|
+
PRIORITY_FACTORS
|
|
679
|
+
};
|