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
package/dist/cli/index.js
CHANGED
|
@@ -417,6 +417,17 @@ async function main() {
|
|
|
417
417
|
const commandArgs = process.argv.slice(2).filter(arg => arg !== '--');
|
|
418
418
|
const learningSnapshot = commandArgs[0] === 'learning'
|
|
419
419
|
&& (commandArgs[1] === 'backup' || commandArgs[1] === 'restore');
|
|
420
|
+
// `aqe init` must not create a mistyped AQE_PROJECT_ROOT: the token bootstrap
|
|
421
|
+
// below does `mkdir -p <root>/.agentic-qe`, so the check has to run first.
|
|
422
|
+
if (commandArgs[0] === 'init') {
|
|
423
|
+
const { explicitRootError } = await import('./handlers/init-guard.js');
|
|
424
|
+
const rootError = explicitRootError();
|
|
425
|
+
if (rootError) {
|
|
426
|
+
console.error(chalk.red(`\n ${rootError}\n`));
|
|
427
|
+
await cleanupAndExit(1);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
420
431
|
if (!learningSnapshot) {
|
|
421
432
|
const { bootstrapTokenTracking } = await import('../init/token-bootstrap.js');
|
|
422
433
|
await bootstrapTokenTracking({
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { SecurityCoverage } from '../../domains/security-compliance/interfaces.js';
|
|
8
8
|
import type { SecurityScanEvidence } from '../../domains/security-compliance/scan-evidence.js';
|
|
9
9
|
import type { discoverSecurityFiles } from '../../domains/security-compliance/scan-discovery.js';
|
|
10
|
+
import type { DependencyScanReport } from '../../domains/security-compliance/dependency-advisory-engine.js';
|
|
10
11
|
export type OutputFormat = 'text' | 'json' | 'sarif' | 'junit' | 'markdown';
|
|
11
12
|
export interface CIOutputOptions {
|
|
12
13
|
format: OutputFormat;
|
|
@@ -20,6 +21,8 @@ export interface SecurityVulnerability {
|
|
|
20
21
|
message: string;
|
|
21
22
|
ruleId?: string;
|
|
22
23
|
cweId?: string;
|
|
24
|
+
/** CVE id of a dependency advisory, when the advisory has one (#1049). */
|
|
25
|
+
cveId?: string;
|
|
23
26
|
}
|
|
24
27
|
export interface SecurityScanResult {
|
|
25
28
|
vulnerabilities: SecurityVulnerability[];
|
|
@@ -38,6 +41,8 @@ export interface SecurityScanResult {
|
|
|
38
41
|
coverage?: SecurityCoverage;
|
|
39
42
|
evidence?: SecurityScanEvidence;
|
|
40
43
|
discovery?: Awaited<ReturnType<typeof discoverSecurityFiles>>['discovery'];
|
|
44
|
+
/** #1049: OSV dependency advisory scan; any status but 'complete' is not a clean result. */
|
|
45
|
+
dependencyScan?: DependencyScanReport;
|
|
41
46
|
}
|
|
42
47
|
export type SecurityExecutionStatus = 'complete' | 'partial' | 'none' | 'failed' | 'not-run' | 'unverified';
|
|
43
48
|
export interface SecurityCheckResult {
|
|
@@ -297,6 +297,14 @@ export function securityToMarkdown(result) {
|
|
|
297
297
|
if (result.evidence || result.discovery) {
|
|
298
298
|
md += `## Execution receipts\n\n\`\`\`json\n${toJSON({ evidence: result.evidence, discovery: result.discovery })}\n\`\`\`\n\n`;
|
|
299
299
|
}
|
|
300
|
+
if (result.dependencyScan) {
|
|
301
|
+
md += `## Dependency advisories (OSV)\n\n**Status:** ${result.dependencyScan.status}\n\n${result.dependencyScan.message}\n\n`;
|
|
302
|
+
for (const pkg of result.dependencyScan.uncheckedPackages) {
|
|
303
|
+
md += `- not checked: ${pkg.name}@${pkg.version} (${pkg.reason})\n`;
|
|
304
|
+
}
|
|
305
|
+
if (result.dependencyScan.uncheckedPackages.length > 0)
|
|
306
|
+
md += '\n';
|
|
307
|
+
}
|
|
300
308
|
if (result.vulnerabilities.length > 0) {
|
|
301
309
|
md += `## Vulnerabilities\n\n`;
|
|
302
310
|
md += `| Severity | Type | File | Line | Message |\n`;
|
|
@@ -12,6 +12,7 @@ import { toError } from '../../shared/error-utils.js';
|
|
|
12
12
|
import { FilePath } from '../../shared/value-objects/index.js';
|
|
13
13
|
import { generateSecurityRecommendations } from './handler-utils.js';
|
|
14
14
|
import { discoverSecurityFiles, isSecuritySourceFile } from '../../domains/security-compliance/scan-discovery.js';
|
|
15
|
+
import { runDependencyAdvisoryScan } from '../../domains/security-compliance/dependency-advisory-engine.js';
|
|
15
16
|
export function registerSecurityHandlers(ctx) {
|
|
16
17
|
// Register security scan handler - REAL IMPLEMENTATION
|
|
17
18
|
ctx.registerHandler('scan-security', async (task) => {
|
|
@@ -257,6 +258,13 @@ export function registerSecurityHandlers(ctx) {
|
|
|
257
258
|
status: payload.dast ? 'not-run' : 'disabled', scope: 'url', ruleCoverage: 'unknown',
|
|
258
259
|
errors: payload.dast ? ['DAST was requested without targetUrl.'] : [], limitations: [] });
|
|
259
260
|
}
|
|
261
|
+
// #1049: OSV dependency advisories. A failed or partial lookup is a
|
|
262
|
+
// failed/partial required engine, never a completed scan with no findings.
|
|
263
|
+
let dependencyScan = null;
|
|
264
|
+
if (payload.dependencies === true) {
|
|
265
|
+
dependencyScan = await runDependencyAdvisoryScan(ctx.getSecurityScanner(), targetPath);
|
|
266
|
+
engines.push(dependencyScan.engine);
|
|
267
|
+
}
|
|
260
268
|
if (payload.compliance?.length) {
|
|
261
269
|
engines.push({ id: 'compliance', requested: true, required: true, status: 'not-run',
|
|
262
270
|
scope: 'requested-files', ruleCoverage: 'unknown', errors: [],
|
|
@@ -265,7 +273,7 @@ export function registerSecurityHandlers(ctx) {
|
|
|
265
273
|
const requestedPaths = new Set(filesToScan);
|
|
266
274
|
const analyzedPaths = new Set(fileEvidence.filter(file => file.status === 'analyzed' && requestedPaths.has(file.path)).map(file => file.path));
|
|
267
275
|
const requiredEngines = engines.filter(engine => engine.requested && engine.required);
|
|
268
|
-
const hasExecuted = analyzedPaths.size > 0;
|
|
276
|
+
const hasExecuted = analyzedPaths.size > 0 || (dependencyScan?.report.packagesChecked ?? 0) > 0;
|
|
269
277
|
const complete = hasExecuted && requiredEngines.every(engine => engine.status === 'completed') &&
|
|
270
278
|
(!discoveryResult || discoveryResult.discovery.status === 'complete');
|
|
271
279
|
const evidence = {
|
|
@@ -286,18 +294,21 @@ export function registerSecurityHandlers(ctx) {
|
|
|
286
294
|
low: crossLangVulns.filter(v => v.severity === 'low').length,
|
|
287
295
|
informational: crossLangVulns.filter(v => v.severity === 'informational').length,
|
|
288
296
|
};
|
|
297
|
+
const depVulns = dependencyScan?.vulnerabilities ?? [];
|
|
298
|
+
const depCount = (severity) => depVulns.filter(v => v.severity === severity).length;
|
|
289
299
|
const summary = {
|
|
290
|
-
critical: (sastResult?.summary?.critical || 0) + (dastResult?.summary?.critical || 0) + crossLangSeverityCounts.critical,
|
|
291
|
-
high: (sastResult?.summary?.high || 0) + (dastResult?.summary?.high || 0) + crossLangSeverityCounts.high,
|
|
292
|
-
medium: (sastResult?.summary?.medium || 0) + (dastResult?.summary?.medium || 0) + crossLangSeverityCounts.medium,
|
|
293
|
-
low: (sastResult?.summary?.low || 0) + (dastResult?.summary?.low || 0) + crossLangSeverityCounts.low,
|
|
294
|
-
informational: (sastResult?.summary?.informational || 0) + (dastResult?.summary?.informational || 0) + crossLangSeverityCounts.informational,
|
|
300
|
+
critical: (sastResult?.summary?.critical || 0) + (dastResult?.summary?.critical || 0) + crossLangSeverityCounts.critical + depCount('critical'),
|
|
301
|
+
high: (sastResult?.summary?.high || 0) + (dastResult?.summary?.high || 0) + crossLangSeverityCounts.high + depCount('high'),
|
|
302
|
+
medium: (sastResult?.summary?.medium || 0) + (dastResult?.summary?.medium || 0) + crossLangSeverityCounts.medium + depCount('medium'),
|
|
303
|
+
low: (sastResult?.summary?.low || 0) + (dastResult?.summary?.low || 0) + crossLangSeverityCounts.low + depCount('low'),
|
|
304
|
+
informational: (sastResult?.summary?.informational || 0) + (dastResult?.summary?.informational || 0) + crossLangSeverityCounts.informational + depCount('informational'),
|
|
295
305
|
};
|
|
296
306
|
// Extract top vulnerabilities from all sources
|
|
297
307
|
const allVulns = [
|
|
298
308
|
...(sastResult?.vulnerabilities || []),
|
|
299
309
|
...(dastResult?.vulnerabilities || []),
|
|
300
310
|
...crossLangVulns,
|
|
311
|
+
...depVulns,
|
|
301
312
|
];
|
|
302
313
|
const topVulnerabilities = allVulns
|
|
303
314
|
.sort((a, b) => {
|
|
@@ -316,6 +327,9 @@ export function registerSecurityHandlers(ctx) {
|
|
|
316
327
|
const recommendations = allVulns.length === 0 && evidence.completeness !== 'complete'
|
|
317
328
|
? ['No findings reported; requested analysis is incomplete or unverified. Inspect execution receipts.']
|
|
318
329
|
: generateSecurityRecommendations(allVulns);
|
|
330
|
+
if (dependencyScan && dependencyScan.report.status !== 'complete') {
|
|
331
|
+
recommendations.unshift(dependencyScan.report.message);
|
|
332
|
+
}
|
|
319
333
|
return ok({
|
|
320
334
|
vulnerabilities: allVulns.length,
|
|
321
335
|
critical: summary.critical,
|
|
@@ -329,7 +343,9 @@ export function registerSecurityHandlers(ctx) {
|
|
|
329
343
|
scanTypes: {
|
|
330
344
|
sast: payload.sast !== false,
|
|
331
345
|
dast: payload.dast || false,
|
|
346
|
+
dependencies: payload.dependencies === true,
|
|
332
347
|
},
|
|
348
|
+
...(dependencyScan ? { dependencyScan: dependencyScan.report } : {}),
|
|
333
349
|
status: evidence.completeness === 'complete' ? 'completed' : evidence.completeness === 'partial' ? 'partial' : 'unavailable',
|
|
334
350
|
evidence,
|
|
335
351
|
limitations: evidence.limitations,
|
|
@@ -13,6 +13,7 @@ import { toError } from '../../shared/error-utils.js';
|
|
|
13
13
|
import { LoggerFactory } from '../../logging/index.js';
|
|
14
14
|
import { addToCount } from '../../shared/utils/safe-record.js';
|
|
15
15
|
import { measuredFileCoverage } from '../../domains/quality-assessment/coverage-report-event.js';
|
|
16
|
+
import { fileCoverageLookupKeys } from '../../domains/coverage-analysis/collected-metrics.js';
|
|
16
17
|
const logger = LoggerFactory.create('defect-investigation');
|
|
17
18
|
export const DefectInvestigationEvents = {
|
|
18
19
|
DefectInvestigationStarted: 'coordination.DefectInvestigationStarted',
|
|
@@ -607,7 +608,12 @@ export class DefectInvestigationProtocol {
|
|
|
607
608
|
try {
|
|
608
609
|
// Try per-file coverage (written by coverage-analyzer and test-executor)
|
|
609
610
|
// #1014: only measured records; legacy unstamped estimates are ignored.
|
|
610
|
-
|
|
611
|
+
let coverage = null;
|
|
612
|
+
for (const key of fileCoverageLookupKeys(file)) {
|
|
613
|
+
coverage = measuredFileCoverage(await this.memory.get(key));
|
|
614
|
+
if (coverage)
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
611
617
|
if (!coverage) {
|
|
612
618
|
return null;
|
|
613
619
|
}
|
|
@@ -137,6 +137,12 @@ export class SecurityAuditProtocol {
|
|
|
137
137
|
if (depResult.success) {
|
|
138
138
|
this.currentAudit = { ...this.currentAudit, dependencyResult: depResult.value };
|
|
139
139
|
await this.publishDependencyVulnerabilities(depResult.value.vulnerabilities);
|
|
140
|
+
// #1049: a failed or partial advisory lookup (or a result without a
|
|
141
|
+
// status, which cannot show it was complete) is not a clean dependency scan.
|
|
142
|
+
if (depResult.value.status !== 'complete') {
|
|
143
|
+
this.recordIncompleteCheck(depResult.value.error
|
|
144
|
+
?? `Dependency advisories could not be checked for ${depResult.value.uncheckedPackages?.length ?? 'unknown number of'} package(s)`);
|
|
145
|
+
}
|
|
140
146
|
}
|
|
141
147
|
else {
|
|
142
148
|
this.recordIncompleteCheck('Dependency scan did not complete');
|
|
@@ -280,6 +286,11 @@ export class SecurityAuditProtocol {
|
|
|
280
286
|
vulnerabilities: scanResult.value.vulnerabilities,
|
|
281
287
|
outdatedPackages: [],
|
|
282
288
|
summary: scanResult.value.summary,
|
|
289
|
+
status: scanResult.value.status,
|
|
290
|
+
measured: scanResult.value.measured,
|
|
291
|
+
packagesChecked: scanResult.value.packagesChecked,
|
|
292
|
+
uncheckedPackages: scanResult.value.uncheckedPackages,
|
|
293
|
+
...(scanResult.value.error ? { error: scanResult.value.error } : {}),
|
|
283
294
|
});
|
|
284
295
|
}
|
|
285
296
|
}
|
|
@@ -88,6 +88,15 @@ export declare class ResultSaver {
|
|
|
88
88
|
* `name-1.ext`, `name-2.ext`, … instead of replacing the earlier file (#1007).
|
|
89
89
|
*/
|
|
90
90
|
private writeNewFile;
|
|
91
|
+
/**
|
|
92
|
+
* File name for a generated test source: the sanitized name capped at
|
|
93
|
+
* MAX_GENERATED_STEM_LENGTH characters (a long source file name would
|
|
94
|
+
* otherwise exceed the filesystem's 255-byte limit once the temp-file suffix
|
|
95
|
+
* is added) plus a short hash of the source path and full name. The hash keeps
|
|
96
|
+
* `src/one/math.ts` and `src/two/math.ts` (or a truncated long name) from
|
|
97
|
+
* overwriting each other, while the same test still maps to the same file.
|
|
98
|
+
*/
|
|
99
|
+
private generatedTestFilename;
|
|
91
100
|
private sanitizeFilename;
|
|
92
101
|
private getTestExtension;
|
|
93
102
|
private createFileEntry;
|
|
@@ -7,6 +7,8 @@ import * as path from 'path';
|
|
|
7
7
|
import { createHash, randomBytes } from 'crypto';
|
|
8
8
|
import { safeJsonParse } from '../shared/safe-json.js';
|
|
9
9
|
import { getProjectStorePath } from '../kernel/project-root.js';
|
|
10
|
+
/** Cap on the sanitized stem of a generated test file name (see generatedTestFilename). */
|
|
11
|
+
const MAX_GENERATED_STEM_LENGTH = 100;
|
|
10
12
|
function securityReportExecution(data) {
|
|
11
13
|
return data.evidence?.completeness === 'complete' ? 'completed'
|
|
12
14
|
: data.evidence?.completeness === 'partial' ? 'partial'
|
|
@@ -174,14 +176,26 @@ export class ResultSaver {
|
|
|
174
176
|
// Save individual test files if code is provided
|
|
175
177
|
if (data.tests) {
|
|
176
178
|
for (const test of data.tests) {
|
|
177
|
-
|
|
179
|
+
// The test-generation domain returns `testCode`; retain `code` for
|
|
180
|
+
// older callers of ResultSaver that already use that field.
|
|
181
|
+
const code = test.testCode ?? test.code;
|
|
182
|
+
if (code) {
|
|
178
183
|
const ext = this.getTestExtension(options.language || 'typescript', options.framework || 'vitest');
|
|
179
|
-
const testFilename = this.
|
|
184
|
+
const testFilename = this.generatedTestFilename(test, ext);
|
|
180
185
|
const testPath = path.join(testDir, testFilename);
|
|
181
186
|
// Review of #1026 N7: a generated test keeps one file per test name
|
|
182
187
|
// (replaced atomically), unlike reports, so numbered copies never
|
|
183
188
|
// pile up for a test runner to collect.
|
|
184
|
-
|
|
189
|
+
//
|
|
190
|
+
// One unwritable source file (e.g. a name the filesystem rejects)
|
|
191
|
+
// must not discard the manifest and report, so a per-file failure is
|
|
192
|
+
// skipped; `files` then lists only what is actually on disk.
|
|
193
|
+
try {
|
|
194
|
+
files.push(await this.replaceFile(testPath, code, 'source'));
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.warn(`ResultSaver: could not write generated test ${testFilename}: ${error.message}`);
|
|
198
|
+
}
|
|
185
199
|
}
|
|
186
200
|
}
|
|
187
201
|
}
|
|
@@ -504,7 +518,7 @@ ${data.recommendations.length === 0 ? noRecommendations : data.recommendations.m
|
|
|
504
518
|
// ==========================================================================
|
|
505
519
|
// Utilities
|
|
506
520
|
// ==========================================================================
|
|
507
|
-
async ensureDirectories(
|
|
521
|
+
async ensureDirectories(_taskType) {
|
|
508
522
|
const dirs = [
|
|
509
523
|
this.resultsDir,
|
|
510
524
|
path.join(this.resultsDir, 'security'),
|
|
@@ -563,6 +577,22 @@ ${data.recommendations.length === 0 ? noRecommendations : data.recommendations.m
|
|
|
563
577
|
}
|
|
564
578
|
throw new Error(`ResultSaver: no free file name for ${filePath}`);
|
|
565
579
|
}
|
|
580
|
+
/**
|
|
581
|
+
* File name for a generated test source: the sanitized name capped at
|
|
582
|
+
* MAX_GENERATED_STEM_LENGTH characters (a long source file name would
|
|
583
|
+
* otherwise exceed the filesystem's 255-byte limit once the temp-file suffix
|
|
584
|
+
* is added) plus a short hash of the source path and full name. The hash keeps
|
|
585
|
+
* `src/one/math.ts` and `src/two/math.ts` (or a truncated long name) from
|
|
586
|
+
* overwriting each other, while the same test still maps to the same file.
|
|
587
|
+
*/
|
|
588
|
+
generatedTestFilename(test, ext) {
|
|
589
|
+
const stem = this.sanitizeFilename(test.name).slice(0, MAX_GENERATED_STEM_LENGTH) || 'test';
|
|
590
|
+
const hash = createHash('sha256')
|
|
591
|
+
.update(`${test.file ?? ''}\0${test.name}`)
|
|
592
|
+
.digest('hex')
|
|
593
|
+
.slice(0, 8);
|
|
594
|
+
return `${stem}-${hash}${ext}`;
|
|
595
|
+
}
|
|
566
596
|
sanitizeFilename(name) {
|
|
567
597
|
return name.replace(/[^a-zA-Z0-9_-]/g, '_').toLowerCase();
|
|
568
598
|
}
|
|
@@ -14,6 +14,8 @@ import type { CoverageSummary, FileCoverage } from './interfaces';
|
|
|
14
14
|
* (or the cwd when none is known), so one file never has two records.
|
|
15
15
|
*/
|
|
16
16
|
export declare function fileCoverageKey(filePath: string, projectRoot?: string): string;
|
|
17
|
+
/** Read the canonical key first, then a measured legacy relative key if present. */
|
|
18
|
+
export declare function fileCoverageLookupKeys(filePath: string, projectRoot?: string): string[];
|
|
17
19
|
export interface CollectedMetrics {
|
|
18
20
|
branch: boolean;
|
|
19
21
|
function: boolean;
|
|
@@ -16,6 +16,12 @@ import * as path from 'path';
|
|
|
16
16
|
export function fileCoverageKey(filePath, projectRoot) {
|
|
17
17
|
return path.isAbsolute(filePath) ? path.normalize(filePath) : path.resolve(projectRoot ?? process.cwd(), filePath);
|
|
18
18
|
}
|
|
19
|
+
/** Read the canonical key first, then a measured legacy relative key if present. */
|
|
20
|
+
export function fileCoverageLookupKeys(filePath, projectRoot) {
|
|
21
|
+
const canonical = `coverage:file:${fileCoverageKey(filePath, projectRoot)}`;
|
|
22
|
+
const legacy = `coverage:file:${filePath}`;
|
|
23
|
+
return canonical === legacy ? [canonical] : [canonical, legacy];
|
|
24
|
+
}
|
|
19
25
|
/** Which optional metrics the files carry. Line coverage is always collected. */
|
|
20
26
|
export function collectedMetrics(files) {
|
|
21
27
|
return {
|
|
@@ -15,6 +15,7 @@ import { toError } from '../../../shared/error-utils.js';
|
|
|
15
15
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
16
16
|
import { getClaudeModelForTier } from '../../../shared/llm/model-registry.js';
|
|
17
17
|
import { measuredCoverageSummary, measuredFileCoverage } from '../../quality-assessment/coverage-report-event.js';
|
|
18
|
+
import { fileCoverageLookupKeys } from '../../coverage-analysis/collected-metrics.js';
|
|
18
19
|
// LLMDefectAnalysis is imported from ../interfaces
|
|
19
20
|
const DEFAULT_CONFIG = {
|
|
20
21
|
defaultThreshold: 0.5,
|
|
@@ -161,7 +162,7 @@ Be specific and actionable. Focus on concrete issues, not generic advice.`,
|
|
|
161
162
|
}
|
|
162
163
|
return null;
|
|
163
164
|
}
|
|
164
|
-
catch
|
|
165
|
+
catch {
|
|
165
166
|
logger.warn('LLM analysis failed, using heuristics only');
|
|
166
167
|
return null;
|
|
167
168
|
}
|
|
@@ -498,7 +499,7 @@ Be specific and actionable. Focus on concrete issues, not generic advice.`,
|
|
|
498
499
|
// Count complexity indicators in code
|
|
499
500
|
const content = fileResult.value;
|
|
500
501
|
const ifCount = (content.match(/\bif\s*\(/g) || []).length;
|
|
501
|
-
const loopCount = (content.match(/\b(for|while|do)\s*[
|
|
502
|
+
const loopCount = (content.match(/\b(for|while|do)\s*[{(]/g) || []).length;
|
|
502
503
|
const switchCount = (content.match(/\bswitch\s*\(/g) || []).length;
|
|
503
504
|
const catchCount = (content.match(/\bcatch\s*\(/g) || []).length;
|
|
504
505
|
const ternaryCount = (content.match(/\?[^?:]+:/g) || []).length;
|
|
@@ -592,10 +593,12 @@ Be specific and actionable. Focus on concrete issues, not generic advice.`,
|
|
|
592
593
|
try {
|
|
593
594
|
// Try per-file coverage (written by coverage-analyzer and test-executor)
|
|
594
595
|
// #1014: only measured records; legacy unstamped estimates are ignored.
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
596
|
+
for (const key of fileCoverageLookupKeys(file)) {
|
|
597
|
+
const fileCoverage = measuredFileCoverage(await this.memory.get(key));
|
|
598
|
+
if (fileCoverage) {
|
|
599
|
+
// Invert: low coverage = high defect risk
|
|
600
|
+
return 1 - fileCoverage.line / 100;
|
|
601
|
+
}
|
|
599
602
|
}
|
|
600
603
|
// Fall back to project-wide coverage
|
|
601
604
|
const summary = measuredCoverageSummary(await this.memory.get('coverage:latest'));
|
|
@@ -56,6 +56,10 @@ export interface GateResult {
|
|
|
56
56
|
checks: GateCheck[];
|
|
57
57
|
overallScore: number;
|
|
58
58
|
failedChecks: string[];
|
|
59
|
+
/** Gate service evidence state; absent for other gate implementations. */
|
|
60
|
+
evidenceStatus?: 'measured' | 'insufficient-evidence';
|
|
61
|
+
/** Configured checks whose input was missing, negative, or non-finite. */
|
|
62
|
+
unmeasured?: string[];
|
|
59
63
|
}
|
|
60
64
|
export interface GateCheck {
|
|
61
65
|
name: string;
|
|
@@ -98,7 +98,7 @@ export declare class InsufficientQualityEvidenceError extends Error {
|
|
|
98
98
|
* Inspect every canonical metric with the same validation, collecting each
|
|
99
99
|
* absent, stale, future-dated or malformed record instead of stopping at the first.
|
|
100
100
|
*/
|
|
101
|
-
export declare function inspectQualityEvidence(memory: MemoryBackend, options?: {
|
|
101
|
+
export declare function inspectQualityEvidence(memory: Pick<MemoryBackend, 'get'>, options?: {
|
|
102
102
|
now?: number;
|
|
103
103
|
maxAgeMs?: number;
|
|
104
104
|
}): Promise<{
|
|
@@ -10,6 +10,7 @@ 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
12
|
import { measuredCoverageSummary, measuredFileCoverage } from '../coverage-report-event.js';
|
|
13
|
+
import { fileCoverageLookupKeys } from '../../coverage-analysis/collected-metrics.js';
|
|
13
14
|
/** Metrics the static analyzer produces when the caller asks for all of them. */
|
|
14
15
|
const ANALYZER_METRICS = ['coverage', 'complexity', 'maintainability', 'duplication', 'testability'];
|
|
15
16
|
/** Metrics computed from parsing each source file. */
|
|
@@ -157,7 +158,7 @@ Focus on:
|
|
|
157
158
|
}
|
|
158
159
|
return null;
|
|
159
160
|
}
|
|
160
|
-
catch
|
|
161
|
+
catch {
|
|
161
162
|
logger.warn('LLM insights generation failed:');
|
|
162
163
|
return null;
|
|
163
164
|
}
|
|
@@ -226,7 +227,7 @@ Focus on:
|
|
|
226
227
|
}
|
|
227
228
|
return null;
|
|
228
229
|
}
|
|
229
|
-
catch
|
|
230
|
+
catch {
|
|
230
231
|
logger.warn('Failed to parse LLM insights response:');
|
|
231
232
|
return null;
|
|
232
233
|
}
|
|
@@ -508,9 +509,10 @@ Focus on:
|
|
|
508
509
|
// 1. Try per-file coverage stored by test executor
|
|
509
510
|
// #1014: only measured records count. Legacy unstamped estimate
|
|
510
511
|
// records (written by <= 3.15.4, never expiring) are ignored.
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
512
|
+
for (const key of fileCoverageLookupKeys(file)) {
|
|
513
|
+
const fileCoverage = measuredFileCoverage(await this.memory.get(key));
|
|
514
|
+
if (fileCoverage)
|
|
515
|
+
return fileCoverage.line;
|
|
514
516
|
}
|
|
515
517
|
// 2. Fall back to project-wide summary from coverage-analyzer
|
|
516
518
|
const summary = measuredCoverageSummary(await this.memory.get('coverage:latest'));
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
6
|
import { ok, err } from '../../../shared/types/index.js';
|
|
7
7
|
import { toError } from '../../../shared/error-utils.js';
|
|
8
|
+
import { isMeasuredMetricValue } from '../evidence-sufficiency.js';
|
|
8
9
|
const DEFAULT_CONFIG = {
|
|
9
10
|
strictMode: false,
|
|
10
11
|
enableWarnings: true,
|
|
@@ -80,6 +81,12 @@ export class QualityGateService {
|
|
|
80
81
|
// Evaluate each threshold
|
|
81
82
|
checks.push(...this.evaluateMinThresholds(metrics, thresholds));
|
|
82
83
|
checks.push(...this.evaluateMaxThresholds(metrics, thresholds));
|
|
84
|
+
if (checks.length === 0) {
|
|
85
|
+
return err(new Error('No thresholds configured for gate evaluation'));
|
|
86
|
+
}
|
|
87
|
+
const unmeasured = checks
|
|
88
|
+
.filter((check) => !isMeasuredMetricValue(check.value))
|
|
89
|
+
.map((check) => check.name);
|
|
83
90
|
// Collect failed checks
|
|
84
91
|
for (const check of checks) {
|
|
85
92
|
if (!check.passed) {
|
|
@@ -89,13 +96,15 @@ export class QualityGateService {
|
|
|
89
96
|
// Calculate overall score (0-100)
|
|
90
97
|
const overallScore = this.calculateOverallScore(checks);
|
|
91
98
|
// Determine pass/fail based on critical checks
|
|
92
|
-
const passed = this.determineGateStatus(checks);
|
|
99
|
+
const passed = unmeasured.length === 0 && this.determineGateStatus(checks);
|
|
93
100
|
const result = {
|
|
94
101
|
gateName,
|
|
95
102
|
passed,
|
|
96
103
|
checks,
|
|
97
104
|
overallScore,
|
|
98
105
|
failedChecks,
|
|
106
|
+
evidenceStatus: unmeasured.length === 0 ? 'measured' : 'insufficient-evidence',
|
|
107
|
+
unmeasured,
|
|
99
108
|
};
|
|
100
109
|
// Store evaluation result in memory
|
|
101
110
|
await this.storeEvaluationResult(result);
|
|
@@ -188,9 +197,9 @@ export class QualityGateService {
|
|
|
188
197
|
return checks;
|
|
189
198
|
}
|
|
190
199
|
createCheck(name, value, threshold, type, severity) {
|
|
191
|
-
const passed = type === 'min'
|
|
200
|
+
const passed = isMeasuredMetricValue(value) && (type === 'min'
|
|
192
201
|
? value >= threshold
|
|
193
|
-
: value <= threshold;
|
|
202
|
+
: value <= threshold);
|
|
194
203
|
return {
|
|
195
204
|
name,
|
|
196
205
|
passed,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency advisory (OSV) engine for the scan-security task (#1049).
|
|
3
|
+
*
|
|
4
|
+
* Runs the security-compliance DependencyScanner on the project's package.json
|
|
5
|
+
* and turns its outcome into an execution receipt. A failed or partial OSV
|
|
6
|
+
* lookup is a failed/partial engine with the unchecked packages listed, never
|
|
7
|
+
* a completed engine with zero findings.
|
|
8
|
+
*/
|
|
9
|
+
import type { SecurityEngineEvidence } from './scan-evidence.js';
|
|
10
|
+
import type { Vulnerability, UncheckedDependency, LocalDependency } from './interfaces.js';
|
|
11
|
+
import type { DependencyScanResult } from './services/scanners/scanner-types.js';
|
|
12
|
+
import type { Result } from '../../shared/types/index.js';
|
|
13
|
+
export declare const DEPENDENCY_ADVISORY_ENGINE_ID = "osv-dependency-advisories";
|
|
14
|
+
/** The dependency scan as reported to MCP and CLI consumers. */
|
|
15
|
+
export interface DependencyScanReport {
|
|
16
|
+
status: 'complete' | 'incomplete' | 'failed' | 'not-run';
|
|
17
|
+
measured: boolean;
|
|
18
|
+
manifest?: string;
|
|
19
|
+
/** Lockfile the checked versions were resolved from, or null (exact specs only). */
|
|
20
|
+
lockfile?: string | null;
|
|
21
|
+
packagesRequested: number;
|
|
22
|
+
packagesChecked: number;
|
|
23
|
+
uncheckedPackages: UncheckedDependency[];
|
|
24
|
+
/** Local workspace / linked packages: not OSV subjects, excluded from the counts. */
|
|
25
|
+
localPackages: LocalDependency[];
|
|
26
|
+
/** Why the scan is not complete beyond individual packages (malformed lockfile, workspace root #1057). */
|
|
27
|
+
resolutionErrors: string[];
|
|
28
|
+
/** Only direct dependencies are checked; transitive dependencies are not. */
|
|
29
|
+
scope: 'direct';
|
|
30
|
+
vulnerabilities: number;
|
|
31
|
+
scanId?: string;
|
|
32
|
+
error?: string;
|
|
33
|
+
/** One plain sentence for humans; says when advisories could not be checked. */
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
export interface DependencyAdvisoryOutcome {
|
|
37
|
+
engine: SecurityEngineEvidence;
|
|
38
|
+
vulnerabilities: Vulnerability[];
|
|
39
|
+
report: DependencyScanReport;
|
|
40
|
+
}
|
|
41
|
+
interface PackageJsonScanner {
|
|
42
|
+
scanPackageJson(packageJsonPath: string): Promise<Result<DependencyScanResult>>;
|
|
43
|
+
}
|
|
44
|
+
/** The package.json for a scan target: the target directory's, else the project root's. */
|
|
45
|
+
export declare function findPackageJson(targetPath: string, env?: NodeJS.ProcessEnv): Promise<string | null>;
|
|
46
|
+
/** Human message for a dependency scan outcome. */
|
|
47
|
+
export declare const DEPENDENCY_SCOPE_NOTE = "direct dependencies of this package.json only; workspace members and transitive dependencies are not checked";
|
|
48
|
+
export declare function dependencyScanMessage(report: Omit<DependencyScanReport, 'message'>): string;
|
|
49
|
+
/** Run the OSV dependency scan for a target and describe it as an engine receipt. */
|
|
50
|
+
export declare function runDependencyAdvisoryScan(scanner: PackageJsonScanner, targetPath: string): Promise<DependencyAdvisoryOutcome>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=dependency-advisory-engine.d.ts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency advisory (OSV) engine for the scan-security task (#1049).
|
|
3
|
+
*
|
|
4
|
+
* Runs the security-compliance DependencyScanner on the project's package.json
|
|
5
|
+
* and turns its outcome into an execution receipt. A failed or partial OSV
|
|
6
|
+
* lookup is a failed/partial engine with the unchecked packages listed, never
|
|
7
|
+
* a completed engine with zero findings.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs/promises';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
export const DEPENDENCY_ADVISORY_ENGINE_ID = 'osv-dependency-advisories';
|
|
12
|
+
/** The package.json for a scan target: the target directory's, else the project root's. */
|
|
13
|
+
export async function findPackageJson(targetPath, env = process.env) {
|
|
14
|
+
let dir = targetPath;
|
|
15
|
+
try {
|
|
16
|
+
if (!(await fs.stat(targetPath)).isDirectory())
|
|
17
|
+
dir = path.dirname(targetPath);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
dir = path.dirname(targetPath);
|
|
21
|
+
}
|
|
22
|
+
const candidates = [dir, env.AQE_PROJECT_ROOT ? path.resolve(env.AQE_PROJECT_ROOT) : null];
|
|
23
|
+
for (const candidate of candidates) {
|
|
24
|
+
if (!candidate)
|
|
25
|
+
continue;
|
|
26
|
+
const manifest = path.join(candidate, 'package.json');
|
|
27
|
+
try {
|
|
28
|
+
if ((await fs.stat(manifest)).isFile())
|
|
29
|
+
return manifest;
|
|
30
|
+
}
|
|
31
|
+
catch { /* try next */ }
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
/** Human message for a dependency scan outcome. */
|
|
36
|
+
export const DEPENDENCY_SCOPE_NOTE = 'direct dependencies of this package.json only; workspace members and transitive dependencies are not checked';
|
|
37
|
+
export function dependencyScanMessage(report) {
|
|
38
|
+
return `${statusMessage(report)} Scope: ${DEPENDENCY_SCOPE_NOTE}.`;
|
|
39
|
+
}
|
|
40
|
+
function statusMessage(report) {
|
|
41
|
+
switch (report.status) {
|
|
42
|
+
case 'complete':
|
|
43
|
+
return report.packagesRequested === 0
|
|
44
|
+
? `No registry dependencies to check${report.localPackages.length ? ` (${report.localPackages.length} local package(s) excluded)` : ' in package.json'}; nothing to check (complete).`
|
|
45
|
+
: `Dependency advisories checked for all ${report.packagesChecked} package(s): ${report.vulnerabilities} advisory finding(s).`;
|
|
46
|
+
case 'incomplete':
|
|
47
|
+
return (report.uncheckedPackages.length > 0
|
|
48
|
+
? `Dependency advisories could not be checked for ${report.uncheckedPackages.length} of ${report.packagesRequested} package(s); ` : '') +
|
|
49
|
+
(report.resolutionErrors.length > 0 ? `${report.resolutionErrors.slice(0, 3).join('; ')}; ` : '') +
|
|
50
|
+
`${report.vulnerabilities} finding(s) from the ${report.packagesChecked} checked package(s). Dependency scan is INCOMPLETE, not clean.`;
|
|
51
|
+
case 'failed':
|
|
52
|
+
return `${report.error ?? `Dependency advisories could not be checked for ${report.uncheckedPackages.length} package(s)`}. ` +
|
|
53
|
+
'Dependency vulnerabilities are UNMEASURED, not zero.';
|
|
54
|
+
default:
|
|
55
|
+
return report.error ?? 'Dependency advisory scan did not run.';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function notRun(reason, manifest) {
|
|
59
|
+
const base = { status: 'not-run', measured: false, ...(manifest ? { manifest } : {}),
|
|
60
|
+
packagesRequested: 0, packagesChecked: 0, uncheckedPackages: [], localPackages: [],
|
|
61
|
+
resolutionErrors: [], scope: 'direct',
|
|
62
|
+
vulnerabilities: 0, error: reason };
|
|
63
|
+
return {
|
|
64
|
+
engine: { id: DEPENDENCY_ADVISORY_ENGINE_ID, requested: true, required: true, status: 'failed', scope: 'parent-directory',
|
|
65
|
+
...(manifest ? { target: manifest } : {}), analyzedFiles: 0, ruleCoverage: 'unknown', errors: [reason], limitations: [] },
|
|
66
|
+
vulnerabilities: [],
|
|
67
|
+
report: { ...base, message: dependencyScanMessage(base) },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Run the OSV dependency scan for a target and describe it as an engine receipt. */
|
|
71
|
+
export async function runDependencyAdvisoryScan(scanner, targetPath) {
|
|
72
|
+
const manifest = await findPackageJson(targetPath);
|
|
73
|
+
if (!manifest)
|
|
74
|
+
return notRun('No package.json found for the dependency advisory scan.');
|
|
75
|
+
let scan;
|
|
76
|
+
try {
|
|
77
|
+
scan = await scanner.scanPackageJson(manifest);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
return notRun(`Dependency advisory scan failed: ${error instanceof Error ? error.message : String(error)}`, manifest);
|
|
81
|
+
}
|
|
82
|
+
if (!scan.success)
|
|
83
|
+
return notRun(`Dependency advisory scan did not run: ${scan.error.message}`, manifest);
|
|
84
|
+
const value = scan.value;
|
|
85
|
+
const unchecked = value.uncheckedPackages.map((p) => `${p.name}@${p.version}: ${p.reason}`);
|
|
86
|
+
const base = {
|
|
87
|
+
status: value.status, measured: value.measured, manifest, lockfile: value.lockfile ?? null,
|
|
88
|
+
packagesRequested: value.packagesScanned, packagesChecked: value.packagesChecked,
|
|
89
|
+
uncheckedPackages: value.uncheckedPackages, localPackages: value.localPackages ?? [],
|
|
90
|
+
resolutionErrors: value.resolutionErrors ?? [], scope: 'direct',
|
|
91
|
+
vulnerabilities: value.vulnerabilities.length,
|
|
92
|
+
scanId: value.scanId, ...(value.error ? { error: value.error } : {}),
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
engine: {
|
|
96
|
+
id: DEPENDENCY_ADVISORY_ENGINE_ID, requested: true, required: true,
|
|
97
|
+
status: value.status === 'complete' ? 'completed' : value.status === 'incomplete' ? 'partial' : 'failed',
|
|
98
|
+
scope: 'parent-directory', target: manifest, ruleCoverage: 'unknown',
|
|
99
|
+
errors: [...(value.error ? [value.error] : []), ...(value.resolutionErrors ?? []), ...unchecked.slice(0, 20),
|
|
100
|
+
...(unchecked.length > 20 ? [`... and ${unchecked.length - 20} more unchecked package(s)`] : [])],
|
|
101
|
+
limitations: [
|
|
102
|
+
value.lockfile
|
|
103
|
+
? `Direct dependencies are checked at the versions ${value.lockfile} resolves (when in sync with package.json); transitive dependencies are not checked.`
|
|
104
|
+
: 'No lockfile: only exact versions in package.json are checked; ranges are reported unchecked. Transitive dependencies are not checked.',
|
|
105
|
+
...((value.localPackages ?? []).length > 0
|
|
106
|
+
? [`${value.localPackages.length} local workspace/linked package(s) are not OSV subjects and were excluded.`] : []),
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
vulnerabilities: value.vulnerabilities,
|
|
110
|
+
report: { ...base, message: dependencyScanMessage(base) },
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=dependency-advisory-engine.js.map
|