@yasserkhanorg/e2e-agents 1.8.5 → 1.10.0

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 (274) hide show
  1. package/README.md +95 -8
  2. package/dist/adapters/cypress.d.ts +10 -0
  3. package/dist/adapters/cypress.d.ts.map +1 -0
  4. package/dist/adapters/cypress.js +86 -0
  5. package/dist/adapters/framework_adapter.d.ts +41 -0
  6. package/dist/adapters/framework_adapter.d.ts.map +1 -0
  7. package/dist/adapters/framework_adapter.js +152 -0
  8. package/dist/adapters/playwright.d.ts +10 -0
  9. package/dist/adapters/playwright.d.ts.map +1 -0
  10. package/dist/adapters/playwright.js +86 -0
  11. package/dist/adapters/pytest.d.ts +10 -0
  12. package/dist/adapters/pytest.d.ts.map +1 -0
  13. package/dist/adapters/pytest.js +96 -0
  14. package/dist/adapters/supertest.d.ts +12 -0
  15. package/dist/adapters/supertest.d.ts.map +1 -0
  16. package/dist/adapters/supertest.js +85 -0
  17. package/dist/agent/config.d.ts +1 -1
  18. package/dist/agent/config.d.ts.map +1 -1
  19. package/dist/agent/git.d.ts +1 -0
  20. package/dist/agent/git.d.ts.map +1 -1
  21. package/dist/agent/git.js +3 -0
  22. package/dist/agentic/fix_loop.d.ts.map +1 -1
  23. package/dist/agentic/fix_loop.js +5 -4
  24. package/dist/agentic/runner.d.ts +2 -0
  25. package/dist/agentic/runner.d.ts.map +1 -1
  26. package/dist/agentic/runner.js +15 -12
  27. package/dist/agents/cross-impact.d.ts.map +1 -1
  28. package/dist/agents/cross-impact.js +6 -1
  29. package/dist/agents/executor.d.ts.map +1 -1
  30. package/dist/agents/executor.js +6 -1
  31. package/dist/agents/strategist.d.ts.map +1 -1
  32. package/dist/agents/strategist.js +6 -1
  33. package/dist/agents/test-designer.d.ts.map +1 -1
  34. package/dist/agents/test-designer.js +6 -1
  35. package/dist/anthropic_provider.d.ts.map +1 -1
  36. package/dist/anthropic_provider.js +1 -0
  37. package/dist/base_provider.d.ts +56 -0
  38. package/dist/base_provider.d.ts.map +1 -1
  39. package/dist/base_provider.js +123 -1
  40. package/dist/budget_ledger.d.ts +28 -0
  41. package/dist/budget_ledger.d.ts.map +1 -0
  42. package/dist/budget_ledger.js +62 -0
  43. package/dist/cache/cached_provider.d.ts +45 -0
  44. package/dist/cache/cached_provider.d.ts.map +1 -0
  45. package/dist/cache/cached_provider.js +88 -0
  46. package/dist/cache/response_cache.d.ts +79 -0
  47. package/dist/cache/response_cache.d.ts.map +1 -0
  48. package/dist/cache/response_cache.js +177 -0
  49. package/dist/cli/commands/bootstrap.d.ts +3 -0
  50. package/dist/cli/commands/bootstrap.d.ts.map +1 -0
  51. package/dist/cli/commands/bootstrap.js +109 -0
  52. package/dist/cli/commands/cost_report.d.ts +3 -0
  53. package/dist/cli/commands/cost_report.d.ts.map +1 -0
  54. package/dist/cli/commands/cost_report.js +115 -0
  55. package/dist/cli/commands/crew.d.ts.map +1 -1
  56. package/dist/cli/commands/crew.js +118 -1
  57. package/dist/cli/commands/gate.d.ts +3 -0
  58. package/dist/cli/commands/gate.d.ts.map +1 -0
  59. package/dist/cli/commands/gate.js +86 -0
  60. package/dist/cli/commands/init.d.ts.map +1 -1
  61. package/dist/cli/commands/init.js +7 -62
  62. package/dist/cli/commands/train.d.ts.map +1 -1
  63. package/dist/cli/commands/train.js +16 -21
  64. package/dist/cli/defaults.d.ts +35 -0
  65. package/dist/cli/defaults.d.ts.map +1 -0
  66. package/dist/cli/defaults.js +125 -0
  67. package/dist/cli/errors.d.ts +27 -0
  68. package/dist/cli/errors.d.ts.map +1 -0
  69. package/dist/cli/errors.js +57 -0
  70. package/dist/cli/parse_args.d.ts.map +1 -1
  71. package/dist/cli/parse_args.js +24 -2
  72. package/dist/cli/types.d.ts +7 -1
  73. package/dist/cli/types.d.ts.map +1 -1
  74. package/dist/cli.js +47 -2
  75. package/dist/crew/context.d.ts +15 -0
  76. package/dist/crew/context.d.ts.map +1 -1
  77. package/dist/crew/orchestrator.d.ts +14 -0
  78. package/dist/crew/orchestrator.d.ts.map +1 -1
  79. package/dist/crew/orchestrator.js +162 -4
  80. package/dist/crew/protocol.d.ts +13 -0
  81. package/dist/crew/protocol.d.ts.map +1 -1
  82. package/dist/crew/provider.d.ts +15 -1
  83. package/dist/crew/provider.d.ts.map +1 -1
  84. package/dist/crew/provider.js +24 -4
  85. package/dist/custom_provider.d.ts.map +1 -1
  86. package/dist/custom_provider.js +1 -0
  87. package/dist/engine/diff_loader.d.ts.map +1 -1
  88. package/dist/engine/diff_loader.js +3 -14
  89. package/dist/engine/impact_engine.d.ts.map +1 -1
  90. package/dist/engine/impact_engine.js +9 -23
  91. package/dist/esm/adapters/cypress.js +49 -0
  92. package/dist/esm/adapters/framework_adapter.js +114 -0
  93. package/dist/esm/adapters/playwright.js +49 -0
  94. package/dist/esm/adapters/pytest.js +59 -0
  95. package/dist/esm/adapters/supertest.js +48 -0
  96. package/dist/esm/agent/git.js +3 -1
  97. package/dist/esm/agentic/fix_loop.js +5 -4
  98. package/dist/esm/agentic/runner.js +15 -12
  99. package/dist/esm/agents/cross-impact.js +6 -1
  100. package/dist/esm/agents/executor.js +6 -1
  101. package/dist/esm/agents/strategist.js +6 -1
  102. package/dist/esm/agents/test-designer.js +6 -1
  103. package/dist/esm/anthropic_provider.js +1 -0
  104. package/dist/esm/base_provider.js +121 -0
  105. package/dist/esm/budget_ledger.js +58 -0
  106. package/dist/esm/cache/cached_provider.js +82 -0
  107. package/dist/esm/cache/response_cache.js +140 -0
  108. package/dist/esm/cli/commands/bootstrap.js +106 -0
  109. package/dist/esm/cli/commands/cost_report.js +112 -0
  110. package/dist/esm/cli/commands/crew.js +118 -1
  111. package/dist/esm/cli/commands/gate.js +83 -0
  112. package/dist/esm/cli/commands/init.js +3 -58
  113. package/dist/esm/cli/commands/train.js +16 -21
  114. package/dist/esm/cli/defaults.js +118 -0
  115. package/dist/esm/cli/errors.js +52 -0
  116. package/dist/esm/cli/parse_args.js +24 -2
  117. package/dist/esm/cli.js +47 -2
  118. package/dist/esm/crew/orchestrator.js +162 -4
  119. package/dist/esm/crew/provider.js +24 -4
  120. package/dist/esm/custom_provider.js +1 -0
  121. package/dist/esm/engine/diff_loader.js +1 -12
  122. package/dist/esm/engine/impact_engine.js +9 -23
  123. package/dist/esm/index.js +21 -0
  124. package/dist/esm/knowledge/api_surface.js +265 -34
  125. package/dist/esm/knowledge/cluster_utils.js +60 -0
  126. package/dist/esm/knowledge/failure_history.js +121 -0
  127. package/dist/esm/knowledge/kg_bridge.js +381 -0
  128. package/dist/esm/knowledge/kg_types.js +3 -0
  129. package/dist/esm/knowledge/route_families.js +119 -0
  130. package/dist/esm/mcp-server.js +2 -4
  131. package/dist/esm/metrics/prometheus.js +149 -0
  132. package/dist/esm/model_router.js +59 -0
  133. package/dist/esm/ollama_provider.js +1 -0
  134. package/dist/esm/openai_provider.js +1 -0
  135. package/dist/esm/pipeline/orchestrator.js +6 -12
  136. package/dist/esm/pipeline/stage0_preprocess.js +12 -19
  137. package/dist/esm/pipeline/stage1_impact.js +19 -3
  138. package/dist/esm/pipeline/stage2_coverage.js +29 -7
  139. package/dist/esm/pipeline/stage3_generation.js +21 -1
  140. package/dist/esm/progress.js +112 -0
  141. package/dist/esm/prompts/coverage.js +17 -24
  142. package/dist/esm/prompts/cross-impact.js +3 -21
  143. package/dist/esm/prompts/generation.js +201 -45
  144. package/dist/esm/prompts/generation_profile.js +147 -0
  145. package/dist/esm/prompts/heal.js +33 -15
  146. package/dist/esm/prompts/impact.js +3 -22
  147. package/dist/esm/prompts/json_extract.js +36 -0
  148. package/dist/esm/prompts/strategist.js +2 -20
  149. package/dist/esm/prompts/test-designer.js +6 -21
  150. package/dist/esm/provider_factory.js +6 -4
  151. package/dist/esm/reporters/junit.js +86 -0
  152. package/dist/esm/reporters/reporter.js +3 -0
  153. package/dist/esm/reporters/sarif.js +131 -0
  154. package/dist/esm/resilience/circuit_breaker.js +78 -0
  155. package/dist/esm/resilience/retry.js +56 -0
  156. package/dist/esm/sanitize.js +66 -0
  157. package/dist/esm/training/kg_scanner.js +115 -0
  158. package/dist/esm/training/scanner.js +27 -34
  159. package/dist/esm/validation/guardrails.js +5 -0
  160. package/dist/esm/version.js +33 -0
  161. package/dist/index.d.ts +21 -1
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +45 -1
  164. package/dist/knowledge/api_surface.d.ts +12 -0
  165. package/dist/knowledge/api_surface.d.ts.map +1 -1
  166. package/dist/knowledge/api_surface.js +268 -34
  167. package/dist/knowledge/cluster_utils.d.ts +28 -0
  168. package/dist/knowledge/cluster_utils.d.ts.map +1 -0
  169. package/dist/knowledge/cluster_utils.js +67 -0
  170. package/dist/knowledge/failure_history.d.ts +39 -0
  171. package/dist/knowledge/failure_history.d.ts.map +1 -0
  172. package/dist/knowledge/failure_history.js +128 -0
  173. package/dist/knowledge/kg_bridge.d.ts +31 -0
  174. package/dist/knowledge/kg_bridge.d.ts.map +1 -0
  175. package/dist/knowledge/kg_bridge.js +388 -0
  176. package/dist/knowledge/kg_types.d.ts +75 -0
  177. package/dist/knowledge/kg_types.d.ts.map +1 -0
  178. package/dist/knowledge/kg_types.js +4 -0
  179. package/dist/knowledge/route_families.d.ts +29 -0
  180. package/dist/knowledge/route_families.d.ts.map +1 -1
  181. package/dist/knowledge/route_families.js +122 -0
  182. package/dist/mcp-server.d.ts.map +1 -1
  183. package/dist/mcp-server.js +2 -4
  184. package/dist/metrics/prometheus.d.ts +37 -0
  185. package/dist/metrics/prometheus.d.ts.map +1 -0
  186. package/dist/metrics/prometheus.js +153 -0
  187. package/dist/model_router.d.ts +28 -0
  188. package/dist/model_router.d.ts.map +1 -0
  189. package/dist/model_router.js +63 -0
  190. package/dist/ollama_provider.d.ts.map +1 -1
  191. package/dist/ollama_provider.js +1 -0
  192. package/dist/openai_provider.d.ts.map +1 -1
  193. package/dist/openai_provider.js +1 -0
  194. package/dist/pipeline/orchestrator.d.ts +2 -0
  195. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  196. package/dist/pipeline/orchestrator.js +6 -12
  197. package/dist/pipeline/stage0_preprocess.d.ts.map +1 -1
  198. package/dist/pipeline/stage0_preprocess.js +11 -18
  199. package/dist/pipeline/stage1_impact.d.ts +1 -1
  200. package/dist/pipeline/stage1_impact.d.ts.map +1 -1
  201. package/dist/pipeline/stage1_impact.js +18 -2
  202. package/dist/pipeline/stage2_coverage.d.ts +2 -0
  203. package/dist/pipeline/stage2_coverage.d.ts.map +1 -1
  204. package/dist/pipeline/stage2_coverage.js +29 -7
  205. package/dist/pipeline/stage3_generation.d.ts +2 -0
  206. package/dist/pipeline/stage3_generation.d.ts.map +1 -1
  207. package/dist/pipeline/stage3_generation.js +21 -1
  208. package/dist/pipeline/stage4_heal.d.ts +2 -0
  209. package/dist/pipeline/stage4_heal.d.ts.map +1 -1
  210. package/dist/progress.d.ts +22 -0
  211. package/dist/progress.d.ts.map +1 -0
  212. package/dist/progress.js +116 -0
  213. package/dist/prompts/coverage.d.ts +2 -0
  214. package/dist/prompts/coverage.d.ts.map +1 -1
  215. package/dist/prompts/coverage.js +17 -24
  216. package/dist/prompts/cross-impact.d.ts +1 -0
  217. package/dist/prompts/cross-impact.d.ts.map +1 -1
  218. package/dist/prompts/cross-impact.js +3 -21
  219. package/dist/prompts/generation.d.ts +4 -2
  220. package/dist/prompts/generation.d.ts.map +1 -1
  221. package/dist/prompts/generation.js +201 -45
  222. package/dist/prompts/generation_profile.d.ts +29 -0
  223. package/dist/prompts/generation_profile.d.ts.map +1 -0
  224. package/dist/prompts/generation_profile.js +151 -0
  225. package/dist/prompts/heal.d.ts +3 -1
  226. package/dist/prompts/heal.d.ts.map +1 -1
  227. package/dist/prompts/heal.js +33 -15
  228. package/dist/prompts/impact.d.ts +1 -0
  229. package/dist/prompts/impact.d.ts.map +1 -1
  230. package/dist/prompts/impact.js +3 -22
  231. package/dist/prompts/json_extract.d.ts +14 -0
  232. package/dist/prompts/json_extract.d.ts.map +1 -0
  233. package/dist/prompts/json_extract.js +39 -0
  234. package/dist/prompts/strategist.d.ts.map +1 -1
  235. package/dist/prompts/strategist.js +2 -20
  236. package/dist/prompts/test-designer.d.ts +2 -0
  237. package/dist/prompts/test-designer.d.ts.map +1 -1
  238. package/dist/prompts/test-designer.js +6 -21
  239. package/dist/provider_factory.d.ts.map +1 -1
  240. package/dist/provider_factory.js +6 -4
  241. package/dist/reporters/junit.d.ts +6 -0
  242. package/dist/reporters/junit.d.ts.map +1 -0
  243. package/dist/reporters/junit.js +89 -0
  244. package/dist/reporters/reporter.d.ts +42 -0
  245. package/dist/reporters/reporter.d.ts.map +1 -0
  246. package/dist/reporters/reporter.js +4 -0
  247. package/dist/reporters/sarif.d.ts +7 -0
  248. package/dist/reporters/sarif.d.ts.map +1 -0
  249. package/dist/reporters/sarif.js +134 -0
  250. package/dist/resilience/circuit_breaker.d.ts +36 -0
  251. package/dist/resilience/circuit_breaker.d.ts.map +1 -0
  252. package/dist/resilience/circuit_breaker.js +82 -0
  253. package/dist/resilience/retry.d.ts +11 -0
  254. package/dist/resilience/retry.d.ts.map +1 -0
  255. package/dist/resilience/retry.js +59 -0
  256. package/dist/sanitize.d.ts +15 -0
  257. package/dist/sanitize.d.ts.map +1 -0
  258. package/dist/sanitize.js +71 -0
  259. package/dist/training/kg_scanner.d.ts +13 -0
  260. package/dist/training/kg_scanner.d.ts.map +1 -0
  261. package/dist/training/kg_scanner.js +118 -0
  262. package/dist/training/scanner.d.ts +7 -2
  263. package/dist/training/scanner.d.ts.map +1 -1
  264. package/dist/training/scanner.js +27 -34
  265. package/dist/validation/guardrails.d.ts +2 -0
  266. package/dist/validation/guardrails.d.ts.map +1 -1
  267. package/dist/validation/guardrails.js +5 -0
  268. package/dist/validation/output_schema.d.ts +3 -0
  269. package/dist/validation/output_schema.d.ts.map +1 -1
  270. package/dist/version.d.ts +6 -0
  271. package/dist/version.d.ts.map +1 -0
  272. package/dist/version.js +36 -0
  273. package/package.json +7 -2
  274. package/schemas/route-families.schema.json +31 -1
