agentic-qe 3.15.4 → 3.15.5
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 +70 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/bridge/captured-experience-bridge.js +7 -9
- package/dist/cli/bundle.js +5 -5
- package/dist/cli/chunks/adapter-EGIPTX5H.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-MHJBRXMK.js → agent-booster-wasm-CCTTGCQS.js} +2 -2
- package/dist/cli/chunks/{agent-handler-G64SD7J2.js → agent-handler-DHYUF3NX.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-G4UXFPKH.js → agent-memory-branch-642W7CYX.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-WP4GCBDT.js +2 -0
- package/dist/cli/chunks/{arena-QJMKYPHS.js → arena-MUCC7UUN.js} +4 -4
- package/dist/cli/chunks/{arena-63M3M6EW.js → arena-NW2JVAFY.js} +2 -2
- package/dist/cli/chunks/{audit-UDFVTWSX.js → audit-VKQTZJAA.js} +3 -3
- package/dist/cli/chunks/base-6ORFD62I.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-JLX2G56I.js → better-sqlite3-7ZUFVWLQ.js} +2 -2
- package/dist/cli/chunks/{brain-handler-PWF32LLW.js → brain-handler-7LKAWSBI.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-PB7QWXDP.js → branch-enumerator-HUNXJKM4.js} +2 -2
- package/dist/cli/chunks/{browser-CYNV2F3U.js → browser-ZSZEYUDP.js} +2 -2
- package/dist/cli/chunks/browser-workflow-PIXGERWP.js +2 -0
- package/dist/cli/chunks/{chunk-RWZ4F44Y.js → chunk-2KWI3MT3.js} +2 -2
- package/dist/cli/chunks/{chunk-UORI2CZ4.js → chunk-2WFTZSRT.js} +1 -1
- package/dist/cli/chunks/{chunk-HCDTLV5J.js → chunk-2XYTS2WY.js} +2 -2
- package/dist/cli/chunks/{chunk-DBIK4OFX.js → chunk-35MDATQE.js} +1 -1
- package/dist/cli/chunks/{chunk-54XTJBHV.js → chunk-3AYYGR6W.js} +1 -1
- package/dist/cli/chunks/{chunk-SJB4KMZS.js → chunk-3DTEQHFB.js} +3 -3
- package/dist/cli/chunks/{chunk-RG67RZIX.js → chunk-3OAQPN2N.js} +2 -2
- package/dist/cli/chunks/{chunk-2DRMTRBM.js → chunk-3QD7U3FY.js} +2 -2
- package/dist/cli/chunks/{chunk-VMSO6DMF.js → chunk-3SH23PS3.js} +2 -2
- package/dist/cli/chunks/{chunk-RJ5CZ7B6.js → chunk-3YASZPLO.js} +2 -2
- package/dist/cli/chunks/{chunk-JFQDWAU3.js → chunk-3YNP33GB.js} +2 -2
- package/dist/cli/chunks/{chunk-I53365HG.js → chunk-47GEI2LT.js} +3 -3
- package/dist/cli/chunks/{chunk-PCWZCXBD.js → chunk-4AZP7ZCW.js} +2 -2
- package/dist/cli/chunks/{chunk-54ITMOFM.js → chunk-4PT5KNXL.js} +4 -4
- package/dist/cli/chunks/{chunk-SIUUAKCE.js → chunk-4UXPDV7E.js} +1 -1
- package/dist/cli/chunks/{chunk-LZSLJJII.js → chunk-4XSCZVON.js} +2 -2
- package/dist/cli/chunks/{chunk-DFJGXXCL.js → chunk-5BOZCMXZ.js} +1 -1
- package/dist/cli/chunks/{chunk-B7J3O2WM.js → chunk-644DFAGS.js} +1 -1
- package/dist/cli/chunks/{chunk-2ICC4H6K.js → chunk-663ZFPUL.js} +2 -2
- package/dist/cli/chunks/{chunk-YUWUFYHK.js → chunk-6JFGB2JB.js} +1 -1
- package/dist/cli/chunks/{chunk-MBV57LKC.js → chunk-6LG5UEQE.js} +2 -2
- package/dist/cli/chunks/{chunk-LRTF5RMG.js → chunk-6UYN5PHA.js} +4 -4
- package/dist/cli/chunks/{chunk-5SS2Z7JC.js → chunk-6ZIDZ4TJ.js} +2 -2
- package/dist/cli/chunks/{chunk-2534PXIV.js → chunk-7BIYJRQJ.js} +2 -2
- package/dist/cli/chunks/{chunk-HX5KQK7I.js → chunk-7EZLOC4K.js} +2 -2
- package/dist/cli/chunks/{chunk-ZAOQIVHG.js → chunk-7YB2KELI.js} +2 -2
- package/dist/cli/chunks/{chunk-SOSJFEFB.js → chunk-A2WOQO2N.js} +2 -2
- package/dist/cli/chunks/{chunk-M6SJALLA.js → chunk-A337MD3C.js} +2 -2
- package/dist/cli/chunks/{chunk-YZ2AGC7O.js → chunk-A5J4XJS6.js} +1 -1
- package/dist/cli/chunks/{chunk-PEA4DVXW.js → chunk-AQN5EDBM.js} +1 -1
- package/dist/cli/chunks/{chunk-EGHK6NMH.js → chunk-AUZXRFOX.js} +2 -2
- package/dist/cli/chunks/{chunk-BBKLVHDQ.js → chunk-B2UHTA4Q.js} +1 -1
- package/dist/cli/chunks/{chunk-LY53L6NH.js → chunk-BBL6YXD3.js} +2 -2
- package/dist/cli/chunks/chunk-BJ5P4IV2.js +2 -0
- package/dist/cli/chunks/{chunk-I43QRLLB.js → chunk-BMWAWZAN.js} +2 -2
- package/dist/cli/chunks/chunk-BO4PKNYP.js +102 -0
- package/dist/cli/chunks/{chunk-PMXWDTDK.js → chunk-BY646JOM.js} +2 -2
- package/dist/cli/chunks/{chunk-OFQDM73J.js → chunk-BYXNHGQC.js} +2 -2
- package/dist/cli/chunks/{chunk-73MTUM6F.js → chunk-BZFT4QDQ.js} +2 -2
- package/dist/cli/chunks/{chunk-RA3MI5WK.js → chunk-CFPR24YK.js} +2 -2
- package/dist/cli/chunks/{chunk-WEDVLKRB.js → chunk-CQMHDAJS.js} +2 -2
- package/dist/cli/chunks/{chunk-HFSBONCS.js → chunk-CR2JUANW.js} +2 -2
- package/dist/cli/chunks/{chunk-BY3IL56R.js → chunk-CXOXUBYU.js} +1 -1
- package/dist/cli/chunks/{chunk-AOKSLWON.js → chunk-D3G2NN7F.js} +77 -78
- package/dist/cli/chunks/{chunk-I5A3HGO6.js → chunk-DEGWCUMY.js} +2 -2
- package/dist/cli/chunks/{chunk-CQ3WSTJ2.js → chunk-DFPL5N3Q.js} +2 -2
- package/dist/cli/chunks/{chunk-TVQPYP2Z.js → chunk-DL5JENWD.js} +3 -3
- package/dist/cli/chunks/{chunk-V3NZ23X6.js → chunk-DLY4YEN3.js} +2 -2
- package/dist/cli/chunks/{chunk-HEKCN5XQ.js → chunk-DPV33C77.js} +2 -2
- package/dist/cli/chunks/{chunk-KOLHZSEC.js → chunk-DPYDUKVZ.js} +2 -2
- package/dist/cli/chunks/{chunk-3MSBVOYW.js → chunk-DTJODGCE.js} +2 -2
- package/dist/cli/chunks/{chunk-MGH4XIHH.js → chunk-DWZI3IVB.js} +2 -2
- package/dist/cli/chunks/{chunk-DPL4ZXTE.js → chunk-DXVZBJE4.js} +1 -1
- package/dist/cli/chunks/{chunk-LXYTC62V.js → chunk-E4VIVMDL.js} +2 -2
- package/dist/cli/chunks/{chunk-DVE5SM5G.js → chunk-EAYQCBXL.js} +3 -3
- package/dist/cli/chunks/{chunk-BY5PLEPZ.js → chunk-EOR3RECZ.js} +2 -2
- package/dist/cli/chunks/chunk-ERGWWI4Y.js +3 -0
- package/dist/cli/chunks/{chunk-LPSE6DOQ.js → chunk-EUEHBERE.js} +1 -1
- package/dist/cli/chunks/{chunk-3BDDOFYW.js → chunk-EVCFUYYK.js} +2 -2
- package/dist/cli/chunks/{chunk-SZWXUG36.js → chunk-FBEXG4HD.js} +2 -2
- package/dist/cli/chunks/{chunk-5GWTJJEO.js → chunk-FE3AIZI6.js} +1 -1
- package/dist/cli/chunks/{chunk-4GLR2S2M.js → chunk-FHUJCVT3.js} +2 -2
- package/dist/cli/chunks/{chunk-6TMUZGM2.js → chunk-FNAYDITO.js} +1 -1
- package/dist/cli/chunks/{chunk-U2E5F3VZ.js → chunk-FQKEZVN6.js} +2 -2
- package/dist/cli/chunks/{chunk-2LL35V3A.js → chunk-FWYJ6UDX.js} +2 -2
- package/dist/cli/chunks/{chunk-ISASRHZP.js → chunk-GGDKOJVF.js} +2 -2
- package/dist/cli/chunks/{chunk-ZKXZTIVF.js → chunk-GKPRECLL.js} +2 -2
- package/dist/cli/chunks/{chunk-OHH6BUZK.js → chunk-GRIPCYW5.js} +1 -1
- package/dist/cli/chunks/{chunk-XZ5Z56OP.js → chunk-GTSOFCMQ.js} +1 -1
- package/dist/cli/chunks/{chunk-2MU4WCMQ.js → chunk-HBYQYGXP.js} +2 -2
- package/dist/cli/chunks/{chunk-YQ6BK7QC.js → chunk-HGBJ2QQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-N6CRIUTO.js → chunk-HIUNCO2W.js} +2 -2
- package/dist/cli/chunks/{chunk-5H7MR6HP.js → chunk-HLFDC4SF.js} +1 -1
- package/dist/cli/chunks/{chunk-GAXTPQCZ.js → chunk-HPLMX62I.js} +2 -2
- package/dist/cli/chunks/{chunk-WO4NSPLX.js → chunk-IHFUEPZH.js} +2 -2
- package/dist/cli/chunks/{chunk-ADF6LGHZ.js → chunk-IJ2EXSMO.js} +2 -2
- package/dist/cli/chunks/{chunk-GLKLEHK3.js → chunk-IJOFZBXD.js} +2 -2
- package/dist/cli/chunks/{chunk-IKWAPHJA.js → chunk-JANLATHN.js} +2 -2
- package/dist/cli/chunks/{chunk-J3RNVHDH.js → chunk-JCC7QEKZ.js} +1 -1
- package/dist/cli/chunks/{chunk-C5EN5WB6.js → chunk-JI77KJP7.js} +1 -1
- package/dist/cli/chunks/{chunk-B7GJXQD2.js → chunk-JNMUVBAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZP6ANUP7.js → chunk-JYY7AYGA.js} +1 -1
- package/dist/cli/chunks/{chunk-6HTO4BLV.js → chunk-KHCALIFP.js} +2 -2
- package/dist/cli/chunks/{chunk-BND6M2JX.js → chunk-KJ3KBP24.js} +2 -2
- package/dist/cli/chunks/{chunk-O7TMY4GS.js → chunk-KZVJW2SD.js} +2 -2
- package/dist/cli/chunks/chunk-L336HFFE.js +2 -0
- package/dist/cli/chunks/{chunk-W3PPYNHF.js → chunk-L375O3CZ.js} +2 -2
- package/dist/cli/chunks/{chunk-PJAXWCFC.js → chunk-L6SVCNXK.js} +1 -1
- package/dist/cli/chunks/{chunk-VAXQUD5G.js → chunk-LNO5IWGH.js} +1 -1
- package/dist/cli/chunks/{chunk-CFXFGQEN.js → chunk-LRASYSGV.js} +2 -2
- package/dist/cli/chunks/{chunk-MVTUFPM2.js → chunk-MB4VFAJC.js} +2 -2
- package/dist/cli/chunks/{chunk-SCL2OYN7.js → chunk-MNQ36MAF.js} +2 -2
- package/dist/cli/chunks/{chunk-W6TJXK5Y.js → chunk-MQGEZA2A.js} +2 -2
- package/dist/cli/chunks/{chunk-73PCVMGA.js → chunk-MS3Z2CP5.js} +2 -2
- package/dist/cli/chunks/{chunk-WI5AEB7Q.js → chunk-N2TJNIHA.js} +2 -2
- package/dist/cli/chunks/{chunk-DEJM2P5K.js → chunk-NF6AFIAX.js} +1 -1
- package/dist/cli/chunks/{chunk-JL3TI43V.js → chunk-NLDFNAOS.js} +2 -2
- package/dist/cli/chunks/{chunk-UK5HY6LC.js → chunk-NMJVG22Z.js} +1 -1
- package/dist/cli/chunks/{chunk-WW6WUMS7.js → chunk-OGYWWZU7.js} +2 -2
- package/dist/cli/chunks/{chunk-3C2BFLYC.js → chunk-ONCH5AXU.js} +3 -3
- package/dist/cli/chunks/{chunk-OG4KHX7S.js → chunk-OQDC7GCM.js} +2 -2
- package/dist/cli/chunks/{chunk-3ZIVBTX6.js → chunk-ORTBRO7F.js} +2 -2
- package/dist/cli/chunks/{chunk-NIJMLEAX.js → chunk-OU4ZAWCC.js} +2 -2
- package/dist/cli/chunks/{chunk-FDK2GF4G.js → chunk-OW42F2TX.js} +2 -2
- package/dist/cli/chunks/{chunk-TB22Y3WW.js → chunk-PCCIZFD7.js} +1 -1
- package/dist/cli/chunks/{chunk-BZWZTGMF.js → chunk-PDPEMBFV.js} +2 -2
- package/dist/cli/chunks/{chunk-D7RVZ5C2.js → chunk-PHAQWAEV.js} +2 -2
- package/dist/cli/chunks/{chunk-P7GM3EE7.js → chunk-PHP4UJYP.js} +1 -1
- package/dist/cli/chunks/{chunk-6QPW4OVH.js → chunk-PURHGLEC.js} +1 -1
- package/dist/cli/chunks/{chunk-BPGFCUDO.js → chunk-PVAE65B4.js} +1 -1
- package/dist/cli/chunks/{chunk-7X2IVMXN.js → chunk-QPV3OKX2.js} +2 -2
- package/dist/cli/chunks/{chunk-DAYMT7TH.js → chunk-QXY3IRBW.js} +3 -3
- package/dist/cli/chunks/{chunk-QIAX3JJB.js → chunk-RCXMUEZN.js} +2 -2
- package/dist/cli/chunks/{chunk-RB2SL5GD.js → chunk-RMJ7PJOS.js} +2 -2
- package/dist/cli/chunks/{chunk-FRBCX46J.js → chunk-RUJLVJDE.js} +2 -2
- package/dist/cli/chunks/{chunk-S5D3HCGN.js → chunk-RUSLEOMC.js} +2 -2
- package/dist/cli/chunks/chunk-SAPIRK2G.js +3 -0
- package/dist/cli/chunks/{chunk-A4OPQJ4A.js → chunk-SDWMLT7B.js} +5 -5
- package/dist/cli/chunks/{chunk-RJMBHZYL.js → chunk-SEZLYRCS.js} +1 -1
- package/dist/cli/chunks/{chunk-AHVN3UQZ.js → chunk-TDLKXLJC.js} +2 -2
- package/dist/cli/chunks/{chunk-EWUFVWRT.js → chunk-U4TV75AC.js} +2 -2
- package/dist/cli/chunks/{chunk-X5S5UEM6.js → chunk-U6OVPMQX.js} +2 -2
- package/dist/cli/chunks/{chunk-5B5D5KCV.js → chunk-UE22ODHN.js} +1 -1
- package/dist/cli/chunks/{chunk-I6E4X3L3.js → chunk-UXZEVIFX.js} +1 -1
- package/dist/cli/chunks/{chunk-DF4Y3HPO.js → chunk-V7GNUVYI.js} +1 -1
- package/dist/cli/chunks/{chunk-OOK6GPJR.js → chunk-VCKDVOPD.js} +2 -2
- package/dist/cli/chunks/{chunk-G3ZUB3HD.js → chunk-VH3EB6ZG.js} +2 -2
- package/dist/cli/chunks/{chunk-PB2WSCBW.js → chunk-VLOIEVER.js} +3 -3
- package/dist/cli/chunks/{chunk-7INP6HZH.js → chunk-VML4SG3X.js} +3 -3
- package/dist/cli/chunks/{chunk-K2VUYRMG.js → chunk-VRJPH3LG.js} +2 -2
- package/dist/cli/chunks/{chunk-RI4JPBZD.js → chunk-VYDNLQJN.js} +2 -2
- package/dist/cli/chunks/{chunk-35A22AUL.js → chunk-W3ZGNNDV.js} +1 -1
- package/dist/cli/chunks/{chunk-R47LNH5W.js → chunk-WC47GICZ.js} +2 -2
- package/dist/cli/chunks/{chunk-Z56QTRRB.js → chunk-WLIYWBQR.js} +2 -2
- package/dist/cli/chunks/{chunk-ZURYZEHX.js → chunk-WN55MNZ2.js} +2 -2
- package/dist/cli/chunks/chunk-WOZIXXY5.js +7 -0
- package/dist/cli/chunks/{chunk-NBMQOP2R.js → chunk-WR64BKUE.js} +1 -1
- package/dist/cli/chunks/{chunk-T3BMCEQR.js → chunk-WT3JC4A6.js} +2 -2
- package/dist/cli/chunks/{chunk-WYO5VN2L.js → chunk-X52TMBHU.js} +1 -1
- package/dist/cli/chunks/{chunk-6EHVPFHW.js → chunk-XIE7OHML.js} +1 -1
- package/dist/cli/chunks/{chunk-LOLAEDZD.js → chunk-XNEEYXR2.js} +2 -2
- package/dist/cli/chunks/{chunk-EY5IUF7U.js → chunk-XNHB6TLC.js} +2 -2
- package/dist/cli/chunks/{chunk-GJVRQBLI.js → chunk-XQRE2HWM.js} +2 -2
- package/dist/cli/chunks/{chunk-33IUCP34.js → chunk-Y2E3IJ53.js} +2 -2
- package/dist/cli/chunks/{chunk-6HO3XRXE.js → chunk-Y2WMPEUP.js} +2 -2
- package/dist/cli/chunks/{chunk-LGA6J4I4.js → chunk-Y7GPLOXB.js} +2 -2
- package/dist/cli/chunks/{chunk-76PRW2KY.js → chunk-YINFES3E.js} +2 -2
- package/dist/cli/chunks/{chunk-LJRZAALA.js → chunk-ZLBBX24Q.js} +133 -133
- package/dist/cli/chunks/{chunk-ASKPTGUU.js → chunk-ZT3GUYM5.js} +2 -2
- package/dist/cli/chunks/{chunk-XHCCH7UC.js → chunk-ZTC5FBL6.js} +3 -3
- package/dist/cli/chunks/ci-KP4GZKJ7.js +81 -0
- package/dist/cli/chunks/ci-config-XDDZOOEI.js +2 -0
- package/dist/cli/chunks/{ci-output-BMJABAEX.js → ci-output-7ZUQI4U6.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-GYD5CMJQ.js → circuit-breaker-ALXKCFAL.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-MMOYVBVD.js → claude-flow-setup-RL7K2NI2.js} +2 -2
- package/dist/cli/chunks/client-C3KHVRM6.js +2 -0
- package/dist/cli/chunks/{cline-installer-B2SOZ44R.js → cline-installer-2Z2QQKC3.js} +2 -2
- package/dist/cli/chunks/{code-V3FIRAXD.js → code-QSZTDINQ.js} +4 -4
- package/dist/cli/chunks/{code-index-extractor-CV6A756Z.js → code-index-extractor-5CGR5D3Y.js} +2 -2
- package/dist/cli/chunks/{codex-installer-EUC6J47Y.js → codex-installer-7JLSEDE5.js} +2 -2
- package/dist/cli/chunks/{completions-DQQIBAHR.js → completions-U4NBSXEB.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-HPXMXP5I.js → complexity-analyzer-WYZD2YSY.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-RCIYXH6V.js → continuedev-installer-UPXINJFT.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-VUH32SHF.js → copilot-installer-WIVYQRIF.js} +2 -2
- package/dist/cli/chunks/core-handlers-KSQM6Q6S.js +2 -0
- package/dist/cli/chunks/{cost-tracker-YLCKLOAL.js → cost-tracker-RIN4JDDM.js} +2 -2
- package/dist/cli/chunks/coverage-SPFVHRRU.js +43 -0
- package/dist/cli/chunks/coverage-target-GSRBNHXE.js +2 -0
- package/dist/cli/chunks/cross-domain-router-CTGNOVCF.js +2 -0
- package/dist/cli/chunks/{cursor-installer-B42FN62K.js → cursor-installer-POM7NGCC.js} +2 -2
- package/dist/cli/chunks/{daemon-DECQRQII.js → daemon-HFGKQ6LB.js} +3 -3
- package/dist/cli/chunks/{daemon-IPTOSCHM.js → daemon-M5TD5Y6T.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-RY7CDYSC.js → dag-attention-scheduler-HJXM7Q5P.js} +2 -2
- package/dist/cli/chunks/{detect-NW53BMJN.js → detect-XKQGLZYN.js} +2 -2
- package/dist/cli/chunks/{dist-node-LE6KHXAB.js → dist-node-SSKB53QL.js} +2 -2
- package/dist/cli/chunks/{domain-handler-JGXFT4LW.js → domain-handler-6BNDHATU.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-GY3RYKKK.js → domain-plugins-DOX54YE3.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-CGBRXNTC.js → domain-transfer-FW4ZX3Z7.js} +2 -2
- package/dist/cli/chunks/dream-MIK2E4UL.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-65H4XHWR.js → embed-and-insert-pattern-QST77T2B.js} +2 -2
- package/dist/cli/chunks/{eval-YPYIZQUR.js → eval-K7E4XXBS.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-4JXVF5PL.js → experience-capture-middleware-X66IYSRV.js} +3 -3
- package/dist/cli/chunks/{fast-paths-HYQTAF2S.js → fast-paths-5JXXTYAG.js} +2 -2
- package/dist/cli/chunks/{feature-flags-HNSAFFX2.js → feature-flags-2CR3CO23.js} +2 -2
- package/dist/cli/chunks/{feature-flags-YACUH6OW.js → feature-flags-RB72LHOJ.js} +2 -2
- package/dist/cli/chunks/{file-discovery-R73BYEXB.js → file-discovery-3NHRUQQB.js} +2 -2
- package/dist/cli/chunks/{fleet-6M3BP4OO.js → fleet-SDU7QEOA.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-QLD7KHXV.js → gnn-wrapper-AWCFODUV.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-EZP333X4.js → heartbeat-handler-A4PJ3NFP.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-OCKRACUW.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-X67XG73C.js +2 -0
- package/dist/cli/chunks/hnsw-index-I7KCQBQR.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-47CUCSAU.js → hnsw-legacy-bridge-KRS7SSFM.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-SVNYDJZH.js → hnswlib-node-OGGCPKPO.js} +2 -2
- package/dist/cli/chunks/{hooks-6V5LMWP6.js → hooks-XNRNMUBW.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-FOUHTKAK.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-L2FOBIFF.js → hypergraph-engine-X35LTXYT.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-DU6Z57EE.js → hypergraph-handler-M6THKAG6.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-GXYVX46O.js +2 -0
- package/dist/cli/chunks/{init-handler-HETPWU67.js → init-handler-2AXMXHYF.js} +6 -6
- package/dist/cli/chunks/init-wizard-C2MRX2QG.js +2 -0
- package/dist/cli/chunks/kernel-Q2IUDIDC.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-NHKYGJ7Q.js → kilocode-installer-TEPR2ZJD.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-24UK6GGR.js → kiro-installer-RUKHGDEE.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-E2Z6K5EE.js +2 -0
- package/dist/cli/chunks/{learning-QLVRZNHT.js → learning-BEA26RNA.js} +3 -3
- package/dist/cli/chunks/{llm-router-XRMI2VMG.js → llm-router-7GECMDCP.js} +4 -4
- package/dist/cli/chunks/llm-router-service-YATYFEDD.js +2 -0
- package/dist/cli/chunks/{load-W5UWL5C7.js → load-NTJ4Y4ZR.js} +2 -2
- package/dist/cli/chunks/load-test-LV77JXWA.js +2 -0
- package/dist/cli/chunks/{mcp-N7ALQ4BL.js → mcp-4335GTTG.js} +2 -2
- package/dist/cli/chunks/{memory-WV52DLSA.js → memory-HYC4M4XS.js} +5 -5
- package/dist/cli/chunks/memory-backend-XME3X3QX.js +2 -0
- package/dist/cli/chunks/memory-handlers-VG47X5DX.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-3FVTZCSO.js → multi-model-executor-T7FYKM6T.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-NTPWGHUW.js → opencode-installer-3USXVT5M.js} +2 -2
- package/dist/cli/chunks/{orchestrator-ORGJ6VAA.js → orchestrator-VHUXUYIM.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-TAXMLENP.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-WWXHUH5U.js → pattern-usage-recorder-CMZLPX2K.js} +2 -2
- package/dist/cli/chunks/{pipeline-ZOKZFXTH.js → pipeline-BTRZOVSL.js} +2 -2
- package/dist/cli/chunks/{platform-CDNL322F.js → platform-2MCRKC25.js} +2 -2
- package/dist/cli/chunks/{plugin-ZVLFNZZ4.js → plugin-2VAYWAO3.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-FVJDU2JY.js → prime-radiant-advanced-wasm-TXFEMBP6.js} +2 -2
- package/dist/cli/chunks/{project-root-UCHQH3QL.js → project-root-CFFPBGPX.js} +2 -2
- package/dist/cli/chunks/protocol-executor-ML76QAVQ.js +2 -0
- package/dist/cli/chunks/{protocol-handler-4YBN5R23.js → protocol-handler-DZ26OYVZ.js} +2 -2
- package/dist/cli/chunks/{prove-BHDHY664.js → prove-QWONEJWX.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-LUZH6RYV.js +2 -0
- package/dist/cli/chunks/quality-WFH54FY7.js +8 -0
- package/dist/cli/chunks/{quality-gate-WANE7TCN.js → quality-gate-ONJB7XU7.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-EWXNIXB6.js +2 -0
- package/dist/cli/chunks/{real-embeddings-56MNGJGJ.js → real-embeddings-GZV4VKK4.js} +2 -2
- package/dist/cli/chunks/{ref-validation-S7UWXQIP.js → ref-validation-HW5Y55ZC.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-TEYOQYL6.js → roocode-installer-5OABDNZT.js} +2 -2
- package/dist/cli/chunks/router-MXOBVEBF.js +2 -0
- package/dist/cli/chunks/routing-feedback-T6CCRUEK.js +2 -0
- package/dist/cli/chunks/{routing-handler-KDTLMRWD.js → routing-handler-CVHVOQTC.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-AOUDXCYE.js → ruvector-commands-KKDKFGIQ.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-WHXVT3V3.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-JFPWIRCG.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-V74MVBHS.js → rvf-migration-coordinator-D4KUBNRZ.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-KOXR7TJL.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-QI47Y354.js → rvf-store-integrity-UGUXKIFX.js} +2 -2
- package/dist/cli/chunks/safe-db-CI6IPSIN.js +2 -0
- package/dist/cli/chunks/schedule-X4HW6TVJ.js +2 -0
- package/dist/cli/chunks/scheduler-KCNJ2ON3.js +2 -0
- package/dist/cli/chunks/{security-SN6MWOJT.js → security-7723AZZ4.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-2LB56LP4.js → shared-rvf-adapter-KEQ5CLNI.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-WU7PFKQM.js → shared-rvf-dual-writer-ZSHYG5IA.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-PGHU6VUR.js +2 -0
- package/dist/cli/chunks/{standalone-memory-F6FSRFWC.js → standalone-memory-MHZEEYMK.js} +2 -2
- package/dist/cli/chunks/{status-handler-DHD5MS4G.js → status-handler-JKXPJ22K.js} +2 -2
- package/dist/cli/chunks/{structural-health-P6HPSQMR.js → structural-health-J4RKCYWF.js} +2 -2
- package/dist/cli/chunks/{sync-SNAXAVCN.js → sync-EFWXMA2H.js} +2 -2
- package/dist/cli/chunks/{sync-LISJGDSE.js → sync-PDPORHVN.js} +2 -2
- package/dist/cli/chunks/{task-handler-ZT44NT5Z.js → task-handler-VERADM44.js} +2 -2
- package/dist/cli/chunks/{task-handlers-R6DQ5324.js → task-handlers-4RUCWUR2.js} +3 -3
- package/dist/cli/chunks/{test-MUFHR4JQ.js → test-DMBJFQNL.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-TAUSLZJP.js → test-scheduling-LUPTVGCD.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-UGRH7OPU.js → token-bootstrap-S346YBVO.js} +2 -2
- package/dist/cli/chunks/{token-usage-IX65ECBR.js → token-usage-VOA34IKM.js} +2 -2
- package/dist/cli/chunks/{transformers-QKPSVW2W.js → transformers-GU4TYAN5.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-Z7PPA2JO.js → tree-sitter-wasm-parser-MZPXAH7C.js} +2 -2
- package/dist/cli/chunks/{types-ULNNGGGH.js → types-K4FLXR2K.js} +2 -2
- package/dist/cli/chunks/unified-memory-6CK3TUNQ.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-A7BWBGYN.js +2 -0
- package/dist/cli/chunks/unified-persistence-GEPMDBQZ.js +2 -0
- package/dist/cli/chunks/{upgrade-ECI3YUYA.js → upgrade-M3ATDRMK.js} +2 -2
- package/dist/cli/chunks/{validate-3JKRUW2S.js → validate-AAP773B3.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-LZWANCIE.js → validate-swarm-7RGAZX5F.js} +2 -2
- package/dist/cli/chunks/visual-security-L4J7LQWT.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-N5V4A6XG.js → web-tree-sitter-GQMRHGGI.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-5TBM5B3C.js → windsurf-installer-HG6HF2GF.js} +2 -2
- package/dist/cli/chunks/witness-chain-CDUMX623.js +2 -0
- package/dist/cli/chunks/{witness-chain-MFP3HBWQ.js → witness-chain-WKU3ZIBQ.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-5QWRFVUK.js → witness-chain-repair-WNYH6O4L.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-SRAT7LVY.js → witness-chain-verifier-Q2KW3QEQ.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-FYZXQTLJ.js → witness-key-manager-NQ5DAAC4.js} +2 -2
- package/dist/cli/chunks/{workflow-M7TUYYXY.js → workflow-CX6SHFBW.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-USJDWVDR.js +2 -0
- package/dist/cli/chunks/{wrappers-COU73OQ6.js → wrappers-CZDI6Z3X.js} +2 -2
- package/dist/cli/commands/ci.js +14 -6
- package/dist/cli/commands/code.js +1 -0
- package/dist/cli/commands/coverage.d.ts +28 -0
- package/dist/cli/commands/coverage.js +258 -143
- package/dist/cli/commands/quality.d.ts +12 -1
- package/dist/cli/commands/quality.js +51 -3
- package/dist/cli/utils/ci-output.d.ts +14 -4
- package/dist/cli/utils/ci-output.js +21 -4
- package/dist/cli/utils/coverage-data.d.ts +7 -0
- package/dist/cli/utils/coverage-data.js +21 -27
- package/dist/contracts/verdicts.d.ts +14 -0
- package/dist/contracts/verdicts.js +44 -3
- package/dist/coordination/handlers/coverage-handlers.js +121 -120
- package/dist/coordination/handlers/coverage-runner.d.ts +121 -0
- package/dist/coordination/handlers/coverage-runner.js +367 -0
- package/dist/coordination/handlers/coverage-target.d.ts +144 -0
- package/dist/coordination/handlers/coverage-target.js +311 -0
- package/dist/coordination/handlers/handler-utils.d.ts +9 -0
- package/dist/coordination/handlers/handler-utils.js +44 -1
- package/dist/coordination/handlers/quality-handlers.js +101 -15
- package/dist/coordination/result-saver.js +17 -3
- package/dist/coordination/task-executor.d.ts +5 -0
- package/dist/coordination/task-executor.js +7 -0
- package/dist/domains/code-intelligence/coordinator.d.ts +2 -1
- package/dist/domains/code-intelligence/coordinator.js +10 -32
- package/dist/domains/code-intelligence/interfaces.d.ts +5 -0
- package/dist/domains/code-intelligence/plugin.js +1 -0
- package/dist/domains/code-intelligence/project-root-resolver.d.ts +50 -0
- package/dist/domains/code-intelligence/project-root-resolver.js +121 -0
- package/dist/domains/coverage-analysis/coordinator.js +4 -1
- package/dist/domains/coverage-analysis/interfaces.d.ts +15 -0
- package/dist/domains/coverage-analysis/plugin.js +7 -1
- package/dist/domains/coverage-analysis/services/coverage-analyzer.d.ts +7 -0
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +29 -9
- package/dist/domains/quality-assessment/coordinator-claim-verifier.js +2 -1
- package/dist/domains/quality-assessment/coordinator.js +8 -8
- package/dist/domains/quality-assessment/coverage-report-event.d.ts +25 -0
- package/dist/domains/quality-assessment/coverage-report-event.js +36 -0
- package/dist/domains/quality-assessment/evidence-sufficiency.d.ts +57 -0
- package/dist/domains/quality-assessment/evidence-sufficiency.js +97 -0
- package/dist/domains/quality-assessment/index.d.ts +1 -1
- package/dist/domains/quality-assessment/index.js +1 -1
- package/dist/domains/quality-assessment/plugin.js +8 -8
- package/dist/domains/quality-assessment/quality-evidence.d.ts +50 -2
- package/dist/domains/quality-assessment/quality-evidence.js +90 -8
- package/dist/domains/quality-assessment/services/quality-analyzer.js +13 -9
- package/dist/mcp/bundle.js +456 -451
- package/dist/mcp/handlers/domain-handler-configs.d.ts +18 -1
- package/dist/mcp/handlers/domain-handler-configs.js +42 -4
- package/dist/mcp/handlers/handler-factory.js +3 -0
- package/dist/mcp/handlers/wrapped-domain-handlers.js +7 -1
- package/dist/mcp/protocol-server.js +3 -2
- package/dist/mcp/tools/coverage-analysis/index.js +1 -0
- package/dist/mcp/types.d.ts +6 -0
- package/dist/shared/events/domain-events.d.ts +2 -0
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-T54G3TBK.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-HLCJJ3JM.js +0 -2
- package/dist/cli/chunks/base-VLD755UU.js +0 -2
- package/dist/cli/chunks/browser-workflow-6M6VLWRF.js +0 -2
- package/dist/cli/chunks/chunk-5XXLWJU7.js +0 -2
- package/dist/cli/chunks/chunk-HEDLZWPM.js +0 -96
- package/dist/cli/chunks/chunk-XKIFNKHV.js +0 -2
- package/dist/cli/chunks/chunk-ZF5JTQEE.js +0 -4
- package/dist/cli/chunks/ci-NGMGB43T.js +0 -82
- package/dist/cli/chunks/client-FUHNNK5O.js +0 -2
- package/dist/cli/chunks/core-handlers-F7TLX4LM.js +0 -2
- package/dist/cli/chunks/coverage-IVKDV236.js +0 -27
- package/dist/cli/chunks/cross-domain-router-EGWPY67O.js +0 -2
- package/dist/cli/chunks/dream-V4QN6OF5.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-3N3L6CRM.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-2BXJYDXI.js +0 -2
- package/dist/cli/chunks/hnsw-index-2DLI5OVO.js +0 -2
- package/dist/cli/chunks/hybrid-backend-OW4J65YH.js +0 -2
- package/dist/cli/chunks/impact-analyzer-ZH5I2RG6.js +0 -2
- package/dist/cli/chunks/init-wizard-NIKM3ZOK.js +0 -2
- package/dist/cli/chunks/kernel-2EOSVM6X.js +0 -2
- package/dist/cli/chunks/knowledge-graph-D3BPWNNO.js +0 -2
- package/dist/cli/chunks/llm-router-service-TJPPZFUN.js +0 -2
- package/dist/cli/chunks/load-test-RFT7IDOL.js +0 -2
- package/dist/cli/chunks/memory-backend-O2O4CFKZ.js +0 -2
- package/dist/cli/chunks/memory-handlers-DAEGUDBD.js +0 -2
- package/dist/cli/chunks/pattern-null-store-TUBNXS34.js +0 -2
- package/dist/cli/chunks/protocol-executor-6FQTTO3Y.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-TKPND56C.js +0 -2
- package/dist/cli/chunks/quality-46AK277P.js +0 -7
- package/dist/cli/chunks/queen-coordinator-DWMXLPJG.js +0 -2
- package/dist/cli/chunks/router-QIMUYRCC.js +0 -2
- package/dist/cli/chunks/routing-feedback-4OH5ZNF4.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-S6JBZL54.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-TSGMLMYR.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-Z7QOW47S.js +0 -2
- package/dist/cli/chunks/safe-db-JLOVBJNC.js +0 -2
- package/dist/cli/chunks/schedule-IM6XOBGR.js +0 -2
- package/dist/cli/chunks/scheduler-XL2SVVK5.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-LWMIIC4U.js +0 -2
- package/dist/cli/chunks/unified-memory-F5IJY7W7.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-C3WAMAQL.js +0 -2
- package/dist/cli/chunks/unified-persistence-EWXXOTCB.js +0 -2
- package/dist/cli/chunks/visual-security-CKLTAIAB.js +0 -2
- package/dist/cli/chunks/witness-chain-Z6LWFEZS.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-OFTAR2NA.js +0 -2
|
@@ -209,10 +209,14 @@ export function coverageToMarkdown(result) {
|
|
|
209
209
|
let md = `# Coverage Report\n\n`;
|
|
210
210
|
md += `| Metric | Value | Status |\n`;
|
|
211
211
|
md += `|--------|-------|--------|\n`;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
// #995: an uncollected metric is "n/a", with no pass/fail mark — it is not 0%.
|
|
213
|
+
const row = (label, v) => v === null
|
|
214
|
+
? `| ${label} | n/a (not collected) | \u2014 |\n`
|
|
215
|
+
: `| ${label} | ${v}% | ${v >= result.threshold ? '\u2705' : '\u274C'} |\n`;
|
|
216
|
+
md += row('Lines', result.summary.line);
|
|
217
|
+
md += row('Branches', result.summary.branch);
|
|
218
|
+
md += row('Functions', result.summary.function);
|
|
219
|
+
md += row('Statements', result.summary.statement);
|
|
216
220
|
md += `\n**Threshold:** ${result.threshold}% \u2014 ${result.meetsThreshold ? '\u2705 Met' : '\u274C Not met'}\n`;
|
|
217
221
|
if (result.gaps && result.gaps.length > 0) {
|
|
218
222
|
md += `\n## Coverage Gaps\n\n`;
|
|
@@ -232,6 +236,19 @@ export function coverageToMarkdown(result) {
|
|
|
232
236
|
}
|
|
233
237
|
export function qualityGateToMarkdown(result) {
|
|
234
238
|
let md = `# Quality Gate Report\n\n`;
|
|
239
|
+
if (result.evidenceStatus === 'insufficient-evidence') {
|
|
240
|
+
// #996: a gate that could not run is neither a pass nor a measured failure.
|
|
241
|
+
md += `**Result:** \u26A0\uFE0F INSUFFICIENT EVIDENCE \u2014 quality gate not evaluated\n`;
|
|
242
|
+
if (result.unmeasured && result.unmeasured.length > 0) {
|
|
243
|
+
md += `**Unmeasured:** ${result.unmeasured.join(', ')}\n`;
|
|
244
|
+
}
|
|
245
|
+
if (result.error)
|
|
246
|
+
md += `**Reason:** ${result.error}\n`;
|
|
247
|
+
if (result.recommendations && result.recommendations.length > 0) {
|
|
248
|
+
md += `\n## Recommendations\n\n${result.recommendations.map(rec => `- ${rec}`).join('\n')}\n`;
|
|
249
|
+
}
|
|
250
|
+
return md;
|
|
251
|
+
}
|
|
235
252
|
md += `**Result:** ${result.passed ? '\u2705 PASSED' : '\u274C FAILED'}\n`;
|
|
236
253
|
md += `**Score:** ${result.score}\n\n`;
|
|
237
254
|
md += `## Checks\n\n`;
|
|
@@ -41,12 +41,19 @@ export interface CoverageData {
|
|
|
41
41
|
};
|
|
42
42
|
/** True if data came from real instrumented coverage (V8/istanbul) */
|
|
43
43
|
instrumented: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Source files the instrumented report has no entry for (#995). These are
|
|
46
|
+
* UNMEASURED — excluded from the figures rather than counted as 0%.
|
|
47
|
+
*/
|
|
48
|
+
unmeasuredFiles?: string[];
|
|
44
49
|
}
|
|
45
50
|
/**
|
|
46
51
|
* Try to read real coverage data from a coverage-final.json file.
|
|
47
52
|
* Returns null if no instrumented coverage is available.
|
|
48
53
|
*/
|
|
49
54
|
export declare function readInstrumentedCoverage(projectRoot: string): Map<string, FileCoverage> | null;
|
|
55
|
+
/** Aggregate per-file coverage into whole-number percentages. */
|
|
56
|
+
export declare function summarizeCoverage(files: FileCoverage[]): CoverageData['summary'];
|
|
50
57
|
/**
|
|
51
58
|
* Build coverage data for the given source files.
|
|
52
59
|
*
|
|
@@ -161,6 +161,20 @@ function estimateFileCoverage(filePath, content) {
|
|
|
161
161
|
// ============================================================================
|
|
162
162
|
// Public API
|
|
163
163
|
// ============================================================================
|
|
164
|
+
/** Aggregate per-file coverage into whole-number percentages. */
|
|
165
|
+
export function summarizeCoverage(files) {
|
|
166
|
+
const sum = (pick) => files.reduce((acc, f) => acc + pick(f), 0);
|
|
167
|
+
const safeDiv = (a, b) => b > 0 ? Math.round((a / b) * 100) : 0;
|
|
168
|
+
const totalLines = sum(f => f.lines.total);
|
|
169
|
+
const coveredLines = sum(f => f.lines.covered);
|
|
170
|
+
return {
|
|
171
|
+
line: safeDiv(coveredLines, totalLines),
|
|
172
|
+
branch: safeDiv(sum(f => f.branches.covered), sum(f => f.branches.total)),
|
|
173
|
+
function: safeDiv(sum(f => f.functions.covered), sum(f => f.functions.total)),
|
|
174
|
+
statement: safeDiv(coveredLines, totalLines),
|
|
175
|
+
files: files.length,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
164
178
|
/**
|
|
165
179
|
* Build coverage data for the given source files.
|
|
166
180
|
*
|
|
@@ -174,6 +188,7 @@ export function buildCoverageData(sourceFiles, projectRoot) {
|
|
|
174
188
|
// Try instrumented coverage first
|
|
175
189
|
const instrumentedData = readInstrumentedCoverage(root);
|
|
176
190
|
const files = [];
|
|
191
|
+
const unmeasuredFiles = [];
|
|
177
192
|
let isInstrumented = false;
|
|
178
193
|
if (instrumentedData && instrumentedData.size > 0) {
|
|
179
194
|
isInstrumented = true;
|
|
@@ -187,18 +202,10 @@ export function buildCoverageData(sourceFiles, projectRoot) {
|
|
|
187
202
|
files.push({ ...match, path: filePath });
|
|
188
203
|
}
|
|
189
204
|
else {
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
path: filePath,
|
|
195
|
-
lines: { covered: 0, total: totalLines },
|
|
196
|
-
branches: { covered: 0, total: 1 },
|
|
197
|
-
functions: { covered: 0, total: 1 },
|
|
198
|
-
statements: { covered: 0, total: totalLines },
|
|
199
|
-
uncoveredLines: Array.from({ length: totalLines }, (_, i) => i + 1),
|
|
200
|
-
uncoveredBranches: [],
|
|
201
|
-
});
|
|
205
|
+
// #995: the report has no entry for this file — the coverage run did
|
|
206
|
+
// not measure it. That is "unmeasured", not 0%: counting it as fully
|
|
207
|
+
// uncovered invented a figure nobody measured.
|
|
208
|
+
unmeasuredFiles.push(filePath);
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
}
|
|
@@ -209,24 +216,11 @@ export function buildCoverageData(sourceFiles, projectRoot) {
|
|
|
209
216
|
files.push(estimateFileCoverage(filePath, content));
|
|
210
217
|
}
|
|
211
218
|
}
|
|
212
|
-
// Compute summary
|
|
213
|
-
const totalLines = files.reduce((sum, f) => sum + f.lines.total, 0);
|
|
214
|
-
const coveredLines = files.reduce((sum, f) => sum + f.lines.covered, 0);
|
|
215
|
-
const totalBranches = files.reduce((sum, f) => sum + f.branches.total, 0);
|
|
216
|
-
const coveredBranches = files.reduce((sum, f) => sum + f.branches.covered, 0);
|
|
217
|
-
const totalFunctions = files.reduce((sum, f) => sum + f.functions.total, 0);
|
|
218
|
-
const coveredFunctions = files.reduce((sum, f) => sum + f.functions.covered, 0);
|
|
219
|
-
const safeDiv = (a, b) => b > 0 ? Math.round((a / b) * 100) : 0;
|
|
220
219
|
return {
|
|
221
220
|
files,
|
|
222
|
-
summary:
|
|
223
|
-
line: safeDiv(coveredLines, totalLines),
|
|
224
|
-
branch: safeDiv(coveredBranches, totalBranches),
|
|
225
|
-
function: safeDiv(coveredFunctions, totalFunctions),
|
|
226
|
-
statement: safeDiv(coveredLines, totalLines),
|
|
227
|
-
files: files.length,
|
|
228
|
-
},
|
|
221
|
+
summary: summarizeCoverage(files),
|
|
229
222
|
instrumented: isInstrumented,
|
|
223
|
+
...(unmeasuredFiles.length > 0 ? { unmeasuredFiles } : {}),
|
|
230
224
|
};
|
|
231
225
|
}
|
|
232
226
|
//# sourceMappingURL=coverage-data.js.map
|
|
@@ -58,14 +58,28 @@ export interface ValidationResult {
|
|
|
58
58
|
export declare function validateRiskDecision(value: unknown): ValidationResult;
|
|
59
59
|
export declare function validateFindingVerdict(value: unknown): ValidationResult;
|
|
60
60
|
export declare function validateCoverageGap(value: unknown): ValidationResult;
|
|
61
|
+
/** #996: confidence cap for an approve that rests on static analysis alone (no gate). */
|
|
62
|
+
export declare const STATIC_APPROVAL_CONFIDENCE = 0.7;
|
|
61
63
|
/**
|
|
62
64
|
* Derive a RiskDecision from a quality-gate outcome (quality_assess boundary).
|
|
63
65
|
* Indeterminate gates (passed undefined) escalate rather than guess.
|
|
66
|
+
*
|
|
67
|
+
* #996: when key metrics are unmeasured the decision escalates with lowered
|
|
68
|
+
* confidence, whatever `passed` says — never approve on missing data. When
|
|
69
|
+
* `gateEvaluated` is false the rationale says plainly that no gate ran.
|
|
64
70
|
*/
|
|
65
71
|
export declare function buildRiskDecisionFromQualityGate(input: {
|
|
66
72
|
passed?: boolean;
|
|
67
73
|
qualityScore?: number;
|
|
68
74
|
recommendations?: string[];
|
|
75
|
+
/** Requested metrics that had no measured data. */
|
|
76
|
+
unmeasured?: string[];
|
|
77
|
+
/** Share of requested metrics that were measured, in [0, 1]. */
|
|
78
|
+
evidenceConfidence?: number;
|
|
79
|
+
/** False for static analysis: no quality gate was evaluated. */
|
|
80
|
+
gateEvaluated?: boolean;
|
|
81
|
+
/** Measured metrics that fail their own limit — conclusive, so the decision blocks. */
|
|
82
|
+
failedMetrics?: string[];
|
|
69
83
|
}): RiskDecision;
|
|
70
84
|
export declare const RISK_DECISION_SCHEMA: {
|
|
71
85
|
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
@@ -176,21 +176,62 @@ export function validateCoverageGap(value) {
|
|
|
176
176
|
// ============================================================================
|
|
177
177
|
// Builders — derive contract envelopes at MCP boundaries
|
|
178
178
|
// ============================================================================
|
|
179
|
+
/** #996: confidence cap for an approve that rests on static analysis alone (no gate). */
|
|
180
|
+
export const STATIC_APPROVAL_CONFIDENCE = 0.7;
|
|
179
181
|
/**
|
|
180
182
|
* Derive a RiskDecision from a quality-gate outcome (quality_assess boundary).
|
|
181
183
|
* Indeterminate gates (passed undefined) escalate rather than guess.
|
|
184
|
+
*
|
|
185
|
+
* #996: when key metrics are unmeasured the decision escalates with lowered
|
|
186
|
+
* confidence, whatever `passed` says — never approve on missing data. When
|
|
187
|
+
* `gateEvaluated` is false the rationale says plainly that no gate ran.
|
|
182
188
|
*/
|
|
183
189
|
export function buildRiskDecisionFromQualityGate(input) {
|
|
184
|
-
const { passed, qualityScore, recommendations = [] } = input;
|
|
190
|
+
const { passed, qualityScore, recommendations = [], unmeasured = [], failedMetrics = [], gateEvaluated, } = input;
|
|
191
|
+
const noGate = gateEvaluated === false ? ' (no quality gate was evaluated)' : '';
|
|
192
|
+
const score = typeof qualityScore === 'number' ? ` with score ${qualityScore}` : '';
|
|
193
|
+
// A measured failure cannot be rescued by metrics that were never measured.
|
|
194
|
+
if (failedMetrics.length > 0) {
|
|
195
|
+
const missing = unmeasured.length > 0 ? `; also unmeasured: ${unmeasured.join(', ')}` : '';
|
|
196
|
+
return {
|
|
197
|
+
contract: 'risk-decision@1',
|
|
198
|
+
decision: 'block',
|
|
199
|
+
riskFactors: [
|
|
200
|
+
`failed: ${failedMetrics.join(', ')}`,
|
|
201
|
+
...(unmeasured.length > 0 ? [`unmeasured: ${unmeasured.join(', ')}`] : []),
|
|
202
|
+
...recommendations,
|
|
203
|
+
].slice(0, 10),
|
|
204
|
+
confidence: 0.9,
|
|
205
|
+
rationale: `Measured ${failedMetrics.join(', ')} failed its threshold${missing}${noGate}`,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (unmeasured.length > 0) {
|
|
209
|
+
const share = typeof input.evidenceConfidence === 'number' && Number.isFinite(input.evidenceConfidence)
|
|
210
|
+
? Math.min(1, Math.max(0, input.evidenceConfidence))
|
|
211
|
+
: 0;
|
|
212
|
+
return {
|
|
213
|
+
contract: 'risk-decision@1',
|
|
214
|
+
decision: 'escalate',
|
|
215
|
+
riskFactors: [`unmeasured: ${unmeasured.join(', ')}`, ...recommendations].slice(0, 10),
|
|
216
|
+
confidence: Math.round(0.5 * share * 100) / 100,
|
|
217
|
+
rationale: `Insufficient evidence: ${unmeasured.join(', ')} not measured${noGate} — `
|
|
218
|
+
+ 'measure the missing metrics or run the measured quality gate before deciding',
|
|
219
|
+
};
|
|
220
|
+
}
|
|
185
221
|
const decision = passed === true ? 'approve' : passed === false ? 'block' : 'escalate';
|
|
222
|
+
const subject = gateEvaluated === false ? 'Static analysis' : 'Quality gate';
|
|
223
|
+
// #996 (N1): an approval no gate evaluated is weaker evidence than a gate pass.
|
|
224
|
+
const confidence = decision === 'escalate'
|
|
225
|
+
? 0.5
|
|
226
|
+
: decision === 'approve' && gateEvaluated === false ? STATIC_APPROVAL_CONFIDENCE : 0.9;
|
|
186
227
|
return {
|
|
187
228
|
contract: 'risk-decision@1',
|
|
188
229
|
decision,
|
|
189
230
|
riskFactors: recommendations.slice(0, 10),
|
|
190
|
-
confidence
|
|
231
|
+
confidence,
|
|
191
232
|
rationale: decision === 'escalate'
|
|
192
233
|
? 'Quality gate outcome indeterminate — manual review required'
|
|
193
|
-
:
|
|
234
|
+
: `${subject} ${passed ? 'passed' : 'failed'}${score}${noGate}`,
|
|
194
235
|
};
|
|
195
236
|
}
|
|
196
237
|
// ============================================================================
|
|
@@ -4,143 +4,141 @@
|
|
|
4
4
|
* Extracted from task-executor.ts registerHandlers().
|
|
5
5
|
* Covers: analyze-coverage
|
|
6
6
|
*/
|
|
7
|
-
import * as fs from 'fs/promises';
|
|
8
|
-
import * as path from 'path';
|
|
9
7
|
import { ok, err } from '../../shared/types/index.js';
|
|
10
8
|
import { toError } from '../../shared/error-utils.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { buildEstimatedCoverage, collectRustCoverage, findCargoRoot, isCoverageExecDisabled, isRustProject, } from './coverage-collection.js';
|
|
10
|
+
import { describeNoData, evaluateCoverageForTarget, isUnmeasured, resolveExistingCoverage, scopeCoverageToTarget, reconcileRecommendations, thresholdVerdict, } from './coverage-target.js';
|
|
11
|
+
import { describeRunFailure, runJsCoverage } from './coverage-runner.js';
|
|
14
12
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* written — the caller re-checks disk).
|
|
13
|
+
* How long the project's test runner may take before its process tree is
|
|
14
|
+
* killed. `AQE_COVERAGE_TIMEOUT_MS` overrides the 120s default.
|
|
18
15
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// opt-out before doing that.
|
|
23
|
-
if (isCoverageExecDisabled())
|
|
24
|
-
return false;
|
|
25
|
-
try {
|
|
26
|
-
const { execSync } = await import('child_process');
|
|
27
|
-
let coverageCmd = 'npx vitest run --coverage --reporter=json 2>/dev/null';
|
|
28
|
-
try {
|
|
29
|
-
const pkgContent = await fs.readFile(path.join(targetPath, 'package.json'), 'utf-8');
|
|
30
|
-
const pkg = safeJsonParse(pkgContent);
|
|
31
|
-
const deps = {
|
|
32
|
-
...(pkg.devDependencies || {}),
|
|
33
|
-
...(pkg.dependencies || {}),
|
|
34
|
-
};
|
|
35
|
-
if (deps['jest'] || deps['@jest/core']) {
|
|
36
|
-
coverageCmd = 'npx jest --coverage --json 2>/dev/null';
|
|
37
|
-
}
|
|
38
|
-
else if (deps['mocha'] || deps['nyc']) {
|
|
39
|
-
coverageCmd = 'npx nyc mocha 2>/dev/null';
|
|
40
|
-
}
|
|
41
|
-
// vitest is the default — covers vitest, @vitest/coverage-v8, etc.
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// No package.json — use default vitest
|
|
45
|
-
}
|
|
46
|
-
execSync(coverageCmd, {
|
|
47
|
-
cwd: targetPath,
|
|
48
|
-
timeout: 120000,
|
|
49
|
-
encoding: 'utf-8',
|
|
50
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
51
|
-
});
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
// Test runner failed or not available.
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
16
|
+
function coverageTimeoutMs(env = process.env) {
|
|
17
|
+
const parsed = Number.parseInt(env.AQE_COVERAGE_TIMEOUT_MS ?? '', 10);
|
|
18
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 120000;
|
|
58
19
|
}
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
* aggregate from what survives.
|
|
62
|
-
*
|
|
63
|
-
* Returns `null` when the report contains no production files at all — the
|
|
64
|
-
* caller must NOT fall back to the unfiltered set, because that reports the test
|
|
65
|
-
* files' own coverage as the project's (#569's third contradiction).
|
|
66
|
-
*/
|
|
67
|
-
function productionOnly(report, targetPath) {
|
|
68
|
-
const files = report.files.filter(f => !isTestPath(f.path, targetPath));
|
|
69
|
-
if (files.length === 0)
|
|
70
|
-
return null;
|
|
71
|
-
// Recompute rather than carrying the original summary: it was computed over
|
|
72
|
-
// the unfiltered set, so keeping it would blend test-file coverage into the
|
|
73
|
-
// production headline figure.
|
|
20
|
+
/** Aggregate a file list into whole-number percentages. */
|
|
21
|
+
function recomputeSummary(files) {
|
|
74
22
|
const sum = (pick) => files.reduce((acc, f) => acc + pick(f), 0);
|
|
75
|
-
const pct = (covered, total) => total > 0 ? Math.round((covered / total) * 100) : 0;
|
|
23
|
+
const pct = (covered, total) => (total > 0 ? Math.round((covered / total) * 100) : 0);
|
|
76
24
|
const totalLines = sum(f => f.lines.total);
|
|
77
25
|
const coveredLines = sum(f => f.lines.covered);
|
|
78
|
-
const branchDataCollected = files.some(f => f.branches.total > 0);
|
|
79
|
-
const functionDataCollected = files.some(f => f.functions.total > 0);
|
|
80
26
|
return {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
27
|
+
line: pct(coveredLines, totalLines),
|
|
28
|
+
branch: pct(sum(f => f.branches.covered), sum(f => f.branches.total)),
|
|
29
|
+
function: pct(sum(f => f.functions.covered), sum(f => f.functions.total)),
|
|
30
|
+
statement: pct(coveredLines, totalLines),
|
|
31
|
+
files: files.length,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** An instrumented verdict as a collected result with honest provenance. */
|
|
35
|
+
function instrumented(files) {
|
|
36
|
+
return {
|
|
37
|
+
data: { files, summary: recomputeSummary(files) },
|
|
91
38
|
provenance: {
|
|
92
39
|
method: 'instrumented-report',
|
|
93
40
|
estimated: false,
|
|
94
|
-
branchDataCollected,
|
|
95
|
-
functionDataCollected,
|
|
41
|
+
branchDataCollected: files.some(f => f.branches.total > 0),
|
|
42
|
+
functionDataCollected: files.some(f => f.functions.total > 0),
|
|
96
43
|
notes: [],
|
|
97
44
|
},
|
|
98
45
|
};
|
|
99
46
|
}
|
|
47
|
+
function fromEvaluation(evaluation, ranTests, projectRoot) {
|
|
48
|
+
return evaluation.status === 'measured'
|
|
49
|
+
? { collected: instrumented(evaluation.files), ranTests, projectRoot }
|
|
50
|
+
: { collected: null, ranTests, noData: evaluation.reason, projectRoot };
|
|
51
|
+
}
|
|
100
52
|
/**
|
|
101
53
|
* Collect coverage for a target, preferring real measurement over estimation
|
|
102
54
|
* and always reporting which one happened (#569).
|
|
103
55
|
*
|
|
56
|
+
* The target may be the project root, a subfolder or file inside it, or an
|
|
57
|
+
* existing coverage report (#995). Tooling always runs from the project root
|
|
58
|
+
* and the result is scoped back down to the target. The decision about what
|
|
59
|
+
* a report says for a target is shared with the CLI (`resolveExistingCoverage`
|
|
60
|
+
* / `evaluateCoverageForTarget`).
|
|
61
|
+
*
|
|
104
62
|
* Cascade:
|
|
105
|
-
*
|
|
63
|
+
* 0. the target IS a coverage report — parse it, run nothing
|
|
64
|
+
* 1. an instrumented report already on disk at the project root
|
|
106
65
|
* 2. language-specific instrumentation we can run — `cargo llvm-cov` for Rust,
|
|
107
|
-
* the project's test runner for JS/TS
|
|
66
|
+
* the project's test runner for JS/TS — writing to a temp dir
|
|
108
67
|
* 3. static estimation, explicitly labelled `estimated: true`
|
|
109
68
|
*/
|
|
110
69
|
async function collectCoverage(targetPath) {
|
|
111
|
-
const existing = await
|
|
112
|
-
if (existing) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// (`tests/verifier_matrix.rs` analysed at 79.2% as if it were a target).
|
|
118
|
-
if (!fromReport)
|
|
119
|
-
return { collected: null, ranTests: false, testOnlyReport: true };
|
|
120
|
-
return { collected: fromReport, ranTests: false };
|
|
70
|
+
const existing = await resolveExistingCoverage(targetPath);
|
|
71
|
+
if (existing.status === 'target-missing') {
|
|
72
|
+
return { collected: null, ranTests: false, noData: 'target-missing', projectRoot: null };
|
|
73
|
+
}
|
|
74
|
+
if (existing.status === 'evaluated') {
|
|
75
|
+
return fromEvaluation(existing.evaluation, false, existing.projectRoot);
|
|
121
76
|
}
|
|
77
|
+
const { target, projectRoot } = existing;
|
|
122
78
|
// #569 work item 1: delegate to real instrumentation where available.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
79
|
+
if (isRustProject(target)) {
|
|
80
|
+
const rust = await collectRustCoverage(target);
|
|
81
|
+
if (rust) {
|
|
82
|
+
// cargo ran from the crate root; scope its crate-wide output to the target.
|
|
83
|
+
const crateRoot = findCargoRoot(target) ?? projectRoot;
|
|
84
|
+
const scoped = scopeCoverageToTarget(rust.data, crateRoot, target);
|
|
85
|
+
if (scoped.length === 0) {
|
|
86
|
+
return { collected: null, ranTests: true, noData: 'target-not-covered', projectRoot: crateRoot };
|
|
87
|
+
}
|
|
88
|
+
const collected = scoped.length === rust.data.files.length
|
|
89
|
+
? rust
|
|
90
|
+
: { data: { files: scoped, summary: recomputeSummary(scoped) }, provenance: rust.provenance };
|
|
91
|
+
return { collected, ranTests: true, projectRoot: crateRoot };
|
|
92
|
+
}
|
|
128
93
|
// This target is a Rust crate. Do not continue into the JS/TS runner:
|
|
129
94
|
// `npx vitest --coverage` can still be available through the parent
|
|
130
95
|
// process PATH and will write an empty report even though the crate has no
|
|
131
96
|
// JavaScript tests. Treating that artifact as coverage hides the intended
|
|
132
97
|
// Rust static-estimation fallback and mislabels the result.
|
|
133
|
-
return { collected: buildEstimatedCoverage(
|
|
98
|
+
return { collected: buildEstimatedCoverage(target), ranTests: false, projectRoot };
|
|
134
99
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return { collected: null, ranTests, testOnlyReport: true };
|
|
141
|
-
return { collected: fromRun, ranTests };
|
|
100
|
+
// Running the project's test suite executes code from the analyzed repository
|
|
101
|
+
// (the tests themselves, plus npm lifecycle scripts via npx). Honor the
|
|
102
|
+
// opt-out before doing that.
|
|
103
|
+
if (isCoverageExecDisabled()) {
|
|
104
|
+
return { collected: buildEstimatedCoverage(target), ranTests: false, projectRoot };
|
|
142
105
|
}
|
|
143
|
-
|
|
106
|
+
const run = await runJsCoverage(projectRoot, { timeoutMs: coverageTimeoutMs() });
|
|
107
|
+
// An EMPTY report (`{}`) from a run that reported its tests means "the run
|
|
108
|
+
// instrumented nothing under the target" → unmeasured, never an estimate
|
|
109
|
+
// (#995 review BL2). An empty report from a run that crashed before
|
|
110
|
+
// reporting any tests is a crash, handled below.
|
|
111
|
+
const crashedEmpty = run.data !== null && run.data.files.length === 0 &&
|
|
112
|
+
run.numTotalTests === null && !run.exitedCleanly;
|
|
113
|
+
if ((run.data && !crashedEmpty) || run.numTotalTests === 0) {
|
|
114
|
+
const evaluation = run.data
|
|
115
|
+
? evaluateCoverageForTarget(run.data, projectRoot, target, { numTotalTests: run.numTotalTests })
|
|
116
|
+
: { status: 'no-data', reason: 'no-tests-ran' };
|
|
117
|
+
return fromEvaluation(evaluation, run.exitedCleanly || run.data !== null, projectRoot);
|
|
118
|
+
}
|
|
119
|
+
// No report at all: say exactly what happened to the run (not installed,
|
|
120
|
+
// timed out, crashed with stderr), then fall back to a labelled estimate.
|
|
121
|
+
const estimate = buildEstimatedCoverage(target);
|
|
122
|
+
const runNote = describeRunFailure(run, projectRoot);
|
|
123
|
+
if (estimate) {
|
|
124
|
+
estimate.provenance.notes = [
|
|
125
|
+
`${runNote} These numbers are a STATIC ESTIMATE derived from source shape — ` +
|
|
126
|
+
'not measured coverage, and must not be reported as such.',
|
|
127
|
+
...estimate.provenance.notes.filter(n => !/^No instrumentation ran/.test(n)),
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
collected: estimate, ranTests: run.exitedCleanly, projectRoot,
|
|
132
|
+
notes: estimate ? [] : [runNote],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Caller-facing explanation for a result with no coverage figures. */
|
|
136
|
+
function noDataWarning(reason, ranTests, targetPath, projectRoot) {
|
|
137
|
+
if (reason)
|
|
138
|
+
return describeNoData(reason, targetPath, projectRoot);
|
|
139
|
+
return ranTests
|
|
140
|
+
? 'Tests ran but no coverage output was generated. Ensure a coverage provider is configured (e.g., @vitest/coverage-v8, istanbul).'
|
|
141
|
+
: 'No coverage data found and could not run tests automatically. ' + estimationGuidance(targetPath);
|
|
144
142
|
}
|
|
145
143
|
/**
|
|
146
144
|
* Build the guidance string shown when a result is an estimate rather than a
|
|
@@ -169,8 +167,13 @@ export function registerCoverageHandlers(ctx) {
|
|
|
169
167
|
const analyzer = ctx.getCoverageAnalyzer();
|
|
170
168
|
const targetPath = payload.target || process.cwd();
|
|
171
169
|
const threshold = payload.threshold || 80;
|
|
172
|
-
const { collected, ranTests,
|
|
170
|
+
const { collected, ranTests, noData, projectRoot, notes } = await collectCoverage(targetPath);
|
|
171
|
+
// #995 review N5: say so plainly instead of "no coverage data found".
|
|
172
|
+
if (noData === 'target-missing') {
|
|
173
|
+
return err(new Error(describeNoData('target-missing', targetPath, null)));
|
|
174
|
+
}
|
|
173
175
|
if (!collected) {
|
|
176
|
+
const unmeasured = noData !== undefined && isUnmeasured(noData);
|
|
174
177
|
return ok({
|
|
175
178
|
lineCoverage: null,
|
|
176
179
|
branchCoverage: null,
|
|
@@ -182,22 +185,21 @@ export function registerCoverageHandlers(ctx) {
|
|
|
182
185
|
estimated: false,
|
|
183
186
|
measured: false,
|
|
184
187
|
coverageMethod: 'none',
|
|
188
|
+
// #995(d): "no measurement exists for this target", distinct from 0%.
|
|
189
|
+
...(unmeasured ? { unmeasured: true } : {}),
|
|
185
190
|
algorithm: 'sublinear-O(log n)',
|
|
186
|
-
warning:
|
|
187
|
-
? 'The coverage report contains only test files, so there is no production ' +
|
|
188
|
-
'coverage to report. Coverage OF a test file is not a meaningful metric. ' +
|
|
189
|
-
'Check that your coverage tool is instrumenting your source directory.'
|
|
190
|
-
: ranTests
|
|
191
|
-
? 'Tests ran but no coverage output was generated. Ensure a coverage provider is configured (e.g., @vitest/coverage-v8, istanbul).'
|
|
192
|
-
: 'No coverage data found and could not run tests automatically. ' + estimationGuidance(targetPath),
|
|
191
|
+
warning: notes?.length ? notes.join(' ') : noDataWarning(noData, ranTests, targetPath, projectRoot),
|
|
193
192
|
});
|
|
194
193
|
}
|
|
195
194
|
const { data: coverageData, provenance } = collected;
|
|
196
195
|
// Analyze coverage using the real CoverageAnalyzerService
|
|
196
|
+
// #1008: the analyzer persists only measured coverage; a static estimate
|
|
197
|
+
// is returned below, labelled, but never stored as evidence.
|
|
197
198
|
const analysisResult = await analyzer.analyze({
|
|
198
199
|
coverageData,
|
|
199
200
|
threshold,
|
|
200
201
|
includeFileDetails: payload.detectGaps,
|
|
202
|
+
measured: !provenance.estimated,
|
|
201
203
|
});
|
|
202
204
|
if (!analysisResult.success) {
|
|
203
205
|
return analysisResult;
|
|
@@ -227,7 +229,7 @@ export function registerCoverageHandlers(ctx) {
|
|
|
227
229
|
}
|
|
228
230
|
const round = (n) => Math.round(n * 10) / 10;
|
|
229
231
|
const pct = (covered, total) => total > 0 ? Math.round((covered / total) * 1000) / 10 : null;
|
|
230
|
-
const warnings = [...provenance.notes];
|
|
232
|
+
const warnings = [...provenance.notes, ...(notes ?? [])];
|
|
231
233
|
if (provenance.estimated)
|
|
232
234
|
warnings.push(estimationGuidance(targetPath));
|
|
233
235
|
// #569: the analyzer generates recommendations from the summary numbers.
|
|
@@ -236,13 +238,11 @@ export function registerCoverageHandlers(ctx) {
|
|
|
236
238
|
// significantly lower than line coverage", "Function coverage is below
|
|
237
239
|
// 70%") is a statement about a metric nobody measured. Drop it rather
|
|
238
240
|
// than send a developer to fix a number that doesn't exist.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return true;
|
|
245
|
-
});
|
|
241
|
+
// #995 NB5/NB-A: the verdict and the shortfall advice come from the same
|
|
242
|
+
// collected-metrics computation (shared with the CLI), so they can't disagree.
|
|
243
|
+
const metricsCollected = { branch: provenance.branchDataCollected, function: provenance.functionDataCollected };
|
|
244
|
+
const verdict = thresholdVerdict(report.summary, threshold, metricsCollected);
|
|
245
|
+
const recommendations = reconcileRecommendations(report.recommendations, verdict, threshold, metricsCollected);
|
|
246
246
|
return ok({
|
|
247
247
|
lineCoverage: round(report.summary.line),
|
|
248
248
|
// #569 work item 4: never report a branch percentage — least of all
|
|
@@ -258,7 +258,8 @@ export function registerCoverageHandlers(ctx) {
|
|
|
258
258
|
functionCoverage: provenance.functionDataCollected ? pct(f.functions.covered, f.functions.total) : null,
|
|
259
259
|
})),
|
|
260
260
|
gaps,
|
|
261
|
-
|
|
261
|
+
// NB5: judged only on the metrics that were collected (shared with the CLI).
|
|
262
|
+
meetsThreshold: verdict.meetsThreshold,
|
|
262
263
|
delta: report.delta,
|
|
263
264
|
recommendations,
|
|
264
265
|
algorithm: 'sublinear-O(log n)',
|