@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,198 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { withRetry } from './resilience/retry.js';
4
+ import { CircuitBreaker } from './resilience/circuit_breaker.js';
5
+ /**
6
+ * Abstract base class for all LLM providers
7
+ * Eliminates 240+ lines of duplicate stats management code
8
+ * Provides common functionality for token tracking, cost calculation, and stats management
9
+ */
10
+ export class BudgetExceededError extends Error {
11
+ constructor(currentCost, budgetUSD) {
12
+ super(`Budget exceeded: $${currentCost.toFixed(4)} >= $${budgetUSD} limit`);
13
+ this.currentCost = currentCost;
14
+ this.budgetUSD = budgetUSD;
15
+ this.name = 'BudgetExceededError';
16
+ }
17
+ }
18
+ export class BaseProvider {
19
+ constructor() {
20
+ /** Tracks the current in-flight budget reservation for this provider instance. */
21
+ this._activeReservation = 0;
22
+ this.initializeStats();
23
+ }
24
+ /** Lazily get-or-create a circuit breaker shared across all instances of this provider type. */
25
+ get circuitBreaker() {
26
+ let cb = BaseProvider._sharedBreakers.get(this.name);
27
+ if (!cb) {
28
+ cb = new CircuitBreaker({
29
+ shouldCount: (error) => {
30
+ if (error instanceof BudgetExceededError)
31
+ return false;
32
+ if (!(error instanceof Error))
33
+ return true;
34
+ const msg = error.message.toLowerCase();
35
+ return msg.includes('429') || msg.includes('rate limit') ||
36
+ msg.includes('500') || msg.includes('502') || msg.includes('503') || msg.includes('504') ||
37
+ msg.includes('econnreset') || msg.includes('econnrefused') || msg.includes('etimedout') ||
38
+ msg.includes('overloaded') || msg.includes('socket hang up') || msg.includes('network error');
39
+ },
40
+ });
41
+ BaseProvider._sharedBreakers.set(this.name, cb);
42
+ }
43
+ return cb;
44
+ }
45
+ /**
46
+ * Set a hard budget limit. Once totalCost reaches this value,
47
+ * subsequent calls will throw BudgetExceededError.
48
+ */
49
+ setBudget(usd) {
50
+ this._budgetUSD = usd;
51
+ }
52
+ get budgetUSD() {
53
+ return this._budgetUSD;
54
+ }
55
+ /**
56
+ * Attach a shared budget ledger so aggregate cost across all providers
57
+ * in a crew run is checked before each LLM call.
58
+ */
59
+ setBudgetLedger(ledger) {
60
+ this._ledger = ledger;
61
+ }
62
+ /**
63
+ * Check budget and pre-reserve estimated cost for the upcoming LLM call.
64
+ *
65
+ * When a shared ledger exists, reserves an estimate derived from the provider's
66
+ * output token cost × maxTokens (default 4096). This blocks parallel agents from
67
+ * spending into the same headroom — like a credit card authorization hold.
68
+ *
69
+ * Self-healing: if a prior call failed without reaching updateStats(), the stale
70
+ * reservation is released here before placing the new one.
71
+ */
72
+ checkBudget() {
73
+ if (this._ledger) {
74
+ // Release stale reservation from a prior failed call that never hit updateStats
75
+ if (this._activeReservation > 0) {
76
+ this._ledger.release(this._activeReservation);
77
+ this._activeReservation = 0;
78
+ }
79
+ // Reserve estimated cost for the upcoming call
80
+ const estimate = this.estimateCallCost();
81
+ this._ledger.reserve(estimate);
82
+ this._activeReservation = estimate;
83
+ try {
84
+ this._ledger.check();
85
+ }
86
+ catch (err) {
87
+ // Budget exceeded — release reservation immediately so it doesn't leak
88
+ this._ledger.release(estimate);
89
+ this._activeReservation = 0;
90
+ throw err;
91
+ }
92
+ return;
93
+ }
94
+ if (this._budgetUSD !== undefined && this.stats.totalCost >= this._budgetUSD) {
95
+ throw new BudgetExceededError(this.stats.totalCost, this._budgetUSD);
96
+ }
97
+ }
98
+ /**
99
+ * Conservative cost estimate for the upcoming call.
100
+ * Uses maxTokens (or 4096 default) × output cost rate.
101
+ * Overestimating is safe — the reservation is replaced with actual cost in updateStats.
102
+ */
103
+ estimateCallCost() {
104
+ const outputTokenEstimate = 4096;
105
+ const costRate = this.capabilities?.costPer1MOutputTokens ?? 15; // default to ~Sonnet
106
+ return (outputTokenEstimate / 1000000) * costRate;
107
+ }
108
+ /**
109
+ * Initialize stats object with default values
110
+ */
111
+ initializeStats() {
112
+ this.stats = {
113
+ requestCount: 0,
114
+ totalInputTokens: 0,
115
+ totalOutputTokens: 0,
116
+ totalTokens: 0,
117
+ totalCost: 0,
118
+ averageResponseTimeMs: 0,
119
+ failedRequests: 0,
120
+ startTime: new Date(),
121
+ lastUpdated: new Date(),
122
+ };
123
+ }
124
+ /**
125
+ * Update stats with new usage data
126
+ * Maintains rolling average for response time
127
+ */
128
+ updateStats(usage, responseTime, cost) {
129
+ this.stats.requestCount++;
130
+ this.stats.totalInputTokens += usage.inputTokens;
131
+ this.stats.totalOutputTokens += usage.outputTokens;
132
+ this.stats.totalTokens += usage.totalTokens;
133
+ this.stats.totalCost += cost;
134
+ if (this._ledger) {
135
+ // Settle: release the estimate, record actual
136
+ if (this._activeReservation > 0) {
137
+ this._ledger.release(this._activeReservation);
138
+ this._activeReservation = 0;
139
+ }
140
+ this._ledger.record(cost);
141
+ }
142
+ // Update rolling average response time
143
+ const totalRequests = this.stats.requestCount;
144
+ this.stats.averageResponseTimeMs =
145
+ (this.stats.averageResponseTimeMs * (totalRequests - 1) + responseTime) / totalRequests;
146
+ this.stats.lastUpdated = new Date();
147
+ }
148
+ /**
149
+ * Get a copy of current usage stats
150
+ */
151
+ getUsageStats() {
152
+ return { ...this.stats };
153
+ }
154
+ /**
155
+ * Reset all usage stats to initial state
156
+ */
157
+ resetUsageStats() {
158
+ this.initializeStats();
159
+ }
160
+ /**
161
+ * Wrap an async call with circuit breaker + retry logic.
162
+ * Circuit breaker protects against cascading failures from a down provider;
163
+ * retry handles transient failures within a healthy circuit.
164
+ *
165
+ * Non-transient errors (budget, auth, validation) are thrown directly and
166
+ * bypass the circuit breaker so they don't incorrectly trip it.
167
+ */
168
+ retryCall(fn) {
169
+ return this.circuitBreaker.call(() => withRetry(fn, { maxRetries: 2, baseDelayMs: 1000, maxDelayMs: 10000, jitter: true }), () => { throw new Error(`${this.name} provider circuit open — too many consecutive failures`); });
170
+ }
171
+ /**
172
+ * Calculate cost for token usage, accounting for prompt caching discounts
173
+ * Cached tokens cost 90% less than regular tokens
174
+ */
175
+ calculateCost(usage, costPer1MInputTokens, costPer1MOutputTokens) {
176
+ // Calculate input token cost
177
+ let inputCost = 0;
178
+ // Cached tokens cost 90% less
179
+ if (usage.cachedTokens) {
180
+ const cachedCost = (usage.cachedTokens / 1000000) * (costPer1MInputTokens * 0.1);
181
+ const uncachedInputTokens = usage.inputTokens - usage.cachedTokens;
182
+ const uncachedCost = (uncachedInputTokens / 1000000) * costPer1MInputTokens;
183
+ inputCost = cachedCost + uncachedCost;
184
+ }
185
+ else {
186
+ inputCost = (usage.inputTokens / 1000000) * costPer1MInputTokens;
187
+ }
188
+ // Calculate output token cost
189
+ const outputCost = (usage.outputTokens / 1000000) * costPer1MOutputTokens;
190
+ return inputCost + outputCost;
191
+ }
192
+ }
193
+ /**
194
+ * Shared circuit breakers keyed by provider name (e.g., "anthropic", "openai").
195
+ * All instances of the same provider type share one breaker, so if Anthropic is
196
+ * down, ALL agents discover it after 3 total failures instead of 3 × N.
197
+ */
198
+ BaseProvider._sharedBreakers = new Map();
@@ -0,0 +1,58 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ /**
4
+ * Shared budget ledger — tracks aggregate cost across all provider instances
5
+ * in a single crew run. Prevents parallel agents from each seeing only 1/N
6
+ * of actual spend and overshooting the budget by N×limit.
7
+ *
8
+ * Usage: create one BudgetLedger per crew run, pass it to getCrewProvider(),
9
+ * which attaches it to each provider via setBudgetLedger().
10
+ */
11
+ import { BudgetExceededError } from './base_provider.js';
12
+ export class BudgetLedger {
13
+ constructor(limitUSD) {
14
+ this._totalCost = 0;
15
+ this._reserved = 0;
16
+ this._limitUSD = limitUSD;
17
+ }
18
+ get totalCost() {
19
+ return this._totalCost;
20
+ }
21
+ get limitUSD() {
22
+ return this._limitUSD;
23
+ }
24
+ /**
25
+ * Record actual cost from a completed LLM call.
26
+ */
27
+ record(cost) {
28
+ if (!Number.isFinite(cost) || cost < 0)
29
+ return;
30
+ this._totalCost += cost;
31
+ }
32
+ /**
33
+ * Pre-reserve estimated cost before an LLM call begins.
34
+ * Blocks parallel agents from spending into the same headroom.
35
+ * Like a credit card authorization hold.
36
+ */
37
+ reserve(estimate) {
38
+ if (!Number.isFinite(estimate) || estimate <= 0)
39
+ return;
40
+ this._reserved += estimate;
41
+ }
42
+ /**
43
+ * Release a prior reservation (after API response or on error).
44
+ */
45
+ release(estimate) {
46
+ this._reserved = Math.max(0, this._reserved - estimate);
47
+ }
48
+ /**
49
+ * Throws BudgetExceededError if committed cost + in-flight reservations
50
+ * have reached the limit.
51
+ */
52
+ check() {
53
+ const effective = this._totalCost + this._reserved;
54
+ if (effective >= this._limitUSD) {
55
+ throw new BudgetExceededError(effective, this._limitUSD);
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,85 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { ResponseCache, TTL } from './response_cache.js';
4
+ /**
5
+ * Decorator that adds transparent response caching to any LLMProvider.
6
+ *
7
+ * - `generateText()` checks the cache first and returns a cached response on hit.
8
+ * On a miss it delegates to the inner provider, stores the result, and returns it.
9
+ * - All other methods (analyzeImage, streamText, capabilities, usage stats)
10
+ * delegate directly to the wrapped provider.
11
+ *
12
+ * The TTL is selected based on the agent role: agents whose name contains
13
+ * "generat" use the shorter GENERATION TTL; all others use ANALYSIS.
14
+ */
15
+ export class CachedProvider {
16
+ constructor(inner, cache, cacheContext) {
17
+ this.inner = inner;
18
+ this.cache = cache;
19
+ this.ctx = cacheContext;
20
+ this.name = inner.name;
21
+ this.capabilities = inner.capabilities;
22
+ // Pick TTL based on agent role
23
+ this.ttlMs = cacheContext.agent.toLowerCase().includes('generat')
24
+ ? TTL.GENERATION
25
+ : TTL.ANALYSIS;
26
+ // Wire optional methods only when the inner provider supports them
27
+ if (inner.analyzeImage) {
28
+ this.analyzeImage = (images, prompt, options) => inner.analyzeImage(images, prompt, options);
29
+ }
30
+ if (inner.streamText) {
31
+ this.streamText = (prompt, options) => inner.streamText(prompt, options);
32
+ }
33
+ }
34
+ /**
35
+ * Generate text with cache-through semantics.
36
+ * On a cache hit the inner provider is never called, saving tokens and latency.
37
+ */
38
+ async generateText(prompt, options) {
39
+ const { agent, family, fileHashes } = this.ctx;
40
+ const model = this.inner.name;
41
+ // Check cache
42
+ const cached = this.cache.get(agent, family, fileHashes, model);
43
+ if (cached) {
44
+ return {
45
+ text: cached.response,
46
+ usage: {
47
+ inputTokens: cached.usage.inputTokens,
48
+ outputTokens: cached.usage.outputTokens,
49
+ totalTokens: cached.usage.inputTokens + cached.usage.outputTokens,
50
+ cachedTokens: cached.usage.inputTokens,
51
+ },
52
+ cost: 0, // No cost on cache hit
53
+ };
54
+ }
55
+ // Cache miss - call inner provider
56
+ const response = await this.inner.generateText(prompt, options);
57
+ // Store in cache
58
+ const key = ResponseCache.buildKey({ agent, family, fileHashes, model });
59
+ const entry = {
60
+ key,
61
+ family,
62
+ response: response.text,
63
+ usage: {
64
+ inputTokens: response.usage.inputTokens,
65
+ outputTokens: response.usage.outputTokens,
66
+ cost: response.cost,
67
+ },
68
+ createdAt: new Date().toISOString(),
69
+ ttlMs: this.ttlMs,
70
+ };
71
+ this.cache.set(entry);
72
+ return response;
73
+ }
74
+ getUsageStats() {
75
+ return this.inner.getUsageStats();
76
+ }
77
+ resetUsageStats() {
78
+ this.inner.resetUsageStats();
79
+ }
80
+ async checkHealth() {
81
+ return this.inner.checkHealth();
82
+ }
83
+ }
84
+ // Re-export for convenience
85
+ export { ResponseCache, TTL } from './response_cache.js';
@@ -0,0 +1,140 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import * as crypto from 'node:crypto';
6
+ /**
7
+ * TTL presets for different cache entry types.
8
+ */
9
+ export const TTL = {
10
+ /** 24 hours - for analysis results that change infrequently */
11
+ ANALYSIS: 24 * 60 * 60 * 1000,
12
+ /** 1 hour - for generated content that may need fresher context */
13
+ GENERATION: 1 * 60 * 60 * 1000,
14
+ };
15
+ /**
16
+ * Cross-run LLM response cache backed by JSON files.
17
+ *
18
+ * Stores entries as `{cacheDir}/{sha256}.json` using a content-addressed key
19
+ * derived from (agentRole + familyName + sorted file hashes + model).
20
+ */
21
+ export class ResponseCache {
22
+ constructor(workspaceRoot) {
23
+ this.cacheDir = path.join(workspaceRoot, '.e2e-ai-agents', 'cache');
24
+ }
25
+ /**
26
+ * Build a deterministic SHA-256 cache key from the provided parameters.
27
+ */
28
+ static buildKey(params) {
29
+ const sorted = [...params.fileHashes].sort();
30
+ const payload = params.agent + params.family + JSON.stringify(sorted) + params.model;
31
+ return crypto.createHash('sha256').update(payload).digest('hex');
32
+ }
33
+ /**
34
+ * Retrieve a cached response if it exists and has not expired.
35
+ * Returns `null` on cache miss or expiry.
36
+ */
37
+ get(agent, family, fileHashes, model) {
38
+ const key = ResponseCache.buildKey({ agent, family, fileHashes, model });
39
+ const filePath = path.join(this.cacheDir, `${key}.json`);
40
+ try {
41
+ if (!fs.existsSync(filePath)) {
42
+ return null;
43
+ }
44
+ const raw = fs.readFileSync(filePath, 'utf-8');
45
+ const entry = JSON.parse(raw);
46
+ const age = Date.now() - new Date(entry.createdAt).getTime();
47
+ if (age > entry.ttlMs) {
48
+ // Expired - clean up eagerly
49
+ fs.unlinkSync(filePath);
50
+ return null;
51
+ }
52
+ return entry;
53
+ }
54
+ catch {
55
+ // Corrupted or unreadable - treat as miss
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Write a cache entry to disk.
61
+ * Creates the cache directory if it does not yet exist.
62
+ */
63
+ set(entry) {
64
+ this.ensureCacheDir();
65
+ const filePath = path.join(this.cacheDir, `${entry.key}.json`);
66
+ fs.writeFileSync(filePath, JSON.stringify(entry, null, 2), 'utf-8');
67
+ }
68
+ /**
69
+ * Remove all cache entries belonging to the given family.
70
+ *
71
+ * Because the cache key is a one-way SHA-256 hash, we scan each file and
72
+ * check its stored `family` field. The directory is scoped to a single
73
+ * workspace so the scan is bounded.
74
+ */
75
+ invalidateFamily(familyName) {
76
+ if (!fs.existsSync(this.cacheDir)) {
77
+ return 0;
78
+ }
79
+ let deleted = 0;
80
+ const files = fs.readdirSync(this.cacheDir).filter((f) => f.endsWith('.json'));
81
+ for (const file of files) {
82
+ const filePath = path.join(this.cacheDir, file);
83
+ try {
84
+ const raw = fs.readFileSync(filePath, 'utf-8');
85
+ const entry = JSON.parse(raw);
86
+ if (entry.family === familyName) {
87
+ fs.unlinkSync(filePath);
88
+ deleted++;
89
+ }
90
+ }
91
+ catch {
92
+ // Skip unreadable files
93
+ }
94
+ }
95
+ return deleted;
96
+ }
97
+ /**
98
+ * Remove all expired entries from the cache directory.
99
+ * Returns the number of entries deleted.
100
+ */
101
+ prune() {
102
+ if (!fs.existsSync(this.cacheDir)) {
103
+ return 0;
104
+ }
105
+ let deleted = 0;
106
+ const now = Date.now();
107
+ const files = fs.readdirSync(this.cacheDir).filter((f) => f.endsWith('.json'));
108
+ for (const file of files) {
109
+ const filePath = path.join(this.cacheDir, file);
110
+ try {
111
+ const raw = fs.readFileSync(filePath, 'utf-8');
112
+ const entry = JSON.parse(raw);
113
+ const age = now - new Date(entry.createdAt).getTime();
114
+ if (age > entry.ttlMs) {
115
+ fs.unlinkSync(filePath);
116
+ deleted++;
117
+ }
118
+ }
119
+ catch {
120
+ // Corrupted file - remove it
121
+ try {
122
+ fs.unlinkSync(filePath);
123
+ deleted++;
124
+ }
125
+ catch {
126
+ // Ignore if removal also fails
127
+ }
128
+ }
129
+ }
130
+ return deleted;
131
+ }
132
+ /**
133
+ * Ensure the cache directory exists on disk.
134
+ */
135
+ ensureCacheDir() {
136
+ if (!fs.existsSync(this.cacheDir)) {
137
+ fs.mkdirSync(this.cacheDir, { recursive: true });
138
+ }
139
+ }
140
+ }
@@ -0,0 +1,74 @@
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 { runPipeline } from '../../pipeline/orchestrator.js';
5
+ export async function runAnalyzeCommand(args, autoConfig) {
6
+ if (!args.path && !autoConfig) {
7
+ console.error('Error: --path is required for analyze command');
8
+ process.exit(1);
9
+ }
10
+ const { config } = resolveConfig(process.cwd(), autoConfig, {
11
+ path: args.path,
12
+ profile: args.profile,
13
+ testsRoot: args.testsRoot,
14
+ mode: 'impact',
15
+ gitSince: args.gitSince,
16
+ llmProvider: args.llmProvider,
17
+ });
18
+ const testsRoot = config.testsRoot || config.path;
19
+ const analyzeStages = [
20
+ 'preprocess', 'impact', 'coverage',
21
+ ];
22
+ if (args.analyzeGenerate) {
23
+ analyzeStages.push('generation');
24
+ }
25
+ if (args.analyzeHeal || args.analyzeHealReport) {
26
+ analyzeStages.push('heal');
27
+ }
28
+ const result = await runPipeline({
29
+ appPath: config.path,
30
+ testsRoot,
31
+ gitSince: args.gitSince || config.git.since,
32
+ routeFamilies: config.routeFamilies,
33
+ apiSurface: config.apiSurface,
34
+ stages: analyzeStages,
35
+ generation: args.analyzeGenerate
36
+ ? {
37
+ defaultOutputDir: args.analyzeGenerateOutputDir || 'specs/functional/ai-assisted',
38
+ dryRun: args.dryRun,
39
+ }
40
+ : undefined,
41
+ heal: (args.analyzeHeal || args.analyzeHealReport)
42
+ ? {
43
+ mcp: args.pipelineMcp ?? true,
44
+ mcpAllowFallback: args.pipelineMcpAllowFallback ?? false,
45
+ mcpOnly: args.pipelineMcpOnly ?? false,
46
+ mcpCommandTimeoutMs: args.pipelineMcpTimeoutMs,
47
+ mcpRetries: args.pipelineMcpRetries ?? 1,
48
+ dryRun: args.dryRun,
49
+ }
50
+ : undefined,
51
+ playwrightReportPath: args.analyzeHealReport,
52
+ });
53
+ console.log(`Analyze report: ${result.reportPath}`);
54
+ console.log(`Analyze flows identified: ${result.report.summary.flowsIdentified}`);
55
+ console.log(`Analyze flows covered: ${result.report.summary.flowsCovered}`);
56
+ console.log(`Analyze flows uncovered: ${result.report.summary.flowsUncovered}`);
57
+ console.log(`Analyze overall confidence: ${result.report.summary.overallConfidence}`);
58
+ console.log(`Analyze route families: ${result.report.summary.routeFamiliesImpacted.join(', ') || 'none'}`);
59
+ if (result.generated && result.generated.length > 0) {
60
+ const written = result.generated.filter((g) => g.written).length;
61
+ console.log(`Analyze generated specs: ${result.generated.length} (written=${written})`);
62
+ for (const g of result.generated) {
63
+ console.log(` ${g.mode}: ${g.specPath}`);
64
+ }
65
+ }
66
+ if (result.healResult) {
67
+ const healed = result.healResult.summary.results.filter((r) => r.healStatus === 'success').length;
68
+ const healFailed = result.healResult.summary.results.filter((r) => r.healStatus === 'failed').length;
69
+ console.log(`Analyze heal targets: ${result.healResult.targets.length} (healed=${healed}, failed=${healFailed})`);
70
+ }
71
+ if (result.warnings.length > 0) {
72
+ console.log(`Analyze warnings: ${result.warnings.join(' | ')}`);
73
+ }
74
+ }
@@ -0,0 +1,106 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ /**
4
+ * Bootstrap command — takes a project with an Understand-Anything knowledge graph
5
+ * and generates route-families.json + initial test stubs.
6
+ */
7
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
8
+ import { join, resolve } from 'path';
9
+ import { logger, LogLevel } from '../../logger.js';
10
+ import { loadKnowledgeGraph, classifyProjectType, transformKGToFamilies } from '../../knowledge/kg_bridge.js';
11
+ import { serializeManifest } from '../../knowledge/route_families.js';
12
+ import { detectFramework, detectTestMode } from '../../adapters/framework_adapter.js';
13
+ import { resolveGenerationProfile } from '../../prompts/generation_profile.js';
14
+ class BootstrapError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = 'BootstrapError';
18
+ }
19
+ }
20
+ export async function runBootstrapCommand(args) {
21
+ const projectRoot = resolve(args.path || '.');
22
+ if (args.verbose)
23
+ logger.setLevel(LogLevel.DEBUG);
24
+ if (args.jsonOutput)
25
+ logger.setJsonMode(true);
26
+ logger.info('impact-gate bootstrap');
27
+ logger.info('=======================');
28
+ // ---------- Step 1: Check for knowledge graph ----------
29
+ const kgPath = args.bootstrapKgPath
30
+ ? resolve(args.bootstrapKgPath)
31
+ : join(projectRoot, '.understand-anything', 'knowledge-graph.json');
32
+ if (!existsSync(kgPath)) {
33
+ throw new BootstrapError(`Knowledge graph not found at: ${kgPath}\n\n` +
34
+ 'To bootstrap, first generate a knowledge graph for your project:\n' +
35
+ ' 1. Install Understand-Anything: npm install -g understand-anything\n' +
36
+ ' 2. Run: understand-anything analyze .\n' +
37
+ ' 3. Then run: impact-gate bootstrap\n\n' +
38
+ 'Or provide a path: impact-gate bootstrap --kg-path /path/to/knowledge-graph.json');
39
+ }
40
+ // ---------- Step 2: Load KG and classify ----------
41
+ logger.info('Loading knowledge graph...');
42
+ const kg = loadKnowledgeGraph(projectRoot, args.bootstrapKgPath ? kgPath : undefined);
43
+ if (!kg) {
44
+ throw new BootstrapError('Failed to load knowledge graph. Ensure it is valid JSON with nodes and edges arrays.');
45
+ }
46
+ const projectType = classifyProjectType(kg);
47
+ logger.info(`Project: ${kg.project.name || '(unnamed)'}`);
48
+ logger.info(`Type: ${projectType}`);
49
+ logger.info(`Frameworks: ${kg.project.frameworks.join(', ')}`);
50
+ logger.info(`Languages: ${kg.project.languages.join(', ')}`);
51
+ logger.info(`Nodes: ${kg.nodes.length}, Edges: ${kg.edges.length}`);
52
+ // ---------- Step 3: Transform KG to route families ----------
53
+ logger.info('');
54
+ logger.info('Generating route families from knowledge graph...');
55
+ const manifest = transformKGToFamilies(kg);
56
+ const maxFamilies = args.bootstrapMaxFamilies || 50;
57
+ if (manifest.families.length > maxFamilies) {
58
+ logger.info(`Limiting to top ${maxFamilies} families (of ${manifest.families.length} discovered). Use --max-families to adjust.`);
59
+ manifest.families = manifest.families.slice(0, maxFamilies);
60
+ }
61
+ const p0Count = manifest.families.filter((f) => f.priority === 'P0').length;
62
+ const p1Count = manifest.families.filter((f) => f.priority === 'P1').length;
63
+ const p2Count = manifest.families.filter((f) => f.priority === 'P2').length;
64
+ logger.info(`Discovered ${manifest.families.length} families: ${p0Count} P0, ${p1Count} P1, ${p2Count} P2`);
65
+ // ---------- Step 4: Detect/scaffold test framework ----------
66
+ const framework = detectFramework(projectRoot);
67
+ const testMode = args.bootstrapTestMode || detectTestMode(projectRoot, kg);
68
+ const profile = resolveGenerationProfile({ profile: args.profile, testMode }, kg);
69
+ logger.info(`Test framework: ${framework.name}`);
70
+ logger.info(`Test mode: ${testMode}`);
71
+ logger.info(`Generation profile: ${profile.projectName} (${profile.testFramework})`);
72
+ // ---------- Step 5: Write route-families.json ----------
73
+ const outputDir = join(projectRoot, '.e2e-ai-agents');
74
+ const outputPath = join(outputDir, 'route-families.json');
75
+ if (args.dryRun) {
76
+ logger.info('');
77
+ logger.info('Dry run — proposed manifest:');
78
+ console.log(serializeManifest(manifest));
79
+ }
80
+ else {
81
+ if (!existsSync(outputDir)) {
82
+ mkdirSync(outputDir, { recursive: true });
83
+ }
84
+ writeFileSync(outputPath, serializeManifest(manifest), 'utf-8');
85
+ logger.info(`Wrote ${outputPath}`);
86
+ }
87
+ // ---------- Step 6: Summary and next steps ----------
88
+ logger.info('');
89
+ logger.info('Bootstrap complete!');
90
+ logger.info('');
91
+ logger.info('Route families summary:');
92
+ for (const family of manifest.families.slice(0, 15)) {
93
+ const endpoints = family.apiEndpoints?.length || 0;
94
+ const endpointSuffix = endpoints > 0 ? ` (${endpoints} API endpoints)` : '';
95
+ logger.info(` ${family.priority || 'P2'} ${family.id}: ${family.routes.join(', ')}${endpointSuffix}`);
96
+ }
97
+ if (manifest.families.length > 15) {
98
+ logger.info(` ... and ${manifest.families.length - 15} more`);
99
+ }
100
+ logger.info('');
101
+ logger.info('Next steps:');
102
+ logger.info(' 1. Review and refine .e2e-ai-agents/route-families.json');
103
+ logger.info(' 2. Run `impact-gate train --enrich` to add LLM-enriched metadata');
104
+ logger.info(' 3. Run `impact-gate plan` to see what tests are needed');
105
+ logger.info(' 4. Run `impact-gate generate` to create test stubs');
106
+ }