agentic-qe 3.13.0 → 3.13.1

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 (378) hide show
  1. package/.agents/skills/aqe-plan-quality/SKILL.md +25 -0
  2. package/.agents/skills/aqe-plan-quality/agents/openai.yaml +4 -0
  3. package/.agents/skills/aqe-plan-quality/references/qe-routing.md +22 -0
  4. package/.agents/skills/aqe-review-quality/SKILL.md +24 -0
  5. package/.agents/skills/aqe-review-quality/agents/openai.yaml +4 -0
  6. package/.agents/skills/aqe-review-quality/references/quality-gates.md +20 -0
  7. package/.agents/skills/aqe-test-change/SKILL.md +26 -0
  8. package/.agents/skills/aqe-test-change/agents/openai.yaml +4 -0
  9. package/.agents/skills/aqe-test-change/references/test-specialties.md +23 -0
  10. package/.claude/helpers/ruflo-hook.cjs +5 -1
  11. package/.claude/skills/skills-manifest.json +1 -1
  12. package/.codex/hooks/aqe-codex-hook.cjs +69 -0
  13. package/.codex/hooks/ruflo-codex-hook.cjs +94 -0
  14. package/.codex/hooks.json +169 -0
  15. package/CHANGELOG.md +94 -0
  16. package/assets/skills/skills-manifest.json +1 -1
  17. package/dist/cli/bundle.js +5 -5
  18. package/dist/cli/chunks/adapter-VRZNL53W.js +2 -0
  19. package/dist/cli/chunks/{agent-booster-wasm-ACX2DK7Y.js → agent-booster-wasm-4VM3DE42.js} +2 -2
  20. package/dist/cli/chunks/{agent-handler-B45WP4ZJ.js → agent-handler-ZDLMZQQX.js} +2 -2
  21. package/dist/cli/chunks/{agent-memory-branch-QQLZDE56.js → agent-memory-branch-P72MDHHV.js} +2 -2
  22. package/dist/cli/chunks/aqe-learning-engine-XCNMNERX.js +2 -0
  23. package/dist/cli/chunks/{arena-G3IKZAG5.js → arena-55FZGKEV.js} +4 -4
  24. package/dist/cli/chunks/{arena-SDB7723R.js → arena-GCRBQ26R.js} +2 -2
  25. package/dist/cli/chunks/{audit-GY46XUZA.js → audit-VYAYVLIV.js} +3 -3
  26. package/dist/cli/chunks/base-VZZNR4UR.js +2 -0
  27. package/dist/cli/chunks/{hnswlib-node-RJPBJU2Q.js → better-sqlite3-JDDFYVCX.js} +2 -2
  28. package/dist/cli/chunks/{brain-handler-347CYMPN.js → brain-handler-IUKMRGWO.js} +3 -3
  29. package/dist/cli/chunks/{branch-enumerator-Z3ULBFSM.js → branch-enumerator-TUI3RWLX.js} +2 -2
  30. package/dist/cli/chunks/{browser-OYEIHD7F.js → browser-NBQTZYX2.js} +2 -2
  31. package/dist/cli/chunks/browser-workflow-5DZNIFUY.js +2 -0
  32. package/dist/cli/chunks/{chunk-2NRZYQSF.js → chunk-23MT7OBY.js} +2 -2
  33. package/dist/cli/chunks/{chunk-7UNY32PU.js → chunk-2CQAWYYE.js} +1 -1
  34. package/dist/cli/chunks/{chunk-ZLXBNNNT.js → chunk-2D2XFUKI.js} +2 -2
  35. package/dist/cli/chunks/{chunk-SHCTEXNH.js → chunk-2G2QWV7B.js} +2 -2
  36. package/dist/cli/chunks/{chunk-TZ73SXQ5.js → chunk-2ISLQU3G.js} +1 -1
  37. package/dist/cli/chunks/{chunk-VLNPJAVH.js → chunk-2OM3TDC4.js} +1 -1
  38. package/dist/cli/chunks/{chunk-JGM6XCCP.js → chunk-2XZ4BHWS.js} +1 -1
  39. package/dist/cli/chunks/{chunk-32ZGV4Q4.js → chunk-3F4XH4ZA.js} +1 -1
  40. package/dist/cli/chunks/{chunk-RDU4WTV2.js → chunk-3K4YC3GC.js} +2 -2
  41. package/dist/cli/chunks/chunk-3KGCBAUH.js +2 -0
  42. package/dist/cli/chunks/{chunk-DYUC7WFA.js → chunk-3Y6CHW67.js} +1 -1
  43. package/dist/cli/chunks/{chunk-3JVUWKCO.js → chunk-4QMWWYNU.js} +2 -2
  44. package/dist/cli/chunks/{chunk-L4LLA5U7.js → chunk-4WGSMODQ.js} +1 -1
  45. package/dist/cli/chunks/{chunk-KUA4HHU6.js → chunk-55WDVSCM.js} +2 -2
  46. package/dist/cli/chunks/{chunk-RVJPWRV6.js → chunk-5BB5DUL4.js} +2 -2
  47. package/dist/cli/chunks/{chunk-ZOXWASCC.js → chunk-6C3MZLYW.js} +2 -2
  48. package/dist/cli/chunks/{chunk-CFVEDUTW.js → chunk-6QKQFHS7.js} +2 -2
  49. package/dist/cli/chunks/{chunk-YFGAHNCG.js → chunk-6XZXMEK4.js} +3 -3
  50. package/dist/cli/chunks/{chunk-Z6QCOZ2H.js → chunk-7D7XFZZI.js} +2 -2
  51. package/dist/cli/chunks/{chunk-AO7AHX6K.js → chunk-7WEHZCSK.js} +2 -2
  52. package/dist/cli/chunks/{chunk-K5N6SLHO.js → chunk-A2MG3YXO.js} +1 -1
  53. package/dist/cli/chunks/{chunk-LXPB7H2P.js → chunk-AHTOWWSE.js} +1 -1
  54. package/dist/cli/chunks/{chunk-U2SW6KK5.js → chunk-AOMXMFDH.js} +2 -2
  55. package/dist/cli/chunks/{chunk-VSNRPMAZ.js → chunk-ARTLSAXO.js} +2 -2
  56. package/dist/cli/chunks/{chunk-FBBZHATF.js → chunk-AY7S7AWN.js} +1 -1
  57. package/dist/cli/chunks/{chunk-CYL2FV23.js → chunk-AYYDO52G.js} +2 -2
  58. package/dist/cli/chunks/chunk-BBLWZT5I.js +2 -0
  59. package/dist/cli/chunks/{chunk-QTU3CVOB.js → chunk-BF5BKSDU.js} +2 -2
  60. package/dist/cli/chunks/{chunk-CWUBOLKY.js → chunk-BOCEOLLJ.js} +2 -2
  61. package/dist/cli/chunks/{chunk-FL3BM54K.js → chunk-CE6LYEHT.js} +1 -1
  62. package/dist/cli/chunks/{chunk-THBTN7XB.js → chunk-CWP4RMOM.js} +2 -2
  63. package/dist/cli/chunks/{chunk-Q7PBGNUD.js → chunk-CWXDL7AH.js} +1 -1
  64. package/dist/cli/chunks/{chunk-RVRBTOWX.js → chunk-DTRFZD7N.js} +2 -2
  65. package/dist/cli/chunks/{chunk-IZRLIWFN.js → chunk-DVPGQG4W.js} +2 -2
  66. package/dist/cli/chunks/{chunk-3NOCK6ED.js → chunk-E4D47QTF.js} +2 -2
  67. package/dist/cli/chunks/{chunk-FQLWQWRU.js → chunk-EAKHU5YX.js} +3 -3
  68. package/dist/cli/chunks/{chunk-56WZFXTQ.js → chunk-EGMGOWCE.js} +2 -2
  69. package/dist/cli/chunks/{chunk-OXXMVQDF.js → chunk-ELMUHNXN.js} +2 -2
  70. package/dist/cli/chunks/{chunk-SNTUKW4Q.js → chunk-EVDYFGVH.js} +2 -2
  71. package/dist/cli/chunks/{chunk-RLCWR7TS.js → chunk-FDUSWM6O.js} +98 -88
  72. package/dist/cli/chunks/{chunk-D3MPV5G7.js → chunk-FM272B4O.js} +2 -2
  73. package/dist/cli/chunks/{chunk-DRIJYTSK.js → chunk-FQUUMC57.js} +2 -2
  74. package/dist/cli/chunks/{chunk-5KAT6WBQ.js → chunk-FQXQJMSF.js} +2 -2
  75. package/dist/cli/chunks/{chunk-BCKTBGDM.js → chunk-FRAGSKXQ.js} +3 -3
  76. package/dist/cli/chunks/{chunk-SRQ3CPJE.js → chunk-GASOBSNB.js} +4 -4
  77. package/dist/cli/chunks/{chunk-GTUFX7AR.js → chunk-GJEEPKAT.js} +2 -2
  78. package/dist/cli/chunks/{chunk-5EIOQCGN.js → chunk-GOV2MHLV.js} +2 -2
  79. package/dist/cli/chunks/{chunk-QI4CGJNK.js → chunk-GTPZVLL6.js} +1 -1
  80. package/dist/cli/chunks/chunk-H7YZ2YF2.js +3 -0
  81. package/dist/cli/chunks/{chunk-ANIDFJCT.js → chunk-HFI5PHG5.js} +3 -3
  82. package/dist/cli/chunks/{chunk-2VQVEQS4.js → chunk-HUMQU4ES.js} +2 -2
  83. package/dist/cli/chunks/{chunk-VHYMSZNF.js → chunk-HYIRFJDB.js} +2 -2
  84. package/dist/cli/chunks/{chunk-A4QLGPYO.js → chunk-IBSBOHUX.js} +2 -2
  85. package/dist/cli/chunks/{chunk-6SXKCIN5.js → chunk-IJA4WS7B.js} +1 -1
  86. package/dist/cli/chunks/{chunk-3GSYD5SL.js → chunk-IJP42OGW.js} +2 -2
  87. package/dist/cli/chunks/{chunk-PERJO2DY.js → chunk-IMQKEFW6.js} +1 -1
  88. package/dist/cli/chunks/{chunk-ZEIG5IQ4.js → chunk-INYS35DV.js} +2 -2
  89. package/dist/cli/chunks/{chunk-J3L52EA4.js → chunk-IV2VCR75.js} +5 -5
  90. package/dist/cli/chunks/{chunk-TVMFH5N2.js → chunk-IZO6TPGX.js} +2 -2
  91. package/dist/cli/chunks/{chunk-ZJG6N2OK.js → chunk-J45DX3IK.js} +1 -1
  92. package/dist/cli/chunks/{chunk-HL2QMM4M.js → chunk-J4T6D2OQ.js} +2 -2
  93. package/dist/cli/chunks/{chunk-5ICQL42E.js → chunk-JAPOMPFD.js} +2 -2
  94. package/dist/cli/chunks/{chunk-L2SFGFE6.js → chunk-JELNVHBF.js} +1 -1
  95. package/dist/cli/chunks/{chunk-RSFIOR2I.js → chunk-JOTNKZ7A.js} +87 -87
  96. package/dist/cli/chunks/{chunk-34PEINFS.js → chunk-KNWDXI3I.js} +2 -2
  97. package/dist/cli/chunks/{chunk-FUU32QY5.js → chunk-KW5NBORV.js} +2 -2
  98. package/dist/cli/chunks/{chunk-N5MMBA35.js → chunk-L7IOTWWY.js} +1 -1
  99. package/dist/cli/chunks/{chunk-RJZRWVL4.js → chunk-LJQ27PUE.js} +1 -1
  100. package/dist/cli/chunks/{chunk-QQB55ZJJ.js → chunk-LSKQUUUN.js} +2 -2
  101. package/dist/cli/chunks/{chunk-NETN3OUG.js → chunk-LSZZQ7H6.js} +1 -1
  102. package/dist/cli/chunks/{chunk-IYDYJ33J.js → chunk-LTKNCYMO.js} +2 -2
  103. package/dist/cli/chunks/{chunk-6DTOGSDV.js → chunk-LTWT4GZD.js} +4 -4
  104. package/dist/cli/chunks/{chunk-NQNKKVNO.js → chunk-LVHMXGDI.js} +3 -3
  105. package/dist/cli/chunks/{chunk-3UHEZ5HZ.js → chunk-M3T6FB54.js} +2 -2
  106. package/dist/cli/chunks/{chunk-ZJIX5FGQ.js → chunk-MAYZTGJ2.js} +2 -2
  107. package/dist/cli/chunks/{chunk-3K4SF57Q.js → chunk-MCIO7BDK.js} +1 -1
  108. package/dist/cli/chunks/{chunk-A7GLWWSE.js → chunk-MPD7RR4P.js} +1 -1
  109. package/dist/cli/chunks/{chunk-FAQLI3P5.js → chunk-MUFYDKVC.js} +2 -2
  110. package/dist/cli/chunks/{chunk-XFCWYQHW.js → chunk-MX5ZDKRR.js} +2 -2
  111. package/dist/cli/chunks/{chunk-MBCGI3M2.js → chunk-MXKHIZVM.js} +5 -5
  112. package/dist/cli/chunks/chunk-MY47CR27.js +2 -0
  113. package/dist/cli/chunks/chunk-N7WAZ2Y6.js +2 -0
  114. package/dist/cli/chunks/{chunk-VC6EXDGY.js → chunk-NHV4PTG6.js} +2 -2
  115. package/dist/cli/chunks/{chunk-LBE2P6UC.js → chunk-NP4CP3LR.js} +2 -2
  116. package/dist/cli/chunks/{chunk-6AOBLBR4.js → chunk-OCKTPTQ7.js} +2 -2
  117. package/dist/cli/chunks/{chunk-ES7WCYOU.js → chunk-OE4B6LDZ.js} +1 -1
  118. package/dist/cli/chunks/{chunk-IPHLXAMX.js → chunk-OPQY2333.js} +2 -2
  119. package/dist/cli/chunks/{chunk-7DMXCCSD.js → chunk-ORDH4VPL.js} +1 -1
  120. package/dist/cli/chunks/{chunk-HTPM3URI.js → chunk-P4Y3G6OB.js} +2 -2
  121. package/dist/cli/chunks/{chunk-TNRIGQ6U.js → chunk-PIOO2M4W.js} +2 -2
  122. package/dist/cli/chunks/{chunk-BGYLNCL6.js → chunk-PKMCZFET.js} +2 -2
  123. package/dist/cli/chunks/{chunk-G7FMYFTN.js → chunk-QES4QHQW.js} +1 -1
  124. package/dist/cli/chunks/{chunk-UIPPJKON.js → chunk-QG6BXSNJ.js} +2 -2
  125. package/dist/cli/chunks/{chunk-7YXT6BXN.js → chunk-QLOOW23R.js} +3 -3
  126. package/dist/cli/chunks/{chunk-CQFT7H3F.js → chunk-RSCGBHLM.js} +2 -2
  127. package/dist/cli/chunks/{chunk-QCEW4ZDW.js → chunk-RZ6CO3RZ.js} +2 -2
  128. package/dist/cli/chunks/{chunk-OETDMOOE.js → chunk-S6F3IJMK.js} +1 -1
  129. package/dist/cli/chunks/{chunk-KVL63BSU.js → chunk-S6VNPKHO.js} +1 -1
  130. package/dist/cli/chunks/{chunk-BUGWPTMF.js → chunk-SHWXADCI.js} +2 -2
  131. package/dist/cli/chunks/{chunk-FQY3UTGA.js → chunk-SPJQJWGK.js} +2 -2
  132. package/dist/cli/chunks/{chunk-BOVH6WSM.js → chunk-SS6K4FBH.js} +2 -2
  133. package/dist/cli/chunks/{chunk-4BESADKE.js → chunk-SXADKQJN.js} +2 -2
  134. package/dist/cli/chunks/{chunk-USMDIIHY.js → chunk-TBQTGQ75.js} +2 -2
  135. package/dist/cli/chunks/{chunk-4BDLD7V2.js → chunk-TDGE52HJ.js} +1 -1
  136. package/dist/cli/chunks/{chunk-JPIBPKBP.js → chunk-THFLRJT6.js} +3 -3
  137. package/dist/cli/chunks/{chunk-ZCFZ4USU.js → chunk-TQ2MA3SR.js} +1 -1
  138. package/dist/cli/chunks/{chunk-G5DFYX3J.js → chunk-UCQ66N6M.js} +2 -2
  139. package/dist/cli/chunks/{chunk-CPH5JP4L.js → chunk-UHGMS2PJ.js} +1 -1
  140. package/dist/cli/chunks/{chunk-ANYYTWOQ.js → chunk-UHKXKWMD.js} +2 -2
  141. package/dist/cli/chunks/{chunk-YRQLVGCI.js → chunk-UJ6TMZC6.js} +2 -2
  142. package/dist/cli/chunks/{chunk-EECM5XKY.js → chunk-UKBDH27A.js} +1 -1
  143. package/dist/cli/chunks/{chunk-VLBV2VL3.js → chunk-UMCEEXQN.js} +1 -1
  144. package/dist/cli/chunks/{chunk-LOXVVMS4.js → chunk-USUFTHHT.js} +3 -3
  145. package/dist/cli/chunks/{chunk-HOKON5EL.js → chunk-V32MDID3.js} +2 -2
  146. package/dist/cli/chunks/{chunk-KZTBNDNE.js → chunk-VAJT6QWX.js} +1 -1
  147. package/dist/cli/chunks/{chunk-UNIBND6A.js → chunk-VLUJWI56.js} +1 -1
  148. package/dist/cli/chunks/{chunk-QWYISZTN.js → chunk-WINA3XUT.js} +2 -2
  149. package/dist/cli/chunks/{chunk-YPTGE5NJ.js → chunk-WWCH5SSF.js} +2 -2
  150. package/dist/cli/chunks/{chunk-W5YEIHIO.js → chunk-WWP2VXYJ.js} +2 -2
  151. package/dist/cli/chunks/{chunk-GFBLWFRV.js → chunk-WZROSTQZ.js} +1 -1
  152. package/dist/cli/chunks/{chunk-UMG5URNV.js → chunk-XFUF654L.js} +1 -1
  153. package/dist/cli/chunks/{chunk-54MFKCLT.js → chunk-XN2CD5S6.js} +2 -2
  154. package/dist/cli/chunks/{chunk-IHQTXJAQ.js → chunk-XOQQGZFY.js} +1 -1
  155. package/dist/cli/chunks/{chunk-WRYT4HTZ.js → chunk-XSCOEY4C.js} +2 -2
  156. package/dist/cli/chunks/{chunk-R3GEXYO4.js → chunk-Y734CWHJ.js} +2 -2
  157. package/dist/cli/chunks/{chunk-NUQBJGGF.js → chunk-YBPCBFEE.js} +2 -2
  158. package/dist/cli/chunks/{chunk-GUEZQOHL.js → chunk-YLAEIS6F.js} +1 -1
  159. package/dist/cli/chunks/{chunk-EFRESRLB.js → chunk-YMMVCOPF.js} +3 -3
  160. package/dist/cli/chunks/{chunk-N7VOOI3U.js → chunk-YQCAXYBF.js} +2 -2
  161. package/dist/cli/chunks/{chunk-5FLTZ3KT.js → chunk-YRVUYM62.js} +2 -2
  162. package/dist/cli/chunks/{chunk-GJMZR7WU.js → chunk-YVKMHXQK.js} +3 -3
  163. package/dist/cli/chunks/{chunk-TZPKTRJB.js → chunk-ZCLFAOVT.js} +2 -2
  164. package/dist/cli/chunks/{chunk-L4S722JD.js → chunk-ZH6ZBDVV.js} +1 -1
  165. package/dist/cli/chunks/{chunk-KSYLRM4Q.js → chunk-ZHEKGB4A.js} +2 -2
  166. package/dist/cli/chunks/{chunk-E3B5XTXJ.js → chunk-ZIBW7CB4.js} +1 -1
  167. package/dist/cli/chunks/{chunk-2DIT5AUU.js → chunk-ZLCATRXI.js} +2 -2
  168. package/dist/cli/chunks/{chunk-LWYLW7RX.js → chunk-ZXX2VFMA.js} +2 -2
  169. package/dist/cli/chunks/{chunk-XKFE3FLI.js → chunk-ZYPESQ4M.js} +2 -2
  170. package/dist/cli/chunks/{ci-74ZUCO5V.js → ci-HHL5WQXQ.js} +2 -2
  171. package/dist/cli/chunks/{ci-output-HD6IZNJA.js → ci-output-HVOJC2KN.js} +2 -2
  172. package/dist/cli/chunks/{circuit-breaker-USZVMA42.js → circuit-breaker-HRXMIY2G.js} +2 -2
  173. package/dist/cli/chunks/{claude-flow-setup-S4XKNCD5.js → claude-flow-setup-3I7WVMZN.js} +2 -2
  174. package/dist/cli/chunks/client-EY2IYQDL.js +2 -0
  175. package/dist/cli/chunks/{cline-installer-6EW4CHAR.js → cline-installer-NBREL4QT.js} +2 -2
  176. package/dist/cli/chunks/{code-TOLWD2XL.js → code-TX4E2RWU.js} +2 -2
  177. package/dist/cli/chunks/{code-index-extractor-UA4QQ7B3.js → code-index-extractor-YELOFLSL.js} +2 -2
  178. package/dist/cli/chunks/codex-installer-HEX3KFRB.js +10 -0
  179. package/dist/cli/chunks/{completions-KVUMQQ4K.js → completions-72GGFRGG.js} +2 -2
  180. package/dist/cli/chunks/{complexity-analyzer-DFH6LMK2.js → complexity-analyzer-WRAKDYUK.js} +2 -2
  181. package/dist/cli/chunks/{continuedev-installer-LYDQSAU7.js → continuedev-installer-UGYKSKTI.js} +2 -2
  182. package/dist/cli/chunks/{copilot-installer-7USXLZHZ.js → copilot-installer-RPCRUKIJ.js} +2 -2
  183. package/dist/cli/chunks/core-handlers-G4GLA4DT.js +2 -0
  184. package/dist/cli/chunks/{cost-tracker-JBDIUMKZ.js → cost-tracker-CNHJ7G4M.js} +2 -2
  185. package/dist/cli/chunks/{coverage-RGO3K357.js → coverage-RHIQ4XEX.js} +3 -3
  186. package/dist/cli/chunks/cross-domain-router-P3K4IH5H.js +2 -0
  187. package/dist/cli/chunks/{cursor-installer-YEZGD37F.js → cursor-installer-KSRVA4V2.js} +2 -2
  188. package/dist/cli/chunks/{daemon-FVETQ3LL.js → daemon-IT4AAFBW.js} +3 -3
  189. package/dist/cli/chunks/{daemon-LPEXHNYG.js → daemon-QBXSJABV.js} +4 -4
  190. package/dist/cli/chunks/{dag-attention-scheduler-UKYE2FII.js → dag-attention-scheduler-F7WCQTLY.js} +2 -2
  191. package/dist/cli/chunks/{detect-WBG5P7ER.js → detect-2IYU332U.js} +2 -2
  192. package/dist/cli/chunks/{dist-node-YW6YRBCU.js → dist-node-CIYNYCYN.js} +2 -2
  193. package/dist/cli/chunks/{domain-handler-HH7J4A32.js → domain-handler-QRYQO2QK.js} +2 -2
  194. package/dist/cli/chunks/{domain-transfer-V34GXD5I.js → domain-transfer-2OQDOD3G.js} +2 -2
  195. package/dist/cli/chunks/dream-IT4ZQGEO.js +2 -0
  196. package/dist/cli/chunks/{embed-and-insert-pattern-WYLRS3CL.js → embed-and-insert-pattern-P2IFC7JL.js} +2 -2
  197. package/dist/cli/chunks/{eval-EIMVXY5J.js → eval-SBPK37IB.js} +2 -2
  198. package/dist/cli/chunks/{experience-capture-middleware-QMZHRUKM.js → experience-capture-middleware-3GMFND3F.js} +3 -3
  199. package/dist/cli/chunks/{fast-paths-NHLW6XS6.js → fast-paths-4OYYII2F.js} +2 -2
  200. package/dist/cli/chunks/{feature-flags-NE3MBL3P.js → feature-flags-BM6QTMMC.js} +2 -2
  201. package/dist/cli/chunks/{feature-flags-N3UHMSZ3.js → feature-flags-NFCAYUWO.js} +2 -2
  202. package/dist/cli/chunks/{file-discovery-SI44X4YS.js → file-discovery-2M3ZUAGC.js} +2 -2
  203. package/dist/cli/chunks/{fleet-MMYUXRRM.js → fleet-QMGGVIDV.js} +3 -3
  204. package/dist/cli/chunks/{gnn-wrapper-RLYXYU2Q.js → gnn-wrapper-WGMAGZMO.js} +2 -2
  205. package/dist/cli/chunks/{heartbeat-handler-6EDRUYLV.js → heartbeat-handler-5RSMEZGG.js} +4 -4
  206. package/dist/cli/chunks/heartbeat-scheduler-UUWSPHF2.js +2 -0
  207. package/dist/cli/chunks/hnsw-adapter-YUJVSFPD.js +2 -0
  208. package/dist/cli/chunks/hnsw-index-FQZ47RSJ.js +2 -0
  209. package/dist/cli/chunks/{hnsw-legacy-bridge-RVM7EAIH.js → hnsw-legacy-bridge-TYPQ2T6P.js} +2 -2
  210. package/dist/cli/chunks/{better-sqlite3-DUZ6FFAH.js → hnswlib-node-GMRPPMDM.js} +2 -2
  211. package/dist/cli/chunks/{hooks-ZF4VKHEO.js → hooks-NUC5P3OJ.js} +10 -10
  212. package/dist/cli/chunks/hybrid-router-T5MF73NF.js +2 -0
  213. package/dist/cli/chunks/{hypergraph-engine-YWS66PGO.js → hypergraph-engine-OIB7WK54.js} +2 -2
  214. package/dist/cli/chunks/{hypergraph-handler-OQHVRPWB.js → hypergraph-handler-XX2N75QC.js} +3 -3
  215. package/dist/cli/chunks/impact-analyzer-AEGELYMD.js +2 -0
  216. package/dist/cli/chunks/{init-handler-YW74YF2V.js → init-handler-AKSTJMZY.js} +6 -6
  217. package/dist/cli/chunks/init-wizard-WKX3OGWM.js +2 -0
  218. package/dist/cli/chunks/kernel-5CVWFIGR.js +2 -0
  219. package/dist/cli/chunks/{kilocode-installer-APWB2GMA.js → kilocode-installer-375V5ZZB.js} +2 -2
  220. package/dist/cli/chunks/{kiro-installer-DICKFVNC.js → kiro-installer-GKY5GB5Q.js} +2 -2
  221. package/dist/cli/chunks/knowledge-graph-EGPMNDMT.js +2 -0
  222. package/dist/cli/chunks/{learning-MXHNYW5D.js → learning-2CQE3QP6.js} +3 -3
  223. package/dist/cli/chunks/{llm-router-LTFIX7NY.js → llm-router-FTQNRF45.js} +4 -4
  224. package/dist/cli/chunks/llm-router-service-H4LXOARB.js +2 -0
  225. package/dist/cli/chunks/{load-JUMIQ4LZ.js → load-3DBAO5ZG.js} +2 -2
  226. package/dist/cli/chunks/load-test-OOOGITSN.js +2 -0
  227. package/dist/cli/chunks/{mcp-WHIARJGO.js → mcp-AWR6TDXM.js} +2 -2
  228. package/dist/cli/chunks/{memory-KAHS6Z5A.js → memory-GI4LCNXY.js} +5 -5
  229. package/dist/cli/chunks/memory-backend-O2YOT4LW.js +2 -0
  230. package/dist/cli/chunks/{memory-handlers-DG3RRXB6.js → memory-handlers-MALKG7GP.js} +2 -2
  231. package/dist/cli/chunks/{multi-model-executor-E3Y2RHMX.js → multi-model-executor-SWFT5U72.js} +2 -2
  232. package/dist/cli/chunks/{opencode-installer-3RKGNGGE.js → opencode-installer-EYXGYJX5.js} +2 -2
  233. package/dist/cli/chunks/{orchestrator-TXITUKWD.js → orchestrator-MP3EAZVC.js} +5 -5
  234. package/dist/cli/chunks/pattern-null-store-WBOHE2XL.js +2 -0
  235. package/dist/cli/chunks/{pattern-usage-recorder-EE2BUFZT.js → pattern-usage-recorder-25P3R3W7.js} +2 -2
  236. package/dist/cli/chunks/{pipeline-AXTT6KZB.js → pipeline-LSAFL25D.js} +2 -2
  237. package/dist/cli/chunks/{platform-TICPVKE2.js → platform-IJ6DJ2PG.js} +2 -2
  238. package/dist/cli/chunks/{plugin-VQKNV3EM.js → plugin-OXOZRZW2.js} +2 -2
  239. package/dist/cli/chunks/{prime-radiant-advanced-wasm-6GY5YY7D.js → prime-radiant-advanced-wasm-HJNJQQ3R.js} +2 -2
  240. package/dist/cli/chunks/protocol-executor-JCNTPW5J.js +2 -0
  241. package/dist/cli/chunks/{protocol-handler-YFWDR7UZ.js → protocol-handler-TCMUH2HL.js} +2 -2
  242. package/dist/cli/chunks/{prove-FUMRCXAA.js → prove-ADXQ2GOX.js} +2 -2
  243. package/dist/cli/chunks/provider-manager-LPGQ5GOO.js +2 -0
  244. package/dist/cli/chunks/qe-reasoning-bank-FWVYVSPP.js +2 -0
  245. package/dist/cli/chunks/{quality-2APISBW5.js → quality-EWP36ORX.js} +2 -2
  246. package/dist/cli/chunks/{quality-gate-MCC3E5TM.js → quality-gate-3BIG7PVU.js} +3 -3
  247. package/dist/cli/chunks/queen-coordinator-UXNALRVD.js +2 -0
  248. package/dist/cli/chunks/{real-embeddings-CC5TNOTI.js → real-embeddings-D4NBT7W5.js} +2 -2
  249. package/dist/cli/chunks/{roocode-installer-YAHTEVPI.js → roocode-installer-DOPWH6YV.js} +2 -2
  250. package/dist/cli/chunks/router-C6LUIQYY.js +2 -0
  251. package/dist/cli/chunks/routing-feedback-KMSGGDVD.js +2 -0
  252. package/dist/cli/chunks/{routing-handler-6NQBW4TQ.js → routing-handler-5ADEFOHS.js} +2 -2
  253. package/dist/cli/chunks/{ruvector-commands-ZHXLHUPG.js → ruvector-commands-PLMEIHSN.js} +2 -2
  254. package/dist/cli/chunks/{rvf-dual-writer-5KF2DGCW.js → rvf-dual-writer-EQWKVNQB.js} +2 -2
  255. package/dist/cli/chunks/{rvf-migration-adapter-BBU57BGF.js → rvf-migration-adapter-2OWFUUCG.js} +2 -2
  256. package/dist/cli/chunks/{rvf-migration-coordinator-VN4VRZA4.js → rvf-migration-coordinator-URAETAPU.js} +2 -2
  257. package/dist/cli/chunks/rvf-native-adapter-K54BELUE.js +2 -0
  258. package/dist/cli/chunks/{rvf-store-integrity-XCY2XQZA.js → rvf-store-integrity-4AWPW4TF.js} +2 -2
  259. package/dist/cli/chunks/safe-db-NGOZWF2D.js +2 -0
  260. package/dist/cli/chunks/schedule-B3Y5P64E.js +2 -0
  261. package/dist/cli/chunks/scheduler-Z6QVRMTB.js +2 -0
  262. package/dist/cli/chunks/{security-PYP4H3KN.js → security-HDLZVM62.js} +3 -3
  263. package/dist/cli/chunks/{shared-rvf-adapter-3CJHRNX6.js → shared-rvf-adapter-YQT7PF7X.js} +2 -2
  264. package/dist/cli/chunks/{shared-rvf-dual-writer-MKSLKWDI.js → shared-rvf-dual-writer-N5D3NSJ7.js} +2 -2
  265. package/dist/cli/chunks/sqlite-persistence-PLOUGATS.js +2 -0
  266. package/dist/cli/chunks/{status-handler-VYIZ3VJF.js → status-handler-KLYRJ2MR.js} +2 -2
  267. package/dist/cli/chunks/{structural-health-MVV4OWXP.js → structural-health-6LKVRP6Y.js} +2 -2
  268. package/dist/cli/chunks/{sync-VNX6L3TI.js → sync-7VMFPBVB.js} +2 -2
  269. package/dist/cli/chunks/{sync-G47OYIQ3.js → sync-YYOW6L6W.js} +2 -2
  270. package/dist/cli/chunks/{task-handler-GOWF2GEH.js → task-handler-RKQDGFN2.js} +2 -2
  271. package/dist/cli/chunks/{task-handlers-J2WC6J37.js → task-handlers-6YJ4QTEP.js} +3 -3
  272. package/dist/cli/chunks/{test-DMCJ3BXS.js → test-ASPUIUJH.js} +4 -4
  273. package/dist/cli/chunks/{test-scheduling-TRFHHKFM.js → test-scheduling-I7ABQBBU.js} +3 -3
  274. package/dist/cli/chunks/{token-bootstrap-KEQ7AHFF.js → token-bootstrap-2XZBTODN.js} +2 -2
  275. package/dist/cli/chunks/{token-usage-B54FOFOF.js → token-usage-TMUE6PTF.js} +2 -2
  276. package/dist/cli/chunks/{transformers-IACZG7IV.js → transformers-FDHHH4SL.js} +2 -2
  277. package/dist/cli/chunks/{tree-sitter-wasm-parser-N7H4X37E.js → tree-sitter-wasm-parser-G7PGZA5C.js} +2 -2
  278. package/dist/cli/chunks/{types-B3SHT4OD.js → types-JGT57UFP.js} +2 -2
  279. package/dist/cli/chunks/unified-memory-P5YVLMFI.js +2 -0
  280. package/dist/cli/chunks/unified-memory-hnsw-7HI43A2O.js +2 -0
  281. package/dist/cli/chunks/unified-persistence-U26YP3N3.js +2 -0
  282. package/dist/cli/chunks/{upgrade-A2PQ5EWK.js → upgrade-V6UQODJF.js} +2 -2
  283. package/dist/cli/chunks/{validate-UXV7UQUT.js → validate-UBZAE5RW.js} +2 -2
  284. package/dist/cli/chunks/{validate-swarm-MMBU4FPP.js → validate-swarm-TSO2MI5X.js} +2 -2
  285. package/dist/cli/chunks/{vibium-R4GUVADA.js → vibium-7G3VYSQA.js} +2 -2
  286. package/dist/cli/chunks/visual-security-6FCDY5FF.js +2 -0
  287. package/dist/cli/chunks/{web-tree-sitter-MP6E6CJB.js → web-tree-sitter-MIYJSF2L.js} +2 -2
  288. package/dist/cli/chunks/{windsurf-installer-Z6BWMUUO.js → windsurf-installer-5TLZSQIJ.js} +2 -2
  289. package/dist/cli/chunks/witness-chain-I3K3WQID.js +2 -0
  290. package/dist/cli/chunks/{witness-chain-EFLTABBA.js → witness-chain-LTV7H2HM.js} +2 -2
  291. package/dist/cli/chunks/{witness-key-manager-PN36TV43.js → witness-key-manager-PAJ2J4AL.js} +2 -2
  292. package/dist/cli/chunks/{workflow-A2AX3RJU.js → workflow-DL3ESR2H.js} +4 -4
  293. package/dist/cli/chunks/workflow-orchestrator-MAALP4WA.js +2 -0
  294. package/dist/cli/chunks/{wrappers-NA6FHA63.js → wrappers-5HSU665E.js} +2 -2
  295. package/dist/cli/handlers/init-handler.js +1 -1
  296. package/dist/coordination/handlers/coverage-collection.d.ts +161 -0
  297. package/dist/coordination/handlers/coverage-collection.js +639 -0
  298. package/dist/coordination/handlers/coverage-handlers.js +199 -146
  299. package/dist/coordination/handlers/handler-types.d.ts +6 -1
  300. package/dist/coordination/handlers/handler-utils.js +10 -3
  301. package/dist/coordination/handlers/security-handlers.js +17 -2
  302. package/dist/coordination/handlers/test-execution-handlers.js +16 -1
  303. package/dist/coordination/result-saver.js +119 -97
  304. package/dist/coordination/task-executor.d.ts +26 -1
  305. package/dist/coordination/task-executor.js +52 -4
  306. package/dist/domains/code-intelligence/services/knowledge-graph.js +8 -0
  307. package/dist/domains/coverage-analysis/services/coverage-analyzer.js +4 -0
  308. package/dist/domains/coverage-analysis/services/gap-detector.js +4 -0
  309. package/dist/domains/defect-intelligence/services/defect-predictor.js +4 -0
  310. package/dist/domains/defect-intelligence/services/root-cause-analyzer.js +4 -0
  311. package/dist/domains/quality-assessment/services/deployment-advisor.js +4 -0
  312. package/dist/domains/quality-assessment/services/quality-analyzer.js +4 -0
  313. package/dist/domains/security-compliance/services/scanners/sast-scanner.js +4 -0
  314. package/dist/domains/test-generation/index.js +17 -2
  315. package/dist/domains/test-generation/services/test-generator.js +31 -9
  316. package/dist/init/codex-installer.d.ts +13 -0
  317. package/dist/init/codex-installer.js +122 -1
  318. package/dist/init/phases/09-assets.js +4 -0
  319. package/dist/init/phases/phase-interface.d.ts +1 -1
  320. package/dist/learning/real-embeddings.js +15 -1
  321. package/dist/mcp/bundle.js +429 -419
  322. package/dist/mcp/handlers/domain-handler-configs.js +79 -14
  323. package/dist/mcp/types.d.ts +42 -4
  324. package/dist/optimization/session-cache.d.ts +13 -1
  325. package/dist/optimization/session-cache.js +27 -2
  326. package/dist/shared/llm/llm-router-service.js +59 -4
  327. package/dist/shared/llm/router/agent-router-config.d.ts +46 -2
  328. package/dist/shared/llm/router/agent-router-config.js +124 -2
  329. package/dist/shared/llm/router/config-store.d.ts +17 -1
  330. package/dist/shared/llm/router/config-store.js +103 -0
  331. package/dist/shared/llm/router/index.d.ts +2 -2
  332. package/dist/shared/llm/router/index.js +2 -0
  333. package/dist/shared/llm/router/types.d.ts +44 -0
  334. package/dist/shared/llm/router/types.js +1 -0
  335. package/package.json +9 -6
  336. package/dist/cli/chunks/adapter-CWIMFWAI.js +0 -2
  337. package/dist/cli/chunks/aqe-learning-engine-OTXT2DLN.js +0 -2
  338. package/dist/cli/chunks/base-O3SPSWBA.js +0 -2
  339. package/dist/cli/chunks/browser-workflow-MXS3ZKY2.js +0 -2
  340. package/dist/cli/chunks/chunk-G4GTE3RJ.js +0 -2
  341. package/dist/cli/chunks/chunk-HVB2L52I.js +0 -2
  342. package/dist/cli/chunks/chunk-MVI2QMRW.js +0 -2
  343. package/dist/cli/chunks/chunk-OZR25R7W.js +0 -2
  344. package/dist/cli/chunks/chunk-PP2RYSHT.js +0 -3
  345. package/dist/cli/chunks/client-33PGO5FA.js +0 -2
  346. package/dist/cli/chunks/codex-installer-C2CUP4FW.js +0 -8
  347. package/dist/cli/chunks/core-handlers-CSNZIM3A.js +0 -2
  348. package/dist/cli/chunks/cross-domain-router-DRIBR5L3.js +0 -2
  349. package/dist/cli/chunks/dream-WUNO723O.js +0 -2
  350. package/dist/cli/chunks/heartbeat-scheduler-VAFQDJLL.js +0 -2
  351. package/dist/cli/chunks/hnsw-adapter-TIRPA7XE.js +0 -2
  352. package/dist/cli/chunks/hnsw-index-SSQBRQCQ.js +0 -2
  353. package/dist/cli/chunks/hybrid-router-AKBWZOQ3.js +0 -2
  354. package/dist/cli/chunks/impact-analyzer-46FQIZ6Y.js +0 -2
  355. package/dist/cli/chunks/init-wizard-U3NHGYSS.js +0 -2
  356. package/dist/cli/chunks/kernel-ZDXHT6QF.js +0 -2
  357. package/dist/cli/chunks/knowledge-graph-6XTW6WO6.js +0 -2
  358. package/dist/cli/chunks/llm-router-service-3F4E64SY.js +0 -2
  359. package/dist/cli/chunks/load-test-SWZNGEIY.js +0 -2
  360. package/dist/cli/chunks/memory-backend-PR74ZPBA.js +0 -2
  361. package/dist/cli/chunks/pattern-null-store-EPE36BVT.js +0 -2
  362. package/dist/cli/chunks/protocol-executor-IELENNST.js +0 -2
  363. package/dist/cli/chunks/provider-manager-3R3KOBHG.js +0 -2
  364. package/dist/cli/chunks/qe-reasoning-bank-S2R2PCBS.js +0 -2
  365. package/dist/cli/chunks/queen-coordinator-2E23NEV4.js +0 -2
  366. package/dist/cli/chunks/router-3FVLWO6S.js +0 -2
  367. package/dist/cli/chunks/routing-feedback-ZQLRNNR7.js +0 -2
  368. package/dist/cli/chunks/rvf-native-adapter-YFGLQNEB.js +0 -2
  369. package/dist/cli/chunks/safe-db-4SBLBTW7.js +0 -2
  370. package/dist/cli/chunks/schedule-5Y3BGVAA.js +0 -2
  371. package/dist/cli/chunks/scheduler-DOID3QF3.js +0 -2
  372. package/dist/cli/chunks/sqlite-persistence-M4JEQO57.js +0 -2
  373. package/dist/cli/chunks/unified-memory-WNYWTGVX.js +0 -2
  374. package/dist/cli/chunks/unified-memory-hnsw-YPAV7U4E.js +0 -2
  375. package/dist/cli/chunks/unified-persistence-TJ252S7L.js +0 -2
  376. package/dist/cli/chunks/visual-security-VKYXEGJB.js +0 -2
  377. package/dist/cli/chunks/witness-chain-WVXRXKQP.js +0 -2
  378. package/dist/cli/chunks/workflow-orchestrator-GOWSPR3G.js +0 -2
