agentic-qe 3.7.5 → 3.7.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 (80) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +18 -0
  3. package/dist/cli/bundle.js +5199 -1335
  4. package/dist/cli/commands/security.d.ts.map +1 -1
  5. package/dist/cli/commands/security.js +66 -1
  6. package/dist/cli/commands/security.js.map +1 -1
  7. package/dist/cli/commands/test.d.ts.map +1 -1
  8. package/dist/cli/commands/test.js +86 -3
  9. package/dist/cli/commands/test.js.map +1 -1
  10. package/dist/cli/index.js +119 -0
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/coordination/workflow-orchestrator.d.ts.map +1 -1
  13. package/dist/coordination/workflow-orchestrator.js +2 -6
  14. package/dist/coordination/workflow-orchestrator.js.map +1 -1
  15. package/dist/mcp/bundle.js +3977 -153
  16. package/dist/mcp/handlers/core-handlers.d.ts.map +1 -1
  17. package/dist/mcp/handlers/core-handlers.js +35 -0
  18. package/dist/mcp/handlers/core-handlers.js.map +1 -1
  19. package/dist/mcp/protocol-server.d.ts.map +1 -1
  20. package/dist/mcp/protocol-server.js +4 -1
  21. package/dist/mcp/protocol-server.js.map +1 -1
  22. package/dist/mcp/qe-tool-bridge.d.ts +27 -0
  23. package/dist/mcp/qe-tool-bridge.d.ts.map +1 -0
  24. package/dist/mcp/qe-tool-bridge.js +87 -0
  25. package/dist/mcp/qe-tool-bridge.js.map +1 -0
  26. package/dist/mcp/tools/registry.d.ts +4 -0
  27. package/dist/mcp/tools/registry.d.ts.map +1 -1
  28. package/dist/mcp/tools/registry.js +20 -0
  29. package/dist/mcp/tools/registry.js.map +1 -1
  30. package/dist/mcp/tools/security-compliance/visual-security.d.ts +45 -0
  31. package/dist/mcp/tools/security-compliance/visual-security.d.ts.map +1 -0
  32. package/dist/mcp/tools/security-compliance/visual-security.js +218 -0
  33. package/dist/mcp/tools/security-compliance/visual-security.js.map +1 -0
  34. package/dist/mcp/tools/test-execution/browser-workflow.d.ts +50 -0
  35. package/dist/mcp/tools/test-execution/browser-workflow.d.ts.map +1 -0
  36. package/dist/mcp/tools/test-execution/browser-workflow.js +145 -0
  37. package/dist/mcp/tools/test-execution/browser-workflow.js.map +1 -0
  38. package/dist/mcp/tools/test-execution/load-test.d.ts +37 -0
  39. package/dist/mcp/tools/test-execution/load-test.d.ts.map +1 -0
  40. package/dist/mcp/tools/test-execution/load-test.js +98 -0
  41. package/dist/mcp/tools/test-execution/load-test.js.map +1 -0
  42. package/dist/mcp/tools/test-execution/schedule.d.ts +44 -0
  43. package/dist/mcp/tools/test-execution/schedule.d.ts.map +1 -0
  44. package/dist/mcp/tools/test-execution/schedule.js +96 -0
  45. package/dist/mcp/tools/test-execution/schedule.js.map +1 -0
  46. package/dist/planning/goap-planner.d.ts.map +1 -1
  47. package/dist/planning/goap-planner.js +7 -28
  48. package/dist/planning/goap-planner.js.map +1 -1
  49. package/dist/planning/plan-executor.d.ts.map +1 -1
  50. package/dist/planning/plan-executor.js +7 -28
  51. package/dist/planning/plan-executor.js.map +1 -1
  52. package/package.json +3 -10
  53. package/dist/cli/commands/qe-tools.d.ts +0 -27
  54. package/dist/cli/commands/qe-tools.d.ts.map +0 -1
  55. package/dist/cli/commands/qe-tools.js +0 -771
  56. package/dist/cli/commands/qe-tools.js.map +0 -1
  57. package/dist/neural-optimizer/index.d.ts +0 -55
  58. package/dist/neural-optimizer/index.d.ts.map +0 -1
  59. package/dist/neural-optimizer/index.js +0 -57
  60. package/dist/neural-optimizer/index.js.map +0 -1
  61. package/dist/neural-optimizer/replay-buffer.d.ts +0 -126
  62. package/dist/neural-optimizer/replay-buffer.d.ts.map +0 -1
  63. package/dist/neural-optimizer/replay-buffer.js +0 -356
  64. package/dist/neural-optimizer/replay-buffer.js.map +0 -1
  65. package/dist/neural-optimizer/swarm-topology.d.ts +0 -157
  66. package/dist/neural-optimizer/swarm-topology.d.ts.map +0 -1
  67. package/dist/neural-optimizer/swarm-topology.js +0 -384
  68. package/dist/neural-optimizer/swarm-topology.js.map +0 -1
  69. package/dist/neural-optimizer/topology-optimizer.d.ts +0 -137
  70. package/dist/neural-optimizer/topology-optimizer.d.ts.map +0 -1
  71. package/dist/neural-optimizer/topology-optimizer.js +0 -657
  72. package/dist/neural-optimizer/topology-optimizer.js.map +0 -1
  73. package/dist/neural-optimizer/types.d.ts +0 -333
  74. package/dist/neural-optimizer/types.d.ts.map +0 -1
  75. package/dist/neural-optimizer/types.js +0 -57
  76. package/dist/neural-optimizer/types.js.map +0 -1
  77. package/dist/neural-optimizer/value-network.d.ts +0 -129
  78. package/dist/neural-optimizer/value-network.d.ts.map +0 -1
  79. package/dist/neural-optimizer/value-network.js +0 -279
  80. package/dist/neural-optimizer/value-network.js.map +0 -1
