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.
Files changed (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. package/src/sync/sync-engine-backup.js +0 -559
@@ -0,0 +1,809 @@
1
+ /**
2
+ * Circular Dependency Resolver
3
+ *
4
+ * Detects and resolves circular dependencies in the codebase.
5
+ * Provides strategies for breaking cycles while maintaining functionality.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Dependency types
13
+ */
14
+ const DEPENDENCY_TYPES = {
15
+ IMPORT: 'import',
16
+ REQUIRE: 'require',
17
+ DYNAMIC: 'dynamic',
18
+ INDIRECT: 'indirect'
19
+ };
20
+
21
+ /**
22
+ * Cycle severity levels
23
+ */
24
+ const CYCLE_SEVERITY = {
25
+ LOW: 'low',
26
+ MEDIUM: 'medium',
27
+ HIGH: 'high',
28
+ CRITICAL: 'critical'
29
+ };
30
+
31
+ /**
32
+ * Dependency node class
33
+ */
34
+ class DependencyNode {
35
+ constructor(filePath) {
36
+ this.filePath = filePath;
37
+ this.dependencies = new Set();
38
+ this.dependents = new Set();
39
+ this.visited = false;
40
+ this.visiting = false;
41
+ this.metadata = {
42
+ size: 0,
43
+ type: this.detectFileType(),
44
+ package: this.extractPackage()
45
+ };
46
+ }
47
+
48
+ detectFileType() {
49
+ const ext = path.extname(this.filePath).toLowerCase();
50
+ if (['.js', '.jsx', '.ts', '.tsx'].includes(ext)) return 'javascript';
51
+ if (ext === '.json') return 'json';
52
+ return 'other';
53
+ }
54
+
55
+ extractPackage() {
56
+ const match = this.filePath.match(/packages\/([^\/]+)/);
57
+ return match ? match[1] : 'root';
58
+ }
59
+
60
+ addDependency(filePath, type = DEPENDENCY_TYPES.IMPORT) {
61
+ this.dependencies.add({ path: filePath, type });
62
+ }
63
+
64
+ addDependent(filePath) {
65
+ this.dependents.add(filePath);
66
+ }
67
+
68
+ hasDependency(filePath) {
69
+ return this.dependencies.has(filePath);
70
+ }
71
+
72
+ getDependencyCount() {
73
+ return this.dependencies.size;
74
+ }
75
+
76
+ getDependentCount() {
77
+ return this.dependents.size;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Circular dependency class
83
+ */
84
+ class CircularDependency {
85
+ constructor(cycle) {
86
+ this.cycle = cycle;
87
+ this.length = cycle.length;
88
+ this.severity = this.calculateSeverity();
89
+ this.impact = this.calculateImpact();
90
+ this.resolution = null;
91
+ this.metadata = {
92
+ detectedAt: new Date().toISOString(),
93
+ confidence: 0.8
94
+ };
95
+ }
96
+
97
+ calculateSeverity() {
98
+ if (this.length === 2) return CYCLE_SEVERITY.CRITICAL;
99
+ if (this.length === 3) return CYCLE_SEVERITY.HIGH;
100
+ if (this.length <= 5) return CYCLE_SEVERITY.MEDIUM;
101
+ return CYCLE_SEVERITY.LOW;
102
+ }
103
+
104
+ calculateImpact() {
105
+ let impact = 0;
106
+
107
+ // Impact based on cycle length
108
+ impact += (6 - Math.min(this.length, 6)) * 10;
109
+
110
+ // Impact based on file types
111
+ for (const filePath of this.cycle) {
112
+ if (filePath.includes('packages/core')) impact += 15;
113
+ if (filePath.includes('packages/cli')) impact += 10;
114
+ if (filePath.includes('packages/electron-app')) impact += 8;
115
+ }
116
+
117
+ return Math.min(100, impact);
118
+ }
119
+
120
+ setResolution(resolution) {
121
+ this.resolution = resolution;
122
+ }
123
+
124
+ getSummary() {
125
+ return {
126
+ cycle: this.cycle,
127
+ length: this.length,
128
+ severity: this.severity,
129
+ impact: this.impact,
130
+ resolution: this.resolution,
131
+ confidence: this.metadata.confidence
132
+ };
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Resolution strategy class
138
+ */
139
+ class ResolutionStrategy {
140
+ constructor(type, description, effort, risk) {
141
+ this.type = type;
142
+ this.description = description;
143
+ this.effort = effort; // 1-10 scale
144
+ this.risk = risk; // 1-10 scale
145
+ this.steps = [];
146
+ this.applicable = true;
147
+ }
148
+
149
+ addStep(step) {
150
+ this.steps.push(step);
151
+ }
152
+
153
+ setApplicable(applicable) {
154
+ this.applicable = applicable;
155
+ }
156
+
157
+ getSummary() {
158
+ return {
159
+ type: this.type,
160
+ description: this.description,
161
+ effort: this.effort,
162
+ risk: this.risk,
163
+ steps: this.steps,
164
+ applicable: this.applicable
165
+ };
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Circular dependency resolver result class
171
+ */
172
+ class CircularDependencyResult {
173
+ constructor() {
174
+ this.cycles = [];
175
+ this.strategies = [];
176
+ this.resolved = [];
177
+ this.failed = [];
178
+ this.metadata = {
179
+ analyzedAt: new Date().toISOString(),
180
+ totalFiles: 0,
181
+ totalDependencies: 0
182
+ };
183
+ this.errors = [];
184
+ this.warnings = [];
185
+ }
186
+
187
+ addCycle(cycle) {
188
+ this.cycles.push(cycle);
189
+ }
190
+
191
+ addStrategy(strategy) {
192
+ this.strategies.push(strategy);
193
+ }
194
+
195
+ addResolved(resolution) {
196
+ this.resolved.push(resolution);
197
+ }
198
+
199
+ addFailed(failure) {
200
+ this.failed.push(failure);
201
+ }
202
+
203
+ addError(error) {
204
+ this.errors.push({
205
+ message: error.message,
206
+ timestamp: new Date().toISOString()
207
+ });
208
+ }
209
+
210
+ addWarning(warning) {
211
+ this.warnings.push({
212
+ message: warning,
213
+ timestamp: new Date().toISOString()
214
+ });
215
+ }
216
+
217
+ getSummary() {
218
+ return {
219
+ cyclesFound: this.cycles.length,
220
+ strategiesGenerated: this.strategies.length,
221
+ cyclesResolved: this.resolved.length,
222
+ cyclesFailed: this.failed.length,
223
+ totalFiles: this.metadata.totalFiles,
224
+ totalDependencies: this.metadata.totalDependencies,
225
+ errorCount: this.errors.length,
226
+ warningCount: this.warnings.length
227
+ };
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Circular dependency resolver class
233
+ */
234
+ class CircularDependencyResolver {
235
+ constructor(options = {}) {
236
+ this.options = {
237
+ maxDepth: 10,
238
+ includeIndirect: true,
239
+ ignoreTestFiles: true,
240
+ ignoreVendorFiles: true,
241
+ generateStrategies: true,
242
+ autoResolve: false,
243
+ ...options
244
+ };
245
+
246
+ this.nodes = new Map();
247
+ this.result = new CircularDependencyResult();
248
+ }
249
+
250
+ /**
251
+ * Analyze codebase for circular dependencies
252
+ */
253
+ async analyze(rootPath = process.cwd()) {
254
+ console.log('Analyzing circular dependencies...');
255
+
256
+ try {
257
+ // Build dependency graph
258
+ await this.buildDependencyGraph(rootPath);
259
+
260
+ // Detect cycles
261
+ await this.detectCycles();
262
+
263
+ // Generate resolution strategies
264
+ if (this.options.generateStrategies) {
265
+ await this.generateStrategies();
266
+ }
267
+
268
+ // Auto-resolve if enabled
269
+ if (this.options.autoResolve) {
270
+ await this.autoResolve();
271
+ }
272
+
273
+ this.result.metadata.totalFiles = this.nodes.size;
274
+ this.result.metadata.totalDependencies = this.calculateTotalDependencies();
275
+
276
+ console.log(`Analysis complete: ${this.result.cycles.length} cycles found`);
277
+
278
+ } catch (error) {
279
+ this.result.addError(error);
280
+ }
281
+
282
+ return this.result;
283
+ }
284
+
285
+ /**
286
+ * Build dependency graph
287
+ */
288
+ async buildDependencyGraph(rootPath) {
289
+ const files = await this.getAllFiles(rootPath);
290
+
291
+ for (const filePath of files) {
292
+ const node = new DependencyNode(filePath);
293
+
294
+ // Extract dependencies from file
295
+ const dependencies = await this.extractDependencies(filePath);
296
+ for (const dep of dependencies) {
297
+ node.addDependency(dep.path, dep.type);
298
+
299
+ // Add reverse dependency
300
+ const depNode = this.getOrCreateNode(dep.path);
301
+ depNode.addDependent(filePath);
302
+ }
303
+
304
+ this.nodes.set(filePath, node);
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Get all files to analyze
310
+ */
311
+ async getAllFiles(rootPath) {
312
+ const files = [];
313
+
314
+ const walkDir = (dir) => {
315
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
316
+
317
+ for (const entry of entries) {
318
+ const fullPath = path.join(dir, entry.name);
319
+
320
+ if (entry.isDirectory()) {
321
+ // Skip certain directories
322
+ if (this.shouldSkipDirectory(fullPath)) {
323
+ continue;
324
+ }
325
+ walkDir(fullPath);
326
+ } else if (entry.isFile()) {
327
+ // Only include certain file types
328
+ if (this.shouldIncludeFile(fullPath)) {
329
+ files.push(fullPath);
330
+ }
331
+ }
332
+ }
333
+ };
334
+
335
+ walkDir(rootPath);
336
+ return files;
337
+ }
338
+
339
+ /**
340
+ * Check if directory should be skipped
341
+ */
342
+ shouldSkipDirectory(dirPath) {
343
+ const dirName = path.basename(dirPath);
344
+ const skipDirs = [
345
+ 'node_modules', '.git', 'dist', 'build', 'coverage',
346
+ '.vscode', '.idea', '.cursor', '.windsurf'
347
+ ];
348
+
349
+ return skipDirs.includes(dirName) || dirName.startsWith('.');
350
+ }
351
+
352
+ /**
353
+ * Check if file should be included
354
+ */
355
+ shouldIncludeFile(filePath) {
356
+ const ext = path.extname(filePath);
357
+ const includeExts = ['.js', '.jsx', '.ts', '.tsx'];
358
+
359
+ if (!includeExts.includes(ext)) {
360
+ return false;
361
+ }
362
+
363
+ if (this.options.ignoreTestFiles && filePath.includes('test')) {
364
+ return false;
365
+ }
366
+
367
+ if (this.options.ignoreVendorFiles && filePath.includes('vendor')) {
368
+ return false;
369
+ }
370
+
371
+ return true;
372
+ }
373
+
374
+ /**
375
+ * Extract dependencies from file
376
+ */
377
+ async extractDependencies(filePath) {
378
+ const dependencies = [];
379
+
380
+ try {
381
+ const content = fs.readFileSync(filePath, 'utf8');
382
+ const lines = content.split('\n');
383
+
384
+ for (const line of lines) {
385
+ const trimmed = line.trim();
386
+
387
+ // ES6 imports
388
+ const importMatch = trimmed.match(/import\s+(?:.*?\s+from\s+)?['"]([^'"]+)['"]/);
389
+ if (importMatch) {
390
+ const depPath = this.resolveDependencyPath(filePath, importMatch[1]);
391
+ if (depPath) {
392
+ dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.IMPORT });
393
+ }
394
+ }
395
+
396
+ // CommonJS requires
397
+ const requireMatch = trimmed.match(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
398
+ if (requireMatch) {
399
+ const depPath = this.resolveDependencyPath(filePath, requireMatch[1]);
400
+ if (depPath) {
401
+ dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.REQUIRE });
402
+ }
403
+ }
404
+
405
+ // Dynamic imports
406
+ const dynamicMatch = trimmed.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
407
+ if (dynamicMatch) {
408
+ const depPath = this.resolveDependencyPath(filePath, dynamicMatch[1]);
409
+ if (depPath) {
410
+ dependencies.push({ path: depPath, type: DEPENDENCY_TYPES.DYNAMIC });
411
+ }
412
+ }
413
+ }
414
+
415
+ } catch (error) {
416
+ // Skip files that can't be read
417
+ }
418
+
419
+ return dependencies;
420
+ }
421
+
422
+ /**
423
+ * Resolve dependency path to absolute path
424
+ */
425
+ resolveDependencyPath(fromPath, importPath) {
426
+ if (!importPath.startsWith('./') && !importPath.startsWith('../')) {
427
+ // Skip non-relative imports (node_modules, etc.)
428
+ return null;
429
+ }
430
+
431
+ const absolutePath = path.resolve(path.dirname(fromPath), importPath);
432
+
433
+ // Try different extensions
434
+ const extensions = ['.js', '.jsx', '.ts', '.tsx', '/index.js', '/index.jsx', '/index.ts', '/index.tsx'];
435
+
436
+ for (const ext of extensions) {
437
+ const testPath = absolutePath + ext;
438
+ if (fs.existsSync(testPath)) {
439
+ return path.resolve(testPath);
440
+ }
441
+ }
442
+
443
+ return null;
444
+ }
445
+
446
+ /**
447
+ * Detect cycles using DFS
448
+ */
449
+ async detectCycles() {
450
+ const visited = new Set();
451
+
452
+ for (const [filePath, node] of this.nodes) {
453
+ if (!visited.has(filePath)) {
454
+ const cycle = this.findCycle(filePath, new Set(), new Set());
455
+ if (cycle.length > 0) {
456
+ const circularDep = new CircularDependency(cycle);
457
+ this.result.addCycle(circularDep);
458
+ }
459
+ }
460
+ }
461
+ }
462
+
463
+ /**
464
+ * Find cycle starting from a node
465
+ */
466
+ findCycle(startPath, currentPath, visiting) {
467
+ const node = this.nodes.get(startPath);
468
+ if (!node) return [];
469
+
470
+ visiting.add(startPath);
471
+
472
+ for (const dep of node.dependencies) {
473
+ const depPath = typeof dep === 'object' ? dep.path : dep;
474
+
475
+ if (depPath === startPath) {
476
+ // Found cycle
477
+ return [startPath];
478
+ }
479
+
480
+ if (visiting.has(depPath)) {
481
+ // Found cycle through current path
482
+ return [depPath, startPath];
483
+ }
484
+
485
+ if (!currentPath.has(depPath)) {
486
+ const cycle = this.findCycle(depPath, currentPath, visiting);
487
+ if (cycle.length > 0) {
488
+ if (cycle[cycle.length - 1] === startPath) {
489
+ return cycle;
490
+ } else {
491
+ return [...cycle, startPath];
492
+ }
493
+ }
494
+ }
495
+ }
496
+
497
+ visiting.delete(startPath);
498
+ currentPath.add(startPath);
499
+
500
+ return [];
501
+ }
502
+
503
+ /**
504
+ * Generate resolution strategies
505
+ */
506
+ async generateStrategies() {
507
+ for (const cycle of this.result.cycles) {
508
+ const strategies = this.generateStrategiesForCycle(cycle);
509
+ for (const strategy of strategies) {
510
+ this.result.addStrategy(strategy);
511
+ }
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Generate strategies for a specific cycle
517
+ */
518
+ generateStrategiesForCycle(cycle) {
519
+ const strategies = [];
520
+
521
+ // Strategy 1: Extract common dependencies
522
+ const extractStrategy = this.generateExtractStrategy(cycle);
523
+ strategies.push(extractStrategy);
524
+
525
+ // Strategy 2: Invert dependency
526
+ const invertStrategy = this.generateInvertStrategy(cycle);
527
+ strategies.push(invertStrategy);
528
+
529
+ // Strategy 3: Introduce interface/abstraction
530
+ const interfaceStrategy = this.generateInterfaceStrategy(cycle);
531
+ strategies.push(interfaceStrategy);
532
+
533
+ // Strategy 4: Merge modules
534
+ const mergeStrategy = this.generateMergeStrategy(cycle);
535
+ strategies.push(mergeStrategy);
536
+
537
+ // Strategy 5: Dependency injection
538
+ const diStrategy = this.generateDIStrategy(cycle);
539
+ strategies.push(diStrategy);
540
+
541
+ return strategies.filter(s => s.applicable);
542
+ }
543
+
544
+ /**
545
+ * Generate extract common dependencies strategy
546
+ */
547
+ generateExtractStrategy(cycle) {
548
+ const strategy = new ResolutionStrategy(
549
+ 'extract_common',
550
+ 'Extract common dependencies into a shared module',
551
+ 6,
552
+ 4
553
+ );
554
+
555
+ strategy.addStep('Analyze all files in the cycle for common dependencies');
556
+ strategy.addStep('Create a new module for shared dependencies');
557
+ strategy.addStep('Update all files to import from the shared module');
558
+ strategy.addStep('Remove duplicate dependencies from individual files');
559
+
560
+ // Check if applicable
561
+ const commonDeps = this.findCommonDependencies(cycle);
562
+ strategy.setApplicable(commonDeps.length > 1);
563
+
564
+ return strategy;
565
+ }
566
+
567
+ /**
568
+ * Generate invert dependency strategy
569
+ */
570
+ generateInvertStrategy(cycle) {
571
+ const strategy = new ResolutionStrategy(
572
+ 'invert_dependency',
573
+ 'Invert one dependency in the cycle',
574
+ 4,
575
+ 3
576
+ );
577
+
578
+ strategy.addStep('Identify the dependency to invert');
579
+ strategy.addStep('Use dependency injection or events instead');
580
+ strategy.addStep('Update the dependent file');
581
+ strategy.addStep('Test the inverted dependency');
582
+
583
+ // Always applicable for cycles of length 2
584
+ strategy.setApplicable(cycle.length <= 3);
585
+
586
+ return strategy;
587
+ }
588
+
589
+ /**
590
+ * Generate interface/abstraction strategy
591
+ */
592
+ generateInterfaceStrategy(cycle) {
593
+ const strategy = new ResolutionStrategy(
594
+ 'interface_abstraction',
595
+ 'Introduce interface/abstraction to break cycle',
596
+ 7,
597
+ 5
598
+ );
599
+
600
+ strategy.addStep('Design an interface for the shared functionality');
601
+ strategy.addStep('Create the interface module');
602
+ strategy.addStep('Implement the interface in one of the modules');
603
+ strategy.addStep('Update other modules to use the interface');
604
+ strategy.addStep('Remove direct dependencies');
605
+
606
+ // Check if applicable (needs TypeScript or similar)
607
+ strategy.setApplicable(this.hasTypeScriptFiles(cycle));
608
+
609
+ return strategy;
610
+ }
611
+
612
+ /**
613
+ * Generate merge modules strategy
614
+ */
615
+ generateMergeStrategy(cycle) {
616
+ const strategy = new ResolutionStrategy(
617
+ 'merge_modules',
618
+ 'Merge modules in the cycle',
619
+ 3,
620
+ 2
621
+ );
622
+
623
+ strategy.addStep('Identify modules that can be safely merged');
624
+ strategy.addStep('Create merged module');
625
+ strategy.addStep('Update all dependencies');
626
+ strategy.addStep('Remove original modules');
627
+
628
+ // Check if applicable (small files only)
629
+ strategy.setApplicable(this.canMergeModules(cycle));
630
+
631
+ return strategy;
632
+ }
633
+
634
+ /**
635
+ * Generate dependency injection strategy
636
+ */
637
+ generateDIStrategy(cycle) {
638
+ const strategy = new ResolutionStrategy(
639
+ 'dependency_injection',
640
+ 'Use dependency injection to break cycle',
641
+ 8,
642
+ 6
643
+ );
644
+
645
+ strategy.addStep('Create a dependency injection container');
646
+ strategy.addStep('Register dependencies in the container');
647
+ strategy.addStep('Update modules to use injected dependencies');
648
+ strategy.addStep('Configure the injection at application startup');
649
+
650
+ // Always applicable
651
+ strategy.setApplicable(true);
652
+
653
+ return strategy;
654
+ }
655
+
656
+ /**
657
+ * Find common dependencies in a cycle
658
+ */
659
+ findCommonDependencies(cycle) {
660
+ const dependencyCounts = new Map();
661
+
662
+ for (const filePath of cycle) {
663
+ const node = this.nodes.get(filePath);
664
+ if (node) {
665
+ for (const dep of node.dependencies) {
666
+ const depPath = typeof dep === 'object' ? dep.path : dep;
667
+ dependencyCounts.set(depPath, (dependencyCounts.get(depPath) || 0) + 1);
668
+ }
669
+ }
670
+ }
671
+
672
+ return Array.from(dependencyCounts.entries())
673
+ .filter(([_, count]) => count > 1)
674
+ .map(([path, _]) => path);
675
+ }
676
+
677
+ /**
678
+ * Check if cycle has TypeScript files
679
+ */
680
+ hasTypeScriptFiles(cycle) {
681
+ return cycle.some(filePath => filePath.endsWith('.ts') || filePath.endsWith('.tsx'));
682
+ }
683
+
684
+ /**
685
+ * Check if modules can be merged
686
+ */
687
+ canMergeModules(cycle) {
688
+ for (const filePath of cycle) {
689
+ const node = this.nodes.get(filePath);
690
+ if (node && node.metadata.size > 200) {
691
+ return false;
692
+ }
693
+ }
694
+ return true;
695
+ }
696
+
697
+ /**
698
+ * Auto-resolve cycles
699
+ */
700
+ async autoResolve() {
701
+ for (const cycle of this.result.cycles) {
702
+ if (cycle.severity === CYCLE_SEVERITY.CRITICAL) {
703
+ // Try to resolve critical cycles automatically
704
+ const strategy = this.result.strategies.find(s => s.applicable && s.effort <= 5);
705
+ if (strategy) {
706
+ try {
707
+ const resolution = await this.applyStrategy(cycle, strategy);
708
+ this.result.addResolved(resolution);
709
+ } catch (error) {
710
+ this.result.addFailed({ cycle, strategy, error: error.message });
711
+ }
712
+ }
713
+ }
714
+ }
715
+ }
716
+
717
+ /**
718
+ * Apply a resolution strategy
719
+ */
720
+ async applyStrategy(cycle, strategy) {
721
+ // This would implement the actual resolution
722
+ // For now, return a placeholder resolution
723
+ return {
724
+ cycle: cycle.cycle,
725
+ strategy: strategy.type,
726
+ success: true,
727
+ changes: []
728
+ };
729
+ }
730
+
731
+ /**
732
+ * Get or create node
733
+ */
734
+ getOrCreateNode(filePath) {
735
+ if (!this.nodes.has(filePath)) {
736
+ this.nodes.set(filePath, new DependencyNode(filePath));
737
+ }
738
+ return this.nodes.get(filePath);
739
+ }
740
+
741
+ /**
742
+ * Calculate total dependencies
743
+ */
744
+ calculateTotalDependencies() {
745
+ let total = 0;
746
+ for (const node of this.nodes.values()) {
747
+ total += node.getDependencyCount();
748
+ }
749
+ return total;
750
+ }
751
+
752
+ /**
753
+ * Get statistics
754
+ */
755
+ getStatistics() {
756
+ const cyclesBySeverity = {
757
+ [CYCLE_SEVERITY.CRITICAL]: 0,
758
+ [CYCLE_SEVERITY.HIGH]: 0,
759
+ [CYCLE_SEVERITY.MEDIUM]: 0,
760
+ [CYCLE_SEVERITY.LOW]: 0
761
+ };
762
+
763
+ for (const cycle of this.result.cycles) {
764
+ cyclesBySeverity[cycle.severity]++;
765
+ }
766
+
767
+ return {
768
+ totalFiles: this.result.metadata.totalFiles,
769
+ totalDependencies: this.result.metadata.totalDependencies,
770
+ cyclesFound: this.result.cycles.length,
771
+ cyclesBySeverity,
772
+ strategiesGenerated: this.result.strategies.length,
773
+ cyclesResolved: this.result.resolved.length,
774
+ cyclesFailed: this.result.failed.length
775
+ };
776
+ }
777
+
778
+ /**
779
+ * Export dependency graph
780
+ */
781
+ exportGraph(format = 'json') {
782
+ const graph = {
783
+ nodes: Array.from(this.nodes.entries()).map(([path, node]) => ({
784
+ path,
785
+ dependencies: Array.from(node.dependencies),
786
+ dependents: Array.from(node.dependents),
787
+ metadata: node.metadata
788
+ })),
789
+ cycles: this.result.cycles.map(cycle => cycle.getSummary()),
790
+ strategies: this.result.strategies.map(strategy => strategy.getSummary())
791
+ };
792
+
793
+ if (format === 'json') {
794
+ return JSON.stringify(graph, null, 2);
795
+ }
796
+
797
+ return graph;
798
+ }
799
+ }
800
+
801
+ module.exports = {
802
+ CircularDependencyResolver,
803
+ CircularDependencyResult,
804
+ CircularDependency,
805
+ DependencyNode,
806
+ ResolutionStrategy,
807
+ DEPENDENCY_TYPES,
808
+ CYCLE_SEVERITY
809
+ };