vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642

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,351 @@
1
+ /**
2
+ * GUI Smoke Testing Utility
3
+ *
4
+ * Provides smoke testing functionality for the GUI (Electron) interface
5
+ * to ensure it starts without critical errors.
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const path = require('path');
10
+ const fs = require('fs');
11
+
12
+ class GuiSmokeTest {
13
+ constructor(options = {}) {
14
+ this.guiPath = options.guiPath || path.join(__dirname, '../../../electron-app');
15
+ this.mainScript = options.mainScript || 'src/main.js';
16
+ this.timeout = options.timeout || 45000; // 45 seconds for Electron startup
17
+ this.verbose = options.verbose || false;
18
+ }
19
+
20
+ /**
21
+ * Run comprehensive GUI smoke tests
22
+ * @returns {Promise<Object>} Test results
23
+ */
24
+ async runSmokeTests() {
25
+ const results = {
26
+ passed: 0,
27
+ failed: 0,
28
+ total: 0,
29
+ details: []
30
+ };
31
+
32
+ const tests = [
33
+ { name: 'GUI Directory Exists', test: () => this.testGuiDirectoryExists() },
34
+ { name: 'Package.json Exists', test: () => this.testPackageJsonExists() },
35
+ { name: 'Main Script Exists', test: () => this.testMainScriptExists() },
36
+ { name: 'Dependencies Available', test: () => this.testDependenciesAvailable() },
37
+ { name: 'GUI Starts Without Crashing', test: () => this.testGuiStarts() }
38
+ ];
39
+
40
+ for (const test of tests) {
41
+ results.total++;
42
+ try {
43
+ const result = await test.test();
44
+ if (result.passed) {
45
+ results.passed++;
46
+ if (this.verbose) {
47
+ console.log(`āœ… ${test.name}: PASSED`);
48
+ }
49
+ } else {
50
+ results.failed++;
51
+ console.error(`āŒ ${test.name}: FAILED - ${result.error}`);
52
+ }
53
+ results.details.push({
54
+ name: test.name,
55
+ passed: result.passed,
56
+ error: result.error,
57
+ details: result.details
58
+ });
59
+ } catch (error) {
60
+ results.failed++;
61
+ console.error(`āŒ ${test.name}: ERROR - ${error.message}`);
62
+ results.details.push({
63
+ name: test.name,
64
+ passed: false,
65
+ error: error.message,
66
+ details: null
67
+ });
68
+ }
69
+ }
70
+
71
+ return {
72
+ success: results.failed === 0,
73
+ ...results
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Test if GUI directory exists
79
+ */
80
+ async testGuiDirectoryExists() {
81
+ try {
82
+ const exists = fs.existsSync(this.guiPath);
83
+ if (!exists) {
84
+ return { passed: false, error: `GUI directory not found: ${this.guiPath}` };
85
+ }
86
+
87
+ const stats = fs.statSync(this.guiPath);
88
+ if (!stats.isDirectory()) {
89
+ return { passed: false, error: `GUI path is not a directory: ${this.guiPath}` };
90
+ }
91
+
92
+ return { passed: true, details: { path: this.guiPath } };
93
+ } catch (error) {
94
+ return { passed: false, error: error.message };
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Test if package.json exists in GUI directory
100
+ */
101
+ async testPackageJsonExists() {
102
+ try {
103
+ const packageJsonPath = path.join(this.guiPath, 'package.json');
104
+ const exists = fs.existsSync(packageJsonPath);
105
+ if (!exists) {
106
+ return { passed: false, error: `package.json not found: ${packageJsonPath}` };
107
+ }
108
+
109
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
110
+ return {
111
+ passed: true,
112
+ details: {
113
+ name: packageJson.name,
114
+ version: packageJson.version,
115
+ hasMain: !!packageJson.main
116
+ }
117
+ };
118
+ } catch (error) {
119
+ return { passed: false, error: `package.json error: ${error.message}` };
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Test if main script exists
125
+ */
126
+ async testMainScriptExists() {
127
+ try {
128
+ const mainScriptPath = path.join(this.guiPath, this.mainScript);
129
+ const exists = fs.existsSync(mainScriptPath);
130
+ if (!exists) {
131
+ return { passed: false, error: `Main script not found: ${mainScriptPath}` };
132
+ }
133
+
134
+ const stats = fs.statSync(mainScriptPath);
135
+ return {
136
+ passed: true,
137
+ details: {
138
+ path: mainScriptPath,
139
+ size: stats.size
140
+ }
141
+ };
142
+ } catch (error) {
143
+ return { passed: false, error: error.message };
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Test if dependencies are available
149
+ */
150
+ async testDependenciesAvailable() {
151
+ try {
152
+ const packageJsonPath = path.join(this.guiPath, 'package.json');
153
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
154
+ const nodeModulesPath = path.join(this.guiPath, 'node_modules');
155
+
156
+ const nodeModulesExists = fs.existsSync(nodeModulesPath);
157
+ const hasDependencies = packageJson.dependencies && Object.keys(packageJson.dependencies).length > 0;
158
+
159
+ if (!nodeModulesExists && hasDependencies) {
160
+ return {
161
+ passed: false,
162
+ error: 'node_modules directory not found but dependencies exist in package.json'
163
+ };
164
+ }
165
+
166
+ // Check for key Electron dependencies
167
+ const keyDeps = ['electron'];
168
+ const missingDeps = keyDeps.filter(dep =>
169
+ packageJson.dependencies && packageJson.dependencies[dep] &&
170
+ !fs.existsSync(path.join(nodeModulesPath, dep))
171
+ );
172
+
173
+ if (missingDeps.length > 0) {
174
+ return {
175
+ passed: false,
176
+ error: `Missing key dependencies: ${missingDeps.join(', ')}`
177
+ };
178
+ }
179
+
180
+ return {
181
+ passed: true,
182
+ details: {
183
+ nodeModulesExists,
184
+ dependencyCount: hasDependencies ? Object.keys(packageJson.dependencies).length : 0,
185
+ hasElectron: packageJson.dependencies && !!packageJson.dependencies.electron
186
+ }
187
+ };
188
+ } catch (error) {
189
+ return { passed: false, error: `Dependency check error: ${error.message}` };
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Test if GUI starts without crashing
195
+ * Note: This is a basic startup test - we don't actually launch the full GUI
196
+ * as that would require a display environment
197
+ */
198
+ async testGuiStarts() {
199
+ return new Promise((resolve) => {
200
+ const startTime = Date.now();
201
+
202
+ // Try to run electron with --version to test if it can start
203
+ const electronPath = path.join(this.guiPath, 'node_modules', '.bin', 'electron');
204
+ const packageJsonPath = path.join(this.guiPath, 'package.json');
205
+
206
+ // Check if electron binary exists
207
+ if (!fs.existsSync(electronPath)) {
208
+ // Try alternative paths
209
+ const electronPaths = [
210
+ path.join(this.guiPath, 'node_modules', 'electron', 'dist', 'electron'),
211
+ path.join(this.guiPath, 'node_modules', '.bin', 'electron.cmd'),
212
+ 'npx electron'
213
+ ];
214
+
215
+ let foundElectron = false;
216
+ for (const ePath of electronPaths) {
217
+ if (ePath.includes('npx') || fs.existsSync(ePath)) {
218
+ foundElectron = true;
219
+ break;
220
+ }
221
+ }
222
+
223
+ if (!foundElectron) {
224
+ resolve({
225
+ passed: false,
226
+ error: 'Electron binary not found'
227
+ });
228
+ return;
229
+ }
230
+ }
231
+
232
+ // Test electron version
233
+ const child = spawn('npm', ['run', 'electron:version'], {
234
+ stdio: ['pipe', 'pipe', 'pipe'],
235
+ cwd: this.guiPath,
236
+ timeout: this.timeout
237
+ });
238
+
239
+ let stdout = '';
240
+ let stderr = '';
241
+
242
+ child.stdout.on('data', (data) => {
243
+ stdout += data.toString();
244
+ });
245
+
246
+ child.stderr.on('data', (data) => {
247
+ stderr += data.toString();
248
+ });
249
+
250
+ const timeoutId = setTimeout(() => {
251
+ child.kill('SIGTERM');
252
+ resolve({
253
+ passed: false,
254
+ error: `GUI startup test timeout after ${this.timeout}ms`,
255
+ details: { stdout, stderr }
256
+ });
257
+ }, this.timeout);
258
+
259
+ child.on('close', (code) => {
260
+ clearTimeout(timeoutId);
261
+ const duration = Date.now() - startTime;
262
+
263
+ // If electron:version script doesn't exist, try alternative test
264
+ if (code === 1 && stderr.includes('Missing script')) {
265
+ // Try to validate package.json main entry point
266
+ try {
267
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
268
+ const mainEntry = packageJson.main || this.mainScript;
269
+ const mainEntryPath = path.join(this.guiPath, mainEntry);
270
+
271
+ if (fs.existsSync(mainEntryPath)) {
272
+ resolve({
273
+ passed: true,
274
+ details: {
275
+ test: 'package-json-validation',
276
+ mainEntry,
277
+ mainEntryExists: true,
278
+ duration
279
+ }
280
+ });
281
+ } else {
282
+ resolve({
283
+ passed: false,
284
+ error: `Main entry point not found: ${mainEntryPath}`,
285
+ details: { mainEntry, duration }
286
+ });
287
+ }
288
+ } catch (error) {
289
+ resolve({
290
+ passed: false,
291
+ error: `Package.json validation failed: ${error.message}`,
292
+ details: { duration }
293
+ });
294
+ }
295
+ } else if (code === 0) {
296
+ resolve({
297
+ passed: true,
298
+ details: {
299
+ exitCode: code,
300
+ duration,
301
+ electronVersion: stdout.trim()
302
+ }
303
+ });
304
+ } else {
305
+ resolve({
306
+ passed: false,
307
+ error: `GUI startup test failed - exit code: ${code}`,
308
+ details: { exitCode: code, stdout, stderr, duration }
309
+ });
310
+ }
311
+ });
312
+
313
+ child.on('error', (error) => {
314
+ clearTimeout(timeoutId);
315
+
316
+ // If npm script fails, try basic validation
317
+ try {
318
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
319
+ const mainEntry = packageJson.main || this.mainScript;
320
+ const mainEntryPath = path.join(this.guiPath, mainEntry);
321
+
322
+ if (fs.existsSync(mainEntryPath)) {
323
+ resolve({
324
+ passed: true,
325
+ details: {
326
+ test: 'fallback-validation',
327
+ mainEntry,
328
+ mainEntryExists: true,
329
+ note: 'npm script failed but main entry exists'
330
+ }
331
+ });
332
+ } else {
333
+ resolve({
334
+ passed: false,
335
+ error: `Main entry point not found: ${mainEntryPath}`,
336
+ details: { error: error.message }
337
+ });
338
+ }
339
+ } catch (validationError) {
340
+ resolve({
341
+ passed: false,
342
+ error: `GUI startup test error: ${error.message}`,
343
+ details: { error: error.message }
344
+ });
345
+ }
346
+ });
347
+ });
348
+ }
349
+ }
350
+
351
+ module.exports = { GuiSmokeTest };
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Smoke Test Orchestrator
3
+ *
4
+ * Coordinates smoke testing across all interfaces (CLI, GUI, Web)
5
+ * and provides unified reporting and rollback triggering.
6
+ */
7
+
8
+ const { CliSmokeTest } = require('./smoke-test-cli');
9
+ const { GuiSmokeTest } = require('./smoke-test-gui');
10
+ const { WebSmokeTest } = require('./smoke-test-web');
11
+
12
+ class SmokeTestOrchestrator {
13
+ constructor(options = {}) {
14
+ this.options = {
15
+ cliPath: options.cliPath,
16
+ guiPath: options.guiPath,
17
+ webPath: options.webPath,
18
+ timeout: options.timeout || 120000, // 2 minutes total
19
+ parallel: options.parallel !== false, // Run tests in parallel by default
20
+ verbose: options.verbose || false,
21
+ rollbackTrigger: options.rollbackTrigger || null
22
+ };
23
+
24
+ this.testers = {
25
+ cli: new CliSmokeTest({
26
+ cliPath: this.options.cliPath,
27
+ verbose: this.options.verbose
28
+ }),
29
+ gui: new GuiSmokeTest({
30
+ guiPath: this.options.guiPath,
31
+ verbose: this.options.verbose
32
+ }),
33
+ web: new WebSmokeTest({
34
+ webPath: this.options.webPath,
35
+ verbose: this.options.verbose
36
+ })
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Run smoke tests for all interfaces
42
+ * @param {string} phase - 'pre-refactor' or 'post-refactor'
43
+ * @returns {Promise<Object>} Comprehensive test results
44
+ */
45
+ async runSmokeTests(phase = 'pre-refactor') {
46
+ const startTime = Date.now();
47
+ const results = {
48
+ phase,
49
+ timestamp: new Date().toISOString(),
50
+ totalDuration: 0,
51
+ interfaces: {},
52
+ summary: {
53
+ totalTests: 0,
54
+ passedTests: 0,
55
+ failedTests: 0,
56
+ interfacesPassed: 0,
57
+ interfacesFailed: 0
58
+ },
59
+ success: false,
60
+ rollbackTriggered: false
61
+ };
62
+
63
+ if (this.options.verbose) {
64
+ console.log(`\nšŸ”„ Running ${phase} smoke tests...`);
65
+ }
66
+
67
+ const interfaceTests = [
68
+ { name: 'cli', tester: this.testers.cli, required: true },
69
+ { name: 'gui', tester: this.testers.gui, required: false }, // GUI might not be always available
70
+ { name: 'web', tester: this.testers.web, required: false } // Web might not be always available
71
+ ];
72
+
73
+ if (this.options.parallel) {
74
+ // Run all tests in parallel
75
+ const testPromises = interfaceTests.map(async (interfaceTest) => {
76
+ try {
77
+ const testResult = await interfaceTest.tester.runSmokeTests();
78
+ return {
79
+ name: interfaceTest.name,
80
+ required: interfaceTest.required,
81
+ result: testResult
82
+ };
83
+ } catch (error) {
84
+ return {
85
+ name: interfaceTest.name,
86
+ required: interfaceTest.required,
87
+ result: {
88
+ success: false,
89
+ error: error.message,
90
+ passed: 0,
91
+ failed: 0,
92
+ total: 0,
93
+ details: []
94
+ }
95
+ };
96
+ }
97
+ });
98
+
99
+ const interfaceResults = await Promise.all(testPromises);
100
+
101
+ // Process results
102
+ interfaceResults.forEach(({ name, required, result }) => {
103
+ results.interfaces[name] = {
104
+ ...result,
105
+ required,
106
+ available: true
107
+ };
108
+
109
+ results.summary.totalTests += result.total;
110
+ results.summary.passedTests += result.passed;
111
+ results.summary.failedTests += result.failed;
112
+
113
+ if (result.success) {
114
+ results.summary.interfacesPassed++;
115
+ } else {
116
+ results.summary.interfacesFailed++;
117
+ }
118
+ });
119
+ } else {
120
+ // Run tests sequentially
121
+ for (const interfaceTest of interfaceTests) {
122
+ try {
123
+ const testResult = await interfaceTest.tester.runSmokeTests();
124
+ results.interfaces[interfaceTest.name] = {
125
+ ...testResult,
126
+ required: interfaceTest.required,
127
+ available: true
128
+ };
129
+
130
+ results.summary.totalTests += testResult.total;
131
+ results.summary.passedTests += testResult.passed;
132
+ results.summary.failedTests += testResult.failed;
133
+
134
+ if (testResult.success) {
135
+ results.summary.interfacesPassed++;
136
+ } else {
137
+ results.summary.interfacesFailed++;
138
+ }
139
+ } catch (error) {
140
+ results.interfaces[interfaceTest.name] = {
141
+ success: false,
142
+ error: error.message,
143
+ passed: 0,
144
+ failed: 0,
145
+ total: 0,
146
+ details: [],
147
+ required: interfaceTest.required,
148
+ available: false
149
+ };
150
+
151
+ results.summary.interfacesFailed++;
152
+ }
153
+ }
154
+ }
155
+
156
+ results.totalDuration = Date.now() - startTime;
157
+
158
+ // Determine overall success
159
+ const requiredInterfaces = interfaceTests
160
+ .filter(iface => iface.required)
161
+ .map(iface => iface.name);
162
+
163
+ const requiredInterfacesPassed = requiredInterfaces
164
+ .filter(name => results.interfaces[name] && results.interfaces[name].success)
165
+ .length;
166
+
167
+ // Success if all required interfaces pass
168
+ results.success = requiredInterfacesPassed === requiredInterfaces.length;
169
+
170
+ // Trigger rollback if this is post-refactor and tests failed
171
+ if (phase === 'post-refactor' && !results.success && this.options.rollbackTrigger) {
172
+ if (this.options.verbose) {
173
+ console.log('🚨 Smoke tests failed - triggering rollback');
174
+ }
175
+
176
+ try {
177
+ await this.options.rollbackTrigger({
178
+ reason: 'Smoke tests failed',
179
+ phase,
180
+ results
181
+ });
182
+ results.rollbackTriggered = true;
183
+ } catch (rollbackError) {
184
+ console.error('Rollback trigger failed:', rollbackError.message);
185
+ results.rollbackError = rollbackError.message;
186
+ }
187
+ }
188
+
189
+ // Print summary
190
+ this.printSummary(results);
191
+
192
+ return results;
193
+ }
194
+
195
+ /**
196
+ * Run pre-refactor smoke tests
197
+ */
198
+ async runPreRefactorTests() {
199
+ return this.runSmokeTests('pre-refactor');
200
+ }
201
+
202
+ /**
203
+ * Run post-refactor smoke tests
204
+ */
205
+ async runPostRefactorTests() {
206
+ return this.runSmokeTests('post-refactor');
207
+ }
208
+
209
+ /**
210
+ * Print test summary to console
211
+ */
212
+ printSummary(results) {
213
+ if (this.options.verbose) {
214
+ console.log(`\nšŸ“Š Smoke Test Results - ${results.phase.toUpperCase()}`);
215
+ console.log(`ā±ļø Duration: ${results.totalDuration}ms`);
216
+ console.log(`šŸ“ˆ Summary: ${results.summary.passedTests}/${results.summary.totalTests} tests passed`);
217
+ console.log(`šŸ–„ļø Interfaces: ${results.summary.interfacesPassed}/${results.summary.interfacesPassed + results.summary.interfacesFailed} passed`);
218
+
219
+ Object.entries(results.interfaces).forEach(([name, result]) => {
220
+ const status = result.success ? 'āœ…' : 'āŒ';
221
+ const availability = result.available ? '' : ' (not available)';
222
+ const requirement = result.required ? ' (required)' : ' (optional)';
223
+ console.log(` ${status} ${name.toUpperCase()}${availability}${requirement}: ${result.passed}/${result.total} tests passed`);
224
+
225
+ if (!result.success && result.error) {
226
+ console.log(` Error: ${result.error}`);
227
+ }
228
+ });
229
+
230
+ if (results.success) {
231
+ console.log('šŸŽ‰ All required interfaces passed smoke tests!');
232
+ } else {
233
+ console.log('šŸ’„ Some required interfaces failed smoke tests!');
234
+ }
235
+
236
+ if (results.rollbackTriggered) {
237
+ console.log('šŸ”„ Rollback was triggered due to failures');
238
+ }
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Generate detailed report
244
+ */
245
+ generateReport(results) {
246
+ const report = {
247
+ metadata: {
248
+ phase: results.phase,
249
+ timestamp: results.timestamp,
250
+ duration: results.totalDuration,
251
+ orchestratorVersion: '1.0.0'
252
+ },
253
+ summary: results.summary,
254
+ interfaces: {},
255
+ recommendations: []
256
+ };
257
+
258
+ // Process each interface result
259
+ Object.entries(results.interfaces).forEach(([name, result]) => {
260
+ report.interfaces[name] = {
261
+ available: result.available,
262
+ required: result.required,
263
+ success: result.success,
264
+ testSummary: {
265
+ total: result.total,
266
+ passed: result.passed,
267
+ failed: result.failed
268
+ },
269
+ error: result.error || null,
270
+ testDetails: result.details || []
271
+ };
272
+
273
+ // Generate recommendations
274
+ if (!result.success) {
275
+ if (result.error && result.error.includes('not found')) {
276
+ report.recommendations.push({
277
+ interface: name,
278
+ priority: 'high',
279
+ issue: 'Missing files or dependencies',
280
+ suggestion: `Ensure ${name} interface is properly installed and dependencies are available`
281
+ });
282
+ } else if (result.error && result.error.includes('timeout')) {
283
+ report.recommendations.push({
284
+ interface: name,
285
+ priority: 'medium',
286
+ issue: 'Startup timeout',
287
+ suggestion: `Check ${name} configuration and increase timeout if necessary`
288
+ });
289
+ } else {
290
+ report.recommendations.push({
291
+ interface: name,
292
+ priority: 'high',
293
+ issue: 'Unknown error',
294
+ suggestion: `Investigate ${name} interface logs and configuration`
295
+ });
296
+ }
297
+ }
298
+ });
299
+
300
+ return report;
301
+ }
302
+
303
+ /**
304
+ * Save report to file
305
+ */
306
+ async saveReport(results, filePath) {
307
+ const fs = require('fs').promises;
308
+ const report = this.generateReport(results);
309
+
310
+ try {
311
+ await fs.writeFile(filePath, JSON.stringify(report, null, 2));
312
+ if (this.options.verbose) {
313
+ console.log(`šŸ“„ Report saved to: ${filePath}`);
314
+ }
315
+ } catch (error) {
316
+ console.error(`Failed to save report: ${error.message}`);
317
+ }
318
+ }
319
+ }
320
+
321
+ module.exports = { SmokeTestOrchestrator };