agentic-qe 3.15.13 → 3.15.15
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/agents/v3/templates/qx-report-template.html +1 -1
- package/.claude/helpers/brain-checkpoint.cjs +124 -5
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +124 -0
- package/assets/agents/v3/templates/qx-report-template.html +1 -1
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/bundle.js +6 -6
- package/dist/cli/chunks/adapter-QU6INSKP.js +2 -0
- package/dist/cli/chunks/agent-booster-wasm-EUF4XVUC.js +2 -0
- package/dist/cli/chunks/{agent-handler-AOH6TV7W.js → agent-handler-MOX6PSIQ.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-2P54SF5N.js → agent-memory-branch-AEXKIGDG.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-PAJPENJD.js +2 -0
- package/dist/cli/chunks/{arena-NSVFCAF5.js → arena-IQ5ZZDRF.js} +2 -2
- package/dist/cli/chunks/{arena-X6MOGQHA.js → arena-M7GA3CVG.js} +4 -4
- package/dist/cli/chunks/{audit-27DJLQNM.js → audit-4IPBMKWB.js} +3 -3
- package/dist/cli/chunks/base-OTGSN6IC.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-BU5GXILS.js → better-sqlite3-IKDKJ2IE.js} +2 -2
- package/dist/cli/chunks/brain-handler-5NQUDH4W.js +95 -0
- package/dist/cli/chunks/{branch-enumerator-5CLULOCU.js → branch-enumerator-KSXELWRC.js} +2 -2
- package/dist/cli/chunks/{browser-R4DMU3LN.js → browser-6LACARWE.js} +2 -2
- package/dist/cli/chunks/browser-workflow-WLZGR6SB.js +2 -0
- package/dist/cli/chunks/{chunk-LUZNKJE6.js → chunk-22UKJGGN.js} +3 -3
- package/dist/cli/chunks/{chunk-BLSLEVDI.js → chunk-27HE2BHC.js} +2 -2
- package/dist/cli/chunks/{chunk-K4CZA77U.js → chunk-2CKERSMB.js} +2 -2
- package/dist/cli/chunks/{chunk-YSZ5OE3Z.js → chunk-2IIXCEMS.js} +2 -2
- package/dist/cli/chunks/{chunk-F3YS57NF.js → chunk-2LUTPMBO.js} +2 -2
- package/dist/cli/chunks/{chunk-GHM6MQNK.js → chunk-2ZFLULL4.js} +2 -2
- package/dist/cli/chunks/{chunk-7CMTY45A.js → chunk-337Z52QM.js} +2 -2
- package/dist/cli/chunks/{chunk-W26B7ERY.js → chunk-3CYNZFKH.js} +1 -1
- package/dist/cli/chunks/chunk-3HVFIITW.js +2 -0
- package/dist/cli/chunks/{chunk-K3TLLJMX.js → chunk-3J3RNJNX.js} +1 -1
- package/dist/cli/chunks/{chunk-MAMQA43L.js → chunk-4ATQP3PR.js} +1 -1
- package/dist/cli/chunks/{chunk-YXRASAPI.js → chunk-4D4CWP72.js} +2 -2
- package/dist/cli/chunks/{chunk-GHY6Z6KO.js → chunk-4HKAD25N.js} +3 -3
- package/dist/cli/chunks/{chunk-XNBOGCF3.js → chunk-4X3SWKBA.js} +2 -2
- package/dist/cli/chunks/{chunk-IJUHSJ2U.js → chunk-5AFVEWMT.js} +2 -2
- package/dist/cli/chunks/{chunk-SE4VNN4I.js → chunk-5C62XMJR.js} +3 -3
- package/dist/cli/chunks/{chunk-KDNJ4F3P.js → chunk-5G4UFTV4.js} +2 -2
- package/dist/cli/chunks/{chunk-DVGRPK7A.js → chunk-5I7357KS.js} +2 -2
- package/dist/cli/chunks/{chunk-YZWBNBTW.js → chunk-5KA5TVPR.js} +2 -2
- package/dist/cli/chunks/{chunk-JGZ722G3.js → chunk-5PTAFGJT.js} +2 -2
- package/dist/cli/chunks/{chunk-SVLQRAMF.js → chunk-6BRQPHMZ.js} +1 -1
- package/dist/cli/chunks/{chunk-KDVZND5Q.js → chunk-6KCSKGVY.js} +1 -1
- package/dist/cli/chunks/{chunk-LWR3FV3Y.js → chunk-6LE362LZ.js} +2 -2
- package/dist/cli/chunks/{chunk-WKGTGOYS.js → chunk-6NBRMD25.js} +3 -3
- package/dist/cli/chunks/{chunk-HQZGPJYG.js → chunk-6RBTS3NF.js} +2 -2
- package/dist/cli/chunks/{chunk-WOCGL4QP.js → chunk-6YVMX2TC.js} +2 -2
- package/dist/cli/chunks/{chunk-I3C7JOXC.js → chunk-73PBAWAF.js} +2 -2
- package/dist/cli/chunks/{chunk-75RDHBAX.js → chunk-74YG72NQ.js} +3 -3
- package/dist/cli/chunks/{chunk-O6FGXMHD.js → chunk-76P32JVU.js} +1 -1
- package/dist/cli/chunks/{chunk-LL7LDPXS.js → chunk-7ACCBHRB.js} +1 -1
- package/dist/cli/chunks/{chunk-3LJ7LQMV.js → chunk-7BLZHFKD.js} +1 -1
- package/dist/cli/chunks/{chunk-CM4LSLKR.js → chunk-7O45RQHF.js} +2 -2
- package/dist/cli/chunks/{chunk-NU3W5WFT.js → chunk-7XB3FCKM.js} +2 -2
- package/dist/cli/chunks/{chunk-E56B6IDX.js → chunk-AHMWD6JG.js} +2 -2
- package/dist/cli/chunks/{chunk-G2Q66Z23.js → chunk-AJPROCDW.js} +2 -2
- package/dist/cli/chunks/{chunk-NW7IBHJA.js → chunk-AKZO6GGG.js} +13 -13
- package/dist/cli/chunks/{chunk-IC3TQEOA.js → chunk-AOKKUB5F.js} +1 -1
- package/dist/cli/chunks/{chunk-4OVC4RIL.js → chunk-AP2W7Z3A.js} +1 -1
- package/dist/cli/chunks/{chunk-PHP5UBT4.js → chunk-BBRROA3Z.js} +2 -2
- package/dist/cli/chunks/{chunk-5FKWCZNF.js → chunk-BDKEAGQ2.js} +2 -2
- package/dist/cli/chunks/{chunk-BTVEYBW2.js → chunk-BFQTLF5X.js} +2 -2
- package/dist/cli/chunks/{chunk-HZ5NXFXH.js → chunk-BLL2XU7A.js} +2 -2
- package/dist/cli/chunks/{chunk-UTRV7T2N.js → chunk-BP5T3OEV.js} +2 -2
- package/dist/cli/chunks/{chunk-GB6HBNH2.js → chunk-BQ47GQPK.js} +2 -2
- package/dist/cli/chunks/{chunk-RFNW2LGD.js → chunk-BU4UQR36.js} +2 -2
- package/dist/cli/chunks/{chunk-WO274FRI.js → chunk-BZULJMGH.js} +2 -2
- package/dist/cli/chunks/{chunk-GU5HNCWI.js → chunk-C4KLXFJP.js} +1 -1
- package/dist/cli/chunks/{chunk-LFJALJOA.js → chunk-C4RTAVC6.js} +2 -2
- package/dist/cli/chunks/{chunk-WNQS4WTS.js → chunk-C5CXL3JP.js} +2 -2
- package/dist/cli/chunks/{chunk-MGZ5FJUW.js → chunk-CAOUV5GZ.js} +2 -2
- package/dist/cli/chunks/{chunk-XPRVF4YE.js → chunk-CBK5CT6T.js} +2 -2
- package/dist/cli/chunks/{chunk-JRRXCODW.js → chunk-DEKR3CTS.js} +2 -2
- package/dist/cli/chunks/{chunk-AQSVJNEH.js → chunk-DKX4GNRU.js} +2 -2
- package/dist/cli/chunks/{chunk-6KATY3KS.js → chunk-DUKE27HC.js} +2 -2
- package/dist/cli/chunks/{chunk-W2QWSQVE.js → chunk-DURD37JZ.js} +2 -2
- package/dist/cli/chunks/{chunk-KCW47QR5.js → chunk-E3MRDIZF.js} +1 -1
- package/dist/cli/chunks/{chunk-6Z7PRBSG.js → chunk-E56PVVWC.js} +2 -2
- package/dist/cli/chunks/{chunk-WQL7WCIZ.js → chunk-E5G4WZ2T.js} +1 -1
- package/dist/cli/chunks/{chunk-PB6J6HAA.js → chunk-EBTNMQSS.js} +2 -2
- package/dist/cli/chunks/{chunk-KADFXPPN.js → chunk-EFUJDMNC.js} +2 -2
- package/dist/cli/chunks/{chunk-QPNG5ZN2.js → chunk-EKP2SC77.js} +2 -2
- package/dist/cli/chunks/{chunk-U2FUXDDJ.js → chunk-EMSZVUYA.js} +3 -3
- package/dist/cli/chunks/{chunk-XEAEYC6Y.js → chunk-ERN56H6S.js} +1 -1
- package/dist/cli/chunks/{chunk-DNDL7SOS.js → chunk-FOOW4JVS.js} +2 -2
- package/dist/cli/chunks/{chunk-HOAJUIBQ.js → chunk-FTRSS64D.js} +2 -2
- package/dist/cli/chunks/{chunk-TOQWL2ZF.js → chunk-G242G224.js} +2 -2
- package/dist/cli/chunks/{chunk-VTDFVFST.js → chunk-G6RDCCFV.js} +2 -2
- package/dist/cli/chunks/{chunk-TWDW32W2.js → chunk-GCHYOPRZ.js} +2 -2
- package/dist/cli/chunks/{chunk-MFW5HSG4.js → chunk-GGQGCT4Y.js} +2 -2
- package/dist/cli/chunks/{chunk-G6WDYBLQ.js → chunk-GKSMRBHU.js} +1 -1
- package/dist/cli/chunks/{chunk-CCMKSHAT.js → chunk-GQABPCQE.js} +2 -2
- package/dist/cli/chunks/{chunk-G77ERMUD.js → chunk-GV2QE5TO.js} +1 -1
- package/dist/cli/chunks/{chunk-756CGMEH.js → chunk-H5DER3JY.js} +1 -1
- package/dist/cli/chunks/{chunk-W3PPFHI5.js → chunk-HH4ED4F7.js} +52 -50
- package/dist/cli/chunks/{chunk-3Y2ROSCL.js → chunk-HL2ANKN3.js} +2 -2
- package/dist/cli/chunks/{chunk-T3PGQFDI.js → chunk-HTZSRMHW.js} +2 -2
- package/dist/cli/chunks/{chunk-3QZEGE67.js → chunk-IXL5ZHWJ.js} +1 -1
- package/dist/cli/chunks/{chunk-5ZGM3RMH.js → chunk-J3FP5UGL.js} +1 -1
- package/dist/cli/chunks/{chunk-FZ76G4QJ.js → chunk-JCQGJGGZ.js} +1 -1
- package/dist/cli/chunks/chunk-JCZCJE6X.js +86 -0
- package/dist/cli/chunks/{chunk-YZEXYO4W.js → chunk-JKJOB65O.js} +1 -1
- package/dist/cli/chunks/{chunk-A64JFBWI.js → chunk-JUDUBQHA.js} +2 -2
- package/dist/cli/chunks/{chunk-PIDQVU3L.js → chunk-JW74KRBC.js} +2 -2
- package/dist/cli/chunks/{chunk-EXGMJFAT.js → chunk-K3WZICFA.js} +1 -1
- package/dist/cli/chunks/{chunk-ASQYASNV.js → chunk-K3XBQC3R.js} +1 -1
- package/dist/cli/chunks/{chunk-E7CLYGS7.js → chunk-KCQNFBBR.js} +1 -1
- package/dist/cli/chunks/chunk-KJBPB7P5.js +3 -0
- package/dist/cli/chunks/chunk-KLTMOXIK.js +3 -0
- package/dist/cli/chunks/{chunk-5MDERQH3.js → chunk-L32JNNKL.js} +1 -1
- package/dist/cli/chunks/{chunk-32ZMWEP3.js → chunk-LB2LGEDP.js} +2 -2
- package/dist/cli/chunks/{chunk-42J34YG4.js → chunk-LHMQIZ6B.js} +2 -2
- package/dist/cli/chunks/{chunk-NURIILUB.js → chunk-LJMYRTJ7.js} +1 -1
- package/dist/cli/chunks/{chunk-M6AAGIG7.js → chunk-LNX74WHQ.js} +1 -1
- package/dist/cli/chunks/{chunk-P7A4NKTZ.js → chunk-LTQVUAPH.js} +2 -2
- package/dist/cli/chunks/{chunk-3YNLWPBF.js → chunk-LVABQNRF.js} +2 -2
- package/dist/cli/chunks/{chunk-2G7TVT6W.js → chunk-LYJHUNBK.js} +2 -2
- package/dist/cli/chunks/{chunk-DLD7RUZ4.js → chunk-M4CJCPCQ.js} +2 -2
- package/dist/cli/chunks/{chunk-Q3UDLV5Z.js → chunk-M4WMSCAE.js} +1 -1
- package/dist/cli/chunks/{chunk-UDQSYWVF.js → chunk-MIA447GY.js} +1 -1
- package/dist/cli/chunks/{chunk-RF7HWBHN.js → chunk-MPFPWJTH.js} +2 -2
- package/dist/cli/chunks/{chunk-BK577VL7.js → chunk-MV55NXTD.js} +2 -2
- package/dist/cli/chunks/{chunk-JQGMW45H.js → chunk-NQS3BWS6.js} +1 -1
- package/dist/cli/chunks/{chunk-BEGR4D6N.js → chunk-NWIIYHT6.js} +2 -2
- package/dist/cli/chunks/{chunk-SSU73QAX.js → chunk-O6EWL5DQ.js} +2 -2
- package/dist/cli/chunks/chunk-OBDONJQM.js +2 -0
- package/dist/cli/chunks/chunk-OLZH5LRT.js +141 -0
- package/dist/cli/chunks/{chunk-W3INMZZ6.js → chunk-OQG3UQQ7.js} +1 -1
- package/dist/cli/chunks/{chunk-72ASBE35.js → chunk-PFQCV6YS.js} +3 -3
- package/dist/cli/chunks/{chunk-7YTGHGK4.js → chunk-PS6UMZVK.js} +2 -2
- package/dist/cli/chunks/{chunk-OCAEXYFA.js → chunk-PXATBHWN.js} +2 -2
- package/dist/cli/chunks/{chunk-ARJW4I2O.js → chunk-PYPS65P7.js} +2 -2
- package/dist/cli/chunks/{chunk-SYV2V3PL.js → chunk-Q6I4SIUU.js} +4 -4
- package/dist/cli/chunks/{chunk-H4H2YSFH.js → chunk-QFGYH6HD.js} +1 -1
- package/dist/cli/chunks/{chunk-526QYFJU.js → chunk-QGBGSQ2E.js} +2 -2
- package/dist/cli/chunks/{chunk-YBQH2VOP.js → chunk-QRKTBSZT.js} +2 -2
- package/dist/cli/chunks/{chunk-C7JM7CD3.js → chunk-R6LHJ7ME.js} +2 -2
- package/dist/cli/chunks/{chunk-TSQC2KKZ.js → chunk-RBKUU7WF.js} +2 -2
- package/dist/cli/chunks/{chunk-CE7B5LU7.js → chunk-RDMRY7CT.js} +1 -1
- package/dist/cli/chunks/chunk-RIRZHOS2.js +8 -0
- package/dist/cli/chunks/{chunk-CRWPZT74.js → chunk-SHRI7TKJ.js} +2 -2
- package/dist/cli/chunks/{chunk-KWYH3FI4.js → chunk-SJCKCSN3.js} +1 -1
- package/dist/cli/chunks/{chunk-DFUASIKA.js → chunk-SON6ZRH3.js} +2 -2
- package/dist/cli/chunks/{chunk-J2ZIFFM6.js → chunk-SZAZQZWI.js} +2 -2
- package/dist/cli/chunks/{chunk-HD7YIFOI.js → chunk-T4GE7MPI.js} +2 -2
- package/dist/cli/chunks/{chunk-3Y7TJFHU.js → chunk-T66PPF4D.js} +2 -2
- package/dist/cli/chunks/{chunk-3RZV5DGO.js → chunk-T67R2MUN.js} +2 -2
- package/dist/cli/chunks/{chunk-H4GG2NLO.js → chunk-TDQWTSBS.js} +2 -2
- package/dist/cli/chunks/{chunk-TWJTK4CC.js → chunk-TODNOP7C.js} +2 -2
- package/dist/cli/chunks/{chunk-NZ3GUMB2.js → chunk-TX2CHQD7.js} +2 -2
- package/dist/cli/chunks/{chunk-AL6FBH3E.js → chunk-TZIHDJZD.js} +2 -2
- package/dist/cli/chunks/{chunk-GII6UM3F.js → chunk-U62OUXBF.js} +1 -1
- package/dist/cli/chunks/{chunk-YQFLQE53.js → chunk-UAQZI6N4.js} +2 -2
- package/dist/cli/chunks/{chunk-R7SYRCRP.js → chunk-UE2J6MA5.js} +1 -1
- package/dist/cli/chunks/{chunk-VRHRBAEM.js → chunk-UGYM4U44.js} +1 -1
- package/dist/cli/chunks/{chunk-NT4DBXSX.js → chunk-UJABDXST.js} +2 -2
- package/dist/cli/chunks/{chunk-OFACHK5O.js → chunk-UORB2QDU.js} +9 -9
- package/dist/cli/chunks/{chunk-QDEJ4CI2.js → chunk-UQPA33UK.js} +2 -2
- package/dist/cli/chunks/{chunk-TCBBNUBP.js → chunk-UUBIQR6A.js} +3 -3
- package/dist/cli/chunks/{chunk-NZD4DPSU.js → chunk-UXIY4IAI.js} +2 -2
- package/dist/cli/chunks/{chunk-SG3NX7QE.js → chunk-VCXI4XC4.js} +2 -2
- package/dist/cli/chunks/{chunk-PSFSPGUD.js → chunk-VMAM46HQ.js} +2 -2
- package/dist/cli/chunks/{chunk-3AN5TNGD.js → chunk-VY4U6DPO.js} +3 -3
- package/dist/cli/chunks/{chunk-X7N2JF2X.js → chunk-W27AJ5B4.js} +2 -2
- package/dist/cli/chunks/{chunk-CT6SAVXQ.js → chunk-W5ZJG2OU.js} +2 -2
- package/dist/cli/chunks/{chunk-KV4T4MXK.js → chunk-W62OOK7A.js} +2 -2
- package/dist/cli/chunks/{chunk-5K26BEYB.js → chunk-WNTA4YKE.js} +2 -2
- package/dist/cli/chunks/{chunk-LZYQHVD4.js → chunk-WUOOX7UG.js} +2 -2
- package/dist/cli/chunks/{chunk-7NA7JXNB.js → chunk-WVXJ2QIG.js} +2 -2
- package/dist/cli/chunks/{chunk-KB56CPU4.js → chunk-X33CWRDF.js} +2 -2
- package/dist/cli/chunks/{chunk-7JUC2MVZ.js → chunk-XG4F4XH4.js} +2 -2
- package/dist/cli/chunks/{chunk-ZAKQLAHT.js → chunk-XH4JMX5O.js} +1 -1
- package/dist/cli/chunks/{chunk-X2Z7F4EU.js → chunk-XHHWABJV.js} +2 -2
- package/dist/cli/chunks/{chunk-7PLIEBY7.js → chunk-XHLYGXYE.js} +2 -2
- package/dist/cli/chunks/{chunk-UXZSUMEA.js → chunk-XIVVTYM2.js} +2 -2
- package/dist/cli/chunks/{chunk-MVVB7C2E.js → chunk-XM6ZVFM5.js} +156 -156
- package/dist/cli/chunks/{chunk-VTOBUZL6.js → chunk-XWIAZG3C.js} +2 -2
- package/dist/cli/chunks/{chunk-CV77DMDQ.js → chunk-Y2OX6KGN.js} +2 -2
- package/dist/cli/chunks/{chunk-VRVMIPTM.js → chunk-YUS6TWAL.js} +2 -2
- package/dist/cli/chunks/{chunk-VU5TBX2V.js → chunk-ZIPAB5J6.js} +2 -2
- package/dist/cli/chunks/{chunk-KUAKV3IW.js → chunk-ZSOMUTNL.js} +1 -1
- package/dist/cli/chunks/{chunk-UOC3O6RP.js → chunk-ZWBGYJ7K.js} +2 -2
- package/dist/cli/chunks/{chunk-5VMAV6T6.js → chunk-ZYJB6FML.js} +1 -1
- package/dist/cli/chunks/{ci-ENOASTYB.js → ci-UCUJOSBW.js} +2 -2
- package/dist/cli/chunks/{ci-config-B26OXHQM.js → ci-config-2XILD3XG.js} +2 -2
- package/dist/cli/chunks/{ci-output-JTCLLNOQ.js → ci-output-BL6KWOHW.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-23JMFNM5.js → circuit-breaker-5XLIOXE5.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-ON6L462G.js → claude-flow-setup-4IMP6ACS.js} +2 -2
- package/dist/cli/chunks/client-KKRNPX4F.js +2 -0
- package/dist/cli/chunks/{cline-installer-OWQ4D2FQ.js → cline-installer-RYLHCDK7.js} +2 -2
- package/dist/cli/chunks/{code-2ZRL7SEU.js → code-WY3GJXHX.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-JXSQVM67.js → code-index-extractor-Y4MZBZCW.js} +2 -2
- package/dist/cli/chunks/{codex-installer-7LXZYBSQ.js → codex-installer-SCJ3T3DX.js} +4 -4
- package/dist/cli/chunks/{completions-C2LR623C.js → completions-CN2DXQFU.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-TGQLHCYJ.js → complexity-analyzer-7MDPPIBH.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-RUGD24D2.js → continuedev-installer-GCEJRK34.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-ZLFVLEJP.js → copilot-installer-BHPDSELY.js} +2 -2
- package/dist/cli/chunks/core-handlers-47MPMED7.js +2 -0
- package/dist/cli/chunks/{cost-tracker-RT4QL745.js → cost-tracker-VO5MFWR6.js} +2 -2
- package/dist/cli/chunks/coverage-LYFQYNH6.js +51 -0
- package/dist/cli/chunks/cross-domain-router-U6MBFHEC.js +2 -0
- package/dist/cli/chunks/{cursor-installer-LJKLNFF6.js → cursor-installer-KP4HA7TV.js} +2 -2
- package/dist/cli/chunks/{daemon-BMDXCQT5.js → daemon-7RC7TS57.js} +3 -3
- package/dist/cli/chunks/{daemon-FBH3IRYN.js → daemon-AXLVPKVO.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-JGDED55I.js → dag-attention-scheduler-NKA44RSR.js} +2 -2
- package/dist/cli/chunks/{detect-SZIHIVCJ.js → detect-CMYAJWYF.js} +2 -2
- package/dist/cli/chunks/{dist-node-FV3KWXQ6.js → dist-node-EN3PYEGW.js} +2 -2
- package/dist/cli/chunks/{domain-handler-GI5JWQOV.js → domain-handler-EXSZCX7A.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-BUWY36TL.js → domain-plugins-HCQFSNL7.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-GCY7W5DA.js → domain-transfer-3LGSNTPO.js} +2 -2
- package/dist/cli/chunks/dream-76L6EEN7.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-GPRR3ZGD.js → embed-and-insert-pattern-B6MNHICW.js} +2 -2
- package/dist/cli/chunks/{eval-XPB3IGAP.js → eval-OQELIWJK.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-2E554UB3.js → experience-capture-middleware-SUFILYPW.js} +3 -3
- package/dist/cli/chunks/{fast-paths-ZSMWZPUC.js → fast-paths-UV4NDEWM.js} +2 -2
- package/dist/cli/chunks/{feature-flags-GIWVDVVC.js → feature-flags-CKTYX67J.js} +2 -2
- package/dist/cli/chunks/{feature-flags-N7EOGE5P.js → feature-flags-H7H33B6C.js} +2 -2
- package/dist/cli/chunks/file-discovery-VSFKZ3LJ.js +2 -0
- package/dist/cli/chunks/{fleet-HCHDOUCX.js → fleet-ZJBCAKRG.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-CZNCNXXZ.js → gnn-wrapper-RUE2QZRG.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-6YUIF2YQ.js → heartbeat-handler-XRV327M7.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-NIK3KKEH.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-WJG7LUJJ.js +2 -0
- package/dist/cli/chunks/hnsw-index-D6PRI5HC.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-J3M3IK24.js → hnsw-legacy-bridge-UJID6ZZ4.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-ULGTGDZW.js → hnswlib-node-WS43R4AX.js} +2 -2
- package/dist/cli/chunks/{hooks-C4BUGYUQ.js → hooks-YZNJKXAJ.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-RIUR3I7F.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-WINGVMPG.js → hypergraph-engine-XQJSIMTS.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-GADMWKAU.js → hypergraph-handler-ZD2NYXMR.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-C36YYTJ5.js +2 -0
- package/dist/cli/chunks/{init-guard-K2T4QWAO.js → init-guard-DSRUAVRT.js} +2 -2
- package/dist/cli/chunks/{init-handler-PCZTDZYI.js → init-handler-RJU5QMAP.js} +6 -6
- package/dist/cli/chunks/init-wizard-JCKNGIGT.js +2 -0
- package/dist/cli/chunks/kernel-F7ILJTYD.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-XENXNEIU.js → kilocode-installer-BCPOCVMC.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-3PG2TJ67.js → kiro-installer-GFCWCB2S.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-VTXDBHB2.js +2 -0
- package/dist/cli/chunks/learning-FZTD72CF.js +131 -0
- package/dist/cli/chunks/{llm-router-RKVDEWU2.js → llm-router-GJVKGRJL.js} +4 -4
- package/dist/cli/chunks/llm-router-service-TNOWQINA.js +2 -0
- package/dist/cli/chunks/{load-ITHC564X.js → load-YKTPOYBE.js} +2 -2
- package/dist/cli/chunks/load-test-FPVBK2EV.js +2 -0
- package/dist/cli/chunks/{mcp-TCL5UW3N.js → mcp-LT6R2IKS.js} +2 -2
- package/dist/cli/chunks/{memory-BKDAY2N2.js → memory-4HKKOLRY.js} +5 -5
- package/dist/cli/chunks/memory-backend-2QE7O67A.js +2 -0
- package/dist/cli/chunks/{memory-handlers-WN4FXFOA.js → memory-handlers-X4CMVBXB.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-VHAT7ZPF.js → multi-model-executor-2YPM2WTK.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-E3VM3EEY.js → opencode-installer-WBAJMH5K.js} +2 -2
- package/dist/cli/chunks/{orchestrator-BMQ6X762.js → orchestrator-5W5WVMVJ.js} +109 -25
- package/dist/cli/chunks/pattern-null-store-UI35ORHW.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-GOOR2BV5.js → pattern-usage-recorder-GXRMNPAZ.js} +2 -2
- package/dist/cli/chunks/{pipeline-5NSFQQIX.js → pipeline-2NA4DRDA.js} +2 -2
- package/dist/cli/chunks/{platform-SQM34J5G.js → platform-BGERNQ5V.js} +2 -2
- package/dist/cli/chunks/{plugin-UQJZRMZG.js → plugin-L4EPVENR.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-WMDJOL4S.js → prime-radiant-advanced-wasm-RTQRTPTM.js} +2 -2
- package/dist/cli/chunks/project-root-S7WDFTMU.js +2 -0
- package/dist/cli/chunks/protocol-executor-OPANXQVB.js +2 -0
- package/dist/cli/chunks/{protocol-handler-OBDCVY6X.js → protocol-handler-SYQXM6JK.js} +2 -2
- package/dist/cli/chunks/{prove-XDC7I4XT.js → prove-5O7GPJCU.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-3OTF4DYQ.js +2 -0
- package/dist/cli/chunks/{quality-L4GQ6WX4.js → quality-KIIDHGNF.js} +2 -2
- package/dist/cli/chunks/{quality-gate-MJG66LKN.js → quality-gate-H65VECD3.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-WTYH4TAN.js +2 -0
- package/dist/cli/chunks/{real-embeddings-HW4G2LWL.js → real-embeddings-DYIOLKQ3.js} +2 -2
- package/dist/cli/chunks/{ref-validation-FC7JOJ2C.js → ref-validation-CSBJOMZM.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-KWS4CEIC.js → roocode-installer-G7OVYXEN.js} +2 -2
- package/dist/cli/chunks/router-DBBW4NC2.js +2 -0
- package/dist/cli/chunks/routing-feedback-W35QHCL4.js +2 -0
- package/dist/cli/chunks/{routing-handler-QF4WVB2S.js → routing-handler-ZNZPPI5Y.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-2MTCOUK6.js → ruvector-commands-C6IG3OY3.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-X3NSL25Z.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-TZR7GDOK.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-BREJCXWN.js → rvf-migration-coordinator-4ATTHGHD.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-HD25ZYV5.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-KKC6HOJD.js → rvf-store-integrity-3G6LFLT3.js} +2 -2
- package/dist/cli/chunks/safe-db-ZS2QKANY.js +2 -0
- package/dist/cli/chunks/schedule-ZH6VNA32.js +2 -0
- package/dist/cli/chunks/scheduler-T6CD74B6.js +2 -0
- package/dist/cli/chunks/{security-OSAE7VAP.js → security-A3IMVLFM.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-COUOS665.js → shared-rvf-adapter-VHWQ6US5.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-YXMPZKQE.js → shared-rvf-dual-writer-JB3QS7IG.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-47WU5EKZ.js +2 -0
- package/dist/cli/chunks/{standalone-memory-E6JBMOIL.js → standalone-memory-DDNXCSBD.js} +2 -2
- package/dist/cli/chunks/{status-handler-AFTCIYIX.js → status-handler-2HK7XPEK.js} +2 -2
- package/dist/cli/chunks/{structural-health-2FROCEI4.js → structural-health-DSJVLEPV.js} +2 -2
- package/dist/cli/chunks/{sync-VAYTOWDC.js → sync-3MUV6S5E.js} +2 -2
- package/dist/cli/chunks/{sync-YIQYOFGW.js → sync-NTUR53PI.js} +2 -2
- package/dist/cli/chunks/{task-handler-KVQHDEX3.js → task-handler-74MZN2EO.js} +2 -2
- package/dist/cli/chunks/{task-handlers-MVVECQA6.js → task-handlers-VJR6EHRZ.js} +3 -3
- package/dist/cli/chunks/{test-5JSVTOMY.js → test-O6FK3FVF.js} +4 -4
- package/dist/cli/chunks/test-runner-process-2NPW3UDQ.js +2 -0
- package/dist/cli/chunks/{test-scheduling-HBOHVLI3.js → test-scheduling-Q6QEEOS6.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-5VEPTPFA.js → token-bootstrap-TTRCECLP.js} +2 -2
- package/dist/cli/chunks/{token-usage-TBJHDLY6.js → token-usage-YEEFWSSI.js} +2 -2
- package/dist/cli/chunks/{transformers-VAWYMHMZ.js → transformers-BZCHJJJT.js} +2 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-RZAND65G.js +2 -0
- package/dist/cli/chunks/{types-R5SDZU2E.js → types-4AOKZYOX.js} +2 -2
- package/dist/cli/chunks/unified-memory-FZ5K2C7W.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-VREWX56M.js +2 -0
- package/dist/cli/chunks/unified-persistence-YZGMKX6B.js +2 -0
- package/dist/cli/chunks/{upgrade-K5PIHXRB.js → upgrade-2MWW6BT2.js} +2 -2
- package/dist/cli/chunks/{validate-RPTS7RYJ.js → validate-PAEV3GT5.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-B2ZL556X.js → validate-swarm-ZIXACK5K.js} +2 -2
- package/dist/cli/chunks/visual-security-GXGSFBVA.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-K4DUJC32.js → web-tree-sitter-VLTXZFAB.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-OK2AJN35.js → windsurf-installer-VELMLOZF.js} +2 -2
- package/dist/cli/chunks/witness-chain-MRJKVCOW.js +2 -0
- package/dist/cli/chunks/witness-chain-WWHJKITG.js +2 -0
- package/dist/cli/chunks/{witness-chain-repair-L6Y5RFXR.js → witness-chain-repair-5SAXPETG.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-N4CW7FZX.js → witness-chain-verifier-MIDWD4JS.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-TDNPS3WD.js → witness-key-manager-OSVCWOB2.js} +2 -2
- package/dist/cli/chunks/{workflow-XRZA3YCY.js → workflow-MK7A7QCX.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-SG7DV72E.js +2 -0
- package/dist/cli/chunks/{wrappers-5JIFWKN6.js → wrappers-5QFMCKXL.js} +2 -2
- package/dist/cli/commands/coverage.js +6 -0
- package/dist/cli/commands/learning-prune.d.ts +14 -0
- package/dist/cli/commands/learning-prune.js +105 -0
- package/dist/cli/commands/learning.js +9 -0
- package/dist/cli/handlers/brain-handler.js +12 -1
- package/dist/cli/utils/coverage-verdict.js +14 -3
- package/dist/context/compaction/index.d.ts +7 -0
- package/dist/context/compaction/index.js +30 -6
- package/dist/coordination/handlers/coverage-evidence.d.ts +19 -0
- package/dist/coordination/handlers/coverage-evidence.js +31 -2
- package/dist/coordination/handlers/coverage-handlers.js +5 -1
- package/dist/coordination/handlers/coverage-target.js +8 -1
- package/dist/coordination/handlers/quality-handlers.js +9 -1
- package/dist/coordination/result-saver-adapters.js +1 -0
- package/dist/coordination/result-saver.js +9 -5
- package/dist/domains/chaos-resilience/services/chaos-engineer.d.ts +1 -0
- package/dist/domains/chaos-resilience/services/chaos-engineer.js +23 -45
- package/dist/domains/coverage-analysis/collected-metrics.d.ts +22 -6
- package/dist/domains/coverage-analysis/collected-metrics.js +37 -12
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +2 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +3 -6
- package/dist/domains/quality-assessment/coverage-report-event.d.ts +8 -0
- package/dist/domains/quality-assessment/coverage-report-event.js +22 -1
- package/dist/domains/quality-assessment/interfaces.d.ts +6 -0
- package/dist/domains/quality-assessment/services/quality-analyzer.d.ts +4 -0
- package/dist/domains/quality-assessment/services/quality-analyzer.js +63 -17
- package/dist/domains/test-execution/interfaces.d.ts +5 -0
- package/dist/domains/test-execution/services/test-executor.js +6 -0
- package/dist/init/init-wizard-hooks.d.ts +1 -1
- package/dist/init/init-wizard-hooks.js +7 -8
- package/dist/init/phases/07-hooks.js +90 -6
- package/dist/init/phases/08-mcp.js +9 -0
- package/dist/init/settings-merge.d.ts +13 -0
- package/dist/init/settings-merge.js +49 -2
- package/dist/integrations/agent-booster-wasm/agent_booster_wasm.js +849 -0
- package/dist/integrations/agent-booster-wasm/agent_booster_wasm_bg.wasm +0 -0
- package/dist/integrations/agent-booster-wasm/index.d.ts +8 -0
- package/dist/integrations/agent-booster-wasm/index.js +25 -2
- package/dist/integrations/agent-booster-wasm/package.json +16 -0
- package/dist/integrations/ruvector/brain-rvf-exporter.d.ts +25 -0
- package/dist/integrations/ruvector/brain-rvf-exporter.js +154 -61
- package/dist/learning/dream/dream-engine.d.ts +27 -3
- package/dist/learning/dream/dream-engine.js +97 -28
- package/dist/learning/dream/dream-lock-retry.d.ts +38 -0
- package/dist/learning/dream/dream-lock-retry.js +66 -0
- package/dist/learning/dream/speculative-dreamer.js +1 -1
- package/dist/learning/learning-retention.d.ts +103 -0
- package/dist/learning/learning-retention.js +213 -0
- package/dist/mcp/bundle.js +501 -496
- package/dist/mcp/handlers/domain-handler-configs.d.ts +9 -1
- package/dist/mcp/handlers/domain-handler-configs.js +24 -14
- package/dist/mcp/protocol-server.js +1 -1
- package/dist/mcp/tools/chaos-resilience/inject.d.ts +3 -4
- package/dist/mcp/tools/chaos-resilience/inject.js +11 -81
- package/dist/mcp/tools/learning-optimization/dream.d.ts +8 -0
- package/dist/mcp/tools/learning-optimization/dream.js +4 -0
- package/package.json +4 -2
- package/dist/cli/chunks/adapter-KCQDVYY2.js +0 -2
- package/dist/cli/chunks/agent-booster-wasm-6RRQWMNE.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-SAQOHSGN.js +0 -2
- package/dist/cli/chunks/base-WCACU3FN.js +0 -2
- package/dist/cli/chunks/brain-handler-GTQNHHZS.js +0 -94
- package/dist/cli/chunks/browser-workflow-G6IASEAP.js +0 -2
- package/dist/cli/chunks/chunk-C6JTLKG7.js +0 -141
- package/dist/cli/chunks/chunk-K65CGKLD.js +0 -8
- package/dist/cli/chunks/chunk-MB46UBGY.js +0 -3
- package/dist/cli/chunks/chunk-N4CYAKOX.js +0 -79
- package/dist/cli/chunks/chunk-PT4FMJPQ.js +0 -3
- package/dist/cli/chunks/chunk-S5AZCIZS.js +0 -2
- package/dist/cli/chunks/chunk-UT2VZ33P.js +0 -2
- package/dist/cli/chunks/client-TV3V2YZ5.js +0 -2
- package/dist/cli/chunks/core-handlers-PZT4OLWR.js +0 -2
- package/dist/cli/chunks/coverage-NV3C4IMM.js +0 -50
- package/dist/cli/chunks/cross-domain-router-QOFCZ7G4.js +0 -2
- package/dist/cli/chunks/dream-TRFBGDSQ.js +0 -2
- package/dist/cli/chunks/file-discovery-WCKGMSPZ.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-P44A2OX3.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-ZJQIQJKC.js +0 -2
- package/dist/cli/chunks/hnsw-index-HMG2GH3Z.js +0 -2
- package/dist/cli/chunks/hybrid-backend-B7M74PZG.js +0 -2
- package/dist/cli/chunks/impact-analyzer-PZYOVKQO.js +0 -2
- package/dist/cli/chunks/init-wizard-TZDJQK3U.js +0 -2
- package/dist/cli/chunks/kernel-Y6RRIOKW.js +0 -2
- package/dist/cli/chunks/knowledge-graph-BVD5Z66M.js +0 -2
- package/dist/cli/chunks/learning-6KDH7FK4.js +0 -122
- package/dist/cli/chunks/llm-router-service-KHCAMSUU.js +0 -2
- package/dist/cli/chunks/load-test-RUF7DZA5.js +0 -2
- package/dist/cli/chunks/memory-backend-7ZLFOVGG.js +0 -2
- package/dist/cli/chunks/pattern-null-store-RY6CVYHP.js +0 -2
- package/dist/cli/chunks/project-root-IO5KRNGL.js +0 -2
- package/dist/cli/chunks/protocol-executor-U2CUDWDE.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-DQSSX2IP.js +0 -2
- package/dist/cli/chunks/queen-coordinator-6FN4BZIX.js +0 -2
- package/dist/cli/chunks/router-YUO3I7RU.js +0 -2
- package/dist/cli/chunks/routing-feedback-36SLQGJE.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-FRYZH3WZ.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-XXNITL5I.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-D2WWKJIV.js +0 -2
- package/dist/cli/chunks/safe-db-4RRIGRXD.js +0 -2
- package/dist/cli/chunks/schedule-25RTO4DQ.js +0 -2
- package/dist/cli/chunks/scheduler-BPIOJZ5P.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-EDF47DDX.js +0 -2
- package/dist/cli/chunks/test-runner-process-LEPF2OSS.js +0 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-TSZTCMFV.js +0 -2
- package/dist/cli/chunks/unified-memory-TLGSSLMI.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-MSUR7ZOO.js +0 -2
- package/dist/cli/chunks/unified-persistence-VFFOTWK7.js +0 -2
- package/dist/cli/chunks/visual-security-6Q44XNLB.js +0 -2
- package/dist/cli/chunks/witness-chain-KDOMXDQX.js +0 -2
- package/dist/cli/chunks/witness-chain-N3OY2RMH.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-CVNNT2RJ.js +0 -2
|
@@ -9,7 +9,7 @@ import { getCodeMetricsAnalyzer } from '../../../shared/metrics/index.js';
|
|
|
9
9
|
import { toError } from '../../../shared/error-utils.js';
|
|
10
10
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
11
11
|
import { getClaudeModelForTier } from '../../../shared/llm/model-registry.js';
|
|
12
|
-
import {
|
|
12
|
+
import { measuredFileCoverage } from '../coverage-report-event.js';
|
|
13
13
|
import { fileCoverageLookupKeys } from '../../coverage-analysis/collected-metrics.js';
|
|
14
14
|
/** Metrics the static analyzer produces when the caller asks for all of them. */
|
|
15
15
|
const ANALYZER_METRICS = ['coverage', 'complexity', 'maintainability', 'duplication', 'testability'];
|
|
@@ -25,6 +25,22 @@ const PARSED_METRICS = new Set(['complexity', 'maintainability', 'testability'])
|
|
|
25
25
|
export const MIN_ANALYSED_SHARE = 0.95;
|
|
26
26
|
/** #1011: the sentinel for "not measured" in score and complexity fields. */
|
|
27
27
|
const UNMEASURED = -1;
|
|
28
|
+
/**
|
|
29
|
+
* #1219: covered lines over total lines across the files, or `null` when a
|
|
30
|
+
* record has no line counts (a mean of percentages would weight a 10-line
|
|
31
|
+
* file like a 1000-line one).
|
|
32
|
+
*/
|
|
33
|
+
function lineWeightedCoverage(records) {
|
|
34
|
+
let covered = 0;
|
|
35
|
+
let total = 0;
|
|
36
|
+
for (const record of records) {
|
|
37
|
+
if (!record.lines)
|
|
38
|
+
return null;
|
|
39
|
+
covered += record.lines.covered;
|
|
40
|
+
total += record.lines.total;
|
|
41
|
+
}
|
|
42
|
+
return total > 0 ? (covered / total) * 100 : null;
|
|
43
|
+
}
|
|
28
44
|
/** First reasons of a failure list, for a one-line explanation. */
|
|
29
45
|
function summariseFailures(failures) {
|
|
30
46
|
return failures.slice(0, 3).map((f) => f.reason).join('; ')
|
|
@@ -262,11 +278,16 @@ Focus on:
|
|
|
262
278
|
return err(new Error('No source files provided for analysis'));
|
|
263
279
|
}
|
|
264
280
|
// Analyze metrics for each file; failures become unmeasured (#1011)
|
|
265
|
-
const { fileMetrics, unmeasured, excluded, partial } = await this.collectFileMetrics(sourceFiles, includeMetrics, request.explicitFiles ?? []);
|
|
281
|
+
const { fileMetrics, scopeValues, unmeasured, excluded, partial } = await this.collectFileMetrics(sourceFiles, includeMetrics, request.explicitFiles ?? []);
|
|
266
282
|
// Calculate aggregated metrics
|
|
267
|
-
const metricDetails = this.aggregateMetrics(fileMetrics);
|
|
268
|
-
// Calculate overall quality score
|
|
269
|
-
|
|
283
|
+
const metricDetails = this.aggregateMetrics(fileMetrics, scopeValues);
|
|
284
|
+
// Calculate overall quality score. With a requested metric unmeasured
|
|
285
|
+
// there is no overall score (-1, as the gate's overallScore since
|
|
286
|
+
// #1223); the score over the measured metrics is kept as subsetScore.
|
|
287
|
+
const computed = this.calculateQualityScore(metricDetails);
|
|
288
|
+
const insufficient = unmeasured.length > 0;
|
|
289
|
+
const score = insufficient ? { ...computed, overall: UNMEASURED } : computed;
|
|
290
|
+
const subsetScore = insufficient && computed.overall >= 0 ? computed.overall : undefined;
|
|
270
291
|
// Generate trends if enabled
|
|
271
292
|
const trends = this.config.enableTrendAnalysis
|
|
272
293
|
? await this.generateTrends(metricDetails, compareBaseline)
|
|
@@ -290,6 +311,7 @@ Focus on:
|
|
|
290
311
|
unmeasured,
|
|
291
312
|
excluded,
|
|
292
313
|
partial,
|
|
314
|
+
...(subsetScore !== undefined ? { subsetScore } : {}),
|
|
293
315
|
};
|
|
294
316
|
// Store the report
|
|
295
317
|
await this.storeReport(report, sourceFiles);
|
|
@@ -395,6 +417,8 @@ Focus on:
|
|
|
395
417
|
const unreadable = [];
|
|
396
418
|
const readable = [];
|
|
397
419
|
const missingCoverage = [];
|
|
420
|
+
const coverageRecords = [];
|
|
421
|
+
const scopeValues = {};
|
|
398
422
|
const explicit = new Set(explicitFiles);
|
|
399
423
|
const needsAnalysis = requested.some((m) => PARSED_METRICS.has(m) || m === 'duplication');
|
|
400
424
|
for (const file of files) {
|
|
@@ -430,7 +454,8 @@ Focus on:
|
|
|
430
454
|
// Coverage requires external data (from test runners) — never fabricate a number
|
|
431
455
|
const storedCoverage = await this.getStoredCoverage(file);
|
|
432
456
|
if (storedCoverage !== null) {
|
|
433
|
-
metrics.coverage = storedCoverage;
|
|
457
|
+
metrics.coverage = storedCoverage.line;
|
|
458
|
+
coverageRecords.push(storedCoverage);
|
|
434
459
|
}
|
|
435
460
|
else {
|
|
436
461
|
missingCoverage.push(file);
|
|
@@ -442,11 +467,33 @@ Focus on:
|
|
|
442
467
|
if (missingCoverage.length > 0) {
|
|
443
468
|
for (const metrics of fileMetrics.values())
|
|
444
469
|
delete metrics.coverage;
|
|
470
|
+
// #1219: the project-wide summary is not a measurement of these files.
|
|
445
471
|
unmeasured.push({
|
|
446
472
|
metric: 'coverage',
|
|
447
|
-
reason: `no measured coverage recorded for ${missingCoverage.length} of ${total} file(s)
|
|
473
|
+
reason: `no measured coverage recorded for ${missingCoverage.length} of ${total} file(s) `
|
|
474
|
+
+ `(${missingCoverage.slice(0, 3).join(', ')}${missingCoverage.length > 3 ? ', …' : ''}); `
|
|
475
|
+
+ 'a project-wide coverage figure is not a measurement of these files',
|
|
476
|
+
files: missingCoverage,
|
|
448
477
|
});
|
|
449
478
|
}
|
|
479
|
+
else if (coverageRecords.length > 1) {
|
|
480
|
+
const weighted = lineWeightedCoverage(coverageRecords);
|
|
481
|
+
if (weighted === null) {
|
|
482
|
+
for (const metrics of fileMetrics.values())
|
|
483
|
+
delete metrics.coverage;
|
|
484
|
+
const legacy = coverageRecords.filter((r) => !r.lines).length;
|
|
485
|
+
// #1219: a plain mean of per-file percentages is not the scope's coverage.
|
|
486
|
+
unmeasured.push({
|
|
487
|
+
metric: 'coverage',
|
|
488
|
+
reason: `${legacy} of ${coverageRecords.length} per-file coverage record(s) carry no line counts `
|
|
489
|
+
+ '(written before 3.15.13), so the files cannot be weighted by size and a mean of their '
|
|
490
|
+
+ 'percentages is not the coverage of the scope; re-run coverage to record line counts',
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
scopeValues.coverage = weighted;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
450
497
|
/** Decide whether a metric with these failures is measured, partial or unmeasured. */
|
|
451
498
|
const judge = (metric, failures) => {
|
|
452
499
|
const analysed = total - failures.length;
|
|
@@ -502,8 +549,12 @@ Focus on:
|
|
|
502
549
|
unmeasured.push({ metric: 'duplication', reason: `duplication detection failed: ${toError(error).message}` });
|
|
503
550
|
}
|
|
504
551
|
}
|
|
505
|
-
return { fileMetrics, unmeasured, excluded, partial };
|
|
552
|
+
return { fileMetrics, scopeValues, unmeasured, excluded, partial };
|
|
506
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* The file's own measured coverage record, or `null`. #1219: never the
|
|
556
|
+
* project-wide `coverage:latest` summary — that is not this file's coverage.
|
|
557
|
+
*/
|
|
507
558
|
async getStoredCoverage(file) {
|
|
508
559
|
try {
|
|
509
560
|
// 1. Try per-file coverage stored by test executor
|
|
@@ -512,21 +563,16 @@ Focus on:
|
|
|
512
563
|
for (const key of fileCoverageLookupKeys(file)) {
|
|
513
564
|
const fileCoverage = measuredFileCoverage(await this.memory.get(key));
|
|
514
565
|
if (fileCoverage)
|
|
515
|
-
return fileCoverage
|
|
516
|
-
}
|
|
517
|
-
// 2. Fall back to project-wide summary from coverage-analyzer
|
|
518
|
-
const summary = measuredCoverageSummary(await this.memory.get('coverage:latest'));
|
|
519
|
-
if (summary) {
|
|
520
|
-
return summary.line;
|
|
566
|
+
return fileCoverage;
|
|
521
567
|
}
|
|
522
|
-
// No coverage data
|
|
568
|
+
// No coverage data for this file — return null (never fabricate)
|
|
523
569
|
return null;
|
|
524
570
|
}
|
|
525
571
|
catch {
|
|
526
572
|
return null;
|
|
527
573
|
}
|
|
528
574
|
}
|
|
529
|
-
aggregateMetrics(fileMetrics) {
|
|
575
|
+
aggregateMetrics(fileMetrics, scopeValues = {}) {
|
|
530
576
|
const aggregated = new Map();
|
|
531
577
|
// Collect all values per metric
|
|
532
578
|
for (const metrics of fileMetrics.values()) {
|
|
@@ -539,7 +585,7 @@ Focus on:
|
|
|
539
585
|
// Calculate averages and generate details
|
|
540
586
|
const details = [];
|
|
541
587
|
for (const [name, values] of aggregated.entries()) {
|
|
542
|
-
const average = values.reduce((a, b) => a + b, 0) / values.length;
|
|
588
|
+
const average = scopeValues[name] ?? values.reduce((a, b) => a + b, 0) / values.length;
|
|
543
589
|
const rating = this.getMetricRating(average, name);
|
|
544
590
|
const trend = this.estimateTrend(values);
|
|
545
591
|
details.push({
|
|
@@ -128,6 +128,11 @@ export interface IFileCoverageData {
|
|
|
128
128
|
/** `null` = no functions in the file (istanbul 0/0): not collected, not 100% (#1015). */
|
|
129
129
|
function: number | null;
|
|
130
130
|
statement: number | null;
|
|
131
|
+
/** #1219: the line counts behind `line`, when the report has them. */
|
|
132
|
+
lines?: {
|
|
133
|
+
covered: number;
|
|
134
|
+
total: number;
|
|
135
|
+
};
|
|
131
136
|
}
|
|
132
137
|
export interface IFailedTest {
|
|
133
138
|
testId: string;
|
|
@@ -1114,6 +1114,7 @@ Provide:
|
|
|
1114
1114
|
branch: ratio(branches),
|
|
1115
1115
|
function: ratio(fns),
|
|
1116
1116
|
statement: ratio(statements),
|
|
1117
|
+
lines: { covered: lines[0], total: lines[1] },
|
|
1117
1118
|
});
|
|
1118
1119
|
for (const [key, [covered, count]] of [['line', lines], ['branch', branches], ['function', fns], ['statement', statements]]) {
|
|
1119
1120
|
totals[key][0] += covered;
|
|
@@ -1171,12 +1172,15 @@ Provide:
|
|
|
1171
1172
|
const line = summaryPct(entry?.lines);
|
|
1172
1173
|
if (line !== null) {
|
|
1173
1174
|
// #1015: a metric with total 0 is not collected (null), not its 100 pct.
|
|
1175
|
+
const counts = entry.lines;
|
|
1174
1176
|
perFile.push({
|
|
1175
1177
|
path: normalizedPath,
|
|
1176
1178
|
line,
|
|
1177
1179
|
branch: summaryPct(entry.branches),
|
|
1178
1180
|
function: summaryPct(entry.functions),
|
|
1179
1181
|
statement: summaryPct(entry.statements),
|
|
1182
|
+
...(typeof counts?.covered === 'number' && typeof counts.total === 'number'
|
|
1183
|
+
? { lines: { covered: counts.covered, total: counts.total } } : {}),
|
|
1180
1184
|
});
|
|
1181
1185
|
}
|
|
1182
1186
|
}
|
|
@@ -1268,6 +1272,8 @@ Provide:
|
|
|
1268
1272
|
function: fc.function ?? null,
|
|
1269
1273
|
statement: fc.statement ?? null,
|
|
1270
1274
|
measured: true,
|
|
1275
|
+
// #1219: the counts behind `line`, so several files can be line-weighted.
|
|
1276
|
+
...(fc.lines ? { lines: fc.lines } : {}),
|
|
1271
1277
|
runStatus,
|
|
1272
1278
|
}, { persist: true });
|
|
1273
1279
|
}
|
|
@@ -21,7 +21,7 @@ export declare function configureHooks(projectRoot: string, config: AQEInitConfi
|
|
|
21
21
|
/**
|
|
22
22
|
* Configure MCP server.
|
|
23
23
|
* Creates .mcp.json (root level) with AQE v3 MCP server configuration.
|
|
24
|
-
*
|
|
24
|
+
* Runs the installed `aqe-mcp` binary, matching the phase-based installer.
|
|
25
25
|
*
|
|
26
26
|
* #922: skipped when the agentic-qe-fleet Claude Code plugin is enabled (it
|
|
27
27
|
* already provides the AQE MCP server) unless `force` is set (--with-mcp).
|
|
@@ -13,6 +13,7 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync } from
|
|
|
13
13
|
import { join, dirname } from 'path';
|
|
14
14
|
import { safeJsonParse } from '../shared/safe-json.js';
|
|
15
15
|
import { aqePluginMcpSkipMessage, detectAqeFleetPlugin } from './claude-plugin-detection.js';
|
|
16
|
+
import { removeUntrustedAqeMcpServers, scrubUntrustedAqeMcpFile } from './settings-merge.js';
|
|
16
17
|
import { mergeHooksSmart, generateAqeEnvVars, generateV3SettingsSections, applyV3Sections, mergeAqeEnv, backupSettingsFile, } from './settings-merge.js';
|
|
17
18
|
// ============================================================================
|
|
18
19
|
// Hook Configuration
|
|
@@ -240,7 +241,7 @@ async function installCrossPhaseMemoryHooks(projectRoot) {
|
|
|
240
241
|
// If no asset found, create minimal config
|
|
241
242
|
const minimalConfig = `# Cross-Phase Memory Hooks Configuration
|
|
242
243
|
# Generated by aqe init
|
|
243
|
-
# See: https://github.com/
|
|
244
|
+
# See: https://github.com/proffesor-for-testing/agentic-qe/blob/main/docs/architecture/CROSS-PHASE-MEMORY-IMPLEMENTATION.md
|
|
244
245
|
|
|
245
246
|
version: "1.0"
|
|
246
247
|
enabled: true
|
|
@@ -272,7 +273,7 @@ routing:
|
|
|
272
273
|
/**
|
|
273
274
|
* Configure MCP server.
|
|
274
275
|
* Creates .mcp.json (root level) with AQE v3 MCP server configuration.
|
|
275
|
-
*
|
|
276
|
+
* Runs the installed `aqe-mcp` binary, matching the phase-based installer.
|
|
276
277
|
*
|
|
277
278
|
* #922: skipped when the agentic-qe-fleet Claude Code plugin is enabled (it
|
|
278
279
|
* already provides the AQE MCP server) unless `force` is set (--with-mcp).
|
|
@@ -280,6 +281,7 @@ routing:
|
|
|
280
281
|
export async function configureMCP(projectRoot, options = {}) {
|
|
281
282
|
if (!options.force && detectAqeFleetPlugin(projectRoot).enabled) {
|
|
282
283
|
console.log(aqePluginMcpSkipMessage(projectRoot));
|
|
284
|
+
scrubUntrustedAqeMcpFile(join(projectRoot, '.mcp.json'));
|
|
283
285
|
return false;
|
|
284
286
|
}
|
|
285
287
|
const mcpPath = join(projectRoot, '.mcp.json');
|
|
@@ -297,13 +299,10 @@ export async function configureMCP(projectRoot, options = {}) {
|
|
|
297
299
|
mcpConfig.mcpServers = {};
|
|
298
300
|
}
|
|
299
301
|
const servers = mcpConfig.mcpServers;
|
|
302
|
+
removeUntrustedAqeMcpServers(servers);
|
|
300
303
|
servers['agentic-qe'] = {
|
|
301
|
-
command: '
|
|
302
|
-
args: [
|
|
303
|
-
'@anthropics/agentic-qe',
|
|
304
|
-
'mcp',
|
|
305
|
-
'start'
|
|
306
|
-
],
|
|
304
|
+
command: 'aqe-mcp',
|
|
305
|
+
args: [],
|
|
307
306
|
env: {
|
|
308
307
|
AQE_LEARNING_ENABLED: 'true',
|
|
309
308
|
AQE_VERBOSE: 'false',
|
|
@@ -394,6 +394,7 @@ console.log(\`\\x1b[1m\\x1b[35m▊ Agentic QE v3\\x1b[0m\${branchStr}\${patStr}\
|
|
|
394
394
|
* node brain-checkpoint.cjs verify # Verify aqe.rvf exists (session-start)
|
|
395
395
|
*/
|
|
396
396
|
const { execFileSync } = require('child_process');
|
|
397
|
+
const crypto = require('crypto');
|
|
397
398
|
const fs = require('fs');
|
|
398
399
|
const path = require('path');
|
|
399
400
|
|
|
@@ -402,6 +403,11 @@ const AQE_DIR = path.join(PROJECT_ROOT, '.agentic-qe');
|
|
|
402
403
|
const RVF_PATH = path.join(AQE_DIR, 'aqe.rvf');
|
|
403
404
|
const DB_PATH = path.join(AQE_DIR, 'memory.db');
|
|
404
405
|
const MAX_AGE_HOURS = 24;
|
|
406
|
+
// #1238: after a too-large export, skip the Stop-hook export for a while
|
|
407
|
+
// unless a newer aqe.rvf shows that an export has succeeded since.
|
|
408
|
+
const SKIP_PATH = path.join(AQE_DIR, 'brain-checkpoint.skip.json');
|
|
409
|
+
const RETRY_ENV = Number.parseFloat(process.env.AQE_BRAIN_CHECKPOINT_RETRY_HOURS || '');
|
|
410
|
+
const TOO_LARGE_RETRY_HOURS = Number.isFinite(RETRY_ENV) && RETRY_ENV >= 0 ? RETRY_ENV : 6;
|
|
405
411
|
// Windows (#872): never execFile aqe.cmd (EINVAL without a shell); reuse the
|
|
406
412
|
// hook shim's resolver, which runs the AQE bundle via node instead.
|
|
407
413
|
function aqeInvocation() {
|
|
@@ -422,32 +428,110 @@ function aqeInvocation() {
|
|
|
422
428
|
|
|
423
429
|
function log(msg) { process.stderr.write('[brain-checkpoint] ' + msg + '\\n'); }
|
|
424
430
|
|
|
431
|
+
function activeSkip() {
|
|
432
|
+
let st; try { st = fs.lstatSync(SKIP_PATH); } catch { return null; }
|
|
433
|
+
let skip = null;
|
|
434
|
+
if (st.isFile()) { try { skip = JSON.parse(fs.readFileSync(SKIP_PATH, 'utf8')); } catch { /* unreadable */ } }
|
|
435
|
+
const at = skip ? Date.parse(skip.at) : NaN;
|
|
436
|
+
let rvfMtime = 0; try { rvfMtime = fs.lstatSync(RVF_PATH).mtimeMs; } catch { /* absent */ }
|
|
437
|
+
if (!Number.isFinite(at) || Date.now() >= at + TOO_LARGE_RETRY_HOURS * 3600000 || rvfMtime > at) {
|
|
438
|
+
try { fs.unlinkSync(SKIP_PATH); } catch { /* best-effort */ }
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
return skip;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function writeSkip(reason) {
|
|
445
|
+
const at = new Date();
|
|
446
|
+
const skip = { reason, at: at.toISOString(), retryAfter: new Date(at.getTime() + TOO_LARGE_RETRY_HOURS * 3600000).toISOString() };
|
|
447
|
+
// 'wx' after unlink: never write through a planted symlink (#970).
|
|
448
|
+
try { try { fs.unlinkSync(SKIP_PATH); } catch { /* absent */ } fs.writeFileSync(SKIP_PATH, JSON.stringify(skip) + '\\n', { flag: 'wx' }); } catch { /* best-effort */ }
|
|
449
|
+
return skip;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Export to a temp store next to aqe.rvf; rename it over aqe.rvf only on
|
|
453
|
+
// success, so a failed, too-large or killed export keeps the last checkpoint.
|
|
454
|
+
const RVF_SIDECARS = ['.idmap.json', '.manifest.json'];
|
|
455
|
+
const TMP_PREFIX = path.basename(RVF_PATH) + '.tmp-';
|
|
456
|
+
function removeEntry(p) { try { fs.unlinkSync(p); } catch (e) { if (!e || e.code !== 'ENOENT') throw e; } }
|
|
457
|
+
function isPidAlive(pid) { try { process.kill(pid, 0); return true; } catch (e) { return !!e && e.code === 'EPERM'; } }
|
|
458
|
+
function removeByPrefix(prefix, keep) {
|
|
459
|
+
let entries = []; try { entries = fs.readdirSync(AQE_DIR); } catch { return; }
|
|
460
|
+
for (const entry of entries) {
|
|
461
|
+
if (!entry.startsWith(prefix) || (keep && keep(entry))) continue;
|
|
462
|
+
try { removeEntry(path.join(AQE_DIR, entry)); } catch { /* best-effort */ }
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function sweepStaleTmp() {
|
|
466
|
+
removeByPrefix(TMP_PREFIX, (entry) => {
|
|
467
|
+
const pid = Number.parseInt(entry.slice(TMP_PREFIX.length).split('-')[0], 10);
|
|
468
|
+
return !Number.isInteger(pid) || pid <= 0 || isPidAlive(pid);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
function lexists(p) { try { fs.lstatSync(p); return true; } catch { return false; } }
|
|
472
|
+
// rename() replaces a planted symlink without writing through it (#970). The
|
|
473
|
+
// store goes first: if that fails nothing changed. If a sidecar rename fails
|
|
474
|
+
// afterwards, the stale sidecar is removed, so the new store is never read
|
|
475
|
+
// with the previous export's idmap.
|
|
476
|
+
function promote(tmp) {
|
|
477
|
+
fs.renameSync(tmp, RVF_PATH);
|
|
478
|
+
for (const suffix of RVF_SIDECARS) {
|
|
479
|
+
try {
|
|
480
|
+
if (lexists(tmp + suffix)) fs.renameSync(tmp + suffix, RVF_PATH + suffix);
|
|
481
|
+
else removeEntry(RVF_PATH + suffix);
|
|
482
|
+
} catch { try { removeEntry(RVF_PATH + suffix); } catch { /* best-effort */ } }
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
425
486
|
function exportBrain() {
|
|
426
487
|
if (!fs.existsSync(DB_PATH)) { log('No memory.db, skipping'); return { exported: false }; }
|
|
427
488
|
const aqe = aqeInvocation();
|
|
428
489
|
if (!aqe.cmd) { log('Export skipped: ' + aqe.reason); return { exported: false, reason: aqe.reason }; }
|
|
429
|
-
// Never write through a committed symlink: .agentic-qe must be a real dir
|
|
430
|
-
// unlink (not existsSync) drops a planted aqe.rvf link, even a dangling one.
|
|
490
|
+
// Never write through a committed symlink: .agentic-qe must be a real dir.
|
|
431
491
|
let st; try { st = fs.lstatSync(AQE_DIR); } catch { /* missing */ }
|
|
432
492
|
if (!st || !st.isDirectory()) { log('Export skipped: .agentic-qe is a symlink'); return { exported: false }; }
|
|
433
|
-
|
|
493
|
+
const skip = activeSkip();
|
|
494
|
+
if (skip) {
|
|
495
|
+
log('Export skipped until ' + skip.retryAfter + ': ' + skip.reason);
|
|
496
|
+
return { exported: false, skipped: true, reason: skip.reason, retryAfter: skip.retryAfter };
|
|
497
|
+
}
|
|
498
|
+
sweepStaleTmp();
|
|
499
|
+
const tmp = path.join(AQE_DIR, TMP_PREFIX + process.pid + '-' + crypto.randomBytes(4).toString('hex'));
|
|
434
500
|
try {
|
|
501
|
+
for (const suffix of ['', ...RVF_SIDECARS]) removeEntry(tmp + suffix);
|
|
435
502
|
const result = execFileSync(
|
|
436
|
-
aqe.cmd, [...aqe.args, 'brain', 'export', '-o',
|
|
437
|
-
{ timeout: 60000, encoding: 'utf-8', windowsHide: true }
|
|
503
|
+
aqe.cmd, [...aqe.args, 'brain', 'export', '-o', tmp, '--format', 'rvf'],
|
|
504
|
+
{ timeout: 60000, encoding: 'utf-8', windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] }
|
|
438
505
|
);
|
|
506
|
+
// A zero exit without a store is a failure, not an empty checkpoint.
|
|
507
|
+
if (!lexists(tmp)) throw new Error('brain export exited 0 but wrote no store');
|
|
508
|
+
promote(tmp);
|
|
439
509
|
const m = result.match(/Patterns:\\s+(\\d+)/);
|
|
440
510
|
const p = m ? m[1] : '0';
|
|
441
511
|
log('Exported ' + p + ' patterns to aqe.rvf');
|
|
442
512
|
return { exported: true, patterns: parseInt(p) };
|
|
443
513
|
} catch (e) {
|
|
444
|
-
|
|
514
|
+
const tooLarge = (String(e.stderr || '') + String(e.stdout || '')).match(/RVF_KERNEL_TOO_LARGE:[^\\n]*/);
|
|
515
|
+
if (tooLarge) {
|
|
516
|
+
const skip = writeSkip(tooLarge[0].trim());
|
|
517
|
+
log('Export failed: ' + skip.reason);
|
|
518
|
+
log('Skipping the checkpoint export until ' + skip.retryAfter + ' (AQE_BRAIN_CHECKPOINT_RETRY_HOURS sets the wait).');
|
|
519
|
+
return { exported: false, tooLarge: true, reason: skip.reason, retryAfter: skip.retryAfter };
|
|
520
|
+
}
|
|
521
|
+
log('Export failed: ' + e.message + ' (previous aqe.rvf kept)');
|
|
445
522
|
return { exported: false, reason: e.message };
|
|
523
|
+
} finally {
|
|
524
|
+
removeByPrefix(path.basename(tmp));
|
|
446
525
|
}
|
|
447
526
|
}
|
|
448
527
|
|
|
449
528
|
function verifyBrain() {
|
|
450
529
|
if (!fs.existsSync(RVF_PATH)) {
|
|
530
|
+
const skip = activeSkip();
|
|
531
|
+
if (skip) {
|
|
532
|
+
log('No aqe.rvf found; checkpoint export paused until ' + skip.retryAfter + ': ' + skip.reason);
|
|
533
|
+
return { valid: false, reason: 'missing', skippedUntil: skip.retryAfter };
|
|
534
|
+
}
|
|
451
535
|
log('No aqe.rvf found');
|
|
452
536
|
return { valid: false, reason: 'missing' };
|
|
453
537
|
}
|
|
@@ -16,6 +16,7 @@ import { writeFileIfChanged } from '../idempotent-write.js';
|
|
|
16
16
|
import { join } from 'path';
|
|
17
17
|
import { safeJsonParse } from '../../shared/safe-json.js';
|
|
18
18
|
import { aqePluginMcpSkipMessage, detectAqeFleetPlugin, } from '../claude-plugin-detection.js';
|
|
19
|
+
import { removeUntrustedAqeMcpServers, scrubUntrustedAqeMcpFile } from '../settings-merge.js';
|
|
19
20
|
import { BasePhase, } from './phase-interface.js';
|
|
20
21
|
/**
|
|
21
22
|
* MCP phase - configures MCP server
|
|
@@ -56,6 +57,7 @@ export class MCPPhase extends BasePhase {
|
|
|
56
57
|
const plugin = this.detectPlugin(projectRoot);
|
|
57
58
|
if (plugin.enabled) {
|
|
58
59
|
context.services.log(aqePluginMcpSkipMessage(projectRoot));
|
|
60
|
+
reportUntrustedMcpRemoval(context, scrubUntrustedAqeMcpFile(join(projectRoot, '.mcp.json')));
|
|
59
61
|
return {
|
|
60
62
|
configured: false,
|
|
61
63
|
mcpPath: '',
|
|
@@ -107,6 +109,7 @@ export class MCPPhase extends BasePhase {
|
|
|
107
109
|
rootMcpConfig.mcpServers = {};
|
|
108
110
|
}
|
|
109
111
|
const rootServers = rootMcpConfig.mcpServers;
|
|
112
|
+
reportUntrustedMcpRemoval(context, removeUntrustedAqeMcpServers(rootServers));
|
|
110
113
|
rootServers['agentic-qe'] = aqeServerConfig;
|
|
111
114
|
// #778: no rewrite (mtime churn) when the merged config is unchanged.
|
|
112
115
|
writeFileIfChanged(rootMcpPath, JSON.stringify(rootMcpConfig, null, 2));
|
|
@@ -128,5 +131,11 @@ export class MCPPhase extends BasePhase {
|
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
}
|
|
134
|
+
/** GHSA-chjc-8q37-52fg: say which stale server entries init removed. */
|
|
135
|
+
function reportUntrustedMcpRemoval(context, removed) {
|
|
136
|
+
if (removed.length > 0) {
|
|
137
|
+
context.services.log(` MCP: removed server entry launching @anthropics/agentic-qe: ${removed.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
131
140
|
// Instance exported from index.ts
|
|
132
141
|
//# sourceMappingURL=08-mcp.js.map
|
|
@@ -59,12 +59,25 @@ export declare function generateAqeEnvVars(config: AQEInitConfig, options?: {
|
|
|
59
59
|
* "Agentic QE v3" banner). Anything else is treated as user-owned and preserved.
|
|
60
60
|
*/
|
|
61
61
|
export declare function isAqeStatusLine(statusLine: unknown): boolean;
|
|
62
|
+
/** Drop allow-list entries that pre-approve the untrusted package. */
|
|
63
|
+
export declare function removeUntrustedAqePermissions(allow: string[]): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Remove MCP servers that launch the untrusted package.
|
|
66
|
+
* Mutates `servers` and returns the removed server names.
|
|
67
|
+
*/
|
|
68
|
+
export declare function removeUntrustedAqeMcpServers(servers: Record<string, unknown>): string[];
|
|
69
|
+
/**
|
|
70
|
+
* Remove untrusted-package servers from an existing `.mcp.json`, leaving the
|
|
71
|
+
* rest of the file alone. Used where init does not write its own entry.
|
|
72
|
+
*/
|
|
73
|
+
export declare function scrubUntrustedAqeMcpFile(mcpPath: string): string[];
|
|
62
74
|
/**
|
|
63
75
|
* Apply the generated v3 settings sections onto an existing settings object
|
|
64
76
|
* WITHOUT clobbering configuration the user already set:
|
|
65
77
|
*
|
|
66
78
|
* - `_aqePermissions`: union-merge into `permissions.allow`, preserving the
|
|
67
79
|
* user's existing allow/deny entries (#362).
|
|
80
|
+
* Entries naming the untrusted package are dropped (GHSA-chjc-8q37-52fg).
|
|
68
81
|
* - `statusLine`: generic Claude Code setting — only written when absent or when
|
|
69
82
|
* the existing one is AQE's own (so a user's custom status line is preserved).
|
|
70
83
|
* - `includeCoAuthoredBy`: generic Claude Code setting — only written when the
|
|
@@ -186,12 +186,60 @@ function deepMergeOwned(target, source) {
|
|
|
186
186
|
function isPlainObject(value) {
|
|
187
187
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
188
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* A package name earlier AQE versions wrote into `permissions.allow` and
|
|
191
|
+
* `.mcp.json` (GHSA-chjc-8q37-52fg). AQE does not publish or control it, so
|
|
192
|
+
* init removes any entry naming it instead of leaving a standing grant.
|
|
193
|
+
*/
|
|
194
|
+
const UNTRUSTED_AQE_PACKAGE = /@anthropics\/agentic-qe\b/i;
|
|
195
|
+
/** Drop allow-list entries that pre-approve the untrusted package. */
|
|
196
|
+
export function removeUntrustedAqePermissions(allow) {
|
|
197
|
+
return allow.filter((entry) => typeof entry !== 'string' || !UNTRUSTED_AQE_PACKAGE.test(entry));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Remove MCP servers that launch the untrusted package.
|
|
201
|
+
* Mutates `servers` and returns the removed server names.
|
|
202
|
+
*/
|
|
203
|
+
export function removeUntrustedAqeMcpServers(servers) {
|
|
204
|
+
const removed = [];
|
|
205
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
206
|
+
const { command, args } = (isPlainObject(server) ? server : {});
|
|
207
|
+
const parts = [command, ...(Array.isArray(args) ? args : [])];
|
|
208
|
+
if (parts.some((part) => typeof part === 'string' && UNTRUSTED_AQE_PACKAGE.test(part))) {
|
|
209
|
+
delete servers[name];
|
|
210
|
+
removed.push(name);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return removed;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Remove untrusted-package servers from an existing `.mcp.json`, leaving the
|
|
217
|
+
* rest of the file alone. Used where init does not write its own entry.
|
|
218
|
+
*/
|
|
219
|
+
export function scrubUntrustedAqeMcpFile(mcpPath) {
|
|
220
|
+
if (!existsSync(mcpPath))
|
|
221
|
+
return [];
|
|
222
|
+
let config;
|
|
223
|
+
try {
|
|
224
|
+
config = JSON.parse(readFileSync(mcpPath, 'utf-8'));
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
if (!isPlainObject(config) || !isPlainObject(config.mcpServers))
|
|
230
|
+
return [];
|
|
231
|
+
const removed = removeUntrustedAqeMcpServers(config.mcpServers);
|
|
232
|
+
if (removed.length > 0)
|
|
233
|
+
writeFileSync(mcpPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
234
|
+
return removed;
|
|
235
|
+
}
|
|
189
236
|
/**
|
|
190
237
|
* Apply the generated v3 settings sections onto an existing settings object
|
|
191
238
|
* WITHOUT clobbering configuration the user already set:
|
|
192
239
|
*
|
|
193
240
|
* - `_aqePermissions`: union-merge into `permissions.allow`, preserving the
|
|
194
241
|
* user's existing allow/deny entries (#362).
|
|
242
|
+
* Entries naming the untrusted package are dropped (GHSA-chjc-8q37-52fg).
|
|
195
243
|
* - `statusLine`: generic Claude Code setting — only written when absent or when
|
|
196
244
|
* the existing one is AQE's own (so a user's custom status line is preserved).
|
|
197
245
|
* - `includeCoAuthoredBy`: generic Claude Code setting — only written when the
|
|
@@ -205,7 +253,7 @@ export function applyV3Sections(settings, sections, options = {}) {
|
|
|
205
253
|
for (const [key, value] of Object.entries(sections)) {
|
|
206
254
|
if (key === '_aqePermissions') {
|
|
207
255
|
const existingPerms = settings.permissions || {};
|
|
208
|
-
const existingAllow = existingPerms.allow || [];
|
|
256
|
+
const existingAllow = removeUntrustedAqePermissions(existingPerms.allow || []);
|
|
209
257
|
const merged = [...new Set([...existingAllow, ...value])];
|
|
210
258
|
settings.permissions = { ...existingPerms, allow: merged };
|
|
211
259
|
}
|
|
@@ -261,7 +309,6 @@ export function generateV3SettingsSections(config, projectRoot, options = {}) {
|
|
|
261
309
|
// permissions are union-merged in 07-hooks.ts — not set here to avoid overwriting user entries (#362)
|
|
262
310
|
_aqePermissions: [
|
|
263
311
|
'Bash(npx agentic-qe:*)',
|
|
264
|
-
'Bash(npx @anthropics/agentic-qe:*)',
|
|
265
312
|
'mcp__agentic-qe__*',
|
|
266
313
|
],
|
|
267
314
|
includeCoAuthoredBy: true,
|