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,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages rollback capabilities for refactoring operations.
|
|
5
|
+
* Provides safe backup and restore functionality.
|
|
6
|
+
*
|
|
7
|
+
* Refactored into modular components for better maintainability.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { DEFAULT_BACKUP_DIR } = require('./rollback/rollback-types');
|
|
12
|
+
const { RollbackOperation } = require('./rollback/rollback-operation');
|
|
13
|
+
const { RollbackRecorder } = require('./rollback/rollback-recorder');
|
|
14
|
+
const { RollbackHandlers } = require('./rollback/rollback-handlers');
|
|
15
|
+
const { RollbackStateManager } = require('./rollback/rollback-state-manager');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Main rollback manager class
|
|
19
|
+
*/
|
|
20
|
+
class RollbackManager {
|
|
21
|
+
constructor(backupDir = DEFAULT_BACKUP_DIR) {
|
|
22
|
+
this.backupDir = path.resolve(backupDir);
|
|
23
|
+
this.operations = [];
|
|
24
|
+
this.stateManager = new RollbackStateManager(this.backupDir);
|
|
25
|
+
this.sessionId = this.stateManager.generateSessionId();
|
|
26
|
+
this.recorder = new RollbackRecorder(this.backupDir, this.sessionId);
|
|
27
|
+
|
|
28
|
+
this.ensureBackupDirectory();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generate unique session ID
|
|
33
|
+
*/
|
|
34
|
+
generateSessionId() {
|
|
35
|
+
return this.stateManager.generateSessionId();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Ensure backup directory exists
|
|
40
|
+
*/
|
|
41
|
+
ensureBackupDirectory() {
|
|
42
|
+
this.stateManager.ensureBackupDirectory(this.sessionId);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get session backup directory
|
|
47
|
+
*/
|
|
48
|
+
getSessionBackupDir() {
|
|
49
|
+
return path.join(this.backupDir, this.sessionId);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create backup of a file before modification
|
|
54
|
+
*/
|
|
55
|
+
backupFile(filePath) {
|
|
56
|
+
const operation = this.recorder.backupFile(filePath);
|
|
57
|
+
this.operations.push(operation);
|
|
58
|
+
return operation;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Record file creation
|
|
63
|
+
*/
|
|
64
|
+
recordFileCreation(filePath) {
|
|
65
|
+
const operation = this.recorder.recordFileCreation(filePath);
|
|
66
|
+
this.operations.push(operation);
|
|
67
|
+
return operation;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Record file deletion (with backup)
|
|
72
|
+
*/
|
|
73
|
+
recordFileDeletion(filePath) {
|
|
74
|
+
const operation = this.recorder.recordFileDeletion(filePath);
|
|
75
|
+
this.operations.push(operation);
|
|
76
|
+
return operation;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Record file move/rename
|
|
81
|
+
*/
|
|
82
|
+
recordFileMove(oldPath, newPath) {
|
|
83
|
+
const operation = this.recorder.recordFileMove(oldPath, newPath);
|
|
84
|
+
this.operations.push(operation);
|
|
85
|
+
return operation;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Record directory creation
|
|
90
|
+
*/
|
|
91
|
+
recordDirectoryCreation(dirPath) {
|
|
92
|
+
const operation = this.recorder.recordDirectoryCreation(dirPath);
|
|
93
|
+
this.operations.push(operation);
|
|
94
|
+
return operation;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Record directory deletion (with backup)
|
|
99
|
+
*/
|
|
100
|
+
recordDirectoryDeletion(dirPath) {
|
|
101
|
+
const operation = this.recorder.recordDirectoryDeletion(dirPath);
|
|
102
|
+
this.operations.push(operation);
|
|
103
|
+
return operation;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Execute rollback for all operations
|
|
108
|
+
*/
|
|
109
|
+
async rollback() {
|
|
110
|
+
const results = {
|
|
111
|
+
success: [],
|
|
112
|
+
failed: [],
|
|
113
|
+
skipped: []
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Execute rollbacks in reverse order
|
|
117
|
+
for (let i = this.operations.length - 1; i >= 0; i--) {
|
|
118
|
+
const operation = this.operations[i];
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
await RollbackHandlers.rollbackOperation(operation);
|
|
122
|
+
results.success.push(operation);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
operation.error = error.message;
|
|
125
|
+
results.failed.push(operation);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Rollback a single operation
|
|
134
|
+
*/
|
|
135
|
+
async rollbackOperation(operation) {
|
|
136
|
+
return await RollbackHandlers.rollbackOperation(operation);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get operation summary
|
|
141
|
+
*/
|
|
142
|
+
getSummary() {
|
|
143
|
+
return this.stateManager.generateSummary(this.sessionId, this.operations);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Save rollback state to file
|
|
148
|
+
*/
|
|
149
|
+
saveState() {
|
|
150
|
+
const summary = this.getSummary();
|
|
151
|
+
return this.stateManager.saveState(this.sessionId, this.operations, summary);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Load rollback state from file
|
|
156
|
+
*/
|
|
157
|
+
loadState(sessionId) {
|
|
158
|
+
const state = this.stateManager.loadState(sessionId);
|
|
159
|
+
this.sessionId = state.sessionId;
|
|
160
|
+
this.operations = state.operations;
|
|
161
|
+
this.recorder = new RollbackRecorder(this.backupDir, this.sessionId);
|
|
162
|
+
return state;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* List available rollback sessions
|
|
167
|
+
*/
|
|
168
|
+
listSessions() {
|
|
169
|
+
return this.stateManager.listSessions();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Cleanup old backup sessions
|
|
174
|
+
*/
|
|
175
|
+
cleanup(maxAge) {
|
|
176
|
+
return this.stateManager.cleanup(maxAge);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Clear current session operations
|
|
181
|
+
*/
|
|
182
|
+
clear() {
|
|
183
|
+
this.operations = [];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get backup size
|
|
188
|
+
*/
|
|
189
|
+
getBackupSize() {
|
|
190
|
+
return this.stateManager.getBackupSize(this.sessionId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Export all components for backward compatibility
|
|
195
|
+
module.exports = {
|
|
196
|
+
RollbackManager,
|
|
197
|
+
RollbackOperation,
|
|
198
|
+
RollbackRecorder,
|
|
199
|
+
RollbackHandlers,
|
|
200
|
+
RollbackStateManager,
|
|
201
|
+
DEFAULT_BACKUP_DIR
|
|
202
|
+
};
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Smoke Testing Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides smoke testing functionality for the CLI interface
|
|
5
|
+
* to ensure it starts and responds to basic commands correctly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawn } = require('child_process');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
|
|
12
|
+
class CliSmokeTest {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.cliPath = options.cliPath || path.join(__dirname, '../../../cli/bin/vibecodingmachine.js');
|
|
15
|
+
this.timeout = options.timeout || 30000; // 30 seconds default
|
|
16
|
+
this.verbose = options.verbose || false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Run comprehensive CLI smoke tests
|
|
21
|
+
* @returns {Promise<Object>} Test results
|
|
22
|
+
*/
|
|
23
|
+
async runSmokeTests() {
|
|
24
|
+
const results = {
|
|
25
|
+
passed: 0,
|
|
26
|
+
failed: 0,
|
|
27
|
+
total: 0,
|
|
28
|
+
details: []
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const tests = [
|
|
32
|
+
{ name: 'CLI File Exists', test: () => this.testCliFileExists() },
|
|
33
|
+
{ name: 'CLI Starts Without Crashing', test: () => this.testCliStarts() },
|
|
34
|
+
{ name: 'CLI --help Command', test: () => this.testHelpCommand() },
|
|
35
|
+
{ name: 'CLI --version Command', test: () => this.testVersionCommand() },
|
|
36
|
+
{ name: 'CLI Basic Commands Available', test: () => this.testBasicCommands() }
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
for (const test of tests) {
|
|
40
|
+
results.total++;
|
|
41
|
+
try {
|
|
42
|
+
const result = await test.test();
|
|
43
|
+
if (result.passed) {
|
|
44
|
+
results.passed++;
|
|
45
|
+
if (this.verbose) {
|
|
46
|
+
console.log(`✅ ${test.name}: PASSED`);
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
results.failed++;
|
|
50
|
+
console.error(`❌ ${test.name}: FAILED - ${result.error}`);
|
|
51
|
+
}
|
|
52
|
+
results.details.push({
|
|
53
|
+
name: test.name,
|
|
54
|
+
passed: result.passed,
|
|
55
|
+
error: result.error,
|
|
56
|
+
details: result.details
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
results.failed++;
|
|
60
|
+
console.error(`❌ ${test.name}: ERROR - ${error.message}`);
|
|
61
|
+
results.details.push({
|
|
62
|
+
name: test.name,
|
|
63
|
+
passed: false,
|
|
64
|
+
error: error.message,
|
|
65
|
+
details: null
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
success: results.failed === 0,
|
|
72
|
+
...results
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Test if CLI file exists and is executable
|
|
78
|
+
*/
|
|
79
|
+
async testCliFileExists() {
|
|
80
|
+
try {
|
|
81
|
+
const exists = fs.existsSync(this.cliPath);
|
|
82
|
+
if (!exists) {
|
|
83
|
+
return { passed: false, error: `CLI file not found: ${this.cliPath}` };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const stats = fs.statSync(this.cliPath);
|
|
87
|
+
if (!stats.isFile()) {
|
|
88
|
+
return { passed: false, error: `CLI path is not a file: ${this.cliPath}` };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { passed: true, details: { path: this.cliPath, size: stats.size } };
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return { passed: false, error: error.message };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Test if CLI starts without crashing
|
|
99
|
+
*/
|
|
100
|
+
async testCliStarts() {
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
const child = spawn('node', [this.cliPath, '--help'], {
|
|
104
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
105
|
+
cwd: path.dirname(this.cliPath)
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
let stdout = '';
|
|
109
|
+
let stderr = '';
|
|
110
|
+
|
|
111
|
+
child.stdout.on('data', (data) => {
|
|
112
|
+
stdout += data.toString();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
child.stderr.on('data', (data) => {
|
|
116
|
+
stderr += data.toString();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const timeoutId = setTimeout(() => {
|
|
120
|
+
child.kill('SIGTERM');
|
|
121
|
+
resolve({
|
|
122
|
+
passed: false,
|
|
123
|
+
error: `CLI startup timeout after ${this.timeout}ms`,
|
|
124
|
+
details: { stdout, stderr }
|
|
125
|
+
});
|
|
126
|
+
}, this.timeout);
|
|
127
|
+
|
|
128
|
+
child.on('close', (code) => {
|
|
129
|
+
clearTimeout(timeoutId);
|
|
130
|
+
const duration = Date.now() - startTime;
|
|
131
|
+
|
|
132
|
+
// Allow exit code 0 or 1 (help command might exit with 1)
|
|
133
|
+
if (code === 0 || code === 1) {
|
|
134
|
+
resolve({
|
|
135
|
+
passed: true,
|
|
136
|
+
details: {
|
|
137
|
+
exitCode: code,
|
|
138
|
+
duration,
|
|
139
|
+
stdout: stdout.substring(0, 500), // First 500 chars
|
|
140
|
+
hasOutput: stdout.length > 0
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
resolve({
|
|
145
|
+
passed: false,
|
|
146
|
+
error: `CLI exited with code ${code}`,
|
|
147
|
+
details: { exitCode: code, stdout, stderr, duration }
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
child.on('error', (error) => {
|
|
153
|
+
clearTimeout(timeoutId);
|
|
154
|
+
resolve({
|
|
155
|
+
passed: false,
|
|
156
|
+
error: `CLI failed to start: ${error.message}`,
|
|
157
|
+
details: { error: error.message }
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Test --help command specifically
|
|
165
|
+
*/
|
|
166
|
+
async testHelpCommand() {
|
|
167
|
+
return new Promise((resolve) => {
|
|
168
|
+
const child = spawn('node', [this.cliPath, '--help'], {
|
|
169
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
170
|
+
cwd: path.dirname(this.cliPath)
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
let stdout = '';
|
|
174
|
+
let stderr = '';
|
|
175
|
+
|
|
176
|
+
child.stdout.on('data', (data) => {
|
|
177
|
+
stdout += data.toString();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
child.stderr.on('data', (data) => {
|
|
181
|
+
stderr += data.toString();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const timeoutId = setTimeout(() => {
|
|
185
|
+
child.kill('SIGTERM');
|
|
186
|
+
resolve({
|
|
187
|
+
passed: false,
|
|
188
|
+
error: `Help command timeout after ${this.timeout}ms`
|
|
189
|
+
});
|
|
190
|
+
}, this.timeout);
|
|
191
|
+
|
|
192
|
+
child.on('close', (code) => {
|
|
193
|
+
clearTimeout(timeoutId);
|
|
194
|
+
|
|
195
|
+
// Check for help-related content
|
|
196
|
+
const hasHelpContent = stdout.includes('Usage:') ||
|
|
197
|
+
stdout.includes('Options:') ||
|
|
198
|
+
stdout.includes('Commands:') ||
|
|
199
|
+
stdout.includes('help');
|
|
200
|
+
|
|
201
|
+
// Allow exit code 0 or 1 for help
|
|
202
|
+
if ((code === 0 || code === 1) && hasHelpContent) {
|
|
203
|
+
resolve({
|
|
204
|
+
passed: true,
|
|
205
|
+
details: {
|
|
206
|
+
exitCode: code,
|
|
207
|
+
hasHelpContent,
|
|
208
|
+
outputLength: stdout.length
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
resolve({
|
|
213
|
+
passed: false,
|
|
214
|
+
error: `Help command failed - exit code: ${code}, has help content: ${hasHelpContent}`,
|
|
215
|
+
details: { exitCode: code, stdout: stdout.substring(0, 200), stderr }
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
child.on('error', (error) => {
|
|
221
|
+
clearTimeout(timeoutId);
|
|
222
|
+
resolve({
|
|
223
|
+
passed: false,
|
|
224
|
+
error: `Help command error: ${error.message}`
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Test --version command
|
|
232
|
+
*/
|
|
233
|
+
async testVersionCommand() {
|
|
234
|
+
return new Promise((resolve) => {
|
|
235
|
+
const child = spawn('node', [this.cliPath, '--version'], {
|
|
236
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
237
|
+
cwd: path.dirname(this.cliPath)
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
let stdout = '';
|
|
241
|
+
let stderr = '';
|
|
242
|
+
|
|
243
|
+
child.stdout.on('data', (data) => {
|
|
244
|
+
stdout += data.toString();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
child.stderr.on('data', (data) => {
|
|
248
|
+
stderr += data.toString();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const timeoutId = setTimeout(() => {
|
|
252
|
+
child.kill('SIGTERM');
|
|
253
|
+
resolve({
|
|
254
|
+
passed: false,
|
|
255
|
+
error: `Version command timeout after ${this.timeout}ms`
|
|
256
|
+
});
|
|
257
|
+
}, this.timeout);
|
|
258
|
+
|
|
259
|
+
child.on('close', (code) => {
|
|
260
|
+
clearTimeout(timeoutId);
|
|
261
|
+
|
|
262
|
+
// Check for version-like content
|
|
263
|
+
const hasVersionContent = /\d+\.\d+\.\d+/.test(stdout) ||
|
|
264
|
+
stdout.includes('version') ||
|
|
265
|
+
stdout.length > 0;
|
|
266
|
+
|
|
267
|
+
if (code === 0 && hasVersionContent) {
|
|
268
|
+
resolve({
|
|
269
|
+
passed: true,
|
|
270
|
+
details: {
|
|
271
|
+
exitCode: code,
|
|
272
|
+
version: stdout.trim(),
|
|
273
|
+
hasVersionContent
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
} else {
|
|
277
|
+
resolve({
|
|
278
|
+
passed: false,
|
|
279
|
+
error: `Version command failed - exit code: ${code}`,
|
|
280
|
+
details: { exitCode: code, stdout, stderr }
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
child.on('error', (error) => {
|
|
286
|
+
clearTimeout(timeoutId);
|
|
287
|
+
resolve({
|
|
288
|
+
passed: false,
|
|
289
|
+
error: `Version command error: ${error.message}`
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Test that basic commands are available
|
|
297
|
+
*/
|
|
298
|
+
async testBasicCommands() {
|
|
299
|
+
return new Promise((resolve) => {
|
|
300
|
+
const child = spawn('node', [this.cliPath, '--help'], {
|
|
301
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
302
|
+
cwd: path.dirname(this.cliPath)
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
let stdout = '';
|
|
306
|
+
|
|
307
|
+
child.stdout.on('data', (data) => {
|
|
308
|
+
stdout += data.toString();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const timeoutId = setTimeout(() => {
|
|
312
|
+
child.kill('SIGTERM');
|
|
313
|
+
resolve({
|
|
314
|
+
passed: false,
|
|
315
|
+
error: `Basic commands check timeout after ${this.timeout}ms`
|
|
316
|
+
});
|
|
317
|
+
}, this.timeout);
|
|
318
|
+
|
|
319
|
+
child.on('close', (code) => {
|
|
320
|
+
clearTimeout(timeoutId);
|
|
321
|
+
|
|
322
|
+
// Look for basic command patterns
|
|
323
|
+
const basicCommands = [
|
|
324
|
+
'repo', 'auto', 'help', 'version'
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
const foundCommands = basicCommands.filter(cmd =>
|
|
328
|
+
stdout.toLowerCase().includes(cmd.toLowerCase())
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const hasEnoughCommands = foundCommands.length >= 2;
|
|
332
|
+
|
|
333
|
+
if ((code === 0 || code === 1) && hasEnoughCommands) {
|
|
334
|
+
resolve({
|
|
335
|
+
passed: true,
|
|
336
|
+
details: {
|
|
337
|
+
exitCode: code,
|
|
338
|
+
foundCommands,
|
|
339
|
+
commandCount: foundCommands.length
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
} else {
|
|
343
|
+
resolve({
|
|
344
|
+
passed: false,
|
|
345
|
+
error: `Basic commands check failed - found ${foundCommands.length} commands`,
|
|
346
|
+
details: { exitCode: code, foundCommands, stdout: stdout.substring(0, 300) }
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
child.on('error', (error) => {
|
|
352
|
+
clearTimeout(timeoutId);
|
|
353
|
+
resolve({
|
|
354
|
+
passed: false,
|
|
355
|
+
error: `Basic commands check error: ${error.message}`
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
module.exports = { CliSmokeTest };
|