agentic-qe 3.14.7 → 3.15.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 (428) hide show
  1. package/.claude/helpers/.helpers-version +1 -1
  2. package/.claude/helpers/auto-memory-hook.mjs +18 -9
  3. package/.claude/helpers/helpers.manifest.json +6 -5
  4. package/.claude/helpers/hook-handler.cjs +40 -12
  5. package/.claude/helpers/memory.cjs +86 -0
  6. package/.claude/helpers/router.cjs +105 -0
  7. package/.claude/helpers/session.cjs +166 -0
  8. package/.claude/helpers/statusline.cjs +73 -621
  9. package/.claude/skills/release/SKILL.md +6 -0
  10. package/.claude/skills/skills-manifest.json +1 -1
  11. package/CHANGELOG.md +275 -0
  12. package/README.md +143 -366
  13. package/assets/readme/credit-ruflo.svg +1 -0
  14. package/assets/readme/credit-ruvector.svg +1 -0
  15. package/assets/readme/project-header.svg +1 -0
  16. package/assets/readme/quality-loop.svg +1 -0
  17. package/assets/skills/skills-manifest.json +1 -1
  18. package/dist/adapters/a2a/notifications/retry-queue.js +10 -1
  19. package/dist/adapters/ag-ui/json-patch.js +14 -7
  20. package/dist/adapters/ag-ui/state-delta-cache.js +20 -12
  21. package/dist/adapters/claude-flow/pretrain-bridge.js +3 -2
  22. package/dist/agents/claim-verifier/verifiers/file-verifier.js +3 -2
  23. package/dist/cli/bundle.js +6 -6
  24. package/dist/cli/chunks/adapter-D7G5MIDQ.js +2 -0
  25. package/dist/cli/chunks/{agent-booster-wasm-AK2W76RG.js → agent-booster-wasm-GDHJ6QUN.js} +2 -2
  26. package/dist/cli/chunks/{agent-handler-MGZCWHIY.js → agent-handler-MPYYQ2RZ.js} +2 -2
  27. package/dist/cli/chunks/{agent-memory-branch-JZ54MCSP.js → agent-memory-branch-QBSHKLA2.js} +2 -2
  28. package/dist/cli/chunks/aqe-learning-engine-G6TUFGHC.js +2 -0
  29. package/dist/cli/chunks/{arena-YSWTKBCL.js → arena-UJE2FROF.js} +4 -4
  30. package/dist/cli/chunks/{arena-CUVH3V7H.js → arena-WIGSL37B.js} +2 -2
  31. package/dist/cli/chunks/{audit-LVU76QGA.js → audit-VT7Y2Z7V.js} +3 -3
  32. package/dist/cli/chunks/base-B45BOC7E.js +2 -0
  33. package/dist/cli/chunks/{better-sqlite3-DB3LOJQU.js → better-sqlite3-DSL7LFRK.js} +2 -2
  34. package/dist/cli/chunks/{brain-handler-SD63KOQ6.js → brain-handler-N3C2MDMK.js} +4 -4
  35. package/dist/cli/chunks/{branch-enumerator-4MNOPUC7.js → branch-enumerator-B6NSQ3PZ.js} +2 -2
  36. package/dist/cli/chunks/{browser-OLPNTWQE.js → browser-KQ3YNRGW.js} +2 -2
  37. package/dist/cli/chunks/browser-workflow-MIBU4XMV.js +2 -0
  38. package/dist/cli/chunks/{chunk-ZWEKAEEV.js → chunk-2ORTL5WG.js} +1 -1
  39. package/dist/cli/chunks/{chunk-KD2BLA5Y.js → chunk-2ZEV3O24.js} +1 -1
  40. package/dist/cli/chunks/{chunk-25P6JA6V.js → chunk-32YSI6OT.js} +1 -1
  41. package/dist/cli/chunks/{chunk-A5MA7A23.js → chunk-3DKYBHNA.js} +6 -6
  42. package/dist/cli/chunks/{chunk-JOZ47MV6.js → chunk-3Y24VTZ3.js} +1 -1
  43. package/dist/cli/chunks/{chunk-2G63VIJE.js → chunk-4BWDCUZZ.js} +1 -1
  44. package/dist/cli/chunks/{chunk-36VKMAMN.js → chunk-4DCDIKBX.js} +2 -2
  45. package/dist/cli/chunks/chunk-4EEY23JS.js +4 -0
  46. package/dist/cli/chunks/{chunk-BD7FEUN3.js → chunk-4FOKHGP5.js} +3 -3
  47. package/dist/cli/chunks/{chunk-MQZ53OR3.js → chunk-4OQSAUKR.js} +2 -2
  48. package/dist/cli/chunks/{chunk-EYXE2XKP.js → chunk-4YPL3OXS.js} +2 -2
  49. package/dist/cli/chunks/{chunk-PCJQCEBA.js → chunk-5DJGP4TA.js} +2 -2
  50. package/dist/cli/chunks/{chunk-RC2A4JZ5.js → chunk-5KN4QL3G.js} +2 -2
  51. package/dist/cli/chunks/chunk-5LN7FQZI.js +2 -0
  52. package/dist/cli/chunks/{chunk-LU2EDWQK.js → chunk-5PNRUMRV.js} +2 -2
  53. package/dist/cli/chunks/{chunk-YRHTQZU4.js → chunk-62IEVKN3.js} +2 -2
  54. package/dist/cli/chunks/{chunk-DOBKEXMJ.js → chunk-6GTIJNRO.js} +1 -1
  55. package/dist/cli/chunks/{chunk-O5V7RHVG.js → chunk-6MN4L6BS.js} +2 -2
  56. package/dist/cli/chunks/{chunk-6PJPQGF4.js → chunk-7D6NVIGP.js} +6 -6
  57. package/dist/cli/chunks/{chunk-B2YGVSOP.js → chunk-7JABIXP3.js} +2 -2
  58. package/dist/cli/chunks/chunk-7JC3LHA6.js +742 -0
  59. package/dist/cli/chunks/{chunk-P7XSPP5D.js → chunk-7WUHVGGT.js} +2 -2
  60. package/dist/cli/chunks/{chunk-RKI3IQKQ.js → chunk-A37YYHUD.js} +3 -3
  61. package/dist/cli/chunks/{chunk-UBJG3IHT.js → chunk-AAQNRZKT.js} +2 -2
  62. package/dist/cli/chunks/{chunk-ND4QTZOL.js → chunk-AGYPPPXR.js} +2 -2
  63. package/dist/cli/chunks/chunk-AIE6OKCD.js +2 -0
  64. package/dist/cli/chunks/{chunk-JHJUSSAU.js → chunk-ANUZGOLQ.js} +2 -2
  65. package/dist/cli/chunks/{chunk-RLW25X66.js → chunk-AQZSF32Y.js} +2 -2
  66. package/dist/cli/chunks/{chunk-OIDWDGLG.js → chunk-ATXAMGVE.js} +2 -2
  67. package/dist/cli/chunks/{chunk-GLGKQX2V.js → chunk-AV3RX2L5.js} +2 -2
  68. package/dist/cli/chunks/{chunk-7QYOTUOX.js → chunk-AW5OWYQ4.js} +2 -2
  69. package/dist/cli/chunks/{chunk-B4I43GE2.js → chunk-B6QTNTCU.js} +2 -2
  70. package/dist/cli/chunks/{chunk-P2UPYSDJ.js → chunk-BAPMEDWC.js} +1 -1
  71. package/dist/cli/chunks/{chunk-Y6AKKQIQ.js → chunk-BH2SQQ2N.js} +1 -1
  72. package/dist/cli/chunks/{chunk-O6MO5KMR.js → chunk-C6M27NQE.js} +2 -2
  73. package/dist/cli/chunks/{chunk-XBYQ2BS4.js → chunk-CMYZWIXS.js} +2 -2
  74. package/dist/cli/chunks/{chunk-DYTQHRUS.js → chunk-CZWWC7GC.js} +1 -1
  75. package/dist/cli/chunks/{chunk-WF6UISKW.js → chunk-D7NOHASX.js} +4 -4
  76. package/dist/cli/chunks/{chunk-H5RQPO3X.js → chunk-DGRE6ZAA.js} +2 -2
  77. package/dist/cli/chunks/{chunk-53BXTTRO.js → chunk-DSGRXW6K.js} +3 -3
  78. package/dist/cli/chunks/{chunk-A2VUCUTT.js → chunk-DXA7RLYU.js} +2 -2
  79. package/dist/cli/chunks/{chunk-GVVFTFMB.js → chunk-DZHIE5UW.js} +2 -2
  80. package/dist/cli/chunks/{chunk-MZB2UV2O.js → chunk-EBK6CUBD.js} +1 -1
  81. package/dist/cli/chunks/{chunk-WIH522AP.js → chunk-EPEKEUCF.js} +1 -1
  82. package/dist/cli/chunks/{chunk-SRPLERER.js → chunk-EQ4SDE4L.js} +25 -25
  83. package/dist/cli/chunks/{chunk-EGOIIUBD.js → chunk-EZPWSS3B.js} +2 -2
  84. package/dist/cli/chunks/{chunk-EADSQN5T.js → chunk-F76SYOBT.js} +1 -1
  85. package/dist/cli/chunks/{chunk-XL5KIYE3.js → chunk-F7JVDLOI.js} +2 -2
  86. package/dist/cli/chunks/{chunk-QGOWNVVG.js → chunk-FCSETOWZ.js} +4 -4
  87. package/dist/cli/chunks/{chunk-A3DK3XNZ.js → chunk-FFE4XAQA.js} +1 -1
  88. package/dist/cli/chunks/{chunk-7EZ2Z2CK.js → chunk-FPTZP7W5.js} +1 -1
  89. package/dist/cli/chunks/{chunk-GV4DYPJP.js → chunk-FTFIA4I5.js} +2 -2
  90. package/dist/cli/chunks/{chunk-SM2YJ2AL.js → chunk-FTS6NGBP.js} +2 -2
  91. package/dist/cli/chunks/{chunk-XWYELBZS.js → chunk-FZ3TQAPW.js} +1 -1
  92. package/dist/cli/chunks/{chunk-HPWWYT67.js → chunk-G35KP72N.js} +2 -2
  93. package/dist/cli/chunks/{chunk-HZY42OVU.js → chunk-GCHDMO5V.js} +2 -2
  94. package/dist/cli/chunks/{chunk-23CX7JNL.js → chunk-GRN47ANK.js} +2 -2
  95. package/dist/cli/chunks/{chunk-HYFQUWNB.js → chunk-GV7P5JYF.js} +2 -2
  96. package/dist/cli/chunks/{chunk-YO4ESCB4.js → chunk-GX5RFGW2.js} +1 -1
  97. package/dist/cli/chunks/{chunk-TFK2AYIN.js → chunk-H77AUJNW.js} +2 -2
  98. package/dist/cli/chunks/{chunk-NBLDBVAW.js → chunk-HBIV7PQH.js} +1 -1
  99. package/dist/cli/chunks/{chunk-VYDVI6FZ.js → chunk-HOPXHZA3.js} +2 -2
  100. package/dist/cli/chunks/{chunk-HYOPJHHW.js → chunk-I3BH3KIF.js} +1 -1
  101. package/dist/cli/chunks/{chunk-ZELWDJXT.js → chunk-ILKMNDUM.js} +2 -2
  102. package/dist/cli/chunks/{chunk-C3FXFU2T.js → chunk-IRHBR56R.js} +1 -1
  103. package/dist/cli/chunks/{chunk-FYPX5WBJ.js → chunk-ISAMM7QA.js} +1 -1
  104. package/dist/cli/chunks/{chunk-V5AK56DA.js → chunk-ISGFAMHZ.js} +2 -2
  105. package/dist/cli/chunks/{chunk-KUHLTVWC.js → chunk-J46XGXPS.js} +1 -1
  106. package/dist/cli/chunks/{chunk-ZS4XVJGV.js → chunk-J4XCBOPA.js} +2 -2
  107. package/dist/cli/chunks/{chunk-BEFTQVEW.js → chunk-JIWMFLHV.js} +2 -2
  108. package/dist/cli/chunks/{chunk-UFSVUBTR.js → chunk-JJ7WAU4I.js} +2 -2
  109. package/dist/cli/chunks/{chunk-WOV6XI3A.js → chunk-JLPNYHJJ.js} +1 -1
  110. package/dist/cli/chunks/{chunk-77QZHIVX.js → chunk-JO2YLIZH.js} +2 -2
  111. package/dist/cli/chunks/{chunk-J7AQZLIH.js → chunk-JSYNSJDQ.js} +4 -4
  112. package/dist/cli/chunks/{chunk-OAZX6WFU.js → chunk-JYRBOSOF.js} +2 -2
  113. package/dist/cli/chunks/{chunk-EJ6MMYLK.js → chunk-KEZ4PXVF.js} +1 -1
  114. package/dist/cli/chunks/{chunk-N5XOXPHZ.js → chunk-KLGFEHEN.js} +2 -2
  115. package/dist/cli/chunks/{chunk-7MIOK72I.js → chunk-KU4WLKDK.js} +7 -7
  116. package/dist/cli/chunks/{chunk-Z4Q5PCRZ.js → chunk-KUTMQBV4.js} +4 -4
  117. package/dist/cli/chunks/{chunk-VW6FRMLW.js → chunk-L6PUBB6L.js} +2 -2
  118. package/dist/cli/chunks/{chunk-OEPNNLR4.js → chunk-LDJ5DZT5.js} +1 -1
  119. package/dist/cli/chunks/{chunk-QQFQDEUE.js → chunk-LLS6JYPN.js} +2 -2
  120. package/dist/cli/chunks/{chunk-UOI6ULCH.js → chunk-LPCFIFZF.js} +2 -2
  121. package/dist/cli/chunks/{chunk-6RD44SCE.js → chunk-M5EKZA7Q.js} +1 -1
  122. package/dist/cli/chunks/chunk-MEYSIVMP.js +2 -0
  123. package/dist/cli/chunks/{chunk-YMW57PEL.js → chunk-MFGLRMO4.js} +1 -1
  124. package/dist/cli/chunks/{chunk-BE4KALTE.js → chunk-MM57SD2F.js} +1 -1
  125. package/dist/cli/chunks/{chunk-FW4DJ4FJ.js → chunk-MO3QXLF2.js} +1 -1
  126. package/dist/cli/chunks/{chunk-QFETNCNN.js → chunk-MRIZY6HB.js} +2 -2
  127. package/dist/cli/chunks/{chunk-RT6O2HW2.js → chunk-N2MDNEF7.js} +2 -2
  128. package/dist/cli/chunks/{chunk-UA7TDVL7.js → chunk-N5ZHIQAV.js} +4 -4
  129. package/dist/cli/chunks/{chunk-Q6NTEICT.js → chunk-NZ556KZN.js} +2 -2
  130. package/dist/cli/chunks/{chunk-CVOQ6ESD.js → chunk-O5AUOBGU.js} +2 -2
  131. package/dist/cli/chunks/{chunk-5D7ZFWDS.js → chunk-OBSX3I4Y.js} +2 -2
  132. package/dist/cli/chunks/{chunk-NOHWJOBS.js → chunk-OLD2CIDI.js} +1 -1
  133. package/dist/cli/chunks/{chunk-5U6N4V5M.js → chunk-OTJ22IO2.js} +4 -4
  134. package/dist/cli/chunks/{chunk-5GFKTJ65.js → chunk-OYVDTD3A.js} +2 -2
  135. package/dist/cli/chunks/{chunk-LY7MFGBD.js → chunk-P2PPJUGD.js} +147 -150
  136. package/dist/cli/chunks/{chunk-OZGIOKEA.js → chunk-P4FRYNHL.js} +1 -1
  137. package/dist/cli/chunks/{chunk-X7ADKL7T.js → chunk-P4WE6VRR.js} +2 -2
  138. package/dist/cli/chunks/{chunk-ZUB5YOCM.js → chunk-P725KXHX.js} +2 -2
  139. package/dist/cli/chunks/{chunk-74IOEOMH.js → chunk-P7MNF2SK.js} +2 -2
  140. package/dist/cli/chunks/{chunk-TXSPBLBT.js → chunk-PJU5HVWV.js} +2 -2
  141. package/dist/cli/chunks/{chunk-MT7UNBZ7.js → chunk-PN3FYSQ6.js} +2 -2
  142. package/dist/cli/chunks/{chunk-F2OPFVQH.js → chunk-PPFW3H7E.js} +1 -1
  143. package/dist/cli/chunks/{chunk-IEJ7ZV3M.js → chunk-Q4RCUCHD.js} +1 -1
  144. package/dist/cli/chunks/{chunk-IAENZ2DR.js → chunk-QRALXNNX.js} +2 -2
  145. package/dist/cli/chunks/{chunk-AJUBT4NP.js → chunk-QVX22EIM.js} +3 -3
  146. package/dist/cli/chunks/chunk-R6CZCMKD.js +2 -0
  147. package/dist/cli/chunks/chunk-ROK5YQ5P.js +3 -0
  148. package/dist/cli/chunks/{chunk-ON2UTP2U.js → chunk-S2GNFAOC.js} +2 -2
  149. package/dist/cli/chunks/{chunk-HXXHMLJ5.js → chunk-S644OORE.js} +1 -1
  150. package/dist/cli/chunks/{chunk-XYLQZWF6.js → chunk-S7CROKX4.js} +2 -2
  151. package/dist/cli/chunks/{chunk-T77GZF4B.js → chunk-S7QUHLXV.js} +1 -1
  152. package/dist/cli/chunks/{chunk-RDGPXENG.js → chunk-UGYXUPGN.js} +2 -2
  153. package/dist/cli/chunks/{chunk-QVH5Y7AP.js → chunk-URRPJ3M7.js} +1 -1
  154. package/dist/cli/chunks/{chunk-AEUEMVJK.js → chunk-URUOTHPO.js} +2 -2
  155. package/dist/cli/chunks/{chunk-VXKWNRGA.js → chunk-VCYOFWMG.js} +2 -2
  156. package/dist/cli/chunks/{chunk-6EGS77BB.js → chunk-VQVFGFYK.js} +1 -1
  157. package/dist/cli/chunks/{chunk-NHUGHAY6.js → chunk-VT5SMBEM.js} +1 -1
  158. package/dist/cli/chunks/{chunk-ROVZSZCS.js → chunk-VTGRGYY4.js} +3 -3
  159. package/dist/cli/chunks/{chunk-QPLSYEWJ.js → chunk-VWCFXCSV.js} +2 -2
  160. package/dist/cli/chunks/{chunk-ENK44A6Q.js → chunk-VY4557VF.js} +2 -2
  161. package/dist/cli/chunks/{chunk-5FSLMYAC.js → chunk-VYERAOQL.js} +2 -2
  162. package/dist/cli/chunks/{chunk-EIGRV3J6.js → chunk-W6H2SOIK.js} +2 -2
  163. package/dist/cli/chunks/{chunk-CBONQM5D.js → chunk-WBR4VRQE.js} +2 -2
  164. package/dist/cli/chunks/{chunk-JZT7BU44.js → chunk-WDV6CBED.js} +2 -2
  165. package/dist/cli/chunks/{chunk-G367W7XR.js → chunk-WO7NPGUD.js} +19 -19
  166. package/dist/cli/chunks/{chunk-4INST4ZL.js → chunk-WPOYFV4X.js} +1 -1
  167. package/dist/cli/chunks/{chunk-3M7J4U74.js → chunk-WPSGMTI4.js} +4 -4
  168. package/dist/cli/chunks/{chunk-RKUAWQOF.js → chunk-WQMXQO3O.js} +2 -2
  169. package/dist/cli/chunks/{chunk-Q3NSU24F.js → chunk-WR54SKKL.js} +2 -2
  170. package/dist/cli/chunks/{chunk-UYUJT6QO.js → chunk-X4OESN7M.js} +2 -2
  171. package/dist/cli/chunks/{chunk-ZUOVNFXK.js → chunk-X5RELRY7.js} +2 -2
  172. package/dist/cli/chunks/{chunk-BLG7SH4A.js → chunk-X7JEBPEW.js} +1 -1
  173. package/dist/cli/chunks/{chunk-FSSR6WBE.js → chunk-XEABMIUH.js} +2 -2
  174. package/dist/cli/chunks/{chunk-ONR2NXXD.js → chunk-XELFJC77.js} +3 -3
  175. package/dist/cli/chunks/{chunk-MM56VPNE.js → chunk-XPUY3ZKD.js} +3 -3
  176. package/dist/cli/chunks/{chunk-QUORH2MG.js → chunk-XZDPR6I2.js} +8 -8
  177. package/dist/cli/chunks/{chunk-MZMG6CUJ.js → chunk-Y63DADOR.js} +2 -2
  178. package/dist/cli/chunks/{chunk-CQNMGK6Y.js → chunk-YFRZVNE4.js} +2 -2
  179. package/dist/cli/chunks/{chunk-3QJU4Q4R.js → chunk-YIDZ3TEN.js} +2 -2
  180. package/dist/cli/chunks/{chunk-4EKV7PHB.js → chunk-Z6CRROLU.js} +2 -2
  181. package/dist/cli/chunks/{chunk-IWFFO6VT.js → chunk-ZPH2YT3J.js} +2 -2
  182. package/dist/cli/chunks/{chunk-PYKY22GC.js → chunk-ZV7LJPSI.js} +5 -5
  183. package/dist/cli/chunks/chunk-ZXIIB3QE.js +2 -0
  184. package/dist/cli/chunks/ci-63JINRNB.js +82 -0
  185. package/dist/cli/chunks/{ci-output-RLS32FUY.js → ci-output-CRFWLUAA.js} +2 -2
  186. package/dist/cli/chunks/{circuit-breaker-MRCC7WCM.js → circuit-breaker-PJLG3WYL.js} +2 -2
  187. package/dist/cli/chunks/{claude-flow-setup-LIZCEKDF.js → claude-flow-setup-UKHSQMJU.js} +2 -2
  188. package/dist/cli/chunks/client-A4FTITK3.js +2 -0
  189. package/dist/cli/chunks/{cline-installer-T7H6R2RC.js → cline-installer-PYQ27AS3.js} +2 -2
  190. package/dist/cli/chunks/{code-XMBLI7OF.js → code-K7VGLZ3W.js} +3 -3
  191. package/dist/cli/chunks/{code-index-extractor-QS7BYLEX.js → code-index-extractor-NNWAVWSL.js} +2 -2
  192. package/dist/cli/chunks/{codex-installer-6PGT5FM6.js → codex-installer-U4VJIKRN.js} +2 -2
  193. package/dist/cli/chunks/{completions-2A3WRXY2.js → completions-DOCI3P4W.js} +2 -2
  194. package/dist/cli/chunks/{complexity-analyzer-23HOOGJ7.js → complexity-analyzer-RFW2QRFR.js} +2 -2
  195. package/dist/cli/chunks/{continuedev-installer-4FSF7B3N.js → continuedev-installer-S5WXXOBU.js} +2 -2
  196. package/dist/cli/chunks/{copilot-installer-A5GRQQUU.js → copilot-installer-AAQ6YLVJ.js} +2 -2
  197. package/dist/cli/chunks/core-handlers-FO3QTNWI.js +2 -0
  198. package/dist/cli/chunks/{cost-tracker-Z4STQ5VB.js → cost-tracker-R4VOHTWQ.js} +2 -2
  199. package/dist/cli/chunks/{coverage-NUPP6KZZ.js → coverage-P54HPCLV.js} +3 -3
  200. package/dist/cli/chunks/cross-domain-router-LIV6SRWF.js +2 -0
  201. package/dist/cli/chunks/{cursor-installer-FVJ7ROPJ.js → cursor-installer-VHBWZE5A.js} +2 -2
  202. package/dist/cli/chunks/{daemon-D662EX5N.js → daemon-BTRSWNB4.js} +4 -4
  203. package/dist/cli/chunks/{daemon-7ZZA2MMN.js → daemon-JLH5TTWZ.js} +4 -4
  204. package/dist/cli/chunks/{dag-attention-scheduler-IB4TQ2KA.js → dag-attention-scheduler-5Z6DCRFK.js} +2 -2
  205. package/dist/cli/chunks/{detect-LGLBZN4I.js → detect-NWGASRJJ.js} +2 -2
  206. package/dist/cli/chunks/{dist-node-Z3OL42YE.js → dist-node-XMNNSEFJ.js} +2 -2
  207. package/dist/cli/chunks/{domain-handler-L3CLNL7U.js → domain-handler-BWVBZTNR.js} +2 -2
  208. package/dist/cli/chunks/{domain-plugins-GQ3V5X6L.js → domain-plugins-YAD4USA4.js} +2 -2
  209. package/dist/cli/chunks/domain-transfer-Z3MRPZEZ.js +2 -0
  210. package/dist/cli/chunks/dream-DNLGHYXY.js +2 -0
  211. package/dist/cli/chunks/{embed-and-insert-pattern-UGD6USYH.js → embed-and-insert-pattern-5CCO45WC.js} +2 -2
  212. package/dist/cli/chunks/{eval-3B7UIYGY.js → eval-JEMLTGY4.js} +2 -2
  213. package/dist/cli/chunks/{experience-capture-middleware-3RQ4NYY3.js → experience-capture-middleware-FKVYBBAN.js} +4 -4
  214. package/dist/cli/chunks/{fast-paths-QOSAEPYD.js → fast-paths-TFL32H3C.js} +2 -2
  215. package/dist/cli/chunks/{feature-flags-3S5TH6P4.js → feature-flags-CNGAUUMT.js} +2 -2
  216. package/dist/cli/chunks/{feature-flags-TLF4NKOH.js → feature-flags-OHGD2NCW.js} +2 -2
  217. package/dist/cli/chunks/{file-discovery-AEVMJRNB.js → file-discovery-IHGDYW34.js} +2 -2
  218. package/dist/cli/chunks/{fleet-E6WTXWFL.js → fleet-OGTSDGJ2.js} +4 -4
  219. package/dist/cli/chunks/{gnn-wrapper-MCKH3AUU.js → gnn-wrapper-QYTTKNCE.js} +2 -2
  220. package/dist/cli/chunks/{heartbeat-handler-U7XENHRR.js → heartbeat-handler-R5OD2SKN.js} +4 -4
  221. package/dist/cli/chunks/heartbeat-scheduler-DL4LXXJF.js +2 -0
  222. package/dist/cli/chunks/hnsw-adapter-Y64M43J4.js +2 -0
  223. package/dist/cli/chunks/hnsw-index-5V6DDMTA.js +2 -0
  224. package/dist/cli/chunks/{hnsw-legacy-bridge-5GW4SAEI.js → hnsw-legacy-bridge-ULJWYXBQ.js} +2 -2
  225. package/dist/cli/chunks/{hnswlib-node-7BLZBK5T.js → hnswlib-node-SYKJXGE2.js} +2 -2
  226. package/dist/cli/chunks/{hooks-F3O2SB6H.js → hooks-XAJXPXTU.js} +10 -10
  227. package/dist/cli/chunks/hybrid-backend-JWT2V4FQ.js +2 -0
  228. package/dist/cli/chunks/{hypergraph-engine-PV4EKXHB.js → hypergraph-engine-GIBPGW4N.js} +2 -2
  229. package/dist/cli/chunks/{hypergraph-handler-VOWO5ZTW.js → hypergraph-handler-ENFK6IDN.js} +3 -3
  230. package/dist/cli/chunks/impact-analyzer-XUZQSZZC.js +2 -0
  231. package/dist/cli/chunks/{init-handler-ENJ5ONJX.js → init-handler-CSA62LGT.js} +6 -6
  232. package/dist/cli/chunks/init-wizard-KDJKHEPN.js +2 -0
  233. package/dist/cli/chunks/kernel-MUDYPGFR.js +2 -0
  234. package/dist/cli/chunks/{kilocode-installer-HNNJOOPE.js → kilocode-installer-YXFIRTSA.js} +2 -2
  235. package/dist/cli/chunks/{kiro-installer-UZBIQ3IC.js → kiro-installer-JW3BG2MQ.js} +2 -2
  236. package/dist/cli/chunks/knowledge-graph-GR52N7PU.js +2 -0
  237. package/dist/cli/chunks/{learning-YMLCVFUT.js → learning-BDBZ7ZVG.js} +4 -4
  238. package/dist/cli/chunks/{llm-router-YWTARCCT.js → llm-router-CCX2DYTC.js} +4 -4
  239. package/dist/cli/chunks/llm-router-service-QL6LVKZ4.js +2 -0
  240. package/dist/cli/chunks/{load-DKE3F3IP.js → load-UJTTEOOK.js} +2 -2
  241. package/dist/cli/chunks/load-test-76V75WZ5.js +2 -0
  242. package/dist/cli/chunks/{mcp-5PSGIUCW.js → mcp-2NAJYREC.js} +2 -2
  243. package/dist/cli/chunks/{memory-3L3O6JMM.js → memory-C3UQSN5F.js} +5 -5
  244. package/dist/cli/chunks/memory-backend-SMQRS5QN.js +2 -0
  245. package/dist/cli/chunks/memory-handlers-ESFIJENU.js +2 -0
  246. package/dist/cli/chunks/{multi-model-executor-AEEO7IA4.js → multi-model-executor-SIHSHAD7.js} +2 -2
  247. package/dist/cli/chunks/{opencode-installer-ABBO355U.js → opencode-installer-KDYHUGPG.js} +2 -2
  248. package/dist/cli/chunks/{orchestrator-E36Q7MKE.js → orchestrator-MJHIQEHD.js} +6 -6
  249. package/dist/cli/chunks/pattern-null-store-MWAJMOYU.js +2 -0
  250. package/dist/cli/chunks/{pattern-usage-recorder-H4XKSID4.js → pattern-usage-recorder-OLBE4UIF.js} +2 -2
  251. package/dist/cli/chunks/{pipeline-BGFEHXIN.js → pipeline-IOK2CV3U.js} +2 -2
  252. package/dist/cli/chunks/{platform-GK7ZVDJI.js → platform-53JQ7JXN.js} +2 -2
  253. package/dist/cli/chunks/{plugin-CAH2CKI6.js → plugin-L5SDIWDI.js} +2 -2
  254. package/dist/cli/chunks/{prime-radiant-advanced-wasm-M5EYRONA.js → prime-radiant-advanced-wasm-2DS67JFS.js} +2 -2
  255. package/dist/cli/chunks/{project-root-BSNZC243.js → project-root-LQMOFO2Z.js} +2 -2
  256. package/dist/cli/chunks/protocol-executor-32X3GAJT.js +2 -0
  257. package/dist/cli/chunks/{protocol-handler-JDSSC2SF.js → protocol-handler-NXG2M43B.js} +2 -2
  258. package/dist/cli/chunks/{prove-ANPTOZJE.js → prove-7K7PFSSX.js} +2 -2
  259. package/dist/cli/chunks/qe-reasoning-bank-KAFV3TGI.js +2 -0
  260. package/dist/cli/chunks/{quality-SXWGYRQR.js → quality-ATILUGMJ.js} +2 -2
  261. package/dist/cli/chunks/quality-gate-MPZMDPIZ.js +7 -0
  262. package/dist/cli/chunks/queen-coordinator-L3SODGRX.js +2 -0
  263. package/dist/cli/chunks/{real-embeddings-WSRYAOZM.js → real-embeddings-VZN3KIAI.js} +2 -2
  264. package/dist/cli/chunks/{ref-validation-AZ3LRWEK.js → ref-validation-EUATPVXX.js} +2 -2
  265. package/dist/cli/chunks/{roocode-installer-2QKGFIEU.js → roocode-installer-7M2GOUNZ.js} +2 -2
  266. package/dist/cli/chunks/router-DDCSSXYQ.js +2 -0
  267. package/dist/cli/chunks/routing-feedback-RFASKYCD.js +2 -0
  268. package/dist/cli/chunks/{routing-handler-UYDC5MMD.js → routing-handler-VWANE652.js} +2 -2
  269. package/dist/cli/chunks/{ruvector-commands-QXADPVEY.js → ruvector-commands-B2YIPGOV.js} +2 -2
  270. package/dist/cli/chunks/rvf-dual-writer-HCIF2G56.js +2 -0
  271. package/dist/cli/chunks/rvf-migration-adapter-UVAHQ7SV.js +2 -0
  272. package/dist/cli/chunks/{rvf-migration-coordinator-GD4NBFKT.js → rvf-migration-coordinator-RQXOQJ5T.js} +2 -2
  273. package/dist/cli/chunks/rvf-native-adapter-F2I5FFHK.js +2 -0
  274. package/dist/cli/chunks/{rvf-store-integrity-7SXG66IL.js → rvf-store-integrity-7P5YDXRH.js} +2 -2
  275. package/dist/cli/chunks/safe-db-6ZAA4S23.js +2 -0
  276. package/dist/cli/chunks/schedule-SM5Q6UVP.js +2 -0
  277. package/dist/cli/chunks/scheduler-4EYP4EZ6.js +2 -0
  278. package/dist/cli/chunks/{security-YKB622PK.js → security-VJ7TVSQF.js} +3 -3
  279. package/dist/cli/chunks/{shared-rvf-adapter-KMLAV7JK.js → shared-rvf-adapter-63NXQFBX.js} +2 -2
  280. package/dist/cli/chunks/{shared-rvf-dual-writer-OYY27DFV.js → shared-rvf-dual-writer-JQRP7P5A.js} +2 -2
  281. package/dist/cli/chunks/sqlite-persistence-KLN2K266.js +2 -0
  282. package/dist/cli/chunks/{standalone-memory-2DOABVLC.js → standalone-memory-WJ72PH5P.js} +2 -2
  283. package/dist/cli/chunks/{status-handler-EXRKETV7.js → status-handler-G72ZSLAX.js} +2 -2
  284. package/dist/cli/chunks/{structural-health-2SKK6DU6.js → structural-health-HYBGP4BD.js} +2 -2
  285. package/dist/cli/chunks/{sync-DQ2YUNI6.js → sync-5YMZZIF4.js} +2 -2
  286. package/dist/cli/chunks/{sync-UW7SX7GO.js → sync-O5FQAHT7.js} +2 -2
  287. package/dist/cli/chunks/{task-handler-LYQ6WYUY.js → task-handler-E6IFNHZG.js} +2 -2
  288. package/dist/cli/chunks/{task-handlers-DIJO232S.js → task-handlers-P3GC2L5L.js} +3 -3
  289. package/dist/cli/chunks/{test-WRHZMUCW.js → test-OU6ERW67.js} +6 -6
  290. package/dist/cli/chunks/{test-scheduling-HI23RXFK.js → test-scheduling-3HY4I3HY.js} +7 -7
  291. package/dist/cli/chunks/{token-bootstrap-23SA6SWZ.js → token-bootstrap-A5QA4CWK.js} +2 -2
  292. package/dist/cli/chunks/{token-usage-M7RRDPXO.js → token-usage-MUNQVPFT.js} +2 -2
  293. package/dist/cli/chunks/{transformers-4TC35KKS.js → transformers-IEO25W5V.js} +2 -2
  294. package/dist/cli/chunks/{tree-sitter-wasm-parser-F4LTKAWD.js → tree-sitter-wasm-parser-T2EQHEAY.js} +2 -2
  295. package/dist/cli/chunks/{types-NBXV6LXQ.js → types-ODCPGCID.js} +2 -2
  296. package/dist/cli/chunks/unified-memory-B5IA2KKQ.js +2 -0
  297. package/dist/cli/chunks/unified-memory-hnsw-YF74LL3Z.js +2 -0
  298. package/dist/cli/chunks/unified-persistence-VZMGNGWY.js +2 -0
  299. package/dist/cli/chunks/{upgrade-4BGOU5RM.js → upgrade-4DN6EIW2.js} +2 -2
  300. package/dist/cli/chunks/{validate-EDWAR63H.js → validate-TBNAPDE3.js} +2 -2
  301. package/dist/cli/chunks/{validate-swarm-VI72CPR7.js → validate-swarm-ZN7XXUY4.js} +2 -2
  302. package/dist/cli/chunks/visual-security-ZV3BLLSH.js +2 -0
  303. package/dist/cli/chunks/{web-tree-sitter-Y5XBRQXF.js → web-tree-sitter-DWAWVD2X.js} +2 -2
  304. package/dist/cli/chunks/{windsurf-installer-VEX23WAF.js → windsurf-installer-U6EROS5S.js} +2 -2
  305. package/dist/cli/chunks/{witness-chain-3YNL6YGY.js → witness-chain-EQEJS2P4.js} +2 -2
  306. package/dist/cli/chunks/witness-chain-OA24MQWX.js +2 -0
  307. package/dist/cli/chunks/{witness-chain-repair-MJZGZRWT.js → witness-chain-repair-KBXDRXS3.js} +2 -2
  308. package/dist/cli/chunks/{witness-chain-verifier-TTJYXTBE.js → witness-chain-verifier-HSQGZ4R4.js} +2 -2
  309. package/dist/cli/chunks/{witness-key-manager-EM6YXYOY.js → witness-key-manager-RAODG73T.js} +2 -2
  310. package/dist/cli/chunks/{workflow-2RBDOM7V.js → workflow-KNFJNNKG.js} +4 -4
  311. package/dist/cli/chunks/workflow-orchestrator-IMX2LSVE.js +2 -0
  312. package/dist/cli/chunks/{wrappers-5OTAVVOV.js → wrappers-NIJBA22T.js} +2 -2
  313. package/dist/cli/commands/ci.js +17 -6
  314. package/dist/cli/commands/quality-gate.js +6 -1
  315. package/dist/cli/index.js +7 -2
  316. package/dist/cli/process-store-cleanup.d.ts +7 -0
  317. package/dist/cli/process-store-cleanup.js +27 -0
  318. package/dist/cli/utils/ci-config.d.ts +3 -3
  319. package/dist/cli/utils/ci-config.js +202 -68
  320. package/dist/cli/utils/workflow-parser.js +73 -57
  321. package/dist/domains/code-intelligence/services/metric-collector/test-counter.d.ts +1 -1
  322. package/dist/domains/code-intelligence/services/metric-collector/test-counter.js +17 -15
  323. package/dist/domains/quality-assessment/quality-evidence.d.ts +3 -1
  324. package/dist/domains/quality-assessment/quality-evidence.js +7 -2
  325. package/dist/domains/test-execution/services/retry-handler.js +38 -16
  326. package/dist/domains/test-execution/services/test-executor.d.ts +3 -3
  327. package/dist/domains/test-execution/services/test-executor.js +66 -22
  328. package/dist/governance/ab-benchmarking.d.ts +5 -1
  329. package/dist/governance/ab-benchmarking.js +64 -29
  330. package/dist/init/fleet-integration.js +3 -2
  331. package/dist/init/init-wizard-steps.js +3 -2
  332. package/dist/init/phases/06-code-intelligence.js +6 -4
  333. package/dist/integrations/ruvector/sona-persistence.d.ts +1 -0
  334. package/dist/integrations/ruvector/sona-persistence.js +74 -20
  335. package/dist/integrations/ruvector/sona-wrapper.d.ts +2 -0
  336. package/dist/integrations/ruvector/sona-wrapper.js +13 -0
  337. package/dist/kernel/memory-backend.js +5 -4
  338. package/dist/kernel/unified-memory.js +3 -2
  339. package/dist/learning/aqe-learning-engine.js +3 -2
  340. package/dist/mcp/bundle.js +474 -471
  341. package/dist/mcp/connection-pool.d.ts +2 -0
  342. package/dist/mcp/connection-pool.js +13 -2
  343. package/dist/mcp/handlers/memory-handlers.d.ts +1 -0
  344. package/dist/mcp/handlers/memory-handlers.js +16 -6
  345. package/dist/mcp/protocol-server.js +29 -8
  346. package/dist/mcp/security/rate-limiter.d.ts +1 -0
  347. package/dist/mcp/security/rate-limiter.js +22 -5
  348. package/dist/mcp/services/session-store.js +17 -17
  349. package/dist/mcp/tools/planning/goap-status.d.ts +2 -0
  350. package/dist/mcp/tools/planning/goap-status.js +8 -2
  351. package/dist/mcp/types.d.ts +2 -0
  352. package/dist/optimization/session-cache.js +13 -11
  353. package/dist/planning/goap-planner.d.ts +3 -0
  354. package/dist/planning/goap-planner.js +80 -37
  355. package/dist/plugins/cache.js +10 -3
  356. package/dist/shared/embeddings/embedding-cache.js +5 -5
  357. package/dist/shared/embeddings/nomic-embedder.js +17 -7
  358. package/dist/shared/embeddings/ollama-client.js +5 -3
  359. package/dist/shared/git/git-analyzer.js +31 -30
  360. package/dist/shared/http/http-client.js +20 -13
  361. package/dist/shared/io/file-reader.js +11 -8
  362. package/dist/shared/llm/cache.d.ts +8 -29
  363. package/dist/shared/llm/cache.js +12 -11
  364. package/dist/shared/llm/cost-tracker.js +2 -1
  365. package/dist/shared/llm/provider-manager.js +4 -22
  366. package/dist/shared/llm/providers/gemini.d.ts +1 -0
  367. package/dist/shared/llm/providers/gemini.js +14 -5
  368. package/dist/shared/llm/providers/openrouter.js +6 -3
  369. package/dist/shared/metrics/code-metrics.js +1 -1
  370. package/dist/shared/metrics/system-metrics.js +8 -2
  371. package/dist/shared/retry-engine.js +6 -12
  372. package/dist/shared/test-runner-process.d.ts +10 -0
  373. package/dist/shared/test-runner-process.js +210 -0
  374. package/dist/test-scheduling/executors/vitest-executor.js +26 -17
  375. package/dist/validation/quality-verdict.js +3 -2
  376. package/dist/workers/quality-daemon/priority-queue.js +4 -1
  377. package/package.json +6 -4
  378. package/dist/cli/chunks/adapter-TVQKH65T.js +0 -2
  379. package/dist/cli/chunks/aqe-learning-engine-ULGTVVWE.js +0 -2
  380. package/dist/cli/chunks/base-W42BURDL.js +0 -2
  381. package/dist/cli/chunks/browser-workflow-HKGHFFFT.js +0 -2
  382. package/dist/cli/chunks/chunk-2IMSJ7IO.js +0 -2
  383. package/dist/cli/chunks/chunk-FBZC4IGB.js +0 -2
  384. package/dist/cli/chunks/chunk-LXZMP3VX.js +0 -736
  385. package/dist/cli/chunks/chunk-MNQN7UZX.js +0 -4
  386. package/dist/cli/chunks/chunk-OXHF3L2T.js +0 -2
  387. package/dist/cli/chunks/chunk-PELENDDQ.js +0 -2
  388. package/dist/cli/chunks/chunk-TW3SR4TS.js +0 -2
  389. package/dist/cli/chunks/chunk-V6RE4YRQ.js +0 -2
  390. package/dist/cli/chunks/chunk-ZQZD55MN.js +0 -3
  391. package/dist/cli/chunks/ci-J3TDK5RA.js +0 -81
  392. package/dist/cli/chunks/client-3BD2DI4N.js +0 -2
  393. package/dist/cli/chunks/core-handlers-C3H2ZCS2.js +0 -2
  394. package/dist/cli/chunks/cross-domain-router-JCQ7SWDP.js +0 -2
  395. package/dist/cli/chunks/domain-transfer-MFCI76IY.js +0 -2
  396. package/dist/cli/chunks/dream-FTP33IJB.js +0 -2
  397. package/dist/cli/chunks/heartbeat-scheduler-HXBJVJL2.js +0 -2
  398. package/dist/cli/chunks/hnsw-adapter-TU6WG2ME.js +0 -2
  399. package/dist/cli/chunks/hnsw-index-MS5KODD7.js +0 -2
  400. package/dist/cli/chunks/hybrid-backend-HT45LBHC.js +0 -2
  401. package/dist/cli/chunks/impact-analyzer-AP4AGTG5.js +0 -2
  402. package/dist/cli/chunks/init-wizard-I5DFZUQL.js +0 -2
  403. package/dist/cli/chunks/kernel-MISPSPPA.js +0 -2
  404. package/dist/cli/chunks/knowledge-graph-L26JESGE.js +0 -2
  405. package/dist/cli/chunks/llm-router-service-MWGC43ZA.js +0 -2
  406. package/dist/cli/chunks/load-test-H5ISNNM5.js +0 -2
  407. package/dist/cli/chunks/memory-backend-HWDNOBKW.js +0 -2
  408. package/dist/cli/chunks/memory-handlers-ZFDVQZM5.js +0 -2
  409. package/dist/cli/chunks/pattern-null-store-GQP6ICWK.js +0 -2
  410. package/dist/cli/chunks/protocol-executor-AD5A4DAI.js +0 -2
  411. package/dist/cli/chunks/qe-reasoning-bank-W3Z2PKTR.js +0 -2
  412. package/dist/cli/chunks/quality-gate-GYNCA4ZY.js +0 -7
  413. package/dist/cli/chunks/queen-coordinator-HQRHLIJX.js +0 -2
  414. package/dist/cli/chunks/router-MTP5LH4H.js +0 -2
  415. package/dist/cli/chunks/routing-feedback-GWETVB4L.js +0 -2
  416. package/dist/cli/chunks/rvf-dual-writer-4UE5S7WP.js +0 -2
  417. package/dist/cli/chunks/rvf-migration-adapter-PHH3HF4Q.js +0 -2
  418. package/dist/cli/chunks/rvf-native-adapter-KTLZBUWV.js +0 -2
  419. package/dist/cli/chunks/safe-db-FWWGAPVE.js +0 -2
  420. package/dist/cli/chunks/schedule-TPA4V4D5.js +0 -2
  421. package/dist/cli/chunks/scheduler-5ZTEPNDD.js +0 -2
  422. package/dist/cli/chunks/sqlite-persistence-HPTT624C.js +0 -2
  423. package/dist/cli/chunks/unified-memory-OVFEPRPS.js +0 -2
  424. package/dist/cli/chunks/unified-memory-hnsw-KKRSCZHR.js +0 -2
  425. package/dist/cli/chunks/unified-persistence-7GLR4RI3.js +0 -2
  426. package/dist/cli/chunks/visual-security-2FUM5GLI.js +0 -2
  427. package/dist/cli/chunks/witness-chain-MH6GA5L6.js +0 -2
  428. package/dist/cli/chunks/workflow-orchestrator-H6G65YKU.js +0 -2
