agentic-qe 3.14.5 → 3.14.6
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 +76 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/adapters/ag-ui/event-types.d.ts +1 -1
- package/dist/audit/witness-chain-hash.d.ts +18 -0
- package/dist/audit/witness-chain-hash.js +37 -0
- package/dist/audit/witness-chain-repair.d.ts +71 -0
- package/dist/audit/witness-chain-repair.js +203 -0
- package/dist/audit/witness-chain-verifier.d.ts +152 -0
- package/dist/audit/witness-chain-verifier.js +293 -0
- package/dist/audit/witness-chain.d.ts +10 -43
- package/dist/audit/witness-chain.js +16 -106
- package/dist/audit/witness-findings.js +4 -1
- package/dist/cli/bundle.js +7 -7
- package/dist/cli/chunks/adapter-UYOJPTOX.js +2 -0
- package/dist/cli/chunks/agent-booster-wasm-2YGML6OU.js +2 -0
- package/dist/cli/chunks/{agent-handler-V6CZ7Q6S.js → agent-handler-D5SSQYNU.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-ZMD6ULC3.js → agent-memory-branch-YHPLTITV.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-JR5AVQXR.js +2 -0
- package/dist/cli/chunks/{arena-QLSBESC7.js → arena-7BGOXGXO.js} +2 -2
- package/dist/cli/chunks/{arena-4UPAEHFT.js → arena-MCE6EU7K.js} +4 -4
- package/dist/cli/chunks/audit-BMWTQECB.js +4 -0
- package/dist/cli/chunks/base-DRZ2LS6X.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-4DSBPDRH.js → better-sqlite3-PMUNGASU.js} +2 -2
- package/dist/cli/chunks/{brain-handler-GBY4EZ4P.js → brain-handler-QPUFYX7F.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-XYBVXCNO.js → branch-enumerator-WKFDGRN4.js} +2 -2
- package/dist/cli/chunks/{browser-32F6MREU.js → browser-VY5HKH5X.js} +2 -2
- package/dist/cli/chunks/browser-workflow-CJ7T3MXF.js +2 -0
- package/dist/cli/chunks/{chunk-C3Z4VVHP.js → chunk-257E2A5M.js} +5 -5
- package/dist/cli/chunks/{chunk-EFV4ADMO.js → chunk-2JVWITNK.js} +2 -2
- package/dist/cli/chunks/{chunk-IGBEJ4UJ.js → chunk-2NPKIBAZ.js} +2 -2
- package/dist/cli/chunks/{chunk-KIP6WZGV.js → chunk-2TMWAQQ3.js} +3 -3
- package/dist/cli/chunks/{chunk-DLF5BOJD.js → chunk-2YXGBZWV.js} +1 -1
- package/dist/cli/chunks/{chunk-KEY43ANX.js → chunk-3EA536JF.js} +2 -2
- package/dist/cli/chunks/{chunk-WX6RRIGW.js → chunk-3EZOZN25.js} +2 -2
- package/dist/cli/chunks/{chunk-BYG36QC5.js → chunk-3HZS4M3O.js} +2 -2
- package/dist/cli/chunks/{chunk-G3L5L6YQ.js → chunk-3NIG7S5W.js} +1 -1
- package/dist/cli/chunks/{chunk-CZO4BJG5.js → chunk-4N23RFDU.js} +2 -2
- package/dist/cli/chunks/{chunk-QWUXCG2L.js → chunk-5J6W7SIA.js} +1 -1
- package/dist/cli/chunks/{chunk-RD2VGOUH.js → chunk-5OOMJGFN.js} +1 -1
- package/dist/cli/chunks/{chunk-YDFL445W.js → chunk-5QQSIGUA.js} +2 -2
- package/dist/cli/chunks/{chunk-TUSSPKRM.js → chunk-5VFPCSK7.js} +1 -1
- package/dist/cli/chunks/{chunk-WLXK2KNU.js → chunk-62N4NUJH.js} +2 -2
- package/dist/cli/chunks/{chunk-JSZ663MU.js → chunk-64VGZQLB.js} +1 -1
- package/dist/cli/chunks/{chunk-UMGFMKDW.js → chunk-66VWCR67.js} +2 -2
- package/dist/cli/chunks/{chunk-6ITZZIQX.js → chunk-6LIHFV7O.js} +2 -2
- package/dist/cli/chunks/{chunk-DKUBQQFG.js → chunk-6OS76PHI.js} +2 -2
- package/dist/cli/chunks/{chunk-Y5L3ES4L.js → chunk-6RE3X4V5.js} +2 -2
- package/dist/cli/chunks/{chunk-CVMNJSCB.js → chunk-6SH5VZUD.js} +2 -2
- package/dist/cli/chunks/chunk-6SQM2MUX.js +4 -0
- package/dist/cli/chunks/{chunk-6CR4VQBQ.js → chunk-6U7LNMWZ.js} +2 -2
- package/dist/cli/chunks/{chunk-HYEJJJY3.js → chunk-72KXSMWI.js} +1 -1
- package/dist/cli/chunks/chunk-7CUQCCMD.js +27 -0
- package/dist/cli/chunks/chunk-7D3V65N5.js +2 -0
- package/dist/cli/chunks/{chunk-K7NJHFLZ.js → chunk-7J6QC567.js} +3 -3
- package/dist/cli/chunks/{chunk-6LKDHEBY.js → chunk-7LPR6HJG.js} +2 -2
- package/dist/cli/chunks/{chunk-RGGK6VZ7.js → chunk-7NITCZWD.js} +1 -1
- package/dist/cli/chunks/{chunk-IYTLXUBO.js → chunk-7Z5LHRC3.js} +2 -2
- package/dist/cli/chunks/{chunk-ZCWERUYB.js → chunk-AHKELLIO.js} +3 -3
- package/dist/cli/chunks/{chunk-IJHCIXJC.js → chunk-AIRGNL55.js} +2 -2
- package/dist/cli/chunks/{chunk-2OMLTYQK.js → chunk-AJRUJAAK.js} +1 -1
- package/dist/cli/chunks/{chunk-QYOGD2VW.js → chunk-AVBJYI5I.js} +1 -1
- package/dist/cli/chunks/{chunk-PSPKSUF6.js → chunk-B6D2CHEH.js} +1 -1
- package/dist/cli/chunks/{chunk-M23ZOZVY.js → chunk-B6MOJC3X.js} +1 -1
- package/dist/cli/chunks/{chunk-VD5IO5EO.js → chunk-BAMN2CHI.js} +1 -1
- package/dist/cli/chunks/{chunk-KO4FNAUR.js → chunk-BBT64TII.js} +3 -3
- package/dist/cli/chunks/{chunk-7JZJJA7U.js → chunk-BJTJLJRZ.js} +3 -3
- package/dist/cli/chunks/{chunk-LULD4JV2.js → chunk-BMAPORJ7.js} +2 -2
- package/dist/cli/chunks/{chunk-GTKCGPJZ.js → chunk-BPEDWS6O.js} +2 -2
- package/dist/cli/chunks/{chunk-3DDXWYMO.js → chunk-BVR7RMC5.js} +1 -1
- package/dist/cli/chunks/{chunk-52L77RMG.js → chunk-C6KWXUFJ.js} +2 -2
- package/dist/cli/chunks/{chunk-BJPL6THQ.js → chunk-CCK4BF76.js} +1 -1
- package/dist/cli/chunks/{chunk-RP2ZKPYV.js → chunk-CD542DNJ.js} +1 -1
- package/dist/cli/chunks/{chunk-AFEDJ3RU.js → chunk-CF2ISEOJ.js} +2 -2
- package/dist/cli/chunks/chunk-CM7U6TAX.js +5 -0
- package/dist/cli/chunks/{chunk-R74ZKREV.js → chunk-D45SG6CP.js} +1 -1
- package/dist/cli/chunks/{chunk-YXP6BKGS.js → chunk-D6CJIGRU.js} +89 -83
- package/dist/cli/chunks/{chunk-NVYBM3R4.js → chunk-DBDPRORT.js} +2 -2
- package/dist/cli/chunks/{chunk-CYE2TJFV.js → chunk-DHVX5UB2.js} +2 -2
- package/dist/cli/chunks/{chunk-XUR2M2WB.js → chunk-DK4XN4CU.js} +2 -2
- package/dist/cli/chunks/{chunk-W2XCZU62.js → chunk-DPYSUDAO.js} +1 -1
- package/dist/cli/chunks/{chunk-WJHWH5D2.js → chunk-DUYOVM5I.js} +2 -2
- package/dist/cli/chunks/{chunk-XLAUGSW7.js → chunk-DZ3AUAAB.js} +2 -2
- package/dist/cli/chunks/{chunk-37TUN44F.js → chunk-E6G2RD5H.js} +2 -2
- package/dist/cli/chunks/{chunk-ELBZON4V.js → chunk-EAY2JMZG.js} +2 -2
- package/dist/cli/chunks/{chunk-HSVKZ5KI.js → chunk-ELLBS5RP.js} +2 -2
- package/dist/cli/chunks/chunk-ENGZ4D5V.js +2 -0
- package/dist/cli/chunks/chunk-FBMN7B46.js +4 -0
- package/dist/cli/chunks/{chunk-F34OAHOM.js → chunk-FWASDOT2.js} +2 -2
- package/dist/cli/chunks/{chunk-E4AZXCT5.js → chunk-FZOBD67M.js} +1 -1
- package/dist/cli/chunks/{chunk-QZMUXJHZ.js → chunk-GDSXITFH.js} +2 -2
- package/dist/cli/chunks/{chunk-LSUILON7.js → chunk-GGRHV6D7.js} +1 -1
- package/dist/cli/chunks/{chunk-3YUB5HER.js → chunk-GPYVDFB3.js} +101 -101
- package/dist/cli/chunks/{chunk-4FWTLJEP.js → chunk-GSF6MB64.js} +2 -2
- package/dist/cli/chunks/{chunk-3KDL6QDK.js → chunk-H52HZ67P.js} +2 -2
- package/dist/cli/chunks/{chunk-2JGEZHWY.js → chunk-H5BS5VH7.js} +2 -2
- package/dist/cli/chunks/{chunk-SQF6HRXR.js → chunk-H6ZM3PUT.js} +1 -1
- package/dist/cli/chunks/{chunk-OEIQTWQP.js → chunk-HM6ZSCPI.js} +1 -1
- package/dist/cli/chunks/{chunk-URVHZPWY.js → chunk-HNFVJP4I.js} +2 -2
- package/dist/cli/chunks/{chunk-RD6TEZ64.js → chunk-I33ERSGB.js} +2 -2
- package/dist/cli/chunks/{chunk-IUDWEOLX.js → chunk-IAF6T27S.js} +2 -2
- package/dist/cli/chunks/{chunk-XZSMZHM2.js → chunk-IB27QACC.js} +2 -2
- package/dist/cli/chunks/{chunk-I6X3EGJI.js → chunk-ICTXTNQZ.js} +1 -1
- package/dist/cli/chunks/chunk-IG5GNEC6.js +4 -0
- package/dist/cli/chunks/{chunk-6A44AOGN.js → chunk-IQO7UCFR.js} +2 -2
- package/dist/cli/chunks/{chunk-R6IU3EWP.js → chunk-IV5UZOHH.js} +2 -2
- package/dist/cli/chunks/{chunk-VTOVWHEM.js → chunk-JBTPOIAC.js} +2 -2
- package/dist/cli/chunks/{chunk-KLTP5IDB.js → chunk-JIXUMYKZ.js} +1 -1
- package/dist/cli/chunks/{chunk-3VIXOHMS.js → chunk-JMONHE4B.js} +1 -1
- package/dist/cli/chunks/{chunk-SX4JLSLV.js → chunk-JVNTSNWU.js} +2 -2
- package/dist/cli/chunks/{chunk-JVQBWYHW.js → chunk-JXGFRBUO.js} +2 -2
- package/dist/cli/chunks/{chunk-HVXJC3OC.js → chunk-JZOS5FCX.js} +2 -2
- package/dist/cli/chunks/{chunk-XEZIIQYJ.js → chunk-KNNISEDY.js} +1 -1
- package/dist/cli/chunks/{chunk-73EI4C2E.js → chunk-L4RUBPLR.js} +2 -2
- package/dist/cli/chunks/{chunk-AF4XKLXO.js → chunk-LL3IGZBI.js} +2 -2
- package/dist/cli/chunks/{chunk-UJWAWIRV.js → chunk-MBRHSU6W.js} +10 -10
- package/dist/cli/chunks/{chunk-J5UNP6W3.js → chunk-MJS53PRX.js} +2 -2
- package/dist/cli/chunks/{chunk-EOR2UT72.js → chunk-MQROI74N.js} +2 -2
- package/dist/cli/chunks/{chunk-BXVAVFGU.js → chunk-MUOG6QXR.js} +2 -2
- package/dist/cli/chunks/{chunk-O3JTQ7N4.js → chunk-MW2GGZZ5.js} +1 -1
- package/dist/cli/chunks/{chunk-IIAR5S7Q.js → chunk-NHWGMJAP.js} +2 -2
- package/dist/cli/chunks/{chunk-WOIGKU2N.js → chunk-NMAIY4PX.js} +3 -3
- package/dist/cli/chunks/{chunk-QIRL6B3C.js → chunk-NQZ5AR3D.js} +2 -2
- package/dist/cli/chunks/{chunk-6TU7FEMD.js → chunk-P6OYS755.js} +1 -1
- package/dist/cli/chunks/{chunk-HVU64GP5.js → chunk-PI7TJS62.js} +2 -2
- package/dist/cli/chunks/{chunk-N7H767TP.js → chunk-PX5YDCRH.js} +2 -2
- package/dist/cli/chunks/{chunk-3EZ5DR2R.js → chunk-PZPWRQ2M.js} +2 -2
- package/dist/cli/chunks/{chunk-RKOUXVZZ.js → chunk-Q5XTSMWR.js} +2 -2
- package/dist/cli/chunks/{chunk-K27SU3RE.js → chunk-Q7EAGKAE.js} +2 -2
- package/dist/cli/chunks/{chunk-M5AEL7IS.js → chunk-QDFTT3RF.js} +2 -2
- package/dist/cli/chunks/{chunk-TY5WC3FT.js → chunk-QGA55PFM.js} +3 -3
- package/dist/cli/chunks/{chunk-NQI7FWCS.js → chunk-QW6VMTBR.js} +2 -2
- package/dist/cli/chunks/{chunk-BHFR2EXL.js → chunk-QZANMBIT.js} +1 -1
- package/dist/cli/chunks/{chunk-5D36YHS3.js → chunk-RETBYIAC.js} +4 -4
- package/dist/cli/chunks/{chunk-UKGXWW64.js → chunk-RFNPJK6N.js} +3 -3
- package/dist/cli/chunks/{chunk-G3W6BMVJ.js → chunk-RG52OKAM.js} +1 -1
- package/dist/cli/chunks/{chunk-DO6EI5KB.js → chunk-RSXXCL4A.js} +1 -1
- package/dist/cli/chunks/{chunk-E3W6XQ57.js → chunk-RTFO5UQH.js} +2 -2
- package/dist/cli/chunks/{chunk-DDCIYOGT.js → chunk-RZZCUIAI.js} +2 -2
- package/dist/cli/chunks/{chunk-C3HQL6S4.js → chunk-SDRHUMJB.js} +2 -2
- package/dist/cli/chunks/{chunk-KYA5LARK.js → chunk-SE4WIB26.js} +1 -1
- package/dist/cli/chunks/{chunk-NU7UTXMP.js → chunk-SESK3ARK.js} +2 -2
- package/dist/cli/chunks/{chunk-YQGPQBCX.js → chunk-SJUXE4IC.js} +2 -2
- package/dist/cli/chunks/{chunk-HBCGYMQU.js → chunk-SMDN3BQZ.js} +1 -1
- package/dist/cli/chunks/{chunk-D6OUCB2H.js → chunk-SNOBH4AZ.js} +2 -2
- package/dist/cli/chunks/{chunk-QRCIZFNK.js → chunk-SPV2VKC5.js} +2 -2
- package/dist/cli/chunks/chunk-TCHGOB2N.js +2 -0
- package/dist/cli/chunks/{chunk-2KJQ2UQE.js → chunk-TVYY3OCX.js} +1 -1
- package/dist/cli/chunks/{chunk-RIZVC4XY.js → chunk-UCFQALXO.js} +2 -2
- package/dist/cli/chunks/{chunk-XFPPERA2.js → chunk-UKA2KOXE.js} +2 -2
- package/dist/cli/chunks/{chunk-UTBYJ4RF.js → chunk-UNFFDHER.js} +16 -11
- package/dist/cli/chunks/{chunk-6VAZAHQG.js → chunk-UQ32JHES.js} +2 -2
- package/dist/cli/chunks/{chunk-CPC7FN52.js → chunk-V4DM6ELU.js} +2 -2
- package/dist/cli/chunks/{chunk-67YV75XP.js → chunk-VGFFFKGK.js} +2 -2
- package/dist/cli/chunks/{chunk-WK7B4B6Y.js → chunk-VMNWDJIZ.js} +2 -2
- package/dist/cli/chunks/chunk-W6HXLH5G.js +180 -0
- package/dist/cli/chunks/{chunk-7VFY7TUR.js → chunk-WCJBU2KI.js} +2 -2
- package/dist/cli/chunks/{chunk-JROVR6YS.js → chunk-WGM35YWL.js} +2 -2
- package/dist/cli/chunks/{chunk-IUHB5GVS.js → chunk-WO4QMXIG.js} +2 -2
- package/dist/cli/chunks/{chunk-JES6R5KP.js → chunk-XAS3XRYM.js} +1 -1
- package/dist/cli/chunks/chunk-Y3LZ35OG.js +2 -0
- package/dist/cli/chunks/{chunk-75QJ5HWE.js → chunk-Y3UOUNHM.js} +2 -2
- package/dist/cli/chunks/{chunk-WJTSY5MC.js → chunk-YFBSPLJG.js} +1 -1
- package/dist/cli/chunks/{chunk-DPBRWP4J.js → chunk-YHKEDEAA.js} +3 -3
- package/dist/cli/chunks/{chunk-NRE4NAVA.js → chunk-YS4FCTWF.js} +1 -1
- package/dist/cli/chunks/{chunk-I2NENQ44.js → chunk-YSLL6VSL.js} +2 -2
- package/dist/cli/chunks/chunk-Z6GGIRQQ.js +65 -0
- package/dist/cli/chunks/{chunk-E4EYPYR3.js → chunk-Z7WODOTH.js} +2 -2
- package/dist/cli/chunks/{chunk-7DETTOPZ.js → chunk-ZCRTRYXK.js} +2 -2
- package/dist/cli/chunks/{chunk-FUNGTIF2.js → chunk-ZEV3YTO7.js} +2 -2
- package/dist/cli/chunks/{chunk-SQKW3B6B.js → chunk-ZL6SYKUK.js} +1 -1
- package/dist/cli/chunks/{chunk-AMMQOV35.js → chunk-ZSPU4MOS.js} +2 -2
- package/dist/cli/chunks/{chunk-KKHYJF5U.js → chunk-ZVWVV4EX.js} +1 -1
- package/dist/cli/chunks/{ci-RACDAJMR.js → ci-W6K6G2KZ.js} +2 -2
- package/dist/cli/chunks/{ci-output-EHRSZBKG.js → ci-output-LDT24TS3.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-GBV7M5XG.js → circuit-breaker-F5V4KITU.js} +2 -2
- package/dist/cli/chunks/claude-flow-setup-DT6WQQVD.js +2 -0
- package/dist/cli/chunks/client-KHWJT6FB.js +2 -0
- package/dist/cli/chunks/{cline-installer-W4NMXJSG.js → cline-installer-G7TJOAEX.js} +2 -2
- package/dist/cli/chunks/{code-JWXJMYXB.js → code-PGE6A42V.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-RVI2IFTM.js → code-index-extractor-RNITH372.js} +2 -2
- package/dist/cli/chunks/{codex-installer-3BORJINH.js → codex-installer-LBX77AI3.js} +6 -6
- package/dist/cli/chunks/{completions-A55NCTAO.js → completions-4AWLAARX.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-JCXHGGLY.js → complexity-analyzer-ZPNSS476.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-PUVFMGYW.js → continuedev-installer-UAPWX6OA.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-4DCMYWHB.js → copilot-installer-BJN2YJGI.js} +2 -2
- package/dist/cli/chunks/core-handlers-HING5RRG.js +2 -0
- package/dist/cli/chunks/{cost-tracker-5TV2GGKY.js → cost-tracker-MHP2VJ63.js} +2 -2
- package/dist/cli/chunks/{coverage-NNWM7TX3.js → coverage-PQB4IEFG.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-PQTD6AZN.js +2 -0
- package/dist/cli/chunks/{cursor-installer-4NCHGJGK.js → cursor-installer-ZXBWYAS3.js} +2 -2
- package/dist/cli/chunks/{daemon-T4JO4IXP.js → daemon-64C7R6OJ.js} +3 -3
- package/dist/cli/chunks/{daemon-QIKCXKWO.js → daemon-N2BEGEFY.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-RPAAIDAD.js → dag-attention-scheduler-SPZDAPNL.js} +2 -2
- package/dist/cli/chunks/{detect-SBEEVDSN.js → detect-LXJBSSZW.js} +2 -2
- package/dist/cli/chunks/{dist-node-ZHI6NCSU.js → dist-node-U3TKZ2IZ.js} +2 -2
- package/dist/cli/chunks/{domain-handler-LBC3GJ7Z.js → domain-handler-3DDWUVSR.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-H6IZ5USZ.js → domain-plugins-JJVWI4OQ.js} +2 -2
- package/dist/cli/chunks/domain-transfer-M36KUJ2U.js +2 -0
- package/dist/cli/chunks/dream-WUGRSNCV.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-AHTR7CRU.js → embed-and-insert-pattern-JPAR7TXX.js} +2 -2
- package/dist/cli/chunks/{eval-DZU2KISM.js → eval-SOLG23EA.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-5IQCWKSL.js → experience-capture-middleware-T7G2VOOD.js} +3 -3
- package/dist/cli/chunks/{fast-paths-2KLDUWCY.js → fast-paths-32N3ELI4.js} +2 -2
- package/dist/cli/chunks/{feature-flags-N6UAEZY4.js → feature-flags-APJDQ4N7.js} +2 -2
- package/dist/cli/chunks/{feature-flags-7AC3XDZA.js → feature-flags-NAHKLDRN.js} +2 -2
- package/dist/cli/chunks/{file-discovery-5SDIW4V2.js → file-discovery-YKVM3MDB.js} +2 -2
- package/dist/cli/chunks/{fleet-ZIQCAZ2Y.js → fleet-55M5CJS4.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-DUMBZJEV.js → gnn-wrapper-UD6E6S6Z.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-6HVM6ZMR.js → heartbeat-handler-OYVW3VSC.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-33XX5XNQ.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-XQPERX3H.js +2 -0
- package/dist/cli/chunks/hnsw-index-2GNXTWHH.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-5DRL5FLX.js → hnsw-legacy-bridge-HBYIS3ZW.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-GW67GTCL.js → hnswlib-node-EQPM42OU.js} +2 -2
- package/dist/cli/chunks/{hooks-QHH6FVO4.js → hooks-5ZSSJWO6.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-CCF7URKI.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-7XDCCVG2.js → hypergraph-engine-XBGVQ4PD.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-QHF7NOU5.js → hypergraph-handler-CAWAQ673.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-HGKAZWIG.js +2 -0
- package/dist/cli/chunks/{init-handler-5UIVOM7K.js → init-handler-PRHXSARK.js} +6 -6
- package/dist/cli/chunks/init-wizard-72MFBI3G.js +2 -0
- package/dist/cli/chunks/kernel-BRCBVMSK.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-TGGV6K5Q.js → kilocode-installer-F7LXBM7I.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-4XYBHZWW.js → kiro-installer-NM723ZRG.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-DG44IPEI.js +2 -0
- package/dist/cli/chunks/{learning-STE5W6BS.js → learning-5QYIDHH3.js} +3 -3
- package/dist/cli/chunks/{llm-router-NKF7J3RI.js → llm-router-43HKWPSX.js} +4 -4
- package/dist/cli/chunks/llm-router-service-24KXFX32.js +2 -0
- package/dist/cli/chunks/{load-B2T77UJQ.js → load-5YDBWSCS.js} +2 -2
- package/dist/cli/chunks/load-test-N4TAYJY3.js +2 -0
- package/dist/cli/chunks/mcp-UMAPMNMY.js +2 -0
- package/dist/cli/chunks/{memory-WRFZKG56.js → memory-FWCPCQFP.js} +5 -5
- package/dist/cli/chunks/memory-backend-NVYFYVAU.js +2 -0
- package/dist/cli/chunks/memory-handlers-UTWCNCHL.js +2 -0
- package/dist/cli/chunks/multi-model-executor-2XTBGLE4.js +14 -0
- package/dist/cli/chunks/{opencode-installer-J36EMQU7.js → opencode-installer-GIXOJ6NS.js} +2 -2
- package/dist/cli/chunks/orchestrator-VW6BKHLI.js +393 -0
- package/dist/cli/chunks/pattern-null-store-SBPNYDBR.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-BVMTWI3E.js → pattern-usage-recorder-7CEUC3J7.js} +2 -2
- package/dist/cli/chunks/{pipeline-OWAHDUAQ.js → pipeline-IGUQPPPO.js} +2 -2
- package/dist/cli/chunks/{platform-ANGBFWBV.js → platform-2P636I7B.js} +2 -2
- package/dist/cli/chunks/{plugin-OO7ON2YW.js → plugin-NY6SWDPE.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-HFG3BXWU.js → prime-radiant-advanced-wasm-2UUDTIO2.js} +2 -2
- package/dist/cli/chunks/{project-root-LNOYVTYY.js → project-root-IOISG5KX.js} +2 -2
- package/dist/cli/chunks/protocol-executor-IBYEII5Q.js +2 -0
- package/dist/cli/chunks/{protocol-handler-CE3Q6LY4.js → protocol-handler-ZTPCRQ5W.js} +2 -2
- package/dist/cli/chunks/{prove-7XPN53PY.js → prove-SQX5A3IG.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-7IETWW6W.js +2 -0
- package/dist/cli/chunks/{quality-TT23JRFX.js → quality-DROILKRY.js} +2 -2
- package/dist/cli/chunks/{quality-gate-PPPRP255.js → quality-gate-PWKWDJY2.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-NHUK2MWJ.js +2 -0
- package/dist/cli/chunks/{real-embeddings-EYNZIFJE.js → real-embeddings-P5U3MGYC.js} +2 -2
- package/dist/cli/chunks/{ref-validation-QQR64ZXD.js → ref-validation-KY73NQXD.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-UIGS7ZJD.js → roocode-installer-6JPPRB3W.js} +2 -2
- package/dist/cli/chunks/router-SRSO3IHF.js +2 -0
- package/dist/cli/chunks/routing-feedback-PASRE5HY.js +2 -0
- package/dist/cli/chunks/{routing-handler-6AENUIRG.js → routing-handler-VTJIVFUO.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-5AWMEV34.js → ruvector-commands-C6RPSJJO.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-4M4J67OU.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-TSXGT5LF.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-NWRJ7C22.js → rvf-migration-coordinator-R53URRIO.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-MOF3E7BR.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-ISKRP563.js → rvf-store-integrity-MMXN5TEJ.js} +2 -2
- package/dist/cli/chunks/safe-db-QJLFO33B.js +2 -0
- package/dist/cli/chunks/schedule-YIVXW5O2.js +2 -0
- package/dist/cli/chunks/scheduler-AON7DWSJ.js +2 -0
- package/dist/cli/chunks/{security-325A7FMB.js → security-3B3R2NL4.js} +3 -3
- package/dist/cli/chunks/shared-rvf-adapter-VIJB7JUS.js +2 -0
- package/dist/cli/chunks/{shared-rvf-dual-writer-THFDYS2Z.js → shared-rvf-dual-writer-UVWGDUWC.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-75VHKKQB.js +2 -0
- package/dist/cli/chunks/{standalone-memory-UD4MJ6GZ.js → standalone-memory-M4LWAAYZ.js} +2 -2
- package/dist/cli/chunks/{status-handler-CPFTN4XL.js → status-handler-YYFV6OZL.js} +2 -2
- package/dist/cli/chunks/{structural-health-2MG2IVBL.js → structural-health-27E6LLKB.js} +2 -2
- package/dist/cli/chunks/sync-26CEGSTC.js +2 -0
- package/dist/cli/chunks/{sync-EE4VVKOW.js → sync-J3LJ56WN.js} +2 -2
- package/dist/cli/chunks/{task-handler-7H5OYJG4.js → task-handler-4MCEBQZL.js} +2 -2
- package/dist/cli/chunks/{task-handlers-NH4GJHCJ.js → task-handlers-GYBAWKE2.js} +3 -3
- package/dist/cli/chunks/{test-MPHGT4T6.js → test-MPC5HRH5.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-CHQ4ZLLJ.js → test-scheduling-ZJBFRZ3J.js} +3 -3
- package/dist/cli/chunks/token-bootstrap-2Y2XITBX.js +2 -0
- package/dist/cli/chunks/{token-usage-EBXUJNRB.js → token-usage-3X5WMTG2.js} +2 -2
- package/dist/cli/chunks/{transformers-ZEKS2OJZ.js → transformers-MVL4C5IX.js} +2 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-SLW65ZFO.js +2 -0
- package/dist/cli/chunks/{types-KYAA5VLV.js → types-TG5P3CRS.js} +2 -2
- package/dist/cli/chunks/unified-memory-UCQ6AB32.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-IXYUMKRR.js +2 -0
- package/dist/cli/chunks/unified-persistence-7E6JQ4FZ.js +2 -0
- package/dist/cli/chunks/{upgrade-UJBJ5AYM.js → upgrade-ETBHDEPY.js} +2 -2
- package/dist/cli/chunks/{validate-RUV6YMWS.js → validate-C2A73LZK.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-IVEVMGVM.js → validate-swarm-67XN42ML.js} +2 -2
- package/dist/cli/chunks/{vibium-HOGMFJ2Z.js → vibium-NILGKHLN.js} +2 -2
- package/dist/cli/chunks/visual-security-4VZXPEVG.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-AVWA6HKE.js → web-tree-sitter-USJN77P4.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-DAH7HI2W.js → windsurf-installer-5GGZXGJW.js} +2 -2
- package/dist/cli/chunks/witness-chain-IWS5ZHHL.js +2 -0
- package/dist/cli/chunks/witness-chain-JQA2VPZI.js +2 -0
- package/dist/cli/chunks/witness-chain-repair-4UA7IPS3.js +2 -0
- package/dist/cli/chunks/witness-chain-verifier-3GEADWPE.js +2 -0
- package/dist/cli/chunks/{witness-key-manager-JSTBMG43.js → witness-key-manager-ZWEIK3VJ.js} +2 -2
- package/dist/cli/chunks/{workflow-TWOIA6LZ.js → workflow-KHMVVBBA.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-GI5NQH7C.js +2 -0
- package/dist/cli/chunks/wrappers-N6XIK5PT.js +2 -0
- package/dist/cli/commands/audit.d.ts +20 -2
- package/dist/cli/commands/audit.js +158 -16
- package/dist/cli/commands/claude-flow-setup.js +5 -4
- package/dist/cli/index.js +2 -1
- package/dist/init/agents-installer.d.ts +4 -0
- package/dist/init/agents-installer.js +24 -11
- package/dist/init/codex-installer.js +4 -2
- package/dist/init/idempotent-write.d.ts +53 -0
- package/dist/init/idempotent-write.js +160 -0
- package/dist/init/phases/05-learning.js +3 -1
- package/dist/init/phases/07-hooks.js +32 -16
- package/dist/init/phases/08-mcp.js +4 -2
- package/dist/init/phases/10-workers.js +7 -5
- package/dist/init/phases/12-verification.js +7 -2
- package/dist/init/project-analyzer.d.ts +9 -0
- package/dist/init/project-analyzer.js +20 -1
- package/dist/init/self-configurator.d.ts +5 -3
- package/dist/init/self-configurator.js +18 -29
- package/dist/init/skills-installer.js +4 -2
- package/dist/init/types.d.ts +6 -0
- package/dist/init/types.js +20 -24
- package/dist/integrations/coherence/coherence-service.js +84 -24
- package/dist/integrations/coherence/vote-tally.d.ts +38 -0
- package/dist/integrations/coherence/vote-tally.js +39 -0
- package/dist/integrations/ruvector/shared-rvf-adapter.d.ts +23 -0
- package/dist/integrations/ruvector/shared-rvf-adapter.js +24 -0
- package/dist/kernel/kernel.js +3 -2
- package/dist/learning/pattern-store.d.ts +11 -0
- package/dist/learning/pattern-store.js +26 -8
- package/dist/learning/qe-patterns.d.ts +6 -0
- package/dist/learning/qe-patterns.js +7 -1
- package/dist/learning/qe-reasoning-bank.js +3 -0
- package/dist/learning/rvf-pattern-store.js +20 -7
- package/dist/learning/sqlite-persistence.d.ts +8 -1
- package/dist/learning/sqlite-persistence.js +49 -9
- package/dist/logging/console-logger.d.ts +2 -5
- package/dist/logging/console-logger.js +10 -46
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.js +1 -0
- package/dist/logging/redaction.d.ts +27 -0
- package/dist/logging/redaction.js +170 -0
- package/dist/mcp/bundle.js +435 -421
- package/dist/mcp/handlers/core-handlers.js +5 -4
- package/dist/mcp/protocol-server.js +2 -1
- package/dist/mcp/tools/base.d.ts +9 -2
- package/dist/mcp/tools/base.js +7 -0
- package/dist/mcp/tools/coherence/consensus.js +51 -2
- package/dist/mcp/tools/planning/goap-plan.d.ts +20 -7
- package/dist/mcp/tools/planning/goap-plan.js +92 -20
- package/dist/mcp/tools/planning/goap-status.d.ts +37 -12
- package/dist/mcp/tools/planning/goap-status.js +52 -23
- package/dist/mcp/tools/planning/world-state.d.ts +101 -0
- package/dist/mcp/tools/planning/world-state.js +274 -0
- package/dist/mcp/types.d.ts +4 -2
- package/dist/planning/goap-planner.d.ts +60 -4
- package/dist/planning/goap-planner.js +218 -60
- package/dist/planning/index.d.ts +1 -1
- package/dist/planning/index.js +1 -1
- package/dist/planning/plan-executor.d.ts +20 -1
- package/dist/planning/plan-executor.js +209 -100
- package/dist/planning/types.d.ts +16 -0
- package/dist/planning/types.js +17 -0
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-IYC62SXA.js +0 -2
- package/dist/cli/chunks/agent-booster-wasm-EDNKP3SP.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-LLOU2IXD.js +0 -2
- package/dist/cli/chunks/audit-CVZQMF55.js +0 -3
- package/dist/cli/chunks/base-P3Z4IKCT.js +0 -2
- package/dist/cli/chunks/browser-workflow-YYHQQ25X.js +0 -2
- package/dist/cli/chunks/chunk-5WOSWNDN.js +0 -2
- package/dist/cli/chunks/chunk-7CD7PBHY.js +0 -3
- package/dist/cli/chunks/chunk-7X7JYWT4.js +0 -27
- package/dist/cli/chunks/chunk-J27F4NSB.js +0 -2
- package/dist/cli/chunks/chunk-MI5Q55DG.js +0 -65
- package/dist/cli/chunks/chunk-UDHVCKGA.js +0 -5
- package/dist/cli/chunks/chunk-XQSIRBKT.js +0 -180
- package/dist/cli/chunks/chunk-ZBABIZ2D.js +0 -2
- package/dist/cli/chunks/claude-flow-setup-5LVJOFKP.js +0 -2
- package/dist/cli/chunks/client-HUVFA5PF.js +0 -2
- package/dist/cli/chunks/core-handlers-UEXO3VAA.js +0 -2
- package/dist/cli/chunks/cross-domain-router-ODU5IZD6.js +0 -2
- package/dist/cli/chunks/domain-transfer-JZA5TMW3.js +0 -2
- package/dist/cli/chunks/dream-HE3OX42F.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-QUIFGGLX.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-42KB37KP.js +0 -2
- package/dist/cli/chunks/hnsw-index-T2PGO77J.js +0 -2
- package/dist/cli/chunks/hybrid-backend-FRNWYRKH.js +0 -2
- package/dist/cli/chunks/impact-analyzer-A5QYOYBR.js +0 -2
- package/dist/cli/chunks/init-wizard-XBU674YH.js +0 -2
- package/dist/cli/chunks/kernel-DV5MTNZD.js +0 -2
- package/dist/cli/chunks/knowledge-graph-4ACGVJQK.js +0 -2
- package/dist/cli/chunks/llm-router-service-PSMASERT.js +0 -2
- package/dist/cli/chunks/load-test-MRUO2VPF.js +0 -2
- package/dist/cli/chunks/mcp-JGSFCEMH.js +0 -2
- package/dist/cli/chunks/memory-backend-2MPGI6JW.js +0 -2
- package/dist/cli/chunks/memory-handlers-XT4HMITB.js +0 -2
- package/dist/cli/chunks/multi-model-executor-26Q5BSVG.js +0 -14
- package/dist/cli/chunks/orchestrator-D5IFV65I.js +0 -393
- package/dist/cli/chunks/pattern-null-store-TGWUL237.js +0 -2
- package/dist/cli/chunks/protocol-executor-GEVH5KD6.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-DJ2JL6QB.js +0 -2
- package/dist/cli/chunks/queen-coordinator-F7E3AS26.js +0 -2
- package/dist/cli/chunks/router-OZH3QSAU.js +0 -2
- package/dist/cli/chunks/routing-feedback-J2E3ADZB.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-HK525Y5Y.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-Q7FB3BKR.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-5ZRCGUI6.js +0 -2
- package/dist/cli/chunks/safe-db-3OYEPVEH.js +0 -2
- package/dist/cli/chunks/schedule-AG4C2EIQ.js +0 -2
- package/dist/cli/chunks/scheduler-SQS2CZFZ.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-NFL6QSZ6.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-MAKDFSHC.js +0 -2
- package/dist/cli/chunks/sync-MBTW5XBF.js +0 -2
- package/dist/cli/chunks/token-bootstrap-SSDCYEKK.js +0 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-J6ZMAK37.js +0 -2
- package/dist/cli/chunks/unified-memory-DDWMC435.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-4JA7SGBK.js +0 -2
- package/dist/cli/chunks/unified-persistence-F6OSNTXY.js +0 -2
- package/dist/cli/chunks/visual-security-25SMBIYT.js +0 -2
- package/dist/cli/chunks/witness-chain-PJOQPFUX.js +0 -2
- package/dist/cli/chunks/witness-chain-ZW6KKUZU.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-UKSIDM7Q.js +0 -2
- package/dist/cli/chunks/wrappers-UR7BLXKV.js +0 -2
|
@@ -31,6 +31,31 @@
|
|
|
31
31
|
import { DEFAULT_COHERENCE_CONFIG, DEFAULT_COHERENCE_LOGGER, WasmNotLoadedError, CoherenceError, } from './types.js';
|
|
32
32
|
import { toErrorMessage, toError } from '../../shared/error-utils.js';
|
|
33
33
|
import { CohomologyAdapter, SpectralAdapter, CausalAdapter, CategoryAdapter, HomotopyAdapter, WitnessAdapter, } from './engines/index.js';
|
|
34
|
+
import { tallyVotes, describeLeader, describeBreakdown } from './vote-tally.js';
|
|
35
|
+
/** Fallback consensus is valid only when more than this share of votes agree */
|
|
36
|
+
const FALLBACK_MAJORITY_THRESHOLD = 0.6;
|
|
37
|
+
/**
|
|
38
|
+
* Minimum number of voters for unanimity to be flagged as possible false
|
|
39
|
+
* consensus. Two agreeing agents are too few to call it groupthink.
|
|
40
|
+
*/
|
|
41
|
+
const MIN_VOTERS_FOR_FALSE_CONSENSUS = 3;
|
|
42
|
+
/**
|
|
43
|
+
* False consensus means votes that *appear* unified but may not be
|
|
44
|
+
* (tool contract: "appears unified but isn't"). From verdicts alone the only
|
|
45
|
+
* observable "appears unified" signal is unanimity, so both the spectral and
|
|
46
|
+
* the fallback path flag unanimity among at least three voters as a risk.
|
|
47
|
+
* A split vote (e.g. 2 pass / 1 fail) shows its disagreement openly: it is a
|
|
48
|
+
* majority or an unverified consensus, never a false one (issue #535).
|
|
49
|
+
*/
|
|
50
|
+
function appearsFalselyUnified(tally) {
|
|
51
|
+
return tally.isUnanimous && tally.total >= MIN_VOTERS_FOR_FALSE_CONSENSUS;
|
|
52
|
+
}
|
|
53
|
+
/** e.g. "3 of 3 votes 'pass'" or "2 of 3 votes 'pass'; 2 'pass' / 1 'fail'" */
|
|
54
|
+
function describeTally(tally) {
|
|
55
|
+
return tally.isUnanimous
|
|
56
|
+
? describeLeader(tally)
|
|
57
|
+
: `${describeLeader(tally)}; ${describeBreakdown(tally)}`;
|
|
58
|
+
}
|
|
34
59
|
// ============================================================================
|
|
35
60
|
// Coherence Service Implementation
|
|
36
61
|
// ============================================================================
|
|
@@ -557,15 +582,44 @@ export class CoherenceService {
|
|
|
557
582
|
}
|
|
558
583
|
const collapseRisk = this.spectralAdapter.predictCollapseRisk();
|
|
559
584
|
const fiedlerValue = this.spectralAdapter.computeFiedlerValue();
|
|
585
|
+
const tally = tallyVotes(votes);
|
|
586
|
+
// When every vote agrees and carries positive confidence, the agreement
|
|
587
|
+
// graph is complete with positive edge weights, so its algebraic
|
|
588
|
+
// connectivity is necessarily > 0. A non-positive value here means the
|
|
589
|
+
// engine's eigen-solver result cannot be trusted; count votes instead
|
|
590
|
+
// of reporting a unanimous vote as a collapsed one.
|
|
591
|
+
if (tally.isUnanimous && votes.every(v => v.confidence > 0) && !(fiedlerValue > 0)) {
|
|
592
|
+
this.logger.warn('Spectral engine returned a zero Fiedler value for a connected agreement graph, using fallback', {
|
|
593
|
+
fiedlerValue,
|
|
594
|
+
voteCount: votes.length,
|
|
595
|
+
});
|
|
596
|
+
return this.verifyConsensusWithFallback(votes, startTime);
|
|
597
|
+
}
|
|
598
|
+
// Agents are connected only when they share a verdict, so any split
|
|
599
|
+
// vote disconnects the graph (λ2 = 0) and fails verification here.
|
|
600
|
+
const isValid = collapseRisk < 0.3 && fiedlerValue > 0.1;
|
|
601
|
+
const isFalseConsensus = appearsFalselyUnified(tally);
|
|
602
|
+
let recommendation;
|
|
603
|
+
if (!isValid) {
|
|
604
|
+
recommendation =
|
|
605
|
+
`No verified consensus (${describeTally(tally)}): agreement-graph Fiedler value ` +
|
|
606
|
+
`${fiedlerValue.toFixed(3)}, collapse risk ${collapseRisk.toFixed(2)}. Spawn independent reviewer.`;
|
|
607
|
+
}
|
|
608
|
+
else if (isFalseConsensus) {
|
|
609
|
+
recommendation =
|
|
610
|
+
`Consensus verified (${describeTally(tally)}), but unanimous agreement may indicate ` +
|
|
611
|
+
'false consensus. Consider adding diversity.';
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
recommendation = `Consensus verified (${describeTally(tally)}).`;
|
|
615
|
+
}
|
|
560
616
|
return {
|
|
561
|
-
isValid
|
|
617
|
+
isValid,
|
|
562
618
|
confidence: 1 - collapseRisk,
|
|
563
|
-
isFalseConsensus
|
|
619
|
+
isFalseConsensus,
|
|
564
620
|
fiedlerValue,
|
|
565
621
|
collapseRisk,
|
|
566
|
-
recommendation
|
|
567
|
-
? 'Spawn independent reviewer'
|
|
568
|
-
: 'Consensus verified',
|
|
622
|
+
recommendation,
|
|
569
623
|
durationMs: Date.now() - startTime,
|
|
570
624
|
usedFallback: false,
|
|
571
625
|
};
|
|
@@ -586,30 +640,36 @@ export class CoherenceService {
|
|
|
586
640
|
* Fallback consensus verification
|
|
587
641
|
*/
|
|
588
642
|
verifyConsensusWithFallback(votes, startTime) {
|
|
589
|
-
|
|
590
|
-
const
|
|
591
|
-
for (const vote of votes) {
|
|
592
|
-
const key = String(vote.verdict);
|
|
593
|
-
verdictCounts.set(key, (verdictCounts.get(key) || 0) + 1);
|
|
594
|
-
}
|
|
595
|
-
// Find majority
|
|
596
|
-
let maxCount = 0;
|
|
597
|
-
verdictCounts.forEach(count => {
|
|
598
|
-
maxCount = Math.max(maxCount, count);
|
|
599
|
-
});
|
|
600
|
-
const majorityRatio = maxCount / votes.length;
|
|
643
|
+
const tally = tallyVotes(votes);
|
|
644
|
+
const { majorityRatio } = tally;
|
|
601
645
|
const avgConfidence = votes.reduce((sum, v) => sum + v.confidence, 0) / votes.length;
|
|
646
|
+
// Flags and text are derived from the same predicates so the
|
|
647
|
+
// recommendation can never contradict them (issue #535).
|
|
648
|
+
const isValid = majorityRatio > FALLBACK_MAJORITY_THRESHOLD;
|
|
649
|
+
const isFalseConsensus = appearsFalselyUnified(tally);
|
|
650
|
+
let recommendation;
|
|
651
|
+
if (!isValid) {
|
|
652
|
+
recommendation =
|
|
653
|
+
`No clear majority: ${describeBreakdown(tally)} across ${tally.total} votes ` +
|
|
654
|
+
`(needs more than ${Math.round(FALLBACK_MAJORITY_THRESHOLD * 100)}% agreeing). Consider spawning additional agents.`;
|
|
655
|
+
}
|
|
656
|
+
else if (isFalseConsensus) {
|
|
657
|
+
recommendation =
|
|
658
|
+
`Unanimous consensus (${describeLeader(tally)}) may indicate false consensus. Consider adding diversity.`;
|
|
659
|
+
}
|
|
660
|
+
else if (tally.isUnanimous) {
|
|
661
|
+
recommendation = `Unanimous consensus achieved (${describeLeader(tally)}).`;
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
recommendation = `Majority consensus achieved (${describeTally(tally)}).`;
|
|
665
|
+
}
|
|
602
666
|
return {
|
|
603
|
-
isValid
|
|
667
|
+
isValid,
|
|
604
668
|
confidence: majorityRatio * avgConfidence,
|
|
605
|
-
isFalseConsensus
|
|
669
|
+
isFalseConsensus,
|
|
606
670
|
fiedlerValue: majorityRatio, // Approximation
|
|
607
671
|
collapseRisk: 1 - majorityRatio,
|
|
608
|
-
recommendation
|
|
609
|
-
? 'No clear majority. Consider spawning additional agents.'
|
|
610
|
-
: majorityRatio === 1 && verdictCounts.size === 1
|
|
611
|
-
? 'Unanimous consensus may indicate false consensus. Consider adding diversity.'
|
|
612
|
-
: 'Majority consensus achieved.',
|
|
672
|
+
recommendation,
|
|
613
673
|
durationMs: Date.now() - startTime,
|
|
614
674
|
usedFallback: true,
|
|
615
675
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Consensus vote tally
|
|
3
|
+
*
|
|
4
|
+
* Counts verdicts once so that every consensus flag and every
|
|
5
|
+
* recommendation string is derived from the same numbers (issue #535).
|
|
6
|
+
*/
|
|
7
|
+
/** Minimal vote shape needed to tally verdicts */
|
|
8
|
+
export interface TallyableVote {
|
|
9
|
+
verdict: string | number | boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Verdict counts for a set of votes */
|
|
12
|
+
export interface VoteTally {
|
|
13
|
+
/** Total number of votes */
|
|
14
|
+
total: number;
|
|
15
|
+
/** Verdicts with counts, most votes first (ties ordered by verdict) */
|
|
16
|
+
counts: Array<{
|
|
17
|
+
verdict: string;
|
|
18
|
+
count: number;
|
|
19
|
+
}>;
|
|
20
|
+
/** Verdict with the most votes (first in `counts`) */
|
|
21
|
+
topVerdict: string;
|
|
22
|
+
/** Number of votes for `topVerdict` */
|
|
23
|
+
topCount: number;
|
|
24
|
+
/** topCount / total (0 when there are no votes) */
|
|
25
|
+
majorityRatio: number;
|
|
26
|
+
/** True when every vote has the same verdict */
|
|
27
|
+
isUnanimous: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Tally votes by verdict. Verdicts are compared by their string form,
|
|
31
|
+
* matching how consensus has always grouped them.
|
|
32
|
+
*/
|
|
33
|
+
export declare function tallyVotes(votes: readonly TallyableVote[]): VoteTally;
|
|
34
|
+
/** e.g. "2 of 3 votes 'pass'" */
|
|
35
|
+
export declare function describeLeader(tally: VoteTally): string;
|
|
36
|
+
/** e.g. "2 'pass' / 1 'fail'" */
|
|
37
|
+
export declare function describeBreakdown(tally: VoteTally): string;
|
|
38
|
+
//# sourceMappingURL=vote-tally.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Consensus vote tally
|
|
3
|
+
*
|
|
4
|
+
* Counts verdicts once so that every consensus flag and every
|
|
5
|
+
* recommendation string is derived from the same numbers (issue #535).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Tally votes by verdict. Verdicts are compared by their string form,
|
|
9
|
+
* matching how consensus has always grouped them.
|
|
10
|
+
*/
|
|
11
|
+
export function tallyVotes(votes) {
|
|
12
|
+
const byVerdict = new Map();
|
|
13
|
+
for (const vote of votes) {
|
|
14
|
+
const key = String(vote.verdict);
|
|
15
|
+
byVerdict.set(key, (byVerdict.get(key) ?? 0) + 1);
|
|
16
|
+
}
|
|
17
|
+
const counts = [...byVerdict.entries()]
|
|
18
|
+
.map(([verdict, count]) => ({ verdict, count }))
|
|
19
|
+
.sort((a, b) => b.count - a.count || a.verdict.localeCompare(b.verdict));
|
|
20
|
+
const top = counts[0] ?? { verdict: '', count: 0 };
|
|
21
|
+
const total = votes.length;
|
|
22
|
+
return {
|
|
23
|
+
total,
|
|
24
|
+
counts,
|
|
25
|
+
topVerdict: top.verdict,
|
|
26
|
+
topCount: top.count,
|
|
27
|
+
majorityRatio: total > 0 ? top.count / total : 0,
|
|
28
|
+
isUnanimous: counts.length === 1,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** e.g. "2 of 3 votes 'pass'" */
|
|
32
|
+
export function describeLeader(tally) {
|
|
33
|
+
return `${tally.topCount} of ${tally.total} votes '${tally.topVerdict}'`;
|
|
34
|
+
}
|
|
35
|
+
/** e.g. "2 'pass' / 1 'fail'" */
|
|
36
|
+
export function describeBreakdown(tally) {
|
|
37
|
+
return tally.counts.map(({ verdict, count }) => `${count} '${verdict}'`).join(' / ');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=vote-tally.js.map
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
* @module integrations/ruvector/shared-rvf-adapter
|
|
12
12
|
*/
|
|
13
13
|
import type { RvfNativeAdapter, RvfCompactionResult, RvfStatus } from './rvf-native-adapter.js';
|
|
14
|
+
/**
|
|
15
|
+
* The store is locked by a live process. The open ladder has already logged
|
|
16
|
+
* why it is degrading, so callers should not log it again (#574).
|
|
17
|
+
*/
|
|
18
|
+
export declare class RvfLiveLockError extends Error {
|
|
19
|
+
readonly lockError: unknown;
|
|
20
|
+
constructor(lockError: unknown);
|
|
21
|
+
}
|
|
14
22
|
/** @internal test-only seam */
|
|
15
23
|
export declare function __setSharedRvfAdapterForTests(adapter: RvfNativeAdapter | null): void;
|
|
16
24
|
/**
|
|
@@ -21,6 +29,19 @@ export declare function __setSharedRvfAdapterForTests(adapter: RvfNativeAdapter
|
|
|
21
29
|
* @returns The shared adapter, or null if native bindings are unavailable
|
|
22
30
|
*/
|
|
23
31
|
export declare function getSharedRvfAdapter(dataDir?: string, dimensions?: number): RvfNativeAdapter | null;
|
|
32
|
+
/**
|
|
33
|
+
* Race-tolerant open-or-create.
|
|
34
|
+
* Tries open first (cheap, succeeds for the common case where init has
|
|
35
|
+
* already produced the file). On open failure we attempt create. On the
|
|
36
|
+
* concurrent-create loser, create itself fails with `FsyncFailed`; we
|
|
37
|
+
* retry open once more. Any final exception bubbles up to the caller.
|
|
38
|
+
*
|
|
39
|
+
* Also asserts `dim()` matches the caller-requested `dimensions` after
|
|
40
|
+
* open so silent dimension drift between releases / configs is detected
|
|
41
|
+
* — a bad-dim file is closed and create() is attempted (fail-loud rather
|
|
42
|
+
* than corrupt-silently, which would manifest as wrong vector hits later).
|
|
43
|
+
*/
|
|
44
|
+
declare function openOrCreateRvf(openFn: (p: string) => RvfNativeAdapter, createFn: (p: string, dim: number) => RvfNativeAdapter, rvfPath: string, dimensions: number): RvfNativeAdapter;
|
|
24
45
|
export interface CompactDecision {
|
|
25
46
|
shouldCompact: boolean;
|
|
26
47
|
trigger: 'force' | 'size-guard' | 'dead-ratio' | 'none';
|
|
@@ -64,6 +85,8 @@ export declare function compactSharedRvfAdapter(opts?: {
|
|
|
64
85
|
* `getSharedRvfAdapter()` which invokes it internally.
|
|
65
86
|
*/
|
|
66
87
|
export declare function runBootCompactGuard(adapter: RvfNativeAdapter, rvfPath: string): RvfCompactionResult | null;
|
|
88
|
+
/** @internal test-only seam: the open ladder with injectable open/create */
|
|
89
|
+
export { openOrCreateRvf as __openOrCreateRvfForTests };
|
|
67
90
|
/** Close the shared adapter and reset the singleton. */
|
|
68
91
|
export declare function resetSharedRvfAdapter(): void;
|
|
69
92
|
//# sourceMappingURL=shared-rvf-adapter.d.ts.map
|
|
@@ -18,6 +18,18 @@ import { findProjectRoot } from '../../kernel/project-root.js';
|
|
|
18
18
|
import { quarantineUnusableStore, isLockHeldByLiveProcess, isRvfLockHeldError, removeStaleRvfLock, readLockOwnerPid, } from './rvf-store-integrity.js';
|
|
19
19
|
let sharedAdapter = null;
|
|
20
20
|
let initAttempted = false;
|
|
21
|
+
/**
|
|
22
|
+
* The store is locked by a live process. The open ladder has already logged
|
|
23
|
+
* why it is degrading, so callers should not log it again (#574).
|
|
24
|
+
*/
|
|
25
|
+
export class RvfLiveLockError extends Error {
|
|
26
|
+
lockError;
|
|
27
|
+
constructor(lockError) {
|
|
28
|
+
super(lockError instanceof Error ? lockError.message : String(lockError));
|
|
29
|
+
this.lockError = lockError;
|
|
30
|
+
this.name = 'RvfLiveLockError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
21
33
|
// ---------------------------------------------------------------------------
|
|
22
34
|
// Test seam: allow tests to install a fake adapter without going through the
|
|
23
35
|
// native binding loader. NOT part of the public API — used by tests only.
|
|
@@ -97,6 +109,9 @@ export function getSharedRvfAdapter(dataDir = '.agentic-qe', dimensions = 384) {
|
|
|
97
109
|
return sharedAdapter;
|
|
98
110
|
}
|
|
99
111
|
catch (error) {
|
|
112
|
+
// Already reported by the open ladder as "locked by a live process".
|
|
113
|
+
if (error instanceof RvfLiveLockError)
|
|
114
|
+
return null;
|
|
100
115
|
console.warn('[RVF] Shared adapter init failed:', error instanceof Error ? error.message : error);
|
|
101
116
|
return null;
|
|
102
117
|
}
|
|
@@ -137,12 +152,14 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
|
|
|
137
152
|
// assumption. This includes a lock owned by the current PID: another
|
|
138
153
|
// in-process adapter may still hold the store, so PID equality is not proof
|
|
139
154
|
// that the lock can be removed safely.
|
|
155
|
+
let liveOwner = false;
|
|
140
156
|
if (!opened && isRvfLockHeldError(openErr)) {
|
|
141
157
|
try {
|
|
142
158
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
143
159
|
const fs = require('fs');
|
|
144
160
|
const lockPath = `${rvfPath}.lock`;
|
|
145
161
|
if (fs.existsSync(lockPath) && isLockHeldByLiveProcess(rvfPath)) {
|
|
162
|
+
liveOwner = true;
|
|
146
163
|
console.warn(`[RVF] ${rvfPath} is locked by a live process (pid ${readLockOwnerPid(rvfPath)}) — ` +
|
|
147
164
|
'not breaking the lock; degrading to SQLite for this run.');
|
|
148
165
|
}
|
|
@@ -159,6 +176,11 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
|
|
|
159
176
|
}
|
|
160
177
|
}
|
|
161
178
|
}
|
|
179
|
+
// #574: a live owner means the store is busy, not missing or broken. A
|
|
180
|
+
// create on an existing path always fails and a reopen hits the same lock,
|
|
181
|
+
// so stop at the warning above instead of running Passes 2 and 3.
|
|
182
|
+
if (liveOwner)
|
|
183
|
+
throw new RvfLiveLockError(openErr);
|
|
162
184
|
if (opened) {
|
|
163
185
|
const actualDim = opened.dimension();
|
|
164
186
|
if (actualDim === dimensions)
|
|
@@ -312,6 +334,8 @@ function formatBytes(n) {
|
|
|
312
334
|
}
|
|
313
335
|
return `${v.toFixed(i === 0 ? 0 : 1)}${units[i]}`;
|
|
314
336
|
}
|
|
337
|
+
/** @internal test-only seam: the open ladder with injectable open/create */
|
|
338
|
+
export { openOrCreateRvf as __openOrCreateRvfForTests };
|
|
315
339
|
/** Close the shared adapter and reset the singleton. */
|
|
316
340
|
export function resetSharedRvfAdapter() {
|
|
317
341
|
if (sharedAdapter) {
|
package/dist/kernel/kernel.js
CHANGED
|
@@ -7,6 +7,7 @@ import { ALL_DOMAINS } from '../shared/types/index.js';
|
|
|
7
7
|
import { InMemoryEventBus } from './event-bus.js';
|
|
8
8
|
import { DefaultAgentCoordinator } from './agent-coordinator.js';
|
|
9
9
|
import { DefaultPluginLoader } from './plugin-loader.js';
|
|
10
|
+
import { formatErrorForLog } from '../logging/redaction.js';
|
|
10
11
|
import { InMemoryBackend } from './memory-backend.js';
|
|
11
12
|
import { createKernelMemoryBackend } from './hybrid-backend.js';
|
|
12
13
|
import { SemanticAntiDriftMiddleware, ToolCallSignatureTracker } from './anti-drift-middleware.js';
|
|
@@ -488,7 +489,7 @@ export class QEKernelImpl {
|
|
|
488
489
|
plugin = await this._plugins.load(domain);
|
|
489
490
|
}
|
|
490
491
|
catch (error) {
|
|
491
|
-
console.error(`[QEKernel] Failed to lazy load domain ${domain}:`, error);
|
|
492
|
+
console.error(`[QEKernel] Failed to lazy load domain ${domain}:`, formatErrorForLog(error));
|
|
492
493
|
return undefined;
|
|
493
494
|
}
|
|
494
495
|
}
|
|
@@ -511,7 +512,7 @@ export class QEKernelImpl {
|
|
|
511
512
|
return true;
|
|
512
513
|
}
|
|
513
514
|
catch (error) {
|
|
514
|
-
console.error(`[QEKernel] Failed to load domain ${domain}:`, error);
|
|
515
|
+
console.error(`[QEKernel] Failed to load domain ${domain}:`, formatErrorForLog(error));
|
|
515
516
|
return false;
|
|
516
517
|
}
|
|
517
518
|
}
|
|
@@ -128,6 +128,11 @@ export interface PatternSearchOptions {
|
|
|
128
128
|
useVectorSearch?: boolean;
|
|
129
129
|
/** Provenance of a pre-computed query vector. Required for semantic ranking. */
|
|
130
130
|
embeddingSpaceId?: string;
|
|
131
|
+
/**
|
|
132
|
+
* Original text of a pre-computed query vector (#653). Lets FTS5 lexical
|
|
133
|
+
* scoring participate when the caller embedded the text before searching.
|
|
134
|
+
*/
|
|
135
|
+
textQuery?: string;
|
|
131
136
|
/**
|
|
132
137
|
* Composable metadata filter expression (Task 1.2: ruvector-filter).
|
|
133
138
|
* Applied post-search to refine results by domain, severity,
|
|
@@ -386,6 +391,12 @@ export declare class PatternStore implements IPatternStore {
|
|
|
386
391
|
*/
|
|
387
392
|
searchHyperbolic(query: Float32Array | number[], k?: number): Promise<Result<PatternSearchResult[]>>;
|
|
388
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Hybrid score for a hit found by both vector and FTS5 search (#653):
|
|
396
|
+
* 75% vector + 25% BM25, but lexical agreement may only raise the vector
|
|
397
|
+
* score — a weak BM25 match must not demote a near-identical vector hit.
|
|
398
|
+
*/
|
|
399
|
+
export declare function blendFtsScore(vectorScore: number, ftsScore: number): number;
|
|
389
400
|
/**
|
|
390
401
|
* Create a new pattern store instance.
|
|
391
402
|
*
|
|
@@ -772,10 +772,11 @@ export class PatternStore {
|
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
// FTS5 hybrid search: blend BM25 text relevance with vector similarity
|
|
775
|
-
//
|
|
776
|
-
|
|
775
|
+
// (see blendFtsScore) for patterns found by both
|
|
776
|
+
const ftsText = typeof query === 'string' ? query : options.textQuery;
|
|
777
|
+
if (ftsText?.trim() && this.sqliteStore) {
|
|
777
778
|
try {
|
|
778
|
-
const ftsResults = this.sqliteStore.searchFTS(
|
|
779
|
+
const ftsResults = this.sqliteStore.searchFTS(ftsText, limit * 2);
|
|
779
780
|
if (ftsResults.length > 0) {
|
|
780
781
|
const ftsScoreMap = new Map(ftsResults.map(r => [r.id, r.ftsScore]));
|
|
781
782
|
const existingIds = new Set(results.map(r => r.pattern.id));
|
|
@@ -783,7 +784,7 @@ export class PatternStore {
|
|
|
783
784
|
for (const result of results) {
|
|
784
785
|
const ftsScore = ftsScoreMap.get(result.pattern.id);
|
|
785
786
|
if (ftsScore !== undefined) {
|
|
786
|
-
result.score =
|
|
787
|
+
result.score = blendFtsScore(result.score, ftsScore);
|
|
787
788
|
}
|
|
788
789
|
}
|
|
789
790
|
// Add FTS5-only results not already in vector results
|
|
@@ -792,12 +793,19 @@ export class PatternStore {
|
|
|
792
793
|
continue;
|
|
793
794
|
const pattern = await this.get(ftsResult.id);
|
|
794
795
|
if (pattern && this.matchesFilters(pattern, options)) {
|
|
795
|
-
|
|
796
|
+
// #653: ftsScore is normalized to the best hit, so only a
|
|
797
|
+
// whole-phrase hit may read as a near-duplicate; term-only hits
|
|
798
|
+
// report the conservative keyword score as their similarity.
|
|
799
|
+
// Scaled by query-term coverage so the best of a weak lexical
|
|
800
|
+
// set (e.g. one shared stopword) cannot outrank vector hits.
|
|
801
|
+
const keywordScore = 0.5 * ftsResult.ftsScore * ftsResult.coverage;
|
|
802
|
+
const similarity = ftsResult.phrase ? ftsResult.ftsScore : keywordScore;
|
|
803
|
+
const reuseInfo = this.calculateReuseInfo(pattern, similarity);
|
|
796
804
|
results.push({
|
|
797
805
|
pattern,
|
|
798
|
-
score:
|
|
806
|
+
score: keywordScore, // FTS-only: exact keyword match is valuable
|
|
799
807
|
matchType: 'exact',
|
|
800
|
-
similarity
|
|
808
|
+
similarity,
|
|
801
809
|
canReuse: reuseInfo.canReuse,
|
|
802
810
|
estimatedTokenSavings: reuseInfo.estimatedTokenSavings,
|
|
803
811
|
reuseConfidence: reuseInfo.reuseConfidence,
|
|
@@ -812,7 +820,9 @@ export class PatternStore {
|
|
|
812
820
|
}
|
|
813
821
|
// Text search fallback or additional
|
|
814
822
|
if (typeof query === 'string' || results.length < limit) {
|
|
815
|
-
|
|
823
|
+
// #653: with the caller's text, pad with text matches rather than
|
|
824
|
+
// unrelated patterns ranked by quality score alone.
|
|
825
|
+
const textResults = await this.searchByText(ftsText ?? '', options, limit - results.length);
|
|
816
826
|
// Deduplicate: only add text results not already present
|
|
817
827
|
const existingIds = new Set(results.map(r => r.pattern.id));
|
|
818
828
|
for (const tr of textResults) {
|
|
@@ -1443,6 +1453,14 @@ export class PatternStore {
|
|
|
1443
1453
|
// ============================================================================
|
|
1444
1454
|
// Factory Functions
|
|
1445
1455
|
// ============================================================================
|
|
1456
|
+
/**
|
|
1457
|
+
* Hybrid score for a hit found by both vector and FTS5 search (#653):
|
|
1458
|
+
* 75% vector + 25% BM25, but lexical agreement may only raise the vector
|
|
1459
|
+
* score — a weak BM25 match must not demote a near-identical vector hit.
|
|
1460
|
+
*/
|
|
1461
|
+
export function blendFtsScore(vectorScore, ftsScore) {
|
|
1462
|
+
return Math.max(vectorScore, 0.75 * vectorScore + 0.25 * ftsScore);
|
|
1463
|
+
}
|
|
1446
1464
|
/**
|
|
1447
1465
|
* Create a new pattern store instance.
|
|
1448
1466
|
*
|
|
@@ -201,6 +201,12 @@ export declare function calculateQualityScore(pattern: {
|
|
|
201
201
|
* experience-capture, and shouldPromotePattern().
|
|
202
202
|
*/
|
|
203
203
|
export declare const PROMOTION_THRESHOLD = 3;
|
|
204
|
+
/**
|
|
205
|
+
* Minimum success rate a pattern needs before it can be promoted to long-term
|
|
206
|
+
* storage. Paired with PROMOTION_THRESHOLD; `aqe init` reports both values in
|
|
207
|
+
* the generated settings so they match what the runtime enforces (#778).
|
|
208
|
+
*/
|
|
209
|
+
export declare const PROMOTION_MIN_SUCCESS_RATE = 0.7;
|
|
204
210
|
export interface PromotionCheck {
|
|
205
211
|
meetsUsageCriteria: boolean;
|
|
206
212
|
meetsQualityCriteria: boolean;
|
|
@@ -81,6 +81,12 @@ export function calculateQualityScore(pattern) {
|
|
|
81
81
|
* experience-capture, and shouldPromotePattern().
|
|
82
82
|
*/
|
|
83
83
|
export const PROMOTION_THRESHOLD = 3;
|
|
84
|
+
/**
|
|
85
|
+
* Minimum success rate a pattern needs before it can be promoted to long-term
|
|
86
|
+
* storage. Paired with PROMOTION_THRESHOLD; `aqe init` reports both values in
|
|
87
|
+
* the generated settings so they match what the runtime enforces (#778).
|
|
88
|
+
*/
|
|
89
|
+
export const PROMOTION_MIN_SUCCESS_RATE = 0.7;
|
|
84
90
|
/**
|
|
85
91
|
* Check if pattern should be promoted to long-term storage
|
|
86
92
|
* Requires 3+ successful uses as per ADR-021
|
|
@@ -92,7 +98,7 @@ export const PROMOTION_THRESHOLD = 3;
|
|
|
92
98
|
*/
|
|
93
99
|
export function shouldPromotePattern(pattern, coherenceEnergy, coherenceThreshold = 0.4) {
|
|
94
100
|
const meetsUsageCriteria = pattern.tier === 'short-term' && pattern.successfulUses >= PROMOTION_THRESHOLD;
|
|
95
|
-
const meetsQualityCriteria = pattern.successRate >=
|
|
101
|
+
const meetsQualityCriteria = pattern.successRate >= PROMOTION_MIN_SUCCESS_RATE && pattern.confidence >= 0.6;
|
|
96
102
|
// NEW: Coherence criteria - only block if coherence energy is provided and exceeds threshold
|
|
97
103
|
const meetsCoherenceCriteria = coherenceEnergy === undefined || coherenceEnergy < coherenceThreshold;
|
|
98
104
|
let blockReason;
|
|
@@ -342,6 +342,8 @@ export class QEReasoningBank {
|
|
|
342
342
|
}
|
|
343
343
|
return this.patternStore.search(searchQuery, {
|
|
344
344
|
...options,
|
|
345
|
+
// #653: keep the text so FTS5 hybrid scoring still runs on the vector path
|
|
346
|
+
textQuery: typeof query === 'string' && query.trim() ? query : options?.textQuery,
|
|
345
347
|
useVectorSearch,
|
|
346
348
|
embeddingSpaceId: typeof query === 'string'
|
|
347
349
|
? getActiveEmbeddingSpaceIdentity()?.spaceId
|
|
@@ -444,6 +446,7 @@ export class QEReasoningBank {
|
|
|
444
446
|
limit: this.config.maxRoutingCandidates,
|
|
445
447
|
domain: detectedDomains[0],
|
|
446
448
|
useVectorSearch: true,
|
|
449
|
+
textQuery: request.task,
|
|
447
450
|
});
|
|
448
451
|
const patterns = patternResults.success
|
|
449
452
|
? patternResults.value.map((r) => r.pattern)
|
|
@@ -15,7 +15,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
15
15
|
import { ok, err } from '../shared/types/index.js';
|
|
16
16
|
import { toErrorMessage } from '../shared/error-utils.js';
|
|
17
17
|
import { calculateQualityScore, validateQEPattern, mapQEDomainToAQE, PROMOTION_THRESHOLD, } from './qe-patterns.js';
|
|
18
|
-
import { DEFAULT_PATTERN_STORE_CONFIG } from './pattern-store.js';
|
|
18
|
+
import { DEFAULT_PATTERN_STORE_CONFIG, blendFtsScore } from './pattern-store.js';
|
|
19
19
|
import { ensureEndpointEmbeddingSpaceIdentity, getActiveEmbeddingSpaceIdentity } from './real-embeddings.js';
|
|
20
20
|
import { verifyOrCreateEmbeddingSpaceManifest } from './embedding-space.js';
|
|
21
21
|
import { PatternMutationError } from './pattern-mutation-error.js';
|
|
@@ -382,22 +382,35 @@ export class RvfPatternStore {
|
|
|
382
382
|
}
|
|
383
383
|
catch { /* SQLite unavailable */ }
|
|
384
384
|
}
|
|
385
|
-
// FTS5
|
|
386
|
-
|
|
385
|
+
// FTS5 hybrid search via SQLite
|
|
386
|
+
const ftsText = typeof query === 'string' ? query : options.textQuery;
|
|
387
|
+
if (ftsText?.trim() && this.sqliteStore) {
|
|
387
388
|
try {
|
|
388
|
-
const ftsResults = this.sqliteStore.searchFTS(
|
|
389
|
+
const ftsResults = this.sqliteStore.searchFTS(ftsText, limit * 2);
|
|
389
390
|
const existingIds = new Set(results.map(r => r.pattern.id));
|
|
391
|
+
// #653: same vector/FTS5 blend as PatternStore for hits found by
|
|
392
|
+
// both, so lexical relevance can reorder vector results.
|
|
393
|
+
const ftsScoreMap = new Map(ftsResults.map(r => [r.id, r.ftsScore]));
|
|
394
|
+
for (const result of results) {
|
|
395
|
+
const ftsScore = ftsScoreMap.get(result.pattern.id);
|
|
396
|
+
if (ftsScore !== undefined) {
|
|
397
|
+
result.score = blendFtsScore(result.score, ftsScore);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
390
400
|
for (const ftsResult of ftsResults) {
|
|
391
401
|
if (existingIds.has(ftsResult.id))
|
|
392
402
|
continue;
|
|
393
403
|
const pattern = await this.get(ftsResult.id);
|
|
394
404
|
if (pattern && this.matchesFilters(pattern, options)) {
|
|
395
|
-
|
|
405
|
+
// Same keyword-only similarity rule as PatternStore (#653)
|
|
406
|
+
const keywordScore = 0.5 * ftsResult.ftsScore * ftsResult.coverage;
|
|
407
|
+
const similarity = ftsResult.phrase ? ftsResult.ftsScore : keywordScore;
|
|
408
|
+
const reuseInfo = this.calculateReuseInfo(pattern, similarity);
|
|
396
409
|
results.push({
|
|
397
410
|
pattern,
|
|
398
|
-
score:
|
|
411
|
+
score: keywordScore,
|
|
399
412
|
matchType: 'exact',
|
|
400
|
-
similarity
|
|
413
|
+
similarity,
|
|
401
414
|
canReuse: reuseInfo.canReuse,
|
|
402
415
|
estimatedTokenSavings: reuseInfo.estimatedTokenSavings,
|
|
403
416
|
reuseConfidence: reuseInfo.reuseConfidence,
|
|
@@ -91,12 +91,19 @@ export declare class SQLitePatternStore {
|
|
|
91
91
|
}): QEPattern[];
|
|
92
92
|
/**
|
|
93
93
|
* FTS5 full-text search for patterns.
|
|
94
|
-
* Returns pattern IDs with BM25 relevance scores.
|
|
94
|
+
* Returns pattern IDs with BM25 relevance scores. `phrase` marks hits that
|
|
95
|
+
* also contain the whole query as a phrase (near-duplicate evidence).
|
|
96
|
+
* `coverage` is the fraction of distinct query terms the hit contains: an
|
|
97
|
+
* absolute measure, unlike `ftsScore`, which is relative to the best hit.
|
|
95
98
|
*/
|
|
96
99
|
searchFTS(query: string, limit?: number): Array<{
|
|
97
100
|
id: string;
|
|
98
101
|
ftsScore: number;
|
|
102
|
+
phrase: boolean;
|
|
103
|
+
coverage: number;
|
|
99
104
|
}>;
|
|
105
|
+
/** IDs whose FTS5 text contains the whole query as one phrase. */
|
|
106
|
+
private searchFTSPhraseIds;
|
|
100
107
|
/** Last FTS5 search latency in ms, for instrumentation */
|
|
101
108
|
private _lastFtsLatencyMs;
|
|
102
109
|
get lastFtsLatencyMs(): number;
|