agentic-qe 3.15.3 → 3.15.5
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/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +139 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/bridge/captured-experience-bridge.js +7 -9
- package/dist/cli/bundle.js +5 -5
- package/dist/cli/chunks/adapter-EGIPTX5H.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-CYG3PKHH.js → agent-booster-wasm-CCTTGCQS.js} +2 -2
- package/dist/cli/chunks/{agent-handler-WTFYFZKL.js → agent-handler-DHYUF3NX.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-G6WE3ZXU.js → agent-memory-branch-642W7CYX.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-WP4GCBDT.js +2 -0
- package/dist/cli/chunks/{arena-S72QW44C.js → arena-MUCC7UUN.js} +4 -4
- package/dist/cli/chunks/{arena-ZFXQEVUQ.js → arena-NW2JVAFY.js} +2 -2
- package/dist/cli/chunks/{audit-KPYIEQJ3.js → audit-VKQTZJAA.js} +3 -3
- package/dist/cli/chunks/base-6ORFD62I.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-L2M3TI5D.js → better-sqlite3-7ZUFVWLQ.js} +2 -2
- package/dist/cli/chunks/{brain-handler-FHKLQTB4.js → brain-handler-7LKAWSBI.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-3BSHOPOK.js → branch-enumerator-HUNXJKM4.js} +2 -2
- package/dist/cli/chunks/{browser-JUIJPL6Y.js → browser-ZSZEYUDP.js} +2 -2
- package/dist/cli/chunks/browser-workflow-PIXGERWP.js +2 -0
- package/dist/cli/chunks/{chunk-VHBZADYK.js → chunk-2KWI3MT3.js} +2 -2
- package/dist/cli/chunks/{chunk-35VDOH4Y.js → chunk-2WFTZSRT.js} +1 -1
- package/dist/cli/chunks/{chunk-UTALYUMW.js → chunk-2XYTS2WY.js} +2 -2
- package/dist/cli/chunks/{chunk-OTTTHNIT.js → chunk-35MDATQE.js} +1 -1
- package/dist/cli/chunks/{chunk-Z7UGEQ4G.js → chunk-3AYYGR6W.js} +1 -1
- package/dist/cli/chunks/{chunk-LPZAB3N2.js → chunk-3DTEQHFB.js} +3 -3
- package/dist/cli/chunks/{chunk-YHZGFWJE.js → chunk-3OAQPN2N.js} +2 -2
- package/dist/cli/chunks/{chunk-PUPEKA2J.js → chunk-3QD7U3FY.js} +2 -2
- package/dist/cli/chunks/{chunk-3Y4GX5FL.js → chunk-3SH23PS3.js} +2 -2
- package/dist/cli/chunks/{chunk-NT6FYFJA.js → chunk-3YASZPLO.js} +2 -2
- package/dist/cli/chunks/{chunk-QVNMTMDJ.js → chunk-3YNP33GB.js} +2 -2
- package/dist/cli/chunks/{chunk-AQTQ24SK.js → chunk-47GEI2LT.js} +3 -3
- package/dist/cli/chunks/{chunk-JJBTM4JO.js → chunk-4AZP7ZCW.js} +2 -2
- package/dist/cli/chunks/{chunk-6W6GZHQA.js → chunk-4PT5KNXL.js} +4 -4
- package/dist/cli/chunks/{chunk-EQGT4VLC.js → chunk-4UXPDV7E.js} +1 -1
- package/dist/cli/chunks/{chunk-SP2JO53K.js → chunk-4XSCZVON.js} +2 -2
- package/dist/cli/chunks/{chunk-DWG4TN6A.js → chunk-5BOZCMXZ.js} +1 -1
- package/dist/cli/chunks/{chunk-PBUWNMZ2.js → chunk-644DFAGS.js} +1 -1
- package/dist/cli/chunks/{chunk-6EQDA4EC.js → chunk-663ZFPUL.js} +2 -2
- package/dist/cli/chunks/{chunk-HU474NXP.js → chunk-6JFGB2JB.js} +1 -1
- package/dist/cli/chunks/{chunk-AS54N3H7.js → chunk-6LG5UEQE.js} +2 -2
- package/dist/cli/chunks/{chunk-3UUMGWHW.js → chunk-6UYN5PHA.js} +4 -4
- package/dist/cli/chunks/{chunk-RQUSJEON.js → chunk-6ZIDZ4TJ.js} +2 -2
- package/dist/cli/chunks/{chunk-P36IODAM.js → chunk-7BIYJRQJ.js} +2 -2
- package/dist/cli/chunks/{chunk-5LEUEWJY.js → chunk-7EZLOC4K.js} +2 -2
- package/dist/cli/chunks/{chunk-EBIMVSPH.js → chunk-7YB2KELI.js} +2 -2
- package/dist/cli/chunks/{chunk-YCGU2LI7.js → chunk-A2WOQO2N.js} +2 -2
- package/dist/cli/chunks/{chunk-HSR53REE.js → chunk-A337MD3C.js} +2 -2
- package/dist/cli/chunks/{chunk-ZJW4HRUA.js → chunk-A5J4XJS6.js} +1 -1
- package/dist/cli/chunks/{chunk-POTVF6BY.js → chunk-AQN5EDBM.js} +1 -1
- package/dist/cli/chunks/{chunk-X335K4SU.js → chunk-AUZXRFOX.js} +2 -2
- package/dist/cli/chunks/{chunk-WI7I6LMM.js → chunk-B2UHTA4Q.js} +1 -1
- package/dist/cli/chunks/{chunk-W7EHNX3Y.js → chunk-BBL6YXD3.js} +2 -2
- package/dist/cli/chunks/chunk-BJ5P4IV2.js +2 -0
- package/dist/cli/chunks/{chunk-RDTR43YN.js → chunk-BMWAWZAN.js} +2 -2
- package/dist/cli/chunks/chunk-BO4PKNYP.js +102 -0
- package/dist/cli/chunks/{chunk-KGS6H2HB.js → chunk-BY646JOM.js} +2 -2
- package/dist/cli/chunks/{chunk-PPA53NJB.js → chunk-BYXNHGQC.js} +2 -2
- package/dist/cli/chunks/{chunk-RRSZ27A7.js → chunk-BZFT4QDQ.js} +2 -2
- package/dist/cli/chunks/{chunk-M3ACHBC7.js → chunk-CFPR24YK.js} +2 -2
- package/dist/cli/chunks/{chunk-SRDECRTL.js → chunk-CQMHDAJS.js} +2 -2
- package/dist/cli/chunks/{chunk-WW4RJ6BH.js → chunk-CR2JUANW.js} +2 -2
- package/dist/cli/chunks/{chunk-QSVNVDA5.js → chunk-CXOXUBYU.js} +1 -1
- package/dist/cli/chunks/chunk-D3G2NN7F.js +741 -0
- package/dist/cli/chunks/{chunk-RGD2CG23.js → chunk-DEGWCUMY.js} +2 -2
- package/dist/cli/chunks/{chunk-AEL4XJGJ.js → chunk-DFPL5N3Q.js} +2 -2
- package/dist/cli/chunks/{chunk-FTUNC4EI.js → chunk-DL5JENWD.js} +3 -3
- package/dist/cli/chunks/{chunk-DH5NWHH2.js → chunk-DLY4YEN3.js} +2 -2
- package/dist/cli/chunks/{chunk-V5NYGDSX.js → chunk-DPV33C77.js} +2 -2
- package/dist/cli/chunks/{chunk-A5H7TF7C.js → chunk-DPYDUKVZ.js} +2 -2
- package/dist/cli/chunks/{chunk-4JVVVKAX.js → chunk-DTJODGCE.js} +2 -2
- package/dist/cli/chunks/{chunk-6AKJ73X3.js → chunk-DWZI3IVB.js} +2 -2
- package/dist/cli/chunks/{chunk-7UUSV2SK.js → chunk-DXVZBJE4.js} +1 -1
- package/dist/cli/chunks/{chunk-FPFGN2Z5.js → chunk-E4VIVMDL.js} +2 -2
- package/dist/cli/chunks/{chunk-GPZH6OPP.js → chunk-EAYQCBXL.js} +3 -3
- package/dist/cli/chunks/{chunk-7SWHW5AC.js → chunk-EOR3RECZ.js} +20 -20
- package/dist/cli/chunks/chunk-ERGWWI4Y.js +3 -0
- package/dist/cli/chunks/{chunk-XXW4KFBB.js → chunk-EUEHBERE.js} +1 -1
- package/dist/cli/chunks/{chunk-VUBLJBHQ.js → chunk-EVCFUYYK.js} +2 -2
- package/dist/cli/chunks/{chunk-YQ3ZW47V.js → chunk-FBEXG4HD.js} +2 -2
- package/dist/cli/chunks/{chunk-HV3ZVUHO.js → chunk-FE3AIZI6.js} +1 -1
- package/dist/cli/chunks/{chunk-TBVPNN65.js → chunk-FHUJCVT3.js} +2 -2
- package/dist/cli/chunks/{chunk-3ZTBV6M3.js → chunk-FNAYDITO.js} +1 -1
- package/dist/cli/chunks/{chunk-JVQK6NGI.js → chunk-FQKEZVN6.js} +2 -2
- package/dist/cli/chunks/{chunk-MUSYQF53.js → chunk-FWYJ6UDX.js} +2 -2
- package/dist/cli/chunks/{chunk-QUXX2DP7.js → chunk-GGDKOJVF.js} +2 -2
- package/dist/cli/chunks/{chunk-VRT736E3.js → chunk-GKPRECLL.js} +2 -2
- package/dist/cli/chunks/{chunk-3MNKYCLH.js → chunk-GRIPCYW5.js} +1 -1
- package/dist/cli/chunks/{chunk-DE3QNPTG.js → chunk-GTSOFCMQ.js} +1 -1
- package/dist/cli/chunks/{chunk-2MEWIXW4.js → chunk-HBYQYGXP.js} +2 -2
- package/dist/cli/chunks/{chunk-RWLOERKK.js → chunk-HGBJ2QQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-4IYHYHTG.js → chunk-HIUNCO2W.js} +2 -2
- package/dist/cli/chunks/{chunk-WSUYEVSY.js → chunk-HLFDC4SF.js} +1 -1
- package/dist/cli/chunks/{chunk-OKNMZLGB.js → chunk-HPLMX62I.js} +2 -2
- package/dist/cli/chunks/{chunk-Z7JPWXW2.js → chunk-IHFUEPZH.js} +2 -2
- package/dist/cli/chunks/{chunk-2TBHPYOU.js → chunk-IJ2EXSMO.js} +2 -2
- package/dist/cli/chunks/{chunk-SKHP5WUP.js → chunk-IJOFZBXD.js} +2 -2
- package/dist/cli/chunks/{chunk-YW4GM36K.js → chunk-JANLATHN.js} +2 -2
- package/dist/cli/chunks/{chunk-BDKQSEEY.js → chunk-JCC7QEKZ.js} +1 -1
- package/dist/cli/chunks/{chunk-7PDC4SKR.js → chunk-JI77KJP7.js} +1 -1
- package/dist/cli/chunks/{chunk-LEB6O2IN.js → chunk-JNMUVBAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZI6NJEBY.js → chunk-JYY7AYGA.js} +1 -1
- package/dist/cli/chunks/{chunk-ASUXS4N4.js → chunk-KHCALIFP.js} +2 -2
- package/dist/cli/chunks/{chunk-ED5HUPUR.js → chunk-KJ3KBP24.js} +2 -2
- package/dist/cli/chunks/{chunk-YTRGMILO.js → chunk-KZVJW2SD.js} +2 -2
- package/dist/cli/chunks/chunk-L336HFFE.js +2 -0
- package/dist/cli/chunks/{chunk-GJB3LPCS.js → chunk-L375O3CZ.js} +2 -2
- package/dist/cli/chunks/{chunk-WQZBKLAG.js → chunk-L6SVCNXK.js} +1 -1
- package/dist/cli/chunks/{chunk-YGKU2QRC.js → chunk-LNO5IWGH.js} +1 -1
- package/dist/cli/chunks/{chunk-APV5UWTU.js → chunk-LRASYSGV.js} +2 -2
- package/dist/cli/chunks/{chunk-HW4V7BVV.js → chunk-MB4VFAJC.js} +2 -2
- package/dist/cli/chunks/{chunk-366IBPZB.js → chunk-MNQ36MAF.js} +2 -2
- package/dist/cli/chunks/{chunk-7TW5UGDP.js → chunk-MQGEZA2A.js} +2 -2
- package/dist/cli/chunks/{chunk-CFXROOIU.js → chunk-MS3Z2CP5.js} +2 -2
- package/dist/cli/chunks/{chunk-4TM5K6EZ.js → chunk-N2TJNIHA.js} +2 -2
- package/dist/cli/chunks/{chunk-DLA3EHKJ.js → chunk-NF6AFIAX.js} +1 -1
- package/dist/cli/chunks/{chunk-2GJJGO5D.js → chunk-NLDFNAOS.js} +2 -2
- package/dist/cli/chunks/{chunk-UCSGZVJX.js → chunk-NMJVG22Z.js} +1 -1
- package/dist/cli/chunks/{chunk-WSND64RL.js → chunk-OGYWWZU7.js} +2 -2
- package/dist/cli/chunks/{chunk-FXTZXZCU.js → chunk-ONCH5AXU.js} +3 -3
- package/dist/cli/chunks/{chunk-M3ONCPSU.js → chunk-OQDC7GCM.js} +2 -2
- package/dist/cli/chunks/{chunk-P6EGRAQG.js → chunk-ORTBRO7F.js} +2 -2
- package/dist/cli/chunks/{chunk-D6PUDLJ4.js → chunk-OU4ZAWCC.js} +2 -2
- package/dist/cli/chunks/{chunk-AOZJ6UUZ.js → chunk-OW42F2TX.js} +2 -2
- package/dist/cli/chunks/{chunk-4N7YXTV3.js → chunk-PCCIZFD7.js} +1 -1
- package/dist/cli/chunks/{chunk-OT6SOPAL.js → chunk-PDPEMBFV.js} +2 -2
- package/dist/cli/chunks/{chunk-A3IQU2ND.js → chunk-PHAQWAEV.js} +2 -2
- package/dist/cli/chunks/{chunk-XV2TIODR.js → chunk-PHP4UJYP.js} +1 -1
- package/dist/cli/chunks/{chunk-POVP6O6K.js → chunk-PURHGLEC.js} +1 -1
- package/dist/cli/chunks/{chunk-5QUOM357.js → chunk-PVAE65B4.js} +1 -1
- package/dist/cli/chunks/{chunk-ZL2GYU7H.js → chunk-QPV3OKX2.js} +2 -2
- package/dist/cli/chunks/{chunk-B23ROYST.js → chunk-QXY3IRBW.js} +21 -21
- package/dist/cli/chunks/chunk-RCXMUEZN.js +3 -0
- package/dist/cli/chunks/{chunk-HVIFA73X.js → chunk-RMJ7PJOS.js} +2 -2
- package/dist/cli/chunks/{chunk-OGARNKLS.js → chunk-RUJLVJDE.js} +2 -2
- package/dist/cli/chunks/{chunk-UGNTLSBL.js → chunk-RUSLEOMC.js} +2 -2
- package/dist/cli/chunks/chunk-SAPIRK2G.js +3 -0
- package/dist/cli/chunks/{chunk-F5BREV2Q.js → chunk-SDWMLT7B.js} +5 -5
- package/dist/cli/chunks/{chunk-A6PII4R4.js → chunk-SEZLYRCS.js} +1 -1
- package/dist/cli/chunks/{chunk-RWQDRPN5.js → chunk-TDLKXLJC.js} +2 -2
- package/dist/cli/chunks/{chunk-YJH7UFA2.js → chunk-U4TV75AC.js} +2 -2
- package/dist/cli/chunks/{chunk-34Y4CIHD.js → chunk-U6OVPMQX.js} +2 -2
- package/dist/cli/chunks/{chunk-L6OSEWOS.js → chunk-UE22ODHN.js} +1 -1
- package/dist/cli/chunks/{chunk-IARE5VGI.js → chunk-UXZEVIFX.js} +1 -1
- package/dist/cli/chunks/{chunk-OMHISPPF.js → chunk-V7GNUVYI.js} +1 -1
- package/dist/cli/chunks/{chunk-HR7RL4PB.js → chunk-VCKDVOPD.js} +2 -2
- package/dist/cli/chunks/{chunk-UZDTRCVU.js → chunk-VH3EB6ZG.js} +2 -2
- package/dist/cli/chunks/{chunk-6V6XVGCL.js → chunk-VLOIEVER.js} +3 -3
- package/dist/cli/chunks/{chunk-XTGVGZ4J.js → chunk-VML4SG3X.js} +3 -3
- package/dist/cli/chunks/{chunk-6TYTBQPV.js → chunk-VRJPH3LG.js} +2 -2
- package/dist/cli/chunks/{chunk-5WOBFN2T.js → chunk-VYDNLQJN.js} +2 -2
- package/dist/cli/chunks/{chunk-U5AVZ3T2.js → chunk-W3ZGNNDV.js} +1 -1
- package/dist/cli/chunks/{chunk-YGEC3PSD.js → chunk-WC47GICZ.js} +2 -2
- package/dist/cli/chunks/{chunk-WLOHTLHO.js → chunk-WLIYWBQR.js} +2 -2
- package/dist/cli/chunks/{chunk-I5VJ3FBC.js → chunk-WN55MNZ2.js} +2 -2
- package/dist/cli/chunks/chunk-WOZIXXY5.js +7 -0
- package/dist/cli/chunks/{chunk-X33LID2T.js → chunk-WR64BKUE.js} +1 -1
- package/dist/cli/chunks/{chunk-VGN46ZT4.js → chunk-WT3JC4A6.js} +2 -2
- package/dist/cli/chunks/{chunk-VOKIUF7I.js → chunk-X52TMBHU.js} +1 -1
- package/dist/cli/chunks/{chunk-ZATQLTYL.js → chunk-XIE7OHML.js} +1 -1
- package/dist/cli/chunks/{chunk-BO43BGHX.js → chunk-XNEEYXR2.js} +2 -2
- package/dist/cli/chunks/{chunk-KCBCYF7M.js → chunk-XNHB6TLC.js} +2 -2
- package/dist/cli/chunks/{chunk-VX7CQUO7.js → chunk-XQRE2HWM.js} +2 -2
- package/dist/cli/chunks/{chunk-CNQUU6CF.js → chunk-Y2E3IJ53.js} +2 -2
- package/dist/cli/chunks/{chunk-2M75CW5Q.js → chunk-Y2WMPEUP.js} +2 -2
- package/dist/cli/chunks/{chunk-WTMLRMKW.js → chunk-Y7GPLOXB.js} +2 -2
- package/dist/cli/chunks/{chunk-O66D4NEJ.js → chunk-YINFES3E.js} +2 -2
- package/dist/cli/chunks/{chunk-CF3BPD2R.js → chunk-ZLBBX24Q.js} +163 -164
- package/dist/cli/chunks/{chunk-S7D4GD7H.js → chunk-ZT3GUYM5.js} +2 -2
- package/dist/cli/chunks/{chunk-D5V6C3XG.js → chunk-ZTC5FBL6.js} +3 -3
- package/dist/cli/chunks/ci-KP4GZKJ7.js +81 -0
- package/dist/cli/chunks/ci-config-XDDZOOEI.js +2 -0
- package/dist/cli/chunks/{ci-output-DPHTFIGX.js → ci-output-7ZUQI4U6.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-PQ65VU2M.js → circuit-breaker-ALXKCFAL.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-GKHVO7AD.js → claude-flow-setup-RL7K2NI2.js} +2 -2
- package/dist/cli/chunks/client-C3KHVRM6.js +2 -0
- package/dist/cli/chunks/{cline-installer-HWMQZJ64.js → cline-installer-2Z2QQKC3.js} +2 -2
- package/dist/cli/chunks/{code-OTY7BF3D.js → code-QSZTDINQ.js} +4 -4
- package/dist/cli/chunks/{code-index-extractor-FG3TMHHR.js → code-index-extractor-5CGR5D3Y.js} +2 -2
- package/dist/cli/chunks/{codex-installer-63JARKKS.js → codex-installer-7JLSEDE5.js} +2 -2
- package/dist/cli/chunks/{completions-4ZHONFML.js → completions-U4NBSXEB.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-FYHTJW5Y.js → complexity-analyzer-WYZD2YSY.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-ZAWDSUR3.js → continuedev-installer-UPXINJFT.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-5QK565JX.js → copilot-installer-WIVYQRIF.js} +2 -2
- package/dist/cli/chunks/core-handlers-KSQM6Q6S.js +2 -0
- package/dist/cli/chunks/{cost-tracker-AWWMPPBJ.js → cost-tracker-RIN4JDDM.js} +2 -2
- package/dist/cli/chunks/coverage-SPFVHRRU.js +43 -0
- package/dist/cli/chunks/coverage-target-GSRBNHXE.js +2 -0
- package/dist/cli/chunks/cross-domain-router-CTGNOVCF.js +2 -0
- package/dist/cli/chunks/{cursor-installer-3BL7JACV.js → cursor-installer-POM7NGCC.js} +2 -2
- package/dist/cli/chunks/{daemon-R6ULBHHF.js → daemon-HFGKQ6LB.js} +3 -3
- package/dist/cli/chunks/{daemon-OJ624POF.js → daemon-M5TD5Y6T.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-J6I3LTMY.js → dag-attention-scheduler-HJXM7Q5P.js} +2 -2
- package/dist/cli/chunks/{detect-5Q5W33UR.js → detect-XKQGLZYN.js} +2 -2
- package/dist/cli/chunks/{dist-node-GJNW56NA.js → dist-node-SSKB53QL.js} +2 -2
- package/dist/cli/chunks/{domain-handler-IZQY2G44.js → domain-handler-6BNDHATU.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-PIGO3KI2.js → domain-plugins-DOX54YE3.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-NU3B4FQG.js → domain-transfer-FW4ZX3Z7.js} +2 -2
- package/dist/cli/chunks/dream-MIK2E4UL.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-5QDDRPWV.js → embed-and-insert-pattern-QST77T2B.js} +2 -2
- package/dist/cli/chunks/{eval-TB5HOAUY.js → eval-K7E4XXBS.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-SIYVLKDE.js → experience-capture-middleware-X66IYSRV.js} +3 -3
- package/dist/cli/chunks/{fast-paths-T7QELS6D.js → fast-paths-5JXXTYAG.js} +2 -2
- package/dist/cli/chunks/{feature-flags-TNZ7ZAJV.js → feature-flags-2CR3CO23.js} +2 -2
- package/dist/cli/chunks/{feature-flags-T3CNNYMJ.js → feature-flags-RB72LHOJ.js} +2 -2
- package/dist/cli/chunks/{file-discovery-M45P2ZCY.js → file-discovery-3NHRUQQB.js} +2 -2
- package/dist/cli/chunks/{fleet-DSBZPHBZ.js → fleet-SDU7QEOA.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-EHODCF32.js → gnn-wrapper-AWCFODUV.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-V5DBVF7V.js → heartbeat-handler-A4PJ3NFP.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-OCKRACUW.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-X67XG73C.js +2 -0
- package/dist/cli/chunks/hnsw-index-I7KCQBQR.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-IYKDYA2F.js → hnsw-legacy-bridge-KRS7SSFM.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-DKG4LW3X.js → hnswlib-node-OGGCPKPO.js} +2 -2
- package/dist/cli/chunks/{hooks-VKNMAILY.js → hooks-XNRNMUBW.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-FOUHTKAK.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-AXZVP7A7.js → hypergraph-engine-X35LTXYT.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-6EO6JN4Z.js → hypergraph-handler-M6THKAG6.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-GXYVX46O.js +2 -0
- package/dist/cli/chunks/{init-handler-N3NG3RHN.js → init-handler-2AXMXHYF.js} +6 -6
- package/dist/cli/chunks/init-wizard-C2MRX2QG.js +2 -0
- package/dist/cli/chunks/kernel-Q2IUDIDC.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-JICGAHLM.js → kilocode-installer-TEPR2ZJD.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-VYBFP6ZH.js → kiro-installer-RUKHGDEE.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-E2Z6K5EE.js +2 -0
- package/dist/cli/chunks/{learning-3BHEZEPK.js → learning-BEA26RNA.js} +3 -3
- package/dist/cli/chunks/{llm-router-GPTEZCUN.js → llm-router-7GECMDCP.js} +4 -4
- package/dist/cli/chunks/llm-router-service-YATYFEDD.js +2 -0
- package/dist/cli/chunks/{load-W5BIRPU4.js → load-NTJ4Y4ZR.js} +2 -2
- package/dist/cli/chunks/load-test-LV77JXWA.js +2 -0
- package/dist/cli/chunks/{mcp-EBV4DZPG.js → mcp-4335GTTG.js} +2 -2
- package/dist/cli/chunks/{memory-7F6YYKNL.js → memory-HYC4M4XS.js} +5 -5
- package/dist/cli/chunks/memory-backend-XME3X3QX.js +2 -0
- package/dist/cli/chunks/memory-handlers-VG47X5DX.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-3ZIA2YOL.js → multi-model-executor-T7FYKM6T.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-2XRZUTLR.js → opencode-installer-3USXVT5M.js} +2 -2
- package/dist/cli/chunks/{orchestrator-VSZVJUJW.js → orchestrator-VHUXUYIM.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-TAXMLENP.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-I2IGVHRL.js → pattern-usage-recorder-CMZLPX2K.js} +2 -2
- package/dist/cli/chunks/{pipeline-5G3O6WBY.js → pipeline-BTRZOVSL.js} +2 -2
- package/dist/cli/chunks/{platform-6GUFDIA3.js → platform-2MCRKC25.js} +2 -2
- package/dist/cli/chunks/{plugin-GYXE4CIC.js → plugin-2VAYWAO3.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-THX6JLGZ.js → prime-radiant-advanced-wasm-TXFEMBP6.js} +2 -2
- package/dist/cli/chunks/{project-root-QJRBKZQU.js → project-root-CFFPBGPX.js} +2 -2
- package/dist/cli/chunks/protocol-executor-ML76QAVQ.js +2 -0
- package/dist/cli/chunks/{protocol-handler-B54LRU26.js → protocol-handler-DZ26OYVZ.js} +2 -2
- package/dist/cli/chunks/{prove-PCY2WQOD.js → prove-QWONEJWX.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-LUZH6RYV.js +2 -0
- package/dist/cli/chunks/quality-WFH54FY7.js +8 -0
- package/dist/cli/chunks/{quality-gate-L3KXL6WE.js → quality-gate-ONJB7XU7.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-EWXNIXB6.js +2 -0
- package/dist/cli/chunks/{real-embeddings-N3H523PJ.js → real-embeddings-GZV4VKK4.js} +2 -2
- package/dist/cli/chunks/{ref-validation-6BKDPHZ7.js → ref-validation-HW5Y55ZC.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-NSGGTWXE.js → roocode-installer-5OABDNZT.js} +2 -2
- package/dist/cli/chunks/router-MXOBVEBF.js +2 -0
- package/dist/cli/chunks/routing-feedback-T6CCRUEK.js +2 -0
- package/dist/cli/chunks/{routing-handler-SRQNUBG3.js → routing-handler-CVHVOQTC.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-2IGULGDE.js → ruvector-commands-KKDKFGIQ.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-WHXVT3V3.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-JFPWIRCG.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-ZD6WK5CK.js → rvf-migration-coordinator-D4KUBNRZ.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-KOXR7TJL.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-QULKUBBI.js → rvf-store-integrity-UGUXKIFX.js} +2 -2
- package/dist/cli/chunks/safe-db-CI6IPSIN.js +2 -0
- package/dist/cli/chunks/schedule-X4HW6TVJ.js +2 -0
- package/dist/cli/chunks/scheduler-KCNJ2ON3.js +2 -0
- package/dist/cli/chunks/{security-JW4EBARW.js → security-7723AZZ4.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-VQ7NJTGY.js → shared-rvf-adapter-KEQ5CLNI.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-SKTS52HK.js → shared-rvf-dual-writer-ZSHYG5IA.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-PGHU6VUR.js +2 -0
- package/dist/cli/chunks/{standalone-memory-3N4YJCSY.js → standalone-memory-MHZEEYMK.js} +2 -2
- package/dist/cli/chunks/{status-handler-5BQ2IIDG.js → status-handler-JKXPJ22K.js} +2 -2
- package/dist/cli/chunks/{structural-health-WGYR2RJB.js → structural-health-J4RKCYWF.js} +2 -2
- package/dist/cli/chunks/{sync-R5OKUBTQ.js → sync-EFWXMA2H.js} +2 -2
- package/dist/cli/chunks/{sync-DLKSXTIR.js → sync-PDPORHVN.js} +2 -2
- package/dist/cli/chunks/{task-handler-Z5KNTSUX.js → task-handler-VERADM44.js} +2 -2
- package/dist/cli/chunks/{task-handlers-RZFMYFSC.js → task-handlers-4RUCWUR2.js} +3 -3
- package/dist/cli/chunks/{test-LHWKZJRN.js → test-DMBJFQNL.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-EN7WXUMS.js → test-scheduling-LUPTVGCD.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-4V3OO4EC.js → token-bootstrap-S346YBVO.js} +2 -2
- package/dist/cli/chunks/{token-usage-PFC2BYBS.js → token-usage-VOA34IKM.js} +2 -2
- package/dist/cli/chunks/{transformers-VZCC4SHC.js → transformers-GU4TYAN5.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-ZYDQXGKN.js → tree-sitter-wasm-parser-MZPXAH7C.js} +2 -2
- package/dist/cli/chunks/{types-I6AWHZZQ.js → types-K4FLXR2K.js} +2 -2
- package/dist/cli/chunks/unified-memory-6CK3TUNQ.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-A7BWBGYN.js +2 -0
- package/dist/cli/chunks/unified-persistence-GEPMDBQZ.js +2 -0
- package/dist/cli/chunks/{upgrade-T7SG75PA.js → upgrade-M3ATDRMK.js} +2 -2
- package/dist/cli/chunks/{validate-YLYEHTY3.js → validate-AAP773B3.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-VTLTRUE3.js → validate-swarm-7RGAZX5F.js} +2 -2
- package/dist/cli/chunks/visual-security-L4J7LQWT.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-JUM7ZY5M.js → web-tree-sitter-GQMRHGGI.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-4KS2466T.js → windsurf-installer-HG6HF2GF.js} +2 -2
- package/dist/cli/chunks/witness-chain-CDUMX623.js +2 -0
- package/dist/cli/chunks/{witness-chain-E4X6TOCT.js → witness-chain-WKU3ZIBQ.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-MB53OZO6.js → witness-chain-repair-WNYH6O4L.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-LBWJHO7Y.js → witness-chain-verifier-Q2KW3QEQ.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-5IHVMXHJ.js → witness-key-manager-NQ5DAAC4.js} +2 -2
- package/dist/cli/chunks/{workflow-XUQXIRNE.js → workflow-CX6SHFBW.js} +5 -5
- package/dist/cli/chunks/workflow-orchestrator-USJDWVDR.js +2 -0
- package/dist/cli/chunks/{wrappers-YVF5SQUN.js → wrappers-CZDI6Z3X.js} +2 -2
- package/dist/cli/commands/ci.js +14 -6
- package/dist/cli/commands/code.js +1 -0
- package/dist/cli/commands/coverage.d.ts +28 -0
- package/dist/cli/commands/coverage.js +258 -143
- package/dist/cli/commands/quality.d.ts +12 -1
- package/dist/cli/commands/quality.js +51 -3
- package/dist/cli/commands/workflow.js +3 -0
- package/dist/cli/scheduler/persistent-scheduler.d.ts +2 -0
- package/dist/cli/scheduler/persistent-scheduler.js +12 -2
- package/dist/cli/utils/ci-output.d.ts +14 -4
- package/dist/cli/utils/ci-output.js +21 -4
- package/dist/cli/utils/coverage-data.d.ts +7 -0
- package/dist/cli/utils/coverage-data.js +21 -27
- package/dist/contracts/verdicts.d.ts +14 -0
- package/dist/contracts/verdicts.js +44 -3
- package/dist/coordination/handlers/coverage-handlers.js +121 -120
- package/dist/coordination/handlers/coverage-runner.d.ts +121 -0
- package/dist/coordination/handlers/coverage-runner.js +367 -0
- package/dist/coordination/handlers/coverage-target.d.ts +144 -0
- package/dist/coordination/handlers/coverage-target.js +311 -0
- package/dist/coordination/handlers/handler-utils.d.ts +9 -0
- package/dist/coordination/handlers/handler-utils.js +44 -1
- package/dist/coordination/handlers/quality-handlers.js +101 -15
- package/dist/coordination/result-saver.js +17 -3
- package/dist/coordination/task-executor.d.ts +5 -0
- package/dist/coordination/task-executor.js +7 -0
- package/dist/domains/code-intelligence/coordinator.d.ts +2 -1
- package/dist/domains/code-intelligence/coordinator.js +10 -32
- package/dist/domains/code-intelligence/interfaces.d.ts +5 -0
- package/dist/domains/code-intelligence/plugin.js +1 -0
- package/dist/domains/code-intelligence/project-root-resolver.d.ts +50 -0
- package/dist/domains/code-intelligence/project-root-resolver.js +121 -0
- package/dist/domains/code-intelligence/services/metric-collector/listing-process-owner.d.ts +3 -0
- package/dist/domains/code-intelligence/services/metric-collector/listing-process-owner.js +57 -0
- package/dist/domains/code-intelligence/services/metric-collector/test-counter.js +124 -36
- package/dist/domains/coverage-analysis/coordinator.js +4 -1
- package/dist/domains/coverage-analysis/interfaces.d.ts +15 -0
- package/dist/domains/coverage-analysis/plugin.js +7 -1
- package/dist/domains/coverage-analysis/services/coverage-analyzer.d.ts +7 -0
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +29 -9
- package/dist/domains/quality-assessment/coordinator-claim-verifier.js +2 -1
- package/dist/domains/quality-assessment/coordinator.js +8 -8
- package/dist/domains/quality-assessment/coverage-report-event.d.ts +25 -0
- package/dist/domains/quality-assessment/coverage-report-event.js +36 -0
- package/dist/domains/quality-assessment/evidence-sufficiency.d.ts +57 -0
- package/dist/domains/quality-assessment/evidence-sufficiency.js +97 -0
- package/dist/domains/quality-assessment/index.d.ts +1 -1
- package/dist/domains/quality-assessment/index.js +1 -1
- package/dist/domains/quality-assessment/plugin.js +8 -8
- package/dist/domains/quality-assessment/quality-evidence.d.ts +50 -2
- package/dist/domains/quality-assessment/quality-evidence.js +90 -8
- package/dist/domains/quality-assessment/services/quality-analyzer.js +13 -9
- package/dist/mcp/bundle.js +457 -453
- package/dist/mcp/handlers/domain-handler-configs.d.ts +60 -1
- package/dist/mcp/handlers/domain-handler-configs.js +42 -4
- package/dist/mcp/handlers/handler-factory.js +3 -0
- package/dist/mcp/handlers/wrapped-domain-handlers.js +7 -1
- package/dist/mcp/protocol-server.js +3 -2
- package/dist/mcp/services/session-store.js +11 -1
- package/dist/mcp/tools/coverage-analysis/index.js +1 -0
- package/dist/mcp/types.d.ts +24 -0
- package/dist/memory/crdt/convergence-tracker.js +14 -24
- package/dist/memory/crdt/crdt-store.js +15 -0
- package/dist/memory/crdt/lww-register.js +3 -3
- package/dist/memory/crdt/or-set.js +18 -0
- package/dist/planning/goap-planner.js +18 -10
- package/dist/shared/embeddings/embedding-cache.d.ts +3 -3
- package/dist/shared/embeddings/embedding-cache.js +8 -8
- package/dist/shared/embeddings/nomic-embedder.js +9 -6
- package/dist/shared/events/domain-events.d.ts +2 -0
- package/dist/shared/llm/cache.js +1 -1
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-WQSFQES5.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-TDHBBADE.js +0 -2
- package/dist/cli/chunks/base-CZSB27VO.js +0 -2
- package/dist/cli/chunks/browser-workflow-AEMIS6PA.js +0 -2
- package/dist/cli/chunks/chunk-7IJVCDDC.js +0 -96
- package/dist/cli/chunks/chunk-INVDDFJC.js +0 -2
- package/dist/cli/chunks/chunk-K65X6CQA.js +0 -4
- package/dist/cli/chunks/chunk-MZDUBFLP.js +0 -2
- package/dist/cli/chunks/chunk-QDQLL2QB.js +0 -3
- package/dist/cli/chunks/chunk-QZBFMXO5.js +0 -742
- package/dist/cli/chunks/ci-JPISJ25U.js +0 -82
- package/dist/cli/chunks/client-BS7I637W.js +0 -2
- package/dist/cli/chunks/core-handlers-UG7RMTK5.js +0 -2
- package/dist/cli/chunks/coverage-SMFQEGKE.js +0 -27
- package/dist/cli/chunks/cross-domain-router-NX7F6TOF.js +0 -2
- package/dist/cli/chunks/dream-GYEH57FW.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-4TJ3T7LR.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-PHFK4EAP.js +0 -2
- package/dist/cli/chunks/hnsw-index-434XDDBH.js +0 -2
- package/dist/cli/chunks/hybrid-backend-DYVJQENQ.js +0 -2
- package/dist/cli/chunks/impact-analyzer-CBAST6M2.js +0 -2
- package/dist/cli/chunks/init-wizard-DWIJW7HY.js +0 -2
- package/dist/cli/chunks/kernel-AQGCS4X2.js +0 -2
- package/dist/cli/chunks/knowledge-graph-2ICXFUUV.js +0 -2
- package/dist/cli/chunks/llm-router-service-C47RGTH6.js +0 -2
- package/dist/cli/chunks/load-test-LRDAW3N6.js +0 -2
- package/dist/cli/chunks/memory-backend-UFBAYPQ6.js +0 -2
- package/dist/cli/chunks/memory-handlers-OGLJHAAJ.js +0 -2
- package/dist/cli/chunks/pattern-null-store-27FCITT3.js +0 -2
- package/dist/cli/chunks/protocol-executor-XWXXTMEW.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-3RMYXENE.js +0 -2
- package/dist/cli/chunks/quality-LPVDZC7U.js +0 -7
- package/dist/cli/chunks/queen-coordinator-AS6DZ7UJ.js +0 -2
- package/dist/cli/chunks/router-OVNLNGHO.js +0 -2
- package/dist/cli/chunks/routing-feedback-TBOWEB6H.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-YJYRCYGT.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-VMRQ2SFO.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-B75L3ALW.js +0 -2
- package/dist/cli/chunks/safe-db-CRQHMCV6.js +0 -2
- package/dist/cli/chunks/schedule-L3DKJRXU.js +0 -2
- package/dist/cli/chunks/scheduler-VRHYUGY5.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-JVAZETTL.js +0 -2
- package/dist/cli/chunks/unified-memory-WOOCCIUM.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-PDDHFLUB.js +0 -2
- package/dist/cli/chunks/unified-persistence-6ETD3JSC.js +0 -2
- package/dist/cli/chunks/visual-security-O4OT2YPY.js +0 -2
- package/dist/cli/chunks/witness-chain-67JHPDCN.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-ZVFSNRYZ.js +0 -2
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a JS/TS project's test runner with coverage — safely (issue #995).
|
|
3
|
+
*
|
|
4
|
+
* Properties, each learned the hard way:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Run from the project root, write to a private temp dir.** The coverage
|
|
7
|
+
* report and the runner's JSON result go to `reportDir`, never into the
|
|
8
|
+
* project tree (#995 wrote `src/coverage/`). The result file is set with
|
|
9
|
+
* plain `--outputFile=` — vitest ignores `--outputFile.json=` when the
|
|
10
|
+
* user's config sets `outputFile` as a string.
|
|
11
|
+
* 2. **No shell, no download.** The runner's own JS entry point is resolved
|
|
12
|
+
* from the project's `node_modules` and started with `process.execPath`.
|
|
13
|
+
* Arguments are an array, so `$(…)`, spaces, `& ^ %` in a path are data on
|
|
14
|
+
* every platform. A runner that isn't installed is reported, never fetched
|
|
15
|
+
* (`npx` would silently download one).
|
|
16
|
+
* 3. **Kill the whole process tree.** Runner → workers is several levels deep.
|
|
17
|
+
* The child is started in its own process group (POSIX) and the group is
|
|
18
|
+
* killed on timeout (`taskkill /T /F` on Windows).
|
|
19
|
+
* 4. **Die with the host.** Every live run is registered; a synchronous
|
|
20
|
+
* `process.on('exit')` hook kills each group and removes its temp dir. That
|
|
21
|
+
* covers every path that ends in `process.exit()` or a natural exit — the
|
|
22
|
+
* MCP server's shutdown on SIGTERM/SIGINT/stdin EOF routes there. It cannot
|
|
23
|
+
* cover SIGKILL of the host (or a signal with no handler installed): no
|
|
24
|
+
* code runs in that case, and the group is left to its own timeout-less
|
|
25
|
+
* fate. Hosts should shut down via a handled signal.
|
|
26
|
+
*/
|
|
27
|
+
import type { CoverageData } from '../../domains/coverage-analysis/interfaces';
|
|
28
|
+
export type JsRunnerName = 'vitest' | 'jest' | 'nyc';
|
|
29
|
+
export interface JsCoverageInvocation {
|
|
30
|
+
runner: JsRunnerName;
|
|
31
|
+
/** `process.execPath`, or null when the runner is not installed. */
|
|
32
|
+
command: string | null;
|
|
33
|
+
/** `[<runner JS entry>, ...runner args]`. */
|
|
34
|
+
args: string[];
|
|
35
|
+
/** Where the runner writes its own JSON result (tests run / passed), if supported. */
|
|
36
|
+
resultsFile: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface JsCoverageRun {
|
|
39
|
+
runner: JsRunnerName;
|
|
40
|
+
/** The runner package was not found in the project's node_modules. Nothing ran. */
|
|
41
|
+
missing: boolean;
|
|
42
|
+
exitCode: number | null;
|
|
43
|
+
exitedCleanly: boolean;
|
|
44
|
+
timedOut: boolean;
|
|
45
|
+
timeoutMs: number;
|
|
46
|
+
/**
|
|
47
|
+
* Parsed istanbul report, or null when none was written. A report that was
|
|
48
|
+
* written but lists no files is `{ files: [] }` — NOT null: "the run covered
|
|
49
|
+
* nothing" is different from "the run produced no report".
|
|
50
|
+
*/
|
|
51
|
+
data: CoverageData | null;
|
|
52
|
+
/**
|
|
53
|
+
* Number of tests the runner reports having run, from its own JSON result.
|
|
54
|
+
* `null` when the runner gives no machine-readable result (nyc) or it could
|
|
55
|
+
* not be read — "unknown", which callers must not treat as 0.
|
|
56
|
+
*/
|
|
57
|
+
numTotalTests: number | null;
|
|
58
|
+
/** The runner's first error line plus the last ~2 KB of its stderr, for diagnosing a crash. */
|
|
59
|
+
stderrTail: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Summarise a runner's stderr for a caller: the FIRST error-looking line (or
|
|
63
|
+
* the first ~512 bytes) plus the last ~2 KB (#995 review NB-C). A tail alone
|
|
64
|
+
* loses the cause when a long stack follows it — a vitest config syntax error
|
|
65
|
+
* prints `[PARSE_ERROR] …` first and then kilobytes of frames.
|
|
66
|
+
*/
|
|
67
|
+
export declare function summarizeStderr(head: string, tail: string, totalBytes: number): string;
|
|
68
|
+
/**
|
|
69
|
+
* Find an installed package's bin script, walking up `node_modules` from the
|
|
70
|
+
* project root (hoisted monorepo installs live above the package).
|
|
71
|
+
*/
|
|
72
|
+
export declare function findPackageBin(projectRoot: string, pkg: string, binName?: string, maxDepth?: number): string | null;
|
|
73
|
+
/**
|
|
74
|
+
* Pick the runner and its argv. No shell is involved: `command` is the Node
|
|
75
|
+
* binary and `args[0]` the runner's JS entry, so paths are passed verbatim.
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildJsCoverageInvocation(projectRoot: string, reportDir: string): JsCoverageInvocation;
|
|
78
|
+
/**
|
|
79
|
+
* Synchronously kill every live coverage run and remove its temp dir. Runs from
|
|
80
|
+
* `process.on('exit')`, where only synchronous work is possible.
|
|
81
|
+
*/
|
|
82
|
+
export declare function killAllLiveRunsSync(): void;
|
|
83
|
+
/** Number of runs currently registered (for tests and diagnostics). */
|
|
84
|
+
export declare function liveRunCount(): number;
|
|
85
|
+
export interface ProcessTreeResult {
|
|
86
|
+
exitCode: number | null;
|
|
87
|
+
timedOut: boolean;
|
|
88
|
+
spawnError: boolean;
|
|
89
|
+
pid: number | undefined;
|
|
90
|
+
stderrTail: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Spawn `command args` in `cwd` (no shell) as the leader of a new process
|
|
94
|
+
* group, wait for it, and on timeout kill the entire group. Resolves only once
|
|
95
|
+
* no process of the group remains (bounded), so the caller can safely delete
|
|
96
|
+
* its temp dir. While running, the group and `cleanupDir` are registered with
|
|
97
|
+
* the exit hook so they never outlive the host process.
|
|
98
|
+
*/
|
|
99
|
+
export declare function runProcessTree(command: string, args: string[], options: {
|
|
100
|
+
cwd: string;
|
|
101
|
+
timeoutMs: number;
|
|
102
|
+
graceMs?: number;
|
|
103
|
+
cleanupDir?: string;
|
|
104
|
+
env?: NodeJS.ProcessEnv;
|
|
105
|
+
}): Promise<ProcessTreeResult>;
|
|
106
|
+
/**
|
|
107
|
+
* Run the project's test runner with coverage from `projectRoot`.
|
|
108
|
+
*
|
|
109
|
+
* Everything the runner writes goes to a fresh temp dir that is removed before
|
|
110
|
+
* this returns — after the whole process group is gone — or by the exit hook if
|
|
111
|
+
* the host exits first.
|
|
112
|
+
*/
|
|
113
|
+
export declare function runJsCoverage(projectRoot: string, options?: {
|
|
114
|
+
timeoutMs?: number;
|
|
115
|
+
}): Promise<JsCoverageRun>;
|
|
116
|
+
/**
|
|
117
|
+
* One-line, caller-facing explanation of why a run produced no usable report.
|
|
118
|
+
* Never "No instrumentation ran" when the runner did run and failed.
|
|
119
|
+
*/
|
|
120
|
+
export declare function describeRunFailure(run: JsCoverageRun, projectRoot: string): string;
|
|
121
|
+
//# sourceMappingURL=coverage-runner.d.ts.map
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a JS/TS project's test runner with coverage — safely (issue #995).
|
|
3
|
+
*
|
|
4
|
+
* Properties, each learned the hard way:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Run from the project root, write to a private temp dir.** The coverage
|
|
7
|
+
* report and the runner's JSON result go to `reportDir`, never into the
|
|
8
|
+
* project tree (#995 wrote `src/coverage/`). The result file is set with
|
|
9
|
+
* plain `--outputFile=` — vitest ignores `--outputFile.json=` when the
|
|
10
|
+
* user's config sets `outputFile` as a string.
|
|
11
|
+
* 2. **No shell, no download.** The runner's own JS entry point is resolved
|
|
12
|
+
* from the project's `node_modules` and started with `process.execPath`.
|
|
13
|
+
* Arguments are an array, so `$(…)`, spaces, `& ^ %` in a path are data on
|
|
14
|
+
* every platform. A runner that isn't installed is reported, never fetched
|
|
15
|
+
* (`npx` would silently download one).
|
|
16
|
+
* 3. **Kill the whole process tree.** Runner → workers is several levels deep.
|
|
17
|
+
* The child is started in its own process group (POSIX) and the group is
|
|
18
|
+
* killed on timeout (`taskkill /T /F` on Windows).
|
|
19
|
+
* 4. **Die with the host.** Every live run is registered; a synchronous
|
|
20
|
+
* `process.on('exit')` hook kills each group and removes its temp dir. That
|
|
21
|
+
* covers every path that ends in `process.exit()` or a natural exit — the
|
|
22
|
+
* MCP server's shutdown on SIGTERM/SIGINT/stdin EOF routes there. It cannot
|
|
23
|
+
* cover SIGKILL of the host (or a signal with no handler installed): no
|
|
24
|
+
* code runs in that case, and the group is left to its own timeout-less
|
|
25
|
+
* fate. Hosts should shut down via a handled signal.
|
|
26
|
+
*/
|
|
27
|
+
import { spawn, spawnSync } from 'child_process';
|
|
28
|
+
import * as fs from 'fs';
|
|
29
|
+
import * as os from 'os';
|
|
30
|
+
import * as path from 'path';
|
|
31
|
+
import { safeJsonParse } from '../../shared/safe-json.js';
|
|
32
|
+
import { loadCoverageReportFile } from './coverage-target.js';
|
|
33
|
+
const RESULTS_FILE = 'test-results.json';
|
|
34
|
+
const STDERR_TAIL_BYTES = 2048;
|
|
35
|
+
const STDERR_HEAD_BYTES = 4096;
|
|
36
|
+
const STDERR_PREFIX_BYTES = 512;
|
|
37
|
+
const ERROR_LINE_RE = /^.*(?:error|\[[A-Z][A-Z_]{2,}\]|ERR_[A-Z_]+).*$/im;
|
|
38
|
+
/**
|
|
39
|
+
* Summarise a runner's stderr for a caller: the FIRST error-looking line (or
|
|
40
|
+
* the first ~512 bytes) plus the last ~2 KB (#995 review NB-C). A tail alone
|
|
41
|
+
* loses the cause when a long stack follows it — a vitest config syntax error
|
|
42
|
+
* prints `[PARSE_ERROR] …` first and then kilobytes of frames.
|
|
43
|
+
*/
|
|
44
|
+
export function summarizeStderr(head, tail, totalBytes) {
|
|
45
|
+
if (totalBytes <= STDERR_TAIL_BYTES)
|
|
46
|
+
return tail.trim();
|
|
47
|
+
const errorLine = ERROR_LINE_RE.exec(head)?.[0]?.trim();
|
|
48
|
+
const prefix = (errorLine ?? head.slice(0, STDERR_PREFIX_BYTES)).trim();
|
|
49
|
+
if (prefix && tail.includes(prefix))
|
|
50
|
+
return tail.trim();
|
|
51
|
+
return `${prefix}\n…\n${tail.trim()}`;
|
|
52
|
+
}
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Locating the runner
|
|
55
|
+
// ============================================================================
|
|
56
|
+
/**
|
|
57
|
+
* Find an installed package's bin script, walking up `node_modules` from the
|
|
58
|
+
* project root (hoisted monorepo installs live above the package).
|
|
59
|
+
*/
|
|
60
|
+
export function findPackageBin(projectRoot, pkg, binName = pkg, maxDepth = 10) {
|
|
61
|
+
let dir = path.resolve(projectRoot);
|
|
62
|
+
for (let i = 0; i <= maxDepth; i++) {
|
|
63
|
+
const pkgDir = path.join(dir, 'node_modules', pkg);
|
|
64
|
+
try {
|
|
65
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf-8'));
|
|
66
|
+
const rel = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.[binName];
|
|
67
|
+
if (rel) {
|
|
68
|
+
const binPath = path.join(pkgDir, rel);
|
|
69
|
+
if (fs.existsSync(binPath))
|
|
70
|
+
return binPath;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// not installed at this level
|
|
75
|
+
}
|
|
76
|
+
const parent = path.dirname(dir);
|
|
77
|
+
if (parent === dir)
|
|
78
|
+
break;
|
|
79
|
+
dir = parent;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function readDeps(projectRoot) {
|
|
84
|
+
try {
|
|
85
|
+
const pkg = safeJsonParse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf-8'));
|
|
86
|
+
return {
|
|
87
|
+
...(pkg.devDependencies || {}),
|
|
88
|
+
...(pkg.dependencies || {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Pick the runner and its argv. No shell is involved: `command` is the Node
|
|
97
|
+
* binary and `args[0]` the runner's JS entry, so paths are passed verbatim.
|
|
98
|
+
*/
|
|
99
|
+
export function buildJsCoverageInvocation(projectRoot, reportDir) {
|
|
100
|
+
const resultsFile = path.join(reportDir, RESULTS_FILE);
|
|
101
|
+
const deps = readDeps(projectRoot);
|
|
102
|
+
let runner = 'vitest';
|
|
103
|
+
let runnerArgs;
|
|
104
|
+
let results = resultsFile;
|
|
105
|
+
if (deps['jest'] || deps['@jest/core']) {
|
|
106
|
+
runner = 'jest';
|
|
107
|
+
runnerArgs = ['--coverage', `--coverageDirectory=${reportDir}`, '--coverageReporters=json',
|
|
108
|
+
'--json', `--outputFile=${resultsFile}`];
|
|
109
|
+
}
|
|
110
|
+
else if (deps['mocha'] || deps['nyc']) {
|
|
111
|
+
runner = 'nyc';
|
|
112
|
+
runnerArgs = [`--report-dir=${reportDir}`, `--temp-dir=${path.join(reportDir, '.nyc_output')}`,
|
|
113
|
+
'--reporter=json', 'mocha'];
|
|
114
|
+
results = null;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// vitest is the default — covers vitest, @vitest/coverage-v8, etc.
|
|
118
|
+
// Plain `--outputFile=` (not `.json=`): it overrides a string, object, or
|
|
119
|
+
// absent `outputFile` in the user's config alike.
|
|
120
|
+
runnerArgs = ['run', '--coverage', `--coverage.reportsDirectory=${reportDir}`,
|
|
121
|
+
'--coverage.reporter=json', '--reporter=json', `--outputFile=${resultsFile}`];
|
|
122
|
+
}
|
|
123
|
+
const bin = findPackageBin(projectRoot, runner === 'jest' ? 'jest' : runner);
|
|
124
|
+
return {
|
|
125
|
+
runner,
|
|
126
|
+
command: bin ? process.execPath : null,
|
|
127
|
+
args: bin ? [bin, ...runnerArgs] : runnerArgs,
|
|
128
|
+
resultsFile: results,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function readNumTotalTests(resultsFile) {
|
|
132
|
+
if (!resultsFile)
|
|
133
|
+
return null;
|
|
134
|
+
try {
|
|
135
|
+
const parsed = JSON.parse(fs.readFileSync(resultsFile, 'utf-8'));
|
|
136
|
+
return typeof parsed.numTotalTests === 'number' ? parsed.numTotalTests : null;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Read the istanbul report the runner wrote. Distinguishes an EMPTY report
|
|
144
|
+
* (`{}` — the run instrumented nothing) from NO report.
|
|
145
|
+
*/
|
|
146
|
+
async function readRunReport(file) {
|
|
147
|
+
const data = await loadCoverageReportFile(file);
|
|
148
|
+
if (data)
|
|
149
|
+
return data;
|
|
150
|
+
try {
|
|
151
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
152
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed) && Object.keys(parsed).length === 0) {
|
|
153
|
+
return { files: [], summary: { line: 0, branch: 0, function: 0, statement: 0, files: 0 } };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// absent or unparseable
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Process-tree lifecycle
|
|
163
|
+
// ============================================================================
|
|
164
|
+
/** Live runs: process-group leader pid → temp dir to remove. */
|
|
165
|
+
const liveRuns = new Map();
|
|
166
|
+
let exitHookInstalled = false;
|
|
167
|
+
function killTree(pid, signal) {
|
|
168
|
+
if (process.platform === 'win32') {
|
|
169
|
+
// Windows has no process groups; taskkill /T walks the tree.
|
|
170
|
+
try {
|
|
171
|
+
spawnSync('taskkill', ['/pid', String(pid), '/T', '/F'], { stdio: 'ignore' });
|
|
172
|
+
}
|
|
173
|
+
catch { /* gone */ }
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
process.kill(-pid, signal);
|
|
178
|
+
}
|
|
179
|
+
catch { /* group already gone */ }
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Synchronously kill every live coverage run and remove its temp dir. Runs from
|
|
183
|
+
* `process.on('exit')`, where only synchronous work is possible.
|
|
184
|
+
*/
|
|
185
|
+
export function killAllLiveRunsSync() {
|
|
186
|
+
for (const [pid, dir] of liveRuns) {
|
|
187
|
+
killTree(pid, 'SIGKILL');
|
|
188
|
+
if (dir) {
|
|
189
|
+
try {
|
|
190
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
191
|
+
}
|
|
192
|
+
catch { /* best-effort */ }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
liveRuns.clear();
|
|
196
|
+
}
|
|
197
|
+
/** Number of runs currently registered (for tests and diagnostics). */
|
|
198
|
+
export function liveRunCount() {
|
|
199
|
+
return liveRuns.size;
|
|
200
|
+
}
|
|
201
|
+
function ensureExitHook() {
|
|
202
|
+
if (exitHookInstalled)
|
|
203
|
+
return;
|
|
204
|
+
process.on('exit', killAllLiveRunsSync);
|
|
205
|
+
exitHookInstalled = true;
|
|
206
|
+
}
|
|
207
|
+
/** Is any process of this group still alive? */
|
|
208
|
+
function groupAlive(pgid) {
|
|
209
|
+
try {
|
|
210
|
+
process.kill(-pgid, 0);
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function waitForGroupExit(pid, maxMs) {
|
|
218
|
+
if (process.platform === 'win32')
|
|
219
|
+
return;
|
|
220
|
+
const deadline = Date.now() + maxMs;
|
|
221
|
+
while (groupAlive(pid) && Date.now() < deadline) {
|
|
222
|
+
await new Promise(r => setTimeout(r, 50));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Spawn `command args` in `cwd` (no shell) as the leader of a new process
|
|
227
|
+
* group, wait for it, and on timeout kill the entire group. Resolves only once
|
|
228
|
+
* no process of the group remains (bounded), so the caller can safely delete
|
|
229
|
+
* its temp dir. While running, the group and `cleanupDir` are registered with
|
|
230
|
+
* the exit hook so they never outlive the host process.
|
|
231
|
+
*/
|
|
232
|
+
export async function runProcessTree(command, args, options) {
|
|
233
|
+
const graceMs = options.graceMs ?? 3000;
|
|
234
|
+
const isWindows = process.platform === 'win32';
|
|
235
|
+
ensureExitHook();
|
|
236
|
+
return new Promise(resolve => {
|
|
237
|
+
let timedOut = false;
|
|
238
|
+
let settled = false;
|
|
239
|
+
let stderrTail = '';
|
|
240
|
+
let stderrHead = '';
|
|
241
|
+
let stderrBytes = 0;
|
|
242
|
+
const child = spawn(command, args, {
|
|
243
|
+
cwd: options.cwd,
|
|
244
|
+
env: options.env ?? process.env,
|
|
245
|
+
// Own process group (POSIX) so the whole tree can be signalled at once.
|
|
246
|
+
detached: !isWindows,
|
|
247
|
+
shell: false,
|
|
248
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
249
|
+
windowsHide: true,
|
|
250
|
+
});
|
|
251
|
+
if (child.pid !== undefined)
|
|
252
|
+
liveRuns.set(child.pid, options.cleanupDir);
|
|
253
|
+
child.stderr?.on('data', (chunk) => {
|
|
254
|
+
const text = chunk.toString('utf-8');
|
|
255
|
+
stderrBytes += chunk.length;
|
|
256
|
+
if (stderrHead.length < STDERR_HEAD_BYTES)
|
|
257
|
+
stderrHead = (stderrHead + text).slice(0, STDERR_HEAD_BYTES);
|
|
258
|
+
stderrTail = (stderrTail + text).slice(-STDERR_TAIL_BYTES);
|
|
259
|
+
});
|
|
260
|
+
// A grandchild holding the pipe open must not keep the host alive.
|
|
261
|
+
child.stderr?.on('error', () => { });
|
|
262
|
+
const finish = async (exitCode, spawnError) => {
|
|
263
|
+
if (settled)
|
|
264
|
+
return;
|
|
265
|
+
settled = true;
|
|
266
|
+
clearTimeout(timer);
|
|
267
|
+
if (child.pid !== undefined && !isWindows && groupAlive(child.pid)) {
|
|
268
|
+
// Anything left in the group after the runner exited is orphaned work
|
|
269
|
+
// (stray workers, a hung watcher). Sweep it before the caller cleans up.
|
|
270
|
+
killTree(child.pid, 'SIGTERM');
|
|
271
|
+
await waitForGroupExit(child.pid, graceMs);
|
|
272
|
+
if (groupAlive(child.pid))
|
|
273
|
+
killTree(child.pid, 'SIGKILL');
|
|
274
|
+
await waitForGroupExit(child.pid, graceMs);
|
|
275
|
+
}
|
|
276
|
+
child.stderr?.destroy();
|
|
277
|
+
if (child.pid !== undefined)
|
|
278
|
+
liveRuns.delete(child.pid);
|
|
279
|
+
resolve({
|
|
280
|
+
exitCode, timedOut, spawnError, pid: child.pid,
|
|
281
|
+
stderrTail: summarizeStderr(stderrHead, stderrTail, stderrBytes),
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
const timer = setTimeout(() => {
|
|
285
|
+
timedOut = true;
|
|
286
|
+
if (child.pid === undefined)
|
|
287
|
+
return;
|
|
288
|
+
killTree(child.pid, 'SIGTERM');
|
|
289
|
+
setTimeout(() => { if (!settled && child.pid !== undefined)
|
|
290
|
+
killTree(child.pid, 'SIGKILL'); }, graceMs).unref();
|
|
291
|
+
}, options.timeoutMs);
|
|
292
|
+
child.on('error', () => { void finish(null, true); });
|
|
293
|
+
child.on('exit', code => { void finish(code, false); });
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Run the project's test runner with coverage from `projectRoot`.
|
|
298
|
+
*
|
|
299
|
+
* Everything the runner writes goes to a fresh temp dir that is removed before
|
|
300
|
+
* this returns — after the whole process group is gone — or by the exit hook if
|
|
301
|
+
* the host exits first.
|
|
302
|
+
*/
|
|
303
|
+
export async function runJsCoverage(projectRoot, options = {}) {
|
|
304
|
+
const timeoutMs = options.timeoutMs ?? 120000;
|
|
305
|
+
const reportDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aqe-js-cov-'));
|
|
306
|
+
try {
|
|
307
|
+
const inv = buildJsCoverageInvocation(projectRoot, reportDir);
|
|
308
|
+
if (!inv.command) {
|
|
309
|
+
return {
|
|
310
|
+
runner: inv.runner, missing: true, exitCode: null, exitedCleanly: false, timedOut: false,
|
|
311
|
+
timeoutMs, data: null, numTotalTests: null, stderrTail: '',
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
// Runners that shell out to sibling tools (nyc → mocha) find them here.
|
|
315
|
+
const binDir = path.join(projectRoot, 'node_modules', '.bin');
|
|
316
|
+
// The runner's own temp files (vite's SSR cache, etc.) go inside reportDir
|
|
317
|
+
// too, so a killed run leaves nothing behind in the system temp dir.
|
|
318
|
+
const runnerTmp = path.join(reportDir, 'tmp');
|
|
319
|
+
fs.mkdirSync(runnerTmp);
|
|
320
|
+
const env = {
|
|
321
|
+
...process.env,
|
|
322
|
+
PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ''}`,
|
|
323
|
+
TMPDIR: runnerTmp, TMP: runnerTmp, TEMP: runnerTmp,
|
|
324
|
+
};
|
|
325
|
+
const run = await runProcessTree(inv.command, inv.args, {
|
|
326
|
+
cwd: projectRoot, timeoutMs, cleanupDir: reportDir, env,
|
|
327
|
+
});
|
|
328
|
+
const data = run.timedOut ? null : await readRunReport(path.join(reportDir, 'coverage-final.json'));
|
|
329
|
+
return {
|
|
330
|
+
runner: inv.runner,
|
|
331
|
+
missing: false,
|
|
332
|
+
exitCode: run.exitCode,
|
|
333
|
+
exitedCleanly: run.exitCode === 0 && !run.timedOut,
|
|
334
|
+
timedOut: run.timedOut,
|
|
335
|
+
timeoutMs,
|
|
336
|
+
data,
|
|
337
|
+
numTotalTests: run.timedOut ? null : readNumTotalTests(inv.resultsFile),
|
|
338
|
+
stderrTail: run.stderrTail,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
try {
|
|
343
|
+
fs.rmSync(reportDir, { recursive: true, force: true });
|
|
344
|
+
}
|
|
345
|
+
catch { /* best-effort */ }
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* One-line, caller-facing explanation of why a run produced no usable report.
|
|
350
|
+
* Never "No instrumentation ran" when the runner did run and failed.
|
|
351
|
+
*/
|
|
352
|
+
export function describeRunFailure(run, projectRoot) {
|
|
353
|
+
if (run.missing) {
|
|
354
|
+
return `${run.runner} is not installed in ${projectRoot} (no node_modules/${run.runner} found); ` +
|
|
355
|
+
'nothing was run and nothing was downloaded. Install it, or generate a coverage report and pass it as the target.';
|
|
356
|
+
}
|
|
357
|
+
if (run.timedOut) {
|
|
358
|
+
return `The coverage run timed out after ${Math.round(run.timeoutMs / 1000)}s and was stopped.`;
|
|
359
|
+
}
|
|
360
|
+
if (run.exitCode !== 0) {
|
|
361
|
+
const tail = run.stderrTail ? `: ${run.stderrTail}` : '';
|
|
362
|
+
return `Test runner (${run.runner}) exited with code ${run.exitCode ?? 'unknown'} without a coverage report${tail}`;
|
|
363
|
+
}
|
|
364
|
+
return `Test runner (${run.runner}) exited cleanly but wrote no coverage report. ` +
|
|
365
|
+
'Ensure a coverage provider is configured (e.g., @vitest/coverage-v8, istanbul).';
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=coverage-runner.js.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage target resolution (issue #995).
|
|
3
|
+
*
|
|
4
|
+
* A coverage target can be the project root, a subfolder of it, a single source
|
|
5
|
+
* file, or an existing coverage report. Before #995 every target was treated as
|
|
6
|
+
* if it were the project root: `target: "src/"` ran vitest FROM `src/` (which
|
|
7
|
+
* found no tests, reported 0%, and wrote `src/coverage/` into the source tree),
|
|
8
|
+
* and `target: "coverage/lcov.info"` was searched for a `coverage/` folder
|
|
9
|
+
* inside a file and came back empty.
|
|
10
|
+
*
|
|
11
|
+
* This module answers the three questions every collector needs first:
|
|
12
|
+
* 1. Which project does the target belong to? (`findCoverageProjectRoot`)
|
|
13
|
+
* 2. Is the target itself a coverage report? (`isCoverageReportFile` /
|
|
14
|
+
* `loadCoverageReportFile`)
|
|
15
|
+
* 3. Which entries of a project-wide report belong to the target?
|
|
16
|
+
* (`scopeCoverageToTarget`)
|
|
17
|
+
*
|
|
18
|
+
* Kept free of task-executor and child-process imports so both the MCP handler
|
|
19
|
+
* and the CLI `coverage` command can share it.
|
|
20
|
+
*/
|
|
21
|
+
import type { CoverageData, FileCoverage } from '../../domains/coverage-analysis/interfaces';
|
|
22
|
+
/**
|
|
23
|
+
* Walk up from a target to the nearest directory that holds a project marker.
|
|
24
|
+
*
|
|
25
|
+
* NEAREST rather than topmost: in a monorepo, `packages/core/src` belongs to
|
|
26
|
+
* `packages/core` (its own package.json and test config), not the workspace
|
|
27
|
+
* root. This intentionally differs from `kernel/findProjectRoot`, which locates
|
|
28
|
+
* the AQE data root (honouring AQE_PROJECT_ROOT and `.agentic-qe`).
|
|
29
|
+
*
|
|
30
|
+
* Returns `null` when the target does not exist (a typo must not silently
|
|
31
|
+
* resolve to — and run tests for — an ancestor project) or when no marker is
|
|
32
|
+
* found below the home directory / filesystem root within `maxDepth` levels.
|
|
33
|
+
*/
|
|
34
|
+
export declare function findCoverageProjectRoot(target: string, maxDepth?: number): string | null;
|
|
35
|
+
/** Is this path (by name) a coverage report rather than source code? */
|
|
36
|
+
export declare function isCoverageReportFile(filePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Parse a coverage report file of any supported format.
|
|
39
|
+
*
|
|
40
|
+
* Returns `null` — never an empty "0%" report — when the file can't be read,
|
|
41
|
+
* can't be parsed, or lists no files.
|
|
42
|
+
*/
|
|
43
|
+
export declare function loadCoverageReportFile(filePath: string): Promise<CoverageData | null>;
|
|
44
|
+
/**
|
|
45
|
+
* Keep only the report entries that lie under `target`.
|
|
46
|
+
*
|
|
47
|
+
* Report paths come in two shapes: absolute (istanbul `coverage-final.json`)
|
|
48
|
+
* and project-root-relative (vitest/jest `lcov.info` writes `SF:src/math.ts`).
|
|
49
|
+
* Relative entries are resolved against `root` before comparing. Entry paths are
|
|
50
|
+
* returned unchanged.
|
|
51
|
+
*/
|
|
52
|
+
export declare function scopeCoverageToTarget(data: CoverageData, root: string, target: string): FileCoverage[];
|
|
53
|
+
/** Why there are no coverage figures for a target. */
|
|
54
|
+
export type NoDataReason =
|
|
55
|
+
/** The target path does not exist. */
|
|
56
|
+
'target-missing'
|
|
57
|
+
/** A coverage report was given but cannot be parsed (malformed, raw V8, empty). */
|
|
58
|
+
| 'unreadable-report'
|
|
59
|
+
/** The report lists only test files. */
|
|
60
|
+
| 'test-only-report'
|
|
61
|
+
/** The report has no entries under the target — it did not measure it. */
|
|
62
|
+
| 'target-not-covered'
|
|
63
|
+
/** The test runner itself reports running zero tests. */
|
|
64
|
+
| 'no-tests-ran';
|
|
65
|
+
export type CoverageEvaluation = {
|
|
66
|
+
status: 'measured';
|
|
67
|
+
files: FileCoverage[];
|
|
68
|
+
} | {
|
|
69
|
+
status: 'no-data';
|
|
70
|
+
reason: NoDataReason;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Decide what a report says about `target`. Shared by the MCP handler and the
|
|
74
|
+
* CLI so the two cannot disagree (#995 review B2).
|
|
75
|
+
*
|
|
76
|
+
* "Unmeasured" is decided ONLY from evidence that nothing was measured:
|
|
77
|
+
* - the runner's own result says it ran 0 tests (`numTotalTests === 0`), or
|
|
78
|
+
* - the report has no entry under the target.
|
|
79
|
+
* Hit counts are never used: a file listed with 0 hits is a measured 0%,
|
|
80
|
+
* whether the report came from our run or from the user (#995 review B3).
|
|
81
|
+
*/
|
|
82
|
+
export declare function evaluateCoverageForTarget(report: CoverageData, projectRoot: string, target: string, options?: {
|
|
83
|
+
numTotalTests?: number | null;
|
|
84
|
+
}): CoverageEvaluation;
|
|
85
|
+
export type ExistingCoverage = {
|
|
86
|
+
status: 'target-missing';
|
|
87
|
+
target: string;
|
|
88
|
+
} | {
|
|
89
|
+
status: 'no-report';
|
|
90
|
+
target: string;
|
|
91
|
+
projectRoot: string;
|
|
92
|
+
} | {
|
|
93
|
+
status: 'evaluated';
|
|
94
|
+
target: string;
|
|
95
|
+
projectRoot: string;
|
|
96
|
+
source: 'report-file' | 'project-report';
|
|
97
|
+
evaluation: CoverageEvaluation;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Resolve a target to coverage that already exists on disk, without running
|
|
101
|
+
* anything:
|
|
102
|
+
* - a coverage report passed as the target is parsed and analysed whole;
|
|
103
|
+
* - otherwise the PROJECT ROOT's report (not the cwd's, not the subfolder's)
|
|
104
|
+
* is scoped to the target;
|
|
105
|
+
* - `no-report` tells the caller it may run tooling from `projectRoot`.
|
|
106
|
+
*/
|
|
107
|
+
export declare function resolveExistingCoverage(targetPath: string): Promise<ExistingCoverage>;
|
|
108
|
+
/**
|
|
109
|
+
* Threshold verdict over the metrics that were actually collected. Shared by
|
|
110
|
+
* MCP and CLI (#995 review NB5): an uncollected metric (no branch data in the
|
|
111
|
+
* report) is null, and a null must not drag the average down as a fake 0.
|
|
112
|
+
*/
|
|
113
|
+
export declare function thresholdVerdict(summary: {
|
|
114
|
+
line: number;
|
|
115
|
+
branch: number;
|
|
116
|
+
function: number;
|
|
117
|
+
statement: number;
|
|
118
|
+
}, threshold: number, collected: {
|
|
119
|
+
branch: boolean;
|
|
120
|
+
function: boolean;
|
|
121
|
+
}): {
|
|
122
|
+
overall: number;
|
|
123
|
+
meetsThreshold: boolean;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Make the analyzer's recommendations agree with `thresholdVerdict`
|
|
127
|
+
* (#995 review NB-A). The analyzer computes its "Coverage is X% below
|
|
128
|
+
* threshold" line from a 4-metric average that counts an uncollected metric as
|
|
129
|
+
* 0 — so a line-only report at 90% got "Met" next to "35.0% below threshold".
|
|
130
|
+
* Here the shortfall line is recomputed from the collected-metrics verdict,
|
|
131
|
+
* and advice about a metric that was never collected is dropped.
|
|
132
|
+
*/
|
|
133
|
+
export declare function reconcileRecommendations(recommendations: string[], verdict: {
|
|
134
|
+
overall: number;
|
|
135
|
+
meetsThreshold: boolean;
|
|
136
|
+
}, threshold: number, collected: {
|
|
137
|
+
branch: boolean;
|
|
138
|
+
function: boolean;
|
|
139
|
+
}): string[];
|
|
140
|
+
/** Is this verdict "no measurement exists" (as opposed to an error or test-only report)? */
|
|
141
|
+
export declare function isUnmeasured(reason: NoDataReason): boolean;
|
|
142
|
+
/** Caller-facing explanation of a no-data verdict. Shared by MCP and CLI. */
|
|
143
|
+
export declare function describeNoData(reason: NoDataReason, target: string, projectRoot: string | null): string;
|
|
144
|
+
//# sourceMappingURL=coverage-target.d.ts.map
|