@@ -104,7 +104,12 @@ function resolveArtifact(options) {
104
104
  function resolveOracle(options) {
105
105
  if (options.oracleFile) {
106
106
  const raw = JSON.parse(fs.readFileSync(options.oracleFile, 'utf8'));
107
- return { passed: !!raw.passed, baselinePassed: !!raw.baselinePassed };
107
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)
108
+ || !('passed' in raw) || typeof raw.passed !== 'boolean'
109
+ || !('baselinePassed' in raw) || typeof raw.baselinePassed !== 'boolean') {
110
+ throw new Error('oracle-file must contain boolean passed and baselinePassed fields');
111
+ }
112
+ return { passed: raw.passed, baselinePassed: raw.baselinePassed };
108
113
  }
109
114
  if (options.oraclePassed === undefined && options.baselinePassed === undefined) {
110
115
  return null;
package/dist/cli/index.js CHANGED
@@ -22,7 +22,11 @@ import { ALL_DOMAINS } from '../shared/types/index.js';
22
22
  import { applyCommandVerbosity, installCliLogGate, isCliLogLevelEnabled } from './log-gate.js';
23
23
  import { LogLevel } from '../logging/index.js';
24
24
  import { formatErrorForLog } from '../logging/redaction.js';
25
+ import { releaseCliProcessStores } from './process-store-cleanup.js';
25
26
  installCliLogGate();
27
+ // Backstop for direct process.exit() paths as well as cleanupAndExit(). An
28
+ // in-process MCP owner still drains before exit; this callback is synchronous.
29
+ process.on('exit', releaseCliProcessStores);
26
30
  // ============================================================================
27
31
  // CLI State
28
32
  // ============================================================================
@@ -180,11 +184,12 @@ async function cleanupAndExit(code = 0) {
180
184
  }
181
185
  }
