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,569 @@
1
+ /**
2
+ * Rollback Manager
3
+ *
4
+ * Manages rollback capabilities for refactoring operations.
5
+ * Provides safe backup and restore functionality.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const crypto = require('crypto');
11
+
12
+ /**
13
+ * Rollback operation types
14
+ */
15
+ const ROLLBACK_TYPES = {
16
+ FILE_CREATE: 'file_create',
17
+ FILE_UPDATE: 'file_update',
18
+ FILE_DELETE: 'file_delete',
19
+ FILE_MOVE: 'file_move',
20
+ DIRECTORY_CREATE: 'directory_create',
21
+ DIRECTORY_DELETE: 'directory_delete'
22
+ };
23
+
24
+ /**
25
+ * Rollback operation class
26
+ */
27
+ class RollbackOperation {
28
+ constructor(type, targetPath, backupPath = null, metadata = {}) {
29
+ this.id = this.generateId();
30
+ this.type = type;
31
+ this.targetPath = targetPath;
32
+ this.backupPath = backupPath;
33
+ this.metadata = metadata;
34
+ this.timestamp = new Date().toISOString();
35
+ this.executed = false;
36
+ this.rollbackExecuted = false;
37
+ }
38
+
39
+ generateId() {
40
+ return crypto.randomBytes(16).toString('hex');
41
+ }
42
+
43
+ execute() {
44
+ this.executed = true;
45
+ this.executionTime = new Date().toISOString();
46
+ }
47
+
48
+ rollback() {
49
+ this.rollbackExecuted = true;
50
+ this.rollbackTime = new Date().toISOString();
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Rollback manager class
56
+ */
57
+ class RollbackManager {
58
+ constructor(backupDir = '.refactoring-backups') {
59
+ this.backupDir = path.resolve(backupDir);
60
+ this.operations = [];
61
+ this.sessionId = this.generateSessionId();
62
+ this.ensureBackupDirectory();
63
+ }
64
+
65
+ /**
66
+ * Generate unique session ID
67
+ */
68
+ generateSessionId() {
69
+ return `session_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
70
+ }
71
+
72
+ /**
73
+ * Ensure backup directory exists
74
+ */
75
+ ensureBackupDirectory() {
76
+ if (!fs.existsSync(this.backupDir)) {
77
+ fs.mkdirSync(this.backupDir, { recursive: true });
78
+ }
79
+
80
+ const sessionDir = path.join(this.backupDir, this.sessionId);
81
+ if (!fs.existsSync(sessionDir)) {
82
+ fs.mkdirSync(sessionDir, { recursive: true });
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Get session backup directory
88
+ */
89
+ getSessionBackupDir() {
90
+ return path.join(this.backupDir, this.sessionId);
91
+ }
92
+
93
+ /**
94
+ * Create backup of a file before modification
95
+ */
96
+ backupFile(filePath) {
97
+ if (!fs.existsSync(filePath)) {
98
+ throw new Error(`File not found for backup: ${filePath}`);
99
+ }
100
+
101
+ const backupPath = this.getBackupPath(filePath);
102
+ const backupDir = path.dirname(backupPath);
103
+
104
+ // Ensure backup directory exists
105
+ if (!fs.existsSync(backupDir)) {
106
+ fs.mkdirSync(backupDir, { recursive: true });
107
+ }
108
+
109
+ // Copy file to backup location
110
+ fs.copyFileSync(filePath, backupPath);
111
+
112
+ const operation = new RollbackOperation(
113
+ ROLLBACK_TYPES.FILE_UPDATE,
114
+ filePath,
115
+ backupPath,
116
+ {
117
+ originalSize: fs.statSync(filePath).size,
118
+ originalModified: fs.statSync(filePath).mtime.toISOString()
119
+ }
120
+ );
121
+
122
+ this.operations.push(operation);
123
+ return operation;
124
+ }
125
+
126
+ /**
127
+ * Record file creation
128
+ */
129
+ recordFileCreation(filePath) {
130
+ const operation = new RollbackOperation(
131
+ ROLLBACK_TYPES.FILE_CREATE,
132
+ filePath,
133
+ null,
134
+ {
135
+ createdTime: fs.existsSync(filePath) ? fs.statSync(filePath).mtime.toISOString() : null
136
+ }
137
+ );
138
+
139
+ this.operations.push(operation);
140
+ return operation;
141
+ }
142
+
143
+ /**
144
+ * Record file deletion (with backup)
145
+ */
146
+ recordFileDeletion(filePath) {
147
+ let backupPath = null;
148
+
149
+ if (fs.existsSync(filePath)) {
150
+ backupPath = this.getBackupPath(filePath);
151
+ const backupDir = path.dirname(backupPath);
152
+
153
+ if (!fs.existsSync(backupDir)) {
154
+ fs.mkdirSync(backupDir, { recursive: true });
155
+ }
156
+
157
+ fs.copyFileSync(filePath, backupPath);
158
+ }
159
+
160
+ const operation = new RollbackOperation(
161
+ ROLLBACK_TYPES.FILE_DELETE,
162
+ filePath,
163
+ backupPath,
164
+ {
165
+ originalSize: fs.existsSync(filePath) ? fs.statSync(filePath).size : 0,
166
+ originalModified: fs.existsSync(filePath) ? fs.statSync(filePath).mtime.toISOString() : null
167
+ }
168
+ );
169
+
170
+ this.operations.push(operation);
171
+ return operation;
172
+ }
173
+
174
+ /**
175
+ * Record file move/rename
176
+ */
177
+ recordFileMove(oldPath, newPath) {
178
+ const backupPath = this.getBackupPath(oldPath);
179
+ const backupDir = path.dirname(backupPath);
180
+
181
+ if (!fs.existsSync(backupDir)) {
182
+ fs.mkdirSync(backupDir, { recursive: true });
183
+ }
184
+
185
+ if (fs.existsSync(oldPath)) {
186
+ fs.copyFileSync(oldPath, backupPath);
187
+ }
188
+
189
+ const operation = new RollbackOperation(
190
+ ROLLBACK_TYPES.FILE_MOVE,
191
+ newPath,
192
+ backupPath,
193
+ {
194
+ originalPath: oldPath,
195
+ newPath: newPath
196
+ }
197
+ );
198
+
199
+ this.operations.push(operation);
200
+ return operation;
201
+ }
202
+
203
+ /**
204
+ * Record directory creation
205
+ */
206
+ recordDirectoryCreation(dirPath) {
207
+ const operation = new RollbackOperation(
208
+ ROLLBACK_TYPES.DIRECTORY_CREATE,
209
+ dirPath,
210
+ null,
211
+ {
212
+ createdTime: fs.existsSync(dirPath) ? fs.statSync(dirPath).mtime.toISOString() : null
213
+ }
214
+ );
215
+
216
+ this.operations.push(operation);
217
+ return operation;
218
+ }
219
+
220
+ /**
221
+ * Record directory deletion (with backup)
222
+ */
223
+ recordDirectoryDeletion(dirPath) {
224
+ const backupPath = this.getBackupPath(dirPath);
225
+
226
+ if (fs.existsSync(dirPath)) {
227
+ this.copyDirectory(dirPath, backupPath);
228
+ }
229
+
230
+ const operation = new RollbackOperation(
231
+ ROLLBACK_TYPES.DIRECTORY_DELETE,
232
+ dirPath,
233
+ backupPath,
234
+ {
235
+ originalPath: dirPath
236
+ }
237
+ );
238
+
239
+ this.operations.push(operation);
240
+ return operation;
241
+ }
242
+
243
+ /**
244
+ * Execute rollback for all operations
245
+ */
246
+ async rollback() {
247
+ const results = {
248
+ success: [],
249
+ failed: [],
250
+ skipped: []
251
+ };
252
+
253
+ // Execute rollbacks in reverse order
254
+ for (let i = this.operations.length - 1; i >= 0; i--) {
255
+ const operation = this.operations[i];
256
+
257
+ try {
258
+ await this.rollbackOperation(operation);
259
+ results.success.push(operation);
260
+ } catch (error) {
261
+ operation.error = error.message;
262
+ results.failed.push(operation);
263
+ }
264
+ }
265
+
266
+ return results;
267
+ }
268
+
269
+ /**
270
+ * Rollback a single operation
271
+ */
272
+ async rollbackOperation(operation) {
273
+ if (operation.rollbackExecuted) {
274
+ throw new Error(`Operation already rolled back: ${operation.id}`);
275
+ }
276
+
277
+ switch (operation.type) {
278
+ case ROLLBACK_TYPES.FILE_UPDATE:
279
+ await this.rollbackFileUpdate(operation);
280
+ break;
281
+ case ROLLBACK_TYPES.FILE_CREATE:
282
+ await this.rollbackFileCreate(operation);
283
+ break;
284
+ case ROLLBACK_TYPES.FILE_DELETE:
285
+ await this.rollbackFileDelete(operation);
286
+ break;
287
+ case ROLLBACK_TYPES.FILE_MOVE:
288
+ await this.rollbackFileMove(operation);
289
+ break;
290
+ case ROLLBACK_TYPES.DIRECTORY_CREATE:
291
+ await this.rollbackDirectoryCreate(operation);
292
+ break;
293
+ case ROLLBACK_TYPES.DIRECTORY_DELETE:
294
+ await this.rollbackDirectoryDelete(operation);
295
+ break;
296
+ default:
297
+ throw new Error(`Unknown rollback operation type: ${operation.type}`);
298
+ }
299
+
300
+ operation.rollback();
301
+ }
302
+
303
+ /**
304
+ * Rollback file update
305
+ */
306
+ async rollbackFileUpdate(operation) {
307
+ if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
308
+ throw new Error(`Backup not found for file update: ${operation.targetPath}`);
309
+ }
310
+
311
+ // Restore original file
312
+ fs.copyFileSync(operation.backupPath, operation.targetPath);
313
+ }
314
+
315
+ /**
316
+ * Rollback file creation
317
+ */
318
+ async rollbackFileCreate(operation) {
319
+ if (fs.existsSync(operation.targetPath)) {
320
+ fs.unlinkSync(operation.targetPath);
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Rollback file deletion
326
+ */
327
+ async rollbackFileDelete(operation) {
328
+ if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
329
+ throw new Error(`Backup not found for file deletion: ${operation.targetPath}`);
330
+ }
331
+
332
+ // Ensure target directory exists
333
+ const targetDir = path.dirname(operation.targetPath);
334
+ if (!fs.existsSync(targetDir)) {
335
+ fs.mkdirSync(targetDir, { recursive: true });
336
+ }
337
+
338
+ // Restore deleted file
339
+ fs.copyFileSync(operation.backupPath, operation.targetPath);
340
+ }
341
+
342
+ /**
343
+ * Rollback file move
344
+ */
345
+ async rollbackFileMove(operation) {
346
+ const originalPath = operation.metadata.originalPath;
347
+
348
+ if (fs.existsSync(operation.targetPath)) {
349
+ // Move file back to original location
350
+ fs.renameSync(operation.targetPath, originalPath);
351
+ }
352
+ }
353
+
354
+ /**
355
+ * Rollback directory creation
356
+ */
357
+ async rollbackDirectoryCreate(operation) {
358
+ if (fs.existsSync(operation.targetPath)) {
359
+ fs.rmSync(operation.targetPath, { recursive: true, force: true });
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Rollback directory deletion
365
+ */
366
+ async rollbackDirectoryDelete(operation) {
367
+ if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
368
+ throw new Error(`Backup not found for directory deletion: ${operation.targetPath}`);
369
+ }
370
+
371
+ // Restore deleted directory
372
+ this.copyDirectory(operation.backupPath, operation.targetPath);
373
+ }
374
+
375
+ /**
376
+ * Get backup path for a file
377
+ */
378
+ getBackupPath(filePath) {
379
+ const relativePath = path.relative(process.cwd(), filePath);
380
+ const backupPath = path.join(this.getSessionBackupDir(), relativePath);
381
+ return backupPath;
382
+ }
383
+
384
+ /**
385
+ * Copy directory recursively
386
+ */
387
+ copyDirectory(src, dest) {
388
+ if (!fs.existsSync(dest)) {
389
+ fs.mkdirSync(dest, { recursive: true });
390
+ }
391
+
392
+ const entries = fs.readdirSync(src, { withFileTypes: true });
393
+
394
+ for (const entry of entries) {
395
+ const srcPath = path.join(src, entry.name);
396
+ const destPath = path.join(dest, entry.name);
397
+
398
+ if (entry.isDirectory()) {
399
+ this.copyDirectory(srcPath, destPath);
400
+ } else {
401
+ fs.copyFileSync(srcPath, destPath);
402
+ }
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Get operation summary
408
+ */
409
+ getSummary() {
410
+ const summary = {
411
+ sessionId: this.sessionId,
412
+ totalOperations: this.operations.length,
413
+ executedOperations: this.operations.filter(op => op.executed).length,
414
+ rollbackOperations: this.operations.filter(op => op.rollbackExecuted).length,
415
+ byType: {},
416
+ backupDirectory: this.getSessionBackupDir()
417
+ };
418
+
419
+ // Count operations by type
420
+ for (const operation of this.operations) {
421
+ if (!summary.byType[operation.type]) {
422
+ summary.byType[operation.type] = 0;
423
+ }
424
+ summary.byType[operation.type]++;
425
+ }
426
+
427
+ return summary;
428
+ }
429
+
430
+ /**
431
+ * Save rollback state to file
432
+ */
433
+ saveState() {
434
+ const stateFile = path.join(this.getSessionBackupDir(), 'rollback-state.json');
435
+ const state = {
436
+ sessionId: this.sessionId,
437
+ operations: this.operations,
438
+ summary: this.getSummary(),
439
+ savedAt: new Date().toISOString()
440
+ };
441
+
442
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
443
+ return stateFile;
444
+ }
445
+
446
+ /**
447
+ * Load rollback state from file
448
+ */
449
+ loadState(sessionId) {
450
+ const sessionDir = path.join(this.backupDir, sessionId);
451
+ const stateFile = path.join(sessionDir, 'rollback-state.json');
452
+
453
+ if (!fs.existsSync(stateFile)) {
454
+ throw new Error(`Rollback state not found: ${sessionId}`);
455
+ }
456
+
457
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
458
+ this.sessionId = state.sessionId;
459
+ this.operations = state.operations.map(op => Object.assign(new RollbackOperation(), op));
460
+
461
+ return state;
462
+ }
463
+
464
+ /**
465
+ * List available rollback sessions
466
+ */
467
+ listSessions() {
468
+ if (!fs.existsSync(this.backupDir)) {
469
+ return [];
470
+ }
471
+
472
+ const sessions = [];
473
+ const entries = fs.readdirSync(this.backupDir, { withFileTypes: true });
474
+
475
+ for (const entry of entries) {
476
+ if (entry.isDirectory() && entry.name.startsWith('session_')) {
477
+ const sessionDir = path.join(this.backupDir, entry.name);
478
+ const stateFile = path.join(sessionDir, 'rollback-state.json');
479
+
480
+ if (fs.existsSync(stateFile)) {
481
+ try {
482
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
483
+ sessions.push({
484
+ sessionId: state.sessionId,
485
+ operationCount: state.operations.length,
486
+ createdAt: entry.name.replace('session_', '').split('_')[0],
487
+ summary: state.summary
488
+ });
489
+ } catch (error) {
490
+ // Skip invalid sessions
491
+ }
492
+ }
493
+ }
494
+ }
495
+
496
+ return sessions.sort((a, b) => b.createdAt - a.createdAt);
497
+ }
498
+
499
+ /**
500
+ * Cleanup old backup sessions
501
+ */
502
+ cleanup(maxAge = 7 * 24 * 60 * 60 * 1000) { // 7 days default
503
+ const sessions = this.listSessions();
504
+ const now = Date.now();
505
+ let cleaned = 0;
506
+
507
+ for (const session of sessions) {
508
+ const sessionAge = now - parseInt(session.createdAt);
509
+ if (sessionAge > maxAge) {
510
+ const sessionDir = path.join(this.backupDir, session.sessionId);
511
+ fs.rmSync(sessionDir, { recursive: true, force: true });
512
+ cleaned++;
513
+ }
514
+ }
515
+
516
+ return cleaned;
517
+ }
518
+
519
+ /**
520
+ * Clear current session operations
521
+ */
522
+ clear() {
523
+ this.operations = [];
524
+ }
525
+
526
+ /**
527
+ * Get backup size
528
+ */
529
+ getBackupSize() {
530
+ const sessionDir = this.getSessionBackupDir();
531
+ if (!fs.existsSync(sessionDir)) {
532
+ return 0;
533
+ }
534
+
535
+ return this.getDirectorySize(sessionDir);
536
+ }
537
+
538
+ /**
539
+ * Get directory size recursively
540
+ */
541
+ getDirectorySize(dirPath) {
542
+ let totalSize = 0;
543
+
544
+ try {
545
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
546
+
547
+ for (const entry of entries) {
548
+ const fullPath = path.join(dirPath, entry.name);
549
+
550
+ if (entry.isDirectory()) {
551
+ totalSize += this.getDirectorySize(fullPath);
552
+ } else {
553
+ totalSize += fs.statSync(fullPath).size;
554
+ }
555
+ }
556
+ } catch (error) {
557
+ // Directory might not exist or be inaccessible
558
+ }
559
+
560
+ return totalSize;
561
+ }
562
+ }
563
+
564
+ module.exports = {
565
+ RollbackManager,
566
+ RollbackOperation,
567
+ ROLLBACK_TYPES
568
+ };
569
+ // Updated for 800 line limit test