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,554 @@
1
+ /**
2
+ * Boundary Extraction Strategies
3
+ */
4
+
5
+ const { BOUNDARY_TYPES } = require('./boundary-types');
6
+
7
+ /**
8
+ * Extraction strategy base class
9
+ */
10
+ class ExtractionStrategy {
11
+ constructor(name, description) {
12
+ this.name = name;
13
+ this.description = description;
14
+ this.priority = 'MEDIUM';
15
+ }
16
+
17
+ /**
18
+ * Check if strategy is applicable to boundary
19
+ * @param {Object} boundary - Boundary to check
20
+ * @returns {boolean} Whether strategy applies
21
+ */
22
+ isApplicable(boundary) {
23
+ return true; // Override in subclasses
24
+ }
25
+
26
+ /**
27
+ * Extract boundary to new module
28
+ * @param {Object} boundary - Boundary to extract
29
+ * @param {Array} lines - Source code lines
30
+ * @returns {Object} Extraction result
31
+ */
32
+ extract(boundary, lines) {
33
+ throw new Error('extract method must be implemented by subclasses');
34
+ }
35
+
36
+ /**
37
+ * Generate new file name for extracted boundary
38
+ * @param {Object} boundary - Boundary being extracted
39
+ * @returns {string} New file name
40
+ */
41
+ generateFileName(boundary) {
42
+ const baseName = boundary.name.toLowerCase()
43
+ .replace(/[^a-z0-9]/g, '-')
44
+ .replace(/-+/g, '-');
45
+
46
+ return `${baseName}.js`;
47
+ }
48
+
49
+ /**
50
+ * Generate import statement for extracted module
51
+ * @param {Object} boundary - Boundary being extracted
52
+ * @param {string} fileName - New file name
53
+ * @returns {string} Import statement
54
+ */
55
+ generateImportStatement(boundary, fileName) {
56
+ const baseName = fileName.replace('.js', '');
57
+
58
+ if (boundary.exports.length > 0) {
59
+ const exports = boundary.exports.join(', ');
60
+ return `import { ${exports} } from './${baseName}';\n`;
61
+ } else if (boundary.type === 'function' || boundary.type === 'class') {
62
+ return `import ${boundary.name} from './${baseName}';\n`;
63
+ }
64
+
65
+ return '';
66
+ }
67
+
68
+ /**
69
+ * Generate export statement for extracted module
70
+ * @param {Object} boundary - Boundary being extracted
71
+ * @returns {string} Export statement
72
+ */
73
+ generateExportStatement(boundary) {
74
+ if (boundary.exports.length > 0) {
75
+ return `export { ${boundary.exports.join(', ')};`;
76
+ } else if (boundary.type === 'function' || boundary.type === 'class') {
77
+ return `export ${boundary.type === 'function' ? 'function ' : ''}${boundary.name};`;
78
+ }
79
+
80
+ return '';
81
+ }
82
+
83
+ /**
84
+ * Update original file with extraction changes
85
+ * @param {Array} lines - Original file lines
86
+ * @param {Object} boundary - Boundary being extracted
87
+ * @param {string} importStatement - Import statement to add
88
+ * @returns {Array} Updated lines
89
+ */
90
+ updateOriginalFile(lines, boundary, importStatement) {
91
+ const updatedLines = [...lines];
92
+
93
+ // Remove original boundary lines
94
+ updatedLines.splice(boundary.startLine - 1, boundary.lineCount);
95
+
96
+ // Add import statement at original location
97
+ if (importStatement) {
98
+ updatedLines.splice(boundary.startLine - 1, 0, importStatement);
99
+ }
100
+
101
+ return updatedLines;
102
+ }
103
+
104
+ /**
105
+ * Validate extraction result
106
+ * @param {Object} result - Extraction result
107
+ * @returns {Object} Validation result
108
+ */
109
+ validateExtraction(result) {
110
+ const errors = [];
111
+
112
+ if (!result.extractedCode) {
113
+ errors.push('No extracted code generated');
114
+ }
115
+
116
+ if (!result.fileName) {
117
+ errors.push('No file name generated');
118
+ }
119
+
120
+ if (!result.originalCode) {
121
+ errors.push('Original code not preserved');
122
+ }
123
+
124
+ return {
125
+ isValid: errors.length === 0,
126
+ errors
127
+ };
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Standard extraction strategy
133
+ */
134
+ class StandardExtractionStrategy extends ExtractionStrategy {
135
+ constructor() {
136
+ super('standard', 'Standard boundary extraction with imports and exports');
137
+ this.priority = 'HIGH';
138
+ }
139
+
140
+ isApplicable(boundary) {
141
+ return boundary.isExtractable() &&
142
+ boundary.lineCount >= 10 &&
143
+ boundary.lineCount <= 200;
144
+ }
145
+
146
+ extract(boundary, lines) {
147
+ const boundaryLines = lines.slice(boundary.startLine - 1, boundary.endLine);
148
+ const extractedCode = boundaryLines.join('\n');
149
+
150
+ const fileName = this.generateFileName(boundary);
151
+ const importStatement = this.generateImportStatement(boundary, fileName);
152
+ const exportStatement = this.generateExportStatement(boundary);
153
+
154
+ // Add export statement if needed
155
+ let finalExtractedCode = extractedCode;
156
+ if (exportStatement) {
157
+ finalExtractedCode += '\n\n' + exportStatement;
158
+ }
159
+
160
+ const originalCode = lines.join('\n');
161
+ const updatedOriginalCode = this.updateOriginalFile(lines, boundary, importStatement);
162
+
163
+ const result = {
164
+ strategy: this.name,
165
+ boundary,
166
+ fileName,
167
+ extractedCode: finalExtractedCode,
168
+ originalCode: updatedOriginalCode,
169
+ importStatement,
170
+ exportStatement,
171
+ dependencies: boundary.dependencies,
172
+ exports: boundary.exports
173
+ };
174
+
175
+ const validation = this.validateExtraction(result);
176
+ if (!validation.isValid) {
177
+ throw new Error(`Extraction validation failed: ${validation.errors.join(', ')}`);
178
+ }
179
+
180
+ return result;
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Minimal extraction strategy
186
+ */
187
+ class MinimalExtractionStrategy extends ExtractionStrategy {
188
+ constructor() {
189
+ super('minimal', 'Minimal extraction with no imports/exports');
190
+ this.priority = 'LOW';
191
+ }
192
+
193
+ isApplicable(boundary) {
194
+ return boundary.isExtractable() &&
195
+ boundary.lineCount <= 50;
196
+ }
197
+
198
+ extract(boundary, lines) {
199
+ const boundaryLines = lines.slice(boundary.startLine - 1, boundary.endLine);
200
+ const extractedCode = boundaryLines.join('\n');
201
+
202
+ const fileName = this.generateFileName(boundary);
203
+ const originalCode = lines.join('\n');
204
+ const updatedOriginalCode = this.updateOriginalFile(lines, boundary, '');
205
+
206
+ const result = {
207
+ strategy: this.name,
208
+ boundary,
209
+ fileName,
210
+ extractedCode,
211
+ originalCode: updatedOriginalCode,
212
+ dependencies: boundary.dependencies,
213
+ exports: []
214
+ };
215
+
216
+ const validation = this.validateExtraction(result);
217
+ if (!validation.isValid) {
218
+ throw new Error(`Extraction validation failed: ${validation.errors.join(', ')}`);
219
+ }
220
+
221
+ return result;
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Class extraction strategy
227
+ */
228
+ class ClassExtractionStrategy extends ExtractionStrategy {
229
+ constructor() {
230
+ super('class', 'Specialized extraction for classes');
231
+ this.priority = 'HIGH';
232
+ }
233
+
234
+ isApplicable(boundary) {
235
+ return boundary.type === BOUNDARY_TYPES.CLASS &&
236
+ boundary.isExtractable() &&
237
+ boundary.lineCount <= 300;
238
+ }
239
+
240
+ extract(boundary, lines) {
241
+ const boundaryLines = lines.slice(boundary.startLine - 1, boundary.endLine);
242
+ let extractedCode = boundaryLines.join('\n');
243
+
244
+ const fileName = this.generateFileName(boundary);
245
+ const importStatement = this.generateImportStatement(boundary, fileName);
246
+
247
+ // Ensure class is properly exported
248
+ if (!extractedCode.includes('export ')) {
249
+ extractedCode = `export ${extractedCode}`;
250
+ }
251
+
252
+ const originalCode = lines.join('\n');
253
+ const updatedOriginalCode = this.updateOriginalFile(lines, boundary, importStatement);
254
+
255
+ const result = {
256
+ strategy: this.name,
257
+ boundary,
258
+ fileName,
259
+ extractedCode,
260
+ originalCode: updatedOriginalCode,
261
+ importStatement,
262
+ dependencies: boundary.dependencies,
263
+ exports: boundary.exports
264
+ };
265
+
266
+ const validation = this.validateExtraction(result);
267
+ if (!validation.isValid) {
268
+ throw new Error(`Extraction validation failed: ${validation.errors.join(', ')}`);
269
+ }
270
+
271
+ return result;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Utility extraction strategy
277
+ */
278
+ class UtilityExtractionStrategy extends ExtractionStrategy {
279
+ constructor() {
280
+ super('utility', 'Specialized extraction for utility functions');
281
+ this.priority = 'MEDIUM';
282
+ }
283
+
284
+ isApplicable(boundary) {
285
+ return boundary.type === BOUNDARY_TYPES.UTILITY &&
286
+ boundary.isExtractable() &&
287
+ boundary.lineCount <= 100;
288
+ }
289
+
290
+ extract(boundary, lines) {
291
+ const boundaryLines = lines.slice(boundary.startLine - 1, boundary.endLine);
292
+ let extractedCode = boundaryLines.join('\n');
293
+
294
+ const fileName = this.generateFileName(boundary);
295
+ const importStatement = this.generateImportStatement(boundary, fileName);
296
+
297
+ // Ensure utility function is exported
298
+ if (!extractedCode.includes('export ')) {
299
+ extractedCode = `export ${extractedCode}`;
300
+ }
301
+
302
+ const originalCode = lines.join('\n');
303
+ const updatedOriginalCode = this.updateOriginalFile(lines, boundary, importStatement);
304
+
305
+ const result = {
306
+ strategy: this.name,
307
+ boundary,
308
+ fileName,
309
+ extractedCode,
310
+ originalCode: updatedOriginalCode,
311
+ importStatement,
312
+ dependencies: boundary.dependencies,
313
+ exports: boundary.exports
314
+ };
315
+
316
+ const validation = this.validateExtraction(result);
317
+ if (!validation.isValid) {
318
+ throw new Error(`Extraction validation failed: ${validation.errors.join(', ')}`);
319
+ }
320
+
321
+ return result;
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Strategy selector
327
+ */
328
+ class StrategySelector {
329
+ constructor() {
330
+ this.strategies = [
331
+ new StandardExtractionStrategy(),
332
+ new ClassExtractionStrategy(),
333
+ new UtilityExtractionStrategy(),
334
+ new MinimalExtractionStrategy()
335
+ ];
336
+ }
337
+
338
+ /**
339
+ * Select best strategy for boundary
340
+ * @param {Object} boundary - Boundary to extract
341
+ * @returns {ExtractionStrategy|null} Selected strategy
342
+ */
343
+ selectStrategy(boundary) {
344
+ const applicableStrategies = this.strategies.filter(strategy =>
345
+ strategy.isApplicable(boundary)
346
+ );
347
+
348
+ if (applicableStrategies.length === 0) {
349
+ return null;
350
+ }
351
+
352
+ // Sort by priority (HIGH > MEDIUM > LOW)
353
+ applicableStrategies.sort((a, b) => {
354
+ const priorityOrder = { HIGH: 3, MEDIUM: 2, LOW: 1 };
355
+ return priorityOrder[b.priority] - priorityOrder[a.priority];
356
+ });
357
+
358
+ return applicableStrategies[0];
359
+ }
360
+
361
+ /**
362
+ * Get all strategies
363
+ * @returns {Array} All strategies
364
+ */
365
+ getAllStrategies() {
366
+ return [...this.strategies];
367
+ }
368
+
369
+ /**
370
+ * Add custom strategy
371
+ * @param {ExtractionStrategy} strategy - Custom strategy to add
372
+ */
373
+ addStrategy(strategy) {
374
+ if (strategy instanceof ExtractionStrategy) {
375
+ this.strategies.push(strategy);
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Remove strategy
381
+ * @param {string} strategyName - Name of strategy to remove
382
+ */
383
+ removeStrategy(strategyName) {
384
+ this.strategies = this.strategies.filter(s => s.name !== strategyName);
385
+ }
386
+
387
+ /**
388
+ * Get strategy by name
389
+ * @param {string} strategyName - Name of strategy
390
+ * @returns {ExtractionStrategy|null} Strategy or null
391
+ */
392
+ getStrategy(strategyName) {
393
+ return this.strategies.find(s => s.name === strategyName) || null;
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Extraction orchestrator
399
+ */
400
+ class ExtractionOrchestrator {
401
+ constructor() {
402
+ this.strategySelector = new StrategySelector();
403
+ }
404
+
405
+ /**
406
+ * Extract boundary using best available strategy
407
+ * @param {Object} boundary - Boundary to extract
408
+ * @param {Array} lines - Source code lines
409
+ * @returns {Object} Extraction result
410
+ */
411
+ extract(boundary, lines) {
412
+ const strategy = this.strategySelector.selectStrategy(boundary);
413
+
414
+ if (!strategy) {
415
+ throw new Error(`No applicable extraction strategy found for boundary: ${boundary.name}`);
416
+ }
417
+
418
+ console.log(`Using ${strategy.name} strategy for ${boundary.name} boundary`);
419
+
420
+ return strategy.extract(boundary, lines);
421
+ }
422
+
423
+ /**
424
+ * Extract multiple boundaries
425
+ * @param {Array} boundaries - Boundaries to extract
426
+ * @param {Array} lines - Source code lines
427
+ * @returns {Array} Array of extraction results
428
+ */
429
+ extractMultiple(boundaries, lines) {
430
+ const results = [];
431
+
432
+ // Sort boundaries by priority (extractable, then by score)
433
+ const sortedBoundaries = boundaries
434
+ .filter(b => b.isExtractable())
435
+ .sort((a, b) => b.calculateScore() - a.calculateScore());
436
+
437
+ for (const boundary of sortedBoundaries) {
438
+ try {
439
+ const result = this.extract(boundary, lines);
440
+ results.push(result);
441
+ } catch (error) {
442
+ console.warn(`Failed to extract boundary ${boundary.name}:`, error.message);
443
+ // Continue with other boundaries
444
+ }
445
+ }
446
+
447
+ return results;
448
+ }
449
+
450
+ /**
451
+ * Plan extraction for multiple boundaries
452
+ * @param {Array} boundaries - Boundaries to extract
453
+ * @returns {Object} Extraction plan
454
+ */
455
+ planExtraction(boundaries) {
456
+ const extractable = boundaries.filter(b => b.isExtractable());
457
+ const strategyMap = new Map();
458
+
459
+ // Select strategies for each boundary
460
+ for (const boundary of extractable) {
461
+ const strategy = this.strategySelector.selectStrategy(boundary);
462
+ if (strategy) {
463
+ strategyMap.set(boundary.id, strategy);
464
+ }
465
+ }
466
+
467
+ // Group boundaries by strategy
468
+ const strategyGroups = new Map();
469
+ for (const [boundaryId, strategy] of strategyMap) {
470
+ if (!strategyGroups.has(strategy.name)) {
471
+ strategyGroups.set(strategy.name, []);
472
+ }
473
+ strategyGroups.get(strategy.name).push(boundaryId);
474
+ }
475
+
476
+ // Generate extraction plan
477
+ const plan = {
478
+ totalBoundaries: extractable.length,
479
+ strategyGroups: Array.from(strategyGroups.entries()).map(([strategy, boundaryIds]) => ({
480
+ strategy,
481
+ boundaries: boundaryIds.map(id => extractable.find(b => b.id === id)),
482
+ count: boundaryIds.length
483
+ })),
484
+ estimatedEffort: this.estimateEffort(extractable),
485
+ dependencies: this.analyzeDependencies(extractable)
486
+ };
487
+
488
+ return plan;
489
+ }
490
+
491
+ /**
492
+ * Estimate extraction effort
493
+ * @param {Array} boundaries - Boundaries to extract
494
+ * @returns {string} Effort estimate
495
+ */
496
+ estimateEffort(boundaries) {
497
+ const totalLines = boundaries.reduce((sum, b) => sum + b.lineCount, 0);
498
+ const hours = Math.round(totalLines / 50); // Rough estimate
499
+
500
+ if (hours <= 2) return 'Low';
501
+ if (hours <= 8) return 'Medium';
502
+ if (hours <= 20) return 'High';
503
+ return 'Very High';
504
+ }
505
+
506
+ /**
507
+ * Analyze dependencies between boundaries
508
+ * @param {Array} boundaries - Boundaries to analyze
509
+ * @returns {Object} Dependency analysis
510
+ */
511
+ analyzeDependencies(boundaries) {
512
+ const allDependencies = new Set();
513
+ const internalDependencies = new Map();
514
+
515
+ for (const boundary of boundaries) {
516
+ for (const dep of boundary.dependencies) {
517
+ allDependencies.add(dep);
518
+
519
+ // Check if dependency is internal (from another boundary)
520
+ const dependentBoundary = boundaries.find(b =>
521
+ b.exports.includes(dep) || b.name === dep
522
+ );
523
+
524
+ if (dependentBoundary) {
525
+ if (!internalDependencies.has(boundary.id)) {
526
+ internalDependencies.set(boundary.id, []);
527
+ }
528
+ internalDependencies.get(boundary.id).push(dependentBoundary.id);
529
+ }
530
+ }
531
+ }
532
+
533
+ return {
534
+ totalDependencies: allDependencies.size,
535
+ internalDependencies: Array.from(internalDependencies.entries()).map(([id, deps]) => ({
536
+ boundaryId: id,
537
+ dependencies: deps
538
+ })),
539
+ externalDependencies: Array.from(allDependencies).filter(dep =>
540
+ !boundaries.some(b => b.exports.includes(dep) || b.name === dep)
541
+ )
542
+ };
543
+ }
544
+ }
545
+
546
+ module.exports = {
547
+ ExtractionStrategy,
548
+ StandardExtractionStrategy,
549
+ MinimalExtractionStrategy,
550
+ ClassExtractionStrategy,
551
+ UtilityExtractionStrategy,
552
+ StrategySelector,
553
+ ExtractionOrchestrator
554
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Boundary Extraction Result Class
3
+ *
4
+ * Represents the result of boundary extraction from a file.
5
+ */
6
+
7
+ const { COHESION_LEVELS } = require('./boundary-types');
8
+
9
+ /**
10
+ * Boundary extraction result class
11
+ */
12
+ class BoundaryExtractionResult {
13
+ constructor(filePath) {
14
+ this.filePath = filePath;
15
+ this.boundaries = [];
16
+ this.metadata = {
17
+ extractedAt: new Date().toISOString(),
18
+ totalLines: 0,
19
+ coverage: 0
20
+ };
21
+ this.errors = [];
22
+ this.warnings = [];
23
+ }
24
+
25
+ addBoundary(boundary) {
26
+ this.boundaries.push(boundary);
27
+ }
28
+
29
+ addError(error) {
30
+ this.errors.push({
31
+ message: error.message,
32
+ timestamp: new Date().toISOString()
33
+ });
34
+ }
35
+
36
+ addWarning(warning) {
37
+ this.warnings.push({
38
+ message: warning,
39
+ timestamp: new Date().toISOString()
40
+ });
41
+ }
42
+
43
+ getBoundariesByType(type) {
44
+ return this.boundaries.filter(b => b.type === type);
45
+ }
46
+
47
+ getExtractableBoundaries() {
48
+ return this.boundaries.filter(b => b.metadata.extractable);
49
+ }
50
+
51
+ getHighCohesionBoundaries() {
52
+ return this.boundaries.filter(b => b.cohesion === COHESION_LEVELS.HIGH);
53
+ }
54
+
55
+ calculateCoverage() {
56
+ if (this.metadata.totalLines === 0) return 0;
57
+
58
+ const coveredLines = this.boundaries.reduce((sum, b) => sum + b.lineCount, 0);
59
+ this.metadata.coverage = (coveredLines / this.metadata.totalLines) * 100;
60
+
61
+ return this.metadata.coverage;
62
+ }
63
+
64
+ getSummary() {
65
+ return {
66
+ filePath: this.filePath,
67
+ boundaryCount: this.boundaries.length,
68
+ extractableCount: this.getExtractableBoundaries().length,
69
+ highCohesionCount: this.getHighCohesionBoundaries().length,
70
+ coverage: this.calculateCoverage(),
71
+ errorCount: this.errors.length,
72
+ warningCount: this.warnings.length
73
+ };
74
+ }
75
+ }
76
+
77
+ module.exports = BoundaryExtractionResult;