vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850

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 (192) hide show
  1. package/package.json +1 -1
  2. package/src/agents/AgentCheckDiscoveryService.js +180 -0
  3. package/src/agents/AgentCheckService.js +18 -261
  4. package/src/agents/AgentCheckStatisticsService.js +195 -0
  5. package/src/agents/EnvironmentConfigurationManager.js +31 -380
  6. package/src/agents/InstallationType.js +19 -6
  7. package/src/agents/SimpleAgentCheckService.js +472 -0
  8. package/src/agents/config-managers/ConfigUtils.js +72 -0
  9. package/src/agents/config-managers/DefaultConfig.js +58 -0
  10. package/src/agents/config-managers/EnvVarLoader.js +66 -0
  11. package/src/agents/config-managers/FileConfigLoader.js +124 -0
  12. package/src/agents/config-managers/TypeConverters.js +61 -0
  13. package/src/agents/config-managers/VariableMappings.js +92 -0
  14. package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
  15. package/src/agents/discovery/AgentDiscoveryService.js +29 -403
  16. package/src/agents/discovery/agent-validator.js +262 -0
  17. package/src/agents/discovery/discovery-results.js +176 -0
  18. package/src/agents/discovery/discovery-scanner.js +268 -0
  19. package/src/agents/discovery/discovery-utils.js +161 -0
  20. package/src/agents/discovery/executable-analyzer.js +290 -0
  21. package/src/agents/discovery/history-manager.js +310 -0
  22. package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
  23. package/src/agents/verification/ResultAnalyzer.js +30 -431
  24. package/src/agents/verification/analysis-utils.js +310 -0
  25. package/src/agents/verification/batch-analyzer.js +440 -0
  26. package/src/agents/verification/pattern-recognizer.js +369 -0
  27. package/src/agents/verification/report-generator.js +320 -0
  28. package/src/agents/verification/test-analyzer.js +290 -0
  29. package/src/agents/windows/InstallerFactory.js +4 -0
  30. package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
  31. package/src/analysis/analysis-engine.js +314 -0
  32. package/src/analysis/ast-analyzer.js +342 -0
  33. package/src/analysis/boundary-detector-refactored.js +378 -0
  34. package/src/analysis/boundary-detector.js +200 -603
  35. package/src/analysis/boundary-scanner.js +609 -0
  36. package/src/analysis/boundary-types.js +118 -0
  37. package/src/analysis/boundary-utils.js +293 -0
  38. package/src/analysis/deadline-priority-calculator.js +18 -0
  39. package/src/analysis/detection-methods.js +347 -0
  40. package/src/analysis/importance-priority-calculator.js +18 -0
  41. package/src/analysis/priority/factor-calculators.js +204 -0
  42. package/src/analysis/priority/factor-helpers.js +71 -0
  43. package/src/analysis/priority/priority-constants.js +73 -0
  44. package/src/analysis/priority/priority-factor-calculators.js +301 -0
  45. package/src/analysis/priority/reasons-generator.js +44 -0
  46. package/src/analysis/priority-calculator.js +15 -580
  47. package/src/analysis/strategy-generator.js +16 -66
  48. package/src/analysis/type-priority-calculator.js +18 -0
  49. package/src/analysis/urgency-priority-calculator.js +18 -0
  50. package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
  51. package/src/commands/disable-requirement.js +60 -0
  52. package/src/commands/disable-spec.js +60 -0
  53. package/src/commands/enable-requirement.js +60 -0
  54. package/src/commands/enable-spec.js +60 -0
  55. package/src/commands/registry.js +1 -6
  56. package/src/commands/requirements.js +8 -2
  57. package/src/ide-integration/applescript-manager.cjs +9 -24
  58. package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
  59. package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
  60. package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
  61. package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
  62. package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
  63. package/src/ide-integration/cdp-manager.js +28 -573
  64. package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
  65. package/src/ide-integration/ide-openers/claude-opener.js +171 -0
  66. package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
  67. package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
  68. package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
  69. package/src/ide-integration/macos-ide-manager.js +20 -582
  70. package/src/ide-integration/macos-quota-checker.js +164 -0
  71. package/src/ide-integration/macos-text-sender.js +19 -38
  72. package/src/ide-integration/provider-manager.cjs +52 -7
  73. package/src/index.cjs +6 -0
  74. package/src/index.js +10 -0
  75. package/src/llm/direct-llm-manager.cjs +501 -0
  76. package/src/localization/translations/en-part1.js +363 -0
  77. package/src/localization/translations/en-part2.js +320 -0
  78. package/src/localization/translations/en.js +4 -687
  79. package/src/localization/translations/es-part1.js +363 -0
  80. package/src/localization/translations/es-part2.js +320 -0
  81. package/src/localization/translations/es.js +4 -688
  82. package/src/models/file-analysis-collection.js +139 -0
  83. package/src/models/file-analysis-metrics.js +50 -0
  84. package/src/models/file-analysis.js +15 -262
  85. package/src/models/plan-manager.js +410 -0
  86. package/src/models/refactoring-models.js +380 -0
  87. package/src/models/refactoring-plan-refactored.js +81 -0
  88. package/src/models/refactoring-plan.js +2 -663
  89. package/src/monitoring/alert-system.js +4 -45
  90. package/src/monitoring/continuous-scan-notifications.js +37 -191
  91. package/src/monitoring/notification-handlers/base-handler.js +58 -0
  92. package/src/monitoring/notification-handlers/error-handler.js +36 -0
  93. package/src/monitoring/notification-handlers/index.js +21 -0
  94. package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
  95. package/src/monitoring/notification-handlers/progress-handler.js +48 -0
  96. package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
  97. package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
  98. package/src/provider-registry.js +8 -0
  99. package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
  100. package/src/refactoring/boundary/boundary-detector.js +26 -596
  101. package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
  102. package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
  103. package/src/refactoring/boundary/detectors/class-detector.js +247 -0
  104. package/src/refactoring/boundary/detectors/config-detector.js +270 -0
  105. package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
  106. package/src/refactoring/boundary/detectors/function-detector.js +248 -0
  107. package/src/refactoring/boundary/detectors/module-detector.js +249 -0
  108. package/src/refactoring/boundary/detectors/object-detector.js +247 -0
  109. package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
  110. package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
  111. package/src/refactoring/circular-dependency-resolver-original.js +16 -76
  112. package/src/refactoring/code-mover-refactored.js +309 -0
  113. package/src/refactoring/code-mover.js +48 -355
  114. package/src/refactoring/execution-status.js +18 -0
  115. package/src/refactoring/execution-strategies.js +172 -0
  116. package/src/refactoring/file-splitter-core.js +568 -0
  117. package/src/refactoring/file-splitter-types.js +136 -0
  118. package/src/refactoring/file-splitter.js +2 -682
  119. package/src/refactoring/functionality-validator.js +11 -51
  120. package/src/refactoring/import-manager-refactored.js +385 -0
  121. package/src/refactoring/import-manager.js +112 -487
  122. package/src/refactoring/import-models.js +189 -0
  123. package/src/refactoring/import-parser.js +306 -0
  124. package/src/refactoring/move-executor.js +431 -0
  125. package/src/refactoring/move-utils.js +368 -0
  126. package/src/refactoring/operation-executor.js +76 -0
  127. package/src/refactoring/plan-creator.js +36 -0
  128. package/src/refactoring/plan-executor.js +143 -0
  129. package/src/refactoring/plan-validator.js +68 -0
  130. package/src/refactoring/refactoring-executor-result.js +70 -0
  131. package/src/refactoring/refactoring-executor.js +34 -569
  132. package/src/refactoring/refactoring-operation.js +94 -0
  133. package/src/refactoring/refactoring-plan.js +69 -0
  134. package/src/refactoring/refactoring-rollback.js +22 -527
  135. package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
  136. package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
  137. package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
  138. package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
  139. package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
  140. package/src/refactoring/test-validator.js +32 -448
  141. package/src/refactoring/validation/baseline-runner.js +71 -0
  142. package/src/refactoring/validation/report-generator.js +136 -0
  143. package/src/refactoring/validation/result-comparator.js +92 -0
  144. package/src/refactoring/validation/test-suite.js +59 -0
  145. package/src/refactoring/validation/test-validation-result.js +83 -0
  146. package/src/refactoring/validation/validation-runner.js +95 -0
  147. package/src/refactoring/validation/validation-status.js +18 -0
  148. package/src/rui/commands/AgentCommandParser.js +60 -369
  149. package/src/rui/commands/AgentResponseFormatter.js +7 -47
  150. package/src/rui/commands/parsers/CommandMapper.js +148 -0
  151. package/src/rui/commands/parsers/CommandValidator.js +228 -0
  152. package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
  153. package/src/rui/commands/parsers/TokenParser.js +69 -0
  154. package/src/rui/commands/parsers/tokenizer.js +153 -0
  155. package/src/utils/current-requirement-operations.js +50 -1
  156. package/src/utils/report-generator.js +18 -514
  157. package/src/utils/report-generators/analysis-generator.js +115 -0
  158. package/src/utils/report-generators/base-generator.js +141 -0
  159. package/src/utils/report-generators/compliance-generator.js +41 -0
  160. package/src/utils/report-generators/format-handlers.js +185 -0
  161. package/src/utils/report-generators/refactoring-generator.js +46 -0
  162. package/src/utils/report-generators/validation-generator.js +63 -0
  163. package/src/utils/requirement-enable-disable.js +265 -0
  164. package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
  165. package/src/utils/requirement-helpers/requirement-mover.js +88 -1
  166. package/src/utils/requirement-helpers.js +5 -2
  167. package/src/utils/smoke-test-cli.js +45 -8
  168. package/src/utils/specification-enable-disable.js +122 -0
  169. package/src/utils/specification-helpers.js +30 -4
  170. package/src/utils/specification-migration.js +5 -5
  171. package/src/utils/test-comparator.js +118 -0
  172. package/src/utils/test-config.js +54 -0
  173. package/src/utils/test-executor.js +133 -0
  174. package/src/utils/test-parser.js +215 -0
  175. package/src/utils/test-runner-baseline.js +63 -0
  176. package/src/utils/test-runner-core.js +98 -0
  177. package/src/utils/test-runner-report.js +39 -0
  178. package/src/utils/test-runner-validation.js +71 -0
  179. package/src/utils/test-runner.js +11 -535
  180. package/src/validation/comparison-analyzer.js +333 -0
  181. package/src/validation/compliance-reporter-new.js +282 -0
  182. package/src/validation/compliance-reporter-refactored.js +344 -0
  183. package/src/validation/compliance-reporter.js +278 -591
  184. package/src/validation/compliance-utils.js +278 -0
  185. package/src/validation/html-generator.js +446 -0
  186. package/src/validation/metrics/category-calculator.js +137 -0
  187. package/src/validation/metrics/metrics-helpers.js +155 -0
  188. package/src/validation/metrics/overview-calculator.js +85 -0
  189. package/src/validation/metrics/overview-metrics.js +41 -0
  190. package/src/validation/metrics/quality-calculator.js +166 -0
  191. package/src/validation/metrics/size-calculator.js +69 -0
  192. package/src/validation/metrics-calculator.js +27 -551
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Specification Enable/Disable Utilities
3
+ * Provides functions to enable and disable specifications using DISABLED.vcm files
4
+ */
5
+
6
+ const fs = require('fs-extra');
7
+ const path = require('path');
8
+
9
+ /**
10
+ * Enable a specification by removing DISABLED.vcm file if it exists
11
+ * @param {string} specId - Specification ID (e.g., "001-agent-defaults")
12
+ * @param {string} repoPath - Repository root path
13
+ * @returns {Promise<{success: boolean, message: string}>}
14
+ */
15
+ async function enableSpec(specId, repoPath = process.cwd()) {
16
+ try {
17
+ const specPath = path.join(repoPath, 'specs', specId);
18
+ const disabledFile = path.join(specPath, 'DISABLED.vcm');
19
+
20
+ // Check if spec directory exists
21
+ if (!await fs.pathExists(specPath)) {
22
+ return {
23
+ success: false,
24
+ message: `Specification ${specId} not found`
25
+ };
26
+ }
27
+
28
+ // Check if spec is currently disabled
29
+ const isDisabled = await fs.pathExists(disabledFile);
30
+ if (!isDisabled) {
31
+ return {
32
+ success: true,
33
+ message: `Specification ${specId} is already enabled`
34
+ };
35
+ }
36
+
37
+ // Remove DISABLED.vcm file to enable the spec
38
+ await fs.remove(disabledFile);
39
+
40
+ return {
41
+ success: true,
42
+ message: `Specification ${specId} enabled successfully`
43
+ };
44
+ } catch (error) {
45
+ return {
46
+ success: false,
47
+ message: `Failed to enable specification ${specId}: ${error.message}`
48
+ };
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Disable a specification by creating DISABLED.vcm file
54
+ * @param {string} specId - Specification ID (e.g., "001-agent-defaults")
55
+ * @param {string} repoPath - Repository root path
56
+ * @returns {Promise<{success: boolean, message: string}>}
57
+ */
58
+ async function disableSpec(specId, repoPath = process.cwd()) {
59
+ try {
60
+ const specPath = path.join(repoPath, 'specs', specId);
61
+ const disabledFile = path.join(specPath, 'DISABLED.vcm');
62
+
63
+ // Check if spec directory exists
64
+ if (!await fs.pathExists(specPath)) {
65
+ return {
66
+ success: false,
67
+ message: `Specification ${specId} not found`
68
+ };
69
+ }
70
+
71
+ // Check if spec is already disabled
72
+ const isDisabled = await fs.pathExists(disabledFile);
73
+ if (isDisabled) {
74
+ return {
75
+ success: true,
76
+ message: `Specification ${specId} is already disabled`
77
+ };
78
+ }
79
+
80
+ // Create DISABLED.vcm file to disable the spec
81
+ const disabledContent = `# Specification Disabled\n\nThis specification is disabled and will be skipped by auto-mode.\nDisabled at: ${new Date().toISOString()}\n`;
82
+ await fs.writeFile(disabledFile, disabledContent, 'utf8');
83
+
84
+ return {
85
+ success: true,
86
+ message: `Specification ${specId} disabled successfully`
87
+ };
88
+ } catch (error) {
89
+ return {
90
+ success: false,
91
+ message: `Failed to disable specification ${specId}: ${error.message}`
92
+ };
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Check if a specification is disabled
98
+ * @param {string} specId - Specification ID
99
+ * @param {string} repoPath - Repository root path
100
+ * @returns {Promise<boolean>} - True if disabled, false otherwise
101
+ */
102
+ async function isSpecDisabled(specId, repoPath = process.cwd()) {
103
+ try {
104
+ const specPath = path.join(repoPath, 'specs', specId);
105
+ const disabledFile = path.join(specPath, 'DISABLED.vcm');
106
+
107
+ if (!await fs.pathExists(specPath)) {
108
+ return false; // Spec doesn't exist, treat as not disabled
109
+ }
110
+
111
+ return await fs.pathExists(disabledFile);
112
+ } catch (error) {
113
+ // logger.error(`Error checking if spec is disabled: ${error.message}`);
114
+ return false; // Default to not disabled on error
115
+ }
116
+ };
117
+
118
+ module.exports = {
119
+ enableSpec,
120
+ disableSpec,
121
+ isSpecDisabled
122
+ };
@@ -8,6 +8,7 @@
8
8
  const fs = require('fs-extra');
9
9
  const path = require('path');
10
10
  const { migrateAllDisabledSpecs, isMigrationNeeded } = require('./specification-migration');
11
+ const { enableSpec, disableSpec, isSpecDisabled } = require('./specification-enable-disable');
11
12
 
12
13
  /**
13
14
  * Extract the title from spec.md content (first H1 or H2)
@@ -57,6 +58,27 @@ function extractCompletionPercentage(text) {
57
58
  return null;
58
59
  }
59
60
 
61
+ /**
62
+ * Extract task counts from arbitrary text
63
+ * Looks for patterns like "N/M tasks" or "N of M tasks"
64
+ * @param {string} text
65
+ * @returns {{completed: number, total: number}|null} task counts or null if not found
66
+ */
67
+ function extractTaskCounts(text) {
68
+ if (!text || typeof text !== 'string') return null;
69
+
70
+ // Match patterns like "5/10 tasks" or "5 / 10 tasks" or "5 of 10 tasks"
71
+ const p1 = text.match(/(\d+)\s*(?:\/|of)\s*(\d+)\s+tasks?/i);
72
+ if (p1) {
73
+ return {
74
+ completed: parseInt(p1[1]),
75
+ total: parseInt(p1[2])
76
+ };
77
+ }
78
+
79
+ return null;
80
+ }
81
+
60
82
  /**
61
83
  * Check whether a spec directory has a tasks.md file
62
84
  * @param {string} specPath - absolute path to spec directory
@@ -80,7 +102,7 @@ async function isSpecComplete(specPath) {
80
102
  * Get all specifications in repo's specs/ directory
81
103
  * @param {string} repoPath
82
104
  * @param {Object} [options] - Optional configuration
83
- * @param {boolean} [options.skipDisabled=false] - Skip specs with DISABLED.txt file
105
+ * @param {boolean} [options.skipDisabled=false] - Skip specs with DISABLED.vcm file
84
106
  * @param {boolean} [options.includeWithoutSpec=false] - Include spec directories even without spec.md
85
107
  * @returns {Promise<Array<{directory, title, path, hasPlan, hasPlanPrompt, hasTasks, hasSpec}>>}
86
108
  */
@@ -97,8 +119,8 @@ async function getAllSpecifications(repoPath, options = {}) {
97
119
  const stat = await fs.stat(specPath).catch(() => null);
98
120
  if (!stat || !stat.isDirectory()) continue;
99
121
 
100
- // Skip disabled specs if skipDisabled is true and DISABLED.txt exists or directory starts with DISABLED-
101
- if (skipDisabled && (await fs.pathExists(path.join(specPath, 'DISABLED.txt')) || entry.startsWith('DISABLED-'))) {
122
+ // Skip disabled specs if skipDisabled is true and DISABLED.vcm exists or directory starts with DISABLED-
123
+ if (skipDisabled && (await fs.pathExists(path.join(specPath, 'DISABLED.vcm')) || entry.startsWith('DISABLED-'))) {
102
124
  continue;
103
125
  }
104
126
 
@@ -231,6 +253,7 @@ async function initializeSpecifications(repoPath) {
231
253
  module.exports = {
232
254
  extractSpecTitle,
233
255
  extractCompletionPercentage,
256
+ extractTaskCounts,
234
257
  hasImplementation,
235
258
  isSpecComplete,
236
259
  getAllSpecifications,
@@ -238,5 +261,8 @@ module.exports = {
238
261
  getTodoSpecifications,
239
262
  createSpecification,
240
263
  updateSpecification,
241
- initializeSpecifications
264
+ initializeSpecifications,
265
+ enableSpec,
266
+ disableSpec,
267
+ isSpecDisabled
242
268
  };
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * Specification Migration Utilities
3
3
  * Handles migration from old DISABLED- prefix naming convention
4
- * to the new DISABLED.txt file-based disable tracking.
4
+ * to new DISABLED.vcm file-based disable tracking.
5
5
  */
6
6
 
7
7
  const fs = require('fs-extra');
8
8
  const path = require('path');
9
9
 
10
10
  /**
11
- * Migrate a single specification from DISABLED- prefix to DISABLED.txt file
11
+ * Migrate a single specification from DISABLED- prefix to DISABLED.vcm file
12
12
  * @param {string} specsDir - path to specs/ directory
13
13
  * @param {string} dirName - directory name (e.g., "DISABLED-001-example")
14
14
  * @returns {Promise<{success: boolean, oldName: string, newName: string|null, error: string|null}>}
@@ -29,8 +29,8 @@ async function migrateDisabledSpec(specsDir, dirName) {
29
29
  return { success: false, oldName: dirName, newName: null, error: 'No spec.md found' };
30
30
  }
31
31
 
32
- // Create DISABLED.txt in the old directory before renaming
33
- const disabledFilePath = path.join(oldPath, 'DISABLED.txt');
32
+ // Create DISABLED.vcm in the old directory before renaming
33
+ const disabledFilePath = path.join(oldPath, 'DISABLED.vcm');
34
34
  await fs.writeFile(disabledFilePath, '');
35
35
 
36
36
  // Rename directory to remove DISABLED- prefix
@@ -43,7 +43,7 @@ async function migrateDisabledSpec(specsDir, dirName) {
43
43
  }
44
44
 
45
45
  /**
46
- * Migrate all DISABLED- prefixed specs to the new DISABLED.txt format
46
+ * Migrate all DISABLED- prefixed specs to the new DISABLED.vcm format
47
47
  * @param {string} repoPath - root repository path
48
48
  * @returns {Promise<{totalFound: number, migrated: number, failed: number, results: Array}>}
49
49
  */
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Test Comparator
3
+ *
4
+ * Compares test results to detect regressions and improvements.
5
+ */
6
+
7
+ /**
8
+ * Compare baseline and current results
9
+ */
10
+ function compareResults(baseline, current) {
11
+ const comparison = {
12
+ hasRegressions: false,
13
+ regressions: [],
14
+ improvements: [],
15
+ unchanged: [],
16
+ summary: {
17
+ baseline: {
18
+ total: baseline.total,
19
+ passed: baseline.passed,
20
+ failed: baseline.failed,
21
+ duration: baseline.duration
22
+ },
23
+ current: {
24
+ total: current.total,
25
+ passed: current.passed,
26
+ failed: current.failed,
27
+ duration: current.duration
28
+ }
29
+ }
30
+ };
31
+
32
+ // Check for test count changes
33
+ if (current.total < baseline.total) {
34
+ comparison.regressions.push({
35
+ type: 'missing_tests',
36
+ message: `${baseline.total - current.total} tests are missing`,
37
+ severity: 'high'
38
+ });
39
+ comparison.hasRegressions = true;
40
+ }
41
+
42
+ if (current.total > baseline.total) {
43
+ comparison.improvements.push({
44
+ type: 'new_tests',
45
+ message: `${current.total - baseline.total} new tests added`,
46
+ severity: 'info'
47
+ });
48
+ }
49
+
50
+ // Check for test failures
51
+ if (current.failed > baseline.failed) {
52
+ comparison.regressions.push({
53
+ type: 'new_failures',
54
+ message: `${current.failed - baseline.failed} new test failures`,
55
+ severity: 'high'
56
+ });
57
+ comparison.hasRegressions = true;
58
+ }
59
+
60
+ if (current.failed < baseline.failed) {
61
+ comparison.improvements.push({
62
+ type: 'fixed_failures',
63
+ message: `${baseline.failed - current.failed} test failures fixed`,
64
+ severity: 'good'
65
+ });
66
+ }
67
+
68
+ // Check for performance regression
69
+ const performanceIncrease = current.duration - baseline.duration;
70
+ const performancePercent = (performanceIncrease / baseline.duration) * 100;
71
+
72
+ if (performanceIncrease > 5000 && performancePercent > 10) { // 5s and 10%
73
+ comparison.regressions.push({
74
+ type: 'performance',
75
+ message: `Test execution increased by ${Math.round(performancePercent)}% (${Math.round(performanceIncrease/1000)}s)`,
76
+ severity: 'medium'
77
+ });
78
+ comparison.hasRegressions = true;
79
+ }
80
+
81
+ // Compare individual test results
82
+ const baselineTests = new Map();
83
+ for (const test of baseline.tests) {
84
+ baselineTests.set(test.fullName, test);
85
+ }
86
+
87
+ for (const test of current.tests) {
88
+ const baselineTest = baselineTests.get(test.fullName);
89
+
90
+ if (!baselineTest) {
91
+ comparison.improvements.push({
92
+ type: 'new_test',
93
+ message: `New test: ${test.title}`,
94
+ severity: 'info'
95
+ });
96
+ } else if (baselineTest.status === 'passed' && test.status === 'failed') {
97
+ comparison.regressions.push({
98
+ type: 'test_regression',
99
+ message: `Test now failing: ${test.title}`,
100
+ severity: 'high',
101
+ test: test
102
+ });
103
+ comparison.hasRegressions = true;
104
+ } else if (baselineTest.status === 'failed' && test.status === 'passed') {
105
+ comparison.improvements.push({
106
+ type: 'test_fixed',
107
+ message: `Test now passing: ${test.title}`,
108
+ severity: 'good'
109
+ });
110
+ }
111
+ }
112
+
113
+ return comparison;
114
+ }
115
+
116
+ module.exports = {
117
+ compareResults
118
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Test Configuration
3
+ *
4
+ * Handles test configuration detection and validation.
5
+ */
6
+
7
+ const fs = require('fs');
8
+
9
+ /**
10
+ * Check if tests are available
11
+ */
12
+ function checkTestAvailability() {
13
+ const testPaths = [
14
+ 'package.json',
15
+ 'tests',
16
+ '__tests__',
17
+ 'test',
18
+ 'spec'
19
+ ];
20
+
21
+ for (const testPath of testPaths) {
22
+ if (fs.existsSync(testPath)) {
23
+ return true;
24
+ }
25
+ }
26
+
27
+ return false;
28
+ }
29
+
30
+ /**
31
+ * Get test configuration
32
+ */
33
+ function getTestConfig() {
34
+ try {
35
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
36
+ return {
37
+ hasTestScript: !!packageJson.scripts?.test,
38
+ testScript: packageJson.scripts?.test,
39
+ jestConfig: packageJson.jest,
40
+ dependencies: {
41
+ jest: packageJson.dependencies?.jest || packageJson.devDependencies?.jest,
42
+ mocha: packageJson.dependencies?.mocha || packageJson.devDependencies?.mocha,
43
+ jasmine: packageJson.dependencies?.jasmine || packageJson.devDependencies?.jasmine
44
+ }
45
+ };
46
+ } catch (error) {
47
+ return { hasTestScript: false };
48
+ }
49
+ }
50
+
51
+ module.exports = {
52
+ checkTestAvailability,
53
+ getTestConfig
54
+ };
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Test Executor
3
+ *
4
+ * Handles test execution and process management.
5
+ */
6
+
7
+ const { spawn } = require('child_process');
8
+
9
+ /**
10
+ * Execute tests and collect results
11
+ */
12
+ async function executeTests(options = {}) {
13
+ const defaultOptions = {
14
+ verbose: false,
15
+ timeout: 300000, // 5 minutes
16
+ cwd: process.cwd()
17
+ };
18
+
19
+ const opts = { ...defaultOptions, ...options };
20
+
21
+ return new Promise((resolve, reject) => {
22
+ const startTime = Date.now();
23
+ let output = '';
24
+ let errorOutput = '';
25
+
26
+ try {
27
+ // Use npm test with JSON reporter if available
28
+ const testProcess = spawn('npm', ['test', '--', '--json', '--verbose'], {
29
+ stdio: ['pipe', 'pipe', 'pipe'],
30
+ cwd: opts.cwd
31
+ });
32
+
33
+ testProcess.stdout.on('data', (data) => {
34
+ output += data.toString();
35
+ if (opts.verbose) {
36
+ process.stdout.write(data);
37
+ }
38
+ });
39
+
40
+ testProcess.stderr.on('data', (data) => {
41
+ errorOutput += data.toString();
42
+ if (opts.verbose) {
43
+ process.stderr.write(data);
44
+ }
45
+ });
46
+
47
+ testProcess.on('close', (code) => {
48
+ const duration = Date.now() - startTime;
49
+ resolve({
50
+ stdout: output,
51
+ stderr: errorOutput,
52
+ exitCode: code,
53
+ duration
54
+ });
55
+ });
56
+
57
+ testProcess.on('error', (error) => {
58
+ reject(new Error(`Test process failed: ${error.message}`));
59
+ });
60
+
61
+ // Set timeout
62
+ if (opts.timeout) {
63
+ setTimeout(() => {
64
+ testProcess.kill('SIGKILL');
65
+ reject(new Error(`Test execution timed out after ${opts.timeout}ms`));
66
+ }, opts.timeout);
67
+ }
68
+
69
+ } catch (error) {
70
+ reject(new Error(`Failed to start test process: ${error.message}`));
71
+ }
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Run specific test files
77
+ */
78
+ async function runSpecificTests(testFiles, options = {}) {
79
+ const defaultOptions = {
80
+ verbose: false,
81
+ cwd: process.cwd()
82
+ };
83
+
84
+ const opts = { ...defaultOptions, ...options };
85
+
86
+ console.log(`Running ${testFiles.length} specific tests...`);
87
+
88
+ const testArgs = ['test', '--', ...testFiles];
89
+
90
+ return new Promise((resolve, reject) => {
91
+ const startTime = Date.now();
92
+ let output = '';
93
+ let errorOutput = '';
94
+
95
+ const testProcess = spawn('npm', testArgs, {
96
+ stdio: ['pipe', 'pipe', 'pipe'],
97
+ cwd: opts.cwd
98
+ });
99
+
100
+ testProcess.stdout.on('data', (data) => {
101
+ output += data.toString();
102
+ if (opts.verbose) {
103
+ process.stdout.write(data);
104
+ }
105
+ });
106
+
107
+ testProcess.stderr.on('data', (data) => {
108
+ errorOutput += data.toString();
109
+ if (opts.verbose) {
110
+ process.stderr.write(data);
111
+ }
112
+ });
113
+
114
+ testProcess.on('close', (code) => {
115
+ const duration = Date.now() - startTime;
116
+ resolve({
117
+ stdout: output,
118
+ stderr: errorOutput,
119
+ exitCode: code,
120
+ duration
121
+ });
122
+ });
123
+
124
+ testProcess.on('error', (error) => {
125
+ reject(new Error(`Test process failed: ${error.message}`));
126
+ });
127
+ });
128
+ }
129
+
130
+ module.exports = {
131
+ executeTests,
132
+ runSpecificTests
133
+ };