agentic-qe 3.15.16 → 3.15.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/helpers/brain-checkpoint.cjs +107 -10
- package/.claude/skills/agentic-quality-engineering/SKILL.md +67 -44
- package/.claude/skills/brutal-honesty-review/SKILL.md +12 -7
- package/.claude/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml +120 -0
- package/.claude/skills/brutal-honesty-review/schemas/output.json +9 -3
- package/.claude/skills/code-review-quality/SKILL.md +2 -2
- package/.claude/skills/holistic-testing-pact/SKILL.md +11 -11
- package/.claude/skills/sherlock-review/SKILL.md +4 -2
- package/.claude/skills/sherlock-review/evals/sherlock-review.yaml +124 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/.claude/skills/technical-writing/SKILL.md +12 -6
- package/.claude/skills/technical-writing/evals/technical-writing.yaml +96 -0
- package/.opencode/skills/qe-agentic-quality-engineering.yaml +2 -2
- package/.opencode/skills/qe-holistic-testing-pact.yaml +2 -2
- package/CHANGELOG.md +201 -0
- package/assets/skills/agentic-quality-engineering/SKILL.md +67 -44
- package/assets/skills/brutal-honesty-review/SKILL.md +12 -8
- package/assets/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml +120 -0
- package/assets/skills/brutal-honesty-review/schemas/output.json +9 -3
- package/assets/skills/code-review-quality/SKILL.md +2 -2
- package/assets/skills/holistic-testing-pact/SKILL.md +11 -11
- package/assets/skills/sherlock-review/SKILL.md +4 -3
- package/assets/skills/sherlock-review/evals/sherlock-review.yaml +124 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/assets/skills/technical-writing/SKILL.md +12 -6
- package/assets/skills/technical-writing/evals/technical-writing.yaml +96 -0
- package/dist/cli/brain-commands.d.ts +5 -0
- package/dist/cli/brain-commands.js +4 -0
- package/dist/cli/bundle.js +6 -6
- package/dist/cli/chunks/adapter-WRSDXLOT.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-45NWEKVS.js → agent-booster-wasm-UFNJNF3M.js} +2 -2
- package/dist/cli/chunks/{agent-handler-LVHMYFEF.js → agent-handler-EAYVRJXN.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-YDWOJFEQ.js → agent-memory-branch-M65C6WAQ.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-O6NJBCCM.js +2 -0
- package/dist/cli/chunks/{arena-ELDZH3CZ.js → arena-2GDICP6R.js} +4 -4
- package/dist/cli/chunks/{arena-CZKHXDDS.js → arena-CG3X67OE.js} +2 -2
- package/dist/cli/chunks/{audit-5MT4T47Z.js → audit-F4FSPJPL.js} +3 -3
- package/dist/cli/chunks/base-J2FXOE77.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-6TGYPC2B.js → better-sqlite3-2MCFXW4J.js} +2 -2
- package/dist/cli/chunks/brain-handler-WGTJNYNB.js +95 -0
- package/dist/cli/chunks/{branch-enumerator-WVILM4SO.js → branch-enumerator-KL7C535H.js} +2 -2
- package/dist/cli/chunks/{browser-RX5ALU3H.js → browser-SJEXDVHS.js} +2 -2
- package/dist/cli/chunks/browser-workflow-LXGER6ZD.js +2 -0
- package/dist/cli/chunks/{chunk-2H4XH6FT.js → chunk-244RKAEP.js} +2 -2
- package/dist/cli/chunks/{chunk-SI6DPU5D.js → chunk-27TUMXPD.js} +1 -1
- package/dist/cli/chunks/{chunk-YNMJEDN5.js → chunk-2MBYDPCP.js} +2 -2
- package/dist/cli/chunks/{chunk-24QHCVX6.js → chunk-2Q6DTBMT.js} +1 -1
- package/dist/cli/chunks/{chunk-XWUWX7BV.js → chunk-355MI7RV.js} +13 -13
- package/dist/cli/chunks/{chunk-NQXXI77K.js → chunk-3LX5OKBD.js} +2 -2
- package/dist/cli/chunks/{chunk-63GMRQ25.js → chunk-3RPDKJGV.js} +1 -1
- package/dist/cli/chunks/chunk-3YMIT73A.js +4 -0
- package/dist/cli/chunks/{chunk-P3EYRILV.js → chunk-43KUVBSU.js} +2 -2
- package/dist/cli/chunks/chunk-477FKXSS.js +2 -0
- package/dist/cli/chunks/{chunk-HGWXF45W.js → chunk-4BIMTRRX.js} +1 -1
- package/dist/cli/chunks/{chunk-SSUAAX3F.js → chunk-4CVNVBX5.js} +2 -2
- package/dist/cli/chunks/{chunk-5V3TI2LG.js → chunk-4HL3SD4A.js} +1 -1
- package/dist/cli/chunks/{chunk-KKU2QGSJ.js → chunk-4PEG4DU2.js} +2 -2
- package/dist/cli/chunks/{chunk-J4ELZNLY.js → chunk-4QSQKFED.js} +2 -2
- package/dist/cli/chunks/chunk-53ZBETYR.js +16 -0
- package/dist/cli/chunks/{chunk-7TE5ONQQ.js → chunk-544KDWL4.js} +1 -1
- package/dist/cli/chunks/chunk-54RCGMLB.js +8 -0
- package/dist/cli/chunks/{chunk-KU2AUFGX.js → chunk-5AGXIZQ5.js} +2 -2
- package/dist/cli/chunks/{chunk-LQLPB2T6.js → chunk-5M24X6W7.js} +2 -2
- package/dist/cli/chunks/{chunk-YU2BDRSD.js → chunk-5O5T4LEU.js} +1 -1
- package/dist/cli/chunks/{chunk-NAEWCFQT.js → chunk-5RFXX4IF.js} +2 -2
- package/dist/cli/chunks/{chunk-MD43XRX5.js → chunk-62MLAQRJ.js} +1 -1
- package/dist/cli/chunks/{chunk-PEQDY4BO.js → chunk-6D6TGL2E.js} +2 -2
- package/dist/cli/chunks/{chunk-IOYG4VFL.js → chunk-6IHZDSDL.js} +2 -2
- package/dist/cli/chunks/{chunk-C5FP5GW3.js → chunk-6P3Y45QL.js} +2 -2
- package/dist/cli/chunks/{chunk-4LQFBY5L.js → chunk-6TEVM3X3.js} +10 -10
- package/dist/cli/chunks/{chunk-YPBSUGMI.js → chunk-7XTUKKRA.js} +1 -1
- package/dist/cli/chunks/chunk-A3GDX6UF.js +2 -0
- package/dist/cli/chunks/{chunk-HLUXXCHF.js → chunk-A5YTKKNA.js} +1 -1
- package/dist/cli/chunks/{chunk-Y4PFUMOU.js → chunk-ADNGZAT2.js} +1 -1
- package/dist/cli/chunks/{chunk-KNSRL6NO.js → chunk-AWQAE3SW.js} +2 -2
- package/dist/cli/chunks/{chunk-BY5OF7OH.js → chunk-AXDBQFR4.js} +2 -2
- package/dist/cli/chunks/{chunk-525CFDUE.js → chunk-AXVD7O3F.js} +2 -2
- package/dist/cli/chunks/{chunk-JHQCRRJI.js → chunk-B52ULNYO.js} +2 -2
- package/dist/cli/chunks/chunk-B6S4FC7M.js +3 -0
- package/dist/cli/chunks/{chunk-AJMJNQMP.js → chunk-BDVFSMOQ.js} +1 -1
- package/dist/cli/chunks/{chunk-DXD6K2ZP.js → chunk-BGXXMX3Y.js} +2 -2
- package/dist/cli/chunks/{chunk-EK7OLYOZ.js → chunk-BKMQQY5T.js} +2 -2
- package/dist/cli/chunks/{chunk-VWPM27GU.js → chunk-BN2FROBQ.js} +2 -2
- package/dist/cli/chunks/{chunk-J7I6PABJ.js → chunk-BO6EQNOC.js} +2 -2
- package/dist/cli/chunks/{chunk-4D4DENG6.js → chunk-BOVAKCDC.js} +2 -2
- package/dist/cli/chunks/{chunk-ZFL436FN.js → chunk-BSXKZDKO.js} +2 -2
- package/dist/cli/chunks/{chunk-J442IZLE.js → chunk-C5QVJ5XQ.js} +1 -1
- package/dist/cli/chunks/{chunk-ZB3LEFYG.js → chunk-CFQLLF3D.js} +2 -2
- package/dist/cli/chunks/{chunk-UHEOGZLX.js → chunk-DUCVLT3F.js} +7 -7
- package/dist/cli/chunks/{chunk-TVGI32MB.js → chunk-E4RMJCGA.js} +3 -3
- package/dist/cli/chunks/{chunk-TIUKLYAI.js → chunk-EONDCWY4.js} +1 -1
- package/dist/cli/chunks/{chunk-ZJH5MU2I.js → chunk-F4AGNKL2.js} +2 -2
- package/dist/cli/chunks/{chunk-N7HL5PHH.js → chunk-F6YD3BOW.js} +1 -1
- package/dist/cli/chunks/{chunk-5VZL4UVN.js → chunk-FQRS7WVA.js} +2 -2
- package/dist/cli/chunks/{chunk-SHKOCGNK.js → chunk-FT24SSDG.js} +2 -2
- package/dist/cli/chunks/chunk-FV4YNSAJ.js +5 -0
- package/dist/cli/chunks/{chunk-KXCLACFG.js → chunk-FVDM3X42.js} +2 -2
- package/dist/cli/chunks/{chunk-32BPDLRZ.js → chunk-FVH7TXWU.js} +2 -2
- package/dist/cli/chunks/{chunk-72XSEQMW.js → chunk-FWR5QY37.js} +2 -2
- package/dist/cli/chunks/chunk-FYINK2B7.js +6 -0
- package/dist/cli/chunks/{chunk-5JZRZI4S.js → chunk-GGISVPOZ.js} +2 -2
- package/dist/cli/chunks/{chunk-5LAVKGLH.js → chunk-GPIJIZJQ.js} +2 -2
- package/dist/cli/chunks/{chunk-5QO3R3TU.js → chunk-GXEVOT5F.js} +2 -2
- package/dist/cli/chunks/{chunk-IHRXZZQM.js → chunk-GZ4VB5RI.js} +1 -1
- package/dist/cli/chunks/chunk-HBDSCYSK.js +2 -0
- package/dist/cli/chunks/{chunk-GSKMOPL7.js → chunk-HGG4HR7C.js} +2 -2
- package/dist/cli/chunks/{chunk-AR67RJPY.js → chunk-HSCKWWO2.js} +2 -2
- package/dist/cli/chunks/{chunk-6XXZDV2C.js → chunk-HSQ3GUYJ.js} +2 -2
- package/dist/cli/chunks/{chunk-AAMLQ2LF.js → chunk-HZQBW5EM.js} +3 -3
- package/dist/cli/chunks/{chunk-O5W3FIO6.js → chunk-IGIYANVT.js} +2 -2
- package/dist/cli/chunks/{chunk-C6D5AHBO.js → chunk-IPWMSXBF.js} +2 -2
- package/dist/cli/chunks/{chunk-NDJ7P2EP.js → chunk-IWVNC7VY.js} +1 -1
- package/dist/cli/chunks/{chunk-FDDC72IA.js → chunk-IZODXKZD.js} +2 -2
- package/dist/cli/chunks/{chunk-NO3IV5Q5.js → chunk-J2MT2OJV.js} +1 -1
- package/dist/cli/chunks/{chunk-GQ6TUIKY.js → chunk-JKIJVVSP.js} +1 -1
- package/dist/cli/chunks/{chunk-LE4QJREF.js → chunk-JMRDT2XK.js} +1 -1
- package/dist/cli/chunks/{chunk-2YZ4G6NW.js → chunk-JR2UMTKG.js} +1 -1
- package/dist/cli/chunks/{chunk-RJIEG3NA.js → chunk-K6CH4CFF.js} +2 -2
- package/dist/cli/chunks/{chunk-5NNNEWLS.js → chunk-K7KW5QB5.js} +81 -88
- package/dist/cli/chunks/chunk-KFCQP434.js +2 -0
- package/dist/cli/chunks/{chunk-A5GBXCP5.js → chunk-KH4T6STG.js} +2 -2
- package/dist/cli/chunks/{chunk-VMDFFTCK.js → chunk-KJBYZO57.js} +1 -1
- package/dist/cli/chunks/{chunk-GJYHWYXR.js → chunk-KP4OKOKV.js} +2 -2
- package/dist/cli/chunks/chunk-L2MBKVSE.js +2 -0
- package/dist/cli/chunks/{chunk-XIQW7EFL.js → chunk-L3IPUIT3.js} +2 -2
- package/dist/cli/chunks/{chunk-W5HQUIML.js → chunk-L7PSU2YN.js} +2 -2
- package/dist/cli/chunks/{chunk-6DPYNAOK.js → chunk-LA3JPGQA.js} +2 -2
- package/dist/cli/chunks/{chunk-5PBLPQ5T.js → chunk-LC2QRN7V.js} +14 -13
- package/dist/cli/chunks/{chunk-SSYAQZXA.js → chunk-LHY7TMTM.js} +2 -2
- package/dist/cli/chunks/{chunk-QQWBWEJS.js → chunk-LLQ2UMF6.js} +3 -3
- package/dist/cli/chunks/{chunk-DTMAS2GB.js → chunk-LOJ7OO6W.js} +2 -2
- package/dist/cli/chunks/{chunk-32GN3JKR.js → chunk-LPUSH3VF.js} +1 -1
- package/dist/cli/chunks/{chunk-SDLWKRVL.js → chunk-LSEC2BU7.js} +2 -2
- package/dist/cli/chunks/{chunk-IOKYCMTJ.js → chunk-LTGB7OIU.js} +2 -2
- package/dist/cli/chunks/{chunk-6ZBXSOX6.js → chunk-LUG7YNVZ.js} +2 -2
- package/dist/cli/chunks/{chunk-CAKMOVZ6.js → chunk-LWAFRYKE.js} +2 -2
- package/dist/cli/chunks/{chunk-FLNAW7C4.js → chunk-M24ZAZ4U.js} +2 -2
- package/dist/cli/chunks/{chunk-L2DWPVNJ.js → chunk-MKRKRXTX.js} +1 -1
- package/dist/cli/chunks/{chunk-YTHTQPWR.js → chunk-MNNLONAD.js} +1 -1
- package/dist/cli/chunks/{chunk-V5NHZV7S.js → chunk-MQM37KAR.js} +2 -2
- package/dist/cli/chunks/{chunk-PPUZWYUG.js → chunk-MSX2OHYT.js} +2 -2
- package/dist/cli/chunks/{chunk-YRAX7SFJ.js → chunk-MVYQRVLP.js} +2 -2
- package/dist/cli/chunks/{chunk-QVDCVD5D.js → chunk-MZC5WM2P.js} +2 -2
- package/dist/cli/chunks/{chunk-S75SOOZL.js → chunk-MZRBNBB3.js} +2 -2
- package/dist/cli/chunks/{chunk-FL64OUBA.js → chunk-N3KQU4UC.js} +2 -2
- package/dist/cli/chunks/{chunk-G5RHFBAY.js → chunk-NKU3FFM4.js} +2 -2
- package/dist/cli/chunks/chunk-O5EWFR76.js +2 -0
- package/dist/cli/chunks/{chunk-63ZKI4PX.js → chunk-O5RDHD5T.js} +2 -2
- package/dist/cli/chunks/chunk-O6UWIXME.js +3 -0
- package/dist/cli/chunks/{chunk-HCH4Y6XX.js → chunk-OA4EQDC4.js} +2 -2
- package/dist/cli/chunks/{chunk-QPEOLAAS.js → chunk-OBCXCRXK.js} +1 -1
- package/dist/cli/chunks/{chunk-6ICX3FEG.js → chunk-OHU5P25N.js} +22 -22
- package/dist/cli/chunks/{chunk-GFWHUQSF.js → chunk-OOSV2RIA.js} +2 -2
- package/dist/cli/chunks/{chunk-MO55CVMT.js → chunk-OW23N2Y5.js} +14 -14
- package/dist/cli/chunks/{chunk-M7WJCTG3.js → chunk-OXOO3YDL.js} +2 -2
- package/dist/cli/chunks/{chunk-KQYJ4VQ5.js → chunk-OYGKSSSI.js} +1 -1
- package/dist/cli/chunks/chunk-PGO46IIW.js +2 -0
- package/dist/cli/chunks/{chunk-NVEWF4JV.js → chunk-PZOYQHWS.js} +1 -1
- package/dist/cli/chunks/{chunk-IESR7TNB.js → chunk-Q2BZSG7Z.js} +2 -2
- package/dist/cli/chunks/{chunk-XIIQ5QTT.js → chunk-Q7V722K5.js} +2 -2
- package/dist/cli/chunks/{chunk-F742SZAX.js → chunk-QZU6M5IO.js} +2 -2
- package/dist/cli/chunks/{chunk-PINSJCM3.js → chunk-R55Y76SJ.js} +1 -1
- package/dist/cli/chunks/{chunk-5B5QPCNU.js → chunk-RMEQYJPU.js} +4 -4
- package/dist/cli/chunks/{chunk-ZQ2XW3IP.js → chunk-RTYXFXTI.js} +2 -2
- package/dist/cli/chunks/{chunk-DVYHMDFR.js → chunk-SJF3O4FX.js} +374 -371
- package/dist/cli/chunks/{chunk-AG2EWGXS.js → chunk-SOUS7Z2H.js} +2 -2
- package/dist/cli/chunks/{chunk-3HD7E6HN.js → chunk-SRVNR3R3.js} +2 -2
- package/dist/cli/chunks/{chunk-KITOPKRG.js → chunk-SU3SXMVG.js} +2 -2
- package/dist/cli/chunks/chunk-SWGPLXWW.js +32 -0
- package/dist/cli/chunks/{chunk-ZR2TKVXQ.js → chunk-TRB3EVH3.js} +2 -2
- package/dist/cli/chunks/{chunk-OCV2XEWQ.js → chunk-TVBDUMKT.js} +2 -2
- package/dist/cli/chunks/{chunk-IOQ6ZQ5W.js → chunk-TWTXPSFU.js} +1 -1
- package/dist/cli/chunks/{chunk-CJSHWQXP.js → chunk-ULYUVUL2.js} +2 -2
- package/dist/cli/chunks/{chunk-PHT5N7SC.js → chunk-UNTBVJ5X.js} +2 -2
- package/dist/cli/chunks/{chunk-LKTTUHLF.js → chunk-UQAA4PHU.js} +2 -2
- package/dist/cli/chunks/{chunk-SR52XP5F.js → chunk-UWSJVKTE.js} +1 -1
- package/dist/cli/chunks/{chunk-L6QSTQME.js → chunk-V2LJ54KP.js} +2 -2
- package/dist/cli/chunks/{chunk-FBDVGRSC.js → chunk-VCCTTKP3.js} +7 -7
- package/dist/cli/chunks/{chunk-YLMNVLDK.js → chunk-VEGUYUVS.js} +1 -1
- package/dist/cli/chunks/{chunk-ASEOFRIG.js → chunk-VUQPVWNK.js} +2 -2
- package/dist/cli/chunks/{chunk-VXFLJNCA.js → chunk-VVGUE2T2.js} +2 -2
- package/dist/cli/chunks/{chunk-4NFQLP6R.js → chunk-W5ASDHJQ.js} +1 -1
- package/dist/cli/chunks/{chunk-I7MQIM2U.js → chunk-WGXT5NWQ.js} +1 -1
- package/dist/cli/chunks/chunk-WJN3V7QB.js +7 -0
- package/dist/cli/chunks/chunk-WPCRQIIF.js +29 -0
- package/dist/cli/chunks/{chunk-SASBO5Y5.js → chunk-WQNLXUWA.js} +6 -6
- package/dist/cli/chunks/{chunk-5SPCGMBB.js → chunk-WZVRMKG2.js} +2 -2
- package/dist/cli/chunks/{chunk-MI5MFHRA.js → chunk-X27IUWTD.js} +2 -2
- package/dist/cli/chunks/{chunk-HJ6ZGVTB.js → chunk-X4B345B6.js} +2 -2
- package/dist/cli/chunks/{chunk-HVRRLYX6.js → chunk-X5I2Y4VO.js} +2 -2
- package/dist/cli/chunks/{chunk-SUDMM5SO.js → chunk-X7IQIFTS.js} +2 -2
- package/dist/cli/chunks/chunk-XJN3RKUD.js +3 -0
- package/dist/cli/chunks/{chunk-E3D4GPLP.js → chunk-XQMGXTHJ.js} +3 -3
- package/dist/cli/chunks/{chunk-67Z5R7RJ.js → chunk-XTSAMB2Q.js} +2 -2
- package/dist/cli/chunks/{chunk-KVF4NXGQ.js → chunk-XZLIF4O2.js} +2 -2
- package/dist/cli/chunks/{chunk-EA4YQVKS.js → chunk-Y4LSEOZ3.js} +1 -1
- package/dist/cli/chunks/{chunk-OAEE6JWQ.js → chunk-Y4YN2RXR.js} +2 -2
- package/dist/cli/chunks/{chunk-CEYSYSK5.js → chunk-YDI56L35.js} +2 -2
- package/dist/cli/chunks/{chunk-JDIYMZCQ.js → chunk-YFILS5D5.js} +2 -2
- package/dist/cli/chunks/{chunk-GAHNO6JJ.js → chunk-YISDX6WB.js} +2 -2
- package/dist/cli/chunks/{chunk-AGRV5B3T.js → chunk-YP2GHQSV.js} +2 -2
- package/dist/cli/chunks/{chunk-UNGBRZDK.js → chunk-YSX756AM.js} +4 -4
- package/dist/cli/chunks/{chunk-BEKDKVQT.js → chunk-YWANOASW.js} +2 -2
- package/dist/cli/chunks/{chunk-JQ3DYUMS.js → chunk-YYIJLG7S.js} +2 -2
- package/dist/cli/chunks/{chunk-CRPIYUTJ.js → chunk-Z7SD7LXM.js} +2 -2
- package/dist/cli/chunks/{chunk-U2A7NHZA.js → chunk-ZDWD73UF.js} +2 -2
- package/dist/cli/chunks/{chunk-WP4RETKG.js → chunk-ZFT3RLA4.js} +2 -2
- package/dist/cli/chunks/{chunk-VJCIEHEF.js → chunk-ZNTHX5G3.js} +1 -1
- package/dist/cli/chunks/{chunk-PF7RBAYL.js → chunk-ZS27R7VL.js} +2 -2
- package/dist/cli/chunks/{chunk-24OX5TQJ.js → chunk-ZXHHHR7K.js} +1 -1
- package/dist/cli/chunks/{ci-MFUR4CWV.js → ci-N5MOMNXH.js} +2 -2
- package/dist/cli/chunks/{ci-config-PNDLQ6XV.js → ci-config-6L2ROQCW.js} +2 -2
- package/dist/cli/chunks/{ci-output-PFZ4M7NC.js → ci-output-DSRBYEIK.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-5HH6NLZN.js → circuit-breaker-VRPTNBL7.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-QCKYLGLC.js → claude-flow-setup-4YFG3FU5.js} +2 -2
- package/dist/cli/chunks/client-I3L6BKRQ.js +2 -0
- package/dist/cli/chunks/{cline-installer-EASVPFXR.js → cline-installer-7RGYJWGN.js} +2 -2
- package/dist/cli/chunks/{code-UJXDVYRK.js → code-ISC6NW2K.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-BZJ3UDP4.js → code-index-extractor-2FID75YV.js} +2 -2
- package/dist/cli/chunks/{codex-installer-XSQZUVOZ.js → codex-installer-DZ7OG6KM.js} +2 -2
- package/dist/cli/chunks/{completions-OWOOJFI2.js → completions-SM3LICWK.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-KP5TOHDT.js → complexity-analyzer-ZWD2CTAD.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-IFKQXLHM.js → continuedev-installer-AGASOA26.js} +2 -2
- package/dist/cli/chunks/copilot-installer-CLPZYTQC.js +3 -0
- package/dist/cli/chunks/core-handlers-5EFOJ37H.js +2 -0
- package/dist/cli/chunks/{cost-tracker-MMDDNKZB.js → cost-tracker-7PIGQYDV.js} +2 -2
- package/dist/cli/chunks/{coverage-LUH2B7NT.js → coverage-T2GEBTYS.js} +9 -9
- package/dist/cli/chunks/cross-domain-router-65WJAKVD.js +2 -0
- package/dist/cli/chunks/{cursor-installer-4YLM5GWM.js → cursor-installer-KXBID4MB.js} +2 -2
- package/dist/cli/chunks/daemon-43MXIVH3.js +18 -0
- package/dist/cli/chunks/{daemon-MZKVM4CJ.js → daemon-VAMJLQJ5.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-X4CYW665.js → dag-attention-scheduler-UBP4VHTA.js} +2 -2
- package/dist/cli/chunks/{detect-7BM2XINO.js → detect-QWFIQRKI.js} +2 -2
- package/dist/cli/chunks/{dist-node-Y5APLEYB.js → dist-node-I2GICS3W.js} +2 -2
- package/dist/cli/chunks/{domain-handler-X3ZRJNAH.js → domain-handler-Z66ISB2A.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-2UW5KQJB.js → domain-plugins-KHMD3FKT.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-35W4CIBV.js → domain-transfer-JWGNNA6K.js} +2 -2
- package/dist/cli/chunks/dream-VQ2PZCVR.js +2 -0
- package/dist/cli/chunks/embed-and-insert-pattern-F5P5B6JX.js +3 -0
- package/dist/cli/chunks/{embedding-space-SBM2MZD2.js → embedding-space-KHG6TITM.js} +2 -2
- package/dist/cli/chunks/{eval-4QA2SROK.js → eval-43OHU7EI.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-Z6BF6KYM.js → experience-capture-middleware-KXD47H6P.js} +3 -3
- package/dist/cli/chunks/{fast-paths-FIORX6GN.js → fast-paths-6D75D5KD.js} +2 -2
- package/dist/cli/chunks/{feature-flags-6LYI2T4G.js → feature-flags-IE35Y55N.js} +2 -2
- package/dist/cli/chunks/{feature-flags-ZOO7LMIC.js → feature-flags-OYYHY7LS.js} +2 -2
- package/dist/cli/chunks/file-discovery-LGBTY3ID.js +2 -0
- package/dist/cli/chunks/{fleet-7WF53H4F.js → fleet-AGVJMFGD.js} +16 -16
- package/dist/cli/chunks/{gnn-wrapper-KJ6B7BRM.js → gnn-wrapper-5L66A7LW.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-DEKKMOVW.js → heartbeat-handler-2BY6YYOT.js} +5 -5
- package/dist/cli/chunks/heartbeat-scheduler-3DU3M5AT.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-N2IMSRPV.js +2 -0
- package/dist/cli/chunks/hnsw-index-DVU7TTJE.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-L27WS27N.js → hnsw-legacy-bridge-RYMWFNAH.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-4YOQC6L4.js → hnswlib-node-GG47HP2P.js} +2 -2
- package/dist/cli/chunks/{hooks-TAOKV4EJ.js → hooks-FQNACS24.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-AS2PNHOD.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-BODRJLHL.js → hypergraph-engine-6BYNJQEP.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-RKMYJNTU.js → hypergraph-handler-CYTAXZKJ.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-Y4OONLFP.js +2 -0
- package/dist/cli/chunks/{init-guard-MXHSLSB2.js → init-guard-METTAV5O.js} +2 -2
- package/dist/cli/chunks/{init-handler-HUE57IFW.js → init-handler-GFT74U5Y.js} +6 -6
- package/dist/cli/chunks/init-wizard-HLNUBJQN.js +2 -0
- package/dist/cli/chunks/kernel-XKFWCL7Y.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-S333IKYQ.js → kilocode-installer-GZV2D3FF.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-WM5DLQWC.js → kiro-installer-Q4ZXUFC7.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-CNL77CSZ.js +2 -0
- package/dist/cli/chunks/{learning-LNHMQLH5.js → learning-WA2QEYL7.js} +35 -34
- package/dist/cli/chunks/{llm-router-EWFXYZZR.js → llm-router-GRTCHWH7.js} +4 -4
- package/dist/cli/chunks/llm-router-service-UIYTYKP6.js +2 -0
- package/dist/cli/chunks/{load-FGYGWVDK.js → load-WXN3Q7Y5.js} +2 -2
- package/dist/cli/chunks/load-test-PXLW4A5B.js +2 -0
- package/dist/cli/chunks/{mcp-2FHNAAOM.js → mcp-LIQCPSJN.js} +2 -2
- package/dist/cli/chunks/{memory-DZMQ73AB.js → memory-OP6CHRFH.js} +5 -5
- package/dist/cli/chunks/memory-backend-XYOSO73Q.js +2 -0
- package/dist/cli/chunks/memory-handlers-PQFYVNVG.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-6F2UAEUW.js → multi-model-executor-H54DEVRZ.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-XY3BGOTZ.js → opencode-installer-BSQV6UAT.js} +2 -2
- package/dist/cli/chunks/{orchestrator-B4CNKUOS.js → orchestrator-TJDPQ4VL.js} +122 -35
- package/dist/cli/chunks/pattern-null-store-BKGTQFNF.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-R4GUFNMD.js → pattern-usage-recorder-FOVS4M5L.js} +2 -2
- package/dist/cli/chunks/{pipeline-FG5RKVRO.js → pipeline-4AY2ZIC6.js} +2 -2
- package/dist/cli/chunks/{platform-3BT4KEVJ.js → platform-FCSITYMR.js} +2 -2
- package/dist/cli/chunks/{plugin-WI4RIN7O.js → plugin-E56TV5S2.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-7ECDNQFS.js → prime-radiant-advanced-wasm-ACOPC533.js} +2 -2
- package/dist/cli/chunks/project-root-MPX7CN2C.js +2 -0
- package/dist/cli/chunks/protocol-executor-CRQOCC4A.js +2 -0
- package/dist/cli/chunks/{protocol-handler-WNODKPGW.js → protocol-handler-KRVXF4LS.js} +2 -2
- package/dist/cli/chunks/{prove-5RHAEPYZ.js → prove-KMFPSKGD.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-UEGQ3O7F.js +2 -0
- package/dist/cli/chunks/{quality-WPHR7BGQ.js → quality-6DBI3HLB.js} +2 -2
- package/dist/cli/chunks/{quality-gate-4RKTEZMX.js → quality-gate-3ROZMEIL.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-32574XSG.js +2 -0
- package/dist/cli/chunks/real-embeddings-MIGZNKK3.js +2 -0
- package/dist/cli/chunks/{ref-validation-TPAWHOHH.js → ref-validation-EYIP7DHW.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-7AVHFNDI.js → roocode-installer-IGGZHR2Y.js} +2 -2
- package/dist/cli/chunks/router-CZJY5WX6.js +2 -0
- package/dist/cli/chunks/routing-feedback-RC3UBNFX.js +2 -0
- package/dist/cli/chunks/{routing-handler-YKEDVJSH.js → routing-handler-BWNHBYDC.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-JUAMM354.js → ruvector-commands-PXIHF432.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-OG7OV2AK.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-THYMW7ZO.js +2 -0
- package/dist/cli/chunks/rvf-migration-coordinator-3H6CLFU7.js +2 -0
- package/dist/cli/chunks/rvf-native-adapter-6JQJIKKW.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-VJDUIRTX.js → rvf-store-integrity-CVB3NMSL.js} +2 -2
- package/dist/cli/chunks/safe-db-QFKCVTIJ.js +2 -0
- package/dist/cli/chunks/schedule-6JLVMMYB.js +2 -0
- package/dist/cli/chunks/scheduler-3MPZRMJD.js +2 -0
- package/dist/cli/chunks/{security-ORDN3RD2.js → security-DCRGOTWU.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-CF4BCIO7.js → shared-rvf-adapter-GKD74QUB.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-C32UBR6D.js → shared-rvf-dual-writer-HVAAVEOH.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-LGTIKAEX.js +2 -0
- package/dist/cli/chunks/{standalone-memory-OXRJYZXN.js → standalone-memory-O7O2U5N4.js} +2 -2
- package/dist/cli/chunks/{status-handler-BCX5D4HY.js → status-handler-BQTPJJTL.js} +2 -2
- package/dist/cli/chunks/{structural-health-LFG7RUU6.js → structural-health-4H6J4OHK.js} +2 -2
- package/dist/cli/chunks/sync-DJ4TF6QX.js +2 -0
- package/dist/cli/chunks/{sync-YJEE2K2L.js → sync-WW5TAVYW.js} +2 -2
- package/dist/cli/chunks/{task-handler-6LXKPTXJ.js → task-handler-HEM4IEOW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-CILP36I7.js → task-handlers-JRA3NXIR.js} +3 -3
- package/dist/cli/chunks/test-772ZXVG2.js +34 -0
- package/dist/cli/chunks/test-runner-process-XGF2U3NG.js +2 -0
- package/dist/cli/chunks/{test-scheduling-ISI2O4Q5.js → test-scheduling-4TRB7LZ7.js} +3 -3
- package/dist/cli/chunks/token-bootstrap-CICBIJ7T.js +2 -0
- package/dist/cli/chunks/{token-usage-XOC5KG7S.js → token-usage-B7PEKE2G.js} +2 -2
- package/dist/cli/chunks/{transformers-LSLQAARK.js → transformers-V7X7BDZX.js} +2 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-OXPFKFZS.js +2 -0
- package/dist/cli/chunks/{types-5BLCGLCR.js → types-AHHTUY3I.js} +2 -2
- package/dist/cli/chunks/unified-memory-GUR3IUI6.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-NJP2F2RY.js +2 -0
- package/dist/cli/chunks/unified-persistence-NILBWXDP.js +2 -0
- package/dist/cli/chunks/{upgrade-RQJYLK3J.js → upgrade-DZ4DLUQ5.js} +2 -2
- package/dist/cli/chunks/{validate-QBHWXXCK.js → validate-4DTLIDJE.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-IKXBKFB5.js → validate-swarm-A26UFVIS.js} +2 -2
- package/dist/cli/chunks/visual-security-YECYZ27X.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-ZF6FIE5R.js → web-tree-sitter-F2C7QRYT.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-HQGDZT5D.js → windsurf-installer-OOBTDA6W.js} +2 -2
- package/dist/cli/chunks/{witness-chain-DCHCAMSQ.js → witness-chain-KGFZJP32.js} +2 -2
- package/dist/cli/chunks/witness-chain-LYBXFLJB.js +2 -0
- package/dist/cli/chunks/witness-chain-repair-CNTXOGPN.js +2 -0
- package/dist/cli/chunks/{witness-chain-verifier-PX2OQ6XT.js → witness-chain-verifier-OB7ZZOI3.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-RXYQNFJB.js → witness-key-manager-YCKGKGQI.js} +2 -2
- package/dist/cli/chunks/{workflow-FBKCA4H6.js → workflow-PRERHWKY.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-UIBGWCU3.js +2 -0
- package/dist/cli/chunks/wrappers-L4UY4V63.js +2 -0
- package/dist/cli/commands/coverage.js +4 -1
- package/dist/cli/commands/learning-prune.js +9 -1
- package/dist/cli/commands/test.js +26 -4
- package/dist/cli/handlers/brain-handler.js +32 -2
- package/dist/cli/handlers/heartbeat-handler.js +3 -1
- package/dist/cli/utils/coverage-data.js +5 -1
- package/dist/cli/utils/coverage-verdict.d.ts +10 -2
- package/dist/cli/utils/coverage-verdict.js +23 -8
- package/dist/cli/utils/fleet-operation.js +9 -3
- package/dist/coordination/handlers/code-intelligence-handlers.js +17 -3
- package/dist/coordination/handlers/coverage-handlers.js +22 -9
- package/dist/coordination/handlers/coverage-target.d.ts +22 -2
- package/dist/coordination/handlers/coverage-target.js +45 -9
- package/dist/coordination/handlers/handler-utils.d.ts +19 -0
- package/dist/coordination/handlers/handler-utils.js +22 -8
- package/dist/coordination/handlers/test-execution-handlers.js +64 -20
- package/dist/coordination/protocols/code-intelligence-index.js +6 -3
- package/dist/coordination/protocols/learning-consolidation-archive.d.ts +6 -3
- package/dist/coordination/protocols/learning-consolidation-archive.js +4 -3
- package/dist/coordination/workflow-builtin.js +1 -0
- 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/defect-intelligence/interfaces.d.ts +2 -0
- package/dist/domains/defect-intelligence/prediction-history.d.ts +15 -1
- package/dist/domains/defect-intelligence/prediction-history.js +63 -7
- package/dist/domains/defect-intelligence/services/defect-predictor.d.ts +1 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +33 -13
- package/dist/domains/learning-optimization/coordinator.js +17 -10
- package/dist/domains/learning-optimization/domain-ranking.d.ts +26 -0
- package/dist/domains/learning-optimization/domain-ranking.js +28 -0
- package/dist/domains/learning-optimization/interfaces.d.ts +5 -0
- package/dist/domains/learning-optimization/pattern-archive.d.ts +55 -8
- package/dist/domains/learning-optimization/pattern-archive.js +90 -17
- package/dist/domains/learning-optimization/pattern-consolidation.js +18 -2
- package/dist/domains/learning-optimization/pattern-merge.d.ts +26 -0
- package/dist/domains/learning-optimization/pattern-merge.js +127 -0
- package/dist/domains/learning-optimization/services/learning-coordinator.js +21 -35
- 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 +85 -17
- package/dist/init/copilot-installer.d.ts +6 -0
- package/dist/init/copilot-installer.js +37 -17
- package/dist/init/init-wizard-steps.js +3 -1
- package/dist/init/phases/07-hooks.js +97 -10
- package/dist/init/platform-config-generator.d.ts +10 -0
- package/dist/init/platform-config-generator.js +26 -1
- package/dist/integrations/embeddings/cache/EmbeddingCache.js +1 -1
- package/dist/integrations/ruvector/brain-rvf-exporter.d.ts +16 -1
- package/dist/integrations/ruvector/brain-rvf-exporter.js +18 -32
- package/dist/integrations/ruvector/brain-rvf-richness.d.ts +75 -0
- package/dist/integrations/ruvector/brain-rvf-richness.js +127 -0
- package/dist/kernel/unified-memory-migration.js +1 -1
- package/dist/kernel/unified-memory.d.ts +8 -0
- package/dist/kernel/unified-memory.js +13 -0
- package/dist/learning/checkpoint-shrink-ack.d.ts +25 -0
- package/dist/learning/checkpoint-shrink-ack.js +57 -0
- package/dist/learning/dream/dream-engine.d.ts +44 -3
- package/dist/learning/dream/dream-engine.js +6 -2
- package/dist/learning/embedder-endpoint-client.d.ts +45 -0
- package/dist/learning/embedder-endpoint-client.js +98 -3
- package/dist/learning/embedder-identity-store.js +3 -1
- package/dist/learning/embedding-space-legacy-adoption.d.ts +53 -0
- package/dist/learning/embedding-space-legacy-adoption.js +115 -0
- package/dist/learning/embedding-space-registry.d.ts +90 -0
- package/dist/learning/embedding-space-registry.js +181 -0
- package/dist/learning/experience-capture.d.ts +3 -1
- package/dist/learning/experience-capture.js +15 -5
- package/dist/learning/experience-space-verification.d.ts +2 -0
- package/dist/learning/experience-space-verification.js +3 -2
- package/dist/learning/learning-retention.js +4 -0
- package/dist/learning/pattern-promotion.d.ts +7 -0
- package/dist/learning/pattern-promotion.js +64 -12
- package/dist/learning/real-embeddings.d.ts +3 -0
- package/dist/learning/real-embeddings.js +73 -11
- package/dist/learning/rvf-pattern-store.js +6 -1
- package/dist/mcp/bundle.js +558 -537
- package/dist/mcp/handlers/domain-handler-configs.d.ts +3 -0
- package/dist/mcp/handlers/domain-handler-configs.js +1 -0
- package/dist/mcp/handlers/heartbeat-handlers.d.ts +4 -2
- package/dist/mcp/protocol-server.js +1 -1
- package/dist/mcp/tools/learning-optimization/optimize.d.ts +6 -1
- package/dist/mcp/tools/learning-optimization/optimize.js +20 -11
- package/dist/planning/goap-planner.js +4 -0
- package/dist/planning/plan-executor.js +6 -2
- 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/git/git-analyzer.d.ts +30 -11
- package/dist/shared/git/git-analyzer.js +95 -48
- package/dist/shared/io/confined-read.d.ts +32 -7
- package/dist/shared/io/confined-read.js +58 -25
- package/dist/shared/io/file-reader.js +4 -1
- package/dist/shared/pytest-junit-report.d.ts +93 -0
- package/dist/shared/pytest-junit-report.js +241 -0
- package/dist/shared/safe-db.d.ts +1 -1
- package/dist/shared/safe-db.js +20 -5
- package/dist/shared/sqlite-journal-mode.d.ts +39 -0
- package/dist/shared/sqlite-journal-mode.js +53 -0
- package/dist/shared/test-runner-project.d.ts +51 -1
- package/dist/shared/test-runner-project.js +140 -25
- package/dist/sync/claude-flow-bridge.js +1 -1
- package/dist/sync/readers/sqlite-reader.js +3 -4
- package/dist/sync/writers/sqlite-writer.js +1 -1
- package/dist/workers/interfaces.d.ts +2 -2
- package/dist/workers/quality-daemon/git-watcher.d.ts +8 -0
- package/dist/workers/quality-daemon/git-watcher.js +54 -12
- package/dist/workers/quality-daemon/index.js +1 -1
- package/dist/workers/quality-daemon/priority-queue.d.ts +2 -1
- package/dist/workers/workers/defect-predictor.d.ts +9 -4
- package/dist/workers/workers/defect-predictor.js +98 -37
- 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/brain-handler-HQWZFO52.js +0 -95
- package/dist/cli/chunks/browser-workflow-A2MEZ66K.js +0 -2
- package/dist/cli/chunks/chunk-CGGUM2YJ.js +0 -3
- package/dist/cli/chunks/chunk-D6COXLYE.js +0 -8
- package/dist/cli/chunks/chunk-EGYE5UPQ.js +0 -2
- package/dist/cli/chunks/chunk-IUBJVHNB.js +0 -3
- package/dist/cli/chunks/chunk-KL7OKSU2.js +0 -4
- package/dist/cli/chunks/chunk-KPRCB5LT.js +0 -7
- package/dist/cli/chunks/chunk-LRSX2FJM.js +0 -2
- package/dist/cli/chunks/chunk-M4FRQ4TE.js +0 -12
- package/dist/cli/chunks/chunk-MAFQV4U4.js +0 -16
- package/dist/cli/chunks/chunk-NZU4ACBZ.js +0 -2
- package/dist/cli/chunks/chunk-RV74I3YO.js +0 -3
- package/dist/cli/chunks/chunk-SJ6Y4725.js +0 -5
- package/dist/cli/chunks/chunk-UE5ZOZR2.js +0 -2
- package/dist/cli/chunks/chunk-VSIKHWZ4.js +0 -29
- package/dist/cli/chunks/chunk-YAPLJR7K.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/daemon-CAVZ7OFV.js +0 -18
- 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/token-bootstrap-VUELSBOS.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/witness-chain-repair-PUX2NFDL.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-P2APAJAA.js +0 -2
- package/dist/cli/chunks/wrappers-TWSKBTWD.js +0 -2
|
@@ -0,0 +1,93 @@
|
|
|
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 { TestRunnerExecutionError } from './test-runner-verdict.js';
|
|
21
|
+
import { Result } from './types';
|
|
22
|
+
/** True for a Python test file, which only pytest can run. */
|
|
23
|
+
export declare function isPythonTestFile(file: string): boolean;
|
|
24
|
+
/** The Python interpreter that runs pytest. */
|
|
25
|
+
export declare function resolvePythonCommand(env?: NodeJS.ProcessEnv): string;
|
|
26
|
+
/** Environment for a pytest process: no ANSI colour in its output or report. */
|
|
27
|
+
export declare const PYTEST_ENV: Readonly<Record<string, string>>;
|
|
28
|
+
/** Command and arguments that run `targets` (paths or node ids) with pytest. */
|
|
29
|
+
export declare function pytestCommand(targets: readonly string[], reportPath: string, env?: NodeJS.ProcessEnv): {
|
|
30
|
+
command: string;
|
|
31
|
+
args: string[];
|
|
32
|
+
};
|
|
33
|
+
/** A per-run JUnit report location, read back after pytest exits. */
|
|
34
|
+
export interface PytestJunitReport {
|
|
35
|
+
/** Absolute path pytest writes the report to. */
|
|
36
|
+
readonly path: string;
|
|
37
|
+
/** Arguments that point pytest at the report (already in pytestCommand). */
|
|
38
|
+
readonly args: readonly string[];
|
|
39
|
+
/** The report text; undefined when pytest wrote none. Malformed reports throw. */
|
|
40
|
+
read(stdout?: string): string | undefined;
|
|
41
|
+
/** Remove the temporary report directory. Safe to call more than once. */
|
|
42
|
+
cleanup(): void;
|
|
43
|
+
}
|
|
44
|
+
export declare function createPytestJunitReport(): PytestJunitReport;
|
|
45
|
+
export type PytestCaseStatus = 'passed' | 'failed' | 'error' | 'skipped';
|
|
46
|
+
/** One `<testcase>` of a pytest JUnit report. */
|
|
47
|
+
export interface PytestJunitCase {
|
|
48
|
+
classname: string;
|
|
49
|
+
name: string;
|
|
50
|
+
status: PytestCaseStatus;
|
|
51
|
+
/** Duration in milliseconds, when reported. */
|
|
52
|
+
duration?: number;
|
|
53
|
+
/** The failure, error or skip message attribute. */
|
|
54
|
+
message?: string;
|
|
55
|
+
/** The failure or error body (traceback). */
|
|
56
|
+
details?: string;
|
|
57
|
+
}
|
|
58
|
+
/** The test cases of a pytest JUnit XML report, in report order. */
|
|
59
|
+
export declare function parsePytestJunitXml(xml: string): PytestJunitCase[];
|
|
60
|
+
/**
|
|
61
|
+
* The run file a test case belongs to, and its name inside that file
|
|
62
|
+
* (`TestClass::test_name[param]`, the node id without the file). The class
|
|
63
|
+
* name is the module's dotted path relative to pytest's rootdir followed by
|
|
64
|
+
* any classes, so the file is the one whose path ends with the longest
|
|
65
|
+
* leading part of it.
|
|
66
|
+
*/
|
|
67
|
+
export declare function locatePytestCase(testCase: Pick<PytestJunitCase, 'classname' | 'name'>, files: readonly string[]): {
|
|
68
|
+
file: string;
|
|
69
|
+
name: string;
|
|
70
|
+
};
|
|
71
|
+
/** One test of a finished pytest run. */
|
|
72
|
+
export interface PytestTest {
|
|
73
|
+
name: string;
|
|
74
|
+
file: string;
|
|
75
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
76
|
+
duration?: number;
|
|
77
|
+
/** Failure or error text for a failed test. */
|
|
78
|
+
failureMessage?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface PytestRun {
|
|
81
|
+
total: number;
|
|
82
|
+
passed: number;
|
|
83
|
+
failed: number;
|
|
84
|
+
skipped: number;
|
|
85
|
+
tests: PytestTest[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The result of a finished pytest run, or the runner error that kept it from
|
|
89
|
+
* being one. `report` is the JUnit XML text, undefined when pytest wrote none.
|
|
90
|
+
* A test case that errored (in a fixture, say) counts as a failed test.
|
|
91
|
+
*/
|
|
92
|
+
export declare function pytestRunFromReport(report: string | undefined, files: readonly string[], exitCode: number | null, output: string, python?: string): Result<PytestRun, TestRunnerExecutionError>;
|
|
93
|
+
//# sourceMappingURL=pytest-junit-report.d.ts.map
|
|
@@ -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
|
package/dist/shared/safe-db.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface SafeDbOptions {
|
|
|
16
16
|
fileMustExist?: boolean;
|
|
17
17
|
/** Busy timeout in ms (default: 5000) */
|
|
18
18
|
busyTimeout?: number;
|
|
19
|
-
/** Enable WAL mode (default: true for writable
|
|
19
|
+
/** Enable WAL mode (default: true for writable; always ignored for readonly) */
|
|
20
20
|
walMode?: boolean;
|
|
21
21
|
/**
|
|
22
22
|
* M3.2: on a malformed/corrupt existing DB, auto-restore the newest verified
|
package/dist/shared/safe-db.js
CHANGED
|
@@ -12,6 +12,7 @@ import Database from 'better-sqlite3';
|
|
|
12
12
|
import { basename } from 'node:path';
|
|
13
13
|
import { attemptAutoRestore } from './db-recovery.js';
|
|
14
14
|
import { withNativeModuleRemedy } from './native-module-errors.js';
|
|
15
|
+
import { setJournalModeWithRetry } from './sqlite-journal-mode.js';
|
|
15
16
|
/**
|
|
16
17
|
* Open a SQLite database with safe defaults that prevent corruption.
|
|
17
18
|
*
|
|
@@ -95,8 +96,11 @@ export function openDatabase(dbPath, opts) {
|
|
|
95
96
|
// 2026-07-07), so continuing to write in WAL would trade a loud outage for
|
|
96
97
|
// silent corruption. Availability is not worth that; the message below
|
|
97
98
|
// carries the exact command that finds the real holder.
|
|
99
|
+
//
|
|
100
|
+
// Concurrent openers racing the same one-time switch (#1164) are retried
|
|
101
|
+
// within busyTimeout first; only contention that outlasts it fails closed.
|
|
98
102
|
try {
|
|
99
|
-
db
|
|
103
|
+
setJournalModeWithRetry(db, desired, busyTimeout);
|
|
100
104
|
}
|
|
101
105
|
catch (err) {
|
|
102
106
|
const code = err?.code;
|
|
@@ -135,11 +139,22 @@ export function openDatabase(dbPath, opts) {
|
|
|
135
139
|
}
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
|
-
else if (walMode) {
|
|
142
|
+
else if (walMode && !readonly) {
|
|
139
143
|
// WAL mode for writable connections prevents corruption from concurrent
|
|
140
|
-
// writers. Readonly connections inherit
|
|
141
|
-
//
|
|
142
|
-
|
|
144
|
+
// writers. Readonly connections inherit the file's journal mode and must
|
|
145
|
+
// not switch it: that is a write and fails with SQLITE_READONLY on a
|
|
146
|
+
// rollback-journal file (#1320), so `walMode` is ignored for readonly opens.
|
|
147
|
+
//
|
|
148
|
+
// #1164: switching a rollback-journal file to WAL upgrades a read lock to a
|
|
149
|
+
// write lock, and SQLite returns SQLITE_BUSY for that at once instead of
|
|
150
|
+
// waiting on busy_timeout. Concurrent first opens retry within busyTimeout.
|
|
151
|
+
try {
|
|
152
|
+
setJournalModeWithRetry(db, 'WAL', busyTimeout);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
db.close();
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
143
158
|
}
|
|
144
159
|
return db;
|
|
145
160
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch a SQLite connection's journal mode, retrying lock contention (#1164).
|
|
3
|
+
*
|
|
4
|
+
* `PRAGMA journal_mode = WAL` on a rollback-journal database reads page 1
|
|
5
|
+
* under a SHARED lock and then upgrades to a write lock to rewrite the header.
|
|
6
|
+
* SQLite does not run the busy handler for that upgrade (an upgrade from a
|
|
7
|
+
* held read lock could deadlock), so when several processes open the same
|
|
8
|
+
* non-WAL database at once, all but one can get SQLITE_BUSY in well under a
|
|
9
|
+
* millisecond even with busy_timeout set. Leaving WAL needs an EXCLUSIVE lock
|
|
10
|
+
* and fails the same way.
|
|
11
|
+
*
|
|
12
|
+
* This retries the switch with a short, growing sleep until `budgetMs` has
|
|
13
|
+
* passed, then throws the last error. Once another process has switched the
|
|
14
|
+
* file, the retry finds the mode already set, which needs no write lock.
|
|
15
|
+
*
|
|
16
|
+
* Dependency-free (no better-sqlite3 import) so optional-dependency callers can
|
|
17
|
+
* use it with a connection they loaded themselves.
|
|
18
|
+
*/
|
|
19
|
+
/** The part of a better-sqlite3 connection this needs. */
|
|
20
|
+
export interface JournalModeConnection {
|
|
21
|
+
pragma(source: string, options?: {
|
|
22
|
+
simple?: boolean;
|
|
23
|
+
}): unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface JournalModeRetryOptions {
|
|
26
|
+
/** Synchronous sleep, injectable for tests. */
|
|
27
|
+
sleep?: (ms: number) => void;
|
|
28
|
+
/** Clock in ms, injectable for tests. */
|
|
29
|
+
now?: () => number;
|
|
30
|
+
}
|
|
31
|
+
/** True for SQLITE_BUSY / SQLITE_LOCKED, including extended codes such as SQLITE_BUSY_RECOVERY. */
|
|
32
|
+
export declare function isJournalLockContention(err: unknown): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Set `journal_mode` to `mode`, retrying SQLITE_BUSY / SQLITE_LOCKED for up to
|
|
35
|
+
* `budgetMs`. Returns the mode SQLite reports afterwards, lower-cased. Any
|
|
36
|
+
* other error is thrown at once.
|
|
37
|
+
*/
|
|
38
|
+
export declare function setJournalModeWithRetry(db: JournalModeConnection, mode: string, budgetMs: number, options?: JournalModeRetryOptions): string;
|
|
39
|
+
//# sourceMappingURL=sqlite-journal-mode.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch a SQLite connection's journal mode, retrying lock contention (#1164).
|
|
3
|
+
*
|
|
4
|
+
* `PRAGMA journal_mode = WAL` on a rollback-journal database reads page 1
|
|
5
|
+
* under a SHARED lock and then upgrades to a write lock to rewrite the header.
|
|
6
|
+
* SQLite does not run the busy handler for that upgrade (an upgrade from a
|
|
7
|
+
* held read lock could deadlock), so when several processes open the same
|
|
8
|
+
* non-WAL database at once, all but one can get SQLITE_BUSY in well under a
|
|
9
|
+
* millisecond even with busy_timeout set. Leaving WAL needs an EXCLUSIVE lock
|
|
10
|
+
* and fails the same way.
|
|
11
|
+
*
|
|
12
|
+
* This retries the switch with a short, growing sleep until `budgetMs` has
|
|
13
|
+
* passed, then throws the last error. Once another process has switched the
|
|
14
|
+
* file, the retry finds the mode already set, which needs no write lock.
|
|
15
|
+
*
|
|
16
|
+
* Dependency-free (no better-sqlite3 import) so optional-dependency callers can
|
|
17
|
+
* use it with a connection they loaded themselves.
|
|
18
|
+
*/
|
|
19
|
+
const FIRST_BACKOFF_MS = 2;
|
|
20
|
+
const MAX_BACKOFF_MS = 50;
|
|
21
|
+
/** True for SQLITE_BUSY / SQLITE_LOCKED, including extended codes such as SQLITE_BUSY_RECOVERY. */
|
|
22
|
+
export function isJournalLockContention(err) {
|
|
23
|
+
const code = err?.code;
|
|
24
|
+
return typeof code === 'string' && (code.startsWith('SQLITE_BUSY') || code.startsWith('SQLITE_LOCKED'));
|
|
25
|
+
}
|
|
26
|
+
function sleepSync(ms) {
|
|
27
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set `journal_mode` to `mode`, retrying SQLITE_BUSY / SQLITE_LOCKED for up to
|
|
31
|
+
* `budgetMs`. Returns the mode SQLite reports afterwards, lower-cased. Any
|
|
32
|
+
* other error is thrown at once.
|
|
33
|
+
*/
|
|
34
|
+
export function setJournalModeWithRetry(db, mode, budgetMs, options = {}) {
|
|
35
|
+
const sleep = options.sleep ?? sleepSync;
|
|
36
|
+
const now = options.now ?? Date.now;
|
|
37
|
+
const deadline = now() + Math.max(0, budgetMs);
|
|
38
|
+
let backoff = FIRST_BACKOFF_MS;
|
|
39
|
+
for (;;) {
|
|
40
|
+
try {
|
|
41
|
+
return String(db.pragma(`journal_mode = ${mode}`, { simple: true }) ?? '').toLowerCase();
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
const remaining = deadline - now();
|
|
45
|
+
if (!isJournalLockContention(err) || remaining <= 0)
|
|
46
|
+
throw err;
|
|
47
|
+
// Jitter so processes that collided do not retry in lockstep.
|
|
48
|
+
sleep(Math.min(remaining, backoff / 2 + Math.random() * backoff / 2));
|
|
49
|
+
backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=sqlite-journal-mode.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
|