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,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph Builder
|
|
3
|
+
*
|
|
4
|
+
* Handles building and analyzing dependency graphs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { DependencyNode } = require('./dependency-node');
|
|
10
|
+
const { DEPENDENCY_TYPES, ANALYZED_EXTENSIONS, SKIP_DIRECTORIES } = require('./dependency-types');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Dependency graph building utilities
|
|
14
|
+
*/
|
|
15
|
+
class DependencyGraphBuilder {
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.nodes = new Map();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Build dependency graph from root path
|
|
23
|
+
*/
|
|
24
|
+
async buildGraph(rootPath = process.cwd()) {
|
|
25
|
+
const files = await this.getAllFiles(rootPath);
|
|
26
|
+
|
|
27
|
+
for (const filePath of files) {
|
|
28
|
+
const node = new DependencyNode(filePath);
|
|
29
|
+
|
|
30
|
+
// Extract dependencies from file
|
|
31
|
+
const dependencies = await this.extractDependencies(filePath);
|
|
32
|
+
for (const dep of dependencies) {
|
|
33
|
+
node.addDependency(dep.path, dep.type);
|
|
34
|
+
|
|
35
|
+
// Add reverse dependency
|
|
36
|
+
const depNode = this.getOrCreateNode(dep.path);
|
|
37
|
+
depNode.addDependent(filePath);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.nodes.set(filePath, node);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return this.nodes;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get all files to analyze
|
|
48
|
+
*/
|
|
49
|
+
async getAllFiles(rootPath) {
|
|
50
|
+
const files = [];
|
|
51
|
+
|
|
52
|
+
const walkDir = (dir) => {
|
|
53
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
54
|
+
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const fullPath = path.join(dir, entry.name);
|
|
57
|
+
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
// Skip certain directories
|
|
60
|
+
if (this.shouldSkipDirectory(fullPath)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
walkDir(fullPath);
|
|
64
|
+
} else if (entry.isFile()) {
|
|
65
|
+
// Only include certain file types
|
|
66
|
+
if (this.shouldIncludeFile(fullPath)) {
|
|
67
|
+
files.push(fullPath);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
walkDir(rootPath);
|
|
74
|
+
return files;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if directory should be skipped
|
|
79
|
+
*/
|
|
80
|
+
shouldSkipDirectory(dirPath) {
|
|
81
|
+
const dirName = path.basename(dirPath);
|
|
82
|
+
return SKIP_DIRECTORIES.includes(dirName) || dirName.startsWith('.');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if file should be included
|
|
87
|
+
*/
|
|
88
|
+
shouldIncludeFile(filePath) {
|
|
89
|
+
const ext = path.extname(filePath);
|
|
90
|
+
|
|
91
|
+
if (!ANALYZED_EXTENSIONS.includes(ext)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (this.options.ignoreTestFiles && filePath.includes('test')) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (this.options.ignoreVendorFiles && filePath.includes('vendor')) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Extract dependencies from file
|
|
108
|
+
*/
|
|
109
|
+
async extractDependencies(filePath) {
|
|
110
|
+
const dependencies = [];
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
114
|
+
const lines = content.split('\n');
|
|
115
|
+
|
|
116
|
+
for (const line of lines) {
|
|
117
|
+
const trimmed = line.trim();
|
|
118
|
+
|
|
119
|
+
// ES6 imports
|
|
120
|
+
const importMatch = trimmed.match(/import\s+(?:.*?\s+from\s+)?['"]([^'"]+)['"]/);
|
|
121
|
+
if (importMatch) {
|
|
122
|
+
const depPath = this.resolveDependencyPath(filePath, importMatch[1]);
|
|
123
|
+
if (depPath) {
|
|
124
|
+
dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.IMPORT });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// CommonJS requires
|
|
129
|
+
const requireMatch = trimmed.match(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
130
|
+
if (requireMatch) {
|
|
131
|
+
const depPath = this.resolveDependencyPath(filePath, requireMatch[1]);
|
|
132
|
+
if (depPath) {
|
|
133
|
+
dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.REQUIRE });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Dynamic imports
|
|
138
|
+
const dynamicMatch = trimmed.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
139
|
+
if (dynamicMatch) {
|
|
140
|
+
const depPath = this.resolveDependencyPath(filePath, dynamicMatch[1]);
|
|
141
|
+
if (depPath) {
|
|
142
|
+
dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.DYNAMIC });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
} catch (error) {
|
|
148
|
+
// Skip files that can't be read
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return dependencies;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Resolve dependency path to absolute path
|
|
156
|
+
*/
|
|
157
|
+
resolveDependencyPath(fromPath, importPath) {
|
|
158
|
+
if (!importPath.startsWith('./') && !importPath.startsWith('../')) {
|
|
159
|
+
// Skip non-relative imports (node_modules, etc.)
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const absolutePath = path.resolve(path.dirname(fromPath), importPath);
|
|
164
|
+
|
|
165
|
+
// Try different extensions
|
|
166
|
+
const extensions = ['.js', '.jsx', '.ts', '.tsx', '/index.js', '/index.jsx', '/index.ts', '/index.tsx'];
|
|
167
|
+
|
|
168
|
+
for (const ext of extensions) {
|
|
169
|
+
const testPath = absolutePath + ext;
|
|
170
|
+
if (fs.existsSync(testPath)) {
|
|
171
|
+
return path.resolve(testPath);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get or create node
|
|
180
|
+
*/
|
|
181
|
+
getOrCreateNode(filePath) {
|
|
182
|
+
if (!this.nodes.has(filePath)) {
|
|
183
|
+
this.nodes.set(filePath, new DependencyNode(filePath));
|
|
184
|
+
}
|
|
185
|
+
return this.nodes.get(filePath);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Calculate total dependencies
|
|
190
|
+
*/
|
|
191
|
+
calculateTotalDependencies() {
|
|
192
|
+
let total = 0;
|
|
193
|
+
for (const node of this.nodes.values()) {
|
|
194
|
+
total += node.getDependencyCount();
|
|
195
|
+
}
|
|
196
|
+
return total;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get graph statistics
|
|
201
|
+
*/
|
|
202
|
+
getStatistics() {
|
|
203
|
+
return {
|
|
204
|
+
totalFiles: this.nodes.size,
|
|
205
|
+
totalDependencies: this.calculateTotalDependencies(),
|
|
206
|
+
averageDependencies: this.nodes.size > 0 ? this.calculateTotalDependencies() / this.nodes.size : 0
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
module.exports = {
|
|
212
|
+
DependencyGraphBuilder
|
|
213
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution Strategy
|
|
3
|
+
*
|
|
4
|
+
* Represents a strategy for resolving circular dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolution strategy class
|
|
9
|
+
*/
|
|
10
|
+
class ResolutionStrategy {
|
|
11
|
+
constructor(type, description, effort, risk) {
|
|
12
|
+
this.type = type;
|
|
13
|
+
this.description = description;
|
|
14
|
+
this.effort = effort; // 1-10 scale
|
|
15
|
+
this.risk = risk; // 1-10 scale
|
|
16
|
+
this.steps = [];
|
|
17
|
+
this.applicable = true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
addStep(step) {
|
|
21
|
+
this.steps.push(step);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setApplicable(applicable) {
|
|
25
|
+
this.applicable = applicable;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getSummary() {
|
|
29
|
+
return {
|
|
30
|
+
type: this.type,
|
|
31
|
+
description: this.description,
|
|
32
|
+
effort: this.effort,
|
|
33
|
+
risk: this.risk,
|
|
34
|
+
steps: this.steps,
|
|
35
|
+
applicable: this.applicable
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get total score (effort + risk)
|
|
41
|
+
*/
|
|
42
|
+
getScore() {
|
|
43
|
+
return this.effort + this.risk;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check if strategy is low risk
|
|
48
|
+
*/
|
|
49
|
+
isLowRisk() {
|
|
50
|
+
return this.risk <= 3;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if strategy is low effort
|
|
55
|
+
*/
|
|
56
|
+
isLowEffort() {
|
|
57
|
+
return this.effort <= 5;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get recommended priority
|
|
62
|
+
*/
|
|
63
|
+
getPriority() {
|
|
64
|
+
if (this.isLowRisk() && this.isLowEffort()) return 'high';
|
|
65
|
+
if (this.isLowRisk() || this.isLowEffort()) return 'medium';
|
|
66
|
+
return 'low';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
ResolutionStrategy
|
|
72
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates resolution strategies for circular dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ResolutionStrategy } = require('./resolution-strategy');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Strategy generation utilities
|
|
11
|
+
*/
|
|
12
|
+
class StrategyGenerator {
|
|
13
|
+
constructor(nodes) {
|
|
14
|
+
this.nodes = nodes;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate strategies for all cycles
|
|
19
|
+
*/
|
|
20
|
+
generateStrategies(cycles) {
|
|
21
|
+
const allStrategies = [];
|
|
22
|
+
|
|
23
|
+
for (const cycle of cycles) {
|
|
24
|
+
const strategies = this.generateStrategiesForCycle(cycle);
|
|
25
|
+
allStrategies.push(...strategies);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return allStrategies;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generate strategies for a specific cycle
|
|
33
|
+
*/
|
|
34
|
+
generateStrategiesForCycle(cycle) {
|
|
35
|
+
const strategies = [];
|
|
36
|
+
|
|
37
|
+
// Strategy 1: Extract common dependencies
|
|
38
|
+
const extractStrategy = this.generateExtractStrategy(cycle);
|
|
39
|
+
strategies.push(extractStrategy);
|
|
40
|
+
|
|
41
|
+
// Strategy 2: Invert dependency
|
|
42
|
+
const invertStrategy = this.generateInvertStrategy(cycle);
|
|
43
|
+
strategies.push(invertStrategy);
|
|
44
|
+
|
|
45
|
+
// Strategy 3: Introduce interface/abstraction
|
|
46
|
+
const interfaceStrategy = this.generateInterfaceStrategy(cycle);
|
|
47
|
+
strategies.push(interfaceStrategy);
|
|
48
|
+
|
|
49
|
+
// Strategy 4: Merge modules
|
|
50
|
+
const mergeStrategy = this.generateMergeStrategy(cycle);
|
|
51
|
+
strategies.push(mergeStrategy);
|
|
52
|
+
|
|
53
|
+
// Strategy 5: Dependency injection
|
|
54
|
+
const diStrategy = this.generateDIStrategy(cycle);
|
|
55
|
+
strategies.push(diStrategy);
|
|
56
|
+
|
|
57
|
+
return strategies.filter(s => s.applicable);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate extract common dependencies strategy
|
|
62
|
+
*/
|
|
63
|
+
generateExtractStrategy(cycle) {
|
|
64
|
+
const strategy = new ResolutionStrategy(
|
|
65
|
+
'extract_common',
|
|
66
|
+
'Extract common dependencies into a shared module',
|
|
67
|
+
6,
|
|
68
|
+
4
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
strategy.addStep('Analyze all files in the cycle for common dependencies');
|
|
72
|
+
strategy.addStep('Create a new module for shared dependencies');
|
|
73
|
+
strategy.addStep('Update all files to import from the shared module');
|
|
74
|
+
strategy.addStep('Remove duplicate dependencies from individual files');
|
|
75
|
+
|
|
76
|
+
// Check if applicable
|
|
77
|
+
const commonDeps = this.findCommonDependencies(cycle);
|
|
78
|
+
strategy.setApplicable(commonDeps.length > 1);
|
|
79
|
+
|
|
80
|
+
return strategy;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Generate invert dependency strategy
|
|
85
|
+
*/
|
|
86
|
+
generateInvertStrategy(cycle) {
|
|
87
|
+
const strategy = new ResolutionStrategy(
|
|
88
|
+
'invert_dependency',
|
|
89
|
+
'Invert one dependency in the cycle',
|
|
90
|
+
4,
|
|
91
|
+
3
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
strategy.addStep('Identify the dependency to invert');
|
|
95
|
+
strategy.addStep('Use dependency injection or events instead');
|
|
96
|
+
strategy.addStep('Update the dependent file');
|
|
97
|
+
strategy.addStep('Test the inverted dependency');
|
|
98
|
+
|
|
99
|
+
// Always applicable for cycles of length 2
|
|
100
|
+
strategy.setApplicable(cycle.length <= 3);
|
|
101
|
+
|
|
102
|
+
return strategy;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generate interface/abstraction strategy
|
|
107
|
+
*/
|
|
108
|
+
generateInterfaceStrategy(cycle) {
|
|
109
|
+
const strategy = new ResolutionStrategy(
|
|
110
|
+
'interface_abstraction',
|
|
111
|
+
'Introduce interface/abstraction to break cycle',
|
|
112
|
+
7,
|
|
113
|
+
5
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
strategy.addStep('Design an interface for the shared functionality');
|
|
117
|
+
strategy.addStep('Create the interface module');
|
|
118
|
+
strategy.addStep('Implement the interface in one of the modules');
|
|
119
|
+
strategy.addStep('Update other modules to use the interface');
|
|
120
|
+
strategy.addStep('Remove direct dependencies');
|
|
121
|
+
|
|
122
|
+
// Check if applicable (needs TypeScript or similar)
|
|
123
|
+
strategy.setApplicable(this.hasTypeScriptFiles(cycle));
|
|
124
|
+
|
|
125
|
+
return strategy;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Generate merge modules strategy
|
|
130
|
+
*/
|
|
131
|
+
generateMergeStrategy(cycle) {
|
|
132
|
+
const strategy = new ResolutionStrategy(
|
|
133
|
+
'merge_modules',
|
|
134
|
+
'Merge modules in the cycle',
|
|
135
|
+
3,
|
|
136
|
+
2
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
strategy.addStep('Identify modules that can be safely merged');
|
|
140
|
+
strategy.addStep('Create merged module');
|
|
141
|
+
strategy.addStep('Update all dependencies');
|
|
142
|
+
strategy.addStep('Remove original modules');
|
|
143
|
+
|
|
144
|
+
// Check if applicable (small files only)
|
|
145
|
+
strategy.setApplicable(this.canMergeModules(cycle));
|
|
146
|
+
|
|
147
|
+
return strategy;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate dependency injection strategy
|
|
152
|
+
*/
|
|
153
|
+
generateDIStrategy(cycle) {
|
|
154
|
+
const strategy = new ResolutionStrategy(
|
|
155
|
+
'dependency_injection',
|
|
156
|
+
'Use dependency injection to break cycle',
|
|
157
|
+
8,
|
|
158
|
+
6
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
strategy.addStep('Create a dependency injection container');
|
|
162
|
+
strategy.addStep('Register dependencies in the container');
|
|
163
|
+
strategy.addStep('Update modules to use injected dependencies');
|
|
164
|
+
strategy.addStep('Configure the injection at application startup');
|
|
165
|
+
|
|
166
|
+
// Always applicable
|
|
167
|
+
strategy.setApplicable(true);
|
|
168
|
+
|
|
169
|
+
return strategy;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Find common dependencies in a cycle
|
|
174
|
+
*/
|
|
175
|
+
findCommonDependencies(cycle) {
|
|
176
|
+
const dependencyCounts = new Map();
|
|
177
|
+
|
|
178
|
+
for (const filePath of cycle) {
|
|
179
|
+
const node = this.nodes.get(filePath);
|
|
180
|
+
if (node) {
|
|
181
|
+
for (const dep of node.dependencies) {
|
|
182
|
+
const depPath = typeof dep === 'object' ? dep.path : dep;
|
|
183
|
+
dependencyCounts.set(depPath, (dependencyCounts.get(depPath) || 0) + 1);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return Array.from(dependencyCounts.entries())
|
|
189
|
+
.filter(([_, count]) => count > 1)
|
|
190
|
+
.map(([path, _]) => path);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Check if cycle has TypeScript files
|
|
195
|
+
*/
|
|
196
|
+
hasTypeScriptFiles(cycle) {
|
|
197
|
+
return cycle.some(filePath => filePath.endsWith('.ts') || filePath.endsWith('.tsx'));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if modules can be merged
|
|
202
|
+
*/
|
|
203
|
+
canMergeModules(cycle) {
|
|
204
|
+
for (const filePath of cycle) {
|
|
205
|
+
const node = this.nodes.get(filePath);
|
|
206
|
+
if (node && node.metadata.size > 200) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get best strategy for a cycle
|
|
215
|
+
*/
|
|
216
|
+
getBestStrategy(cycle) {
|
|
217
|
+
const strategies = this.generateStrategiesForCycle(cycle);
|
|
218
|
+
if (strategies.length === 0) return null;
|
|
219
|
+
|
|
220
|
+
// Sort by score (effort + risk)
|
|
221
|
+
strategies.sort((a, b) => a.getScore() - b.getScore());
|
|
222
|
+
|
|
223
|
+
return strategies[0];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = {
|
|
228
|
+
StrategyGenerator
|
|
229
|
+
};
|