@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,310 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
4
+ import { dirname, isAbsolute, resolve } from 'path';
5
+ import { getChangedFiles } from './git.js';
6
+ import { normalizePath } from './utils.js';
7
+ function asRecord(value) {
8
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
9
+ return null;
10
+ }
11
+ return value;
12
+ }
13
+ function asArray(value) {
14
+ return Array.isArray(value) ? value : [];
15
+ }
16
+ function resolveFilePath(cwd, value) {
17
+ if (isAbsolute(value)) {
18
+ return value;
19
+ }
20
+ return resolve(cwd, value);
21
+ }
22
+ function normalizeList(values) {
23
+ return Array.from(new Set(values
24
+ .map((value) => normalizePath(value))
25
+ .filter(Boolean)));
26
+ }
27
+ function parseStringArray(value) {
28
+ return normalizeList(asArray(value)
29
+ .filter((item) => typeof item === 'string')
30
+ .map((item) => item));
31
+ }
32
+ function isExecutedStatus(status) {
33
+ return status !== 'skipped';
34
+ }
35
+ function specExecuted(spec) {
36
+ const tests = asArray(spec.tests);
37
+ if (tests.length === 0) {
38
+ return false;
39
+ }
40
+ for (const testValue of tests) {
41
+ const testNode = asRecord(testValue);
42
+ if (!testNode) {
43
+ continue;
44
+ }
45
+ const testStatus = typeof testNode.status === 'string' ? testNode.status : undefined;
46
+ if (testStatus && isExecutedStatus(testStatus)) {
47
+ return true;
48
+ }
49
+ const outcome = typeof testNode.outcome === 'string' ? testNode.outcome : undefined;
50
+ if (outcome && isExecutedStatus(outcome)) {
51
+ return true;
52
+ }
53
+ const results = asArray(testNode.results);
54
+ for (const resultValue of results) {
55
+ const resultNode = asRecord(resultValue);
56
+ if (!resultNode) {
57
+ continue;
58
+ }
59
+ const status = typeof resultNode.status === 'string' ? resultNode.status : undefined;
60
+ if (status && isExecutedStatus(status)) {
61
+ return true;
62
+ }
63
+ }
64
+ }
65
+ return false;
66
+ }
67
+ function relativizePath(path, roots) {
68
+ const normalized = normalizePath(path);
69
+ for (const root of roots) {
70
+ const normalizedRoot = normalizePath(resolve(root));
71
+ if (normalized === normalizedRoot) {
72
+ return '.';
73
+ }
74
+ if (normalized.startsWith(`${normalizedRoot}/`)) {
75
+ return normalized.slice(normalizedRoot.length + 1);
76
+ }
77
+ }
78
+ return normalized;
79
+ }
80
+ function collectExecutedSpecs(value, roots, output) {
81
+ const node = asRecord(value);
82
+ if (!node) {
83
+ return;
84
+ }
85
+ const specs = asArray(node.specs);
86
+ for (const specValue of specs) {
87
+ const specNode = asRecord(specValue);
88
+ if (!specNode) {
89
+ continue;
90
+ }
91
+ const file = typeof specNode.file === 'string' ? specNode.file : '';
92
+ if (!file) {
93
+ continue;
94
+ }
95
+ if (!specExecuted(specNode)) {
96
+ continue;
97
+ }
98
+ output.add(relativizePath(file, roots));
99
+ }
100
+ const suites = asArray(node.suites);
101
+ for (const suite of suites) {
102
+ collectExecutedSpecs(suite, roots, output);
103
+ }
104
+ }
105
+ function loadPlaywrightExecutedSpecs(reportPath, roots) {
106
+ const raw = JSON.parse(readFileSync(reportPath, 'utf-8'));
107
+ const specs = new Set();
108
+ collectExecutedSpecs(raw, roots, specs);
109
+ return Array.from(specs).sort();
110
+ }
111
+ function loadChangedFilesFromPath(filePath) {
112
+ const rawText = readFileSync(filePath, 'utf-8');
113
+ const trimmed = rawText.trim();
114
+ if (!trimmed) {
115
+ return [];
116
+ }
117
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
118
+ const parsed = JSON.parse(trimmed);
119
+ if (Array.isArray(parsed)) {
120
+ return normalizeList(parsed.filter((value) => typeof value === 'string'));
121
+ }
122
+ const node = asRecord(parsed);
123
+ if (!node) {
124
+ return [];
125
+ }
126
+ if (Array.isArray(node.files)) {
127
+ return normalizeList(node.files.filter((value) => typeof value === 'string'));
128
+ }
129
+ if (Array.isArray(node.changedFiles)) {
130
+ return normalizeList(node.changedFiles.filter((value) => typeof value === 'string'));
131
+ }
132
+ return [];
133
+ }
134
+ return normalizeList(rawText
135
+ .split('\n')
136
+ .map((line) => line.trim())
137
+ .filter(Boolean));
138
+ }
139
+ function addCoverageEntry(map, test, files) {
140
+ if (!test || files.length === 0) {
141
+ return;
142
+ }
143
+ const normalizedTest = normalizePath(test);
144
+ if (!map.has(normalizedTest)) {
145
+ map.set(normalizedTest, new Set());
146
+ }
147
+ const bucket = map.get(normalizedTest);
148
+ for (const file of files) {
149
+ bucket?.add(normalizePath(file));
150
+ }
151
+ }
152
+ function loadCoverageMap(path) {
153
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
154
+ const map = new Map();
155
+ const appendTestEntry = (testValue, filesValue) => {
156
+ if (typeof testValue !== 'string') {
157
+ return;
158
+ }
159
+ const files = parseStringArray(filesValue);
160
+ addCoverageEntry(map, testValue, files);
161
+ };
162
+ if (Array.isArray(raw)) {
163
+ for (const entry of raw) {
164
+ const node = asRecord(entry);
165
+ if (!node) {
166
+ continue;
167
+ }
168
+ appendTestEntry(node.test, node.touchedFiles);
169
+ }
170
+ return map;
171
+ }
172
+ const node = asRecord(raw);
173
+ if (!node) {
174
+ return map;
175
+ }
176
+ for (const entry of asArray(node.tests)) {
177
+ const testNode = asRecord(entry);
178
+ if (!testNode) {
179
+ continue;
180
+ }
181
+ appendTestEntry(testNode.test, Array.isArray(testNode.touchedFiles) ? testNode.touchedFiles : testNode.files);
182
+ }
183
+ for (const entry of asArray(node.runs)) {
184
+ const runNode = asRecord(entry);
185
+ if (!runNode) {
186
+ continue;
187
+ }
188
+ const files = Array.isArray(runNode.touchedFiles)
189
+ ? runNode.touchedFiles
190
+ : (Array.isArray(runNode.coveredFiles) ? runNode.coveredFiles : runNode.files);
191
+ appendTestEntry(runNode.test, files);
192
+ }
193
+ const mappings = asArray(node.mappings);
194
+ for (const mapping of mappings) {
195
+ const mappingNode = asRecord(mapping);
196
+ if (!mappingNode || typeof mappingNode.file !== 'string' || !Array.isArray(mappingNode.tests)) {
197
+ continue;
198
+ }
199
+ const normalizedFile = normalizePath(mappingNode.file);
200
+ for (const test of mappingNode.tests) {
201
+ if (typeof test !== 'string') {
202
+ continue;
203
+ }
204
+ addCoverageEntry(map, test, [normalizedFile]);
205
+ }
206
+ }
207
+ const fileToTests = asRecord(node.fileToTests);
208
+ if (fileToTests) {
209
+ for (const [file, tests] of Object.entries(fileToTests)) {
210
+ if (!Array.isArray(tests)) {
211
+ continue;
212
+ }
213
+ for (const test of tests) {
214
+ if (typeof test !== 'string') {
215
+ continue;
216
+ }
217
+ addCoverageEntry(map, test, [normalizePath(file)]);
218
+ }
219
+ }
220
+ }
221
+ return map;
222
+ }
223
+ function coverageForSpec(specPath, coverageMap) {
224
+ const normalizedSpec = normalizePath(specPath);
225
+ const files = new Set();
226
+ const direct = coverageMap.get(normalizedSpec);
227
+ if (direct) {
228
+ for (const file of direct) {
229
+ files.add(file);
230
+ }
231
+ }
232
+ const prefix = `${normalizedSpec}#`;
233
+ for (const [key, value] of coverageMap.entries()) {
234
+ if (key.startsWith(prefix)) {
235
+ for (const file of value) {
236
+ files.add(file);
237
+ }
238
+ }
239
+ }
240
+ return Array.from(files).sort();
241
+ }
242
+ export function captureTraceabilityInput(options) {
243
+ const warnings = [];
244
+ const reportPath = resolveFilePath(process.cwd(), options.reportPath);
245
+ if (!existsSync(reportPath)) {
246
+ throw new Error(`Traceability report not found: ${reportPath}`);
247
+ }
248
+ const roots = [options.testsRoot, options.appPath].map((root) => resolve(root));
249
+ const executedSpecs = loadPlaywrightExecutedSpecs(reportPath, roots);
250
+ if (executedSpecs.length === 0) {
251
+ warnings.push('No executed tests found in Playwright report.');
252
+ }
253
+ let changedFiles = [];
254
+ if (options.changedFilesPath) {
255
+ const changedPath = resolveFilePath(process.cwd(), options.changedFilesPath);
256
+ if (existsSync(changedPath)) {
257
+ changedFiles = loadChangedFilesFromPath(changedPath);
258
+ }
259
+ else {
260
+ warnings.push(`Changed files path not found: ${changedPath}`);
261
+ }
262
+ }
263
+ else {
264
+ const diff = getChangedFiles(options.appPath, options.sinceRef, { includeUncommitted: false });
265
+ if (diff.error) {
266
+ warnings.push(`Git diff failed while building traceability input: ${diff.error}`);
267
+ }
268
+ changedFiles = diff.files;
269
+ }
270
+ changedFiles = normalizeList(changedFiles);
271
+ let coverageMap = new Map();
272
+ if (options.coverageMapPath) {
273
+ const coveragePath = resolveFilePath(process.cwd(), options.coverageMapPath);
274
+ if (existsSync(coveragePath)) {
275
+ coverageMap = loadCoverageMap(coveragePath);
276
+ }
277
+ else {
278
+ warnings.push(`Coverage map path not found: ${coveragePath}`);
279
+ }
280
+ }
281
+ const runs = executedSpecs.map((spec) => {
282
+ const mappedFiles = coverageForSpec(spec, coverageMap);
283
+ const touchedFiles = mappedFiles.length > 0 ? mappedFiles : changedFiles;
284
+ return {
285
+ test: spec,
286
+ touchedFiles,
287
+ timestamp: new Date().toISOString(),
288
+ };
289
+ }).filter((entry) => entry.touchedFiles.length > 0);
290
+ if (runs.length < executedSpecs.length && changedFiles.length === 0) {
291
+ warnings.push('Some executed tests had no coverage-map entries and no changed-files fallback.');
292
+ }
293
+ const outputPath = options.outputPath
294
+ ? resolveFilePath(process.cwd(), options.outputPath)
295
+ : resolve(options.testsRoot, '.e2e-ai-agents', 'traceability-input.json');
296
+ mkdirSync(dirname(outputPath), { recursive: true });
297
+ writeFileSync(outputPath, JSON.stringify({
298
+ schemaVersion: '1.0.0',
299
+ source: 'traceability-capture',
300
+ generatedAt: new Date().toISOString(),
301
+ runs,
302
+ }, null, 2), 'utf-8');
303
+ return {
304
+ outputPath,
305
+ testsSeen: executedSpecs.length,
306
+ runsGenerated: runs.length,
307
+ changedFilesUsed: changedFiles.length,
308
+ warnings,
309
+ };
310
+ }
@@ -0,0 +1,234 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
4
+ import { dirname, isAbsolute, join } from 'path';
5
+ import { normalizePath } from './utils.js';
6
+ const DEFAULT_OPTIONS = {
7
+ minHits: 1,
8
+ maxFilesPerTest: 200,
9
+ maxAgeDays: 120,
10
+ };
11
+ function resolvePath(root, value) {
12
+ if (isAbsolute(value)) {
13
+ return value;
14
+ }
15
+ return join(root, value);
16
+ }
17
+ function parseDate(value) {
18
+ const parsed = Date.parse(value);
19
+ if (Number.isNaN(parsed)) {
20
+ return null;
21
+ }
22
+ return parsed;
23
+ }
24
+ function safeReadJson(path) {
25
+ if (!existsSync(path)) {
26
+ return null;
27
+ }
28
+ try {
29
+ return JSON.parse(readFileSync(path, 'utf-8'));
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ function normalizeFiles(value) {
36
+ if (!Array.isArray(value)) {
37
+ return [];
38
+ }
39
+ return Array.from(new Set(value
40
+ .filter((entry) => typeof entry === 'string')
41
+ .map((entry) => normalizePath(entry))));
42
+ }
43
+ function normalizeTest(value) {
44
+ if (typeof value !== 'string') {
45
+ return null;
46
+ }
47
+ const normalized = normalizePath(value);
48
+ return normalized ? normalized : null;
49
+ }
50
+ function buildEntriesFromInput(payload) {
51
+ const warnings = [];
52
+ const entries = [];
53
+ const pushEntry = (testValue, filesValue, timestampValue) => {
54
+ const test = normalizeTest(testValue);
55
+ const files = normalizeFiles(filesValue);
56
+ if (!test || files.length === 0) {
57
+ return;
58
+ }
59
+ entries.push({
60
+ test,
61
+ touchedFiles: files,
62
+ timestamp: typeof timestampValue === 'string' ? timestampValue : undefined,
63
+ });
64
+ };
65
+ if (Array.isArray(payload)) {
66
+ for (const item of payload) {
67
+ if (!item || typeof item !== 'object') {
68
+ continue;
69
+ }
70
+ const entry = item;
71
+ pushEntry(entry.test, entry.touchedFiles, entry.timestamp);
72
+ }
73
+ if (entries.length === 0) {
74
+ warnings.push('Traceability input array had no valid entries.');
75
+ }
76
+ return { entries, warnings };
77
+ }
78
+ if (!payload || typeof payload !== 'object') {
79
+ warnings.push('Traceability input must be an object or array.');
80
+ return { entries, warnings };
81
+ }
82
+ const input = payload;
83
+ if (Array.isArray(input.tests)) {
84
+ for (const item of input.tests) {
85
+ pushEntry(item?.test, item?.touchedFiles, item?.timestamp);
86
+ }
87
+ }
88
+ if (Array.isArray(input.runs)) {
89
+ for (const item of input.runs) {
90
+ const files = Array.isArray(item?.touchedFiles) ? item?.touchedFiles : (Array.isArray(item?.coveredFiles) ? item?.coveredFiles : item?.files);
91
+ pushEntry(item?.test, files, item?.timestamp);
92
+ }
93
+ }
94
+ if (input.fileToTests && typeof input.fileToTests === 'object') {
95
+ for (const [file, tests] of Object.entries(input.fileToTests)) {
96
+ if (!Array.isArray(tests)) {
97
+ continue;
98
+ }
99
+ const normalizedFile = normalizePath(file);
100
+ for (const test of tests) {
101
+ pushEntry(test, [normalizedFile]);
102
+ }
103
+ }
104
+ }
105
+ if (Array.isArray(input.mappings)) {
106
+ for (const mapping of input.mappings) {
107
+ const file = typeof mapping?.file === 'string' ? normalizePath(mapping.file) : null;
108
+ if (!file || !Array.isArray(mapping.tests)) {
109
+ continue;
110
+ }
111
+ for (const test of mapping.tests) {
112
+ pushEntry(test, [file]);
113
+ }
114
+ }
115
+ }
116
+ if (entries.length === 0) {
117
+ warnings.push('Traceability input had no valid test<->file entries.');
118
+ }
119
+ return { entries, warnings };
120
+ }
121
+ function defaultState() {
122
+ return {
123
+ schemaVersion: '1.0.0',
124
+ updatedAt: new Date().toISOString(),
125
+ tests: {},
126
+ };
127
+ }
128
+ function loadState(path) {
129
+ const existing = safeReadJson(path);
130
+ if (!existing || typeof existing !== 'object' || !existing.tests) {
131
+ return defaultState();
132
+ }
133
+ return {
134
+ schemaVersion: '1.0.0',
135
+ updatedAt: existing.updatedAt || new Date().toISOString(),
136
+ tests: existing.tests,
137
+ };
138
+ }
139
+ function pruneByAge(state, maxAgeDays) {
140
+ const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
141
+ for (const [test, entry] of Object.entries(state.tests)) {
142
+ const lastSeen = parseDate(entry.lastSeen);
143
+ if (lastSeen === null) {
144
+ continue;
145
+ }
146
+ if (lastSeen < cutoff) {
147
+ delete state.tests[test];
148
+ }
149
+ }
150
+ }
151
+ function buildManifest(state, minHits, maxFilesPerTest) {
152
+ const tests = Object.entries(state.tests)
153
+ .map(([test, entry]) => {
154
+ const touchedFiles = Object.entries(entry.files)
155
+ .filter(([, hits]) => hits >= minHits)
156
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
157
+ .slice(0, maxFilesPerTest)
158
+ .map(([file]) => file);
159
+ const signalCount = Object.values(entry.files).reduce((acc, value) => acc + value, 0);
160
+ return {
161
+ test,
162
+ touchedFiles,
163
+ signalCount,
164
+ lastSeen: entry.lastSeen,
165
+ };
166
+ })
167
+ .filter((entry) => entry.touchedFiles.length > 0)
168
+ .sort((a, b) => a.test.localeCompare(b.test));
169
+ return {
170
+ schemaVersion: '1.0.0',
171
+ generatedAt: new Date().toISOString(),
172
+ tests,
173
+ };
174
+ }
175
+ function ensureParent(path) {
176
+ mkdirSync(dirname(path), { recursive: true });
177
+ }
178
+ export function ingestTraceabilityInput(rootPath, traceabilityConfig, inputPayload, options) {
179
+ const resolvedOptions = {
180
+ minHits: options?.minHits ?? DEFAULT_OPTIONS.minHits,
181
+ maxFilesPerTest: options?.maxFilesPerTest ?? DEFAULT_OPTIONS.maxFilesPerTest,
182
+ maxAgeDays: options?.maxAgeDays ?? DEFAULT_OPTIONS.maxAgeDays,
183
+ };
184
+ const warnings = [];
185
+ const manifestPath = resolvePath(rootPath, traceabilityConfig.manifestPath);
186
+ const statePath = join(dirname(manifestPath), 'traceability-state.json');
187
+ if (!traceabilityConfig.enabled) {
188
+ warnings.push('Traceability is disabled in config. Input was not ingested.');
189
+ return {
190
+ manifestPath,
191
+ statePath,
192
+ entriesIngested: 0,
193
+ testsTracked: 0,
194
+ edgesTracked: 0,
195
+ warnings,
196
+ };
197
+ }
198
+ const parsed = buildEntriesFromInput(inputPayload);
199
+ warnings.push(...parsed.warnings);
200
+ const state = loadState(statePath);
201
+ const now = new Date().toISOString();
202
+ for (const entry of parsed.entries) {
203
+ const bucket = state.tests[entry.test] || {
204
+ files: {},
205
+ seenCount: 0,
206
+ lastSeen: now,
207
+ };
208
+ bucket.seenCount += 1;
209
+ bucket.lastSeen = entry.timestamp || now;
210
+ for (const file of entry.touchedFiles) {
211
+ bucket.files[file] = (bucket.files[file] || 0) + 1;
212
+ }
213
+ state.tests[entry.test] = bucket;
214
+ }
215
+ pruneByAge(state, Math.max(1, resolvedOptions.maxAgeDays));
216
+ state.updatedAt = now;
217
+ const manifest = buildManifest(state, Math.max(1, resolvedOptions.minHits), Math.max(1, resolvedOptions.maxFilesPerTest));
218
+ let edgesTracked = 0;
219
+ for (const entry of manifest.tests) {
220
+ edgesTracked += entry.touchedFiles.length;
221
+ }
222
+ ensureParent(statePath);
223
+ ensureParent(manifestPath);
224
+ writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf-8');
225
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');
226
+ return {
227
+ manifestPath,
228
+ statePath,
229
+ entriesIngested: parsed.entries.length,
230
+ testsTracked: manifest.tests.length,
231
+ edgesTracked,
232
+ warnings,
233
+ };
234
+ }
@@ -0,0 +1,3 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ export {};
@@ -0,0 +1,138 @@
1
+ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2
+ // See LICENSE.txt for license information.
3
+ import { readFileSync, statSync } from 'fs';
4
+ import { basename, extname, posix, relative, resolve } from 'path';
5
+ const MAX_READ_BYTES = 1024 * 1024; // 1MB
6
+ const STOP_WORDS = new Set([
7
+ 'index',
8
+ 'component',
9
+ 'components',
10
+ 'page',
11
+ 'pages',
12
+ 'screen',
13
+ 'screens',
14
+ 'view',
15
+ 'views',
16
+ 'route',
17
+ 'routes',
18
+ 'feature',
19
+ 'features',
20
+ 'module',
21
+ 'modules',
22
+ 'flow',
23
+ 'flows',
24
+ 'test',
25
+ 'tests',
26
+ 'spec',
27
+ 'specs',
28
+ 'hooks',
29
+ 'hook',
30
+ 'context',
31
+ 'state',
32
+ 'store',
33
+ ]);
34
+ const GLOB_CHARS = /[*?[\]{}()!]/;
35
+ export function hasGlobChars(value) {
36
+ return GLOB_CHARS.test(value);
37
+ }
38
+ export function globToRegExp(pattern) {
39
+ const normalized = normalizePath(pattern);
40
+ let regex = '^';
41
+ let i = 0;
42
+ while (i < normalized.length) {
43
+ const char = normalized[i];
44
+ if (char === '*') {
45
+ const next = normalized[i + 1];
46
+ if (next === '*') {
47
+ regex += '.*';
48
+ i += 2;
49
+ continue;
50
+ }
51
+ regex += '[^/]*';
52
+ i += 1;
53
+ continue;
54
+ }
55
+ if (char === '?') {
56
+ regex += '[^/]';
57
+ i += 1;
58
+ continue;
59
+ }
60
+ if ('\\.[]{}()+-^$|'.includes(char)) {
61
+ regex += `\\${char}`;
62
+ }
63
+ else {
64
+ regex += char;
65
+ }
66
+ i += 1;
67
+ }
68
+ regex += '$';
69
+ return new RegExp(regex);
70
+ }
71
+ export function matchGlob(pathValue, pattern) {
72
+ const normalizedPath = normalizePath(pathValue);
73
+ const normalizedPattern = normalizePath(pattern);
74
+ if (!hasGlobChars(normalizedPattern)) {
75
+ if (normalizedPattern.endsWith('/')) {
76
+ return normalizedPath.startsWith(normalizedPattern);
77
+ }
78
+ return normalizedPath === normalizedPattern || normalizedPath.startsWith(`${normalizedPattern}/`);
79
+ }
80
+ const regex = globToRegExp(normalizedPattern);
81
+ return regex.test(normalizedPath);
82
+ }
83
+ export function safeReadTextFile(path) {
84
+ try {
85
+ const stats = statSync(path);
86
+ if (stats.size > MAX_READ_BYTES) {
87
+ return null;
88
+ }
89
+ return readFileSync(path, 'utf-8');
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ export function normalizePath(pathValue) {
96
+ return pathValue.split('\\').join('/');
97
+ }
98
+ export function toRelativePosix(root, filePath) {
99
+ const relative = posix.relative(normalizePath(root), normalizePath(filePath));
100
+ return relative.startsWith('../') ? normalizePath(filePath) : relative;
101
+ }
102
+ export function isPathWithinRoot(root, target) {
103
+ const rootAbs = resolve(root);
104
+ const targetAbs = resolve(target);
105
+ const rel = relative(rootAbs, targetAbs);
106
+ return rel === '' || (!rel.startsWith('..') && !rel.includes(`..${posix.sep}`) && !rel.includes('..\\'));
107
+ }
108
+ export function fileExtension(pathValue) {
109
+ return extname(pathValue).replace('.', '').toLowerCase();
110
+ }
111
+ export function baseNameWithoutExt(pathValue) {
112
+ const base = basename(pathValue);
113
+ const ext = extname(base);
114
+ return ext ? base.slice(0, -ext.length) : base;
115
+ }
116
+ function splitCamelCase(value) {
117
+ return value.replace(/([a-z])([A-Z])/g, '$1 $2');
118
+ }
119
+ export function tokenize(value) {
120
+ const normalized = splitCamelCase(value)
121
+ .replace(/[_\-.]/g, ' ')
122
+ .replace(/[^a-zA-Z0-9\s]/g, ' ')
123
+ .toLowerCase();
124
+ return normalized
125
+ .split(/\s+/)
126
+ .map((token) => token.trim())
127
+ .filter((token) => token.length > 2 && !STOP_WORDS.has(token));
128
+ }
129
+ export function uniqueTokens(tokens) {
130
+ return Array.from(new Set(tokens.filter(Boolean)));
131
+ }
132
+ export function titleCase(value) {
133
+ return value
134
+ .split(/[\s_-]+/)
135
+ .filter(Boolean)
136
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
137
+ .join(' ');
138
+ }