agentic-qe 3.15.6 → 3.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +141 -0
- package/README.md +2 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/bundle.js +8 -6
- package/dist/cli/chunks/adapter-PEOUNYXJ.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-SY7UCLBL.js → agent-booster-wasm-OS5G7KMQ.js} +2 -2
- package/dist/cli/chunks/{agent-handler-KAMYBU3S.js → agent-handler-PI4I7PME.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-2CAW3KUM.js → agent-memory-branch-J7TXHX4U.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-DHKZI5RX.js +2 -0
- package/dist/cli/chunks/{arena-QCCVIOAH.js → arena-FXESDCFR.js} +4 -4
- package/dist/cli/chunks/{arena-4OFLJ3R2.js → arena-OWUGXKNT.js} +2 -2
- package/dist/cli/chunks/{audit-RBDQJQJB.js → audit-EPAWLYIZ.js} +3 -3
- package/dist/cli/chunks/base-QZWK3D5P.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-5JRACCDQ.js → better-sqlite3-IYVR5EQY.js} +2 -2
- package/dist/cli/chunks/{brain-handler-W4QIIRT4.js → brain-handler-3W2E6TC6.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-IBNGI572.js → branch-enumerator-HU7VACJ4.js} +2 -2
- package/dist/cli/chunks/{browser-GMSCVAOI.js → browser-72XOR6E2.js} +2 -2
- package/dist/cli/chunks/browser-workflow-ITPX72RX.js +2 -0
- package/dist/cli/chunks/{chunk-CR66HNAE.js → chunk-2423JAA5.js} +1 -1
- package/dist/cli/chunks/{chunk-LAY7NCQK.js → chunk-24CENUT4.js} +3 -3
- package/dist/cli/chunks/{chunk-PEMSXSP2.js → chunk-2AYBYXOA.js} +2 -2
- package/dist/cli/chunks/{chunk-TUDENMAE.js → chunk-2E3XWKEU.js} +2 -2
- package/dist/cli/chunks/{chunk-KIDOBLUO.js → chunk-2RJYA6WK.js} +2 -2
- package/dist/cli/chunks/{chunk-2IWPJUVV.js → chunk-2YVJ5OUL.js} +5 -5
- package/dist/cli/chunks/{chunk-34MDMFET.js → chunk-34JLY3U6.js} +2 -2
- package/dist/cli/chunks/{chunk-SV5BUYHH.js → chunk-3JD2USUH.js} +2 -2
- package/dist/cli/chunks/{chunk-EF5UHDCG.js → chunk-3RM46XFP.js} +1 -1
- package/dist/cli/chunks/{chunk-7XTANLTN.js → chunk-44DPYNPE.js} +1 -1
- package/dist/cli/chunks/{chunk-ONPPBLRB.js → chunk-4DIZ5BT6.js} +2 -2
- package/dist/cli/chunks/{chunk-22OZIJAD.js → chunk-4G2VNW4C.js} +2 -2
- package/dist/cli/chunks/{chunk-LJCEDTUM.js → chunk-56ZKQYZY.js} +3 -3
- package/dist/cli/chunks/{chunk-HOEWMEF2.js → chunk-5KCBX225.js} +2 -2
- package/dist/cli/chunks/{chunk-V3OLS2NG.js → chunk-5KS7HA37.js} +2 -2
- package/dist/cli/chunks/{chunk-MQCTLTGE.js → chunk-5PBRBS7D.js} +2 -2
- package/dist/cli/chunks/{chunk-TVLOED6O.js → chunk-5Q22XPTH.js} +2 -2
- package/dist/cli/chunks/{chunk-B7RHBKHL.js → chunk-634D2ENF.js} +2 -2
- package/dist/cli/chunks/{chunk-7TVIX4WL.js → chunk-6AYRAOCA.js} +2 -2
- package/dist/cli/chunks/{chunk-4KOVHQXK.js → chunk-6BO3WCK7.js} +2 -2
- package/dist/cli/chunks/{chunk-5HAPS6VD.js → chunk-6FEQ73BF.js} +2 -2
- package/dist/cli/chunks/{chunk-FQ5N666N.js → chunk-6JT73S5B.js} +1 -1
- package/dist/cli/chunks/{chunk-6MXAJBEA.js → chunk-6OS7HREG.js} +1 -1
- package/dist/cli/chunks/{chunk-6R3FBFCJ.js → chunk-6PKCQXEW.js} +2 -2
- package/dist/cli/chunks/{chunk-DQNUPEY5.js → chunk-7EX4DEQR.js} +2 -2
- package/dist/cli/chunks/{chunk-KCB6P463.js → chunk-7UCVYYWL.js} +2 -2
- package/dist/cli/chunks/{chunk-RLB7K7QP.js → chunk-AAA4SHEG.js} +1 -1
- package/dist/cli/chunks/{chunk-ITIJ23K2.js → chunk-AXO7OOOA.js} +2 -2
- package/dist/cli/chunks/{chunk-6RDVY26I.js → chunk-B7M323VL.js} +2 -2
- package/dist/cli/chunks/{chunk-EJ4KZFZN.js → chunk-BB7OLQKO.js} +1 -1
- package/dist/cli/chunks/{chunk-5NC7QEJ6.js → chunk-BTIBXGVQ.js} +4 -4
- package/dist/cli/chunks/{chunk-RD5BYLN7.js → chunk-BTYKGVJ5.js} +1 -1
- package/dist/cli/chunks/{chunk-YXU35GGD.js → chunk-C2CUPJGR.js} +1 -1
- package/dist/cli/chunks/{chunk-XFPQIWEH.js → chunk-C2MDBBFF.js} +3 -3
- package/dist/cli/chunks/{chunk-QLKUCMZC.js → chunk-CG5DZCOZ.js} +1 -1
- package/dist/cli/chunks/{chunk-YLNYPQDR.js → chunk-CIFWOMNX.js} +1 -1
- package/dist/cli/chunks/{chunk-ORBODZSO.js → chunk-CWPRU7ZI.js} +2 -2
- package/dist/cli/chunks/{chunk-WKDWRRDT.js → chunk-CXTJ47QS.js} +2 -2
- package/dist/cli/chunks/{chunk-SOSJWM3E.js → chunk-DCJW2DPL.js} +4 -4
- package/dist/cli/chunks/{chunk-GVRFSXY6.js → chunk-DGK6GQMO.js} +2 -2
- package/dist/cli/chunks/{chunk-X33F7NXH.js → chunk-DVPGBDBP.js} +3 -3
- package/dist/cli/chunks/chunk-EB2PP6X2.js +2 -0
- package/dist/cli/chunks/{chunk-HZFK2Z2Z.js → chunk-ECSLJJOQ.js} +1 -1
- package/dist/cli/chunks/{chunk-JCE76MPP.js → chunk-ED32XJ5R.js} +2 -2
- package/dist/cli/chunks/{chunk-ULCHPPW2.js → chunk-EDU72RTW.js} +1 -1
- package/dist/cli/chunks/{chunk-ZOUEQ6DL.js → chunk-EL75G2A3.js} +1 -1
- package/dist/cli/chunks/{chunk-GNYOHZVV.js → chunk-EV2BYY6T.js} +1 -1
- package/dist/cli/chunks/{chunk-RUTO67PT.js → chunk-F62EKVVC.js} +2 -2
- package/dist/cli/chunks/{chunk-IVJIHZSM.js → chunk-FTTFJ7SJ.js} +1 -1
- package/dist/cli/chunks/{chunk-NYS2GUNO.js → chunk-FVBFASOD.js} +2 -2
- package/dist/cli/chunks/{chunk-5DH5QI7G.js → chunk-G762PEFO.js} +3 -3
- package/dist/cli/chunks/{chunk-JPJEAK4G.js → chunk-G7YTZTGU.js} +1 -1
- package/dist/cli/chunks/{chunk-5VUIXDY2.js → chunk-GY2SAIXP.js} +2 -2
- package/dist/cli/chunks/{chunk-7XUB7U6Z.js → chunk-H4WHDFB5.js} +2 -2
- package/dist/cli/chunks/{chunk-72MQCZSM.js → chunk-HLZATDD2.js} +2 -2
- package/dist/cli/chunks/{chunk-AX26QJ6T.js → chunk-HPG7354V.js} +2 -2
- package/dist/cli/chunks/{chunk-7SAMMQVS.js → chunk-HSDOOFV7.js} +1 -1
- package/dist/cli/chunks/{chunk-K55EAWZ5.js → chunk-HTWIGQL4.js} +2 -2
- package/dist/cli/chunks/{chunk-BXATKI5S.js → chunk-HXBAQKMH.js} +2 -2
- package/dist/cli/chunks/{chunk-46HBVDMU.js → chunk-HZFT3P5B.js} +1 -1
- package/dist/cli/chunks/{chunk-RFDFET3O.js → chunk-I7H4IP7T.js} +2 -2
- package/dist/cli/chunks/{chunk-AJT3XDRD.js → chunk-IARSGAG7.js} +2 -2
- package/dist/cli/chunks/{chunk-TL5GV3PR.js → chunk-IC2WSSD5.js} +3 -3
- package/dist/cli/chunks/{chunk-TLUIO37P.js → chunk-ICPALF4Q.js} +2 -2
- package/dist/cli/chunks/{chunk-ZSBD4FUX.js → chunk-IWQQIXHO.js} +2 -2
- package/dist/cli/chunks/{chunk-AUOSHM63.js → chunk-IYQ7XNE5.js} +2 -2
- package/dist/cli/chunks/{chunk-RHIQ6QO5.js → chunk-J26GADQE.js} +281 -281
- package/dist/cli/chunks/{chunk-AUN4FG7V.js → chunk-J43DV3ME.js} +1 -1
- package/dist/cli/chunks/{chunk-ALCIUWFC.js → chunk-JFPXCQNP.js} +1 -1
- package/dist/cli/chunks/{chunk-R363XXGH.js → chunk-JK6B3ULP.js} +2 -2
- package/dist/cli/chunks/{chunk-7VTKR44N.js → chunk-JPHDMHFG.js} +2 -2
- package/dist/cli/chunks/{chunk-FOJRPEIP.js → chunk-JVYPXW6Y.js} +2 -2
- package/dist/cli/chunks/{chunk-ZUTFHGEO.js → chunk-JY4AIEZ7.js} +1 -1
- package/dist/cli/chunks/{chunk-47Q7JL3V.js → chunk-JY4WLN3K.js} +2 -2
- package/dist/cli/chunks/{chunk-IEPWO4XP.js → chunk-JYXOFN3E.js} +2 -2
- package/dist/cli/chunks/{chunk-2CIDFR2H.js → chunk-K7W55B7Q.js} +2 -2
- package/dist/cli/chunks/{chunk-D5N2O5EH.js → chunk-KPOPBUUJ.js} +2 -2
- package/dist/cli/chunks/{chunk-OQ4S6B7P.js → chunk-LDXQRNTT.js} +1 -1
- package/dist/cli/chunks/{chunk-6T6AHVLF.js → chunk-LDZWIV2O.js} +1 -1
- package/dist/cli/chunks/{chunk-A7ANPS4E.js → chunk-LGBN7TKC.js} +2 -2
- package/dist/cli/chunks/{chunk-X2DR27AY.js → chunk-LMEU64TR.js} +2 -2
- package/dist/cli/chunks/{chunk-GI5HWS4H.js → chunk-LP4AS2E4.js} +1 -1
- package/dist/cli/chunks/{chunk-VVF337SV.js → chunk-LQOVA4YX.js} +2 -2
- package/dist/cli/chunks/{chunk-KYVIOC3C.js → chunk-LVEX4GID.js} +2 -2
- package/dist/cli/chunks/{chunk-BO7UFNYV.js → chunk-M63QB466.js} +2 -2
- package/dist/cli/chunks/{chunk-UHHMAKPE.js → chunk-MDC4G323.js} +1 -1
- package/dist/cli/chunks/{chunk-4CLDYT36.js → chunk-MHZPC4HJ.js} +2 -2
- package/dist/cli/chunks/{chunk-24ZSGYC6.js → chunk-MJJC6HUK.js} +1 -1
- package/dist/cli/chunks/{chunk-ZL5LJT7D.js → chunk-MKFQNCXI.js} +2 -2
- package/dist/cli/chunks/{chunk-XZ46CI35.js → chunk-MMXG3LL6.js} +2 -2
- package/dist/cli/chunks/{chunk-OPDZBRIL.js → chunk-MNCF643K.js} +2 -2
- package/dist/cli/chunks/{chunk-CEXNW5TR.js → chunk-MNZFEIE5.js} +1 -1
- package/dist/cli/chunks/{chunk-L4D3TPFP.js → chunk-MQ6OF6DU.js} +1 -1
- package/dist/cli/chunks/{chunk-UB6DQGWM.js → chunk-MRHM4COP.js} +2 -2
- package/dist/cli/chunks/{chunk-CLAMMGY3.js → chunk-N4PMPSJJ.js} +2 -2
- package/dist/cli/chunks/{chunk-XQ53PZEF.js → chunk-NZQPP533.js} +3 -3
- package/dist/cli/chunks/{chunk-FU7LNUD7.js → chunk-OA4GR3EZ.js} +2 -2
- package/dist/cli/chunks/{chunk-ORFL3YXB.js → chunk-OJEZNLB6.js} +2 -2
- package/dist/cli/chunks/{chunk-5LST62QR.js → chunk-ONVALAZN.js} +2 -2
- package/dist/cli/chunks/{chunk-DA7DGDTI.js → chunk-PEKDSJBC.js} +2 -2
- package/dist/cli/chunks/{chunk-3DJNKNBR.js → chunk-PG64YV6C.js} +57 -57
- package/dist/cli/chunks/{chunk-2ZTWPMTK.js → chunk-PQV7E7XH.js} +2 -2
- package/dist/cli/chunks/chunk-PTK66HEY.js +2 -0
- package/dist/cli/chunks/{chunk-CZBIREL5.js → chunk-PUECC4WI.js} +2 -2
- package/dist/cli/chunks/{chunk-JYKQVYX2.js → chunk-PXZKPUW6.js} +2 -2
- package/dist/cli/chunks/{chunk-I7WAW7TM.js → chunk-PYHYOKYT.js} +2 -2
- package/dist/cli/chunks/{chunk-LCCTJ2PC.js → chunk-PZG3542B.js} +2 -2
- package/dist/cli/chunks/{chunk-F7A2UBZO.js → chunk-Q2T5FXEA.js} +2 -2
- package/dist/cli/chunks/{chunk-PS6WFCA4.js → chunk-QJE6ZW2X.js} +2 -2
- package/dist/cli/chunks/{chunk-LZWJ5BMP.js → chunk-QNQSM2OG.js} +2 -2
- package/dist/cli/chunks/{chunk-QLYO3H7E.js → chunk-QQT6QENQ.js} +2 -2
- package/dist/cli/chunks/{chunk-VCONCVSY.js → chunk-QVG4ZDXX.js} +2 -2
- package/dist/cli/chunks/{chunk-NMY4KTWA.js → chunk-QWLTHFZW.js} +2 -2
- package/dist/cli/chunks/{chunk-NBUXM5X6.js → chunk-RCYLCA7E.js} +2 -2
- package/dist/cli/chunks/{chunk-P7DXVL2S.js → chunk-REEIFA6A.js} +2 -2
- package/dist/cli/chunks/{chunk-5MT7DMD7.js → chunk-RNYX4CPI.js} +2 -2
- package/dist/cli/chunks/{chunk-HAN4MS5T.js → chunk-RORZ5O5Z.js} +2 -2
- package/dist/cli/chunks/{chunk-ZCP4P6O2.js → chunk-RRPYWBFX.js} +2 -2
- package/dist/cli/chunks/{chunk-3NJ7O3OH.js → chunk-RXAFLK34.js} +2 -2
- package/dist/cli/chunks/{chunk-VAYZ5QIE.js → chunk-SQHLC6I5.js} +1 -1
- package/dist/cli/chunks/{chunk-Q2RBOC7V.js → chunk-SSP2B2WR.js} +2 -2
- package/dist/cli/chunks/{chunk-CCL436IU.js → chunk-SX2YSHE7.js} +14 -6
- package/dist/cli/chunks/{chunk-ZTB32K5N.js → chunk-T3ZDVU6F.js} +3 -3
- package/dist/cli/chunks/{chunk-624QRKQX.js → chunk-T6W5APYP.js} +1 -1
- package/dist/cli/chunks/{chunk-BAYGQRNP.js → chunk-TU4LIIOP.js} +2 -2
- package/dist/cli/chunks/{chunk-L2TDHJR3.js → chunk-UBYCR3O4.js} +2 -2
- package/dist/cli/chunks/{chunk-JAPBSSFY.js → chunk-UCLN6AME.js} +1 -1
- package/dist/cli/chunks/{chunk-66NW3ZB4.js → chunk-UIYKR2SA.js} +2 -2
- package/dist/cli/chunks/{chunk-BIXRTOH3.js → chunk-UUHIEM2M.js} +3 -3
- package/dist/cli/chunks/{chunk-ELI4GDQO.js → chunk-UY3REQOK.js} +2 -2
- package/dist/cli/chunks/{chunk-BUTGIVKW.js → chunk-V2SAEMZY.js} +1 -1
- package/dist/cli/chunks/{chunk-6WOZUSSN.js → chunk-V5NGBQAQ.js} +2 -2
- package/dist/cli/chunks/{chunk-7TJZDRDU.js → chunk-VCA6YYII.js} +1 -1
- package/dist/cli/chunks/chunk-VJRZFWR5.js +2 -0
- package/dist/cli/chunks/{chunk-5GIJU2ZY.js → chunk-VKPKYMCT.js} +2 -2
- package/dist/cli/chunks/{chunk-XPB5BVU6.js → chunk-VNW5Q2CX.js} +2 -2
- package/dist/cli/chunks/{chunk-7QVPMH25.js → chunk-VUFRTGML.js} +2 -2
- package/dist/cli/chunks/{chunk-MP3FSUNB.js → chunk-W4X2VTIY.js} +2 -2
- package/dist/cli/chunks/{chunk-GWM4M5NF.js → chunk-WTLIEBDH.js} +1 -1
- package/dist/cli/chunks/{chunk-QS5KZYUZ.js → chunk-WUV5RZUI.js} +2 -2
- package/dist/cli/chunks/{chunk-HEGGV2PT.js → chunk-WXI2STKQ.js} +2 -2
- package/dist/cli/chunks/{chunk-GFB6BZWU.js → chunk-XEWXYGJI.js} +2 -2
- package/dist/cli/chunks/{chunk-NHRF3V4B.js → chunk-XNSQZ3O7.js} +2 -2
- package/dist/cli/chunks/{chunk-4POOJYXA.js → chunk-XTJMY3KS.js} +1 -1
- package/dist/cli/chunks/{chunk-LMAEMVPA.js → chunk-XXAVQACL.js} +1 -1
- package/dist/cli/chunks/{chunk-RV6HSMKJ.js → chunk-Y4SAWE45.js} +1 -1
- package/dist/cli/chunks/{chunk-DLSFT6PO.js → chunk-Y6A46M3B.js} +2 -2
- package/dist/cli/chunks/{chunk-5UPIL62W.js → chunk-YDZJWDR6.js} +3 -3
- package/dist/cli/chunks/{chunk-F3KS3TAB.js → chunk-YFOBQSOW.js} +2 -2
- package/dist/cli/chunks/{chunk-XBEI2JBA.js → chunk-YK3NOC2R.js} +2 -2
- package/dist/cli/chunks/{chunk-MQTA6KIO.js → chunk-YUC7RJGR.js} +1 -1
- package/dist/cli/chunks/{chunk-A74J23QB.js → chunk-Z3VJLWRR.js} +2 -2
- package/dist/cli/chunks/{chunk-YNG7E26C.js → chunk-ZLVQSEZK.js} +2 -2
- package/dist/cli/chunks/{chunk-6HWARQWV.js → chunk-ZRLNACPY.js} +2 -2
- package/dist/cli/chunks/{chunk-XBFQJZWX.js → chunk-ZTMZFF25.js} +2 -2
- package/dist/cli/chunks/chunk-ZUMDDMDE.js +3 -0
- package/dist/cli/chunks/{ci-GEJCXMBK.js → ci-5HEXJZ2C.js} +2 -2
- package/dist/cli/chunks/{ci-config-2ZVV4OXL.js → ci-config-WU4NPDAM.js} +2 -2
- package/dist/cli/chunks/{ci-output-E45OGVPR.js → ci-output-BJQVXX5E.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-X73ITYZC.js → circuit-breaker-3BMGTQCB.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-W4PPH46C.js → claude-flow-setup-GVDGJWMU.js} +2 -2
- package/dist/cli/chunks/client-S7GNYTZ5.js +2 -0
- package/dist/cli/chunks/{cline-installer-NUEPMWDE.js → cline-installer-V4MRGWVA.js} +2 -2
- package/dist/cli/chunks/{code-6WQHBS7G.js → code-A3TGQPEO.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-BXQIFIFT.js → code-index-extractor-YJQSYWD3.js} +2 -2
- package/dist/cli/chunks/{codex-installer-Z337R2KH.js → codex-installer-7N7UQPAH.js} +2 -2
- package/dist/cli/chunks/{completions-F5DMYFHV.js → completions-PPGVYLZS.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-W2SYPZDI.js → complexity-analyzer-XZTFLYV5.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-ZCHUIFTN.js → continuedev-installer-Z5I57RAH.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-M5JNODXF.js → copilot-installer-F5YZ6BHB.js} +2 -2
- package/dist/cli/chunks/core-handlers-CUEPOQIO.js +2 -0
- package/dist/cli/chunks/{cost-tracker-LSYTHBHV.js → cost-tracker-GO33ZQAP.js} +2 -2
- package/dist/cli/chunks/{coverage-PGMRS5SS.js → coverage-GSHKLY74.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-CXN5QFEV.js +2 -0
- package/dist/cli/chunks/{cursor-installer-XPUA73UW.js → cursor-installer-JJ7IVJZB.js} +2 -2
- package/dist/cli/chunks/daemon-3DQCKRYO.js +10 -0
- package/dist/cli/chunks/{daemon-ITKDIYMW.js → daemon-IRL7QRNE.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-T55AXLD6.js → dag-attention-scheduler-ORXSUHPA.js} +2 -2
- package/dist/cli/chunks/{detect-DR7J6K4O.js → detect-RHU62KRI.js} +2 -2
- package/dist/cli/chunks/{dist-node-LAJJBOUT.js → dist-node-3VKV4Z6C.js} +2 -2
- package/dist/cli/chunks/{domain-handler-OMSHCRMK.js → domain-handler-SFIML4FK.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-EQXSKC5K.js → domain-plugins-CJ4FA3OC.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-FKRAGVSW.js → domain-transfer-BCRKPCAA.js} +2 -2
- package/dist/cli/chunks/dream-5AUNJW24.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-JZFPCNL3.js → embed-and-insert-pattern-VL3HFLPV.js} +2 -2
- package/dist/cli/chunks/{eval-JSNNASBW.js → eval-GGKRI4P5.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-UPD3IZBK.js → experience-capture-middleware-F72TIRQY.js} +3 -3
- package/dist/cli/chunks/{fast-paths-YNMIBS2E.js → fast-paths-7KOOF3MA.js} +2 -2
- package/dist/cli/chunks/{feature-flags-SRLXDKBI.js → feature-flags-FNHBTHBH.js} +2 -2
- package/dist/cli/chunks/{feature-flags-VIR7O4L7.js → feature-flags-IOZEWWFU.js} +2 -2
- package/dist/cli/chunks/file-discovery-AYWF357I.js +2 -0
- package/dist/cli/chunks/{fleet-K2ED46EL.js → fleet-QX5KXTRC.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-QCU4ZRYW.js → gnn-wrapper-OH2DOQP7.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-YYQI4WZM.js → heartbeat-handler-W67NXTNE.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-7ZIDVXIP.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-P77OC7FM.js +2 -0
- package/dist/cli/chunks/hnsw-index-3LBOTQAW.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-C5TJSWTZ.js → hnsw-legacy-bridge-6MLLOGOE.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-SE3MJJYS.js → hnswlib-node-4UDISJ3G.js} +2 -2
- package/dist/cli/chunks/{hooks-C572SRDH.js → hooks-NOQJWQ4P.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-LOM54PDD.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-35A6G3M5.js → hypergraph-engine-2OD3APVP.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-U2756CWI.js → hypergraph-handler-5AZGMBUM.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-QSDJVBPS.js +2 -0
- package/dist/cli/chunks/init-guard-SMGJ45PW.js +2 -0
- package/dist/cli/chunks/init-handler-5T4MP2NM.js +88 -0
- package/dist/cli/chunks/init-wizard-MK2325JJ.js +2 -0
- package/dist/cli/chunks/kernel-2NJQQ2KT.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-32PX5YH7.js → kilocode-installer-RLZYLVQJ.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-C4ROMMUS.js → kiro-installer-LFZOC7VD.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-SDISHO62.js +2 -0
- package/dist/cli/chunks/{learning-GEPVZGJQ.js → learning-XRPGLUWR.js} +20 -20
- package/dist/cli/chunks/{llm-router-XRKTTJTX.js → llm-router-OMK5HYPH.js} +4 -4
- package/dist/cli/chunks/llm-router-service-YTCMRBAN.js +2 -0
- package/dist/cli/chunks/{load-XVH6HW7E.js → load-XADC7KCU.js} +2 -2
- package/dist/cli/chunks/load-test-RPKHLBCC.js +2 -0
- package/dist/cli/chunks/{mcp-IULSTM4Z.js → mcp-PIBKSSVU.js} +2 -2
- package/dist/cli/chunks/{memory-6K7IAU4T.js → memory-AP7EZERS.js} +5 -5
- package/dist/cli/chunks/memory-backend-BZXFO4JZ.js +2 -0
- package/dist/cli/chunks/{memory-handlers-CG6DRLAW.js → memory-handlers-MOFDNB6E.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-VZDUYPLX.js → multi-model-executor-7JJ2FZ33.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-QUTXKNH4.js → opencode-installer-ZZZ6EBYJ.js} +2 -2
- package/dist/cli/chunks/{orchestrator-PCKKUWOP.js → orchestrator-2H2YKSGJ.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-4PRPIOR6.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-PX5HQVRL.js → pattern-usage-recorder-7MJJWC2Z.js} +2 -2
- package/dist/cli/chunks/{pipeline-O562GTOG.js → pipeline-LIE5BWQY.js} +2 -2
- package/dist/cli/chunks/{platform-PM7Q2AZS.js → platform-SMYUNLGX.js} +2 -2
- package/dist/cli/chunks/{plugin-OTYTFGPY.js → plugin-LJDIXQNT.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-6CFXTHC2.js → prime-radiant-advanced-wasm-RIDNE5D2.js} +2 -2
- package/dist/cli/chunks/project-root-NBIQF63D.js +2 -0
- package/dist/cli/chunks/protocol-executor-BRPGIYWQ.js +2 -0
- package/dist/cli/chunks/{protocol-handler-PPGNSAOS.js → protocol-handler-YVM66DLI.js} +2 -2
- package/dist/cli/chunks/{prove-WQ3BKRZG.js → prove-ZBDT52GD.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-GDZACWKW.js +2 -0
- package/dist/cli/chunks/{quality-C5WUU3AA.js → quality-DUKXGDDO.js} +2 -2
- package/dist/cli/chunks/{quality-gate-WSSRKD5U.js → quality-gate-SM3RXF4V.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-LDKLBPD5.js +2 -0
- package/dist/cli/chunks/{real-embeddings-CFQE7IRQ.js → real-embeddings-4QLQZDB5.js} +2 -2
- package/dist/cli/chunks/{ref-validation-DHKHXVZT.js → ref-validation-M3EO32YQ.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-3PPODABV.js → roocode-installer-S6Q5OLV5.js} +2 -2
- package/dist/cli/chunks/router-H5YSIRH2.js +2 -0
- package/dist/cli/chunks/routing-feedback-5R36TJDH.js +2 -0
- package/dist/cli/chunks/{routing-handler-JNXTGT6T.js → routing-handler-55FMUACP.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-6YLROPVP.js → ruvector-commands-QATKAAPK.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-TT2DBQQQ.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-BCLFJKSK.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-4DWB4WRK.js → rvf-migration-coordinator-RFXFU6JD.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-UXI66OQJ.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-YKR2ZNBF.js → rvf-store-integrity-PKDVXQAW.js} +2 -2
- package/dist/cli/chunks/safe-db-MSTD2GDH.js +2 -0
- package/dist/cli/chunks/schedule-KST6KIFD.js +2 -0
- package/dist/cli/chunks/scheduler-FTQS6YK3.js +2 -0
- package/dist/cli/chunks/security-CMRB6WA3.js +18 -0
- package/dist/cli/chunks/{shared-rvf-adapter-LNRLFP5I.js → shared-rvf-adapter-YHLLNFHF.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-GWU6YQNS.js → shared-rvf-dual-writer-4BGDVPQ7.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-ZX5QFDMR.js +2 -0
- package/dist/cli/chunks/{standalone-memory-46KKBSSV.js → standalone-memory-LUHKQAGM.js} +2 -2
- package/dist/cli/chunks/{status-handler-35T5FTDQ.js → status-handler-S6S5PNR7.js} +2 -2
- package/dist/cli/chunks/{structural-health-P7QPQWLO.js → structural-health-PQ7NZAJ4.js} +2 -2
- package/dist/cli/chunks/{sync-W6Z4R4PL.js → sync-Q6KRQXU6.js} +2 -2
- package/dist/cli/chunks/{sync-Y43EWBSY.js → sync-S744AEJC.js} +2 -2
- package/dist/cli/chunks/{task-handler-5CX3ZYT7.js → task-handler-GAMGEHUW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-DQZGOJNE.js → task-handlers-6CRDEELN.js} +3 -3
- package/dist/cli/chunks/{test-TPP53VVV.js → test-FNH67DBK.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-WBV4UMQH.js → test-scheduling-NZA5SHK6.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-GIIDXHLC.js → token-bootstrap-CXKG55JD.js} +2 -2
- package/dist/cli/chunks/{token-usage-AKK37RB7.js → token-usage-M7WWEDJX.js} +2 -2
- package/dist/cli/chunks/{transformers-7MASPELS.js → transformers-2IFMCK6A.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-YZKD6UGB.js → tree-sitter-wasm-parser-NMNA6RJC.js} +2 -2
- package/dist/cli/chunks/{types-AZ3BTXDP.js → types-N7FWTOLD.js} +2 -2
- package/dist/cli/chunks/unified-memory-2Z2F446J.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-A4EWYPJQ.js +2 -0
- package/dist/cli/chunks/unified-persistence-Z6N6JZFA.js +2 -0
- package/dist/cli/chunks/{upgrade-L7OTDKEK.js → upgrade-KDB5RGL7.js} +2 -2
- package/dist/cli/chunks/{validate-O3QVFIGP.js → validate-KMUV5FUA.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-2UGBGLTX.js → validate-swarm-ANZWRCJU.js} +2 -2
- package/dist/cli/chunks/visual-security-GXYZV7KR.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-J75IYPRO.js → web-tree-sitter-SXXC4NMS.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-FQ5DBFCG.js → windsurf-installer-2LWSKMBU.js} +2 -2
- package/dist/cli/chunks/witness-chain-52PEIEGK.js +2 -0
- package/dist/cli/chunks/{witness-chain-I7TN4MXZ.js → witness-chain-JJMSJFZP.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-D3NE3NQK.js → witness-chain-repair-OX7VFW6T.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-RU2WOP5M.js → witness-chain-verifier-QLSMXHAZ.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-IHQB2FR5.js → witness-key-manager-3DS4L7LE.js} +2 -2
- package/dist/cli/chunks/{workflow-6BWTNVV6.js → workflow-ARWAMHD3.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-DORMQMG7.js +2 -0
- package/dist/cli/chunks/{wrappers-URVP25VU.js → wrappers-J6KGTUSJ.js} +2 -2
- package/dist/cli/commands/learning.js +3 -2
- package/dist/cli/commands/security.d.ts +16 -0
- package/dist/cli/commands/security.js +76 -9
- package/dist/cli/handlers/init-guard.d.ts +21 -1
- package/dist/cli/handlers/init-guard.js +51 -8
- package/dist/cli/handlers/init-handler.js +57 -56
- package/dist/cli/index.js +11 -0
- package/dist/cli/utils/ci-output.d.ts +5 -0
- package/dist/cli/utils/ci-output.js +8 -0
- package/dist/coordination/handlers/security-handlers.js +22 -6
- package/dist/coordination/protocols/defect-investigation.js +7 -1
- package/dist/coordination/protocols/security-audit.js +11 -0
- package/dist/coordination/result-saver.d.ts +9 -0
- package/dist/coordination/result-saver.js +34 -4
- package/dist/domains/coverage-analysis/collected-metrics.d.ts +2 -0
- package/dist/domains/coverage-analysis/collected-metrics.js +6 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +9 -6
- package/dist/domains/quality-assessment/interfaces.d.ts +4 -0
- package/dist/domains/quality-assessment/quality-evidence.d.ts +1 -1
- package/dist/domains/quality-assessment/services/quality-analyzer.js +7 -5
- package/dist/domains/quality-assessment/services/quality-gate.js +12 -3
- package/dist/domains/security-compliance/dependency-advisory-engine.d.ts +52 -0
- package/dist/domains/security-compliance/dependency-advisory-engine.js +113 -0
- package/dist/domains/security-compliance/interfaces.d.ts +30 -0
- package/dist/domains/security-compliance/plugin.d.ts +7 -1
- package/dist/domains/security-compliance/plugin.js +19 -0
- package/dist/domains/security-compliance/services/scanners/dependency-resolver.d.ts +71 -0
- package/dist/domains/security-compliance/services/scanners/dependency-resolver.js +232 -0
- package/dist/domains/security-compliance/services/scanners/dependency-scanner.d.ts +21 -6
- package/dist/domains/security-compliance/services/scanners/dependency-scanner.js +142 -64
- package/dist/domains/security-compliance/services/scanners/lockfile-versions.d.ts +43 -0
- package/dist/domains/security-compliance/services/scanners/lockfile-versions.js +248 -0
- package/dist/domains/security-compliance/services/scanners/scanner-types.d.ts +30 -2
- package/dist/domains/security-compliance/services/security-auditor.d.ts +19 -6
- package/dist/domains/security-compliance/services/security-auditor.js +133 -92
- package/dist/domains/test-execution/services/retry-handler.js +17 -6
- package/dist/domains/test-execution/services/test-executor.d.ts +1 -0
- package/dist/domains/test-execution/services/test-executor.js +87 -7
- package/dist/kernel/shared-dirs.js +17 -5
- package/dist/mcp/bundle.js +874 -874
- package/dist/mcp/handlers/domain-handler-configs.d.ts +4 -0
- package/dist/mcp/handlers/domain-handler-configs.js +5 -1
- package/dist/mcp/protocol-server.js +2 -1
- package/dist/mcp/types.d.ts +6 -0
- package/dist/shared/security/index.d.ts +2 -2
- package/dist/shared/security/index.js +1 -1
- package/dist/shared/security/osv-client.d.ts +79 -132
- package/dist/shared/security/osv-client.js +344 -167
- package/dist/shared/security/osv-lookup.d.ts +124 -0
- package/dist/shared/security/osv-lookup.js +246 -0
- package/dist/shared/security/osv-types.d.ts +119 -0
- package/dist/shared/security/osv-types.js +6 -0
- package/dist/workers/interfaces.d.ts +6 -1
- package/dist/workers/namespaced-keys.d.ts +16 -0
- package/dist/workers/namespaced-keys.js +24 -0
- package/dist/workers/quality-daemon/persistent-memory.d.ts +1 -1
- package/dist/workers/quality-daemon/persistent-memory.js +2 -2
- package/dist/workers/worker-manager.js +5 -2
- package/dist/workers/workers/defect-predictor.d.ts +25 -8
- package/dist/workers/workers/defect-predictor.js +223 -216
- package/dist/workers/workers/performance-baseline.d.ts +24 -9
- package/dist/workers/workers/performance-baseline.js +187 -230
- package/dist/workers/workers/quality-gate.d.ts +11 -9
- package/dist/workers/workers/quality-gate.js +125 -267
- package/dist/workers/workers/security-scan-records.d.ts +111 -0
- package/dist/workers/workers/security-scan-records.js +128 -0
- package/dist/workers/workers/security-scan.d.ts +25 -7
- package/dist/workers/workers/security-scan.js +187 -164
- package/package.json +2 -2
- package/dist/cli/chunks/adapter-PP3XIXDV.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-VDUQJKKY.js +0 -2
- package/dist/cli/chunks/base-QSYWWPCE.js +0 -2
- package/dist/cli/chunks/browser-workflow-WXXPBSCM.js +0 -2
- package/dist/cli/chunks/chunk-45MVRQG4.js +0 -2
- package/dist/cli/chunks/chunk-5VZVMO7B.js +0 -3
- package/dist/cli/chunks/chunk-EECF4CMA.js +0 -2
- package/dist/cli/chunks/client-6XKSQ4JT.js +0 -2
- package/dist/cli/chunks/core-handlers-OJYW4Y6M.js +0 -2
- package/dist/cli/chunks/cross-domain-router-QVUPQ2SC.js +0 -2
- package/dist/cli/chunks/daemon-QBYTCIMH.js +0 -10
- package/dist/cli/chunks/dream-3UABDRZJ.js +0 -2
- package/dist/cli/chunks/file-discovery-ZFGZTKZ4.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-MJ6MTPDF.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-FQWJCFVW.js +0 -2
- package/dist/cli/chunks/hnsw-index-NJYKJUHC.js +0 -2
- package/dist/cli/chunks/hybrid-backend-SL7RFID7.js +0 -2
- package/dist/cli/chunks/impact-analyzer-5ZJTXPVC.js +0 -2
- package/dist/cli/chunks/init-handler-PCLYQUSB.js +0 -88
- package/dist/cli/chunks/init-wizard-MQMDSIOF.js +0 -2
- package/dist/cli/chunks/kernel-MEJ5GMRH.js +0 -2
- package/dist/cli/chunks/knowledge-graph-XUBZSEZE.js +0 -2
- package/dist/cli/chunks/llm-router-service-QZAPAEPX.js +0 -2
- package/dist/cli/chunks/load-test-OVXIQ3AF.js +0 -2
- package/dist/cli/chunks/memory-backend-TRPOMPK4.js +0 -2
- package/dist/cli/chunks/pattern-null-store-JWYBRBZG.js +0 -2
- package/dist/cli/chunks/project-root-VVSTHIP4.js +0 -2
- package/dist/cli/chunks/protocol-executor-PXZCLZD3.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-42FRS5V3.js +0 -2
- package/dist/cli/chunks/queen-coordinator-UI3B7DI6.js +0 -2
- package/dist/cli/chunks/router-HYRPWLAY.js +0 -2
- package/dist/cli/chunks/routing-feedback-BPZ5R6F3.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-DEKDQ6KO.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-L53VBS7I.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-I6RUGD2D.js +0 -2
- package/dist/cli/chunks/safe-db-KS65XDCP.js +0 -2
- package/dist/cli/chunks/schedule-KD2VN6GB.js +0 -2
- package/dist/cli/chunks/scheduler-ZH3RMUHY.js +0 -2
- package/dist/cli/chunks/security-PWQTGDRU.js +0 -13
- package/dist/cli/chunks/sqlite-persistence-6DTVME5D.js +0 -2
- package/dist/cli/chunks/unified-memory-FCX7NLFZ.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-VU5QJK37.js +0 -2
- package/dist/cli/chunks/unified-persistence-FM376LGE.js +0 -2
- package/dist/cli/chunks/visual-security-EU7Y3X46.js +0 -2
- package/dist/cli/chunks/witness-chain-CSEBT52D.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-ALNKOM3N.js +0 -2
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { Result } from '../../../shared/types/index.js';
|
|
13
13
|
import type { MemoryBackend } from '../../../kernel/interfaces.js';
|
|
14
14
|
import type { FilePath } from '../../../shared/value-objects/index.js';
|
|
15
|
+
import { OSVClient } from '../../../shared/security/osv-client.js';
|
|
15
16
|
import type { DependencyScanResult, PackageSecurityInfo, UpgradeRecommendation, Vulnerability, DependencyInfo, SecretScanResult, SecurityAuditOptions, SecurityAuditReport } from '../interfaces.js';
|
|
16
17
|
export type { ISecurityAuditorService, SecurityPostureSummary, TriagedVulnerabilities, SecurityAuditorConfig, PackageJson, OSVQueryRequest, OSVVulnerability, OSVQueryResponse, HttpResponse, } from './security-auditor-types.js';
|
|
17
18
|
export { DEFAULT_CONFIG, httpPost, httpGet } from './security-auditor-types.js';
|
|
@@ -19,7 +20,8 @@ import type { ISecurityAuditorService, SecurityPostureSummary, TriagedVulnerabil
|
|
|
19
20
|
export declare class SecurityAuditorService implements ISecurityAuditorService {
|
|
20
21
|
private readonly memory;
|
|
21
22
|
private readonly config;
|
|
22
|
-
|
|
23
|
+
private readonly osvClient;
|
|
24
|
+
constructor(memory: MemoryBackend, config?: Partial<SecurityAuditorConfig>, osvClient?: OSVClient);
|
|
23
25
|
scanDependencies(manifestPath: FilePath): Promise<Result<DependencyScanResult>>;
|
|
24
26
|
checkPackage(name: string, version: string, ecosystem: DependencyInfo['ecosystem']): Promise<Result<PackageSecurityInfo>>;
|
|
25
27
|
getUpgradeRecommendations(vulnerabilities: Vulnerability[]): Promise<Result<UpgradeRecommendation[]>>;
|
|
@@ -29,12 +31,23 @@ export declare class SecurityAuditorService implements ISecurityAuditorService {
|
|
|
29
31
|
triageVulnerabilities(vulnerabilities: Vulnerability[]): Promise<Result<TriagedVulnerabilities>>;
|
|
30
32
|
private detectEcosystem;
|
|
31
33
|
private parseDependencies;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Dependencies to check for a scan. npm uses the shared resolver (#1049):
|
|
36
|
+
* lockfile-resolved versions when in sync with package.json, exact specs
|
|
37
|
+
* otherwise, local packages excluded; anything that cannot be matched without
|
|
38
|
+
* guessing is returned as pre-unchecked. Planning errors (a malformed lockfile,
|
|
39
|
+
* a workspace root whose members are not scanned, #1057) are pre-unchecked too,
|
|
40
|
+
* so the audit is never complete when they occur.
|
|
41
|
+
*/
|
|
42
|
+
private parseDependenciesForScan;
|
|
43
|
+
/**
|
|
44
|
+
* Check dependencies against OSV advisories. A failed or partial lookup is
|
|
45
|
+
* reported with the unchecked dependencies, never as "no vulnerabilities" (#1049).
|
|
46
|
+
*/
|
|
47
|
+
private checkDependencyAdvisories;
|
|
48
|
+
private toDependencyScanResult;
|
|
34
49
|
private mapToOSVEcosystem;
|
|
35
|
-
private
|
|
36
|
-
private mapOSVSeverity;
|
|
37
|
-
private extractFixedVersion;
|
|
50
|
+
private mapParsedVulnerability;
|
|
38
51
|
private categorizeVulnerability;
|
|
39
52
|
private checkOutdated;
|
|
40
53
|
private queryVulnerabilityDatabase;
|
|
@@ -16,8 +16,11 @@ import * as path from 'path';
|
|
|
16
16
|
import { ok, err } from '../../../shared/types/index.js';
|
|
17
17
|
import { toError } from '../../../shared/error-utils.js';
|
|
18
18
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
19
|
+
import { OSVClient } from '../../../shared/security/osv-client.js';
|
|
20
|
+
import { lookupKey } from '../../../shared/security/osv-lookup.js';
|
|
21
|
+
import { resolveDependencies } from './scanners/dependency-resolver.js';
|
|
19
22
|
export { DEFAULT_CONFIG, httpPost, httpGet } from './security-auditor-types.js';
|
|
20
|
-
import { DEFAULT_CONFIG,
|
|
23
|
+
import { DEFAULT_CONFIG, httpGet } from './security-auditor-types.js';
|
|
21
24
|
// Import extracted modules
|
|
22
25
|
import { performSASTScan } from './security-auditor-sast.js';
|
|
23
26
|
import { performDASTScan } from './security-auditor-dast.js';
|
|
@@ -27,12 +30,16 @@ import { calculateOverallRisk, generateRecommendations, countBySeverity, countOp
|
|
|
27
30
|
// Security Auditor Service Implementation
|
|
28
31
|
// ============================================================================
|
|
29
32
|
const logger = LoggerFactory.create('security-compliance/security-auditor');
|
|
33
|
+
/** Name of an unchecked entry that stands for a planning error (malformed lockfile, workspace root #1057). */
|
|
34
|
+
const PLANNING_ENTRY = '(dependency plan)';
|
|
30
35
|
export class SecurityAuditorService {
|
|
31
36
|
memory;
|
|
32
37
|
config;
|
|
33
|
-
|
|
38
|
+
osvClient;
|
|
39
|
+
constructor(memory, config = {}, osvClient) {
|
|
34
40
|
this.memory = memory;
|
|
35
41
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
42
|
+
this.osvClient = osvClient ?? new OSVClient();
|
|
36
43
|
}
|
|
37
44
|
// ==========================================================================
|
|
38
45
|
// IDependencySecurityService Implementation
|
|
@@ -44,20 +51,19 @@ export class SecurityAuditorService {
|
|
|
44
51
|
if (!ecosystem) {
|
|
45
52
|
return err(new Error(`Unknown manifest format: ${manifest}`));
|
|
46
53
|
}
|
|
47
|
-
const vulnerabilities = [];
|
|
48
54
|
const outdatedPackages = [];
|
|
49
|
-
const dependencies = await this.
|
|
55
|
+
const { dependencies, preUnchecked } = await this.parseDependenciesForScan(manifest, ecosystem);
|
|
56
|
+
const advisories = await this.checkDependencyAdvisories(dependencies, preUnchecked);
|
|
50
57
|
for (const dep of dependencies) {
|
|
51
|
-
const vulns = await this.checkDependencyVulnerabilities(dep, ecosystem);
|
|
52
|
-
vulnerabilities.push(...vulns);
|
|
53
58
|
const outdated = await this.checkOutdated(dep);
|
|
54
59
|
if (outdated) {
|
|
55
60
|
outdatedPackages.push(outdated);
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
|
-
const summary = this.createDependencySummary(vulnerabilities, dependencies.length);
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
const summary = this.createDependencySummary(advisories.vulnerabilities, dependencies.length);
|
|
64
|
+
const result = this.toDependencyScanResult(advisories, outdatedPackages, summary);
|
|
65
|
+
await this.memory.set(`security:deps:${manifestPath.filename}`, result, { namespace: 'security-compliance', ttl: 86400 });
|
|
66
|
+
return ok(result);
|
|
61
67
|
}
|
|
62
68
|
catch (error) {
|
|
63
69
|
return err(toError(error));
|
|
@@ -134,6 +140,10 @@ export class SecurityAuditorService {
|
|
|
134
140
|
}
|
|
135
141
|
const overallRiskScore = calculateOverallRisk(sastResults, dastResults, dependencyResults, secretScanResults);
|
|
136
142
|
const recommendations = generateRecommendations(sastResults, dastResults, dependencyResults, secretScanResults);
|
|
143
|
+
// #1049: an incomplete advisory lookup leaves dependency risk unmeasured.
|
|
144
|
+
if (dependencyResults && dependencyResults.status !== 'complete') {
|
|
145
|
+
recommendations.unshift(`${dependencyResults.error ?? 'Dependency advisories could not be checked'}. Dependency risk is unmeasured; re-run the scan when the OSV API is reachable.`);
|
|
146
|
+
}
|
|
137
147
|
const report = {
|
|
138
148
|
auditId,
|
|
139
149
|
timestamp,
|
|
@@ -247,9 +257,9 @@ export class SecurityAuditorService {
|
|
|
247
257
|
...packageJson.peerDependencies,
|
|
248
258
|
...packageJson.optionalDependencies,
|
|
249
259
|
};
|
|
260
|
+
// Declared specs only; scans resolve versions via parseDependenciesForScan (#1049).
|
|
250
261
|
for (const [name, versionSpec] of Object.entries(allDeps)) {
|
|
251
|
-
|
|
252
|
-
dependencies.push({ name, version, ecosystem: 'npm' });
|
|
262
|
+
dependencies.push({ name, version: versionSpec, ecosystem: 'npm' });
|
|
253
263
|
}
|
|
254
264
|
}
|
|
255
265
|
else if (ecosystem === 'pip') {
|
|
@@ -259,11 +269,14 @@ export class SecurityAuditorService {
|
|
|
259
269
|
const trimmed = line.trim();
|
|
260
270
|
if (!trimmed || trimmed.startsWith('#'))
|
|
261
271
|
continue;
|
|
262
|
-
|
|
272
|
+
// Only an `==` pin is a concrete version; any other specifier is kept
|
|
273
|
+
// verbatim so the lookup reports it unchecked (#1049).
|
|
274
|
+
const match = trimmed.match(/^([a-zA-Z0-9_.-]+)\s*(===?|>=|<=|~=|!=|>|<)?\s*([^\s;#]+)?/);
|
|
263
275
|
if (match) {
|
|
276
|
+
const [, name, op, value] = match;
|
|
264
277
|
dependencies.push({
|
|
265
|
-
name
|
|
266
|
-
version:
|
|
278
|
+
name,
|
|
279
|
+
version: value && (op === '==' || op === '===') ? value : op && value ? `${op}${value}` : '*',
|
|
267
280
|
ecosystem: 'pip',
|
|
268
281
|
});
|
|
269
282
|
}
|
|
@@ -272,32 +285,90 @@ export class SecurityAuditorService {
|
|
|
272
285
|
}
|
|
273
286
|
catch (error) {
|
|
274
287
|
logger.error(`Failed to parse dependencies from ${manifest}:`, error instanceof Error ? error : undefined);
|
|
288
|
+
// #1049: an unreadable manifest is a failed scan, not a project with no dependencies.
|
|
289
|
+
throw error;
|
|
275
290
|
}
|
|
276
291
|
return dependencies;
|
|
277
292
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Dependencies to check for a scan. npm uses the shared resolver (#1049):
|
|
295
|
+
* lockfile-resolved versions when in sync with package.json, exact specs
|
|
296
|
+
* otherwise, local packages excluded; anything that cannot be matched without
|
|
297
|
+
* guessing is returned as pre-unchecked. Planning errors (a malformed lockfile,
|
|
298
|
+
* a workspace root whose members are not scanned, #1057) are pre-unchecked too,
|
|
299
|
+
* so the audit is never complete when they occur.
|
|
300
|
+
*/
|
|
301
|
+
async parseDependenciesForScan(manifest, ecosystem) {
|
|
302
|
+
if (ecosystem !== 'npm')
|
|
303
|
+
return { dependencies: await this.parseDependencies(manifest, ecosystem), preUnchecked: [] };
|
|
304
|
+
let resolution;
|
|
283
305
|
try {
|
|
284
|
-
|
|
285
|
-
const osvQuery = {
|
|
286
|
-
package: { name: dep.name, ecosystem: osvEcosystem },
|
|
287
|
-
version: dep.version,
|
|
288
|
-
};
|
|
289
|
-
const response = await httpPost('https://api.osv.dev/v1/query', osvQuery);
|
|
290
|
-
if (response.ok && response.data.vulns && response.data.vulns.length > 0) {
|
|
291
|
-
for (const osvVuln of response.data.vulns) {
|
|
292
|
-
const vulnerability = this.mapOSVVulnerability(osvVuln, dep);
|
|
293
|
-
vulnerabilities.push(vulnerability);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
306
|
+
resolution = await resolveDependencies(manifest);
|
|
296
307
|
}
|
|
297
308
|
catch (error) {
|
|
298
|
-
logger.error(`Failed to
|
|
309
|
+
logger.error(`Failed to parse dependencies from ${manifest}:`, error instanceof Error ? error : undefined);
|
|
310
|
+
// #1049: an unreadable manifest is a failed scan, not a project with no dependencies.
|
|
311
|
+
throw error;
|
|
299
312
|
}
|
|
300
|
-
|
|
313
|
+
const dependencies = [];
|
|
314
|
+
const preUnchecked = [];
|
|
315
|
+
for (const dep of resolution.dependencies) {
|
|
316
|
+
if (dep.kind === 'check')
|
|
317
|
+
dependencies.push({ name: dep.packageName, version: dep.version, ecosystem: 'npm' });
|
|
318
|
+
else if (dep.kind === 'unchecked') {
|
|
319
|
+
preUnchecked.push({ name: dep.name, version: dep.spec, reason: dep.reason ?? 'not checked',
|
|
320
|
+
...(dep.member ? { member: dep.member } : {}), ...(dep.lockedVersion ? { lockedVersion: dep.lockedVersion } : {}) });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
for (const reason of [...(resolution.error ? [resolution.error] : []), ...resolution.memberErrors]) {
|
|
324
|
+
preUnchecked.push({ name: PLANNING_ENTRY, version: '*', reason });
|
|
325
|
+
}
|
|
326
|
+
return { dependencies, preUnchecked };
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Check dependencies against OSV advisories. A failed or partial lookup is
|
|
330
|
+
* reported with the unchecked dependencies, never as "no vulnerabilities" (#1049).
|
|
331
|
+
*/
|
|
332
|
+
async checkDependencyAdvisories(dependencies, preUnchecked = []) {
|
|
333
|
+
const lookup = await this.osvClient.lookupBatch(dependencies.map((dep) => ({
|
|
334
|
+
name: dep.name, ecosystem: this.mapToOSVEcosystem(dep.ecosystem), version: dep.version,
|
|
335
|
+
})));
|
|
336
|
+
const vulnerabilities = [];
|
|
337
|
+
for (const dep of dependencies) {
|
|
338
|
+
const found = lookup.results.get(lookupKey({ ecosystem: this.mapToOSVEcosystem(dep.ecosystem), name: dep.name, version: dep.version })) ?? [];
|
|
339
|
+
vulnerabilities.push(...found.map((parsed) => this.mapParsedVulnerability(parsed, dep)));
|
|
340
|
+
}
|
|
341
|
+
const uncheckedPackages = [...preUnchecked, ...lookup.unchecked.map((pkg) => ({
|
|
342
|
+
name: pkg.name, version: pkg.version ?? 'unknown', reason: pkg.reason,
|
|
343
|
+
}))];
|
|
344
|
+
const reasons = lookup.errors.length > 0 ? lookup.errors : [...new Set(uncheckedPackages.map((p) => p.reason))];
|
|
345
|
+
const requested = lookup.packagesChecked + uncheckedPackages.length;
|
|
346
|
+
// `failed` only when a real package was to be checked and none was; a planning
|
|
347
|
+
// error alone (e.g. an empty workspace root) is incomplete, as in the scanner.
|
|
348
|
+
const realRequested = requested - uncheckedPackages.filter((p) => p.name === PLANNING_ENTRY).length;
|
|
349
|
+
const status = lookup.packagesChecked === requested ? 'complete'
|
|
350
|
+
: lookup.packagesChecked === 0 && realRequested > 0 ? 'failed' : 'incomplete';
|
|
351
|
+
return {
|
|
352
|
+
vulnerabilities,
|
|
353
|
+
status,
|
|
354
|
+
packagesChecked: lookup.packagesChecked,
|
|
355
|
+
uncheckedPackages,
|
|
356
|
+
...(status === 'complete' ? {} : {
|
|
357
|
+
error: `Dependency advisories could not be checked for ${uncheckedPackages.length} package(s): ${reasons.slice(0, 3).join('; ')}`,
|
|
358
|
+
}),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
toDependencyScanResult(advisories, outdatedPackages, summary) {
|
|
362
|
+
return {
|
|
363
|
+
vulnerabilities: advisories.vulnerabilities,
|
|
364
|
+
outdatedPackages,
|
|
365
|
+
summary,
|
|
366
|
+
status: advisories.status,
|
|
367
|
+
measured: advisories.status === 'complete',
|
|
368
|
+
packagesChecked: advisories.packagesChecked,
|
|
369
|
+
uncheckedPackages: advisories.uncheckedPackages,
|
|
370
|
+
...(advisories.error ? { error: advisories.error } : {}),
|
|
371
|
+
};
|
|
301
372
|
}
|
|
302
373
|
mapToOSVEcosystem(ecosystem) {
|
|
303
374
|
const ecosystemMap = {
|
|
@@ -309,13 +380,10 @@ export class SecurityAuditorService {
|
|
|
309
380
|
};
|
|
310
381
|
return ecosystemMap[ecosystem];
|
|
311
382
|
}
|
|
312
|
-
|
|
313
|
-
const
|
|
314
|
-
const severity = this.mapOSVSeverity(osvVuln.severity);
|
|
315
|
-
const fixedVersion = this.extractFixedVersion(osvVuln);
|
|
316
|
-
const references = osvVuln.references?.map((ref) => ref.url) || [];
|
|
383
|
+
mapParsedVulnerability(parsed, dep) {
|
|
384
|
+
const fixedVersion = parsed.fixedVersions[0];
|
|
317
385
|
const location = {
|
|
318
|
-
file: 'package.json',
|
|
386
|
+
file: dep.ecosystem === 'pip' ? 'requirements.txt' : 'package.json',
|
|
319
387
|
dependency: dep,
|
|
320
388
|
};
|
|
321
389
|
const remediation = {
|
|
@@ -328,51 +396,17 @@ export class SecurityAuditorService {
|
|
|
328
396
|
};
|
|
329
397
|
return {
|
|
330
398
|
id: uuidv4(),
|
|
331
|
-
cveId,
|
|
332
|
-
title:
|
|
333
|
-
description:
|
|
334
|
-
severity,
|
|
335
|
-
|
|
399
|
+
cveId: parsed.cveIds[0],
|
|
400
|
+
title: parsed.summary || `Vulnerability in ${dep.name}`,
|
|
401
|
+
description: parsed.details || parsed.summary || 'No description available',
|
|
402
|
+
// An advisory without a severity rating stays reported, at medium (as before).
|
|
403
|
+
severity: parsed.severity === 'unknown' ? 'medium' : parsed.severity,
|
|
404
|
+
category: this.categorizeVulnerability({ summary: parsed.summary, details: parsed.details }),
|
|
336
405
|
location,
|
|
337
406
|
remediation,
|
|
338
|
-
references,
|
|
407
|
+
references: parsed.references,
|
|
339
408
|
};
|
|
340
409
|
}
|
|
341
|
-
mapOSVSeverity(severityScores) {
|
|
342
|
-
if (!severityScores || severityScores.length === 0) {
|
|
343
|
-
return 'medium';
|
|
344
|
-
}
|
|
345
|
-
const cvssScore = severityScores.find((s) => s.type === 'CVSS_V3' || s.type === 'CVSS_V2');
|
|
346
|
-
if (cvssScore) {
|
|
347
|
-
const score = parseFloat(cvssScore.score);
|
|
348
|
-
if (score >= 9.0)
|
|
349
|
-
return 'critical';
|
|
350
|
-
if (score >= 7.0)
|
|
351
|
-
return 'high';
|
|
352
|
-
if (score >= 4.0)
|
|
353
|
-
return 'medium';
|
|
354
|
-
if (score > 0)
|
|
355
|
-
return 'low';
|
|
356
|
-
}
|
|
357
|
-
return 'medium';
|
|
358
|
-
}
|
|
359
|
-
extractFixedVersion(osvVuln) {
|
|
360
|
-
if (!osvVuln.affected)
|
|
361
|
-
return undefined;
|
|
362
|
-
for (const affected of osvVuln.affected) {
|
|
363
|
-
if (affected.ranges) {
|
|
364
|
-
for (const range of affected.ranges) {
|
|
365
|
-
if (range.events) {
|
|
366
|
-
const fixedEvent = range.events.find((event) => event.fixed);
|
|
367
|
-
if (fixedEvent?.fixed) {
|
|
368
|
-
return fixedEvent.fixed;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return undefined;
|
|
375
|
-
}
|
|
376
410
|
categorizeVulnerability(osvVuln) {
|
|
377
411
|
const summary = (osvVuln.summary || '').toLowerCase();
|
|
378
412
|
const details = (osvVuln.details || '').toLowerCase();
|
|
@@ -397,7 +431,8 @@ export class SecurityAuditorService {
|
|
|
397
431
|
}
|
|
398
432
|
async checkOutdated(dep) {
|
|
399
433
|
const latestVersion = await this.getLatestVersion(dep.name, dep.ecosystem);
|
|
400
|
-
|
|
434
|
+
// A failed registry lookup ('unknown') is not evidence the package is outdated.
|
|
435
|
+
if (latestVersion !== 'unknown' && latestVersion !== dep.version) {
|
|
401
436
|
return {
|
|
402
437
|
name: dep.name,
|
|
403
438
|
currentVersion: dep.version,
|
|
@@ -408,8 +443,11 @@ export class SecurityAuditorService {
|
|
|
408
443
|
return null;
|
|
409
444
|
}
|
|
410
445
|
async queryVulnerabilityDatabase(name, version, ecosystem) {
|
|
411
|
-
const
|
|
412
|
-
|
|
446
|
+
const outcome = await this.checkDependencyAdvisories([{ name, version, ecosystem }]);
|
|
447
|
+
if (outcome.status !== 'complete') {
|
|
448
|
+
throw new Error(outcome.error ?? `Dependency advisories could not be checked for ${name}@${version}`);
|
|
449
|
+
}
|
|
450
|
+
return outcome.vulnerabilities;
|
|
413
451
|
}
|
|
414
452
|
async getLatestVersion(name, ecosystem) {
|
|
415
453
|
try {
|
|
@@ -495,25 +533,23 @@ export class SecurityAuditorService {
|
|
|
495
533
|
}
|
|
496
534
|
async performDependencyScan() {
|
|
497
535
|
const startTime = Date.now();
|
|
498
|
-
const vulnerabilities = [];
|
|
499
536
|
const outdatedPackages = [];
|
|
537
|
+
const manifestPath = path.join(process.cwd(), 'package.json');
|
|
500
538
|
try {
|
|
501
|
-
const
|
|
502
|
-
const
|
|
539
|
+
const { dependencies, preUnchecked } = await this.parseDependenciesForScan(manifestPath, 'npm');
|
|
540
|
+
const advisories = await this.checkDependencyAdvisories(dependencies, preUnchecked);
|
|
503
541
|
for (const dep of dependencies) {
|
|
504
|
-
const vulns = await this.checkDependencyVulnerabilities(dep, dep.ecosystem);
|
|
505
|
-
vulnerabilities.push(...vulns);
|
|
506
542
|
const outdated = await this.checkOutdated(dep);
|
|
507
543
|
if (outdated) {
|
|
508
544
|
outdatedPackages.push(outdated);
|
|
509
545
|
}
|
|
510
546
|
}
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
return { vulnerabilities, outdatedPackages, summary: { ...baseSummary, scanDurationMs } };
|
|
547
|
+
const baseSummary = this.createDependencySummary(advisories.vulnerabilities, dependencies.length);
|
|
548
|
+
return this.toDependencyScanResult(advisories, outdatedPackages, { ...baseSummary, scanDurationMs: Date.now() - startTime });
|
|
514
549
|
}
|
|
515
550
|
catch (error) {
|
|
516
551
|
logger.error('Dependency scan failed:', error instanceof Error ? error : undefined);
|
|
552
|
+
// #1049: a scan that could not run is failed, never an empty clean result.
|
|
517
553
|
return {
|
|
518
554
|
vulnerabilities: [],
|
|
519
555
|
outdatedPackages: [],
|
|
@@ -521,6 +557,11 @@ export class SecurityAuditorService {
|
|
|
521
557
|
critical: 0, high: 0, medium: 0, low: 0, informational: 0,
|
|
522
558
|
totalFiles: 0, scanDurationMs: Date.now() - startTime,
|
|
523
559
|
},
|
|
560
|
+
status: 'failed',
|
|
561
|
+
measured: false,
|
|
562
|
+
packagesChecked: 0,
|
|
563
|
+
uncheckedPackages: [],
|
|
564
|
+
error: `Dependency scan of ${manifestPath} failed: ${toError(error).message}`,
|
|
524
565
|
};
|
|
525
566
|
}
|
|
526
567
|
}
|
|
@@ -564,7 +605,7 @@ export class SecurityAuditorService {
|
|
|
564
605
|
}
|
|
565
606
|
}
|
|
566
607
|
}
|
|
567
|
-
catch
|
|
608
|
+
catch {
|
|
568
609
|
logger.debug('Directory read error:');
|
|
569
610
|
}
|
|
570
611
|
return files;
|
|
@@ -7,6 +7,7 @@ import { spawn } from 'node:child_process';
|
|
|
7
7
|
import { createVitestJsonReport } from '../../../shared/vitest-json-report.js';
|
|
8
8
|
import { jestExactPathPattern, nameFilterArg, runnerFilePath } from '../../../shared/test-runner-args.js';
|
|
9
9
|
import { existsSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { resolve as resolvePath } from 'node:path';
|
|
10
11
|
import { ok, err } from '../../../shared/types/index.js';
|
|
11
12
|
import { TEST_EXECUTION_CONSTANTS, RETRY_CONSTANTS } from '../../constants.js';
|
|
12
13
|
import { toError } from '../../../shared/error-utils.js';
|
|
@@ -267,7 +268,7 @@ export class RetryHandlerService {
|
|
|
267
268
|
// Build command based on runner
|
|
268
269
|
const { command, args, report } = this.buildTestCommand(runner, testFile, testName, cwd);
|
|
269
270
|
// Execute the test
|
|
270
|
-
return this.spawnTestProcess(command, args, cwd, report);
|
|
271
|
+
return this.spawnTestProcess(command, args, cwd, report, runner === 'vitest' ? testFile : undefined);
|
|
271
272
|
}
|
|
272
273
|
/**
|
|
273
274
|
* Detect which test runner is available in the project
|
|
@@ -380,7 +381,7 @@ export class RetryHandlerService {
|
|
|
380
381
|
/**
|
|
381
382
|
* Spawn a test process and parse the result
|
|
382
383
|
*/
|
|
383
|
-
spawnTestProcess(command, args, cwd, report) {
|
|
384
|
+
spawnTestProcess(command, args, cwd, report, targetFile) {
|
|
384
385
|
return new Promise((resolve, reject) => {
|
|
385
386
|
const timeout = this.config.testTimeout;
|
|
386
387
|
let stdout = '';
|
|
@@ -431,7 +432,7 @@ export class RetryHandlerService {
|
|
|
431
432
|
if (reportText === undefined) {
|
|
432
433
|
throw new Error('The current Vitest JSON report is missing for the retry run.');
|
|
433
434
|
}
|
|
434
|
-
settle(resolve, this.parseTestResult(code, reportText, stderr));
|
|
435
|
+
settle(resolve, this.parseTestResult(code, reportText, stderr, targetFile));
|
|
435
436
|
}
|
|
436
437
|
catch (error) {
|
|
437
438
|
settle(reject, toError(error));
|
|
@@ -450,7 +451,7 @@ export class RetryHandlerService {
|
|
|
450
451
|
/**
|
|
451
452
|
* Parse test runner output to determine pass/fail status
|
|
452
453
|
*/
|
|
453
|
-
parseTestResult(exitCode, stdout, stderr) {
|
|
454
|
+
parseTestResult(exitCode, stdout, stderr, targetFile) {
|
|
454
455
|
// A retry can clear a prior failure only when the report proves a test
|
|
455
456
|
// actually passed. Empty/fully skipped selections can also exit zero.
|
|
456
457
|
try {
|
|
@@ -458,16 +459,26 @@ export class RetryHandlerService {
|
|
|
458
459
|
const vitestMatch = stdout.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
|
|
459
460
|
if (vitestMatch) {
|
|
460
461
|
const result = safeJsonParse(vitestMatch[0]);
|
|
462
|
+
// Vitest's positional file filter uses prefix matching. A passing
|
|
463
|
+
// sibling must not clear a failure in the requested file (#972).
|
|
464
|
+
const targetPassed = !targetFile || result.testResults?.some((file) => typeof file.name === 'string'
|
|
465
|
+
&& resolvePath(file.name) === resolvePath(targetFile)
|
|
466
|
+
&& file.assertionResults?.some(assertion => assertion.status === 'passed'));
|
|
461
467
|
if (exitCode === 0 && result.success !== false
|
|
462
468
|
&& result.numFailedTests === 0 && result.numFailedTestSuites === 0
|
|
463
|
-
&& Number.isFinite(result.numPassedTests) && result.numPassedTests > 0
|
|
469
|
+
&& Number.isFinite(result.numPassedTests) && result.numPassedTests > 0
|
|
470
|
+
&& targetPassed) {
|
|
464
471
|
return { passed: true };
|
|
465
472
|
}
|
|
466
473
|
const failedTest = result.testResults?.[0]?.assertionResults?.find((r) => r.status === 'failed');
|
|
467
474
|
return {
|
|
468
475
|
passed: false,
|
|
469
476
|
error: failedTest?.failureMessages?.join('\n') || stderr
|
|
470
|
-
|| (exitCode === 0
|
|
477
|
+
|| (exitCode === 0
|
|
478
|
+
? targetFile && !targetPassed
|
|
479
|
+
? `Retry runner did not report a passing test in ${targetFile}.`
|
|
480
|
+
: 'Retry runner did not report any passing tests.'
|
|
481
|
+
: `Test failed with exit code ${exitCode}`),
|
|
471
482
|
};
|
|
472
483
|
}
|
|
473
484
|
// Jest JSON output
|
|
@@ -104,6 +104,7 @@ export declare class TestExecutorService implements ITestExecutionService {
|
|
|
104
104
|
private validateRequest;
|
|
105
105
|
private validateParallelRequest;
|
|
106
106
|
private runTests;
|
|
107
|
+
private mergeSequentialCoverage;
|
|
107
108
|
private executeTestFile;
|
|
108
109
|
private executeTestFiles;
|
|
109
110
|
/**
|
|
@@ -7,6 +7,7 @@ import { spawn } from 'node:child_process';
|
|
|
7
7
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
8
8
|
import { tmpdir } from 'node:os';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
10
11
|
import { v4 as uuidv4 } from 'uuid';
|
|
11
12
|
import { ok, err } from '../../../shared/types/index.js';
|
|
12
13
|
import { TEST_EXECUTION_CONSTANTS, LLM_ANALYSIS_CONSTANTS } from '../../constants.js';
|
|
@@ -305,11 +306,13 @@ Provide:
|
|
|
305
306
|
const failedTests = [];
|
|
306
307
|
const coverages = [];
|
|
307
308
|
const allFileCoverages = [];
|
|
309
|
+
const executionResults = [];
|
|
308
310
|
let passed = 0;
|
|
309
311
|
let failed = 0;
|
|
310
312
|
let skipped = 0;
|
|
311
313
|
for (const file of testFiles) {
|
|
312
314
|
const result = await this.executeTestFile(file, framework, timeout);
|
|
315
|
+
executionResults.push(result);
|
|
313
316
|
passed += result.passed;
|
|
314
317
|
failed += result.failed;
|
|
315
318
|
skipped += result.skipped;
|
|
@@ -321,16 +324,61 @@ Provide:
|
|
|
321
324
|
allFileCoverages.push(...result.fileCoverages);
|
|
322
325
|
}
|
|
323
326
|
}
|
|
327
|
+
// Separate runner invocations each have their own coverage map. Averaging
|
|
328
|
+
// percentages double-counts source files and misses disjoint hits (#1030).
|
|
329
|
+
// If any run lacks raw counters, there is no honest combined measurement.
|
|
330
|
+
const merged = testFiles.length > 1 && !this.config.simulateForTesting
|
|
331
|
+
? this.mergeSequentialCoverage(executionResults)
|
|
332
|
+
: undefined;
|
|
333
|
+
const separateRuns = testFiles.length > 1 && !this.config.simulateForTesting;
|
|
324
334
|
return {
|
|
325
335
|
total: passed + failed + skipped,
|
|
326
336
|
passed,
|
|
327
337
|
failed,
|
|
328
338
|
skipped,
|
|
329
339
|
failedTests,
|
|
330
|
-
coverage: this.aggregateCoverage(coverages),
|
|
331
|
-
fileCoverages:
|
|
340
|
+
coverage: separateRuns ? merged?.summary : this.aggregateCoverage(coverages),
|
|
341
|
+
fileCoverages: separateRuns ? merged?.perFile
|
|
342
|
+
: allFileCoverages.length > 0 ? allFileCoverages : undefined,
|
|
332
343
|
};
|
|
333
344
|
}
|
|
345
|
+
mergeSequentialCoverage(results) {
|
|
346
|
+
if (results.some(result => !result.rawCoverageMap))
|
|
347
|
+
return undefined;
|
|
348
|
+
const merged = {};
|
|
349
|
+
for (const result of results) {
|
|
350
|
+
for (const [rawPath, entry] of Object.entries(result.rawCoverageMap)) {
|
|
351
|
+
if (!isRecord(entry) || !isRecord(entry.statementMap) || !isRecord(entry.fnMap)
|
|
352
|
+
|| !isRecord(entry.branchMap) || !isRecord(entry.s) || !isRecord(entry.f)
|
|
353
|
+
|| !isRecord(entry.b))
|
|
354
|
+
return undefined;
|
|
355
|
+
const file = fileCoverageKey(rawPath);
|
|
356
|
+
const prior = merged[file];
|
|
357
|
+
if (prior) {
|
|
358
|
+
if (!isDeepStrictEqual(prior.statementMap, entry.statementMap)
|
|
359
|
+
|| !isDeepStrictEqual(prior.fnMap, entry.fnMap)
|
|
360
|
+
|| !isDeepStrictEqual(prior.branchMap, entry.branchMap))
|
|
361
|
+
return undefined;
|
|
362
|
+
for (const counter of ['s', 'f', 'b']) {
|
|
363
|
+
const hits = mergeHitCounts(prior[counter], entry[counter]);
|
|
364
|
+
if (!hits)
|
|
365
|
+
return undefined;
|
|
366
|
+
prior[counter] = hits;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const s = mergeHitCounts(entry.s, entry.s);
|
|
371
|
+
const f = mergeHitCounts(entry.f, entry.f);
|
|
372
|
+
const b = mergeHitCounts(entry.b, entry.b);
|
|
373
|
+
if (!s || !f || !b)
|
|
374
|
+
return undefined;
|
|
375
|
+
merged[file] = { ...entry, path: file, s, f, b };
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const coverage = this.extractCoverageFromJson({ coverageMap: merged });
|
|
380
|
+
return coverage.summary ? { summary: coverage.summary, perFile: coverage.perFile } : undefined;
|
|
381
|
+
}
|
|
334
382
|
async executeTestFile(file, framework, timeout) {
|
|
335
383
|
return this.executeTestFiles([file], framework, timeout);
|
|
336
384
|
}
|
|
@@ -460,13 +508,14 @@ Provide:
|
|
|
460
508
|
const parseResult = this.parseTestOutput(reportText, stderr, fileLabel, framework, code);
|
|
461
509
|
// Read only this invocation's coverage artifacts. A previous or
|
|
462
510
|
// concurrent run's project coverage directory is not evidence.
|
|
463
|
-
if (parseResult.success &&
|
|
511
|
+
if (parseResult.success && coverageDirectory) {
|
|
464
512
|
const diskCoverage = this.readCoverageFromDisk(coverageDirectory);
|
|
465
513
|
if (diskCoverage) {
|
|
466
|
-
parseResult.value.coverage
|
|
467
|
-
if (diskCoverage.perFile.length > 0) {
|
|
514
|
+
parseResult.value.coverage ??= diskCoverage.summary;
|
|
515
|
+
if (!parseResult.value.fileCoverages && diskCoverage.perFile.length > 0) {
|
|
468
516
|
parseResult.value.fileCoverages = diskCoverage.perFile;
|
|
469
517
|
}
|
|
518
|
+
parseResult.value.rawCoverageMap ??= diskCoverage.rawMap;
|
|
470
519
|
}
|
|
471
520
|
}
|
|
472
521
|
finish(parseResult);
|
|
@@ -661,6 +710,7 @@ Provide:
|
|
|
661
710
|
failedTests,
|
|
662
711
|
coverage: covData.summary,
|
|
663
712
|
fileCoverages: covData.perFile.length > 0 ? covData.perFile : undefined,
|
|
713
|
+
rawCoverageMap: isRecord(json.coverageMap) && !json.coverageMap.total ? json.coverageMap : undefined,
|
|
664
714
|
});
|
|
665
715
|
}
|
|
666
716
|
catch {
|
|
@@ -715,6 +765,7 @@ Provide:
|
|
|
715
765
|
failedTests,
|
|
716
766
|
coverage: covData.summary,
|
|
717
767
|
fileCoverages: covData.perFile.length > 0 ? covData.perFile : undefined,
|
|
768
|
+
rawCoverageMap: isRecord(json.coverageMap) && !json.coverageMap.total ? json.coverageMap : undefined,
|
|
718
769
|
});
|
|
719
770
|
}
|
|
720
771
|
catch {
|
|
@@ -1067,8 +1118,8 @@ Provide:
|
|
|
1067
1118
|
try {
|
|
1068
1119
|
// Check common coverage output paths
|
|
1069
1120
|
const candidates = [
|
|
1070
|
-
join(coverageDirectory, 'coverage-summary.json'),
|
|
1071
1121
|
join(coverageDirectory, 'coverage-final.json'),
|
|
1122
|
+
join(coverageDirectory, 'coverage-summary.json'),
|
|
1072
1123
|
];
|
|
1073
1124
|
for (const filePath of candidates) {
|
|
1074
1125
|
if (!existsSync(filePath))
|
|
@@ -1117,7 +1168,7 @@ Provide:
|
|
|
1117
1168
|
if (typeof json === 'object' && !json.total) {
|
|
1118
1169
|
const result = this.extractCoverageFromJson({ coverageMap: json });
|
|
1119
1170
|
if (result.summary) {
|
|
1120
|
-
return { summary: result.summary, perFile: result.perFile };
|
|
1171
|
+
return { summary: result.summary, perFile: result.perFile, rawMap: json };
|
|
1121
1172
|
}
|
|
1122
1173
|
}
|
|
1123
1174
|
}
|
|
@@ -1216,4 +1267,33 @@ function summaryPct(metric) {
|
|
|
1216
1267
|
return null;
|
|
1217
1268
|
return metric.pct;
|
|
1218
1269
|
}
|
|
1270
|
+
function isRecord(value) {
|
|
1271
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
1272
|
+
}
|
|
1273
|
+
/** A test covers a counter if any invocation hit it. Reject incompatible maps. */
|
|
1274
|
+
function mergeHitCounts(left, right) {
|
|
1275
|
+
if (!isRecord(left) || !isRecord(right))
|
|
1276
|
+
return undefined;
|
|
1277
|
+
const keys = Object.keys(left);
|
|
1278
|
+
if (!isDeepStrictEqual(keys.sort(), Object.keys(right).sort()))
|
|
1279
|
+
return undefined;
|
|
1280
|
+
const merged = {};
|
|
1281
|
+
for (const key of keys) {
|
|
1282
|
+
const a = left[key];
|
|
1283
|
+
const b = right[key];
|
|
1284
|
+
if (typeof a === 'number' && Number.isFinite(a) && a >= 0
|
|
1285
|
+
&& typeof b === 'number' && Number.isFinite(b) && b >= 0) {
|
|
1286
|
+
merged[key] = Math.max(a, b);
|
|
1287
|
+
}
|
|
1288
|
+
else if (Array.isArray(a) && Array.isArray(b) && a.length === b.length
|
|
1289
|
+
&& a.every(v => typeof v === 'number' && Number.isFinite(v) && v >= 0)
|
|
1290
|
+
&& b.every(v => typeof v === 'number' && Number.isFinite(v) && v >= 0)) {
|
|
1291
|
+
merged[key] = a.map((v, i) => Math.max(v, b[i]));
|
|
1292
|
+
}
|
|
1293
|
+
else {
|
|
1294
|
+
return undefined;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return merged;
|
|
1298
|
+
}
|
|
1219
1299
|
//# sourceMappingURL=test-executor.js.map
|