@yasserkhanorg/impact-gate 2.0.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 (587) hide show
  1. package/LICENSE +168 -0
  2. package/README.md +520 -0
  3. package/dist/adapters/cypress.d.ts +10 -0
  4. package/dist/adapters/cypress.d.ts.map +1 -0
  5. package/dist/adapters/cypress.js +86 -0
  6. package/dist/adapters/framework_adapter.d.ts +41 -0
  7. package/dist/adapters/framework_adapter.d.ts.map +1 -0
  8. package/dist/adapters/framework_adapter.js +152 -0
  9. package/dist/adapters/playwright.d.ts +10 -0
  10. package/dist/adapters/playwright.d.ts.map +1 -0
  11. package/dist/adapters/playwright.js +86 -0
  12. package/dist/adapters/pytest.d.ts +10 -0
  13. package/dist/adapters/pytest.d.ts.map +1 -0
  14. package/dist/adapters/pytest.js +96 -0
  15. package/dist/adapters/supertest.d.ts +12 -0
  16. package/dist/adapters/supertest.d.ts.map +1 -0
  17. package/dist/adapters/supertest.js +85 -0
  18. package/dist/agent/api_catalog.d.ts +11 -0
  19. package/dist/agent/api_catalog.d.ts.map +1 -0
  20. package/dist/agent/api_catalog.js +210 -0
  21. package/dist/agent/config.d.ts +193 -0
  22. package/dist/agent/config.d.ts.map +1 -0
  23. package/dist/agent/config.js +875 -0
  24. package/dist/agent/feedback.d.ts +91 -0
  25. package/dist/agent/feedback.d.ts.map +1 -0
  26. package/dist/agent/feedback.js +323 -0
  27. package/dist/agent/git.d.ts +19 -0
  28. package/dist/agent/git.d.ts.map +1 -0
  29. package/dist/agent/git.js +257 -0
  30. package/dist/agent/handoff.d.ts +22 -0
  31. package/dist/agent/handoff.d.ts.map +1 -0
  32. package/dist/agent/handoff.js +180 -0
  33. package/dist/agent/llm_agents_flow.d.ts +15 -0
  34. package/dist/agent/llm_agents_flow.d.ts.map +1 -0
  35. package/dist/agent/llm_agents_flow.js +434 -0
  36. package/dist/agent/native_flow.d.ts +6 -0
  37. package/dist/agent/native_flow.d.ts.map +1 -0
  38. package/dist/agent/native_flow.js +179 -0
  39. package/dist/agent/pipeline.d.ts +7 -0
  40. package/dist/agent/pipeline.d.ts.map +1 -0
  41. package/dist/agent/pipeline.js +260 -0
  42. package/dist/agent/pipeline_types.d.ts +54 -0
  43. package/dist/agent/pipeline_types.d.ts.map +1 -0
  44. package/dist/agent/pipeline_types.js +4 -0
  45. package/dist/agent/pipeline_utils.d.ts +12 -0
  46. package/dist/agent/pipeline_utils.d.ts.map +1 -0
  47. package/dist/agent/pipeline_utils.js +156 -0
  48. package/dist/agent/plan.d.ts +170 -0
  49. package/dist/agent/plan.d.ts.map +1 -0
  50. package/dist/agent/plan.js +86 -0
  51. package/dist/agent/playwright_report.d.ts +8 -0
  52. package/dist/agent/playwright_report.d.ts.map +1 -0
  53. package/dist/agent/playwright_report.js +126 -0
  54. package/dist/agent/process_runner.d.ts +10 -0
  55. package/dist/agent/process_runner.d.ts.map +1 -0
  56. package/dist/agent/process_runner.js +92 -0
  57. package/dist/agent/spec_generator.d.ts +5 -0
  58. package/dist/agent/spec_generator.d.ts.map +1 -0
  59. package/dist/agent/spec_generator.js +253 -0
  60. package/dist/agent/test_path.d.ts +2 -0
  61. package/dist/agent/test_path.d.ts.map +1 -0
  62. package/dist/agent/test_path.js +23 -0
  63. package/dist/agent/traceability_capture.d.ts +18 -0
  64. package/dist/agent/traceability_capture.d.ts.map +1 -0
  65. package/dist/agent/traceability_capture.js +313 -0
  66. package/dist/agent/traceability_ingest.d.ts +21 -0
  67. package/dist/agent/traceability_ingest.d.ts.map +1 -0
  68. package/dist/agent/traceability_ingest.js +237 -0
  69. package/dist/agent/types.d.ts +42 -0
  70. package/dist/agent/types.d.ts.map +1 -0
  71. package/dist/agent/types.js +4 -0
  72. package/dist/agent/utils.d.ts +13 -0
  73. package/dist/agent/utils.d.ts.map +1 -0
  74. package/dist/agent/utils.js +152 -0
  75. package/dist/agent/validation_runner.d.ts +5 -0
  76. package/dist/agent/validation_runner.d.ts.map +1 -0
  77. package/dist/agent/validation_runner.js +77 -0
  78. package/dist/agentic/fix_loop.d.ts +26 -0
  79. package/dist/agentic/fix_loop.d.ts.map +1 -0
  80. package/dist/agentic/fix_loop.js +96 -0
  81. package/dist/agentic/playwright_runner.d.ts +43 -0
  82. package/dist/agentic/playwright_runner.d.ts.map +1 -0
  83. package/dist/agentic/playwright_runner.js +165 -0
  84. package/dist/agentic/runner.d.ts +27 -0
  85. package/dist/agentic/runner.d.ts.map +1 -0
  86. package/dist/agentic/runner.js +210 -0
  87. package/dist/agentic/types.d.ts +62 -0
  88. package/dist/agentic/types.d.ts.map +1 -0
  89. package/dist/agentic/types.js +4 -0
  90. package/dist/agents/coverage-evaluator.d.ts +8 -0
  91. package/dist/agents/coverage-evaluator.d.ts.map +1 -0
  92. package/dist/agents/coverage-evaluator.js +41 -0
  93. package/dist/agents/cross-impact.d.ts +13 -0
  94. package/dist/agents/cross-impact.d.ts.map +1 -0
  95. package/dist/agents/cross-impact.js +140 -0
  96. package/dist/agents/executor.d.ts +8 -0
  97. package/dist/agents/executor.d.ts.map +1 -0
  98. package/dist/agents/executor.js +75 -0
  99. package/dist/agents/explorer.d.ts +12 -0
  100. package/dist/agents/explorer.d.ts.map +1 -0
  101. package/dist/agents/explorer.js +43 -0
  102. package/dist/agents/generator.d.ts +8 -0
  103. package/dist/agents/generator.d.ts.map +1 -0
  104. package/dist/agents/generator.js +77 -0
  105. package/dist/agents/healer.d.ts +8 -0
  106. package/dist/agents/healer.d.ts.map +1 -0
  107. package/dist/agents/healer.js +31 -0
  108. package/dist/agents/impact-analyst.d.ts +8 -0
  109. package/dist/agents/impact-analyst.d.ts.map +1 -0
  110. package/dist/agents/impact-analyst.js +38 -0
  111. package/dist/agents/regression-advisor.d.ts +8 -0
  112. package/dist/agents/regression-advisor.d.ts.map +1 -0
  113. package/dist/agents/regression-advisor.js +116 -0
  114. package/dist/agents/strategist.d.ts +9 -0
  115. package/dist/agents/strategist.d.ts.map +1 -0
  116. package/dist/agents/strategist.js +92 -0
  117. package/dist/agents/test-designer.d.ts +8 -0
  118. package/dist/agents/test-designer.d.ts.map +1 -0
  119. package/dist/agents/test-designer.js +111 -0
  120. package/dist/anthropic_provider.d.ts +65 -0
  121. package/dist/anthropic_provider.d.ts.map +1 -0
  122. package/dist/anthropic_provider.js +334 -0
  123. package/dist/api.d.ts +48 -0
  124. package/dist/api.d.ts.map +1 -0
  125. package/dist/api.js +151 -0
  126. package/dist/base_provider.d.ts +109 -0
  127. package/dist/base_provider.d.ts.map +1 -0
  128. package/dist/base_provider.js +203 -0
  129. package/dist/budget_ledger.d.ts +28 -0
  130. package/dist/budget_ledger.d.ts.map +1 -0
  131. package/dist/budget_ledger.js +62 -0
  132. package/dist/cache/cached_provider.d.ts +49 -0
  133. package/dist/cache/cached_provider.d.ts.map +1 -0
  134. package/dist/cache/cached_provider.js +91 -0
  135. package/dist/cache/response_cache.d.ts +79 -0
  136. package/dist/cache/response_cache.d.ts.map +1 -0
  137. package/dist/cache/response_cache.js +177 -0
  138. package/dist/cli/commands/analyze.d.ts +3 -0
  139. package/dist/cli/commands/analyze.d.ts.map +1 -0
  140. package/dist/cli/commands/analyze.js +77 -0
  141. package/dist/cli/commands/bootstrap.d.ts +3 -0
  142. package/dist/cli/commands/bootstrap.d.ts.map +1 -0
  143. package/dist/cli/commands/bootstrap.js +109 -0
  144. package/dist/cli/commands/cost_report.d.ts +3 -0
  145. package/dist/cli/commands/cost_report.d.ts.map +1 -0
  146. package/dist/cli/commands/cost_report.js +115 -0
  147. package/dist/cli/commands/crew.d.ts +3 -0
  148. package/dist/cli/commands/crew.d.ts.map +1 -0
  149. package/dist/cli/commands/crew.js +255 -0
  150. package/dist/cli/commands/feedback.d.ts +3 -0
  151. package/dist/cli/commands/feedback.d.ts.map +1 -0
  152. package/dist/cli/commands/feedback.js +39 -0
  153. package/dist/cli/commands/finalize.d.ts +3 -0
  154. package/dist/cli/commands/finalize.d.ts.map +1 -0
  155. package/dist/cli/commands/finalize.js +41 -0
  156. package/dist/cli/commands/gate.d.ts +3 -0
  157. package/dist/cli/commands/gate.d.ts.map +1 -0
  158. package/dist/cli/commands/gate.js +89 -0
  159. package/dist/cli/commands/generate.d.ts +4 -0
  160. package/dist/cli/commands/generate.d.ts.map +1 -0
  161. package/dist/cli/commands/generate.js +108 -0
  162. package/dist/cli/commands/heal.d.ts +3 -0
  163. package/dist/cli/commands/heal.d.ts.map +1 -0
  164. package/dist/cli/commands/heal.js +60 -0
  165. package/dist/cli/commands/impact.d.ts +4 -0
  166. package/dist/cli/commands/impact.d.ts.map +1 -0
  167. package/dist/cli/commands/impact.js +33 -0
  168. package/dist/cli/commands/init.d.ts +2 -0
  169. package/dist/cli/commands/init.d.ts.map +1 -0
  170. package/dist/cli/commands/init.js +169 -0
  171. package/dist/cli/commands/llm_health.d.ts +2 -0
  172. package/dist/cli/commands/llm_health.d.ts.map +1 -0
  173. package/dist/cli/commands/llm_health.js +22 -0
  174. package/dist/cli/commands/plan.d.ts +4 -0
  175. package/dist/cli/commands/plan.d.ts.map +1 -0
  176. package/dist/cli/commands/plan.js +120 -0
  177. package/dist/cli/commands/plan_crew.d.ts +17 -0
  178. package/dist/cli/commands/plan_crew.d.ts.map +1 -0
  179. package/dist/cli/commands/plan_crew.js +316 -0
  180. package/dist/cli/commands/traceability.d.ts +4 -0
  181. package/dist/cli/commands/traceability.d.ts.map +1 -0
  182. package/dist/cli/commands/traceability.js +77 -0
  183. package/dist/cli/commands/train.d.ts +3 -0
  184. package/dist/cli/commands/train.d.ts.map +1 -0
  185. package/dist/cli/commands/train.js +391 -0
  186. package/dist/cli/defaults.d.ts +35 -0
  187. package/dist/cli/defaults.d.ts.map +1 -0
  188. package/dist/cli/defaults.js +172 -0
  189. package/dist/cli/errors.d.ts +27 -0
  190. package/dist/cli/errors.d.ts.map +1 -0
  191. package/dist/cli/errors.js +57 -0
  192. package/dist/cli/parse_args.d.ts +6 -0
  193. package/dist/cli/parse_args.d.ts.map +1 -0
  194. package/dist/cli/parse_args.js +257 -0
  195. package/dist/cli/types.d.ts +87 -0
  196. package/dist/cli/types.d.ts.map +1 -0
  197. package/dist/cli/types.js +4 -0
  198. package/dist/cli/usage.d.ts +2 -0
  199. package/dist/cli/usage.d.ts.map +1 -0
  200. package/dist/cli/usage.js +109 -0
  201. package/dist/cli.d.ts +3 -0
  202. package/dist/cli.d.ts.map +1 -0
  203. package/dist/cli.js +194 -0
  204. package/dist/crew/context.d.ts +55 -0
  205. package/dist/crew/context.d.ts.map +1 -0
  206. package/dist/crew/context.js +36 -0
  207. package/dist/crew/orchestrator.d.ts +50 -0
  208. package/dist/crew/orchestrator.d.ts.map +1 -0
  209. package/dist/crew/orchestrator.js +329 -0
  210. package/dist/crew/protocol.d.ts +46 -0
  211. package/dist/crew/protocol.d.ts.map +1 -0
  212. package/dist/crew/protocol.js +4 -0
  213. package/dist/crew/provider.d.ts +17 -0
  214. package/dist/crew/provider.d.ts.map +1 -0
  215. package/dist/crew/provider.js +36 -0
  216. package/dist/crew/sanitize.d.ts +3 -0
  217. package/dist/crew/sanitize.d.ts.map +1 -0
  218. package/dist/crew/sanitize.js +31 -0
  219. package/dist/crew/types.d.ts +52 -0
  220. package/dist/crew/types.d.ts.map +1 -0
  221. package/dist/crew/types.js +4 -0
  222. package/dist/crew/workflows.d.ts +52 -0
  223. package/dist/crew/workflows.d.ts.map +1 -0
  224. package/dist/crew/workflows.js +36 -0
  225. package/dist/custom_provider.d.ts +20 -0
  226. package/dist/custom_provider.d.ts.map +1 -0
  227. package/dist/custom_provider.js +277 -0
  228. package/dist/engine/ai_enrichment.d.ts +44 -0
  229. package/dist/engine/ai_enrichment.d.ts.map +1 -0
  230. package/dist/engine/ai_enrichment.js +267 -0
  231. package/dist/engine/diff_loader.d.ts +11 -0
  232. package/dist/engine/diff_loader.d.ts.map +1 -0
  233. package/dist/engine/diff_loader.js +63 -0
  234. package/dist/engine/impact_engine.d.ts +72 -0
  235. package/dist/engine/impact_engine.d.ts.map +1 -0
  236. package/dist/engine/impact_engine.js +298 -0
  237. package/dist/engine/plan_builder.d.ts +11 -0
  238. package/dist/engine/plan_builder.d.ts.map +1 -0
  239. package/dist/engine/plan_builder.js +599 -0
  240. package/dist/esm/adapters/cypress.js +49 -0
  241. package/dist/esm/adapters/framework_adapter.js +114 -0
  242. package/dist/esm/adapters/playwright.js +49 -0
  243. package/dist/esm/adapters/pytest.js +59 -0
  244. package/dist/esm/adapters/supertest.js +48 -0
  245. package/dist/esm/agent/api_catalog.js +199 -0
  246. package/dist/esm/agent/config.js +872 -0
  247. package/dist/esm/agent/feedback.js +317 -0
  248. package/dist/esm/agent/git.js +252 -0
  249. package/dist/esm/agent/handoff.js +177 -0
  250. package/dist/esm/agent/llm_agents_flow.js +421 -0
  251. package/dist/esm/agent/native_flow.js +175 -0
  252. package/dist/esm/agent/pipeline.js +256 -0
  253. package/dist/esm/agent/pipeline_types.js +3 -0
  254. package/dist/esm/agent/pipeline_utils.js +146 -0
  255. package/dist/esm/agent/plan.js +83 -0
  256. package/dist/esm/agent/playwright_report.js +123 -0
  257. package/dist/esm/agent/process_runner.js +83 -0
  258. package/dist/esm/agent/spec_generator.js +249 -0
  259. package/dist/esm/agent/test_path.js +20 -0
  260. package/dist/esm/agent/traceability_capture.js +310 -0
  261. package/dist/esm/agent/traceability_ingest.js +234 -0
  262. package/dist/esm/agent/types.js +3 -0
  263. package/dist/esm/agent/utils.js +138 -0
  264. package/dist/esm/agent/validation_runner.js +73 -0
  265. package/dist/esm/agentic/fix_loop.js +91 -0
  266. package/dist/esm/agentic/playwright_runner.js +161 -0
  267. package/dist/esm/agentic/runner.js +207 -0
  268. package/dist/esm/agentic/types.js +3 -0
  269. package/dist/esm/agents/coverage-evaluator.js +37 -0
  270. package/dist/esm/agents/cross-impact.js +136 -0
  271. package/dist/esm/agents/executor.js +71 -0
  272. package/dist/esm/agents/explorer.js +39 -0
  273. package/dist/esm/agents/generator.js +73 -0
  274. package/dist/esm/agents/healer.js +27 -0
  275. package/dist/esm/agents/impact-analyst.js +34 -0
  276. package/dist/esm/agents/regression-advisor.js +112 -0
  277. package/dist/esm/agents/strategist.js +88 -0
  278. package/dist/esm/agents/test-designer.js +107 -0
  279. package/dist/esm/anthropic_provider.js +326 -0
  280. package/dist/esm/api.js +143 -0
  281. package/dist/esm/base_provider.js +198 -0
  282. package/dist/esm/budget_ledger.js +58 -0
  283. package/dist/esm/cache/cached_provider.js +85 -0
  284. package/dist/esm/cache/response_cache.js +140 -0
  285. package/dist/esm/cli/commands/analyze.js +74 -0
  286. package/dist/esm/cli/commands/bootstrap.js +106 -0
  287. package/dist/esm/cli/commands/cost_report.js +112 -0
  288. package/dist/esm/cli/commands/crew.js +252 -0
  289. package/dist/esm/cli/commands/feedback.js +36 -0
  290. package/dist/esm/cli/commands/finalize.js +38 -0
  291. package/dist/esm/cli/commands/gate.js +86 -0
  292. package/dist/esm/cli/commands/generate.js +105 -0
  293. package/dist/esm/cli/commands/heal.js +57 -0
  294. package/dist/esm/cli/commands/impact.js +30 -0
  295. package/dist/esm/cli/commands/init.js +133 -0
  296. package/dist/esm/cli/commands/llm_health.js +19 -0
  297. package/dist/esm/cli/commands/plan.js +117 -0
  298. package/dist/esm/cli/commands/plan_crew.js +309 -0
  299. package/dist/esm/cli/commands/traceability.js +73 -0
  300. package/dist/esm/cli/commands/train.js +355 -0
  301. package/dist/esm/cli/defaults.js +165 -0
  302. package/dist/esm/cli/errors.js +52 -0
  303. package/dist/esm/cli/parse_args.js +251 -0
  304. package/dist/esm/cli/types.js +3 -0
  305. package/dist/esm/cli/usage.js +106 -0
  306. package/dist/esm/cli.js +192 -0
  307. package/dist/esm/crew/context.js +32 -0
  308. package/dist/esm/crew/orchestrator.js +325 -0
  309. package/dist/esm/crew/protocol.js +3 -0
  310. package/dist/esm/crew/provider.js +33 -0
  311. package/dist/esm/crew/sanitize.js +27 -0
  312. package/dist/esm/crew/types.js +3 -0
  313. package/dist/esm/crew/workflows.js +33 -0
  314. package/dist/esm/custom_provider.js +273 -0
  315. package/dist/esm/engine/ai_enrichment.js +264 -0
  316. package/dist/esm/engine/diff_loader.js +59 -0
  317. package/dist/esm/engine/impact_engine.js +291 -0
  318. package/dist/esm/engine/plan_builder.js +593 -0
  319. package/dist/esm/index.js +72 -0
  320. package/dist/esm/knowledge/api_surface.js +408 -0
  321. package/dist/esm/knowledge/cluster_utils.js +60 -0
  322. package/dist/esm/knowledge/context_loader.js +85 -0
  323. package/dist/esm/knowledge/failure_history.js +121 -0
  324. package/dist/esm/knowledge/kg_bridge.js +381 -0
  325. package/dist/esm/knowledge/kg_types.js +3 -0
  326. package/dist/esm/knowledge/route_families.js +393 -0
  327. package/dist/esm/knowledge/spec_index.js +122 -0
  328. package/dist/esm/logger.js +115 -0
  329. package/dist/esm/mcp-server.js +621 -0
  330. package/dist/esm/metrics/prometheus.js +149 -0
  331. package/dist/esm/model_router.js +59 -0
  332. package/dist/esm/ollama_provider.js +301 -0
  333. package/dist/esm/openai_provider.js +243 -0
  334. package/dist/esm/package.json +3 -0
  335. package/dist/esm/pipeline/orchestrator.js +228 -0
  336. package/dist/esm/pipeline/spec_verifier.js +75 -0
  337. package/dist/esm/pipeline/stage0_preprocess.js +102 -0
  338. package/dist/esm/pipeline/stage1_impact.js +140 -0
  339. package/dist/esm/pipeline/stage2_coverage.js +153 -0
  340. package/dist/esm/pipeline/stage3_generation.js +284 -0
  341. package/dist/esm/pipeline/stage4_heal.js +288 -0
  342. package/dist/esm/progress.js +112 -0
  343. package/dist/esm/prompts/coverage.js +57 -0
  344. package/dist/esm/prompts/cross-impact.js +53 -0
  345. package/dist/esm/prompts/generation.js +297 -0
  346. package/dist/esm/prompts/generation_profile.js +147 -0
  347. package/dist/esm/prompts/heal.js +91 -0
  348. package/dist/esm/prompts/impact.js +63 -0
  349. package/dist/esm/prompts/json_extract.js +36 -0
  350. package/dist/esm/prompts/strategist.js +61 -0
  351. package/dist/esm/prompts/test-designer.js +92 -0
  352. package/dist/esm/provider_factory.js +366 -0
  353. package/dist/esm/provider_interface.js +23 -0
  354. package/dist/esm/provider_utils.js +96 -0
  355. package/dist/esm/qa-agent/cli.js +205 -0
  356. package/dist/esm/qa-agent/orchestrator.js +120 -0
  357. package/dist/esm/qa-agent/phase1/runner.js +139 -0
  358. package/dist/esm/qa-agent/phase1/scope.js +126 -0
  359. package/dist/esm/qa-agent/phase2/agent_browser.js +95 -0
  360. package/dist/esm/qa-agent/phase2/agent_loop.js +351 -0
  361. package/dist/esm/qa-agent/phase2/exploration_state.js +97 -0
  362. package/dist/esm/qa-agent/phase2/tools.js +386 -0
  363. package/dist/esm/qa-agent/phase2/vision.js +75 -0
  364. package/dist/esm/qa-agent/phase3/feedback.js +34 -0
  365. package/dist/esm/qa-agent/phase3/reporter.js +145 -0
  366. package/dist/esm/qa-agent/phase3/spec_generator.js +62 -0
  367. package/dist/esm/qa-agent/phase3/verdict.js +66 -0
  368. package/dist/esm/qa-agent/safe_env.js +23 -0
  369. package/dist/esm/qa-agent/types.js +3 -0
  370. package/dist/esm/reporters/junit.js +86 -0
  371. package/dist/esm/reporters/reporter.js +3 -0
  372. package/dist/esm/reporters/sarif.js +132 -0
  373. package/dist/esm/resilience/circuit_breaker.js +78 -0
  374. package/dist/esm/resilience/retry.js +56 -0
  375. package/dist/esm/sanitize.js +66 -0
  376. package/dist/esm/training/enricher.js +345 -0
  377. package/dist/esm/training/kg_scanner.js +115 -0
  378. package/dist/esm/training/merger.js +204 -0
  379. package/dist/esm/training/scanner.js +923 -0
  380. package/dist/esm/training/types.js +6 -0
  381. package/dist/esm/training/validator.js +254 -0
  382. package/dist/esm/validation/guardrails.js +101 -0
  383. package/dist/esm/validation/output_schema.js +80 -0
  384. package/dist/esm/version.js +33 -0
  385. package/dist/index.d.ts +99 -0
  386. package/dist/index.d.ts.map +1 -0
  387. package/dist/index.js +169 -0
  388. package/dist/knowledge/api_surface.d.ts +37 -0
  389. package/dist/knowledge/api_surface.d.ts.map +1 -0
  390. package/dist/knowledge/api_surface.js +418 -0
  391. package/dist/knowledge/cluster_utils.d.ts +28 -0
  392. package/dist/knowledge/cluster_utils.d.ts.map +1 -0
  393. package/dist/knowledge/cluster_utils.js +67 -0
  394. package/dist/knowledge/context_loader.d.ts +13 -0
  395. package/dist/knowledge/context_loader.d.ts.map +1 -0
  396. package/dist/knowledge/context_loader.js +90 -0
  397. package/dist/knowledge/failure_history.d.ts +39 -0
  398. package/dist/knowledge/failure_history.d.ts.map +1 -0
  399. package/dist/knowledge/failure_history.js +128 -0
  400. package/dist/knowledge/kg_bridge.d.ts +31 -0
  401. package/dist/knowledge/kg_bridge.d.ts.map +1 -0
  402. package/dist/knowledge/kg_bridge.js +388 -0
  403. package/dist/knowledge/kg_types.d.ts +75 -0
  404. package/dist/knowledge/kg_types.d.ts.map +1 -0
  405. package/dist/knowledge/kg_types.js +4 -0
  406. package/dist/knowledge/route_families.d.ts +98 -0
  407. package/dist/knowledge/route_families.d.ts.map +1 -0
  408. package/dist/knowledge/route_families.js +410 -0
  409. package/dist/knowledge/spec_index.d.ts +18 -0
  410. package/dist/knowledge/spec_index.d.ts.map +1 -0
  411. package/dist/knowledge/spec_index.js +128 -0
  412. package/dist/logger.d.ts +31 -0
  413. package/dist/logger.d.ts.map +1 -0
  414. package/dist/logger.js +119 -0
  415. package/dist/mcp-server.d.ts +68 -0
  416. package/dist/mcp-server.d.ts.map +1 -0
  417. package/dist/mcp-server.js +629 -0
  418. package/dist/metrics/prometheus.d.ts +37 -0
  419. package/dist/metrics/prometheus.d.ts.map +1 -0
  420. package/dist/metrics/prometheus.js +153 -0
  421. package/dist/model_router.d.ts +28 -0
  422. package/dist/model_router.d.ts.map +1 -0
  423. package/dist/model_router.js +63 -0
  424. package/dist/ollama_provider.d.ts +65 -0
  425. package/dist/ollama_provider.d.ts.map +1 -0
  426. package/dist/ollama_provider.js +309 -0
  427. package/dist/openai_provider.d.ts +23 -0
  428. package/dist/openai_provider.d.ts.map +1 -0
  429. package/dist/openai_provider.js +251 -0
  430. package/dist/pipeline/orchestrator.d.ts +33 -0
  431. package/dist/pipeline/orchestrator.d.ts.map +1 -0
  432. package/dist/pipeline/orchestrator.js +231 -0
  433. package/dist/pipeline/spec_verifier.d.ts +20 -0
  434. package/dist/pipeline/spec_verifier.d.ts.map +1 -0
  435. package/dist/pipeline/spec_verifier.js +79 -0
  436. package/dist/pipeline/stage0_preprocess.d.ts +31 -0
  437. package/dist/pipeline/stage0_preprocess.d.ts.map +1 -0
  438. package/dist/pipeline/stage0_preprocess.js +105 -0
  439. package/dist/pipeline/stage1_impact.d.ts +19 -0
  440. package/dist/pipeline/stage1_impact.d.ts.map +1 -0
  441. package/dist/pipeline/stage1_impact.js +143 -0
  442. package/dist/pipeline/stage2_coverage.d.ts +19 -0
  443. package/dist/pipeline/stage2_coverage.d.ts.map +1 -0
  444. package/dist/pipeline/stage2_coverage.js +156 -0
  445. package/dist/pipeline/stage3_generation.d.ts +43 -0
  446. package/dist/pipeline/stage3_generation.d.ts.map +1 -0
  447. package/dist/pipeline/stage3_generation.js +287 -0
  448. package/dist/pipeline/stage4_heal.d.ts +62 -0
  449. package/dist/pipeline/stage4_heal.d.ts.map +1 -0
  450. package/dist/pipeline/stage4_heal.js +294 -0
  451. package/dist/progress.d.ts +22 -0
  452. package/dist/progress.d.ts.map +1 -0
  453. package/dist/progress.js +116 -0
  454. package/dist/prompts/coverage.d.ts +39 -0
  455. package/dist/prompts/coverage.d.ts.map +1 -0
  456. package/dist/prompts/coverage.js +61 -0
  457. package/dist/prompts/cross-impact.d.ts +23 -0
  458. package/dist/prompts/cross-impact.d.ts.map +1 -0
  459. package/dist/prompts/cross-impact.js +57 -0
  460. package/dist/prompts/generation.d.ts +25 -0
  461. package/dist/prompts/generation.d.ts.map +1 -0
  462. package/dist/prompts/generation.js +302 -0
  463. package/dist/prompts/generation_profile.d.ts +29 -0
  464. package/dist/prompts/generation_profile.d.ts.map +1 -0
  465. package/dist/prompts/generation_profile.js +151 -0
  466. package/dist/prompts/heal.d.ts +23 -0
  467. package/dist/prompts/heal.d.ts.map +1 -0
  468. package/dist/prompts/heal.js +95 -0
  469. package/dist/prompts/impact.d.ts +31 -0
  470. package/dist/prompts/impact.d.ts.map +1 -0
  471. package/dist/prompts/impact.js +67 -0
  472. package/dist/prompts/json_extract.d.ts +14 -0
  473. package/dist/prompts/json_extract.d.ts.map +1 -0
  474. package/dist/prompts/json_extract.js +39 -0
  475. package/dist/prompts/strategist.d.ts +25 -0
  476. package/dist/prompts/strategist.d.ts.map +1 -0
  477. package/dist/prompts/strategist.js +65 -0
  478. package/dist/prompts/test-designer.d.ts +35 -0
  479. package/dist/prompts/test-designer.d.ts.map +1 -0
  480. package/dist/prompts/test-designer.js +96 -0
  481. package/dist/provider_factory.d.ts +104 -0
  482. package/dist/provider_factory.d.ts.map +1 -0
  483. package/dist/provider_factory.js +371 -0
  484. package/dist/provider_interface.d.ts +365 -0
  485. package/dist/provider_interface.d.ts.map +1 -0
  486. package/dist/provider_interface.js +28 -0
  487. package/dist/provider_utils.d.ts +39 -0
  488. package/dist/provider_utils.d.ts.map +1 -0
  489. package/dist/provider_utils.js +103 -0
  490. package/dist/qa-agent/cli.d.ts +3 -0
  491. package/dist/qa-agent/cli.d.ts.map +1 -0
  492. package/dist/qa-agent/cli.js +207 -0
  493. package/dist/qa-agent/orchestrator.d.ts +3 -0
  494. package/dist/qa-agent/orchestrator.d.ts.map +1 -0
  495. package/dist/qa-agent/orchestrator.js +123 -0
  496. package/dist/qa-agent/phase1/runner.d.ts +3 -0
  497. package/dist/qa-agent/phase1/runner.d.ts.map +1 -0
  498. package/dist/qa-agent/phase1/runner.js +142 -0
  499. package/dist/qa-agent/phase1/scope.d.ts +6 -0
  500. package/dist/qa-agent/phase1/scope.d.ts.map +1 -0
  501. package/dist/qa-agent/phase1/scope.js +129 -0
  502. package/dist/qa-agent/phase2/agent_browser.d.ts +35 -0
  503. package/dist/qa-agent/phase2/agent_browser.d.ts.map +1 -0
  504. package/dist/qa-agent/phase2/agent_browser.js +99 -0
  505. package/dist/qa-agent/phase2/agent_loop.d.ts +3 -0
  506. package/dist/qa-agent/phase2/agent_loop.d.ts.map +1 -0
  507. package/dist/qa-agent/phase2/agent_loop.js +357 -0
  508. package/dist/qa-agent/phase2/exploration_state.d.ts +12 -0
  509. package/dist/qa-agent/phase2/exploration_state.d.ts.map +1 -0
  510. package/dist/qa-agent/phase2/exploration_state.js +109 -0
  511. package/dist/qa-agent/phase2/tools.d.ts +28 -0
  512. package/dist/qa-agent/phase2/tools.d.ts.map +1 -0
  513. package/dist/qa-agent/phase2/tools.js +390 -0
  514. package/dist/qa-agent/phase2/vision.d.ts +3 -0
  515. package/dist/qa-agent/phase2/vision.d.ts.map +1 -0
  516. package/dist/qa-agent/phase2/vision.js +78 -0
  517. package/dist/qa-agent/phase3/feedback.d.ts +3 -0
  518. package/dist/qa-agent/phase3/feedback.d.ts.map +1 -0
  519. package/dist/qa-agent/phase3/feedback.js +37 -0
  520. package/dist/qa-agent/phase3/reporter.d.ts +3 -0
  521. package/dist/qa-agent/phase3/reporter.d.ts.map +1 -0
  522. package/dist/qa-agent/phase3/reporter.js +148 -0
  523. package/dist/qa-agent/phase3/spec_generator.d.ts +3 -0
  524. package/dist/qa-agent/phase3/spec_generator.d.ts.map +1 -0
  525. package/dist/qa-agent/phase3/spec_generator.js +65 -0
  526. package/dist/qa-agent/phase3/verdict.d.ts +3 -0
  527. package/dist/qa-agent/phase3/verdict.d.ts.map +1 -0
  528. package/dist/qa-agent/phase3/verdict.js +69 -0
  529. package/dist/qa-agent/safe_env.d.ts +3 -0
  530. package/dist/qa-agent/safe_env.d.ts.map +1 -0
  531. package/dist/qa-agent/safe_env.js +26 -0
  532. package/dist/qa-agent/types.d.ts +130 -0
  533. package/dist/qa-agent/types.d.ts.map +1 -0
  534. package/dist/qa-agent/types.js +4 -0
  535. package/dist/reporters/junit.d.ts +6 -0
  536. package/dist/reporters/junit.d.ts.map +1 -0
  537. package/dist/reporters/junit.js +89 -0
  538. package/dist/reporters/reporter.d.ts +42 -0
  539. package/dist/reporters/reporter.d.ts.map +1 -0
  540. package/dist/reporters/reporter.js +4 -0
  541. package/dist/reporters/sarif.d.ts +7 -0
  542. package/dist/reporters/sarif.d.ts.map +1 -0
  543. package/dist/reporters/sarif.js +135 -0
  544. package/dist/resilience/circuit_breaker.d.ts +36 -0
  545. package/dist/resilience/circuit_breaker.d.ts.map +1 -0
  546. package/dist/resilience/circuit_breaker.js +82 -0
  547. package/dist/resilience/retry.d.ts +11 -0
  548. package/dist/resilience/retry.d.ts.map +1 -0
  549. package/dist/resilience/retry.js +59 -0
  550. package/dist/sanitize.d.ts +15 -0
  551. package/dist/sanitize.d.ts.map +1 -0
  552. package/dist/sanitize.js +71 -0
  553. package/dist/training/enricher.d.ts +17 -0
  554. package/dist/training/enricher.d.ts.map +1 -0
  555. package/dist/training/enricher.js +350 -0
  556. package/dist/training/kg_scanner.d.ts +13 -0
  557. package/dist/training/kg_scanner.d.ts.map +1 -0
  558. package/dist/training/kg_scanner.js +118 -0
  559. package/dist/training/merger.d.ts +15 -0
  560. package/dist/training/merger.d.ts.map +1 -0
  561. package/dist/training/merger.js +208 -0
  562. package/dist/training/scanner.d.ts +36 -0
  563. package/dist/training/scanner.d.ts.map +1 -0
  564. package/dist/training/scanner.js +932 -0
  565. package/dist/training/types.d.ts +117 -0
  566. package/dist/training/types.d.ts.map +1 -0
  567. package/dist/training/types.js +9 -0
  568. package/dist/training/validator.d.ts +21 -0
  569. package/dist/training/validator.d.ts.map +1 -0
  570. package/dist/training/validator.js +262 -0
  571. package/dist/validation/guardrails.d.ts +31 -0
  572. package/dist/validation/guardrails.d.ts.map +1 -0
  573. package/dist/validation/guardrails.js +112 -0
  574. package/dist/validation/output_schema.d.ts +67 -0
  575. package/dist/validation/output_schema.d.ts.map +1 -0
  576. package/dist/validation/output_schema.js +84 -0
  577. package/dist/version.d.ts +6 -0
  578. package/dist/version.d.ts.map +1 -0
  579. package/dist/version.js +36 -0
  580. package/package.json +126 -0
  581. package/schemas/flow-decision.schema.json +83 -0
  582. package/schemas/gap.schema.json +18 -0
  583. package/schemas/impact.schema.json +455 -0
  584. package/schemas/plan.schema.json +491 -0
  585. package/schemas/route-families.schema.json +137 -0
  586. package/schemas/subsystem-risk-map.schema.json +62 -0
  587. package/schemas/traceability-input.schema.json +122 -0
