agentic-qe 3.15.16 → 3.15.17
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 +78 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/bundle.js +6 -6
- package/dist/cli/chunks/adapter-OMILP6KH.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-45NWEKVS.js → agent-booster-wasm-6BUOFQZA.js} +2 -2
- package/dist/cli/chunks/{agent-handler-LVHMYFEF.js → agent-handler-HPDK3JI3.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-YDWOJFEQ.js → agent-memory-branch-5QKUTWK5.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-OXH5CCOS.js +2 -0
- package/dist/cli/chunks/{arena-CZKHXDDS.js → arena-7OKPMNHD.js} +2 -2
- package/dist/cli/chunks/{arena-ELDZH3CZ.js → arena-HZ35LESR.js} +4 -4
- package/dist/cli/chunks/{audit-5MT4T47Z.js → audit-XI575SVK.js} +3 -3
- package/dist/cli/chunks/base-MAK2BLTG.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-6TGYPC2B.js → better-sqlite3-YO5X7ZJS.js} +2 -2
- package/dist/cli/chunks/{brain-handler-HQWZFO52.js → brain-handler-GCQZFZGQ.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-WVILM4SO.js → branch-enumerator-N6G44UU2.js} +2 -2
- package/dist/cli/chunks/{browser-RX5ALU3H.js → browser-EVKPTLOI.js} +2 -2
- package/dist/cli/chunks/browser-workflow-IR3VF2TL.js +2 -0
- package/dist/cli/chunks/{chunk-F742SZAX.js → chunk-2EQK7B5L.js} +2 -2
- package/dist/cli/chunks/{chunk-5NNNEWLS.js → chunk-2PCEMDIX.js} +67 -65
- package/dist/cli/chunks/{chunk-FBDVGRSC.js → chunk-2UUZCQSD.js} +7 -7
- package/dist/cli/chunks/{chunk-AG2EWGXS.js → chunk-2YWYW7NU.js} +2 -2
- package/dist/cli/chunks/{chunk-4LQFBY5L.js → chunk-45223KK6.js} +3 -3
- package/dist/cli/chunks/chunk-4EJLHNER.js +12 -0
- package/dist/cli/chunks/{chunk-KQYJ4VQ5.js → chunk-4L6WX5KC.js} +1 -1
- package/dist/cli/chunks/{chunk-KVF4NXGQ.js → chunk-4NKZU2JZ.js} +2 -2
- package/dist/cli/chunks/{chunk-YRAX7SFJ.js → chunk-4UKTIQDT.js} +2 -2
- package/dist/cli/chunks/{chunk-YTHTQPWR.js → chunk-4YM45Z5B.js} +1 -1
- package/dist/cli/chunks/{chunk-XIIQ5QTT.js → chunk-5FSPELOG.js} +2 -2
- package/dist/cli/chunks/{chunk-LKTTUHLF.js → chunk-5WATBVU6.js} +2 -2
- package/dist/cli/chunks/{chunk-SR52XP5F.js → chunk-5WYZVSL2.js} +1 -1
- package/dist/cli/chunks/{chunk-GQ6TUIKY.js → chunk-6LSZCEW2.js} +1 -1
- package/dist/cli/chunks/{chunk-NDJ7P2EP.js → chunk-6V6BD6PH.js} +1 -1
- package/dist/cli/chunks/{chunk-63GMRQ25.js → chunk-74MDUIAZ.js} +1 -1
- package/dist/cli/chunks/{chunk-4D4DENG6.js → chunk-776K4ZLE.js} +2 -2
- package/dist/cli/chunks/{chunk-ZJH5MU2I.js → chunk-7BSOO3CY.js} +2 -2
- package/dist/cli/chunks/{chunk-IOQ6ZQ5W.js → chunk-7SNSI4VY.js} +1 -1
- package/dist/cli/chunks/{chunk-LRSX2FJM.js → chunk-A4BVDYIL.js} +1 -1
- package/dist/cli/chunks/{chunk-SASBO5Y5.js → chunk-AGCS5GSO.js} +2 -2
- package/dist/cli/chunks/{chunk-GAHNO6JJ.js → chunk-AVHYJ3XP.js} +2 -2
- package/dist/cli/chunks/{chunk-CGGUM2YJ.js → chunk-BE7ZHM34.js} +2 -2
- package/dist/cli/chunks/{chunk-7TE5ONQQ.js → chunk-BHQ2DLJU.js} +1 -1
- package/dist/cli/chunks/{chunk-IESR7TNB.js → chunk-BKHEQIRZ.js} +2 -2
- package/dist/cli/chunks/{chunk-J4ELZNLY.js → chunk-BSIWI4ES.js} +2 -2
- package/dist/cli/chunks/{chunk-NVEWF4JV.js → chunk-C7QLLMYI.js} +1 -1
- package/dist/cli/chunks/{chunk-V5NHZV7S.js → chunk-CMN7PU2H.js} +2 -2
- package/dist/cli/chunks/{chunk-PPUZWYUG.js → chunk-COTQ44YO.js} +2 -2
- package/dist/cli/chunks/{chunk-5V3TI2LG.js → chunk-CQER6IJ5.js} +1 -1
- package/dist/cli/chunks/{chunk-SI6DPU5D.js → chunk-CVPXHDQU.js} +1 -1
- package/dist/cli/chunks/{chunk-6ZBXSOX6.js → chunk-CVYPMGUM.js} +2 -2
- package/dist/cli/chunks/{chunk-DXD6K2ZP.js → chunk-CXCMATZ6.js} +2 -2
- package/dist/cli/chunks/{chunk-PF7RBAYL.js → chunk-D75GLKEL.js} +2 -2
- package/dist/cli/chunks/chunk-DCDSN67A.js +2 -0
- package/dist/cli/chunks/{chunk-MAFQV4U4.js → chunk-DHKSPOUQ.js} +2 -2
- package/dist/cli/chunks/{chunk-RJIEG3NA.js → chunk-DJDVD6RM.js} +2 -2
- package/dist/cli/chunks/{chunk-GFWHUQSF.js → chunk-DNVRTJKB.js} +2 -2
- package/dist/cli/chunks/{chunk-G5RHFBAY.js → chunk-DS5IFRY6.js} +2 -2
- package/dist/cli/chunks/{chunk-BEKDKVQT.js → chunk-E7XIMOKW.js} +2 -2
- package/dist/cli/chunks/{chunk-5JZRZI4S.js → chunk-ECKHDHR2.js} +2 -2
- package/dist/cli/chunks/chunk-EPVPXHL7.js +2 -0
- package/dist/cli/chunks/{chunk-HVRRLYX6.js → chunk-ERYADKMZ.js} +2 -2
- package/dist/cli/chunks/{chunk-SUDMM5SO.js → chunk-EUWG2JG4.js} +2 -2
- package/dist/cli/chunks/{chunk-VSIKHWZ4.js → chunk-FAQ24UHB.js} +3 -3
- package/dist/cli/chunks/{chunk-YNMJEDN5.js → chunk-FBBPRVNF.js} +2 -2
- package/dist/cli/chunks/{chunk-72XSEQMW.js → chunk-FBSBXCZS.js} +2 -2
- package/dist/cli/chunks/{chunk-J7I6PABJ.js → chunk-G2X3OLMN.js} +2 -2
- package/dist/cli/chunks/{chunk-YU2BDRSD.js → chunk-GG7PMTHD.js} +1 -1
- package/dist/cli/chunks/{chunk-HLUXXCHF.js → chunk-GN6OE3JT.js} +1 -1
- package/dist/cli/chunks/{chunk-AGRV5B3T.js → chunk-GPPTRKEM.js} +2 -2
- package/dist/cli/chunks/{chunk-ZQ2XW3IP.js → chunk-H2LHWZRE.js} +2 -2
- package/dist/cli/chunks/{chunk-6DPYNAOK.js → chunk-HAQJFUAQ.js} +2 -2
- package/dist/cli/chunks/{chunk-SSUAAX3F.js → chunk-HD6W6PHV.js} +2 -2
- package/dist/cli/chunks/{chunk-L2DWPVNJ.js → chunk-HFZD5KLR.js} +1 -1
- package/dist/cli/chunks/{chunk-QVDCVD5D.js → chunk-HRUHHHVR.js} +2 -2
- package/dist/cli/chunks/{chunk-PINSJCM3.js → chunk-HVT7RMGV.js} +1 -1
- package/dist/cli/chunks/chunk-HWQPMUSN.js +2 -0
- package/dist/cli/chunks/{chunk-4NFQLP6R.js → chunk-HZ5O7G2P.js} +1 -1
- package/dist/cli/chunks/{chunk-C6D5AHBO.js → chunk-IHQGNDMX.js} +2 -2
- package/dist/cli/chunks/{chunk-QQWBWEJS.js → chunk-IJSROBM6.js} +3 -3
- package/dist/cli/chunks/{chunk-OCV2XEWQ.js → chunk-IJZFJPHS.js} +2 -2
- package/dist/cli/chunks/{chunk-N7HL5PHH.js → chunk-IKB3M7OF.js} +1 -1
- package/dist/cli/chunks/{chunk-24OX5TQJ.js → chunk-INI3Q4CN.js} +1 -1
- package/dist/cli/chunks/{chunk-SJ6Y4725.js → chunk-IOWEBPXJ.js} +2 -2
- package/dist/cli/chunks/{chunk-VXFLJNCA.js → chunk-IQL6XRF5.js} +2 -2
- package/dist/cli/chunks/{chunk-WP4RETKG.js → chunk-IRHXGCQR.js} +2 -2
- package/dist/cli/chunks/{chunk-63ZKI4PX.js → chunk-J3QFJI2Y.js} +2 -2
- package/dist/cli/chunks/{chunk-UHEOGZLX.js → chunk-J6QRNQJF.js} +5 -5
- package/dist/cli/chunks/{chunk-KNSRL6NO.js → chunk-J7Q5TXFZ.js} +2 -2
- package/dist/cli/chunks/{chunk-L6QSTQME.js → chunk-JHKKIJT2.js} +2 -2
- package/dist/cli/chunks/{chunk-VMDFFTCK.js → chunk-JI33PMPZ.js} +1 -1
- package/dist/cli/chunks/{chunk-E3D4GPLP.js → chunk-JRIJM4LE.js} +3 -3
- package/dist/cli/chunks/{chunk-XIQW7EFL.js → chunk-JVWZAE2H.js} +2 -2
- package/dist/cli/chunks/{chunk-YPBSUGMI.js → chunk-K7WAI662.js} +1 -1
- package/dist/cli/chunks/{chunk-RV74I3YO.js → chunk-KB34MTFZ.js} +2 -2
- package/dist/cli/chunks/{chunk-MI5MFHRA.js → chunk-KPIPVSIP.js} +2 -2
- package/dist/cli/chunks/{chunk-Y4PFUMOU.js → chunk-KR2TAAF6.js} +1 -1
- package/dist/cli/chunks/{chunk-W5HQUIML.js → chunk-KT2QCXO6.js} +2 -2
- package/dist/cli/chunks/{chunk-SSYAQZXA.js → chunk-KTORRIX3.js} +2 -2
- package/dist/cli/chunks/{chunk-CRPIYUTJ.js → chunk-LCWEQRZI.js} +2 -2
- package/dist/cli/chunks/{chunk-NO3IV5Q5.js → chunk-LG5PPJT7.js} +1 -1
- package/dist/cli/chunks/{chunk-5VZL4UVN.js → chunk-LIF6UWHV.js} +2 -2
- package/dist/cli/chunks/{chunk-32BPDLRZ.js → chunk-LN7NKE3N.js} +2 -2
- package/dist/cli/chunks/{chunk-ZB3LEFYG.js → chunk-LOLSZG5J.js} +2 -2
- package/dist/cli/chunks/{chunk-6XXZDV2C.js → chunk-LOMT4UC2.js} +2 -2
- package/dist/cli/chunks/{chunk-JDIYMZCQ.js → chunk-LRKLATSH.js} +2 -2
- package/dist/cli/chunks/{chunk-5SPCGMBB.js → chunk-LRY6UIRI.js} +2 -2
- package/dist/cli/chunks/{chunk-5PBLPQ5T.js → chunk-LV7UIK4Q.js} +2 -2
- package/dist/cli/chunks/{chunk-FDDC72IA.js → chunk-M2YI5YUR.js} +2 -2
- package/dist/cli/chunks/{chunk-D6COXLYE.js → chunk-MCXW3DKE.js} +2 -2
- package/dist/cli/chunks/{chunk-J442IZLE.js → chunk-MGZ6XZHU.js} +1 -1
- package/dist/cli/chunks/{chunk-TIUKLYAI.js → chunk-MLMD3I75.js} +1 -1
- package/dist/cli/chunks/{chunk-PHT5N7SC.js → chunk-MVVVGQJ6.js} +2 -2
- package/dist/cli/chunks/{chunk-525CFDUE.js → chunk-ND72UDVH.js} +2 -2
- package/dist/cli/chunks/{chunk-XWUWX7BV.js → chunk-NE3LRUNC.js} +4 -4
- package/dist/cli/chunks/{chunk-DTMAS2GB.js → chunk-NKUHMA4T.js} +2 -2
- package/dist/cli/chunks/{chunk-QPEOLAAS.js → chunk-NQFDJ6BT.js} +1 -1
- package/dist/cli/chunks/{chunk-MO55CVMT.js → chunk-NZJVDOUN.js} +14 -14
- package/dist/cli/chunks/{chunk-NZU4ACBZ.js → chunk-O7VJ3VKD.js} +2 -2
- package/dist/cli/chunks/{chunk-32GN3JKR.js → chunk-OJIUIEI4.js} +1 -1
- package/dist/cli/chunks/{chunk-UNGBRZDK.js → chunk-OO2M2QUV.js} +3 -3
- package/dist/cli/chunks/{chunk-CJSHWQXP.js → chunk-ORQ2YBRR.js} +2 -2
- package/dist/cli/chunks/chunk-OWIQR6N2.js +4 -0
- package/dist/cli/chunks/{chunk-NAEWCFQT.js → chunk-OWIZBZLN.js} +2 -2
- package/dist/cli/chunks/{chunk-24QHCVX6.js → chunk-P3D7SEHW.js} +1 -1
- package/dist/cli/chunks/{chunk-YLMNVLDK.js → chunk-P4OB6WDJ.js} +1 -1
- package/dist/cli/chunks/{chunk-PEQDY4BO.js → chunk-PCL5JRKN.js} +2 -2
- package/dist/cli/chunks/{chunk-IUBJVHNB.js → chunk-PIWGKGWP.js} +2 -2
- package/dist/cli/chunks/{chunk-GJYHWYXR.js → chunk-PK34KJH7.js} +2 -2
- package/dist/cli/chunks/{chunk-5B5QPCNU.js → chunk-POPSZDI2.js} +4 -4
- package/dist/cli/chunks/{chunk-HCH4Y6XX.js → chunk-Q6F3DYZN.js} +2 -2
- package/dist/cli/chunks/{chunk-SHKOCGNK.js → chunk-QJSSUBO3.js} +2 -2
- package/dist/cli/chunks/{chunk-DVYHMDFR.js → chunk-QN7HP2UW.js} +421 -418
- package/dist/cli/chunks/{chunk-ZFL436FN.js → chunk-QSQNXBD2.js} +2 -2
- package/dist/cli/chunks/{chunk-TVGI32MB.js → chunk-QTQDX4TZ.js} +3 -3
- package/dist/cli/chunks/{chunk-EK7OLYOZ.js → chunk-R3KBOQ3O.js} +2 -2
- package/dist/cli/chunks/{chunk-LE4QJREF.js → chunk-REY52O7J.js} +1 -1
- package/dist/cli/chunks/{chunk-LQLPB2T6.js → chunk-RKCN4B26.js} +2 -2
- package/dist/cli/chunks/{chunk-ZR2TKVXQ.js → chunk-S3DT5TPR.js} +2 -2
- package/dist/cli/chunks/{chunk-6ICX3FEG.js → chunk-S3TBOKAZ.js} +22 -22
- package/dist/cli/chunks/{chunk-JHQCRRJI.js → chunk-SAEECT23.js} +2 -2
- package/dist/cli/chunks/{chunk-VWPM27GU.js → chunk-SAZ4PJBR.js} +2 -2
- package/dist/cli/chunks/{chunk-KPRCB5LT.js → chunk-SFITYZLV.js} +2 -2
- package/dist/cli/chunks/{chunk-5LAVKGLH.js → chunk-SRBCBVSI.js} +2 -2
- package/dist/cli/chunks/{chunk-O5W3FIO6.js → chunk-SUAZ5Z47.js} +2 -2
- package/dist/cli/chunks/{chunk-KU2AUFGX.js → chunk-TDZ6N43D.js} +2 -2
- package/dist/cli/chunks/{chunk-YAPLJR7K.js → chunk-TIVKDIF7.js} +2 -2
- package/dist/cli/chunks/{chunk-U2A7NHZA.js → chunk-TM75GAXG.js} +2 -2
- package/dist/cli/chunks/{chunk-A5GBXCP5.js → chunk-TWBZONKT.js} +2 -2
- package/dist/cli/chunks/{chunk-I7MQIM2U.js → chunk-U4S74IIZ.js} +1 -1
- package/dist/cli/chunks/{chunk-3HD7E6HN.js → chunk-U5SMBJ6F.js} +2 -2
- package/dist/cli/chunks/{chunk-JQ3DYUMS.js → chunk-UHJVZEQA.js} +2 -2
- package/dist/cli/chunks/{chunk-C5FP5GW3.js → chunk-UOVCTK5L.js} +2 -2
- package/dist/cli/chunks/{chunk-HJ6ZGVTB.js → chunk-VDEKVIP5.js} +2 -2
- package/dist/cli/chunks/{chunk-KXCLACFG.js → chunk-VITV7AEC.js} +2 -2
- package/dist/cli/chunks/{chunk-P3EYRILV.js → chunk-VKREKVFI.js} +2 -2
- package/dist/cli/chunks/{chunk-2H4XH6FT.js → chunk-VLTDW7XJ.js} +2 -2
- package/dist/cli/chunks/{chunk-MD43XRX5.js → chunk-VQFV2IPV.js} +1 -1
- package/dist/cli/chunks/{chunk-67Z5R7RJ.js → chunk-VYPVU3JF.js} +2 -2
- package/dist/cli/chunks/{chunk-SDLWKRVL.js → chunk-WAOEQA3W.js} +2 -2
- package/dist/cli/chunks/{chunk-IOYG4VFL.js → chunk-WBDWHHKP.js} +2 -2
- package/dist/cli/chunks/{chunk-ASEOFRIG.js → chunk-WX4PO65Q.js} +2 -2
- package/dist/cli/chunks/chunk-X2DWHGCC.js +6 -0
- package/dist/cli/chunks/{chunk-CEYSYSK5.js → chunk-X5QD76IU.js} +2 -2
- package/dist/cli/chunks/{chunk-GSKMOPL7.js → chunk-XBTGEYED.js} +2 -2
- package/dist/cli/chunks/{chunk-FL64OUBA.js → chunk-XEMCHGAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-2YZ4G6NW.js → chunk-XEYFZLIT.js} +1 -1
- package/dist/cli/chunks/{chunk-EA4YQVKS.js → chunk-XFTX3KLE.js} +1 -1
- package/dist/cli/chunks/{chunk-HGWXF45W.js → chunk-XPTCQKVE.js} +1 -1
- package/dist/cli/chunks/{chunk-CAKMOVZ6.js → chunk-YAJOBZE5.js} +2 -2
- package/dist/cli/chunks/{chunk-NQXXI77K.js → chunk-YCVLKU6H.js} +2 -2
- package/dist/cli/chunks/{chunk-AR67RJPY.js → chunk-YD2C6EPN.js} +2 -2
- package/dist/cli/chunks/{chunk-S75SOOZL.js → chunk-YKRLUTK7.js} +2 -2
- package/dist/cli/chunks/{chunk-IOKYCMTJ.js → chunk-YMUY3TES.js} +2 -2
- package/dist/cli/chunks/{chunk-5QO3R3TU.js → chunk-YR5QBUHZ.js} +2 -2
- package/dist/cli/chunks/{chunk-AJMJNQMP.js → chunk-Z7SKUC6P.js} +1 -1
- package/dist/cli/chunks/{chunk-KITOPKRG.js → chunk-ZAQMRFBB.js} +2 -2
- package/dist/cli/chunks/{chunk-AAMLQ2LF.js → chunk-ZC3KDNJW.js} +3 -3
- package/dist/cli/chunks/{chunk-VJCIEHEF.js → chunk-ZGV7L4MW.js} +1 -1
- package/dist/cli/chunks/{chunk-BY5OF7OH.js → chunk-ZN35XSKF.js} +2 -2
- package/dist/cli/chunks/{chunk-KKU2QGSJ.js → chunk-ZNXM6WVL.js} +2 -2
- package/dist/cli/chunks/{chunk-FLNAW7C4.js → chunk-ZP5AWQRO.js} +2 -2
- package/dist/cli/chunks/{chunk-IHRXZZQM.js → chunk-ZTP3DQ5M.js} +1 -1
- package/dist/cli/chunks/{chunk-OAEE6JWQ.js → chunk-ZVMSSCTH.js} +2 -2
- package/dist/cli/chunks/{chunk-M7WJCTG3.js → chunk-ZWUF27P4.js} +2 -2
- package/dist/cli/chunks/{ci-MFUR4CWV.js → ci-3RTTTS2D.js} +2 -2
- package/dist/cli/chunks/{ci-config-PNDLQ6XV.js → ci-config-XRUR3I4K.js} +2 -2
- package/dist/cli/chunks/{ci-output-PFZ4M7NC.js → ci-output-E5IAMU2U.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-5HH6NLZN.js → circuit-breaker-SHR2P44P.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-QCKYLGLC.js → claude-flow-setup-ZDDILFMF.js} +2 -2
- package/dist/cli/chunks/client-NO5FOWT4.js +2 -0
- package/dist/cli/chunks/{cline-installer-EASVPFXR.js → cline-installer-BGYVUM6G.js} +2 -2
- package/dist/cli/chunks/{code-UJXDVYRK.js → code-PJ4MC3MC.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-BZJ3UDP4.js → code-index-extractor-IW2P22YG.js} +2 -2
- package/dist/cli/chunks/{codex-installer-XSQZUVOZ.js → codex-installer-A7WZ6OGL.js} +2 -2
- package/dist/cli/chunks/{completions-OWOOJFI2.js → completions-KS23WD5J.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-KP5TOHDT.js → complexity-analyzer-Q7GLSR2E.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-IFKQXLHM.js → continuedev-installer-SK55BFW2.js} +2 -2
- package/dist/cli/chunks/copilot-installer-3N5J3WTM.js +3 -0
- package/dist/cli/chunks/core-handlers-JNAZPXE2.js +2 -0
- package/dist/cli/chunks/{cost-tracker-MMDDNKZB.js → cost-tracker-NENVSO4A.js} +2 -2
- package/dist/cli/chunks/{coverage-LUH2B7NT.js → coverage-5L7UQWDH.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-HEBM767Z.js +2 -0
- package/dist/cli/chunks/{cursor-installer-4YLM5GWM.js → cursor-installer-XXBO2ZE6.js} +2 -2
- package/dist/cli/chunks/{daemon-MZKVM4CJ.js → daemon-CDCQU3LR.js} +3 -3
- package/dist/cli/chunks/{daemon-CAVZ7OFV.js → daemon-JEBJGEUK.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-X4CYW665.js → dag-attention-scheduler-HOMMF7FA.js} +2 -2
- package/dist/cli/chunks/{detect-7BM2XINO.js → detect-FXCOUG6X.js} +2 -2
- package/dist/cli/chunks/{dist-node-Y5APLEYB.js → dist-node-GXQ7FMTY.js} +2 -2
- package/dist/cli/chunks/{domain-handler-X3ZRJNAH.js → domain-handler-TI3JBAPC.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-2UW5KQJB.js → domain-plugins-R7LTUM32.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-35W4CIBV.js → domain-transfer-LBIAFHIQ.js} +2 -2
- package/dist/cli/chunks/dream-GQDCEJMS.js +2 -0
- package/dist/cli/chunks/embed-and-insert-pattern-33KLHDD5.js +3 -0
- package/dist/cli/chunks/{embedding-space-SBM2MZD2.js → embedding-space-HHLWTBF5.js} +2 -2
- package/dist/cli/chunks/{eval-4QA2SROK.js → eval-KDOZMAXJ.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-Z6BF6KYM.js → experience-capture-middleware-X45PECQN.js} +3 -3
- package/dist/cli/chunks/{fast-paths-FIORX6GN.js → fast-paths-462V6UUB.js} +2 -2
- package/dist/cli/chunks/{feature-flags-ZOO7LMIC.js → feature-flags-G66OT3AS.js} +2 -2
- package/dist/cli/chunks/{feature-flags-6LYI2T4G.js → feature-flags-NIRQ4YDM.js} +2 -2
- package/dist/cli/chunks/file-discovery-33USPLB5.js +2 -0
- package/dist/cli/chunks/{fleet-7WF53H4F.js → fleet-PXWGB7CU.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-KJ6B7BRM.js → gnn-wrapper-7MUW3M5M.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-DEKKMOVW.js → heartbeat-handler-5237PB35.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-LIXLC5IH.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-62D5UH27.js +2 -0
- package/dist/cli/chunks/hnsw-index-GSGUMQQC.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-L27WS27N.js → hnsw-legacy-bridge-OSQPW7JP.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-4YOQC6L4.js → hnswlib-node-GX6WG2GB.js} +2 -2
- package/dist/cli/chunks/{hooks-TAOKV4EJ.js → hooks-GUWHL7VC.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-FRWP4BOY.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-BODRJLHL.js → hypergraph-engine-SRWLLCU3.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-RKMYJNTU.js → hypergraph-handler-AVOPRHHO.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-7KF3AQXV.js +2 -0
- package/dist/cli/chunks/{init-guard-MXHSLSB2.js → init-guard-P4N6EVZS.js} +2 -2
- package/dist/cli/chunks/{init-handler-HUE57IFW.js → init-handler-LRGWOJMD.js} +6 -6
- package/dist/cli/chunks/init-wizard-XWWAXY25.js +2 -0
- package/dist/cli/chunks/kernel-ZEJPNDBW.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-S333IKYQ.js → kilocode-installer-7R2EPOQ6.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-WM5DLQWC.js → kiro-installer-QNM7DPOB.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-RRZQS7KY.js +2 -0
- package/dist/cli/chunks/{learning-LNHMQLH5.js → learning-7OIZBPXZ.js} +3 -3
- package/dist/cli/chunks/{llm-router-EWFXYZZR.js → llm-router-SIDXES23.js} +4 -4
- package/dist/cli/chunks/llm-router-service-3OSW67LC.js +2 -0
- package/dist/cli/chunks/{load-FGYGWVDK.js → load-EI2E2C3S.js} +2 -2
- package/dist/cli/chunks/load-test-7TRIH2WJ.js +2 -0
- package/dist/cli/chunks/{mcp-2FHNAAOM.js → mcp-IOE5WOCS.js} +2 -2
- package/dist/cli/chunks/{memory-DZMQ73AB.js → memory-DLYGJAP7.js} +5 -5
- package/dist/cli/chunks/memory-backend-G7ZW6Q2B.js +2 -0
- package/dist/cli/chunks/memory-handlers-TPF3KCO5.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-6F2UAEUW.js → multi-model-executor-WHH4YCHM.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-XY3BGOTZ.js → opencode-installer-63FDZAMS.js} +2 -2
- package/dist/cli/chunks/{orchestrator-B4CNKUOS.js → orchestrator-3LA776KK.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-OU3ZC3NR.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-R4GUFNMD.js → pattern-usage-recorder-NW54QUGI.js} +2 -2
- package/dist/cli/chunks/{pipeline-FG5RKVRO.js → pipeline-P3TYX6J6.js} +2 -2
- package/dist/cli/chunks/{platform-3BT4KEVJ.js → platform-FNA2WLI6.js} +2 -2
- package/dist/cli/chunks/{plugin-WI4RIN7O.js → plugin-NJS7BC2S.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-7ECDNQFS.js → prime-radiant-advanced-wasm-NIAVL2OT.js} +2 -2
- package/dist/cli/chunks/project-root-GMOFJEKD.js +2 -0
- package/dist/cli/chunks/protocol-executor-AD345XRO.js +2 -0
- package/dist/cli/chunks/{protocol-handler-WNODKPGW.js → protocol-handler-JU5C4JHY.js} +2 -2
- package/dist/cli/chunks/{prove-5RHAEPYZ.js → prove-35VOSLYP.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-NLTP26RC.js +2 -0
- package/dist/cli/chunks/{quality-WPHR7BGQ.js → quality-ET74X7HN.js} +2 -2
- package/dist/cli/chunks/{quality-gate-4RKTEZMX.js → quality-gate-FEDQISNB.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-2TB4FWS6.js +2 -0
- package/dist/cli/chunks/real-embeddings-II6CXTCI.js +2 -0
- package/dist/cli/chunks/{ref-validation-TPAWHOHH.js → ref-validation-DTBPYCEB.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-7AVHFNDI.js → roocode-installer-LYQEMR4J.js} +2 -2
- package/dist/cli/chunks/router-PLM3MWME.js +2 -0
- package/dist/cli/chunks/routing-feedback-I7VOX2HU.js +2 -0
- package/dist/cli/chunks/{routing-handler-YKEDVJSH.js → routing-handler-DJOJFPII.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-JUAMM354.js → ruvector-commands-VXYGJDPW.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-GQZHFWO2.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-3TVKBCAM.js +2 -0
- package/dist/cli/chunks/rvf-migration-coordinator-XUHKLMT6.js +2 -0
- package/dist/cli/chunks/rvf-native-adapter-5GUTYOWS.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-VJDUIRTX.js → rvf-store-integrity-GA2ZYOEG.js} +2 -2
- package/dist/cli/chunks/safe-db-RZPQGLGQ.js +2 -0
- package/dist/cli/chunks/schedule-G7JMQDUX.js +2 -0
- package/dist/cli/chunks/scheduler-4SEGPCKD.js +2 -0
- package/dist/cli/chunks/{security-ORDN3RD2.js → security-MM6YOECX.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-CF4BCIO7.js → shared-rvf-adapter-6AHPA3V5.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-C32UBR6D.js → shared-rvf-dual-writer-EYAVY2GZ.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-IVE4SQXR.js +2 -0
- package/dist/cli/chunks/{standalone-memory-OXRJYZXN.js → standalone-memory-A3PLB4CZ.js} +2 -2
- package/dist/cli/chunks/{status-handler-BCX5D4HY.js → status-handler-OSSFAP4Z.js} +2 -2
- package/dist/cli/chunks/{structural-health-LFG7RUU6.js → structural-health-PGY5XUNO.js} +2 -2
- package/dist/cli/chunks/{sync-YJEE2K2L.js → sync-CWEHYGNN.js} +2 -2
- package/dist/cli/chunks/sync-PM6D7EQF.js +2 -0
- package/dist/cli/chunks/{task-handler-6LXKPTXJ.js → task-handler-LHMQ75W4.js} +2 -2
- package/dist/cli/chunks/{task-handlers-CILP36I7.js → task-handlers-S2TX5FTR.js} +3 -3
- package/dist/cli/chunks/test-4EGZZ6NJ.js +34 -0
- package/dist/cli/chunks/test-runner-process-72YACW6M.js +2 -0
- package/dist/cli/chunks/{test-scheduling-ISI2O4Q5.js → test-scheduling-YJQHH3XE.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-VUELSBOS.js → token-bootstrap-DJNETMVW.js} +2 -2
- package/dist/cli/chunks/{token-usage-XOC5KG7S.js → token-usage-WPNOJR6H.js} +2 -2
- package/dist/cli/chunks/{transformers-LSLQAARK.js → transformers-4MRPXCPU.js} +2 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-UVWSDXFR.js +2 -0
- package/dist/cli/chunks/{types-5BLCGLCR.js → types-6P5FB4EB.js} +2 -2
- package/dist/cli/chunks/unified-memory-2VMGSGQL.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-3KULVD3N.js +2 -0
- package/dist/cli/chunks/unified-persistence-QCSLU2SV.js +2 -0
- package/dist/cli/chunks/{upgrade-RQJYLK3J.js → upgrade-4ICTN63Y.js} +2 -2
- package/dist/cli/chunks/{validate-QBHWXXCK.js → validate-HQF5GZ7L.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-IKXBKFB5.js → validate-swarm-45JYG7VW.js} +2 -2
- package/dist/cli/chunks/visual-security-ZYP2KPH7.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-ZF6FIE5R.js → web-tree-sitter-UOTWZLNH.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-HQGDZT5D.js → windsurf-installer-WDWSBXGN.js} +2 -2
- package/dist/cli/chunks/witness-chain-5QRT7EMX.js +2 -0
- package/dist/cli/chunks/{witness-chain-DCHCAMSQ.js → witness-chain-DOYMNPC7.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-PUX2NFDL.js → witness-chain-repair-CUF2AFQB.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-PX2OQ6XT.js → witness-chain-verifier-JB42X62J.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-RXYQNFJB.js → witness-key-manager-LXXO6L2G.js} +2 -2
- package/dist/cli/chunks/{workflow-FBKCA4H6.js → workflow-6ARK47NF.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-RYDDWIXN.js +2 -0
- package/dist/cli/chunks/{wrappers-TWSKBTWD.js → wrappers-CYQBOMPL.js} +2 -2
- package/dist/cli/commands/test.js +26 -4
- package/dist/coordination/handlers/test-execution-handlers.js +64 -20
- package/dist/domains/code-intelligence/services/semantic-analyzer.d.ts +8 -3
- package/dist/domains/code-intelligence/services/semantic-analyzer.js +39 -25
- package/dist/domains/code-intelligence/services/text-relevance.d.ts +32 -0
- package/dist/domains/code-intelligence/services/text-relevance.js +63 -0
- package/dist/domains/test-execution/coordinator.d.ts +3 -1
- package/dist/domains/test-execution/coordinator.js +13 -4
- package/dist/domains/test-execution/interfaces.d.ts +5 -0
- package/dist/domains/test-execution/plugin.js +2 -0
- package/dist/domains/test-execution/services/flaky-detector.d.ts +9 -1
- package/dist/domains/test-execution/services/flaky-detector.js +26 -8
- package/dist/domains/test-execution/services/retry-handler.d.ts +7 -1
- package/dist/domains/test-execution/services/retry-handler.js +44 -5
- package/dist/domains/test-execution/services/runner-test-cases.d.ts +2 -0
- package/dist/domains/test-execution/services/runner-test-cases.js +7 -3
- package/dist/domains/test-execution/services/test-executor.d.ts +5 -1
- package/dist/domains/test-execution/services/test-executor.js +79 -15
- package/dist/init/copilot-installer.d.ts +6 -0
- package/dist/init/copilot-installer.js +37 -17
- package/dist/init/platform-config-generator.d.ts +10 -0
- package/dist/init/platform-config-generator.js +26 -1
- package/dist/kernel/unified-memory.d.ts +8 -0
- package/dist/kernel/unified-memory.js +13 -0
- package/dist/learning/embedder-endpoint-client.d.ts +45 -0
- package/dist/learning/embedder-endpoint-client.js +98 -3
- package/dist/learning/embedding-space-registry.d.ts +75 -0
- package/dist/learning/embedding-space-registry.js +142 -0
- package/dist/learning/real-embeddings.d.ts +3 -0
- package/dist/learning/real-embeddings.js +49 -11
- package/dist/mcp/bundle.js +564 -555
- package/dist/mcp/protocol-server.js +1 -1
- package/dist/shared/embeddings/index.d.ts +2 -2
- package/dist/shared/embeddings/index.js +1 -1
- package/dist/shared/embeddings/nomic-embedder.d.ts +8 -2
- package/dist/shared/embeddings/nomic-embedder.js +19 -11
- package/dist/shared/embeddings/ollama-client.d.ts +28 -2
- package/dist/shared/embeddings/ollama-client.js +84 -22
- package/dist/shared/embeddings/types.d.ts +15 -0
- package/dist/shared/embeddings/types.js +4 -0
- package/dist/shared/pytest-junit-report.d.ts +93 -0
- package/dist/shared/pytest-junit-report.js +241 -0
- package/dist/shared/test-runner-project.d.ts +51 -1
- package/dist/shared/test-runner-project.js +140 -25
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-6CQ2PIP5.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-73RR52VS.js +0 -2
- package/dist/cli/chunks/base-SMCMMVGP.js +0 -2
- package/dist/cli/chunks/browser-workflow-A2MEZ66K.js +0 -2
- package/dist/cli/chunks/chunk-EGYE5UPQ.js +0 -2
- package/dist/cli/chunks/chunk-KL7OKSU2.js +0 -4
- package/dist/cli/chunks/chunk-M4FRQ4TE.js +0 -12
- package/dist/cli/chunks/chunk-UE5ZOZR2.js +0 -2
- package/dist/cli/chunks/client-MHQRTZM4.js +0 -2
- package/dist/cli/chunks/copilot-installer-IGJ6KGQY.js +0 -3
- package/dist/cli/chunks/core-handlers-UAK3LLJE.js +0 -2
- package/dist/cli/chunks/cross-domain-router-WTRZQPNQ.js +0 -2
- package/dist/cli/chunks/dream-EJY24JN6.js +0 -2
- package/dist/cli/chunks/embed-and-insert-pattern-COG4C7ZI.js +0 -3
- package/dist/cli/chunks/file-discovery-UZSFSS4V.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-NVR356I7.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-LFMPLUJU.js +0 -2
- package/dist/cli/chunks/hnsw-index-POCPMVJH.js +0 -2
- package/dist/cli/chunks/hybrid-backend-4STAO7CV.js +0 -2
- package/dist/cli/chunks/impact-analyzer-3VIIISBQ.js +0 -2
- package/dist/cli/chunks/init-wizard-PL6QN6RQ.js +0 -2
- package/dist/cli/chunks/kernel-CCDWT7KS.js +0 -2
- package/dist/cli/chunks/knowledge-graph-KFOMEN3H.js +0 -2
- package/dist/cli/chunks/llm-router-service-7NBE2EX6.js +0 -2
- package/dist/cli/chunks/load-test-UNZUWY3F.js +0 -2
- package/dist/cli/chunks/memory-backend-DFGKWA2Q.js +0 -2
- package/dist/cli/chunks/memory-handlers-MP426XRJ.js +0 -2
- package/dist/cli/chunks/pattern-null-store-SSVF5TE5.js +0 -2
- package/dist/cli/chunks/project-root-BEANNYWU.js +0 -2
- package/dist/cli/chunks/protocol-executor-FQVIHXZ7.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-5TFYSE24.js +0 -2
- package/dist/cli/chunks/queen-coordinator-Y2OUL7IN.js +0 -2
- package/dist/cli/chunks/real-embeddings-OXLYU7JW.js +0 -2
- package/dist/cli/chunks/router-EP34O3KB.js +0 -2
- package/dist/cli/chunks/routing-feedback-FJCRKXNG.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-ILITJSFG.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-XF6W4C2N.js +0 -2
- package/dist/cli/chunks/rvf-migration-coordinator-CMKG56AR.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-7YFW6S4Y.js +0 -2
- package/dist/cli/chunks/safe-db-TCAU4FUT.js +0 -2
- package/dist/cli/chunks/schedule-NB5KV435.js +0 -2
- package/dist/cli/chunks/scheduler-JKXGKVK6.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-IXCNZRTW.js +0 -2
- package/dist/cli/chunks/sync-OSF7C2NL.js +0 -2
- package/dist/cli/chunks/test-SD457QJ6.js +0 -34
- package/dist/cli/chunks/test-runner-process-VKD65QQU.js +0 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-YAIPHRIL.js +0 -2
- package/dist/cli/chunks/unified-memory-GI76TXFV.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-GXJ5BTZO.js +0 -2
- package/dist/cli/chunks/unified-persistence-OP7FDQPD.js +0 -2
- package/dist/cli/chunks/visual-security-GZ2MOKWB.js +0 -2
- package/dist/cli/chunks/witness-chain-P3XXXA62.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-P2APAJAA.js +0 -2
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1248: running pytest and reading its JUnit XML report.
|
|
3
|
+
*
|
|
4
|
+
* pytest is started as `<python> -m pytest <files> --junitxml=<file>`, with
|
|
5
|
+
* the report in a temporary directory owned by the run, so the result never
|
|
6
|
+
* depends on the console summary. The interpreter is `AQE_PYTHON` when set,
|
|
7
|
+
* otherwise `python` when it is on PATH, otherwise `python3`.
|
|
8
|
+
*
|
|
9
|
+
* The report is read with a small parser for the XML pytest writes (one or
|
|
10
|
+
* more `<testsuite>` elements holding `<testcase>` elements, each with an
|
|
11
|
+
* optional `<failure>`, `<error>` or `<skipped>` child). Counts come from the
|
|
12
|
+
* test cases themselves, so they always match the per-test list. An expected
|
|
13
|
+
* failure (xfail) is reported by pytest as skipped and counted as skipped.
|
|
14
|
+
*
|
|
15
|
+
* A run is only a result when pytest finished its tests: exit code 5 (no
|
|
16
|
+
* tests collected), 2 (interrupted, for example by a collection error),
|
|
17
|
+
* 3 (internal error) and 4 (usage error), or a missing report (pytest not
|
|
18
|
+
* installed for the interpreter), are runner errors, never a pass.
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, statSync } from 'node:fs';
|
|
21
|
+
import { tmpdir } from 'node:os';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import { capDiagnostics, getTestRunnerExecutionError, TestRunnerExecutionError } from './test-runner-verdict.js';
|
|
24
|
+
import { ok, err } from './types/index.js';
|
|
25
|
+
/** True for a Python test file, which only pytest can run. */
|
|
26
|
+
export function isPythonTestFile(file) {
|
|
27
|
+
return /\.py$/i.test(file);
|
|
28
|
+
}
|
|
29
|
+
function onPath(command, env) {
|
|
30
|
+
const names = process.platform === 'win32' ? [`${command}.exe`, `${command}.cmd`, command] : [command];
|
|
31
|
+
for (const dir of (env.PATH ?? env.Path ?? '').split(path.delimiter)) {
|
|
32
|
+
if (!dir)
|
|
33
|
+
continue;
|
|
34
|
+
for (const name of names) {
|
|
35
|
+
try {
|
|
36
|
+
if (statSync(path.join(dir, name)).isFile())
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Not in this directory.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/** The Python interpreter that runs pytest. */
|
|
47
|
+
export function resolvePythonCommand(env = process.env) {
|
|
48
|
+
const configured = env.AQE_PYTHON?.trim();
|
|
49
|
+
if (configured)
|
|
50
|
+
return configured;
|
|
51
|
+
if (onPath('python', env))
|
|
52
|
+
return 'python';
|
|
53
|
+
return onPath('python3', env) ? 'python3' : 'python';
|
|
54
|
+
}
|
|
55
|
+
/** Environment for a pytest process: no ANSI colour in its output or report. */
|
|
56
|
+
export const PYTEST_ENV = { PY_COLORS: '0' };
|
|
57
|
+
/** Command and arguments that run `targets` (paths or node ids) with pytest. */
|
|
58
|
+
export function pytestCommand(targets, reportPath, env = process.env) {
|
|
59
|
+
return {
|
|
60
|
+
command: resolvePythonCommand(env),
|
|
61
|
+
// No colour: runners are started with FORCE_COLOR set, which pytest reads
|
|
62
|
+
// as "force colour" (even in its report). PY_COLORS=0 (PYTEST_ENV) wins
|
|
63
|
+
// over FORCE_COLOR; --color=no covers the console output.
|
|
64
|
+
args: ['-m', 'pytest', ...targets, `--junitxml=${reportPath}`, '--color=no'],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function createPytestJunitReport() {
|
|
68
|
+
const dir = mkdtempSync(path.join(tmpdir(), 'aqe-pytest-report-'));
|
|
69
|
+
const reportPath = path.join(dir, 'junit.xml');
|
|
70
|
+
let cleaned = false;
|
|
71
|
+
return {
|
|
72
|
+
path: reportPath,
|
|
73
|
+
args: [],
|
|
74
|
+
read: () => {
|
|
75
|
+
if (!existsSync(reportPath))
|
|
76
|
+
return undefined;
|
|
77
|
+
const text = readFileSync(reportPath, 'utf-8');
|
|
78
|
+
if (!/<testsuite\b/.test(text))
|
|
79
|
+
throw new TestRunnerExecutionError('The current pytest JUnit report is malformed.');
|
|
80
|
+
return text;
|
|
81
|
+
},
|
|
82
|
+
cleanup: () => {
|
|
83
|
+
if (cleaned)
|
|
84
|
+
return;
|
|
85
|
+
cleaned = true;
|
|
86
|
+
try {
|
|
87
|
+
rmSync(dir, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Best effort: a leftover temp dir is not worth failing a test run over.
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function unescapeXml(text) {
|
|
96
|
+
return text.replace(/&(#x[0-9a-f]+|#\d+|lt|gt|amp|quot|apos);/gi, (_, entity) => {
|
|
97
|
+
const lower = entity.toLowerCase();
|
|
98
|
+
if (lower === 'lt')
|
|
99
|
+
return '<';
|
|
100
|
+
if (lower === 'gt')
|
|
101
|
+
return '>';
|
|
102
|
+
if (lower === 'amp')
|
|
103
|
+
return '&';
|
|
104
|
+
if (lower === 'quot')
|
|
105
|
+
return '"';
|
|
106
|
+
if (lower === 'apos')
|
|
107
|
+
return '\'';
|
|
108
|
+
const code = lower.startsWith('#x') ? parseInt(lower.slice(2), 16) : parseInt(lower.slice(1), 10);
|
|
109
|
+
return Number.isFinite(code) && code >= 0 && code <= 0x10ffff ? String.fromCodePoint(code) : '';
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function attributes(text) {
|
|
113
|
+
const attrs = {};
|
|
114
|
+
for (const match of text.matchAll(/([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
|
|
115
|
+
attrs[match[1]] = unescapeXml(match[2] ?? match[3] ?? '');
|
|
116
|
+
}
|
|
117
|
+
return attrs;
|
|
118
|
+
}
|
|
119
|
+
/** The test cases of a pytest JUnit XML report, in report order. */
|
|
120
|
+
export function parsePytestJunitXml(xml) {
|
|
121
|
+
if (!/<testsuite\b/.test(xml))
|
|
122
|
+
throw new Error('Not a JUnit XML report: no <testsuite> element.');
|
|
123
|
+
const cases = [];
|
|
124
|
+
const testcase = /<testcase\b((?:[^>"']|"[^"]*"|'[^']*')*?)(?:\/>|>([\s\S]*?)<\/testcase>)/g;
|
|
125
|
+
for (const match of xml.matchAll(testcase)) {
|
|
126
|
+
const attrs = attributes(match[1]);
|
|
127
|
+
const body = match[2] ?? '';
|
|
128
|
+
// An error (setup/teardown) outranks a failure in the same test case.
|
|
129
|
+
const child = (tag) => body.match(new RegExp(`<${tag}\\b((?:[^>"']|"[^"]*"|'[^']*')*?)(?:\\/>|>([\\s\\S]*?)<\\/${tag}>)`));
|
|
130
|
+
const error = child('error');
|
|
131
|
+
const failure = child('failure');
|
|
132
|
+
const skipped = child('skipped');
|
|
133
|
+
const outcome = error ?? failure ?? skipped;
|
|
134
|
+
const status = error ? 'error' : failure ? 'failed' : skipped ? 'skipped' : 'passed';
|
|
135
|
+
const seconds = Number.parseFloat(attrs.time ?? '');
|
|
136
|
+
const message = outcome ? attributes(outcome[1]).message : undefined;
|
|
137
|
+
const details = outcome?.[2] !== undefined ? unescapeXml(outcome[2]).trim() : undefined;
|
|
138
|
+
cases.push({
|
|
139
|
+
classname: attrs.classname ?? '',
|
|
140
|
+
name: attrs.name ?? '',
|
|
141
|
+
status,
|
|
142
|
+
...(Number.isFinite(seconds) ? { duration: Math.round(seconds * 1000) } : {}),
|
|
143
|
+
...(message ? { message } : {}),
|
|
144
|
+
...(details ? { details } : {}),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return cases;
|
|
148
|
+
}
|
|
149
|
+
/** A collection error is reported as an error case with no class name. */
|
|
150
|
+
function isCollectionError(testCase) {
|
|
151
|
+
return testCase.status === 'error' && (testCase.classname === '' || testCase.message === 'collection failure');
|
|
152
|
+
}
|
|
153
|
+
function pathSegments(file) {
|
|
154
|
+
return file.replace(/\.py$/i, '').split(/[\\/]+/).filter(Boolean);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The run file a test case belongs to, and its name inside that file
|
|
158
|
+
* (`TestClass::test_name[param]`, the node id without the file). The class
|
|
159
|
+
* name is the module's dotted path relative to pytest's rootdir followed by
|
|
160
|
+
* any classes, so the file is the one whose path ends with the longest
|
|
161
|
+
* leading part of it.
|
|
162
|
+
*/
|
|
163
|
+
export function locatePytestCase(testCase, files) {
|
|
164
|
+
const dotted = testCase.classname ? testCase.classname.split('.') : [];
|
|
165
|
+
let best;
|
|
166
|
+
for (const file of files) {
|
|
167
|
+
const segments = pathSegments(file);
|
|
168
|
+
for (let length = Math.min(dotted.length, segments.length); length > 0; length--) {
|
|
169
|
+
const tail = segments.slice(segments.length - length);
|
|
170
|
+
if (tail.every((segment, index) => segment === dotted[index])) {
|
|
171
|
+
if (!best || length > best.matched)
|
|
172
|
+
best = { file, matched: length };
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (!best) {
|
|
178
|
+
return {
|
|
179
|
+
file: files.length === 1 ? files[0] : files.join(', '),
|
|
180
|
+
name: testCase.classname ? `${testCase.classname}::${testCase.name}` : testCase.name,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return { file: best.file, name: [...dotted.slice(best.matched), testCase.name].join('::') };
|
|
184
|
+
}
|
|
185
|
+
const PYTEST_EXIT_REASONS = {
|
|
186
|
+
2: 'was interrupted (for example by a collection error)',
|
|
187
|
+
3: 'hit an internal error',
|
|
188
|
+
4: 'rejected its command line',
|
|
189
|
+
5: 'collected no tests',
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* The result of a finished pytest run, or the runner error that kept it from
|
|
193
|
+
* being one. `report` is the JUnit XML text, undefined when pytest wrote none.
|
|
194
|
+
* A test case that errored (in a fixture, say) counts as a failed test.
|
|
195
|
+
*/
|
|
196
|
+
export function pytestRunFromReport(report, files, exitCode, output, python = resolvePythonCommand()) {
|
|
197
|
+
const label = files.join(', ');
|
|
198
|
+
if (report === undefined) {
|
|
199
|
+
const notInstalled = /No module named pytest/.test(output);
|
|
200
|
+
return err(new TestRunnerExecutionError(`pytest wrote no JUnit report for ${label} (exit code ${exitCode ?? 'unknown'}).` +
|
|
201
|
+
(notInstalled
|
|
202
|
+
? ` pytest is not installed for '${python}'; install it, or set AQE_PYTHON to an interpreter that has it.`
|
|
203
|
+
: ` Check that '${python} -m pytest' runs; set AQE_PYTHON to choose the interpreter.`) +
|
|
204
|
+
(output.trim() ? `\n${capDiagnostics(output.trim())}` : '')));
|
|
205
|
+
}
|
|
206
|
+
let cases;
|
|
207
|
+
try {
|
|
208
|
+
cases = parsePytestJunitXml(report);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
return err(new TestRunnerExecutionError(`Could not read the pytest JUnit report for ${label}: ${error instanceof Error ? error.message : String(error)}`));
|
|
212
|
+
}
|
|
213
|
+
const collectionErrors = cases.filter(isCollectionError);
|
|
214
|
+
const exitReason = exitCode !== null ? PYTEST_EXIT_REASONS[exitCode] : undefined;
|
|
215
|
+
if (exitReason || collectionErrors.length > 0) {
|
|
216
|
+
const reasons = collectionErrors.map(c => `${c.name}: ${c.details ?? c.message ?? 'collection failure'}`);
|
|
217
|
+
return err(new TestRunnerExecutionError(`pytest ${exitReason ?? 'reported a collection error'} for ${label} (exit code ${exitCode ?? 'unknown'}).` +
|
|
218
|
+
`\n${capDiagnostics([...reasons, output.trim()].filter(Boolean).join('\n'))}`));
|
|
219
|
+
}
|
|
220
|
+
const tests = cases.map(testCase => {
|
|
221
|
+
const { file, name } = locatePytestCase(testCase, files);
|
|
222
|
+
const failed = testCase.status === 'failed' || testCase.status === 'error';
|
|
223
|
+
const failureMessage = failed
|
|
224
|
+
? [testCase.message, testCase.details].filter(Boolean).join('\n') || 'Test failed'
|
|
225
|
+
: undefined;
|
|
226
|
+
return {
|
|
227
|
+
name, file,
|
|
228
|
+
status: failed ? 'failed' : testCase.status === 'skipped' ? 'skipped' : 'passed',
|
|
229
|
+
...(testCase.duration !== undefined ? { duration: testCase.duration } : {}),
|
|
230
|
+
...(failureMessage ? { failureMessage } : {}),
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
const passed = tests.filter(t => t.status === 'passed').length;
|
|
234
|
+
const failed = tests.filter(t => t.status === 'failed').length;
|
|
235
|
+
const skipped = tests.filter(t => t.status === 'skipped').length;
|
|
236
|
+
const executionError = getTestRunnerExecutionError('pytest', label, exitCode, { passed, failed, skipped }, output);
|
|
237
|
+
if (executionError)
|
|
238
|
+
return err(executionError);
|
|
239
|
+
return ok({ total: tests.length, passed, failed, skipped, tests });
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=pytest-junit-report.js.map
|
|
@@ -14,6 +14,26 @@
|
|
|
14
14
|
* A run from the current working directory is kept whenever that directory is
|
|
15
15
|
* already inside the file's runner project (a single-project repository, or a
|
|
16
16
|
* server started inside the package), so those runs behave as before.
|
|
17
|
+
*
|
|
18
|
+
* #1272: a package with its own config runs from that package, even when the
|
|
19
|
+
* root config also lists it in `test.projects` (or a `vitest.workspace.*`).
|
|
20
|
+
* Settings that only the root config adds to that project (its setup files,
|
|
21
|
+
* aliases or environment) are then not applied; the package's own config is
|
|
22
|
+
* what runs. A package without its own config still runs from the root.
|
|
23
|
+
*
|
|
24
|
+
* #1272: `vite.config.*` counts only when its text contains `test:`. The
|
|
25
|
+
* config is code, and reading what it exports would mean running it, so a
|
|
26
|
+
* `test` block built some other way (spread from another module, say) is not
|
|
27
|
+
* seen and a `test:` that only appears in a comment is. Name the runner config
|
|
28
|
+
* `vitest.config.*` for an exact match.
|
|
29
|
+
*
|
|
30
|
+
* #1248: a Python test file belongs to the nearest directory with pytest
|
|
31
|
+
* configuration instead (`pytest.ini`, `pyproject.toml` with
|
|
32
|
+
* `[tool.pytest.ini_options]`, `setup.cfg` with `[tool:pytest]`, `tox.ini`
|
|
33
|
+
* with `[pytest]`), and JavaScript files ignore that configuration. A
|
|
34
|
+
* `conftest.py` marks a pytest project for detection but is not a directory
|
|
35
|
+
* to run from: it is often in `tests/`, and pytest started there would not
|
|
36
|
+
* have the project root on `sys.path`.
|
|
17
37
|
*/
|
|
18
38
|
import { Result } from './types';
|
|
19
39
|
/**
|
|
@@ -34,8 +54,30 @@ export interface RunnerProjectGroup {
|
|
|
34
54
|
cwd: string;
|
|
35
55
|
files: string[];
|
|
36
56
|
}
|
|
57
|
+
/** A runner whose project configuration can be recognised from its files. */
|
|
58
|
+
export type RunnerFramework = 'vitest' | 'jest';
|
|
37
59
|
/** True when `dir` holds a Vitest or Jest configuration. */
|
|
38
60
|
export declare function isRunnerProjectDir(dir: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* #1248: true when `dir` holds pytest configuration; with `conftest`, a
|
|
63
|
+
* `conftest.py` counts too (see the header note).
|
|
64
|
+
*/
|
|
65
|
+
export declare function isPytestProjectDir(dir: string, conftest?: boolean): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* #1248: true when `dir`, or a directory above it no higher than `boundary`,
|
|
68
|
+
* is configured for pytest (including a `conftest.py`).
|
|
69
|
+
*/
|
|
70
|
+
export declare function isPytestProject(dir: string, boundary?: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* #1272: the runner configured by the runner project that `dir` belongs to:
|
|
73
|
+
* the nearest directory at or above `dir`, no higher than `boundary`, with
|
|
74
|
+
* runner configuration. Jest config (`jest.config.*`, or a `jest` key in
|
|
75
|
+
* package.json) means jest; Vitest config (`vitest.config.*`,
|
|
76
|
+
* `vitest.workspace.*`, a `vite.config.*` with `test`, or a `vitest` key)
|
|
77
|
+
* means vitest. Undefined when no project is found or it configures both, so
|
|
78
|
+
* the caller keeps its own choice.
|
|
79
|
+
*/
|
|
80
|
+
export declare function runnerFrameworkFor(dir: string, boundary?: string): RunnerFramework | undefined;
|
|
39
81
|
/**
|
|
40
82
|
* The nearest directory at or above `file` with runner configuration, searching no
|
|
41
83
|
* higher than `boundary`. Undefined when the file lies outside the boundary or
|
|
@@ -50,7 +92,8 @@ export declare function findRunnerProjectDir(file: string, boundary: string, cwd
|
|
|
50
92
|
export declare function runnerCwdFor(file: string, options?: RunnerProjectOptions): string;
|
|
51
93
|
/**
|
|
52
94
|
* Group `files` by the directory each must run from, in first-seen order.
|
|
53
|
-
* Files keep the spelling they were given.
|
|
95
|
+
* Files keep the spelling they were given. #1248: Python files never share a
|
|
96
|
+
* group with other files, since only pytest runs them.
|
|
54
97
|
*/
|
|
55
98
|
export declare function groupByRunnerProject(files: readonly string[], options?: RunnerProjectOptions): RunnerProjectGroup[];
|
|
56
99
|
/** Test files to run, and the directory to run them from when the caller named one. */
|
|
@@ -66,4 +109,11 @@ export interface TestRunTargets {
|
|
|
66
109
|
* files are then read from it, and every path is returned absolute.
|
|
67
110
|
*/
|
|
68
111
|
export declare function requireTestRunTargets(taskType: string, testFiles: unknown, projectRoot: unknown): Promise<Result<TestRunTargets, Error>>;
|
|
112
|
+
/**
|
|
113
|
+
* An explicit `projectRoot` (MCP `test_execute_parallel`, CLI
|
|
114
|
+
* `aqe test execute --project-root`): a directory inside the project, checked
|
|
115
|
+
* by realpath so `..`, an outside absolute path or a symlink pointing out is
|
|
116
|
+
* refused. Returns the absolute directory.
|
|
117
|
+
*/
|
|
118
|
+
export declare function requireRunProjectRoot(taskType: string, projectRoot: unknown): Promise<Result<string, Error>>;
|
|
69
119
|
//# sourceMappingURL=test-runner-project.d.ts.map
|
|
@@ -14,12 +14,33 @@
|
|
|
14
14
|
* A run from the current working directory is kept whenever that directory is
|
|
15
15
|
* already inside the file's runner project (a single-project repository, or a
|
|
16
16
|
* server started inside the package), so those runs behave as before.
|
|
17
|
+
*
|
|
18
|
+
* #1272: a package with its own config runs from that package, even when the
|
|
19
|
+
* root config also lists it in `test.projects` (or a `vitest.workspace.*`).
|
|
20
|
+
* Settings that only the root config adds to that project (its setup files,
|
|
21
|
+
* aliases or environment) are then not applied; the package's own config is
|
|
22
|
+
* what runs. A package without its own config still runs from the root.
|
|
23
|
+
*
|
|
24
|
+
* #1272: `vite.config.*` counts only when its text contains `test:`. The
|
|
25
|
+
* config is code, and reading what it exports would mean running it, so a
|
|
26
|
+
* `test` block built some other way (spread from another module, say) is not
|
|
27
|
+
* seen and a `test:` that only appears in a comment is. Name the runner config
|
|
28
|
+
* `vitest.config.*` for an exact match.
|
|
29
|
+
*
|
|
30
|
+
* #1248: a Python test file belongs to the nearest directory with pytest
|
|
31
|
+
* configuration instead (`pytest.ini`, `pyproject.toml` with
|
|
32
|
+
* `[tool.pytest.ini_options]`, `setup.cfg` with `[tool:pytest]`, `tox.ini`
|
|
33
|
+
* with `[pytest]`), and JavaScript files ignore that configuration. A
|
|
34
|
+
* `conftest.py` marks a pytest project for detection but is not a directory
|
|
35
|
+
* to run from: it is often in `tests/`, and pytest started there would not
|
|
36
|
+
* have the project root on `sys.path`.
|
|
17
37
|
*/
|
|
18
38
|
import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
19
39
|
import * as path from 'node:path';
|
|
20
40
|
import { findProjectRoot } from '../kernel/project-root.js';
|
|
21
41
|
import { CallerInputError } from './error-utils.js';
|
|
22
42
|
import { requirePayloadFiles, requirePayloadPath } from './io/payload-path-guard.js';
|
|
43
|
+
import { isPythonTestFile } from './pytest-junit-report.js';
|
|
23
44
|
import { safeJsonParse } from './safe-json.js';
|
|
24
45
|
import { runnerFilePath } from './test-runner-args.js';
|
|
25
46
|
import { ok, err } from './types/index.js';
|
|
@@ -63,36 +84,112 @@ function readSmallFile(file) {
|
|
|
63
84
|
}
|
|
64
85
|
}
|
|
65
86
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
87
|
+
* Runners a package.json in `dir` configures (a top-level `jest` or `vitest`
|
|
88
|
+
* key). Listing a runner as a dependency or in `scripts.test` does not count:
|
|
89
|
+
* in a workspace the packages do that while the root config defines their
|
|
90
|
+
* projects and setup.
|
|
70
91
|
*/
|
|
71
|
-
function
|
|
92
|
+
function packageRunnerKeys(dir) {
|
|
72
93
|
const text = readSmallFile(path.join(dir, 'package.json'));
|
|
73
94
|
if (text === undefined)
|
|
74
|
-
return
|
|
95
|
+
return [];
|
|
75
96
|
let pkg;
|
|
76
97
|
try {
|
|
77
98
|
pkg = safeJsonParse(text);
|
|
78
99
|
}
|
|
79
100
|
catch {
|
|
80
|
-
return
|
|
101
|
+
return [];
|
|
81
102
|
}
|
|
82
103
|
if (!pkg || typeof pkg !== 'object')
|
|
83
|
-
return
|
|
84
|
-
return
|
|
104
|
+
return [];
|
|
105
|
+
return ['vitest', 'jest'].filter(key => pkg[key] !== undefined);
|
|
106
|
+
}
|
|
107
|
+
/** True when a `vite.config.*` in `dir` mentions `test:` (see the header note). */
|
|
108
|
+
function viteConfiguresTest(dir) {
|
|
109
|
+
return VITE_CONFIG_FILES.some(name => {
|
|
110
|
+
const text = readSmallFile(path.join(dir, name));
|
|
111
|
+
return text !== undefined && /\btest\s*:/.test(text);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/** The runners whose configuration `dir` holds. */
|
|
115
|
+
function configuredRunners(dir) {
|
|
116
|
+
const runners = new Set(packageRunnerKeys(dir));
|
|
117
|
+
for (const name of RUNNER_CONFIG_FILES) {
|
|
118
|
+
if (existsSync(path.join(dir, name)))
|
|
119
|
+
runners.add(name.startsWith('jest.') ? 'jest' : 'vitest');
|
|
120
|
+
}
|
|
121
|
+
if (!runners.has('vitest') && viteConfiguresTest(dir))
|
|
122
|
+
runners.add('vitest');
|
|
123
|
+
return runners;
|
|
85
124
|
}
|
|
86
125
|
/** True when `dir` holds a Vitest or Jest configuration. */
|
|
87
126
|
export function isRunnerProjectDir(dir) {
|
|
88
|
-
|
|
127
|
+
return configuredRunners(dir).size > 0;
|
|
128
|
+
}
|
|
129
|
+
/** pytest configuration files, and the section each must contain (none: always). */
|
|
130
|
+
const PYTEST_CONFIG_SECTIONS = [
|
|
131
|
+
['pytest.ini', undefined],
|
|
132
|
+
['pyproject.toml', /^\s*\[tool\.pytest(?:\.ini_options)?\]/m],
|
|
133
|
+
['tox.ini', /^\s*\[pytest\]/m],
|
|
134
|
+
['setup.cfg', /^\s*\[tool:pytest\]/m],
|
|
135
|
+
];
|
|
136
|
+
/**
|
|
137
|
+
* #1248: true when `dir` holds pytest configuration; with `conftest`, a
|
|
138
|
+
* `conftest.py` counts too (see the header note).
|
|
139
|
+
*/
|
|
140
|
+
export function isPytestProjectDir(dir, conftest = false) {
|
|
141
|
+
if (conftest && existsSync(path.join(dir, 'conftest.py')))
|
|
89
142
|
return true;
|
|
90
|
-
|
|
143
|
+
return PYTEST_CONFIG_SECTIONS.some(([name, section]) => {
|
|
144
|
+
if (!section)
|
|
145
|
+
return existsSync(path.join(dir, name));
|
|
91
146
|
const text = readSmallFile(path.join(dir, name));
|
|
92
|
-
|
|
147
|
+
return text !== undefined && section.test(text);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* #1248: true when `dir`, or a directory above it no higher than `boundary`,
|
|
152
|
+
* is configured for pytest (including a `conftest.py`).
|
|
153
|
+
*/
|
|
154
|
+
export function isPytestProject(dir, boundary = findProjectRoot()) {
|
|
155
|
+
const root = realDir(boundary);
|
|
156
|
+
let current = realDir(dir);
|
|
157
|
+
const bounded = isWithin(root, current);
|
|
158
|
+
for (;;) {
|
|
159
|
+
if (isPytestProjectDir(current, true))
|
|
93
160
|
return true;
|
|
161
|
+
if (!bounded || current === root)
|
|
162
|
+
return false;
|
|
163
|
+
const parent = path.dirname(current);
|
|
164
|
+
if (parent === current)
|
|
165
|
+
return false;
|
|
166
|
+
current = parent;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* #1272: the runner configured by the runner project that `dir` belongs to:
|
|
171
|
+
* the nearest directory at or above `dir`, no higher than `boundary`, with
|
|
172
|
+
* runner configuration. Jest config (`jest.config.*`, or a `jest` key in
|
|
173
|
+
* package.json) means jest; Vitest config (`vitest.config.*`,
|
|
174
|
+
* `vitest.workspace.*`, a `vite.config.*` with `test`, or a `vitest` key)
|
|
175
|
+
* means vitest. Undefined when no project is found or it configures both, so
|
|
176
|
+
* the caller keeps its own choice.
|
|
177
|
+
*/
|
|
178
|
+
export function runnerFrameworkFor(dir, boundary = findProjectRoot()) {
|
|
179
|
+
const root = realDir(boundary);
|
|
180
|
+
let current = realDir(dir);
|
|
181
|
+
const bounded = isWithin(root, current);
|
|
182
|
+
for (;;) {
|
|
183
|
+
const runners = configuredRunners(current);
|
|
184
|
+
if (runners.size > 0)
|
|
185
|
+
return runners.size === 1 ? [...runners][0] : undefined;
|
|
186
|
+
if (!bounded || current === root)
|
|
187
|
+
return undefined;
|
|
188
|
+
const parent = path.dirname(current);
|
|
189
|
+
if (parent === current)
|
|
190
|
+
return undefined;
|
|
191
|
+
current = parent;
|
|
94
192
|
}
|
|
95
|
-
return packageConfiguresRunner(dir);
|
|
96
193
|
}
|
|
97
194
|
/**
|
|
98
195
|
* The nearest directory at or above `file` with runner configuration, searching no
|
|
@@ -104,11 +201,14 @@ export function findRunnerProjectDir(file, boundary, cwd = process.cwd(), checke
|
|
|
104
201
|
let dir = path.dirname(runnerFilePath(file, cwd));
|
|
105
202
|
if (!isWithin(root, dir))
|
|
106
203
|
return undefined;
|
|
204
|
+
// #1248: Python files run from pytest config, other files from Vitest/Jest config.
|
|
205
|
+
const python = isPythonTestFile(file);
|
|
107
206
|
for (;;) {
|
|
108
|
-
|
|
207
|
+
const key = python ? `pytest:${dir}` : dir;
|
|
208
|
+
let isProject = checked.get(key);
|
|
109
209
|
if (isProject === undefined) {
|
|
110
|
-
isProject = isRunnerProjectDir(dir);
|
|
111
|
-
checked.set(
|
|
210
|
+
isProject = python ? isPytestProjectDir(dir) : isRunnerProjectDir(dir);
|
|
211
|
+
checked.set(key, isProject);
|
|
112
212
|
}
|
|
113
213
|
if (isProject)
|
|
114
214
|
return dir;
|
|
@@ -134,7 +234,8 @@ export function runnerCwdFor(file, options = {}) {
|
|
|
134
234
|
}
|
|
135
235
|
/**
|
|
136
236
|
* Group `files` by the directory each must run from, in first-seen order.
|
|
137
|
-
* Files keep the spelling they were given.
|
|
237
|
+
* Files keep the spelling they were given. #1248: Python files never share a
|
|
238
|
+
* group with other files, since only pytest runs them.
|
|
138
239
|
*/
|
|
139
240
|
export function groupByRunnerProject(files, options = {}) {
|
|
140
241
|
const resolved = {
|
|
@@ -145,13 +246,14 @@ export function groupByRunnerProject(files, options = {}) {
|
|
|
145
246
|
const groups = new Map();
|
|
146
247
|
for (const file of files) {
|
|
147
248
|
const cwd = runnerCwdFor(file, resolved);
|
|
148
|
-
const
|
|
249
|
+
const key = `${isPythonTestFile(file) ? 'py' : 'js'}\0${cwd}`;
|
|
250
|
+
const group = groups.get(key);
|
|
149
251
|
if (group)
|
|
150
|
-
group.push(file);
|
|
252
|
+
group.files.push(file);
|
|
151
253
|
else
|
|
152
|
-
groups.set(cwd, [file]);
|
|
254
|
+
groups.set(key, { cwd, files: [file] });
|
|
153
255
|
}
|
|
154
|
-
return [...groups
|
|
256
|
+
return [...groups.values()];
|
|
155
257
|
}
|
|
156
258
|
/**
|
|
157
259
|
* Handler-side check for an execute-tests payload. `testFiles` must name
|
|
@@ -166,6 +268,22 @@ export async function requireTestRunTargets(taskType, testFiles, projectRoot) {
|
|
|
166
268
|
const confined = await requirePayloadFiles(taskType, 'testFiles', testFiles, fileOptions);
|
|
167
269
|
return confined.success ? ok({ testFiles: confined.value }) : confined;
|
|
168
270
|
}
|
|
271
|
+
const checked = await requireRunProjectRoot(taskType, projectRoot);
|
|
272
|
+
if (!checked.success)
|
|
273
|
+
return checked;
|
|
274
|
+
const root = checked.value;
|
|
275
|
+
const confined = await requirePayloadFiles(taskType, 'testFiles', testFiles, { ...fileOptions, basePath: root });
|
|
276
|
+
if (!confined.success)
|
|
277
|
+
return confined;
|
|
278
|
+
return ok({ testFiles: confined.value.map(file => path.resolve(root, file)), projectRoot: root });
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* An explicit `projectRoot` (MCP `test_execute_parallel`, CLI
|
|
282
|
+
* `aqe test execute --project-root`): a directory inside the project, checked
|
|
283
|
+
* by realpath so `..`, an outside absolute path or a symlink pointing out is
|
|
284
|
+
* refused. Returns the absolute directory.
|
|
285
|
+
*/
|
|
286
|
+
export async function requireRunProjectRoot(taskType, projectRoot) {
|
|
169
287
|
const checked = await requirePayloadPath(taskType, 'projectRoot', projectRoot, { allowDirectory: true });
|
|
170
288
|
if (!checked.success)
|
|
171
289
|
return checked;
|
|
@@ -178,9 +296,6 @@ export async function requireTestRunTargets(taskType, testFiles, projectRoot) {
|
|
|
178
296
|
if (!isDirectory) {
|
|
179
297
|
return err(new CallerInputError(`Invalid ${taskType} payload: 'projectRoot' must be a directory inside the project.`));
|
|
180
298
|
}
|
|
181
|
-
|
|
182
|
-
if (!confined.success)
|
|
183
|
-
return confined;
|
|
184
|
-
return ok({ testFiles: confined.value.map(file => path.resolve(root, file)), projectRoot: root });
|
|
299
|
+
return ok(root);
|
|
185
300
|
}
|
|
186
301
|
//# sourceMappingURL=test-runner-project.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-qe",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.17",
|
|
4
4
|
"description": "Agentic Quality Engineering V3 - Domain-Driven Design Architecture with 13 Bounded Contexts, O(log n) coverage analysis, ReasoningBank learning, 60 specialized QE agents, mathematical Coherence verification, deep Claude Flow integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{a,b,c}from"./chunk-E3D4GPLP.js";import"./chunk-VWPM27GU.js";import"./chunk-MD43XRX5.js";import"./chunk-V5NHZV7S.js";import"./chunk-KNSRL6NO.js";import"./chunk-AJMJNQMP.js";export{a as AgentBoosterAdapter,b as createAgentBoosterAdapter,c as createAgentBoosterAdapterSync};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{a,b,c,d,e,f}from"./chunk-UNGBRZDK.js";import"./chunk-FDDC72IA.js";import"./chunk-4LQFBY5L.js";import"./chunk-KU2AUFGX.js";import"./chunk-5B5QPCNU.js";import"./chunk-PHT5N7SC.js";import"./chunk-EA4YQVKS.js";import"./chunk-N7HL5PHH.js";import"./chunk-GQ6TUIKY.js";import"./chunk-HVRRLYX6.js";import"./chunk-63ZKI4PX.js";import"./chunk-5LAVKGLH.js";import"./chunk-IOQ6ZQ5W.js";import"./chunk-KVF4NXGQ.js";import"./chunk-IOKYCMTJ.js";import"./chunk-HGWXF45W.js";import"./chunk-VJCIEHEF.js";import"./chunk-MO55CVMT.js";import"./chunk-CEYSYSK5.js";import"./chunk-WP4RETKG.js";import"./chunk-JDIYMZCQ.js";import"./chunk-V5NHZV7S.js";import"./chunk-S75SOOZL.js";import"./chunk-PPUZWYUG.js";import"./chunk-3HD7E6HN.js";import"./chunk-CRPIYUTJ.js";import"./chunk-F742SZAX.js";import"./chunk-CAKMOVZ6.js";import"./chunk-M4FRQ4TE.js";import"./chunk-DXD6K2ZP.js";import"./chunk-FLNAW7C4.js";import"./chunk-LE4QJREF.js";import"./chunk-J4ELZNLY.js";import"./chunk-YAPLJR7K.js";import"./chunk-G5RHFBAY.js";import"./chunk-XIIQ5QTT.js";import"./chunk-A5GBXCP5.js";import"./chunk-L6QSTQME.js";import"./chunk-EK7OLYOZ.js";import"./chunk-AGRV5B3T.js";import"./chunk-U2A7NHZA.js";import"./chunk-I7MQIM2U.js";import"./chunk-ZFL436FN.js";import"./chunk-KPRCB5LT.js";import"./chunk-KNSRL6NO.js";import"./chunk-2H4XH6FT.js";import"./chunk-AJMJNQMP.js";export{b as AQELearningEngine,a as DEFAULT_ENGINE_CONFIG,c as DEFAULT_META_LEARNING_CONFIG,d as MetaLearningEngine,e as createAQELearningEngine,f as createDefaultLearningEngine};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{a,b,c,d,e,f,g,h,i,j,k,l}from"./chunk-GAHNO6JJ.js";import"./chunk-SUDMM5SO.js";import"./chunk-JQ3DYUMS.js";import"./chunk-HGWXF45W.js";import"./chunk-MO55CVMT.js";import"./chunk-CEYSYSK5.js";import"./chunk-WP4RETKG.js";import"./chunk-JDIYMZCQ.js";import"./chunk-V5NHZV7S.js";import"./chunk-S75SOOZL.js";import"./chunk-PPUZWYUG.js";import"./chunk-3HD7E6HN.js";import"./chunk-CRPIYUTJ.js";import"./chunk-F742SZAX.js";import"./chunk-CAKMOVZ6.js";import"./chunk-FLNAW7C4.js";import"./chunk-J4ELZNLY.js";import"./chunk-YAPLJR7K.js";import"./chunk-G5RHFBAY.js";import"./chunk-XIIQ5QTT.js";import"./chunk-A5GBXCP5.js";import"./chunk-L6QSTQME.js";import"./chunk-AGRV5B3T.js";import"./chunk-U2A7NHZA.js";import"./chunk-KPRCB5LT.js";import"./chunk-KNSRL6NO.js";import"./chunk-2H4XH6FT.js";import"./chunk-AJMJNQMP.js";export{l as MCPToolBase,k as defaultToolLogger,j as getKernel,i as getLLMRouter,e as getMemoryBackend,g as getSharedLLMRouter,c as getSharedMemoryBackend,a as isMemoryOnlyMode,b as registerRvfResetFn,h as resetSharedLLMRouter,d as resetSharedMemoryBackend,f as setSharedLLMRouter};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{a}from"./chunk-KITOPKRG.js";import"./chunk-GAHNO6JJ.js";import"./chunk-SUDMM5SO.js";import"./chunk-JQ3DYUMS.js";import"./chunk-HGWXF45W.js";import"./chunk-MO55CVMT.js";import"./chunk-CEYSYSK5.js";import"./chunk-WP4RETKG.js";import"./chunk-JDIYMZCQ.js";import"./chunk-V5NHZV7S.js";import"./chunk-S75SOOZL.js";import"./chunk-PPUZWYUG.js";import"./chunk-3HD7E6HN.js";import"./chunk-CRPIYUTJ.js";import"./chunk-F742SZAX.js";import"./chunk-CAKMOVZ6.js";import"./chunk-FLNAW7C4.js";import"./chunk-J4ELZNLY.js";import"./chunk-YAPLJR7K.js";import"./chunk-G5RHFBAY.js";import"./chunk-XIIQ5QTT.js";import"./chunk-A5GBXCP5.js";import"./chunk-L6QSTQME.js";import"./chunk-AGRV5B3T.js";import"./chunk-U2A7NHZA.js";import"./chunk-KPRCB5LT.js";import"./chunk-KNSRL6NO.js";import"./chunk-2H4XH6FT.js";import"./chunk-AJMJNQMP.js";export{a as BrowserWorkflowTool};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{c as i,e as m}from"./chunk-KNSRL6NO.js";m();var u='expected [{ "functionName": "add", "args": [2, 3], "expected": 5 }]',g={type:"object",description:"One caller-owned specification example",properties:{functionName:{type:"string",description:"Named export of the source file to call"},args:{type:"array",description:"Positional JSON arguments; length must equal the function arity",items:{}},expected:{description:"Expected JSON return value (use null for a null result)"}},required:["functionName","args","expected"]};function d(t,s="Behavior example value"){let o=(e,r)=>{if(!(e===null||typeof e=="string"||typeof e=="boolean")&&!(typeof e=="number"&&Number.isFinite(e)&&!Object.is(e,-0))){if(typeof e!="object"||r.has(e))throw new i(`${s} must be finite JSON data (no undefined, functions, NaN/Infinity, cycles, or negative zero)`);if(!Array.isArray(e)&&Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null)throw new i(`${s} must contain only plain JSON objects`);r.add(e);for(let l of Array.isArray(e)?Array.from(e):Object.values(e))o(l,r);r.delete(e)}};o(t,new Set)}function h(t){if(t!==void 0){if(!Array.isArray(t))throw new i(`behaviorExamples must be an array; ${u}`);return t.forEach((s,o)=>{let e=`behaviorExamples[${o}]`;if(typeof s!="object"||s===null||Array.isArray(s))throw new i(`${e} must be an object; ${u}`);let r=s;if(typeof r.functionName!="string"||r.functionName.trim()==="")throw new i(`${e}.functionName must be a non-empty string`);if(!Array.isArray(r.args))throw new i(`${e}.args must be an array of arguments`);if(!Object.prototype.hasOwnProperty.call(r,"expected"))throw new i(`${e}.expected is required (use null for a null result)`);d(r.args,`${e}.args`),d(r.expected,`${e}.expected`)}),t}}function x(t,s){let o=new Map(t.failedTests.map(n=>[n.testId,n])),e=s.tests??[],r={totalRetries:s.retried,nowPassing:s.nowPassing,stillFailing:s.stillFailing,tests:e.map(({testId:n,...a})=>({name:o.get(n)?.testName??n,file:o.get(n)?.file??"",...a}))};t.retries=r;let l=new Set(e.filter(n=>n.passed&&!n.unmatched).map(n=>n.testId)),f=t.failedTests.filter(n=>l.has(n.testId));if(f.length!==0&&(t.failedTests=t.failedTests.filter(n=>!l.has(n.testId)),t.failed=Math.max(0,t.failed-f.length),t.passed+=f.length,t.flaky=(t.flaky??0)+f.length,t.failed===0&&t.status==="failed"&&(t.status="passed"),t.testCases)){let n=[...f];t.testCases=t.testCases.map(a=>{if(a.status!=="failed")return a;let c=n.findIndex(p=>p.testName===a.name&&p.file===a.file);return c<0?a:(n.splice(c,1),{...a,status:"passed",flaky:!0})})}}export{g as a,d as b,h as c,x as d};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.15.16");process.exit(0)}
|
|
2
|
-
import{a,d as R}from"./chunk-XIIQ5QTT.js";import{realpathSync as x,statSync as y}from"node:fs";import{basename as h,dirname as E,extname as $,resolve as p,sep as j}from"node:path";function m(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function N(e,t=process.cwd()){let r=p(t,e);try{return p(x(E(r)),h(r))}catch{return r}}function S(e){try{return y(e).isDirectory()}catch{return $(e)===""}}function A(e,t=process.cwd()){let r=N(e,t),n=r.split(j).join("/"),s=S(r)?"(?:/|$)":"$";return`^${m(n)}${s}`}function k(e,t){let r=`^${t.split(" ").map(m).join("(?: > | )")}$`;return e==="mocha"?`--grep=${r}`:`--testNamePattern=${r}`}function P(e){return e.some(t=>/(^|[\\/])jest(\.cmd|\.js|\.mjs)?$/i.test(t))}R();var c=class extends Error{constructor(t){super(a(t,Number.POSITIVE_INFINITY)),this.name="TestRunnerExecutionError"}};function b(e,t=4e3){return a(e,Number.POSITIVE_INFINITY).slice(0,t)}function z(e,t,r,n,s,i){let l=(i?.testResults??[]).filter(u=>u.status==="failed"&&(e==="vitest"&&u.message||!u.assertionResults?.some(g=>g.status==="failed"))),o;if(r===null?o="terminated without an exit code":n.passed+n.failed+n.skipped===0?o="reported zero tests":l.length>0||(i?.numRuntimeErrorTestSuites??0)>0||(i?.numFailedTestSuites??0)>0&&n.failed===0?o="reported a suite execution error":(r!==0||i?.success===!1)&&n.failed===0&&(o="failed without a failed assertion"),!o)return;let d=[...l.map(u=>u.message).filter(Boolean),s.trim()].filter(Boolean).join(`
|
|
3
|
-
`);return new c(`${e} ${o} for ${t} (exit code ${r??"unknown"}).`+(d?`
|
|
4
|
-
${b(d)}`:""))}import{mkdtempSync as T,readFileSync as F,rmSync as w}from"node:fs";import{tmpdir as I}from"node:os";import{join as f}from"node:path";function J(e,t){if(!t)return;let r;try{r=F(t,"utf-8")}catch(n){if(n.code==="ENOENT")return;throw new Error("Could not read the current Vitest JSON report.")}try{let n=JSON.parse(r);if(!n||!Array.isArray(n.testResults))throw new Error("Invalid report")}catch{throw new Error("The current Vitest JSON report is malformed.")}return r}function q(){let e=T(f(I(),"aqe-vitest-report-")),t=f(e,"report.json"),r=!1;return{path:t,args:[`--outputFile=${t}`],read:n=>J(n,t),cleanup:()=>{if(!r){r=!0;try{w(e,{recursive:!0,force:!0})}catch{}}}}}function W(e){let t=e.some(s=>/(^|[\\/])vitest(\.cmd|\.js|\.mjs)?$/i.test(s)),r=e.some((s,i)=>s==="--reporter=json"||s==="--reporter"&&e[i+1]==="json"),n=e.some(s=>s.startsWith("--outputFile"));return t&&r&&!n}export{N as a,A as b,k as c,P as d,c as e,b as f,z as g,q as h,W as i};
|