vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,330 @@
1
+ /**
2
+ * Boundary Extraction Strategies
3
+ *
4
+ * Contains methods for extracting different types of boundaries from code.
5
+ */
6
+
7
+ const { BOUNDARY_TYPES } = require('./boundary-types');
8
+ const ModuleBoundary = require('./module-boundary');
9
+
10
+ /**
11
+ * Boundary extraction strategies class
12
+ */
13
+ class BoundaryExtractionStrategies {
14
+ /**
15
+ * Extract function boundaries
16
+ */
17
+ static async extractFunctionBoundaries(lines, result) {
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i].trim();
20
+
21
+ // Function declarations
22
+ const funcMatch = line.match(/^(?:async\s+)?function\s+(\w+)/);
23
+ if (funcMatch) {
24
+ const boundary = BoundaryExtractionStrategies.findFunctionBoundary(lines, i, funcMatch[1], result.filePath);
25
+ if (boundary) {
26
+ result.addBoundary(boundary);
27
+ }
28
+ continue;
29
+ }
30
+
31
+ // Function expressions
32
+ const exprMatch = line.match(/^(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function/);
33
+ if (exprMatch) {
34
+ const boundary = BoundaryExtractionStrategies.findFunctionBoundary(lines, i, exprMatch[1], result.filePath);
35
+ if (boundary) {
36
+ result.addBoundary(boundary);
37
+ }
38
+ continue;
39
+ }
40
+
41
+ // Arrow functions
42
+ const arrowMatch = line.match(/^(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(/);
43
+ if (arrowMatch) {
44
+ const boundary = BoundaryExtractionStrategies.findArrowFunctionBoundary(lines, i, arrowMatch[1], result.filePath);
45
+ if (boundary) {
46
+ result.addBoundary(boundary);
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Find function boundary
54
+ */
55
+ static findFunctionBoundary(lines, startLine, name, filePath) {
56
+ let braceCount = 0;
57
+ let foundBrace = false;
58
+
59
+ for (let i = startLine; i < lines.length; i++) {
60
+ const line = lines[i];
61
+
62
+ for (let j = 0; j < line.length; j++) {
63
+ if (line[j] === '{') {
64
+ braceCount++;
65
+ foundBrace = true;
66
+ } else if (line[j] === '}') {
67
+ braceCount--;
68
+ if (foundBrace && braceCount === 0) {
69
+ const boundary = new ModuleBoundary(
70
+ BOUNDARY_TYPES.FUNCTION,
71
+ name,
72
+ startLine + 1,
73
+ i + 1,
74
+ filePath
75
+ );
76
+ return boundary;
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ return null;
83
+ }
84
+
85
+ /**
86
+ * Find arrow function boundary
87
+ */
88
+ static findArrowFunctionBoundary(lines, startLine, name, filePath) {
89
+ let braceCount = 0;
90
+ let foundBrace = false;
91
+ let foundArrow = false;
92
+
93
+ for (let i = startLine; i < lines.length; i++) {
94
+ const line = lines[i];
95
+
96
+ if (line.includes('=>')) {
97
+ foundArrow = true;
98
+ }
99
+
100
+ for (let j = 0; j < line.length; j++) {
101
+ if (line[j] === '{') {
102
+ braceCount++;
103
+ foundBrace = true;
104
+ } else if (line[j] === '}') {
105
+ braceCount--;
106
+ if (foundBrace && foundArrow && braceCount === 0) {
107
+ const boundary = new ModuleBoundary(
108
+ BOUNDARY_TYPES.FUNCTION,
109
+ name,
110
+ startLine + 1,
111
+ i + 1,
112
+ filePath
113
+ );
114
+ return boundary;
115
+ }
116
+ }
117
+ }
118
+ }
119
+
120
+ return null;
121
+ }
122
+
123
+ /**
124
+ * Extract class boundaries
125
+ */
126
+ static async extractClassBoundaries(lines, result) {
127
+ for (let i = 0; i < lines.length; i++) {
128
+ const line = lines[i].trim();
129
+
130
+ const classMatch = line.match(/^class\s+(\w+)/);
131
+ if (classMatch) {
132
+ const boundary = BoundaryExtractionStrategies.findClassBoundary(lines, i, classMatch[1], result.filePath);
133
+ if (boundary) {
134
+ result.addBoundary(boundary);
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Find class boundary
142
+ */
143
+ static findClassBoundary(lines, startLine, name, filePath) {
144
+ let braceCount = 0;
145
+ let foundBrace = false;
146
+
147
+ for (let i = startLine; i < lines.length; i++) {
148
+ const line = lines[i];
149
+
150
+ for (let j = 0; j < line.length; j++) {
151
+ if (line[j] === '{') {
152
+ braceCount++;
153
+ foundBrace = true;
154
+ } else if (line[j] === '}') {
155
+ braceCount--;
156
+ if (foundBrace && braceCount === 0) {
157
+ return new ModuleBoundary(
158
+ BOUNDARY_TYPES.CLASS,
159
+ name,
160
+ startLine + 1,
161
+ i + 1,
162
+ filePath
163
+ );
164
+ }
165
+ }
166
+ }
167
+ }
168
+
169
+ return null;
170
+ }
171
+
172
+ /**
173
+ * Extract object boundaries
174
+ */
175
+ static async extractObjectBoundaries(lines, result) {
176
+ for (let i = 0; i < lines.length; i++) {
177
+ const line = lines[i].trim();
178
+
179
+ // Object assignments
180
+ const objMatch = line.match(/^(?:const|let|var)\s+(\w+)\s*=\s*\{/);
181
+ if (objMatch) {
182
+ const boundary = BoundaryExtractionStrategies.findObjectBoundary(lines, i, objMatch[1], result.filePath);
183
+ if (boundary) {
184
+ result.addBoundary(boundary);
185
+ }
186
+ }
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Find object boundary
192
+ */
193
+ static findObjectBoundary(lines, startLine, name, filePath) {
194
+ let braceCount = 0;
195
+ let foundBrace = false;
196
+
197
+ for (let i = startLine; i < lines.length; i++) {
198
+ const line = lines[i];
199
+
200
+ for (let j = 0; j < line.length; j++) {
201
+ if (line[j] === '{') {
202
+ braceCount++;
203
+ foundBrace = true;
204
+ } else if (line[j] === '}') {
205
+ braceCount--;
206
+ if (foundBrace && braceCount === 0) {
207
+ const boundary = new ModuleBoundary(
208
+ BOUNDARY_TYPES.OBJECT,
209
+ name,
210
+ startLine + 1,
211
+ i + 1,
212
+ filePath
213
+ );
214
+ return boundary;
215
+ }
216
+ }
217
+ }
218
+ }
219
+
220
+ return null;
221
+ }
222
+
223
+ /**
224
+ * Extract utility boundaries
225
+ */
226
+ static async extractUtilityBoundaries(lines, result) {
227
+ // Look for utility sections marked by comments
228
+ let utilityStart = null;
229
+ let utilityName = null;
230
+
231
+ for (let i = 0; i < lines.length; i++) {
232
+ const line = lines[i].trim();
233
+
234
+ if (line.startsWith('//') && (line.includes('utility') || line.includes('helper'))) {
235
+ if (utilityStart) {
236
+ // Close previous utility section
237
+ const boundary = new ModuleBoundary(
238
+ BOUNDARY_TYPES.UTILITY,
239
+ utilityName || 'utilities',
240
+ utilityStart,
241
+ i,
242
+ result.filePath
243
+ );
244
+ result.addBoundary(boundary);
245
+ }
246
+
247
+ utilityStart = i + 1;
248
+ utilityName = line.replace('//', '').trim();
249
+ } else if (line.startsWith('//') && line.includes('end utility')) {
250
+ if (utilityStart) {
251
+ const boundary = new ModuleBoundary(
252
+ BOUNDARY_TYPES.UTILITY,
253
+ utilityName || 'utilities',
254
+ utilityStart,
255
+ i,
256
+ result.filePath
257
+ );
258
+ result.addBoundary(boundary);
259
+ utilityStart = null;
260
+ utilityName = null;
261
+ }
262
+ }
263
+ }
264
+
265
+ // Close final utility section
266
+ if (utilityStart) {
267
+ const boundary = new ModuleBoundary(
268
+ BOUNDARY_TYPES.UTILITY,
269
+ utilityName || 'utilities',
270
+ utilityStart,
271
+ lines.length,
272
+ result.filePath
273
+ );
274
+ result.addBoundary(boundary);
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Extract constant boundaries
280
+ */
281
+ static async extractConstantBoundaries(lines, result) {
282
+ // Look for constant blocks
283
+ const constants = [];
284
+ let constStart = null;
285
+
286
+ for (let i = 0; i < lines.length; i++) {
287
+ const line = lines[i].trim();
288
+
289
+ if (line.startsWith('const ') && line.includes('=')) {
290
+ const match = line.match(/^const\s+(\w+)/);
291
+ if (match) {
292
+ constants.push({ name: match[1], line: i + 1 });
293
+
294
+ if (constStart === null) {
295
+ constStart = i + 1;
296
+ }
297
+ }
298
+ } else if (constStart !== null && !line.startsWith('const ') && line.trim() !== '') {
299
+ // End of constant block
300
+ if (constants.length >= 3) { // Only extract if there are multiple constants
301
+ const boundary = new ModuleBoundary(
302
+ BOUNDARY_TYPES.CONSTANT,
303
+ 'constants',
304
+ constStart,
305
+ i,
306
+ result.filePath
307
+ );
308
+ result.addBoundary(boundary);
309
+ }
310
+
311
+ constants.length = 0;
312
+ constStart = null;
313
+ }
314
+ }
315
+
316
+ // Close final constant block
317
+ if (constStart !== null && constants.length >= 3) {
318
+ const boundary = new ModuleBoundary(
319
+ BOUNDARY_TYPES.CONSTANT,
320
+ 'constants',
321
+ constStart,
322
+ lines.length,
323
+ result.filePath
324
+ );
325
+ result.addBoundary(boundary);
326
+ }
327
+ }
328
+ }
329
+
330
+ module.exports = BoundaryExtractionStrategies;
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Module Boundary Extractor
3
+ *
4
+ * Main orchestrator for extracting logical module boundaries from files for refactoring.
5
+ * Identifies cohesive code segments that can be safely extracted.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const { ModuleBoundary, BOUNDARY_TYPES, COHESION_LEVELS } = require('./boundaries/module-boundary');
11
+ const {
12
+ FunctionExtractionStrategy,
13
+ ClassExtractionStrategy,
14
+ ObjectExtractionStrategy,
15
+ UtilityExtractionStrategy
16
+ } = require('./boundaries/extraction-strategies');
17
+ const CohesionAnalyzer = require('./boundaries/cohesion-analyzer');
18
+ const BoundaryExtractionResult = require('./boundaries/extraction-result');
19
+
20
+ /**
21
+ * Main Boundary Extractor class
22
+ */
23
+ class BoundaryExtractor {
24
+ constructor(options = {}) {
25
+ this.options = {
26
+ minBoundarySize: options.minBoundarySize || 5,
27
+ maxBoundarySize: options.maxBoundarySize || 200,
28
+ includeStrategies: options.includeStrategies || ['function', 'class', 'object', 'utility'],
29
+ analyzeCohesion: options.analyzeCohesion !== false,
30
+ confidenceThreshold: options.confidenceThreshold || 0.6,
31
+ ...options
32
+ };
33
+
34
+ this.strategies = this.initializeStrategies();
35
+ this.cohesionAnalyzer = new CohesionAnalyzer();
36
+ }
37
+
38
+ /**
39
+ * Initialize extraction strategies
40
+ */
41
+ initializeStrategies() {
42
+ const strategyMap = {
43
+ function: new FunctionExtractionStrategy(),
44
+ class: new ClassExtractionStrategy(),
45
+ object: new ObjectExtractionStrategy(),
46
+ utility: new UtilityExtractionStrategy()
47
+ };
48
+
49
+ return Object.keys(strategyMap)
50
+ .filter(key => this.options.includeStrategies.includes(key))
51
+ .reduce((acc, key) => {
52
+ acc[key] = strategyMap[key];
53
+ return acc;
54
+ }, {});
55
+ }
56
+
57
+ /**
58
+ * Extract boundaries from a file
59
+ */
60
+ async extractBoundaries(filePath) {
61
+ const startTime = Date.now();
62
+ const result = new BoundaryExtractionResult(filePath);
63
+
64
+ try {
65
+ // Read file content
66
+ const content = fs.readFileSync(filePath, 'utf8');
67
+ const lines = content.split('\n');
68
+
69
+ result.setMetadata('totalLines', lines.length);
70
+ result.setMetadata('processedLines', lines.length);
71
+
72
+ // Extract boundaries using all strategies
73
+ for (const [strategyName, strategy] of Object.entries(this.strategies)) {
74
+ if (strategy.canHandle(content)) {
75
+ try {
76
+ const boundaries = strategy.extract(content, filePath);
77
+ this.addBoundariesToResult(result, boundaries, strategyName);
78
+ } catch (error) {
79
+ result.addError({
80
+ message: `Strategy ${strategyName} failed: ${error.message}`,
81
+ severity: 'warning'
82
+ });
83
+ }
84
+ }
85
+ }
86
+
87
+ // Analyze cohesion for all boundaries
88
+ if (this.options.analyzeCohesion) {
89
+ await this.analyzeCohesionForBoundaries(result, content);
90
+ }
91
+
92
+ // Filter boundaries by size and confidence
93
+ this.filterBoundaries(result);
94
+
95
+ // Validate results
96
+ const issues = result.validate();
97
+ issues.forEach(issue => {
98
+ if (issue.type === 'overlap') {
99
+ result.addWarning({ message: issue.message, code: 'OVERLAP' });
100
+ }
101
+ });
102
+
103
+ } catch (error) {
104
+ result.addError({
105
+ message: `Failed to process file: ${error.message}`,
106
+ severity: 'error'
107
+ });
108
+ }
109
+
110
+ result.setMetadata('extractionTime', Date.now() - startTime);
111
+ return result;
112
+ }
113
+
114
+ /**
115
+ * Extract boundaries from multiple files
116
+ */
117
+ async extractBoundariesFromFiles(filePaths) {
118
+ const results = [];
119
+
120
+ for (const filePath of filePaths) {
121
+ try {
122
+ const result = await this.extractBoundaries(filePath);
123
+ results.push(result);
124
+ } catch (error) {
125
+ // Create error result
126
+ const errorResult = new BoundaryExtractionResult(filePath);
127
+ errorResult.addError({
128
+ message: `File processing failed: ${error.message}`,
129
+ severity: 'error'
130
+ });
131
+ results.push(errorResult);
132
+ }
133
+ }
134
+
135
+ return results;
136
+ }
137
+
138
+ /**
139
+ * Add boundaries to result
140
+ */
141
+ addBoundariesToResult(result, boundaries, strategyName) {
142
+ for (const boundaryData of boundaries) {
143
+ // Apply confidence threshold
144
+ if (boundaryData.confidence < this.options.confidenceThreshold) {
145
+ continue;
146
+ }
147
+
148
+ const boundary = result.addBoundary(boundaryData);
149
+
150
+ // Add strategy metadata
151
+ boundary.extractionStrategy = strategyName;
152
+ boundary.confidence = boundaryData.confidence;
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Analyze cohesion for all boundaries
158
+ */
159
+ async analyzeCohesionForBoundaries(result, content) {
160
+ for (const boundary of result.boundaries) {
161
+ try {
162
+ // Extract code segment for this boundary
163
+ const lines = content.split('\n');
164
+ const segmentLines = lines.slice(boundary.startLine - 1, boundary.endLine);
165
+ const segmentCode = segmentLines.join('\n');
166
+
167
+ // Analyze cohesion
168
+ const cohesion = this.cohesionAnalyzer.analyzeCohesion(segmentCode, boundary);
169
+
170
+ boundary.setCohesion(cohesion.level);
171
+ boundary.cohesionScore = cohesion.score;
172
+ boundary.cohesionDetails = cohesion.details;
173
+
174
+ } catch (error) {
175
+ result.addWarning({
176
+ message: `Cohesion analysis failed for ${boundary.name}: ${error.message}`,
177
+ line: boundary.startLine
178
+ });
179
+ }
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Filter boundaries based on criteria
185
+ */
186
+ filterBoundaries(result) {
187
+ result.boundaries = result.boundaries.filter(boundary => {
188
+ // Size filter
189
+ if (boundary.lineCount < this.options.minBoundarySize) {
190
+ return false;
191
+ }
192
+ if (boundary.lineCount > this.options.maxBoundarySize) {
193
+ return false;
194
+ }
195
+
196
+ // Name filter
197
+ if (!boundary.name || boundary.name.trim() === '') {
198
+ return false;
199
+ }
200
+
201
+ return true;
202
+ });
203
+ }
204
+
205
+ /**
206
+ * Get extraction statistics for multiple results
207
+ */
208
+ getStatistics(results) {
209
+ const stats = {
210
+ totalFiles: results.length,
211
+ totalBoundaries: 0,
212
+ extractableBoundaries: 0,
213
+ highCohesionBoundaries: 0,
214
+ averageCoverage: 0,
215
+ byType: {},
216
+ errors: [],
217
+ warnings: [],
218
+ extractionTime: 0
219
+ };
220
+
221
+ let totalCoverage = 0;
222
+
223
+ for (const result of results) {
224
+ const resultStats = result.getStatistics();
225
+
226
+ stats.totalBoundaries += resultStats.totalBoundaries;
227
+ stats.extractableBoundaries += resultStats.extractableBoundaries;
228
+ stats.highCohesionBoundaries += resultStats.highCohesionBoundaries;
229
+ totalCoverage += resultStats.coverage;
230
+ stats.extractionTime += result.metadata.extractionTime || 0;
231
+
232
+ stats.errors.push(...result.errors);
233
+ stats.warnings.push(...result.warnings);
234
+
235
+ // Count by type
236
+ for (const [type, count] of Object.entries(resultStats.typeDistribution)) {
237
+ stats.byType[type] = (stats.byType[type] || 0) + count;
238
+ }
239
+ }
240
+
241
+ stats.averageCoverage = results.length > 0 ? totalCoverage / results.length : 0;
242
+
243
+ return stats;
244
+ }
245
+
246
+ /**
247
+ * Get top extraction candidates across all results
248
+ */
249
+ getTopExtractionCandidates(results, limit = 20) {
250
+ const allCandidates = [];
251
+
252
+ for (const result of results) {
253
+ const candidates = result.getTopExtractionCandidates(limit);
254
+ allCandidates.push(...candidates);
255
+ }
256
+
257
+ return allCandidates
258
+ .sort((a, b) => b.getExtractionPriority() - a.getExtractionPriority())
259
+ .slice(0, limit);
260
+ }
261
+
262
+ /**
263
+ * Generate extraction plan
264
+ */
265
+ generateExtractionPlan(results, options = {}) {
266
+ const candidates = this.getTopExtractionCandidates(results, options.limit || 50);
267
+
268
+ return {
269
+ summary: this.getStatistics(results),
270
+ candidates: candidates.map(boundary => ({
271
+ ...boundary.getSummary(),
272
+ extractionPlan: this.generateBoundaryExtractionPlan(boundary)
273
+ })),
274
+ recommendations: this.generateRecommendations(results),
275
+ estimatedEffort: this.estimateExtractionEffort(candidates)
276
+ };
277
+ }
278
+
279
+ /**
280
+ * Generate extraction plan for a single boundary
281
+ */
282
+ generateBoundaryExtractionPlan(boundary) {
283
+ return {
284
+ targetFile: boundary.getSuggestedFilename(),
285
+ extractionSteps: [
286
+ `Create new file: ${boundary.getSuggestedFilename()}`,
287
+ `Extract lines ${boundary.startLine}-${boundary.endLine}`,
288
+ `Update imports in ${boundary.filePath}`,
289
+ `Add export statement to new file`,
290
+ `Test extraction and functionality`
291
+ ],
292
+ complexity: boundary.complexity,
293
+ estimatedTime: this.estimateBoundaryExtractionTime(boundary)
294
+ };
295
+ }
296
+
297
+ /**
298
+ * Generate recommendations
299
+ */
300
+ generateRecommendations(results) {
301
+ const stats = this.getStatistics(results);
302
+ const recommendations = [];
303
+
304
+ if (stats.extractableBoundaries === 0) {
305
+ recommendations.push('No extractable boundaries found. Consider adjusting extraction criteria.');
306
+ } else if (stats.extractableBoundaries < 5) {
307
+ recommendations.push('Few extractable boundaries found. Code may already be well-modularized.');
308
+ } else {
309
+ recommendations.push(`Found ${stats.extractableBoundaries} extractable boundaries. Prioritize high cohesion boundaries.`);
310
+ }
311
+
312
+ if (stats.averageCoverage < 30) {
313
+ recommendations.push('Low coverage suggests boundaries may be too small. Consider increasing minimum size.');
314
+ } else if (stats.averageCoverage > 80) {
315
+ recommendations.push('High coverage suggests boundaries may be too large. Consider decreasing maximum size.');
316
+ }
317
+
318
+ if (stats.highCohesionBoundaries / stats.extractableBoundaries < 0.5) {
319
+ recommendations.push('Many boundaries have low cohesion. Focus on improving code organization.');
320
+ }
321
+
322
+ return recommendations;
323
+ }
324
+
325
+ /**
326
+ * Estimate extraction effort
327
+ */
328
+ estimateExtractionEffort(candidates) {
329
+ let totalEffort = 0;
330
+
331
+ for (const boundary of candidates) {
332
+ totalEffort += this.estimateBoundaryExtractionTime(boundary);
333
+ }
334
+
335
+ return {
336
+ totalHours: totalEffort,
337
+ averageHoursPerBoundary: totalEffort / candidates.length,
338
+ complexityBreakdown: this.getComplexityBreakdown(candidates)
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Estimate extraction time for a boundary
344
+ */
345
+ estimateBoundaryExtractionTime(boundary) {
346
+ let baseTime = 1; // 1 hour base
347
+
348
+ // Adjust for size
349
+ if (boundary.lineCount > 100) baseTime += 2;
350
+ else if (boundary.lineCount > 50) baseTime += 1;
351
+
352
+ // Adjust for complexity
353
+ if (boundary.complexity > 50) baseTime += 2;
354
+ else if (boundary.complexity > 20) baseTime += 1;
355
+
356
+ // Adjust for dependencies
357
+ baseTime += Math.min(boundary.dependencies.length * 0.5, 2);
358
+
359
+ return baseTime;
360
+ }
361
+
362
+ /**
363
+ * Get complexity breakdown
364
+ */
365
+ getComplexityBreakdown(candidates) {
366
+ const breakdown = { low: 0, medium: 0, high: 0 };
367
+
368
+ for (const boundary of candidates) {
369
+ if (boundary.complexity <= 20) breakdown.low++;
370
+ else if (boundary.complexity <= 50) breakdown.medium++;
371
+ else breakdown.high++;
372
+ }
373
+
374
+ return breakdown;
375
+ }
376
+ }
377
+
378
+ module.exports = {
379
+ BoundaryExtractor,
380
+ ModuleBoundary,
381
+ BoundaryExtractionResult,
382
+ BOUNDARY_TYPES,
383
+ COHESION_LEVELS
384
+ };