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,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Handlers
|
|
3
|
+
*
|
|
4
|
+
* Contains the actual rollback execution logic for different operation types.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { ROLLBACK_TYPES } = require('./rollback-types');
|
|
10
|
+
const { RollbackUtils } = require('./rollback-utils');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Rollback execution handlers
|
|
14
|
+
*/
|
|
15
|
+
class RollbackHandlers {
|
|
16
|
+
/**
|
|
17
|
+
* Rollback file update
|
|
18
|
+
*/
|
|
19
|
+
static async rollbackFileUpdate(operation) {
|
|
20
|
+
if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
|
|
21
|
+
throw new Error(`Backup not found for file update: ${operation.targetPath}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Restore original file
|
|
25
|
+
fs.copyFileSync(operation.backupPath, operation.targetPath);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Rollback file creation
|
|
30
|
+
*/
|
|
31
|
+
static async rollbackFileCreate(operation) {
|
|
32
|
+
if (fs.existsSync(operation.targetPath)) {
|
|
33
|
+
fs.unlinkSync(operation.targetPath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Rollback file deletion
|
|
39
|
+
*/
|
|
40
|
+
static async rollbackFileDelete(operation) {
|
|
41
|
+
if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
|
|
42
|
+
throw new Error(`Backup not found for file deletion: ${operation.targetPath}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Ensure target directory exists
|
|
46
|
+
const targetDir = path.dirname(operation.targetPath);
|
|
47
|
+
if (!fs.existsSync(targetDir)) {
|
|
48
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Restore deleted file
|
|
52
|
+
fs.copyFileSync(operation.backupPath, operation.targetPath);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Rollback file move
|
|
57
|
+
*/
|
|
58
|
+
static async rollbackFileMove(operation) {
|
|
59
|
+
const originalPath = operation.metadata.originalPath;
|
|
60
|
+
|
|
61
|
+
if (fs.existsSync(operation.targetPath)) {
|
|
62
|
+
// Move file back to original location
|
|
63
|
+
fs.renameSync(operation.targetPath, originalPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Rollback directory creation
|
|
69
|
+
*/
|
|
70
|
+
static async rollbackDirectoryCreate(operation) {
|
|
71
|
+
if (fs.existsSync(operation.targetPath)) {
|
|
72
|
+
fs.rmSync(operation.targetPath, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Rollback directory deletion
|
|
78
|
+
*/
|
|
79
|
+
static async rollbackDirectoryDelete(operation) {
|
|
80
|
+
if (!operation.backupPath || !fs.existsSync(operation.backupPath)) {
|
|
81
|
+
throw new Error(`Backup not found for directory deletion: ${operation.targetPath}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Restore deleted directory
|
|
85
|
+
RollbackUtils.copyDirectory(operation.backupPath, operation.targetPath);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Rollback a single operation by type
|
|
90
|
+
*/
|
|
91
|
+
static async rollbackOperation(operation) {
|
|
92
|
+
if (operation.rollbackExecuted) {
|
|
93
|
+
throw new Error(`Operation already rolled back: ${operation.id}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
switch (operation.type) {
|
|
97
|
+
case ROLLBACK_TYPES.FILE_UPDATE:
|
|
98
|
+
await RollbackHandlers.rollbackFileUpdate(operation);
|
|
99
|
+
break;
|
|
100
|
+
case ROLLBACK_TYPES.FILE_CREATE:
|
|
101
|
+
await RollbackHandlers.rollbackFileCreate(operation);
|
|
102
|
+
break;
|
|
103
|
+
case ROLLBACK_TYPES.FILE_DELETE:
|
|
104
|
+
await RollbackHandlers.rollbackFileDelete(operation);
|
|
105
|
+
break;
|
|
106
|
+
case ROLLBACK_TYPES.FILE_MOVE:
|
|
107
|
+
await RollbackHandlers.rollbackFileMove(operation);
|
|
108
|
+
break;
|
|
109
|
+
case ROLLBACK_TYPES.DIRECTORY_CREATE:
|
|
110
|
+
await RollbackHandlers.rollbackDirectoryCreate(operation);
|
|
111
|
+
break;
|
|
112
|
+
case ROLLBACK_TYPES.DIRECTORY_DELETE:
|
|
113
|
+
await RollbackHandlers.rollbackDirectoryDelete(operation);
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
throw new Error(`Unknown rollback operation type: ${operation.type}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
operation.rollback();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
RollbackHandlers
|
|
125
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Operation
|
|
3
|
+
*
|
|
4
|
+
* Represents a single rollback operation with metadata and state tracking.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Rollback operation class
|
|
11
|
+
*/
|
|
12
|
+
class RollbackOperation {
|
|
13
|
+
constructor(type, targetPath, backupPath = null, metadata = {}) {
|
|
14
|
+
this.id = this.generateId();
|
|
15
|
+
this.type = type;
|
|
16
|
+
this.targetPath = targetPath;
|
|
17
|
+
this.backupPath = backupPath;
|
|
18
|
+
this.metadata = metadata;
|
|
19
|
+
this.timestamp = new Date().toISOString();
|
|
20
|
+
this.executed = false;
|
|
21
|
+
this.rollbackExecuted = false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
generateId() {
|
|
25
|
+
return crypto.randomBytes(16).toString('hex');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
execute() {
|
|
29
|
+
this.executed = true;
|
|
30
|
+
this.executionTime = new Date().toISOString();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
rollback() {
|
|
34
|
+
this.rollbackExecuted = true;
|
|
35
|
+
this.rollbackTime = new Date().toISOString();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if operation can be rolled back
|
|
40
|
+
*/
|
|
41
|
+
canRollback() {
|
|
42
|
+
return this.executed && !this.rollbackExecuted;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get operation summary
|
|
47
|
+
*/
|
|
48
|
+
getSummary() {
|
|
49
|
+
return {
|
|
50
|
+
id: this.id,
|
|
51
|
+
type: this.type,
|
|
52
|
+
targetPath: this.targetPath,
|
|
53
|
+
timestamp: this.timestamp,
|
|
54
|
+
executed: this.executed,
|
|
55
|
+
rollbackExecuted: this.rollbackExecuted,
|
|
56
|
+
hasBackup: !!this.backupPath
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
RollbackOperation
|
|
63
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Recorder
|
|
3
|
+
*
|
|
4
|
+
* Handles recording of operations for potential rollback.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const { RollbackOperation } = require('./rollback-operation');
|
|
11
|
+
const { ROLLBACK_TYPES } = require('./rollback-types');
|
|
12
|
+
const { RollbackUtils } = require('./rollback-utils');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Rollback recording functionality
|
|
16
|
+
*/
|
|
17
|
+
class RollbackRecorder {
|
|
18
|
+
constructor(backupDir, sessionId) {
|
|
19
|
+
this.backupDir = backupDir;
|
|
20
|
+
this.sessionId = sessionId;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get session backup directory
|
|
25
|
+
*/
|
|
26
|
+
getSessionBackupDir() {
|
|
27
|
+
return path.join(this.backupDir, this.sessionId);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create backup of a file before modification
|
|
32
|
+
*/
|
|
33
|
+
backupFile(filePath) {
|
|
34
|
+
if (!fs.existsSync(filePath)) {
|
|
35
|
+
throw new Error(`File not found for backup: ${filePath}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const backupPath = RollbackUtils.getBackupPath(this.getSessionBackupDir(), filePath);
|
|
39
|
+
RollbackUtils.safeCopyFile(filePath, backupPath);
|
|
40
|
+
|
|
41
|
+
const metadata = RollbackUtils.getFileMetadata(filePath);
|
|
42
|
+
|
|
43
|
+
const operation = new RollbackOperation(
|
|
44
|
+
ROLLBACK_TYPES.FILE_UPDATE,
|
|
45
|
+
filePath,
|
|
46
|
+
backupPath,
|
|
47
|
+
{
|
|
48
|
+
originalSize: metadata.size,
|
|
49
|
+
originalModified: metadata.modified
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return operation;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Record file creation
|
|
58
|
+
*/
|
|
59
|
+
recordFileCreation(filePath) {
|
|
60
|
+
const metadata = RollbackUtils.getFileMetadata(filePath);
|
|
61
|
+
|
|
62
|
+
const operation = new RollbackOperation(
|
|
63
|
+
ROLLBACK_TYPES.FILE_CREATE,
|
|
64
|
+
filePath,
|
|
65
|
+
null,
|
|
66
|
+
{
|
|
67
|
+
createdTime: metadata.modified
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return operation;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Record file deletion (with backup)
|
|
76
|
+
*/
|
|
77
|
+
recordFileDeletion(filePath) {
|
|
78
|
+
let backupPath = null;
|
|
79
|
+
|
|
80
|
+
if (fs.existsSync(filePath)) {
|
|
81
|
+
backupPath = RollbackUtils.getBackupPath(this.getSessionBackupDir(), filePath);
|
|
82
|
+
RollbackUtils.safeCopyFile(filePath, backupPath);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const metadata = RollbackUtils.getFileMetadata(filePath);
|
|
86
|
+
|
|
87
|
+
const operation = new RollbackOperation(
|
|
88
|
+
ROLLBACK_TYPES.FILE_DELETE,
|
|
89
|
+
filePath,
|
|
90
|
+
backupPath,
|
|
91
|
+
{
|
|
92
|
+
originalSize: metadata.size,
|
|
93
|
+
originalModified: metadata.modified
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return operation;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Record file move/rename
|
|
102
|
+
*/
|
|
103
|
+
recordFileMove(oldPath, newPath) {
|
|
104
|
+
const backupPath = RollbackUtils.getBackupPath(this.getSessionBackupDir(), oldPath);
|
|
105
|
+
|
|
106
|
+
if (fs.existsSync(oldPath)) {
|
|
107
|
+
RollbackUtils.safeCopyFile(oldPath, backupPath);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const operation = new RollbackOperation(
|
|
111
|
+
ROLLBACK_TYPES.FILE_MOVE,
|
|
112
|
+
newPath,
|
|
113
|
+
backupPath,
|
|
114
|
+
{
|
|
115
|
+
originalPath: oldPath,
|
|
116
|
+
newPath: newPath
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return operation;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Record directory creation
|
|
125
|
+
*/
|
|
126
|
+
recordDirectoryCreation(dirPath) {
|
|
127
|
+
const metadata = RollbackUtils.getFileMetadata(dirPath);
|
|
128
|
+
|
|
129
|
+
const operation = new RollbackOperation(
|
|
130
|
+
ROLLBACK_TYPES.DIRECTORY_CREATE,
|
|
131
|
+
dirPath,
|
|
132
|
+
null,
|
|
133
|
+
{
|
|
134
|
+
createdTime: metadata.modified
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
return operation;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Record directory deletion (with backup)
|
|
143
|
+
*/
|
|
144
|
+
recordDirectoryDeletion(dirPath) {
|
|
145
|
+
const backupPath = RollbackUtils.getBackupPath(this.getSessionBackupDir(), dirPath);
|
|
146
|
+
|
|
147
|
+
if (fs.existsSync(dirPath)) {
|
|
148
|
+
RollbackUtils.copyDirectory(dirPath, backupPath);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const operation = new RollbackOperation(
|
|
152
|
+
ROLLBACK_TYPES.DIRECTORY_DELETE,
|
|
153
|
+
dirPath,
|
|
154
|
+
backupPath,
|
|
155
|
+
{
|
|
156
|
+
originalPath: dirPath
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return operation;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = {
|
|
165
|
+
RollbackRecorder
|
|
166
|
+
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback State Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles state persistence, session management, and cleanup operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const { RollbackOperation } = require('./rollback-operation');
|
|
11
|
+
const { DEFAULT_CLEANUP_AGE } = require('./rollback-types');
|
|
12
|
+
const { RollbackUtils } = require('./rollback-utils');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Rollback state management
|
|
16
|
+
*/
|
|
17
|
+
class RollbackStateManager {
|
|
18
|
+
constructor(backupDir) {
|
|
19
|
+
this.backupDir = backupDir;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Generate unique session ID
|
|
24
|
+
*/
|
|
25
|
+
generateSessionId() {
|
|
26
|
+
return `session_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Ensure backup directory exists
|
|
31
|
+
*/
|
|
32
|
+
ensureBackupDirectory(sessionId) {
|
|
33
|
+
if (!fs.existsSync(this.backupDir)) {
|
|
34
|
+
fs.mkdirSync(this.backupDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const sessionDir = path.join(this.backupDir, sessionId);
|
|
38
|
+
RollbackUtils.ensureDirectory(sessionDir);
|
|
39
|
+
|
|
40
|
+
return sessionDir;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Save rollback state to file
|
|
45
|
+
*/
|
|
46
|
+
saveState(sessionId, operations, summary) {
|
|
47
|
+
const sessionDir = path.join(this.backupDir, sessionId);
|
|
48
|
+
const stateFile = path.join(sessionDir, 'rollback-state.json');
|
|
49
|
+
|
|
50
|
+
const state = {
|
|
51
|
+
sessionId,
|
|
52
|
+
operations,
|
|
53
|
+
summary,
|
|
54
|
+
savedAt: new Date().toISOString()
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
|
|
58
|
+
return stateFile;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Load rollback state from file
|
|
63
|
+
*/
|
|
64
|
+
loadState(sessionId) {
|
|
65
|
+
const sessionDir = path.join(this.backupDir, sessionId);
|
|
66
|
+
const stateFile = path.join(sessionDir, 'rollback-state.json');
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(stateFile)) {
|
|
69
|
+
throw new Error(`Rollback state not found: ${sessionId}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
73
|
+
const operations = state.operations.map(op => Object.assign(new RollbackOperation(), op));
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
...state,
|
|
77
|
+
operations
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* List available rollback sessions
|
|
83
|
+
*/
|
|
84
|
+
listSessions() {
|
|
85
|
+
if (!fs.existsSync(this.backupDir)) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const sessions = [];
|
|
90
|
+
const entries = fs.readdirSync(this.backupDir, { withFileTypes: true });
|
|
91
|
+
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
if (entry.isDirectory() && entry.name.startsWith('session_')) {
|
|
94
|
+
const sessionDir = path.join(this.backupDir, entry.name);
|
|
95
|
+
const stateFile = path.join(sessionDir, 'rollback-state.json');
|
|
96
|
+
|
|
97
|
+
if (fs.existsSync(stateFile)) {
|
|
98
|
+
try {
|
|
99
|
+
const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
100
|
+
sessions.push({
|
|
101
|
+
sessionId: state.sessionId,
|
|
102
|
+
operationCount: state.operations.length,
|
|
103
|
+
createdAt: entry.name.replace('session_', '').split('_')[0],
|
|
104
|
+
summary: state.summary
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
// Skip invalid sessions
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return sessions.sort((a, b) => b.createdAt - a.createdAt);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Cleanup old backup sessions
|
|
118
|
+
*/
|
|
119
|
+
cleanup(maxAge = DEFAULT_CLEANUP_AGE) {
|
|
120
|
+
const sessions = this.listSessions();
|
|
121
|
+
const now = Date.now();
|
|
122
|
+
let cleaned = 0;
|
|
123
|
+
|
|
124
|
+
for (const session of sessions) {
|
|
125
|
+
const sessionAge = now - parseInt(session.createdAt);
|
|
126
|
+
if (sessionAge > maxAge) {
|
|
127
|
+
const sessionDir = path.join(this.backupDir, session.sessionId);
|
|
128
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
129
|
+
cleaned++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return cleaned;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get backup size for a session
|
|
138
|
+
*/
|
|
139
|
+
getBackupSize(sessionId) {
|
|
140
|
+
const sessionDir = path.join(this.backupDir, sessionId);
|
|
141
|
+
if (!fs.existsSync(sessionDir)) {
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return RollbackUtils.getDirectorySize(sessionDir);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Generate operation summary
|
|
150
|
+
*/
|
|
151
|
+
generateSummary(sessionId, operations) {
|
|
152
|
+
const summary = {
|
|
153
|
+
sessionId,
|
|
154
|
+
totalOperations: operations.length,
|
|
155
|
+
executedOperations: operations.filter(op => op.executed).length,
|
|
156
|
+
rollbackOperations: operations.filter(op => op.rollbackExecuted).length,
|
|
157
|
+
byType: {},
|
|
158
|
+
backupDirectory: path.join(this.backupDir, sessionId)
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Count operations by type
|
|
162
|
+
for (const operation of operations) {
|
|
163
|
+
if (!summary.byType[operation.type]) {
|
|
164
|
+
summary.byType[operation.type] = 0;
|
|
165
|
+
}
|
|
166
|
+
summary.byType[operation.type]++;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return summary;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
module.exports = {
|
|
174
|
+
RollbackStateManager
|
|
175
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Types and Constants
|
|
3
|
+
*
|
|
4
|
+
* Defines operation types and shared constants for rollback functionality.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Rollback operation types
|
|
9
|
+
*/
|
|
10
|
+
const ROLLBACK_TYPES = {
|
|
11
|
+
FILE_CREATE: 'file_create',
|
|
12
|
+
FILE_UPDATE: 'file_update',
|
|
13
|
+
FILE_DELETE: 'file_delete',
|
|
14
|
+
FILE_MOVE: 'file_move',
|
|
15
|
+
DIRECTORY_CREATE: 'directory_create',
|
|
16
|
+
DIRECTORY_DELETE: 'directory_delete'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default backup directory name
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_BACKUP_DIR = '.refactoring-backups';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default cleanup age (7 days in milliseconds)
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_CLEANUP_AGE = 7 * 24 * 60 * 60 * 1000;
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
ROLLBACK_TYPES,
|
|
31
|
+
DEFAULT_BACKUP_DIR,
|
|
32
|
+
DEFAULT_CLEANUP_AGE
|
|
33
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for backup operations, directory management, and file operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Rollback utility functions
|
|
12
|
+
*/
|
|
13
|
+
class RollbackUtils {
|
|
14
|
+
/**
|
|
15
|
+
* Copy directory recursively
|
|
16
|
+
*/
|
|
17
|
+
static copyDirectory(src, dest) {
|
|
18
|
+
if (!fs.existsSync(dest)) {
|
|
19
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
23
|
+
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const srcPath = path.join(src, entry.name);
|
|
26
|
+
const destPath = path.join(dest, entry.name);
|
|
27
|
+
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
RollbackUtils.copyDirectory(srcPath, destPath);
|
|
30
|
+
} else {
|
|
31
|
+
fs.copyFileSync(srcPath, destPath);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get directory size recursively
|
|
38
|
+
*/
|
|
39
|
+
static getDirectorySize(dirPath) {
|
|
40
|
+
let totalSize = 0;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
44
|
+
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
47
|
+
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
totalSize += RollbackUtils.getDirectorySize(fullPath);
|
|
50
|
+
} else {
|
|
51
|
+
totalSize += fs.statSync(fullPath).size;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
// Directory might not exist or be inaccessible
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return totalSize;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Ensure directory exists
|
|
63
|
+
*/
|
|
64
|
+
static ensureDirectory(dirPath) {
|
|
65
|
+
if (!fs.existsSync(dirPath)) {
|
|
66
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Safe file copy with directory creation
|
|
72
|
+
*/
|
|
73
|
+
static safeCopyFile(src, dest) {
|
|
74
|
+
const destDir = path.dirname(dest);
|
|
75
|
+
RollbackUtils.ensureDirectory(destDir);
|
|
76
|
+
fs.copyFileSync(src, dest);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Generate backup path for a file
|
|
81
|
+
*/
|
|
82
|
+
static getBackupPath(baseDir, filePath) {
|
|
83
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
84
|
+
return path.join(baseDir, relativePath);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get file metadata
|
|
89
|
+
*/
|
|
90
|
+
static getFileMetadata(filePath) {
|
|
91
|
+
if (!fs.existsSync(filePath)) {
|
|
92
|
+
return {
|
|
93
|
+
size: 0,
|
|
94
|
+
modified: null,
|
|
95
|
+
exists: false
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const stats = fs.statSync(filePath);
|
|
100
|
+
return {
|
|
101
|
+
size: stats.size,
|
|
102
|
+
modified: stats.mtime.toISOString(),
|
|
103
|
+
exists: true
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
RollbackUtils
|
|
110
|
+
};
|