@@ -4,6 +4,7 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.buildImpactPrompt = buildImpactPrompt;
6
6
  exports.parseImpactResponse = parseImpactResponse;
7
+ const json_extract_js_1 = require("./json_extract.js");
7
8
  const spec_index_js_1 = require("../knowledge/spec_index.js");
8
9
  const api_surface_js_1 = require("../knowledge/api_surface.js");
9
10
  function buildImpactPrompt(ctx) {
@@ -27,7 +28,7 @@ function buildImpactPrompt(ctx) {
27
28
  })
28
29
  .join('\n\n');
29
30
  return [
30
- 'You are analyzing code changes in Mattermost to identify impacted user-facing flows.',
31
+ `You are analyzing code changes in ${ctx.projectName || 'Mattermost'} to identify impacted user-facing flows.`,
31
32
  '',
32
33
  `ROUTE FAMILY: ${ctx.family.id}`,
33
34
  `ROUTES: ${familyRoutes}`,
@@ -62,25 +63,5 @@ function buildImpactPrompt(ctx) {
62
63
  ].filter(Boolean).join('\n');
63
64
  }
64
65
  function parseImpactResponse(text) {
65
- // Try to extract JSON from the response
66
- const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
67
- const candidates = fenced ? [fenced[1], text] : [text];
68
- for (const candidate of candidates) {
69
- const start = candidate.indexOf('{');
70
- const end = candidate.lastIndexOf('}');
71
- if (start < 0 || end <= start) {
72
- continue;
73
- }
74
- const raw = candidate.slice(start, end + 1);
75
- try {
76
- const parsed = JSON.parse(raw);
77
- if (parsed && Array.isArray(parsed.flows)) {
78
- return parsed;
79
- }
80
- }
81
- catch {
82
- continue;
83
- }
84
- }
85
- return null;
66
+ return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.flows));
86
67
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared JSON extraction from LLM text responses.
3
+ * Handles fenced code blocks, bare JSON, and partial text.
4
+ */
5
+ /**
6
+ * Extract and parse JSON from LLM response text.
7
+ * Tries fenced code blocks first, then raw text.
8
+ * Returns null if no valid JSON found.
9
+ *
10
+ * @param text - Raw LLM response text
11
+ * @param validate - Predicate to check if parsed object has the expected shape
12
+ */
13
+ export declare function extractJsonFromResponse<T>(text: string, validate: (obj: unknown) => obj is T): T | null;
14
+ //# sourceMappingURL=json_extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_extract.d.ts","sourceRoot":"","sources":["../../src/prompts/json_extract.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAqBvG"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
+ // See LICENSE.txt for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.extractJsonFromResponse = extractJsonFromResponse;
6
+ /**
7
+ * Shared JSON extraction from LLM text responses.
8
+ * Handles fenced code blocks, bare JSON, and partial text.
9
+ */
10
+ /**
11
+ * Extract and parse JSON from LLM response text.
12
+ * Tries fenced code blocks first, then raw text.
13
+ * Returns null if no valid JSON found.
14
+ *
15
+ * @param text - Raw LLM response text
16
+ * @param validate - Predicate to check if parsed object has the expected shape
17
+ */
18
+ function extractJsonFromResponse(text, validate) {
19
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
20
+ const candidates = fenced ? [fenced[1], text] : [text];
21
+ for (const candidate of candidates) {
22
+ const start = candidate.indexOf('{');
23
+ const end = candidate.lastIndexOf('}');
24
+ if (start < 0 || end <= start) {
25
+ continue;
26
+ }
27
+ const raw = candidate.slice(start, end + 1);
28
+ try {
29
+ const parsed = JSON.parse(raw);
30
+ if (validate(parsed)) {
31
+ return parsed;
32
+ }
33
+ }
34
+ catch {
35
+ continue;
36
+ }
37
+ }
38
+ return null;
39
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"strategist.d.ts","sourceRoot":"","sources":["../../src/prompts/strategist.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,WAAW,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAGjF,MAAM,WAAW,uBAAuB;IACpC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,cAAc,EAAE,CAAC;CACrC;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CA4D1E;AAED,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;QACtC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;QACzE,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;KAChE,CAAC,CAAC;CACN;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAqBpF"}
1
+ {"version":3,"file":"strategist.d.ts","sourceRoot":"","sources":["../../src/prompts/strategist.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,WAAW,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAIjF,MAAM,WAAW,uBAAuB;IACpC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,cAAc,EAAE,CAAC;CACrC;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CA4D1E;AAED,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;QACtC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;QACzE,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;KAChE,CAAC,CAAC;CACN;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAMpF"}
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.buildStrategistPrompt = buildStrategistPrompt;
6
6
  exports.parseStrategistResponse = parseStrategistResponse;
7
7
  const sanitize_js_1 = require("../crew/sanitize.js");
8
+ const json_extract_js_1 = require("./json_extract.js");
8
9
  function buildStrategistPrompt(ctx) {
9
10
  const flowsBlock = ctx.impactedFlows
10
11
  .map((f) => {
@@ -60,24 +61,5 @@ function buildStrategistPrompt(ctx) {
60
61
  ].join('\n');
61
62
  }
62
63
  function parseStrategistResponse(text) {
63
- const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
64
- const candidates = fenced ? [fenced[1], text] : [text];
65
- for (const candidate of candidates) {
66
- const start = candidate.indexOf('{');
67
- const end = candidate.lastIndexOf('}');
68
- if (start < 0 || end <= start) {
69
- continue;
70
- }
71
- const raw = candidate.slice(start, end + 1);
72
- try {
73
- const parsed = JSON.parse(raw);
74
- if (parsed && Array.isArray(parsed.strategy)) {
75
- return parsed;
76
- }
77
- }
78
- catch {
79
- continue;
80
- }
81
- }
82
- return null;
64
+ return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.strategy));
83
65
  }
@@ -6,12 +6,14 @@ import type { FlowDecision } from '../validation/output_schema.js';
6
6
  import { type ApiSurfaceCatalog } from '../knowledge/api_surface.js';
7
7
  import type { SpecEntry } from '../knowledge/spec_index.js';
8
8
  import type { StrategyEntry, CrossImpact } from '../crew/types.js';
9
+ import type { GenerationProfile } from './generation_profile.js';
9
10
  export interface TestDesignerPromptContext {
10
11
  flow: FlowDecision;
11
12
  strategy: StrategyEntry;
12
13
  apiSurface: ApiSurfaceCatalog;
13
14
  existingSpecs: SpecEntry[];
14
15
  crossImpacts: CrossImpact[];
16
+ profile?: GenerationProfile;
15
17
  }
16
18
  export declare function buildTestDesignerPrompt(ctx: TestDesignerPromptContext): string;
17
19
  export interface TestDesignerAgentResponse {
@@ -1 +1 @@
1
- {"version":3,"file":"test-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/test-designer.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAA4B,KAAK,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAC9F,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAa,MAAM,kBAAkB,CAAC;AAG7E,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,yBAAyB,GAAG,MAAM,CAuF9E;AAED,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,YAAY,GAAG,eAAe,GAAG,aAAa,GAAG,MAAM,CAAC;YAC7J,aAAa,EAAE,MAAM,EAAE,CAAC;YACxB,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,eAAe,EAAE,MAAM,CAAC;YACxB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;YACtC,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC,CAAC;KACN,CAAC;CACL;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,GAAG,IAAI,CAqBxF"}
1
+ {"version":3,"file":"test-designer.d.ts","sourceRoot":"","sources":["../../src/prompts/test-designer.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAA4B,KAAK,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAC9F,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAa,MAAM,kBAAkB,CAAC;AAE7E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,yBAAyB,GAAG,MAAM,CAuF9E;AAED,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,YAAY,GAAG,eAAe,GAAG,aAAa,GAAG,MAAM,CAAC;YAC7J,aAAa,EAAE,MAAM,EAAE,CAAC;YACxB,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,eAAe,EAAE,MAAM,CAAC;YACxB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;YACtC,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC,CAAC;KACN,CAAC;CACL;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,GAAG,IAAI,CAQxF"}
@@ -4,6 +4,7 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.buildTestDesignerPrompt = buildTestDesignerPrompt;
6
6
  exports.parseTestDesignerResponse = parseTestDesignerResponse;
7
+ const json_extract_js_1 = require("./json_extract.js");
7
8
  const api_surface_js_1 = require("../knowledge/api_surface.js");
8
9
  const sanitize_js_1 = require("../crew/sanitize.js");
9
10
  function buildTestDesignerPrompt(ctx) {
@@ -28,7 +29,7 @@ function buildTestDesignerPrompt(ctx) {
28
29
  : 'None detected.';
29
30
  const categories = ctx.strategy.testCategories.join(', ');
30
31
  return [
31
- 'You are a senior QA engineer designing comprehensive test cases for a Mattermost user flow.',
32
+ `You are a senior QA engineer designing comprehensive test cases for a ${ctx.profile?.projectName || 'Mattermost'} user flow.`,
32
33
  '',
33
34
  `FLOW: ${ctx.flow.flowName}`,
34
35
  `Flow ID: ${ctx.flow.flowId}`,
@@ -88,24 +89,8 @@ function buildTestDesignerPrompt(ctx) {
88
89
  ].join('\n');
89
90
  }
90
91
  function parseTestDesignerResponse(text) {
91
- const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
92
- const candidates = fenced ? [fenced[1], text] : [text];
93
- for (const candidate of candidates) {
94
- const start = candidate.indexOf('{');
95
- const end = candidate.lastIndexOf('}');
96
- if (start < 0 || end <= start) {
97
- continue;
98
- }
99
- const raw = candidate.slice(start, end + 1);
100
- try {
101
- const parsed = JSON.parse(raw);
102
- if (parsed?.testDesign?.testCases && Array.isArray(parsed.testDesign.testCases)) {
103
- return parsed;
104
- }
105
- }
106
- catch {
107
- continue;
108
- }
109
- }
110
- return null;
92
+ return (0, json_extract_js_1.extractJsonFromResponse)(text, (obj) => {
93
+ const r = obj;
94
+ return r?.testDesign?.testCases != null && Array.isArray(r.testDesign.testCases);
95
+ });
111
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider_factory.d.ts","sourceRoot":"","sources":["../src/provider_factory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAKR,WAAW,EAIX,cAAc,EAEjB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBAAkB;IAC3B;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW;IAmBlD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAWtD;;;;;;;;;OASG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC;IAyElD;;;OAGG;WACU,oBAAoB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASpF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;CAkC/D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;CACrF;AA+ID;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC;IACxE,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC,CAsCD"}
1
+ {"version":3,"file":"provider_factory.d.ts","sourceRoot":"","sources":["../src/provider_factory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAKR,WAAW,EAIX,cAAc,EAEjB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBAAkB;IAC3B;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW;IAmBlD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAWtD;;;;;;;;;OASG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC;IAyElD;;;OAGG;WACU,oBAAoB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASpF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW;CAkC/D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,cAAc,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;CACrF;AAgJD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC;IACxE,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC,CAsCD"}
@@ -268,15 +268,17 @@ class HybridProvider {
268
268
  const primaryStats = this.primary.getUsageStats();
269
269
  const fallbackStats = this.fallback.getUsageStats();
270
270
  // Combine stats
271
+ const totalRequests = primaryStats.requestCount + fallbackStats.requestCount;
271
272
  return {
272
- requestCount: primaryStats.requestCount + fallbackStats.requestCount,
273
+ requestCount: totalRequests,
273
274
  totalInputTokens: primaryStats.totalInputTokens + fallbackStats.totalInputTokens,
274
275
  totalOutputTokens: primaryStats.totalOutputTokens + fallbackStats.totalOutputTokens,
275
276
  totalTokens: primaryStats.totalTokens + fallbackStats.totalTokens,
276
277
  totalCost: primaryStats.totalCost + fallbackStats.totalCost,
277
- averageResponseTimeMs: (primaryStats.averageResponseTimeMs * primaryStats.requestCount +
278
- fallbackStats.averageResponseTimeMs * fallbackStats.requestCount) /
279
- (primaryStats.requestCount + fallbackStats.requestCount),
278
+ averageResponseTimeMs: totalRequests > 0
279
+ ? (primaryStats.averageResponseTimeMs * primaryStats.requestCount +
280
+ fallbackStats.averageResponseTimeMs * fallbackStats.requestCount) / totalRequests
281
+ : 0,
280
282
  failedRequests: primaryStats.failedRequests + fallbackStats.failedRequests,
281
283
  startTime: new Date(Math.min(primaryStats.startTime.getTime(), fallbackStats.startTime.getTime())),
282
284
  lastUpdated: new Date(Math.max(primaryStats.lastUpdated.getTime(), fallbackStats.lastUpdated.getTime())),
@@ -0,0 +1,6 @@
1
+ /**
2
+ * JUnit XML reporter — maps crew results to JUnit format for Jenkins/GitLab CI.
3
+ */
4
+ import type { Reporter } from './reporter.js';
5
+ export declare const junitReporter: Reporter;
6
+ //# sourceMappingURL=junit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"junit.d.ts","sourceRoot":"","sources":["../../src/reporters/junit.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,OAAO,KAAK,EAAc,QAAQ,EAAC,MAAM,eAAe,CAAC;AA6BzD,eAAO,MAAM,aAAa,EAAE,QAyE3B,CAAC"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
+ // See LICENSE.txt for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.junitReporter = void 0;
6
+ function escapeXml(str) {
7
+ return str
8
+ .replace(/&/g, '&amp;')
9
+ .replace(/</g, '&lt;')
10
+ .replace(/>/g, '&gt;')
11
+ .replace(/"/g, '&quot;')
12
+ .replace(/'/g, '&apos;');
13
+ }
14
+ function buildTestCase(tc, flowName) {
15
+ const className = escapeXml(flowName.replace(/\s+/g, '.'));
16
+ const testName = escapeXml(tc.name);
17
+ return ` <testcase classname="${className}" name="${testName}" status="${escapeXml(tc.priority)}">\n` +
18
+ ` <properties>\n` +
19
+ ` <property name="type" value="${escapeXml(tc.type)}" />\n` +
20
+ ` <property name="priority" value="${escapeXml(tc.priority)}" />\n` +
21
+ ` </properties>\n` +
22
+ ` </testcase>`;
23
+ }
24
+ function buildFailureCase(finding) {
25
+ const name = escapeXml(finding.title);
26
+ return ` <testcase classname="findings" name="${name}">\n` +
27
+ ` <failure message="${escapeXml(finding.title)}" type="${escapeXml(finding.severity)}">${escapeXml(finding.description)}</failure>\n` +
28
+ ` </testcase>`;
29
+ }
30
+ exports.junitReporter = {
31
+ name: 'junit',
32
+ extension: '.xml',
33
+ format(results) {
34
+ const suites = [];
35
+ // Build a lookup from flowName -> test cases
36
+ const designsByFlow = new Map();
37
+ for (const design of results.testDesigns) {
38
+ designsByFlow.set(design.flowName, design.testCases);
39
+ }
40
+ // High-severity findings as failure cases
41
+ const highFindings = results.findings.filter((f) => f.severity === 'high');
42
+ // Each strategy entry becomes a test suite
43
+ for (const entry of results.strategyEntries) {
44
+ const testCases = designsByFlow.get(entry.flowName) ?? [];
45
+ const failures = highFindings.filter((f) => f.title.includes(entry.flowName));
46
+ const totalTests = testCases.length + failures.length;
47
+ const casesXml = testCases.map((tc) => buildTestCase(tc, entry.flowName)).join('\n');
48
+ const failuresXml = failures.map((f) => buildFailureCase(f)).join('\n');
49
+ const allCases = [casesXml, failuresXml].filter(Boolean).join('\n');
50
+ // Warnings as system-out
51
+ const warningsText = results.warnings.length > 0
52
+ ? ` <system-out>${escapeXml(results.warnings.join('\n'))}</system-out>`
53
+ : '';
54
+ suites.push(` <testsuite name="${escapeXml(entry.flowName)}" tests="${totalTests}" failures="${failures.length}" ` +
55
+ `id="${escapeXml(entry.flowId)}">\n` +
56
+ ` <properties>\n` +
57
+ ` <property name="priority" value="${escapeXml(entry.priority)}" />\n` +
58
+ ` <property name="approach" value="${escapeXml(entry.approach)}" />\n` +
59
+ ` <property name="rationale" value="${escapeXml(entry.rationale)}" />\n` +
60
+ ` </properties>\n` +
61
+ (allCases ? allCases + '\n' : '') +
62
+ (warningsText ? warningsText + '\n' : '') +
63
+ ` </testsuite>`);
64
+ }
65
+ // Remaining high findings not tied to a strategy entry
66
+ const coveredFlowNames = new Set(results.strategyEntries.map((e) => e.flowName));
67
+ const uncoveredFindings = highFindings.filter((f) => !Array.from(coveredFlowNames).some((name) => f.title.includes(name)));
68
+ if (uncoveredFindings.length > 0) {
69
+ const failureCases = uncoveredFindings.map((f) => buildFailureCase(f)).join('\n');
70
+ suites.push(` <testsuite name="findings" tests="${uncoveredFindings.length}" failures="${uncoveredFindings.length}">\n` +
71
+ failureCases + '\n' +
72
+ ` </testsuite>`);
73
+ }
74
+ const totalTests = results.testDesigns.reduce((sum, d) => sum + d.testCases.length, 0) + highFindings.length;
75
+ const totalFailures = highFindings.length;
76
+ return `<?xml version="1.0" encoding="UTF-8"?>\n` +
77
+ `<testsuites name="e2e-agents: ${escapeXml(results.workflow)}" ` +
78
+ `tests="${totalTests}" failures="${totalFailures}" ` +
79
+ `time="0">\n` +
80
+ ` <properties>\n` +
81
+ ` <property name="changedFiles" value="${results.changedFiles}" />\n` +
82
+ ` <property name="impactedFlows" value="${results.impactedFlows}" />\n` +
83
+ ` <property name="cost" value="${results.cost}" />\n` +
84
+ ` <property name="tokens" value="${results.tokens}" />\n` +
85
+ ` </properties>\n` +
86
+ suites.join('\n') + '\n' +
87
+ `</testsuites>\n`;
88
+ },
89
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Reporter interface and shared types for output format plugins.
3
+ */
4
+ export interface CrewResults {
5
+ workflow: string;
6
+ changedFiles: number;
7
+ impactedFlows: number;
8
+ strategyEntries: Array<{
9
+ flowId: string;
10
+ flowName: string;
11
+ priority: string;
12
+ approach: string;
13
+ rationale: string;
14
+ }>;
15
+ testDesigns: Array<{
16
+ flowName: string;
17
+ testCases: Array<{
18
+ name: string;
19
+ type: string;
20
+ priority: string;
21
+ }>;
22
+ }>;
23
+ crossImpacts: Array<{
24
+ sourceFamily: string;
25
+ affectedFamily: string;
26
+ riskLevel: string;
27
+ }>;
28
+ findings: Array<{
29
+ title: string;
30
+ severity: string;
31
+ description: string;
32
+ }>;
33
+ warnings: string[];
34
+ cost: number;
35
+ tokens: number;
36
+ }
37
+ export interface Reporter {
38
+ name: string;
39
+ extension: string;
40
+ format(results: CrewResults): string;
41
+ }
42
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/reporter.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,KAAK,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,WAAW,EAAE,KAAK,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,QAAQ,EAAE,MAAM,CAAC;SACpB,CAAC,CAAC;KACN,CAAC,CAAC;IACH,YAAY,EAAE,KAAK,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC;CACxC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
+ // See LICENSE.txt for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * SARIF v2.1.0 reporter — maps crew results to Static Analysis Results
3
+ * Interchange Format for GitHub Advanced Security / Azure DevOps.
4
+ */
5
+ import type { Reporter } from './reporter.js';
6
+ export declare const sarifReporter: Reporter;
7
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/reporters/sarif.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAc,QAAQ,EAAC,MAAM,eAAe,CAAC;AAyDzD,eAAO,MAAM,aAAa,EAAE,QAoH3B,CAAC"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
3
+ // See LICENSE.txt for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.sarifReporter = void 0;
6
+ function severityToLevel(severity) {
7
+ switch (severity.toLowerCase()) {
8
+ case 'high':
9
+ case 'critical':
10
+ return 'error';
11
+ case 'medium':
12
+ return 'warning';
13
+ case 'low':
14
+ case 'info':
15
+ return 'note';
16
+ default:
17
+ return 'note';
18
+ }
19
+ }
20
+ function riskToLevel(risk) {
21
+ switch (risk.toLowerCase()) {
22
+ case 'high':
23
+ return 'warning';
24
+ case 'medium':
25
+ return 'note';
26
+ default:
27
+ return 'none';
28
+ }
29
+ }
30
+ exports.sarifReporter = {
31
+ name: 'sarif',
32
+ extension: '.sarif',
33
+ format(results) {
34
+ const rules = [];
35
+ const sarifResults = [];
36
+ const ruleIds = new Set();
37
+ function ensureRule(id, description, level) {
38
+ if (!ruleIds.has(id)) {
39
+ ruleIds.add(id);
40
+ rules.push({
41
+ id,
42
+ shortDescription: { text: description },
43
+ defaultConfiguration: { level },
44
+ });
45
+ }
46
+ }
47
+ // Findings -> results
48
+ for (const finding of results.findings) {
49
+ const level = severityToLevel(finding.severity);
50
+ const ruleId = `finding/${finding.severity}`;
51
+ ensureRule(ruleId, `Finding (${finding.severity})`, level);
52
+ sarifResults.push({
53
+ ruleId,
54
+ level,
55
+ message: { text: `${finding.title}: ${finding.description}` },
56
+ properties: {
57
+ severity: finding.severity,
58
+ },
59
+ });
60
+ }
61
+ // Strategy entries without matching test designs -> coverage gap results
62
+ const designedFlows = new Set(results.testDesigns.map((d) => d.flowName));
63
+ for (const entry of results.strategyEntries) {
64
+ if (!designedFlows.has(entry.flowName)) {
65
+ const ruleId = 'coverage/gap';
66
+ ensureRule(ruleId, 'Missing test coverage for impacted flow', 'warning');
67
+ sarifResults.push({
68
+ ruleId,
69
+ level: 'warning',
70
+ message: {
71
+ text: `Flow "${entry.flowName}" (${entry.flowId}) has strategy but no test design. ` +
72
+ `Priority: ${entry.priority}, approach: ${entry.approach}.`,
73
+ },
74
+ properties: {
75
+ flowId: entry.flowId,
76
+ priority: entry.priority,
77
+ },
78
+ });
79
+ }
80
+ }
81
+ // High-risk cross-impacts -> warning results
82
+ for (const impact of results.crossImpacts) {
83
+ const level = riskToLevel(impact.riskLevel);
84
+ if (level === 'none') {
85
+ continue;
86
+ }
87
+ const ruleId = `cross-impact/${impact.riskLevel}`;
88
+ ensureRule(ruleId, `Cross-impact (${impact.riskLevel} risk)`, level);
89
+ sarifResults.push({
90
+ ruleId,
91
+ level,
92
+ message: {
93
+ text: `Cross-impact: "${impact.sourceFamily}" affects "${impact.affectedFamily}" ` +
94
+ `with ${impact.riskLevel} risk.`,
95
+ },
96
+ properties: {
97
+ sourceFamily: impact.sourceFamily,
98
+ affectedFamily: impact.affectedFamily,
99
+ riskLevel: impact.riskLevel,
100
+ },
101
+ });
102
+ }
103
+ const run = {
104
+ tool: {
105
+ driver: {
106
+ name: 'e2e-agents',
107
+ version: '1.8.5',
108
+ informationUri: 'https://github.com/mattermost/e2e-agents',
109
+ rules,
110
+ },
111
+ },
112
+ results: sarifResults,
113
+ invocations: [
114
+ {
115
+ executionSuccessful: true,
116
+ properties: {
117
+ workflow: results.workflow,
118
+ changedFiles: results.changedFiles,
119
+ impactedFlows: results.impactedFlows,
120
+ cost: results.cost,
121
+ tokens: results.tokens,
122
+ warnings: results.warnings,
123
+ },
124
+ },
125
+ ],
126
+ };
127
+ const sarif = {
128
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json',
129
+ version: '2.1.0',
130
+ runs: [run],
131
+ };
132
+ return JSON.stringify(sarif, null, 2) + '\n';
133
+ },
134
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Circuit Breaker — protects against cascading failures from unavailable LLM providers.
3
+ *
4
+ * States:
5
+ * - CLOSED: normal operation, requests pass through
6
+ * - OPEN: provider is down, all requests short-circuit to fallback
7
+ * - HALF_OPEN: after cooldown, allows one test request through
8
+ */
9
+ export interface CircuitBreakerConfig {
10
+ failureThreshold: number;
11
+ cooldownMs: number;
12
+ /** Optional predicate: only count errors where this returns true. Defaults to counting all errors. */
13
+ shouldCount?: (error: unknown) => boolean;
14
+ }
15
+ type CircuitState = 'closed' | 'open' | 'half-open';
16
+ export declare class CircuitBreaker {
17
+ private state;
18
+ private failures;
19
+ private lastFailureTime;
20
+ private config;
21
+ constructor(config?: Partial<CircuitBreakerConfig>);
22
+ /** Returns the derived state without mutating internal state. */
23
+ get currentState(): CircuitState;
24
+ get isOpen(): boolean;
25
+ /**
26
+ * Execute a function with circuit breaker protection.
27
+ * If the circuit is open, the fallback is called instead.
28
+ */
29
+ call<T>(fn: () => Promise<T>, fallback: () => T): Promise<T>;
30
+ private onSuccess;
31
+ private onFailure;
32
+ /** Reset the circuit breaker to closed state */
33
+ reset(): void;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=circuit_breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit_breaker.d.ts","sourceRoot":"","sources":["../../src/resilience/circuit_breaker.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,sGAAsG;IACtG,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAC7C;AAOD,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAEpD,qBAAa,cAAc;IACvB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,GAAE,OAAO,CAAC,oBAAoB,CAAM;IAItD,iEAAiE;IACjE,IAAI,YAAY,IAAI,YAAY,CAK/B;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;OAGG;IACG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiClE,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,SAAS;IAQjB,gDAAgD;IAChD,KAAK,IAAI,IAAI;CAKhB"}