agentic-qe 3.9.25 → 3.9.26
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 +104 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/bundle.js +5 -5
- package/dist/cli/chunks/adapter-LIPKRUFH.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-3JH5PJWN.js → agent-booster-wasm-ZOADSKRX.js} +2 -2
- package/dist/cli/chunks/{agent-handler-3FEJU2TM.js → agent-handler-SPLFCIHA.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-FCLJ7NQB.js → agent-memory-branch-R6ZVL2FT.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-XJGJ6YS7.js +2 -0
- package/dist/cli/chunks/{audit-FSLEJMM5.js → audit-6TQQFGQN.js} +2 -2
- package/dist/cli/chunks/base-22RFSMJU.js +2 -0
- package/dist/cli/chunks/{hnswlib-node-KUWXTCD4.js → better-sqlite3-QIKWKEGD.js} +2 -2
- package/dist/cli/chunks/{brain-handler-IVRXCPLL.js → brain-handler-6BQCTD3M.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-EXW3AFAQ.js → branch-enumerator-JTESSKID.js} +2 -2
- package/dist/cli/chunks/{browser-3J6OTKWZ.js → browser-YDZLFZNH.js} +2 -2
- package/dist/cli/chunks/browser-workflow-ST7DX7KA.js +2 -0
- package/dist/cli/chunks/{chunk-5RJENBAG.js → chunk-22YZRYG4.js} +3 -3
- package/dist/cli/chunks/{chunk-SDOG2MMY.js → chunk-2OFL5HSB.js} +2 -2
- package/dist/cli/chunks/{chunk-7VNGENWZ.js → chunk-2XOIJE7J.js} +2 -2
- package/dist/cli/chunks/{chunk-V3L3FD4I.js → chunk-3K2QCWFD.js} +1 -1
- package/dist/cli/chunks/{chunk-WOD7Y7NC.js → chunk-3QPQZJUY.js} +2 -2
- package/dist/cli/chunks/{chunk-VUEYEMMJ.js → chunk-4EBC7ATS.js} +9 -9
- package/dist/cli/chunks/{chunk-IJH3WAC4.js → chunk-4F6RPT7N.js} +3 -3
- package/dist/cli/chunks/{chunk-F3IEJL4O.js → chunk-4GUVB7FG.js} +2 -2
- package/dist/cli/chunks/{chunk-R7VO6E3E.js → chunk-4I6XGKSB.js} +2 -2
- package/dist/cli/chunks/{chunk-LFD3YTNY.js → chunk-4QUKBJAS.js} +2 -2
- package/dist/cli/chunks/{chunk-M4GE3R5K.js → chunk-4RFODPDS.js} +2 -2
- package/dist/cli/chunks/{chunk-DZVIMPC2.js → chunk-4U57VG6R.js} +2 -2
- package/dist/cli/chunks/{chunk-LTWNVZDR.js → chunk-4ZAOHYFA.js} +2 -2
- package/dist/cli/chunks/{chunk-GV3LIGPJ.js → chunk-5JGFDJA6.js} +2 -2
- package/dist/cli/chunks/{chunk-5SGWYFOV.js → chunk-5TTQNRAP.js} +1 -1
- package/dist/cli/chunks/{chunk-UHWGEZXG.js → chunk-6AH4SN6I.js} +1 -1
- package/dist/cli/chunks/{chunk-X66FBTTD.js → chunk-6UFMNYQV.js} +1 -1
- package/dist/cli/chunks/{chunk-3ITRVWXL.js → chunk-6VRKHHYI.js} +1 -1
- package/dist/cli/chunks/{chunk-I5WMRFJ2.js → chunk-7L3F76MS.js} +3 -3
- package/dist/cli/chunks/{chunk-XXG6OQSR.js → chunk-7T2KT74O.js} +25 -9
- package/dist/cli/chunks/{chunk-NURG5LQO.js → chunk-A4U4DNPR.js} +1 -1
- package/dist/cli/chunks/{chunk-W7ULVE22.js → chunk-AGBIQXB4.js} +2 -2
- package/dist/cli/chunks/{chunk-DPDDWIL7.js → chunk-AH3IPNOJ.js} +2 -2
- package/dist/cli/chunks/{chunk-AQXKM5VB.js → chunk-ANEIDNH7.js} +2 -2
- package/dist/cli/chunks/{chunk-I5AVFRDJ.js → chunk-AOURUJFN.js} +1 -1
- package/dist/cli/chunks/{chunk-3OPXTQMB.js → chunk-ARLHD5MG.js} +1 -1
- package/dist/cli/chunks/{chunk-74YWPNUB.js → chunk-AUD45G7X.js} +2 -2
- package/dist/cli/chunks/{chunk-THQNIMJU.js → chunk-B3KHJQ34.js} +2 -2
- package/dist/cli/chunks/{chunk-7YV5T64G.js → chunk-BBALCRJM.js} +1 -1
- package/dist/cli/chunks/{chunk-4EUPBVPV.js → chunk-BFSKBIAM.js} +1 -1
- package/dist/cli/chunks/{chunk-AFQNJJWA.js → chunk-BOV44F3Z.js} +2 -2
- package/dist/cli/chunks/{chunk-J2O5RRNH.js → chunk-C5ZA6UBI.js} +1 -1
- package/dist/cli/chunks/{chunk-EY2W47L3.js → chunk-C77FS4ER.js} +2 -2
- package/dist/cli/chunks/{chunk-N64WUFUI.js → chunk-CBBVUZFD.js} +4 -4
- package/dist/cli/chunks/{chunk-W2OPF27P.js → chunk-CMFRBO4N.js} +3 -3
- package/dist/cli/chunks/{chunk-MVT2F4Z4.js → chunk-CU5Q46NR.js} +4 -4
- package/dist/cli/chunks/{chunk-IV4OBL4P.js → chunk-CYPOU765.js} +1 -1
- package/dist/cli/chunks/{chunk-5XCHNZNW.js → chunk-DBSEDJ7P.js} +2 -2
- package/dist/cli/chunks/{chunk-4DVQS5LA.js → chunk-EEWGVVKH.js} +2 -2
- package/dist/cli/chunks/{chunk-LKRGOCDO.js → chunk-EFAN5HUX.js} +2 -2
- package/dist/cli/chunks/{chunk-FFP7OV5L.js → chunk-EPCKRFMU.js} +2 -2
- package/dist/cli/chunks/{chunk-HLVL2N5U.js → chunk-EQ4IZRD5.js} +2 -2
- package/dist/cli/chunks/{chunk-4FRRDVWH.js → chunk-ETBVBV2M.js} +2 -2
- package/dist/cli/chunks/{chunk-M4F7EAR6.js → chunk-EX7UGFWX.js} +2 -2
- package/dist/cli/chunks/{chunk-MP4GPPOD.js → chunk-EYFL6QLX.js} +2 -2
- package/dist/cli/chunks/{chunk-MMWH7D2O.js → chunk-F24XTOID.js} +2 -2
- package/dist/cli/chunks/{chunk-P5ZV4RCF.js → chunk-F77VZ4IY.js} +2 -2
- package/dist/cli/chunks/{chunk-AZ3GC5UX.js → chunk-FDC2ANCP.js} +3 -3
- package/dist/cli/chunks/{chunk-TCRBP7GO.js → chunk-FRUDEEZH.js} +1 -1
- package/dist/cli/chunks/{chunk-NIXA5DVA.js → chunk-FWPV44HL.js} +2 -2
- package/dist/cli/chunks/{chunk-76RCKSCL.js → chunk-G3KTLF57.js} +2 -2
- package/dist/cli/chunks/{chunk-PFH2G7AP.js → chunk-G42KXBBG.js} +2 -2
- package/dist/cli/chunks/{chunk-3LSHQUQ2.js → chunk-GHQ6QT47.js} +2 -2
- package/dist/cli/chunks/{chunk-2ZN6YGSA.js → chunk-GW5T4BSO.js} +5 -5
- package/dist/cli/chunks/{chunk-2ACE3T6H.js → chunk-HKHRIPXP.js} +7 -7
- package/dist/cli/chunks/{chunk-MYDJYPBT.js → chunk-HSQLB4GR.js} +2 -2
- package/dist/cli/chunks/{chunk-FUNP4GGE.js → chunk-IKRLPS4M.js} +2 -2
- package/dist/cli/chunks/{chunk-JPB44BMP.js → chunk-IVNZLESN.js} +2 -2
- package/dist/cli/chunks/{chunk-U67BTJC3.js → chunk-JWKNHSXP.js} +2 -2
- package/dist/cli/chunks/{chunk-Q3MHHREJ.js → chunk-K64UL5PA.js} +2 -2
- package/dist/cli/chunks/{chunk-OJ7RJC7F.js → chunk-KQQPUHQD.js} +1 -1
- package/dist/cli/chunks/{chunk-QJKXAYOM.js → chunk-LP7ILPFQ.js} +2 -2
- package/dist/cli/chunks/{chunk-75PD5ATI.js → chunk-LPDPGCDC.js} +2 -2
- package/dist/cli/chunks/{chunk-VLNCDVU6.js → chunk-MAPQ2UZ5.js} +2 -2
- package/dist/cli/chunks/{chunk-H6IV3LHA.js → chunk-MSPY7HMF.js} +2 -2
- package/dist/cli/chunks/{chunk-6UH7B3PE.js → chunk-MTRA6I7Y.js} +1 -1
- package/dist/cli/chunks/{chunk-W5RRYCQ7.js → chunk-MW4WEMLE.js} +2 -2
- package/dist/cli/chunks/{chunk-CRTUB5NH.js → chunk-MXZY5IJA.js} +1 -1
- package/dist/cli/chunks/{chunk-XMYX6HAG.js → chunk-N2ET2TL5.js} +2 -2
- package/dist/cli/chunks/{chunk-JXSEJIIB.js → chunk-N3GLRFMH.js} +1 -1
- package/dist/cli/chunks/{chunk-ML7AEOPI.js → chunk-OFAXQGU5.js} +2 -2
- package/dist/cli/chunks/{chunk-XPXL75LN.js → chunk-ONYCSOAR.js} +1 -1
- package/dist/cli/chunks/{chunk-4GVLZIHN.js → chunk-P6M6LNSI.js} +2 -2
- package/dist/cli/chunks/{chunk-2IRRXFBV.js → chunk-PJPNRDEF.js} +2 -2
- package/dist/cli/chunks/{chunk-R3OII6WM.js → chunk-PLB75ASZ.js} +1 -1
- package/dist/cli/chunks/{chunk-73SPNQDP.js → chunk-PPP7KZQL.js} +2 -2
- package/dist/cli/chunks/{chunk-5ZADSKFC.js → chunk-PS7YB3IV.js} +3 -3
- package/dist/cli/chunks/{chunk-KYDLYPOG.js → chunk-PSOF6DZA.js} +8 -8
- package/dist/cli/chunks/{chunk-T5WFV3EH.js → chunk-QFXOKERO.js} +1 -1
- package/dist/cli/chunks/{chunk-VRNRR3VU.js → chunk-QQMGUORN.js} +2 -2
- package/dist/cli/chunks/{chunk-QOVAU4DT.js → chunk-QU7TNCUB.js} +1 -1
- package/dist/cli/chunks/{chunk-MAWGLIAE.js → chunk-QUHNBIUZ.js} +1 -1
- package/dist/cli/chunks/{chunk-5DOCH2OX.js → chunk-QXQWQRZA.js} +1 -1
- package/dist/cli/chunks/{chunk-XC34CWA3.js → chunk-RD3CNJWR.js} +2 -2
- package/dist/cli/chunks/{chunk-JFWRCQCV.js → chunk-RLAXE5HU.js} +2 -2
- package/dist/cli/chunks/{chunk-XBBNMF3C.js → chunk-RNVXTNEB.js} +2 -2
- package/dist/cli/chunks/chunk-RSNZQ3MN.js +2 -0
- package/dist/cli/chunks/{chunk-4ASWQOFE.js → chunk-RXQX6JNQ.js} +2 -2
- package/dist/cli/chunks/{chunk-VZVHYH7B.js → chunk-SDD3XQ7X.js} +1 -1
- package/dist/cli/chunks/{chunk-NADXRFKX.js → chunk-SGGYSL7J.js} +1 -1
- package/dist/cli/chunks/{chunk-7G2UJMKQ.js → chunk-SYQZPNHQ.js} +2 -2
- package/dist/cli/chunks/{chunk-PMAMZZ6B.js → chunk-SYRUG2T7.js} +1 -1
- package/dist/cli/chunks/{chunk-X33KZ6WO.js → chunk-TLBP7EVX.js} +1 -1
- package/dist/cli/chunks/{chunk-6IRQAAMQ.js → chunk-TQBP3YGG.js} +1 -1
- package/dist/cli/chunks/{chunk-7QILWWRD.js → chunk-TRIA62JA.js} +2 -2
- package/dist/cli/chunks/{chunk-DNIU6W6Z.js → chunk-TU2A5BGA.js} +2 -2
- package/dist/cli/chunks/{chunk-SKRQF45C.js → chunk-TZ73IAF5.js} +2 -2
- package/dist/cli/chunks/{chunk-XBGO4NQE.js → chunk-U5BMUXV2.js} +2 -2
- package/dist/cli/chunks/{chunk-P6REB3IC.js → chunk-UJPERPQU.js} +1 -1
- package/dist/cli/chunks/{chunk-OGBDSSVO.js → chunk-VBJ4UQ3X.js} +2 -2
- package/dist/cli/chunks/{chunk-FHKQSSQT.js → chunk-VC2FHUOY.js} +2 -2
- package/dist/cli/chunks/{chunk-KAVN56IT.js → chunk-VHHFSVR3.js} +2 -2
- package/dist/cli/chunks/{chunk-ZGGHGWXF.js → chunk-VPPXZORB.js} +1 -1
- package/dist/cli/chunks/{chunk-VYFRA4ZP.js → chunk-WCI2FMWZ.js} +1 -1
- package/dist/cli/chunks/{chunk-ILIKB32B.js → chunk-WND3EYCS.js} +2 -2
- package/dist/cli/chunks/{chunk-FO3VJDCI.js → chunk-XAA7ZBNG.js} +1 -1
- package/dist/cli/chunks/{chunk-KVZKBPKC.js → chunk-XDEF6UFY.js} +2 -2
- package/dist/cli/chunks/{chunk-FL2G2VFC.js → chunk-XHENTAXI.js} +2 -2
- package/dist/cli/chunks/{chunk-5KWOG53N.js → chunk-XYMUYLHY.js} +1 -1
- package/dist/cli/chunks/{chunk-HEVA2HR3.js → chunk-Y3YJMKXS.js} +2 -2
- package/dist/cli/chunks/{chunk-6PW5L2SC.js → chunk-YCZEXLKL.js} +2 -2
- package/dist/cli/chunks/{chunk-73SK2MNU.js → chunk-YUMVG55I.js} +2 -2
- package/dist/cli/chunks/{chunk-EKQI2HRL.js → chunk-YYOKX7VH.js} +2 -2
- package/dist/cli/chunks/{chunk-QFNWLRPV.js → chunk-ZFLD5ATZ.js} +2 -2
- package/dist/cli/chunks/{chunk-XNXFB4TV.js → chunk-ZUUNOGHI.js} +2 -2
- package/dist/cli/chunks/{ci-2UUAA532.js → ci-EAX5WWT6.js} +2 -2
- package/dist/cli/chunks/{ci-output-NLBMSDOP.js → ci-output-JCWHRJ2A.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-UMHTVSA2.js → circuit-breaker-RAEDVT33.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-Q6A7T2CH.js → claude-flow-setup-NJAY4WXY.js} +2 -2
- package/dist/cli/chunks/client-6463JNJR.js +2 -0
- package/dist/cli/chunks/{cline-installer-UPIZH2ZF.js → cline-installer-X3GCUEWC.js} +2 -2
- package/dist/cli/chunks/{code-TPVQFW7C.js → code-GXJ6JC6O.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-Z7J3RZ4Q.js → code-index-extractor-TTA7HZEW.js} +2 -2
- package/dist/cli/chunks/{codex-installer-GTT3IBZT.js → codex-installer-TXMSGJHK.js} +2 -2
- package/dist/cli/chunks/{completions-TXYGM6BK.js → completions-RSFIDY22.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-HMXULCFI.js → complexity-analyzer-C6244ZOI.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-3GDGFMEE.js → continuedev-installer-5WQIRQW4.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-S4KIV6OT.js → copilot-installer-5Q64SC52.js} +2 -2
- package/dist/cli/chunks/{cost-tracker-E2M57AGD.js → cost-tracker-6SBRULNN.js} +2 -2
- package/dist/cli/chunks/{coverage-NXF6THG2.js → coverage-X2AG3K6E.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-OYUCD42M.js +2 -0
- package/dist/cli/chunks/{cursor-installer-GSMPSNIZ.js → cursor-installer-VHZ5LEPG.js} +2 -2
- package/dist/cli/chunks/{daemon-IGNIH3TQ.js → daemon-CDQXWIV4.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-FFCTYK3P.js → dag-attention-scheduler-33UWNTSB.js} +2 -2
- package/dist/cli/chunks/{detect-CFB72DRI.js → detect-UDWTKRQL.js} +2 -2
- package/dist/cli/chunks/{dist-node-RGD4BMAQ.js → dist-node-CKTPNPBG.js} +2 -2
- package/dist/cli/chunks/{domain-handler-SAKJIOXO.js → domain-handler-5J4AH4XR.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-44QPKEAY.js → domain-transfer-P6VPN56R.js} +2 -2
- package/dist/cli/chunks/dream-R76KD347.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-Z4MA4ZST.js → embed-and-insert-pattern-2YFFI7IN.js} +2 -2
- package/dist/cli/chunks/{eval-IDTYZI7P.js → eval-K7VFIO2T.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-HXLGMWLK.js → experience-capture-middleware-P4RQW7JV.js} +3 -3
- package/dist/cli/chunks/{fast-paths-V47QDNVC.js → fast-paths-T27YLQWQ.js} +2 -2
- package/dist/cli/chunks/{feature-flags-YWKFG357.js → feature-flags-HHQNCU6V.js} +2 -2
- package/dist/cli/chunks/{feature-flags-RALYJOEU.js → feature-flags-YFPFETDZ.js} +2 -2
- package/dist/cli/chunks/{file-discovery-R3CDYNKP.js → file-discovery-ZKNENDOJ.js} +2 -2
- package/dist/cli/chunks/{fleet-XBVAD6CL.js → fleet-N5OTMFIN.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-HVZMQHEX.js → gnn-wrapper-D6L4FIWY.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-BBHOWYMJ.js → heartbeat-handler-5RDU3KKK.js} +4 -4
- package/dist/cli/chunks/{heartbeat-scheduler-SNUBX4LF.js → heartbeat-scheduler-FALV24GQ.js} +2 -2
- package/dist/cli/chunks/hnsw-adapter-CYWGI732.js +2 -0
- package/dist/cli/chunks/hnsw-index-UOYT3QKQ.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-NKQVKQ3J.js → hnsw-legacy-bridge-ARD7KA3G.js} +2 -2
- package/dist/cli/chunks/{better-sqlite3-SAJ7HAFG.js → hnswlib-node-TULXUZI4.js} +2 -2
- package/dist/cli/chunks/hooks-6HA23JHQ.js +259 -0
- package/dist/cli/chunks/{hybrid-router-YUVRBFMA.js → hybrid-router-XUYQW7FJ.js} +2 -2
- package/dist/cli/chunks/{hypergraph-engine-EKOOW425.js → hypergraph-engine-OGGXYQAO.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-M4MSX62E.js → hypergraph-handler-UFV3XYVX.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-PWV7CJUA.js +2 -0
- package/dist/cli/chunks/{init-handler-W3DIXGVJ.js → init-handler-VUSXGONQ.js} +6 -6
- package/dist/cli/chunks/init-wizard-DKIFAPJJ.js +2 -0
- package/dist/cli/chunks/kernel-WQL2MUBH.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-VVFIT4TJ.js → kilocode-installer-C2JMSYAU.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-JCNYLJXT.js → kiro-installer-6LJFFEEZ.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-U5OZDWGT.js +2 -0
- package/dist/cli/chunks/{learning-5X4UDI4G.js → learning-4B624JV3.js} +3 -3
- package/dist/cli/chunks/{llm-router-M6NOWWP3.js → llm-router-QUOLZECD.js} +4 -4
- package/dist/cli/chunks/{load-UMYB2ZGL.js → load-MIQWBMGE.js} +2 -2
- package/dist/cli/chunks/load-test-D2CQYRZQ.js +2 -0
- package/dist/cli/chunks/{mcp-ZDAIT7D5.js → mcp-MBJWNXDM.js} +2 -2
- package/dist/cli/chunks/{memory-FIWC4JNS.js → memory-WX3XHQZP.js} +5 -5
- package/dist/cli/chunks/memory-backend-HFIGDCZE.js +2 -0
- package/dist/cli/chunks/{memory-handlers-AHZIB4VB.js → memory-handlers-Q3XCN5SC.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-SA4CVCSA.js → multi-model-executor-RLY7OQOG.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-S6UDYAAQ.js → opencode-installer-JATQNZWA.js} +2 -2
- package/dist/cli/chunks/{orchestrator-JNVRGX5Z.js → orchestrator-7BNG32I2.js} +5 -5
- package/dist/cli/chunks/{pipeline-TLZ66K2O.js → pipeline-ORKGL7DP.js} +2 -2
- package/dist/cli/chunks/{platform-MQ5UXRLD.js → platform-4SLJDRVL.js} +2 -2
- package/dist/cli/chunks/{plugin-5S4YEY4C.js → plugin-V6FRBF4W.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-LIVSVFZA.js → prime-radiant-advanced-wasm-NA7AXKCA.js} +2 -2
- package/dist/cli/chunks/protocol-executor-LTJIEFVG.js +2 -0
- package/dist/cli/chunks/{protocol-handler-KQIOJKTK.js → protocol-handler-RSJOZ4XL.js} +2 -2
- package/dist/cli/chunks/{prove-YFRZIQ2O.js → prove-2ZMKUODH.js} +2 -2
- package/dist/cli/chunks/{provider-manager-OKEHQIHC.js → provider-manager-PSPAFCK7.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-ZJ56AWO2.js +2 -0
- package/dist/cli/chunks/{quality-GGBNSKJU.js → quality-6PZOOQSK.js} +2 -2
- package/dist/cli/chunks/queen-coordinator-CZA7SS4O.js +2 -0
- package/dist/cli/chunks/{real-embeddings-2KWJAO6Y.js → real-embeddings-BGNTSKHD.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-KYZQFIEV.js → roocode-installer-NOHRQJIP.js} +2 -2
- package/dist/cli/chunks/router-N23IDBEQ.js +2 -0
- package/dist/cli/chunks/routing-feedback-IADXJ4RV.js +2 -0
- package/dist/cli/chunks/{routing-handler-Y5FLAUB2.js → routing-handler-ZAOGNENU.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-MHSEXDRI.js → ruvector-commands-5K3Q4N5H.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-5PV65OR3.js → rvf-dual-writer-NWFQC4KN.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-3SZW2YA4.js → rvf-migration-adapter-MS7QGBWK.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-5LN2I44C.js → rvf-migration-coordinator-YUBSSB6Z.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-MOR7NUA5.js +2 -0
- package/dist/cli/chunks/safe-db-IRAUFZTC.js +2 -0
- package/dist/cli/chunks/schedule-PKUUCNCA.js +2 -0
- package/dist/cli/chunks/scheduler-NE4NP4W5.js +2 -0
- package/dist/cli/chunks/{security-THETDKDS.js → security-BJWJWQRB.js} +3 -3
- package/dist/cli/chunks/shared-rvf-adapter-OTON2BMV.js +2 -0
- package/dist/cli/chunks/{shared-rvf-dual-writer-NFUIB2ZL.js → shared-rvf-dual-writer-LEBD3EHA.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-DXFBYN5L.js +2 -0
- package/dist/cli/chunks/{status-handler-CUW2OUS2.js → status-handler-XANOAVIB.js} +2 -2
- package/dist/cli/chunks/{structural-health-IK2LN4ES.js → structural-health-TZA7PJ2T.js} +2 -2
- package/dist/cli/chunks/{sync-DA33QCRD.js → sync-MKNYPUYP.js} +2 -2
- package/dist/cli/chunks/{task-handler-24CAZ4MB.js → task-handler-KXSUKNQV.js} +2 -2
- package/dist/cli/chunks/{task-handlers-YHMFT7G3.js → task-handlers-54MMRT3D.js} +3 -3
- package/dist/cli/chunks/{test-ED6UE2EP.js → test-AKS5AAT7.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-RQP2IPFY.js → test-scheduling-OA7UPWQ5.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-POOTQ33M.js → token-bootstrap-ZIUNRF3E.js} +2 -2
- package/dist/cli/chunks/{token-usage-YNKDAQDK.js → token-usage-IJENSXPQ.js} +2 -2
- package/dist/cli/chunks/{transformers-NONXIEJK.js → transformers-CACTFP7H.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-HF7WUMJQ.js → tree-sitter-wasm-parser-4H4UVHAQ.js} +2 -2
- package/dist/cli/chunks/{types-UUKKK3L5.js → types-AGACOWV3.js} +2 -2
- package/dist/cli/chunks/unified-memory-4M3V7XL6.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-6IKIDXEW.js +2 -0
- package/dist/cli/chunks/unified-persistence-XJ4D23TB.js +2 -0
- package/dist/cli/chunks/{upgrade-ZNUFD44G.js → upgrade-EKE25VPL.js} +2 -2
- package/dist/cli/chunks/{validate-6IFD37Q4.js → validate-BZTYZQGP.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-74CENSXV.js → validate-swarm-GZANKJ7M.js} +2 -2
- package/dist/cli/chunks/{vibium-B2DDFMOQ.js → vibium-5X7QY25W.js} +2 -2
- package/dist/cli/chunks/visual-security-2X63QHFJ.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-X6ELMFG4.js → web-tree-sitter-KDFT6ZUY.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-HEIKCJDP.js → windsurf-installer-QFZJISMO.js} +2 -2
- package/dist/cli/chunks/{witness-chain-TO6YFTUT.js → witness-chain-ESSANJ4X.js} +2 -2
- package/dist/cli/chunks/witness-chain-MWIG363M.js +2 -0
- package/dist/cli/chunks/{workflow-WY73P2QK.js → workflow-EQFV2P66.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-B3ECPAFI.js +2 -0
- package/dist/cli/chunks/{wrappers-VF7LWJER.js → wrappers-RKJJDJLC.js} +2 -2
- package/dist/cli/commands/hooks-handlers/editing-hooks.js +21 -6
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.d.ts +2 -0
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.js +106 -6
- package/dist/cli/commands/hooks-handlers/hooks-shared.d.ts +20 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.js +72 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.js +33 -35
- package/dist/cli/commands/hooks-handlers/task-hooks.js +16 -3
- package/dist/learning/qe-reasoning-bank.js +39 -8
- package/dist/learning/rvf-pattern-store.d.ts +9 -0
- package/dist/learning/rvf-pattern-store.js +42 -0
- package/dist/learning/sqlite-persistence.d.ts +18 -0
- package/dist/learning/sqlite-persistence.js +59 -0
- package/dist/mcp/bundle.js +142 -126
- package/package.json +8 -3
- package/dist/cli/chunks/adapter-DRRUAQGD.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-5WYTKZ2I.js +0 -2
- package/dist/cli/chunks/base-LQVASZ6V.js +0 -2
- package/dist/cli/chunks/browser-workflow-TXQBTTSA.js +0 -2
- package/dist/cli/chunks/chunk-EOZIQTHG.js +0 -2
- package/dist/cli/chunks/client-TMGGCVZM.js +0 -2
- package/dist/cli/chunks/cross-domain-router-3WM3FES7.js +0 -2
- package/dist/cli/chunks/dream-SSRYUA2N.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-HGJUAHPN.js +0 -2
- package/dist/cli/chunks/hnsw-index-Q6GETC2C.js +0 -2
- package/dist/cli/chunks/hooks-HOD4SK3C.js +0 -237
- package/dist/cli/chunks/impact-analyzer-AIOLML23.js +0 -2
- package/dist/cli/chunks/init-wizard-FVH6XXAD.js +0 -2
- package/dist/cli/chunks/kernel-EBLOZQ7R.js +0 -2
- package/dist/cli/chunks/knowledge-graph-BXVKN4TE.js +0 -2
- package/dist/cli/chunks/load-test-DAFHZ5B4.js +0 -2
- package/dist/cli/chunks/memory-backend-LW2HMGVV.js +0 -2
- package/dist/cli/chunks/protocol-executor-LP4ID64X.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-6KBZMXKR.js +0 -2
- package/dist/cli/chunks/queen-coordinator-3ZAXRHXE.js +0 -2
- package/dist/cli/chunks/router-QJUMFZN6.js +0 -2
- package/dist/cli/chunks/routing-feedback-TVYNKT3K.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-G5NC4S6V.js +0 -2
- package/dist/cli/chunks/safe-db-7STPJWYA.js +0 -2
- package/dist/cli/chunks/schedule-NTT6YXMP.js +0 -2
- package/dist/cli/chunks/scheduler-BC5VEZI2.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-T63WSHGK.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-GJDAUFQU.js +0 -2
- package/dist/cli/chunks/unified-memory-JVMA5MJR.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-SSBWEA2T.js +0 -2
- package/dist/cli/chunks/unified-persistence-CWGWVHCB.js +0 -2
- package/dist/cli/chunks/visual-security-LGOI2DGK.js +0 -2
- package/dist/cli/chunks/witness-chain-JDFTWTJS.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-IDCHNGN6.js +0 -2
|
@@ -45,6 +45,37 @@ export async function checkAndTriggerDream(memoryBackend) {
|
|
|
45
45
|
}
|
|
46
46
|
const reason = timeTriggered ? 'time-interval' : 'experience-threshold';
|
|
47
47
|
console.log(chalk.dim(`[hooks] Dream trigger: ${reason} (${dreamState.experienceCount} experiences, ${Math.round(timeSinceLastDream / 60000)}min since last dream)`));
|
|
48
|
+
// Issue #461: concurrent hook subprocesses all see the same stale
|
|
49
|
+
// dreamState.lastDreamTime, race past the time/experience triggers, and
|
|
50
|
+
// start ~10s dream cycles in parallel. They then all hit the WAL writer
|
|
51
|
+
// at roughly the same time and 35% of cycles fail with
|
|
52
|
+
// `database is locked` (duration_ms ≈ 10050ms — the full cycle ran, only
|
|
53
|
+
// the write-back failed). `busy_timeout` doesn't help: it serializes
|
|
54
|
+
// sequential contention, not simultaneous writers.
|
|
55
|
+
//
|
|
56
|
+
// Peek at dream_cycles before we open the engine — if another process
|
|
57
|
+
// has started a cycle in the last 60s, bail out with reason='already-
|
|
58
|
+
// running'. Fail-open: any error in the guard lets the dream proceed,
|
|
59
|
+
// so this can never make things worse than they were before.
|
|
60
|
+
try {
|
|
61
|
+
const { getUnifiedMemory } = await import('../../../kernel/unified-memory.js');
|
|
62
|
+
const um = getUnifiedMemory();
|
|
63
|
+
if (um.isInitialized()) {
|
|
64
|
+
const db = um.getDatabase();
|
|
65
|
+
const running = db
|
|
66
|
+
.prepare(`SELECT COUNT(*) AS n FROM dream_cycles
|
|
67
|
+
WHERE status = 'running'
|
|
68
|
+
AND start_time > datetime('now', '-60 seconds')`)
|
|
69
|
+
.get();
|
|
70
|
+
if (running && running.n > 0) {
|
|
71
|
+
return { triggered: false, reason: 'already-running' };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// fail-open — if dream_cycles table is missing or unified memory not
|
|
77
|
+
// ready, we'd rather risk the rare lock than block dreaming entirely.
|
|
78
|
+
}
|
|
48
79
|
// Run a quick dream cycle
|
|
49
80
|
const { createDreamEngine } = await import('../../../learning/dream/index.js');
|
|
50
81
|
const { createQEReasoningBank: createRB } = await import('../../../learning/qe-reasoning-bank.js');
|
|
@@ -76,6 +107,27 @@ export async function checkAndTriggerDream(memoryBackend) {
|
|
|
76
107
|
await engine.loadPatternsAsConcepts(importPatterns);
|
|
77
108
|
}
|
|
78
109
|
const result = await engine.dream(10000);
|
|
110
|
+
// Issue #456: apply actionable insights inline so the hook path doesn't
|
|
111
|
+
// leave the backlog growing forever. DreamScheduler.autoApplyInsights()
|
|
112
|
+
// wires this in the daemon path, but checkAndTriggerDream is the
|
|
113
|
+
// hook-driven path and has no scheduler — without this block, every
|
|
114
|
+
// hook-fired dream cycle writes insights with applied=0 and they
|
|
115
|
+
// accumulate indefinitely (#456 evidence: 378 unapplied / 9 applied).
|
|
116
|
+
// Threshold matches DreamSchedulerConfig.insightConfidenceThreshold
|
|
117
|
+
// default (0.5) and InsightGenerator's `actionable` gate.
|
|
118
|
+
let insightsApplied = 0;
|
|
119
|
+
try {
|
|
120
|
+
for (const insight of result.insights) {
|
|
121
|
+
if (insight.actionable && insight.confidenceScore >= 0.5) {
|
|
122
|
+
const applyResult = await engine.applyInsight(insight.id);
|
|
123
|
+
if (applyResult.success)
|
|
124
|
+
insightsApplied++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (applyErr) {
|
|
129
|
+
console.error(chalk.dim(`[hooks] Dream apply: ${applyErr instanceof Error ? applyErr.message : 'unknown'}`));
|
|
130
|
+
}
|
|
79
131
|
// Update state
|
|
80
132
|
dreamState.lastDreamTime = new Date().toISOString();
|
|
81
133
|
dreamState.experienceCount = 0;
|
|
@@ -86,6 +138,7 @@ export async function checkAndTriggerDream(memoryBackend) {
|
|
|
86
138
|
triggered: true,
|
|
87
139
|
reason,
|
|
88
140
|
insightsGenerated: result.insights.length,
|
|
141
|
+
insightsApplied,
|
|
89
142
|
};
|
|
90
143
|
}
|
|
91
144
|
catch (error) {
|
|
@@ -236,12 +289,19 @@ export async function persistTaskOutcome(opts) {
|
|
|
236
289
|
model_tier, started_at, completed_at, source)
|
|
237
290
|
VALUES (?, ?, ?, ?, ?, ?, ?, NULL, datetime('now'), datetime('now'), ?)
|
|
238
291
|
`).run(experienceId, taskField.slice(0, 500), opts.agent, opts.domain ?? 'general', opts.success ? 1 : 0, qualityScore, durationMs, 'cli-hook-post-task');
|
|
239
|
-
// 2. Base experience_applications row
|
|
292
|
+
// 2. Base experience_applications row.
|
|
293
|
+
//
|
|
294
|
+
// Issue #463: tokens_saved was hardcoded to 0 on every row, so the
|
|
295
|
+
// learning-ROI column was permanently useless. qualityScore is already
|
|
296
|
+
// computed above and ranges 0.34 (failure+slow) to 0.68 (success+fast).
|
|
297
|
+
// Scale by 100 as a proxy until a real per-task token-delta calculation
|
|
298
|
+
// is wired in — gives a non-trivial 34-68 signal that downstream
|
|
299
|
+
// analytics can reason about.
|
|
240
300
|
db.prepare(`
|
|
241
301
|
INSERT INTO experience_applications
|
|
242
302
|
(id, experience_id, task, success, tokens_saved, feedback, applied_at)
|
|
243
303
|
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
|
|
244
|
-
`).run(`app-${Date.now()}-${randomUUID().slice(0, 8)}`, experienceId, taskField, opts.success ? 1 : 0,
|
|
304
|
+
`).run(`app-${Date.now()}-${randomUUID().slice(0, 8)}`, experienceId, taskField, opts.success ? 1 : 0, Math.round(qualityScore * 100), `[Patch 060] post-task outcome: ${opts.success ? 'success' : 'failure'}`);
|
|
245
305
|
// 3. Read bridge → fan out per-pattern application rows + delete bridge
|
|
246
306
|
try {
|
|
247
307
|
const bridgeRow = db.prepare(`
|
|
@@ -287,6 +347,27 @@ export async function persistTaskOutcome(opts) {
|
|
|
287
347
|
WHERE id = ?
|
|
288
348
|
`);
|
|
289
349
|
const getPatternConfidence = db.prepare(`SELECT confidence FROM qe_patterns WHERE id = ?`);
|
|
350
|
+
// Issue #455: recordOutcome() is called with a synthetic
|
|
351
|
+
// `task:agent:taskId` patternId that never matches qe_patterns.id, so
|
|
352
|
+
// checkPatternPromotionWithCoherence() is skipped for the real UUIDs
|
|
353
|
+
// updated here. Without an inline promotion check, short-term patterns
|
|
354
|
+
// that cross the thresholds (successful_uses ≥ 3, success_rate ≥ 0.7,
|
|
355
|
+
// confidence ≥ 0.6) stay short-term forever — qe_patterns.long-term
|
|
356
|
+
// count never grows past zero.
|
|
357
|
+
const promotionSelectStmt = db.prepare(`
|
|
358
|
+
SELECT tier, successful_uses, success_rate, confidence
|
|
359
|
+
FROM qe_patterns
|
|
360
|
+
WHERE id = ?
|
|
361
|
+
`);
|
|
362
|
+
const promotionUpdateStmt = db.prepare(`
|
|
363
|
+
UPDATE qe_patterns
|
|
364
|
+
SET tier = 'long-term', updated_at = datetime('now')
|
|
365
|
+
WHERE id = ?
|
|
366
|
+
AND tier = 'short-term'
|
|
367
|
+
AND successful_uses >= 3
|
|
368
|
+
AND success_rate >= 0.7
|
|
369
|
+
AND confidence >= 0.6
|
|
370
|
+
`);
|
|
290
371
|
for (const patternId of bridge.selectedPatternIds) {
|
|
291
372
|
insertApp.run(`app-${Date.now()}-${randomUUID().slice(0, 8)}`, experienceId, `${taskField}:pattern:${patternId}`, opts.success ? 1 : 0, perPatternTokens, `[Patch 160+300] task-bridge pattern_id=${patternId} ts=${perPatternTokens}`);
|
|
292
373
|
try {
|
|
@@ -297,6 +378,19 @@ export async function persistTaskOutcome(opts) {
|
|
|
297
378
|
}
|
|
298
379
|
}
|
|
299
380
|
catch { /* fail-soft per pattern */ }
|
|
381
|
+
// Issue #455: re-read post-UPDATE state and promote if thresholds met.
|
|
382
|
+
// Guarded WHERE clause makes the UPDATE idempotent and no-op for
|
|
383
|
+
// already-long-term rows or rows below threshold.
|
|
384
|
+
try {
|
|
385
|
+
const pm = promotionSelectStmt.get(patternId);
|
|
386
|
+
if (pm?.tier === 'short-term' &&
|
|
387
|
+
pm.successful_uses >= 3 &&
|
|
388
|
+
pm.success_rate >= 0.7 &&
|
|
389
|
+
pm.confidence >= 0.6) {
|
|
390
|
+
promotionUpdateStmt.run(patternId);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
catch { /* fail-soft per pattern */ }
|
|
300
394
|
}
|
|
301
395
|
// 4. Delete bridge entry (one-shot consumption)
|
|
302
396
|
if (bridgeRow) {
|
|
@@ -530,9 +624,16 @@ export async function consolidateExperiencesToPatterns() {
|
|
|
530
624
|
}
|
|
531
625
|
}
|
|
532
626
|
// Aggregate unprocessed experiences by domain+agent with quality thresholds.
|
|
533
|
-
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
627
|
+
//
|
|
628
|
+
// Issue #464: dropped the `AND agent != 'cli-hook'` filter. The original
|
|
629
|
+
// exclusion (issue #348) was meant to keep low-quality Bash telemetry
|
|
630
|
+
// (quality ~0.40, success_rate ~0.24) from flooding the pipeline — but
|
|
631
|
+
// post-edit experiences also use agent='cli-hook' and have avg_quality
|
|
632
|
+
// ~0.75 / success_rate ~1.0, well above the HAVING thresholds. Excluding
|
|
633
|
+
// by agent name meant the dominant share of high-quality experiences was
|
|
634
|
+
// ineligible and consolidation never produced patterns. The HAVING clause
|
|
635
|
+
// below is the real quality gate; tighten it if #348's concern resurfaces
|
|
636
|
+
// rather than filtering by agent name.
|
|
536
637
|
const aggregates = db.prepare(`
|
|
537
638
|
SELECT
|
|
538
639
|
domain,
|
|
@@ -545,7 +646,6 @@ export async function consolidateExperiencesToPatterns() {
|
|
|
545
646
|
GROUP_CONCAT(DISTINCT source) as sources
|
|
546
647
|
FROM captured_experiences
|
|
547
648
|
WHERE application_count = 0
|
|
548
|
-
AND agent != 'cli-hook'
|
|
549
649
|
GROUP BY domain, agent
|
|
550
650
|
HAVING cnt >= 3 AND avg_quality >= 0.5 AND success_rate >= 0.6
|
|
551
651
|
ORDER BY avg_quality DESC
|
|
@@ -67,5 +67,25 @@ export declare function printJson(data: unknown): void;
|
|
|
67
67
|
export declare function printSuccess(message: string): void;
|
|
68
68
|
export declare function printError(message: string): void;
|
|
69
69
|
export declare function printGuidance(guidance: string[]): void;
|
|
70
|
+
/**
|
|
71
|
+
* Read piped stdin with a short timeout. Claude Code delivers
|
|
72
|
+
* UserPromptSubmit / PostToolUse / PreToolUse events as JSON on stdin —
|
|
73
|
+
* `$PROMPT`, `$TOOL_INPUT_file_path`, etc. are NOT exposed as env vars in
|
|
74
|
+
* every hook surface, so reading stdin is the only reliable fallback when
|
|
75
|
+
* the explicit CLI option resolves to an empty string.
|
|
76
|
+
*
|
|
77
|
+
* Returns '' when stdin is a TTY (interactive run) or no data arrives
|
|
78
|
+
* before the timeout. Never throws — a hook must never crash the host.
|
|
79
|
+
*/
|
|
80
|
+
export declare function readStdinJsonEvent(timeoutMs?: number): Promise<string>;
|
|
81
|
+
/**
|
|
82
|
+
* Extract a file path from a Claude Code PostToolUse / PreToolUse hook event.
|
|
83
|
+
* Edit / Write / MultiEdit / NotebookEdit tools all put the target path in
|
|
84
|
+
* `tool_input.file_path` (snake_case from Claude Code) — older transports
|
|
85
|
+
* use `toolInput.file_path`. Returns '' when no recognized field is present.
|
|
86
|
+
*
|
|
87
|
+
* Exported for unit testing.
|
|
88
|
+
*/
|
|
89
|
+
export declare function extractFilePathFromEvent(raw: string): string;
|
|
70
90
|
export { DREAM_STATE_KEY, DREAM_INTERVAL_MS, DREAM_EXPERIENCE_THRESHOLD, DREAM_MIN_GAP_MS, type DreamHookState, type TaskBridgePayload, type TaskOutcomeResult, checkAndTriggerDream, incrementDreamExperience, persistCommandExperience, persistTaskOutcome, updateHookRouterQValue, updateRoutingOutcomeQuality, consolidateExperiencesToPatterns, } from './hooks-dream-learning.js';
|
|
71
91
|
//# sourceMappingURL=hooks-shared.d.ts.map
|
|
@@ -250,6 +250,78 @@ export function printGuidance(guidance) {
|
|
|
250
250
|
});
|
|
251
251
|
}
|
|
252
252
|
// ============================================================================
|
|
253
|
+
// Stdin Event Helpers
|
|
254
|
+
// ============================================================================
|
|
255
|
+
/**
|
|
256
|
+
* Read piped stdin with a short timeout. Claude Code delivers
|
|
257
|
+
* UserPromptSubmit / PostToolUse / PreToolUse events as JSON on stdin —
|
|
258
|
+
* `$PROMPT`, `$TOOL_INPUT_file_path`, etc. are NOT exposed as env vars in
|
|
259
|
+
* every hook surface, so reading stdin is the only reliable fallback when
|
|
260
|
+
* the explicit CLI option resolves to an empty string.
|
|
261
|
+
*
|
|
262
|
+
* Returns '' when stdin is a TTY (interactive run) or no data arrives
|
|
263
|
+
* before the timeout. Never throws — a hook must never crash the host.
|
|
264
|
+
*/
|
|
265
|
+
export async function readStdinJsonEvent(timeoutMs = 500) {
|
|
266
|
+
if (process.stdin.isTTY)
|
|
267
|
+
return '';
|
|
268
|
+
return new Promise((resolve) => {
|
|
269
|
+
let data = '';
|
|
270
|
+
const timer = setTimeout(() => {
|
|
271
|
+
process.stdin.removeAllListeners();
|
|
272
|
+
process.stdin.pause();
|
|
273
|
+
resolve(data);
|
|
274
|
+
}, timeoutMs);
|
|
275
|
+
process.stdin.setEncoding('utf8');
|
|
276
|
+
process.stdin.on('data', (chunk) => {
|
|
277
|
+
data += chunk;
|
|
278
|
+
});
|
|
279
|
+
process.stdin.on('end', () => {
|
|
280
|
+
clearTimeout(timer);
|
|
281
|
+
resolve(data);
|
|
282
|
+
});
|
|
283
|
+
process.stdin.on('error', () => {
|
|
284
|
+
clearTimeout(timer);
|
|
285
|
+
resolve(data);
|
|
286
|
+
});
|
|
287
|
+
process.stdin.resume();
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Extract a file path from a Claude Code PostToolUse / PreToolUse hook event.
|
|
292
|
+
* Edit / Write / MultiEdit / NotebookEdit tools all put the target path in
|
|
293
|
+
* `tool_input.file_path` (snake_case from Claude Code) — older transports
|
|
294
|
+
* use `toolInput.file_path`. Returns '' when no recognized field is present.
|
|
295
|
+
*
|
|
296
|
+
* Exported for unit testing.
|
|
297
|
+
*/
|
|
298
|
+
export function extractFilePathFromEvent(raw) {
|
|
299
|
+
if (!raw.trim())
|
|
300
|
+
return '';
|
|
301
|
+
let event;
|
|
302
|
+
try {
|
|
303
|
+
event = JSON.parse(raw);
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
return '';
|
|
307
|
+
}
|
|
308
|
+
const toolInputSnake = event.tool_input;
|
|
309
|
+
const toolInputCamel = event.toolInput;
|
|
310
|
+
const candidates = [
|
|
311
|
+
toolInputSnake?.file_path,
|
|
312
|
+
toolInputSnake?.filePath,
|
|
313
|
+
toolInputCamel?.file_path,
|
|
314
|
+
toolInputCamel?.filePath,
|
|
315
|
+
event.file_path,
|
|
316
|
+
event.filePath,
|
|
317
|
+
];
|
|
318
|
+
for (const c of candidates) {
|
|
319
|
+
if (typeof c === 'string' && c.trim())
|
|
320
|
+
return c;
|
|
321
|
+
}
|
|
322
|
+
return '';
|
|
323
|
+
}
|
|
324
|
+
// ============================================================================
|
|
253
325
|
// Dream Scheduler & Learning — re-exported from hooks-dream-learning.ts
|
|
254
326
|
// ============================================================================
|
|
255
327
|
export { DREAM_STATE_KEY, DREAM_INTERVAL_MS, DREAM_EXPERIENCE_THRESHOLD, DREAM_MIN_GAP_MS, checkAndTriggerDream, incrementDreamExperience, persistCommandExperience, persistTaskOutcome, updateHookRouterQValue, updateRoutingOutcomeQuality, consolidateExperiencesToPatterns, } from './hooks-dream-learning.js';
|
|
@@ -8,41 +8,7 @@ import { randomUUID } from 'crypto';
|
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { findProjectRoot, getUnifiedMemory } from '../../../kernel/unified-memory.js';
|
|
11
|
-
import { applyHookBusyTimeout, getHooksSystem, createHybridBackendWithTimeout, incrementDreamExperience, printJson, printError, printGuidance, } from './hooks-shared.js';
|
|
12
|
-
/**
|
|
13
|
-
* Read piped stdin with a short timeout. Claude Code delivers
|
|
14
|
-
* UserPromptSubmit / PostToolUse / etc. events as JSON on stdin —
|
|
15
|
-
* `$PROMPT` is NOT exposed as an env var, so reading stdin is the
|
|
16
|
-
* only reliable way to recover the prompt body for routing.
|
|
17
|
-
*
|
|
18
|
-
* Returns '' when stdin is a TTY (interactive run) or no data arrives
|
|
19
|
-
* before the timeout. Never throws — a hook must never crash the host.
|
|
20
|
-
*/
|
|
21
|
-
async function readStdinJsonEvent(timeoutMs = 500) {
|
|
22
|
-
if (process.stdin.isTTY)
|
|
23
|
-
return '';
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
let data = '';
|
|
26
|
-
const timer = setTimeout(() => {
|
|
27
|
-
process.stdin.removeAllListeners();
|
|
28
|
-
process.stdin.pause();
|
|
29
|
-
resolve(data);
|
|
30
|
-
}, timeoutMs);
|
|
31
|
-
process.stdin.setEncoding('utf8');
|
|
32
|
-
process.stdin.on('data', (chunk) => {
|
|
33
|
-
data += chunk;
|
|
34
|
-
});
|
|
35
|
-
process.stdin.on('end', () => {
|
|
36
|
-
clearTimeout(timer);
|
|
37
|
-
resolve(data);
|
|
38
|
-
});
|
|
39
|
-
process.stdin.on('error', () => {
|
|
40
|
-
clearTimeout(timer);
|
|
41
|
-
resolve(data);
|
|
42
|
-
});
|
|
43
|
-
process.stdin.resume();
|
|
44
|
-
});
|
|
45
|
-
}
|
|
11
|
+
import { applyHookBusyTimeout, getHooksSystem, createHybridBackendWithTimeout, incrementDreamExperience, printJson, printError, printGuidance, readStdinJsonEvent, } from './hooks-shared.js';
|
|
46
12
|
/**
|
|
47
13
|
* Extract a routable task description from a Claude Code hook event JSON
|
|
48
14
|
* payload. Different hook surfaces use different field names — try the
|
|
@@ -234,14 +200,46 @@ export function registerRoutingHooks(hooks) {
|
|
|
234
200
|
LIMIT 1
|
|
235
201
|
)
|
|
236
202
|
`).run(success ? 1 : 0, qualityScore);
|
|
203
|
+
// Issue #465: orphan-sentinel sweep. Sessions that terminate without
|
|
204
|
+
// firing Stop (context compact, process kill, IDE crash) leave their
|
|
205
|
+
// sentinels at quality_score=-1 forever — every subsequent post-route
|
|
206
|
+
// call only closes the most-recent one (LIMIT 1) and newer rows keep
|
|
207
|
+
// pre-empting old ones in the ORDER BY DESC. Reporter saw 122/149
|
|
208
|
+
// rows stuck at -1, inverting AVG(quality_score) to -0.717.
|
|
209
|
+
//
|
|
210
|
+
// We use the conservative base score (0.325 = no success/duration
|
|
211
|
+
// bonus) rather than the current turn's qualityScore: those orphans
|
|
212
|
+
// belong to UNKNOWN historical turns and shouldn't inherit the
|
|
213
|
+
// current turn's outcome. Tag with error='stale-sentinel' so
|
|
214
|
+
// precision-sensitive queries can filter them out.
|
|
215
|
+
// Discriminator mirrors the LIMIT-1 close above and #451's symmetric
|
|
216
|
+
// design: route sentinels are owned by post-route, pre-task sentinels
|
|
217
|
+
// (task_json carries "taskId") are owned by post-task. Sweeping a
|
|
218
|
+
// pre-task sentinel here would race with updateRoutingOutcomeQuality
|
|
219
|
+
// and break the ownership split. If pre-task sentinels orphan, that
|
|
220
|
+
// belongs in a separate fix.
|
|
221
|
+
const staleResult = db.prepare(`
|
|
222
|
+
UPDATE routing_outcomes
|
|
223
|
+
SET success = 0,
|
|
224
|
+
quality_score = 0.325,
|
|
225
|
+
duration_ms = 0,
|
|
226
|
+
error = 'stale-sentinel'
|
|
227
|
+
WHERE quality_score = -1
|
|
228
|
+
AND task_json NOT LIKE '%"taskId"%'
|
|
229
|
+
AND created_at < datetime('now', '-300 seconds')
|
|
230
|
+
`).run();
|
|
237
231
|
if (options.json) {
|
|
238
232
|
printJson({
|
|
239
233
|
success: true,
|
|
240
234
|
resolved: result.changes > 0,
|
|
235
|
+
staleSwept: staleResult.changes,
|
|
241
236
|
qualityScore,
|
|
242
237
|
turnSuccess: success,
|
|
243
238
|
});
|
|
244
239
|
}
|
|
240
|
+
else if (staleResult.changes > 0) {
|
|
241
|
+
console.log(chalk.dim(`[hooks] post-route: swept ${staleResult.changes} stale sentinel(s)`));
|
|
242
|
+
}
|
|
245
243
|
return;
|
|
246
244
|
}
|
|
247
245
|
catch (error) {
|
|
@@ -311,10 +311,19 @@ export function registerTaskHooks(hooks) {
|
|
|
311
311
|
durationMs,
|
|
312
312
|
success,
|
|
313
313
|
});
|
|
314
|
+
// Issue #460: when --agent arrives empty (Claude Code does not
|
|
315
|
+
// expose $TOOL_RESULT_agent_id in PostToolUse context), `agent`
|
|
316
|
+
// resolves to 'unknown' and every Q-value lands in the same
|
|
317
|
+
// bucket — the router can never learn per-agent differentiation.
|
|
318
|
+
// The pre-task bridge already carries `agent: routing.recommendedAgent`
|
|
319
|
+
// which is the correct action key, so prefer that over 'unknown'.
|
|
320
|
+
const effectiveAgent = agent === 'unknown' && outcome.bridge?.agent
|
|
321
|
+
? outcome.bridge.agent
|
|
322
|
+
: agent;
|
|
314
323
|
// Stream D (patch 150): apply 6-dim outcome quality to the
|
|
315
324
|
// routing_outcomes sentinel that pre-task wrote with quality=-1.
|
|
316
325
|
await updateRoutingOutcomeQuality({
|
|
317
|
-
agent,
|
|
326
|
+
agent: effectiveAgent,
|
|
318
327
|
success,
|
|
319
328
|
durationMs,
|
|
320
329
|
qualityScore: outcome.qualityScore,
|
|
@@ -327,7 +336,7 @@ export function registerTaskHooks(hooks) {
|
|
|
327
336
|
priority: outcome.bridge.priority,
|
|
328
337
|
domain: outcome.bridge.domain,
|
|
329
338
|
complexityBucket: outcome.bridge.complexityBucket,
|
|
330
|
-
agent,
|
|
339
|
+
agent: effectiveAgent,
|
|
331
340
|
success,
|
|
332
341
|
});
|
|
333
342
|
}
|
|
@@ -355,6 +364,7 @@ export function registerTaskHooks(hooks) {
|
|
|
355
364
|
dreamTriggered: dreamResult.triggered,
|
|
356
365
|
dreamReason: dreamResult.reason,
|
|
357
366
|
dreamInsights: dreamResult.insightsGenerated,
|
|
367
|
+
dreamInsightsApplied: dreamResult.insightsApplied,
|
|
358
368
|
});
|
|
359
369
|
}
|
|
360
370
|
else {
|
|
@@ -364,7 +374,10 @@ export function registerTaskHooks(hooks) {
|
|
|
364
374
|
console.log(chalk.green(` Patterns learned: ${patternsLearned}`));
|
|
365
375
|
}
|
|
366
376
|
if (dreamResult.triggered) {
|
|
367
|
-
|
|
377
|
+
const appliedSuffix = typeof dreamResult.insightsApplied === 'number'
|
|
378
|
+
? `, ${dreamResult.insightsApplied} applied`
|
|
379
|
+
: '';
|
|
380
|
+
console.log(chalk.blue(` 🌙 Dream cycle triggered (${dreamResult.reason}): ${dreamResult.insightsGenerated} insights${appliedSuffix}`));
|
|
368
381
|
}
|
|
369
382
|
}
|
|
370
383
|
return;
|
|
@@ -466,17 +466,48 @@ export class QEReasoningBank {
|
|
|
466
466
|
for (const domain of QE_DOMAIN_LIST) {
|
|
467
467
|
byDomain[domain] = patternStoreStats.byDomain[domain] || 0;
|
|
468
468
|
}
|
|
469
|
+
// DB fallback (#454): in-memory `this.stats` is reset on every process
|
|
470
|
+
// start, but every hook invocation spawns a fresh node. Without a DB
|
|
471
|
+
// fallback, `aqe hooks stats` always reports zeros even when historical
|
|
472
|
+
// routing_outcomes / qe_pattern_usage rows exist. We use the in-memory
|
|
473
|
+
// counters when they're non-zero (live, current-process data), otherwise
|
|
474
|
+
// fall back to aggregated DB totals.
|
|
475
|
+
let routingRequests = this.stats.routingRequests;
|
|
476
|
+
let avgRoutingConfidence = this.stats.routingRequests > 0
|
|
477
|
+
? this.stats.totalRoutingConfidence / this.stats.routingRequests
|
|
478
|
+
: 0;
|
|
479
|
+
let learningOutcomes = this.stats.learningOutcomes;
|
|
480
|
+
let patternSuccessRate = this.stats.learningOutcomes > 0
|
|
481
|
+
? this.stats.successfulOutcomes / this.stats.learningOutcomes
|
|
482
|
+
: 0;
|
|
483
|
+
if (routingRequests === 0 || learningOutcomes === 0) {
|
|
484
|
+
try {
|
|
485
|
+
const agg = this.getSqliteStore().getAggregateOutcomeStats();
|
|
486
|
+
if (routingRequests === 0 && agg.routingRequests > 0) {
|
|
487
|
+
routingRequests = agg.routingRequests;
|
|
488
|
+
avgRoutingConfidence = agg.avgRoutingConfidence;
|
|
489
|
+
}
|
|
490
|
+
if (learningOutcomes === 0 && agg.learningOutcomes > 0) {
|
|
491
|
+
learningOutcomes = agg.learningOutcomes;
|
|
492
|
+
// Prefer per-usage success rate (closer to recordOutcome semantics);
|
|
493
|
+
// fall back to qe_patterns.success_rate aggregate when no usage rows.
|
|
494
|
+
patternSuccessRate =
|
|
495
|
+
agg.learningOutcomes > 0
|
|
496
|
+
? agg.successfulOutcomes / agg.learningOutcomes
|
|
497
|
+
: agg.avgPatternSuccessRate;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch {
|
|
501
|
+
// best-effort — never let stats reporting crash the host
|
|
502
|
+
}
|
|
503
|
+
}
|
|
469
504
|
return {
|
|
470
505
|
totalPatterns: patternStoreStats.totalPatterns,
|
|
471
506
|
byDomain,
|
|
472
|
-
routingRequests
|
|
473
|
-
avgRoutingConfidence
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
learningOutcomes: this.stats.learningOutcomes,
|
|
477
|
-
patternSuccessRate: this.stats.learningOutcomes > 0
|
|
478
|
-
? this.stats.successfulOutcomes / this.stats.learningOutcomes
|
|
479
|
-
: 0,
|
|
507
|
+
routingRequests,
|
|
508
|
+
avgRoutingConfidence,
|
|
509
|
+
learningOutcomes,
|
|
510
|
+
patternSuccessRate,
|
|
480
511
|
patternStoreStats,
|
|
481
512
|
};
|
|
482
513
|
}
|
|
@@ -49,6 +49,15 @@ export declare class RvfPatternStore implements IPatternStore {
|
|
|
49
49
|
/** Get the underlying RVF adapter (for COW branching, migration, etc.) */
|
|
50
50
|
getAdapter(): RvfNativeAdapter | null;
|
|
51
51
|
initialize(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Compare the RVF vector count with the SQLite pattern count; if RVF has
|
|
54
|
+
* more rows, read the idmap.json and delete any vector IDs that no longer
|
|
55
|
+
* have a matching qe_patterns row.
|
|
56
|
+
*
|
|
57
|
+
* Fail-open: any error in the purge path is swallowed so a stale or
|
|
58
|
+
* corrupted idmap can't keep the store from initializing (#462).
|
|
59
|
+
*/
|
|
60
|
+
private purgeOrphanedVectors;
|
|
52
61
|
dispose(): Promise<void>;
|
|
53
62
|
store(pattern: QEPattern): Promise<Result<string>>;
|
|
54
63
|
create(options: CreateQEPatternOptions): Promise<Result<QEPattern>>;
|
|
@@ -89,6 +89,48 @@ export class RvfPatternStore {
|
|
|
89
89
|
// SQLite auto-attach is best-effort
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
+
// Issue #462: purge orphan vectors that survived in patterns.rvf when an
|
|
93
|
+
// upgrade workflow rewrote qe_patterns via INSERT OR REPLACE without
|
|
94
|
+
// calling RvfPatternStore.delete() on the old IDs. Ghost vectors win
|
|
95
|
+
// cosine-similarity matches, route to non-existent pattern IDs, and
|
|
96
|
+
// every learning write fails silently. Run once on init.
|
|
97
|
+
await this.purgeOrphanedVectors();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Compare the RVF vector count with the SQLite pattern count; if RVF has
|
|
101
|
+
* more rows, read the idmap.json and delete any vector IDs that no longer
|
|
102
|
+
* have a matching qe_patterns row.
|
|
103
|
+
*
|
|
104
|
+
* Fail-open: any error in the purge path is swallowed so a stale or
|
|
105
|
+
* corrupted idmap can't keep the store from initializing (#462).
|
|
106
|
+
*/
|
|
107
|
+
async purgeOrphanedVectors() {
|
|
108
|
+
if (!this.adapter || !this.sqliteStore)
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
const rvfCount = this.adapter.status()?.totalVectors ?? 0;
|
|
112
|
+
const dbCount = this.sqliteStore.getStats()?.totalPatterns ?? 0;
|
|
113
|
+
if (rvfCount <= dbCount)
|
|
114
|
+
return;
|
|
115
|
+
const { readFileSync, existsSync } = await import('node:fs');
|
|
116
|
+
const idmapPath = `${this.rvfPath}.idmap.json`;
|
|
117
|
+
if (!existsSync(idmapPath))
|
|
118
|
+
return;
|
|
119
|
+
const idmap = JSON.parse(readFileSync(idmapPath, 'utf-8'));
|
|
120
|
+
const rvfIds = new Set((idmap.entries ?? [])
|
|
121
|
+
.map((e) => (Array.isArray(e) ? e[0] : undefined))
|
|
122
|
+
.filter((id) => typeof id === 'string'));
|
|
123
|
+
const dbIds = new Set(this.sqliteStore.getPatterns({ limit: 10_000 }).map((p) => p.id));
|
|
124
|
+
const orphans = [...rvfIds].filter((id) => !dbIds.has(id));
|
|
125
|
+
if (orphans.length === 0)
|
|
126
|
+
return;
|
|
127
|
+
this.adapter.delete(orphans);
|
|
128
|
+
console.log(`[RvfPatternStore] Removed ${orphans.length} ghost vectors (index ${rvfCount} > DB ${dbCount})`);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
// fail-open: a stale idmap or read error must not block initialization
|
|
132
|
+
console.warn(`[RvfPatternStore] orphan purge skipped: ${toErrorMessage(error)}`);
|
|
133
|
+
}
|
|
92
134
|
}
|
|
93
135
|
async dispose() {
|
|
94
136
|
if (this.adapter && !this.skipCloseOnDispose) {
|
|
@@ -134,6 +134,24 @@ export declare class SQLitePatternStore {
|
|
|
134
134
|
byDomain: Record<string, number>;
|
|
135
135
|
byTier: Record<string, number>;
|
|
136
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* Aggregate outcome counters used by QEReasoningBank.getStats() as a fallback
|
|
139
|
+
* when the in-memory `this.stats` object is zero — every hook subprocess
|
|
140
|
+
* starts with a fresh counter, so without this fallback observability is
|
|
141
|
+
* always blank (#454).
|
|
142
|
+
*
|
|
143
|
+
* routing_outcomes and qe_pattern_usage live in the same unified memory.db
|
|
144
|
+
* as qe_patterns. avgConfidence/avgSuccessRate return 0 when the source
|
|
145
|
+
* tables are empty rather than NaN.
|
|
146
|
+
*/
|
|
147
|
+
getAggregateOutcomeStats(): {
|
|
148
|
+
routingRequests: number;
|
|
149
|
+
avgRoutingConfidence: number;
|
|
150
|
+
successfulRoutings: number;
|
|
151
|
+
learningOutcomes: number;
|
|
152
|
+
successfulOutcomes: number;
|
|
153
|
+
avgPatternSuccessRate: number;
|
|
154
|
+
};
|
|
137
155
|
/**
|
|
138
156
|
* Check if there's any historical data (embeddings, usage, trajectories)
|
|
139
157
|
* even if qe_patterns is empty. Used to detect data loss vs fresh database.
|
|
@@ -596,6 +596,65 @@ export class SQLitePatternStore {
|
|
|
596
596
|
}
|
|
597
597
|
return { totalPatterns: total, byDomain, byTier };
|
|
598
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Aggregate outcome counters used by QEReasoningBank.getStats() as a fallback
|
|
601
|
+
* when the in-memory `this.stats` object is zero — every hook subprocess
|
|
602
|
+
* starts with a fresh counter, so without this fallback observability is
|
|
603
|
+
* always blank (#454).
|
|
604
|
+
*
|
|
605
|
+
* routing_outcomes and qe_pattern_usage live in the same unified memory.db
|
|
606
|
+
* as qe_patterns. avgConfidence/avgSuccessRate return 0 when the source
|
|
607
|
+
* tables are empty rather than NaN.
|
|
608
|
+
*/
|
|
609
|
+
getAggregateOutcomeStats() {
|
|
610
|
+
const empty = {
|
|
611
|
+
routingRequests: 0,
|
|
612
|
+
avgRoutingConfidence: 0,
|
|
613
|
+
successfulRoutings: 0,
|
|
614
|
+
learningOutcomes: 0,
|
|
615
|
+
successfulOutcomes: 0,
|
|
616
|
+
avgPatternSuccessRate: 0,
|
|
617
|
+
};
|
|
618
|
+
if (!this.db)
|
|
619
|
+
return empty;
|
|
620
|
+
const safeGet = (sql) => {
|
|
621
|
+
try {
|
|
622
|
+
return this.db.prepare(sql).get();
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
return undefined;
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
// routing_outcomes carries (success, quality_score) per closed turn.
|
|
629
|
+
// Sentinels still have quality_score = -1, so filter to closed rows.
|
|
630
|
+
const routing = safeGet(`
|
|
631
|
+
SELECT
|
|
632
|
+
COUNT(*) AS total,
|
|
633
|
+
COUNT(CASE WHEN quality_score >= 0 THEN 1 END) AS closed,
|
|
634
|
+
AVG(CASE WHEN quality_score >= 0 THEN quality_score END) AS avg_q,
|
|
635
|
+
COALESCE(SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END), 0) AS succ
|
|
636
|
+
FROM routing_outcomes
|
|
637
|
+
`);
|
|
638
|
+
const usage = safeGet(`
|
|
639
|
+
SELECT
|
|
640
|
+
COUNT(*) AS total,
|
|
641
|
+
COALESCE(SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END), 0) AS succ
|
|
642
|
+
FROM qe_pattern_usage
|
|
643
|
+
`);
|
|
644
|
+
const patternAvg = safeGet(`
|
|
645
|
+
SELECT AVG(success_rate) AS avg_sr
|
|
646
|
+
FROM qe_patterns
|
|
647
|
+
WHERE usage_count > 0
|
|
648
|
+
`);
|
|
649
|
+
return {
|
|
650
|
+
routingRequests: routing?.total ?? 0,
|
|
651
|
+
avgRoutingConfidence: routing?.avg_q ?? 0,
|
|
652
|
+
successfulRoutings: routing?.succ ?? 0,
|
|
653
|
+
learningOutcomes: usage?.total ?? 0,
|
|
654
|
+
successfulOutcomes: usage?.succ ?? 0,
|
|
655
|
+
avgPatternSuccessRate: patternAvg?.avg_sr ?? 0,
|
|
656
|
+
};
|
|
657
|
+
}
|
|
599
658
|
/**
|
|
600
659
|
* Check if there's any historical data (embeddings, usage, trajectories)
|
|
601
660
|
* even if qe_patterns is empty. Used to detect data loss vs fresh database.
|