@@ -0,0 +1,107 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ /**
4
+ * Test Designer Agent — designs structured test cases across 9 categories.
5
+ * Takes strategist output + API surface + existing specs and produces TestDesign[].
6
+ */
7
+ import { getCrewProvider } from '../crew/provider.js';
8
+ import { getSpecsForFamily } from '../knowledge/spec_index.js';
9
+ import { buildTestDesignerPrompt, parseTestDesignerResponse } from '../prompts/test-designer.js';
10
+ const MAX_TEST_CASES_PER_FLOW = 15;
11
+ const VALID_TYPES = new Set([
12
+ 'happy-path', 'edge-case', 'boundary', 'negative',
13
+ 'state-transition', 'race-condition', 'permission', 'accessibility', 'performance',
14
+ ]);
15
+ export class TestDesignerAgent {
16
+ constructor() {
17
+ this.role = 'test-designer';
18
+ }
19
+ async execute(_task, ctx) {
20
+ const warnings = [];
21
+ if (ctx.strategyEntries.length === 0) {
22
+ warnings.push('Test designer: no strategy entries to design tests for.');
23
+ return { role: this.role, status: 'partial', output: [], warnings };
24
+ }
25
+ // Only design tests for flows with full-test or smoke-test approach
26
+ const designable = ctx.strategyEntries.filter((s) => s.approach === 'full-test' || s.approach === 'smoke-test');
27
+ if (designable.length === 0) {
28
+ warnings.push('Test designer: all flows are skip or manual-review.');
29
+ return { role: this.role, status: 'partial', output: [], warnings };
30
+ }
31
+ let provider;
32
+ try {
33
+ provider = await getCrewProvider(ctx.providerOverride, ctx.budgetUSD, {
34
+ agentRole: 'test-designer',
35
+ modelRoutingProviderType: ctx.modelRoutingProviderType,
36
+ modelRoutingOverrides: ctx.modelRoutingOverrides,
37
+ budgetLedger: ctx.budgetLedger,
38
+ });
39
+ }
40
+ catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ warnings.push(`Test designer provider unavailable: ${message}`);
43
+ return { role: this.role, status: 'failed', output: [], warnings };
44
+ }
45
+ const designs = [];
46
+ for (const strategy of designable) {
47
+ const flow = ctx.impactedFlows.find((f) => f.flowId === strategy.flowId);
48
+ if (!flow) {
49
+ warnings.push(`Test designer: strategy entry '${strategy.flowId}' has no matching flow.`);
50
+ continue;
51
+ }
52
+ const familySpecs = getSpecsForFamily(ctx.specIndex, flow.routeFamily, flow.featureId);
53
+ const relevantCrossImpacts = ctx.crossImpacts.filter((ci) => ci.sourceFamily === flow.routeFamily || ci.affectedFamily === flow.routeFamily);
54
+ const prompt = buildTestDesignerPrompt({
55
+ flow,
56
+ strategy,
57
+ apiSurface: ctx.apiSurface,
58
+ existingSpecs: familySpecs,
59
+ crossImpacts: relevantCrossImpacts,
60
+ });
61
+ try {
62
+ const response = await provider.generateText(prompt, {
63
+ maxTokens: 4000,
64
+ temperature: 0.1,
65
+ timeout: 60000,
66
+ systemPrompt: 'Return only valid JSON. Do not include markdown fences unless necessary.',
67
+ });
68
+ const parsed = parseTestDesignerResponse(response.text);
69
+ if (!parsed || parsed.testDesign.testCases.length === 0) {
70
+ warnings.push(`Test designer: no test cases returned for flow ${strategy.flowId}.`);
71
+ continue;
72
+ }
73
+ const validatedCases = parsed.testDesign.testCases
74
+ .filter((tc) => tc.name && tc.steps && tc.steps.length > 0)
75
+ .map((tc) => ({
76
+ name: tc.name,
77
+ type: VALID_TYPES.has(tc.type) ? tc.type : 'happy-path',
78
+ preconditions: Array.isArray(tc.preconditions) ? tc.preconditions : [],
79
+ steps: Array.isArray(tc.steps) ? tc.steps : [],
80
+ expectedOutcome: tc.expectedOutcome || '',
81
+ priority: (['P0', 'P1', 'P2'].includes(tc.priority) ? tc.priority : 'P2'),
82
+ rationale: tc.rationale || '',
83
+ }))
84
+ .slice(0, MAX_TEST_CASES_PER_FLOW);
85
+ if (validatedCases.length > 0) {
86
+ designs.push({
87
+ flowId: strategy.flowId,
88
+ flowName: strategy.flowName,
89
+ testCases: validatedCases,
90
+ });
91
+ }
92
+ }
93
+ catch (error) {
94
+ const message = error instanceof Error ? error.message : String(error);
95
+ warnings.push(`Test designer failed for flow ${strategy.flowId}: ${message}`);
96
+ }
97
+ }
98
+ ctx.testDesigns.push(...designs);
99
+ return {
100
+ role: this.role,
101
+ status: designs.length > 0 ? 'success' : 'partial',
102
+ output: designs,
103
+ usage: provider.getUsageStats(),
104
+ warnings,
105
+ };
106
+ }
107
+ }
@@ -0,0 +1,326 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import Anthropic from '@anthropic-ai/sdk';
4
+ import { LLMProviderError } from './provider_interface.js';
5
+ import { API_KEY_PATTERNS, sanitizeErrorMessage, withTimeout, validateAndSanitizeUrl } from './provider_utils.js';
6
+ import { BaseProvider } from './base_provider.js';
7
+ import { logger } from './logger.js';
8
+ /**
9
+ * Anthropic Provider - Claude AI models
10
+ *
11
+ * Features:
12
+ * - Highest quality AI (98% accuracy in testing)
13
+ * - Vision support (analyze screenshots, compare UI)
14
+ * - Fast response times (<1 second)
15
+ * - 200K token context window
16
+ * - Prompt caching (reduces costs by 90% on repeated prompts)
17
+ *
18
+ * Costs (Claude Sonnet 4.5):
19
+ * - Input: $3 per 1M tokens
20
+ * - Output: $15 per 1M tokens
21
+ * - Cached input: $0.30 per 1M tokens
22
+ * - Estimated: ~$30-80/month for autonomous testing
23
+ *
24
+ * Use cases:
25
+ * - Vision tasks (screenshot comparison)
26
+ * - Complex failure diagnosis
27
+ * - High-stakes production testing
28
+ * - When quality is paramount
29
+ *
30
+ * Models:
31
+ * - claude-sonnet-4-5-20250929 (recommended - best balance)
32
+ * - claude-opus-4-5-20251101 (highest quality, slower, more expensive)
33
+ * - claude-haiku-4-0-20250430 (fastest, cheapest, lower quality)
34
+ */
35
+ export class AnthropicProvider extends BaseProvider {
36
+ constructor(config) {
37
+ super();
38
+ this.name = 'anthropic';
39
+ this.capabilities = {
40
+ vision: true, // Full vision support
41
+ streaming: true,
42
+ maxTokens: 200000, // 200K context window
43
+ costPer1MInputTokens: 3, // $3 per 1M input tokens
44
+ costPer1MOutputTokens: 15, // $15 per 1M output tokens
45
+ supportsTools: true, // Function calling support
46
+ supportsPromptCaching: true, // Reduces costs by 90%
47
+ typicalResponseTimeMs: 800, // ~0.8 seconds
48
+ };
49
+ // SECURITY: Validate API key format
50
+ if (!API_KEY_PATTERNS.anthropic.test(config.apiKey)) {
51
+ throw new Error('Invalid API key format. Expected sk-ant-* format.');
52
+ }
53
+ // SECURITY: Validate and enforce HTTPS for remote connections
54
+ if (config.baseUrl) {
55
+ const validation = validateAndSanitizeUrl(config.baseUrl);
56
+ if (!validation.valid) {
57
+ throw new Error(`Invalid base URL: ${validation.warning}`);
58
+ }
59
+ if (validation.warning) {
60
+ logger.warn(`HTTPS required for remote URLs: ${validation.warning}`);
61
+ }
62
+ }
63
+ this.client = new Anthropic({
64
+ apiKey: config.apiKey,
65
+ baseURL: config.baseUrl,
66
+ maxRetries: 0,
67
+ });
68
+ this.model = config.model || 'claude-sonnet-4-5-20250929';
69
+ }
70
+ async generateText(prompt, options) {
71
+ this.checkBudget();
72
+ const startTime = Date.now();
73
+ try {
74
+ // SECURITY: Validate prompt length to prevent resource exhaustion
75
+ if (prompt.length > 10 * 1024 * 1024) {
76
+ throw new Error('Prompt exceeds maximum size (10MB)');
77
+ }
78
+ const response = await withTimeout(this.client.messages.create({
79
+ model: this.model,
80
+ max_tokens: options?.maxTokens || 4000,
81
+ temperature: options?.temperature,
82
+ top_p: options?.topP,
83
+ stop_sequences: options?.stopSequences,
84
+ system: options?.systemPrompt,
85
+ messages: [
86
+ {
87
+ role: 'user',
88
+ content: prompt,
89
+ },
90
+ ],
91
+ }), options?.timeout, 'generateText');
92
+ const responseTime = Date.now() - startTime;
93
+ const text = this.extractTextFromResponse(response);
94
+ // SECURITY: Type-safe usage extraction
95
+ const usage = this.extractUsageFromResponse(response.usage);
96
+ const cost = this.calculateCost(usage, this.capabilities.costPer1MInputTokens, this.capabilities.costPer1MOutputTokens);
97
+ // Update stats
98
+ this.updateStats(usage, responseTime, cost);
99
+ return {
100
+ text,
101
+ usage,
102
+ cost,
103
+ metadata: {
104
+ model: this.model,
105
+ responseTimeMs: responseTime,
106
+ stopReason: response.stop_reason,
107
+ stopSequence: response.stop_sequence,
108
+ },
109
+ };
110
+ }
111
+ catch (error) {
112
+ this.stats.failedRequests++;
113
+ throw new LLMProviderError(sanitizeErrorMessage(error, 'generateText'), this.name, this.extractStatusCode(error), error);
114
+ }
115
+ }
116
+ async analyzeImage(images, prompt, options) {
117
+ const startTime = Date.now();
118
+ try {
119
+ // SECURITY: Validate image array size
120
+ if (images.length === 0 || images.length > 20) {
121
+ throw new Error('Image count must be between 1 and 20');
122
+ }
123
+ // SECURITY: Validate prompt length
124
+ if (prompt.length > 10 * 1024 * 1024) {
125
+ throw new Error('Prompt exceeds maximum size (10MB)');
126
+ }
127
+ // Build content array with text and images
128
+ const content = [];
129
+ // Add prompt text first
130
+ content.push({
131
+ type: 'text',
132
+ text: prompt,
133
+ });
134
+ // Add each image
135
+ for (const image of images) {
136
+ // Validate media type
137
+ const mediaType = (image.mimeType || image.mediaType || 'image/png');
138
+ if (!['image/png', 'image/jpeg', 'image/webp', 'image/gif'].includes(mediaType)) {
139
+ throw new Error(`Unsupported image type: ${mediaType}`);
140
+ }
141
+ const data = image.data || image.base64 || '';
142
+ // SECURITY: Validate base64 data size (limit to 20MB per image)
143
+ if (data.length > 20 * 1024 * 1024) {
144
+ throw new Error('Image data exceeds maximum size (20MB)');
145
+ }
146
+ content.push({
147
+ type: 'image',
148
+ source: {
149
+ type: 'base64',
150
+ media_type: mediaType,
151
+ data: data,
152
+ },
153
+ });
154
+ // Add description if provided
155
+ if (image.description) {
156
+ content.push({
157
+ type: 'text',
158
+ text: `[Image: ${image.description}]`,
159
+ });
160
+ }
161
+ }
162
+ const response = await withTimeout(this.client.messages.create({
163
+ model: this.model,
164
+ max_tokens: options?.maxTokens || 4000,
165
+ temperature: options?.temperature,
166
+ top_p: options?.topP,
167
+ stop_sequences: options?.stopSequences,
168
+ system: options?.systemPrompt,
169
+ messages: [
170
+ {
171
+ role: 'user',
172
+ content,
173
+ },
174
+ ],
175
+ }), options?.timeout, 'analyzeImage');
176
+ const responseTime = Date.now() - startTime;
177
+ const text = this.extractTextFromResponse(response);
178
+ // SECURITY: Type-safe usage extraction
179
+ const usage = this.extractUsageFromResponse(response.usage);
180
+ const cost = this.calculateCost(usage, this.capabilities.costPer1MInputTokens, this.capabilities.costPer1MOutputTokens);
181
+ // Update stats
182
+ this.updateStats(usage, responseTime, cost);
183
+ return {
184
+ text,
185
+ usage,
186
+ cost,
187
+ metadata: {
188
+ model: this.model,
189
+ responseTimeMs: responseTime,
190
+ stopReason: response.stop_reason,
191
+ imageCount: images.length,
192
+ },
193
+ };
194
+ }
195
+ catch (error) {
196
+ this.stats.failedRequests++;
197
+ throw new LLMProviderError(sanitizeErrorMessage(error, 'analyzeImage'), this.name, this.extractStatusCode(error), error);
198
+ }
199
+ }
200
+ async *streamText(prompt, options) {
201
+ try {
202
+ // SECURITY: Validate prompt length
203
+ if (prompt.length > 10 * 1024 * 1024) {
204
+ throw new Error('Prompt exceeds maximum size (10MB)');
205
+ }
206
+ const stream = await withTimeout(this.client.messages.create({
207
+ model: this.model,
208
+ max_tokens: options?.maxTokens || 4000,
209
+ temperature: options?.temperature,
210
+ top_p: options?.topP,
211
+ stop_sequences: options?.stopSequences,
212
+ system: options?.systemPrompt,
213
+ messages: [
214
+ {
215
+ role: 'user',
216
+ content: prompt,
217
+ },
218
+ ],
219
+ stream: true,
220
+ }), options?.timeout, 'streamText');
221
+ for await (const event of stream) {
222
+ if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
223
+ yield event.delta.text;
224
+ }
225
+ }
226
+ // Note: Streaming doesn't provide detailed usage stats
227
+ // We increment request count but can't track exact tokens/cost
228
+ this.stats.requestCount++;
229
+ this.stats.lastUpdated = new Date();
230
+ }
231
+ catch (error) {
232
+ this.stats.failedRequests++;
233
+ throw new LLMProviderError(sanitizeErrorMessage(error, 'streamText'), this.name, this.extractStatusCode(error), error);
234
+ }
235
+ }
236
+ extractTextFromResponse(response) {
237
+ const textBlocks = response.content.filter((block) => block.type === 'text');
238
+ return textBlocks.map((block) => {
239
+ if (block.type === 'text') {
240
+ return block.text;
241
+ }
242
+ return '';
243
+ }).join('\n');
244
+ }
245
+ /**
246
+ * SECURITY: Type-safe usage extraction
247
+ * Avoids unsafe `as any` casts
248
+ */
249
+ extractUsageFromResponse(usage) {
250
+ return {
251
+ inputTokens: usage.input_tokens || 0,
252
+ outputTokens: usage.output_tokens || 0,
253
+ totalTokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),
254
+ cachedTokens: usage.cache_read_input_tokens ?? undefined,
255
+ };
256
+ }
257
+ /**
258
+ * SECURITY: Extract status code safely
259
+ */
260
+ extractStatusCode(error) {
261
+ if (error && typeof error === 'object') {
262
+ const err = error;
263
+ const status = err.status;
264
+ if (typeof status === 'number') {
265
+ return status;
266
+ }
267
+ }
268
+ return undefined;
269
+ }
270
+ /**
271
+ * Check if API key is valid and service is accessible
272
+ */
273
+ async checkHealth() {
274
+ try {
275
+ // Try a minimal request to verify API key
276
+ await withTimeout(this.client.messages.create({
277
+ model: this.model,
278
+ max_tokens: 10,
279
+ messages: [
280
+ {
281
+ role: 'user',
282
+ content: 'Hi',
283
+ },
284
+ ],
285
+ }), 5000, 'health check');
286
+ return {
287
+ healthy: true,
288
+ message: `Anthropic API is accessible`,
289
+ };
290
+ }
291
+ catch (error) {
292
+ return {
293
+ healthy: false,
294
+ message: `Anthropic API error: ${sanitizeErrorMessage(error, 'health check')}`,
295
+ };
296
+ }
297
+ }
298
+ }
299
+ /**
300
+ * Helper to check Anthropic setup
301
+ */
302
+ export async function checkAnthropicSetup(apiKey) {
303
+ if (!apiKey) {
304
+ return {
305
+ valid: false,
306
+ message: 'No API key provided',
307
+ estimatedMonthlyCost: 'N/A',
308
+ };
309
+ }
310
+ try {
311
+ const provider = new AnthropicProvider({ apiKey });
312
+ const health = await provider.checkHealth();
313
+ return {
314
+ valid: health.healthy,
315
+ message: health.message,
316
+ estimatedMonthlyCost: '$30-80 for autonomous testing (24 cycles/day)',
317
+ };
318
+ }
319
+ catch (error) {
320
+ return {
321
+ valid: false,
322
+ message: `Setup check failed: ${sanitizeErrorMessage(error, 'setup check')}`,
323
+ estimatedMonthlyCost: 'N/A',
324
+ };
325
+ }
326
+ }
@@ -0,0 +1,143 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { resolveConfig } from './agent/config.js';
4
+ import { appendPlanMetrics, } from './agent/plan.js';
5
+ import { analyzeImpact as analyzeImpactV2 } from './engine/impact_engine.js';
6
+ import { buildPlanFromImpact, renderCiSummaryMarkdown, writeCiSummary, writePlanReport, } from './engine/plan_builder.js';
7
+ import { getChangedFiles } from './agent/git.js';
8
+ import { getAdaptiveThresholds } from './agent/feedback.js';
9
+ import { loadDiffs } from './engine/diff_loader.js';
10
+ import { enrichImpactWithAI } from './engine/ai_enrichment.js';
11
+ import { LLMProviderFactory } from './provider_factory.js';
12
+ import { finalizeGeneratedTests } from './agent/handoff.js';
13
+ import { ingestTraceabilityInput, } from './agent/traceability_ingest.js';
14
+ import { captureTraceabilityInput, } from './agent/traceability_capture.js';
15
+ function resolveAgent(options, mode) {
16
+ const cwd = options.cwd || process.cwd();
17
+ const { config } = resolveConfig(cwd, options.configPath, {
18
+ ...options,
19
+ mode,
20
+ });
21
+ if (options.allowFallback) {
22
+ config.impact.allowFallback = true;
23
+ }
24
+ return config;
25
+ }
26
+ export function handoffGeneratedTests(options) {
27
+ return finalizeGeneratedTests(options);
28
+ }
29
+ export function ingestTraceability(options) {
30
+ const cwd = options.cwd || process.cwd();
31
+ const { config } = resolveConfig(cwd, options.configPath, {
32
+ path: options.path,
33
+ testsRoot: options.testsRoot,
34
+ mode: 'impact',
35
+ });
36
+ const reportRoot = config.testsRoot || config.path;
37
+ return ingestTraceabilityInput(reportRoot, config.impact.traceability, options.payload, options.options);
38
+ }
39
+ export function analyzeImpactDeterministic(options = {}) {
40
+ const config = resolveAgent(options, 'impact');
41
+ const reportRoot = config.testsRoot || config.path;
42
+ const gitResult = getChangedFiles(config.path, config.git.since, { includeUncommitted: config.git.includeUncommitted });
43
+ return analyzeImpactV2(gitResult.files, {
44
+ testsRoot: reportRoot,
45
+ routeFamilies: config.routeFamilies,
46
+ filteredTestFiles: gitResult.filteredTestFiles,
47
+ });
48
+ }
49
+ export function recommendTestsDeterministic(options = {}) {
50
+ const config = resolveAgent(options, 'impact');
51
+ const reportRoot = config.testsRoot || config.path;
52
+ const gitResult = getChangedFiles(config.path, config.git.since, { includeUncommitted: config.git.includeUncommitted });
53
+ const impact = analyzeImpactV2(gitResult.files, {
54
+ testsRoot: reportRoot,
55
+ routeFamilies: config.routeFamilies,
56
+ filteredTestFiles: gitResult.filteredTestFiles,
57
+ });
58
+ const adaptive = getAdaptiveThresholds(reportRoot);
59
+ const plan = buildPlanFromImpact(impact, config.policy, undefined, adaptive);
60
+ const planPath = writePlanReport(reportRoot, plan);
61
+ const ciSummaryMarkdown = renderCiSummaryMarkdown(plan);
62
+ const ciSummaryPath = writeCiSummary(reportRoot, ciSummaryMarkdown);
63
+ appendPlanMetrics(reportRoot, plan);
64
+ return { impact, plan, planPath, ciSummaryMarkdown, ciSummaryPath };
65
+ }
66
+ export async function recommendTestsAI(options = {}) {
67
+ const config = resolveAgent(options, 'impact');
68
+ const reportRoot = config.testsRoot || config.path;
69
+ const gitResult = getChangedFiles(config.path, config.git.since, { includeUncommitted: config.git.includeUncommitted });
70
+ const impact = analyzeImpactV2(gitResult.files, {
71
+ testsRoot: reportRoot,
72
+ routeFamilies: config.routeFamilies,
73
+ filteredTestFiles: gitResult.filteredTestFiles,
74
+ });
75
+ let aiEnrichment;
76
+ let provider;
77
+ try {
78
+ provider = await LLMProviderFactory.createFromPreference(config.llm.provider);
79
+ }
80
+ catch (error) {
81
+ const configuredProvider = config.llm.provider?.trim().toLowerCase();
82
+ const envProvider = process.env.LLM_PROVIDER?.trim().toLowerCase();
83
+ const shouldThrow = Boolean((configuredProvider && configuredProvider !== 'auto') ||
84
+ (envProvider && envProvider !== 'auto'));
85
+ if (shouldThrow) {
86
+ throw error;
87
+ }
88
+ }
89
+ if (provider) {
90
+ const diffs = loadDiffs(config.path, config.git.since, gitResult.files);
91
+ // Collect all known spec paths and scenario details from impacted features
92
+ const specSet = new Set();
93
+ const specDetailsMap = new Map();
94
+ for (const feature of impact.impactedFeatures) {
95
+ for (const s of feature.playwrightSpecs) {
96
+ specSet.add(s);
97
+ }
98
+ for (const detail of feature.playwrightSpecDetails) {
99
+ if (!specDetailsMap.has(detail.file)) {
100
+ specDetailsMap.set(detail.file, detail);
101
+ }
102
+ }
103
+ for (const detail of feature.cypressSpecDetails) {
104
+ if (!specDetailsMap.has(detail.file)) {
105
+ specDetailsMap.set(detail.file, detail);
106
+ }
107
+ }
108
+ }
109
+ aiEnrichment = await enrichImpactWithAI({
110
+ deterministicImpact: impact,
111
+ diffs,
112
+ provider,
113
+ specList: [...specSet],
114
+ specDetails: [...specDetailsMap.values()],
115
+ });
116
+ }
117
+ const adaptive = getAdaptiveThresholds(reportRoot);
118
+ const plan = buildPlanFromImpact(impact, config.policy, aiEnrichment, adaptive);
119
+ const planPath = writePlanReport(reportRoot, plan);
120
+ const ciSummaryMarkdown = renderCiSummaryMarkdown(plan);
121
+ const ciSummaryPath = writeCiSummary(reportRoot, ciSummaryMarkdown);
122
+ appendPlanMetrics(reportRoot, plan);
123
+ return { impact, plan, planPath, ciSummaryMarkdown, ciSummaryPath, aiEnrichment };
124
+ }
125
+ export function captureTraceability(options) {
126
+ const cwd = options.cwd || process.cwd();
127
+ const { config } = resolveConfig(cwd, options.configPath, {
128
+ path: options.path,
129
+ testsRoot: options.testsRoot,
130
+ mode: 'impact',
131
+ });
132
+ const reportRoot = config.testsRoot || config.path;
133
+ const captureOptions = {
134
+ appPath: config.path,
135
+ testsRoot: reportRoot,
136
+ reportPath: options.reportPath,
137
+ sinceRef: options.sinceRef || config.git.since,
138
+ outputPath: options.outputPath,
139
+ coverageMapPath: options.coverageMapPath,
140
+ changedFilesPath: options.changedFilesPath,
141
+ };
142
+ return captureTraceabilityInput(captureOptions);
143
+ }