vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,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;
|