@@ -20388,7 +20388,7 @@ var init_ollama_client = __esm({
20388
20388
  * Sleep utility for retry delays
20389
20389
  */
20390
20390
  sleep(ms) {
20391
- return new Promise((resolve9) => setTimeout(resolve9, ms));
20391
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
20392
20392
  }
20393
20393
  /**
20394
20394
  * Get Ollama server info
@@ -23174,7 +23174,7 @@ Focus on accuracy over speed. It's better to mark something as "INCONCLUSIVE" if
23174
23174
  * Sleep for specified milliseconds
23175
23175
  */
23176
23176
  sleep(ms) {
23177
- return new Promise((resolve9) => setTimeout(resolve9, ms));
23177
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
23178
23178
  }
23179
23179
  /**
23180
23180
  * Get cost per token for current model
@@ -23500,7 +23500,7 @@ Focus on accuracy over speed. It's better to mark something as "INCONCLUSIVE" if
23500
23500
  * Sleep for specified milliseconds
23501
23501
  */
23502
23502
  sleep(ms) {
23503
- return new Promise((resolve9) => setTimeout(resolve9, ms));
23503
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
23504
23504
  }
23505
23505
  /**
23506
23506
  * Get cost per token for current model
@@ -23784,7 +23784,7 @@ Focus on accuracy over speed. It's better to mark something as "INCONCLUSIVE" if
23784
23784
  * Sleep for specified milliseconds
23785
23785
  */
23786
23786
  sleep(ms) {
23787
- return new Promise((resolve9) => setTimeout(resolve9, ms));
23787
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
23788
23788
  }
23789
23789
  /**
23790
23790
  * Get cost per token for current model
@@ -24070,7 +24070,7 @@ var init_openrouter_provider = __esm({
24070
24070
  * Sleep for a given duration
24071
24071
  */
24072
24072
  sleep(ms) {
24073
- return new Promise((resolve9) => setTimeout(resolve9, ms));
24073
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
24074
24074
  }
24075
24075
  /**
24076
24076
  * Get default system prompt for security verification
@@ -24353,7 +24353,7 @@ var init_ollama_provider = __esm({
24353
24353
  * Sleep for a given duration
24354
24354
  */
24355
24355
  sleep(ms) {
24356
- return new Promise((resolve9) => setTimeout(resolve9, ms));
24356
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
24357
24357
  }
24358
24358
  /**
24359
24359
  * Get default system prompt for security verification
@@ -40800,7 +40800,7 @@ Provide:
40800
40800
  return err(new Error(`Test file not found: ${file}`));
40801
40801
  }
40802
40802
  const { command, args } = this.buildTestCommand(file, framework);
40803
- return new Promise((resolve9) => {
40803
+ return new Promise((resolve10) => {
40804
40804
  let stdout = "";
40805
40805
  let stderr = "";
40806
40806
  let killed = false;
@@ -40817,7 +40817,7 @@ Provide:
40817
40817
  const timeoutId = setTimeout(() => {
40818
40818
  killed = true;
40819
40819
  proc.kill("SIGTERM");
40820
- resolve9(err(new Error(`Test execution timed out after ${timeout}ms for file: ${file}`)));
40820
+ resolve10(err(new Error(`Test execution timed out after ${timeout}ms for file: ${file}`)));
40821
40821
  }, timeout);
40822
40822
  proc.stdout?.on("data", (data) => {
40823
40823
  stdout += data.toString();
@@ -40831,11 +40831,11 @@ Provide:
40831
40831
  return;
40832
40832
  }
40833
40833
  const parseResult = this.parseTestOutput(stdout, stderr, file, framework, code);
40834
- resolve9(parseResult);
40834
+ resolve10(parseResult);
40835
40835
  });
40836
40836
  proc.on("error", (error) => {
40837
40837
  clearTimeout(timeoutId);
40838
- resolve9(err(new Error(`Failed to spawn test runner: ${error.message}. Is '${command}' installed?`)));
40838
+ resolve10(err(new Error(`Failed to spawn test runner: ${error.message}. Is '${command}' installed?`)));
40839
40839
  });
40840
40840
  });
40841
40841
  }
@@ -41430,7 +41430,7 @@ var init_flaky_detector = __esm({
41430
41430
  const results = /* @__PURE__ */ new Map();
41431
41431
  const runId = v4_default();
41432
41432
  const startTime = Date.now();
41433
- return new Promise((resolve9, reject) => {
41433
+ return new Promise((resolve10, reject) => {
41434
41434
  const args = [...this.config.testRunnerArgs, file];
41435
41435
  const cwd = this.config.cwd ?? process.cwd();
41436
41436
  const child = spawn2(this.config.testRunner, args, {
@@ -41495,7 +41495,7 @@ var init_flaky_detector = __esm({
41495
41495
  results.set(testId, records);
41496
41496
  }
41497
41497
  }
41498
- resolve9(results);
41498
+ resolve10(results);
41499
41499
  } catch (parseError) {
41500
41500
  const testId = this.generateTestId(file, "main");
41501
41501
  results.set(testId, [
@@ -41511,7 +41511,7 @@ var init_flaky_detector = __esm({
41511
41511
  }
41512
41512
  }
41513
41513
  ]);
41514
- resolve9(results);
41514
+ resolve10(results);
41515
41515
  }
41516
41516
  });
41517
41517
  });
@@ -42394,7 +42394,7 @@ var init_retry_handler = __esm({
42394
42394
  * Spawn a test process and parse the result
42395
42395
  */
42396
42396
  spawnTestProcess(command, args, cwd) {
42397
- return new Promise((resolve9, reject) => {
42397
+ return new Promise((resolve10, reject) => {
42398
42398
  const timeout = this.config.testTimeout;
42399
42399
  let stdout = "";
42400
42400
  let stderr = "";
@@ -42423,7 +42423,7 @@ var init_retry_handler = __esm({
42423
42423
  return;
42424
42424
  }
42425
42425
  const result = this.parseTestResult(code, stdout, stderr);
42426
- resolve9(result);
42426
+ resolve10(result);
42427
42427
  });
42428
42428
  proc.on("error", (err4) => {
42429
42429
  clearTimeout(timeoutHandle);
@@ -42512,7 +42512,7 @@ var init_retry_handler = __esm({
42512
42512
  return Math.min(delay, maxDelay);
42513
42513
  }
42514
42514
  sleep(ms) {
42515
- return new Promise((resolve9) => setTimeout(resolve9, ms));
42515
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
42516
42516
  }
42517
42517
  async recordRetry(testId, result) {
42518
42518
  const history = this.retryHistory.get(testId) ?? [];
@@ -43253,7 +43253,7 @@ var init_command_executor = __esm({
43253
43253
  * Execute a command asynchronously (for long-running ops)
43254
43254
  */
43255
43255
  async executeAsync(command, args = []) {
43256
- return new Promise((resolve9) => {
43256
+ return new Promise((resolve10) => {
43257
43257
  const fullArgs = this.buildArgs(command, args);
43258
43258
  if (this.config.debug) {
43259
43259
  console.log(`[agent-browser] Executing async: npx agent-browser ${fullArgs.join(" ")}`);
@@ -43273,16 +43273,16 @@ var init_command_executor = __esm({
43273
43273
  if (code === 0) {
43274
43274
  try {
43275
43275
  const parsed = safeJsonParse(stdout.trim());
43276
- resolve9({ success: true, data: parsed });
43276
+ resolve10({ success: true, data: parsed });
43277
43277
  } catch {
43278
- resolve9({ success: true, data: stdout.trim() });
43278
+ resolve10({ success: true, data: stdout.trim() });
43279
43279
  }
43280
43280
  } else {
43281
- resolve9({ success: false, error: stderr || `Exit code: ${code}` });
43281
+ resolve10({ success: false, error: stderr || `Exit code: ${code}` });
43282
43282
  }
43283
43283
  });
43284
43284
  process2.on("error", (error) => {
43285
- resolve9({ success: false, error: error.message });
43285
+ resolve10({ success: false, error: error.message });
43286
43286
  });
43287
43287
  });
43288
43288
  }
@@ -45933,7 +45933,7 @@ var init_wait_condition_handler = __esm({
45933
45933
  * Delay execution
45934
45934
  */
45935
45935
  delay(ms) {
45936
- return new Promise((resolve9) => setTimeout(resolve9, ms));
45936
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
45937
45937
  }
45938
45938
  };
45939
45939
  }
@@ -46369,7 +46369,7 @@ var init_step_executors = __esm({
46369
46369
  return new URL(url, baseUrl).toString();
46370
46370
  }
46371
46371
  delay(ms) {
46372
- return new Promise((resolve9) => setTimeout(resolve9, ms));
46372
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
46373
46373
  }
46374
46374
  };
46375
46375
  }
@@ -46793,13 +46793,13 @@ var init_step_retry_handler = __esm({
46793
46793
  * Wrap promise with timeout
46794
46794
  */
46795
46795
  async withTimeout(promise, timeout, stepId) {
46796
- return new Promise((resolve9, reject) => {
46796
+ return new Promise((resolve10, reject) => {
46797
46797
  const timer = setTimeout(() => {
46798
46798
  reject(new StepTimeoutError(stepId, timeout));
46799
46799
  }, timeout);
46800
46800
  promise.then((result) => {
46801
46801
  clearTimeout(timer);
46802
- resolve9(result);
46802
+ resolve10(result);
46803
46803
  }).catch((error) => {
46804
46804
  clearTimeout(timer);
46805
46805
  reject(error);
@@ -46810,7 +46810,7 @@ var init_step_retry_handler = __esm({
46810
46810
  * Delay execution
46811
46811
  */
46812
46812
  delay(ms) {
46813
- return new Promise((resolve9) => setTimeout(resolve9, ms));
46813
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
46814
46814
  }
46815
46815
  };
46816
46816
  }
@@ -47173,7 +47173,7 @@ var init_e2e_coordinator = __esm({
47173
47173
  * Delay execution
47174
47174
  */
47175
47175
  delay(ms) {
47176
- return new Promise((resolve9) => setTimeout(resolve9, ms));
47176
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
47177
47177
  }
47178
47178
  /**
47179
47179
  * Log message if verbose mode is enabled
@@ -70885,6 +70885,10 @@ var init_semantic_analyzer = __esm({
70885
70885
  });
70886
70886
 
70887
70887
  // src/domains/code-intelligence/services/impact-analyzer.ts
70888
+ var impact_analyzer_exports = {};
70889
+ __export(impact_analyzer_exports, {
70890
+ ImpactAnalyzerService: () => ImpactAnalyzerService
70891
+ });
70888
70892
  var DEFAULT_CONFIG38, ImpactAnalyzerService;
70889
70893
  var init_impact_analyzer = __esm({
70890
70894
  "src/domains/code-intelligence/services/impact-analyzer.ts"() {
@@ -77258,7 +77262,7 @@ var init_http_client = __esm({
77258
77262
  * Sleep utility for retry delays
77259
77263
  */
77260
77264
  sleep(ms) {
77261
- return new Promise((resolve9) => setTimeout(resolve9, ms));
77265
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
77262
77266
  }
77263
77267
  };
77264
77268
  }
@@ -92374,13 +92378,13 @@ Provide:
92374
92378
  }
92375
92379
  }
92376
92380
  async executeTcpProbe(probe) {
92377
- return new Promise((resolve9) => {
92381
+ return new Promise((resolve10) => {
92378
92382
  try {
92379
92383
  const [host, portStr] = probe.target.split(":");
92380
92384
  const port = parseInt(portStr, 10);
92381
92385
  if (!host || isNaN(port)) {
92382
92386
  console.log(`TCP probe invalid target: ${probe.target} (expected host:port)`);
92383
- resolve9(false);
92387
+ resolve10(false);
92384
92388
  return;
92385
92389
  }
92386
92390
  const timeout = probe.timeout ?? 5e3;
@@ -92388,22 +92392,22 @@ Provide:
92388
92392
  const timer = setTimeout(() => {
92389
92393
  socket.destroy();
92390
92394
  console.log(`TCP probe timeout: ${probe.name} -> ${probe.target}`);
92391
- resolve9(false);
92395
+ resolve10(false);
92392
92396
  }, timeout);
92393
92397
  socket.connect(port, host, () => {
92394
92398
  clearTimeout(timer);
92395
92399
  socket.destroy();
92396
- resolve9(true);
92400
+ resolve10(true);
92397
92401
  });
92398
92402
  socket.on("error", (err4) => {
92399
92403
  clearTimeout(timer);
92400
92404
  socket.destroy();
92401
92405
  console.log(`TCP probe error: ${probe.name} -> ${err4.message}`);
92402
- resolve9(false);
92406
+ resolve10(false);
92403
92407
  });
92404
92408
  } catch (error) {
92405
92409
  console.log(`TCP probe exception: ${probe.name} -> ${toErrorMessage(error)}`);
92406
- resolve9(false);
92410
+ resolve10(false);
92407
92411
  }
92408
92412
  });
92409
92413
  }
@@ -92442,13 +92446,13 @@ Provide:
92442
92446
  // Node.js checks
92443
92447
  ];
92444
92448
  async executeCommandProbe(probe) {
92445
- return new Promise((resolve9) => {
92449
+ return new Promise((resolve10) => {
92446
92450
  const timeout = probe.timeout ?? 1e4;
92447
92451
  const validation = validateCommand(probe.target, _ChaosEngineerService.ALLOWED_PROBE_COMMANDS);
92448
92452
  if (!validation.valid) {
92449
92453
  console.log(`Command probe ${probe.name} blocked: ${validation.error}`);
92450
92454
  console.log(`Blocked patterns: ${validation.blockedPatterns?.join(", ") || "none"}`);
92451
- resolve9(false);
92455
+ resolve10(false);
92452
92456
  return;
92453
92457
  }
92454
92458
  const sanitizedCommand = validation.sanitizedCommand || probe.target;
@@ -92458,7 +92462,7 @@ Provide:
92458
92462
  execFile(executable, args, { timeout }, (error, stdout, _stderr) => {
92459
92463
  if (error) {
92460
92464
  console.log(`Command probe failed: ${probe.name} -> ${error.message}`);
92461
- resolve9(false);
92465
+ resolve10(false);
92462
92466
  return;
92463
92467
  }
92464
92468
  if (probe.expectedOutput !== void 0) {
@@ -92466,10 +92470,10 @@ Provide:
92466
92470
  if (!passed) {
92467
92471
  console.log(`Command probe ${probe.name}: output did not contain expected value`);
92468
92472
  }
92469
- resolve9(passed);
92473
+ resolve10(passed);
92470
92474
  return;
92471
92475
  }
92472
- resolve9(true);
92476
+ resolve10(true);
92473
92477
  });
92474
92478
  });
92475
92479
  }
@@ -92789,7 +92793,7 @@ Provide:
92789
92793
  // No-op commands
92790
92794
  ];
92791
92795
  executeCommandRollback(command, timeout) {
92792
- return new Promise((resolve9, reject) => {
92796
+ return new Promise((resolve10, reject) => {
92793
92797
  const validation = validateCommand(command, _ChaosEngineerService.ALLOWED_ROLLBACK_COMMANDS);
92794
92798
  if (!validation.valid) {
92795
92799
  reject(new Error(`Rollback command blocked: ${validation.error}`));
@@ -92803,7 +92807,7 @@ Provide:
92803
92807
  if (error) {
92804
92808
  reject(new Error(`Command rollback failed: ${error.message}. ${stderr}`));
92805
92809
  } else {
92806
- resolve9();
92810
+ resolve10();
92807
92811
  }
92808
92812
  });
92809
92813
  });
@@ -92824,7 +92828,7 @@ Provide:
92824
92828
  await this.sleep(100);
92825
92829
  }
92826
92830
  sleep(ms) {
92827
- return new Promise((resolve9) => setTimeout(resolve9, ms));
92831
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
92828
92832
  }
92829
92833
  };
92830
92834
  }
@@ -93382,7 +93386,7 @@ var init_load_tester = __esm({
93382
93386
  return result;
93383
93387
  }
93384
93388
  sleep(ms) {
93385
- return new Promise((resolve9) => setTimeout(resolve9, ms));
93389
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
93386
93390
  }
93387
93391
  };
93388
93392
  }
@@ -93954,7 +93958,7 @@ var init_performance_profiler = __esm({
93954
93958
  );
93955
93959
  }
93956
93960
  sleep(ms) {
93957
- return new Promise((resolve9) => setTimeout(resolve9, ms));
93961
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
93958
93962
  }
93959
93963
  };
93960
93964
  }
@@ -99941,7 +99945,7 @@ var init_spreading_activation = __esm({
99941
99945
  * Helper to sleep for a duration
99942
99946
  */
99943
99947
  sleep(ms) {
99944
- return new Promise((resolve9) => setTimeout(resolve9, ms));
99948
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
99945
99949
  }
99946
99950
  };
99947
99951
  }
@@ -105018,14 +105022,13 @@ var init_workflow_orchestrator = __esm({
105018
105022
  let current = obj;
105019
105023
  for (let i58 = 0; i58 < parts.length - 1; i58++) {
105020
105024
  const part = parts[i58];
105021
- if (dangerousKeys.has(part)) throw new Error(`Invalid path segment: '${part}' is a dangerous prototype key`);
105022
105025
  if (!Object.hasOwn(current, part)) {
105023
- Object.defineProperty(current, part, { value: /* @__PURE__ */ Object.create(null), writable: true, enumerable: true, configurable: true });
105026
+ const container = /* @__PURE__ */ Object.create(null);
105027
+ Object.defineProperty(current, part, { value: container, writable: true, enumerable: true, configurable: true });
105024
105028
  }
105025
105029
  current = current[part];
105026
105030
  }
105027
105031
  const finalKey = parts[parts.length - 1];
105028
- if (dangerousKeys.has(finalKey)) throw new Error(`Invalid final key: '${finalKey}' is a dangerous prototype key`);
105029
105032
  Object.defineProperty(current, finalKey, { value, writable: true, enumerable: true, configurable: true });
105030
105033
  }
105031
105034
  // ============================================================================
@@ -105264,7 +105267,7 @@ var init_workflow_orchestrator = __esm({
105264
105267
  // Private Methods - Utilities
105265
105268
  // ============================================================================
105266
105269
  delay(ms) {
105267
- return new Promise((resolve9) => setTimeout(resolve9, ms));
105270
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
105268
105271
  }
105269
105272
  };
105270
105273
  }
@@ -115075,7 +115078,7 @@ function startWorkStealingTimer(config, doStealing) {
115075
115078
  clearInterval(timer);
115076
115079
  return;
115077
115080
  }
115078
- await new Promise((resolve9) => setTimeout(resolve9, backoffMs));
115081
+ await new Promise((resolve10) => setTimeout(resolve10, backoffMs));
115079
115082
  }
115080
115083
  }, config.workStealing.checkInterval);
115081
115084
  return timer;
@@ -134566,13 +134569,13 @@ var init_trajectory_bridge = __esm({
134566
134569
  */
134567
134570
  async persistTrajectory(trajectory) {
134568
134571
  try {
134569
- const { join: join28 } = await import("path");
134572
+ const { join: join29 } = await import("path");
134570
134573
  const { existsSync: existsSync20, mkdirSync: mkdirSync6 } = await import("fs");
134571
134574
  const { createRequire: createRequire12 } = await import("module");
134572
134575
  const require3 = createRequire12(import.meta.url);
134573
134576
  const { openDatabase: openDatabase2 } = require3("../../shared/safe-db.js");
134574
- const dbPath = join28(this.options.projectRoot, ".agentic-qe", "trajectories.db");
134575
- const dir = join28(this.options.projectRoot, ".agentic-qe");
134577
+ const dbPath = join29(this.options.projectRoot, ".agentic-qe", "trajectories.db");
134578
+ const dir = join29(this.options.projectRoot, ".agentic-qe");
134576
134579
  if (!existsSync20(dir)) {
134577
134580
  mkdirSync6(dir, { recursive: true });
134578
134581
  }
@@ -134939,7 +134942,7 @@ var init_pretrain_bridge = __esm({
134939
134942
  try {
134940
134943
  const glob = await import("fast-glob");
134941
134944
  const { existsSync: existsSync20, readFileSync: readFileSync17 } = await import("fs");
134942
- const { join: join28 } = await import("path");
134945
+ const { join: join29 } = await import("path");
134943
134946
  const patterns = depth === "shallow" ? ["*.ts", "*.js", "*.json"] : depth === "medium" ? ["**/*.ts", "**/*.js", "**/*.json", "**/*.py"] : ["**/*"];
134944
134947
  const ignore = ["node_modules/**", "dist/**", "coverage/**", ".git/**"];
134945
134948
  const files = await glob.default(patterns, {
@@ -134956,7 +134959,7 @@ var init_pretrain_bridge = __esm({
134956
134959
  if (file.endsWith(".go")) languages.add("go");
134957
134960
  if (file.endsWith(".rs")) languages.add("rust");
134958
134961
  }
134959
- const packageJsonPath = join28(targetPath, "package.json");
134962
+ const packageJsonPath = join29(targetPath, "package.json");
134960
134963
  if (existsSync20(packageJsonPath)) {
134961
134964
  try {
134962
134965
  const pkg2 = safeJsonParse(readFileSync17(packageJsonPath, "utf-8"));
@@ -139082,7 +139085,7 @@ Ensure prime-radiant-advanced-wasm is installed.`
139082
139085
  * Sleep for a specified duration.
139083
139086
  */
139084
139087
  sleep(ms) {
139085
- return new Promise((resolve9) => setTimeout(resolve9, ms));
139088
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
139086
139089
  }
139087
139090
  // ===========================================================================
139088
139091
  // ADR-052 A4.3: Fallback Mode Management
@@ -140864,7 +140867,7 @@ var init_aqe_learning_engine = __esm({
140864
140867
  try {
140865
140868
  const glob = await import("fast-glob");
140866
140869
  const { existsSync: existsSync20, readFileSync: readFileSync17 } = await import("fs");
140867
- const { join: join28 } = await import("path");
140870
+ const { join: join29 } = await import("path");
140868
140871
  const patterns = depth === "shallow" ? ["*.ts", "*.js", "*.json"] : depth === "medium" ? ["**/*.ts", "**/*.js", "**/*.json", "**/*.py"] : ["**/*"];
140869
140872
  const ignore = ["node_modules/**", "dist/**", "coverage/**", ".git/**"];
140870
140873
  const files = await glob.default(patterns, {
@@ -140881,7 +140884,7 @@ var init_aqe_learning_engine = __esm({
140881
140884
  if (file.endsWith(".go")) languages.add("go");
140882
140885
  if (file.endsWith(".rs")) languages.add("rust");
140883
140886
  }
140884
- const packageJsonPath = join28(targetPath, "package.json");
140887
+ const packageJsonPath = join29(targetPath, "package.json");
140885
140888
  if (existsSync20(packageJsonPath)) {
140886
140889
  try {
140887
140890
  const pkg2 = safeJsonParse(readFileSync17(packageJsonPath, "utf-8"));
@@ -144467,11 +144470,11 @@ async function parseJSONCoverage(jsonPath, projectRoot) {
144467
144470
  }
144468
144471
  async function parseCoverage(coveragePath, projectRoot) {
144469
144472
  const ext = path21.extname(coveragePath).toLowerCase();
144470
- const basename5 = path21.basename(coveragePath).toLowerCase();
144471
- if (ext === ".json" || basename5.includes("coverage-final")) {
144473
+ const basename7 = path21.basename(coveragePath).toLowerCase();
144474
+ if (ext === ".json" || basename7.includes("coverage-final")) {
144472
144475
  return parseJSONCoverage(coveragePath, projectRoot);
144473
144476
  }
144474
- if (basename5 === "lcov.info" || ext === ".info" || basename5.includes("lcov")) {
144477
+ if (basename7 === "lcov.info" || ext === ".info" || basename7.includes("lcov")) {
144475
144478
  return parseLCOV(coveragePath, projectRoot);
144476
144479
  }
144477
144480
  const content = await fs22.readFile(coveragePath, "utf-8");
@@ -151596,31 +151599,16 @@ var init_goap_planner = __esm({
151596
151599
  let current = state2;
151597
151600
  for (let i58 = 0; i58 < parts.length - 1; i58++) {
151598
151601
  const part = parts[i58];
151599
- if (DANGEROUS_PROPS.has(part)) {
151600
- console.warn(`[GOAPPlanner] Blocked prototype pollution: ${part}`);
151601
- return;
151602
- }
151603
151602
  if (!Object.hasOwn(current, part)) {
151604
- Object.defineProperty(current, part, {
151605
- value: /* @__PURE__ */ Object.create(null),
151606
- writable: true,
151607
- enumerable: true,
151608
- configurable: true
151609
- });
151603
+ const container = /* @__PURE__ */ Object.create(null);
151604
+ Object.defineProperty(current, part, { value: container, writable: true, enumerable: true, configurable: true });
151610
151605
  }
151611
- current = current[part];
151606
+ const desc = Object.getOwnPropertyDescriptor(current, part);
151607
+ if (!desc) return;
151608
+ current = desc.value;
151612
151609
  }
151613
151610
  const finalKey = parts[parts.length - 1];
151614
- if (DANGEROUS_PROPS.has(finalKey)) {
151615
- console.warn(`[GOAPPlanner] Blocked prototype pollution: ${finalKey}`);
151616
- return;
151617
- }
151618
- Object.defineProperty(current, finalKey, {
151619
- value,
151620
- writable: true,
151621
- enumerable: true,
151622
- configurable: true
151623
- });
151611
+ Object.defineProperty(current, finalKey, { value, writable: true, enumerable: true, configurable: true });
151624
151612
  }
151625
151613
  /**
151626
151614
  * Create hash of state for deduplication
@@ -152663,31 +152651,16 @@ Expected effects:`;
152663
152651
  let current = state2;
152664
152652
  for (let i58 = 0; i58 < parts.length - 1; i58++) {
152665
152653
  const part = parts[i58];
152666
- if (dangerousProps.has(part)) {
152667
- console.warn(`[PlanExecutor] Blocked prototype pollution: ${part}`);
152668
- return;
152669
- }
152670
152654
  if (!Object.hasOwn(current, part)) {
152671
- Object.defineProperty(current, part, {
152672
- value: /* @__PURE__ */ Object.create(null),
152673
- writable: true,
152674
- enumerable: true,
152675
- configurable: true
152676
- });
152655
+ const container = /* @__PURE__ */ Object.create(null);
152656
+ Object.defineProperty(current, part, { value: container, writable: true, enumerable: true, configurable: true });
152677
152657
  }
152678
- current = current[part];
152658
+ const desc = Object.getOwnPropertyDescriptor(current, part);
152659
+ if (!desc) return;
152660
+ current = desc.value;
152679
152661
  }
152680
152662
  const finalKey = parts[parts.length - 1];
152681
- if (dangerousProps.has(finalKey)) {
152682
- console.warn(`[PlanExecutor] Blocked prototype pollution: ${finalKey}`);
152683
- return;
152684
- }
152685
- Object.defineProperty(current, finalKey, {
152686
- value,
152687
- writable: true,
152688
- enumerable: true,
152689
- configurable: true
152690
- });
152663
+ Object.defineProperty(current, finalKey, { value, writable: true, enumerable: true, configurable: true });
152691
152664
  }
152692
152665
  /**
152693
152666
  * Deep clone world state.
@@ -152713,7 +152686,7 @@ Expected effects:`;
152713
152686
  * Delay helper for exponential backoff
152714
152687
  */
152715
152688
  delay(ms) {
152716
- return new Promise((resolve9) => setTimeout(resolve9, ms));
152689
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
152717
152690
  }
152718
152691
  // ==========================================================================
152719
152692
  // Cleanup
@@ -152745,7 +152718,7 @@ Expected effects:`;
152745
152718
  this.executionDelay = options?.executionDelay ?? 100;
152746
152719
  }
152747
152720
  async spawn(agentType, task) {
152748
- await new Promise((resolve9) => setTimeout(resolve9, this.executionDelay));
152721
+ await new Promise((resolve10) => setTimeout(resolve10, this.executionDelay));
152749
152722
  const success = secureRandom() < this.successRate;
152750
152723
  const agentId = `mock-agent-${randomUUID23().slice(0, 8)}`;
152751
152724
  if (success) {
@@ -156712,6 +156685,3568 @@ var init_analyze2 = __esm({
156712
156685
  }
156713
156686
  });
156714
156687
 
156688
+ // src/test-scheduling/interfaces.ts
156689
+ var DEFAULT_TEST_PHASES;
156690
+ var init_interfaces7 = __esm({
156691
+ "src/test-scheduling/interfaces.ts"() {
156692
+ "use strict";
156693
+ DEFAULT_TEST_PHASES = [
156694
+ {
156695
+ id: "unit",
156696
+ name: "Unit Tests",
156697
+ testTypes: ["unit"],
156698
+ testPatterns: ["**/*.test.ts", "**/*.spec.ts", "!**/*.integration.*", "!**/*.e2e.*"],
156699
+ thresholds: { minPassRate: 0.99, maxFlakyRatio: 0.01, minCoverage: 0.8 },
156700
+ parallelism: 8,
156701
+ timeoutMs: 6e4,
156702
+ failFast: true
156703
+ },
156704
+ {
156705
+ id: "integration",
156706
+ name: "Integration Tests",
156707
+ testTypes: ["integration", "contract"],
156708
+ testPatterns: ["**/*.integration.test.ts", "**/*.integration.spec.ts"],
156709
+ thresholds: { minPassRate: 0.95, maxFlakyRatio: 0.05, minCoverage: 0.7 },
156710
+ parallelism: 4,
156711
+ timeoutMs: 3e5,
156712
+ failFast: false
156713
+ },
156714
+ {
156715
+ id: "e2e",
156716
+ name: "E2E Tests",
156717
+ testTypes: ["e2e", "visual"],
156718
+ testPatterns: ["**/*.e2e.test.ts", "**/*.e2e.spec.ts"],
156719
+ thresholds: { minPassRate: 0.9, maxFlakyRatio: 0.1, minCoverage: 0.5 },
156720
+ parallelism: 2,
156721
+ timeoutMs: 6e5,
156722
+ failFast: false
156723
+ }
156724
+ ];
156725
+ }
156726
+ });
156727
+
156728
+ // src/test-scheduling/phase-scheduler.ts
156729
+ function createPhaseScheduler(executor2, config) {
156730
+ return new PhaseScheduler(executor2, {
156731
+ phases: DEFAULT_TEST_PHASES,
156732
+ failFast: true,
156733
+ retryFailedPhases: false,
156734
+ maxRetries: 1,
156735
+ ...config
156736
+ });
156737
+ }
156738
+ function checkQualityThresholds(result, thresholds) {
156739
+ return result.passRate >= thresholds.minPassRate && result.flakyRatio <= thresholds.maxFlakyRatio && result.coverage >= thresholds.minCoverage;
156740
+ }
156741
+ var PhaseScheduler;
156742
+ var init_phase_scheduler = __esm({
156743
+ "src/test-scheduling/phase-scheduler.ts"() {
156744
+ "use strict";
156745
+ init_interfaces7();
156746
+ PhaseScheduler = class {
156747
+ constructor(executor2, config = {
156748
+ phases: DEFAULT_TEST_PHASES,
156749
+ failFast: true,
156750
+ retryFailedPhases: false,
156751
+ maxRetries: 1
156752
+ }) {
156753
+ this.executor = executor2;
156754
+ this.config = config;
156755
+ }
156756
+ state = "idle";
156757
+ currentPhaseIndex = 0;
156758
+ results = [];
156759
+ startTime;
156760
+ endTime;
156761
+ abortController;
156762
+ // --------------------------------------------------------------------------
156763
+ // Public API
156764
+ // --------------------------------------------------------------------------
156765
+ /**
156766
+ * Run all test phases sequentially
156767
+ */
156768
+ async run() {
156769
+ if (this.state === "running") {
156770
+ throw new Error("Scheduler is already running");
156771
+ }
156772
+ this.state = "running";
156773
+ this.currentPhaseIndex = 0;
156774
+ this.results = [];
156775
+ this.startTime = /* @__PURE__ */ new Date();
156776
+ this.abortController = new AbortController();
156777
+ try {
156778
+ for (const phase of this.config.phases) {
156779
+ if (this.state === "paused") {
156780
+ await this.waitForResume();
156781
+ }
156782
+ if (this.abortController.signal.aborted) {
156783
+ break;
156784
+ }
156785
+ const result = await this.executePhaseWithRetry(phase);
156786
+ this.results.push(result);
156787
+ this.currentPhaseIndex++;
156788
+ this.config.onPhaseComplete?.(result);
156789
+ if (!result.success && this.config.failFast) {
156790
+ this.state = "failed";
156791
+ break;
156792
+ }
156793
+ }
156794
+ this.endTime = /* @__PURE__ */ new Date();
156795
+ this.state = this.results.every((r54) => r54.success) ? "completed" : "failed";
156796
+ this.config.onAllComplete?.(this.results);
156797
+ return this.results;
156798
+ } catch (error) {
156799
+ this.state = "failed";
156800
+ this.endTime = /* @__PURE__ */ new Date();
156801
+ throw error;
156802
+ }
156803
+ }
156804
+ /**
156805
+ * Run a specific phase by ID
156806
+ */
156807
+ async runPhase(phaseId) {
156808
+ const phase = this.config.phases.find((p74) => p74.id === phaseId);
156809
+ if (!phase) {
156810
+ throw new Error(`Phase not found: ${phaseId}`);
156811
+ }
156812
+ return this.executePhaseWithRetry(phase);
156813
+ }
156814
+ /**
156815
+ * Pause execution after current phase completes
156816
+ */
156817
+ pause() {
156818
+ if (this.state === "running") {
156819
+ this.state = "paused";
156820
+ }
156821
+ }
156822
+ /**
156823
+ * Resume paused execution
156824
+ */
156825
+ resume() {
156826
+ if (this.state === "paused") {
156827
+ this.state = "running";
156828
+ }
156829
+ }
156830
+ /**
156831
+ * Abort execution immediately
156832
+ */
156833
+ async abort() {
156834
+ this.abortController?.abort();
156835
+ await this.executor.abort();
156836
+ this.state = "idle";
156837
+ }
156838
+ /**
156839
+ * Get current scheduler stats
156840
+ */
156841
+ getStats() {
156842
+ const durationMs = this.startTime && this.endTime ? this.endTime.getTime() - this.startTime.getTime() : this.startTime ? Date.now() - this.startTime.getTime() : void 0;
156843
+ return {
156844
+ state: this.state,
156845
+ currentPhaseIndex: this.currentPhaseIndex,
156846
+ totalPhases: this.config.phases.length,
156847
+ completedPhases: this.results.filter((r54) => r54.success).length,
156848
+ failedPhases: this.results.filter((r54) => !r54.success).length,
156849
+ results: [...this.results],
156850
+ startTime: this.startTime,
156851
+ endTime: this.endTime,
156852
+ durationMs
156853
+ };
156854
+ }
156855
+ /**
156856
+ * Check if scheduler is ready to run
156857
+ */
156858
+ async isReady() {
156859
+ return this.executor.isReady();
156860
+ }
156861
+ // --------------------------------------------------------------------------
156862
+ // Private Methods
156863
+ // --------------------------------------------------------------------------
156864
+ async executePhaseWithRetry(phase) {
156865
+ let lastResult;
156866
+ const maxAttempts = this.config.retryFailedPhases ? this.config.maxRetries : 1;
156867
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
156868
+ try {
156869
+ lastResult = await this.executor.execute(phase);
156870
+ if (lastResult.success || !this.config.retryFailedPhases) {
156871
+ return lastResult;
156872
+ }
156873
+ } catch (error) {
156874
+ this.config.onError?.(error, phase);
156875
+ if (attempt === maxAttempts) {
156876
+ return this.createErrorResult(phase, error);
156877
+ }
156878
+ }
156879
+ }
156880
+ return lastResult;
156881
+ }
156882
+ createErrorResult(phase, error) {
156883
+ return {
156884
+ phaseId: phase.id,
156885
+ phaseName: phase.name,
156886
+ success: false,
156887
+ passRate: 0,
156888
+ flakyRatio: 0,
156889
+ coverage: 0,
156890
+ durationMs: 0,
156891
+ totalTests: 0,
156892
+ passed: 0,
156893
+ failed: 0,
156894
+ skipped: 0,
156895
+ testResults: [],
156896
+ flakyTests: [],
156897
+ error: error.message
156898
+ };
156899
+ }
156900
+ waitForResume() {
156901
+ return new Promise((resolve10) => {
156902
+ const check = () => {
156903
+ if (this.state !== "paused") {
156904
+ resolve10();
156905
+ } else {
156906
+ setTimeout(check, 100);
156907
+ }
156908
+ };
156909
+ check();
156910
+ });
156911
+ }
156912
+ };
156913
+ }
156914
+ });
156915
+
156916
+ // src/test-scheduling/executors/vitest-executor.ts
156917
+ import { spawn as spawn5 } from "child_process";
156918
+ function createVitestExecutor(config) {
156919
+ return new VitestPhaseExecutor(config);
156920
+ }
156921
+ var VitestPhaseExecutor;
156922
+ var init_vitest_executor = __esm({
156923
+ "src/test-scheduling/executors/vitest-executor.ts"() {
156924
+ "use strict";
156925
+ init_safe_json();
156926
+ VitestPhaseExecutor = class {
156927
+ constructor(config = {}) {
156928
+ this.config = config;
156929
+ }
156930
+ currentProcess = null;
156931
+ isAborted = false;
156932
+ // --------------------------------------------------------------------------
156933
+ // PhaseExecutor Interface
156934
+ // --------------------------------------------------------------------------
156935
+ async execute(phase, testFiles) {
156936
+ this.isAborted = false;
156937
+ const startTime = Date.now();
156938
+ try {
156939
+ const args = this.buildArgs(phase, testFiles);
156940
+ const result = await this.runVitest(args, phase.timeoutMs);
156941
+ const endTime = Date.now();
156942
+ return this.parseResult(phase, result, endTime - startTime);
156943
+ } catch (error) {
156944
+ const endTime = Date.now();
156945
+ return this.createErrorResult(phase, error, endTime - startTime);
156946
+ }
156947
+ }
156948
+ async isReady() {
156949
+ try {
156950
+ const result = await this.runCommand("npx", ["vitest", "--version"], 5e3);
156951
+ return result.exitCode === 0;
156952
+ } catch {
156953
+ return false;
156954
+ }
156955
+ }
156956
+ getName() {
156957
+ return "vitest-executor";
156958
+ }
156959
+ async abort() {
156960
+ this.isAborted = true;
156961
+ if (this.currentProcess) {
156962
+ this.currentProcess.kill("SIGTERM");
156963
+ this.currentProcess = null;
156964
+ }
156965
+ }
156966
+ // --------------------------------------------------------------------------
156967
+ // Private Methods
156968
+ // --------------------------------------------------------------------------
156969
+ buildArgs(phase, testFiles) {
156970
+ const args = ["vitest", "run", "--reporter=json"];
156971
+ if (testFiles && testFiles.length > 0) {
156972
+ args.push(...testFiles);
156973
+ } else {
156974
+ for (const pattern of phase.testPatterns) {
156975
+ if (pattern.startsWith("!")) {
156976
+ args.push("--exclude", pattern.slice(1));
156977
+ } else {
156978
+ args.push(pattern);
156979
+ }
156980
+ }
156981
+ }
156982
+ if (phase.parallelism > 0) {
156983
+ args.push("--pool", "threads");
156984
+ args.push("--poolOptions.threads.maxThreads", String(phase.parallelism));
156985
+ }
156986
+ if (phase.failFast) {
156987
+ args.push("--bail", "1");
156988
+ }
156989
+ args.push("--coverage");
156990
+ args.push("--coverage.reporter", this.config.coverageReporter || "json");
156991
+ if (this.config.coverageDir) {
156992
+ args.push("--coverage.reportsDirectory", this.config.coverageDir);
156993
+ }
156994
+ if (this.config.extraArgs) {
156995
+ args.push(...this.config.extraArgs);
156996
+ }
156997
+ return args;
156998
+ }
156999
+ async runVitest(args, timeoutMs) {
157000
+ const { stdout, exitCode } = await this.runCommand(
157001
+ this.config.vitestPath || "npx",
157002
+ args,
157003
+ timeoutMs
157004
+ );
157005
+ try {
157006
+ const jsonStart = stdout.indexOf("{");
157007
+ const jsonEnd = stdout.lastIndexOf("}");
157008
+ if (jsonStart === -1 || jsonEnd === -1) {
157009
+ throw new Error("No JSON output from Vitest");
157010
+ }
157011
+ const jsonStr = stdout.slice(jsonStart, jsonEnd + 1);
157012
+ return safeJsonParse(jsonStr);
157013
+ } catch (parseError) {
157014
+ return {
157015
+ numTotalTestSuites: 0,
157016
+ numPassedTestSuites: 0,
157017
+ numFailedTestSuites: 0,
157018
+ numTotalTests: 0,
157019
+ numPassedTests: 0,
157020
+ numFailedTests: 0,
157021
+ numPendingTests: 0,
157022
+ success: exitCode === 0,
157023
+ startTime: Date.now(),
157024
+ testResults: []
157025
+ };
157026
+ }
157027
+ }
157028
+ runCommand(command, args, timeoutMs) {
157029
+ return new Promise((resolve10, reject) => {
157030
+ let stdout = "";
157031
+ let stderr = "";
157032
+ const executable = process.platform === "win32" && command === "npx" ? "npx.cmd" : command;
157033
+ this.currentProcess = spawn5(executable, args, {
157034
+ cwd: this.config.cwd || process.cwd(),
157035
+ env: { ...process.env, ...this.config.env },
157036
+ shell: false
157037
+ });
157038
+ const timeout = setTimeout(() => {
157039
+ this.currentProcess?.kill("SIGTERM");
157040
+ reject(new Error(`Test execution timed out after ${timeoutMs}ms`));
157041
+ }, timeoutMs);
157042
+ this.currentProcess.stdout?.on("data", (data) => {
157043
+ stdout += data.toString();
157044
+ });
157045
+ this.currentProcess.stderr?.on("data", (data) => {
157046
+ stderr += data.toString();
157047
+ });
157048
+ this.currentProcess.on("close", (code) => {
157049
+ clearTimeout(timeout);
157050
+ this.currentProcess = null;
157051
+ if (this.isAborted) {
157052
+ reject(new Error("Test execution aborted"));
157053
+ } else {
157054
+ resolve10({ stdout, stderr, exitCode: code ?? 1 });
157055
+ }
157056
+ });
157057
+ this.currentProcess.on("error", (error) => {
157058
+ clearTimeout(timeout);
157059
+ this.currentProcess = null;
157060
+ reject(error);
157061
+ });
157062
+ });
157063
+ }
157064
+ async parseResult(phase, vitestResult, durationMs) {
157065
+ const testResults = [];
157066
+ for (const file of vitestResult.testResults) {
157067
+ for (const assertion of file.assertionResults) {
157068
+ const testResult = {
157069
+ file: file.name,
157070
+ name: assertion.title,
157071
+ suite: assertion.ancestorTitles.join(" > "),
157072
+ passed: assertion.status === "passed",
157073
+ durationMs: assertion.duration || 0,
157074
+ // NOTE: Vitest JSON reporter doesn't include retry data.
157075
+ // Flakiness is detected historically via FlakyTracker.
157076
+ retries: 0,
157077
+ error: assertion.failureMessages.join("\n") || void 0
157078
+ };
157079
+ testResults.push(testResult);
157080
+ }
157081
+ }
157082
+ const tracker = this.config.flakyTracker;
157083
+ if (tracker) {
157084
+ tracker.recordResults(testResults);
157085
+ }
157086
+ const totalTests = vitestResult.numTotalTests;
157087
+ const passed = vitestResult.numPassedTests;
157088
+ const failed = vitestResult.numFailedTests;
157089
+ const skipped = vitestResult.numPendingTests;
157090
+ const passRate = totalTests > 0 ? passed / totalTests : 0;
157091
+ let flakyTests = [];
157092
+ let flakyRatio = 0;
157093
+ if (tracker) {
157094
+ const analysis = tracker.analyze();
157095
+ flakyTests = analysis.flakyTests.map((r54) => r54.testId);
157096
+ const runTestIds = new Set(
157097
+ testResults.map((r54) => `${r54.file}:${r54.suite}:${r54.name}`)
157098
+ );
157099
+ const flakyInRun = flakyTests.filter((id) => runTestIds.has(id));
157100
+ flakyRatio = totalTests > 0 ? flakyInRun.length / totalTests : 0;
157101
+ }
157102
+ const coverage = await this.getCoverageFromReport();
157103
+ const success = passRate >= phase.thresholds.minPassRate && flakyRatio <= phase.thresholds.maxFlakyRatio && coverage >= phase.thresholds.minCoverage;
157104
+ return {
157105
+ phaseId: phase.id,
157106
+ phaseName: phase.name,
157107
+ success,
157108
+ passRate,
157109
+ flakyRatio,
157110
+ coverage,
157111
+ durationMs,
157112
+ totalTests,
157113
+ passed,
157114
+ failed,
157115
+ skipped,
157116
+ testResults,
157117
+ flakyTests
157118
+ };
157119
+ }
157120
+ async getCoverageFromReport() {
157121
+ try {
157122
+ const fs26 = await import("fs/promises");
157123
+ const path26 = await import("path");
157124
+ const coverageDir = this.config.coverageDir || "coverage";
157125
+ const coverageFile = path26.join(
157126
+ this.config.cwd || process.cwd(),
157127
+ coverageDir,
157128
+ "coverage-summary.json"
157129
+ );
157130
+ const content = await fs26.readFile(coverageFile, "utf-8");
157131
+ const coverage = safeJsonParse(content);
157132
+ return (coverage.total?.lines?.pct ?? 0) / 100;
157133
+ } catch {
157134
+ return 0;
157135
+ }
157136
+ }
157137
+ createErrorResult(phase, error, durationMs) {
157138
+ return {
157139
+ phaseId: phase.id,
157140
+ phaseName: phase.name,
157141
+ success: false,
157142
+ passRate: 0,
157143
+ flakyRatio: 0,
157144
+ coverage: 0,
157145
+ durationMs,
157146
+ totalTests: 0,
157147
+ passed: 0,
157148
+ failed: 0,
157149
+ skipped: 0,
157150
+ testResults: [],
157151
+ flakyTests: [],
157152
+ error: error.message
157153
+ };
157154
+ }
157155
+ };
157156
+ }
157157
+ });
157158
+
157159
+ // src/test-scheduling/git-aware/test-selector.ts
157160
+ import { spawn as spawn6 } from "child_process";
157161
+ import { resolve as resolve7, dirname as dirname7, basename as basename4 } from "path";
157162
+ function createTestSelector(config) {
157163
+ return new GitAwareTestSelector(config);
157164
+ }
157165
+ async function getAffectedTests(impactAnalyzer, baseRef, cwd) {
157166
+ const selector = createTestSelector({ impactAnalyzer, baseRef, cwd });
157167
+ const result = await selector.selectAffectedTests();
157168
+ if (result.runAllTests) {
157169
+ return [];
157170
+ }
157171
+ return result.selectedTests;
157172
+ }
157173
+ var DEFAULT_MAPPING_RULES, GitAwareTestSelector;
157174
+ var init_test_selector = __esm({
157175
+ "src/test-scheduling/git-aware/test-selector.ts"() {
157176
+ "use strict";
157177
+ DEFAULT_MAPPING_RULES = [
157178
+ // src/foo/bar.ts -> tests/unit/foo/bar.test.ts
157179
+ {
157180
+ sourcePattern: /^src\/(.+)\.ts$/,
157181
+ toTestPaths: (match, _sourceFile) => {
157182
+ const path26 = match[1];
157183
+ return [
157184
+ `tests/unit/${path26}.test.ts`,
157185
+ `tests/unit/${path26}.spec.ts`,
157186
+ `tests/${path26}.test.ts`,
157187
+ `tests/${path26}.spec.ts`,
157188
+ `src/${path26}.test.ts`,
157189
+ `src/${path26}.spec.ts`
157190
+ ];
157191
+ }
157192
+ },
157193
+ // src/foo/bar/index.ts -> tests/unit/foo/bar.test.ts
157194
+ {
157195
+ sourcePattern: /^src\/(.+)\/index\.ts$/,
157196
+ toTestPaths: (match, _sourceFile) => {
157197
+ const path26 = match[1];
157198
+ return [
157199
+ `tests/unit/${path26}.test.ts`,
157200
+ `tests/unit/${path26}/index.test.ts`,
157201
+ `tests/unit/${path26}.spec.ts`
157202
+ ];
157203
+ }
157204
+ },
157205
+ // Any changed test file selects itself
157206
+ {
157207
+ sourcePattern: /\.(test|spec)\.(ts|tsx|js|jsx)$/,
157208
+ toTestPaths: (_match, sourceFile) => [sourceFile]
157209
+ },
157210
+ // Config files run all tests
157211
+ {
157212
+ sourcePattern: /^(vitest\.config|jest\.config|tsconfig|package\.json)/,
157213
+ toTestPaths: () => ["**/*.test.ts", "**/*.spec.ts"]
157214
+ }
157215
+ ];
157216
+ GitAwareTestSelector = class {
157217
+ constructor(config) {
157218
+ this.config = config;
157219
+ if (!config.impactAnalyzer) {
157220
+ throw new Error(
157221
+ "GitAwareTestSelector requires impactAnalyzer. Use ImpactAnalyzerService from code-intelligence domain. NO FALLBACK TO PATTERN MATCHING - use real dependency analysis."
157222
+ );
157223
+ }
157224
+ this.cwd = config.cwd || process.cwd();
157225
+ this.baseRef = config.baseRef || "HEAD~1";
157226
+ this.mappingRules = config.mappingRules || DEFAULT_MAPPING_RULES;
157227
+ this.impactAnalyzer = config.impactAnalyzer;
157228
+ }
157229
+ cwd;
157230
+ baseRef;
157231
+ mappingRules;
157232
+ impactAnalyzer;
157233
+ // --------------------------------------------------------------------------
157234
+ // Public API
157235
+ // --------------------------------------------------------------------------
157236
+ /**
157237
+ * Get tests affected by changes since base ref
157238
+ */
157239
+ async selectAffectedTests() {
157240
+ try {
157241
+ const changedFiles = await this.getChangedFiles();
157242
+ if (changedFiles.length === 0) {
157243
+ return {
157244
+ changedFiles: [],
157245
+ selectedTests: [],
157246
+ mappings: [],
157247
+ runAllTests: false
157248
+ };
157249
+ }
157250
+ const { selectedTests, mappings, runAllTests, runAllReason } = await this.mapChangesToTests(changedFiles);
157251
+ return {
157252
+ changedFiles,
157253
+ selectedTests: [...new Set(selectedTests)],
157254
+ // Dedupe
157255
+ mappings,
157256
+ runAllTests,
157257
+ runAllReason
157258
+ };
157259
+ } catch (error) {
157260
+ return {
157261
+ changedFiles: [],
157262
+ selectedTests: [],
157263
+ mappings: [],
157264
+ runAllTests: true,
157265
+ runAllReason: `Git error: ${error.message}`
157266
+ };
157267
+ }
157268
+ }
157269
+ /**
157270
+ * Get tests for a specific list of changed files
157271
+ */
157272
+ async selectTestsForFiles(files) {
157273
+ const changedFiles = files.map((path26) => ({
157274
+ path: path26,
157275
+ changeType: "modified"
157276
+ }));
157277
+ const { selectedTests, mappings, runAllTests, runAllReason } = await this.mapChangesToTests(changedFiles);
157278
+ return {
157279
+ changedFiles,
157280
+ selectedTests: [...new Set(selectedTests)],
157281
+ mappings,
157282
+ runAllTests,
157283
+ runAllReason
157284
+ };
157285
+ }
157286
+ /**
157287
+ * Get changed files since base ref
157288
+ */
157289
+ async getChangedFiles() {
157290
+ const output = await this.git([
157291
+ "diff",
157292
+ "--name-status",
157293
+ this.baseRef,
157294
+ "HEAD"
157295
+ ]);
157296
+ const lines = output.trim().split("\n").filter(Boolean);
157297
+ const changedFiles = [];
157298
+ for (const line of lines) {
157299
+ const [status, ...pathParts] = line.split(" ");
157300
+ const path26 = pathParts.join(" ");
157301
+ let changeType;
157302
+ let previousPath;
157303
+ switch (status[0]) {
157304
+ case "A":
157305
+ changeType = "added";
157306
+ break;
157307
+ case "M":
157308
+ changeType = "modified";
157309
+ break;
157310
+ case "D":
157311
+ changeType = "deleted";
157312
+ break;
157313
+ case "R":
157314
+ changeType = "renamed";
157315
+ previousPath = path26;
157316
+ break;
157317
+ default:
157318
+ changeType = "modified";
157319
+ }
157320
+ changedFiles.push({
157321
+ path: changeType === "renamed" ? pathParts[1] || path26 : path26,
157322
+ changeType,
157323
+ previousPath
157324
+ });
157325
+ }
157326
+ return changedFiles;
157327
+ }
157328
+ /**
157329
+ * Get the merge base between current branch and main
157330
+ */
157331
+ async getMergeBase(targetBranch = "main") {
157332
+ try {
157333
+ const output = await this.git(["merge-base", "HEAD", targetBranch]);
157334
+ return output.trim();
157335
+ } catch {
157336
+ const output = await this.git(["merge-base", "HEAD", "master"]);
157337
+ return output.trim();
157338
+ }
157339
+ }
157340
+ // --------------------------------------------------------------------------
157341
+ // Private Methods
157342
+ // --------------------------------------------------------------------------
157343
+ async mapChangesToTests(changedFiles) {
157344
+ const selectedTests = [];
157345
+ const mappings = [];
157346
+ let runAllTests = false;
157347
+ let runAllReason;
157348
+ for (const file of changedFiles) {
157349
+ if (this.isConfigFile(file.path)) {
157350
+ return {
157351
+ selectedTests: [],
157352
+ mappings: [],
157353
+ runAllTests: true,
157354
+ runAllReason: `Config file changed: ${file.path}`
157355
+ };
157356
+ }
157357
+ }
157358
+ const changedPaths = changedFiles.filter((f74) => f74.changeType !== "deleted" || this.config.includeDeletedFileTests).map((f74) => f74.path);
157359
+ if (changedPaths.length === 0) {
157360
+ return { selectedTests: [], mappings: [], runAllTests: false };
157361
+ }
157362
+ const impactResult = await this.impactAnalyzer.getImpactedTests(changedPaths);
157363
+ if (!impactResult.success) {
157364
+ const failureResult = impactResult;
157365
+ const errorMsg = failureResult.error instanceof Error ? failureResult.error.message : String(failureResult.error);
157366
+ return {
157367
+ selectedTests: [],
157368
+ mappings: [],
157369
+ runAllTests: true,
157370
+ runAllReason: `Impact analysis failed: ${errorMsg}`
157371
+ };
157372
+ }
157373
+ if (impactResult.value.length === 0) {
157374
+ return { selectedTests: [], mappings: [], runAllTests: false };
157375
+ }
157376
+ selectedTests.push(...impactResult.value);
157377
+ for (const changedFile of changedFiles) {
157378
+ if (changedFile.changeType === "deleted" && !this.config.includeDeletedFileTests) {
157379
+ continue;
157380
+ }
157381
+ const relatedTests = impactResult.value.filter(
157382
+ (test) => test.includes(basename4(changedFile.path, ".ts").replace(/\.(tsx?|jsx?)$/, ""))
157383
+ );
157384
+ if (relatedTests.length > 0) {
157385
+ mappings.push({
157386
+ sourceFile: changedFile.path,
157387
+ testFiles: relatedTests,
157388
+ confidence: 0.95
157389
+ // High confidence for graph-based analysis
157390
+ });
157391
+ }
157392
+ }
157393
+ return { selectedTests, mappings, runAllTests, runAllReason };
157394
+ }
157395
+ /**
157396
+ * Check if a file is a config file that should trigger full test run
157397
+ */
157398
+ isConfigFile(path26) {
157399
+ return /^(vitest\.config|jest\.config|tsconfig|package\.json)/.test(path26);
157400
+ }
157401
+ async findTestsHeuristically(sourcePath) {
157402
+ const baseName = basename4(sourcePath, ".ts").replace(/\.(tsx?|jsx?)$/, "");
157403
+ const dir = dirname7(sourcePath);
157404
+ const candidates = [
157405
+ `${dir}/${baseName}.test.ts`,
157406
+ `${dir}/${baseName}.spec.ts`,
157407
+ `${dir}/__tests__/${baseName}.test.ts`,
157408
+ `tests/${dir}/${baseName}.test.ts`,
157409
+ `tests/unit/${dir.replace("src/", "")}/${baseName}.test.ts`
157410
+ ];
157411
+ return this.filterExistingFiles(candidates);
157412
+ }
157413
+ async filterExistingFiles(files) {
157414
+ const fs26 = await import("fs/promises");
157415
+ const existing = [];
157416
+ for (const file of files) {
157417
+ try {
157418
+ const fullPath = resolve7(this.cwd, file);
157419
+ await fs26.access(fullPath);
157420
+ existing.push(file);
157421
+ } catch (error) {
157422
+ console.debug("[TestSelector] File access check failed:", error instanceof Error ? error.message : error);
157423
+ }
157424
+ }
157425
+ return existing;
157426
+ }
157427
+ git(args) {
157428
+ return new Promise((resolve10, reject) => {
157429
+ let stdout = "";
157430
+ let stderr = "";
157431
+ const proc = spawn6("git", args, { cwd: this.cwd });
157432
+ proc.stdout.on("data", (data) => {
157433
+ stdout += data.toString();
157434
+ });
157435
+ proc.stderr.on("data", (data) => {
157436
+ stderr += data.toString();
157437
+ });
157438
+ proc.on("close", (code) => {
157439
+ if (code === 0) {
157440
+ resolve10(stdout);
157441
+ } else {
157442
+ reject(new Error(`git ${args.join(" ")} failed: ${stderr}`));
157443
+ }
157444
+ });
157445
+ proc.on("error", reject);
157446
+ });
157447
+ }
157448
+ };
157449
+ }
157450
+ });
157451
+
157452
+ // src/test-scheduling/flaky-tracking/flaky-tracker.ts
157453
+ function createFlakyTracker(config) {
157454
+ return new FlakyTestTracker(config);
157455
+ }
157456
+ async function loadFlakyTracker(historyPath, config) {
157457
+ const tracker = createFlakyTracker({ ...config, historyPath });
157458
+ try {
157459
+ const fs26 = await import("fs/promises");
157460
+ const content = await fs26.readFile(historyPath, "utf-8");
157461
+ const records = safeJsonParse(content);
157462
+ tracker.importHistory(records);
157463
+ } catch (error) {
157464
+ console.debug("[FlakyTracker] History load failed, starting fresh:", error instanceof Error ? error.message : error);
157465
+ }
157466
+ return tracker;
157467
+ }
157468
+ async function saveFlakyTracker(tracker, historyPath) {
157469
+ const fs26 = await import("fs/promises");
157470
+ const history = tracker.exportHistory();
157471
+ await fs26.writeFile(historyPath, JSON.stringify(history, null, 2));
157472
+ }
157473
+ var DEFAULT_CONFIG70, FlakyTestTracker;
157474
+ var init_flaky_tracker = __esm({
157475
+ "src/test-scheduling/flaky-tracking/flaky-tracker.ts"() {
157476
+ "use strict";
157477
+ init_safe_json();
157478
+ DEFAULT_CONFIG70 = {
157479
+ minRunsForFlakiness: 5,
157480
+ flakinessThreshold: 0.1,
157481
+ // 10% failure rate = flaky
157482
+ maxRecentErrors: 5,
157483
+ historyRetentionDays: 30
157484
+ };
157485
+ FlakyTestTracker = class {
157486
+ records = /* @__PURE__ */ new Map();
157487
+ config;
157488
+ constructor(config) {
157489
+ this.config = { ...DEFAULT_CONFIG70, ...config };
157490
+ }
157491
+ // --------------------------------------------------------------------------
157492
+ // Public API
157493
+ // --------------------------------------------------------------------------
157494
+ /**
157495
+ * Record a test execution result
157496
+ */
157497
+ recordResult(result) {
157498
+ const testId = this.getTestId(result);
157499
+ const record = this.getOrCreateRecord(testId, result);
157500
+ record.totalRuns++;
157501
+ record.lastRun = /* @__PURE__ */ new Date();
157502
+ if (result.passed) {
157503
+ record.passCount++;
157504
+ } else {
157505
+ record.failCount++;
157506
+ if (result.error) {
157507
+ record.recentErrors = [
157508
+ result.error,
157509
+ ...record.recentErrors.slice(0, this.config.maxRecentErrors - 1)
157510
+ ];
157511
+ }
157512
+ }
157513
+ if (result.retries > 0 && result.passed) {
157514
+ record.flakyCount++;
157515
+ record.lastFlaky = /* @__PURE__ */ new Date();
157516
+ }
157517
+ record.flakinessScore = this.calculateFlakiness(record);
157518
+ }
157519
+ /**
157520
+ * Record multiple test results
157521
+ */
157522
+ recordResults(results) {
157523
+ for (const result of results) {
157524
+ this.recordResult(result);
157525
+ }
157526
+ }
157527
+ /**
157528
+ * Get flaky test record by ID
157529
+ */
157530
+ getRecord(testId) {
157531
+ return this.records.get(testId);
157532
+ }
157533
+ /**
157534
+ * Get all flaky tests
157535
+ */
157536
+ getFlakyTests() {
157537
+ return Array.from(this.records.values()).filter(
157538
+ (record) => record.totalRuns >= this.config.minRunsForFlakiness && record.flakinessScore >= this.config.flakinessThreshold
157539
+ );
157540
+ }
157541
+ /**
157542
+ * Check if a specific test is flaky
157543
+ */
157544
+ isFlaky(testId) {
157545
+ const record = this.records.get(testId);
157546
+ if (!record) return false;
157547
+ return record.totalRuns >= this.config.minRunsForFlakiness && record.flakinessScore >= this.config.flakinessThreshold;
157548
+ }
157549
+ /**
157550
+ * Get comprehensive flaky analysis
157551
+ */
157552
+ analyze() {
157553
+ const allRecords = Array.from(this.records.values());
157554
+ const flakyTests = allRecords.filter(
157555
+ (r54) => r54.totalRuns >= this.config.minRunsForFlakiness && r54.flakinessScore >= this.config.flakinessThreshold
157556
+ );
157557
+ const stabilizedTests = allRecords.filter(
157558
+ (r54) => r54.totalRuns >= this.config.minRunsForFlakiness && r54.flakyCount > 0 && r54.flakinessScore < this.config.flakinessThreshold
157559
+ );
157560
+ const insufficientData = allRecords.filter(
157561
+ (r54) => r54.totalRuns < this.config.minRunsForFlakiness
157562
+ );
157563
+ const totalWithSufficientData = allRecords.filter(
157564
+ (r54) => r54.totalRuns >= this.config.minRunsForFlakiness
157565
+ );
157566
+ const overallFlakiness = totalWithSufficientData.length > 0 ? flakyTests.length / totalWithSufficientData.length : 0;
157567
+ const trend = this.calculateTrend(flakyTests);
157568
+ return {
157569
+ totalTests: allRecords.length,
157570
+ flakyTests: flakyTests.sort((a37, b68) => b68.flakinessScore - a37.flakinessScore),
157571
+ stabilizedTests,
157572
+ insufficientData,
157573
+ overallFlakiness,
157574
+ trend
157575
+ };
157576
+ }
157577
+ /**
157578
+ * Get quarantine list (tests that should be isolated)
157579
+ */
157580
+ getQuarantineList(threshold = 0.3) {
157581
+ return Array.from(this.records.values()).filter((r54) => r54.flakinessScore >= threshold).map((r54) => r54.testId);
157582
+ }
157583
+ /**
157584
+ * Clear old history based on retention policy
157585
+ */
157586
+ pruneHistory() {
157587
+ const cutoff = /* @__PURE__ */ new Date();
157588
+ cutoff.setDate(cutoff.getDate() - this.config.historyRetentionDays);
157589
+ let pruned = 0;
157590
+ for (const [testId, record] of this.records) {
157591
+ if (record.lastRun < cutoff) {
157592
+ this.records.delete(testId);
157593
+ pruned++;
157594
+ }
157595
+ }
157596
+ return pruned;
157597
+ }
157598
+ /**
157599
+ * Export history for persistence
157600
+ */
157601
+ exportHistory() {
157602
+ return Array.from(this.records.values());
157603
+ }
157604
+ /**
157605
+ * Import history from persistence
157606
+ */
157607
+ importHistory(records) {
157608
+ for (const record of records) {
157609
+ const imported = {
157610
+ ...record,
157611
+ lastRun: new Date(record.lastRun),
157612
+ lastFlaky: record.lastFlaky ? new Date(record.lastFlaky) : void 0
157613
+ };
157614
+ this.records.set(record.testId, imported);
157615
+ }
157616
+ }
157617
+ /**
157618
+ * Reset all tracking data
157619
+ */
157620
+ reset() {
157621
+ this.records.clear();
157622
+ }
157623
+ // --------------------------------------------------------------------------
157624
+ // Private Methods
157625
+ // --------------------------------------------------------------------------
157626
+ getTestId(result) {
157627
+ return `${result.file}:${result.suite}:${result.name}`;
157628
+ }
157629
+ getOrCreateRecord(testId, result) {
157630
+ let record = this.records.get(testId);
157631
+ if (!record) {
157632
+ record = {
157633
+ testId,
157634
+ file: result.file,
157635
+ name: result.name,
157636
+ totalRuns: 0,
157637
+ passCount: 0,
157638
+ failCount: 0,
157639
+ flakyCount: 0,
157640
+ flakinessScore: 0,
157641
+ lastRun: /* @__PURE__ */ new Date(),
157642
+ recentErrors: []
157643
+ };
157644
+ this.records.set(testId, record);
157645
+ }
157646
+ return record;
157647
+ }
157648
+ calculateFlakiness(record) {
157649
+ if (record.totalRuns < this.config.minRunsForFlakiness) {
157650
+ return 0;
157651
+ }
157652
+ const flakyRatio = record.flakyCount / record.totalRuns;
157653
+ const passRatio = record.passCount / record.totalRuns;
157654
+ const inconsistencyScore = passRatio > 0 && passRatio < 1 ? Math.min(passRatio, 1 - passRatio) * 2 : 0;
157655
+ return Math.min(1, flakyRatio * 3 + inconsistencyScore);
157656
+ }
157657
+ calculateTrend(flakyTests) {
157658
+ if (flakyTests.length === 0) {
157659
+ return "stable";
157660
+ }
157661
+ const now = Date.now();
157662
+ const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1e3;
157663
+ let recentFlaky = 0;
157664
+ let oldFlaky = 0;
157665
+ for (const test of flakyTests) {
157666
+ if (test.lastFlaky) {
157667
+ if (test.lastFlaky.getTime() > oneWeekAgo) {
157668
+ recentFlaky++;
157669
+ } else {
157670
+ oldFlaky++;
157671
+ }
157672
+ }
157673
+ }
157674
+ if (recentFlaky > oldFlaky * 1.5) {
157675
+ return "degrading";
157676
+ } else if (oldFlaky > recentFlaky * 1.5) {
157677
+ return "improving";
157678
+ }
157679
+ return "stable";
157680
+ }
157681
+ };
157682
+ }
157683
+ });
157684
+
157685
+ // src/test-scheduling/cicd/github-actions.ts
157686
+ function detectCIEnvironment() {
157687
+ const env = process.env;
157688
+ if (env.GITHUB_ACTIONS === "true") {
157689
+ return {
157690
+ isCI: true,
157691
+ provider: "github-actions",
157692
+ branch: env.GITHUB_HEAD_REF || env.GITHUB_REF_NAME,
157693
+ commitSha: env.GITHUB_SHA,
157694
+ prNumber: env.GITHUB_EVENT_NAME === "pull_request" ? parseInt(env.GITHUB_REF?.split("/")[2] || "", 10) || void 0 : void 0,
157695
+ baseBranch: env.GITHUB_BASE_REF,
157696
+ buildUrl: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}`
157697
+ };
157698
+ }
157699
+ if (env.GITLAB_CI === "true") {
157700
+ return {
157701
+ isCI: true,
157702
+ provider: "gitlab-ci",
157703
+ branch: env.CI_COMMIT_REF_NAME,
157704
+ commitSha: env.CI_COMMIT_SHA,
157705
+ prNumber: env.CI_MERGE_REQUEST_IID ? parseInt(env.CI_MERGE_REQUEST_IID, 10) : void 0,
157706
+ baseBranch: env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME,
157707
+ buildUrl: env.CI_JOB_URL
157708
+ };
157709
+ }
157710
+ if (env.JENKINS_URL) {
157711
+ return {
157712
+ isCI: true,
157713
+ provider: "jenkins",
157714
+ branch: env.GIT_BRANCH || env.BRANCH_NAME,
157715
+ commitSha: env.GIT_COMMIT,
157716
+ prNumber: env.CHANGE_ID ? parseInt(env.CHANGE_ID, 10) : void 0,
157717
+ baseBranch: env.CHANGE_TARGET,
157718
+ buildUrl: env.BUILD_URL
157719
+ };
157720
+ }
157721
+ if (env.CIRCLECI === "true") {
157722
+ return {
157723
+ isCI: true,
157724
+ provider: "circleci",
157725
+ branch: env.CIRCLE_BRANCH,
157726
+ commitSha: env.CIRCLE_SHA1,
157727
+ prNumber: env.CIRCLE_PULL_REQUEST ? parseInt(env.CIRCLE_PULL_REQUEST.split("/").pop() || "", 10) : void 0,
157728
+ buildUrl: env.CIRCLE_BUILD_URL
157729
+ };
157730
+ }
157731
+ if (env.CI === "true" || env.CI === "1") {
157732
+ return {
157733
+ isCI: true,
157734
+ provider: "unknown"
157735
+ };
157736
+ }
157737
+ return { isCI: false };
157738
+ }
157739
+ function createGitHubActionsReporter(config) {
157740
+ return new GitHubActionsReporter(config);
157741
+ }
157742
+ async function reportToGitHubActions(results, config) {
157743
+ const reporter = createGitHubActionsReporter(config);
157744
+ await reporter.writeOutput(results);
157745
+ }
157746
+ var DEFAULT_CONFIG71, GitHubActionsReporter;
157747
+ var init_github_actions = __esm({
157748
+ "src/test-scheduling/cicd/github-actions.ts"() {
157749
+ "use strict";
157750
+ DEFAULT_CONFIG71 = {
157751
+ enableAnnotations: true,
157752
+ enableSummary: true,
157753
+ enableOutputs: true,
157754
+ maxAnnotations: 10,
157755
+ includeFlakyWarnings: true,
157756
+ includeCoverage: true
157757
+ };
157758
+ GitHubActionsReporter = class {
157759
+ config;
157760
+ constructor(config) {
157761
+ this.config = { ...DEFAULT_CONFIG71, ...config };
157762
+ }
157763
+ // --------------------------------------------------------------------------
157764
+ // Public API
157765
+ // --------------------------------------------------------------------------
157766
+ /**
157767
+ * Generate complete GitHub Actions output
157768
+ */
157769
+ generateOutput(results) {
157770
+ const annotations = this.config.enableAnnotations ? this.generateAnnotations(results) : [];
157771
+ const summary = this.config.enableSummary ? this.generateSummary(results) : "";
157772
+ const outputs = this.config.enableOutputs ? this.generateOutputs(results) : {};
157773
+ return { summary, annotations, outputs };
157774
+ }
157775
+ /**
157776
+ * Write output to GitHub Actions
157777
+ */
157778
+ async writeOutput(results) {
157779
+ const output = this.generateOutput(results);
157780
+ const fs26 = await import("fs/promises");
157781
+ for (const annotation of output.annotations) {
157782
+ this.writeAnnotation(annotation);
157783
+ }
157784
+ if (output.summary && process.env.GITHUB_STEP_SUMMARY) {
157785
+ await fs26.appendFile(process.env.GITHUB_STEP_SUMMARY, output.summary);
157786
+ }
157787
+ if (process.env.GITHUB_OUTPUT) {
157788
+ const outputLines = Object.entries(output.outputs).map(([key, value]) => `${key}=${value}`).join("\n");
157789
+ await fs26.appendFile(process.env.GITHUB_OUTPUT, outputLines + "\n");
157790
+ }
157791
+ }
157792
+ // --------------------------------------------------------------------------
157793
+ // Annotation Generation
157794
+ // --------------------------------------------------------------------------
157795
+ generateAnnotations(results) {
157796
+ const annotations = [];
157797
+ for (const phase of results) {
157798
+ for (const test of phase.testResults) {
157799
+ if (!test.passed && annotations.length < this.config.maxAnnotations) {
157800
+ annotations.push({
157801
+ file: test.file,
157802
+ line: this.extractLineNumber(test.stack) || 1,
157803
+ level: "error",
157804
+ title: `Test Failed: ${test.name}`,
157805
+ message: test.error || "Test failed without error message"
157806
+ });
157807
+ }
157808
+ }
157809
+ if (this.config.includeFlakyWarnings) {
157810
+ for (const flakyTest of phase.flakyTests) {
157811
+ if (annotations.length < this.config.maxAnnotations) {
157812
+ annotations.push({
157813
+ file: flakyTest,
157814
+ line: 1,
157815
+ level: "warning",
157816
+ title: "Flaky Test Detected",
157817
+ message: `This test is flaky and may cause intermittent failures`
157818
+ });
157819
+ }
157820
+ }
157821
+ }
157822
+ }
157823
+ return annotations;
157824
+ }
157825
+ // --------------------------------------------------------------------------
157826
+ // Summary Generation
157827
+ // --------------------------------------------------------------------------
157828
+ generateSummary(results) {
157829
+ const lines = ["## \u{1F9EA} Test Results\n"];
157830
+ const allPassed = results.every((r54) => r54.success);
157831
+ lines.push(allPassed ? "\u2705 **All phases passed**\n" : "\u274C **Some phases failed**\n");
157832
+ lines.push("| Phase | Status | Pass Rate | Duration | Tests |");
157833
+ lines.push("|-------|--------|-----------|----------|-------|");
157834
+ for (const phase of results) {
157835
+ const status = phase.success ? "\u2705" : "\u274C";
157836
+ const passRate = `${(phase.passRate * 100).toFixed(1)}%`;
157837
+ const duration = this.formatDuration(phase.durationMs);
157838
+ const tests = `${phase.passed}/${phase.totalTests}`;
157839
+ lines.push(`| ${phase.phaseName} | ${status} | ${passRate} | ${duration} | ${tests} |`);
157840
+ }
157841
+ lines.push("");
157842
+ if (this.config.includeCoverage) {
157843
+ lines.push("### \u{1F4CA} Coverage\n");
157844
+ for (const phase of results) {
157845
+ const coverage = `${(phase.coverage * 100).toFixed(1)}%`;
157846
+ const bar = this.generateCoverageBar(phase.coverage);
157847
+ lines.push(`- **${phase.phaseName}**: ${bar} ${coverage}`);
157848
+ }
157849
+ lines.push("");
157850
+ }
157851
+ const failedTests = results.flatMap(
157852
+ (r54) => r54.testResults.filter((t50) => !t50.passed)
157853
+ );
157854
+ if (failedTests.length > 0) {
157855
+ lines.push("### \u274C Failed Tests\n");
157856
+ lines.push("<details>");
157857
+ lines.push("<summary>Click to expand</summary>\n");
157858
+ for (const test of failedTests.slice(0, 20)) {
157859
+ lines.push(`#### ${test.suite} > ${test.name}`);
157860
+ lines.push(`- **File**: \`${test.file}\``);
157861
+ if (test.error) {
157862
+ lines.push("```");
157863
+ lines.push(test.error.slice(0, 500));
157864
+ lines.push("```");
157865
+ }
157866
+ lines.push("");
157867
+ }
157868
+ if (failedTests.length > 20) {
157869
+ lines.push(`_... and ${failedTests.length - 20} more failures_`);
157870
+ }
157871
+ lines.push("</details>\n");
157872
+ }
157873
+ const flakyTests = results.flatMap((r54) => r54.flakyTests);
157874
+ if (flakyTests.length > 0 && this.config.includeFlakyWarnings) {
157875
+ lines.push("### \u26A0\uFE0F Flaky Tests\n");
157876
+ for (const test of flakyTests.slice(0, 10)) {
157877
+ lines.push(`- \`${test}\``);
157878
+ }
157879
+ lines.push("");
157880
+ }
157881
+ return lines.join("\n");
157882
+ }
157883
+ // --------------------------------------------------------------------------
157884
+ // Output Variables
157885
+ // --------------------------------------------------------------------------
157886
+ generateOutputs(results) {
157887
+ const totalTests = results.reduce((sum, r54) => sum + r54.totalTests, 0);
157888
+ const totalPassed = results.reduce((sum, r54) => sum + r54.passed, 0);
157889
+ const totalFailed = results.reduce((sum, r54) => sum + r54.failed, 0);
157890
+ const allPassed = results.every((r54) => r54.success);
157891
+ const avgCoverage = results.length > 0 ? results.reduce((sum, r54) => sum + r54.coverage, 0) / results.length : 0;
157892
+ return {
157893
+ test_result: allPassed ? "success" : "failure",
157894
+ total_tests: String(totalTests),
157895
+ passed_tests: String(totalPassed),
157896
+ failed_tests: String(totalFailed),
157897
+ coverage_percent: String((avgCoverage * 100).toFixed(1)),
157898
+ phases_completed: String(results.length),
157899
+ phases_passed: String(results.filter((r54) => r54.success).length),
157900
+ has_flaky_tests: String(results.some((r54) => r54.flakyTests.length > 0))
157901
+ };
157902
+ }
157903
+ // --------------------------------------------------------------------------
157904
+ // Helpers
157905
+ // --------------------------------------------------------------------------
157906
+ writeAnnotation(annotation) {
157907
+ const params = [
157908
+ `file=${annotation.file}`,
157909
+ `line=${annotation.line}`,
157910
+ `title=${annotation.title}`
157911
+ ].join(",");
157912
+ console.log(`::${annotation.level} ${params}::${annotation.message}`);
157913
+ }
157914
+ extractLineNumber(stack) {
157915
+ if (!stack) return void 0;
157916
+ const match = stack.match(/:(\d+):\d+/);
157917
+ return match ? parseInt(match[1], 10) : void 0;
157918
+ }
157919
+ formatDuration(ms) {
157920
+ if (ms < 1e3) return `${ms}ms`;
157921
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
157922
+ return `${(ms / 6e4).toFixed(1)}m`;
157923
+ }
157924
+ generateCoverageBar(coverage) {
157925
+ const filled = Math.round(coverage * 10);
157926
+ const empty = 10 - filled;
157927
+ return "\u2588".repeat(filled) + "\u2591".repeat(empty);
157928
+ }
157929
+ };
157930
+ }
157931
+ });
157932
+
157933
+ // src/test-scheduling/pipeline.ts
157934
+ async function createTestPipeline(config) {
157935
+ return TestSchedulingPipeline.create(config);
157936
+ }
157937
+ async function runTestPipeline(config) {
157938
+ const pipeline10 = await createTestPipeline(config);
157939
+ return pipeline10.run();
157940
+ }
157941
+ var TestSchedulingPipeline;
157942
+ var init_pipeline = __esm({
157943
+ "src/test-scheduling/pipeline.ts"() {
157944
+ "use strict";
157945
+ init_phase_scheduler();
157946
+ init_vitest_executor();
157947
+ init_test_selector();
157948
+ init_flaky_tracker();
157949
+ init_github_actions();
157950
+ TestSchedulingPipeline = class _TestSchedulingPipeline {
157951
+ constructor(config, selector, executor2, scheduler, flakyTracker, reporter) {
157952
+ this.config = config;
157953
+ this.selector = selector;
157954
+ this.executor = executor2;
157955
+ this.scheduler = scheduler;
157956
+ this.flakyTracker = flakyTracker;
157957
+ this.reporter = reporter;
157958
+ this.ciEnvironment = detectCIEnvironment();
157959
+ }
157960
+ selector;
157961
+ executor;
157962
+ scheduler;
157963
+ flakyTracker;
157964
+ reporter;
157965
+ ciEnvironment;
157966
+ /**
157967
+ * Create a fully integrated test scheduling pipeline
157968
+ *
157969
+ * This factory method:
157970
+ * 1. Creates FlakyTracker (loads history if exists)
157971
+ * 2. Creates VitestExecutor with FlakyTracker integration
157972
+ * 3. Optionally creates ImpactAnalyzerService for import graph analysis
157973
+ * 4. Creates GitAwareTestSelector with ImpactAnalyzer integration
157974
+ * 5. Creates PhaseScheduler with the executor
157975
+ * 6. Creates GitHubActionsReporter
157976
+ */
157977
+ static async create(config) {
157978
+ const flakyTracker = config.flakyHistoryPath ? await loadFlakyTracker(config.flakyHistoryPath, config.flakyTracker) : createFlakyTracker(config.flakyTracker);
157979
+ const executor2 = new VitestPhaseExecutor({
157980
+ ...config.vitest,
157981
+ cwd: config.cwd,
157982
+ flakyTracker
157983
+ // INTEGRATION: Pass tracker to executor
157984
+ });
157985
+ const { ImpactAnalyzerService: ImpactAnalyzerService2 } = await Promise.resolve().then(() => (init_impact_analyzer(), impact_analyzer_exports));
157986
+ const impactAnalyzer = new ImpactAnalyzerService2(config.memory);
157987
+ const selector = createTestSelector({
157988
+ cwd: config.cwd,
157989
+ baseRef: config.baseRef,
157990
+ impactAnalyzer
157991
+ // INTEGRATION: Pass analyzer to selector
157992
+ });
157993
+ const scheduler = createPhaseScheduler(executor2, {
157994
+ ...config.scheduler,
157995
+ phases: config.phases
157996
+ });
157997
+ const reporter = createGitHubActionsReporter(config.reporter);
157998
+ return new _TestSchedulingPipeline(
157999
+ config,
158000
+ selector,
158001
+ executor2,
158002
+ scheduler,
158003
+ flakyTracker,
158004
+ reporter
158005
+ );
158006
+ }
158007
+ // --------------------------------------------------------------------------
158008
+ // Public API
158009
+ // --------------------------------------------------------------------------
158010
+ /**
158011
+ * Run the complete test scheduling pipeline:
158012
+ * 1. Select affected tests (git-aware + import graph)
158013
+ * 2. Execute tests in phases
158014
+ * 3. Track flaky tests
158015
+ * 4. Report to CI/CD
158016
+ */
158017
+ async run() {
158018
+ const startTime = Date.now();
158019
+ let selectedTests = [];
158020
+ let ranAllTests = this.config.runAllTests ?? false;
158021
+ if (!ranAllTests) {
158022
+ const selectionResult = await this.selector.selectAffectedTests();
158023
+ if (selectionResult.runAllTests) {
158024
+ ranAllTests = true;
158025
+ console.log(`[TestSchedulingPipeline] Running all tests: ${selectionResult.runAllReason}`);
158026
+ } else if (selectionResult.selectedTests.length === 0) {
158027
+ console.log("[TestSchedulingPipeline] No affected tests found, running all");
158028
+ ranAllTests = true;
158029
+ } else {
158030
+ selectedTests = selectionResult.selectedTests;
158031
+ console.log(`[TestSchedulingPipeline] Selected ${selectedTests.length} affected tests`);
158032
+ }
158033
+ }
158034
+ let phaseResults;
158035
+ if (ranAllTests) {
158036
+ phaseResults = await this.scheduler.run();
158037
+ } else {
158038
+ phaseResults = await this.runWithSelectedTests(selectedTests);
158039
+ }
158040
+ const flakyAnalysis = this.flakyTracker.analyze();
158041
+ if (this.config.flakyHistoryPath) {
158042
+ await saveFlakyTracker(this.flakyTracker, this.config.flakyHistoryPath);
158043
+ }
158044
+ if (this.ciEnvironment.isCI) {
158045
+ await this.reporter.writeOutput(phaseResults);
158046
+ }
158047
+ const totalDurationMs = Date.now() - startTime;
158048
+ return {
158049
+ phaseResults,
158050
+ selectedTests,
158051
+ ranAllTests,
158052
+ flakyAnalysis,
158053
+ ciEnvironment: this.ciEnvironment,
158054
+ totalDurationMs
158055
+ };
158056
+ }
158057
+ /**
158058
+ * Run only affected tests for a specific phase
158059
+ */
158060
+ async runPhase(phaseId) {
158061
+ return this.scheduler.runPhase(phaseId);
158062
+ }
158063
+ /**
158064
+ * Get the flaky test tracker for direct access
158065
+ */
158066
+ getFlakyTracker() {
158067
+ return this.flakyTracker;
158068
+ }
158069
+ /**
158070
+ * Get the test selector for direct access
158071
+ */
158072
+ getSelector() {
158073
+ return this.selector;
158074
+ }
158075
+ /**
158076
+ * Get scheduler stats
158077
+ */
158078
+ getStats() {
158079
+ return this.scheduler.getStats();
158080
+ }
158081
+ /**
158082
+ * Abort running tests
158083
+ */
158084
+ async abort() {
158085
+ await this.scheduler.abort();
158086
+ }
158087
+ // --------------------------------------------------------------------------
158088
+ // Private Methods
158089
+ // --------------------------------------------------------------------------
158090
+ async runWithSelectedTests(testFiles) {
158091
+ const results = [];
158092
+ const phases = this.config.phases ?? [];
158093
+ for (const phase of phases) {
158094
+ const phaseTests = testFiles.filter(
158095
+ (file) => phase.testPatterns.some((pattern) => {
158096
+ if (pattern.startsWith("!")) return false;
158097
+ const regex = this.patternToRegex(pattern);
158098
+ return regex.test(file);
158099
+ })
158100
+ );
158101
+ if (phaseTests.length > 0) {
158102
+ const result = await this.executor.execute(phase, phaseTests);
158103
+ results.push(result);
158104
+ }
158105
+ }
158106
+ return results;
158107
+ }
158108
+ patternToRegex(pattern) {
158109
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
158110
+ return new RegExp(escaped);
158111
+ }
158112
+ };
158113
+ }
158114
+ });
158115
+
158116
+ // src/test-scheduling/index.ts
158117
+ var test_scheduling_exports = {};
158118
+ __export(test_scheduling_exports, {
158119
+ DEFAULT_TEST_PHASES: () => DEFAULT_TEST_PHASES,
158120
+ FlakyTestTracker: () => FlakyTestTracker,
158121
+ GitAwareTestSelector: () => GitAwareTestSelector,
158122
+ GitHubActionsReporter: () => GitHubActionsReporter,
158123
+ PhaseScheduler: () => PhaseScheduler,
158124
+ TestSchedulingPipeline: () => TestSchedulingPipeline,
158125
+ VitestPhaseExecutor: () => VitestPhaseExecutor,
158126
+ checkQualityThresholds: () => checkQualityThresholds,
158127
+ createFlakyTracker: () => createFlakyTracker,
158128
+ createGitHubActionsReporter: () => createGitHubActionsReporter,
158129
+ createPhaseScheduler: () => createPhaseScheduler,
158130
+ createTestPipeline: () => createTestPipeline,
158131
+ createTestSelector: () => createTestSelector,
158132
+ createVitestExecutor: () => createVitestExecutor,
158133
+ detectCIEnvironment: () => detectCIEnvironment,
158134
+ getAffectedTests: () => getAffectedTests,
158135
+ loadFlakyTracker: () => loadFlakyTracker,
158136
+ reportToGitHubActions: () => reportToGitHubActions,
158137
+ runTestPipeline: () => runTestPipeline,
158138
+ saveFlakyTracker: () => saveFlakyTracker
158139
+ });
158140
+ var init_test_scheduling = __esm({
158141
+ "src/test-scheduling/index.ts"() {
158142
+ "use strict";
158143
+ init_interfaces7();
158144
+ init_phase_scheduler();
158145
+ init_vitest_executor();
158146
+ init_test_selector();
158147
+ init_flaky_tracker();
158148
+ init_github_actions();
158149
+ init_pipeline();
158150
+ }
158151
+ });
158152
+
158153
+ // src/mcp/tools/test-execution/schedule.ts
158154
+ var TestScheduleTool;
158155
+ var init_schedule = __esm({
158156
+ "src/mcp/tools/test-execution/schedule.ts"() {
158157
+ "use strict";
158158
+ init_base();
158159
+ init_error_utils();
158160
+ TestScheduleTool = class extends MCPToolBase {
158161
+ config = {
158162
+ name: "qe/tests/schedule",
158163
+ description: "Schedule and execute tests using phase-based pipeline with git-aware selection and flaky tracking. Runs tests in phases (unit, integration, e2e), selects affected tests from git changes, and tracks flaky tests.",
158164
+ domain: "test-execution",
158165
+ schema: this.buildSchema()
158166
+ };
158167
+ buildSchema() {
158168
+ return {
158169
+ type: "object",
158170
+ properties: {
158171
+ cwd: {
158172
+ type: "string",
158173
+ description: "Working directory for test execution (defaults to project root)"
158174
+ },
158175
+ gitRef: {
158176
+ type: "string",
158177
+ description: 'Git ref to compare for affected test selection (e.g., "main", "HEAD~3")'
158178
+ },
158179
+ useGitAware: {
158180
+ type: "boolean",
158181
+ description: "Enable git-aware test selection to only run affected tests",
158182
+ default: true
158183
+ },
158184
+ trackFlaky: {
158185
+ type: "boolean",
158186
+ description: "Enable flaky test tracking and quarantine",
158187
+ default: true
158188
+ }
158189
+ }
158190
+ };
158191
+ }
158192
+ async execute(params, context) {
158193
+ try {
158194
+ const { runTestPipeline: runTestPipeline2 } = await Promise.resolve().then(() => (init_test_scheduling(), test_scheduling_exports));
158195
+ const memory = await getMemoryBackend(context);
158196
+ const result = await runTestPipeline2({
158197
+ cwd: params.cwd || process.cwd(),
158198
+ memory,
158199
+ baseRef: params.gitRef,
158200
+ flakyHistoryPath: params.trackFlaky !== false ? ".agentic-qe/flaky-history.json" : void 0,
158201
+ runAllTests: params.useGitAware === false
158202
+ });
158203
+ const totalTests = result.phaseResults.reduce((sum, pr3) => sum + pr3.totalTests, 0);
158204
+ const totalPassed = result.phaseResults.reduce((sum, pr3) => sum + pr3.passed, 0);
158205
+ const totalFailed = result.phaseResults.reduce((sum, pr3) => sum + pr3.failed, 0);
158206
+ return {
158207
+ success: true,
158208
+ data: {
158209
+ pipelineId: context.requestId,
158210
+ phases: result.phaseResults.map((pr3) => ({
158211
+ phaseId: pr3.phaseId,
158212
+ phaseName: pr3.phaseName,
158213
+ totalTests: pr3.totalTests,
158214
+ passed: pr3.passed,
158215
+ failed: pr3.failed,
158216
+ passRate: pr3.passRate,
158217
+ durationMs: pr3.durationMs
158218
+ })),
158219
+ gitAware: {
158220
+ enabled: !result.ranAllTests,
158221
+ selectedTests: result.selectedTests.length,
158222
+ gitRef: params.gitRef
158223
+ },
158224
+ flakyTracking: {
158225
+ enabled: params.trackFlaky !== false
158226
+ },
158227
+ totalDuration: result.totalDurationMs,
158228
+ ranAllTests: result.ranAllTests,
158229
+ summary: `Executed ${result.phaseResults.length} phases, ${totalTests} tests (${totalPassed} passed, ${totalFailed} failed) in ${result.totalDurationMs}ms`
158230
+ }
158231
+ };
158232
+ } catch (error) {
158233
+ return {
158234
+ success: false,
158235
+ error: toErrorMessage(error)
158236
+ };
158237
+ }
158238
+ }
158239
+ };
158240
+ }
158241
+ });
158242
+
158243
+ // src/testing/load/metrics-collector.ts
158244
+ function createMetricsCollector(config) {
158245
+ return new MetricsCollector2(config);
158246
+ }
158247
+ var DEFAULT_CONFIG72, MetricsCollector2;
158248
+ var init_metrics_collector2 = __esm({
158249
+ "src/testing/load/metrics-collector.ts"() {
158250
+ "use strict";
158251
+ init_utils();
158252
+ DEFAULT_CONFIG72 = {
158253
+ maxEvents: 1e5,
158254
+ memorySampleInterval: 1e3,
158255
+ enableTimeline: true,
158256
+ timelineSampleInterval: 1e3
158257
+ };
158258
+ MetricsCollector2 = class {
158259
+ config;
158260
+ // Active agent tracking
158261
+ activeAgents = /* @__PURE__ */ new Map();
158262
+ // agentId -> spawnTimestamp
158263
+ peakAgentCount = 0;
158264
+ totalAgentsSpawned = 0;
158265
+ // Task tracking
158266
+ activeTasks = /* @__PURE__ */ new Map();
158267
+ totalTasksStarted = 0;
158268
+ totalTasksCompleted = 0;
158269
+ // Latency buffers (using CircularBuffer for memory efficiency)
158270
+ coordinationLatencies;
158271
+ taskDurations;
158272
+ // Memory tracking
158273
+ memorySnapshots;
158274
+ peakMemoryUsed = 0;
158275
+ memorySum = 0;
158276
+ memorySamples = 0;
158277
+ // Timeline tracking
158278
+ agentTimeline = [];
158279
+ latencyTimeline = [];
158280
+ memoryTimeline = [];
158281
+ // Timing
158282
+ startTime = 0;
158283
+ endTime = 0;
158284
+ running = false;
158285
+ memorySamplerTimer = null;
158286
+ timelineSamplerTimer = null;
158287
+ // Issue tracking
158288
+ issues = [];
158289
+ constructor(config = {}) {
158290
+ this.config = { ...DEFAULT_CONFIG72, ...config };
158291
+ this.coordinationLatencies = new CircularBuffer(this.config.maxEvents);
158292
+ this.taskDurations = new CircularBuffer(this.config.maxEvents);
158293
+ this.memorySnapshots = new CircularBuffer(1e4);
158294
+ }
158295
+ // ============================================================================
158296
+ // Lifecycle
158297
+ // ============================================================================
158298
+ /**
158299
+ * Start collecting metrics
158300
+ */
158301
+ start() {
158302
+ if (this.running) return;
158303
+ this.running = true;
158304
+ this.startTime = Date.now();
158305
+ this.memorySamplerTimer = setInterval(() => {
158306
+ this.sampleMemory();
158307
+ }, this.config.memorySampleInterval);
158308
+ if (this.config.enableTimeline) {
158309
+ this.timelineSamplerTimer = setInterval(() => {
158310
+ this.sampleTimeline();
158311
+ }, this.config.timelineSampleInterval);
158312
+ }
158313
+ }
158314
+ /**
158315
+ * Stop collecting metrics
158316
+ */
158317
+ stop() {
158318
+ if (!this.running) return;
158319
+ this.running = false;
158320
+ this.endTime = Date.now();
158321
+ if (this.memorySamplerTimer) {
158322
+ clearInterval(this.memorySamplerTimer);
158323
+ this.memorySamplerTimer = null;
158324
+ }
158325
+ if (this.timelineSamplerTimer) {
158326
+ clearInterval(this.timelineSamplerTimer);
158327
+ this.timelineSamplerTimer = null;
158328
+ }
158329
+ }
158330
+ /**
158331
+ * Reset all metrics
158332
+ */
158333
+ reset() {
158334
+ this.stop();
158335
+ this.activeAgents.clear();
158336
+ this.peakAgentCount = 0;
158337
+ this.totalAgentsSpawned = 0;
158338
+ this.activeTasks.clear();
158339
+ this.totalTasksStarted = 0;
158340
+ this.totalTasksCompleted = 0;
158341
+ this.coordinationLatencies.clear();
158342
+ this.taskDurations.clear();
158343
+ this.memorySnapshots.clear();
158344
+ this.peakMemoryUsed = 0;
158345
+ this.memorySum = 0;
158346
+ this.memorySamples = 0;
158347
+ this.agentTimeline.length = 0;
158348
+ this.latencyTimeline.length = 0;
158349
+ this.memoryTimeline.length = 0;
158350
+ this.startTime = 0;
158351
+ this.endTime = 0;
158352
+ this.issues.length = 0;
158353
+ }
158354
+ // ============================================================================
158355
+ // Recording Methods
158356
+ // ============================================================================
158357
+ /**
158358
+ * Record agent spawn
158359
+ */
158360
+ recordAgentSpawn(agentId, timestamp = Date.now()) {
158361
+ this.activeAgents.set(agentId, timestamp);
158362
+ this.totalAgentsSpawned++;
158363
+ const currentCount = this.activeAgents.size;
158364
+ if (currentCount > this.peakAgentCount) {
158365
+ this.peakAgentCount = currentCount;
158366
+ }
158367
+ }
158368
+ /**
158369
+ * Record agent termination
158370
+ */
158371
+ recordAgentTerminate(agentId, _timestamp = Date.now()) {
158372
+ this.activeAgents.delete(agentId);
158373
+ }
158374
+ /**
158375
+ * Record task start
158376
+ */
158377
+ recordTaskStart(agentId, taskId, timestamp = Date.now()) {
158378
+ this.activeTasks.set(taskId, { agentId, startTime: timestamp });
158379
+ this.totalTasksStarted++;
158380
+ }
158381
+ /**
158382
+ * Record task completion with duration
158383
+ */
158384
+ recordTaskComplete(agentId, taskId, duration, _timestamp = Date.now()) {
158385
+ const taskInfo = this.activeTasks.get(taskId);
158386
+ if (taskInfo && taskInfo.agentId === agentId) {
158387
+ this.activeTasks.delete(taskId);
158388
+ this.taskDurations.push(duration);
158389
+ this.totalTasksCompleted++;
158390
+ }
158391
+ }
158392
+ /**
158393
+ * Record coordination latency
158394
+ */
158395
+ recordCoordination(agentId, latency, _timestamp = Date.now()) {
158396
+ this.coordinationLatencies.push(latency);
158397
+ if (latency > 100) {
158398
+ this.issues.push(`High coordination latency for agent ${agentId}: ${latency}ms`);
158399
+ }
158400
+ }
158401
+ /**
158402
+ * Record memory usage
158403
+ */
158404
+ recordMemoryUsage(heapUsed, heapTotal) {
158405
+ const snapshot = {
158406
+ timestamp: Date.now(),
158407
+ heapUsed,
158408
+ heapTotal,
158409
+ external: 0,
158410
+ rss: 0
158411
+ };
158412
+ this.memorySnapshots.push(snapshot);
158413
+ this.memorySum += heapUsed;
158414
+ this.memorySamples++;
158415
+ if (heapUsed > this.peakMemoryUsed) {
158416
+ this.peakMemoryUsed = heapUsed;
158417
+ }
158418
+ const MEMORY_LIMIT = 4 * 1024 * 1024 * 1024;
158419
+ if (heapUsed > MEMORY_LIMIT) {
158420
+ this.issues.push(`Memory exceeded 4GB limit: ${(heapUsed / 1024 / 1024 / 1024).toFixed(2)}GB`);
158421
+ }
158422
+ }
158423
+ /**
158424
+ * Record an issue
158425
+ */
158426
+ recordIssue(message) {
158427
+ this.issues.push(message);
158428
+ }
158429
+ // ============================================================================
158430
+ // Query Methods
158431
+ // ============================================================================
158432
+ /**
158433
+ * Get current active agent count
158434
+ */
158435
+ getAgentCount() {
158436
+ return this.activeAgents.size;
158437
+ }
158438
+ /**
158439
+ * Get peak agent count
158440
+ */
158441
+ getPeakAgentCount() {
158442
+ return this.peakAgentCount;
158443
+ }
158444
+ /**
158445
+ * Get total agents spawned
158446
+ */
158447
+ getTotalAgentsSpawned() {
158448
+ return this.totalAgentsSpawned;
158449
+ }
158450
+ /**
158451
+ * Get coordination latency at P95
158452
+ */
158453
+ getP95CoordinationLatency() {
158454
+ return this.calculatePercentile(this.coordinationLatencies.toArray(), 0.95);
158455
+ }
158456
+ /**
158457
+ * Get coordination latency at P99
158458
+ */
158459
+ getP99CoordinationLatency() {
158460
+ return this.calculatePercentile(this.coordinationLatencies.toArray(), 0.99);
158461
+ }
158462
+ /**
158463
+ * Get coordination latency percentiles
158464
+ */
158465
+ getCoordinationLatencyPercentiles() {
158466
+ return this.calculatePercentiles(this.coordinationLatencies.toArray());
158467
+ }
158468
+ /**
158469
+ * Get task latency percentiles
158470
+ */
158471
+ getTaskLatencyPercentiles() {
158472
+ return this.calculatePercentiles(this.taskDurations.toArray());
158473
+ }
158474
+ /**
158475
+ * Get maximum memory usage
158476
+ */
158477
+ getMaxMemoryUsage() {
158478
+ return this.peakMemoryUsed;
158479
+ }
158480
+ /**
158481
+ * Get average memory usage
158482
+ */
158483
+ getAverageMemoryUsage() {
158484
+ return this.memorySamples > 0 ? this.memorySum / this.memorySamples : 0;
158485
+ }
158486
+ /**
158487
+ * Get throughput metrics
158488
+ */
158489
+ getThroughput() {
158490
+ const duration = this.getDuration();
158491
+ const durationSeconds = duration / 1e3;
158492
+ return {
158493
+ tasks: this.totalTasksCompleted,
158494
+ tasksPerSecond: durationSeconds > 0 ? this.totalTasksCompleted / durationSeconds : 0,
158495
+ agents: this.totalAgentsSpawned,
158496
+ agentsPerSecond: durationSeconds > 0 ? this.totalAgentsSpawned / durationSeconds : 0
158497
+ };
158498
+ }
158499
+ /**
158500
+ * Get test duration in milliseconds
158501
+ */
158502
+ getDuration() {
158503
+ if (this.startTime === 0) return 0;
158504
+ const end = this.endTime > 0 ? this.endTime : Date.now();
158505
+ return end - this.startTime;
158506
+ }
158507
+ /**
158508
+ * Check if any agents are starving (no tasks for extended period)
158509
+ */
158510
+ hasAgentStarvation() {
158511
+ const activeAgentCount = this.activeAgents.size;
158512
+ const activeTaskCount = this.activeTasks.size;
158513
+ return activeAgentCount > 0 && activeTaskCount === 0 && this.totalTasksCompleted > 0;
158514
+ }
158515
+ /**
158516
+ * Check for potential deadlocks (tasks started but not completing)
158517
+ */
158518
+ hasDeadlocks() {
158519
+ const now = Date.now();
158520
+ const DEADLOCK_THRESHOLD = 6e4;
158521
+ const tasks = Array.from(this.activeTasks.values());
158522
+ for (const taskInfo of tasks) {
158523
+ if (now - taskInfo.startTime > DEADLOCK_THRESHOLD) {
158524
+ return true;
158525
+ }
158526
+ }
158527
+ return false;
158528
+ }
158529
+ // ============================================================================
158530
+ // Report Generation
158531
+ // ============================================================================
158532
+ /**
158533
+ * Export complete load test report
158534
+ */
158535
+ exportReport() {
158536
+ const duration = this.getDuration();
158537
+ const coordinationLatency = this.getCoordinationLatencyPercentiles();
158538
+ const taskLatency = this.getTaskLatencyPercentiles();
158539
+ const throughput = this.getThroughput();
158540
+ const AGENT_TARGET = 100;
158541
+ const MEMORY_LIMIT = 4 * 1024 * 1024 * 1024;
158542
+ const LATENCY_TARGET = 100;
158543
+ const successCriteria = {
158544
+ agentCount: this.peakAgentCount >= AGENT_TARGET,
158545
+ memoryLimit: this.peakMemoryUsed < MEMORY_LIMIT,
158546
+ coordinationLatency: coordinationLatency.p95 <= LATENCY_TARGET,
158547
+ noDeadlocks: !this.hasDeadlocks(),
158548
+ noStarvation: !this.hasAgentStarvation()
158549
+ };
158550
+ const allCriteriaMet = Object.values(successCriteria).every(Boolean);
158551
+ const recommendations = this.generateRecommendations(
158552
+ coordinationLatency,
158553
+ this.peakMemoryUsed,
158554
+ throughput
158555
+ );
158556
+ return {
158557
+ summary: {
158558
+ totalAgents: this.totalAgentsSpawned,
158559
+ peakAgents: this.peakAgentCount,
158560
+ totalTasks: this.totalTasksCompleted,
158561
+ duration,
158562
+ success: allCriteriaMet,
158563
+ successCriteria
158564
+ },
158565
+ performance: {
158566
+ coordinationLatency,
158567
+ taskLatency,
158568
+ throughput
158569
+ },
158570
+ resources: {
158571
+ memoryPeak: this.peakMemoryUsed,
158572
+ memoryAverage: this.getAverageMemoryUsage(),
158573
+ cpuPeak: 0,
158574
+ // Not tracked yet
158575
+ cpuAverage: 0
158576
+ },
158577
+ timeline: {
158578
+ agentCounts: [...this.agentTimeline],
158579
+ latencies: [...this.latencyTimeline],
158580
+ memoryUsage: [...this.memoryTimeline]
158581
+ },
158582
+ issues: [...this.issues],
158583
+ recommendations
158584
+ };
158585
+ }
158586
+ // ============================================================================
158587
+ // Private Methods
158588
+ // ============================================================================
158589
+ sampleMemory() {
158590
+ const memUsage = process.memoryUsage();
158591
+ this.recordMemoryUsage(memUsage.heapUsed, memUsage.heapTotal);
158592
+ }
158593
+ sampleTimeline() {
158594
+ const now = Date.now();
158595
+ this.agentTimeline.push({
158596
+ timestamp: now,
158597
+ count: this.activeAgents.size
158598
+ });
158599
+ const latencies = this.coordinationLatencies.toArray();
158600
+ if (latencies.length > 0) {
158601
+ this.latencyTimeline.push({
158602
+ timestamp: now,
158603
+ p95: this.calculatePercentile(latencies, 0.95)
158604
+ });
158605
+ }
158606
+ const memUsage = process.memoryUsage();
158607
+ this.memoryTimeline.push({
158608
+ timestamp: now,
158609
+ heapUsed: memUsage.heapUsed
158610
+ });
158611
+ const MAX_TIMELINE_POINTS = 1e3;
158612
+ if (this.agentTimeline.length > MAX_TIMELINE_POINTS) {
158613
+ this.agentTimeline.shift();
158614
+ }
158615
+ if (this.latencyTimeline.length > MAX_TIMELINE_POINTS) {
158616
+ this.latencyTimeline.shift();
158617
+ }
158618
+ if (this.memoryTimeline.length > MAX_TIMELINE_POINTS) {
158619
+ this.memoryTimeline.shift();
158620
+ }
158621
+ }
158622
+ calculatePercentile(values, percentile) {
158623
+ if (values.length === 0) return 0;
158624
+ const sorted = [...values].sort((a37, b68) => a37 - b68);
158625
+ const index = Math.ceil(sorted.length * percentile) - 1;
158626
+ return sorted[Math.max(0, index)];
158627
+ }
158628
+ calculatePercentiles(values) {
158629
+ if (values.length === 0) {
158630
+ return { p50: 0, p95: 0, p99: 0, max: 0, min: 0, avg: 0, count: 0 };
158631
+ }
158632
+ const sorted = [...values].sort((a37, b68) => a37 - b68);
158633
+ const sum = sorted.reduce((a37, b68) => a37 + b68, 0);
158634
+ return {
158635
+ p50: this.calculatePercentile(sorted, 0.5),
158636
+ p95: this.calculatePercentile(sorted, 0.95),
158637
+ p99: this.calculatePercentile(sorted, 0.99),
158638
+ max: sorted[sorted.length - 1],
158639
+ min: sorted[0],
158640
+ avg: sum / sorted.length,
158641
+ count: sorted.length
158642
+ };
158643
+ }
158644
+ generateRecommendations(latency, memoryPeak, throughput) {
158645
+ const recommendations = [];
158646
+ if (latency.p95 > 100) {
158647
+ recommendations.push(
158648
+ `P95 coordination latency (${latency.p95.toFixed(1)}ms) exceeds 100ms target. Consider optimizing gossip protocol or reducing agent count.`
158649
+ );
158650
+ }
158651
+ if (latency.p99 > latency.p95 * 2) {
158652
+ recommendations.push(
158653
+ "High P99/P95 ratio indicates latency outliers. Investigate specific agents or network conditions."
158654
+ );
158655
+ }
158656
+ const memoryGB = memoryPeak / 1024 / 1024 / 1024;
158657
+ if (memoryGB > 3) {
158658
+ recommendations.push(
158659
+ `Memory usage (${memoryGB.toFixed(2)}GB) approaching 4GB limit. Consider implementing agent pooling or reducing per-agent memory.`
158660
+ );
158661
+ }
158662
+ if (throughput.tasksPerSecond < 10) {
158663
+ recommendations.push(
158664
+ `Task throughput (${throughput.tasksPerSecond.toFixed(1)}/s) is low. Consider parallelizing task execution or reducing task complexity.`
158665
+ );
158666
+ }
158667
+ if (this.issues.length > 10) {
158668
+ recommendations.push(
158669
+ `${this.issues.length} issues recorded. Review issue log for patterns and prioritize fixes.`
158670
+ );
158671
+ }
158672
+ return recommendations;
158673
+ }
158674
+ };
158675
+ }
158676
+ });
158677
+
158678
+ // src/testing/load/bottleneck-analyzer.ts
158679
+ function createBottleneckAnalyzer(config) {
158680
+ return new BottleneckAnalyzer(config);
158681
+ }
158682
+ function createBottleneckAnalyzerWithThresholds(thresholds) {
158683
+ return new BottleneckAnalyzer({
158684
+ thresholds: { ...DEFAULT_THRESHOLDS2, ...thresholds }
158685
+ });
158686
+ }
158687
+ var DEFAULT_THRESHOLDS2, DEFAULT_CONFIG73, BottleneckAnalyzer;
158688
+ var init_bottleneck_analyzer = __esm({
158689
+ "src/testing/load/bottleneck-analyzer.ts"() {
158690
+ "use strict";
158691
+ DEFAULT_THRESHOLDS2 = {
158692
+ // Memory (Issue #177: <4GB)
158693
+ memoryWarning: 3 * 1024 * 1024 * 1024,
158694
+ // 3GB
158695
+ memoryCritical: 4 * 1024 * 1024 * 1024,
158696
+ // 4GB
158697
+ // Coordination latency (Issue #177: <100ms p95)
158698
+ latencyP95Warning: 75,
158699
+ latencyP95Critical: 100,
158700
+ latencyP99Warning: 150,
158701
+ latencyP99Critical: 200,
158702
+ // Agent health
158703
+ agentStarvationTime: 3e4,
158704
+ // 30 seconds
158705
+ deadlockTimeout: 6e4,
158706
+ // 60 seconds
158707
+ // Throughput
158708
+ minTasksPerSecond: 5,
158709
+ minAgentUtilization: 0.5,
158710
+ // Gossip protocol
158711
+ gossipConvergenceTime: 5e3,
158712
+ gossipMaxPartitions: 0
158713
+ };
158714
+ DEFAULT_CONFIG73 = {
158715
+ thresholds: DEFAULT_THRESHOLDS2,
158716
+ enableDetailedAnalysis: true
158717
+ };
158718
+ BottleneckAnalyzer = class {
158719
+ config;
158720
+ constructor(config = {}) {
158721
+ this.config = {
158722
+ ...DEFAULT_CONFIG73,
158723
+ ...config,
158724
+ thresholds: {
158725
+ ...DEFAULT_THRESHOLDS2,
158726
+ ...config.thresholds
158727
+ }
158728
+ };
158729
+ }
158730
+ // ============================================================================
158731
+ // Main Analysis Methods
158732
+ // ============================================================================
158733
+ /**
158734
+ * Perform complete bottleneck analysis on collected metrics
158735
+ */
158736
+ analyze(metrics) {
158737
+ const bottlenecks = [];
158738
+ bottlenecks.push(this.checkMemoryPressure(metrics));
158739
+ bottlenecks.push(this.checkCoordinationLatencyP95(metrics));
158740
+ bottlenecks.push(this.checkCoordinationLatencyP99(metrics));
158741
+ bottlenecks.push(this.checkAgentStarvation(metrics));
158742
+ bottlenecks.push(this.checkDeadlocks(metrics));
158743
+ bottlenecks.push(this.checkThroughput(metrics));
158744
+ const detected = bottlenecks.filter((b68) => b68.detected);
158745
+ const summary = {
158746
+ totalChecks: bottlenecks.length,
158747
+ detected: detected.length,
158748
+ critical: detected.filter((b68) => b68.severity === "critical").length,
158749
+ high: detected.filter((b68) => b68.severity === "high").length,
158750
+ medium: detected.filter((b68) => b68.severity === "medium").length,
158751
+ low: detected.filter((b68) => b68.severity === "low").length
158752
+ };
158753
+ let overallSeverity = "low";
158754
+ if (summary.critical > 0) {
158755
+ overallSeverity = "critical";
158756
+ } else if (summary.high > 0) {
158757
+ overallSeverity = "high";
158758
+ } else if (summary.medium > 0) {
158759
+ overallSeverity = "medium";
158760
+ }
158761
+ const recommendations = this.generatePrioritizedRecommendations(detected);
158762
+ return {
158763
+ overallSeverity,
158764
+ hasCritical: summary.critical > 0,
158765
+ bottlenecks,
158766
+ summary,
158767
+ recommendations,
158768
+ timestamp: /* @__PURE__ */ new Date()
158769
+ };
158770
+ }
158771
+ /**
158772
+ * Analyze from a load test report
158773
+ */
158774
+ analyzeReport(report) {
158775
+ const bottlenecks = [];
158776
+ bottlenecks.push(this.checkMemoryFromReport(report));
158777
+ bottlenecks.push(this.checkLatencyP95FromReport(report));
158778
+ bottlenecks.push(this.checkLatencyP99FromReport(report));
158779
+ bottlenecks.push(this.checkThroughputFromReport(report));
158780
+ bottlenecks.push(this.checkSuccessCriteria(report));
158781
+ const detected = bottlenecks.filter((b68) => b68.detected);
158782
+ const summary = {
158783
+ totalChecks: bottlenecks.length,
158784
+ detected: detected.length,
158785
+ critical: detected.filter((b68) => b68.severity === "critical").length,
158786
+ high: detected.filter((b68) => b68.severity === "high").length,
158787
+ medium: detected.filter((b68) => b68.severity === "medium").length,
158788
+ low: detected.filter((b68) => b68.severity === "low").length
158789
+ };
158790
+ let overallSeverity = "low";
158791
+ if (summary.critical > 0) {
158792
+ overallSeverity = "critical";
158793
+ } else if (summary.high > 0) {
158794
+ overallSeverity = "high";
158795
+ } else if (summary.medium > 0) {
158796
+ overallSeverity = "medium";
158797
+ }
158798
+ const recommendations = this.generatePrioritizedRecommendations(detected);
158799
+ return {
158800
+ overallSeverity,
158801
+ hasCritical: summary.critical > 0,
158802
+ bottlenecks,
158803
+ summary,
158804
+ recommendations,
158805
+ timestamp: /* @__PURE__ */ new Date()
158806
+ };
158807
+ }
158808
+ // ============================================================================
158809
+ // Individual Check Methods
158810
+ // ============================================================================
158811
+ /**
158812
+ * Check for memory pressure
158813
+ */
158814
+ checkMemoryPressure(metrics) {
158815
+ const actual = metrics?.getMaxMemoryUsage() ?? process.memoryUsage().heapUsed;
158816
+ const { memoryWarning, memoryCritical } = this.config.thresholds;
158817
+ const detected = actual >= memoryWarning;
158818
+ let severity = "low";
158819
+ let recommendation = "Memory usage is within acceptable limits.";
158820
+ if (actual >= memoryCritical) {
158821
+ severity = "critical";
158822
+ recommendation = "Memory usage exceeds 4GB limit. Implement agent pooling, reduce per-agent state, or decrease concurrent agent count.";
158823
+ } else if (actual >= memoryWarning) {
158824
+ severity = "high";
158825
+ recommendation = "Memory usage approaching critical threshold. Consider optimizing agent memory footprint or implementing memory pressure relief mechanisms.";
158826
+ }
158827
+ return {
158828
+ detected,
158829
+ severity,
158830
+ metric: "memory_pressure",
158831
+ threshold: memoryCritical,
158832
+ actual,
158833
+ recommendation,
158834
+ context: {
158835
+ usedGB: actual / 1024 / 1024 / 1024,
158836
+ warningThresholdGB: memoryWarning / 1024 / 1024 / 1024,
158837
+ criticalThresholdGB: memoryCritical / 1024 / 1024 / 1024
158838
+ }
158839
+ };
158840
+ }
158841
+ /**
158842
+ * Check coordination latency P95
158843
+ */
158844
+ checkCoordinationLatency() {
158845
+ return this.checkCoordinationLatencyP95();
158846
+ }
158847
+ checkCoordinationLatencyP95(metrics) {
158848
+ const actual = metrics?.getP95CoordinationLatency() ?? 0;
158849
+ const { latencyP95Warning, latencyP95Critical } = this.config.thresholds;
158850
+ const detected = actual >= latencyP95Warning;
158851
+ let severity = "low";
158852
+ let recommendation = "P95 coordination latency is within acceptable limits.";
158853
+ if (actual >= latencyP95Critical) {
158854
+ severity = "critical";
158855
+ recommendation = "P95 coordination latency exceeds 100ms target. Optimize gossip protocol, reduce message size, or implement batching.";
158856
+ } else if (actual >= latencyP95Warning) {
158857
+ severity = "medium";
158858
+ recommendation = "P95 coordination latency approaching target. Monitor closely and consider proactive optimization.";
158859
+ }
158860
+ return {
158861
+ detected,
158862
+ severity,
158863
+ metric: "coordination_latency_p95",
158864
+ threshold: latencyP95Critical,
158865
+ actual,
158866
+ recommendation
158867
+ };
158868
+ }
158869
+ checkCoordinationLatencyP99(metrics) {
158870
+ const actual = metrics?.getP99CoordinationLatency() ?? 0;
158871
+ const { latencyP99Warning, latencyP99Critical } = this.config.thresholds;
158872
+ const detected = actual >= latencyP99Warning;
158873
+ let severity = "low";
158874
+ let recommendation = "P99 coordination latency is within acceptable limits.";
158875
+ if (actual >= latencyP99Critical) {
158876
+ severity = "high";
158877
+ recommendation = "P99 coordination latency indicates outliers. Investigate specific agents or network conditions causing delays.";
158878
+ } else if (actual >= latencyP99Warning) {
158879
+ severity = "medium";
158880
+ recommendation = "P99 coordination latency elevated. Some agents may be experiencing delays.";
158881
+ }
158882
+ return {
158883
+ detected,
158884
+ severity,
158885
+ metric: "coordination_latency_p99",
158886
+ threshold: latencyP99Critical,
158887
+ actual,
158888
+ recommendation
158889
+ };
158890
+ }
158891
+ /**
158892
+ * Check for agent starvation
158893
+ */
158894
+ checkAgentStarvation(metrics) {
158895
+ const hasStarvation = metrics?.hasAgentStarvation() ?? false;
158896
+ return {
158897
+ detected: hasStarvation,
158898
+ severity: hasStarvation ? "high" : "low",
158899
+ metric: "agent_starvation",
158900
+ threshold: this.config.thresholds.agentStarvationTime,
158901
+ actual: hasStarvation ? 1 : 0,
158902
+ recommendation: hasStarvation ? "Agent starvation detected. Agents are idle without tasks. Review task distribution algorithm and work stealing configuration." : "No agent starvation detected."
158903
+ };
158904
+ }
158905
+ /**
158906
+ * Check for deadlocks
158907
+ */
158908
+ checkDeadlocks(metrics) {
158909
+ const hasDeadlocks = metrics?.hasDeadlocks() ?? false;
158910
+ return {
158911
+ detected: hasDeadlocks,
158912
+ severity: hasDeadlocks ? "critical" : "low",
158913
+ metric: "deadlock_detection",
158914
+ threshold: this.config.thresholds.deadlockTimeout,
158915
+ actual: hasDeadlocks ? 1 : 0,
158916
+ recommendation: hasDeadlocks ? "Potential deadlock detected. Tasks running for extended period. Review lock ordering and add timeout mechanisms." : "No deadlocks detected."
158917
+ };
158918
+ }
158919
+ /**
158920
+ * Check gossip protocol stability
158921
+ */
158922
+ checkGossipStability() {
158923
+ return {
158924
+ detected: false,
158925
+ severity: "low",
158926
+ metric: "gossip_stability",
158927
+ threshold: this.config.thresholds.gossipMaxPartitions,
158928
+ actual: 0,
158929
+ recommendation: "Gossip protocol stability check requires integration with gossip metrics."
158930
+ };
158931
+ }
158932
+ /**
158933
+ * Check throughput
158934
+ */
158935
+ checkThroughput(metrics) {
158936
+ const throughput = metrics?.getThroughput();
158937
+ const actual = throughput?.tasksPerSecond ?? 0;
158938
+ const threshold = this.config.thresholds.minTasksPerSecond;
158939
+ const detected = actual < threshold && actual > 0;
158940
+ return {
158941
+ detected,
158942
+ severity: detected ? "medium" : "low",
158943
+ metric: "throughput",
158944
+ threshold,
158945
+ actual,
158946
+ recommendation: detected ? `Task throughput (${actual.toFixed(1)}/s) below minimum (${threshold}/s). Consider parallelizing task execution or optimizing task handlers.` : "Task throughput is acceptable."
158947
+ };
158948
+ }
158949
+ // ============================================================================
158950
+ // Report-based Check Methods
158951
+ // ============================================================================
158952
+ checkMemoryFromReport(report) {
158953
+ const actual = report.resources.memoryPeak;
158954
+ const { memoryCritical } = this.config.thresholds;
158955
+ return {
158956
+ detected: actual >= memoryCritical,
158957
+ severity: actual >= memoryCritical ? "critical" : "low",
158958
+ metric: "memory_pressure",
158959
+ threshold: memoryCritical,
158960
+ actual,
158961
+ recommendation: actual >= memoryCritical ? "Memory exceeded 4GB limit during test." : "Memory usage within limits."
158962
+ };
158963
+ }
158964
+ checkLatencyP95FromReport(report) {
158965
+ const actual = report.performance.coordinationLatency.p95;
158966
+ const { latencyP95Critical } = this.config.thresholds;
158967
+ return {
158968
+ detected: actual >= latencyP95Critical,
158969
+ severity: actual >= latencyP95Critical ? "critical" : "low",
158970
+ metric: "coordination_latency_p95",
158971
+ threshold: latencyP95Critical,
158972
+ actual,
158973
+ recommendation: actual >= latencyP95Critical ? "P95 coordination latency exceeded 100ms target." : "P95 latency within target."
158974
+ };
158975
+ }
158976
+ checkLatencyP99FromReport(report) {
158977
+ const actual = report.performance.coordinationLatency.p99;
158978
+ const { latencyP99Critical } = this.config.thresholds;
158979
+ return {
158980
+ detected: actual >= latencyP99Critical,
158981
+ severity: actual >= latencyP99Critical ? "high" : "low",
158982
+ metric: "coordination_latency_p99",
158983
+ threshold: latencyP99Critical,
158984
+ actual,
158985
+ recommendation: actual >= latencyP99Critical ? "P99 coordination latency indicates significant outliers." : "P99 latency acceptable."
158986
+ };
158987
+ }
158988
+ checkThroughputFromReport(report) {
158989
+ const actual = report.performance.throughput.tasksPerSecond;
158990
+ const threshold = this.config.thresholds.minTasksPerSecond;
158991
+ return {
158992
+ detected: actual < threshold && actual > 0,
158993
+ severity: actual < threshold ? "medium" : "low",
158994
+ metric: "throughput",
158995
+ threshold,
158996
+ actual,
158997
+ recommendation: actual < threshold ? "Throughput below minimum target." : "Throughput acceptable."
158998
+ };
158999
+ }
159000
+ checkSuccessCriteria(report) {
159001
+ const criteria = report.summary.successCriteria;
159002
+ const failedCriteria = Object.entries(criteria).filter(([_56, passed]) => !passed).map(([name]) => name);
159003
+ return {
159004
+ detected: failedCriteria.length > 0,
159005
+ severity: failedCriteria.length > 0 ? "high" : "low",
159006
+ metric: "success_criteria",
159007
+ threshold: 0,
159008
+ actual: failedCriteria.length,
159009
+ recommendation: failedCriteria.length > 0 ? `Failed criteria: ${failedCriteria.join(", ")}` : "All success criteria met.",
159010
+ context: { failedCriteria }
159011
+ };
159012
+ }
159013
+ // ============================================================================
159014
+ // Private Methods
159015
+ // ============================================================================
159016
+ generatePrioritizedRecommendations(detectedBottlenecks) {
159017
+ const priorityMap = {
159018
+ critical: 0,
159019
+ high: 1,
159020
+ medium: 2,
159021
+ low: 3
159022
+ };
159023
+ const sorted = [...detectedBottlenecks].sort(
159024
+ (a37, b68) => priorityMap[a37.severity] - priorityMap[b68.severity]
159025
+ );
159026
+ const seen = /* @__PURE__ */ new Set();
159027
+ const recommendations = [];
159028
+ for (const bottleneck of sorted) {
159029
+ if (!seen.has(bottleneck.recommendation)) {
159030
+ seen.add(bottleneck.recommendation);
159031
+ recommendations.push(
159032
+ `[${bottleneck.severity.toUpperCase()}] ${bottleneck.metric}: ${bottleneck.recommendation}`
159033
+ );
159034
+ }
159035
+ }
159036
+ return recommendations;
159037
+ }
159038
+ };
159039
+ }
159040
+ });
159041
+
159042
+ // src/testing/load/agent-load-tester.ts
159043
+ function createAgentLoadTester(config, metricsConfig, thresholds) {
159044
+ return new AgentLoadTester(config, metricsConfig, thresholds);
159045
+ }
159046
+ function createLoadTesterForTarget(targetAgents, workloadProfile = "medium") {
159047
+ return new AgentLoadTester({
159048
+ maxAgents: targetAgents,
159049
+ workloadProfile,
159050
+ mockMode: true
159051
+ });
159052
+ }
159053
+ var DEFAULT_CONFIG74, DEFAULT_SUCCESS_CRITERIA, WORKLOAD_PROFILES, SCENARIO_RAMP_UP_100, SCENARIO_BURST_100, SCENARIO_CHURN_100, SCENARIO_STRESS_150, AgentLoadTester;
159054
+ var init_agent_load_tester = __esm({
159055
+ "src/testing/load/agent-load-tester.ts"() {
159056
+ "use strict";
159057
+ init_esm_node();
159058
+ init_metrics_collector2();
159059
+ init_error_utils();
159060
+ init_bottleneck_analyzer();
159061
+ DEFAULT_CONFIG74 = {
159062
+ maxAgents: 100,
159063
+ memoryLimit: 4 * 1024 * 1024 * 1024,
159064
+ // 4GB
159065
+ coordinationTimeout: 100,
159066
+ workloadProfile: "medium",
159067
+ mockMode: true
159068
+ };
159069
+ DEFAULT_SUCCESS_CRITERIA = {
159070
+ agentCount: 100,
159071
+ memoryLimit: 4 * 1024 * 1024 * 1024,
159072
+ coordinationLatency: 100,
159073
+ noAgentStarvation: true,
159074
+ noDeadlocks: true,
159075
+ gossipStable: true
159076
+ };
159077
+ WORKLOAD_PROFILES = {
159078
+ light: {
159079
+ taskCount: 5,
159080
+ taskDuration: 50,
159081
+ memoryUsage: 5 * 1024 * 1024,
159082
+ // 5MB
159083
+ coordinationFrequency: 2,
159084
+ durationVariance: 0.1
159085
+ },
159086
+ medium: {
159087
+ taskCount: 10,
159088
+ taskDuration: 100,
159089
+ memoryUsage: 10 * 1024 * 1024,
159090
+ // 10MB
159091
+ coordinationFrequency: 5,
159092
+ durationVariance: 0.2
159093
+ },
159094
+ heavy: {
159095
+ taskCount: 20,
159096
+ taskDuration: 200,
159097
+ memoryUsage: 20 * 1024 * 1024,
159098
+ // 20MB
159099
+ coordinationFrequency: 10,
159100
+ durationVariance: 0.3
159101
+ }
159102
+ };
159103
+ SCENARIO_RAMP_UP_100 = {
159104
+ name: "ramp-up-100",
159105
+ description: "Gradually add agents until reaching 100",
159106
+ steps: [
159107
+ { agents: 25, holdTime: 3e4 },
159108
+ { agents: 50, holdTime: 3e4 },
159109
+ { agents: 75, holdTime: 3e4 },
159110
+ { agents: 100, holdTime: 6e4 }
159111
+ ],
159112
+ workload: WORKLOAD_PROFILES.medium
159113
+ };
159114
+ SCENARIO_BURST_100 = {
159115
+ name: "burst-100",
159116
+ description: "Instantly spawn 100 agents",
159117
+ steps: [{ agents: 100, holdTime: 12e4 }],
159118
+ workload: {
159119
+ taskCount: 20,
159120
+ taskDuration: 50,
159121
+ memoryUsage: 10 * 1024 * 1024,
159122
+ coordinationFrequency: 5
159123
+ }
159124
+ };
159125
+ SCENARIO_CHURN_100 = {
159126
+ name: "churn-100",
159127
+ description: "Maintain 100 agents with continuous spawn/terminate",
159128
+ steps: [{ agents: 100, holdTime: 18e4, churnRate: 0.1 }],
159129
+ workload: {
159130
+ taskCount: 15,
159131
+ taskDuration: 75,
159132
+ memoryUsage: 10 * 1024 * 1024,
159133
+ coordinationFrequency: 5
159134
+ }
159135
+ };
159136
+ SCENARIO_STRESS_150 = {
159137
+ name: "stress-150",
159138
+ description: "Push beyond 100 agents to find limits",
159139
+ steps: [
159140
+ { agents: 100, holdTime: 3e4 },
159141
+ { agents: 125, holdTime: 3e4 },
159142
+ { agents: 150, holdTime: 6e4 }
159143
+ ],
159144
+ workload: WORKLOAD_PROFILES.heavy,
159145
+ criteria: {
159146
+ agentCount: 150
159147
+ }
159148
+ };
159149
+ AgentLoadTester = class {
159150
+ config;
159151
+ metrics;
159152
+ analyzer;
159153
+ running = false;
159154
+ stopRequested = false;
159155
+ // Mock agents for mock mode
159156
+ mockAgents = /* @__PURE__ */ new Map();
159157
+ mockTaskTimers = /* @__PURE__ */ new Map();
159158
+ mockCoordinationTimers = /* @__PURE__ */ new Map();
159159
+ churnTimer = null;
159160
+ // Random number generator (seeded for reproducibility)
159161
+ random;
159162
+ constructor(config = {}, metricsConfig, thresholds) {
159163
+ this.config = { ...DEFAULT_CONFIG74, ...config };
159164
+ this.metrics = createMetricsCollector(metricsConfig);
159165
+ this.analyzer = thresholds ? createBottleneckAnalyzerWithThresholds(thresholds) : createBottleneckAnalyzer();
159166
+ this.random = this.config.seed !== void 0 ? this.seededRandom(this.config.seed) : Math.random.bind(Math);
159167
+ }
159168
+ // ============================================================================
159169
+ // Public API
159170
+ // ============================================================================
159171
+ /**
159172
+ * Run a load test with specified agent count and duration
159173
+ */
159174
+ async runTest(agentCount, duration) {
159175
+ const scenario = {
159176
+ name: "custom",
159177
+ description: `Custom test with ${agentCount} agents for ${duration}ms`,
159178
+ steps: [{ agents: agentCount, holdTime: duration }],
159179
+ workload: this.getWorkload()
159180
+ };
159181
+ return this.runScenario(scenario);
159182
+ }
159183
+ /**
159184
+ * Run a predefined load test scenario
159185
+ */
159186
+ async runScenario(scenario) {
159187
+ if (this.running) {
159188
+ throw new Error("Load test already running");
159189
+ }
159190
+ this.running = true;
159191
+ this.stopRequested = false;
159192
+ const startTime = Date.now();
159193
+ try {
159194
+ this.metrics.reset();
159195
+ this.metrics.start();
159196
+ for (const step of scenario.steps) {
159197
+ if (this.stopRequested) break;
159198
+ await this.executeStep(step, scenario.workload);
159199
+ }
159200
+ this.metrics.stop();
159201
+ const report = this.metrics.exportReport();
159202
+ const bottlenecks = this.analyzer.analyzeReport(report);
159203
+ const criteria = { ...DEFAULT_SUCCESS_CRITERIA, ...scenario.criteria };
159204
+ const success = this.evaluateSuccess(report, criteria);
159205
+ return {
159206
+ success,
159207
+ report,
159208
+ bottlenecks,
159209
+ config: this.config,
159210
+ duration: Date.now() - startTime
159211
+ };
159212
+ } catch (error) {
159213
+ this.metrics.stop();
159214
+ return {
159215
+ success: false,
159216
+ report: this.metrics.exportReport(),
159217
+ bottlenecks: this.analyzer.analyze(this.metrics),
159218
+ config: this.config,
159219
+ duration: Date.now() - startTime,
159220
+ error: toErrorMessage(error)
159221
+ };
159222
+ } finally {
159223
+ await this.cleanup();
159224
+ this.running = false;
159225
+ }
159226
+ }
159227
+ /**
159228
+ * Gradually ramp up to target agent count
159229
+ */
159230
+ async rampUp(targetCount, rampDuration) {
159231
+ const currentCount = this.mockAgents.size;
159232
+ const agentsToSpawn = targetCount - currentCount;
159233
+ if (agentsToSpawn <= 0) return;
159234
+ const spawnInterval = rampDuration / agentsToSpawn;
159235
+ const workload = this.getWorkload();
159236
+ for (let i58 = 0; i58 < agentsToSpawn && !this.stopRequested; i58++) {
159237
+ await this.spawnMockAgent(workload);
159238
+ await this.delay(spawnInterval);
159239
+ }
159240
+ }
159241
+ /**
159242
+ * Simulate a single agent's lifecycle
159243
+ */
159244
+ async simulateAgent(agentId, workload) {
159245
+ const startTime = Date.now();
159246
+ let tasksCompleted = 0;
159247
+ let coordinationEvents = 0;
159248
+ for (let i58 = 0; i58 < workload.taskCount && !this.stopRequested; i58++) {
159249
+ const taskId = `${agentId}_task_${i58}`;
159250
+ const taskStart = Date.now();
159251
+ this.metrics.recordTaskStart(agentId, taskId, taskStart);
159252
+ const variance = workload.durationVariance ?? 0.2;
159253
+ const actualDuration = workload.taskDuration * (1 + (this.random() - 0.5) * 2 * variance);
159254
+ await this.delay(actualDuration);
159255
+ this.metrics.recordTaskComplete(agentId, taskId, Date.now() - taskStart);
159256
+ tasksCompleted++;
159257
+ const coordLatency = this.simulateCoordinationLatency();
159258
+ this.metrics.recordCoordination(agentId, coordLatency);
159259
+ coordinationEvents++;
159260
+ }
159261
+ return {
159262
+ agentId,
159263
+ tasksCompleted,
159264
+ totalDuration: Date.now() - startTime,
159265
+ coordinationEvents
159266
+ };
159267
+ }
159268
+ /**
159269
+ * Stop the running test
159270
+ */
159271
+ async stop() {
159272
+ this.stopRequested = true;
159273
+ await this.delay(100);
159274
+ await this.cleanup();
159275
+ }
159276
+ /**
159277
+ * Get current metrics collector
159278
+ */
159279
+ getMetrics() {
159280
+ return this.metrics;
159281
+ }
159282
+ /**
159283
+ * Get current agent count
159284
+ */
159285
+ getAgentCount() {
159286
+ return this.mockAgents.size;
159287
+ }
159288
+ /**
159289
+ * Check if test is running
159290
+ */
159291
+ isRunning() {
159292
+ return this.running;
159293
+ }
159294
+ // ============================================================================
159295
+ // Private Methods - Scenario Execution
159296
+ // ============================================================================
159297
+ async executeStep(step, workload) {
159298
+ const targetAgents = step.agents;
159299
+ const currentAgents = this.mockAgents.size;
159300
+ if (targetAgents > currentAgents) {
159301
+ await this.spawnAgents(targetAgents - currentAgents, workload);
159302
+ } else if (targetAgents < currentAgents) {
159303
+ await this.terminateAgents(currentAgents - targetAgents);
159304
+ }
159305
+ if (step.churnRate && step.churnRate > 0) {
159306
+ this.startChurn(step.churnRate, targetAgents, workload);
159307
+ }
159308
+ await this.hold(step.holdTime);
159309
+ this.stopChurn();
159310
+ }
159311
+ async spawnAgents(count, workload) {
159312
+ const promises2 = [];
159313
+ for (let i58 = 0; i58 < count && !this.stopRequested; i58++) {
159314
+ promises2.push(this.spawnMockAgent(workload));
159315
+ if (promises2.length >= 10) {
159316
+ await Promise.all(promises2);
159317
+ promises2.length = 0;
159318
+ await this.delay(10);
159319
+ }
159320
+ }
159321
+ if (promises2.length > 0) {
159322
+ await Promise.all(promises2);
159323
+ }
159324
+ }
159325
+ async terminateAgents(count) {
159326
+ const agents = Array.from(this.mockAgents.keys()).slice(0, count);
159327
+ for (const agentId of agents) {
159328
+ await this.terminateMockAgent(agentId);
159329
+ }
159330
+ }
159331
+ async hold(duration) {
159332
+ const checkInterval = 100;
159333
+ let elapsed = 0;
159334
+ while (elapsed < duration && !this.stopRequested) {
159335
+ await this.delay(checkInterval);
159336
+ elapsed += checkInterval;
159337
+ }
159338
+ }
159339
+ startChurn(rate, targetCount, workload) {
159340
+ const churnPerMinute = Math.ceil(targetCount * rate);
159341
+ const churnInterval = 6e4 / churnPerMinute;
159342
+ this.churnTimer = setInterval(async () => {
159343
+ if (this.random() < 0.5) {
159344
+ const agents = Array.from(this.mockAgents.keys());
159345
+ if (agents.length > 0) {
159346
+ const randomAgent = agents[Math.floor(this.random() * agents.length)];
159347
+ await this.terminateMockAgent(randomAgent);
159348
+ }
159349
+ }
159350
+ if (this.mockAgents.size < targetCount) {
159351
+ await this.spawnMockAgent(workload);
159352
+ }
159353
+ }, churnInterval);
159354
+ }
159355
+ stopChurn() {
159356
+ if (this.churnTimer) {
159357
+ clearInterval(this.churnTimer);
159358
+ this.churnTimer = null;
159359
+ }
159360
+ }
159361
+ // ============================================================================
159362
+ // Private Methods - Mock Agent Management
159363
+ // ============================================================================
159364
+ async spawnMockAgent(workload) {
159365
+ const agentId = `agent_${v4_default().slice(0, 8)}`;
159366
+ const now = Date.now();
159367
+ const agent = {
159368
+ id: agentId,
159369
+ domain: this.getRandomDomain(),
159370
+ spawnedAt: now,
159371
+ workload,
159372
+ activeTasks: 0,
159373
+ totalTasks: 0,
159374
+ terminated: false
159375
+ };
159376
+ this.mockAgents.set(agentId, agent);
159377
+ this.metrics.recordAgentSpawn(agentId, now);
159378
+ this.startAgentTasks(agent);
159379
+ this.startAgentCoordination(agent);
159380
+ this.simulateMemoryUsage();
159381
+ }
159382
+ async terminateMockAgent(agentId) {
159383
+ const agent = this.mockAgents.get(agentId);
159384
+ if (!agent) return;
159385
+ agent.terminated = true;
159386
+ const taskTimer = this.mockTaskTimers.get(agentId);
159387
+ if (taskTimer) {
159388
+ clearInterval(taskTimer);
159389
+ this.mockTaskTimers.delete(agentId);
159390
+ }
159391
+ const coordTimer = this.mockCoordinationTimers.get(agentId);
159392
+ if (coordTimer) {
159393
+ clearInterval(coordTimer);
159394
+ this.mockCoordinationTimers.delete(agentId);
159395
+ }
159396
+ this.mockAgents.delete(agentId);
159397
+ this.metrics.recordAgentTerminate(agentId, Date.now());
159398
+ }
159399
+ startAgentTasks(agent) {
159400
+ const taskInterval = agent.workload.taskDuration * 1.5;
159401
+ const timer = setInterval(() => {
159402
+ if (agent.terminated || agent.totalTasks >= agent.workload.taskCount) {
159403
+ clearInterval(timer);
159404
+ this.mockTaskTimers.delete(agent.id);
159405
+ return;
159406
+ }
159407
+ const taskId = `${agent.id}_task_${agent.totalTasks}`;
159408
+ const taskStart = Date.now();
159409
+ agent.activeTasks++;
159410
+ agent.totalTasks++;
159411
+ this.metrics.recordTaskStart(agent.id, taskId, taskStart);
159412
+ const variance = agent.workload.durationVariance ?? 0.2;
159413
+ const duration = agent.workload.taskDuration * (1 + (this.random() - 0.5) * 2 * variance);
159414
+ setTimeout(() => {
159415
+ if (!agent.terminated) {
159416
+ agent.activeTasks--;
159417
+ this.metrics.recordTaskComplete(agent.id, taskId, Date.now() - taskStart);
159418
+ }
159419
+ }, duration);
159420
+ }, taskInterval);
159421
+ this.mockTaskTimers.set(agent.id, timer);
159422
+ }
159423
+ startAgentCoordination(agent) {
159424
+ const coordInterval = 1e3 / agent.workload.coordinationFrequency;
159425
+ const timer = setInterval(() => {
159426
+ if (agent.terminated) {
159427
+ clearInterval(timer);
159428
+ this.mockCoordinationTimers.delete(agent.id);
159429
+ return;
159430
+ }
159431
+ const latency = this.simulateCoordinationLatency();
159432
+ this.metrics.recordCoordination(agent.id, latency);
159433
+ }, coordInterval);
159434
+ this.mockCoordinationTimers.set(agent.id, timer);
159435
+ }
159436
+ // ============================================================================
159437
+ // Private Methods - Simulation Helpers
159438
+ // ============================================================================
159439
+ simulateCoordinationLatency() {
159440
+ const baseLatency = 5;
159441
+ const variableLatency = this.random() * 30;
159442
+ const spike = this.random() < 0.05 ? this.random() * 100 : 0;
159443
+ const loadFactor = Math.min(this.mockAgents.size / 100, 2);
159444
+ const loadLatency = loadFactor * 10;
159445
+ return baseLatency + variableLatency + spike + loadLatency;
159446
+ }
159447
+ simulateMemoryUsage() {
159448
+ const agentCount = this.mockAgents.size;
159449
+ const avgMemoryPerAgent = this.getWorkload().memoryUsage;
159450
+ const baseMemory = 50 * 1024 * 1024;
159451
+ const agentMemory = agentCount * avgMemoryPerAgent;
159452
+ const overhead = agentCount * 1024 * 100;
159453
+ const estimatedHeapUsed = baseMemory + agentMemory + overhead;
159454
+ const estimatedHeapTotal = estimatedHeapUsed * 1.5;
159455
+ this.metrics.recordMemoryUsage(estimatedHeapUsed, estimatedHeapTotal);
159456
+ }
159457
+ getRandomDomain() {
159458
+ const domains = [
159459
+ "test-generation",
159460
+ "test-execution",
159461
+ "coverage-analysis",
159462
+ "quality-assessment",
159463
+ "defect-intelligence",
159464
+ "security-compliance"
159465
+ ];
159466
+ return domains[Math.floor(this.random() * domains.length)];
159467
+ }
159468
+ getWorkload() {
159469
+ if (this.config.customWorkload) {
159470
+ return this.config.customWorkload;
159471
+ }
159472
+ return WORKLOAD_PROFILES[this.config.workloadProfile];
159473
+ }
159474
+ evaluateSuccess(report, criteria) {
159475
+ const { summary, performance: performance4 } = report;
159476
+ if (summary.peakAgents < criteria.agentCount) return false;
159477
+ if (report.resources.memoryPeak >= criteria.memoryLimit) return false;
159478
+ if (performance4.coordinationLatency.p95 > criteria.coordinationLatency) return false;
159479
+ if (criteria.noAgentStarvation && !summary.successCriteria.noStarvation) return false;
159480
+ if (criteria.noDeadlocks && !summary.successCriteria.noDeadlocks) return false;
159481
+ return true;
159482
+ }
159483
+ async cleanup() {
159484
+ this.stopChurn();
159485
+ const agents = Array.from(this.mockAgents.keys());
159486
+ for (const agentId of agents) {
159487
+ await this.terminateMockAgent(agentId);
159488
+ }
159489
+ this.mockTaskTimers.forEach((timer) => {
159490
+ clearInterval(timer);
159491
+ });
159492
+ this.mockTaskTimers.clear();
159493
+ this.mockCoordinationTimers.forEach((timer) => {
159494
+ clearInterval(timer);
159495
+ });
159496
+ this.mockCoordinationTimers.clear();
159497
+ }
159498
+ delay(ms) {
159499
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
159500
+ }
159501
+ seededRandom(seed) {
159502
+ return function() {
159503
+ let t50 = seed += 1831565813;
159504
+ t50 = Math.imul(t50 ^ t50 >>> 15, t50 | 1);
159505
+ t50 ^= t50 + Math.imul(t50 ^ t50 >>> 7, t50 | 61);
159506
+ return ((t50 ^ t50 >>> 14) >>> 0) / 4294967296;
159507
+ };
159508
+ }
159509
+ };
159510
+ }
159511
+ });
159512
+
159513
+ // src/testing/load/index.ts
159514
+ var load_exports = {};
159515
+ __export(load_exports, {
159516
+ AgentLoadTester: () => AgentLoadTester,
159517
+ BottleneckAnalyzer: () => BottleneckAnalyzer,
159518
+ DEFAULT_ANALYZER_CONFIG: () => DEFAULT_CONFIG73,
159519
+ DEFAULT_LOAD_TEST_CONFIG: () => DEFAULT_CONFIG74,
159520
+ DEFAULT_SUCCESS_CRITERIA: () => DEFAULT_SUCCESS_CRITERIA,
159521
+ DEFAULT_THRESHOLDS: () => DEFAULT_THRESHOLDS2,
159522
+ MetricsCollector: () => MetricsCollector2,
159523
+ SCENARIO_BURST_100: () => SCENARIO_BURST_100,
159524
+ SCENARIO_CHURN_100: () => SCENARIO_CHURN_100,
159525
+ SCENARIO_RAMP_UP_100: () => SCENARIO_RAMP_UP_100,
159526
+ SCENARIO_STRESS_150: () => SCENARIO_STRESS_150,
159527
+ WORKLOAD_PROFILES: () => WORKLOAD_PROFILES,
159528
+ createAgentLoadTester: () => createAgentLoadTester,
159529
+ createBottleneckAnalyzer: () => createBottleneckAnalyzer,
159530
+ createBottleneckAnalyzerWithThresholds: () => createBottleneckAnalyzerWithThresholds,
159531
+ createLoadTesterForTarget: () => createLoadTesterForTarget,
159532
+ createMetricsCollector: () => createMetricsCollector
159533
+ });
159534
+ var init_load = __esm({
159535
+ "src/testing/load/index.ts"() {
159536
+ "use strict";
159537
+ init_agent_load_tester();
159538
+ init_metrics_collector2();
159539
+ init_bottleneck_analyzer();
159540
+ }
159541
+ });
159542
+
159543
+ // src/mcp/tools/test-execution/load-test.ts
159544
+ var LoadTestTool;
159545
+ var init_load_test = __esm({
159546
+ "src/mcp/tools/test-execution/load-test.ts"() {
159547
+ "use strict";
159548
+ init_base();
159549
+ init_error_utils();
159550
+ LoadTestTool = class extends MCPToolBase {
159551
+ config = {
159552
+ name: "qe/tests/load",
159553
+ description: "Run agent load tests to validate fleet scalability. Supports light, medium, and heavy workload profiles. Uses mock agents by default (safe); set mockMode=false to test with real fleet agents (requires fleet_init). Reports bottlenecks and pass/fail criteria.",
159554
+ domain: "test-execution",
159555
+ schema: this.buildSchema(),
159556
+ timeout: 3e5
159557
+ };
159558
+ buildSchema() {
159559
+ return {
159560
+ type: "object",
159561
+ properties: {
159562
+ targetAgents: {
159563
+ type: "number",
159564
+ description: "Target number of concurrent agents to simulate",
159565
+ default: 10,
159566
+ minimum: 1,
159567
+ maximum: 200
159568
+ },
159569
+ profile: {
159570
+ type: "string",
159571
+ description: "Workload profile: light, medium, or heavy",
159572
+ enum: ["light", "medium", "heavy"],
159573
+ default: "medium"
159574
+ },
159575
+ durationMs: {
159576
+ type: "number",
159577
+ description: "Test duration in milliseconds",
159578
+ default: 3e4,
159579
+ minimum: 5e3,
159580
+ maximum: 3e5
159581
+ },
159582
+ mockMode: {
159583
+ type: "boolean",
159584
+ description: "Use mock agents (true, default) or real fleet agents (false, requires fleet_init)",
159585
+ default: true
159586
+ }
159587
+ }
159588
+ };
159589
+ }
159590
+ async execute(params, context) {
159591
+ try {
159592
+ const { createAgentLoadTester: createAgentLoadTester2 } = await Promise.resolve().then(() => (init_load(), load_exports));
159593
+ const profile = params.profile || "medium";
159594
+ const targetAgents = params.targetAgents || 10;
159595
+ const durationMs = params.durationMs || 3e4;
159596
+ const mockMode = params.mockMode !== false;
159597
+ const tester = createAgentLoadTester2({
159598
+ maxAgents: targetAgents,
159599
+ workloadProfile: profile,
159600
+ mockMode
159601
+ });
159602
+ const result = await tester.runTest(targetAgents, durationMs);
159603
+ const bottlenecks = result.bottlenecks;
159604
+ return {
159605
+ success: true,
159606
+ data: {
159607
+ testId: context.requestId,
159608
+ profile,
159609
+ targetAgents,
159610
+ duration: result.duration,
159611
+ mockMode,
159612
+ passed: result.success,
159613
+ bottleneckCount: bottlenecks?.bottlenecks?.length ?? 0,
159614
+ report: {
159615
+ overallSeverity: bottlenecks?.overallSeverity ?? "none",
159616
+ hasCritical: bottlenecks?.hasCritical ?? false,
159617
+ checksPerformed: bottlenecks?.summary?.totalChecks ?? 0,
159618
+ bottlenecksDetected: bottlenecks?.summary?.detected ?? 0
159619
+ },
159620
+ summary: `Load test (${profile}, ${mockMode ? "mock" : "real"}): ${targetAgents} agents, ${durationMs}ms \u2014 ${result.success ? "PASSED" : "FAILED"}` + (bottlenecks?.hasCritical ? " [CRITICAL BOTTLENECKS]" : "")
159621
+ }
159622
+ };
159623
+ } catch (error) {
159624
+ return {
159625
+ success: false,
159626
+ error: toErrorMessage(error)
159627
+ };
159628
+ }
159629
+ }
159630
+ };
159631
+ }
159632
+ });
159633
+
159634
+ // src/mcp/tools/security-compliance/visual-security.ts
159635
+ var PII_PATTERNS, VisualSecurityTool;
159636
+ var init_visual_security = __esm({
159637
+ "src/mcp/tools/security-compliance/visual-security.ts"() {
159638
+ "use strict";
159639
+ init_base();
159640
+ init_error_utils();
159641
+ PII_PATTERNS = [
159642
+ {
159643
+ type: "email",
159644
+ pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
159645
+ mask: (m74) => m74[0] + "***@" + m74.split("@")[1]
159646
+ },
159647
+ {
159648
+ type: "ssn",
159649
+ pattern: /\b\d{3}-\d{2}-\d{4}\b/g,
159650
+ mask: () => "***-**-****"
159651
+ },
159652
+ {
159653
+ type: "credit-card",
159654
+ pattern: /\b(?:\d[ -]*?){13,19}\b/g,
159655
+ mask: (m74) => "****-****-****-" + m74.replace(/\D/g, "").slice(-4)
159656
+ },
159657
+ {
159658
+ type: "phone",
159659
+ pattern: /\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
159660
+ mask: (m74) => m74.slice(0, 3) + "***" + m74.slice(-2)
159661
+ },
159662
+ {
159663
+ type: "api-key",
159664
+ // Common API key patterns: long hex/base64 strings in query params
159665
+ pattern: /(?:key|token|api_key|apikey|secret|password|passwd|auth)=([A-Za-z0-9_\-]{16,})/gi,
159666
+ mask: () => "***REDACTED***"
159667
+ }
159668
+ ];
159669
+ VisualSecurityTool = class extends MCPToolBase {
159670
+ config = {
159671
+ name: "qe/security/url-validate",
159672
+ description: "Validate URL security: checks for XSS/injection patterns, unsafe protocols, and scans URL query parameters for PII exposure (emails, SSNs, credit cards, API keys).",
159673
+ domain: "security-compliance",
159674
+ schema: this.buildSchema()
159675
+ };
159676
+ buildSchema() {
159677
+ return {
159678
+ type: "object",
159679
+ properties: {
159680
+ url: {
159681
+ type: "string",
159682
+ description: "URL to validate for security threats and PII exposure"
159683
+ },
159684
+ enablePII: {
159685
+ type: "boolean",
159686
+ description: "Enable PII exposure scanning in URL and query parameters",
159687
+ default: true
159688
+ }
159689
+ },
159690
+ required: ["url"]
159691
+ };
159692
+ }
159693
+ async execute(params, context) {
159694
+ try {
159695
+ const urlSecurity = this.validateURLSecurity(params.url);
159696
+ const piiExposure = params.enablePII !== false ? this.scanForPII(params.url) : { scanned: false, found: false, types: [], details: [] };
159697
+ const issueCount = urlSecurity.issues.length + (piiExposure.found ? piiExposure.types.length : 0);
159698
+ const summary = issueCount === 0 ? `URL passed all checks (security: clean, PII: ${piiExposure.scanned ? "none found" : "not scanned"})` : `URL has ${urlSecurity.issues.length} security issue(s)${piiExposure.found ? ` and ${piiExposure.types.length} PII type(s) exposed in URL` : ""}`;
159699
+ return {
159700
+ success: true,
159701
+ data: {
159702
+ url: params.url,
159703
+ urlSecurity,
159704
+ piiExposure,
159705
+ summary
159706
+ }
159707
+ };
159708
+ } catch (error) {
159709
+ return {
159710
+ success: false,
159711
+ error: toErrorMessage(error)
159712
+ };
159713
+ }
159714
+ }
159715
+ validateURLSecurity(url) {
159716
+ const issues = [];
159717
+ let riskLevel = "none";
159718
+ try {
159719
+ const parsed = new URL(url);
159720
+ if (!["http:", "https:"].includes(parsed.protocol)) {
159721
+ issues.push({
159722
+ type: "unsafe-protocol",
159723
+ description: `Protocol ${parsed.protocol} is not allowed`,
159724
+ severity: "high"
159725
+ });
159726
+ riskLevel = "high";
159727
+ }
159728
+ const xssPatterns = [/<script/i, /javascript:/i, /on\w+=/i, /data:text\/html/i];
159729
+ for (const pattern of xssPatterns) {
159730
+ if (pattern.test(url)) {
159731
+ issues.push({
159732
+ type: "xss",
159733
+ description: "Potential XSS pattern detected in URL",
159734
+ severity: "critical"
159735
+ });
159736
+ riskLevel = "critical";
159737
+ break;
159738
+ }
159739
+ }
159740
+ const sqlPatterns = [/'.*or.*'/i, /union.*select/i, /drop.*table/i, /;\s*--/i];
159741
+ for (const pattern of sqlPatterns) {
159742
+ if (pattern.test(url)) {
159743
+ issues.push({
159744
+ type: "sql-injection",
159745
+ description: "Potential SQL injection pattern detected in URL",
159746
+ severity: "critical"
159747
+ });
159748
+ riskLevel = "critical";
159749
+ break;
159750
+ }
159751
+ }
159752
+ if (/\.\.[/\\]/.test(url)) {
159753
+ issues.push({
159754
+ type: "path-traversal",
159755
+ description: "Potential path traversal pattern (../) detected",
159756
+ severity: "high"
159757
+ });
159758
+ if (riskLevel !== "critical") riskLevel = "high";
159759
+ }
159760
+ const redirectParams = ["redirect", "url", "next", "return", "returnUrl", "goto"];
159761
+ for (const param of redirectParams) {
159762
+ const value = parsed.searchParams.get(param);
159763
+ if (value && /^https?:\/\//.test(value)) {
159764
+ issues.push({
159765
+ type: "open-redirect",
159766
+ description: `Query parameter "${param}" contains an external URL \u2014 potential open redirect`,
159767
+ severity: "medium"
159768
+ });
159769
+ if (riskLevel === "none") riskLevel = "medium";
159770
+ }
159771
+ }
159772
+ } catch {
159773
+ issues.push({
159774
+ type: "invalid-url",
159775
+ description: "URL could not be parsed",
159776
+ severity: "critical"
159777
+ });
159778
+ riskLevel = "critical";
159779
+ }
159780
+ return { valid: issues.length === 0, riskLevel, issues };
159781
+ }
159782
+ scanForPII(url) {
159783
+ const details = [];
159784
+ const typesFound = /* @__PURE__ */ new Set();
159785
+ let decoded;
159786
+ try {
159787
+ decoded = decodeURIComponent(url);
159788
+ } catch {
159789
+ decoded = url;
159790
+ }
159791
+ let queryString = "";
159792
+ let pathString = "";
159793
+ try {
159794
+ const parsed = new URL(decoded);
159795
+ queryString = parsed.search;
159796
+ pathString = parsed.pathname;
159797
+ } catch {
159798
+ queryString = decoded;
159799
+ }
159800
+ for (const { type, pattern, mask } of PII_PATTERNS) {
159801
+ pattern.lastIndex = 0;
159802
+ let match;
159803
+ while ((match = pattern.exec(decoded)) !== null) {
159804
+ typesFound.add(type);
159805
+ const location = queryString.includes(match[0]) ? "query-parameter" : pathString.includes(match[0]) ? "path" : "url";
159806
+ details.push({
159807
+ type,
159808
+ location,
159809
+ masked: mask(match[0])
159810
+ });
159811
+ }
159812
+ }
159813
+ return {
159814
+ scanned: true,
159815
+ found: typesFound.size > 0,
159816
+ types: Array.from(typesFound),
159817
+ details
159818
+ };
159819
+ }
159820
+ };
159821
+ }
159822
+ });
159823
+
159824
+ // src/workflows/browser/workflow-loader.ts
159825
+ import { readFile as readFile16, readdir as readdir5 } from "fs/promises";
159826
+ import { join as join25, basename as basename5 } from "path";
159827
+ import { parse as parseYaml2 } from "yaml";
159828
+ function interpolateVariables(template, variables) {
159829
+ return template.replace(/\{\{([^}]+)\}\}/g, (match, key) => {
159830
+ const trimmedKey = key.trim();
159831
+ const keys = trimmedKey.split(".");
159832
+ let value = variables;
159833
+ for (const k68 of keys) {
159834
+ if (value && typeof value === "object" && k68 in value) {
159835
+ value = value[k68];
159836
+ } else {
159837
+ return match;
159838
+ }
159839
+ }
159840
+ return value !== void 0 && value !== null ? String(value) : match;
159841
+ });
159842
+ }
159843
+ function evaluateCondition(condition, context) {
159844
+ const evalContext = {
159845
+ ...context.variables,
159846
+ result: context.results.get("__last_result__")
159847
+ };
159848
+ const interpolated = interpolateVariables(condition, evalContext);
159849
+ return safeEvaluateBoolean(interpolated, evalContext, false);
159850
+ }
159851
+ var WorkflowLoader, defaultWorkflowLoader;
159852
+ var init_workflow_loader = __esm({
159853
+ "src/workflows/browser/workflow-loader.ts"() {
159854
+ "use strict";
159855
+ init_safe_expression_evaluator();
159856
+ WorkflowLoader = class {
159857
+ templatesDir;
159858
+ cache = /* @__PURE__ */ new Map();
159859
+ constructor(templatesDir) {
159860
+ this.templatesDir = templatesDir || join25(__dirname, "templates");
159861
+ }
159862
+ /**
159863
+ * Load a workflow template by name
159864
+ */
159865
+ async load(templateName) {
159866
+ if (this.cache.has(templateName)) {
159867
+ return this.cache.get(templateName);
159868
+ }
159869
+ try {
159870
+ const templatePath = join25(this.templatesDir, `${templateName}.yaml`);
159871
+ const content = await readFile16(templatePath, "utf-8");
159872
+ const workflow = parseYaml2(content);
159873
+ const validation = await this.validate(workflow);
159874
+ if (!validation.valid) {
159875
+ throw new Error(
159876
+ `Invalid workflow template ${templateName}:
159877
+ ${validation.errors.join("\n")}`
159878
+ );
159879
+ }
159880
+ this.cache.set(templateName, workflow);
159881
+ return workflow;
159882
+ } catch (error) {
159883
+ if (error.code === "ENOENT") {
159884
+ throw new Error(`Workflow template not found: ${templateName}`);
159885
+ }
159886
+ throw error;
159887
+ }
159888
+ }
159889
+ /**
159890
+ * List all available workflow templates
159891
+ */
159892
+ async list() {
159893
+ try {
159894
+ const files = await readdir5(this.templatesDir);
159895
+ return files.filter((file) => file.endsWith(".yaml") || file.endsWith(".yml")).map((file) => basename5(file, file.endsWith(".yaml") ? ".yaml" : ".yml")).sort();
159896
+ } catch (error) {
159897
+ if (error.code === "ENOENT") {
159898
+ return [];
159899
+ }
159900
+ throw error;
159901
+ }
159902
+ }
159903
+ /**
159904
+ * Validate a workflow template
159905
+ */
159906
+ async validate(workflow) {
159907
+ const errors = [];
159908
+ const warnings = [];
159909
+ if (!workflow.name) {
159910
+ errors.push("Workflow must have a name");
159911
+ }
159912
+ if (!workflow.version) {
159913
+ errors.push("Workflow must have a version");
159914
+ }
159915
+ if (!workflow.description) {
159916
+ warnings.push("Workflow should have a description");
159917
+ }
159918
+ if (!Array.isArray(workflow.variables)) {
159919
+ errors.push("Workflow must have a variables array");
159920
+ } else {
159921
+ workflow.variables.forEach((variable, index) => {
159922
+ if (!variable.name) {
159923
+ errors.push(`Variable at index ${index} must have a name`);
159924
+ }
159925
+ if (!variable.type) {
159926
+ errors.push(`Variable ${variable.name} must have a type`);
159927
+ }
159928
+ if (variable.required === void 0) {
159929
+ warnings.push(`Variable ${variable.name} should specify if it's required`);
159930
+ }
159931
+ });
159932
+ }
159933
+ if (!Array.isArray(workflow.steps)) {
159934
+ errors.push("Workflow must have a steps array");
159935
+ } else if (workflow.steps.length === 0) {
159936
+ errors.push("Workflow must have at least one step");
159937
+ } else {
159938
+ workflow.steps.forEach((step, index) => {
159939
+ if (!step.name) {
159940
+ errors.push(`Step at index ${index} must have a name`);
159941
+ }
159942
+ if (!step.action) {
159943
+ errors.push(`Step ${step.name || index} must have an action`);
159944
+ }
159945
+ if (!step.config || typeof step.config !== "object") {
159946
+ errors.push(`Step ${step.name || index} must have a config object`);
159947
+ }
159948
+ if (step.assertions && Array.isArray(step.assertions)) {
159949
+ step.assertions.forEach((assertion, assertionIndex) => {
159950
+ if (!assertion.condition) {
159951
+ errors.push(
159952
+ `Assertion ${assertionIndex} in step ${step.name || index} must have a condition`
159953
+ );
159954
+ }
159955
+ if (!assertion.message) {
159956
+ warnings.push(
159957
+ `Assertion ${assertionIndex} in step ${step.name || index} should have a message`
159958
+ );
159959
+ }
159960
+ });
159961
+ }
159962
+ });
159963
+ const stepNames = workflow.steps.map((s70) => s70.name);
159964
+ const duplicates = stepNames.filter(
159965
+ (name, index) => stepNames.indexOf(name) !== index
159966
+ );
159967
+ if (duplicates.length > 0) {
159968
+ errors.push(`Duplicate step names found: ${duplicates.join(", ")}`);
159969
+ }
159970
+ }
159971
+ return {
159972
+ valid: errors.length === 0,
159973
+ errors,
159974
+ warnings
159975
+ };
159976
+ }
159977
+ /**
159978
+ * Create a workflow execution context with resolved variables
159979
+ */
159980
+ async createContext(templateName, variables) {
159981
+ const workflow = await this.load(templateName);
159982
+ const missingVars = workflow.variables.filter((v62) => v62.required && !(v62.name in variables)).map((v62) => v62.name);
159983
+ if (missingVars.length > 0) {
159984
+ throw new Error(
159985
+ `Missing required variables: ${missingVars.join(", ")}`
159986
+ );
159987
+ }
159988
+ const resolvedVariables = {};
159989
+ workflow.variables.forEach((varDef) => {
159990
+ if (varDef.name in variables) {
159991
+ resolvedVariables[varDef.name] = variables[varDef.name];
159992
+ } else if ("default" in varDef) {
159993
+ resolvedVariables[varDef.name] = varDef.default;
159994
+ }
159995
+ });
159996
+ return {
159997
+ variables: resolvedVariables,
159998
+ results: /* @__PURE__ */ new Map(),
159999
+ metadata: {
160000
+ startTime: Date.now(),
160001
+ workflow: workflow.name,
160002
+ templateName
160003
+ }
160004
+ };
160005
+ }
160006
+ /**
160007
+ * Get workflow metadata without loading the full workflow
160008
+ */
160009
+ async getMetadata(templateName) {
160010
+ try {
160011
+ const templatePath = join25(this.templatesDir, `${templateName}.yaml`);
160012
+ const content = await readFile16(templatePath, "utf-8");
160013
+ const workflow = parseYaml2(content);
160014
+ return {
160015
+ name: workflow.name,
160016
+ version: workflow.version,
160017
+ description: workflow.description
160018
+ };
160019
+ } catch (error) {
160020
+ if (error.code === "ENOENT") {
160021
+ throw new Error(`Workflow template not found: ${templateName}`);
160022
+ }
160023
+ throw error;
160024
+ }
160025
+ }
160026
+ /**
160027
+ * Clear the workflow cache
160028
+ */
160029
+ clearCache() {
160030
+ this.cache.clear();
160031
+ }
160032
+ /**
160033
+ * Reload a specific workflow template
160034
+ */
160035
+ async reload(templateName) {
160036
+ this.cache.delete(templateName);
160037
+ return this.load(templateName);
160038
+ }
160039
+ };
160040
+ defaultWorkflowLoader = new WorkflowLoader();
160041
+ }
160042
+ });
160043
+
160044
+ // src/workflows/browser/index.ts
160045
+ var browser_exports = {};
160046
+ __export(browser_exports, {
160047
+ WORKFLOW_CATEGORIES: () => WORKFLOW_CATEGORIES,
160048
+ WORKFLOW_DESCRIPTIONS: () => WORKFLOW_DESCRIPTIONS,
160049
+ WORKFLOW_TEMPLATES: () => WORKFLOW_TEMPLATES,
160050
+ WorkflowLoader: () => WorkflowLoader,
160051
+ defaultWorkflowLoader: () => defaultWorkflowLoader,
160052
+ evaluateCondition: () => evaluateCondition,
160053
+ getAllWorkflowTemplates: () => getAllWorkflowTemplates,
160054
+ getWorkflowsByCategory: () => getWorkflowsByCategory,
160055
+ interpolateVariables: () => interpolateVariables,
160056
+ isValidWorkflowTemplate: () => isValidWorkflowTemplate
160057
+ });
160058
+ function getWorkflowsByCategory(category) {
160059
+ return WORKFLOW_CATEGORIES[category];
160060
+ }
160061
+ function isValidWorkflowTemplate(name) {
160062
+ return WORKFLOW_TEMPLATES.includes(name);
160063
+ }
160064
+ function getAllWorkflowTemplates() {
160065
+ return WORKFLOW_TEMPLATES.map((name) => {
160066
+ const category = Object.entries(WORKFLOW_CATEGORIES).find(
160067
+ ([_56, templates]) => templates.includes(name)
160068
+ )?.[0] || "other";
160069
+ return {
160070
+ name,
160071
+ description: WORKFLOW_DESCRIPTIONS[name],
160072
+ category
160073
+ };
160074
+ });
160075
+ }
160076
+ var WORKFLOW_TEMPLATES, WORKFLOW_DESCRIPTIONS, WORKFLOW_CATEGORIES;
160077
+ var init_browser2 = __esm({
160078
+ "src/workflows/browser/index.ts"() {
160079
+ "use strict";
160080
+ init_workflow_loader();
160081
+ WORKFLOW_TEMPLATES = [
160082
+ "login-flow",
160083
+ "oauth-flow",
160084
+ "scraping-workflow",
160085
+ "visual-regression",
160086
+ "form-validation",
160087
+ "navigation-flow",
160088
+ "api-integration",
160089
+ "performance-audit",
160090
+ "accessibility-audit"
160091
+ ];
160092
+ WORKFLOW_DESCRIPTIONS = {
160093
+ "login-flow": "Authentication testing workflow for login forms with credential validation",
160094
+ "oauth-flow": "OAuth2/OIDC authentication testing workflow with provider integration",
160095
+ "scraping-workflow": "Data extraction workflow for web scraping with pagination and structured output",
160096
+ "visual-regression": "Screenshot comparison workflow for visual regression testing across breakpoints",
160097
+ "form-validation": "Input validation testing workflow for form fields with error handling",
160098
+ "navigation-flow": "Multi-page navigation workflow for testing user journeys and state persistence",
160099
+ "api-integration": "Browser-API hybrid testing workflow for validating frontend-backend integration",
160100
+ "performance-audit": "Lighthouse-style performance audit workflow with Core Web Vitals",
160101
+ "accessibility-audit": "WCAG 2.1 Level AA compliance audit workflow with automated accessibility testing"
160102
+ };
160103
+ WORKFLOW_CATEGORIES = {
160104
+ authentication: ["login-flow", "oauth-flow"],
160105
+ testing: ["form-validation", "navigation-flow", "api-integration"],
160106
+ quality: ["visual-regression", "performance-audit", "accessibility-audit"],
160107
+ automation: ["scraping-workflow"]
160108
+ };
160109
+ }
160110
+ });
160111
+
160112
+ // src/mcp/tools/test-execution/browser-workflow.ts
160113
+ var BrowserWorkflowTool;
160114
+ var init_browser_workflow = __esm({
160115
+ "src/mcp/tools/test-execution/browser-workflow.ts"() {
160116
+ "use strict";
160117
+ init_base();
160118
+ init_error_utils();
160119
+ BrowserWorkflowTool = class extends MCPToolBase {
160120
+ config = {
160121
+ name: "qe/workflows/browser-load",
160122
+ description: "Load, validate, and prepare browser automation workflows from inline YAML or built-in templates. Returns the resolved workflow with steps and variable bindings, ready for browser execution. Templates: login-flow, form-validation, visual-regression, oauth-flow, etc.",
160123
+ domain: "test-execution",
160124
+ schema: this.buildSchema()
160125
+ };
160126
+ buildSchema() {
160127
+ return {
160128
+ type: "object",
160129
+ properties: {
160130
+ workflowYaml: {
160131
+ type: "string",
160132
+ description: "Inline YAML workflow definition. Mutually exclusive with templateName."
160133
+ },
160134
+ templateName: {
160135
+ type: "string",
160136
+ description: "Built-in template name to load.",
160137
+ enum: [
160138
+ "login-flow",
160139
+ "oauth-flow",
160140
+ "scraping-workflow",
160141
+ "visual-regression",
160142
+ "form-validation",
160143
+ "navigation-flow",
160144
+ "api-integration",
160145
+ "performance-audit",
160146
+ "accessibility-audit"
160147
+ ]
160148
+ },
160149
+ variables: {
160150
+ type: "object",
160151
+ description: 'Runtime variable overrides (e.g., { "baseUrl": "https://example.com" })'
160152
+ }
160153
+ }
160154
+ };
160155
+ }
160156
+ async execute(params, context) {
160157
+ try {
160158
+ const {
160159
+ WorkflowLoader: WorkflowLoader2,
160160
+ WORKFLOW_TEMPLATES: WORKFLOW_TEMPLATES2,
160161
+ WORKFLOW_DESCRIPTIONS: WORKFLOW_DESCRIPTIONS2,
160162
+ interpolateVariables: interpolateVariables2
160163
+ } = await Promise.resolve().then(() => (init_browser2(), browser_exports));
160164
+ const { parse: parseYaml4 } = await import("yaml");
160165
+ const loader = new WorkflowLoader2();
160166
+ const templateList = [...WORKFLOW_TEMPLATES2];
160167
+ const descriptions = WORKFLOW_DESCRIPTIONS2;
160168
+ if (!params.workflowYaml && !params.templateName) {
160169
+ return {
160170
+ success: true,
160171
+ data: {
160172
+ workflowName: "none",
160173
+ description: "No workflow specified. Use templateName or workflowYaml.",
160174
+ source: "none",
160175
+ templateUsed: null,
160176
+ steps: [],
160177
+ variables: { defined: [], provided: {} },
160178
+ validation: { valid: true, errors: [], warnings: [] },
160179
+ availableTemplates: templateList,
160180
+ summary: `Available templates: ${templateList.join(", ")}`
160181
+ }
160182
+ };
160183
+ }
160184
+ let workflow;
160185
+ let source;
160186
+ let templateUsed = null;
160187
+ if (params.workflowYaml) {
160188
+ source = "inline-yaml";
160189
+ workflow = parseYaml4(params.workflowYaml);
160190
+ } else {
160191
+ source = "template";
160192
+ templateUsed = params.templateName;
160193
+ workflow = await loader.load(params.templateName);
160194
+ }
160195
+ const validation = await loader.validate(workflow);
160196
+ const resolvedSteps = (workflow.steps ?? []).map((step) => {
160197
+ let config = step.config;
160198
+ if (params.variables) {
160199
+ const interpolated = {};
160200
+ for (const [k68, v62] of Object.entries(config)) {
160201
+ interpolated[k68] = typeof v62 === "string" ? interpolateVariables2(v62, params.variables) : v62;
160202
+ }
160203
+ config = interpolated;
160204
+ }
160205
+ return {
160206
+ name: step.name,
160207
+ action: step.action,
160208
+ config,
160209
+ optional: step.optional ?? false,
160210
+ assertionCount: step.assertions?.length ?? 0
160211
+ };
160212
+ });
160213
+ return {
160214
+ success: true,
160215
+ data: {
160216
+ workflowName: workflow.name || templateUsed || "custom",
160217
+ description: workflow.description || (templateUsed ? descriptions[templateUsed] || "" : ""),
160218
+ source,
160219
+ templateUsed,
160220
+ steps: resolvedSteps,
160221
+ variables: {
160222
+ defined: (workflow.variables ?? []).map((v62) => ({
160223
+ name: v62.name,
160224
+ type: v62.type,
160225
+ required: v62.required,
160226
+ hasDefault: v62.default !== void 0
160227
+ })),
160228
+ provided: params.variables || {}
160229
+ },
160230
+ validation: {
160231
+ valid: validation.valid,
160232
+ errors: validation.errors,
160233
+ warnings: validation.warnings
160234
+ },
160235
+ availableTemplates: templateList,
160236
+ summary: validation.valid ? `Workflow "${workflow.name}" loaded (${source}): ${resolvedSteps.length} steps, ${(workflow.variables ?? []).length} variables` : `Workflow "${workflow.name}" has validation errors: ${validation.errors.join("; ")}`
160237
+ }
160238
+ };
160239
+ } catch (error) {
160240
+ return {
160241
+ success: false,
160242
+ error: toErrorMessage(error)
160243
+ };
160244
+ }
160245
+ }
160246
+ };
160247
+ }
160248
+ });
160249
+
156715
160250
  // src/mcp/tools/registry.ts
156716
160251
  function resetAllToolCaches() {
156717
160252
  for (const tool of QE_TOOLS) {
@@ -156741,6 +160276,10 @@ var init_registry = __esm({
156741
160276
  init_embeddings2();
156742
160277
  init_coherence3();
156743
160278
  init_analyze2();
160279
+ init_schedule();
160280
+ init_load_test();
160281
+ init_visual_security();
160282
+ init_browser_workflow();
156744
160283
  QE_TOOL_NAMES = {
156745
160284
  // Test Generation
156746
160285
  TEST_GENERATE: "qe/tests/generate",
@@ -156787,7 +160326,15 @@ var init_registry = __esm({
156787
160326
  // Coherence Tools (ADR-052)
156788
160327
  ...COHERENCE_TOOL_NAMES,
156789
160328
  // QX Analysis (Quality Experience)
156790
- QX_ANALYZE: "qe/qx/analyze"
160329
+ QX_ANALYZE: "qe/qx/analyze",
160330
+ // Test Scheduling (pipeline, git-aware, flaky tracking)
160331
+ TEST_SCHEDULE: "qe/tests/schedule",
160332
+ // Load Testing (agent fleet scalability)
160333
+ LOAD_TEST: "qe/tests/load",
160334
+ // URL Security Validation (threat detection, PII exposure scanning)
160335
+ URL_VALIDATE: "qe/security/url-validate",
160336
+ // Browser Workflow Loader (YAML template loading and validation)
160337
+ BROWSER_WORKFLOW: "qe/workflows/browser-load"
156791
160338
  };
156792
160339
  QE_TOOLS = [
156793
160340
  // Test Generation Domain
@@ -156835,7 +160382,15 @@ var init_registry = __esm({
156835
160382
  // Coherence Tools (ADR-052)
156836
160383
  ...COHERENCE_TOOLS,
156837
160384
  // QX Analysis (Quality Experience)
156838
- new QXAnalyzeTool()
160385
+ new QXAnalyzeTool(),
160386
+ // Test Scheduling (pipeline, git-aware, flaky tracking)
160387
+ new TestScheduleTool(),
160388
+ // Load Testing (agent fleet scalability)
160389
+ new LoadTestTool(),
160390
+ // Security-Visual Audit (URL validation, PII detection)
160391
+ new VisualSecurityTool(),
160392
+ // Browser Workflows (YAML template execution)
160393
+ new BrowserWorkflowTool()
156839
160394
  ];
156840
160395
  }
156841
160396
  });
@@ -157367,7 +160922,7 @@ var init_protocol_executor = __esm({
157367
160922
  * Sleep helper
157368
160923
  */
157369
160924
  sleep(ms) {
157370
- return new Promise((resolve9) => setTimeout(resolve9, ms));
160925
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
157371
160926
  }
157372
160927
  };
157373
160928
  }
@@ -158611,6 +162166,178 @@ var init_task_handlers = __esm({
158611
162166
  }
158612
162167
  });
158613
162168
 
162169
+ // src/monitoring/structural-health.ts
162170
+ var structural_health_exports = {};
162171
+ __export(structural_health_exports, {
162172
+ DEFAULT_STRUCTURAL_HEALTH_CONFIG: () => DEFAULT_STRUCTURAL_HEALTH_CONFIG,
162173
+ StructuralHealthMonitor: () => StructuralHealthMonitor,
162174
+ createStructuralHealthMonitor: () => createStructuralHealthMonitor
162175
+ });
162176
+ function createStructuralHealthMonitor(config) {
162177
+ return new StructuralHealthMonitor(config);
162178
+ }
162179
+ var DEFAULT_STRUCTURAL_HEALTH_CONFIG, StructuralHealthMonitor;
162180
+ var init_structural_health = __esm({
162181
+ "src/monitoring/structural-health.ts"() {
162182
+ "use strict";
162183
+ init_mincut_wrapper();
162184
+ DEFAULT_STRUCTURAL_HEALTH_CONFIG = {
162185
+ healthyThreshold: 0.4,
162186
+ warningThreshold: 0.2,
162187
+ maxHistoryEntries: 100,
162188
+ enableLogging: false
162189
+ };
162190
+ StructuralHealthMonitor = class {
162191
+ config;
162192
+ minCutService;
162193
+ history = [];
162194
+ constructor(config) {
162195
+ this.config = { ...DEFAULT_STRUCTURAL_HEALTH_CONFIG, ...config };
162196
+ this.minCutService = createQEMinCutService();
162197
+ }
162198
+ /**
162199
+ * Compute fleet health from an array of agent nodes
162200
+ *
162201
+ * @param agents - Current agent fleet
162202
+ * @returns Fleet health result
162203
+ */
162204
+ computeFleetHealth(agents) {
162205
+ if (agents.length === 0) {
162206
+ return this.emptyFleetResult();
162207
+ }
162208
+ const graph = this.minCutService.buildTaskGraphFromTopology(agents);
162209
+ return this.computeFleetHealthFromGraph(graph, agents.length);
162210
+ }
162211
+ /**
162212
+ * Compute fleet health from a pre-built task graph
162213
+ *
162214
+ * @param graph - Task graph representing the fleet
162215
+ * @param agentCount - Number of agents (for history tracking)
162216
+ * @returns Fleet health result
162217
+ */
162218
+ computeFleetHealthFromGraph(graph, agentCount) {
162219
+ if (graph.nodes.length === 0) {
162220
+ return this.emptyFleetResult();
162221
+ }
162222
+ const healthReport = this.minCutService.getStructuralHealth(graph);
162223
+ const status = this.determineStatus(healthReport.normalizedLambda);
162224
+ const result = {
162225
+ lambda: healthReport.lambda,
162226
+ healthy: healthReport.healthy,
162227
+ weakPoints: healthReport.weakPoints,
162228
+ normalizedLambda: healthReport.normalizedLambda,
162229
+ riskScore: healthReport.riskScore,
162230
+ status,
162231
+ suggestions: healthReport.suggestions,
162232
+ measuredAt: /* @__PURE__ */ new Date()
162233
+ };
162234
+ this.addHistoryEntry({
162235
+ lambda: healthReport.lambda,
162236
+ healthy: healthReport.healthy,
162237
+ weakPointCount: healthReport.weakPoints.length,
162238
+ agentCount: agentCount ?? graph.nodes.length,
162239
+ timestamp: result.measuredAt
162240
+ });
162241
+ if (this.config.enableLogging) {
162242
+ this.logHealth(result);
162243
+ }
162244
+ return result;
162245
+ }
162246
+ /**
162247
+ * Get health trend from history
162248
+ *
162249
+ * @returns 'improving', 'stable', or 'degrading'
162250
+ */
162251
+ getTrend() {
162252
+ if (this.history.length < 2) {
162253
+ return "stable";
162254
+ }
162255
+ const recentCount = Math.min(5, this.history.length);
162256
+ const recent = this.history.slice(-recentCount);
162257
+ const firstLambda = recent[0].lambda;
162258
+ const lastLambda = recent[recent.length - 1].lambda;
162259
+ const delta = lastLambda - firstLambda;
162260
+ if (Math.abs(delta) < 0.05) {
162261
+ return "stable";
162262
+ }
162263
+ return delta > 0 ? "improving" : "degrading";
162264
+ }
162265
+ /**
162266
+ * Get health history
162267
+ *
162268
+ * @param limit - Maximum entries to return
162269
+ * @returns Array of history entries, most recent last
162270
+ */
162271
+ getHistory(limit) {
162272
+ const entries = [...this.history];
162273
+ if (limit !== void 0 && limit < entries.length) {
162274
+ return entries.slice(-limit);
162275
+ }
162276
+ return entries;
162277
+ }
162278
+ /**
162279
+ * Clear health history
162280
+ */
162281
+ clearHistory() {
162282
+ this.history.length = 0;
162283
+ }
162284
+ /**
162285
+ * Get the underlying QEMinCutService
162286
+ */
162287
+ getMinCutService() {
162288
+ return this.minCutService;
162289
+ }
162290
+ // ==========================================================================
162291
+ // Private Helpers
162292
+ // ==========================================================================
162293
+ /**
162294
+ * Determine status string from normalized lambda
162295
+ */
162296
+ determineStatus(normalizedLambda) {
162297
+ if (normalizedLambda >= this.config.healthyThreshold) {
162298
+ return "healthy";
162299
+ }
162300
+ if (normalizedLambda >= this.config.warningThreshold) {
162301
+ return "warning";
162302
+ }
162303
+ return "critical";
162304
+ }
162305
+ /**
162306
+ * Add an entry to the history, trimming if over limit
162307
+ */
162308
+ addHistoryEntry(entry) {
162309
+ this.history.push(entry);
162310
+ if (this.history.length > this.config.maxHistoryEntries) {
162311
+ this.history.splice(0, this.history.length - this.config.maxHistoryEntries);
162312
+ }
162313
+ }
162314
+ /**
162315
+ * Create result for empty fleet
162316
+ */
162317
+ emptyFleetResult() {
162318
+ return {
162319
+ lambda: 0,
162320
+ healthy: false,
162321
+ weakPoints: [],
162322
+ normalizedLambda: 0,
162323
+ riskScore: 1,
162324
+ status: "empty",
162325
+ suggestions: ["No agents in fleet. Spawn agents to build a topology."],
162326
+ measuredAt: /* @__PURE__ */ new Date()
162327
+ };
162328
+ }
162329
+ /**
162330
+ * Log health check result to stderr
162331
+ */
162332
+ logHealth(result) {
162333
+ console.error(
162334
+ `[StructuralHealth] Status: ${result.status} | Lambda: ${result.normalizedLambda.toFixed(3)} | Weak points: ${result.weakPoints.length} | Risk: ${(result.riskScore * 100).toFixed(0)}%`
162335
+ );
162336
+ }
162337
+ };
162338
+ }
162339
+ });
162340
+
158614
162341
  // src/mcp/handlers/core-handlers.ts
158615
162342
  function getFleetState() {
158616
162343
  return state;
@@ -158873,6 +162600,36 @@ async function handleFleetHealth(params) {
158873
162600
  timestamp: issue.timestamp.toISOString()
158874
162601
  }));
158875
162602
  }
162603
+ try {
162604
+ const { StructuralHealthMonitor: StructuralHealthMonitor2 } = await Promise.resolve().then(() => (init_structural_health(), structural_health_exports));
162605
+ const monitor = new StructuralHealthMonitor2();
162606
+ const allAgents = [];
162607
+ for (const [domain] of health.domainHealth) {
162608
+ const domainAgents = state.queen.getAgentsByDomain(domain);
162609
+ for (const a37 of domainAgents) {
162610
+ allAgents.push({ id: a37.id, name: a37.name, domain: a37.domain });
162611
+ }
162612
+ }
162613
+ const agentNodes = allAgents.map((a37) => ({
162614
+ id: a37.id,
162615
+ name: a37.name,
162616
+ domain: a37.domain,
162617
+ capabilities: [a37.domain],
162618
+ dependsOn: [],
162619
+ weight: 1
162620
+ }));
162621
+ const structuralHealth = monitor.computeFleetHealth(agentNodes);
162622
+ result.structuralHealth = {
162623
+ lambda: structuralHealth.lambda,
162624
+ healthy: structuralHealth.healthy,
162625
+ normalizedLambda: structuralHealth.normalizedLambda,
162626
+ riskScore: structuralHealth.riskScore,
162627
+ status: structuralHealth.status,
162628
+ weakPoints: structuralHealth.weakPoints,
162629
+ suggestions: structuralHealth.suggestions
162630
+ };
162631
+ } catch {
162632
+ }
158876
162633
  return {
158877
162634
  success: true,
158878
162635
  data: result
@@ -158976,7 +162733,7 @@ async function handleAQEHealth() {
158976
162733
  success: true,
158977
162734
  data: {
158978
162735
  status: healthStatus,
158979
- version: true ? "3.7.5" : "3.7.2",
162736
+ version: true ? "3.7.6" : "3.7.2",
158980
162737
  loadedDomains: domainCount,
158981
162738
  memory: memoryStats,
158982
162739
  hnsw: hnswStats,
@@ -159302,17 +163059,17 @@ var StdioTransport = class {
159302
163059
  async writeOnce(data) {
159303
163060
  const message = data + "\n";
159304
163061
  if (this.outputStream.writableNeedDrain) {
159305
- await new Promise((resolve9, reject) => {
163062
+ await new Promise((resolve10, reject) => {
159306
163063
  const drainTimeout = setTimeout(() => {
159307
163064
  reject(new Error("Transport drain timeout after 30 seconds"));
159308
163065
  }, 3e4);
159309
163066
  this.outputStream.once("drain", () => {
159310
163067
  clearTimeout(drainTimeout);
159311
- resolve9();
163068
+ resolve10();
159312
163069
  });
159313
163070
  });
159314
163071
  }
159315
- return new Promise((resolve9, reject) => {
163072
+ return new Promise((resolve10, reject) => {
159316
163073
  const writeTimeout = setTimeout(() => {
159317
163074
  this.metrics.errors++;
159318
163075
  reject(new Error("Transport write timeout after 120 seconds"));
@@ -159325,7 +163082,7 @@ var StdioTransport = class {
159325
163082
  } else {
159326
163083
  this.metrics.messagesSent++;
159327
163084
  this.metrics.bytesSent += Buffer.byteLength(message, "utf-8");
159328
- resolve9();
163085
+ resolve10();
159329
163086
  }
159330
163087
  });
159331
163088
  });
@@ -159856,7 +163613,7 @@ var SSETransport = class {
159856
163613
  if (!this.config.parseBody) {
159857
163614
  throw new Error("Request body parsing is disabled");
159858
163615
  }
159859
- return new Promise((resolve9, reject) => {
163616
+ return new Promise((resolve10, reject) => {
159860
163617
  const chunks = [];
159861
163618
  let size = 0;
159862
163619
  req.on("data", (chunk) => {
@@ -159875,7 +163632,7 @@ var SSETransport = class {
159875
163632
  return;
159876
163633
  }
159877
163634
  const parsed = safeJsonParse(body);
159878
- resolve9(parsed);
163635
+ resolve10(parsed);
159879
163636
  } catch (error) {
159880
163637
  reject(new Error("Invalid JSON in request body"));
159881
163638
  }
@@ -160578,7 +164335,7 @@ var WebSocketTransport = class extends EventEmitter2 {
160578
164335
  * Handle a manual WebSocket upgrade (for testing or custom servers)
160579
164336
  */
160580
164337
  handleUpgrade(request, socket, head) {
160581
- return new Promise(async (resolve9, reject) => {
164338
+ return new Promise(async (resolve10, reject) => {
160582
164339
  if (this.disposed) {
160583
164340
  socket.write("HTTP/1.1 503 Service Unavailable\r\n\r\n");
160584
164341
  socket.destroy();
@@ -160606,7 +164363,7 @@ var WebSocketTransport = class extends EventEmitter2 {
160606
164363
  };
160607
164364
  this.wsServer.handleUpgrade(request, socket, head, (ws) => {
160608
164365
  this.wsServer.emit("connection", ws, request, upgradeInfo);
160609
- resolve9();
164366
+ resolve10();
160610
164367
  });
160611
164368
  } catch (error) {
160612
164369
  socket.write("HTTP/1.1 500 Internal Server Error\r\n\r\n");
@@ -164316,6 +168073,72 @@ async function handleMemoryShare(params) {
164316
168073
  init_cross_phase_memory();
164317
168074
  init_cross_phase_hooks();
164318
168075
 
168076
+ // src/mcp/qe-tool-bridge.ts
168077
+ init_registry();
168078
+ var ALREADY_REGISTERED = /* @__PURE__ */ new Set([
168079
+ "qe/tests/generate",
168080
+ // → test_generate_enhanced
168081
+ "qe/tests/execute",
168082
+ // → test_execute_parallel
168083
+ "qe/coverage/analyze",
168084
+ // → coverage_analyze_sublinear
168085
+ "qe/quality/evaluate",
168086
+ // → quality_assess
168087
+ "qe/defects/predict",
168088
+ // → defect_predict
168089
+ "qe/requirements/validate",
168090
+ // → requirements_validate
168091
+ "qe/code/analyze",
168092
+ // → code_index
168093
+ "qe/security/scan",
168094
+ // → security_scan_comprehensive
168095
+ "qe/contracts/validate",
168096
+ // → contract_validate
168097
+ "qe/a11y/audit",
168098
+ // → accessibility_test
168099
+ "qe/chaos/inject"
168100
+ // → chaos_test
168101
+ ]);
168102
+ function schemaToParameters(tool) {
168103
+ const schema = tool.getSchema();
168104
+ const requiredSet = new Set(schema.required || []);
168105
+ const params = [];
168106
+ for (const [name, prop] of Object.entries(schema.properties)) {
168107
+ params.push({
168108
+ name,
168109
+ type: prop.type,
168110
+ description: prop.description,
168111
+ required: requiredSet.has(name) || void 0,
168112
+ default: prop.default,
168113
+ enum: prop.enum
168114
+ });
168115
+ }
168116
+ return params;
168117
+ }
168118
+ function registerMissingQETools(registerFn) {
168119
+ let count = 0;
168120
+ for (const tool of QE_TOOLS) {
168121
+ if (ALREADY_REGISTERED.has(tool.name)) {
168122
+ continue;
168123
+ }
168124
+ const entry = {
168125
+ definition: {
168126
+ name: tool.name,
168127
+ description: tool.description,
168128
+ category: "domain",
168129
+ parameters: schemaToParameters(tool)
168130
+ },
168131
+ handler: async (params) => {
168132
+ const result = await tool.invoke(params);
168133
+ return result;
168134
+ }
168135
+ };
168136
+ registerFn(entry);
168137
+ count++;
168138
+ }
168139
+ return count;
168140
+ }
168141
+
164319
168142
  // src/mcp/connection-pool.ts
164320
168143
  import { randomUUID as randomUUID25 } from "crypto";
164321
168144
  var DEFAULT_POOL_CONFIG = {
@@ -164384,8 +168207,8 @@ var ConnectionPoolImpl = class {
164384
168207
  * This is the recommended method when concurrent access is expected
164385
168208
  */
164386
168209
  acquireAsync() {
164387
- return new Promise((resolve9) => {
164388
- this.acquireQueue.push(resolve9);
168210
+ return new Promise((resolve10) => {
168211
+ this.acquireQueue.push(resolve10);
164389
168212
  this.processAcquireQueue();
164390
168213
  });
164391
168214
  }
@@ -164397,10 +168220,10 @@ var ConnectionPoolImpl = class {
164397
168220
  return;
164398
168221
  }
164399
168222
  this.acquireLock = true;
164400
- const resolve9 = this.acquireQueue.shift();
168223
+ const resolve10 = this.acquireQueue.shift();
164401
168224
  try {
164402
168225
  const conn = this.doAcquire();
164403
- resolve9(conn);
168226
+ resolve10(conn);
164404
168227
  } finally {
164405
168228
  this.acquireLock = false;
164406
168229
  if (this.acquireQueue.length > 0) {
@@ -164984,10 +168807,10 @@ var MCPProtocolServer = class {
164984
168807
  this.reconnecting = false;
164985
168808
  const buffered2 = [...this.pendingRequests];
164986
168809
  this.pendingRequests = [];
164987
- for (const { resolve: resolve9, request } of buffered2) {
168810
+ for (const { resolve: resolve10, request } of buffered2) {
164988
168811
  try {
164989
168812
  const result = await this.handleRequest(request);
164990
- resolve9(result);
168813
+ resolve10(result);
164991
168814
  } catch (err4) {
164992
168815
  console.error(`[MCP] Failed to replay buffered request: ${request.method}`);
164993
168816
  }
@@ -165677,7 +169500,8 @@ var MCPProtocolServer = class {
165677
169500
  },
165678
169501
  handler: () => handleAQEHealth()
165679
169502
  });
165680
- console.error(`[MCP] Registered ${this.tools.size} tools`);
169503
+ const bridgedCount = registerMissingQETools((entry) => this.registerTool(entry));
169504
+ console.error(`[MCP] Registered ${this.tools.size} tools (${bridgedCount} via QE bridge)`);
165681
169505
  }
165682
169506
  registerTool(entry) {
165683
169507
  this.tools.set(entry.definition.name, entry);
@@ -165726,7 +169550,7 @@ async function quickStart(config) {
165726
169550
  // src/mcp/http-server.ts
165727
169551
  init_safe_json();
165728
169552
  import { createServer } from "http";
165729
- import { join as join26, dirname as dirname8 } from "path";
169553
+ import { join as join27, dirname as dirname9 } from "path";
165730
169554
  import { fileURLToPath as fileURLToPath3 } from "url";
165731
169555
 
165732
169556
  // src/adapters/a2a/agent-cards/schema.ts
@@ -168804,7 +172628,7 @@ var WebhookService = class extends EventEmitter7 {
168804
172628
  * Sleep for a specified duration
168805
172629
  */
168806
172630
  sleep(ms) {
168807
- return new Promise((resolve9) => setTimeout(resolve9, ms));
172631
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
168808
172632
  }
168809
172633
  };
168810
172634
  function createWebhookService(config = {}) {
@@ -168818,8 +172642,8 @@ init_error_utils();
168818
172642
 
168819
172643
  // src/adapters/a2a/agent-cards/generator.ts
168820
172644
  init_error_utils();
168821
- import { readFile as readFile16, readdir as readdir5, stat as stat5 } from "fs/promises";
168822
- import { join as join25, basename as basename4 } from "path";
172645
+ import { readFile as readFile17, readdir as readdir6, stat as stat5 } from "fs/promises";
172646
+ import { join as join26, basename as basename6 } from "path";
168823
172647
  var DEFAULT_GENERATOR_CONFIG = {
168824
172648
  baseUrl: "http://localhost:8080",
168825
172649
  defaultVersion: "3.0.0",
@@ -169154,8 +172978,8 @@ var AgentCardGenerator = class {
169154
172978
  * Generate an agent card from a markdown file path
169155
172979
  */
169156
172980
  async generateFromFile(filePath) {
169157
- const markdown = await readFile16(filePath, "utf-8");
169158
- const agentId = basename4(filePath, ".md");
172981
+ const markdown = await readFile17(filePath, "utf-8");
172982
+ const agentId = basename6(filePath, ".md");
169159
172983
  return this.generateFromMarkdown(markdown, agentId);
169160
172984
  }
169161
172985
  /**
@@ -169166,9 +172990,9 @@ var AgentCardGenerator = class {
169166
172990
  const cards = /* @__PURE__ */ new Map();
169167
172991
  const errors = /* @__PURE__ */ new Map();
169168
172992
  const processDirectory = async (dirPath) => {
169169
- const entries = await readdir5(dirPath);
172993
+ const entries = await readdir6(dirPath);
169170
172994
  for (const entry of entries) {
169171
- const fullPath = join25(dirPath, entry);
172995
+ const fullPath = join26(dirPath, entry);
169172
172996
  const stats = await stat5(fullPath);
169173
172997
  if (stats.isDirectory() && recursive) {
169174
172998
  await processDirectory(fullPath);
@@ -170627,8 +174451,8 @@ var HTTPServerImpl = class {
170627
174451
  this.skipAgentCardLoading = config.skipAgentCardLoading ?? false;
170628
174452
  this.skipCRDTInit = config.skipCRDTInit ?? false;
170629
174453
  this.enableWebSocket = config.enableWebSocket ?? true;
170630
- const currentDir = dirname8(fileURLToPath3(import.meta.url));
170631
- this.agentMarkdownDir = config.agentMarkdownDir ?? join26(currentDir, "../../assets/agents/v3");
174454
+ const currentDir = dirname9(fileURLToPath3(import.meta.url));
174455
+ this.agentMarkdownDir = config.agentMarkdownDir ?? join27(currentDir, "../../assets/agents/v3");
170632
174456
  this.taskStore = createTaskStore();
170633
174457
  this.taskManager = config.taskManager ?? createTaskManager({
170634
174458
  storeConfig: {}
@@ -170782,7 +174606,7 @@ var HTTPServerImpl = class {
170782
174606
  });
170783
174607
  try {
170784
174608
  this.taskManager.startTask(task.id);
170785
- await new Promise((resolve9) => setTimeout(resolve9, 100));
174609
+ await new Promise((resolve10) => setTimeout(resolve10, 100));
170786
174610
  if (!signal.aborted) {
170787
174611
  this.taskManager.completeTask(task.id, [
170788
174612
  this.taskManager.createTextArtifact(
@@ -171117,7 +174941,7 @@ var HTTPServerImpl = class {
171117
174941
  // Helpers
171118
174942
  // ============================================================================
171119
174943
  async parseBody(req) {
171120
- return new Promise((resolve9, reject) => {
174944
+ return new Promise((resolve10, reject) => {
171121
174945
  const chunks = [];
171122
174946
  let size = 0;
171123
174947
  const maxSize = 1024 * 1024;
@@ -171133,10 +174957,10 @@ var HTTPServerImpl = class {
171133
174957
  try {
171134
174958
  const body = Buffer.concat(chunks).toString("utf-8");
171135
174959
  if (!body) {
171136
- resolve9({});
174960
+ resolve10({});
171137
174961
  return;
171138
174962
  }
171139
- resolve9(safeJsonParse(body));
174963
+ resolve10(safeJsonParse(body));
171140
174964
  } catch (error) {
171141
174965
  reject(new Error("Invalid JSON in request body"));
171142
174966
  }
@@ -171185,7 +175009,7 @@ var HTTPServerImpl = class {
171185
175009
  logger21.warn("Failed to load agent cards", { error });
171186
175010
  }
171187
175011
  }
171188
- return new Promise(async (resolve9, reject) => {
175012
+ return new Promise(async (resolve10, reject) => {
171189
175013
  this.server = createServer((req, res) => {
171190
175014
  this.handleHttpRequest(req, res).catch((error) => {
171191
175015
  logger21.error("Request error", error instanceof Error ? error : new Error(String(error)));
@@ -171230,7 +175054,7 @@ var HTTPServerImpl = class {
171230
175054
  console.error(`[AQE] Hot reload enabled for agent cards`);
171231
175055
  }
171232
175056
  console.error(`[AQE] GET /health - Health check`);
171233
- resolve9();
175057
+ resolve10();
171234
175058
  });
171235
175059
  });
171236
175060
  }
@@ -171250,12 +175074,12 @@ var HTTPServerImpl = class {
171250
175074
  if (!this.running || !this.server) {
171251
175075
  return;
171252
175076
  }
171253
- return new Promise((resolve9) => {
175077
+ return new Promise((resolve10) => {
171254
175078
  this.server.close(() => {
171255
175079
  this.running = false;
171256
175080
  this.server = null;
171257
175081
  console.error("[AQE] HTTP server stopped");
171258
- resolve9();
175082
+ resolve10();
171259
175083
  });
171260
175084
  this.sseTransport.dispose();
171261
175085
  if (this.webSocketTransport) {
@@ -171367,7 +175191,7 @@ async function createDefaultMemoryBackend(autoInitialize = true) {
171367
175191
  }
171368
175192
 
171369
175193
  // src/init/token-bootstrap.ts
171370
- var DEFAULT_CONFIG70 = {
175194
+ var DEFAULT_CONFIG75 = {
171371
175195
  enableOptimization: true,
171372
175196
  enablePersistence: true,
171373
175197
  storagePath: process.env.AQE_STORAGE_PATH ?? ".aqe",
@@ -171381,7 +175205,7 @@ async function bootstrapTokenTracking(config) {
171381
175205
  if (initialized) {
171382
175206
  return;
171383
175207
  }
171384
- const cfg = { ...DEFAULT_CONFIG70, ...config };
175208
+ const cfg = { ...DEFAULT_CONFIG75, ...config };
171385
175209
  if (cfg.verbose) {
171386
175210
  console.log("[TokenBootstrap] Initializing token tracking...");
171387
175211
  }
@@ -171920,7 +175744,7 @@ function createTestOutputObserver(customSignatures) {
171920
175744
 
171921
175745
  // src/strange-loop/infra-healing/recovery-playbook.ts
171922
175746
  import * as fs25 from "node:fs/promises";
171923
- import { parse as parseYaml2 } from "yaml";
175747
+ import { parse as parseYaml3 } from "yaml";
171924
175748
  var RecoveryPlaybook = class {
171925
175749
  config = null;
171926
175750
  variables;
@@ -171938,7 +175762,7 @@ var RecoveryPlaybook = class {
171938
175762
  * Load playbook from a YAML string (for testing or inline config).
171939
175763
  */
171940
175764
  loadFromString(yamlContent) {
171941
- const raw = parseYaml2(yamlContent);
175765
+ const raw = parseYaml3(yamlContent);
171942
175766
  this.config = this.parsePlaybook(raw);
171943
175767
  }
171944
175768
  /**
@@ -172126,7 +175950,7 @@ var ShellCommandRunner = class {
172126
175950
  async run(command, timeoutMs) {
172127
175951
  const { execFile: execFile3 } = await import("node:child_process");
172128
175952
  const startTime = Date.now();
172129
- return new Promise((resolve9) => {
175953
+ return new Promise((resolve10) => {
172130
175954
  const child = execFile3(
172131
175955
  "/bin/sh",
172132
175956
  ["-c", command],
@@ -172136,7 +175960,7 @@ var ShellCommandRunner = class {
172136
175960
  const timedOut = (error?.message?.includes("TIMEOUT") || error?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") ?? false;
172137
175961
  const errWithCode = error;
172138
175962
  const exitCode = error ? typeof errWithCode?.code === "number" ? errWithCode.code : 1 : 0;
172139
- resolve9({
175963
+ resolve10({
172140
175964
  exitCode,
172141
175965
  stdout: stdout ?? "",
172142
175966
  stderr: stderr ?? "",
@@ -172146,7 +175970,7 @@ var ShellCommandRunner = class {
172146
175970
  }
172147
175971
  );
172148
175972
  child.on("error", () => {
172149
- resolve9({
175973
+ resolve10({
172150
175974
  exitCode: 1,
172151
175975
  stdout: "",
172152
175976
  stderr: "Process execution error",
@@ -172301,7 +176125,7 @@ var InfraActionExecutor = class {
172301
176125
  this.stats.byService[serviceName][field]++;
172302
176126
  }
172303
176127
  sleep(ms) {
172304
- return new Promise((resolve9) => setTimeout(resolve9, ms));
176128
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
172305
176129
  }
172306
176130
  };
172307
176131
  function createInfraActionExecutor(runner, playbook, lock) {
@@ -172515,7 +176339,7 @@ init_global_instance();
172515
176339
 
172516
176340
  // src/mcp/entry.ts
172517
176341
  import { readFileSync as readFileSync16 } from "node:fs";
172518
- import { resolve as resolve8, dirname as dirname9 } from "node:path";
176342
+ import { resolve as resolve9, dirname as dirname10 } from "node:path";
172519
176343
  import { fileURLToPath as fileURLToPath4 } from "node:url";
172520
176344
  var require2 = createRequire11(import.meta.url);
172521
176345
  var pkg = require2("../../package.json");
@@ -172587,8 +176411,8 @@ async function main() {
172587
176411
  originalStderrWrite("[MCP] Initializing infra-healing...\n");
172588
176412
  try {
172589
176413
  const __filename2 = fileURLToPath4(import.meta.url);
172590
- const __dirname2 = dirname9(__filename2);
172591
- const playbookPath = resolve8(__dirname2, "../strange-loop/infra-healing/default-playbook.yaml");
176414
+ const __dirname2 = dirname10(__filename2);
176415
+ const playbookPath = resolve9(__dirname2, "../strange-loop/infra-healing/default-playbook.yaml");
172592
176416
  let playbookContent;
172593
176417
  try {
172594
176418
  playbookContent = readFileSync16(playbookPath, "utf-8");