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
@@ -157,6 +157,7 @@ export class GOAPPlanner {
157
157
  // for databases seeded before this feature existed, or before a given
158
158
  // action's binding was added to the library.
159
159
  this.backfillActionMethodBindings();
160
+ this.backfillActionDurationEstimates();
160
161
  await this.loadActions();
161
162
  this.initialized = true;
162
163
  console.log(`[GOAPPlanner] Initialized: ${this.persistence.getDbPath()}`);
@@ -170,12 +171,12 @@ export class GOAPPlanner {
170
171
  const allActions = getAllQEActions();
171
172
  const db = this.ensureDb();
172
173
  const insertAction = db.prepare(`
173
- INSERT INTO goap_actions (id, name, description, category, preconditions, effects, cost, qe_domain, agent_type, method, params, implemented)
174
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
174
+ INSERT INTO goap_actions (id, name, description, category, preconditions, effects, cost, qe_domain, agent_type, method, params, implemented, estimated_duration_ms)
175
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
175
176
  `);
176
177
  for (const action of allActions) {
177
178
  const id = `action-${Date.now()}-${randomUUID().slice(0, 8)}`;
178
- insertAction.run(id, action.name, action.description, action.category, JSON.stringify(action.preconditions), JSON.stringify(action.effects), action.cost, action.qeDomain ?? null, action.agentType ?? null, action.method ?? null, action.params ? JSON.stringify(action.params) : null, action.implemented ? 1 : 0);
179
+ insertAction.run(id, action.name, action.description, action.category, JSON.stringify(action.preconditions), JSON.stringify(action.effects), action.cost, action.qeDomain ?? null, action.agentType ?? null, action.method ?? null, action.params ? JSON.stringify(action.params) : null, action.implemented ? 1 : 0, action.estimatedDurationMs ?? null);
179
180
  }
180
181
  // Seed QE goals using direct insertion
181
182
  const insertGoal = db.prepare(`
@@ -212,6 +213,21 @@ export class GOAPPlanner {
212
213
  update.run(action.method, action.params ? JSON.stringify(action.params) : '{}', action.name);
213
214
  }
214
215
  }
216
+ /** Restore missing estimates only for unchanged legacy library definitions. */
217
+ backfillActionDurationEstimates() {
218
+ const update = this.ensureDb().prepare(`
219
+ UPDATE goap_actions SET estimated_duration_ms = ?
220
+ WHERE estimated_duration_ms IS NULL AND name = ?
221
+ AND agent_type IS ? AND category = ? AND qe_domain IS ?
222
+ AND preconditions = ? AND effects = ?
223
+ AND method IS ? AND params IS ? AND implemented = ?
224
+ `);
225
+ for (const action of getAllQEActions()) {
226
+ if (action.estimatedDurationMs === undefined)
227
+ continue;
228
+ update.run(action.estimatedDurationMs, action.name, action.agentType ?? null, action.category, action.qeDomain ?? null, JSON.stringify(action.preconditions), JSON.stringify(action.effects), action.method ?? null, action.params ? JSON.stringify(action.params) : null, action.implemented ? 1 : 0);
229
+ }
230
+ }
215
231
  // ==========================================================================
216
232
  // Core Planning - A* Search
217
233
  // ==========================================================================
@@ -242,6 +258,7 @@ export class GOAPPlanner {
242
258
  this.recordPlanReuse(reusedPlan.id, true);
243
259
  const clonedPlan = {
244
260
  ...reusedPlan,
261
+ estimatedDurationMs: reusedPlan.actions.reduce((sum, action) => sum + (action.estimatedDurationMs ?? 0), 0),
245
262
  id: `plan-${Date.now()}-${randomUUID().slice(0, 8)}`,
246
263
  initialState: this.cloneState(currentState),
247
264
  reusedFrom: reusedPlan.id,
@@ -306,6 +323,9 @@ export class GOAPPlanner {
306
323
  // Entries are added on insert, updated when a better path is found, and
307
324
  // removed when the node is popped (moved to the closed set).
308
325
  const openSetCosts = new Map();
326
+ // Under a duration budget, cheaper paths can be slower or deeper. Keep
327
+ // nondominated labels rather than closing the entire state at its first cost.
328
+ const durationLabels = new Map();
309
329
  // Issue #535: cost-unit heuristic built once per search from the
310
330
  // actions that can actually move each goal key (see buildHeuristic).
311
331
  const heuristic = this.buildHeuristic(goal, availableActions);
@@ -322,34 +342,39 @@ export class GOAPPlanner {
322
342
  h: startH,
323
343
  f: 0,
324
344
  depth: 0,
345
+ estimatedDurationMs: 0,
325
346
  };
326
347
  startNode.f = startNode.g + startNode.h;
327
348
  openHeap.push(startNode);
328
349
  openSetCosts.set(this.hashState(start), 0);
350
+ durationLabels.set(this.hashState(start), [startNode]);
329
351
  // Constraint defaults
330
352
  const maxIterations = 10000;
331
353
  // Issue #535: constraints.maxSteps caps the search depth (= plan length).
332
354
  const maxPlanLength = constraints?.maxSteps ?? DEFAULT_MAX_PLAN_STEPS;
333
355
  const maxCost = constraints?.maxCost ?? Infinity;
334
356
  const maxDuration = constraints?.maxDurationMs ?? Infinity;
357
+ const boundedDuration = Number.isFinite(maxDuration);
335
358
  let iterations = 0;
336
359
  while (openHeap.length > 0 && iterations < maxIterations) {
337
360
  iterations++;
338
361
  // Get node with lowest f score — O(log n)
339
362
  const current = openHeap.pop();
363
+ const stateKey = this.hashState(current.state);
364
+ if (boundedDuration && !durationLabels.get(stateKey)?.includes(current)) {
365
+ continue; // a later label dominates this queued path
366
+ }
340
367
  // Check if goal reached
341
368
  if (this.meetsConditions(current.state, goal)) {
342
369
  return this.reconstructPlan(current);
343
370
  }
344
- // Generate state hash for closed set
345
- const stateKey = this.hashState(current.state);
346
- if (closedSet.has(stateKey)) {
347
- // Lazy deletion: skip stale duplicate nodes
348
- continue;
371
+ if (!boundedDuration) {
372
+ if (closedSet.has(stateKey)) {
373
+ continue; // lazy deletion for the existing cost-only search
374
+ }
375
+ closedSet.add(stateKey);
376
+ openSetCosts.delete(stateKey);
349
377
  }
350
- closedSet.add(stateKey);
351
- // Node is now closed — remove from open set cost tracker
352
- openSetCosts.delete(stateKey);
353
378
  // Check depth limit
354
379
  if (current.depth >= maxPlanLength) {
355
380
  continue;
@@ -364,7 +389,7 @@ export class GOAPPlanner {
364
389
  const newState = this.applyAction(current.state, action);
365
390
  const newStateKey = this.hashState(newState);
366
391
  // Skip if already visited
367
- if (closedSet.has(newStateKey)) {
392
+ if (!boundedDuration && closedSet.has(newStateKey)) {
368
393
  continue;
369
394
  }
370
395
  // Calculate costs
@@ -379,26 +404,33 @@ export class GOAPPlanner {
379
404
  continue;
380
405
  }
381
406
  // Check duration constraints
382
- const estimatedDuration = current.depth * 1000 + (action.estimatedDurationMs ?? 0);
407
+ const estimatedDuration = current.estimatedDurationMs + (action.estimatedDurationMs ?? 0);
383
408
  if (estimatedDuration > maxDuration) {
384
409
  continue;
385
410
  }
386
- // Only push if this is a better path than any previously seen in the open set
387
- const prevG = openSetCosts.get(newStateKey);
388
- if (prevG !== undefined && g >= prevG) {
389
- continue;
411
+ const next = {
412
+ state: newState, action, parent: current, g, h, f,
413
+ depth: current.depth + 1, estimatedDurationMs: estimatedDuration,
414
+ };
415
+ if (boundedDuration) {
416
+ const labels = durationLabels.get(newStateKey) ?? [];
417
+ if (labels.some((label) => label.g <= g &&
418
+ label.estimatedDurationMs <= estimatedDuration && label.depth <= next.depth)) {
419
+ continue;
420
+ }
421
+ durationLabels.set(newStateKey, [
422
+ ...labels.filter((label) => !(g <= label.g &&
423
+ estimatedDuration <= label.estimatedDurationMs && next.depth <= label.depth)),
424
+ next,
425
+ ]);
426
+ }
427
+ else {
428
+ const prevG = openSetCosts.get(newStateKey);
429
+ if (prevG !== undefined && g >= prevG)
430
+ continue;
431
+ openSetCosts.set(newStateKey, g);
390
432
  }
391
- openSetCosts.set(newStateKey, g);
392
- // Add new node — O(log n)
393
- openHeap.push({
394
- state: newState,
395
- action,
396
- parent: current,
397
- g,
398
- h,
399
- f,
400
- depth: current.depth + 1,
401
- });
433
+ openHeap.push(next);
402
434
  }
403
435
  }
404
436
  // No plan found
@@ -896,20 +928,30 @@ export class GOAPPlanner {
896
928
  ORDER BY created_at DESC, id DESC
897
929
  LIMIT ?
898
930
  `).all(...args, boundedLimit);
899
- const plans = rows.map((row) => {
900
- const actionIds = safeJsonParse(row.action_sequence);
901
- if (!Array.isArray(actionIds)) {
902
- throw new Error(`Invalid action sequence in GOAP plan ${row.id}`);
931
+ const plans = [];
932
+ const invalidPlanIds = [];
933
+ for (const row of rows) {
934
+ let actionIds;
935
+ try {
936
+ actionIds = safeJsonParse(row.action_sequence);
937
+ }
938
+ catch {
939
+ invalidPlanIds.push(row.id);
940
+ continue;
941
+ }
942
+ if (!Array.isArray(actionIds) || !actionIds.every((id) => typeof id === 'string')) {
943
+ invalidPlanIds.push(row.id);
944
+ continue;
903
945
  }
904
- return {
946
+ plans.push({
905
947
  id: row.id,
906
948
  status: row.status,
907
949
  stepCount: actionIds.length,
908
950
  totalCost: row.total_cost,
909
951
  createdAt: row.created_at,
910
- };
911
- });
912
- return { plans, count };
952
+ });
953
+ }
954
+ return { plans, count, ...(invalidPlanIds.length ? { invalidPlanIds } : {}) };
913
955
  }
914
956
  /**
915
957
  * Find a similar plan by goal conditions
@@ -998,7 +1040,8 @@ export class GOAPPlanner {
998
1040
  if (plan.actions.length > maxSteps)
999
1041
  return false;
1000
1042
  if (constraints?.maxDurationMs !== undefined &&
1001
- plan.estimatedDurationMs > constraints.maxDurationMs) {
1043
+ plan.actions.reduce((sum, action) => sum + (action.estimatedDurationMs ?? 0), 0)
1044
+ > constraints.maxDurationMs) {
1002
1045
  return false;
1003
1046
  }
1004
1047
  const allowed = new Set(this.getAvailableActions(constraints).map((a) => a.id));
@@ -51,9 +51,16 @@ export class PluginCache {
51
51
  }
52
52
  // Copy source to cache
53
53
  fs.mkdirSync(dir, { recursive: true });
54
- this.copyDir(sourceDir, dir);
55
- // Write the manifest (ensure it's present even if source didn't have it at root)
56
- fs.writeFileSync(path.join(dir, 'qe-plugin.json'), JSON.stringify(manifest, null, 2));
54
+ try {
55
+ this.copyDir(sourceDir, dir);
56
+ // Write the manifest (ensure it's present even if source didn't have it at root)
57
+ fs.writeFileSync(path.join(dir, 'qe-plugin.json'), JSON.stringify(manifest, null, 2));
58
+ }
59
+ catch (error) {
60
+ // A partial directory must not satisfy the immutable-cache fast path on retry.
61
+ fs.rmSync(dir, { recursive: true, force: true });
62
+ throw error;
63
+ }
57
64
  // Cleanup old versions
58
65
  this.pruneOldVersions(manifest.name);
59
66
  return dir;
@@ -22,7 +22,7 @@ export class EmbeddingCache {
22
22
  */
23
23
  hashContent(content, model) {
24
24
  return createHash('sha256')
25
- .update(`${model}:${content}`)
25
+ .update(JSON.stringify([model, content]))
26
26
  .digest('hex');
27
27
  }
28
28
  /**
@@ -36,7 +36,7 @@ export class EmbeddingCache {
36
36
  // Move to end (LRU update)
37
37
  this.cache.delete(key);
38
38
  this.cache.set(key, entry);
39
- return entry.embedding;
39
+ return [...entry.embedding];
40
40
  }
41
41
  this.misses++;
42
42
  return null;
@@ -54,7 +54,7 @@ export class EmbeddingCache {
54
54
  }
55
55
  }
56
56
  const entry = {
57
- embedding,
57
+ embedding: [...embedding],
58
58
  timestamp: Date.now(),
59
59
  model,
60
60
  };
@@ -118,7 +118,7 @@ export class EmbeddingCache {
118
118
  export() {
119
119
  return Array.from(this.cache.entries()).map(([key, entry]) => ({
120
120
  key,
121
- entry,
121
+ entry: { ...entry, embedding: [...entry.embedding] },
122
122
  }));
123
123
  }
124
124
  /**
@@ -128,7 +128,7 @@ export class EmbeddingCache {
128
128
  this.cache.clear();
129
129
  for (const { key, entry } of data) {
130
130
  if (this.cache.size < this.maxSize) {
131
- this.cache.set(key, entry);
131
+ this.cache.set(key, { ...entry, embedding: [...entry.embedding] });
132
132
  }
133
133
  }
134
134
  }
@@ -14,6 +14,7 @@ import { OllamaClient } from './ollama-client.js';
14
14
  import { EmbeddingCache } from './embedding-cache.js';
15
15
  import { toErrorMessage } from '../error-utils.js';
16
16
  import { EMBEDDING_CONFIG, } from './types.js';
17
+ const PSEUDO_EMBEDDING_MODEL = 'pseudo-embedding';
17
18
  /**
18
19
  * Nomic Embedder for generating code embeddings via Ollama
19
20
  */
@@ -50,17 +51,23 @@ export class NomicEmbedder {
50
51
  * Generate embedding for a single text string
51
52
  */
52
53
  async embed(text) {
53
- // Check cache first
54
- const cached = this.cache.get(text, EMBEDDING_CONFIG.MODEL);
54
+ // Prefer genuine cached vectors, then select the active backend before a
55
+ // single counted lookup so alternate namespaces do not inflate misses.
56
+ let model = this.cache.has(text, EMBEDDING_CONFIG.MODEL) ||
57
+ await this.isOllamaAvailable() || !this.enableFallback
58
+ ? EMBEDDING_CONFIG.MODEL : PSEUDO_EMBEDDING_MODEL;
59
+ const cached = this.cache.get(text, model);
55
60
  if (cached) {
56
61
  return cached;
57
62
  }
58
63
  // Try Ollama first, fall back to pseudo-embedding if unavailable
59
64
  let embedding;
60
65
  if (await this.isOllamaAvailable()) {
66
+ model = EMBEDDING_CONFIG.MODEL;
61
67
  embedding = await this.client.generateEmbedding(text);
62
68
  }
63
69
  else if (this.enableFallback) {
70
+ model = PSEUDO_EMBEDDING_MODEL;
64
71
  embedding = this.generatePseudoEmbedding(text);
65
72
  }
66
73
  else {
@@ -68,7 +75,7 @@ export class NomicEmbedder {
68
75
  `Please run: ollama pull ${EMBEDDING_CONFIG.MODEL}`);
69
76
  }
70
77
  // Cache result
71
- this.cache.set(text, EMBEDDING_CONFIG.MODEL, embedding);
78
+ this.cache.set(text, model, embedding);
72
79
  return embedding;
73
80
  }
74
81
  /**
@@ -181,12 +188,14 @@ export class NomicEmbedder {
181
188
  const formattedText = this.formatForEmbedding(chunk);
182
189
  const chunkStartTime = Date.now();
183
190
  // Check cache
184
- const cachedEmbedding = this.cache.get(formattedText, EMBEDDING_CONFIG.MODEL);
191
+ const cachedModel = useOllama || this.cache.has(formattedText, EMBEDDING_CONFIG.MODEL)
192
+ ? EMBEDDING_CONFIG.MODEL : PSEUDO_EMBEDDING_MODEL;
193
+ const cachedEmbedding = this.cache.get(formattedText, cachedModel);
185
194
  if (cachedEmbedding) {
186
195
  return {
187
196
  chunkId: chunk.id,
188
197
  embedding: cachedEmbedding,
189
- model: EMBEDDING_CONFIG.MODEL,
198
+ model: cachedModel,
190
199
  cached: true,
191
200
  computeTimeMs: Date.now() - chunkStartTime,
192
201
  };
@@ -201,11 +210,12 @@ export class NomicEmbedder {
201
210
  embedding = this.generatePseudoEmbedding(formattedText);
202
211
  }
203
212
  // Cache the result
204
- this.cache.set(formattedText, EMBEDDING_CONFIG.MODEL, embedding);
213
+ const model = useOllama ? EMBEDDING_CONFIG.MODEL : PSEUDO_EMBEDDING_MODEL;
214
+ this.cache.set(formattedText, model, embedding);
205
215
  return {
206
216
  chunkId: chunk.id,
207
217
  embedding,
208
- model: useOllama ? EMBEDDING_CONFIG.MODEL : 'pseudo-embedding',
218
+ model,
209
219
  cached: false,
210
220
  computeTimeMs: Date.now() - chunkStartTime,
211
221
  };
@@ -34,10 +34,12 @@ export class OllamaClient {
34
34
  }
35
35
  const data = await response.json();
36
36
  // Check if configured embedding model is available
37
- // Model names may include tags like ":latest", so use startsWith for matching
37
+ // Match the configured model exactly, allowing its existing tag suffix.
38
38
  if (data.models) {
39
- return data.models.some((model) => model.name?.startsWith(EMBEDDING_CONFIG.MODEL) ||
40
- model.model?.startsWith(EMBEDDING_CONFIG.MODEL));
39
+ return data.models.some((model) => model.name === EMBEDDING_CONFIG.MODEL ||
40
+ model.name?.startsWith(`${EMBEDDING_CONFIG.MODEL}:`) ||
41
+ model.model === EMBEDDING_CONFIG.MODEL ||
42
+ model.model?.startsWith(`${EMBEDDING_CONFIG.MODEL}:`));
41
43
  }
42
44
  return false;
43
45
  }
@@ -66,10 +66,11 @@ export class GitAnalyzer {
66
66
  return 0.4; // Default when not in git repo
67
67
  }
68
68
  try {
69
- const relativePath = sanitizeGitArg(this.getRelativePath(filePath));
70
- // Use execFileSync with argument array to prevent injection
69
+ const relativePath = this.getRelativePath(filePath);
70
+ // Literal pathspecs preserve route filenames such as app/[id].tsx.
71
+ // execFileSync passes arguments directly without shell interpretation.
71
72
  const output = execFileSync('git', [
72
- 'log', '--oneline', '--since=90 days ago', '--', relativePath
73
+ '--literal-pathspecs', 'log', '--oneline', '--since=90 days ago', '--', relativePath
73
74
  ], {
74
75
  cwd: this.config.repoRoot,
75
76
  encoding: 'utf-8',
@@ -97,10 +98,10 @@ export class GitAnalyzer {
97
98
  return 0.5; // Default when not in git repo
98
99
  }
99
100
  try {
100
- const relativePath = sanitizeGitArg(this.getRelativePath(filePath));
101
+ const relativePath = this.getRelativePath(filePath);
101
102
  // Get blame info using execFileSync with argument array
102
103
  const blameOutput = execFileSync('git', [
103
- 'blame', '--line-porcelain', '--', relativePath
104
+ '--literal-pathspecs', 'blame', '--line-porcelain', '--', relativePath
104
105
  ], {
105
106
  cwd: this.config.repoRoot,
106
107
  encoding: 'utf-8',
@@ -143,12 +144,12 @@ export class GitAnalyzer {
143
144
  return 0.4; // Default when not in git repo
144
145
  }
145
146
  try {
146
- const relativePath = sanitizeGitArg(this.getRelativePath(filePath));
147
+ const relativePath = this.getRelativePath(filePath);
147
148
  // Get first commit date using execFileSync with argument array
148
149
  let firstCommitTimestamp = NaN;
149
150
  try {
150
151
  const firstCommitOutput = execFileSync('git', [
151
- 'log', '--format=%at', '--follow', '--diff-filter=A', '--', relativePath
152
+ '--literal-pathspecs', 'log', '--format=%at', '--follow', '--diff-filter=A', '--', relativePath
152
153
  ], {
153
154
  cwd: this.config.repoRoot,
154
155
  encoding: 'utf-8',
@@ -167,7 +168,7 @@ export class GitAnalyzer {
167
168
  let lastCommitTimestamp = NaN;
168
169
  try {
169
170
  const lastCommitOutput = execFileSync('git', [
170
- 'log', '-1', '--format=%at', '--', relativePath
171
+ '--literal-pathspecs', 'log', '-1', '--format=%at', '--', relativePath
171
172
  ], {
172
173
  cwd: this.config.repoRoot,
173
174
  encoding: 'utf-8',
@@ -216,7 +217,7 @@ export class GitAnalyzer {
216
217
  return 0.2; // Default when not in git repo
217
218
  }
218
219
  try {
219
- const relativePath = sanitizeGitArg(this.getRelativePath(filePath));
220
+ const relativePath = this.getRelativePath(filePath);
220
221
  // Search for each keyword separately and count unique commits
221
222
  // This avoids shell injection from keywords config
222
223
  let bugCommits = 0;
@@ -225,7 +226,7 @@ export class GitAnalyzer {
225
226
  const sanitizedKeyword = sanitizeGitArg(keyword);
226
227
  try {
227
228
  const output = execFileSync('git', [
228
- 'log', '--oneline', '--grep', sanitizedKeyword, '-i', '--', relativePath
229
+ '--literal-pathspecs', 'log', '--oneline', '--grep', sanitizedKeyword, '-i', '--', relativePath
229
230
  ], {
230
231
  cwd: this.config.repoRoot,
231
232
  encoding: 'utf-8',
@@ -267,12 +268,12 @@ export class GitAnalyzer {
267
268
  return this.getDefaultFileHistory(filePath);
268
269
  }
269
270
  try {
270
- const relativePath = sanitizeGitArg(this.getRelativePath(filePath));
271
+ const relativePath = this.getRelativePath(filePath);
271
272
  // Get commit count using execFileSync with argument array
272
273
  let totalCommits = 0;
273
274
  try {
274
275
  const commitCountOutput = execFileSync('git', [
275
- 'log', '--oneline', '--', relativePath
276
+ '--literal-pathspecs', 'log', '--oneline', '--', relativePath
276
277
  ], {
277
278
  cwd: this.config.repoRoot,
278
279
  encoding: 'utf-8',
@@ -287,7 +288,7 @@ export class GitAnalyzer {
287
288
  let uniqueAuthors = 0;
288
289
  try {
289
290
  const authorsOutput = execFileSync('git', [
290
- 'log', '--format=%ae', '--', relativePath
291
+ '--literal-pathspecs', 'log', '--format=%ae', '--', relativePath
291
292
  ], {
292
293
  cwd: this.config.repoRoot,
293
294
  encoding: 'utf-8',
@@ -305,7 +306,7 @@ export class GitAnalyzer {
305
306
  let firstCommit = null;
306
307
  try {
307
308
  const firstCommitOutput = execFileSync('git', [
308
- 'log', '--format=%at', '--follow', '--', relativePath
309
+ '--literal-pathspecs', 'log', '--format=%at', '--follow', '--', relativePath
309
310
  ], {
310
311
  cwd: this.config.repoRoot,
311
312
  encoding: 'utf-8',
@@ -328,7 +329,7 @@ export class GitAnalyzer {
328
329
  let lastCommit = null;
329
330
  try {
330
331
  const lastCommitOutput = execFileSync('git', [
331
- 'log', '-1', '--format=%at', '--', relativePath
332
+ '--literal-pathspecs', 'log', '-1', '--format=%at', '--', relativePath
332
333
  ], {
333
334
  cwd: this.config.repoRoot,
334
335
  encoding: 'utf-8',
@@ -361,7 +362,7 @@ export class GitAnalyzer {
361
362
  const sanitizedKeyword = sanitizeGitArg(keyword);
362
363
  try {
363
364
  const bugFixOutput = execFileSync('git', [
364
- 'log', '--oneline', '--grep', sanitizedKeyword, '-i', '--', relativePath
365
+ '--literal-pathspecs', 'log', '--oneline', '--grep', sanitizedKeyword, '-i', '--', relativePath
365
366
  ], {
366
367
  cwd: this.config.repoRoot,
367
368
  encoding: 'utf-8',
@@ -410,19 +411,19 @@ export class GitAnalyzer {
410
411
  }
411
412
  try {
412
413
  const sinceDate = since || new Date(Date.now() - 24 * 60 * 60 * 1000);
413
- const sinceStr = sinceDate.toISOString().split('T')[0];
414
+ const sinceStr = sinceDate.toISOString();
414
415
  // Get files changed since the date using execFileSync with argument array
415
416
  const output = execFileSync('git', [
416
- 'log', `--since=${sinceStr}`, '--name-only', '--pretty=format:'
417
+ 'log', `--since=${sinceStr}`, '--name-only', '-z', '--format='
417
418
  ], {
418
419
  cwd: this.config.repoRoot,
419
420
  encoding: 'utf-8',
420
421
  stdio: ['pipe', 'pipe', 'pipe'],
421
- }).trim();
422
+ });
422
423
  if (!output)
423
424
  return [];
424
- // Deduplicate and filter empty lines manually (instead of sort -u | grep -v)
425
- const files = output.split('\n').filter(Boolean);
425
+ // NUL records preserve whitespace, newlines and Git-quoted Unicode paths.
426
+ const files = output.split('\0').filter(Boolean);
426
427
  return Array.from(new Set(files));
427
428
  }
428
429
  catch {
@@ -442,15 +443,15 @@ export class GitAnalyzer {
442
443
  // Sanitize commit hash to prevent injection
443
444
  const sanitizedHash = sanitizeGitArg(commitHash);
444
445
  const output = execFileSync('git', [
445
- 'diff-tree', '--no-commit-id', '--name-only', '-r', sanitizedHash
446
+ 'diff-tree', '--no-commit-id', '--name-only', '-z', '-r', sanitizedHash
446
447
  ], {
447
448
  cwd: this.config.repoRoot,
448
449
  encoding: 'utf-8',
449
450
  stdio: ['pipe', 'pipe', 'pipe'],
450
- }).trim();
451
+ });
451
452
  if (!output)
452
453
  return [];
453
- return output.split('\n').filter(Boolean);
454
+ return output.split('\0').filter(Boolean);
454
455
  }
455
456
  catch {
456
457
  return [];
@@ -469,14 +470,14 @@ export class GitAnalyzer {
469
470
  // Get unstaged changes using execFileSync with argument array
470
471
  try {
471
472
  const unstagedOutput = execFileSync('git', [
472
- 'diff', '--name-only', 'HEAD'
473
+ 'diff', '--name-only', '-z', 'HEAD'
473
474
  ], {
474
475
  cwd: this.config.repoRoot,
475
476
  encoding: 'utf-8',
476
477
  stdio: ['pipe', 'pipe', 'pipe'],
477
- }).trim();
478
+ });
478
479
  if (unstagedOutput) {
479
- files.push(...unstagedOutput.split('\n').filter(Boolean));
480
+ files.push(...unstagedOutput.split('\0').filter(Boolean));
480
481
  }
481
482
  }
482
483
  catch {
@@ -485,14 +486,14 @@ export class GitAnalyzer {
485
486
  // Get staged changes using execFileSync with argument array
486
487
  try {
487
488
  const stagedOutput = execFileSync('git', [
488
- 'diff', '--name-only', '--cached'
489
+ 'diff', '--name-only', '-z', '--cached'
489
490
  ], {
490
491
  cwd: this.config.repoRoot,
491
492
  encoding: 'utf-8',
492
493
  stdio: ['pipe', 'pipe', 'pipe'],
493
- }).trim();
494
+ });
494
495
  if (stagedOutput) {
495
- files.push(...stagedOutput.split('\n').filter(Boolean));
496
+ files.push(...stagedOutput.split('\0').filter(Boolean));
496
497
  }
497
498
  }
498
499
  catch {
@@ -74,8 +74,9 @@ class CircuitBreaker {
74
74
  }
75
75
  return false;
76
76
  }
77
- // half-open: allow one request through
78
- return true;
77
+ // The open -> half-open transition already admitted the recovery probe.
78
+ // Keep further requests out until that probe records success or failure.
79
+ return false;
79
80
  }
80
81
  reset(url) {
81
82
  if (url) {
@@ -253,17 +254,23 @@ export class HttpClient {
253
254
  if (!error) {
254
255
  return 'UNKNOWN_ERROR';
255
256
  }
256
- if (error.name === 'AbortError') {
257
- return 'TIMEOUT';
258
- }
259
- if (error.message.includes('ECONNREFUSED')) {
260
- return 'CONNECTION_REFUSED';
261
- }
262
- if (error.message.includes('ENOTFOUND')) {
263
- return 'DNS_ERROR';
264
- }
265
- if (error.message.includes('ETIMEDOUT')) {
266
- return 'NETWORK_TIMEOUT';
257
+ // Native fetch wraps transport errors in a TypeError whose cause carries
258
+ // the socket/DNS code. Retain message-based handling for existing callers.
259
+ const visited = new Set();
260
+ let current = error;
261
+ while (typeof current === 'object' && current !== null && !visited.has(current)) {
262
+ visited.add(current);
263
+ const detail = current;
264
+ if (detail.name === 'AbortError')
265
+ return 'TIMEOUT';
266
+ const message = typeof detail.message === 'string' ? detail.message : '';
267
+ if (detail.code === 'ECONNREFUSED' || message.includes('ECONNREFUSED'))
268
+ return 'CONNECTION_REFUSED';
269
+ if (detail.code === 'ENOTFOUND' || message.includes('ENOTFOUND'))
270
+ return 'DNS_ERROR';
271
+ if (detail.code === 'ETIMEDOUT' || message.includes('ETIMEDOUT'))
272
+ return 'NETWORK_TIMEOUT';
273
+ current = detail.cause;
267
274
  }
268
275
  return 'REQUEST_FAILED';
269
276
  }