182
186
  catch { /* best effort */ }
183
- // Force exit immediately. Native NAPI handles (@ruvector/rvf-node and
187
+ releaseCliProcessStores();
188
+ // Force exit after synchronous store cleanup. Native NAPI handles (@ruvector/rvf-node and
184
189
  // historically @ruvector/router, replaced by hnswlib-node in #399 /
185
190
  // ADR-090) create ref'd event loop handles that prevent natural exit,
186
191
  // and dynamic import() of cleanup modules can load more native
187
- // bindings that make it worse. Exit now, clean later.
192
+ // bindings that make it worse. Do not wait for asynchronous disposers here.
188
193
  process.exit(code);
189
194
  }
190
195
  // ============================================================================
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Release the CLI's process-wide stores without awaiting native work (#814).
3
+ * Each closer owns its handle; never remove a lock file by path. Synchronous
4
+ * cleanup also runs when Commander or another module calls process.exit().
5
+ */
6
+ export declare function releaseCliProcessStores(): void;
7
+ //# sourceMappingURL=process-store-cleanup.d.ts.map
@@ -0,0 +1,27 @@
1
+ import { resetSharedRvfAdapter } from '../integrations/ruvector/shared-rvf-adapter.js';
2
+ import { resetSharedRvfDualWriter } from '../integrations/ruvector/shared-rvf-dual-writer.js';
3
+ import { closeRegisteredStores } from '../kernel/process-lifecycle.js';
4
+ let released = false;
5
+ /**
6
+ * Release the CLI's process-wide stores without awaiting native work (#814).
7
+ * Each closer owns its handle; never remove a lock file by path. Synchronous
8
+ * cleanup also runs when Commander or another module calls process.exit().
9
+ */
10
+ export function releaseCliProcessStores() {
11
+ if (released)
12
+ return;
13
+ released = true;
14
+ try {
15
+ resetSharedRvfDualWriter();
16
+ }
17
+ catch { /* keep closing other stores */ }
18
+ try {
19
+ resetSharedRvfAdapter();
20
+ }
21
+ catch { /* keep closing other stores */ }
22
+ try {
23
+ closeRegisteredStores();
24
+ }
25
+ catch { /* best effort on process exit */ }
26
+ }
27
+ //# sourceMappingURL=process-store-cleanup.js.map
@@ -67,6 +67,8 @@ export interface CIPhaseResult {
67
67
  }
