agentic-qe 2.6.4 → 2.6.6

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 (182) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +26 -1
  3. package/dist/agents/CoverageAnalyzerAgent.d.ts +31 -0
  4. package/dist/agents/CoverageAnalyzerAgent.d.ts.map +1 -1
  5. package/dist/agents/CoverageAnalyzerAgent.js +159 -0
  6. package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
  7. package/dist/agents/FleetCommanderAgent.d.ts +36 -0
  8. package/dist/agents/FleetCommanderAgent.d.ts.map +1 -1
  9. package/dist/agents/FleetCommanderAgent.js +226 -0
  10. package/dist/agents/FleetCommanderAgent.js.map +1 -1
  11. package/dist/cli/commands/kg/mincut.d.ts +50 -0
  12. package/dist/cli/commands/kg/mincut.d.ts.map +1 -0
  13. package/dist/cli/commands/kg/mincut.js +372 -0
  14. package/dist/cli/commands/kg/mincut.js.map +1 -0
  15. package/dist/cli/commands/providers/index.d.ts +20 -0
  16. package/dist/cli/commands/providers/index.d.ts.map +1 -0
  17. package/dist/cli/commands/providers/index.js +143 -0
  18. package/dist/cli/commands/providers/index.js.map +1 -0
  19. package/dist/cli/commands/providers/status.d.ts +117 -0
  20. package/dist/cli/commands/providers/status.d.ts.map +1 -0
  21. package/dist/cli/commands/providers/status.js +368 -0
  22. package/dist/cli/commands/providers/status.js.map +1 -0
  23. package/dist/cli/index.js +99 -62
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/init/claude-config.js +2 -2
  26. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts +148 -0
  27. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts.map +1 -0
  28. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js +393 -0
  29. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js.map +1 -0
  30. package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts +169 -0
  31. package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts.map +1 -0
  32. package/dist/code-intelligence/analysis/mincut/GraphAdapter.js +335 -0
  33. package/dist/code-intelligence/analysis/mincut/GraphAdapter.js.map +1 -0
  34. package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts +55 -0
  35. package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts.map +1 -0
  36. package/dist/code-intelligence/analysis/mincut/JsMinCut.js +265 -0
  37. package/dist/code-intelligence/analysis/mincut/JsMinCut.js.map +1 -0
  38. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts +92 -0
  39. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts.map +1 -0
  40. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js +200 -0
  41. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js.map +1 -0
  42. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts +157 -0
  43. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts.map +1 -0
  44. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js +434 -0
  45. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js.map +1 -0
  46. package/dist/code-intelligence/analysis/mincut/index.d.ts +12 -0
  47. package/dist/code-intelligence/analysis/mincut/index.d.ts.map +1 -0
  48. package/dist/code-intelligence/analysis/mincut/index.js +20 -0
  49. package/dist/code-intelligence/analysis/mincut/index.js.map +1 -0
  50. package/dist/code-intelligence/analysis/mincut/types.d.ts +145 -0
  51. package/dist/code-intelligence/analysis/mincut/types.d.ts.map +1 -0
  52. package/dist/code-intelligence/analysis/mincut/types.js +16 -0
  53. package/dist/code-intelligence/analysis/mincut/types.js.map +1 -0
  54. package/dist/code-intelligence/chunking/ASTChunker.d.ts +1 -1
  55. package/dist/code-intelligence/chunking/ASTChunker.d.ts.map +1 -1
  56. package/dist/code-intelligence/chunking/ASTChunker.js +4 -4
  57. package/dist/code-intelligence/chunking/ASTChunker.js.map +1 -1
  58. package/dist/code-intelligence/graph/GraphBuilder.d.ts +120 -0
  59. package/dist/code-intelligence/graph/GraphBuilder.d.ts.map +1 -1
  60. package/dist/code-intelligence/graph/GraphBuilder.js +517 -0
  61. package/dist/code-intelligence/graph/GraphBuilder.js.map +1 -1
  62. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.d.ts.map +1 -1
  63. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js +3 -3
  64. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js.map +1 -1
  65. package/dist/code-intelligence/parser/{TreeSitterParser.d.ts → WebTreeSitterParser.d.ts} +45 -10
  66. package/dist/code-intelligence/parser/WebTreeSitterParser.d.ts.map +1 -0
  67. package/dist/code-intelligence/parser/{TreeSitterParser.js → WebTreeSitterParser.js} +147 -54
  68. package/dist/code-intelligence/parser/WebTreeSitterParser.js.map +1 -0
  69. package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts +12 -10
  70. package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts.map +1 -1
  71. package/dist/code-intelligence/parser/extractors/BaseExtractor.js +7 -3
  72. package/dist/code-intelligence/parser/extractors/BaseExtractor.js.map +1 -1
  73. package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts +7 -5
  74. package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts.map +1 -1
  75. package/dist/code-intelligence/parser/extractors/GoExtractor.js +2 -2
  76. package/dist/code-intelligence/parser/extractors/GoExtractor.js.map +1 -1
  77. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts +7 -5
  78. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts.map +1 -1
  79. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js +2 -2
  80. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js.map +1 -1
  81. package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts +7 -5
  82. package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts.map +1 -1
  83. package/dist/code-intelligence/parser/extractors/PythonExtractor.js +2 -2
  84. package/dist/code-intelligence/parser/extractors/PythonExtractor.js.map +1 -1
  85. package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts +7 -5
  86. package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts.map +1 -1
  87. package/dist/code-intelligence/parser/extractors/RustExtractor.js +2 -2
  88. package/dist/code-intelligence/parser/extractors/RustExtractor.js.map +1 -1
  89. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts +7 -5
  90. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts.map +1 -1
  91. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js +2 -2
  92. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js.map +1 -1
  93. package/dist/code-intelligence/parser/index.d.ts +7 -1
  94. package/dist/code-intelligence/parser/index.d.ts.map +1 -1
  95. package/dist/code-intelligence/parser/index.js +11 -3
  96. package/dist/code-intelligence/parser/index.js.map +1 -1
  97. package/dist/code-intelligence/service/CodeIntelligenceService.d.ts.map +1 -1
  98. package/dist/code-intelligence/service/CodeIntelligenceService.js +7 -5
  99. package/dist/code-intelligence/service/CodeIntelligenceService.js.map +1 -1
  100. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  101. package/dist/coverage/CriticalPathDetector.d.ts +240 -0
  102. package/dist/coverage/CriticalPathDetector.d.ts.map +1 -0
  103. package/dist/coverage/CriticalPathDetector.js +388 -0
  104. package/dist/coverage/CriticalPathDetector.js.map +1 -0
  105. package/dist/coverage/index.d.ts +13 -0
  106. package/dist/coverage/index.d.ts.map +1 -0
  107. package/dist/coverage/index.js +16 -0
  108. package/dist/coverage/index.js.map +1 -0
  109. package/dist/fleet/topology/SPOFMonitor.d.ts +181 -0
  110. package/dist/fleet/topology/SPOFMonitor.d.ts.map +1 -0
  111. package/dist/fleet/topology/SPOFMonitor.js +286 -0
  112. package/dist/fleet/topology/SPOFMonitor.js.map +1 -0
  113. package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts +87 -0
  114. package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts.map +1 -0
  115. package/dist/fleet/topology/TopologyMinCutAnalyzer.js +472 -0
  116. package/dist/fleet/topology/TopologyMinCutAnalyzer.js.map +1 -0
  117. package/dist/fleet/topology/index.d.ts +13 -0
  118. package/dist/fleet/topology/index.d.ts.map +1 -0
  119. package/dist/fleet/topology/index.js +20 -0
  120. package/dist/fleet/topology/index.js.map +1 -0
  121. package/dist/fleet/topology/types.d.ts +139 -0
  122. package/dist/fleet/topology/types.d.ts.map +1 -0
  123. package/dist/fleet/topology/types.js +19 -0
  124. package/dist/fleet/topology/types.js.map +1 -0
  125. package/dist/mcp/handlers/test/test-execute-parallel.d.ts +34 -3
  126. package/dist/mcp/handlers/test/test-execute-parallel.d.ts.map +1 -1
  127. package/dist/mcp/handlers/test/test-execute-parallel.js +120 -5
  128. package/dist/mcp/handlers/test/test-execute-parallel.js.map +1 -1
  129. package/dist/mcp/server-instructions.d.ts +2 -2
  130. package/dist/mcp/server-instructions.d.ts.map +1 -1
  131. package/dist/mcp/server-instructions.js +2 -2
  132. package/dist/monitoring/ProviderHealthMonitor.d.ts +195 -0
  133. package/dist/monitoring/ProviderHealthMonitor.d.ts.map +1 -0
  134. package/dist/monitoring/ProviderHealthMonitor.js +431 -0
  135. package/dist/monitoring/ProviderHealthMonitor.js.map +1 -0
  136. package/dist/monitoring/QuotaManager.d.ts +122 -0
  137. package/dist/monitoring/QuotaManager.d.ts.map +1 -0
  138. package/dist/monitoring/QuotaManager.js +351 -0
  139. package/dist/monitoring/QuotaManager.js.map +1 -0
  140. package/dist/providers/GitHubModelsProvider.d.ts +117 -0
  141. package/dist/providers/GitHubModelsProvider.d.ts.map +1 -0
  142. package/dist/providers/GitHubModelsProvider.js +464 -0
  143. package/dist/providers/GitHubModelsProvider.js.map +1 -0
  144. package/dist/providers/GroqProvider.d.ts +115 -0
  145. package/dist/providers/GroqProvider.d.ts.map +1 -0
  146. package/dist/providers/GroqProvider.js +443 -0
  147. package/dist/providers/GroqProvider.js.map +1 -0
  148. package/dist/providers/HybridRouterHealthIntegration.d.ts +191 -0
  149. package/dist/providers/HybridRouterHealthIntegration.d.ts.map +1 -0
  150. package/dist/providers/HybridRouterHealthIntegration.js +439 -0
  151. package/dist/providers/HybridRouterHealthIntegration.js.map +1 -0
  152. package/dist/providers/index.d.ts +6 -0
  153. package/dist/providers/index.d.ts.map +1 -1
  154. package/dist/providers/index.js +12 -1
  155. package/dist/providers/index.js.map +1 -1
  156. package/dist/test/partition/MinCutPartitioner.d.ts +97 -0
  157. package/dist/test/partition/MinCutPartitioner.d.ts.map +1 -0
  158. package/dist/test/partition/MinCutPartitioner.js +459 -0
  159. package/dist/test/partition/MinCutPartitioner.js.map +1 -0
  160. package/dist/test/partition/RealTestExecutor.d.ts +86 -0
  161. package/dist/test/partition/RealTestExecutor.d.ts.map +1 -0
  162. package/dist/test/partition/RealTestExecutor.js +279 -0
  163. package/dist/test/partition/RealTestExecutor.js.map +1 -0
  164. package/dist/test/partition/TestDependencyAnalyzer.d.ts +75 -0
  165. package/dist/test/partition/TestDependencyAnalyzer.d.ts.map +1 -0
  166. package/dist/test/partition/TestDependencyAnalyzer.js +297 -0
  167. package/dist/test/partition/TestDependencyAnalyzer.js.map +1 -0
  168. package/dist/test/partition/index.d.ts +10 -0
  169. package/dist/test/partition/index.d.ts.map +1 -0
  170. package/dist/test/partition/index.js +26 -0
  171. package/dist/test/partition/index.js.map +1 -0
  172. package/dist/test/partition/types.d.ts +120 -0
  173. package/dist/test/partition/types.d.ts.map +1 -0
  174. package/dist/test/partition/types.js +21 -0
  175. package/dist/test/partition/types.js.map +1 -0
  176. package/package.json +5 -8
  177. package/dist/cli/commands/providers.d.ts +0 -50
  178. package/dist/cli/commands/providers.d.ts.map +0 -1
  179. package/dist/cli/commands/providers.js +0 -403
  180. package/dist/cli/commands/providers.js.map +0 -1
  181. package/dist/code-intelligence/parser/TreeSitterParser.d.ts.map +0 -1
  182. package/dist/code-intelligence/parser/TreeSitterParser.js.map +0 -1
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ /**
3
+ * Real Test Executor
4
+ *
5
+ * Executes tests using actual Jest/Vitest via child_process.spawn.
6
+ * This replaces the fake "setTimeout + random pass/fail" mock
7
+ * with real test execution.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.RealTestExecutor = void 0;
44
+ exports.aggregateBatchResults = aggregateBatchResults;
45
+ const child_process_1 = require("child_process");
46
+ const path = __importStar(require("path"));
47
+ const Logger_js_1 = require("../../utils/Logger.js");
48
+ const logger = Logger_js_1.Logger.getInstance();
49
+ const DEFAULT_CONFIG = {
50
+ command: 'npx',
51
+ runnerArgs: ['jest', '--json', '--testLocationInResults'],
52
+ timeout: 30000,
53
+ cwd: process.cwd(),
54
+ collectCoverage: false,
55
+ };
56
+ /**
57
+ * Executes real tests using Jest via child_process
58
+ */
59
+ class RealTestExecutor {
60
+ constructor(config = {}) {
61
+ this.runningProcesses = new Map();
62
+ this.config = { ...DEFAULT_CONFIG, ...config };
63
+ }
64
+ /**
65
+ * Execute a single test file
66
+ */
67
+ async executeTest(testFile, workerIndex = 0) {
68
+ const startTime = performance.now();
69
+ const absolutePath = path.resolve(testFile);
70
+ return new Promise((resolve) => {
71
+ const args = [
72
+ ...this.config.runnerArgs,
73
+ absolutePath,
74
+ '--forceExit',
75
+ '--runInBand',
76
+ '--no-coverage',
77
+ this.config.collectCoverage ? '--coverage' : '',
78
+ ].filter(Boolean);
79
+ let stdout = '';
80
+ let stderr = '';
81
+ let timedOut = false;
82
+ const proc = (0, child_process_1.spawn)(this.config.command, args, {
83
+ cwd: this.config.cwd,
84
+ env: {
85
+ ...process.env,
86
+ ...this.config.env,
87
+ NODE_OPTIONS: '--max-old-space-size=512',
88
+ FORCE_COLOR: '0', // Disable colors for JSON parsing
89
+ },
90
+ stdio: ['pipe', 'pipe', 'pipe'],
91
+ });
92
+ this.runningProcesses.set(testFile, proc);
93
+ const timeoutHandle = setTimeout(() => {
94
+ timedOut = true;
95
+ proc.kill('SIGTERM');
96
+ setTimeout(() => proc.kill('SIGKILL'), 1000);
97
+ }, this.config.timeout);
98
+ proc.stdout?.on('data', (data) => {
99
+ stdout += data.toString();
100
+ });
101
+ proc.stderr?.on('data', (data) => {
102
+ stderr += data.toString();
103
+ });
104
+ proc.on('close', (code) => {
105
+ clearTimeout(timeoutHandle);
106
+ this.runningProcesses.delete(testFile);
107
+ const duration = performance.now() - startTime;
108
+ if (timedOut) {
109
+ resolve({
110
+ testFile,
111
+ passed: false,
112
+ failed: 1,
113
+ total: 1,
114
+ duration,
115
+ error: `Test timed out after ${this.config.timeout}ms`,
116
+ workerIndex,
117
+ });
118
+ return;
119
+ }
120
+ // Try to parse Jest JSON output
121
+ const result = this.parseJestOutput(stdout, testFile, workerIndex, duration);
122
+ if (result) {
123
+ resolve(result);
124
+ return;
125
+ }
126
+ // Fallback: use exit code
127
+ resolve({
128
+ testFile,
129
+ passed: code === 0,
130
+ failed: code === 0 ? 0 : 1,
131
+ total: 1,
132
+ duration,
133
+ error: code !== 0 ? stderr || 'Test failed' : undefined,
134
+ output: stdout,
135
+ workerIndex,
136
+ });
137
+ });
138
+ proc.on('error', (error) => {
139
+ clearTimeout(timeoutHandle);
140
+ this.runningProcesses.delete(testFile);
141
+ resolve({
142
+ testFile,
143
+ passed: false,
144
+ failed: 1,
145
+ total: 1,
146
+ duration: performance.now() - startTime,
147
+ error: error.message,
148
+ workerIndex,
149
+ });
150
+ });
151
+ });
152
+ }
153
+ /**
154
+ * Execute a batch of test files sequentially on a single worker
155
+ */
156
+ async executeBatch(testFiles, workerIndex = 0) {
157
+ const startTime = performance.now();
158
+ const results = [];
159
+ let passed = 0;
160
+ let failed = 0;
161
+ for (const testFile of testFiles) {
162
+ const result = await this.executeTest(testFile, workerIndex);
163
+ results.push(result);
164
+ if (result.passed) {
165
+ passed++;
166
+ }
167
+ else {
168
+ failed++;
169
+ }
170
+ logger.debug(`Worker ${workerIndex}: ${testFile} - ${result.passed ? 'PASS' : 'FAIL'} (${result.duration.toFixed(0)}ms)`);
171
+ }
172
+ return {
173
+ results,
174
+ totalDuration: performance.now() - startTime,
175
+ passed,
176
+ failed,
177
+ };
178
+ }
179
+ /**
180
+ * Execute multiple batches in parallel (one per worker)
181
+ */
182
+ async executeParallel(batches, onProgress) {
183
+ const batchPromises = batches.map((batch, workerIndex) => this.executeBatchWithProgress(batch, workerIndex, onProgress));
184
+ return Promise.all(batchPromises);
185
+ }
186
+ /**
187
+ * Execute batch with progress callback
188
+ */
189
+ async executeBatchWithProgress(testFiles, workerIndex, onProgress) {
190
+ const startTime = performance.now();
191
+ const results = [];
192
+ let passed = 0;
193
+ let failed = 0;
194
+ for (const testFile of testFiles) {
195
+ const result = await this.executeTest(testFile, workerIndex);
196
+ results.push(result);
197
+ if (result.passed) {
198
+ passed++;
199
+ }
200
+ else {
201
+ failed++;
202
+ }
203
+ if (onProgress) {
204
+ onProgress(workerIndex, result);
205
+ }
206
+ }
207
+ return {
208
+ results,
209
+ totalDuration: performance.now() - startTime,
210
+ passed,
211
+ failed,
212
+ };
213
+ }
214
+ /**
215
+ * Parse Jest JSON output to extract test results
216
+ */
217
+ parseJestOutput(output, testFile, workerIndex, duration) {
218
+ try {
219
+ // Jest outputs JSON on a single line, find it
220
+ const lines = output.split('\n');
221
+ for (const line of lines) {
222
+ if (line.startsWith('{') && line.includes('"numTotalTests"')) {
223
+ const json = JSON.parse(line);
224
+ return {
225
+ testFile,
226
+ passed: json.numFailedTests === 0,
227
+ failed: json.numFailedTests || 0,
228
+ total: json.numTotalTests || 1,
229
+ duration: json.testResults?.[0]?.endTime
230
+ ? json.testResults[0].endTime - json.testResults[0].startTime
231
+ : duration,
232
+ workerIndex,
233
+ };
234
+ }
235
+ }
236
+ }
237
+ catch {
238
+ // JSON parsing failed, fall through
239
+ }
240
+ return null;
241
+ }
242
+ /**
243
+ * Kill all running test processes
244
+ */
245
+ killAll() {
246
+ for (const [testFile, proc] of this.runningProcesses) {
247
+ logger.warn(`Killing running test: ${testFile}`);
248
+ proc.kill('SIGTERM');
249
+ }
250
+ this.runningProcesses.clear();
251
+ }
252
+ /**
253
+ * Get number of currently running tests
254
+ */
255
+ getRunningCount() {
256
+ return this.runningProcesses.size;
257
+ }
258
+ }
259
+ exports.RealTestExecutor = RealTestExecutor;
260
+ /**
261
+ * Aggregate results from multiple batch executions
262
+ */
263
+ function aggregateBatchResults(batches) {
264
+ const allResults = batches.flatMap(b => b.results);
265
+ const totalDuration = allResults.reduce((sum, r) => sum + r.duration, 0);
266
+ const maxWorkerDuration = Math.max(...batches.map(b => b.totalDuration));
267
+ const passed = batches.reduce((sum, b) => sum + b.passed, 0);
268
+ const failed = batches.reduce((sum, b) => sum + b.failed, 0);
269
+ return {
270
+ allResults,
271
+ totalDuration,
272
+ maxWorkerDuration,
273
+ passed,
274
+ failed,
275
+ total: passed + failed,
276
+ parallelSpeedup: maxWorkerDuration > 0 ? totalDuration / maxWorkerDuration : 1,
277
+ };
278
+ }
279
+ //# sourceMappingURL=RealTestExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealTestExecutor.js","sourceRoot":"","sources":["../../../src/test/partition/RealTestExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Test Dependency Analyzer
3
+ *
4
+ * Uses ts-morph to parse actual TypeScript/JavaScript imports
5
+ * and build a real dependency graph for test partitioning.
6
+ *
7
+ * This replaces the fake "random 30% chance" dependency inference
8
+ * with actual AST-based import analysis.
9
+ */
10
+ import { TestFile } from './types.js';
11
+ export interface DependencyAnalysisResult {
12
+ /** Map of test file path -> list of dependencies */
13
+ dependencies: Map<string, string[]>;
14
+ /** Map of test file path -> list of files that depend on it */
15
+ dependents: Map<string, string[]>;
16
+ /** Shared fixtures/helpers detected */
17
+ sharedFixtures: string[];
18
+ /** Time taken to analyze in ms */
19
+ analysisTimeMs: number;
20
+ }
21
+ export interface TestFileWithHistory {
22
+ path: string;
23
+ /** Average duration from historical data (ms) */
24
+ avgDuration?: number;
25
+ /** Flakiness rate from historical data (0-1) */
26
+ flakinessRate?: number;
27
+ /** Last N execution times */
28
+ recentDurations?: number[];
29
+ }
30
+ /**
31
+ * Analyzes test file dependencies using AST parsing
32
+ */
33
+ export declare class TestDependencyAnalyzer {
34
+ private project;
35
+ private testDirectory;
36
+ private cachedAnalysis;
37
+ constructor(testDirectory?: string);
38
+ /**
39
+ * Analyze dependencies for all test files in the directory
40
+ */
41
+ analyzeTestDependencies(testFiles: string[]): Promise<DependencyAnalysisResult>;
42
+ /**
43
+ * Extract all imports from a source file, resolving to relative paths
44
+ */
45
+ private extractImports;
46
+ /**
47
+ * Resolve an import path to a normalized file path
48
+ */
49
+ private resolveImportPath;
50
+ /**
51
+ * Check if a path looks like a shared fixture/helper
52
+ */
53
+ private isSharedFixture;
54
+ /**
55
+ * Convert analysis result to TestFile array for partitioner
56
+ */
57
+ toTestFiles(testPaths: string[], analysis: DependencyAnalysisResult, history?: Map<string, TestFileWithHistory>): TestFile[];
58
+ /**
59
+ * Estimate test duration based on file size and complexity
60
+ */
61
+ private estimateDuration;
62
+ /**
63
+ * Infer priority from file path
64
+ */
65
+ private inferPriority;
66
+ /**
67
+ * Infer tags from file path
68
+ */
69
+ private inferTags;
70
+ /**
71
+ * Clear cached analysis
72
+ */
73
+ clearCache(): void;
74
+ }
75
+ //# sourceMappingURL=TestDependencyAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestDependencyAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/test/partition/TestDependencyAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKtC,MAAM,WAAW,wBAAwB;IACvC,oDAAoD;IACpD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,+DAA+D;IAC/D,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,uCAAuC;IACvC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAyC;gBAEnD,aAAa,GAAE,MAAgB;IAQ3C;;OAEG;IACU,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IA2E5F;;OAEG;IACH,OAAO,CAAC,cAAc;IAyCtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;IACI,WAAW,CAChB,SAAS,EAAE,MAAM,EAAE,EACnB,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACzC,QAAQ,EAAE;IAgBb;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,OAAO,CAAC,SAAS;IAqBjB;;OAEG;IACI,UAAU,IAAI,IAAI;CAO1B"}
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ /**
3
+ * Test Dependency Analyzer
4
+ *
5
+ * Uses ts-morph to parse actual TypeScript/JavaScript imports
6
+ * and build a real dependency graph for test partitioning.
7
+ *
8
+ * This replaces the fake "random 30% chance" dependency inference
9
+ * with actual AST-based import analysis.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.TestDependencyAnalyzer = void 0;
46
+ const ts_morph_1 = require("ts-morph");
47
+ const path = __importStar(require("path"));
48
+ const fs = __importStar(require("fs"));
49
+ const Logger_js_1 = require("../../utils/Logger.js");
50
+ const logger = Logger_js_1.Logger.getInstance();
51
+ /**
52
+ * Analyzes test file dependencies using AST parsing
53
+ */
54
+ class TestDependencyAnalyzer {
55
+ constructor(testDirectory = 'tests') {
56
+ this.cachedAnalysis = null;
57
+ this.testDirectory = testDirectory;
58
+ this.project = new ts_morph_1.Project({
59
+ skipAddingFilesFromTsConfig: true,
60
+ skipFileDependencyResolution: false,
61
+ });
62
+ }
63
+ /**
64
+ * Analyze dependencies for all test files in the directory
65
+ */
66
+ async analyzeTestDependencies(testFiles) {
67
+ const startTime = performance.now();
68
+ const dependencies = new Map();
69
+ const dependents = new Map();
70
+ const sharedFixtures = new Set();
71
+ // Add all test files to the project
72
+ const sourceFiles = new Map();
73
+ for (const testPath of testFiles) {
74
+ try {
75
+ const absolutePath = path.resolve(testPath);
76
+ if (fs.existsSync(absolutePath)) {
77
+ const sourceFile = this.project.addSourceFileAtPath(absolutePath);
78
+ sourceFiles.set(testPath, sourceFile);
79
+ dependencies.set(testPath, []);
80
+ dependents.set(testPath, []);
81
+ }
82
+ }
83
+ catch (error) {
84
+ logger.warn(`Failed to parse test file: ${testPath}`, { error });
85
+ }
86
+ }
87
+ // Analyze imports for each test file
88
+ const testFileSet = new Set(testFiles);
89
+ for (const [testPath, sourceFile] of sourceFiles) {
90
+ const imports = this.extractImports(sourceFile, testPath);
91
+ for (const importPath of imports) {
92
+ // Check if this import is another test file
93
+ if (testFileSet.has(importPath)) {
94
+ // Direct test-to-test dependency
95
+ dependencies.get(testPath).push(importPath);
96
+ dependents.get(importPath).push(testPath);
97
+ }
98
+ else if (this.isSharedFixture(importPath)) {
99
+ // Shared fixture/helper
100
+ sharedFixtures.add(importPath);
101
+ // Tests sharing the same fixture are implicitly related
102
+ // Find other tests that import the same fixture
103
+ for (const [otherPath, otherSource] of sourceFiles) {
104
+ if (otherPath !== testPath) {
105
+ const otherImports = this.extractImports(otherSource, otherPath);
106
+ if (otherImports.includes(importPath)) {
107
+ // Both tests depend on same fixture - weak coupling
108
+ if (!dependencies.get(testPath).includes(otherPath)) {
109
+ dependencies.get(testPath).push(otherPath);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ const result = {
118
+ dependencies,
119
+ dependents,
120
+ sharedFixtures: Array.from(sharedFixtures),
121
+ analysisTimeMs: performance.now() - startTime,
122
+ };
123
+ this.cachedAnalysis = result;
124
+ logger.info('Test dependency analysis complete', {
125
+ testCount: testFiles.length,
126
+ totalDependencies: Array.from(dependencies.values()).reduce((sum, deps) => sum + deps.length, 0),
127
+ sharedFixtures: sharedFixtures.size,
128
+ analysisTimeMs: result.analysisTimeMs.toFixed(2),
129
+ });
130
+ return result;
131
+ }
132
+ /**
133
+ * Extract all imports from a source file, resolving to relative paths
134
+ */
135
+ extractImports(sourceFile, testPath) {
136
+ const imports = [];
137
+ const testDir = path.dirname(testPath);
138
+ for (const importDecl of sourceFile.getImportDeclarations()) {
139
+ const moduleSpecifier = importDecl.getModuleSpecifierValue();
140
+ // Skip node_modules imports
141
+ if (!moduleSpecifier.startsWith('.') && !moduleSpecifier.startsWith('/')) {
142
+ continue;
143
+ }
144
+ // Resolve relative import to absolute path
145
+ let resolvedPath = this.resolveImportPath(moduleSpecifier, testDir);
146
+ if (resolvedPath) {
147
+ imports.push(resolvedPath);
148
+ }
149
+ }
150
+ // Also check for dynamic imports
151
+ sourceFile.forEachDescendant((node) => {
152
+ if (ts_morph_1.Node.isCallExpression(node)) {
153
+ const expression = node.getExpression();
154
+ if (ts_morph_1.Node.isIdentifier(expression) && expression.getText() === 'require') {
155
+ const args = node.getArguments();
156
+ if (args.length > 0 && ts_morph_1.Node.isStringLiteral(args[0])) {
157
+ const moduleSpecifier = args[0].getLiteralValue();
158
+ if (moduleSpecifier.startsWith('.') || moduleSpecifier.startsWith('/')) {
159
+ const resolvedPath = this.resolveImportPath(moduleSpecifier, testDir);
160
+ if (resolvedPath) {
161
+ imports.push(resolvedPath);
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ });
168
+ return imports;
169
+ }
170
+ /**
171
+ * Resolve an import path to a normalized file path
172
+ */
173
+ resolveImportPath(moduleSpecifier, fromDir) {
174
+ // Handle .js extension in imports (ESM style)
175
+ let cleanSpecifier = moduleSpecifier.replace(/\.js$/, '');
176
+ // Try different extensions
177
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', ''];
178
+ const basePath = path.resolve(fromDir, cleanSpecifier);
179
+ for (const ext of extensions) {
180
+ const fullPath = basePath + ext;
181
+ if (fs.existsSync(fullPath)) {
182
+ // Return path relative to project root
183
+ return path.relative(process.cwd(), fullPath);
184
+ }
185
+ // Also try index files
186
+ const indexPath = path.join(basePath, `index${ext}`);
187
+ if (fs.existsSync(indexPath)) {
188
+ return path.relative(process.cwd(), indexPath);
189
+ }
190
+ }
191
+ return null;
192
+ }
193
+ /**
194
+ * Check if a path looks like a shared fixture/helper
195
+ */
196
+ isSharedFixture(importPath) {
197
+ const lowerPath = importPath.toLowerCase();
198
+ return (lowerPath.includes('fixture') ||
199
+ lowerPath.includes('helper') ||
200
+ lowerPath.includes('mock') ||
201
+ lowerPath.includes('stub') ||
202
+ lowerPath.includes('factory') ||
203
+ lowerPath.includes('setup') ||
204
+ lowerPath.includes('utils') ||
205
+ lowerPath.includes('__mocks__'));
206
+ }
207
+ /**
208
+ * Convert analysis result to TestFile array for partitioner
209
+ */
210
+ toTestFiles(testPaths, analysis, history) {
211
+ return testPaths.map(testPath => {
212
+ const historyData = history?.get(testPath);
213
+ return {
214
+ path: testPath,
215
+ estimatedDuration: historyData?.avgDuration ?? this.estimateDuration(testPath),
216
+ dependencies: analysis.dependencies.get(testPath) ?? [],
217
+ dependents: analysis.dependents.get(testPath) ?? [],
218
+ flakinessScore: historyData?.flakinessRate ?? 0,
219
+ priority: this.inferPriority(testPath),
220
+ tags: this.inferTags(testPath),
221
+ };
222
+ });
223
+ }
224
+ /**
225
+ * Estimate test duration based on file size and complexity
226
+ */
227
+ estimateDuration(testPath) {
228
+ try {
229
+ const absolutePath = path.resolve(testPath);
230
+ if (!fs.existsSync(absolutePath)) {
231
+ return 100; // Default 100ms
232
+ }
233
+ const content = fs.readFileSync(absolutePath, 'utf-8');
234
+ const lines = content.split('\n').length;
235
+ const testCount = (content.match(/\b(it|test)\s*\(/g) || []).length;
236
+ const describeCount = (content.match(/\bdescribe\s*\(/g) || []).length;
237
+ // Estimate: 50ms base + 20ms per test + 5ms per 100 lines
238
+ return 50 + (testCount * 20) + (lines / 100 * 5);
239
+ }
240
+ catch {
241
+ return 100;
242
+ }
243
+ }
244
+ /**
245
+ * Infer priority from file path
246
+ */
247
+ inferPriority(testPath) {
248
+ const lowerPath = testPath.toLowerCase();
249
+ if (lowerPath.includes('critical') || lowerPath.includes('smoke')) {
250
+ return 'critical';
251
+ }
252
+ if (lowerPath.includes('integration') || lowerPath.includes('e2e')) {
253
+ return 'high';
254
+ }
255
+ if (lowerPath.includes('unit')) {
256
+ return 'medium';
257
+ }
258
+ return 'medium';
259
+ }
260
+ /**
261
+ * Infer tags from file path
262
+ */
263
+ inferTags(testPath) {
264
+ const tags = [];
265
+ const pathParts = testPath.toLowerCase().split(/[/\\]/);
266
+ // Extract directory names as tags
267
+ for (const part of pathParts) {
268
+ if (part === 'tests' || part === 'test' || part === '__tests__')
269
+ continue;
270
+ if (part.endsWith('.ts') || part.endsWith('.js'))
271
+ continue;
272
+ if (part.length > 0 && part.length < 30) {
273
+ tags.push(part);
274
+ }
275
+ }
276
+ // Add test type tags
277
+ if (testPath.includes('unit'))
278
+ tags.push('unit');
279
+ if (testPath.includes('integration'))
280
+ tags.push('integration');
281
+ if (testPath.includes('e2e'))
282
+ tags.push('e2e');
283
+ return [...new Set(tags)]; // Dedupe
284
+ }
285
+ /**
286
+ * Clear cached analysis
287
+ */
288
+ clearCache() {
289
+ this.cachedAnalysis = null;
290
+ this.project = new ts_morph_1.Project({
291
+ skipAddingFilesFromTsConfig: true,
292
+ skipFileDependencyResolution: false,
293
+ });
294
+ }
295
+ }
296
+ exports.TestDependencyAnalyzer = TestDependencyAnalyzer;
297
+ //# sourceMappingURL=TestDependencyAnalyzer.js.map