@@ -108,6 +108,9 @@ export const testGenerateConfig = {
108
108
  const domainTests = data.tests;
109
109
  const hasRealTests = Array.isArray(domainTests) && domainTests.length > 0
110
110
  && domainTests[0].testCode;
111
+ // #567: did the ADR-051 LLM branch actually run? Report it instead of
112
+ // asserting `aiGenerated: true` unconditionally.
113
+ const llmEnhanced = data.llmEnhanced === true;
111
114
  const tests = hasRealTests
112
115
  ? domainTests.map((t, i) => ({
113
116
  id: generateTestId(),
@@ -119,7 +122,7 @@ export const testGenerateConfig = {
119
122
  : [`test assertion ${i}`],
120
123
  expectedResult: null,
121
124
  estimatedDuration: t.type === 'integration' ? 2000 : 1000,
122
- aiGenerated: true,
125
+ aiGenerated: llmEnhanced,
123
126
  testCode: t.testCode,
124
127
  sourceFile: t.sourceFile,
125
128
  testFile: t.testFile || t.file,
@@ -133,7 +136,9 @@ export const testGenerateConfig = {
133
136
  aiInsights,
134
137
  coverage: {
135
138
  predicted: data.coverageEstimate || params?.coverageGoal || 80,
136
- confidence: 0.9,
139
+ // #567: a template scaffold's coverage prediction is a guess, not a
140
+ // 0.9-confidence estimate. Don't dress it up as one.
141
+ confidence: llmEnhanced ? 0.9 : 0.3,
137
142
  achievable: true,
138
143
  },
139
144
  properties: tests.filter(t => t.type === 'property').map(t => ({
@@ -151,6 +156,10 @@ export const testGenerateConfig = {
151
156
  patternsUsed: data.patternsUsed || ['assertion-patterns', 'mock-generation', 'edge-case-detection'],
152
157
  duration,
153
158
  savedFiles,
159
+ // #567: propagate the LLM-enhancement signal to the MCP caller.
160
+ llmEnhanced,
161
+ ...(data.generationMode ? { generationMode: data.generationMode } : {}),
162
+ ...(data.note ? { note: data.note } : {}),
154
163
  };
155
164
  },
156
165
  };
@@ -253,12 +262,40 @@ export const coverageAnalyzeConfig = {
253
262
  // The domain returns CoverageReport { summary: { line, branch, function, statement, files }, ... }
254
263
  // Map from both nested (domain) and flat (legacy) field shapes.
255
264
  const summary = data.summary;
256
- const lineCoverage = summary?.line ?? data.lineCoverage ?? 0;
257
- const branchCoverage = summary?.branch ?? data.branchCoverage ?? 0;
258
- const functionCoverage = summary?.function ?? data.functionCoverage ?? 0;
259
- const statementCoverage = summary?.statement ?? data.statementCoverage ?? lineCoverage;
260
265
  const totalFiles = summary?.files ?? data.totalFiles ?? 0;
261
266
  const gaps = data.gaps || [];
267
+ // #569/ADR-126: an ABSENT provenance flag means "unknown", never "collected".
268
+ //
269
+ // Defaulting these to `true` (`!== false`) meant any producer that supplies
270
+ // no provenance at all — notably the coverage-analysis domain plugin, whose
271
+ // handler returns a nested-`summary` CoverageReport — surfaced the exact
272
+ // impossible pair from the issue: 100% branch coverage alongside 0% function
273
+ // coverage, labelled `measured: true` with `confidence: 0.7` on its gaps.
274
+ // Requiring an explicit `true` makes an unprovenanced result honest (`null`)
275
+ // instead of confidently wrong.
276
+ const branchDataCollected = data.branchDataCollected === true;
277
+ const functionDataCollected = data.functionDataCollected === true;
278
+ const branchCoverage = branchDataCollected
279
+ ? (summary?.branch ?? data.branchCoverage ?? null)
280
+ : null;
281
+ const functionCoverage = functionDataCollected
282
+ ? (summary?.function ?? data.functionCoverage ?? null)
283
+ : null;
284
+ // #569: is this a measurement or a static estimate? Everything downstream —
285
+ // gap confidence, AI insights, risk assessment — must be qualified by it.
286
+ const estimated = data.estimated === true;
287
+ // #569/ADR-126: `measured` is NOT the complement of `estimated` — there is a
288
+ // third state where nothing was collected at all. Deriving it as `!estimated`
289
+ // reported an empty project (no sources, no coverage report, nothing run) as
290
+ // `lineCoverage: 0, measured: true` — "we measured 0%" when the truth is "we
291
+ // measured nothing". Trust only an explicit claim from the producer.
292
+ const measured = data.measured === true;
293
+ // Likewise, a `null` line/statement figure must survive as `null`. `?? 0`
294
+ // turns "no data" into a plottable 0%.
295
+ const rawLine = summary?.line ?? data.lineCoverage;
296
+ const lineCoverage = rawLine ?? null;
297
+ const rawStatement = summary?.statement ?? data.statementCoverage;
298
+ const statementCoverage = rawStatement ?? lineCoverage;
262
299
  const learning = generateV2LearningFeedback('coverage-analyzer');
263
300
  // Map gap analysis from real data — never fabricate file paths
264
301
  const detailedGaps = gaps.map((gap, i) => {
@@ -278,7 +315,12 @@ export const coverageAnalyzeConfig = {
278
315
  suggestion: g.suggestedTest || 'Add test coverage',
279
316
  suggestedTest: g.suggestedTest || 'Add test coverage',
280
317
  riskScore: g.riskScore || 0.5,
281
- confidence: g.confidence || 0.7,
318
+ // #569: the 0.7 default confidence is only defensible for a gap derived
319
+ // from a real measurement. An estimated gap carries its own low
320
+ // confidence from the handler; a gap with no provenance at all is not
321
+ // known to be measured either, so it gets the cautious value too.
322
+ confidence: g.confidence ?? (measured ? 0.7 : 0.2),
323
+ estimated: g.estimated === true || estimated,
282
324
  };
283
325
  }).filter((g) => g !== null);
284
326
  // Use real file data from the analyzer if available, never fabricate file paths
@@ -287,8 +329,9 @@ export const coverageAnalyzeConfig = {
287
329
  ? coverageByFileData.map(f => ({
288
330
  file: f.file,
289
331
  lineCoverage: f.lineCoverage || 0,
290
- branchCoverage: f.branchCoverage || 0,
291
- functionCoverage: f.functionCoverage || 0,
332
+ // #569: preserve null (metric not collected) instead of collapsing to 0.
333
+ branchCoverage: f.branchCoverage ?? null,
334
+ functionCoverage: f.functionCoverage ?? null,
292
335
  }))
293
336
  : [];
294
337
  return {
@@ -305,11 +348,25 @@ export const coverageAnalyzeConfig = {
305
348
  weeklyChange: 0,
306
349
  },
307
350
  aiInsights: totalFiles > 0 ? {
308
- recommendations: data.recommendations || [
309
- 'Run tests with coverage enabled to get accurate metrics',
310
- ],
311
- riskAssessment: lineCoverage < 70 ? 'high' : lineCoverage < 85 ? 'medium' : 'low',
312
- confidence: 0.88,
351
+ recommendations: estimated
352
+ // #569: the reported insights ("Coverage is 15.9% below threshold",
353
+ // "Function coverage is below 70%") were all derived from estimated
354
+ // numbers and presented as findings. Lead with the caveat.
355
+ ? [
356
+ 'ESTIMATED RESULT — no instrumentation ran. The figures below are a ' +
357
+ 'static guess from source shape, not measured coverage. Do not act on ' +
358
+ 'individual gaps without running real instrumentation first.',
359
+ ...(data.recommendations || []),
360
+ ]
361
+ : (data.recommendations || [
362
+ 'Run tests with coverage enabled to get accurate metrics',
363
+ ]),
364
+ // #569: risk can only be graded off a real number. `null < 70` is
365
+ // `false` in JS, which would have silently graded "no data" as 'low'.
366
+ riskAssessment: (estimated || !measured || lineCoverage === null)
367
+ ? 'unknown'
368
+ : (lineCoverage < 70 ? 'high' : lineCoverage < 85 ? 'medium' : 'low'),
369
+ confidence: estimated ? 0.2 : (measured ? 0.88 : 0),
313
370
  } : {
314
371
  recommendations: [
315
372
  'No coverage data found. Run tests with coverage first (e.g., npm test -- --coverage, or pytest --cov)',
@@ -329,6 +386,14 @@ export const coverageAnalyzeConfig = {
329
386
  gaps: detailedGaps,
330
387
  duration,
331
388
  savedFiles,
389
+ // #569: provenance travels with the numbers so a caller can never mistake
390
+ // a static estimate for a measurement.
391
+ estimated,
392
+ measured,
393
+ coverageMethod: data.coverageMethod ?? 'unknown',
394
+ branchDataCollected,
395
+ functionDataCollected,
396
+ ...(data.warning ? { warning: data.warning } : {}),
332
397
  };
333
398
  },
334
399
  };
@@ -446,6 +446,15 @@ export interface TestGenerateResult {
446
446
  suggestions?: string[];
447
447
  savedFiles?: string[];
448
448
  patternsUsed?: string[];
449
+ /**
450
+ * #567: true when the ADR-051 LLM branch actually ran. When false the tests
451
+ * are deterministic template scaffolding — see `generationMode`/`note`.
452
+ */
453
+ llmEnhanced?: boolean;
454
+ /** #567: set to 'deterministic-template' when no LLM enhancement was applied. */
455
+ generationMode?: string;
456
+ /** #567: human-readable reason the LLM branch did not run. */
457
+ note?: string;
449
458
  tests?: unknown[];
450
459
  antiPatterns?: unknown[];
451
460
  aiInsights?: Record<string, unknown>;
@@ -462,19 +471,46 @@ export interface CoverageAnalyzeResult {
462
471
  taskId: string;
463
472
  status: string;
464
473
  duration: number;
465
- lineCoverage: number;
466
- branchCoverage: number;
467
- functionCoverage: number;
474
+ /**
475
+ * #569: `null` when no coverage figure was produced at all (no report, no
476
+ * instrumentation run, nothing to estimate from). `0` means a measured zero;
477
+ * `null` means "we don't know" — the two must not be conflated.
478
+ */
479
+ lineCoverage: number | null;
480
+ /**
481
+ * #569: `null` when branch data was not collected. Never report a branch
482
+ * percentage — least of all 100% — that no instrumentation produced.
483
+ */
484
+ branchCoverage: number | null;
485
+ /** #569: `null` when function-level data was not collected. */
486
+ functionCoverage: number | null;
468
487
  gaps?: CoverageGap[];
469
488
  riskScore?: number;
470
489
  savedFiles?: string[];
471
- statementCoverage?: number;
490
+ /** #569: `null` when no figure was produced — see `lineCoverage`. */
491
+ statementCoverage?: number | null;
472
492
  totalFiles?: number;
473
493
  coverageByFile?: unknown[];
474
494
  gapAnalysis?: Record<string, unknown>;
475
495
  trends?: Record<string, unknown>;
476
496
  aiInsights?: Record<string, unknown>;
477
497
  learning?: Record<string, unknown>;
498
+ /**
499
+ * #569 provenance. `true` means the figures are a STATIC ESTIMATE derived
500
+ * from source shape, not measured coverage. Callers must not present an
501
+ * estimated result as a measurement.
502
+ */
503
+ estimated?: boolean;
504
+ /** Inverse of `estimated`: real instrumentation produced these numbers. */
505
+ measured?: boolean;
506
+ /** How the numbers were obtained: instrumented-report | cargo-llvm-cov | static-estimation | none. */
507
+ coverageMethod?: string;
508
+ /** Whether branch data was actually collected. */
509
+ branchDataCollected?: boolean;
510
+ /** Whether function-level data was actually collected. */
511
+ functionDataCollected?: boolean;
512
+ /** Caveats the caller should surface (e.g. "no instrumentation ran"). */
513
+ warning?: string;
478
514
  }
479
515
  /**
480
516
  * Coverage gap
@@ -492,6 +528,8 @@ export interface CoverageGap {
492
528
  priority?: string;
493
529
  suggestedTest?: string;
494
530
  riskScore?: number;
531
+ /** #569: true when this gap came from a static estimate, not a measurement. */
532
+ estimated?: boolean;
495
533
  }
496
534
  /**
497
535
  * Memory store result
@@ -47,8 +47,20 @@ export declare class SessionOperationCache {
47
47
  private misses;
48
48
  constructor(config?: Partial<SessionCacheConfig>);
49
49
  /**
50
- * Compute a deterministic fingerprint from domain + action + input.
50
+ * Compute a deterministic fingerprint from build + domain + action + input.
51
51
  * Uses SHA-256 of the canonicalized JSON (recursively sorted keys), truncated to 16 hex chars.
52
+ *
53
+ * The build identity is part of the key on purpose. Entries are persisted to
54
+ * `kv_store` and survive process restarts *and package upgrades*, so a
55
+ * fingerprint over inputs alone means an upgraded install keeps replaying the
56
+ * previous version's answers until the TTL lapses — the fix looks like it did
57
+ * not work. That is exactly what happened while verifying issue #569: a
58
+ * project analyzed before the fix kept returning the old fabricated coverage
59
+ * numbers (`lineCoverage: 0, measured: true`) from cache, while an untouched
60
+ * project returned the corrected result.
61
+ *
62
+ * Including the version means an upgrade misses cleanly rather than serving
63
+ * stale answers; entries from the old build simply age out.
52
64
  */
53
65
  computeFingerprint(domain: string, action: string, input: Record<string, unknown>): string;
54
66
  /**
@@ -13,6 +13,19 @@
13
13
  * - TTL-based expiry, LRU-ish eviction at capacity
14
14
  */
15
15
  import { createHash } from 'crypto';
16
+ /**
17
+ * Build identity mixed into every cache fingerprint so persisted entries never
18
+ * outlive the code that produced them. `__CLI_VERSION__` is substituted at bundle
19
+ * time; in source/test runs it is undefined and we fall back to a dev marker.
20
+ *
21
+ * `AQE_SESSION_CACHE_SALT` lets an operator force a cold cache without deleting
22
+ * anything (e.g. after a local rebuild that keeps the same version string).
23
+ */
24
+ function getBuildIdentity() {
25
+ const version = typeof __CLI_VERSION__ !== 'undefined' ? __CLI_VERSION__ : 'dev';
26
+ const salt = (process.env.AQE_SESSION_CACHE_SALT ?? '').trim();
27
+ return salt ? `${version}+${salt}` : version;
28
+ }
16
29
  export const DEFAULT_SESSION_CACHE_CONFIG = {
17
30
  enabled: true,
18
31
  maxEntries: 500,
@@ -51,11 +64,23 @@ export class SessionOperationCache {
51
64
  this.config = { ...DEFAULT_SESSION_CACHE_CONFIG, ...config };
52
65
  }
53
66
  /**
54
- * Compute a deterministic fingerprint from domain + action + input.
67
+ * Compute a deterministic fingerprint from build + domain + action + input.
55
68
  * Uses SHA-256 of the canonicalized JSON (recursively sorted keys), truncated to 16 hex chars.
69
+ *
70
+ * The build identity is part of the key on purpose. Entries are persisted to
71
+ * `kv_store` and survive process restarts *and package upgrades*, so a
72
+ * fingerprint over inputs alone means an upgraded install keeps replaying the
73
+ * previous version's answers until the TTL lapses — the fix looks like it did
74
+ * not work. That is exactly what happened while verifying issue #569: a
75
+ * project analyzed before the fix kept returning the old fabricated coverage
76
+ * numbers (`lineCoverage: 0, measured: true`) from cache, while an untouched
77
+ * project returned the corrected result.
78
+ *
79
+ * Including the version means an upgrade misses cleanly rather than serving
80
+ * stale answers; entries from the old build simply age out.
56
81
  */
57
82
  computeFingerprint(domain, action, input) {
58
- const canonical = canonicalStringify({ action, domain, input });
83
+ const canonical = canonicalStringify({ action, build: getBuildIdentity(), domain, input });
59
84
  return createHash('sha256').update(canonical).digest('hex').slice(0, 16);
60
85
  }
61
86
  /**
@@ -22,6 +22,47 @@
22
22
  import { ProviderManager } from './provider-manager.js';
23
23
  import { HybridRouter } from './router/hybrid-router.js';
24
24
  import { loadRouterConfig, shouldEnableRouter, detectAvailableProvidersFromEnv, } from './router/config-store.js';
25
+ import { setAgentProviderOverrides, createOverrideRoutingRules, } from './router/agent-router-config.js';
26
+ import { DEFAULT_QE_ROUTING_RULES } from './router/routing-rules.js';
27
+ import { createLogger } from '../../logging/logger-factory.js';
28
+ const routerServiceLogger = createLogger('llm/router-service');
29
+ /**
30
+ * Issue #568: make `.agentic-qe/llm-config.json`'s `agentOverrides` map actually
31
+ * take effect.
32
+ *
33
+ * Two steps, and both are needed:
34
+ * 1. install the map so `getPreferredModelForAgent()` consults it, and
35
+ * 2. materialize a routing rule per overridden agent and put it *ahead* of the
36
+ * rules the router would otherwise evaluate.
37
+ *
38
+ * Step 2 is the part that was missing before: `HybridRouter` only ever evaluates
39
+ * `config.rules` (falling back to `DEFAULT_QE_ROUTING_RULES`), and the generated
40
+ * per-agent ruleset was never installed into either — which is why the whole
41
+ * `agent-router-config` mechanism was unreachable from outside a single call
42
+ * stack.
43
+ *
44
+ * No overrides on disk => returns the config untouched.
45
+ */
46
+ function applyAgentOverrides(config) {
47
+ // Pass each provider's own default model so a `{ "provider": "ollama" }`
48
+ // override resolves to a model ollama can serve, not the Claude model id the
49
+ // agent's category default happened to carry.
50
+ const providerDefaultModels = {};
51
+ for (const [provider, cfg] of Object.entries(config.providers ?? {})) {
52
+ if (cfg?.defaultModel) {
53
+ providerDefaultModels[provider] = cfg.defaultModel;
54
+ }
55
+ }
56
+ setAgentProviderOverrides(config.agentOverrides, providerDefaultModels);
57
+ const overrideRules = createOverrideRoutingRules();
58
+ if (overrideRules.length === 0) {
59
+ return config;
60
+ }
61
+ // Mirror HybridRouter's own fallback so materializing overrides never has the
62
+ // side effect of dropping the default QE rules.
63
+ const baseRules = config.rules.length > 0 ? config.rules : DEFAULT_QE_ROUTING_RULES;
64
+ return { ...config, rules: [...overrideRules, ...baseRules] };
65
+ }
25
66
  /**
26
67
  * Order in which we pick fallbacks when the user hasn't specified any.
27
68
  * Local-first (free), then cheapest cloud, then richer providers. This
@@ -46,11 +87,11 @@ const FALLBACK_PRIORITY = [
46
87
  export async function createLLMRouterService(options = {}) {
47
88
  // Honor the test-injected ProviderManager path first.
48
89
  if (options.providerManager) {
49
- const config = loadRouterConfig({
90
+ const config = applyAgentOverrides(loadRouterConfig({
50
91
  projectRoot: options.projectRoot,
51
92
  override: options.override,
52
93
  env: options.env,
53
- });
94
+ }));
54
95
  const router = new HybridRouter(options.providerManager, config);
55
96
  await router.initialize();
56
97
  return {
@@ -63,15 +104,29 @@ export async function createLLMRouterService(options = {}) {
63
104
  if (!shouldEnableRouter({ projectRoot: options.projectRoot, env: options.env })) {
64
105
  return null;
65
106
  }
66
- const config = loadRouterConfig({
107
+ const config = applyAgentOverrides(loadRouterConfig({
67
108
  projectRoot: options.projectRoot,
68
109
  override: options.override,
69
110
  env: options.env,
70
- });
111
+ }));
71
112
  const enabled = pickEnabledProviders(config, options.env ?? process.env);
72
113
  if (enabled.length === 0) {
73
114
  return null;
74
115
  }
116
+ // Issue #568: an override naming a provider that isn't enabled would silently
117
+ // fall through to the default chain — the exact "configured it and nothing
118
+ // happened" failure this feature exists to avoid. Say so out loud. We do NOT
119
+ // auto-enable it: that would opt the user into a provider (and possibly paid
120
+ // billing) they never turned on.
121
+ const enabledSet = new Set(enabled);
122
+ for (const [agentType, override] of Object.entries(config.agentOverrides ?? {})) {
123
+ if (override.provider && !enabledSet.has(override.provider)) {
124
+ routerServiceLogger.warn(`[llm-config] agentOverrides["${agentType}"] routes to provider ` +
125
+ `"${override.provider}", which is not enabled (no API key detected and not ` +
126
+ `enabled in .agentic-qe/llm-config.json). This override will not take effect ` +
127
+ `until that provider is available.`);
128
+ }
129
+ }
75
130
  const { primary, fallbacks } = pickPrimaryAndFallbacks(config, enabled);
76
131
  const providerManagerConfig = {
77
132
  primary: primary,
@@ -8,7 +8,7 @@
8
8
  * - Override mechanism for specific tasks
9
9
  * - Agent category detection and preferred model resolution
10
10
  */
11
- import { ExtendedProviderType, RoutingRule, TaskComplexity } from './types';
11
+ import { ExtendedProviderType, RoutingRule, TaskComplexity, AgentProviderOverride } from './types';
12
12
  /**
13
13
  * Agent categories for routing decisions
14
14
  */
@@ -120,7 +120,34 @@ export declare const DEFAULT_CATEGORY_CAPABILITIES: Record<AgentCategory, AgentC
120
120
  */
121
121
  export declare function getAgentRoutingCategory(agentType: string): AgentCategory;
122
122
  /**
123
- * Get the preferred model for an agent type
123
+ * Install the on-disk per-agent overrides (issue #568). Called by the router
124
+ * service after `loadRouterConfig()` has validated them.
125
+ *
126
+ * Replaces the whole map rather than merging, so reloading a config that
127
+ * removed an entry actually removes it.
128
+ *
129
+ * @param overrides validated `agentOverrides` map
130
+ * @param defaultModels per-provider default model ids, so a provider-only
131
+ * override resolves to a model that provider can actually serve
132
+ */
133
+ export declare function setAgentProviderOverrides(overrides: Record<string, AgentProviderOverride> | undefined, defaultModels?: Partial<Record<ExtendedProviderType, string>>): void;
134
+ /** Current on-disk per-agent overrides. Primarily for diagnostics and tests. */
135
+ export declare function getAgentProviderOverrides(): Readonly<Record<string, AgentProviderOverride>>;
136
+ /** Clear installed overrides. For tests. */
137
+ export declare function resetAgentProviderOverrides(): void;
138
+ /**
139
+ * Get the preferred model for an agent type.
140
+ *
141
+ * Resolution order (issue #568):
142
+ * 1. `agentOverrides[agentType]` from `.agentic-qe/llm-config.json` — the
143
+ * user's explicit, hand-written intent, so it wins.
144
+ * 2. the agent's category default (`AGENT_CATEGORY_MAP` ->
145
+ * `DEFAULT_CATEGORY_MODELS`).
146
+ *
147
+ * An override is a *partial*: fields it does not set keep their category
148
+ * default, so `{ "provider": "ollama" }` re-provisions the provider without
149
+ * forcing the user to also restate temperature, token budget, and priority.
150
+ *
124
151
  * @param agentType - The agent type identifier
125
152
  * @returns The model preference configuration
126
153
  */
@@ -161,6 +188,23 @@ export declare function isLatencySensitive(agentType: string): boolean;
161
188
  * @returns A routing rule for this agent type
162
189
  */
163
190
  export declare function createAgentRoutingRule(agentType: string): RoutingRule;
191
+ /**
192
+ * Build routing rules for exactly the agent types the user overrode on disk
193
+ * (issue #568).
194
+ *
195
+ * Why a separate builder rather than `createAgentRoutingRule`: that one also
196
+ * constrains on `requiresReasoning`, which is right for the generated
197
+ * whole-roster ruleset but wrong here — a user who wrote
198
+ * `"qe-mutation-tester": { "provider": "ollama" }` means *always*, not "only when
199
+ * the request happens to be flagged as needing reasoning". These rules match on
200
+ * agent type alone.
201
+ *
202
+ * Returns `[]` when nothing is overridden, so a project without the key gets the
203
+ * exact rule set it got before.
204
+ *
205
+ * @returns Routing rules, highest priority first
206
+ */
207
+ export declare function createOverrideRoutingRules(): RoutingRule[];
164
208
  /**
165
209
  * Create routing rules for all agents in a category
166
210
  * @param category - The agent category
@@ -324,14 +324,97 @@ export function getAgentRoutingCategory(agentType) {
324
324
  }
325
325
  return 'general';
326
326
  }
327
+ // ============================================================================
328
+ // On-disk per-agent overrides (issue #568)
329
+ // ============================================================================
330
+ /**
331
+ * Per-agent-type overrides sourced from `.agentic-qe/llm-config.json`'s
332
+ * `agentOverrides` key.
333
+ *
334
+ * Module-level state, deliberately: `getPreferredModelForAgent` is a synchronous
335
+ * pure-lookup function called from many places (rule construction, capability
336
+ * resolution, the router's own dispatch), and threading a config object through
337
+ * all of them would be a far larger change than this feature warrants. The
338
+ * router installs the loaded map once at construction via
339
+ * `setAgentProviderOverrides`.
340
+ *
341
+ * Empty by default, so behavior is unchanged for anyone who never writes the
342
+ * key — the category defaults below remain authoritative.
343
+ */
344
+ let agentProviderOverrides = {};
345
+ /**
346
+ * Per-provider default model, from the router config's `providers` map.
347
+ *
348
+ * Needed because the category defaults in `DEFAULT_CATEGORY_MODELS` pair a
349
+ * provider with a provider-specific model id. If a user writes
350
+ * `{ "provider": "ollama" }` and we inherited the category *model* too, the
351
+ * agent would be routed to ollama asking for `claude-sonnet-4-6` — a model that
352
+ * provider cannot serve. Changing provider without naming a model must fall
353
+ * back to that provider's own default, not the previous provider's model.
354
+ */
355
+ let providerDefaultModels = {};
356
+ /**
357
+ * Install the on-disk per-agent overrides (issue #568). Called by the router
358
+ * service after `loadRouterConfig()` has validated them.
359
+ *
360
+ * Replaces the whole map rather than merging, so reloading a config that
361
+ * removed an entry actually removes it.
362
+ *
363
+ * @param overrides validated `agentOverrides` map
364
+ * @param defaultModels per-provider default model ids, so a provider-only
365
+ * override resolves to a model that provider can actually serve
366
+ */
367
+ export function setAgentProviderOverrides(overrides, defaultModels) {
368
+ agentProviderOverrides = { ...(overrides ?? {}) };
369
+ providerDefaultModels = { ...(defaultModels ?? {}) };
370
+ }
371
+ /** Current on-disk per-agent overrides. Primarily for diagnostics and tests. */
372
+ export function getAgentProviderOverrides() {
373
+ return agentProviderOverrides;
374
+ }
375
+ /** Clear installed overrides. For tests. */
376
+ export function resetAgentProviderOverrides() {
377
+ agentProviderOverrides = {};
378
+ providerDefaultModels = {};
379
+ }
327
380
  /**
328
- * Get the preferred model for an agent type
381
+ * Get the preferred model for an agent type.
382
+ *
383
+ * Resolution order (issue #568):
384
+ * 1. `agentOverrides[agentType]` from `.agentic-qe/llm-config.json` — the
385
+ * user's explicit, hand-written intent, so it wins.
386
+ * 2. the agent's category default (`AGENT_CATEGORY_MAP` ->
387
+ * `DEFAULT_CATEGORY_MODELS`).
388
+ *
389
+ * An override is a *partial*: fields it does not set keep their category
390
+ * default, so `{ "provider": "ollama" }` re-provisions the provider without
391
+ * forcing the user to also restate temperature, token budget, and priority.
392
+ *
329
393
  * @param agentType - The agent type identifier
330
394
  * @returns The model preference configuration
331
395
  */
332
396
  export function getPreferredModelForAgent(agentType) {
333
397
  const category = getAgentRoutingCategory(agentType);
334
- return DEFAULT_CATEGORY_MODELS[category];
398
+ const base = DEFAULT_CATEGORY_MODELS[category];
399
+ const override = agentProviderOverrides[agentType];
400
+ if (!override)
401
+ return base;
402
+ // Changing provider without naming a model must NOT inherit the previous
403
+ // provider's model id (see `providerDefaultModels`). Prefer that provider's
404
+ // own default; only keep the category model when the provider is unchanged.
405
+ const switchingProvider = override.provider !== undefined && override.provider !== base.provider;
406
+ const resolvedModel = override.model ??
407
+ (switchingProvider ? providerDefaultModels[override.provider] : undefined);
408
+ return {
409
+ ...base,
410
+ ...(override.provider !== undefined ? { provider: override.provider } : {}),
411
+ ...(resolvedModel !== undefined ? { model: resolvedModel } : {}),
412
+ ...(override.temperature !== undefined ? { temperature: override.temperature } : {}),
413
+ ...(override.maxTokens !== undefined ? { maxTokens: override.maxTokens } : {}),
414
+ // An explicit on-disk entry outranks the built-in category rule by default,
415
+ // so it isn't quietly out-prioritized by DEFAULT_ROUTING_OVERRIDES.
416
+ priority: override.priority ?? base.priority + 100,
417
+ };
335
418
  }
336
419
  /**
337
420
  * Get capability requirements for an agent type
@@ -410,6 +493,45 @@ export function createAgentRoutingRule(agentType) {
410
493
  priority: preference.priority,
411
494
  };
412
495
  }
496
+ /**
497
+ * Build routing rules for exactly the agent types the user overrode on disk
498
+ * (issue #568).
499
+ *
500
+ * Why a separate builder rather than `createAgentRoutingRule`: that one also
501
+ * constrains on `requiresReasoning`, which is right for the generated
502
+ * whole-roster ruleset but wrong here — a user who wrote
503
+ * `"qe-mutation-tester": { "provider": "ollama" }` means *always*, not "only when
504
+ * the request happens to be flagged as needing reasoning". These rules match on
505
+ * agent type alone.
506
+ *
507
+ * Returns `[]` when nothing is overridden, so a project without the key gets the
508
+ * exact rule set it got before.
509
+ *
510
+ * @returns Routing rules, highest priority first
511
+ */
512
+ export function createOverrideRoutingRules() {
513
+ return Object.keys(agentProviderOverrides)
514
+ .map((agentType) => {
515
+ const preference = getPreferredModelForAgent(agentType);
516
+ return {
517
+ id: `agent-override-${agentType}`,
518
+ name: `User override: ${agentType} -> ${preference.provider}/${preference.model}`,
519
+ description: `Per-agent routing override from .agentic-qe/llm-config.json ` +
520
+ `(agentOverrides["${agentType}"])`,
521
+ condition: { agentType: [agentType] },
522
+ action: {
523
+ provider: preference.provider,
524
+ model: preference.model,
525
+ temperature: preference.temperature,
526
+ maxTokens: preference.maxTokens,
527
+ priority: preference.priority,
528
+ },
529
+ enabled: true,
530
+ priority: preference.priority,
531
+ };
532
+ })
533
+ .sort((a, b) => b.priority - a.priority);
534
+ }
413
535
  /**
414
536
  * Create routing rules for all agents in a category
415
537
  * @param category - The agent category
@@ -17,7 +17,7 @@
17
17
  * state — we don't disable it implicitly, because users may set keys
18
18
  * later via `aqe llm config --set`.
19
19
  */
20
- import type { RouterConfig, ExtendedProviderType } from './types.js';
20
+ import type { RouterConfig, ExtendedProviderType, AgentProviderOverride } from './types.js';
21
21
  /** Filename under .agentic-qe/ */
22
22
  export declare const ROUTER_CONFIG_FILENAME = "llm-config.json";
23
23
  /**
@@ -52,6 +52,22 @@ export declare function saveRouterConfigFile(config: Partial<RouterConfig>, proj
52
52
  * top-level scalars use last-wins.
53
53
  */
54
54
  export declare function mergeRouterConfig(base: RouterConfig, override: Partial<RouterConfig>): RouterConfig;
55
+ /**
56
+ * Validate and normalize an on-disk `agentOverrides` map (issue #568).
57
+ *
58
+ * User-hand-edited config is untrusted input: drop entries that name a provider
59
+ * we cannot construct, and strip any `apiKey`-shaped field that leaked in — the
60
+ * same "never persist API keys" discipline `saveRouterConfigFile` already
61
+ * enforces for `providers.*`.
62
+ *
63
+ * Returns the cleaned map plus human-readable warnings for the caller to log.
64
+ * Invalid entries are dropped, never thrown on: a typo in one agent key must not
65
+ * take down router initialization for the whole project.
66
+ */
67
+ export declare function sanitizeAgentOverrides(raw: unknown): {
68
+ overrides: Record<string, AgentProviderOverride>;
69
+ warnings: string[];
70
+ };
55
71
  /**
56
72
  * Apply env-detection on top of a merged config: providers whose API
57
73
  * keys are present in env are force-enabled (so a user who sets