@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,386 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ // ---------------------------------------------------------------------------
4
+ // Tool definitions (Anthropic tool_use schema)
5
+ // ---------------------------------------------------------------------------
6
+ export const TOOL_DEFINITIONS = [
7
+ {
8
+ name: 'navigate',
9
+ description: 'Navigate to a URL. Use absolute paths starting with / or full URLs.',
10
+ input_schema: {
11
+ type: 'object',
12
+ properties: {
13
+ url: { type: 'string', description: 'URL or path to navigate to' },
14
+ },
15
+ required: ['url'],
16
+ },
17
+ },
18
+ {
19
+ name: 'click',
20
+ description: 'Click an element by its accessibility ref (e.g. @e4).',
21
+ input_schema: {
22
+ type: 'object',
23
+ properties: {
24
+ ref: { type: 'string', description: 'Accessibility ref like @e4' },
25
+ },
26
+ required: ['ref'],
27
+ },
28
+ },
29
+ {
30
+ name: 'fill',
31
+ description: 'Clear a field and type new text into it.',
32
+ input_schema: {
33
+ type: 'object',
34
+ properties: {
35
+ ref: { type: 'string', description: 'Accessibility ref of the input field' },
36
+ value: { type: 'string', description: 'Text to type' },
37
+ },
38
+ required: ['ref', 'value'],
39
+ },
40
+ },
41
+ {
42
+ name: 'press_key',
43
+ description: 'Press a keyboard key (e.g. Enter, Escape, Tab).',
44
+ input_schema: {
45
+ type: 'object',
46
+ properties: {
47
+ key: { type: 'string', description: 'Key name (Enter, Escape, Tab, etc.)' },
48
+ },
49
+ required: ['key'],
50
+ },
51
+ },
52
+ {
53
+ name: 'scroll',
54
+ description: 'Scroll the page or a specific element up or down.',
55
+ input_schema: {
56
+ type: 'object',
57
+ properties: {
58
+ direction: { type: 'string', enum: ['up', 'down'] },
59
+ ref: { type: 'string', description: 'Optional element ref to scroll within' },
60
+ },
61
+ required: ['direction'],
62
+ },
63
+ },
64
+ {
65
+ name: 'go_back',
66
+ description: 'Go back to the previous page.',
67
+ input_schema: {
68
+ type: 'object',
69
+ properties: {},
70
+ required: [],
71
+ },
72
+ },
73
+ {
74
+ name: 'take_screenshot',
75
+ description: 'Take an annotated screenshot for evidence or vision analysis. Use sparingly (costs tokens).',
76
+ input_schema: {
77
+ type: 'object',
78
+ properties: {
79
+ label: { type: 'string', description: 'Short label for the screenshot (used in filename)' },
80
+ },
81
+ required: ['label'],
82
+ },
83
+ },
84
+ {
85
+ name: 'get_text',
86
+ description: 'Read the text content of a specific element.',
87
+ input_schema: {
88
+ type: 'object',
89
+ properties: {
90
+ ref: { type: 'string', description: 'Accessibility ref' },
91
+ },
92
+ required: ['ref'],
93
+ },
94
+ },
95
+ {
96
+ name: 'report_finding',
97
+ description: 'Report a bug, visual issue, UX problem, or gap you discovered. Include expected/actual behavior and repro steps. Take before/after screenshots before calling this.',
98
+ input_schema: {
99
+ type: 'object',
100
+ properties: {
101
+ type: { type: 'string', enum: ['bug', 'visual-regression', 'ux-issue', 'gap'] },
102
+ severity: { type: 'string', enum: ['critical', 'high', 'medium', 'low', 'info'] },
103
+ summary: { type: 'string', description: 'What you found' },
104
+ repro_steps: {
105
+ type: 'array',
106
+ items: { type: 'string' },
107
+ description: 'Steps to reproduce',
108
+ },
109
+ screenshot_refs: {
110
+ type: 'array',
111
+ items: { type: 'string' },
112
+ description: 'Paths to before/after screenshots (from take_screenshot)',
113
+ },
114
+ expected_behavior: { type: 'string', description: 'What should have happened' },
115
+ actual_behavior: { type: 'string', description: 'What actually happened' },
116
+ },
117
+ required: ['type', 'severity', 'summary', 'repro_steps'],
118
+ },
119
+ },
120
+ {
121
+ name: 'mark_flow_done',
122
+ description: 'Mark the current flow as verified/explored. Call when you are done testing a flow.',
123
+ input_schema: {
124
+ type: 'object',
125
+ properties: {
126
+ flow_id: { type: 'string', description: 'ID of the flow being marked done' },
127
+ status: { type: 'string', enum: ['verified-ok', 'has-issues'] },
128
+ },
129
+ required: ['flow_id', 'status'],
130
+ },
131
+ },
132
+ {
133
+ name: 'switch_user',
134
+ description: 'Log out and log in as a different user role.',
135
+ input_schema: {
136
+ type: 'object',
137
+ properties: {
138
+ role: { type: 'string', description: 'Role of the user to switch to (e.g. admin, regular, guest)' },
139
+ },
140
+ required: ['role'],
141
+ },
142
+ },
143
+ {
144
+ name: 'wait_for',
145
+ description: 'Wait for an element condition or page state. Use after actions that trigger async changes (navigation, API calls, animations).',
146
+ input_schema: {
147
+ type: 'object',
148
+ properties: {
149
+ condition: {
150
+ type: 'string',
151
+ enum: ['visible', 'hidden', 'stable', 'networkidle'],
152
+ description: 'What to wait for: visible/hidden (element state), stable (no DOM changes for 1s), networkidle (no pending requests)',
153
+ },
154
+ ref: { type: 'string', description: 'Accessibility ref for element conditions (visible/hidden). Not needed for stable/networkidle.' },
155
+ timeout_ms: { type: 'number', description: 'Max wait time in ms (default 5000, max 15000)' },
156
+ },
157
+ required: ['condition'],
158
+ },
159
+ },
160
+ ];
161
+ export function executeTool(ctx, name, input) {
162
+ switch (name) {
163
+ case 'navigate': {
164
+ const url = String(input.url || '');
165
+ const fullUrl = url.startsWith('http') ? url : `${ctx.baseUrl}${url}`;
166
+ // Security: restrict navigation to the configured baseUrl domain
167
+ if (!isAllowedUrl(fullUrl, ctx.baseUrl)) {
168
+ return { output: `Blocked: navigation to "${fullUrl}" is outside the allowed domain (${ctx.baseUrl}).` };
169
+ }
170
+ const output = ctx.browser.open(fullUrl);
171
+ ctx.currentUrl = ctx.browser.getUrl();
172
+ return { output: output || `Navigated to ${ctx.currentUrl}`, navigated: true };
173
+ }
174
+ case 'click': {
175
+ const output = ctx.browser.click(String(input.ref));
176
+ return { output: output || `Clicked ${input.ref}` };
177
+ }
178
+ case 'fill': {
179
+ const ref = String(input.ref);
180
+ const value = String(input.value);
181
+ const output = ctx.browser.fill(ref, value);
182
+ // Redact value for password-like fields to avoid leaking credentials to LLM
183
+ const isSensitive = /password|passwd|pwd|secret|token/i.test(ref);
184
+ const displayValue = isSensitive ? '[REDACTED]' : `"${value}"`;
185
+ return { output: output || `Filled ${ref} with ${displayValue}` };
186
+ }
187
+ case 'press_key': {
188
+ const output = ctx.browser.press(String(input.key));
189
+ return { output: output || `Pressed ${input.key}` };
190
+ }
191
+ case 'scroll': {
192
+ const rawDir = String(input.direction);
193
+ if (rawDir !== 'up' && rawDir !== 'down') {
194
+ return { output: `Invalid scroll direction "${rawDir}". Must be "up" or "down".` };
195
+ }
196
+ const ref = input.ref ? String(input.ref) : undefined;
197
+ const output = ctx.browser.scroll(rawDir, ref);
198
+ return { output: output || `Scrolled ${rawDir}` };
199
+ }
200
+ case 'go_back': {
201
+ const output = ctx.browser.back();
202
+ ctx.currentUrl = ctx.browser.getUrl();
203
+ return { output: output || `Went back to ${ctx.currentUrl}` };
204
+ }
205
+ case 'take_screenshot': {
206
+ ctx.screenshotCounter++;
207
+ const label = String(input.label || 'evidence').replace(/[^a-zA-Z0-9_-]/g, '_');
208
+ const filename = `${String(ctx.screenshotCounter).padStart(3, '0')}-${label}.png`;
209
+ const path = `${ctx.screenshotDir}/${filename}`;
210
+ ctx.browser.screenshot(path);
211
+ return { output: `Screenshot saved: ${path}` };
212
+ }
213
+ case 'get_text': {
214
+ const text = ctx.browser.getText(String(input.ref));
215
+ return { output: text || '(empty)' };
216
+ }
217
+ case 'report_finding': {
218
+ const VALID_TYPES = new Set(['bug', 'visual-regression', 'ux-issue', 'gap']);
219
+ const VALID_SEVERITIES = new Set(['critical', 'high', 'medium', 'low', 'info']);
220
+ const rawType = String(input.type);
221
+ const rawSeverity = String(input.severity);
222
+ if (!VALID_TYPES.has(rawType)) {
223
+ return { output: `Invalid finding type "${rawType}". Must be one of: ${[...VALID_TYPES].join(', ')}.` };
224
+ }
225
+ if (!VALID_SEVERITIES.has(rawSeverity)) {
226
+ return { output: `Invalid severity "${rawSeverity}". Must be one of: ${[...VALID_SEVERITIES].join(', ')}.` };
227
+ }
228
+ if (!Array.isArray(input.repro_steps)) {
229
+ return { output: `Invalid repro_steps: expected an array of strings.` };
230
+ }
231
+ // Auto-capture console errors at time of finding
232
+ let autoConsoleErrors;
233
+ try {
234
+ const raw = ctx.browser.evaluateInternal('JSON.stringify(window.__consoleErrors || [])');
235
+ const parsed = JSON.parse(raw);
236
+ if (Array.isArray(parsed) && parsed.length > 0) {
237
+ autoConsoleErrors = parsed.map(String).slice(-10);
238
+ }
239
+ }
240
+ catch {
241
+ // Console error capture not available
242
+ }
243
+ // Auto-take screenshot if none provided
244
+ let autoScreenshot;
245
+ const screenshotRefs = Array.isArray(input.screenshot_refs)
246
+ ? input.screenshot_refs.map(String)
247
+ : undefined;
248
+ if (!screenshotRefs || screenshotRefs.length === 0) {
249
+ try {
250
+ const nextCount = ctx.screenshotCounter + 1;
251
+ const filename = `${String(nextCount).padStart(3, '0')}-finding-auto.png`;
252
+ const screenshotPath = `${ctx.screenshotDir}/${filename}`;
253
+ ctx.browser.screenshot(screenshotPath);
254
+ ctx.screenshotCounter = nextCount;
255
+ autoScreenshot = screenshotPath;
256
+ }
257
+ catch {
258
+ autoScreenshot = undefined;
259
+ }
260
+ }
261
+ const finding = {
262
+ id: `f-${crypto.randomUUID()}`,
263
+ type: rawType,
264
+ severity: rawSeverity,
265
+ summary: String(input.summary),
266
+ flow: ctx.currentFlow,
267
+ evidence: {
268
+ url: ctx.currentUrl,
269
+ reproSteps: input.repro_steps.map(String),
270
+ screenshotRefs: screenshotRefs || (autoScreenshot ? [autoScreenshot] : undefined),
271
+ screenshotPath: autoScreenshot || (screenshotRefs ? screenshotRefs[0] : undefined),
272
+ consoleErrors: autoConsoleErrors,
273
+ expectedBehavior: input.expected_behavior ? String(input.expected_behavior) : undefined,
274
+ actualBehavior: input.actual_behavior ? String(input.actual_behavior) : undefined,
275
+ },
276
+ timestamp: Date.now(),
277
+ };
278
+ return { output: `Finding recorded: [${finding.severity}] ${finding.summary}`, finding };
279
+ }
280
+ case 'mark_flow_done': {
281
+ const flowId = String(input.flow_id);
282
+ const rawStatus = String(input.status);
283
+ if (rawStatus !== 'verified-ok' && rawStatus !== 'has-issues') {
284
+ return { output: `Invalid status "${rawStatus}". Must be "verified-ok" or "has-issues".` };
285
+ }
286
+ return {
287
+ output: `Flow "${flowId}" marked as ${rawStatus}`,
288
+ flowDone: { flowId, status: rawStatus },
289
+ };
290
+ }
291
+ case 'wait_for': {
292
+ const condition = String(input.condition || '');
293
+ const VALID_CONDITIONS = new Set(['visible', 'hidden', 'stable', 'networkidle']);
294
+ if (!VALID_CONDITIONS.has(condition)) {
295
+ return { output: `Invalid condition "${condition}". Must be one of: ${[...VALID_CONDITIONS].join(', ')}.` };
296
+ }
297
+ const timeoutMs = Math.min(Math.max(Number(input.timeout_ms) || 5000, 500), 15000);
298
+ try {
299
+ if (condition === 'stable' || condition === 'networkidle') {
300
+ const waitMs = condition === 'networkidle' ? Math.min(timeoutMs, 3000) : 1000;
301
+ ctx.browser.evaluateInternal(`new Promise(r => setTimeout(r, ${waitMs}))`);
302
+ return { output: `Waited ${waitMs}ms for ${condition} (heuristic delay)` };
303
+ }
304
+ // Element-level wait: poll snapshot for ref presence/absence
305
+ const ref = input.ref ? String(input.ref) : undefined;
306
+ if (!ref) {
307
+ return { output: `Element condition "${condition}" requires a ref parameter.` };
308
+ }
309
+ const start = Date.now();
310
+ const wantVisible = condition === 'visible';
311
+ // Use word-boundary regex to avoid false positives (@e1 matching @e10)
312
+ const refPattern = new RegExp(`(?<![\\w@])${ref.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\w])`);
313
+ const pollIntervalMs = 300;
314
+ while (Date.now() - start < timeoutMs) {
315
+ const snap = ctx.browser.snapshot();
316
+ const found = refPattern.test(snap);
317
+ if ((wantVisible && found) || (!wantVisible && !found)) {
318
+ return { output: `Element ${ref} is now ${condition} (took ${Date.now() - start}ms)` };
319
+ }
320
+ // Synchronous in-process sleep via Atomics.wait (available in Node.js 8.10+)
321
+ const buf = new SharedArrayBuffer(4);
322
+ Atomics.wait(new Int32Array(buf), 0, 0, pollIntervalMs);
323
+ }
324
+ return { output: `Timeout: element ${ref} did not become ${condition} within ${timeoutMs}ms` };
325
+ }
326
+ catch (err) {
327
+ return { output: `wait_for error: ${String(err)}` };
328
+ }
329
+ }
330
+ case 'switch_user': {
331
+ const role = String(input.role);
332
+ const user = ctx.users?.find((u) => u.role === role);
333
+ if (!user) {
334
+ return { output: `No user configured for role "${role}". Available: ${(ctx.users || []).map((u) => u.role).join(', ')}` };
335
+ }
336
+ // Log out first, then log in as new user
337
+ try {
338
+ ctx.browser.open(`${ctx.baseUrl}/logout`);
339
+ }
340
+ catch {
341
+ // May not be logged in
342
+ }
343
+ ctx.browser.open(`${ctx.baseUrl}/login`);
344
+ // Use snapshot to find login fields, then fill
345
+ const snap = ctx.browser.snapshot();
346
+ const emailRef = extractRef(snap, 'email') || extractRef(snap, 'username') || '@e1';
347
+ const passRef = extractRef(snap, 'password') || '@e2';
348
+ ctx.browser.fill(emailRef, user.username);
349
+ ctx.browser.fill(passRef, user.password);
350
+ ctx.browser.press('Enter');
351
+ ctx.currentUrl = ctx.browser.getUrl();
352
+ // Redact credentials from LLM context — only expose role
353
+ return { output: `Switched to user role: ${user.role}` };
354
+ }
355
+ default:
356
+ return { output: `Unknown tool: ${name}` };
357
+ }
358
+ }
359
+ function isAllowedUrl(url, baseUrl) {
360
+ // Block dangerous schemes
361
+ const scheme = url.split(':')[0]?.toLowerCase();
362
+ if (scheme && !['http', 'https'].includes(scheme))
363
+ return false;
364
+ // Parse both URLs and compare origins (hostname + port)
365
+ try {
366
+ const target = new URL(url);
367
+ const base = new URL(baseUrl);
368
+ return target.origin === base.origin;
369
+ }
370
+ catch {
371
+ // If URL parsing fails, only allow relative paths (already prefixed with baseUrl)
372
+ return url.startsWith(baseUrl);
373
+ }
374
+ }
375
+ function extractRef(snapshot, fieldHint) {
376
+ // Look for lines containing the hint and extract the @eN ref
377
+ const lines = snapshot.split('\n');
378
+ for (const line of lines) {
379
+ if (line.toLowerCase().includes(fieldHint)) {
380
+ const match = line.match(/@e\d+/);
381
+ if (match)
382
+ return match[0];
383
+ }
384
+ }
385
+ return undefined;
386
+ }
@@ -0,0 +1,75 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { readFileSync } from 'fs';
4
+ import { LLMProviderFactory } from '../../provider_factory.js';
5
+ const VALID_TYPES = new Set(['bug', 'visual-regression', 'ux-issue', 'gap']);
6
+ const VALID_SEVERITIES = new Set(['critical', 'high', 'medium', 'low', 'info']);
7
+ const VISION_PROMPT = `You are a QA engineer analyzing a screenshot of a web application.
8
+ Look for these categories of issues:
9
+
10
+ 1. **Layout issues**: overlapping elements, misaligned content, broken grid, elements outside viewport
11
+ 2. **Visual issues**: truncated text, missing icons/images, broken styling, inconsistent spacing
12
+ 3. **UX issues**: unclear button labels, confusing navigation, missing feedback states, poor contrast
13
+ 4. **State issues**: loading spinners stuck, empty states without messaging, stale data indicators
14
+ 5. **Error states**: visible error messages, 404/500 pages, broken components
15
+
16
+ For each issue found, respond with a JSON array of objects:
17
+ [
18
+ {
19
+ "type": "bug" | "visual-regression" | "ux-issue",
20
+ "severity": "critical" | "high" | "medium" | "low" | "info",
21
+ "summary": "description of the issue"
22
+ }
23
+ ]
24
+
25
+ If no issues are found, respond with an empty array: []
26
+
27
+ Only report clear, actionable issues. Do not speculate about functionality you cannot see.`;
28
+ export async function analyzeScreenshot(screenshotPath, url, flow) {
29
+ const provider = await LLMProviderFactory.createFromEnv();
30
+ if (!provider.capabilities.vision || !provider.analyzeImage) {
31
+ return [];
32
+ }
33
+ let imageData;
34
+ try {
35
+ imageData = readFileSync(screenshotPath).toString('base64');
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ const response = await provider.analyzeImage([{ base64: imageData, mediaType: 'image/png' }], VISION_PROMPT, { maxTokens: 2000, temperature: 0.1 });
41
+ return parseVisionResponse(response.text, url, flow, screenshotPath);
42
+ }
43
+ function parseVisionResponse(text, url, flow, screenshotPath) {
44
+ // Extract JSON array from response
45
+ const jsonMatch = text.match(/\[[\s\S]*\]/);
46
+ if (!jsonMatch)
47
+ return [];
48
+ try {
49
+ const items = JSON.parse(jsonMatch[0]);
50
+ if (!Array.isArray(items))
51
+ return [];
52
+ return items
53
+ .filter((item) => {
54
+ const t = String(item.type || '');
55
+ const s = String(item.severity || '');
56
+ return VALID_TYPES.has(t) && VALID_SEVERITIES.has(s);
57
+ })
58
+ .map((item) => ({
59
+ id: `v-${Date.now()}-${crypto.randomUUID().slice(0, 8)}`,
60
+ type: String(item.type),
61
+ severity: String(item.severity),
62
+ summary: String(item.summary || 'Visual issue detected'),
63
+ flow,
64
+ evidence: {
65
+ url,
66
+ screenshotPath,
67
+ reproSteps: ['Captured via automated vision analysis'],
68
+ },
69
+ timestamp: Date.now(),
70
+ }));
71
+ }
72
+ catch {
73
+ return [];
74
+ }
75
+ }
@@ -0,0 +1,34 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { spawnSync } from 'child_process';
4
+ import { logger } from '../../logger.js';
5
+ import { safeEnv } from '../safe_env.js';
6
+ export function submitFeedback(config) {
7
+ const args = ['impact-gate', 'feedback'];
8
+ if (config.testsRoot) {
9
+ args.push('--tests-root', config.testsRoot);
10
+ }
11
+ logger.info('Submitting feedback to calibration system');
12
+ const result = spawnSync('npx', args, {
13
+ cwd: config.testsRoot || process.cwd(),
14
+ encoding: 'utf-8',
15
+ timeout: 30000,
16
+ env: safeEnv(),
17
+ });
18
+ if (result.error) {
19
+ logger.warn('Feedback submission spawn failed', {
20
+ error: result.error.message,
21
+ });
22
+ }
23
+ else if (result.signal) {
24
+ logger.warn('Feedback submission killed by signal', {
25
+ signal: result.signal,
26
+ });
27
+ }
28
+ else if (result.status !== 0) {
29
+ logger.warn('Feedback submission failed', {
30
+ status: result.status,
31
+ stderr: (result.stderr || '').slice(0, 200),
32
+ });
33
+ }
34
+ }
@@ -0,0 +1,145 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { mkdirSync, writeFileSync } from 'fs';
4
+ import { join } from 'path';
5
+ export function generateReport(config, phase1, phase2, verdict, generatedSpecs) {
6
+ const outputDir = config.outputDir || '.e2e-ai-agents';
7
+ mkdirSync(outputDir, { recursive: true });
8
+ const reportPath = join(outputDir, 'qa-report.json');
9
+ const summaryPath = join(outputDir, 'qa-summary.md');
10
+ const report = {
11
+ schemaVersion: '1.0.0',
12
+ generatedAt: new Date().toISOString(),
13
+ mode: config.mode,
14
+ config: {
15
+ baseUrl: config.baseUrl,
16
+ timeLimitMinutes: config.timeLimitMinutes,
17
+ budgetUSD: config.budgetUSD,
18
+ },
19
+ phase1,
20
+ phase2,
21
+ phase3: {
22
+ reportPath,
23
+ summaryPath,
24
+ verdict,
25
+ generatedSpecs,
26
+ },
27
+ verdict,
28
+ };
29
+ try {
30
+ writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf-8');
31
+ }
32
+ catch (err) {
33
+ throw new Error(`Failed to write report to ${reportPath}: ${err instanceof Error ? err.message : String(err)}`);
34
+ }
35
+ const markdown = renderMarkdown(report);
36
+ try {
37
+ writeFileSync(summaryPath, markdown, 'utf-8');
38
+ }
39
+ catch (err) {
40
+ throw new Error(`Failed to write summary to ${summaryPath}: ${err instanceof Error ? err.message : String(err)}`);
41
+ }
42
+ return {
43
+ reportPath,
44
+ summaryPath,
45
+ verdict,
46
+ generatedSpecs,
47
+ };
48
+ }
49
+ function renderMarkdown(report) {
50
+ const v = report.verdict;
51
+ const badge = v.decision === 'go' ? '✅ GO' : v.decision === 'no-go' ? '❌ NO-GO' : '⚠️ CONDITIONAL';
52
+ const lines = [
53
+ `# QA Agent Report — ${badge}`,
54
+ '',
55
+ `**Mode:** ${report.mode}`,
56
+ `**Base URL:** ${report.config.baseUrl}`,
57
+ `**Generated:** ${report.generatedAt}`,
58
+ '',
59
+ `## Verdict`,
60
+ '',
61
+ `**Decision:** ${badge}`,
62
+ `**Reason:** ${v.reason}`,
63
+ '',
64
+ `| Severity | Count |`,
65
+ `|----------|-------|`,
66
+ `| Critical | ${v.criticalFindings} |`,
67
+ `| High | ${v.highFindings} |`,
68
+ `| Medium | ${v.mediumFindings} |`,
69
+ `| Low | ${v.lowFindings} |`,
70
+ '',
71
+ ];
72
+ // Phase 1 summary
73
+ const specTotal = report.phase1.specResults.length;
74
+ const specPassed = report.phase1.specResults.reduce((s, r) => s + r.passed, 0);
75
+ const specFailed = report.phase1.specResults.reduce((s, r) => s + r.failed, 0);
76
+ lines.push(`## Phase 1: Scripted Tests`, '', `- Flows identified: ${report.phase1.flows.length}`, `- Specs run: ${specTotal} (${specPassed} passed, ${specFailed} failed)`, '');
77
+ // Phase 2 summary
78
+ lines.push(`## Phase 2: Autonomous Exploration`, '', `- Flows explored: ${report.phase2.flowsExplored.length}`, `- Actions taken: ${report.phase2.actionsCount}`, `- Duration: ${Math.round(report.phase2.durationMs / 1000)}s`, `- Cost: $${report.phase2.costUSD.toFixed(4)}`, `- Tokens: ${report.phase2.tokensUsed}`, '');
79
+ // Findings
80
+ if (report.phase2.findings.length > 0) {
81
+ lines.push(`## Findings`, '');
82
+ for (const f of report.phase2.findings) {
83
+ const dupNote = f.duplicateCount && f.duplicateCount > 1
84
+ ? ` (seen ${f.duplicateCount} times)`
85
+ : '';
86
+ lines.push(`### [${f.severity.toUpperCase()}] ${f.summary}${dupNote}`);
87
+ lines.push('');
88
+ lines.push(`- **Type:** ${f.type}`);
89
+ lines.push(`- **Flow:** ${f.flow}`);
90
+ lines.push(`- **URL:** ${f.evidence.url}`);
91
+ // Expected vs actual behavior
92
+ if (f.evidence.expectedBehavior || f.evidence.actualBehavior) {
93
+ const escapePipe = (s) => s.replace(/\|/g, '\\|');
94
+ lines.push('');
95
+ lines.push(`| Expected | Actual |`);
96
+ lines.push(`|----------|--------|`);
97
+ lines.push(`| ${escapePipe(f.evidence.expectedBehavior || '—')} | ${escapePipe(f.evidence.actualBehavior || '—')} |`);
98
+ lines.push('');
99
+ }
100
+ // Screenshot evidence (inline images)
101
+ if (f.evidence.screenshotRefs && f.evidence.screenshotRefs.length > 0) {
102
+ for (const ref of f.evidence.screenshotRefs) {
103
+ lines.push(`![Evidence](${ref})`);
104
+ }
105
+ }
106
+ else if (f.evidence.screenshotPath) {
107
+ lines.push(`![Evidence](${f.evidence.screenshotPath})`);
108
+ }
109
+ // Console errors
110
+ if (f.evidence.consoleErrors && f.evidence.consoleErrors.length > 0) {
111
+ lines.push('');
112
+ lines.push('**Console errors:**');
113
+ for (const err of f.evidence.consoleErrors.slice(0, 5)) {
114
+ lines.push(`- \`${err.replace(/`/g, '\\`')}\``);
115
+ }
116
+ }
117
+ if (f.evidence.reproSteps.length > 0) {
118
+ lines.push('');
119
+ lines.push('**Repro steps:**');
120
+ for (const step of f.evidence.reproSteps) {
121
+ lines.push(` 1. ${step}`);
122
+ }
123
+ }
124
+ lines.push('');
125
+ }
126
+ }
127
+ // Flow sign-offs
128
+ lines.push(`## Flow Sign-offs`, '');
129
+ lines.push(`| Flow | Status | Findings |`);
130
+ lines.push(`|------|--------|----------|`);
131
+ for (const s of v.flowSignoffs) {
132
+ const statusIcon = s.status === 'passed' ? '✅' : s.status === 'failed' ? '❌' : '⏭️';
133
+ lines.push(`| ${s.flowName} | ${statusIcon} ${s.status} | ${s.findings.length} |`);
134
+ }
135
+ lines.push('');
136
+ // Generated specs
137
+ if (report.phase3.generatedSpecs.length > 0) {
138
+ lines.push(`## Generated Specs`, '');
139
+ for (const spec of report.phase3.generatedSpecs) {
140
+ lines.push(`- ${spec}`);
141
+ }
142
+ lines.push('');
143
+ }
144
+ return lines.join('\n');
145
+ }