68
68
  /** Result of the full CI run */
69
69
  export interface CIRunResult {
70
+ /** Invalid phase selections fail before execution and retain a fresh report. */
71
+ configurationError?: string;
70
72
  config: string;
71
73
  startedAt: Date;
72
74
  completedAt: Date;
@@ -93,9 +95,7 @@ export interface CIConfigParseResult {
93
95
  * Parse a .aqe-ci.yml file into a CIConfig.
94
96
  */
95
97
  export declare function parseCIConfigFile(filePath: string): CIConfigParseResult;
96
- /**
97
- * Parse CI config YAML content.
98
- */
98
+ /** Parse CI YAML faithfully, validating typed fields before any phase executes. */
99
99
  export declare function parseCIConfigContent(content: string, sourcePath?: string): CIConfigParseResult;
100
100
  /**
101
101
  * Get the default CI config (used when no .aqe-ci.yml exists).
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
- import { parseYAMLContent } from './workflow-parser.js';
9
+ import { isCollection, isScalar, parseDocument, visit } from 'yaml';
10
10
  // ============================================================================
11
11
  // Default Config
12
12
  // ============================================================================
@@ -100,89 +100,223 @@ export function parseCIConfigFile(filePath) {
100
100
  }
101
101
  return parseCIConfigContent(content, filePath);
102
102
  }
103
- /**
104
- * Parse CI config YAML content.
105
- */
103
+ const YAML_MAX_LINES = 10000;
104
+ const YAML_MAX_LINE_LENGTH = 10000;
105
+ const YAML_MAX_DEPTH = 20;
106
+ const UNSAFE_YAML_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
107
+ function isRecord(value) {
108
+ return value !== null && typeof value === 'object' && !Array.isArray(value) &&
109
+ (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
110
+ }
111
+ /** Keep the previous parser's input bounds; reject unsafe expanded aliases too. */
112
+ function parseCIYAML(content) {
113
+ const lines = content.split('\n');
114
+ if (lines.length > YAML_MAX_LINES)
115
+ throw new Error(`YAML exceeds maximum allowed lines (${YAML_MAX_LINES})`);
116
+ if (lines.some(line => line.length > YAML_MAX_LINE_LENGTH)) {
117
+ throw new Error(`YAML exceeds maximum line length (${YAML_MAX_LINE_LENGTH})`);
118
+ }
119
+ const document = parseDocument(content, { prettyErrors: false, merge: true });
120
+ if (document.errors.length)
121
+ throw new Error(document.errors.map(error => error.message).join('; '));
122
+ visit(document, {
123
+ Collection: (_key, _node, ancestry) => {
124
+ if (ancestry.filter(isCollection).length >= YAML_MAX_DEPTH) {
125
+ throw new Error(`YAML exceeds maximum depth (${YAML_MAX_DEPTH})`);
126
+ }
127
+ },
128
+ Pair: (_key, pair) => {
129
+ if (isScalar(pair.key) && UNSAFE_YAML_KEYS.has(String(pair.key.value))) {
130
+ throw new Error(`Unsafe YAML key: ${pair.key.value}`);
131
+ }
132
+ },
133
+ });
134
+ const parsed = document.contents === null ? {} : document.toJS({ maxAliasCount: 100 });
135
+ // Alias references may add nesting or cycles that the syntax tree does not show.
136
+ function checkExpanded(value, depth, ancestors) {
137
+ if (value === null || typeof value !== 'object')
138
+ return;
139
+ if (depth > YAML_MAX_DEPTH)
140
+ throw new Error(`YAML exceeds maximum depth (${YAML_MAX_DEPTH})`);
141
+ if (ancestors.has(value))
142
+ throw new Error('Cyclic YAML aliases are not supported');
143
+ ancestors.add(value);
144
+ for (const child of Object.values(value))
145
+ checkExpanded(child, depth + 1, ancestors);
146
+ ancestors.delete(value);
147
+ }
148
+ checkExpanded(parsed, 0, new Set());
149
+ if (!isRecord(parsed))
150
+ throw new Error('CI config must be a YAML mapping');
151
+ return parsed;
152
+ }
153
+ /** Parse CI YAML faithfully, validating typed fields before any phase executes. */
106
154
  export function parseCIConfigContent(content, sourcePath) {
107
- const errors = [];
108
155
  let parsed;
109
156
  try {
110
- parsed = parseYAMLContent(content);
157
+ parsed = parseCIYAML(content);
111
158
  }
112
159
  catch (err) {
113
160
  return { success: false, errors: [`Invalid YAML: ${err}`] };
114
161
  }
115
- // Build config with defaults
116
- const config = {
117
- version: parsed.version || DEFAULT_CI_CONFIG.version,
118
- name: parsed.name || DEFAULT_CI_CONFIG.name,
119
- phases: [],
120
- output: { ...DEFAULT_CI_CONFIG.output },
121
- qualityGate: { ...DEFAULT_CI_CONFIG.qualityGate, thresholds: { ...DEFAULT_CI_CONFIG.qualityGate.thresholds } },
122
- };
123
- // Parse output section
124
- if (parsed.output && typeof parsed.output === 'object') {
125
- const out = parsed.output;
126
- if (out.format)
127
- config.output.format = out.format;
128
- if (out.directory)
129
- config.output.directory = out.directory;
130
- if (out.combined_report !== undefined)
131
- config.output.combinedReport = out.combined_report;
132
- }
133
- // Parse quality_gate section
134
- if (parsed.quality_gate && typeof parsed.quality_gate === 'object') {
135
- const qg = parsed.quality_gate;
136
- if (qg.enforced !== undefined)
137
- config.qualityGate.enforced = qg.enforced;
138
- if (qg.thresholds && typeof qg.thresholds === 'object') {
139
- const th = qg.thresholds;
140
- if (th.coverage !== undefined)
141
- config.qualityGate.thresholds.coverage = th.coverage;
142
- if (th.security !== undefined)
143
- config.qualityGate.thresholds.security = th.security;
144
- if (th.quality !== undefined)
145
- config.qualityGate.thresholds.quality = th.quality;
162
+ const errors = [];
163
+ const config = getDefaultCIConfig();
164
+ function readString(record, key, fallback, label) {
165
+ const value = record[key];
166
+ if (value === undefined)
167
+ return fallback;
168
+ if (typeof value !== 'string' || !value.trim()) {
169
+ errors.push(`${label} must be a non-empty string`);
170
+ return fallback;
146
171
  }
172
+ return value;
147
173
  }
148
- // Parse phases
149
- if (parsed.phases && Array.isArray(parsed.phases)) {
150
- for (let i = 0; i < parsed.phases.length; i++) {
151
- const p = parsed.phases[i];
152
- if (!p.name) {
153
- errors.push(`Phase ${i + 1} must have a "name" field`);
154
- continue;
155
- }
156
- if (!p.type) {
157
- errors.push(`Phase "${p.name}" must have a "type" field`);
158
- continue;
159
- }
160
- const validTypes = ['test', 'coverage', 'security', 'quality-gate', 'code-intelligence', 'custom'];
161
- if (!validTypes.includes(p.type)) {
162
- errors.push(`Phase "${p.name}" has invalid type "${p.type}". Valid: ${validTypes.join(', ')}`);
163
- continue;
174
+ function readBoolean(record, key, fallback, label) {
175
+ const value = record[key];
176
+ if (value === undefined)
177
+ return fallback;
178
+ if (typeof value !== 'boolean') {
179
+ errors.push(`${label} must be a boolean`);
180
+ return fallback;
181
+ }
182
+ return value;
183
+ }
184
+ if (parsed.version !== undefined) {
185
+ if (typeof parsed.version === 'number' && Number.isFinite(parsed.version))
186
+ config.version = String(parsed.version);
187
+ else
188
+ config.version = readString(parsed, 'version', config.version, 'version');
189
+ }
190
+ config.name = readString(parsed, 'name', config.name, 'name');
191
+ if (parsed.output !== undefined) {
192
+ if (!isRecord(parsed.output))
193
+ errors.push('output must be a mapping');
194
+ else {
195
+ config.output.format = readString(parsed.output, 'format', config.output.format, 'output.format');
196
+ config.output.directory = readString(parsed.output, 'directory', config.output.directory, 'output.directory');
197
+ config.output.combinedReport = readBoolean(parsed.output, 'combined_report', config.output.combinedReport, 'output.combined_report');
198
+ }
199
+ }
200
+ if (parsed.quality_gate !== undefined) {
201
+ if (!isRecord(parsed.quality_gate))
202
+ errors.push('quality_gate must be a mapping');
203
+ else {
204
+ const gate = parsed.quality_gate;
205
+ config.qualityGate.enforced = readBoolean(gate, 'enforced', config.qualityGate.enforced, 'quality_gate.enforced');
206
+ if (gate.thresholds !== undefined) {
207
+ if (!isRecord(gate.thresholds))
208
+ errors.push('quality_gate.thresholds must be a mapping');
209
+ else {
210
+ for (const key of ['coverage', 'quality']) {
211
+ const value = gate.thresholds[key];
212
+ if (value === undefined)
213
+ continue;
214
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 100) {
215
+ errors.push(`quality_gate.thresholds.${key} must be a finite number between 0 and 100`);
216
+ }
217
+ else
218
+ config.qualityGate.thresholds[key] = value;
219
+ }
220
+ if (gate.thresholds.security !== undefined) {
221
+ const value = gate.thresholds.security;
222
+ if (typeof value !== 'string' || !['none', 'low', 'medium', 'high'].includes(value)) {
223
+ errors.push('quality_gate.thresholds.security must be none, low, medium or high');
224
+ }
225
+ else
226
+ config.qualityGate.thresholds.security = value;
227
+ }
228
+ }
164
229
  }
165
- const phase = {
166
- name: p.name,
167
- type: p.type,
168
- enabled: p.enabled !== false,
169
- config: p.config || {},
170
- continueOnFailure: p.continue_on_failure || false,
171
- timeout: p.timeout || 300,
172
- };
173
- config.phases.push(phase);
174
230
  }
175
231
  }
176
- else {
177
- // Use defaults if no phases specified
178
- config.phases = [...DEFAULT_CI_CONFIG.phases];
232
+ if (parsed.phases !== undefined) {
233
+ config.phases = [];
234
+ if (!Array.isArray(parsed.phases))
235
+ errors.push('phases must be a sequence');
236
+ else
237
+ for (const [index, value] of parsed.phases.entries()) {
238
+ if (!isRecord(value)) {
239
+ errors.push(`Phase ${index + 1} must be a mapping`);
240
+ continue;
241
+ }
242
+ if (value.name === undefined)
243
+ errors.push(`Phase ${index + 1} must have a name`);
244
+ const name = readString(value, 'name', '', `Phase ${index + 1} name`);
245
+ const validTypes = ['test', 'coverage', 'security', 'quality-gate', 'code-intelligence', 'custom'];
246
+ if (!validTypes.includes(value.type)) {
247
+ errors.push(`Phase "${name}" has invalid type "${value.type}". Valid: ${validTypes.join(', ')}`);
248
+ continue;
249
+ }
250
+ let timeout = 300;
251
+ if (value.timeout !== undefined) {
252
+ if (typeof value.timeout !== 'number' || !Number.isFinite(value.timeout) || value.timeout <= 0) {
253
+ errors.push(`Phase "${name}" timeout must be a positive finite number`);
254
+ }
255
+ else
256
+ timeout = value.timeout;
257
+ }
258
+ if (value.config !== undefined && !isRecord(value.config))
259
+ errors.push(`Phase "${name}" config must be a mapping`);
260
+ config.phases.push({
261
+ name, type: value.type, timeout,
262
+ enabled: readBoolean(value, 'enabled', true, `Phase "${name}" enabled`),
263
+ continueOnFailure: readBoolean(value, 'continue_on_failure', false, `Phase "${name}" continue_on_failure`),
264
+ config: isRecord(value.config) ? { ...value.config } : {},
265
+ });
266
+ }
179
267
  }
180
- if (config.phases.length === 0) {
268
+ if (config.phases.length === 0)
181
269
  errors.push('Config must have at least one phase');
270
+ // Paths in a file are relative to that file's project, not the caller's cwd.
271
+ // Resolve existing ancestors too so a symlink cannot bypass containment.
272
+ const root = path.resolve(sourcePath ? path.dirname(sourcePath) : process.cwd());
273
+ function canonicalAncestor(candidate) {
274
+ let ancestor = candidate;
275
+ const suffix = [];
276
+ while (!fs.existsSync(ancestor)) {
277
+ const parent = path.dirname(ancestor);
278
+ if (parent === ancestor)
279
+ break;
280
+ suffix.unshift(path.basename(ancestor));
281
+ ancestor = parent;
282
+ }
283
+ return path.resolve(fs.realpathSync(ancestor), ...suffix);
182
284
  }
183
- if (errors.length > 0) {
184
- return { success: false, config, errors };
285
+ function containedPath(value, label) {
286
+ if (typeof value !== 'string' || !value.trim() || value.includes('\0')) {
287
+ errors.push(`${label} must be a non-empty relative path`);
288
+ return undefined;
289
+ }
290
+ const resolved = path.resolve(root, value);
291
+ const relative = path.relative(root, resolved);
292
+ if (path.isAbsolute(value) || path.win32.isAbsolute(value) ||
293
+ relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
294
+ errors.push(`${label} must stay inside the project and use a relative path`);
295
+ return undefined;
296
+ }
297
+ try {
298
+ const realRelative = path.relative(canonicalAncestor(root), canonicalAncestor(resolved));
299
+ if (realRelative === '..' || realRelative.startsWith(`..${path.sep}`) || path.isAbsolute(realRelative)) {
300
+ errors.push(`${label} must stay inside the project (symlink escapes are not allowed)`);
301
+ return undefined;
302
+ }
303
+ }
304
+ catch (error) {
305
+ errors.push(`${label} cannot be resolved safely: ${error}`);
306
+ return undefined;
307
+ }
308
+ return sourcePath ? resolved : value;
309
+ }
310
+ config.output.directory = containedPath(config.output.directory, 'output.directory') ?? config.output.directory;
311
+ for (const phase of config.phases) {
312
+ if (phase.config.target !== undefined) {
313
+ const target = containedPath(phase.config.target, `Phase "${phase.name}" config.target`);
314
+ if (target !== undefined)
315
+ phase.config.target = target;
316
+ }
185
317
  }
318
+ if (errors.length > 0)
319
+ return { success: false, config, errors };
186
320
  return { success: true, config, errors: [], configPath: sourcePath };
187
321
  }
188
322
  /**
@@ -694,33 +694,50 @@ function detectCircularDependencies(stages) {
694
694
  * Validate cron expression (basic validation)
695
695
  */
696
696
  export function isValidCronExpression(expression) {
697
- // Check for aliases
698
- if (Object.keys(CRON_PATTERNS).includes(expression)) {
699
- return true;
700
- }
701
- // Basic cron validation: 5 fields separated by spaces
702
- const parts = expression.trim().split(/\s+/);
703
- if (parts.length !== 5) {
704
- return false;
705
- }
706
- // Validate each field
707
- const fieldPatterns = [
708
- /^(\*|[0-5]?\d)(-[0-5]?\d)?(\/\d+)?$/, // minute (0-59)
709
- /^(\*|1?\d|2[0-3])(-\d+)?(\/\d+)?$/, // hour (0-23)
710
- /^(\*|[1-9]|[12]\d|3[01])(-\d+)?(\/\d+)?$/, // day of month (1-31)
711
- /^(\*|[1-9]|1[0-2])(-\d+)?(\/\d+)?$/, // month (1-12)
712
- /^(\*|[0-7])(-[0-7])?(\/\d+)?$/, // day of week (0-7)
697
+ return parseCronFields(expression) !== undefined;
698
+ }
699
+ /** Parse the existing numeric five-field grammar and its four named aliases. */
700
+ function parseCronFields(expression) {
701
+ const normalized = Object.hasOwn(CRON_PATTERNS, expression)
702
+ ? CRON_PATTERNS[expression]
703
+ : expression;
704
+ const parts = normalized.trim().split(/\s+/);
705
+ if (parts.length !== 5)
706
+ return undefined;
707
+ const bounds = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]];
708
+ const syntax = [
709
+ /^(\*|[0-5]?\d)(-[0-5]?\d)?(\/\d+)?$/,
710
+ /^(\*|1?\d|2[0-3])(-\d+)?(\/\d+)?$/,
711
+ /^(\*|[1-9]|[12]\d|3[01])(-\d+)?(\/\d+)?$/,
712
+ /^(\*|[1-9]|1[0-2])(-\d+)?(\/\d+)?$/,
713
+ /^(\*|[0-7])(-[0-7])?(\/\d+)?$/,
713
714
  ];
714
- for (let i = 0; i < 5; i++) {
715
- // Allow comma-separated values
716
- const values = parts[i].split(',');
717
- for (const value of values) {
718
- if (!fieldPatterns[i].test(value) && value !== '*') {
719
- return false;
715
+ const fields = [];
716
+ for (let index = 0; index < parts.length; index++) {
717
+ const [minimum, maximum] = bounds[index];
718
+ const values = new Set();
719
+ for (const item of parts[index].split(',')) {
720
+ if (!syntax[index].test(item))
721
+ return undefined;
722
+ const match = /^(\*|\d+)(?:-(\d+))?(?:\/(\d+))?$/.exec(item);
723
+ if (!match || (match[1] === '*' && match[2] !== undefined))
724
+ return undefined;
725
+ const start = match[1] === '*' ? minimum : Number(match[1]);
726
+ const end = match[2] !== undefined ? Number(match[2])
727
+ : match[1] === '*' || match[3] !== undefined ? maximum : start;
728
+ const step = match[3] === undefined ? 1 : Number(match[3]);
729
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) ||
730
+ !Number.isSafeInteger(step) || step <= 0 ||
731
+ start < minimum || end > maximum || start > end)
732
+ return undefined;
733
+ for (let value = start; value <= end; value += step) {
734
+ values.add(index === 4 && value === 7 ? 0 : value);
720
735
  }
721
736
  }
737
+ fields.push(values);
722
738
  }
723
- return true;
739
+ // Cronie records DOM_STAR/DOW_STAR from the first character, before parsing lists.
740
+ return { fields: fields, wildcardDay: parts[2].startsWith('*') || parts[4].startsWith('*') };
724
741
  }
725
742
  /**
726
743
  * Parse cron expression to human-readable string
@@ -773,40 +790,39 @@ export function describeCronSchedule(expression) {
773
790
  * Calculate next run time from cron expression
774
791
  */
775
792
  export function calculateNextRun(cronExpression, fromDate = new Date()) {
776
- // Simplified next run calculation
777
- const parts = cronExpression.trim().split(/\s+/);
778
- if (parts.length !== 5) {
779
- // Default to 1 day from now
780
- return new Date(fromDate.getTime() + 24 * 60 * 60 * 1000);
781
- }
782
- const [minute, hour] = parts;
783
- const nextRun = new Date(fromDate);
784
- // Handle specific hour and minute
785
- if (hour !== '*' && minute !== '*') {
786
- nextRun.setHours(parseInt(hour, 10), parseInt(minute, 10), 0, 0);
787
- if (nextRun <= fromDate) {
788
- nextRun.setDate(nextRun.getDate() + 1);
789
- }
790
- }
791
- else if (hour !== '*') {
792
- // Every day at specific hour
793
- nextRun.setHours(parseInt(hour, 10), 0, 0, 0);
794
- if (nextRun <= fromDate) {
795
- nextRun.setDate(nextRun.getDate() + 1);
796
- }
797
- }
798
- else if (minute !== '*') {
799
- // Every hour at specific minute
800
- nextRun.setMinutes(parseInt(minute, 10), 0, 0);
801
- if (nextRun <= fromDate) {
802
- nextRun.setHours(nextRun.getHours() + 1);
793
+ const parsed = parseCronFields(cronExpression);
794
+ if (!parsed)
795
+ throw new Error(`Invalid cron expression: ${cronExpression}`);
796
+ if (!Number.isFinite(fromDate.getTime()))
797
+ throw new Error('Invalid schedule start date');
798
+ const [minutes, hours, days, months, weekdays] = parsed.fields;
799
+ // Preserve the existing host-local timezone. Advance elapsed minutes to
800
+ // skip absent DST times and inspect both occurrences of repeated times.
801
+ let candidate = new Date(Math.floor(fromDate.getTime() / 60000) * 60000 + 60000);
802
+ const deadline = new Date(fromDate);
803
+ deadline.setFullYear(fromDate.getFullYear() + 400);
804
+ // A complete Gregorian cycle contains 146097 days and repeats weekdays.
805
+ // Near the Date maximum a full cycle is not representable: clamp the
806
+ // search to that finite boundary and report the limitation on exhaustion.
807
+ const deadlineMs = Number.isFinite(deadline.getTime())
808
+ ? deadline.getTime() : 8_640_000_000_000_000;
809
+ while (Number.isFinite(candidate.getTime()) && candidate.getTime() <= deadlineMs) {
810
+ const dayMatches = days.has(candidate.getDate());
811
+ const weekdayMatches = weekdays.has(candidate.getDay());
812
+ const calendarMatches = months.has(candidate.getMonth() + 1) &&
813
+ (parsed.wildcardDay ? dayMatches && weekdayMatches : dayMatches || weekdayMatches);
814
+ if (!calendarMatches) {
815
+ // Skip a nonmatching local calendar day instead of scanning its minutes.
816
+ candidate.setHours(24, 0, 0, 0);
817
+ continue;
803
818
  }
804
- }
805
- else {
806
- // Every minute
807
- nextRun.setSeconds(0, 0);
808
- nextRun.setMinutes(nextRun.getMinutes() + 1);
809
- }
810
- return nextRun;
819
+ if (hours.has(candidate.getHours()) && minutes.has(candidate.getMinutes()))
820
+ return candidate;
821
+ candidate = new Date(candidate.getTime() + 60000);
822
+ }
823
+ // An impossible date such as February 31 must not spin indefinitely or
824
+ // silently become a daily schedule. Leap-day/weekday intersections may
825
+ // exceed a leap-day-only horizon, so search one complete Gregorian cycle.
826
+ throw new Error(`No matching cron date within a 400-year Gregorian cycle and the supported Date range: ${cronExpression}`);
811
827
  }
812
828
  //# sourceMappingURL=workflow-parser.js.map
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Detection priority by project type:
8
8
  * 1. Node.js: vitest > jest > fallback pattern matching
9
- * 2. Rust: cargo test --list
9
+ * 2. Rust: cargo test -- --list
10
10
  * 3. Python: pytest --collect-only
11
11
  * 4. Go: go test -list
12
12
  *
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Detection priority by project type:
8
8
  * 1. Node.js: vitest > jest > fallback pattern matching
9
- * 2. Rust: cargo test --list
9
+ * 2. Rust: cargo test -- --list
10
10
  * 3. Python: pytest --collect-only
11
11
  * 4. Go: go test -list
12
12
  *
@@ -262,11 +262,11 @@ function countJestTests(projectPath, config) {
262
262
  }
263
263
  /**
264
264
  * Count tests using Cargo (Rust)
265
- * Uses `cargo test --list` for accurate test enumeration
265
+ * Uses `cargo test -- --list` for accurate test enumeration
266
266
  */
267
267
  function countCargoTests(projectPath, config) {
268
268
  try {
269
- const output = execSync('cargo test --list', {
269
+ const output = execSync('cargo test -- --list', {
270
270
  cwd: projectPath,
271
271
  encoding: 'utf-8',
272
272
  timeout: config.timeout,
@@ -310,13 +310,14 @@ function countPytestTests(projectPath, config) {
310
310
  // Count test function lines (format: "tests/test_foo.py::test_bar")
311
311
  const testLines = output.split('\n').filter(line => line.includes('::test_') || line.includes('::Test'));
312
312
  const total = testLines.length;
313
- // Classify by path patterns
314
- const unit = testLines.filter(t => t.includes('unit') || (!t.includes('integration') && !t.includes('e2e'))).length;
315
- const integration = testLines.filter(t => t.includes('integration') || t.includes('_integration')).length;
313
+ // Match fallback classification precedence so every collected test belongs
314
+ // to exactly one category, even when its path names multiple categories.
316
315
  const e2e = testLines.filter(t => t.includes('e2e') || t.includes('end_to_end')).length;
316
+ const integration = testLines.filter(t => !t.includes('e2e') && !t.includes('end_to_end') && t.includes('integration')).length;
317
+ const unit = total - integration - e2e;
317
318
  return {
318
319
  total,
319
- unit: unit - integration - e2e, // Exclude overlap
320
+ unit,
320
321
  integration,
321
322
  e2e,
322
323
  source: 'pytest',
@@ -343,13 +344,14 @@ function countGoTests(projectPath, config) {
343
344
  encoding: 'utf-8',
344
345
  timeout: config.timeout,
345
346
  });
346
- // Count lines starting with "Test" (Go test naming convention)
347
- const testLines = output.split('\n').filter(line => line.startsWith('Test') || line.startsWith('Example') || line.startsWith('Benchmark'));
348
- const total = testLines.filter(l => l.startsWith('Test')).length;
349
- // Classify by test name patterns
350
- const unit = testLines.filter(t => t.startsWith('Test') && !t.includes('Integration') && !t.includes('E2E')).length;
351
- const integration = testLines.filter(t => t.includes('Integration')).length;
347
+ // Benchmarks and examples are listed too, but are not included in the
348
+ // test total. Apply that same selection to every category.
349
+ const testLines = output.split('\n').filter(line => line.startsWith('Test'));
350
+ const total = testLines.length;
351
+ // Use disjoint categories, with e2e taking precedence over integration.
352
352
  const e2e = testLines.filter(t => t.includes('E2E')).length;
353
+ const integration = testLines.filter(t => !t.includes('E2E') && t.includes('Integration')).length;
354
+ const unit = total - integration - e2e;
353
355
  return {
354
356
  total,
355
357
  unit,
@@ -474,8 +476,8 @@ function countTestsInPythonFile(filePath) {
474
476
  const content = readFileSync(filePath, 'utf-8');
475
477
  // Count def test_ functions and async def test_ functions
476
478
  const funcMatches = content.match(/\bdef\s+test_\w+\s*\(/g) || [];
477
- const asyncMatches = content.match(/\basync\s+def\s+test_\w+\s*\(/g) || [];
478
- return funcMatches.length + asyncMatches.length;
479
+ // The def pattern also matches async def; every declaration counts once.
480
+ return funcMatches.length;
479
481
  }
480
482
  catch {
481
483
  return 0;
@@ -33,7 +33,9 @@ export declare function loadQualityEvidence(memory: MemoryBackend, options?: {
33
33
  now?: number;
34
34
  maxAgeMs?: number;
35
35
  }): Promise<QualityEvidenceValues>;
36
- export declare function evaluateQualityEvidence(values: QualityEvidenceValues): {
36
+ export declare function evaluateQualityEvidence(values: QualityEvidenceValues, thresholds?: {
37
+ coverage?: number;
38
+ }): {
37
39
  passed: boolean;
38
40
  checks: EvaluatedQualityCheck[];
39
41
  recommendations: string[];