vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850

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 (192) hide show
  1. package/package.json +1 -1
  2. package/src/agents/AgentCheckDiscoveryService.js +180 -0
  3. package/src/agents/AgentCheckService.js +18 -261
  4. package/src/agents/AgentCheckStatisticsService.js +195 -0
  5. package/src/agents/EnvironmentConfigurationManager.js +31 -380
  6. package/src/agents/InstallationType.js +19 -6
  7. package/src/agents/SimpleAgentCheckService.js +472 -0
  8. package/src/agents/config-managers/ConfigUtils.js +72 -0
  9. package/src/agents/config-managers/DefaultConfig.js +58 -0
  10. package/src/agents/config-managers/EnvVarLoader.js +66 -0
  11. package/src/agents/config-managers/FileConfigLoader.js +124 -0
  12. package/src/agents/config-managers/TypeConverters.js +61 -0
  13. package/src/agents/config-managers/VariableMappings.js +92 -0
  14. package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
  15. package/src/agents/discovery/AgentDiscoveryService.js +29 -403
  16. package/src/agents/discovery/agent-validator.js +262 -0
  17. package/src/agents/discovery/discovery-results.js +176 -0
  18. package/src/agents/discovery/discovery-scanner.js +268 -0
  19. package/src/agents/discovery/discovery-utils.js +161 -0
  20. package/src/agents/discovery/executable-analyzer.js +290 -0
  21. package/src/agents/discovery/history-manager.js +310 -0
  22. package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
  23. package/src/agents/verification/ResultAnalyzer.js +30 -431
  24. package/src/agents/verification/analysis-utils.js +310 -0
  25. package/src/agents/verification/batch-analyzer.js +440 -0
  26. package/src/agents/verification/pattern-recognizer.js +369 -0
  27. package/src/agents/verification/report-generator.js +320 -0
  28. package/src/agents/verification/test-analyzer.js +290 -0
  29. package/src/agents/windows/InstallerFactory.js +4 -0
  30. package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
  31. package/src/analysis/analysis-engine.js +314 -0
  32. package/src/analysis/ast-analyzer.js +342 -0
  33. package/src/analysis/boundary-detector-refactored.js +378 -0
  34. package/src/analysis/boundary-detector.js +200 -603
  35. package/src/analysis/boundary-scanner.js +609 -0
  36. package/src/analysis/boundary-types.js +118 -0
  37. package/src/analysis/boundary-utils.js +293 -0
  38. package/src/analysis/deadline-priority-calculator.js +18 -0
  39. package/src/analysis/detection-methods.js +347 -0
  40. package/src/analysis/importance-priority-calculator.js +18 -0
  41. package/src/analysis/priority/factor-calculators.js +204 -0
  42. package/src/analysis/priority/factor-helpers.js +71 -0
  43. package/src/analysis/priority/priority-constants.js +73 -0
  44. package/src/analysis/priority/priority-factor-calculators.js +301 -0
  45. package/src/analysis/priority/reasons-generator.js +44 -0
  46. package/src/analysis/priority-calculator.js +15 -580
  47. package/src/analysis/strategy-generator.js +16 -66
  48. package/src/analysis/type-priority-calculator.js +18 -0
  49. package/src/analysis/urgency-priority-calculator.js +18 -0
  50. package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
  51. package/src/commands/disable-requirement.js +60 -0
  52. package/src/commands/disable-spec.js +60 -0
  53. package/src/commands/enable-requirement.js +60 -0
  54. package/src/commands/enable-spec.js +60 -0
  55. package/src/commands/registry.js +1 -6
  56. package/src/commands/requirements.js +8 -2
  57. package/src/ide-integration/applescript-manager.cjs +9 -24
  58. package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
  59. package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
  60. package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
  61. package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
  62. package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
  63. package/src/ide-integration/cdp-manager.js +28 -573
  64. package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
  65. package/src/ide-integration/ide-openers/claude-opener.js +171 -0
  66. package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
  67. package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
  68. package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
  69. package/src/ide-integration/macos-ide-manager.js +20 -582
  70. package/src/ide-integration/macos-quota-checker.js +164 -0
  71. package/src/ide-integration/macos-text-sender.js +19 -38
  72. package/src/ide-integration/provider-manager.cjs +52 -7
  73. package/src/index.cjs +6 -0
  74. package/src/index.js +10 -0
  75. package/src/llm/direct-llm-manager.cjs +501 -0
  76. package/src/localization/translations/en-part1.js +363 -0
  77. package/src/localization/translations/en-part2.js +320 -0
  78. package/src/localization/translations/en.js +4 -687
  79. package/src/localization/translations/es-part1.js +363 -0
  80. package/src/localization/translations/es-part2.js +320 -0
  81. package/src/localization/translations/es.js +4 -688
  82. package/src/models/file-analysis-collection.js +139 -0
  83. package/src/models/file-analysis-metrics.js +50 -0
  84. package/src/models/file-analysis.js +15 -262
  85. package/src/models/plan-manager.js +410 -0
  86. package/src/models/refactoring-models.js +380 -0
  87. package/src/models/refactoring-plan-refactored.js +81 -0
  88. package/src/models/refactoring-plan.js +2 -663
  89. package/src/monitoring/alert-system.js +4 -45
  90. package/src/monitoring/continuous-scan-notifications.js +37 -191
  91. package/src/monitoring/notification-handlers/base-handler.js +58 -0
  92. package/src/monitoring/notification-handlers/error-handler.js +36 -0
  93. package/src/monitoring/notification-handlers/index.js +21 -0
  94. package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
  95. package/src/monitoring/notification-handlers/progress-handler.js +48 -0
  96. package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
  97. package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
  98. package/src/provider-registry.js +8 -0
  99. package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
  100. package/src/refactoring/boundary/boundary-detector.js +26 -596
  101. package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
  102. package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
  103. package/src/refactoring/boundary/detectors/class-detector.js +247 -0
  104. package/src/refactoring/boundary/detectors/config-detector.js +270 -0
  105. package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
  106. package/src/refactoring/boundary/detectors/function-detector.js +248 -0
  107. package/src/refactoring/boundary/detectors/module-detector.js +249 -0
  108. package/src/refactoring/boundary/detectors/object-detector.js +247 -0
  109. package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
  110. package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
  111. package/src/refactoring/circular-dependency-resolver-original.js +16 -76
  112. package/src/refactoring/code-mover-refactored.js +309 -0
  113. package/src/refactoring/code-mover.js +48 -355
  114. package/src/refactoring/execution-status.js +18 -0
  115. package/src/refactoring/execution-strategies.js +172 -0
  116. package/src/refactoring/file-splitter-core.js +568 -0
  117. package/src/refactoring/file-splitter-types.js +136 -0
  118. package/src/refactoring/file-splitter.js +2 -682
  119. package/src/refactoring/functionality-validator.js +11 -51
  120. package/src/refactoring/import-manager-refactored.js +385 -0
  121. package/src/refactoring/import-manager.js +112 -487
  122. package/src/refactoring/import-models.js +189 -0
  123. package/src/refactoring/import-parser.js +306 -0
  124. package/src/refactoring/move-executor.js +431 -0
  125. package/src/refactoring/move-utils.js +368 -0
  126. package/src/refactoring/operation-executor.js +76 -0
  127. package/src/refactoring/plan-creator.js +36 -0
  128. package/src/refactoring/plan-executor.js +143 -0
  129. package/src/refactoring/plan-validator.js +68 -0
  130. package/src/refactoring/refactoring-executor-result.js +70 -0
  131. package/src/refactoring/refactoring-executor.js +34 -569
  132. package/src/refactoring/refactoring-operation.js +94 -0
  133. package/src/refactoring/refactoring-plan.js +69 -0
  134. package/src/refactoring/refactoring-rollback.js +22 -527
  135. package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
  136. package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
  137. package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
  138. package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
  139. package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
  140. package/src/refactoring/test-validator.js +32 -448
  141. package/src/refactoring/validation/baseline-runner.js +71 -0
  142. package/src/refactoring/validation/report-generator.js +136 -0
  143. package/src/refactoring/validation/result-comparator.js +92 -0
  144. package/src/refactoring/validation/test-suite.js +59 -0
  145. package/src/refactoring/validation/test-validation-result.js +83 -0
  146. package/src/refactoring/validation/validation-runner.js +95 -0
  147. package/src/refactoring/validation/validation-status.js +18 -0
  148. package/src/rui/commands/AgentCommandParser.js +60 -369
  149. package/src/rui/commands/AgentResponseFormatter.js +7 -47
  150. package/src/rui/commands/parsers/CommandMapper.js +148 -0
  151. package/src/rui/commands/parsers/CommandValidator.js +228 -0
  152. package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
  153. package/src/rui/commands/parsers/TokenParser.js +69 -0
  154. package/src/rui/commands/parsers/tokenizer.js +153 -0
  155. package/src/utils/current-requirement-operations.js +50 -1
  156. package/src/utils/report-generator.js +18 -514
  157. package/src/utils/report-generators/analysis-generator.js +115 -0
  158. package/src/utils/report-generators/base-generator.js +141 -0
  159. package/src/utils/report-generators/compliance-generator.js +41 -0
  160. package/src/utils/report-generators/format-handlers.js +185 -0
  161. package/src/utils/report-generators/refactoring-generator.js +46 -0
  162. package/src/utils/report-generators/validation-generator.js +63 -0
  163. package/src/utils/requirement-enable-disable.js +265 -0
  164. package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
  165. package/src/utils/requirement-helpers/requirement-mover.js +88 -1
  166. package/src/utils/requirement-helpers.js +5 -2
  167. package/src/utils/smoke-test-cli.js +45 -8
  168. package/src/utils/specification-enable-disable.js +122 -0
  169. package/src/utils/specification-helpers.js +30 -4
  170. package/src/utils/specification-migration.js +5 -5
  171. package/src/utils/test-comparator.js +118 -0
  172. package/src/utils/test-config.js +54 -0
  173. package/src/utils/test-executor.js +133 -0
  174. package/src/utils/test-parser.js +215 -0
  175. package/src/utils/test-runner-baseline.js +63 -0
  176. package/src/utils/test-runner-core.js +98 -0
  177. package/src/utils/test-runner-report.js +39 -0
  178. package/src/utils/test-runner-validation.js +71 -0
  179. package/src/utils/test-runner.js +11 -535
  180. package/src/validation/comparison-analyzer.js +333 -0
  181. package/src/validation/compliance-reporter-new.js +282 -0
  182. package/src/validation/compliance-reporter-refactored.js +344 -0
  183. package/src/validation/compliance-reporter.js +278 -591
  184. package/src/validation/compliance-utils.js +278 -0
  185. package/src/validation/html-generator.js +446 -0
  186. package/src/validation/metrics/category-calculator.js +137 -0
  187. package/src/validation/metrics/metrics-helpers.js +155 -0
  188. package/src/validation/metrics/overview-calculator.js +85 -0
  189. package/src/validation/metrics/overview-metrics.js +41 -0
  190. package/src/validation/metrics/quality-calculator.js +166 -0
  191. package/src/validation/metrics/size-calculator.js +69 -0
  192. package/src/validation/metrics-calculator.js +27 -551
