agentic-qe 3.15.3 → 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 +139 -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-CYG3PKHH.js → agent-booster-wasm-CCTTGCQS.js} +2 -2
- package/dist/cli/chunks/{agent-handler-WTFYFZKL.js → agent-handler-DHYUF3NX.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-G6WE3ZXU.js → agent-memory-branch-642W7CYX.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-WP4GCBDT.js +2 -0
- package/dist/cli/chunks/{arena-S72QW44C.js → arena-MUCC7UUN.js} +4 -4
- package/dist/cli/chunks/{arena-ZFXQEVUQ.js → arena-NW2JVAFY.js} +2 -2
- package/dist/cli/chunks/{audit-KPYIEQJ3.js → audit-VKQTZJAA.js} +3 -3
- package/dist/cli/chunks/base-6ORFD62I.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-L2M3TI5D.js → better-sqlite3-7ZUFVWLQ.js} +2 -2
- package/dist/cli/chunks/{brain-handler-FHKLQTB4.js → brain-handler-7LKAWSBI.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-3BSHOPOK.js → branch-enumerator-HUNXJKM4.js} +2 -2
- package/dist/cli/chunks/{browser-JUIJPL6Y.js → browser-ZSZEYUDP.js} +2 -2
- package/dist/cli/chunks/browser-workflow-PIXGERWP.js +2 -0
- package/dist/cli/chunks/{chunk-VHBZADYK.js → chunk-2KWI3MT3.js} +2 -2
- package/dist/cli/chunks/{chunk-35VDOH4Y.js → chunk-2WFTZSRT.js} +1 -1
- package/dist/cli/chunks/{chunk-UTALYUMW.js → chunk-2XYTS2WY.js} +2 -2
- package/dist/cli/chunks/{chunk-OTTTHNIT.js → chunk-35MDATQE.js} +1 -1
- package/dist/cli/chunks/{chunk-Z7UGEQ4G.js → chunk-3AYYGR6W.js} +1 -1
- package/dist/cli/chunks/{chunk-LPZAB3N2.js → chunk-3DTEQHFB.js} +3 -3
- package/dist/cli/chunks/{chunk-YHZGFWJE.js → chunk-3OAQPN2N.js} +2 -2
- package/dist/cli/chunks/{chunk-PUPEKA2J.js → chunk-3QD7U3FY.js} +2 -2
- package/dist/cli/chunks/{chunk-3Y4GX5FL.js → chunk-3SH23PS3.js} +2 -2
- package/dist/cli/chunks/{chunk-NT6FYFJA.js → chunk-3YASZPLO.js} +2 -2
- package/dist/cli/chunks/{chunk-QVNMTMDJ.js → chunk-3YNP33GB.js} +2 -2
- package/dist/cli/chunks/{chunk-AQTQ24SK.js → chunk-47GEI2LT.js} +3 -3
- package/dist/cli/chunks/{chunk-JJBTM4JO.js → chunk-4AZP7ZCW.js} +2 -2
- package/dist/cli/chunks/{chunk-6W6GZHQA.js → chunk-4PT5KNXL.js} +4 -4
- package/dist/cli/chunks/{chunk-EQGT4VLC.js → chunk-4UXPDV7E.js} +1 -1
- package/dist/cli/chunks/{chunk-SP2JO53K.js → chunk-4XSCZVON.js} +2 -2
- package/dist/cli/chunks/{chunk-DWG4TN6A.js → chunk-5BOZCMXZ.js} +1 -1
- package/dist/cli/chunks/{chunk-PBUWNMZ2.js → chunk-644DFAGS.js} +1 -1
- package/dist/cli/chunks/{chunk-6EQDA4EC.js → chunk-663ZFPUL.js} +2 -2
- package/dist/cli/chunks/{chunk-HU474NXP.js → chunk-6JFGB2JB.js} +1 -1
- package/dist/cli/chunks/{chunk-AS54N3H7.js → chunk-6LG5UEQE.js} +2 -2
- package/dist/cli/chunks/{chunk-3UUMGWHW.js → chunk-6UYN5PHA.js} +4 -4
- package/dist/cli/chunks/{chunk-RQUSJEON.js → chunk-6ZIDZ4TJ.js} +2 -2
- package/dist/cli/chunks/{chunk-P36IODAM.js → chunk-7BIYJRQJ.js} +2 -2
- package/dist/cli/chunks/{chunk-5LEUEWJY.js → chunk-7EZLOC4K.js} +2 -2
- package/dist/cli/chunks/{chunk-EBIMVSPH.js → chunk-7YB2KELI.js} +2 -2
- package/dist/cli/chunks/{chunk-YCGU2LI7.js → chunk-A2WOQO2N.js} +2 -2
- package/dist/cli/chunks/{chunk-HSR53REE.js → chunk-A337MD3C.js} +2 -2
- package/dist/cli/chunks/{chunk-ZJW4HRUA.js → chunk-A5J4XJS6.js} +1 -1
- package/dist/cli/chunks/{chunk-POTVF6BY.js → chunk-AQN5EDBM.js} +1 -1
- package/dist/cli/chunks/{chunk-X335K4SU.js → chunk-AUZXRFOX.js} +2 -2
- package/dist/cli/chunks/{chunk-WI7I6LMM.js → chunk-B2UHTA4Q.js} +1 -1
- package/dist/cli/chunks/{chunk-W7EHNX3Y.js → chunk-BBL6YXD3.js} +2 -2
- package/dist/cli/chunks/chunk-BJ5P4IV2.js +2 -0
- package/dist/cli/chunks/{chunk-RDTR43YN.js → chunk-BMWAWZAN.js} +2 -2
- package/dist/cli/chunks/chunk-BO4PKNYP.js +102 -0
- package/dist/cli/chunks/{chunk-KGS6H2HB.js → chunk-BY646JOM.js} +2 -2
- package/dist/cli/chunks/{chunk-PPA53NJB.js → chunk-BYXNHGQC.js} +2 -2
- package/dist/cli/chunks/{chunk-RRSZ27A7.js → chunk-BZFT4QDQ.js} +2 -2
- package/dist/cli/chunks/{chunk-M3ACHBC7.js → chunk-CFPR24YK.js} +2 -2
- package/dist/cli/chunks/{chunk-SRDECRTL.js → chunk-CQMHDAJS.js} +2 -2
- package/dist/cli/chunks/{chunk-WW4RJ6BH.js → chunk-CR2JUANW.js} +2 -2
- package/dist/cli/chunks/{chunk-QSVNVDA5.js → chunk-CXOXUBYU.js} +1 -1
- package/dist/cli/chunks/chunk-D3G2NN7F.js +741 -0
- package/dist/cli/chunks/{chunk-RGD2CG23.js → chunk-DEGWCUMY.js} +2 -2
- package/dist/cli/chunks/{chunk-AEL4XJGJ.js → chunk-DFPL5N3Q.js} +2 -2
- package/dist/cli/chunks/{chunk-FTUNC4EI.js → chunk-DL5JENWD.js} +3 -3
- package/dist/cli/chunks/{chunk-DH5NWHH2.js → chunk-DLY4YEN3.js} +2 -2
- package/dist/cli/chunks/{chunk-V5NYGDSX.js → chunk-DPV33C77.js} +2 -2
- package/dist/cli/chunks/{chunk-A5H7TF7C.js → chunk-DPYDUKVZ.js} +2 -2
- package/dist/cli/chunks/{chunk-4JVVVKAX.js → chunk-DTJODGCE.js} +2 -2
- package/dist/cli/chunks/{chunk-6AKJ73X3.js → chunk-DWZI3IVB.js} +2 -2
- package/dist/cli/chunks/{chunk-7UUSV2SK.js → chunk-DXVZBJE4.js} +1 -1
- package/dist/cli/chunks/{chunk-FPFGN2Z5.js → chunk-E4VIVMDL.js} +2 -2
- package/dist/cli/chunks/{chunk-GPZH6OPP.js → chunk-EAYQCBXL.js} +3 -3
- package/dist/cli/chunks/{chunk-7SWHW5AC.js → chunk-EOR3RECZ.js} +20 -20
- package/dist/cli/chunks/chunk-ERGWWI4Y.js +3 -0
- package/dist/cli/chunks/{chunk-XXW4KFBB.js → chunk-EUEHBERE.js} +1 -1
- package/dist/cli/chunks/{chunk-VUBLJBHQ.js → chunk-EVCFUYYK.js} +2 -2
- package/dist/cli/chunks/{chunk-YQ3ZW47V.js → chunk-FBEXG4HD.js} +2 -2
- package/dist/cli/chunks/{chunk-HV3ZVUHO.js → chunk-FE3AIZI6.js} +1 -1
- package/dist/cli/chunks/{chunk-TBVPNN65.js → chunk-FHUJCVT3.js} +2 -2
- package/dist/cli/chunks/{chunk-3ZTBV6M3.js → chunk-FNAYDITO.js} +1 -1
- package/dist/cli/chunks/{chunk-JVQK6NGI.js → chunk-FQKEZVN6.js} +2 -2
- package/dist/cli/chunks/{chunk-MUSYQF53.js → chunk-FWYJ6UDX.js} +2 -2
- package/dist/cli/chunks/{chunk-QUXX2DP7.js → chunk-GGDKOJVF.js} +2 -2
- package/dist/cli/chunks/{chunk-VRT736E3.js → chunk-GKPRECLL.js} +2 -2
- package/dist/cli/chunks/{chunk-3MNKYCLH.js → chunk-GRIPCYW5.js} +1 -1
- package/dist/cli/chunks/{chunk-DE3QNPTG.js → chunk-GTSOFCMQ.js} +1 -1
- package/dist/cli/chunks/{chunk-2MEWIXW4.js → chunk-HBYQYGXP.js} +2 -2
- package/dist/cli/chunks/{chunk-RWLOERKK.js → chunk-HGBJ2QQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-4IYHYHTG.js → chunk-HIUNCO2W.js} +2 -2
- package/dist/cli/chunks/{chunk-WSUYEVSY.js → chunk-HLFDC4SF.js} +1 -1
- package/dist/cli/chunks/{chunk-OKNMZLGB.js → chunk-HPLMX62I.js} +2 -2
- package/dist/cli/chunks/{chunk-Z7JPWXW2.js → chunk-IHFUEPZH.js} +2 -2
- package/dist/cli/chunks/{chunk-2TBHPYOU.js → chunk-IJ2EXSMO.js} +2 -2
- package/dist/cli/chunks/{chunk-SKHP5WUP.js → chunk-IJOFZBXD.js} +2 -2
- package/dist/cli/chunks/{chunk-YW4GM36K.js → chunk-JANLATHN.js} +2 -2
- package/dist/cli/chunks/{chunk-BDKQSEEY.js → chunk-JCC7QEKZ.js} +1 -1
- package/dist/cli/chunks/{chunk-7PDC4SKR.js → chunk-JI77KJP7.js} +1 -1
- package/dist/cli/chunks/{chunk-LEB6O2IN.js → chunk-JNMUVBAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZI6NJEBY.js → chunk-JYY7AYGA.js} +1 -1
- package/dist/cli/chunks/{chunk-ASUXS4N4.js → chunk-KHCALIFP.js} +2 -2
- package/dist/cli/chunks/{chunk-ED5HUPUR.js → chunk-KJ3KBP24.js} +2 -2
- package/dist/cli/chunks/{chunk-YTRGMILO.js → chunk-KZVJW2SD.js} +2 -2
- package/dist/cli/chunks/chunk-L336HFFE.js +2 -0
- package/dist/cli/chunks/{chunk-GJB3LPCS.js → chunk-L375O3CZ.js} +2 -2
- package/dist/cli/chunks/{chunk-WQZBKLAG.js → chunk-L6SVCNXK.js} +1 -1
- package/dist/cli/chunks/{chunk-YGKU2QRC.js → chunk-LNO5IWGH.js} +1 -1
- package/dist/cli/chunks/{chunk-APV5UWTU.js → chunk-LRASYSGV.js} +2 -2
- package/dist/cli/chunks/{chunk-HW4V7BVV.js → chunk-MB4VFAJC.js} +2 -2
- package/dist/cli/chunks/{chunk-366IBPZB.js → chunk-MNQ36MAF.js} +2 -2
- package/dist/cli/chunks/{chunk-7TW5UGDP.js → chunk-MQGEZA2A.js} +2 -2
- package/dist/cli/chunks/{chunk-CFXROOIU.js → chunk-MS3Z2CP5.js} +2 -2
- package/dist/cli/chunks/{chunk-4TM5K6EZ.js → chunk-N2TJNIHA.js} +2 -2
- package/dist/cli/chunks/{chunk-DLA3EHKJ.js → chunk-NF6AFIAX.js} +1 -1
- package/dist/cli/chunks/{chunk-2GJJGO5D.js → chunk-NLDFNAOS.js} +2 -2
- package/dist/cli/chunks/{chunk-UCSGZVJX.js → chunk-NMJVG22Z.js} +1 -1
- package/dist/cli/chunks/{chunk-WSND64RL.js → chunk-OGYWWZU7.js} +2 -2
- package/dist/cli/chunks/{chunk-FXTZXZCU.js → chunk-ONCH5AXU.js} +3 -3
- package/dist/cli/chunks/{chunk-M3ONCPSU.js → chunk-OQDC7GCM.js} +2 -2
- package/dist/cli/chunks/{chunk-P6EGRAQG.js → chunk-ORTBRO7F.js} +2 -2
- package/dist/cli/chunks/{chunk-D6PUDLJ4.js → chunk-OU4ZAWCC.js} +2 -2
- package/dist/cli/chunks/{chunk-AOZJ6UUZ.js → chunk-OW42F2TX.js} +2 -2
- package/dist/cli/chunks/{chunk-4N7YXTV3.js → chunk-PCCIZFD7.js} +1 -1
- package/dist/cli/chunks/{chunk-OT6SOPAL.js → chunk-PDPEMBFV.js} +2 -2
- package/dist/cli/chunks/{chunk-A3IQU2ND.js → chunk-PHAQWAEV.js} +2 -2
- package/dist/cli/chunks/{chunk-XV2TIODR.js → chunk-PHP4UJYP.js} +1 -1
- package/dist/cli/chunks/{chunk-POVP6O6K.js → chunk-PURHGLEC.js} +1 -1
- package/dist/cli/chunks/{chunk-5QUOM357.js → chunk-PVAE65B4.js} +1 -1
- package/dist/cli/chunks/{chunk-ZL2GYU7H.js → chunk-QPV3OKX2.js} +2 -2
- package/dist/cli/chunks/{chunk-B23ROYST.js → chunk-QXY3IRBW.js} +21 -21
- package/dist/cli/chunks/chunk-RCXMUEZN.js +3 -0
- package/dist/cli/chunks/{chunk-HVIFA73X.js → chunk-RMJ7PJOS.js} +2 -2
- package/dist/cli/chunks/{chunk-OGARNKLS.js → chunk-RUJLVJDE.js} +2 -2
- package/dist/cli/chunks/{chunk-UGNTLSBL.js → chunk-RUSLEOMC.js} +2 -2
- package/dist/cli/chunks/chunk-SAPIRK2G.js +3 -0
- package/dist/cli/chunks/{chunk-F5BREV2Q.js → chunk-SDWMLT7B.js} +5 -5
- package/dist/cli/chunks/{chunk-A6PII4R4.js → chunk-SEZLYRCS.js} +1 -1
- package/dist/cli/chunks/{chunk-RWQDRPN5.js → chunk-TDLKXLJC.js} +2 -2
- package/dist/cli/chunks/{chunk-YJH7UFA2.js → chunk-U4TV75AC.js} +2 -2
- package/dist/cli/chunks/{chunk-34Y4CIHD.js → chunk-U6OVPMQX.js} +2 -2
- package/dist/cli/chunks/{chunk-L6OSEWOS.js → chunk-UE22ODHN.js} +1 -1
- package/dist/cli/chunks/{chunk-IARE5VGI.js → chunk-UXZEVIFX.js} +1 -1
- package/dist/cli/chunks/{chunk-OMHISPPF.js → chunk-V7GNUVYI.js} +1 -1
- package/dist/cli/chunks/{chunk-HR7RL4PB.js → chunk-VCKDVOPD.js} +2 -2
- package/dist/cli/chunks/{chunk-UZDTRCVU.js → chunk-VH3EB6ZG.js} +2 -2
- package/dist/cli/chunks/{chunk-6V6XVGCL.js → chunk-VLOIEVER.js} +3 -3
- package/dist/cli/chunks/{chunk-XTGVGZ4J.js → chunk-VML4SG3X.js} +3 -3
- package/dist/cli/chunks/{chunk-6TYTBQPV.js → chunk-VRJPH3LG.js} +2 -2
- package/dist/cli/chunks/{chunk-5WOBFN2T.js → chunk-VYDNLQJN.js} +2 -2
- package/dist/cli/chunks/{chunk-U5AVZ3T2.js → chunk-W3ZGNNDV.js} +1 -1
- package/dist/cli/chunks/{chunk-YGEC3PSD.js → chunk-WC47GICZ.js} +2 -2
- package/dist/cli/chunks/{chunk-WLOHTLHO.js → chunk-WLIYWBQR.js} +2 -2
- package/dist/cli/chunks/{chunk-I5VJ3FBC.js → chunk-WN55MNZ2.js} +2 -2
- package/dist/cli/chunks/chunk-WOZIXXY5.js +7 -0
- package/dist/cli/chunks/{chunk-X33LID2T.js → chunk-WR64BKUE.js} +1 -1
- package/dist/cli/chunks/{chunk-VGN46ZT4.js → chunk-WT3JC4A6.js} +2 -2
- package/dist/cli/chunks/{chunk-VOKIUF7I.js → chunk-X52TMBHU.js} +1 -1
- package/dist/cli/chunks/{chunk-ZATQLTYL.js → chunk-XIE7OHML.js} +1 -1
- package/dist/cli/chunks/{chunk-BO43BGHX.js → chunk-XNEEYXR2.js} +2 -2
- package/dist/cli/chunks/{chunk-KCBCYF7M.js → chunk-XNHB6TLC.js} +2 -2
- package/dist/cli/chunks/{chunk-VX7CQUO7.js → chunk-XQRE2HWM.js} +2 -2
- package/dist/cli/chunks/{chunk-CNQUU6CF.js → chunk-Y2E3IJ53.js} +2 -2
- package/dist/cli/chunks/{chunk-2M75CW5Q.js → chunk-Y2WMPEUP.js} +2 -2
- package/dist/cli/chunks/{chunk-WTMLRMKW.js → chunk-Y7GPLOXB.js} +2 -2
- package/dist/cli/chunks/{chunk-O66D4NEJ.js → chunk-YINFES3E.js} +2 -2
- package/dist/cli/chunks/{chunk-CF3BPD2R.js → chunk-ZLBBX24Q.js} +163 -164
- package/dist/cli/chunks/{chunk-S7D4GD7H.js → chunk-ZT3GUYM5.js} +2 -2
- package/dist/cli/chunks/{chunk-D5V6C3XG.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-DPHTFIGX.js → ci-output-7ZUQI4U6.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-PQ65VU2M.js → circuit-breaker-ALXKCFAL.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-GKHVO7AD.js → claude-flow-setup-RL7K2NI2.js} +2 -2
- package/dist/cli/chunks/client-C3KHVRM6.js +2 -0
- package/dist/cli/chunks/{cline-installer-HWMQZJ64.js → cline-installer-2Z2QQKC3.js} +2 -2
- package/dist/cli/chunks/{code-OTY7BF3D.js → code-QSZTDINQ.js} +4 -4
- package/dist/cli/chunks/{code-index-extractor-FG3TMHHR.js → code-index-extractor-5CGR5D3Y.js} +2 -2
- package/dist/cli/chunks/{codex-installer-63JARKKS.js → codex-installer-7JLSEDE5.js} +2 -2
- package/dist/cli/chunks/{completions-4ZHONFML.js → completions-U4NBSXEB.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-FYHTJW5Y.js → complexity-analyzer-WYZD2YSY.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-ZAWDSUR3.js → continuedev-installer-UPXINJFT.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-5QK565JX.js → copilot-installer-WIVYQRIF.js} +2 -2
- package/dist/cli/chunks/core-handlers-KSQM6Q6S.js +2 -0
- package/dist/cli/chunks/{cost-tracker-AWWMPPBJ.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-3BL7JACV.js → cursor-installer-POM7NGCC.js} +2 -2
- package/dist/cli/chunks/{daemon-R6ULBHHF.js → daemon-HFGKQ6LB.js} +3 -3
- package/dist/cli/chunks/{daemon-OJ624POF.js → daemon-M5TD5Y6T.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-J6I3LTMY.js → dag-attention-scheduler-HJXM7Q5P.js} +2 -2
- package/dist/cli/chunks/{detect-5Q5W33UR.js → detect-XKQGLZYN.js} +2 -2
- package/dist/cli/chunks/{dist-node-GJNW56NA.js → dist-node-SSKB53QL.js} +2 -2
- package/dist/cli/chunks/{domain-handler-IZQY2G44.js → domain-handler-6BNDHATU.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-PIGO3KI2.js → domain-plugins-DOX54YE3.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-NU3B4FQG.js → domain-transfer-FW4ZX3Z7.js} +2 -2
- package/dist/cli/chunks/dream-MIK2E4UL.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-5QDDRPWV.js → embed-and-insert-pattern-QST77T2B.js} +2 -2
- package/dist/cli/chunks/{eval-TB5HOAUY.js → eval-K7E4XXBS.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-SIYVLKDE.js → experience-capture-middleware-X66IYSRV.js} +3 -3
- package/dist/cli/chunks/{fast-paths-T7QELS6D.js → fast-paths-5JXXTYAG.js} +2 -2
- package/dist/cli/chunks/{feature-flags-TNZ7ZAJV.js → feature-flags-2CR3CO23.js} +2 -2
- package/dist/cli/chunks/{feature-flags-T3CNNYMJ.js → feature-flags-RB72LHOJ.js} +2 -2
- package/dist/cli/chunks/{file-discovery-M45P2ZCY.js → file-discovery-3NHRUQQB.js} +2 -2
- package/dist/cli/chunks/{fleet-DSBZPHBZ.js → fleet-SDU7QEOA.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-EHODCF32.js → gnn-wrapper-AWCFODUV.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-V5DBVF7V.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-IYKDYA2F.js → hnsw-legacy-bridge-KRS7SSFM.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-DKG4LW3X.js → hnswlib-node-OGGCPKPO.js} +2 -2
- package/dist/cli/chunks/{hooks-VKNMAILY.js → hooks-XNRNMUBW.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-FOUHTKAK.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-AXZVP7A7.js → hypergraph-engine-X35LTXYT.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-6EO6JN4Z.js → hypergraph-handler-M6THKAG6.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-GXYVX46O.js +2 -0
- package/dist/cli/chunks/{init-handler-N3NG3RHN.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-JICGAHLM.js → kilocode-installer-TEPR2ZJD.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-VYBFP6ZH.js → kiro-installer-RUKHGDEE.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-E2Z6K5EE.js +2 -0
- package/dist/cli/chunks/{learning-3BHEZEPK.js → learning-BEA26RNA.js} +3 -3
- package/dist/cli/chunks/{llm-router-GPTEZCUN.js → llm-router-7GECMDCP.js} +4 -4
- package/dist/cli/chunks/llm-router-service-YATYFEDD.js +2 -0
- package/dist/cli/chunks/{load-W5BIRPU4.js → load-NTJ4Y4ZR.js} +2 -2
- package/dist/cli/chunks/load-test-LV77JXWA.js +2 -0
- package/dist/cli/chunks/{mcp-EBV4DZPG.js → mcp-4335GTTG.js} +2 -2
- package/dist/cli/chunks/{memory-7F6YYKNL.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-3ZIA2YOL.js → multi-model-executor-T7FYKM6T.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-2XRZUTLR.js → opencode-installer-3USXVT5M.js} +2 -2
- package/dist/cli/chunks/{orchestrator-VSZVJUJW.js → orchestrator-VHUXUYIM.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-TAXMLENP.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-I2IGVHRL.js → pattern-usage-recorder-CMZLPX2K.js} +2 -2
- package/dist/cli/chunks/{pipeline-5G3O6WBY.js → pipeline-BTRZOVSL.js} +2 -2
- package/dist/cli/chunks/{platform-6GUFDIA3.js → platform-2MCRKC25.js} +2 -2
- package/dist/cli/chunks/{plugin-GYXE4CIC.js → plugin-2VAYWAO3.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-THX6JLGZ.js → prime-radiant-advanced-wasm-TXFEMBP6.js} +2 -2
- package/dist/cli/chunks/{project-root-QJRBKZQU.js → project-root-CFFPBGPX.js} +2 -2
- package/dist/cli/chunks/protocol-executor-ML76QAVQ.js +2 -0
- package/dist/cli/chunks/{protocol-handler-B54LRU26.js → protocol-handler-DZ26OYVZ.js} +2 -2
- package/dist/cli/chunks/{prove-PCY2WQOD.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-L3KXL6WE.js → quality-gate-ONJB7XU7.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-EWXNIXB6.js +2 -0
- package/dist/cli/chunks/{real-embeddings-N3H523PJ.js → real-embeddings-GZV4VKK4.js} +2 -2
- package/dist/cli/chunks/{ref-validation-6BKDPHZ7.js → ref-validation-HW5Y55ZC.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-NSGGTWXE.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-SRQNUBG3.js → routing-handler-CVHVOQTC.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-2IGULGDE.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-ZD6WK5CK.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-QULKUBBI.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-JW4EBARW.js → security-7723AZZ4.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-VQ7NJTGY.js → shared-rvf-adapter-KEQ5CLNI.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-SKTS52HK.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-3N4YJCSY.js → standalone-memory-MHZEEYMK.js} +2 -2
- package/dist/cli/chunks/{status-handler-5BQ2IIDG.js → status-handler-JKXPJ22K.js} +2 -2
- package/dist/cli/chunks/{structural-health-WGYR2RJB.js → structural-health-J4RKCYWF.js} +2 -2
- package/dist/cli/chunks/{sync-R5OKUBTQ.js → sync-EFWXMA2H.js} +2 -2
- package/dist/cli/chunks/{sync-DLKSXTIR.js → sync-PDPORHVN.js} +2 -2
- package/dist/cli/chunks/{task-handler-Z5KNTSUX.js → task-handler-VERADM44.js} +2 -2
- package/dist/cli/chunks/{task-handlers-RZFMYFSC.js → task-handlers-4RUCWUR2.js} +3 -3
- package/dist/cli/chunks/{test-LHWKZJRN.js → test-DMBJFQNL.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-EN7WXUMS.js → test-scheduling-LUPTVGCD.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-4V3OO4EC.js → token-bootstrap-S346YBVO.js} +2 -2
- package/dist/cli/chunks/{token-usage-PFC2BYBS.js → token-usage-VOA34IKM.js} +2 -2
- package/dist/cli/chunks/{transformers-VZCC4SHC.js → transformers-GU4TYAN5.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-ZYDQXGKN.js → tree-sitter-wasm-parser-MZPXAH7C.js} +2 -2
- package/dist/cli/chunks/{types-I6AWHZZQ.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-T7SG75PA.js → upgrade-M3ATDRMK.js} +2 -2
- package/dist/cli/chunks/{validate-YLYEHTY3.js → validate-AAP773B3.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-VTLTRUE3.js → validate-swarm-7RGAZX5F.js} +2 -2
- package/dist/cli/chunks/visual-security-L4J7LQWT.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-JUM7ZY5M.js → web-tree-sitter-GQMRHGGI.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-4KS2466T.js → windsurf-installer-HG6HF2GF.js} +2 -2
- package/dist/cli/chunks/witness-chain-CDUMX623.js +2 -0
- package/dist/cli/chunks/{witness-chain-E4X6TOCT.js → witness-chain-WKU3ZIBQ.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-MB53OZO6.js → witness-chain-repair-WNYH6O4L.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-LBWJHO7Y.js → witness-chain-verifier-Q2KW3QEQ.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-5IHVMXHJ.js → witness-key-manager-NQ5DAAC4.js} +2 -2
- package/dist/cli/chunks/{workflow-XUQXIRNE.js → workflow-CX6SHFBW.js} +5 -5
- package/dist/cli/chunks/workflow-orchestrator-USJDWVDR.js +2 -0
- package/dist/cli/chunks/{wrappers-YVF5SQUN.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/commands/workflow.js +3 -0
- package/dist/cli/scheduler/persistent-scheduler.d.ts +2 -0
- package/dist/cli/scheduler/persistent-scheduler.js +12 -2
- 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/code-intelligence/services/metric-collector/listing-process-owner.d.ts +3 -0
- package/dist/domains/code-intelligence/services/metric-collector/listing-process-owner.js +57 -0
- package/dist/domains/code-intelligence/services/metric-collector/test-counter.js +124 -36
- 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 +457 -453
- package/dist/mcp/handlers/domain-handler-configs.d.ts +60 -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/services/session-store.js +11 -1
- package/dist/mcp/tools/coverage-analysis/index.js +1 -0
- package/dist/mcp/types.d.ts +24 -0
- package/dist/memory/crdt/convergence-tracker.js +14 -24
- package/dist/memory/crdt/crdt-store.js +15 -0
- package/dist/memory/crdt/lww-register.js +3 -3
- package/dist/memory/crdt/or-set.js +18 -0
- package/dist/planning/goap-planner.js +18 -10
- package/dist/shared/embeddings/embedding-cache.d.ts +3 -3
- package/dist/shared/embeddings/embedding-cache.js +8 -8
- package/dist/shared/embeddings/nomic-embedder.js +9 -6
- package/dist/shared/events/domain-events.d.ts +2 -0
- package/dist/shared/llm/cache.js +1 -1
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-WQSFQES5.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-TDHBBADE.js +0 -2
- package/dist/cli/chunks/base-CZSB27VO.js +0 -2
- package/dist/cli/chunks/browser-workflow-AEMIS6PA.js +0 -2
- package/dist/cli/chunks/chunk-7IJVCDDC.js +0 -96
- package/dist/cli/chunks/chunk-INVDDFJC.js +0 -2
- package/dist/cli/chunks/chunk-K65X6CQA.js +0 -4
- package/dist/cli/chunks/chunk-MZDUBFLP.js +0 -2
- package/dist/cli/chunks/chunk-QDQLL2QB.js +0 -3
- package/dist/cli/chunks/chunk-QZBFMXO5.js +0 -742
- package/dist/cli/chunks/ci-JPISJ25U.js +0 -82
- package/dist/cli/chunks/client-BS7I637W.js +0 -2
- package/dist/cli/chunks/core-handlers-UG7RMTK5.js +0 -2
- package/dist/cli/chunks/coverage-SMFQEGKE.js +0 -27
- package/dist/cli/chunks/cross-domain-router-NX7F6TOF.js +0 -2
- package/dist/cli/chunks/dream-GYEH57FW.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-4TJ3T7LR.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-PHFK4EAP.js +0 -2
- package/dist/cli/chunks/hnsw-index-434XDDBH.js +0 -2
- package/dist/cli/chunks/hybrid-backend-DYVJQENQ.js +0 -2
- package/dist/cli/chunks/impact-analyzer-CBAST6M2.js +0 -2
- package/dist/cli/chunks/init-wizard-DWIJW7HY.js +0 -2
- package/dist/cli/chunks/kernel-AQGCS4X2.js +0 -2
- package/dist/cli/chunks/knowledge-graph-2ICXFUUV.js +0 -2
- package/dist/cli/chunks/llm-router-service-C47RGTH6.js +0 -2
- package/dist/cli/chunks/load-test-LRDAW3N6.js +0 -2
- package/dist/cli/chunks/memory-backend-UFBAYPQ6.js +0 -2
- package/dist/cli/chunks/memory-handlers-OGLJHAAJ.js +0 -2
- package/dist/cli/chunks/pattern-null-store-27FCITT3.js +0 -2
- package/dist/cli/chunks/protocol-executor-XWXXTMEW.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-3RMYXENE.js +0 -2
- package/dist/cli/chunks/quality-LPVDZC7U.js +0 -7
- package/dist/cli/chunks/queen-coordinator-AS6DZ7UJ.js +0 -2
- package/dist/cli/chunks/router-OVNLNGHO.js +0 -2
- package/dist/cli/chunks/routing-feedback-TBOWEB6H.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-YJYRCYGT.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-VMRQ2SFO.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-B75L3ALW.js +0 -2
- package/dist/cli/chunks/safe-db-CRQHMCV6.js +0 -2
- package/dist/cli/chunks/schedule-L3DKJRXU.js +0 -2
- package/dist/cli/chunks/scheduler-VRHYUGY5.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-JVAZETTL.js +0 -2
- package/dist/cli/chunks/unified-memory-WOOCCIUM.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-PDDHFLUB.js +0 -2
- package/dist/cli/chunks/unified-persistence-6ETD3JSC.js +0 -2
- package/dist/cli/chunks/visual-security-O4OT2YPY.js +0 -2
- package/dist/cli/chunks/witness-chain-67JHPDCN.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-ZVFSNRYZ.js +0 -2
|
@@ -10,6 +10,17 @@ import { toError } from '../../../shared/error-utils.js';
|
|
|
10
10
|
import { safeJsonParse } from '../../../shared/safe-json.js';
|
|
11
11
|
import { writeQualityEvidence } from '../../quality-assessment/quality-evidence.js';
|
|
12
12
|
import { getClaudeModelForTier } from '../../../shared/llm/model-registry.js';
|
|
13
|
+
/**
|
|
14
|
+
* Whether an analyze request carries instrumented (measured) coverage (#1008).
|
|
15
|
+
* Fail-closed: an explicit `request.measured` wins; otherwise only data a
|
|
16
|
+
* producer marked `instrumented: true` is measured. Anything without
|
|
17
|
+
* provenance is analyzed and returned, but never persisted as evidence.
|
|
18
|
+
*/
|
|
19
|
+
export function isMeasuredCoverage(request) {
|
|
20
|
+
if (typeof request.measured === 'boolean')
|
|
21
|
+
return request.measured;
|
|
22
|
+
return request.coverageData.instrumented === true;
|
|
23
|
+
}
|
|
13
24
|
const DEFAULT_CONFIG = {
|
|
14
25
|
defaultThreshold: 80,
|
|
15
26
|
enableLLMAnalysis: true, // On by default - opt-out
|
|
@@ -66,22 +77,30 @@ export class CoverageAnalyzerService {
|
|
|
66
77
|
// Check if coverage meets threshold
|
|
67
78
|
const overallCoverage = this.calculateOverallCoverage(summary);
|
|
68
79
|
const meetsThreshold = overallCoverage >= threshold;
|
|
80
|
+
// #1008: only instrumented coverage is evidence. A static estimate is
|
|
81
|
+
// analyzed and returned to the caller, but never compared against or
|
|
82
|
+
// written over a measurement, and never stored where a quality gate,
|
|
83
|
+
// quality_assess or another reader would take it as measured.
|
|
84
|
+
const measured = isMeasuredCoverage(request);
|
|
69
85
|
// Calculate delta from previous coverage (if stored)
|
|
70
|
-
const delta = await this.calculateDelta(summary);
|
|
86
|
+
const delta = measured ? await this.calculateDelta(summary) : undefined;
|
|
71
87
|
// Generate recommendations based on analysis
|
|
72
88
|
const recommendations = this.generateRecommendations(coverageData, summary, threshold);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
if (measured) {
|
|
90
|
+
// Store current coverage for future delta calculations
|
|
91
|
+
await this.storeCoverageSnapshot(summary);
|
|
92
|
+
// Store coverage vectors for similarity search + KV for quality-analyzer
|
|
93
|
+
if (request.includeFileDetails) {
|
|
94
|
+
await this.indexFileCoverageVectors(coverageData.files);
|
|
95
|
+
await this.storeFileCoverageKV(coverageData.files);
|
|
96
|
+
}
|
|
79
97
|
}
|
|
80
98
|
return ok({
|
|
81
99
|
summary,
|
|
82
100
|
meetsThreshold,
|
|
83
101
|
delta,
|
|
84
102
|
recommendations,
|
|
103
|
+
measured,
|
|
85
104
|
});
|
|
86
105
|
}
|
|
87
106
|
catch (error) {
|
|
@@ -440,8 +459,9 @@ Provide thoughtful, specific analysis based on the coverage data. Do not include
|
|
|
440
459
|
if (existing) {
|
|
441
460
|
await this.memory.set('coverage:previous', existing, { persist: true });
|
|
442
461
|
}
|
|
443
|
-
// Store latest snapshot
|
|
444
|
-
|
|
462
|
+
// Store latest snapshot, stamped with its provenance (#1008). Only
|
|
463
|
+
// measured coverage reaches this method.
|
|
464
|
+
await this.memory.set('coverage:latest', { ...summary, measured: true }, { persist: true });
|
|
445
465
|
await writeQualityEvidence(this.memory, { coverage: summary.line }, {
|
|
446
466
|
measuredAt: new Date().toISOString(),
|
|
447
467
|
source: 'coverage-analysis',
|
|
@@ -104,7 +104,8 @@ export function convertToQEReport(report, type) {
|
|
|
104
104
|
},
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
// #996: -1 means coverage was not measured; it is not a "-1%" coverage claim.
|
|
108
|
+
if (report.score.coverage >= 0 && report.score.coverage < 80) {
|
|
108
109
|
claims.push({
|
|
109
110
|
id: `coverage-${Date.now()}`,
|
|
110
111
|
type: 'coverage-claim',
|
|
@@ -33,6 +33,7 @@ import { DEFAULT_RATCHET_CONFIG, } from './coherence/types.js';
|
|
|
33
33
|
import { getWitnessChain } from '../../audit/witness-chain.js';
|
|
34
34
|
// Three-loop feature flag for instantAdapt protocol
|
|
35
35
|
import { isSONAThreeLoopEnabled } from '../../integrations/ruvector/feature-flags.js';
|
|
36
|
+
import { measuredCoverageSummary } from './coverage-report-event.js';
|
|
36
37
|
// CQ-002: Base domain coordinator
|
|
37
38
|
import { BaseDomainCoordinator, } from '../base-domain-coordinator.js';
|
|
38
39
|
const DEFAULT_CONFIG = {
|
|
@@ -819,15 +820,14 @@ export class QualityAssessmentCoordinator extends BaseDomainCoordinator {
|
|
|
819
820
|
}
|
|
820
821
|
async handleCoverageReportCreated(event) {
|
|
821
822
|
// Store coverage data for quality assessment
|
|
822
|
-
|
|
823
|
+
// #1008: only a report explicitly marked measured is coverage evidence.
|
|
824
|
+
// Estimates and look-alike events with no coverage figures (e.g. bridged
|
|
825
|
+
// captured experiences) must never touch `coverage:latest`.
|
|
826
|
+
const summary = measuredCoverageSummary(event.payload);
|
|
827
|
+
if (!summary)
|
|
828
|
+
return;
|
|
823
829
|
// Store under the canonical coverage key so quality-analyzer can read it
|
|
824
|
-
await this.memory.set('coverage:latest', {
|
|
825
|
-
line: payload.line,
|
|
826
|
-
branch: payload.branch,
|
|
827
|
-
function: 0,
|
|
828
|
-
statement: 0,
|
|
829
|
-
files: 0,
|
|
830
|
-
}, { persist: true });
|
|
830
|
+
await this.memory.set('coverage:latest', summary, { persist: true });
|
|
831
831
|
}
|
|
832
832
|
async handleSecurityAuditCompleted(event) {
|
|
833
833
|
// Store security findings for deployment decisions
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation of `coverage-analysis.CoverageReportCreated` payloads before the
|
|
3
|
+
* quality-assessment domain stores them as `coverage:latest` (#1008).
|
|
4
|
+
*
|
|
5
|
+
* Only a report its producer explicitly marked `measured: true`, carrying
|
|
6
|
+
* finite coverage figures, is coverage evidence. Anything else — a static
|
|
7
|
+
* estimate, a legacy event without provenance, or a look-alike event with no
|
|
8
|
+
* coverage figures at all — is ignored rather than written as zeros.
|
|
9
|
+
*/
|
|
10
|
+
/** The `coverage:latest` record written from a measured coverage report. */
|
|
11
|
+
export interface MeasuredCoverageSummary {
|
|
12
|
+
line: number;
|
|
13
|
+
branch: number;
|
|
14
|
+
function: number;
|
|
15
|
+
statement: number;
|
|
16
|
+
files: number;
|
|
17
|
+
/** Provenance stamp: this record came from instrumented coverage. */
|
|
18
|
+
measured: true;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Return the measured summary to store, or `null` when the payload is not
|
|
22
|
+
* measured coverage evidence.
|
|
23
|
+
*/
|
|
24
|
+
export declare function measuredCoverageSummary(payload: unknown): MeasuredCoverageSummary | null;
|
|
25
|
+
//# sourceMappingURL=coverage-report-event.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation of `coverage-analysis.CoverageReportCreated` payloads before the
|
|
3
|
+
* quality-assessment domain stores them as `coverage:latest` (#1008).
|
|
4
|
+
*
|
|
5
|
+
* Only a report its producer explicitly marked `measured: true`, carrying
|
|
6
|
+
* finite coverage figures, is coverage evidence. Anything else — a static
|
|
7
|
+
* estimate, a legacy event without provenance, or a look-alike event with no
|
|
8
|
+
* coverage figures at all — is ignored rather than written as zeros.
|
|
9
|
+
*/
|
|
10
|
+
const isPercent = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 100;
|
|
11
|
+
/**
|
|
12
|
+
* Return the measured summary to store, or `null` when the payload is not
|
|
13
|
+
* measured coverage evidence.
|
|
14
|
+
*/
|
|
15
|
+
export function measuredCoverageSummary(payload) {
|
|
16
|
+
if (!payload || typeof payload !== 'object')
|
|
17
|
+
return null;
|
|
18
|
+
const p = payload;
|
|
19
|
+
if (p.measured !== true)
|
|
20
|
+
return null;
|
|
21
|
+
if (!isPercent(p.line) || !isPercent(p.branch) || !isPercent(p.function) || !isPercent(p.statement)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const files = typeof p.files === 'number' && Number.isInteger(p.files) && p.files >= 0 ? p.files : null;
|
|
25
|
+
if (files === null)
|
|
26
|
+
return null;
|
|
27
|
+
return {
|
|
28
|
+
line: p.line,
|
|
29
|
+
branch: p.branch,
|
|
30
|
+
function: p.function,
|
|
31
|
+
statement: p.statement,
|
|
32
|
+
files,
|
|
33
|
+
measured: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=coverage-report-event.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence sufficiency for static quality analysis (#996).
|
|
3
|
+
*
|
|
4
|
+
* The static analyzer marks metrics it could not measure with the `-1`
|
|
5
|
+
* sentinel (or omits them). Such metrics must never be read as numbers that
|
|
6
|
+
* support a verdict: a pass computed without them is a pass on missing data.
|
|
7
|
+
*/
|
|
8
|
+
import { INSUFFICIENT_EVIDENCE, type QualityThresholdOverrides } from './quality-evidence.js';
|
|
9
|
+
/** `measured`: every requested metric has data. Otherwise no verdict may approve. */
|
|
10
|
+
export type StaticEvidenceStatus = 'measured' | typeof INSUFFICIENT_EVIDENCE;
|
|
11
|
+
/** Metric names the static quality analysis understands. */
|
|
12
|
+
export declare const STATIC_QUALITY_METRICS: readonly ["coverage", "complexity", "maintainability", "duplication", "testability", "security"];
|
|
13
|
+
/**
|
|
14
|
+
* #996: the coverage threshold that applies to a static assessment — the
|
|
15
|
+
* request's threshold, else the user-configured gate threshold, else the
|
|
16
|
+
* canonical default (undefined = use the default).
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveCoverageOverride(requested: number | undefined, configured: number | undefined): number | undefined;
|
|
19
|
+
export interface MeasuredFailure {
|
|
20
|
+
metric: string;
|
|
21
|
+
value: number;
|
|
22
|
+
threshold: number;
|
|
23
|
+
direction: 'min' | 'max';
|
|
24
|
+
}
|
|
25
|
+
export interface EvidenceSufficiency {
|
|
26
|
+
evidenceStatus: StaticEvidenceStatus;
|
|
27
|
+
/** Requested metrics backed by measured data. */
|
|
28
|
+
measured: string[];
|
|
29
|
+
/** Requested metrics with no measured data (missing, `-1`, or non-finite). */
|
|
30
|
+
unmeasured: string[];
|
|
31
|
+
/** Share of requested metrics that were measured, in [0, 1], two decimals. */
|
|
32
|
+
confidence: number;
|
|
33
|
+
}
|
|
34
|
+
/** A metric value is measured only if it is a finite, non-negative number. */
|
|
35
|
+
export declare function isMeasuredMetricValue(value: unknown): value is number;
|
|
36
|
+
/**
|
|
37
|
+
* #996 (N3): `metrics` must be a non-empty string[] of known names. A bare
|
|
38
|
+
* string would otherwise be spread into characters. Returns the de-duplicated
|
|
39
|
+
* list, or throws a caller-facing validation error.
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateRequestedMetrics(metrics: unknown): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Decide whether static analysis measured every requested metric.
|
|
44
|
+
*
|
|
45
|
+
* @param requested - metric names the caller asked to assess; when empty,
|
|
46
|
+
* the measured values themselves define the scope.
|
|
47
|
+
* @param values - metric values produced by the analyzer (`-1` = unmeasured).
|
|
48
|
+
*/
|
|
49
|
+
export declare function assessEvidenceSufficiency(requested: readonly string[], values: Readonly<Record<string, number | undefined>>): EvidenceSufficiency;
|
|
50
|
+
/**
|
|
51
|
+
* #996 (N2): measured metrics that already fail their own limit. Such a
|
|
52
|
+
* failure is conclusive — no unmeasured metric can turn it into a pass.
|
|
53
|
+
*/
|
|
54
|
+
export declare function findMeasuredFailures(measured: readonly string[], values: Readonly<Record<string, number | undefined>>, overrides?: QualityThresholdOverrides): MeasuredFailure[];
|
|
55
|
+
/** Plain-language recommendation for one measured failure. */
|
|
56
|
+
export declare function describeMeasuredFailure(failure: MeasuredFailure): string;
|
|
57
|
+
//# sourceMappingURL=evidence-sufficiency.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence sufficiency for static quality analysis (#996).
|
|
3
|
+
*
|
|
4
|
+
* The static analyzer marks metrics it could not measure with the `-1`
|
|
5
|
+
* sentinel (or omits them). Such metrics must never be read as numbers that
|
|
6
|
+
* support a verdict: a pass computed without them is a pass on missing data.
|
|
7
|
+
*/
|
|
8
|
+
import { INSUFFICIENT_EVIDENCE, resolveQualityThresholds, } from './quality-evidence.js';
|
|
9
|
+
/** Metric names the static quality analysis understands. */
|
|
10
|
+
export const STATIC_QUALITY_METRICS = [
|
|
11
|
+
'coverage', 'complexity', 'maintainability', 'duplication', 'testability', 'security',
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Static metrics that a measured value can fail on its own, mapped to the
|
|
15
|
+
* canonical gate metric whose effective threshold applies (by default
|
|
16
|
+
* coverage >= 80, duplication <= 5; see resolveQualityThresholds).
|
|
17
|
+
*/
|
|
18
|
+
const STATIC_TO_GATE_METRIC = {
|
|
19
|
+
coverage: 'coverage',
|
|
20
|
+
duplication: 'duplications',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* #996: the coverage threshold that applies to a static assessment — the
|
|
24
|
+
* request's threshold, else the user-configured gate threshold, else the
|
|
25
|
+
* canonical default (undefined = use the default).
|
|
26
|
+
*/
|
|
27
|
+
export function resolveCoverageOverride(requested, configured) {
|
|
28
|
+
return requested ?? configured;
|
|
29
|
+
}
|
|
30
|
+
/** A metric value is measured only if it is a finite, non-negative number. */
|
|
31
|
+
export function isMeasuredMetricValue(value) {
|
|
32
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* #996 (N3): `metrics` must be a non-empty string[] of known names. A bare
|
|
36
|
+
* string would otherwise be spread into characters. Returns the de-duplicated
|
|
37
|
+
* list, or throws a caller-facing validation error.
|
|
38
|
+
*/
|
|
39
|
+
export function validateRequestedMetrics(metrics) {
|
|
40
|
+
const known = STATIC_QUALITY_METRICS;
|
|
41
|
+
const message = `metrics must be a non-empty array of metric names (${known.join(', ')}).`;
|
|
42
|
+
if (!Array.isArray(metrics) || metrics.length === 0)
|
|
43
|
+
throw new Error(message);
|
|
44
|
+
const unknown = metrics.filter((m) => typeof m !== 'string' || !known.includes(m));
|
|
45
|
+
if (unknown.length > 0) {
|
|
46
|
+
throw new Error(`${message} Unknown: ${unknown.map((m) => JSON.stringify(m)).join(', ')}.`);
|
|
47
|
+
}
|
|
48
|
+
return [...new Set(metrics)];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Decide whether static analysis measured every requested metric.
|
|
52
|
+
*
|
|
53
|
+
* @param requested - metric names the caller asked to assess; when empty,
|
|
54
|
+
* the measured values themselves define the scope.
|
|
55
|
+
* @param values - metric values produced by the analyzer (`-1` = unmeasured).
|
|
56
|
+
*/
|
|
57
|
+
export function assessEvidenceSufficiency(requested, values) {
|
|
58
|
+
const scope = requested.length > 0
|
|
59
|
+
? [...new Set(requested)]
|
|
60
|
+
: Object.keys(values).filter((name) => isMeasuredMetricValue(values[name]));
|
|
61
|
+
const measured = scope.filter((name) => isMeasuredMetricValue(values[name]));
|
|
62
|
+
const unmeasured = scope.filter((name) => !isMeasuredMetricValue(values[name]));
|
|
63
|
+
const confidence = scope.length === 0
|
|
64
|
+
? 0
|
|
65
|
+
: Math.round((measured.length / scope.length) * 100) / 100;
|
|
66
|
+
return {
|
|
67
|
+
evidenceStatus: unmeasured.length === 0 && measured.length > 0 ? 'measured' : INSUFFICIENT_EVIDENCE,
|
|
68
|
+
measured,
|
|
69
|
+
unmeasured,
|
|
70
|
+
confidence,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* #996 (N2): measured metrics that already fail their own limit. Such a
|
|
75
|
+
* failure is conclusive — no unmeasured metric can turn it into a pass.
|
|
76
|
+
*/
|
|
77
|
+
export function findMeasuredFailures(measured, values, overrides = {}) {
|
|
78
|
+
const thresholds = resolveQualityThresholds(overrides);
|
|
79
|
+
const failures = [];
|
|
80
|
+
for (const metric of measured) {
|
|
81
|
+
const gateMetric = STATIC_TO_GATE_METRIC[metric];
|
|
82
|
+
const limit = gateMetric ? thresholds[gateMetric] : undefined;
|
|
83
|
+
const value = values[metric];
|
|
84
|
+
if (!limit || !isMeasuredMetricValue(value))
|
|
85
|
+
continue;
|
|
86
|
+
const fails = limit.direction === 'min' ? value < limit.value : value > limit.value;
|
|
87
|
+
if (fails)
|
|
88
|
+
failures.push({ metric, value, threshold: limit.value, direction: limit.direction });
|
|
89
|
+
}
|
|
90
|
+
return failures;
|
|
91
|
+
}
|
|
92
|
+
/** Plain-language recommendation for one measured failure. */
|
|
93
|
+
export function describeMeasuredFailure(failure) {
|
|
94
|
+
const bound = failure.direction === 'min' ? 'at least' : 'at most';
|
|
95
|
+
return `${failure.metric} measured at ${failure.value} fails its threshold (${bound} ${failure.threshold}).`;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=evidence-sufficiency.js.map
|
|
@@ -9,7 +9,7 @@ export { QualityAssessmentCoordinator, type IQualityAssessmentCoordinator, type
|
|
|
9
9
|
export { QualityGateService, type IQualityGateService, type QualityGateConfig, } from './services/quality-gate';
|
|
10
10
|
export { QualityAnalyzerService, type IQualityAnalyzerService, type QualityAnalyzerConfig, } from './services/quality-analyzer';
|
|
11
11
|
export { DeploymentAdvisorService, type IDeploymentAdvisorService, type DeploymentAdvisorConfig, type DeploymentAccuracy, } from './services/deployment-advisor';
|
|
12
|
-
export { DEFAULT_QUALITY_EVIDENCE_MAX_AGE_MS, DEFAULT_QUALITY_THRESHOLDS, QUALITY_EVIDENCE_NAMESPACE, QUALITY_METRICS, evaluateQualityEvidence, loadQualityEvidence, writeQualityEvidence, type EvaluatedQualityCheck, type QualityEvidenceRecord, type QualityEvidenceValues, type QualityMetricName, type QualityThreshold, } from './quality-evidence.js';
|
|
12
|
+
export { DEFAULT_QUALITY_EVIDENCE_MAX_AGE_MS, DEFAULT_QUALITY_THRESHOLDS, QUALITY_EVIDENCE_NAMESPACE, QUALITY_METRICS, INSUFFICIENT_EVIDENCE, InsufficientQualityEvidenceError, evaluateQualityEvidence, inspectQualityEvidence, loadQualityEvidence, writeQualityEvidence, type EvaluatedQualityCheck, type QualityEvidenceRecord, type QualityEvidenceValues, type QualityMetricName, type QualityThreshold, } from './quality-evidence.js';
|
|
13
13
|
export { CoherenceGateService, createCoherenceGateService, type CoherenceGateResult, type CoherenceGateServiceConfig, } from './services/coherence-gate';
|
|
14
14
|
export * from './coherence';
|
|
15
15
|
export type { QualityAssessmentAPI, GateEvaluationRequest, QualityAnalysisRequest, DeploymentRequest, ComplexityRequest, GateResult, GateCheck, QualityReport, QualityMetricDetail, QualityTrend, Recommendation, DeploymentAdvice, ComplexityReport, FileComplexity, ComplexitySummary, ComplexityHotspot, QualityMetrics, GateThresholds, } from './interfaces';
|
|
@@ -18,7 +18,7 @@ export { QualityAssessmentCoordinator, } from './coordinator.js';
|
|
|
18
18
|
export { QualityGateService, } from './services/quality-gate.js';
|
|
19
19
|
export { QualityAnalyzerService, } from './services/quality-analyzer.js';
|
|
20
20
|
export { DeploymentAdvisorService, } from './services/deployment-advisor.js';
|
|
21
|
-
export { DEFAULT_QUALITY_EVIDENCE_MAX_AGE_MS, DEFAULT_QUALITY_THRESHOLDS, QUALITY_EVIDENCE_NAMESPACE, QUALITY_METRICS, evaluateQualityEvidence, loadQualityEvidence, writeQualityEvidence, } from './quality-evidence.js';
|
|
21
|
+
export { DEFAULT_QUALITY_EVIDENCE_MAX_AGE_MS, DEFAULT_QUALITY_THRESHOLDS, QUALITY_EVIDENCE_NAMESPACE, QUALITY_METRICS, INSUFFICIENT_EVIDENCE, InsufficientQualityEvidenceError, evaluateQualityEvidence, inspectQualityEvidence, loadQualityEvidence, writeQualityEvidence, } from './quality-evidence.js';
|
|
22
22
|
// ============================================================================
|
|
23
23
|
// Coherence-Gated Quality Gates (ADR-030)
|
|
24
24
|
// ============================================================================
|
|
@@ -8,6 +8,7 @@ import { QualityAssessmentCoordinator, } from './coordinator.js';
|
|
|
8
8
|
import { QualityGateService, } from './services/quality-gate.js';
|
|
9
9
|
import { QualityAnalyzerService, } from './services/quality-analyzer.js';
|
|
10
10
|
import { toError } from '../../shared/error-utils.js';
|
|
11
|
+
import { measuredCoverageSummary } from './coverage-report-event.js';
|
|
11
12
|
import { DeploymentAdvisorService, } from './services/deployment-advisor.js';
|
|
12
13
|
/**
|
|
13
14
|
* Quality Assessment Domain Plugin
|
|
@@ -285,15 +286,14 @@ export class QualityAssessmentPlugin extends BaseDomainPlugin {
|
|
|
285
286
|
}
|
|
286
287
|
}
|
|
287
288
|
async handleCoverageReport(event) {
|
|
288
|
-
|
|
289
|
+
// #1008: only a report explicitly marked measured is coverage evidence.
|
|
290
|
+
// Estimates and look-alike events with no coverage figures (e.g. bridged
|
|
291
|
+
// captured experiences) must never touch `coverage:latest`.
|
|
292
|
+
const summary = measuredCoverageSummary(event.payload);
|
|
293
|
+
if (!summary)
|
|
294
|
+
return;
|
|
289
295
|
// Store under the canonical coverage key so quality-analyzer can read it
|
|
290
|
-
await this.memory.set('coverage:latest', {
|
|
291
|
-
line: payload.line,
|
|
292
|
-
branch: payload.branch,
|
|
293
|
-
function: payload.function,
|
|
294
|
-
statement: payload.statement,
|
|
295
|
-
files: 0,
|
|
296
|
-
}, { persist: true });
|
|
296
|
+
await this.memory.set('coverage:latest', summary, { persist: true });
|
|
297
297
|
}
|
|
298
298
|
async handleDefectPrediction(event) {
|
|
299
299
|
const payload = event.payload;
|
|
@@ -29,13 +29,61 @@ export declare function writeQualityEvidence(memory: MemoryBackend, values: Part
|
|
|
29
29
|
measuredAt: string;
|
|
30
30
|
source: string;
|
|
31
31
|
}): Promise<void>;
|
|
32
|
+
/** #996: the single status word for "a verdict cannot be reached on this evidence". */
|
|
33
|
+
export declare const INSUFFICIENT_EVIDENCE: "insufficient-evidence";
|
|
34
|
+
/** #996: one recommendation per unmeasured metric, naming what to run. */
|
|
35
|
+
export declare function describeMissingMetrics(unmeasured: readonly string[]): string[];
|
|
36
|
+
/** Why a canonical metric has no usable evidence. */
|
|
37
|
+
export interface UnusableQualityEvidence {
|
|
38
|
+
metric: QualityMetricName;
|
|
39
|
+
reason: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* #996: thrown when the measured gate cannot be evaluated. The message is the
|
|
43
|
+
* first problem found (unchanged wording); `unmeasured` names every metric
|
|
44
|
+
* whose record is absent, stale, future-dated or malformed.
|
|
45
|
+
*/
|
|
46
|
+
export declare class InsufficientQualityEvidenceError extends Error {
|
|
47
|
+
readonly status: "insufficient-evidence";
|
|
48
|
+
readonly unmeasured: QualityMetricName[];
|
|
49
|
+
readonly problems: UnusableQualityEvidence[];
|
|
50
|
+
constructor(problems: UnusableQualityEvidence[]);
|
|
51
|
+
/** Structured, non-passing description of the gate that could not run. */
|
|
52
|
+
toDetails(): {
|
|
53
|
+
passed: false;
|
|
54
|
+
status: typeof INSUFFICIENT_EVIDENCE;
|
|
55
|
+
evidenceStatus: typeof INSUFFICIENT_EVIDENCE;
|
|
56
|
+
unmeasured: QualityMetricName[];
|
|
57
|
+
gateEvaluated: false;
|
|
58
|
+
recommendations: string[];
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Inspect every canonical metric with the same validation, collecting each
|
|
63
|
+
* absent, stale, future-dated or malformed record instead of stopping at the first.
|
|
64
|
+
*/
|
|
65
|
+
export declare function inspectQualityEvidence(memory: MemoryBackend, options?: {
|
|
66
|
+
now?: number;
|
|
67
|
+
maxAgeMs?: number;
|
|
68
|
+
}): Promise<{
|
|
69
|
+
values: Partial<QualityEvidenceValues>;
|
|
70
|
+
problems: UnusableQualityEvidence[];
|
|
71
|
+
}>;
|
|
32
72
|
export declare function loadQualityEvidence(memory: MemoryBackend, options?: {
|
|
33
73
|
now?: number;
|
|
34
74
|
maxAgeMs?: number;
|
|
35
75
|
}): Promise<QualityEvidenceValues>;
|
|
36
|
-
|
|
76
|
+
/** Threshold overrides a caller or user configuration may apply to the canonical defaults. */
|
|
77
|
+
export interface QualityThresholdOverrides {
|
|
37
78
|
coverage?: number;
|
|
38
|
-
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The single source of effective quality thresholds: canonical defaults with
|
|
82
|
+
* any override applied. Used by the measured gate and by static analysis
|
|
83
|
+
* (#996) so the two never disagree.
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolveQualityThresholds(overrides?: QualityThresholdOverrides): Record<QualityMetricName, QualityThreshold>;
|
|
86
|
+
export declare function evaluateQualityEvidence(values: QualityEvidenceValues, thresholds?: QualityThresholdOverrides): {
|
|
39
87
|
passed: boolean;
|
|
40
88
|
checks: EvaluatedQualityCheck[];
|
|
41
89
|
recommendations: string[];
|
|
@@ -78,27 +78,109 @@ export async function writeQualityEvidence(memory, values, metadata) {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
/** #996: the single status word for "a verdict cannot be reached on this evidence". */
|
|
82
|
+
export const INSUFFICIENT_EVIDENCE = 'insufficient-evidence';
|
|
83
|
+
/** #996: what to run to measure a metric that has no usable evidence. */
|
|
84
|
+
// Advice names only producers a user can actually run. Metrics with no
|
|
85
|
+
// exposed producer say so instead of pointing at an unreachable tool.
|
|
86
|
+
const NO_EXPOSED_PRODUCER = 'no MCP tool or CLI command records it yet, so supply it from your own measurement';
|
|
87
|
+
const MISSING_METRIC_ADVICE = {
|
|
88
|
+
coverage: 'run the tests with coverage instrumentation enabled so measured line coverage is recorded '
|
|
89
|
+
+ '(a static estimate is not measured coverage)',
|
|
90
|
+
testsPassing: 'run the test suite (test_execute_parallel, or `aqe test execute`)',
|
|
91
|
+
// The static analyzer has no security measurement; a scan reports findings separately.
|
|
92
|
+
security: 'static analysis never measures security; drop it from metrics and use '
|
|
93
|
+
+ 'security_scan_comprehensive (or `aqe security`) for findings',
|
|
94
|
+
securityVulnerabilities: `a measured vulnerability count is required; ${NO_EXPOSED_PRODUCER}`,
|
|
95
|
+
criticalBugs: `a measured critical-bug count is required; ${NO_EXPOSED_PRODUCER}`,
|
|
96
|
+
codeSmells: `a measured code-smell count is required; ${NO_EXPOSED_PRODUCER}`,
|
|
97
|
+
technicalDebt: `a measured technical-debt ratio is required; ${NO_EXPOSED_PRODUCER}`,
|
|
98
|
+
duplications: `a measured duplication percentage is required; ${NO_EXPOSED_PRODUCER}`,
|
|
99
|
+
complexity: 'make sure the target contains readable TypeScript/JavaScript source the analyzer can parse',
|
|
100
|
+
maintainability: 'make sure the target contains readable TypeScript/JavaScript source the analyzer can parse',
|
|
101
|
+
testability: 'make sure the target contains readable TypeScript/JavaScript source the analyzer can parse',
|
|
102
|
+
duplication: 'make sure the target contains readable TypeScript/JavaScript source the analyzer can parse',
|
|
103
|
+
};
|
|
104
|
+
/** #996: one recommendation per unmeasured metric, naming what to run. */
|
|
105
|
+
export function describeMissingMetrics(unmeasured) {
|
|
106
|
+
return unmeasured.map((metric) => `Insufficient evidence: ${metric} not measured — ${MISSING_METRIC_ADVICE[metric] ?? 'measure it'}.`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* #996: thrown when the measured gate cannot be evaluated. The message is the
|
|
110
|
+
* first problem found (unchanged wording); `unmeasured` names every metric
|
|
111
|
+
* whose record is absent, stale, future-dated or malformed.
|
|
112
|
+
*/
|
|
113
|
+
export class InsufficientQualityEvidenceError extends Error {
|
|
114
|
+
status = INSUFFICIENT_EVIDENCE;
|
|
115
|
+
unmeasured;
|
|
116
|
+
problems;
|
|
117
|
+
constructor(problems) {
|
|
118
|
+
super(problems[0]?.reason ?? 'Measured quality evidence is unavailable.');
|
|
119
|
+
this.name = 'InsufficientQualityEvidenceError';
|
|
120
|
+
this.problems = problems;
|
|
121
|
+
this.unmeasured = problems.map((p) => p.metric);
|
|
122
|
+
}
|
|
123
|
+
/** Structured, non-passing description of the gate that could not run. */
|
|
124
|
+
toDetails() {
|
|
125
|
+
return {
|
|
126
|
+
passed: false,
|
|
127
|
+
status: INSUFFICIENT_EVIDENCE,
|
|
128
|
+
evidenceStatus: INSUFFICIENT_EVIDENCE,
|
|
129
|
+
unmeasured: this.unmeasured,
|
|
130
|
+
gateEvaluated: false,
|
|
131
|
+
recommendations: describeMissingMetrics(this.unmeasured),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Inspect every canonical metric with the same validation, collecting each
|
|
137
|
+
* absent, stale, future-dated or malformed record instead of stopping at the first.
|
|
138
|
+
*/
|
|
139
|
+
export async function inspectQualityEvidence(memory, options = {}) {
|
|
82
140
|
const now = options.now ?? Date.now();
|
|
83
141
|
const maxAgeMs = options.maxAgeMs ?? DEFAULT_QUALITY_EVIDENCE_MAX_AGE_MS;
|
|
84
142
|
const values = {};
|
|
143
|
+
const problems = [];
|
|
85
144
|
for (const metric of QUALITY_METRICS) {
|
|
86
145
|
const record = await memory.get(evidenceKey(metric), {
|
|
87
146
|
namespace: QUALITY_EVIDENCE_NAMESPACE,
|
|
88
147
|
});
|
|
89
|
-
|
|
90
|
-
|
|
148
|
+
try {
|
|
149
|
+
validateRecord(record, metric, now, maxAgeMs);
|
|
150
|
+
values[metric] = record.value;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
problems.push({ metric, reason: error instanceof Error ? error.message : String(error) });
|
|
154
|
+
}
|
|
91
155
|
}
|
|
156
|
+
return { values, problems };
|
|
157
|
+
}
|
|
158
|
+
export async function loadQualityEvidence(memory, options = {}) {
|
|
159
|
+
const { values, problems } = await inspectQualityEvidence(memory, options);
|
|
160
|
+
if (problems.length > 0)
|
|
161
|
+
throw new InsufficientQualityEvidenceError(problems);
|
|
92
162
|
return values;
|
|
93
163
|
}
|
|
94
|
-
|
|
95
|
-
|
|
164
|
+
/**
|
|
165
|
+
* The single source of effective quality thresholds: canonical defaults with
|
|
166
|
+
* any override applied. Used by the measured gate and by static analysis
|
|
167
|
+
* (#996) so the two never disagree.
|
|
168
|
+
*/
|
|
169
|
+
export function resolveQualityThresholds(overrides = {}) {
|
|
170
|
+
if (overrides.coverage !== undefined && (!Number.isFinite(overrides.coverage) || overrides.coverage < 0 || overrides.coverage > 100)) {
|
|
96
171
|
throw new Error('Coverage quality threshold must be a finite number between 0 and 100.');
|
|
97
172
|
}
|
|
173
|
+
return {
|
|
174
|
+
...DEFAULT_QUALITY_THRESHOLDS,
|
|
175
|
+
...(overrides.coverage !== undefined
|
|
176
|
+
? { coverage: { ...DEFAULT_QUALITY_THRESHOLDS.coverage, value: overrides.coverage } }
|
|
177
|
+
: {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export function evaluateQualityEvidence(values, thresholds = {}) {
|
|
181
|
+
const effective = resolveQualityThresholds(thresholds);
|
|
98
182
|
const checks = QUALITY_METRICS.map((name) => {
|
|
99
|
-
const threshold = name
|
|
100
|
-
? { ...DEFAULT_QUALITY_THRESHOLDS[name], value: thresholds.coverage }
|
|
101
|
-
: DEFAULT_QUALITY_THRESHOLDS[name];
|
|
183
|
+
const threshold = effective[name];
|
|
102
184
|
const value = values[name];
|
|
103
185
|
return {
|
|
104
186
|
name,
|
|
@@ -152,11 +152,13 @@ Focus on:
|
|
|
152
152
|
prompt += `- **${metric.name}**: ${metric.value} (Rating: ${metric.rating}, Trend: ${metric.trend})\n`;
|
|
153
153
|
}
|
|
154
154
|
prompt += `\n`;
|
|
155
|
+
// #996: -1 means "not measured"; never present it to the model as a value.
|
|
156
|
+
const show = (value, unit = '') => (value >= 0 ? `${value}${unit}` : 'not measured');
|
|
155
157
|
prompt += `### Score Breakdown:\n`;
|
|
156
|
-
prompt += `- Coverage: ${score.coverage}
|
|
157
|
-
prompt += `- Complexity: ${score.complexity}\n`;
|
|
158
|
-
prompt += `- Maintainability: ${score.maintainability}\n`;
|
|
159
|
-
prompt += `- Security: ${score.security}\n\n`;
|
|
158
|
+
prompt += `- Coverage: ${show(score.coverage, '%')}\n`;
|
|
159
|
+
prompt += `- Complexity: ${show(score.complexity)}\n`;
|
|
160
|
+
prompt += `- Maintainability: ${show(score.maintainability)}\n`;
|
|
161
|
+
prompt += `- Security: ${show(score.security)}\n\n`;
|
|
160
162
|
if (codeContext) {
|
|
161
163
|
prompt += `### Code Context:\n\`\`\`\n${codeContext.slice(0, 2000)}\n\`\`\`\n\n`;
|
|
162
164
|
}
|
|
@@ -480,13 +482,15 @@ Focus on:
|
|
|
480
482
|
}
|
|
481
483
|
const overall = totalWeight > 0 ? Math.round(weightedSum / totalWeight) : 0;
|
|
482
484
|
// Use -1 to signal "no data available" rather than 0 which implies "0% coverage"
|
|
483
|
-
|
|
485
|
+
// (#996: the same holds for every score field — never fabricate a value).
|
|
486
|
+
const valueOf = (name) => metrics.find((m) => m.name === name)?.value ?? -1;
|
|
484
487
|
return {
|
|
485
488
|
overall,
|
|
486
|
-
coverage:
|
|
487
|
-
complexity:
|
|
488
|
-
maintainability:
|
|
489
|
-
security
|
|
489
|
+
coverage: valueOf('coverage'),
|
|
490
|
+
complexity: valueOf('complexity'),
|
|
491
|
+
maintainability: valueOf('maintainability'),
|
|
492
|
+
// No security analysis runs here; -1 = not measured (was a fixed 85 placeholder).
|
|
493
|
+
security: -1,
|
|
490
494
|
};
|
|
491
495
|
}
|
|
492
496
|
async generateTrends(currentMetrics, _compareBaseline) {
|