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
|
@@ -104,7 +104,12 @@ function resolveArtifact(options) {
|
|
|
104
104
|
function resolveOracle(options) {
|
|
105
105
|
if (options.oracleFile) {
|
|
106
106
|
const raw = JSON.parse(fs.readFileSync(options.oracleFile, 'utf8'));
|
|
107
|
-
|
|
107
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)
|
|
108
|
+
|| !('passed' in raw) || typeof raw.passed !== 'boolean'
|
|
109
|
+
|| !('baselinePassed' in raw) || typeof raw.baselinePassed !== 'boolean') {
|
|
110
|
+
throw new Error('oracle-file must contain boolean passed and baselinePassed fields');
|
|
111
|
+
}
|
|
112
|
+
return { passed: raw.passed, baselinePassed: raw.baselinePassed };
|
|
108
113
|
}
|
|
109
114
|
if (options.oraclePassed === undefined && options.baselinePassed === undefined) {
|
|
110
115
|
return null;
|
package/dist/cli/index.js
CHANGED
|
@@ -22,7 +22,11 @@ import { ALL_DOMAINS } from '../shared/types/index.js';
|
|
|
22
22
|
import { applyCommandVerbosity, installCliLogGate, isCliLogLevelEnabled } from './log-gate.js';
|
|
23
23
|
import { LogLevel } from '../logging/index.js';
|
|
24
24
|
import { formatErrorForLog } from '../logging/redaction.js';
|
|
25
|
+
import { releaseCliProcessStores } from './process-store-cleanup.js';
|
|
25
26
|
installCliLogGate();
|
|
27
|
+
// Backstop for direct process.exit() paths as well as cleanupAndExit(). An
|
|
28
|
+
// in-process MCP owner still drains before exit; this callback is synchronous.
|
|
29
|
+
process.on('exit', releaseCliProcessStores);
|
|
26
30
|
// ============================================================================
|
|
27
31
|
// CLI State
|
|
28
32
|
// ============================================================================
|
|
@@ -180,11 +184,12 @@ async function cleanupAndExit(code = 0) {
|
|
|
180
184
|
}
|
|
181
185
|
}
|
|
182
186
|
catch { /* best effort */ }
|
|
183
|
-
|
|
187
|
+
releaseCliProcessStores();
|
|
188
|
+
// Force exit after synchronous store cleanup. Native NAPI handles (@ruvector/rvf-node and
|
|
184
189
|
// historically @ruvector/router, replaced by hnswlib-node in #399 /
|
|
185
190
|
// ADR-090) create ref'd event loop handles that prevent natural exit,
|
|
186
191
|
// and dynamic import() of cleanup modules can load more native
|
|
187
|
-
// bindings that make it worse.
|
|
192
|
+
// bindings that make it worse. Do not wait for asynchronous disposers here.
|
|
188
193
|
process.exit(code);
|
|
189
194
|
}
|
|
190
195
|
// ============================================================================
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release the CLI's process-wide stores without awaiting native work (#814).
|
|
3
|
+
* Each closer owns its handle; never remove a lock file by path. Synchronous
|
|
4
|
+
* cleanup also runs when Commander or another module calls process.exit().
|
|
5
|
+
*/
|
|
6
|
+
export declare function releaseCliProcessStores(): void;
|
|
7
|
+
//# sourceMappingURL=process-store-cleanup.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { resetSharedRvfAdapter } from '../integrations/ruvector/shared-rvf-adapter.js';
|
|
2
|
+
import { resetSharedRvfDualWriter } from '../integrations/ruvector/shared-rvf-dual-writer.js';
|
|
3
|
+
import { closeRegisteredStores } from '../kernel/process-lifecycle.js';
|
|
4
|
+
let released = false;
|
|
5
|
+
/**
|
|
6
|
+
* Release the CLI's process-wide stores without awaiting native work (#814).
|
|
7
|
+
* Each closer owns its handle; never remove a lock file by path. Synchronous
|
|
8
|
+
* cleanup also runs when Commander or another module calls process.exit().
|
|
9
|
+
*/
|
|
10
|
+
export function releaseCliProcessStores() {
|
|
11
|
+
if (released)
|
|
12
|
+
return;
|
|
13
|
+
released = true;
|
|
14
|
+
try {
|
|
15
|
+
resetSharedRvfDualWriter();
|
|
16
|
+
}
|
|
17
|
+
catch { /* keep closing other stores */ }
|
|
18
|
+
try {
|
|
19
|
+
resetSharedRvfAdapter();
|
|
20
|
+
}
|
|
21
|
+
catch { /* keep closing other stores */ }
|
|
22
|
+
try {
|
|
23
|
+
closeRegisteredStores();
|
|
24
|
+
}
|
|
25
|
+
catch { /* best effort on process exit */ }
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=process-store-cleanup.js.map
|
|
@@ -67,6 +67,8 @@ export interface CIPhaseResult {
|
|
|
67
67
|
}
|
|
68
68
|
/** Result of the full CI run */
|
|
69
69
|
export interface CIRunResult {
|
|
70
|
+
/** Invalid phase selections fail before execution and retain a fresh report. */
|
|
71
|
+
configurationError?: string;
|
|
70
72
|
config: string;
|
|
71
73
|
startedAt: Date;
|
|
72
74
|
completedAt: Date;
|
|
@@ -93,9 +95,7 @@ export interface CIConfigParseResult {
|
|
|
93
95
|
* Parse a .aqe-ci.yml file into a CIConfig.
|
|
94
96
|
*/
|
|
95
97
|
export declare function parseCIConfigFile(filePath: string): CIConfigParseResult;
|
|
96
|
-
/**
|
|
97
|
-
* Parse CI config YAML content.
|
|
98
|
-
*/
|
|
98
|
+
/** Parse CI YAML faithfully, validating typed fields before any phase executes. */
|
|
99
99
|
export declare function parseCIConfigContent(content: string, sourcePath?: string): CIConfigParseResult;
|
|
100
100
|
/**
|
|
101
101
|
* Get the default CI config (used when no .aqe-ci.yml exists).
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as path from 'path';
|
|
9
|
-
import {
|
|
9
|
+
import { isCollection, isScalar, parseDocument, visit } from 'yaml';
|
|
10
10
|
// ============================================================================
|
|
11
11
|
// Default Config
|
|
12
12
|
// ============================================================================
|
|
@@ -100,89 +100,223 @@ export function parseCIConfigFile(filePath) {
|
|
|
100
100
|
}
|
|
101
101
|
return parseCIConfigContent(content, filePath);
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
const YAML_MAX_LINES = 10000;
|
|
104
|
+
const YAML_MAX_LINE_LENGTH = 10000;
|
|
105
|
+
const YAML_MAX_DEPTH = 20;
|
|
106
|
+
const UNSAFE_YAML_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
107
|
+
function isRecord(value) {
|
|
108
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value) &&
|
|
109
|
+
(Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
110
|
+
}
|
|
111
|
+
/** Keep the previous parser's input bounds; reject unsafe expanded aliases too. */
|
|
112
|
+
function parseCIYAML(content) {
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
if (lines.length > YAML_MAX_LINES)
|
|
115
|
+
throw new Error(`YAML exceeds maximum allowed lines (${YAML_MAX_LINES})`);
|
|
116
|
+
if (lines.some(line => line.length > YAML_MAX_LINE_LENGTH)) {
|
|
117
|
+
throw new Error(`YAML exceeds maximum line length (${YAML_MAX_LINE_LENGTH})`);
|
|
118
|
+
}
|
|
119
|
+
const document = parseDocument(content, { prettyErrors: false, merge: true });
|
|
120
|
+
if (document.errors.length)
|
|
121
|
+
throw new Error(document.errors.map(error => error.message).join('; '));
|
|
122
|
+
visit(document, {
|
|
123
|
+
Collection: (_key, _node, ancestry) => {
|
|
124
|
+
if (ancestry.filter(isCollection).length >= YAML_MAX_DEPTH) {
|
|
125
|
+
throw new Error(`YAML exceeds maximum depth (${YAML_MAX_DEPTH})`);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
Pair: (_key, pair) => {
|
|
129
|
+
if (isScalar(pair.key) && UNSAFE_YAML_KEYS.has(String(pair.key.value))) {
|
|
130
|
+
throw new Error(`Unsafe YAML key: ${pair.key.value}`);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const parsed = document.contents === null ? {} : document.toJS({ maxAliasCount: 100 });
|
|
135
|
+
// Alias references may add nesting or cycles that the syntax tree does not show.
|
|
136
|
+
function checkExpanded(value, depth, ancestors) {
|
|
137
|
+
if (value === null || typeof value !== 'object')
|
|
138
|
+
return;
|
|
139
|
+
if (depth > YAML_MAX_DEPTH)
|
|
140
|
+
throw new Error(`YAML exceeds maximum depth (${YAML_MAX_DEPTH})`);
|
|
141
|
+
if (ancestors.has(value))
|
|
142
|
+
throw new Error('Cyclic YAML aliases are not supported');
|
|
143
|
+
ancestors.add(value);
|
|
144
|
+
for (const child of Object.values(value))
|
|
145
|
+
checkExpanded(child, depth + 1, ancestors);
|
|
146
|
+
ancestors.delete(value);
|
|
147
|
+
}
|
|
148
|
+
checkExpanded(parsed, 0, new Set());
|
|
149
|
+
if (!isRecord(parsed))
|
|
150
|
+
throw new Error('CI config must be a YAML mapping');
|
|
151
|
+
return parsed;
|
|
152
|
+
}
|
|
153
|
+
/** Parse CI YAML faithfully, validating typed fields before any phase executes. */
|
|
106
154
|
export function parseCIConfigContent(content, sourcePath) {
|
|
107
|
-
const errors = [];
|
|
108
155
|
let parsed;
|
|
109
156
|
try {
|
|
110
|
-
parsed =
|
|
157
|
+
parsed = parseCIYAML(content);
|
|
111
158
|
}
|
|
112
159
|
catch (err) {
|
|
113
160
|
return { success: false, errors: [`Invalid YAML: ${err}`] };
|
|
114
161
|
}
|
|
115
|
-
|
|
116
|
-
const config =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (parsed.output && typeof parsed.output === 'object') {
|
|
125
|
-
const out = parsed.output;
|
|
126
|
-
if (out.format)
|
|
127
|
-
config.output.format = out.format;
|
|
128
|
-
if (out.directory)
|
|
129
|
-
config.output.directory = out.directory;
|
|
130
|
-
if (out.combined_report !== undefined)
|
|
131
|
-
config.output.combinedReport = out.combined_report;
|
|
132
|
-
}
|
|
133
|
-
// Parse quality_gate section
|
|
134
|
-
if (parsed.quality_gate && typeof parsed.quality_gate === 'object') {
|
|
135
|
-
const qg = parsed.quality_gate;
|
|
136
|
-
if (qg.enforced !== undefined)
|
|
137
|
-
config.qualityGate.enforced = qg.enforced;
|
|
138
|
-
if (qg.thresholds && typeof qg.thresholds === 'object') {
|
|
139
|
-
const th = qg.thresholds;
|
|
140
|
-
if (th.coverage !== undefined)
|
|
141
|
-
config.qualityGate.thresholds.coverage = th.coverage;
|
|
142
|
-
if (th.security !== undefined)
|
|
143
|
-
config.qualityGate.thresholds.security = th.security;
|
|
144
|
-
if (th.quality !== undefined)
|
|
145
|
-
config.qualityGate.thresholds.quality = th.quality;
|
|
162
|
+
const errors = [];
|
|
163
|
+
const config = getDefaultCIConfig();
|
|
164
|
+
function readString(record, key, fallback, label) {
|
|
165
|
+
const value = record[key];
|
|
166
|
+
if (value === undefined)
|
|
167
|
+
return fallback;
|
|
168
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
169
|
+
errors.push(`${label} must be a non-empty string`);
|
|
170
|
+
return fallback;
|
|
146
171
|
}
|
|
172
|
+
return value;
|
|
147
173
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
function readBoolean(record, key, fallback, label) {
|
|
175
|
+
const value = record[key];
|
|
176
|
+
if (value === undefined)
|
|
177
|
+
return fallback;
|
|
178
|
+
if (typeof value !== 'boolean') {
|
|
179
|
+
errors.push(`${label} must be a boolean`);
|
|
180
|
+
return fallback;
|
|
181
|
+
}
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
if (parsed.version !== undefined) {
|
|
185
|
+
if (typeof parsed.version === 'number' && Number.isFinite(parsed.version))
|
|
186
|
+
config.version = String(parsed.version);
|
|
187
|
+
else
|
|
188
|
+
config.version = readString(parsed, 'version', config.version, 'version');
|
|
189
|
+
}
|
|
190
|
+
config.name = readString(parsed, 'name', config.name, 'name');
|
|
191
|
+
if (parsed.output !== undefined) {
|
|
192
|
+
if (!isRecord(parsed.output))
|
|
193
|
+
errors.push('output must be a mapping');
|
|
194
|
+
else {
|
|
195
|
+
config.output.format = readString(parsed.output, 'format', config.output.format, 'output.format');
|
|
196
|
+
config.output.directory = readString(parsed.output, 'directory', config.output.directory, 'output.directory');
|
|
197
|
+
config.output.combinedReport = readBoolean(parsed.output, 'combined_report', config.output.combinedReport, 'output.combined_report');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (parsed.quality_gate !== undefined) {
|
|
201
|
+
if (!isRecord(parsed.quality_gate))
|
|
202
|
+
errors.push('quality_gate must be a mapping');
|
|
203
|
+
else {
|
|
204
|
+
const gate = parsed.quality_gate;
|
|
205
|
+
config.qualityGate.enforced = readBoolean(gate, 'enforced', config.qualityGate.enforced, 'quality_gate.enforced');
|
|
206
|
+
if (gate.thresholds !== undefined) {
|
|
207
|
+
if (!isRecord(gate.thresholds))
|
|
208
|
+
errors.push('quality_gate.thresholds must be a mapping');
|
|
209
|
+
else {
|
|
210
|
+
for (const key of ['coverage', 'quality']) {
|
|
211
|
+
const value = gate.thresholds[key];
|
|
212
|
+
if (value === undefined)
|
|
213
|
+
continue;
|
|
214
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 100) {
|
|
215
|
+
errors.push(`quality_gate.thresholds.${key} must be a finite number between 0 and 100`);
|
|
216
|
+
}
|
|
217
|
+
else
|
|
218
|
+
config.qualityGate.thresholds[key] = value;
|
|
219
|
+
}
|
|
220
|
+
if (gate.thresholds.security !== undefined) {
|
|
221
|
+
const value = gate.thresholds.security;
|
|
222
|
+
if (typeof value !== 'string' || !['none', 'low', 'medium', 'high'].includes(value)) {
|
|
223
|
+
errors.push('quality_gate.thresholds.security must be none, low, medium or high');
|
|
224
|
+
}
|
|
225
|
+
else
|
|
226
|
+
config.qualityGate.thresholds.security = value;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
164
229
|
}
|
|
165
|
-
const phase = {
|
|
166
|
-
name: p.name,
|
|
167
|
-
type: p.type,
|
|
168
|
-
enabled: p.enabled !== false,
|
|
169
|
-
config: p.config || {},
|
|
170
|
-
continueOnFailure: p.continue_on_failure || false,
|
|
171
|
-
timeout: p.timeout || 300,
|
|
172
|
-
};
|
|
173
|
-
config.phases.push(phase);
|
|
174
230
|
}
|
|
175
231
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
232
|
+
if (parsed.phases !== undefined) {
|
|
233
|
+
config.phases = [];
|
|
234
|
+
if (!Array.isArray(parsed.phases))
|
|
235
|
+
errors.push('phases must be a sequence');
|
|
236
|
+
else
|
|
237
|
+
for (const [index, value] of parsed.phases.entries()) {
|
|
238
|
+
if (!isRecord(value)) {
|
|
239
|
+
errors.push(`Phase ${index + 1} must be a mapping`);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (value.name === undefined)
|
|
243
|
+
errors.push(`Phase ${index + 1} must have a name`);
|
|
244
|
+
const name = readString(value, 'name', '', `Phase ${index + 1} name`);
|
|
245
|
+
const validTypes = ['test', 'coverage', 'security', 'quality-gate', 'code-intelligence', 'custom'];
|
|
246
|
+
if (!validTypes.includes(value.type)) {
|
|
247
|
+
errors.push(`Phase "${name}" has invalid type "${value.type}". Valid: ${validTypes.join(', ')}`);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
let timeout = 300;
|
|
251
|
+
if (value.timeout !== undefined) {
|
|
252
|
+
if (typeof value.timeout !== 'number' || !Number.isFinite(value.timeout) || value.timeout <= 0) {
|
|
253
|
+
errors.push(`Phase "${name}" timeout must be a positive finite number`);
|
|
254
|
+
}
|
|
255
|
+
else
|
|
256
|
+
timeout = value.timeout;
|
|
257
|
+
}
|
|
258
|
+
if (value.config !== undefined && !isRecord(value.config))
|
|
259
|
+
errors.push(`Phase "${name}" config must be a mapping`);
|
|
260
|
+
config.phases.push({
|
|
261
|
+
name, type: value.type, timeout,
|
|
262
|
+
enabled: readBoolean(value, 'enabled', true, `Phase "${name}" enabled`),
|
|
263
|
+
continueOnFailure: readBoolean(value, 'continue_on_failure', false, `Phase "${name}" continue_on_failure`),
|
|
264
|
+
config: isRecord(value.config) ? { ...value.config } : {},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
179
267
|
}
|
|
180
|
-
if (config.phases.length === 0)
|
|
268
|
+
if (config.phases.length === 0)
|
|
181
269
|
errors.push('Config must have at least one phase');
|
|
270
|
+
// Paths in a file are relative to that file's project, not the caller's cwd.
|
|
271
|
+
// Resolve existing ancestors too so a symlink cannot bypass containment.
|
|
272
|
+
const root = path.resolve(sourcePath ? path.dirname(sourcePath) : process.cwd());
|
|
273
|
+
function canonicalAncestor(candidate) {
|
|
274
|
+
let ancestor = candidate;
|
|
275
|
+
const suffix = [];
|
|
276
|
+
while (!fs.existsSync(ancestor)) {
|
|
277
|
+
const parent = path.dirname(ancestor);
|
|
278
|
+
if (parent === ancestor)
|
|
279
|
+
break;
|
|
280
|
+
suffix.unshift(path.basename(ancestor));
|
|
281
|
+
ancestor = parent;
|
|
282
|
+
}
|
|
283
|
+
return path.resolve(fs.realpathSync(ancestor), ...suffix);
|
|
182
284
|
}
|
|
183
|
-
|
|
184
|
-
|
|
285
|
+
function containedPath(value, label) {
|
|
286
|
+
if (typeof value !== 'string' || !value.trim() || value.includes('\0')) {
|
|
287
|
+
errors.push(`${label} must be a non-empty relative path`);
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
const resolved = path.resolve(root, value);
|
|
291
|
+
const relative = path.relative(root, resolved);
|
|
292
|
+
if (path.isAbsolute(value) || path.win32.isAbsolute(value) ||
|
|
293
|
+
relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
294
|
+
errors.push(`${label} must stay inside the project and use a relative path`);
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const realRelative = path.relative(canonicalAncestor(root), canonicalAncestor(resolved));
|
|
299
|
+
if (realRelative === '..' || realRelative.startsWith(`..${path.sep}`) || path.isAbsolute(realRelative)) {
|
|
300
|
+
errors.push(`${label} must stay inside the project (symlink escapes are not allowed)`);
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
errors.push(`${label} cannot be resolved safely: ${error}`);
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
return sourcePath ? resolved : value;
|
|
309
|
+
}
|
|
310
|
+
config.output.directory = containedPath(config.output.directory, 'output.directory') ?? config.output.directory;
|
|
311
|
+
for (const phase of config.phases) {
|
|
312
|
+
if (phase.config.target !== undefined) {
|
|
313
|
+
const target = containedPath(phase.config.target, `Phase "${phase.name}" config.target`);
|
|
314
|
+
if (target !== undefined)
|
|
315
|
+
phase.config.target = target;
|
|
316
|
+
}
|
|
185
317
|
}
|
|
318
|
+
if (errors.length > 0)
|
|
319
|
+
return { success: false, config, errors };
|
|
186
320
|
return { success: true, config, errors: [], configPath: sourcePath };
|
|
187
321
|
}
|
|
188
322
|
/**
|
|
@@ -694,33 +694,50 @@ function detectCircularDependencies(stages) {
|
|
|
694
694
|
* Validate cron expression (basic validation)
|
|
695
695
|
*/
|
|
696
696
|
export function isValidCronExpression(expression) {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
/^(\*|
|
|
710
|
-
/^(\*|
|
|
711
|
-
/^(\*|[1-9]|
|
|
712
|
-
/^(\*|[
|
|
697
|
+
return parseCronFields(expression) !== undefined;
|
|
698
|
+
}
|
|
699
|
+
/** Parse the existing numeric five-field grammar and its four named aliases. */
|
|
700
|
+
function parseCronFields(expression) {
|
|
701
|
+
const normalized = Object.hasOwn(CRON_PATTERNS, expression)
|
|
702
|
+
? CRON_PATTERNS[expression]
|
|
703
|
+
: expression;
|
|
704
|
+
const parts = normalized.trim().split(/\s+/);
|
|
705
|
+
if (parts.length !== 5)
|
|
706
|
+
return undefined;
|
|
707
|
+
const bounds = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]];
|
|
708
|
+
const syntax = [
|
|
709
|
+
/^(\*|[0-5]?\d)(-[0-5]?\d)?(\/\d+)?$/,
|
|
710
|
+
/^(\*|1?\d|2[0-3])(-\d+)?(\/\d+)?$/,
|
|
711
|
+
/^(\*|[1-9]|[12]\d|3[01])(-\d+)?(\/\d+)?$/,
|
|
712
|
+
/^(\*|[1-9]|1[0-2])(-\d+)?(\/\d+)?$/,
|
|
713
|
+
/^(\*|[0-7])(-[0-7])?(\/\d+)?$/,
|
|
713
714
|
];
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
715
|
+
const fields = [];
|
|
716
|
+
for (let index = 0; index < parts.length; index++) {
|
|
717
|
+
const [minimum, maximum] = bounds[index];
|
|
718
|
+
const values = new Set();
|
|
719
|
+
for (const item of parts[index].split(',')) {
|
|
720
|
+
if (!syntax[index].test(item))
|
|
721
|
+
return undefined;
|
|
722
|
+
const match = /^(\*|\d+)(?:-(\d+))?(?:\/(\d+))?$/.exec(item);
|
|
723
|
+
if (!match || (match[1] === '*' && match[2] !== undefined))
|
|
724
|
+
return undefined;
|
|
725
|
+
const start = match[1] === '*' ? minimum : Number(match[1]);
|
|
726
|
+
const end = match[2] !== undefined ? Number(match[2])
|
|
727
|
+
: match[1] === '*' || match[3] !== undefined ? maximum : start;
|
|
728
|
+
const step = match[3] === undefined ? 1 : Number(match[3]);
|
|
729
|
+
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) ||
|
|
730
|
+
!Number.isSafeInteger(step) || step <= 0 ||
|
|
731
|
+
start < minimum || end > maximum || start > end)
|
|
732
|
+
return undefined;
|
|
733
|
+
for (let value = start; value <= end; value += step) {
|
|
734
|
+
values.add(index === 4 && value === 7 ? 0 : value);
|
|
720
735
|
}
|
|
721
736
|
}
|
|
737
|
+
fields.push(values);
|
|
722
738
|
}
|
|
723
|
-
|
|
739
|
+
// Cronie records DOM_STAR/DOW_STAR from the first character, before parsing lists.
|
|
740
|
+
return { fields: fields, wildcardDay: parts[2].startsWith('*') || parts[4].startsWith('*') };
|
|
724
741
|
}
|
|
725
742
|
/**
|
|
726
743
|
* Parse cron expression to human-readable string
|
|
@@ -773,40 +790,39 @@ export function describeCronSchedule(expression) {
|
|
|
773
790
|
* Calculate next run time from cron expression
|
|
774
791
|
*/
|
|
775
792
|
export function calculateNextRun(cronExpression, fromDate = new Date()) {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
if (nextRun <= fromDate) {
|
|
802
|
-
nextRun.setHours(nextRun.getHours() + 1);
|
|
793
|
+
const parsed = parseCronFields(cronExpression);
|
|
794
|
+
if (!parsed)
|
|
795
|
+
throw new Error(`Invalid cron expression: ${cronExpression}`);
|
|
796
|
+
if (!Number.isFinite(fromDate.getTime()))
|
|
797
|
+
throw new Error('Invalid schedule start date');
|
|
798
|
+
const [minutes, hours, days, months, weekdays] = parsed.fields;
|
|
799
|
+
// Preserve the existing host-local timezone. Advance elapsed minutes to
|
|
800
|
+
// skip absent DST times and inspect both occurrences of repeated times.
|
|
801
|
+
let candidate = new Date(Math.floor(fromDate.getTime() / 60000) * 60000 + 60000);
|
|
802
|
+
const deadline = new Date(fromDate);
|
|
803
|
+
deadline.setFullYear(fromDate.getFullYear() + 400);
|
|
804
|
+
// A complete Gregorian cycle contains 146097 days and repeats weekdays.
|
|
805
|
+
// Near the Date maximum a full cycle is not representable: clamp the
|
|
806
|
+
// search to that finite boundary and report the limitation on exhaustion.
|
|
807
|
+
const deadlineMs = Number.isFinite(deadline.getTime())
|
|
808
|
+
? deadline.getTime() : 8_640_000_000_000_000;
|
|
809
|
+
while (Number.isFinite(candidate.getTime()) && candidate.getTime() <= deadlineMs) {
|
|
810
|
+
const dayMatches = days.has(candidate.getDate());
|
|
811
|
+
const weekdayMatches = weekdays.has(candidate.getDay());
|
|
812
|
+
const calendarMatches = months.has(candidate.getMonth() + 1) &&
|
|
813
|
+
(parsed.wildcardDay ? dayMatches && weekdayMatches : dayMatches || weekdayMatches);
|
|
814
|
+
if (!calendarMatches) {
|
|
815
|
+
// Skip a nonmatching local calendar day instead of scanning its minutes.
|
|
816
|
+
candidate.setHours(24, 0, 0, 0);
|
|
817
|
+
continue;
|
|
803
818
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
819
|
+
if (hours.has(candidate.getHours()) && minutes.has(candidate.getMinutes()))
|
|
820
|
+
return candidate;
|
|
821
|
+
candidate = new Date(candidate.getTime() + 60000);
|
|
822
|
+
}
|
|
823
|
+
// An impossible date such as February 31 must not spin indefinitely or
|
|
824
|
+
// silently become a daily schedule. Leap-day/weekday intersections may
|
|
825
|
+
// exceed a leap-day-only horizon, so search one complete Gregorian cycle.
|
|
826
|
+
throw new Error(`No matching cron date within a 400-year Gregorian cycle and the supported Date range: ${cronExpression}`);
|
|
811
827
|
}
|
|
812
828
|
//# sourceMappingURL=workflow-parser.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Detection priority by project type:
|
|
8
8
|
* 1. Node.js: vitest > jest > fallback pattern matching
|
|
9
|
-
* 2. Rust: cargo test --list
|
|
9
|
+
* 2. Rust: cargo test -- --list
|
|
10
10
|
* 3. Python: pytest --collect-only
|
|
11
11
|
* 4. Go: go test -list
|
|
12
12
|
*
|
|
@@ -262,11 +262,11 @@ function countJestTests(projectPath, config) {
|
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
264
264
|
* Count tests using Cargo (Rust)
|
|
265
|
-
* Uses `cargo test --list` for accurate test enumeration
|
|
265
|
+
* Uses `cargo test -- --list` for accurate test enumeration
|
|
266
266
|
*/
|
|
267
267
|
function countCargoTests(projectPath, config) {
|
|
268
268
|
try {
|
|
269
|
-
const output = execSync('cargo test --list', {
|
|
269
|
+
const output = execSync('cargo test -- --list', {
|
|
270
270
|
cwd: projectPath,
|
|
271
271
|
encoding: 'utf-8',
|
|
272
272
|
timeout: config.timeout,
|
|
@@ -310,13 +310,14 @@ function countPytestTests(projectPath, config) {
|
|
|
310
310
|
// Count test function lines (format: "tests/test_foo.py::test_bar")
|
|
311
311
|
const testLines = output.split('\n').filter(line => line.includes('::test_') || line.includes('::Test'));
|
|
312
312
|
const total = testLines.length;
|
|
313
|
-
//
|
|
314
|
-
|
|
315
|
-
const integration = testLines.filter(t => t.includes('integration') || t.includes('_integration')).length;
|
|
313
|
+
// Match fallback classification precedence so every collected test belongs
|
|
314
|
+
// to exactly one category, even when its path names multiple categories.
|
|
316
315
|
const e2e = testLines.filter(t => t.includes('e2e') || t.includes('end_to_end')).length;
|
|
316
|
+
const integration = testLines.filter(t => !t.includes('e2e') && !t.includes('end_to_end') && t.includes('integration')).length;
|
|
317
|
+
const unit = total - integration - e2e;
|
|
317
318
|
return {
|
|
318
319
|
total,
|
|
319
|
-
unit
|
|
320
|
+
unit,
|
|
320
321
|
integration,
|
|
321
322
|
e2e,
|
|
322
323
|
source: 'pytest',
|
|
@@ -343,13 +344,14 @@ function countGoTests(projectPath, config) {
|
|
|
343
344
|
encoding: 'utf-8',
|
|
344
345
|
timeout: config.timeout,
|
|
345
346
|
});
|
|
346
|
-
//
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const integration = testLines.filter(t => t.includes('Integration')).length;
|
|
347
|
+
// Benchmarks and examples are listed too, but are not included in the
|
|
348
|
+
// test total. Apply that same selection to every category.
|
|
349
|
+
const testLines = output.split('\n').filter(line => line.startsWith('Test'));
|
|
350
|
+
const total = testLines.length;
|
|
351
|
+
// Use disjoint categories, with e2e taking precedence over integration.
|
|
352
352
|
const e2e = testLines.filter(t => t.includes('E2E')).length;
|
|
353
|
+
const integration = testLines.filter(t => !t.includes('E2E') && t.includes('Integration')).length;
|
|
354
|
+
const unit = total - integration - e2e;
|
|
353
355
|
return {
|
|
354
356
|
total,
|
|
355
357
|
unit,
|
|
@@ -474,8 +476,8 @@ function countTestsInPythonFile(filePath) {
|
|
|
474
476
|
const content = readFileSync(filePath, 'utf-8');
|
|
475
477
|
// Count def test_ functions and async def test_ functions
|
|
476
478
|
const funcMatches = content.match(/\bdef\s+test_\w+\s*\(/g) || [];
|
|
477
|
-
|
|
478
|
-
return funcMatches.length
|
|
479
|
+
// The def pattern also matches async def; every declaration counts once.
|
|
480
|
+
return funcMatches.length;
|
|
479
481
|
}
|
|
480
482
|
catch {
|
|
481
483
|
return 0;
|
|
@@ -33,7 +33,9 @@ export declare function loadQualityEvidence(memory: MemoryBackend, options?: {
|
|
|
33
33
|
now?: number;
|
|
34
34
|
maxAgeMs?: number;
|
|
35
35
|
}): Promise<QualityEvidenceValues>;
|
|
36
|
-
export declare function evaluateQualityEvidence(values: QualityEvidenceValues
|
|
36
|
+
export declare function evaluateQualityEvidence(values: QualityEvidenceValues, thresholds?: {
|
|
37
|
+
coverage?: number;
|
|
38
|
+
}): {
|
|
37
39
|
passed: boolean;
|
|
38
40
|
checks: EvaluatedQualityCheck[];
|
|
39
41
|
recommendations: string[];
|