@@ -7,24 +7,16 @@
7
7
 
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
+ const BoundaryScanner = require('./boundary-scanner');
11
+ const {
12
+ BOUNDARY_TYPES,
13
+ groupBoundariesByType,
14
+ findBoundaryRelationships,
15
+ generateBoundaryRecommendations
16
+ } = require('./boundary-utils');
10
17
 
11
18
  /**
12
- * Boundary types
13
- */
14
- const BOUNDARY_TYPES = {
15
- FUNCTION: 'function',
16
- CLASS: 'class',
17
- MODULE: 'module',
18
- BLOCK: 'block',
19
- IMPORT: 'import',
20
- EXPORT: 'export',
21
- COMMENT: 'comment',
22
- UTILITY: 'utility',
23
- CONSTANT: 'constant'
24
- };
25
-
26
- /**
27
- * Boundary detection result class
19
+ * Boundary Detection Result class
28
20
  */
29
21
  class BoundaryDetectionResult {
30
22
  constructor(filePath) {
@@ -49,664 +41,269 @@ class BoundaryDetectionResult {
49
41
  this.metadata.byType[boundary.type]++;
50
42
  }
51
43
 
52
- getBoundariesByType(type) {
53
- return this.boundaries.filter(b => b.type === type);
54
- }
55
-
56
- getLargestBoundaries(count = 5) {
57
- return this.boundaries
58
- .sort((a, b) => b.lineCount - a.lineCount)
59
- .slice(0, count);
60
- }
61
-
62
- getRefactoringCandidates() {
63
- return this.boundaries.filter(b =>
64
- b.lineCount > 50 && // Reasonable size
65
- (b.type === BOUNDARY_TYPES.FUNCTION || b.type === BOUNDARY_TYPES.CLASS)
66
- );
67
- }
68
- }
69
-
70
- /**
71
- * Boundary class
72
- */
73
- class Boundary {
74
- constructor(type, startLine, endLine, name = '') {
75
- this.type = type;
76
- this.startLine = startLine;
77
- this.endLine = endLine;
78
- this.name = name;
79
- this.lineCount = endLine - startLine + 1;
80
- this.complexity = 0;
81
- this.dependencies = [];
82
- this.exports = [];
83
- this.comments = [];
84
- this.metadata = {};
85
- }
86
-
87
- addDependency(dependency) {
88
- this.dependencies.push(dependency);
89
- }
90
-
91
- addExport(exportName) {
92
- this.exports.push(exportName);
93
- }
94
-
95
- addComment(comment) {
96
- this.comments.push(comment);
97
- }
98
-
99
- setComplexity(complexity) {
100
- this.complexity = complexity;
101
- }
102
-
103
- canExtract() {
104
- // Basic criteria for extraction
105
- return this.lineCount >= 10 &&
106
- this.name !== '' &&
107
- (this.type === BOUNDARY_TYPES.FUNCTION || this.type === BOUNDARY_TYPES.CLASS);
44
+ getSummary() {
45
+ return {
46
+ filePath: this.filePath,
47
+ totalBoundaries: this.metadata.totalBoundaries,
48
+ byType: this.metadata.byType,
49
+ averageSize: this.boundaries.length > 0 ?
50
+ this.boundaries.reduce((sum, b) => sum + b.size, 0) / this.boundaries.length : 0,
51
+ complexity: this.metadata.complexity,
52
+ cohesion: this.metadata.cohesion,
53
+ coupling: this.metadata.coupling
54
+ };
108
55
  }
109
56
  }
110
57
 
111
58
  /**
112
- * Logical boundary detector class
59
+ * Boundary Detector class
113
60
  */
114
61
  class BoundaryDetector {
115
62
  constructor(options = {}) {
116
63
  this.options = {
117
- minFunctionSize: 5,
118
- minClassSize: 10,
119
- detectComments: true,
120
- detectUtilities: true,
64
+ includeComments: options.includeComments !== false,
65
+ includeImports: options.includeImports !== false,
66
+ includeExports: options.includeExports !== false,
67
+ minBoundarySize: options.minBoundarySize || 5,
68
+ analysisDepth: options.analysisDepth || 'standard',
121
69
  ...options
122
70
  };
71
+
72
+ this.scanner = new BoundaryScanner(this.options);
123
73
  }
124
74
 
125
- /**
126
- * Detect boundaries in a file
127
- */
128
75
  async detectBoundaries(filePath) {
129
- const result = new BoundaryDetectionResult(filePath);
130
-
131
76
  try {
132
- const content = fs.readFileSync(filePath, 'utf8');
133
- const lines = content.split('\n');
77
+ const content = await fs.promises.readFile(filePath, 'utf8');
78
+ const scanResult = this.scanner.scanFile(content, filePath);
134
79
 
135
- // Detect based on file type
136
- const ext = path.extname(filePath).toLowerCase();
80
+ const result = new BoundaryDetectionResult(filePath);
137
81
 
138
- if (['.js', '.jsx', '.ts', '.tsx'].includes(ext)) {
139
- await this.detectJavaScriptBoundaries(content, lines, result);
140
- } else if (ext === '.md') {
141
- await this.detectMarkdownBoundaries(content, lines, result);
142
- } else {
143
- await this.detectTextBoundaries(content, lines, result);
144
- }
145
-
146
- // Analyze overall structure
147
- this.analyzeStructure(result);
148
-
149
- } catch (error) {
150
- console.error(`Error detecting boundaries in ${filePath}: ${error.message}`);
151
- }
152
-
153
- return result;
154
- }
155
-
156
- /**
157
- * Detect boundaries in JavaScript/TypeScript files
158
- */
159
- async detectJavaScriptBoundaries(content, lines, result) {
160
- // Detect imports
161
- this.detectImports(lines, result);
162
-
163
- // Detect exports
164
- this.detectExports(lines, result);
165
-
166
- // Detect functions
167
- this.detectFunctions(lines, result);
168
-
169
- // Detect classes
170
- this.detectClasses(lines, result);
171
-
172
- // Detect utility sections
173
- if (this.options.detectUtilities) {
174
- this.detectUtilities(lines, result);
175
- }
176
-
177
- // Detect comment blocks
178
- if (this.options.detectComments) {
179
- this.detectCommentBlocks(lines, result);
180
- }
181
- }
182
-
183
- /**
184
- * Detect import statements
185
- */
186
- detectImports(lines, result) {
187
- let currentImport = null;
188
-
189
- for (let i = 0; i < lines.length; i++) {
190
- const line = lines[i].trim();
191
-
192
- if (line.startsWith('import ')) {
193
- if (currentImport) {
194
- // Close previous import
195
- currentImport.endLine = i - 1;
196
- currentImport.lineCount = currentImport.endLine - currentImport.startLine + 1;
197
- result.addBoundary(currentImport);
198
- }
199
-
200
- // Start new import
201
- const match = line.match(/import\s+(?:.*?\s+from\s+)?['"]([^'"]+)['"]/);
202
- currentImport = new Boundary(
203
- BOUNDARY_TYPES.IMPORT,
204
- i,
205
- i,
206
- match ? match[1] : 'import'
207
- );
208
- } else if (currentImport && (line.startsWith('from ') || line.endsWith(';'))) {
209
- // End of import statement
210
- currentImport.endLine = i;
211
- currentImport.lineCount = currentImport.endLine - currentImport.startLine + 1;
212
- result.addBoundary(currentImport);
213
- currentImport = null;
214
- }
215
- }
216
-
217
- // Handle unclosed import
218
- if (currentImport) {
219
- currentImport.endLine = lines.length - 1;
220
- currentImport.lineCount = currentImport.endLine - currentImport.startLine + 1;
221
- result.addBoundary(currentImport);
222
- }
223
- }
224
-
225
- /**
226
- * Detect export statements
227
- */
228
- detectExports(lines, result) {
229
- for (let i = 0; i < lines.length; i++) {
230
- const line = lines[i].trim();
231
-
232
- if (line.startsWith('export ')) {
233
- const match = line.match(/export\s+(?:default\s+)?(?:function|class|const|let|var)\s+(\w+)/);
234
- const name = match ? match[1] : 'export';
235
-
236
- const boundary = new Boundary(
237
- BOUNDARY_TYPES.EXPORT,
238
- i,
239
- i,
240
- name
241
- );
242
-
82
+ scanResult.boundaries.forEach(boundary => {
243
83
  result.addBoundary(boundary);
244
- }
245
- }
246
- }
247
-
248
- /**
249
- * Detect function boundaries
250
- */
251
- detectFunctions(lines, result) {
252
- for (let i = 0; i < lines.length; i++) {
253
- const line = lines[i].trim();
84
+ });
254
85
 
255
- // Function declarations
256
- const funcMatch = line.match(/^(?:async\s+)?function\s+(\w+)/);
257
- if (funcMatch) {
258
- const boundary = this.findFunctionBoundary(lines, i, funcMatch[1], 'declaration');
259
- if (boundary) result.addBoundary(boundary);
260
- continue;
261
- }
86
+ const relationships = findBoundaryRelationships(result.boundaries);
262
87
 
263
- // Function expressions
264
- const exprMatch = line.match(/^(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function/);
265
- if (exprMatch) {
266
- const boundary = this.findFunctionBoundary(lines, i, exprMatch[1], 'expression');
267
- if (boundary) result.addBoundary(boundary);
268
- continue;
269
- }
88
+ result.metadata.complexity = this.calculateOverallComplexity(result.boundaries);
89
+ result.metadata.cohesion = this.calculateOverallCohesion(result.boundaries);
90
+ result.metadata.coupling = this.calculateOverallCoupling(result.boundaries, relationships);
270
91
 
271
- // Arrow functions
272
- const arrowMatch = line.match(/^(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(/);
273
- if (arrowMatch) {
274
- const boundary = this.findArrowFunctionBoundary(lines, i, arrowMatch[1]);
275
- if (boundary) result.addBoundary(boundary);
276
- continue;
277
- }
92
+ result.metadata.scanMetadata = scanResult.metadata;
93
+ result.metadata.relationships = relationships;
278
94
 
279
- // Method definitions in classes
280
- const methodMatch = line.match(/^(\w+)\s*\(/);
281
- if (methodMatch && this.isInClass(lines, i)) {
282
- const boundary = this.findMethodBoundary(lines, i, methodMatch[1]);
283
- if (boundary) result.addBoundary(boundary);
284
- }
95
+ return result;
96
+
97
+ } catch (error) {
98
+ const result = new BoundaryDetectionResult(filePath);
99
+ result.metadata.error = error.message;
100
+ return result;
285
101
  }
286
102
  }
287
103
 
288
- /**
289
- * Find function boundary
290
- */
291
- findFunctionBoundary(lines, startLine, name, type) {
292
- let braceCount = 0;
293
- let foundBrace = false;
104
+ async detectBoundariesInFiles(filePaths) {
105
+ const results = [];
294
106
 
295
- for (let i = startLine; i < lines.length; i++) {
296
- const line = lines[i];
297
-
298
- for (let j = 0; j < line.length; j++) {
299
- if (line[j] === '{') {
300
- braceCount++;
301
- foundBrace = true;
302
- } else if (line[j] === '}') {
303
- braceCount--;
304
- if (foundBrace && braceCount === 0) {
305
- const boundary = new Boundary(
306
- BOUNDARY_TYPES.FUNCTION,
307
- startLine,
308
- i,
309
- name
310
- );
311
- boundary.metadata.type = type;
312
- return boundary;
313
- }
314
- }
315
- }
107
+ for (const filePath of filePaths) {
108
+ const result = await this.detectBoundaries(filePath);
109
+ results.push(result);
316
110
  }
317
111
 
318
- return null;
112
+ return results;
319
113
  }
320
114
 
321
- /**
322
- * Find arrow function boundary
323
- */
324
- findArrowFunctionBoundary(lines, startLine, name) {
325
- let braceCount = 0;
326
- let foundBrace = false;
327
- let foundArrow = false;
328
-
329
- for (let i = startLine; i < lines.length; i++) {
330
- const line = lines[i];
331
-
332
- if (line.includes('=>')) {
333
- foundArrow = true;
334
- }
335
-
336
- for (let j = 0; j < line.length; j++) {
337
- if (line[j] === '{') {
338
- braceCount++;
339
- foundBrace = true;
340
- } else if (line[j] === '}') {
341
- braceCount--;
342
- if (foundBrace && foundArrow && braceCount === 0) {
343
- const boundary = new Boundary(
344
- BOUNDARY_TYPES.FUNCTION,
345
- startLine,
346
- i,
347
- name
348
- );
349
- boundary.metadata.type = 'arrow';
350
- return boundary;
351
- }
352
- }
353
- }
354
- }
115
+ async detectBoundariesInDirectory(dirPath, options = {}) {
116
+ const scanOptions = {
117
+ recursive: options.recursive !== false,
118
+ extensions: options.extensions || ['.js', '.ts', '.jsx', '.tsx'],
119
+ exclude: options.exclude || ['node_modules', '.git', 'dist'],
120
+ ...options
121
+ };
355
122
 
356
- return null;
123
+ const filePaths = await this.getFilePaths(dirPath, scanOptions);
124
+ return this.detectBoundariesInFiles(filePaths);
357
125
  }
358
126
 
359
- /**
360
- * Find method boundary
361
- */
362
- findMethodBoundary(lines, startLine, name) {
363
- let braceCount = 0;
364
- let foundBrace = false;
127
+ async getFilePaths(dirPath, options) {
128
+ const filePaths = [];
365
129
 
366
- for (let i = startLine; i < lines.length; i++) {
367
- const line = lines[i];
368
-
369
- for (let j = 0; j < line.length; j++) {
370
- if (line[j] === '{') {
371
- braceCount++;
372
- foundBrace = true;
373
- } else if (line[j] === '}') {
374
- braceCount--;
375
- if (foundBrace && braceCount === 0) {
376
- const boundary = new Boundary(
377
- BOUNDARY_TYPES.FUNCTION,
378
- startLine,
379
- i,
380
- name
381
- );
382
- boundary.metadata.type = 'method';
383
- return boundary;
384
- }
385
- }
130
+ const scanDirectory = async (currentPath, depth = 0) => {
131
+ if (depth > (options.maxDepth || 10)) {
132
+ return;
386
133
  }
387
- }
388
-
389
- return null;
390
- }
391
-
392
- /**
393
- * Detect class boundaries
394
- */
395
- detectClasses(lines, result) {
396
- for (let i = 0; i < lines.length; i++) {
397
- const line = lines[i].trim();
398
134
 
399
- const classMatch = line.match(/^class\s+(\w+)/);
400
- if (classMatch) {
401
- const boundary = this.findClassBoundary(lines, i, classMatch[1]);
402
- if (boundary) result.addBoundary(boundary);
403
- }
404
- }
405
- }
406
-
407
- /**
408
- * Find class boundary
409
- */
410
- findClassBoundary(lines, startLine, name) {
411
- let braceCount = 0;
412
- let foundBrace = false;
413
-
414
- for (let i = startLine; i < lines.length; i++) {
415
- const line = lines[i];
135
+ const entries = await fs.promises.readdir(currentPath, { withFileTypes: true });
416
136
 
417
- for (let j = 0; j < line.length; j++) {
418
- if (line[j] === '{') {
419
- braceCount++;
420
- foundBrace = true;
421
- } else if (line[j] === '}') {
422
- braceCount--;
423
- if (foundBrace && braceCount === 0) {
424
- return new Boundary(
425
- BOUNDARY_TYPES.CLASS,
426
- startLine,
427
- i,
428
- name
429
- );
137
+ for (const entry of entries) {
138
+ const fullPath = path.join(currentPath, entry.name);
139
+
140
+ if (entry.isDirectory()) {
141
+ if (options.exclude && !options.exclude.some(exclude => entry.name.includes(exclude))) {
142
+ if (options.recursive) {
143
+ await scanDirectory(fullPath, depth + 1);
144
+ }
145
+ }
146
+ } else if (entry.isFile()) {
147
+ const ext = path.extname(entry.name);
148
+ if (options.extensions.includes(ext)) {
149
+ filePaths.push(fullPath);
430
150
  }
431
151
  }
432
152
  }
433
- }
434
-
435
- return null;
436
- }
437
-
438
- /**
439
- * Detect utility sections
440
- */
441
- detectUtilities(lines, result) {
442
- // Look for sections with utility functions
443
- let utilityStart = null;
444
- let utilityName = null;
445
-
446
- for (let i = 0; i < lines.length; i++) {
447
- const line = lines[i].trim();
448
-
449
- // Detect utility section comments
450
- if (line.startsWith('//') && (line.includes('utility') || line.includes('helper'))) {
451
- if (utilityStart) {
452
- // Close previous utility section
453
- const boundary = new Boundary(
454
- BOUNDARY_TYPES.UTILITY,
455
- utilityStart,
456
- i - 1,
457
- utilityName || 'utilities'
458
- );
459
- result.addBoundary(boundary);
460
- }
461
-
462
- utilityStart = i;
463
- utilityName = line.replace('//', '').trim();
464
- }
465
- }
466
-
467
- // Close final utility section
468
- if (utilityStart) {
469
- const boundary = new Boundary(
470
- BOUNDARY_TYPES.UTILITY,
471
- utilityStart,
472
- lines.length - 1,
473
- utilityName || 'utilities'
474
- );
475
- result.addBoundary(boundary);
476
- }
477
- }
478
-
479
- /**
480
- * Detect comment blocks
481
- */
482
- detectCommentBlocks(lines, result) {
483
- let commentStart = null;
484
- let commentType = null;
153
+ };
485
154
 
486
- for (let i = 0; i < lines.length; i++) {
487
- const line = lines[i].trim();
488
-
489
- if (line.startsWith('/*')) {
490
- commentStart = i;
491
- commentType = 'block';
492
- } else if (line.startsWith('//')) {
493
- // Single line comment
494
- const boundary = new Boundary(
495
- BOUNDARY_TYPES.COMMENT,
496
- i,
497
- i,
498
- 'single-line-comment'
499
- );
500
- result.addBoundary(boundary);
501
- } else if (commentStart && line.endsWith('*/')) {
502
- // End of block comment
503
- const boundary = new Boundary(
504
- BOUNDARY_TYPES.COMMENT,
505
- commentStart,
506
- i,
507
- 'block-comment'
508
- );
509
- result.addBoundary(boundary);
510
- commentStart = null;
511
- commentType = null;
512
- }
513
- }
514
- }
515
-
516
- /**
517
- * Detect boundaries in Markdown files
518
- */
519
- async detectMarkdownBoundaries(content, lines, result) {
520
- for (let i = 0; i < lines.length; i++) {
521
- const line = lines[i];
522
-
523
- // Headers
524
- const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
525
- if (headerMatch) {
526
- const level = headerMatch[1].length;
527
- const title = headerMatch[2];
528
-
529
- const boundary = new Boundary(
530
- BOUNDARY_TYPES.MODULE,
531
- i,
532
- i,
533
- title
534
- );
535
- boundary.metadata.level = level;
536
- result.addBoundary(boundary);
537
- }
538
-
539
- // Code blocks
540
- if (line.startsWith('```')) {
541
- const boundary = new Boundary(
542
- BOUNDARY_TYPES.BLOCK,
543
- i,
544
- i,
545
- 'code-block'
546
- );
547
- result.addBoundary(boundary);
548
- }
549
- }
155
+ await scanDirectory(dirPath);
156
+ return filePaths;
550
157
  }
551
158
 
552
- /**
553
- * Detect boundaries in text files
554
- */
555
- async detectTextBoundaries(content, lines, result) {
556
- // Simple paragraph detection
557
- let paragraphStart = null;
159
+ calculateOverallComplexity(boundaries) {
160
+ if (boundaries.length === 0) return 'unknown';
558
161
 
559
- for (let i = 0; i < lines.length; i++) {
560
- const line = lines[i].trim();
561
-
562
- if (line !== '') {
563
- if (paragraphStart === null) {
564
- paragraphStart = i;
565
- }
566
- } else {
567
- if (paragraphStart !== null) {
568
- const boundary = new Boundary(
569
- BOUNDARY_TYPES.BLOCK,
570
- paragraphStart,
571
- i - 1,
572
- 'paragraph'
573
- );
574
- result.addBoundary(boundary);
575
- paragraphStart = null;
576
- }
577
- }
578
- }
162
+ const complexities = boundaries.map(b => b.complexity || 1);
163
+ const avgComplexity = complexities.reduce((sum, c) => sum + c, 0) / complexities.length;
579
164
 
580
- // Handle final paragraph
581
- if (paragraphStart !== null) {
582
- const boundary = new Boundary(
583
- BOUNDARY_TYPES.BLOCK,
584
- paragraphStart,
585
- lines.length - 1,
586
- 'paragraph'
587
- );
588
- result.addBoundary(boundary);
589
- }
165
+ if (avgComplexity > 7) return 'very_high';
166
+ if (avgComplexity > 5) return 'high';
167
+ if (avgComplexity > 3) return 'medium';
168
+ if (avgComplexity > 2) return 'low';
169
+ return 'very_low';
590
170
  }
591
171
 
592
- /**
593
- * Check if line is inside a class
594
- */
595
- isInClass(lines, lineIndex) {
596
- // Simple check - look backwards for class declaration
597
- for (let i = lineIndex - 1; i >= 0; i--) {
598
- const line = lines[i].trim();
599
- if (line.startsWith('class ')) {
600
- return true;
601
- }
602
- if (line.startsWith('function ') || line.startsWith('const ')) {
603
- return false;
172
+ calculateOverallCohesion(boundaries) {
173
+ if (boundaries.length === 0) return 'unknown';
174
+
175
+ const cohesions = boundaries.map(b => b.cohesion || 'medium');
176
+ const cohesionScores = cohesions.map(c => {
177
+ switch (c) {
178
+ case 'very_low': return 1;
179
+ case 'low': return 2;
180
+ case 'medium': return 3;
181
+ case 'high': return 4;
182
+ case 'very_high': return 5;
183
+ default: return 3;
604
184
  }
605
- }
606
- return false;
607
- }
608
-
609
- /**
610
- * Analyze overall structure
611
- */
612
- analyzeStructure(result) {
613
- // Calculate complexity metrics
614
- const functions = result.getBoundariesByType(BOUNDARY_TYPES.FUNCTION);
615
- const classes = result.getBoundariesByType(BOUNDARY_TYPES.CLASS);
616
-
617
- let totalComplexity = 0;
618
- let totalSize = 0;
185
+ });
619
186
 
620
- for (const boundary of [...functions, ...classes]) {
621
- // Simple complexity estimation based on size
622
- boundary.complexity = Math.min(10, Math.ceil(boundary.lineCount / 20));
623
- totalComplexity += boundary.complexity;
624
- totalSize += boundary.lineCount;
625
- }
187
+ const avgCohesion = cohesionScores.reduce((sum, c) => sum + c, 0) / cohesionScores.length;
626
188
 
627
- result.metadata.complexity = totalComplexity > 20 ? 'high' :
628
- totalComplexity > 10 ? 'medium' : 'low';
629
-
630
- result.metadata.cohesion = this.assessCohesion(result);
631
- result.metadata.coupling = this.assessCoupling(result);
189
+ if (avgCohesion > 4.5) return 'very_high';
190
+ if (avgCohesion > 3.5) return 'high';
191
+ if (avgCohesion > 2.5) return 'medium';
192
+ if (avgCohesion > 1.5) return 'low';
193
+ return 'very_low';
632
194
  }
633
195
 
634
- /**
635
- * Assess cohesion
636
- */
637
- assessCohesion(result) {
638
- // Simple cohesion assessment based on boundary distribution
639
- const functions = result.getBoundariesByType(BOUNDARY_TYPES.FUNCTION);
640
- const avgFunctionSize = functions.length > 0 ?
641
- functions.reduce((sum, f) => sum + f.lineCount, 0) / functions.length : 0;
196
+ calculateOverallCoupling(boundaries, relationships) {
197
+ if (boundaries.length === 0) return 'unknown';
642
198
 
643
- if (avgFunctionSize > 100) return 'low';
644
- if (avgFunctionSize > 50) return 'medium';
645
- return 'high';
646
- }
647
-
648
- /**
649
- * Assess coupling
650
- */
651
- assessCoupling(result) {
652
- // Simple coupling assessment based on imports
653
- const imports = result.getBoundariesByType(BOUNDARY_TYPES.IMPORT);
654
-
655
- if (imports.length > 10) return 'high';
656
- if (imports.length > 5) return 'medium';
657
- return 'low';
199
+ const couplingScores = boundaries.map(b => {
200
+ const boundaryRelationships = relationships.filter(r => r.source === b.name);
201
+ if (boundaryRelationships.length === 0) return 5;
202
+
203
+ const avgStrength = boundaryRelationships.reduce((sum, r) => sum + r.strength, 0) / boundaryRelationships.length;
204
+
205
+ if (avgStrength > 4) return 1;
206
+ if (avgStrength > 3) return 2;
207
+ if (avgStrength > 2) return 3;
208
+ if (avgStrength > 1) return 4;
209
+ return 5;
210
+ });
211
+
212
+ const avgCoupling = couplingScores.reduce((sum, c) => sum + c, 0) / couplingScores.length;
213
+
214
+ if (avgCoupling > 4.5) return 'very_low';
215
+ if (avgCoupling > 3.5) return 'low';
216
+ if (avgCoupling > 2.5) return 'medium';
217
+ if (avgCoupling > 1.5) return 'high';
218
+ return 'very_high';
658
219
  }
659
220
 
660
- /**
661
- * Get refactoring recommendations
662
- */
663
- getRefactoringRecommendations(result) {
221
+ generateRefactoringRecommendations(result) {
664
222
  const recommendations = [];
665
223
 
666
- // Large functions
667
- const largeFunctions = result.getBoundariesByType(BOUNDARY_TYPES.FUNCTION)
668
- .filter(f => f.lineCount > 50);
224
+ const boundaryRecommendations = generateBoundaryRecommendations(result.boundaries);
225
+ recommendations.push(...boundaryRecommendations);
669
226
 
670
- if (largeFunctions.length > 0) {
227
+ if (result.metadata.totalBoundaries > 20) {
671
228
  recommendations.push({
672
- type: 'extract_functions',
229
+ type: 'file_structure',
673
230
  priority: 'high',
674
- description: `${largeFunctions.length} functions are too large and should be split`,
675
- boundaries: largeFunctions.map(f => ({ name: f.name, lineCount: f.lineCount }))
231
+ message: 'File has too many boundaries (>20)',
232
+ action: 'split_into_modules'
676
233
  });
677
234
  }
678
235
 
679
- // Large classes
680
- const largeClasses = result.getBoundariesByType(BOUNDARY_TYPES.CLASS)
681
- .filter(c => c.lineCount > 200);
682
-
683
- if (largeClasses.length > 0) {
236
+ if (result.metadata.complexity === 'very_high') {
684
237
  recommendations.push({
685
- type: 'split_classes',
686
- priority: 'medium',
687
- description: `${largeClasses.length} classes are too large and should be split`,
688
- boundaries: largeClasses.map(c => ({ name: c.name, lineCount: c.lineCount }))
238
+ type: 'complexity',
239
+ priority: 'high',
240
+ message: 'File has very high complexity',
241
+ action: 'reduce_complexity'
689
242
  });
690
243
  }
691
244
 
692
- // Utility extraction
693
- const utilities = result.getBoundariesByType(BOUNDARY_TYPES.UTILITY);
694
- if (utilities.length === 0 && result.metadata.totalBoundaries > 5) {
245
+ if (result.metadata.cohesion === 'very_low') {
695
246
  recommendations.push({
696
- type: 'extract_utilities',
697
- priority: 'low',
698
- description: 'Consider extracting utility functions to separate modules',
699
- boundaries: []
247
+ type: 'cohesion',
248
+ priority: 'medium',
249
+ message: 'File has very low cohesion',
250
+ action: 'improve_cohesion'
700
251
  });
701
252
  }
702
253
 
703
254
  return recommendations;
704
255
  }
256
+
257
+ async exportResults(result, outputPath) {
258
+ const exportData = {
259
+ filePath: result.filePath,
260
+ timestamp: new Date().toISOString(),
261
+ summary: result.getSummary(),
262
+ boundaries: result.boundaries,
263
+ metadata: result.metadata,
264
+ recommendations: this.generateRefactoringRecommendations(result)
265
+ };
266
+
267
+ await fs.promises.writeFile(outputPath, JSON.stringify(exportData, null, 2), 'utf8');
268
+ }
269
+
270
+ getDetectorInfo() {
271
+ return {
272
+ supportedTypes: Object.values(BOUNDARY_TYPES),
273
+ defaultOptions: this.options,
274
+ features: [
275
+ 'boundary detection',
276
+ 'complexity analysis',
277
+ 'cohesion calculation',
278
+ 'coupling analysis',
279
+ 'refactoring recommendations',
280
+ 'batch processing'
281
+ ],
282
+ version: '1.0.0'
283
+ };
284
+ }
285
+
286
+ static createDefault(config = {}) {
287
+ return new BoundaryDetector({
288
+ includeComments: true,
289
+ includeImports: true,
290
+ includeExports: true,
291
+ minBoundarySize: 5,
292
+ analysisDepth: 'standard',
293
+ ...config
294
+ });
295
+ }
296
+
297
+ static createForRefactoring(config = {}) {
298
+ return new BoundaryDetector({
299
+ includeComments: false,
300
+ includeImports: true,
301
+ includeExports: true,
302
+ minBoundarySize: 10,
303
+ analysisDepth: 'deep',
304
+ ...config
305
+ });
306
+ }
705
307
  }
706
308
 
707
- module.exports = {
708
- BoundaryDetector,
709
- BoundaryDetectionResult,
710
- Boundary,
711
- BOUNDARY_TYPES
712
- };
309
+ module.exports = BoundaryDetector;