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,614 @@
1
+ /**
2
+ * Refactoring Rollback
3
+ *
4
+ * Provides rollback capabilities for failed refactoring operations.
5
+ * Ensures safe restoration of original state with comprehensive tracking.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const { RollbackManager } = require('../utils/rollback-manager');
11
+
12
+ /**
13
+ * Rollback status
14
+ */
15
+ const ROLLBACK_STATUS = {
16
+ PENDING: 'pending',
17
+ RUNNING: 'running',
18
+ COMPLETED: 'completed',
19
+ FAILED: 'failed',
20
+ PARTIAL: 'partial'
21
+ };
22
+
23
+ /**
24
+ * Rollback operation class
25
+ */
26
+ class RollbackOperation {
27
+ constructor(operationId, type, targetPath) {
28
+ this.id = this.generateId();
29
+ this.operationId = operationId;
30
+ this.type = type;
31
+ this.targetPath = targetPath;
32
+ this.status = ROLLBACK_STATUS.PENDING;
33
+ this.startTime = null;
34
+ this.endTime = null;
35
+ this.duration = 0;
36
+ this.success = false;
37
+ this.errors = [];
38
+ this.warnings = [];
39
+ this.metadata = {
40
+ createdAt: new Date().toISOString(),
41
+ backupPath: null,
42
+ originalSize: 0,
43
+ restoredSize: 0
44
+ };
45
+ }
46
+
47
+ generateId() {
48
+ return `rollback_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
49
+ }
50
+
51
+ setStatus(status) {
52
+ this.status = status;
53
+ if (status === ROLLBACK_STATUS.RUNNING && !this.startTime) {
54
+ this.startTime = new Date().toISOString();
55
+ }
56
+ if ([ROLLBACK_STATUS.COMPLETED, ROLLBACK_STATUS.FAILED, ROLLBACK_STATUS.PARTIAL].includes(status)) {
57
+ this.endTime = new Date().toISOString();
58
+ this.duration = this.endTime && this.startTime ?
59
+ (new Date(this.endTime) - new Date(this.startTime)) / 1000 : 0;
60
+ }
61
+ }
62
+
63
+ setSuccess(success) {
64
+ this.success = success;
65
+ }
66
+
67
+ addError(error) {
68
+ this.errors.push({
69
+ message: error.message,
70
+ timestamp: new Date().toISOString(),
71
+ stack: error.stack
72
+ });
73
+ }
74
+
75
+ addWarning(warning) {
76
+ this.warnings.push({
77
+ message: warning,
78
+ timestamp: new Date().toISOString()
79
+ });
80
+ }
81
+
82
+ setBackupPath(backupPath) {
83
+ this.metadata.backupPath = backupPath;
84
+ }
85
+
86
+ setOriginalSize(size) {
87
+ this.metadata.originalSize = size;
88
+ }
89
+
90
+ setRestoredSize(size) {
91
+ this.metadata.restoredSize = size;
92
+ }
93
+
94
+ getSummary() {
95
+ return {
96
+ id: this.id,
97
+ operationId: this.operationId,
98
+ type: this.type,
99
+ targetPath: this.targetPath,
100
+ status: this.status,
101
+ success: this.success,
102
+ duration: this.duration,
103
+ errorCount: this.errors.length,
104
+ warningCount: this.warnings.length,
105
+ backupPath: this.metadata.backupPath
106
+ };
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Rollback result class
112
+ */
113
+ class RollbackResult {
114
+ constructor(rollbackId) {
115
+ this.rollbackId = rollbackId;
116
+ this.operations = [];
117
+ this.status = ROLLBACK_STATUS.PENDING;
118
+ this.success = false;
119
+ this.startTime = null;
120
+ this.endTime = null;
121
+ this.duration = 0;
122
+ this.errors = [];
123
+ this.warnings = [];
124
+ this.metadata = {
125
+ createdAt: new Date().toISOString(),
126
+ triggerReason: '',
127
+ affectedFiles: 0,
128
+ totalFilesRestored: 0
129
+ };
130
+ }
131
+
132
+ addOperation(operation) {
133
+ this.operations.push(operation);
134
+ }
135
+
136
+ setStatus(status) {
137
+ this.status = status;
138
+ if (status === ROLLBACK_STATUS.RUNNING && !this.startTime) {
139
+ this.startTime = new Date().toISOString();
140
+ }
141
+ if ([ROLLBACK_STATUS.COMPLETED, ROLLBACK_STATUS.FAILED, ROLLBACK_STATUS.PARTIAL].includes(status)) {
142
+ this.endTime = new Date().toISOString();
143
+ this.duration = this.endTime && this.startTime ?
144
+ (new Date(this.endTime) - new Date(this.startTime)) / 1000 : 0;
145
+ }
146
+ }
147
+
148
+ setSuccess(success) {
149
+ this.success = success;
150
+ }
151
+
152
+ setTriggerReason(reason) {
153
+ this.metadata.triggerReason = reason;
154
+ }
155
+
156
+ addError(error) {
157
+ this.errors.push({
158
+ message: error.message,
159
+ timestamp: new Date().toISOString(),
160
+ stack: error.stack
161
+ });
162
+ }
163
+
164
+ addWarning(warning) {
165
+ this.warnings.push({
166
+ message: warning,
167
+ timestamp: new Date().toISOString()
168
+ });
169
+ }
170
+
171
+ calculateSummary() {
172
+ const successfulOps = this.operations.filter(op => op.success).length;
173
+ const failedOps = this.operations.filter(op => !op.success).length;
174
+
175
+ if (failedOps === 0) {
176
+ this.setStatus(ROLLBACK_STATUS.COMPLETED);
177
+ this.setSuccess(true);
178
+ } else if (successfulOps > 0) {
179
+ this.setStatus(ROLLBACK_STATUS.PARTIAL);
180
+ this.setSuccess(false);
181
+ } else {
182
+ this.setStatus(ROLLBACK_STATUS.FAILED);
183
+ this.setSuccess(false);
184
+ }
185
+
186
+ this.metadata.affectedFiles = this.operations.length;
187
+ this.metadata.totalFilesRestored = successfulOps;
188
+ }
189
+
190
+ getSummary() {
191
+ this.calculateSummary();
192
+
193
+ return {
194
+ rollbackId: this.rollbackId,
195
+ status: this.status,
196
+ success: this.success,
197
+ duration: this.duration,
198
+ triggerReason: this.metadata.triggerReason,
199
+ affectedFiles: this.metadata.affectedFiles,
200
+ totalFilesRestored: this.metadata.totalFilesRestored,
201
+ operations: this.operations.map(op => op.getSummary()),
202
+ errorCount: this.errors.length,
203
+ warningCount: this.warnings.length
204
+ };
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Refactoring rollback manager class
210
+ */
211
+ class RefactoringRollback {
212
+ constructor(options = {}) {
213
+ this.options = {
214
+ createBackups: true,
215
+ validateAfterRollback: true,
216
+ preserveRollbackLogs: true,
217
+ maxRollbackAttempts: 3,
218
+ ...options
219
+ };
220
+
221
+ this.rollbackManager = new RollbackManager();
222
+ this.rollbackHistory = new Map();
223
+ this.currentRollback = null;
224
+ this.isRollingBack = false;
225
+ }
226
+
227
+ /**
228
+ * Create rollback point for a refactoring operation
229
+ */
230
+ async createRollbackPoint(operationId, operation) {
231
+ console.log(`Creating rollback point for operation: ${operationId}`);
232
+
233
+ try {
234
+ const rollbackOp = new RollbackOperation(operationId, 'create_backup', operation.targetPath);
235
+
236
+ // Create backup for each affected file
237
+ for (const affectedFile of operation.affectedFiles || [operation.targetPath]) {
238
+ if (fs.existsSync(affectedFile)) {
239
+ const backupPath = this.rollbackManager.backupFile(affectedFile);
240
+ rollbackOp.setBackupPath(backupPath);
241
+ rollbackOp.setOriginalSize(fs.statSync(affectedFile).size);
242
+ }
243
+ }
244
+
245
+ rollbackOp.setStatus(ROLLBACK_STATUS.COMPLETED);
246
+ rollbackOp.setSuccess(true);
247
+
248
+ // Store rollback operation
249
+ if (!this.rollbackHistory.has(operationId)) {
250
+ this.rollbackHistory.set(operationId, []);
251
+ }
252
+ this.rollbackHistory.get(operationId).push(rollbackOp);
253
+
254
+ console.log(`Rollback point created for ${operationId}`);
255
+
256
+ return rollbackOp;
257
+
258
+ } catch (error) {
259
+ console.error(`Failed to create rollback point for ${operationId}:`, error.message);
260
+ throw error;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Execute rollback for a failed operation
266
+ */
267
+ async executeRollback(operationId, reason = 'Operation failed') {
268
+ if (this.isRollingBack) {
269
+ throw new Error('Rollback already in progress');
270
+ }
271
+
272
+ this.isRollingBack = true;
273
+ const rollbackId = this.generateRollbackId();
274
+ const result = new RollbackResult(rollbackId);
275
+ result.setTriggerReason(reason);
276
+
277
+ try {
278
+ console.log(`Executing rollback for operation: ${operationId}`);
279
+ result.setStatus(ROLLBACK_STATUS.RUNNING);
280
+
281
+ // Get rollback operations for the operation
282
+ const rollbackOps = this.rollbackHistory.get(operationId) || [];
283
+
284
+ if (rollbackOps.length === 0) {
285
+ throw new Error(`No rollback point found for operation: ${operationId}`);
286
+ }
287
+
288
+ // Execute rollback operations in reverse order
289
+ const reversedOps = rollbackOps.reverse();
290
+
291
+ for (const rollbackOp of reversedOps) {
292
+ try {
293
+ await this.executeRollbackOperation(rollbackOp);
294
+ result.addOperation(rollbackOp);
295
+ } catch (error) {
296
+ rollbackOp.addError(error);
297
+ rollbackOp.setStatus(ROLLBACK_STATUS.FAILED);
298
+ rollbackOp.setSuccess(false);
299
+ result.addOperation(rollbackOp);
300
+
301
+ // Continue with other operations even if one fails
302
+ console.warn(`Rollback operation failed: ${rollbackOp.id}`, error.message);
303
+ }
304
+ }
305
+
306
+ // Validate rollback if enabled
307
+ if (this.options.validateAfterRollback) {
308
+ await this.validateRollback(result);
309
+ }
310
+
311
+ result.calculateSummary();
312
+
313
+ console.log(`Rollback completed: ${result.success ? 'SUCCESS' : 'PARTIAL/FAILED'}`);
314
+
315
+ } catch (error) {
316
+ result.addError(error);
317
+ result.setStatus(ROLLBACK_STATUS.FAILED);
318
+ result.setSuccess(false);
319
+ console.error(`Rollback execution failed:`, error.message);
320
+ } finally {
321
+ this.isRollingBack = false;
322
+ this.currentRollback = result;
323
+ }
324
+
325
+ return result;
326
+ }
327
+
328
+ /**
329
+ * Execute individual rollback operation
330
+ */
331
+ async executeRollbackOperation(rollbackOp) {
332
+ console.log(`Executing rollback operation: ${rollbackOp.id}`);
333
+ rollbackOp.setStatus(ROLLBACK_STATUS.RUNNING);
334
+
335
+ try {
336
+ if (!rollbackOp.metadata.backupPath || !fs.existsSync(rollbackOp.metadata.backupPath)) {
337
+ throw new Error(`Backup file not found: ${rollbackOp.metadata.backupPath}`);
338
+ }
339
+
340
+ // Restore file from backup
341
+ const targetDir = path.dirname(rollbackOp.targetPath);
342
+ if (!fs.existsSync(targetDir)) {
343
+ fs.mkdirSync(targetDir, { recursive: true });
344
+ }
345
+
346
+ fs.copyFileSync(rollbackOp.metadata.backupPath, rollbackOp.targetPath);
347
+
348
+ // Verify restoration
349
+ if (fs.existsSync(rollbackOp.targetPath)) {
350
+ const restoredSize = fs.statSync(rollbackOp.targetPath).size;
351
+ rollbackOp.setRestoredSize(restoredSize);
352
+
353
+ // Check if size matches (basic integrity check)
354
+ if (Math.abs(restoredSize - rollbackOp.metadata.originalSize) > 100) {
355
+ rollbackOp.addWarning('File size difference detected after restoration');
356
+ }
357
+ } else {
358
+ throw new Error('Failed to restore file');
359
+ }
360
+
361
+ rollbackOp.setStatus(ROLLBACK_STATUS.COMPLETED);
362
+ rollbackOp.setSuccess(true);
363
+
364
+ console.log(`Rollback operation completed: ${rollbackOp.id}`);
365
+
366
+ } catch (error) {
367
+ rollbackOp.addError(error);
368
+ rollbackOp.setStatus(ROLLBACK_STATUS.FAILED);
369
+ rollbackOp.setSuccess(false);
370
+ throw error;
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Validate rollback results
376
+ */
377
+ async validateRollback(result) {
378
+ console.log('Validating rollback results...');
379
+
380
+ for (const operation of result.operations) {
381
+ if (operation.success) {
382
+ try {
383
+ // Basic file existence check
384
+ if (!fs.existsSync(operation.targetPath)) {
385
+ operation.addWarning('Target file does not exist after rollback');
386
+ }
387
+
388
+ // Basic syntax check for JavaScript files
389
+ if (operation.targetPath.endsWith('.js') && fs.existsSync(operation.targetPath)) {
390
+ const content = fs.readFileSync(operation.targetPath, 'utf8');
391
+ this.validateJavaScriptSyntax(content);
392
+ }
393
+
394
+ } catch (error) {
395
+ operation.addError(error);
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Validate JavaScript syntax
403
+ */
404
+ validateJavaScriptSyntax(content) {
405
+ try {
406
+ const vm = require('vm');
407
+ new vm.Script(content, { filename: 'validation' });
408
+ } catch (error) {
409
+ throw new Error(`JavaScript syntax validation failed: ${error.message}`);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Cancel current rollback
415
+ */
416
+ async cancelRollback() {
417
+ if (!this.isRollingBack || !this.currentRollback) {
418
+ return false;
419
+ }
420
+
421
+ this.currentRollback.setStatus(ROLLBACK_STATUS.FAILED);
422
+ this.currentRollback.addError(new Error('Rollback cancelled by user'));
423
+ this.isRollingBack = false;
424
+
425
+ return true;
426
+ }
427
+
428
+ /**
429
+ * Get rollback status
430
+ */
431
+ getRollbackStatus() {
432
+ return {
433
+ isRollingBack: this.isRollingBack,
434
+ currentRollback: this.currentRollback ? this.currentRollback.getSummary() : null,
435
+ rollbackHistory: Array.from(this.rollbackHistory.entries()).map(([opId, ops]) => ({
436
+ operationId: opId,
437
+ rollbackOperations: ops.length,
438
+ lastRollback: ops[ops.length - 1]?.getSummary()
439
+ }))
440
+ };
441
+ }
442
+
443
+ /**
444
+ * Clean up old rollback points
445
+ */
446
+ async cleanup(maxAge = 7 * 24 * 60 * 60 * 1000) { // 7 days default
447
+ console.log('Cleaning up old rollback points...');
448
+
449
+ let cleaned = 0;
450
+ const now = Date.now();
451
+
452
+ for (const [operationId, rollbackOps] of this.rollbackHistory.entries()) {
453
+ const recentOps = rollbackOps.filter(op => {
454
+ const createdAt = new Date(op.metadata.createdAt).getTime();
455
+ return (now - createdAt) < maxAge;
456
+ });
457
+
458
+ if (recentOps.length < rollbackOps.length) {
459
+ this.rollbackHistory.set(operationId, recentOps);
460
+ cleaned += rollbackOps.length - recentOps.length;
461
+ }
462
+ }
463
+
464
+ // Clean up rollback manager backups
465
+ const backupCleaned = this.rollbackManager.cleanup(maxAge);
466
+
467
+ console.log(`Cleanup completed: ${cleaned} rollback operations, ${backupCleaned} backup files`);
468
+
469
+ return { rollbackOperations: cleaned, backupFiles: backupCleaned };
470
+ }
471
+
472
+ /**
473
+ * Get rollback statistics
474
+ */
475
+ getStatistics() {
476
+ const stats = {
477
+ totalRollbackPoints: 0,
478
+ totalRollbacks: 0,
479
+ successfulRollbacks: 0,
480
+ failedRollbacks: 0,
481
+ partialRollbacks: 0,
482
+ averageRollbackTime: 0,
483
+ commonFailureReasons: {},
484
+ oldestRollback: null,
485
+ newestRollback: null
486
+ };
487
+
488
+ let totalTime = 0;
489
+ let oldestTime = null;
490
+ let newestTime = null;
491
+ const failureReasons = {};
492
+
493
+ for (const rollbackOps of this.rollbackHistory.values()) {
494
+ stats.totalRollbackPoints += rollbackOps.length;
495
+
496
+ for (const op of rollbackOps) {
497
+ if (op.endTime) {
498
+ const opTime = new Date(op.endTime);
499
+ if (!oldestTime || opTime < oldestTime) oldestTime = opTime;
500
+ if (!newestTime || opTime > newestTime) newestTime = opTime;
501
+ }
502
+ }
503
+ }
504
+
505
+ stats.oldestRollback = oldestTime ? oldestTime.toISOString() : null;
506
+ stats.newestRollback = newestTime ? newestTime.toISOString() : null;
507
+
508
+ return stats;
509
+ }
510
+
511
+ /**
512
+ * Export rollback data
513
+ */
514
+ exportRollbackData(format = 'json') {
515
+ const exportData = {
516
+ metadata: {
517
+ exportedAt: new Date().toISOString(),
518
+ version: '1.0.0',
519
+ options: this.options
520
+ },
521
+ rollbackHistory: Array.from(this.rollbackHistory.entries()).map(([opId, ops]) => ({
522
+ operationId: opId,
523
+ operations: ops.map(op => op.getSummary())
524
+ })),
525
+ currentRollback: this.currentRollback ? this.currentRollback.getSummary() : null,
526
+ statistics: this.getStatistics()
527
+ };
528
+
529
+ if (format === 'json') {
530
+ return JSON.stringify(exportData, null, 2);
531
+ }
532
+
533
+ return exportData;
534
+ }
535
+
536
+ /**
537
+ * Generate rollback ID
538
+ */
539
+ generateRollbackId() {
540
+ return `rollback_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
541
+ }
542
+
543
+ /**
544
+ * Check if rollback is available for an operation
545
+ */
546
+ hasRollbackPoint(operationId) {
547
+ const rollbackOps = this.rollbackHistory.get(operationId);
548
+ return rollbackOps && rollbackOps.length > 0;
549
+ }
550
+
551
+ /**
552
+ * Get rollback operations for an operation
553
+ */
554
+ getRollbackOperations(operationId) {
555
+ return this.rollbackHistory.get(operationId) || [];
556
+ }
557
+
558
+ /**
559
+ * Remove rollback point for an operation
560
+ */
561
+ removeRollbackPoint(operationId) {
562
+ const rollbackOps = this.rollbackHistory.get(operationId);
563
+ if (rollbackOps) {
564
+ // Clean up backup files
565
+ for (const op of rollbackOps) {
566
+ if (op.metadata.backupPath && fs.existsSync(op.metadata.backupPath)) {
567
+ try {
568
+ fs.unlinkSync(op.metadata.backupPath);
569
+ } catch (error) {
570
+ console.warn(`Failed to cleanup backup file: ${op.metadata.backupPath}`, error.message);
571
+ }
572
+ }
573
+ }
574
+
575
+ this.rollbackHistory.delete(operationId);
576
+ return true;
577
+ }
578
+
579
+ return false;
580
+ }
581
+
582
+ /**
583
+ * Reset all rollback data
584
+ */
585
+ reset() {
586
+ console.log('Resetting all rollback data...');
587
+
588
+ // Clean up all backup files
589
+ for (const rollbackOps of this.rollbackHistory.values()) {
590
+ for (const op of rollbackOps) {
591
+ if (op.metadata.backupPath && fs.existsSync(op.metadata.backupPath)) {
592
+ try {
593
+ fs.unlinkSync(op.metadata.backupPath);
594
+ } catch (error) {
595
+ console.warn(`Failed to cleanup backup file: ${op.metadata.backupPath}`, error.message);
596
+ }
597
+ }
598
+ }
599
+ }
600
+
601
+ this.rollbackHistory.clear();
602
+ this.currentRollback = null;
603
+ this.isRollingBack = false;
604
+
605
+ console.log('Rollback data reset completed');
606
+ }
607
+ }
608
+
609
+ module.exports = {
610
+ RefactoringRollback,
611
+ RollbackOperation,
612
+ RollbackResult,
613
+ ROLLBACK_STATUS
614
+ };