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.
- package/.claude/helpers/.helpers-version +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +18 -9
- package/.claude/helpers/helpers.manifest.json +6 -5
- package/.claude/helpers/hook-handler.cjs +40 -12
- package/.claude/helpers/memory.cjs +86 -0
- package/.claude/helpers/router.cjs +105 -0
- package/.claude/helpers/session.cjs +166 -0
- package/.claude/helpers/statusline.cjs +73 -621
- package/.claude/skills/release/SKILL.md +6 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +275 -0
- package/README.md +143 -366
- package/assets/readme/credit-ruflo.svg +1 -0
- package/assets/readme/credit-ruvector.svg +1 -0
- package/assets/readme/project-header.svg +1 -0
- package/assets/readme/quality-loop.svg +1 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/adapters/a2a/notifications/retry-queue.js +10 -1
- package/dist/adapters/ag-ui/json-patch.js +14 -7
- package/dist/adapters/ag-ui/state-delta-cache.js +20 -12
- package/dist/adapters/claude-flow/pretrain-bridge.js +3 -2
- package/dist/agents/claim-verifier/verifiers/file-verifier.js +3 -2
- package/dist/cli/bundle.js +6 -6
- package/dist/cli/chunks/adapter-D7G5MIDQ.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-AK2W76RG.js → agent-booster-wasm-GDHJ6QUN.js} +2 -2
- package/dist/cli/chunks/{agent-handler-MGZCWHIY.js → agent-handler-MPYYQ2RZ.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-JZ54MCSP.js → agent-memory-branch-QBSHKLA2.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-G6TUFGHC.js +2 -0
- package/dist/cli/chunks/{arena-YSWTKBCL.js → arena-UJE2FROF.js} +4 -4
- package/dist/cli/chunks/{arena-CUVH3V7H.js → arena-WIGSL37B.js} +2 -2
- package/dist/cli/chunks/{audit-LVU76QGA.js → audit-VT7Y2Z7V.js} +3 -3
- package/dist/cli/chunks/base-B45BOC7E.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-DB3LOJQU.js → better-sqlite3-DSL7LFRK.js} +2 -2
- package/dist/cli/chunks/{brain-handler-SD63KOQ6.js → brain-handler-N3C2MDMK.js} +4 -4
- package/dist/cli/chunks/{branch-enumerator-4MNOPUC7.js → branch-enumerator-B6NSQ3PZ.js} +2 -2
- package/dist/cli/chunks/{browser-OLPNTWQE.js → browser-KQ3YNRGW.js} +2 -2
- package/dist/cli/chunks/browser-workflow-MIBU4XMV.js +2 -0
- package/dist/cli/chunks/{chunk-ZWEKAEEV.js → chunk-2ORTL5WG.js} +1 -1
- package/dist/cli/chunks/{chunk-KD2BLA5Y.js → chunk-2ZEV3O24.js} +1 -1
- package/dist/cli/chunks/{chunk-25P6JA6V.js → chunk-32YSI6OT.js} +1 -1
- package/dist/cli/chunks/{chunk-A5MA7A23.js → chunk-3DKYBHNA.js} +6 -6
- package/dist/cli/chunks/{chunk-JOZ47MV6.js → chunk-3Y24VTZ3.js} +1 -1
- package/dist/cli/chunks/{chunk-2G63VIJE.js → chunk-4BWDCUZZ.js} +1 -1
- package/dist/cli/chunks/{chunk-36VKMAMN.js → chunk-4DCDIKBX.js} +2 -2
- package/dist/cli/chunks/chunk-4EEY23JS.js +4 -0
- package/dist/cli/chunks/{chunk-BD7FEUN3.js → chunk-4FOKHGP5.js} +3 -3
- package/dist/cli/chunks/{chunk-MQZ53OR3.js → chunk-4OQSAUKR.js} +2 -2
- package/dist/cli/chunks/{chunk-EYXE2XKP.js → chunk-4YPL3OXS.js} +2 -2
- package/dist/cli/chunks/{chunk-PCJQCEBA.js → chunk-5DJGP4TA.js} +2 -2
- package/dist/cli/chunks/{chunk-RC2A4JZ5.js → chunk-5KN4QL3G.js} +2 -2
- package/dist/cli/chunks/chunk-5LN7FQZI.js +2 -0
- package/dist/cli/chunks/{chunk-LU2EDWQK.js → chunk-5PNRUMRV.js} +2 -2
- package/dist/cli/chunks/{chunk-YRHTQZU4.js → chunk-62IEVKN3.js} +2 -2
- package/dist/cli/chunks/{chunk-DOBKEXMJ.js → chunk-6GTIJNRO.js} +1 -1
- package/dist/cli/chunks/{chunk-O5V7RHVG.js → chunk-6MN4L6BS.js} +2 -2
- package/dist/cli/chunks/{chunk-6PJPQGF4.js → chunk-7D6NVIGP.js} +6 -6
- package/dist/cli/chunks/{chunk-B2YGVSOP.js → chunk-7JABIXP3.js} +2 -2
- package/dist/cli/chunks/chunk-7JC3LHA6.js +742 -0
- package/dist/cli/chunks/{chunk-P7XSPP5D.js → chunk-7WUHVGGT.js} +2 -2
- package/dist/cli/chunks/{chunk-RKI3IQKQ.js → chunk-A37YYHUD.js} +3 -3
- package/dist/cli/chunks/{chunk-UBJG3IHT.js → chunk-AAQNRZKT.js} +2 -2
- package/dist/cli/chunks/{chunk-ND4QTZOL.js → chunk-AGYPPPXR.js} +2 -2
- package/dist/cli/chunks/chunk-AIE6OKCD.js +2 -0
- package/dist/cli/chunks/{chunk-JHJUSSAU.js → chunk-ANUZGOLQ.js} +2 -2
- package/dist/cli/chunks/{chunk-RLW25X66.js → chunk-AQZSF32Y.js} +2 -2
- package/dist/cli/chunks/{chunk-OIDWDGLG.js → chunk-ATXAMGVE.js} +2 -2
- package/dist/cli/chunks/{chunk-GLGKQX2V.js → chunk-AV3RX2L5.js} +2 -2
- package/dist/cli/chunks/{chunk-7QYOTUOX.js → chunk-AW5OWYQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-B4I43GE2.js → chunk-B6QTNTCU.js} +2 -2
- package/dist/cli/chunks/{chunk-P2UPYSDJ.js → chunk-BAPMEDWC.js} +1 -1
- package/dist/cli/chunks/{chunk-Y6AKKQIQ.js → chunk-BH2SQQ2N.js} +1 -1
- package/dist/cli/chunks/{chunk-O6MO5KMR.js → chunk-C6M27NQE.js} +2 -2
- package/dist/cli/chunks/{chunk-XBYQ2BS4.js → chunk-CMYZWIXS.js} +2 -2
- package/dist/cli/chunks/{chunk-DYTQHRUS.js → chunk-CZWWC7GC.js} +1 -1
- package/dist/cli/chunks/{chunk-WF6UISKW.js → chunk-D7NOHASX.js} +4 -4
- package/dist/cli/chunks/{chunk-H5RQPO3X.js → chunk-DGRE6ZAA.js} +2 -2
- package/dist/cli/chunks/{chunk-53BXTTRO.js → chunk-DSGRXW6K.js} +3 -3
- package/dist/cli/chunks/{chunk-A2VUCUTT.js → chunk-DXA7RLYU.js} +2 -2
- package/dist/cli/chunks/{chunk-GVVFTFMB.js → chunk-DZHIE5UW.js} +2 -2
- package/dist/cli/chunks/{chunk-MZB2UV2O.js → chunk-EBK6CUBD.js} +1 -1
- package/dist/cli/chunks/{chunk-WIH522AP.js → chunk-EPEKEUCF.js} +1 -1
- package/dist/cli/chunks/{chunk-SRPLERER.js → chunk-EQ4SDE4L.js} +25 -25
- package/dist/cli/chunks/{chunk-EGOIIUBD.js → chunk-EZPWSS3B.js} +2 -2
- package/dist/cli/chunks/{chunk-EADSQN5T.js → chunk-F76SYOBT.js} +1 -1
- package/dist/cli/chunks/{chunk-XL5KIYE3.js → chunk-F7JVDLOI.js} +2 -2
- package/dist/cli/chunks/{chunk-QGOWNVVG.js → chunk-FCSETOWZ.js} +4 -4
- package/dist/cli/chunks/{chunk-A3DK3XNZ.js → chunk-FFE4XAQA.js} +1 -1
- package/dist/cli/chunks/{chunk-7EZ2Z2CK.js → chunk-FPTZP7W5.js} +1 -1
- package/dist/cli/chunks/{chunk-GV4DYPJP.js → chunk-FTFIA4I5.js} +2 -2
- package/dist/cli/chunks/{chunk-SM2YJ2AL.js → chunk-FTS6NGBP.js} +2 -2
- package/dist/cli/chunks/{chunk-XWYELBZS.js → chunk-FZ3TQAPW.js} +1 -1
- package/dist/cli/chunks/{chunk-HPWWYT67.js → chunk-G35KP72N.js} +2 -2
- package/dist/cli/chunks/{chunk-HZY42OVU.js → chunk-GCHDMO5V.js} +2 -2
- package/dist/cli/chunks/{chunk-23CX7JNL.js → chunk-GRN47ANK.js} +2 -2
- package/dist/cli/chunks/{chunk-HYFQUWNB.js → chunk-GV7P5JYF.js} +2 -2
- package/dist/cli/chunks/{chunk-YO4ESCB4.js → chunk-GX5RFGW2.js} +1 -1
- package/dist/cli/chunks/{chunk-TFK2AYIN.js → chunk-H77AUJNW.js} +2 -2
- package/dist/cli/chunks/{chunk-NBLDBVAW.js → chunk-HBIV7PQH.js} +1 -1
- package/dist/cli/chunks/{chunk-VYDVI6FZ.js → chunk-HOPXHZA3.js} +2 -2
- package/dist/cli/chunks/{chunk-HYOPJHHW.js → chunk-I3BH3KIF.js} +1 -1
- package/dist/cli/chunks/{chunk-ZELWDJXT.js → chunk-ILKMNDUM.js} +2 -2
- package/dist/cli/chunks/{chunk-C3FXFU2T.js → chunk-IRHBR56R.js} +1 -1
- package/dist/cli/chunks/{chunk-FYPX5WBJ.js → chunk-ISAMM7QA.js} +1 -1
- package/dist/cli/chunks/{chunk-V5AK56DA.js → chunk-ISGFAMHZ.js} +2 -2
- package/dist/cli/chunks/{chunk-KUHLTVWC.js → chunk-J46XGXPS.js} +1 -1
- package/dist/cli/chunks/{chunk-ZS4XVJGV.js → chunk-J4XCBOPA.js} +2 -2
- package/dist/cli/chunks/{chunk-BEFTQVEW.js → chunk-JIWMFLHV.js} +2 -2
- package/dist/cli/chunks/{chunk-UFSVUBTR.js → chunk-JJ7WAU4I.js} +2 -2
- package/dist/cli/chunks/{chunk-WOV6XI3A.js → chunk-JLPNYHJJ.js} +1 -1
- package/dist/cli/chunks/{chunk-77QZHIVX.js → chunk-JO2YLIZH.js} +2 -2
- package/dist/cli/chunks/{chunk-J7AQZLIH.js → chunk-JSYNSJDQ.js} +4 -4
- package/dist/cli/chunks/{chunk-OAZX6WFU.js → chunk-JYRBOSOF.js} +2 -2
- package/dist/cli/chunks/{chunk-EJ6MMYLK.js → chunk-KEZ4PXVF.js} +1 -1
- package/dist/cli/chunks/{chunk-N5XOXPHZ.js → chunk-KLGFEHEN.js} +2 -2
- package/dist/cli/chunks/{chunk-7MIOK72I.js → chunk-KU4WLKDK.js} +7 -7
- package/dist/cli/chunks/{chunk-Z4Q5PCRZ.js → chunk-KUTMQBV4.js} +4 -4
- package/dist/cli/chunks/{chunk-VW6FRMLW.js → chunk-L6PUBB6L.js} +2 -2
- package/dist/cli/chunks/{chunk-OEPNNLR4.js → chunk-LDJ5DZT5.js} +1 -1
- package/dist/cli/chunks/{chunk-QQFQDEUE.js → chunk-LLS6JYPN.js} +2 -2
- package/dist/cli/chunks/{chunk-UOI6ULCH.js → chunk-LPCFIFZF.js} +2 -2
- package/dist/cli/chunks/{chunk-6RD44SCE.js → chunk-M5EKZA7Q.js} +1 -1
- package/dist/cli/chunks/chunk-MEYSIVMP.js +2 -0
- package/dist/cli/chunks/{chunk-YMW57PEL.js → chunk-MFGLRMO4.js} +1 -1
- package/dist/cli/chunks/{chunk-BE4KALTE.js → chunk-MM57SD2F.js} +1 -1
- package/dist/cli/chunks/{chunk-FW4DJ4FJ.js → chunk-MO3QXLF2.js} +1 -1
- package/dist/cli/chunks/{chunk-QFETNCNN.js → chunk-MRIZY6HB.js} +2 -2
- package/dist/cli/chunks/{chunk-RT6O2HW2.js → chunk-N2MDNEF7.js} +2 -2
- package/dist/cli/chunks/{chunk-UA7TDVL7.js → chunk-N5ZHIQAV.js} +4 -4
- package/dist/cli/chunks/{chunk-Q6NTEICT.js → chunk-NZ556KZN.js} +2 -2
- package/dist/cli/chunks/{chunk-CVOQ6ESD.js → chunk-O5AUOBGU.js} +2 -2
- package/dist/cli/chunks/{chunk-5D7ZFWDS.js → chunk-OBSX3I4Y.js} +2 -2
- package/dist/cli/chunks/{chunk-NOHWJOBS.js → chunk-OLD2CIDI.js} +1 -1
- package/dist/cli/chunks/{chunk-5U6N4V5M.js → chunk-OTJ22IO2.js} +4 -4
- package/dist/cli/chunks/{chunk-5GFKTJ65.js → chunk-OYVDTD3A.js} +2 -2
- package/dist/cli/chunks/{chunk-LY7MFGBD.js → chunk-P2PPJUGD.js} +147 -150
- package/dist/cli/chunks/{chunk-OZGIOKEA.js → chunk-P4FRYNHL.js} +1 -1
- package/dist/cli/chunks/{chunk-X7ADKL7T.js → chunk-P4WE6VRR.js} +2 -2
- package/dist/cli/chunks/{chunk-ZUB5YOCM.js → chunk-P725KXHX.js} +2 -2
- package/dist/cli/chunks/{chunk-74IOEOMH.js → chunk-P7MNF2SK.js} +2 -2
- package/dist/cli/chunks/{chunk-TXSPBLBT.js → chunk-PJU5HVWV.js} +2 -2
- package/dist/cli/chunks/{chunk-MT7UNBZ7.js → chunk-PN3FYSQ6.js} +2 -2
- package/dist/cli/chunks/{chunk-F2OPFVQH.js → chunk-PPFW3H7E.js} +1 -1
- package/dist/cli/chunks/{chunk-IEJ7ZV3M.js → chunk-Q4RCUCHD.js} +1 -1
- package/dist/cli/chunks/{chunk-IAENZ2DR.js → chunk-QRALXNNX.js} +2 -2
- package/dist/cli/chunks/{chunk-AJUBT4NP.js → chunk-QVX22EIM.js} +3 -3
- package/dist/cli/chunks/chunk-R6CZCMKD.js +2 -0
- package/dist/cli/chunks/chunk-ROK5YQ5P.js +3 -0
- package/dist/cli/chunks/{chunk-ON2UTP2U.js → chunk-S2GNFAOC.js} +2 -2
- package/dist/cli/chunks/{chunk-HXXHMLJ5.js → chunk-S644OORE.js} +1 -1
- package/dist/cli/chunks/{chunk-XYLQZWF6.js → chunk-S7CROKX4.js} +2 -2
- package/dist/cli/chunks/{chunk-T77GZF4B.js → chunk-S7QUHLXV.js} +1 -1
- package/dist/cli/chunks/{chunk-RDGPXENG.js → chunk-UGYXUPGN.js} +2 -2
- package/dist/cli/chunks/{chunk-QVH5Y7AP.js → chunk-URRPJ3M7.js} +1 -1
- package/dist/cli/chunks/{chunk-AEUEMVJK.js → chunk-URUOTHPO.js} +2 -2
- package/dist/cli/chunks/{chunk-VXKWNRGA.js → chunk-VCYOFWMG.js} +2 -2
- package/dist/cli/chunks/{chunk-6EGS77BB.js → chunk-VQVFGFYK.js} +1 -1
- package/dist/cli/chunks/{chunk-NHUGHAY6.js → chunk-VT5SMBEM.js} +1 -1
- package/dist/cli/chunks/{chunk-ROVZSZCS.js → chunk-VTGRGYY4.js} +3 -3
- package/dist/cli/chunks/{chunk-QPLSYEWJ.js → chunk-VWCFXCSV.js} +2 -2
- package/dist/cli/chunks/{chunk-ENK44A6Q.js → chunk-VY4557VF.js} +2 -2
- package/dist/cli/chunks/{chunk-5FSLMYAC.js → chunk-VYERAOQL.js} +2 -2
- package/dist/cli/chunks/{chunk-EIGRV3J6.js → chunk-W6H2SOIK.js} +2 -2
- package/dist/cli/chunks/{chunk-CBONQM5D.js → chunk-WBR4VRQE.js} +2 -2
- package/dist/cli/chunks/{chunk-JZT7BU44.js → chunk-WDV6CBED.js} +2 -2
- package/dist/cli/chunks/{chunk-G367W7XR.js → chunk-WO7NPGUD.js} +19 -19
- package/dist/cli/chunks/{chunk-4INST4ZL.js → chunk-WPOYFV4X.js} +1 -1
- package/dist/cli/chunks/{chunk-3M7J4U74.js → chunk-WPSGMTI4.js} +4 -4
- package/dist/cli/chunks/{chunk-RKUAWQOF.js → chunk-WQMXQO3O.js} +2 -2
- package/dist/cli/chunks/{chunk-Q3NSU24F.js → chunk-WR54SKKL.js} +2 -2
- package/dist/cli/chunks/{chunk-UYUJT6QO.js → chunk-X4OESN7M.js} +2 -2
- package/dist/cli/chunks/{chunk-ZUOVNFXK.js → chunk-X5RELRY7.js} +2 -2
- package/dist/cli/chunks/{chunk-BLG7SH4A.js → chunk-X7JEBPEW.js} +1 -1
- package/dist/cli/chunks/{chunk-FSSR6WBE.js → chunk-XEABMIUH.js} +2 -2
- package/dist/cli/chunks/{chunk-ONR2NXXD.js → chunk-XELFJC77.js} +3 -3
- package/dist/cli/chunks/{chunk-MM56VPNE.js → chunk-XPUY3ZKD.js} +3 -3
- package/dist/cli/chunks/{chunk-QUORH2MG.js → chunk-XZDPR6I2.js} +8 -8
- package/dist/cli/chunks/{chunk-MZMG6CUJ.js → chunk-Y63DADOR.js} +2 -2
- package/dist/cli/chunks/{chunk-CQNMGK6Y.js → chunk-YFRZVNE4.js} +2 -2
- package/dist/cli/chunks/{chunk-3QJU4Q4R.js → chunk-YIDZ3TEN.js} +2 -2
- package/dist/cli/chunks/{chunk-4EKV7PHB.js → chunk-Z6CRROLU.js} +2 -2
- package/dist/cli/chunks/{chunk-IWFFO6VT.js → chunk-ZPH2YT3J.js} +2 -2
- package/dist/cli/chunks/{chunk-PYKY22GC.js → chunk-ZV7LJPSI.js} +5 -5
- package/dist/cli/chunks/chunk-ZXIIB3QE.js +2 -0
- package/dist/cli/chunks/ci-63JINRNB.js +82 -0
- package/dist/cli/chunks/{ci-output-RLS32FUY.js → ci-output-CRFWLUAA.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-MRCC7WCM.js → circuit-breaker-PJLG3WYL.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-LIZCEKDF.js → claude-flow-setup-UKHSQMJU.js} +2 -2
- package/dist/cli/chunks/client-A4FTITK3.js +2 -0
- package/dist/cli/chunks/{cline-installer-T7H6R2RC.js → cline-installer-PYQ27AS3.js} +2 -2
- package/dist/cli/chunks/{code-XMBLI7OF.js → code-K7VGLZ3W.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-QS7BYLEX.js → code-index-extractor-NNWAVWSL.js} +2 -2
- package/dist/cli/chunks/{codex-installer-6PGT5FM6.js → codex-installer-U4VJIKRN.js} +2 -2
- package/dist/cli/chunks/{completions-2A3WRXY2.js → completions-DOCI3P4W.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-23HOOGJ7.js → complexity-analyzer-RFW2QRFR.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-4FSF7B3N.js → continuedev-installer-S5WXXOBU.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-A5GRQQUU.js → copilot-installer-AAQ6YLVJ.js} +2 -2
- package/dist/cli/chunks/core-handlers-FO3QTNWI.js +2 -0
- package/dist/cli/chunks/{cost-tracker-Z4STQ5VB.js → cost-tracker-R4VOHTWQ.js} +2 -2
- package/dist/cli/chunks/{coverage-NUPP6KZZ.js → coverage-P54HPCLV.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-LIV6SRWF.js +2 -0
- package/dist/cli/chunks/{cursor-installer-FVJ7ROPJ.js → cursor-installer-VHBWZE5A.js} +2 -2
- package/dist/cli/chunks/{daemon-D662EX5N.js → daemon-BTRSWNB4.js} +4 -4
- package/dist/cli/chunks/{daemon-7ZZA2MMN.js → daemon-JLH5TTWZ.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-IB4TQ2KA.js → dag-attention-scheduler-5Z6DCRFK.js} +2 -2
- package/dist/cli/chunks/{detect-LGLBZN4I.js → detect-NWGASRJJ.js} +2 -2
- package/dist/cli/chunks/{dist-node-Z3OL42YE.js → dist-node-XMNNSEFJ.js} +2 -2
- package/dist/cli/chunks/{domain-handler-L3CLNL7U.js → domain-handler-BWVBZTNR.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-GQ3V5X6L.js → domain-plugins-YAD4USA4.js} +2 -2
- package/dist/cli/chunks/domain-transfer-Z3MRPZEZ.js +2 -0
- package/dist/cli/chunks/dream-DNLGHYXY.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-UGD6USYH.js → embed-and-insert-pattern-5CCO45WC.js} +2 -2
- package/dist/cli/chunks/{eval-3B7UIYGY.js → eval-JEMLTGY4.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-3RQ4NYY3.js → experience-capture-middleware-FKVYBBAN.js} +4 -4
- package/dist/cli/chunks/{fast-paths-QOSAEPYD.js → fast-paths-TFL32H3C.js} +2 -2
- package/dist/cli/chunks/{feature-flags-3S5TH6P4.js → feature-flags-CNGAUUMT.js} +2 -2
- package/dist/cli/chunks/{feature-flags-TLF4NKOH.js → feature-flags-OHGD2NCW.js} +2 -2
- package/dist/cli/chunks/{file-discovery-AEVMJRNB.js → file-discovery-IHGDYW34.js} +2 -2
- package/dist/cli/chunks/{fleet-E6WTXWFL.js → fleet-OGTSDGJ2.js} +4 -4
- package/dist/cli/chunks/{gnn-wrapper-MCKH3AUU.js → gnn-wrapper-QYTTKNCE.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-U7XENHRR.js → heartbeat-handler-R5OD2SKN.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-DL4LXXJF.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-Y64M43J4.js +2 -0
- package/dist/cli/chunks/hnsw-index-5V6DDMTA.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-5GW4SAEI.js → hnsw-legacy-bridge-ULJWYXBQ.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-7BLZBK5T.js → hnswlib-node-SYKJXGE2.js} +2 -2
- package/dist/cli/chunks/{hooks-F3O2SB6H.js → hooks-XAJXPXTU.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-JWT2V4FQ.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-PV4EKXHB.js → hypergraph-engine-GIBPGW4N.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-VOWO5ZTW.js → hypergraph-handler-ENFK6IDN.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-XUZQSZZC.js +2 -0
- package/dist/cli/chunks/{init-handler-ENJ5ONJX.js → init-handler-CSA62LGT.js} +6 -6
- package/dist/cli/chunks/init-wizard-KDJKHEPN.js +2 -0
- package/dist/cli/chunks/kernel-MUDYPGFR.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-HNNJOOPE.js → kilocode-installer-YXFIRTSA.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-UZBIQ3IC.js → kiro-installer-JW3BG2MQ.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-GR52N7PU.js +2 -0
- package/dist/cli/chunks/{learning-YMLCVFUT.js → learning-BDBZ7ZVG.js} +4 -4
- package/dist/cli/chunks/{llm-router-YWTARCCT.js → llm-router-CCX2DYTC.js} +4 -4
- package/dist/cli/chunks/llm-router-service-QL6LVKZ4.js +2 -0
- package/dist/cli/chunks/{load-DKE3F3IP.js → load-UJTTEOOK.js} +2 -2
- package/dist/cli/chunks/load-test-76V75WZ5.js +2 -0
- package/dist/cli/chunks/{mcp-5PSGIUCW.js → mcp-2NAJYREC.js} +2 -2
- package/dist/cli/chunks/{memory-3L3O6JMM.js → memory-C3UQSN5F.js} +5 -5
- package/dist/cli/chunks/memory-backend-SMQRS5QN.js +2 -0
- package/dist/cli/chunks/memory-handlers-ESFIJENU.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-AEEO7IA4.js → multi-model-executor-SIHSHAD7.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-ABBO355U.js → opencode-installer-KDYHUGPG.js} +2 -2
- package/dist/cli/chunks/{orchestrator-E36Q7MKE.js → orchestrator-MJHIQEHD.js} +6 -6
- package/dist/cli/chunks/pattern-null-store-MWAJMOYU.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-H4XKSID4.js → pattern-usage-recorder-OLBE4UIF.js} +2 -2
- package/dist/cli/chunks/{pipeline-BGFEHXIN.js → pipeline-IOK2CV3U.js} +2 -2
- package/dist/cli/chunks/{platform-GK7ZVDJI.js → platform-53JQ7JXN.js} +2 -2
- package/dist/cli/chunks/{plugin-CAH2CKI6.js → plugin-L5SDIWDI.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-M5EYRONA.js → prime-radiant-advanced-wasm-2DS67JFS.js} +2 -2
- package/dist/cli/chunks/{project-root-BSNZC243.js → project-root-LQMOFO2Z.js} +2 -2
- package/dist/cli/chunks/protocol-executor-32X3GAJT.js +2 -0
- package/dist/cli/chunks/{protocol-handler-JDSSC2SF.js → protocol-handler-NXG2M43B.js} +2 -2
- package/dist/cli/chunks/{prove-ANPTOZJE.js → prove-7K7PFSSX.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-KAFV3TGI.js +2 -0
- package/dist/cli/chunks/{quality-SXWGYRQR.js → quality-ATILUGMJ.js} +2 -2
- package/dist/cli/chunks/quality-gate-MPZMDPIZ.js +7 -0
- package/dist/cli/chunks/queen-coordinator-L3SODGRX.js +2 -0
- package/dist/cli/chunks/{real-embeddings-WSRYAOZM.js → real-embeddings-VZN3KIAI.js} +2 -2
- package/dist/cli/chunks/{ref-validation-AZ3LRWEK.js → ref-validation-EUATPVXX.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-2QKGFIEU.js → roocode-installer-7M2GOUNZ.js} +2 -2
- package/dist/cli/chunks/router-DDCSSXYQ.js +2 -0
- package/dist/cli/chunks/routing-feedback-RFASKYCD.js +2 -0
- package/dist/cli/chunks/{routing-handler-UYDC5MMD.js → routing-handler-VWANE652.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-QXADPVEY.js → ruvector-commands-B2YIPGOV.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-HCIF2G56.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-UVAHQ7SV.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-GD4NBFKT.js → rvf-migration-coordinator-RQXOQJ5T.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-F2I5FFHK.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-7SXG66IL.js → rvf-store-integrity-7P5YDXRH.js} +2 -2
- package/dist/cli/chunks/safe-db-6ZAA4S23.js +2 -0
- package/dist/cli/chunks/schedule-SM5Q6UVP.js +2 -0
- package/dist/cli/chunks/scheduler-4EYP4EZ6.js +2 -0
- package/dist/cli/chunks/{security-YKB622PK.js → security-VJ7TVSQF.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-KMLAV7JK.js → shared-rvf-adapter-63NXQFBX.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-OYY27DFV.js → shared-rvf-dual-writer-JQRP7P5A.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-KLN2K266.js +2 -0
- package/dist/cli/chunks/{standalone-memory-2DOABVLC.js → standalone-memory-WJ72PH5P.js} +2 -2
- package/dist/cli/chunks/{status-handler-EXRKETV7.js → status-handler-G72ZSLAX.js} +2 -2
- package/dist/cli/chunks/{structural-health-2SKK6DU6.js → structural-health-HYBGP4BD.js} +2 -2
- package/dist/cli/chunks/{sync-DQ2YUNI6.js → sync-5YMZZIF4.js} +2 -2
- package/dist/cli/chunks/{sync-UW7SX7GO.js → sync-O5FQAHT7.js} +2 -2
- package/dist/cli/chunks/{task-handler-LYQ6WYUY.js → task-handler-E6IFNHZG.js} +2 -2
- package/dist/cli/chunks/{task-handlers-DIJO232S.js → task-handlers-P3GC2L5L.js} +3 -3
- package/dist/cli/chunks/{test-WRHZMUCW.js → test-OU6ERW67.js} +6 -6
- package/dist/cli/chunks/{test-scheduling-HI23RXFK.js → test-scheduling-3HY4I3HY.js} +7 -7
- package/dist/cli/chunks/{token-bootstrap-23SA6SWZ.js → token-bootstrap-A5QA4CWK.js} +2 -2
- package/dist/cli/chunks/{token-usage-M7RRDPXO.js → token-usage-MUNQVPFT.js} +2 -2
- package/dist/cli/chunks/{transformers-4TC35KKS.js → transformers-IEO25W5V.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-F4LTKAWD.js → tree-sitter-wasm-parser-T2EQHEAY.js} +2 -2
- package/dist/cli/chunks/{types-NBXV6LXQ.js → types-ODCPGCID.js} +2 -2
- package/dist/cli/chunks/unified-memory-B5IA2KKQ.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-YF74LL3Z.js +2 -0
- package/dist/cli/chunks/unified-persistence-VZMGNGWY.js +2 -0
- package/dist/cli/chunks/{upgrade-4BGOU5RM.js → upgrade-4DN6EIW2.js} +2 -2
- package/dist/cli/chunks/{validate-EDWAR63H.js → validate-TBNAPDE3.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-VI72CPR7.js → validate-swarm-ZN7XXUY4.js} +2 -2
- package/dist/cli/chunks/visual-security-ZV3BLLSH.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-Y5XBRQXF.js → web-tree-sitter-DWAWVD2X.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-VEX23WAF.js → windsurf-installer-U6EROS5S.js} +2 -2
- package/dist/cli/chunks/{witness-chain-3YNL6YGY.js → witness-chain-EQEJS2P4.js} +2 -2
- package/dist/cli/chunks/witness-chain-OA24MQWX.js +2 -0
- package/dist/cli/chunks/{witness-chain-repair-MJZGZRWT.js → witness-chain-repair-KBXDRXS3.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-TTJYXTBE.js → witness-chain-verifier-HSQGZ4R4.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-EM6YXYOY.js → witness-key-manager-RAODG73T.js} +2 -2
- package/dist/cli/chunks/{workflow-2RBDOM7V.js → workflow-KNFJNNKG.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-IMX2LSVE.js +2 -0
- package/dist/cli/chunks/{wrappers-5OTAVVOV.js → wrappers-NIJBA22T.js} +2 -2
- package/dist/cli/commands/ci.js +17 -6
- package/dist/cli/commands/quality-gate.js +6 -1
- package/dist/cli/index.js +7 -2
- package/dist/cli/process-store-cleanup.d.ts +7 -0
- package/dist/cli/process-store-cleanup.js +27 -0
- package/dist/cli/utils/ci-config.d.ts +3 -3
- package/dist/cli/utils/ci-config.js +202 -68
- package/dist/cli/utils/workflow-parser.js +73 -57
- package/dist/domains/code-intelligence/services/metric-collector/test-counter.d.ts +1 -1
- package/dist/domains/code-intelligence/services/metric-collector/test-counter.js +17 -15
- package/dist/domains/quality-assessment/quality-evidence.d.ts +3 -1
- package/dist/domains/quality-assessment/quality-evidence.js +7 -2
- package/dist/domains/test-execution/services/retry-handler.js +38 -16
- package/dist/domains/test-execution/services/test-executor.d.ts +3 -3
- package/dist/domains/test-execution/services/test-executor.js +66 -22
- package/dist/governance/ab-benchmarking.d.ts +5 -1
- package/dist/governance/ab-benchmarking.js +64 -29
- package/dist/init/fleet-integration.js +3 -2
- package/dist/init/init-wizard-steps.js +3 -2
- package/dist/init/phases/06-code-intelligence.js +6 -4
- package/dist/integrations/ruvector/sona-persistence.d.ts +1 -0
- package/dist/integrations/ruvector/sona-persistence.js +74 -20
- package/dist/integrations/ruvector/sona-wrapper.d.ts +2 -0
- package/dist/integrations/ruvector/sona-wrapper.js +13 -0
- package/dist/kernel/memory-backend.js +5 -4
- package/dist/kernel/unified-memory.js +3 -2
- package/dist/learning/aqe-learning-engine.js +3 -2
- package/dist/mcp/bundle.js +474 -471
- package/dist/mcp/connection-pool.d.ts +2 -0
- package/dist/mcp/connection-pool.js +13 -2
- package/dist/mcp/handlers/memory-handlers.d.ts +1 -0
- package/dist/mcp/handlers/memory-handlers.js +16 -6
- package/dist/mcp/protocol-server.js +29 -8
- package/dist/mcp/security/rate-limiter.d.ts +1 -0
- package/dist/mcp/security/rate-limiter.js +22 -5
- package/dist/mcp/services/session-store.js +17 -17
- package/dist/mcp/tools/planning/goap-status.d.ts +2 -0
- package/dist/mcp/tools/planning/goap-status.js +8 -2
- package/dist/mcp/types.d.ts +2 -0
- package/dist/optimization/session-cache.js +13 -11
- package/dist/planning/goap-planner.d.ts +3 -0
- package/dist/planning/goap-planner.js +80 -37
- package/dist/plugins/cache.js +10 -3
- package/dist/shared/embeddings/embedding-cache.js +5 -5
- package/dist/shared/embeddings/nomic-embedder.js +17 -7
- package/dist/shared/embeddings/ollama-client.js +5 -3
- package/dist/shared/git/git-analyzer.js +31 -30
- package/dist/shared/http/http-client.js +20 -13
- package/dist/shared/io/file-reader.js +11 -8
- package/dist/shared/llm/cache.d.ts +8 -29
- package/dist/shared/llm/cache.js +12 -11
- package/dist/shared/llm/cost-tracker.js +2 -1
- package/dist/shared/llm/provider-manager.js +4 -22
- package/dist/shared/llm/providers/gemini.d.ts +1 -0
- package/dist/shared/llm/providers/gemini.js +14 -5
- package/dist/shared/llm/providers/openrouter.js +6 -3
- package/dist/shared/metrics/code-metrics.js +1 -1
- package/dist/shared/metrics/system-metrics.js +8 -2
- package/dist/shared/retry-engine.js +6 -12
- package/dist/shared/test-runner-process.d.ts +10 -0
- package/dist/shared/test-runner-process.js +210 -0
- package/dist/test-scheduling/executors/vitest-executor.js +26 -17
- package/dist/validation/quality-verdict.js +3 -2
- package/dist/workers/quality-daemon/priority-queue.js +4 -1
- package/package.json +6 -4
- package/dist/cli/chunks/adapter-TVQKH65T.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-ULGTVVWE.js +0 -2
- package/dist/cli/chunks/base-W42BURDL.js +0 -2
- package/dist/cli/chunks/browser-workflow-HKGHFFFT.js +0 -2
- package/dist/cli/chunks/chunk-2IMSJ7IO.js +0 -2
- package/dist/cli/chunks/chunk-FBZC4IGB.js +0 -2
- package/dist/cli/chunks/chunk-LXZMP3VX.js +0 -736
- package/dist/cli/chunks/chunk-MNQN7UZX.js +0 -4
- package/dist/cli/chunks/chunk-OXHF3L2T.js +0 -2
- package/dist/cli/chunks/chunk-PELENDDQ.js +0 -2
- package/dist/cli/chunks/chunk-TW3SR4TS.js +0 -2
- package/dist/cli/chunks/chunk-V6RE4YRQ.js +0 -2
- package/dist/cli/chunks/chunk-ZQZD55MN.js +0 -3
- package/dist/cli/chunks/ci-J3TDK5RA.js +0 -81
- package/dist/cli/chunks/client-3BD2DI4N.js +0 -2
- package/dist/cli/chunks/core-handlers-C3H2ZCS2.js +0 -2
- package/dist/cli/chunks/cross-domain-router-JCQ7SWDP.js +0 -2
- package/dist/cli/chunks/domain-transfer-MFCI76IY.js +0 -2
- package/dist/cli/chunks/dream-FTP33IJB.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-HXBJVJL2.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-TU6WG2ME.js +0 -2
- package/dist/cli/chunks/hnsw-index-MS5KODD7.js +0 -2
- package/dist/cli/chunks/hybrid-backend-HT45LBHC.js +0 -2
- package/dist/cli/chunks/impact-analyzer-AP4AGTG5.js +0 -2
- package/dist/cli/chunks/init-wizard-I5DFZUQL.js +0 -2
- package/dist/cli/chunks/kernel-MISPSPPA.js +0 -2
- package/dist/cli/chunks/knowledge-graph-L26JESGE.js +0 -2
- package/dist/cli/chunks/llm-router-service-MWGC43ZA.js +0 -2
- package/dist/cli/chunks/load-test-H5ISNNM5.js +0 -2
- package/dist/cli/chunks/memory-backend-HWDNOBKW.js +0 -2
- package/dist/cli/chunks/memory-handlers-ZFDVQZM5.js +0 -2
- package/dist/cli/chunks/pattern-null-store-GQP6ICWK.js +0 -2
- package/dist/cli/chunks/protocol-executor-AD5A4DAI.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-W3Z2PKTR.js +0 -2
- package/dist/cli/chunks/quality-gate-GYNCA4ZY.js +0 -7
- package/dist/cli/chunks/queen-coordinator-HQRHLIJX.js +0 -2
- package/dist/cli/chunks/router-MTP5LH4H.js +0 -2
- package/dist/cli/chunks/routing-feedback-GWETVB4L.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-4UE5S7WP.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-PHH3HF4Q.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-KTLZBUWV.js +0 -2
- package/dist/cli/chunks/safe-db-FWWGAPVE.js +0 -2
- package/dist/cli/chunks/schedule-TPA4V4D5.js +0 -2
- package/dist/cli/chunks/scheduler-5ZTEPNDD.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-HPTT624C.js +0 -2
- package/dist/cli/chunks/unified-memory-OVFEPRPS.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-KKRSCZHR.js +0 -2
- package/dist/cli/chunks/unified-persistence-7GLR4RI3.js +0 -2
- package/dist/cli/chunks/visual-security-2FUM5GLI.js +0 -2
- package/dist/cli/chunks/witness-chain-MH6GA5L6.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-H6G65YKU.js +0 -2
|
@@ -91,9 +91,14 @@ export async function loadQualityEvidence(memory, options = {}) {
|
|
|
91
91
|
}
|
|
92
92
|
return values;
|
|
93
93
|
}
|
|
94
|
-
export function evaluateQualityEvidence(values) {
|
|
94
|
+
export function evaluateQualityEvidence(values, thresholds = {}) {
|
|
95
|
+
if (thresholds.coverage !== undefined && (!Number.isFinite(thresholds.coverage) || thresholds.coverage < 0 || thresholds.coverage > 100)) {
|
|
96
|
+
throw new Error('Coverage quality threshold must be a finite number between 0 and 100.');
|
|
97
|
+
}
|
|
95
98
|
const checks = QUALITY_METRICS.map((name) => {
|
|
96
|
-
const threshold =
|
|
99
|
+
const threshold = name === 'coverage' && thresholds.coverage !== undefined
|
|
100
|
+
? { ...DEFAULT_QUALITY_THRESHOLDS[name], value: thresholds.coverage }
|
|
101
|
+
: DEFAULT_QUALITY_THRESHOLDS[name];
|
|
97
102
|
const value = values[name];
|
|
98
103
|
return {
|
|
99
104
|
name,
|
|
@@ -11,6 +11,7 @@ import { TEST_EXECUTION_CONSTANTS, RETRY_CONSTANTS } from '../../constants.js';
|
|
|
11
11
|
import { toError } from '../../../shared/error-utils.js';
|
|
12
12
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
13
13
|
import { secureRandom } from '../../../shared/utils/crypto-random.js';
|
|
14
|
+
import { terminateTestRunner, trackTestRunnerExit } from '../../../shared/test-runner-process.js';
|
|
14
15
|
const DEFAULT_RETRY_CONFIG = {
|
|
15
16
|
simulateForTesting: false,
|
|
16
17
|
simulatedRetrySuccessRate: RETRY_CONSTANTS.DEFAULT_FLAKY_PASS_RATE,
|
|
@@ -335,6 +336,9 @@ export class RetryHandlerService {
|
|
|
335
336
|
*/
|
|
336
337
|
buildTestCommand(runner, testFile, testName) {
|
|
337
338
|
const npx = this.config.npxPath;
|
|
339
|
+
// These runners interpret name filters as regular expressions, but a
|
|
340
|
+
// FailedTest contains the literal assertion name from the previous run.
|
|
341
|
+
const namePattern = testName?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') ?? '';
|
|
338
342
|
switch (runner) {
|
|
339
343
|
case 'vitest':
|
|
340
344
|
// vitest run --reporter=json testFile -t "testName"
|
|
@@ -343,7 +347,7 @@ export class RetryHandlerService {
|
|
|
343
347
|
const report = createVitestJsonReport();
|
|
344
348
|
const vitestArgs = ['vitest', 'run', '--reporter=json', testFile];
|
|
345
349
|
if (testName && testName !== testFile) {
|
|
346
|
-
vitestArgs.push('-t',
|
|
350
|
+
vitestArgs.push('-t', namePattern);
|
|
347
351
|
}
|
|
348
352
|
vitestArgs.push(...report.args);
|
|
349
353
|
return { command: npx, args: vitestArgs, report };
|
|
@@ -353,7 +357,7 @@ export class RetryHandlerService {
|
|
|
353
357
|
{
|
|
354
358
|
const jestArgs = ['jest', '--json', '--testPathPattern', testFile];
|
|
355
359
|
if (testName && testName !== testFile) {
|
|
356
|
-
jestArgs.push('-t',
|
|
360
|
+
jestArgs.push('-t', namePattern);
|
|
357
361
|
}
|
|
358
362
|
return { command: npx, args: jestArgs };
|
|
359
363
|
}
|
|
@@ -362,7 +366,7 @@ export class RetryHandlerService {
|
|
|
362
366
|
{
|
|
363
367
|
const mochaArgs = ['mocha', '--reporter', 'json', testFile];
|
|
364
368
|
if (testName && testName !== testFile) {
|
|
365
|
-
mochaArgs.push('--grep',
|
|
369
|
+
mochaArgs.push('--grep', namePattern);
|
|
366
370
|
}
|
|
367
371
|
return { command: npx, args: mochaArgs };
|
|
368
372
|
}
|
|
@@ -379,6 +383,8 @@ export class RetryHandlerService {
|
|
|
379
383
|
let stdout = '';
|
|
380
384
|
let stderr = '';
|
|
381
385
|
let timedOut = false;
|
|
386
|
+
let termination;
|
|
387
|
+
const timeoutError = new Error(`Test execution timed out after ${timeout}ms for command: ${command} ${args.join(' ')}`);
|
|
382
388
|
const settle = (fn, value) => {
|
|
383
389
|
report?.cleanup();
|
|
384
390
|
fn(value);
|
|
@@ -387,13 +393,20 @@ export class RetryHandlerService {
|
|
|
387
393
|
// Arguments are passed as array to avoid shell interpretation
|
|
388
394
|
const proc = spawn(command, args, {
|
|
389
395
|
cwd,
|
|
396
|
+
detached: process.platform !== 'win32',
|
|
390
397
|
env: { ...process.env, FORCE_COLOR: '0', CI: 'true' },
|
|
391
398
|
});
|
|
399
|
+
const untrackExit = trackTestRunnerExit(proc);
|
|
392
400
|
const timeoutHandle = setTimeout(() => {
|
|
393
401
|
timedOut = true;
|
|
394
|
-
proc
|
|
395
|
-
|
|
396
|
-
|
|
402
|
+
termination = terminateTestRunner(proc);
|
|
403
|
+
termination.catch(error => {
|
|
404
|
+
logger.warn(`Retry runner cleanup failed: ${toError(error).message}`);
|
|
405
|
+
// A denied cleanup can leave the root alive: preserve the timeout
|
|
406
|
+
// outcome immediately, keeping artifacts because settlement is unknown.
|
|
407
|
+
reject(timeoutError);
|
|
408
|
+
});
|
|
409
|
+
termination.then(untrackExit, () => undefined);
|
|
397
410
|
}, timeout);
|
|
398
411
|
proc.stdout?.on('data', (data) => {
|
|
399
412
|
stdout += data.toString();
|
|
@@ -404,9 +417,10 @@ export class RetryHandlerService {
|
|
|
404
417
|
proc.on('close', (code) => {
|
|
405
418
|
clearTimeout(timeoutHandle);
|
|
406
419
|
if (timedOut) {
|
|
407
|
-
settle(reject,
|
|
420
|
+
termination?.then(() => settle(reject, timeoutError), () => reject(timeoutError));
|
|
408
421
|
return;
|
|
409
422
|
}
|
|
423
|
+
untrackExit();
|
|
410
424
|
// Parse result based on exit code and output (Vitest writes the JSON
|
|
411
425
|
// report to the --outputFile; read it back rather than trusting stdout).
|
|
412
426
|
try {
|
|
@@ -422,6 +436,7 @@ export class RetryHandlerService {
|
|
|
422
436
|
});
|
|
423
437
|
proc.on('error', (err) => {
|
|
424
438
|
clearTimeout(timeoutHandle);
|
|
439
|
+
untrackExit();
|
|
425
440
|
report?.cleanup();
|
|
426
441
|
reject(new Error(`Failed to spawn test process: ${err.message}. ` +
|
|
427
442
|
`Command: ${command} ${args.join(' ')}. ` +
|
|
@@ -433,20 +448,23 @@ export class RetryHandlerService {
|
|
|
433
448
|
* Parse test runner output to determine pass/fail status
|
|
434
449
|
*/
|
|
435
450
|
parseTestResult(exitCode, stdout, stderr) {
|
|
436
|
-
// A
|
|
451
|
+
// A retry can clear a prior failure only when the report proves a test
|
|
452
|
+
// actually passed. Empty/fully skipped selections can also exit zero.
|
|
437
453
|
try {
|
|
438
454
|
// Vitest JSON output
|
|
439
455
|
const vitestMatch = stdout.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
|
|
440
456
|
if (vitestMatch) {
|
|
441
457
|
const result = safeJsonParse(vitestMatch[0]);
|
|
442
458
|
if (exitCode === 0 && result.success !== false
|
|
443
|
-
&& result.numFailedTests === 0 && result.numFailedTestSuites === 0
|
|
459
|
+
&& result.numFailedTests === 0 && result.numFailedTestSuites === 0
|
|
460
|
+
&& Number.isFinite(result.numPassedTests) && result.numPassedTests > 0) {
|
|
444
461
|
return { passed: true };
|
|
445
462
|
}
|
|
446
463
|
const failedTest = result.testResults?.[0]?.assertionResults?.find((r) => r.status === 'failed');
|
|
447
464
|
return {
|
|
448
465
|
passed: false,
|
|
449
|
-
error: failedTest?.failureMessages?.join('\n') || stderr
|
|
466
|
+
error: failedTest?.failureMessages?.join('\n') || stderr
|
|
467
|
+
|| (exitCode === 0 ? 'Retry runner did not report any passing tests.' : `Test failed with exit code ${exitCode}`),
|
|
450
468
|
};
|
|
451
469
|
}
|
|
452
470
|
// Jest JSON output
|
|
@@ -454,34 +472,38 @@ export class RetryHandlerService {
|
|
|
454
472
|
if (jestMatch) {
|
|
455
473
|
const result = safeJsonParse(jestMatch[0]);
|
|
456
474
|
if (exitCode === 0 && result.success !== false
|
|
457
|
-
&& result.numFailedTests === 0 && result.numFailedTestSuites === 0
|
|
475
|
+
&& result.numFailedTests === 0 && result.numFailedTestSuites === 0
|
|
476
|
+
&& Number.isFinite(result.numPassedTests) && result.numPassedTests > 0) {
|
|
458
477
|
return { passed: true };
|
|
459
478
|
}
|
|
460
479
|
const failedTest = result.testResults?.[0]?.assertionResults?.find((r) => r.status === 'failed');
|
|
461
480
|
return {
|
|
462
481
|
passed: false,
|
|
463
|
-
error: failedTest?.failureMessages?.join('\n') || stderr
|
|
482
|
+
error: failedTest?.failureMessages?.join('\n') || stderr
|
|
483
|
+
|| (exitCode === 0 ? 'Retry runner did not report any passing tests.' : `Test failed with exit code ${exitCode}`),
|
|
464
484
|
};
|
|
465
485
|
}
|
|
466
486
|
// Mocha JSON output
|
|
467
487
|
const mochaMatch = stdout.match(/\{[\s\S]*"stats"[\s\S]*"failures"[\s\S]*\}/);
|
|
468
488
|
if (mochaMatch) {
|
|
469
489
|
const result = safeJsonParse(mochaMatch[0]);
|
|
470
|
-
if (exitCode === 0 && result.stats?.failures === 0
|
|
490
|
+
if (exitCode === 0 && result.stats?.failures === 0
|
|
491
|
+
&& Number.isFinite(result.stats?.passes) && result.stats.passes > 0) {
|
|
471
492
|
return { passed: true };
|
|
472
493
|
}
|
|
473
494
|
const failure = result.failures?.[0];
|
|
474
495
|
return {
|
|
475
496
|
passed: false,
|
|
476
|
-
error: failure?.err?.message || stderr
|
|
497
|
+
error: failure?.err?.message || stderr
|
|
498
|
+
|| (exitCode === 0 ? 'Retry runner did not report any passing tests.' : `Test failed with exit code ${exitCode}`),
|
|
477
499
|
};
|
|
478
500
|
}
|
|
479
501
|
}
|
|
480
502
|
catch {
|
|
481
|
-
//
|
|
503
|
+
// Unreadable output cannot prove that the retry executed a passing test.
|
|
482
504
|
}
|
|
483
505
|
if (exitCode === 0)
|
|
484
|
-
return { passed:
|
|
506
|
+
return { passed: false, error: 'Retry runner did not report any passing tests.' };
|
|
485
507
|
// Non-zero exit code means failure
|
|
486
508
|
const errorOutput = stderr || stdout || `Test failed with exit code ${exitCode}`;
|
|
487
509
|
return {
|
|
@@ -170,9 +170,9 @@ export declare class TestExecutorService implements ITestExecutionService {
|
|
|
170
170
|
*/
|
|
171
171
|
private extractCoverageFromJson;
|
|
172
172
|
/**
|
|
173
|
-
* Read coverage from
|
|
174
|
-
*
|
|
175
|
-
*
|
|
173
|
+
* Read coverage from the private output directory of a completed runner.
|
|
174
|
+
* Setting the directory does not enable coverage; project configuration
|
|
175
|
+
* still decides whether coverage is collected.
|
|
176
176
|
*/
|
|
177
177
|
private readCoverageFromDisk;
|
|
178
178
|
private storeResults;
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { LoggerFactory } from '../../../logging/index.js';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
8
9
|
import { join } from 'node:path';
|
|
9
10
|
import { v4 as uuidv4 } from 'uuid';
|
|
10
11
|
import { ok, err } from '../../../shared/types/index.js';
|
|
@@ -16,6 +17,7 @@ import { writeQualityEvidence } from '../../quality-assessment/quality-evidence.
|
|
|
16
17
|
import { getTestRunnerExecutionError, TestRunnerExecutionError } from '../../../shared/test-runner-verdict.js';
|
|
17
18
|
import { createVitestJsonReport } from '../../../shared/vitest-json-report.js';
|
|
18
19
|
import { getClaudeModelForTier } from '../../../shared/llm/model-registry.js';
|
|
20
|
+
import { terminateTestRunner, trackTestRunnerExit } from '../../../shared/test-runner-process.js';
|
|
19
21
|
const DEFAULT_CONFIG = {
|
|
20
22
|
simulateForTesting: false,
|
|
21
23
|
simulatedTestsPerFile: 5,
|
|
@@ -368,19 +370,29 @@ Provide:
|
|
|
368
370
|
return err(new Error(`Test file not found: ${missingFile}`));
|
|
369
371
|
}
|
|
370
372
|
// Build command based on framework
|
|
371
|
-
const { command, args, report } = this.buildTestCommand(files, framework);
|
|
373
|
+
const { command, args, report, coverageDirectory } = this.buildTestCommand(files, framework);
|
|
372
374
|
const fileLabel = files.join(', ');
|
|
373
375
|
return new Promise((resolve) => {
|
|
374
376
|
let stdout = '';
|
|
375
377
|
let stderr = '';
|
|
376
378
|
let killed = false;
|
|
379
|
+
let termination;
|
|
377
380
|
let settled = false;
|
|
381
|
+
const cleanupArtifacts = () => {
|
|
382
|
+
report?.cleanup();
|
|
383
|
+
if (coverageDirectory) {
|
|
384
|
+
try {
|
|
385
|
+
rmSync(coverageDirectory, { recursive: true, force: true });
|
|
386
|
+
}
|
|
387
|
+
catch { /* Best effort. */ }
|
|
388
|
+
}
|
|
389
|
+
};
|
|
378
390
|
const finish = (result, cleanup = true) => {
|
|
379
391
|
if (settled)
|
|
380
392
|
return;
|
|
381
393
|
settled = true;
|
|
382
394
|
if (cleanup)
|
|
383
|
-
|
|
395
|
+
cleanupArtifacts();
|
|
384
396
|
resolve(result);
|
|
385
397
|
};
|
|
386
398
|
// Spawn the test runner process
|
|
@@ -390,6 +402,7 @@ Provide:
|
|
|
390
402
|
try {
|
|
391
403
|
proc = spawn(command, args, {
|
|
392
404
|
cwd: process.cwd(),
|
|
405
|
+
detached: process.platform !== 'win32',
|
|
393
406
|
env: {
|
|
394
407
|
...process.env,
|
|
395
408
|
FORCE_COLOR: '0', // Disable color codes for easier parsing
|
|
@@ -401,10 +414,15 @@ Provide:
|
|
|
401
414
|
finish(err(new Error(`Failed to spawn test runner: ${toErrorMessage(error)}. Is '${command}' installed?`)));
|
|
402
415
|
return;
|
|
403
416
|
}
|
|
417
|
+
const untrackExit = trackTestRunnerExit(proc);
|
|
404
418
|
// Set timeout
|
|
405
419
|
const timeoutId = setTimeout(() => {
|
|
406
420
|
killed = true;
|
|
407
|
-
proc
|
|
421
|
+
termination = terminateTestRunner(proc);
|
|
422
|
+
// Keep the timeout outcome immediate; cleanup waits for the owned
|
|
423
|
+
// group, rather than treating the root's close as descendant exit.
|
|
424
|
+
termination.catch(error => logger.warn(`Test runner cleanup failed: ${toErrorMessage(error)}`));
|
|
425
|
+
termination.then(untrackExit, () => undefined);
|
|
408
426
|
finish(err(new Error(`Test execution timed out after ${timeout}ms for files: ${fileLabel}`)), false);
|
|
409
427
|
}, timeout);
|
|
410
428
|
proc.stdout?.on('data', (data) => {
|
|
@@ -416,9 +434,12 @@ Provide:
|
|
|
416
434
|
proc.on('close', (code) => {
|
|
417
435
|
clearTimeout(timeoutId);
|
|
418
436
|
if (killed) {
|
|
419
|
-
|
|
420
|
-
|
|
437
|
+
// Coverage and JSON reports belong to this run; clean both only
|
|
438
|
+
// after the entire owned process group has stopped.
|
|
439
|
+
termination?.then(() => cleanupArtifacts(), () => undefined);
|
|
440
|
+
return; // The timeout result has already been returned.
|
|
421
441
|
}
|
|
442
|
+
untrackExit();
|
|
422
443
|
// Parse results based on framework. Vitest 5 writes the JSON report to
|
|
423
444
|
// a file instead of stdout, so read it back through the report handle.
|
|
424
445
|
let reportText;
|
|
@@ -434,10 +455,10 @@ Provide:
|
|
|
434
455
|
return;
|
|
435
456
|
}
|
|
436
457
|
const parseResult = this.parseTestOutput(reportText, stderr, fileLabel, framework, code);
|
|
437
|
-
//
|
|
438
|
-
//
|
|
439
|
-
if (parseResult.success && !parseResult.value.coverage &&
|
|
440
|
-
const diskCoverage = this.readCoverageFromDisk();
|
|
458
|
+
// Read only this invocation's coverage artifacts. A previous or
|
|
459
|
+
// concurrent run's project coverage directory is not evidence.
|
|
460
|
+
if (parseResult.success && !parseResult.value.coverage && coverageDirectory) {
|
|
461
|
+
const diskCoverage = this.readCoverageFromDisk(coverageDirectory);
|
|
441
462
|
if (diskCoverage) {
|
|
442
463
|
parseResult.value.coverage = diskCoverage.summary;
|
|
443
464
|
if (diskCoverage.perFile.length > 0) {
|
|
@@ -451,6 +472,7 @@ Provide:
|
|
|
451
472
|
clearTimeout(timeoutId);
|
|
452
473
|
if (killed)
|
|
453
474
|
return;
|
|
475
|
+
untrackExit();
|
|
454
476
|
finish(err(new Error(`Failed to spawn test runner: ${error.message}. Is '${command}' installed?`)));
|
|
455
477
|
});
|
|
456
478
|
});
|
|
@@ -460,22 +482,35 @@ Provide:
|
|
|
460
482
|
*/
|
|
461
483
|
buildTestCommand(fileOrFiles, framework) {
|
|
462
484
|
const files = Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles];
|
|
485
|
+
const createCoverageDirectory = () => mkdtempSync(join(tmpdir(), 'aqe-test-coverage-'));
|
|
463
486
|
switch (framework.toLowerCase()) {
|
|
464
487
|
case 'vitest': {
|
|
465
488
|
// --outputFile makes Vitest 4 and 5 both write the JSON report to a
|
|
466
489
|
// file we own; Vitest 5 no longer prints it to stdout.
|
|
467
|
-
const
|
|
490
|
+
const coverageDirectory = createCoverageDirectory();
|
|
491
|
+
let report;
|
|
492
|
+
try {
|
|
493
|
+
report = createVitestJsonReport();
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
rmSync(coverageDirectory, { recursive: true, force: true });
|
|
497
|
+
throw error;
|
|
498
|
+
}
|
|
468
499
|
return {
|
|
469
500
|
command: 'npx',
|
|
470
|
-
args: ['vitest', 'run', ...files, '--reporter=json', '--no-color', ...report.args],
|
|
501
|
+
args: ['vitest', 'run', ...files, '--reporter=json', '--no-color', ...report.args, `--coverage.reportsDirectory=${coverageDirectory}`],
|
|
471
502
|
report,
|
|
503
|
+
coverageDirectory,
|
|
472
504
|
};
|
|
473
505
|
}
|
|
474
|
-
case 'jest':
|
|
506
|
+
case 'jest': {
|
|
507
|
+
const coverageDirectory = createCoverageDirectory();
|
|
475
508
|
return {
|
|
476
509
|
command: 'npx',
|
|
477
|
-
args: ['jest', ...files, '--json', '--no-colors', '--testLocationInResults'],
|
|
510
|
+
args: ['jest', ...files, '--json', '--no-colors', '--testLocationInResults', `--coverageDirectory=${coverageDirectory}`],
|
|
511
|
+
coverageDirectory,
|
|
478
512
|
};
|
|
513
|
+
}
|
|
479
514
|
case 'mocha':
|
|
480
515
|
// Note: mocha has no built-in coverage — requires external nyc/c8 wrapper.
|
|
481
516
|
// Coverage data will be unavailable for mocha-based test runs.
|
|
@@ -491,11 +526,20 @@ Provide:
|
|
|
491
526
|
};
|
|
492
527
|
default: {
|
|
493
528
|
// Default to vitest
|
|
494
|
-
const
|
|
529
|
+
const coverageDirectory = createCoverageDirectory();
|
|
530
|
+
let report;
|
|
531
|
+
try {
|
|
532
|
+
report = createVitestJsonReport();
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
rmSync(coverageDirectory, { recursive: true, force: true });
|
|
536
|
+
throw error;
|
|
537
|
+
}
|
|
495
538
|
return {
|
|
496
539
|
command: 'npx',
|
|
497
|
-
args: ['vitest', 'run', ...files, '--reporter=json', '--no-color', ...report.args],
|
|
540
|
+
args: ['vitest', 'run', ...files, '--reporter=json', '--no-color', ...report.args, `--coverage.reportsDirectory=${coverageDirectory}`],
|
|
498
541
|
report,
|
|
542
|
+
coverageDirectory,
|
|
499
543
|
};
|
|
500
544
|
}
|
|
501
545
|
}
|
|
@@ -1003,16 +1047,16 @@ Provide:
|
|
|
1003
1047
|
return { perFile };
|
|
1004
1048
|
}
|
|
1005
1049
|
/**
|
|
1006
|
-
* Read coverage from
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1050
|
+
* Read coverage from the private output directory of a completed runner.
|
|
1051
|
+
* Setting the directory does not enable coverage; project configuration
|
|
1052
|
+
* still decides whether coverage is collected.
|
|
1009
1053
|
*/
|
|
1010
|
-
readCoverageFromDisk() {
|
|
1054
|
+
readCoverageFromDisk(coverageDirectory) {
|
|
1011
1055
|
try {
|
|
1012
1056
|
// Check common coverage output paths
|
|
1013
1057
|
const candidates = [
|
|
1014
|
-
join(
|
|
1015
|
-
join(
|
|
1058
|
+
join(coverageDirectory, 'coverage-summary.json'),
|
|
1059
|
+
join(coverageDirectory, 'coverage-final.json'),
|
|
1016
1060
|
];
|
|
1017
1061
|
for (const filePath of candidates) {
|
|
1018
1062
|
if (!existsSync(filePath))
|
|
@@ -168,7 +168,8 @@ export interface WinnerResult {
|
|
|
168
168
|
benchmarkId: string;
|
|
169
169
|
winnerId: string;
|
|
170
170
|
winnerName: string;
|
|
171
|
-
confidence
|
|
171
|
+
/** Ranking heuristic, not a probability or statistical confidence level. */
|
|
172
|
+
heuristicScore: number;
|
|
172
173
|
combinedScore: number;
|
|
173
174
|
significantMetrics: string[];
|
|
174
175
|
recommendation: string;
|
|
@@ -290,10 +291,13 @@ export declare class ABBenchmarkingFramework {
|
|
|
290
291
|
* Calculate statistical significance for a benchmark
|
|
291
292
|
*/
|
|
292
293
|
calculateStatisticalSignificance(benchmarkId: string): SignificanceResult;
|
|
294
|
+
private calculateSignificance;
|
|
293
295
|
/**
|
|
294
296
|
* Get the winner of a benchmark
|
|
295
297
|
*/
|
|
296
298
|
getWinner(benchmarkId: string): WinnerResult | null;
|
|
299
|
+
/** Require evidence for this candidate over its ranked runner-up. */
|
|
300
|
+
private isSignificantlyBetterThanRunnerUp;
|
|
297
301
|
/**
|
|
298
302
|
* Compare two specific variants
|
|
299
303
|
*/
|
|
@@ -523,11 +523,17 @@ export class ABBenchmarkingFramework {
|
|
|
523
523
|
* Calculate statistical significance for a benchmark
|
|
524
524
|
*/
|
|
525
525
|
calculateStatisticalSignificance(benchmarkId) {
|
|
526
|
+
return this.calculateSignificance(benchmarkId);
|
|
527
|
+
}
|
|
528
|
+
calculateSignificance(benchmarkId, variantIds) {
|
|
526
529
|
const benchmark = this.benchmarks.get(benchmarkId);
|
|
527
530
|
if (!benchmark) {
|
|
528
531
|
throw new Error(`Benchmark ${benchmarkId} not found`);
|
|
529
532
|
}
|
|
530
|
-
const { config
|
|
533
|
+
const { config } = benchmark;
|
|
534
|
+
const variantMetrics = variantIds
|
|
535
|
+
? new Map(variantIds.map(id => [id, benchmark.variantMetrics.get(id)]))
|
|
536
|
+
: benchmark.variantMetrics;
|
|
531
537
|
const alpha = 1 - config.confidenceLevel;
|
|
532
538
|
// Bonferroni correction for multiple comparisons
|
|
533
539
|
const numComparisons = config.metrics.length;
|
|
@@ -540,10 +546,10 @@ export class ABBenchmarkingFramework {
|
|
|
540
546
|
const chiSquareResult = chiSquareTest(variants);
|
|
541
547
|
// Per-metric statistics (pairwise comparisons between first two variants)
|
|
542
548
|
const metricStatistics = [];
|
|
543
|
-
const
|
|
544
|
-
if (
|
|
545
|
-
const v1 = variantMetrics.get(
|
|
546
|
-
const v2 = variantMetrics.get(
|
|
549
|
+
const comparedIds = Array.from(variantMetrics.keys());
|
|
550
|
+
if (comparedIds.length >= 2) {
|
|
551
|
+
const v1 = variantMetrics.get(comparedIds[0]);
|
|
552
|
+
const v2 = variantMetrics.get(comparedIds[1]);
|
|
547
553
|
for (const metricConfig of config.metrics) {
|
|
548
554
|
const values1 = (v1.metrics.get(metricConfig.name) || []).map(d => d.value);
|
|
549
555
|
const values2 = (v2.metrics.get(metricConfig.name) || []).map(d => d.value);
|
|
@@ -618,10 +624,10 @@ export class ABBenchmarkingFramework {
|
|
|
618
624
|
// Sort by combined score (descending)
|
|
619
625
|
scores.sort((a, b) => b.score - a.score);
|
|
620
626
|
const winner = scores[0];
|
|
621
|
-
// Calculate
|
|
627
|
+
// Calculate a ranking heuristic based on significance and score gap
|
|
622
628
|
const significance = this.calculateStatisticalSignificance(benchmarkId);
|
|
623
629
|
const scoreGap = scores.length > 1 ? winner.score - scores[1].score : winner.score;
|
|
624
|
-
const
|
|
630
|
+
const heuristicScore = significance.isSignificant
|
|
625
631
|
? Math.min(0.99, 0.5 + scoreGap * 0.5 + (significance.powerAnalysis.currentPower * 0.25))
|
|
626
632
|
: Math.min(0.5, scoreGap * 0.5);
|
|
627
633
|
const significantMetrics = significance.metricStatistics
|
|
@@ -632,12 +638,38 @@ export class ABBenchmarkingFramework {
|
|
|
632
638
|
benchmarkId,
|
|
633
639
|
winnerId: winner.variantId,
|
|
634
640
|
winnerName: variantConfig?.name || winner.variantId,
|
|
635
|
-
|
|
641
|
+
heuristicScore,
|
|
636
642
|
combinedScore: winner.score,
|
|
637
643
|
significantMetrics,
|
|
638
|
-
recommendation: this.generateWinnerRecommendation(winner,
|
|
644
|
+
recommendation: this.generateWinnerRecommendation(winner, heuristicScore, significantMetrics),
|
|
639
645
|
};
|
|
640
646
|
}
|
|
647
|
+
/** Require evidence for this candidate over its ranked runner-up. */
|
|
648
|
+
isSignificantlyBetterThanRunnerUp(benchmarkId, winnerId) {
|
|
649
|
+
const benchmark = this.benchmarks.get(benchmarkId);
|
|
650
|
+
const scores = this.calculateCombinedScores(benchmark).sort((a, b) => b.score - a.score);
|
|
651
|
+
const [winner, runnerUp] = scores;
|
|
652
|
+
if (!runnerUp || winner.variantId !== winnerId || winner.score <= runnerUp.score) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
const significance = this.calculateSignificance(benchmarkId, [winnerId, runnerUp.variantId]);
|
|
656
|
+
const winnerMetrics = benchmark.variantMetrics.get(winnerId);
|
|
657
|
+
const runnerUpMetrics = benchmark.variantMetrics.get(runnerUp.variantId);
|
|
658
|
+
const successMetrics = benchmark.config.metrics.filter(metric => metric.type === 'success_rate');
|
|
659
|
+
const successContributesToScore = successMetrics.length === 0 ||
|
|
660
|
+
successMetrics.some(metric => metric.weight > 0);
|
|
661
|
+
if (successContributesToScore && significance.chiSquareTest?.isSignificant &&
|
|
662
|
+
this.getSuccessRate(winnerMetrics) > this.getSuccessRate(runnerUpMetrics)) {
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
return significance.metricStatistics.some(statistic => {
|
|
666
|
+
const metric = benchmark.config.metrics.find(config => config.name === statistic.metric);
|
|
667
|
+
return statistic.isSignificant && metric.weight > 0 &&
|
|
668
|
+
(metric.higherIsBetter
|
|
669
|
+
? statistic.variantA.mean > statistic.variantB.mean
|
|
670
|
+
: statistic.variantA.mean < statistic.variantB.mean);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
641
673
|
/**
|
|
642
674
|
* Compare two specific variants
|
|
643
675
|
*/
|
|
@@ -693,9 +725,6 @@ export class ABBenchmarkingFramework {
|
|
|
693
725
|
scoreA += normalizedA * metricConfig.weight;
|
|
694
726
|
scoreB += normalizedB * metricConfig.weight;
|
|
695
727
|
}
|
|
696
|
-
// Add success rate comparison
|
|
697
|
-
const successRateA = this.getSuccessRate(metricsA);
|
|
698
|
-
const successRateB = this.getSuccessRate(metricsB);
|
|
699
728
|
const overallWinner = scoreA > scoreB ? variantA : scoreB > scoreA ? variantB : null;
|
|
700
729
|
const confidence = Math.abs(scoreA - scoreB) / Math.max(scoreA, scoreB, 0.001);
|
|
701
730
|
return {
|
|
@@ -760,16 +789,19 @@ export class ABBenchmarkingFramework {
|
|
|
760
789
|
if (winner.significantMetrics.length > 0) {
|
|
761
790
|
reasoning.push(`Significant improvements in: ${winner.significantMetrics.join(', ')}`);
|
|
762
791
|
}
|
|
763
|
-
if (
|
|
792
|
+
if (!this.isSignificantlyBetterThanRunnerUp(benchmarkId, winner.winnerId)) {
|
|
793
|
+
caveats.push('Leading variant is not significantly better than the runner-up');
|
|
794
|
+
}
|
|
795
|
+
else if (winner.heuristicScore >= 0.95) {
|
|
764
796
|
readyToApply = true;
|
|
765
|
-
reasoning.push('High
|
|
797
|
+
reasoning.push('High heuristic score with runner-up significance - ready to apply');
|
|
766
798
|
}
|
|
767
|
-
else if (winner.
|
|
799
|
+
else if (winner.heuristicScore >= 0.8) {
|
|
768
800
|
readyToApply = true;
|
|
769
|
-
reasoning.push('Good
|
|
801
|
+
reasoning.push('Good heuristic score with runner-up significance - ready to apply');
|
|
770
802
|
}
|
|
771
803
|
else {
|
|
772
|
-
caveats.push(`
|
|
804
|
+
caveats.push(`Heuristic score (${winner.heuristicScore.toFixed(3)}) below recommended threshold`);
|
|
773
805
|
}
|
|
774
806
|
}
|
|
775
807
|
else {
|
|
@@ -778,7 +810,7 @@ export class ABBenchmarkingFramework {
|
|
|
778
810
|
return {
|
|
779
811
|
benchmarkId,
|
|
780
812
|
suggestedWinnerId,
|
|
781
|
-
confidence: winner?.
|
|
813
|
+
confidence: winner?.heuristicScore ?? 0,
|
|
782
814
|
reasoning,
|
|
783
815
|
caveats,
|
|
784
816
|
readyToApply,
|
|
@@ -798,12 +830,15 @@ export class ABBenchmarkingFramework {
|
|
|
798
830
|
if (!winner) {
|
|
799
831
|
throw new Error(`No winner determined for benchmark ${benchmarkId}`);
|
|
800
832
|
}
|
|
833
|
+
if (!this.isSignificantlyBetterThanRunnerUp(benchmarkId, winner.winnerId)) {
|
|
834
|
+
throw new Error(`Winner is not significantly better than the runner-up for benchmark ${benchmarkId}`);
|
|
835
|
+
}
|
|
801
836
|
// Mark benchmark as completed
|
|
802
837
|
benchmark.status = 'completed';
|
|
803
838
|
benchmark.endTime = Date.now();
|
|
804
839
|
benchmark.winnerId = winner.winnerId;
|
|
805
840
|
// Promote winner in Evolution Pipeline
|
|
806
|
-
evolutionPipelineIntegration.promoteRule(winner.winnerId, `Won A/B benchmark ${benchmarkId} with ${
|
|
841
|
+
evolutionPipelineIntegration.promoteRule(winner.winnerId, `Won A/B benchmark ${benchmarkId} with heuristic score ${winner.heuristicScore.toFixed(3)} and runner-up significance`);
|
|
807
842
|
// Complete the variant test
|
|
808
843
|
evolutionPipelineIntegration.completeVariantTest(benchmarkId);
|
|
809
844
|
this.logEvent('winner_applied', `Applied winner ${winner.winnerId} for benchmark ${benchmarkId}`);
|
|
@@ -979,25 +1014,25 @@ export class ABBenchmarkingFramework {
|
|
|
979
1014
|
/**
|
|
980
1015
|
* Generate winner recommendation text
|
|
981
1016
|
*/
|
|
982
|
-
generateWinnerRecommendation(winner,
|
|
983
|
-
if (
|
|
1017
|
+
generateWinnerRecommendation(winner, heuristicScore, significantMetrics) {
|
|
1018
|
+
if (heuristicScore >= 0.95) {
|
|
984
1019
|
return `Strongly recommend applying ${winner.variantId}. ` +
|
|
985
|
-
`High
|
|
1020
|
+
`High heuristic score (${heuristicScore.toFixed(3)}) with significant improvements ` +
|
|
986
1021
|
`in: ${significantMetrics.length > 0 ? significantMetrics.join(', ') : 'overall performance'}.`;
|
|
987
1022
|
}
|
|
988
|
-
else if (
|
|
1023
|
+
else if (heuristicScore >= 0.8) {
|
|
989
1024
|
return `Recommend applying ${winner.variantId}. ` +
|
|
990
|
-
`Good
|
|
991
|
-
`Consider collecting more samples for higher
|
|
1025
|
+
`Good heuristic score (${heuristicScore.toFixed(3)}). ` +
|
|
1026
|
+
`Consider collecting more samples for a higher heuristic score.`;
|
|
992
1027
|
}
|
|
993
|
-
else if (
|
|
994
|
-
return `${winner.variantId} shows promise with moderate
|
|
995
|
-
`(${
|
|
1028
|
+
else if (heuristicScore >= 0.6) {
|
|
1029
|
+
return `${winner.variantId} shows promise with moderate heuristic score ` +
|
|
1030
|
+
`(${heuristicScore.toFixed(3)}). ` +
|
|
996
1031
|
`Recommend collecting more samples before applying.`;
|
|
997
1032
|
}
|
|
998
1033
|
else {
|
|
999
1034
|
return `Results are inconclusive. ${winner.variantId} is currently leading but ` +
|
|
1000
|
-
`
|
|
1035
|
+
`heuristic score (${heuristicScore.toFixed(3)}) is low. Continue collecting data.`;
|
|
1001
1036
|
}
|
|
1002
1037
|
}
|
|
1003
1038
|
/**
|
|
@@ -122,12 +122,13 @@ export class FleetInitEnhancer {
|
|
|
122
122
|
enableVectorEmbeddings: true,
|
|
123
123
|
});
|
|
124
124
|
// Find all source files
|
|
125
|
-
const glob = await import('
|
|
126
|
-
const files = await glob
|
|
125
|
+
const { glob } = await import('tinyglobby');
|
|
126
|
+
const files = await glob([
|
|
127
127
|
'**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py'
|
|
128
128
|
], {
|
|
129
129
|
cwd: this.projectRoot,
|
|
130
130
|
ignore: ['node_modules/**', 'dist/**', 'coverage/**', '.agentic-qe/**'],
|
|
131
|
+
expandDirectories: false,
|
|
131
132
|
});
|
|
132
133
|
console.log(chalk.gray(` Indexing ${files.length} files...`));
|
|
133
134
|
// Index files
|
|
@@ -200,12 +200,13 @@ export async function runCodeIntelligenceScan(projectPath) {
|
|
|
200
200
|
namespace: 'code-intelligence:kg',
|
|
201
201
|
enableVectorEmbeddings: true,
|
|
202
202
|
});
|
|
203
|
-
const glob = await import('
|
|
204
|
-
const files = await glob
|
|
203
|
+
const { glob } = await import('tinyglobby');
|
|
204
|
+
const files = await glob([
|
|
205
205
|
'**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py'
|
|
206
206
|
], {
|
|
207
207
|
cwd: projectPath,
|
|
208
208
|
ignore: ['node_modules/**', 'dist/**', 'coverage/**', '.agentic-qe/**'],
|
|
209
|
+
expandDirectories: false,
|
|
209
210
|
});
|
|
210
211
|
const result = await kgService.index({
|
|
211
212
|
paths: files.map(f => join(projectPath, f)),
|