agentic-qe 3.10.0 → 3.10.2

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.
Files changed (397) hide show
  1. package/.claude/hooks/README.txt +17 -0
  2. package/.claude/hooks/aqe-hook.cjs +98 -0
  3. package/.claude/hooks/cross-phase-memory.yaml +296 -0
  4. package/.claude/hooks/post-task-sync.sh +113 -0
  5. package/.claude/hooks/v3-domain-workers.json +121 -0
  6. package/.claude/skills/skills-manifest.json +1 -1
  7. package/CHANGELOG.md +148 -0
  8. package/README.md +35 -8
  9. package/dist/cli/bundle.js +5 -5
  10. package/dist/cli/chunks/adapter-CR6J5C76.js +2 -0
  11. package/dist/cli/chunks/{agent-booster-wasm-5UDM2PWG.js → agent-booster-wasm-DHSIPFTH.js} +2 -2
  12. package/dist/cli/chunks/{agent-handler-JSYER5YC.js → agent-handler-FPQVHGGT.js} +2 -2
  13. package/dist/cli/chunks/{agent-memory-branch-T2SAHI4F.js → agent-memory-branch-OLOF5ZHV.js} +2 -2
  14. package/dist/cli/chunks/aqe-learning-engine-2MNTHMB6.js +2 -0
  15. package/dist/cli/chunks/{audit-HIBRVGXG.js → audit-ALRYPHGP.js} +2 -2
  16. package/dist/cli/chunks/base-AOQNGMTL.js +2 -0
  17. package/dist/cli/chunks/{hnswlib-node-TA4DZV62.js → better-sqlite3-5BT5FO64.js} +2 -2
  18. package/dist/cli/chunks/{brain-handler-N6AWIMXG.js → brain-handler-ROZUHCOT.js} +3 -3
  19. package/dist/cli/chunks/{branch-enumerator-VYQGBVEJ.js → branch-enumerator-VK7G4NKJ.js} +2 -2
  20. package/dist/cli/chunks/{browser-2X4WKZPT.js → browser-Q2S75M2F.js} +2 -2
  21. package/dist/cli/chunks/browser-workflow-UJ4A2ZXO.js +2 -0
  22. package/dist/cli/chunks/{chunk-BQX5QDU5.js → chunk-2244IFZA.js} +1 -1
  23. package/dist/cli/chunks/{chunk-S33246T4.js → chunk-22D6VBPD.js} +1 -1
  24. package/dist/cli/chunks/{chunk-UGX4EHT5.js → chunk-24LUQICS.js} +2 -2
  25. package/dist/cli/chunks/{chunk-6HCHW5TS.js → chunk-2EDWGHDA.js} +2 -2
  26. package/dist/cli/chunks/{chunk-4WYGUTSF.js → chunk-2JDLQWSV.js} +2 -2
  27. package/dist/cli/chunks/{chunk-3QULDB7K.js → chunk-2OH3ALYB.js} +1 -1
  28. package/dist/cli/chunks/chunk-3RHHKYUR.js +2 -0
  29. package/dist/cli/chunks/{chunk-Z6JLPPAY.js → chunk-3Z4FHA2E.js} +1 -1
  30. package/dist/cli/chunks/{chunk-ZYZWBNKT.js → chunk-4BXGVM2C.js} +1 -1
  31. package/dist/cli/chunks/{chunk-6F3WJOU2.js → chunk-4F3ZTXHP.js} +2 -2
  32. package/dist/cli/chunks/{chunk-CU4IUJ2K.js → chunk-4GTDW2XL.js} +2 -2
  33. package/dist/cli/chunks/{chunk-4UUDFWOP.js → chunk-5HB54RUS.js} +2 -2
  34. package/dist/cli/chunks/{chunk-YHNEBCYQ.js → chunk-5PL7WTCU.js} +2 -2
  35. package/dist/cli/chunks/{chunk-MF3XRML3.js → chunk-5PRFFHFV.js} +2 -2
  36. package/dist/cli/chunks/{chunk-TEJPHJMW.js → chunk-5QHSLWLP.js} +2 -2
  37. package/dist/cli/chunks/{chunk-ZFBMBCKN.js → chunk-5WJ3FWL4.js} +2 -2
  38. package/dist/cli/chunks/{chunk-V5TRAL57.js → chunk-6KSCXPPL.js} +2 -2
  39. package/dist/cli/chunks/{chunk-P6XYFDXN.js → chunk-6NZHEM4V.js} +1 -1
  40. package/dist/cli/chunks/{chunk-HD6CZBZV.js → chunk-6ZFHIKQG.js} +2 -2
  41. package/dist/cli/chunks/{chunk-VEOQH4W6.js → chunk-7DKYCVJI.js} +2 -2
  42. package/dist/cli/chunks/{chunk-Y4I5JBOL.js → chunk-7IVQ6OVR.js} +2 -2
  43. package/dist/cli/chunks/chunk-7IZ2OPC2.js +2 -0
  44. package/dist/cli/chunks/{chunk-AFFYJSW2.js → chunk-7QRMARM7.js} +2 -2
  45. package/dist/cli/chunks/{chunk-L2AIES7X.js → chunk-7SJX4CFK.js} +1 -1
  46. package/dist/cli/chunks/{chunk-UCIJCRPB.js → chunk-7SWD3D6Y.js} +2 -2
  47. package/dist/cli/chunks/{chunk-FCSJ7GIZ.js → chunk-7V5UHLNY.js} +4 -4
  48. package/dist/cli/chunks/{chunk-5QJDH4Z5.js → chunk-7Z46RDDV.js} +2 -2
  49. package/dist/cli/chunks/{chunk-5RQT7EJP.js → chunk-A5RMQG4N.js} +3 -3
  50. package/dist/cli/chunks/{chunk-3BO7EKGO.js → chunk-AH7FXNFE.js} +3 -3
  51. package/dist/cli/chunks/chunk-AIUSZC6K.js +3 -0
  52. package/dist/cli/chunks/{chunk-MJBXQXSX.js → chunk-AOI67HA3.js} +1 -1
  53. package/dist/cli/chunks/{chunk-6H5MRVJS.js → chunk-AV7KYE5P.js} +7 -7
  54. package/dist/cli/chunks/{chunk-OGT45MZN.js → chunk-AWFIEGR3.js} +2 -2
  55. package/dist/cli/chunks/{chunk-J5RJYFRM.js → chunk-BQCSCAUC.js} +2 -2
  56. package/dist/cli/chunks/{chunk-OUJJ34JH.js → chunk-C2M74HCN.js} +1 -1
  57. package/dist/cli/chunks/{chunk-G2HA2O3R.js → chunk-CIRPP7RQ.js} +2 -2
  58. package/dist/cli/chunks/{chunk-LXHA55EB.js → chunk-CMACGG4Z.js} +1 -1
  59. package/dist/cli/chunks/{chunk-LRISVDVO.js → chunk-CTDLI2ON.js} +1 -1
  60. package/dist/cli/chunks/{chunk-DXV6NRG3.js → chunk-CV2SBMBW.js} +2 -2
  61. package/dist/cli/chunks/{chunk-WLLE54TA.js → chunk-DMQPO43S.js} +1 -1
  62. package/dist/cli/chunks/{chunk-I4E6CLC4.js → chunk-DRWGK3YO.js} +2 -2
  63. package/dist/cli/chunks/{chunk-Z2SCTEZD.js → chunk-DZZEHPSJ.js} +2 -2
  64. package/dist/cli/chunks/{chunk-DY7IRNE2.js → chunk-EA7ZSN3V.js} +1 -1
  65. package/dist/cli/chunks/{chunk-M4HDBRVJ.js → chunk-EQBEGDTG.js} +1 -1
  66. package/dist/cli/chunks/{chunk-HZPXOAFW.js → chunk-ETN5563K.js} +2 -2
  67. package/dist/cli/chunks/{chunk-OWMGD7FO.js → chunk-EVCOCGVJ.js} +3 -3
  68. package/dist/cli/chunks/{chunk-27ACATRH.js → chunk-FO43SQXP.js} +2 -2
  69. package/dist/cli/chunks/{chunk-DQJJS4AX.js → chunk-FO73PZVU.js} +2 -2
  70. package/dist/cli/chunks/{chunk-FEBXP74Y.js → chunk-FPAW77XV.js} +1 -1
  71. package/dist/cli/chunks/{chunk-KYLJERZ3.js → chunk-FY3CUPNN.js} +20 -17
  72. package/dist/cli/chunks/{chunk-LQ3TA22E.js → chunk-G5U6Q42D.js} +2 -2
  73. package/dist/cli/chunks/{chunk-JCKX2LEJ.js → chunk-HA63NBFK.js} +49 -49
  74. package/dist/cli/chunks/{chunk-NT4PI5HI.js → chunk-HHCYSAH3.js} +2 -2
  75. package/dist/cli/chunks/{chunk-GPKZ4MMH.js → chunk-HJME6G5M.js} +1 -1
  76. package/dist/cli/chunks/{chunk-TR7BZLB6.js → chunk-HJORBNXW.js} +1 -1
  77. package/dist/cli/chunks/{chunk-BXCS55GB.js → chunk-HO37VP4O.js} +1 -1
  78. package/dist/cli/chunks/{chunk-FX4SYT6Y.js → chunk-I677W5BT.js} +3 -3
  79. package/dist/cli/chunks/chunk-IAZEDWRX.js +2 -0
  80. package/dist/cli/chunks/{chunk-5UOV7T36.js → chunk-IICTTDAA.js} +2 -2
  81. package/dist/cli/chunks/{chunk-BQT4J3BD.js → chunk-JF53LRBL.js} +2 -2
  82. package/dist/cli/chunks/{chunk-S4CNA6Z5.js → chunk-KB5L5TTF.js} +3 -3
  83. package/dist/cli/chunks/{chunk-UE3XXKLN.js → chunk-L7VIX22Y.js} +2 -2
  84. package/dist/cli/chunks/{chunk-C5QESAYA.js → chunk-LQTWPSYL.js} +1 -1
  85. package/dist/cli/chunks/{chunk-2GL4GH52.js → chunk-LZCBSFAU.js} +4 -4
  86. package/dist/cli/chunks/{chunk-LDMG4372.js → chunk-MCOFJHSJ.js} +2 -2
  87. package/dist/cli/chunks/{chunk-ZCNVFULO.js → chunk-MCZHKXB4.js} +2 -2
  88. package/dist/cli/chunks/{chunk-VTIXFHZR.js → chunk-MEY43PIQ.js} +2 -2
  89. package/dist/cli/chunks/{chunk-PNDO4W4L.js → chunk-MMIQ5DMA.js} +2 -2
  90. package/dist/cli/chunks/{chunk-NWHSEXHA.js → chunk-MNUTRAUV.js} +1 -1
  91. package/dist/cli/chunks/{chunk-XFUU2RCA.js → chunk-MNV3E5KY.js} +2 -2
  92. package/dist/cli/chunks/{chunk-WVCIZIKH.js → chunk-MYWQTCS4.js} +1 -1
  93. package/dist/cli/chunks/{chunk-T7DLX3LS.js → chunk-NZO4WUSO.js} +3 -3
  94. package/dist/cli/chunks/{chunk-RF6QKV7M.js → chunk-OIEQF7PG.js} +2 -2
  95. package/dist/cli/chunks/{chunk-NLCUQMUR.js → chunk-OIRZJCZY.js} +2 -2
  96. package/dist/cli/chunks/{chunk-KOSKGZK4.js → chunk-ON4D4TJ4.js} +2 -2
  97. package/dist/cli/chunks/chunk-OPFN5LFT.js +95 -0
  98. package/dist/cli/chunks/{chunk-55JPAF56.js → chunk-ORF2UKQH.js} +1 -1
  99. package/dist/cli/chunks/{chunk-M73IL7FA.js → chunk-OWQ6HEYI.js} +2 -2
  100. package/dist/cli/chunks/{chunk-O3NAUNFC.js → chunk-OXCEUR5F.js} +2 -2
  101. package/dist/cli/chunks/{chunk-BTIVIWIG.js → chunk-PEK6NGVJ.js} +1 -1
  102. package/dist/cli/chunks/{chunk-ALCQRJDY.js → chunk-PIZYRPMT.js} +2 -2
  103. package/dist/cli/chunks/{chunk-L3IFZ4IX.js → chunk-PXTDEO65.js} +2 -2
  104. package/dist/cli/chunks/{chunk-3U77XX6J.js → chunk-PYIHZXCI.js} +12 -12
  105. package/dist/cli/chunks/{chunk-FQ5FT7IE.js → chunk-QBRHKTFT.js} +1 -1
  106. package/dist/cli/chunks/{chunk-I4T4JPR2.js → chunk-QEPFXY6G.js} +1 -1
  107. package/dist/cli/chunks/{chunk-X4U5NYB6.js → chunk-QJ2EHLJ2.js} +1 -1
  108. package/dist/cli/chunks/{chunk-JKVNZASH.js → chunk-QQNCSEZG.js} +2 -2
  109. package/dist/cli/chunks/{chunk-URVDWF2Y.js → chunk-QSE67XJO.js} +2 -2
  110. package/dist/cli/chunks/{chunk-RARSTEUO.js → chunk-R2O6OKT2.js} +1 -1
  111. package/dist/cli/chunks/{chunk-RGONSQ44.js → chunk-RLXTBL3H.js} +210 -210
  112. package/dist/cli/chunks/{chunk-RH3PHCJT.js → chunk-RNREAOY4.js} +2 -2
  113. package/dist/cli/chunks/{chunk-2POXDKUB.js → chunk-S3OZ7XSY.js} +1 -1
  114. package/dist/cli/chunks/{provider-manager-HV55NIIO.js → chunk-S3ZO7JXS.js} +13 -13
  115. package/dist/cli/chunks/{chunk-QWBO76AU.js → chunk-SJH3HYNC.js} +2 -2
  116. package/dist/cli/chunks/{chunk-WC6KZDPM.js → chunk-STEGWLH5.js} +2 -2
  117. package/dist/cli/chunks/{chunk-KCHFF4IE.js → chunk-SVYTN2GT.js} +2 -2
  118. package/dist/cli/chunks/{chunk-OKGK7DBT.js → chunk-SW4OKUTC.js} +2 -2
  119. package/dist/cli/chunks/{chunk-3OSCWD7Z.js → chunk-THRTUW4Z.js} +1 -1
  120. package/dist/cli/chunks/{chunk-U56TIYGP.js → chunk-TJKDATEU.js} +2 -2
  121. package/dist/cli/chunks/{chunk-4NQ6KANC.js → chunk-U3EUH6LX.js} +2 -2
  122. package/dist/cli/chunks/{chunk-7Y54QZKF.js → chunk-UUFOHMUG.js} +2 -2
  123. package/dist/cli/chunks/{chunk-W6U7SIIK.js → chunk-UVU7XLJY.js} +3 -3
  124. package/dist/cli/chunks/chunk-UWXH2UQK.js +2 -0
  125. package/dist/cli/chunks/{chunk-YYDHTBHE.js → chunk-UYYBPWU3.js} +1 -1
  126. package/dist/cli/chunks/{chunk-LYVFC7C7.js → chunk-VSUTI4G6.js} +2 -2
  127. package/dist/cli/chunks/{chunk-SGONA5GS.js → chunk-WDMPJ2M2.js} +2 -2
  128. package/dist/cli/chunks/{chunk-66GIKUI2.js → chunk-WNR2KAUH.js} +2 -2
  129. package/dist/cli/chunks/{chunk-M3M7HXDH.js → chunk-WSVUSIAZ.js} +2 -2
  130. package/dist/cli/chunks/{chunk-SCYF5CQA.js → chunk-WZJUMJ2S.js} +1 -1
  131. package/dist/cli/chunks/{chunk-WG6I7YF3.js → chunk-X2VAOIUY.js} +1 -1
  132. package/dist/cli/chunks/{chunk-7ZIRDBXH.js → chunk-XDSA7YUQ.js} +1 -1
  133. package/dist/cli/chunks/{chunk-HIWBW4IQ.js → chunk-XDU624HU.js} +1 -1
  134. package/dist/cli/chunks/{chunk-JUICZG3T.js → chunk-XGBAHAGC.js} +2 -2
  135. package/dist/cli/chunks/{chunk-DQLEZBWV.js → chunk-XMJTTF5N.js} +2 -2
  136. package/dist/cli/chunks/{chunk-KNL3QWVA.js → chunk-XPCNUX2U.js} +2 -2
  137. package/dist/cli/chunks/{chunk-VTO5O7DA.js → chunk-XRJECWZE.js} +1 -1
  138. package/dist/cli/chunks/{chunk-HD5NQDOL.js → chunk-XTCUN36Z.js} +2 -2
  139. package/dist/cli/chunks/{chunk-KDFW7MVM.js → chunk-Y63MBMOV.js} +2 -2
  140. package/dist/cli/chunks/{chunk-L4N6PTIC.js → chunk-YACT5WFC.js} +2 -2
  141. package/dist/cli/chunks/{chunk-QU54GUEA.js → chunk-YI6GNRQM.js} +2 -2
  142. package/dist/cli/chunks/chunk-YNNOY3XN.js +62 -0
  143. package/dist/cli/chunks/{chunk-GXCD7GNH.js → chunk-YWZHMXTO.js} +2 -2
  144. package/dist/cli/chunks/{chunk-XFMSHTXG.js → chunk-ZDHMZPSL.js} +1 -1
  145. package/dist/cli/chunks/{chunk-F363JJUI.js → chunk-ZGNZJJFF.js} +1 -1
  146. package/dist/cli/chunks/{chunk-UCXQQCIP.js → chunk-ZK2BH23O.js} +2 -2
  147. package/dist/cli/chunks/{chunk-IQNR662U.js → chunk-ZQUXNG5X.js} +2 -2
  148. package/dist/cli/chunks/{chunk-IBXNBLGM.js → chunk-ZXTO4C7R.js} +2 -2
  149. package/dist/cli/chunks/{ci-7TR4NQ5I.js → ci-PYCRCL7G.js} +2 -2
  150. package/dist/cli/chunks/{ci-output-SLTICF3O.js → ci-output-EKQQFE2D.js} +2 -2
  151. package/dist/cli/chunks/{circuit-breaker-7GVVTMBY.js → circuit-breaker-RH3Q2MJO.js} +2 -2
  152. package/dist/cli/chunks/{claude-flow-setup-TYCWYEMM.js → claude-flow-setup-DUDXB4VV.js} +2 -2
  153. package/dist/cli/chunks/client-RDPWGOSA.js +2 -0
  154. package/dist/cli/chunks/{cline-installer-ESIAJOLK.js → cline-installer-3Q4WIWUG.js} +2 -2
  155. package/dist/cli/chunks/{code-I42JGOVI.js → code-E4Q6DGOO.js} +2 -2
  156. package/dist/cli/chunks/{code-index-extractor-2CCXPCQW.js → code-index-extractor-2PCISUOW.js} +2 -2
  157. package/dist/cli/chunks/{codex-installer-HEZRDNUT.js → codex-installer-YNNNOLJ6.js} +2 -2
  158. package/dist/cli/chunks/{completions-44HLIZGI.js → completions-2F7TUFBD.js} +2 -2
  159. package/dist/cli/chunks/{complexity-analyzer-SOCSFDVO.js → complexity-analyzer-2B6MHO7W.js} +2 -2
  160. package/dist/cli/chunks/{continuedev-installer-Q7O4HLIM.js → continuedev-installer-ENOKRU5M.js} +2 -2
  161. package/dist/cli/chunks/{copilot-installer-GIWCVLCS.js → copilot-installer-6YD2KM5F.js} +2 -2
  162. package/dist/cli/chunks/{cost-tracker-G7BONKEV.js → cost-tracker-FCH4QOEA.js} +2 -2
  163. package/dist/cli/chunks/{coverage-5TWVP7KY.js → coverage-JTOXZE3T.js} +3 -3
  164. package/dist/cli/chunks/cross-domain-router-4K5ZVZEZ.js +2 -0
  165. package/dist/cli/chunks/{cursor-installer-43EQZSB5.js → cursor-installer-QZFBUGLQ.js} +2 -2
  166. package/dist/cli/chunks/{daemon-ZXHFRDKG.js → daemon-K4QFB5FQ.js} +3 -3
  167. package/dist/cli/chunks/{daemon-QQZE4BU2.js → daemon-M422U3ZA.js} +4 -4
  168. package/dist/cli/chunks/{dag-attention-scheduler-GOZAVAZQ.js → dag-attention-scheduler-BXAAW33V.js} +2 -2
  169. package/dist/cli/chunks/{detect-X777GVJ4.js → detect-UGSWIOAD.js} +2 -2
  170. package/dist/cli/chunks/{dist-node-EZZK46TB.js → dist-node-FN3HX3OK.js} +2 -2
  171. package/dist/cli/chunks/{domain-handler-ZT32DKYY.js → domain-handler-7PP7VYA7.js} +2 -2
  172. package/dist/cli/chunks/{domain-transfer-LHQVSLJW.js → domain-transfer-XZM44W7I.js} +2 -2
  173. package/dist/cli/chunks/dream-RPNWM7VS.js +2 -0
  174. package/dist/cli/chunks/{embed-and-insert-pattern-XFYPPWG7.js → embed-and-insert-pattern-JZVERJ5L.js} +2 -2
  175. package/dist/cli/chunks/{eval-V4NYJZUZ.js → eval-466NFF2D.js} +2 -2
  176. package/dist/cli/chunks/{experience-capture-middleware-HXX2W4GL.js → experience-capture-middleware-I7IQCC7V.js} +3 -3
  177. package/dist/cli/chunks/{fast-paths-RBPWQSFJ.js → fast-paths-34OICNZA.js} +2 -2
  178. package/dist/cli/chunks/{feature-flags-NX5EXRO3.js → feature-flags-6UBIVTAD.js} +2 -2
  179. package/dist/cli/chunks/{feature-flags-INJJZBMN.js → feature-flags-X5WBBWSO.js} +2 -2
  180. package/dist/cli/chunks/{file-discovery-SNFSG6NK.js → file-discovery-NLMDBWXX.js} +2 -2
  181. package/dist/cli/chunks/{fleet-6SDN4UWE.js → fleet-W7CYCHDI.js} +3 -3
  182. package/dist/cli/chunks/{gnn-wrapper-2JDRTDDK.js → gnn-wrapper-K4VTAG5X.js} +2 -2
  183. package/dist/cli/chunks/{heartbeat-handler-QLK6E7KA.js → heartbeat-handler-ZGKF2Z6T.js} +4 -4
  184. package/dist/cli/chunks/heartbeat-scheduler-JBCXMMZO.js +2 -0
  185. package/dist/cli/chunks/hnsw-adapter-3SC2HZIG.js +2 -0
  186. package/dist/cli/chunks/hnsw-index-FQORAR6K.js +2 -0
  187. package/dist/cli/chunks/{hnsw-legacy-bridge-Q2ZEZQKB.js → hnsw-legacy-bridge-ELDRLKK5.js} +2 -2
  188. package/dist/cli/chunks/{better-sqlite3-Y6GX6CGB.js → hnswlib-node-ZGSUMHDC.js} +2 -2
  189. package/dist/cli/chunks/{hooks-D4YENHO2.js → hooks-T4CBINAV.js} +13 -13
  190. package/dist/cli/chunks/hybrid-router-6CBFDXPR.js +2 -0
  191. package/dist/cli/chunks/{hypergraph-engine-G72U446M.js → hypergraph-engine-UWFW3XP5.js} +2 -2
  192. package/dist/cli/chunks/{hypergraph-handler-TRZ5FDRH.js → hypergraph-handler-PK2BI46K.js} +3 -3
  193. package/dist/cli/chunks/impact-analyzer-SOEFVZWG.js +2 -0
  194. package/dist/cli/chunks/{init-handler-3ZD4GCT4.js → init-handler-HNG6KJOU.js} +6 -6
  195. package/dist/cli/chunks/init-wizard-3E4IU5M4.js +2 -0
  196. package/dist/cli/chunks/kernel-GFZP4G5J.js +2 -0
  197. package/dist/cli/chunks/{kilocode-installer-AXSIW3XW.js → kilocode-installer-25V7FEJ4.js} +2 -2
  198. package/dist/cli/chunks/{kiro-installer-JQGIFWBK.js → kiro-installer-7RMTTCQB.js} +2 -2
  199. package/dist/cli/chunks/knowledge-graph-BKRKBU26.js +2 -0
  200. package/dist/cli/chunks/{learning-SPO7TGWX.js → learning-XQC2MG2R.js} +3 -3
  201. package/dist/cli/chunks/llm-router-6KTTONH4.js +36 -0
  202. package/dist/cli/chunks/llm-router-service-KE4IGZPP.js +2 -0
  203. package/dist/cli/chunks/{load-XIDDK64U.js → load-BV64P3AL.js} +2 -2
  204. package/dist/cli/chunks/load-test-VSYJV2AO.js +2 -0
  205. package/dist/cli/chunks/{mcp-3JXRGXO4.js → mcp-U5ZN77TA.js} +2 -2
  206. package/dist/cli/chunks/{memory-A66KRS2P.js → memory-WB5BNBK7.js} +5 -5
  207. package/dist/cli/chunks/memory-backend-B72RGHRF.js +2 -0
  208. package/dist/cli/chunks/memory-handlers-NWCH7AUO.js +2 -0
  209. package/dist/cli/chunks/{multi-model-executor-XCDGUVCE.js → multi-model-executor-3X3W3UTY.js} +2 -2
  210. package/dist/cli/chunks/{opencode-installer-GELXWLF2.js → opencode-installer-TTTMG7ZZ.js} +2 -2
  211. package/dist/cli/chunks/{orchestrator-CCS3K6NH.js → orchestrator-BLCGSHMZ.js} +18 -18
  212. package/dist/cli/chunks/{pipeline-Z5C72H5S.js → pipeline-DZPGMRG7.js} +2 -2
  213. package/dist/cli/chunks/{platform-4AK7XJ3Y.js → platform-EVMZAUNV.js} +2 -2
  214. package/dist/cli/chunks/{plugin-7RYBIZI7.js → plugin-OR55K4HT.js} +2 -2
  215. package/dist/cli/chunks/{prime-radiant-advanced-wasm-E5PARKRX.js → prime-radiant-advanced-wasm-4ODV27HD.js} +2 -2
  216. package/dist/cli/chunks/protocol-executor-V3F37FPO.js +2 -0
  217. package/dist/cli/chunks/{protocol-handler-R6QJQFNL.js → protocol-handler-ZOTI5PID.js} +2 -2
  218. package/dist/cli/chunks/{prove-7ESQ2YAL.js → prove-DIMBYJ7V.js} +2 -2
  219. package/dist/cli/chunks/provider-manager-2PN72TT6.js +2 -0
  220. package/dist/cli/chunks/qe-reasoning-bank-P665QNIR.js +2 -0
  221. package/dist/cli/chunks/{quality-4UE345QA.js → quality-7MX4VL6M.js} +2 -2
  222. package/dist/cli/chunks/queen-coordinator-XD4F7BGB.js +2 -0
  223. package/dist/cli/chunks/{real-embeddings-TYIVN3N5.js → real-embeddings-YPUHWRN2.js} +2 -2
  224. package/dist/cli/chunks/{roocode-installer-2KOANC47.js → roocode-installer-WG5AU4QM.js} +2 -2
  225. package/dist/cli/chunks/router-4SSNWDJC.js +2 -0
  226. package/dist/cli/chunks/routing-feedback-O2JSIBW6.js +2 -0
  227. package/dist/cli/chunks/{routing-handler-JFEYTN7T.js → routing-handler-LZB4MN2K.js} +2 -2
  228. package/dist/cli/chunks/{ruvector-commands-KSLSZRJX.js → ruvector-commands-YE4ADBMC.js} +2 -2
  229. package/dist/cli/chunks/{rvf-dual-writer-EPBL226J.js → rvf-dual-writer-QS5ATW4C.js} +2 -2
  230. package/dist/cli/chunks/{rvf-migration-adapter-25KSI6SF.js → rvf-migration-adapter-YIGKSBD3.js} +2 -2
  231. package/dist/cli/chunks/{rvf-migration-coordinator-2XBYHPZP.js → rvf-migration-coordinator-2NDCWP7F.js} +2 -2
  232. package/dist/cli/chunks/rvf-native-adapter-WIUHYXRB.js +2 -0
  233. package/dist/cli/chunks/safe-db-WL5Y7ZNS.js +2 -0
  234. package/dist/cli/chunks/schedule-U7QDGU5A.js +2 -0
  235. package/dist/cli/chunks/scheduler-LXKGQYXA.js +2 -0
  236. package/dist/cli/chunks/{security-4XWYKI4O.js → security-HT4SUT24.js} +3 -3
  237. package/dist/cli/chunks/{shared-rvf-adapter-WRZ3HGDQ.js → shared-rvf-adapter-4IZOJL33.js} +2 -2
  238. package/dist/cli/chunks/{shared-rvf-dual-writer-DX2N5STR.js → shared-rvf-dual-writer-ZKFO7CBY.js} +2 -2
  239. package/dist/cli/chunks/sqlite-persistence-4KFO3SEB.js +2 -0
  240. package/dist/cli/chunks/{status-handler-V75OSXMQ.js → status-handler-AMEMKBI4.js} +2 -2
  241. package/dist/cli/chunks/{structural-health-TLX3JHZ6.js → structural-health-RBADRLC3.js} +2 -2
  242. package/dist/cli/chunks/{sync-KGBEXUF7.js → sync-ARDDLQBS.js} +2 -2
  243. package/dist/cli/chunks/{sync-DXZFMVZQ.js → sync-PCB23M4K.js} +2 -2
  244. package/dist/cli/chunks/{task-handler-T3OJ6R7H.js → task-handler-J26FSCH5.js} +2 -2
  245. package/dist/cli/chunks/{task-handlers-NJYR54AS.js → task-handlers-AQRLR6BL.js} +3 -3
  246. package/dist/cli/chunks/{test-KMVDNNQA.js → test-YXWSIOSB.js} +4 -4
  247. package/dist/cli/chunks/{test-scheduling-R5EQ2XGV.js → test-scheduling-XY532GI4.js} +3 -3
  248. package/dist/cli/chunks/{token-bootstrap-PFKVV3RO.js → token-bootstrap-KL2QIQ36.js} +2 -2
  249. package/dist/cli/chunks/{token-usage-ZLOGA6LR.js → token-usage-2MJVE4DT.js} +2 -2
  250. package/dist/cli/chunks/{transformers-TNPSPQI3.js → transformers-QSNTOD2Z.js} +2 -2
  251. package/dist/cli/chunks/{tree-sitter-wasm-parser-A2EEB5BF.js → tree-sitter-wasm-parser-QJOKHOIW.js} +2 -2
  252. package/dist/cli/chunks/{types-DIXPI4NR.js → types-RNKRSYMO.js} +2 -2
  253. package/dist/cli/chunks/unified-memory-7AS4LIEF.js +2 -0
  254. package/dist/cli/chunks/unified-memory-hnsw-GREESNJX.js +2 -0
  255. package/dist/cli/chunks/unified-persistence-BPJOMZOA.js +2 -0
  256. package/dist/cli/chunks/{upgrade-LX5KP6VO.js → upgrade-EKJHIFWP.js} +2 -2
  257. package/dist/cli/chunks/{validate-3L6F7M36.js → validate-KS4T7LWC.js} +2 -2
  258. package/dist/cli/chunks/{validate-swarm-FD42ZKAQ.js → validate-swarm-SKKWRP2H.js} +2 -2
  259. package/dist/cli/chunks/{vibium-GSBSJR53.js → vibium-FLUQO4IF.js} +2 -2
  260. package/dist/cli/chunks/visual-security-BW662FHQ.js +2 -0
  261. package/dist/cli/chunks/{web-tree-sitter-TXHMO4BW.js → web-tree-sitter-UMC63DWD.js} +2 -2
  262. package/dist/cli/chunks/{windsurf-installer-3EUZ6RD3.js → windsurf-installer-V3FQGJIQ.js} +2 -2
  263. package/dist/cli/chunks/{witness-chain-ONAUEJ4M.js → witness-chain-GE74TLSO.js} +2 -2
  264. package/dist/cli/chunks/witness-chain-OXVDLNVT.js +2 -0
  265. package/dist/cli/chunks/{workflow-E7A6BV4C.js → workflow-4YZ2RPWA.js} +4 -4
  266. package/dist/cli/chunks/workflow-orchestrator-KKNR46XV.js +2 -0
  267. package/dist/cli/chunks/{wrappers-AHHAQJM3.js → wrappers-37NLMKPE.js} +2 -2
  268. package/dist/cli/commands/hooks-handlers/command-hooks.js +1 -1
  269. package/dist/cli/commands/hooks-handlers/routing-hooks.js +1 -1
  270. package/dist/cli/commands/hooks-handlers/task-hooks.js +1 -1
  271. package/dist/cli/commands/llm-router.js +83 -26
  272. package/dist/domains/chaos-resilience/coordinator.d.ts +2 -1
  273. package/dist/domains/chaos-resilience/coordinator.js +3 -2
  274. package/dist/domains/chaos-resilience/plugin.d.ts +4 -2
  275. package/dist/domains/chaos-resilience/plugin.js +8 -5
  276. package/dist/domains/code-intelligence/coordinator.d.ts +2 -1
  277. package/dist/domains/code-intelligence/coordinator.js +3 -2
  278. package/dist/domains/code-intelligence/plugin.d.ts +4 -2
  279. package/dist/domains/code-intelligence/plugin.js +8 -5
  280. package/dist/domains/contract-testing/coordinator.d.ts +2 -1
  281. package/dist/domains/contract-testing/coordinator.js +3 -2
  282. package/dist/domains/contract-testing/plugin.d.ts +4 -2
  283. package/dist/domains/contract-testing/plugin.js +8 -5
  284. package/dist/domains/coverage-analysis/coordinator.d.ts +2 -1
  285. package/dist/domains/coverage-analysis/coordinator.js +4 -3
  286. package/dist/domains/coverage-analysis/plugin.d.ts +3 -2
  287. package/dist/domains/coverage-analysis/plugin.js +4 -4
  288. package/dist/domains/defect-intelligence/coordinator.d.ts +2 -1
  289. package/dist/domains/defect-intelligence/coordinator.js +4 -3
  290. package/dist/domains/defect-intelligence/plugin.d.ts +4 -2
  291. package/dist/domains/defect-intelligence/plugin.js +9 -6
  292. package/dist/domains/learning-optimization/coordinator.d.ts +2 -1
  293. package/dist/domains/learning-optimization/coordinator.js +3 -2
  294. package/dist/domains/learning-optimization/plugin.d.ts +4 -2
  295. package/dist/domains/learning-optimization/plugin.js +8 -5
  296. package/dist/domains/quality-assessment/coordinator.d.ts +2 -1
  297. package/dist/domains/quality-assessment/coordinator.js +4 -3
  298. package/dist/domains/quality-assessment/plugin.d.ts +4 -2
  299. package/dist/domains/quality-assessment/plugin.js +10 -6
  300. package/dist/domains/requirements-validation/coordinator.d.ts +2 -1
  301. package/dist/domains/requirements-validation/coordinator.js +3 -2
  302. package/dist/domains/requirements-validation/plugin.d.ts +4 -2
  303. package/dist/domains/requirements-validation/plugin.js +8 -5
  304. package/dist/domains/security-compliance/coordinator.d.ts +2 -1
  305. package/dist/domains/security-compliance/coordinator.js +4 -2
  306. package/dist/domains/security-compliance/plugin.d.ts +4 -2
  307. package/dist/domains/security-compliance/plugin.js +11 -6
  308. package/dist/domains/test-execution/coordinator.d.ts +3 -2
  309. package/dist/domains/test-execution/coordinator.js +6 -5
  310. package/dist/domains/test-execution/plugin.d.ts +4 -2
  311. package/dist/domains/test-execution/plugin.js +6 -4
  312. package/dist/domains/test-generation/coordinator.d.ts +2 -1
  313. package/dist/domains/test-generation/coordinator.js +4 -3
  314. package/dist/domains/test-generation/plugin.d.ts +4 -2
  315. package/dist/domains/test-generation/plugin.js +12 -7
  316. package/dist/domains/visual-accessibility/coordinator.d.ts +2 -1
  317. package/dist/domains/visual-accessibility/coordinator.js +4 -3
  318. package/dist/domains/visual-accessibility/plugin.d.ts +4 -2
  319. package/dist/domains/visual-accessibility/plugin.js +9 -6
  320. package/dist/init/init-wizard-hooks.js +271 -271
  321. package/dist/init/phases/07-hooks.d.ts +7 -0
  322. package/dist/init/phases/07-hooks.js +132 -96
  323. package/dist/kernel/interfaces.d.ts +37 -0
  324. package/dist/kernel/kernel.d.ts +39 -0
  325. package/dist/kernel/kernel.js +157 -17
  326. package/dist/learning/agent-routing.d.ts +19 -0
  327. package/dist/learning/agent-routing.js +27 -1
  328. package/dist/learning/dream/dream-scheduler.d.ts +11 -36
  329. package/dist/learning/dream/dream-scheduler.js +44 -0
  330. package/dist/learning/experience-consolidation.d.ts +16 -0
  331. package/dist/learning/experience-consolidation.js +55 -11
  332. package/dist/learning/pattern-lifecycle.d.ts +21 -0
  333. package/dist/learning/pattern-lifecycle.js +70 -6
  334. package/dist/mcp/bundle.js +426 -401
  335. package/dist/mcp/protocol-server.js +13 -14
  336. package/dist/mcp/qe-tool-bridge.js +8 -1
  337. package/dist/mcp/tools/base.d.ts +56 -0
  338. package/dist/mcp/tools/base.js +104 -1
  339. package/dist/mcp/tools/chaos-resilience/inject.js +4 -2
  340. package/dist/mcp/tools/code-intelligence/analyze.js +5 -3
  341. package/dist/mcp/tools/contract-testing/validate.js +4 -2
  342. package/dist/mcp/tools/coverage-analysis/index.js +11 -5
  343. package/dist/mcp/tools/defect-intelligence/predict.js +5 -10
  344. package/dist/mcp/tools/learning-optimization/optimize.js +4 -2
  345. package/dist/mcp/tools/registry.js +8 -1
  346. package/dist/mcp/tools/test-generation/generate.js +10 -6
  347. package/dist/mcp/tools/visual-accessibility/index.js +7 -4
  348. package/dist/mcp/transport/stdio.d.ts +20 -0
  349. package/dist/mcp/transport/stdio.js +35 -2
  350. package/dist/shared/llm/llm-router-service.d.ts +77 -0
  351. package/dist/shared/llm/llm-router-service.js +166 -0
  352. package/dist/shared/llm/providers/gemini.js +5 -2
  353. package/dist/shared/llm/router/config-store.d.ts +89 -0
  354. package/dist/shared/llm/router/config-store.js +261 -0
  355. package/dist/shared/llm/router/hybrid-router.js +33 -11
  356. package/dist/shared/utils/rabitq.d.ts +133 -0
  357. package/dist/shared/utils/rabitq.js +201 -0
  358. package/package.json +8 -2
  359. package/dist/cli/chunks/adapter-WTE6UVGP.js +0 -2
  360. package/dist/cli/chunks/aqe-learning-engine-LCLEBU7D.js +0 -2
  361. package/dist/cli/chunks/base-73I73HBF.js +0 -2
  362. package/dist/cli/chunks/browser-workflow-2NSV5O6W.js +0 -2
  363. package/dist/cli/chunks/chunk-6MONUYQ5.js +0 -2
  364. package/dist/cli/chunks/chunk-QL3U5VSM.js +0 -62
  365. package/dist/cli/chunks/chunk-VMJXNTJT.js +0 -95
  366. package/dist/cli/chunks/chunk-X73CRYF4.js +0 -2
  367. package/dist/cli/chunks/client-7GB4WWUD.js +0 -2
  368. package/dist/cli/chunks/cross-domain-router-7HQ74TLE.js +0 -2
  369. package/dist/cli/chunks/dream-G5SEFHI4.js +0 -2
  370. package/dist/cli/chunks/heartbeat-scheduler-NG7BY3FR.js +0 -2
  371. package/dist/cli/chunks/hnsw-adapter-TDSLUI7K.js +0 -2
  372. package/dist/cli/chunks/hnsw-index-OWLQSOQH.js +0 -2
  373. package/dist/cli/chunks/hybrid-router-URU2XLBD.js +0 -2
  374. package/dist/cli/chunks/impact-analyzer-NMTN75KA.js +0 -2
  375. package/dist/cli/chunks/init-wizard-SHBFYGBV.js +0 -2
  376. package/dist/cli/chunks/kernel-7KVY2JGO.js +0 -2
  377. package/dist/cli/chunks/knowledge-graph-V4G5J5B7.js +0 -2
  378. package/dist/cli/chunks/llm-router-G6N2OKDA.js +0 -36
  379. package/dist/cli/chunks/load-test-N4RNPLG4.js +0 -2
  380. package/dist/cli/chunks/memory-backend-HPGJ5YDQ.js +0 -2
  381. package/dist/cli/chunks/memory-handlers-K33YVCVQ.js +0 -2
  382. package/dist/cli/chunks/protocol-executor-GNVWUJUP.js +0 -2
  383. package/dist/cli/chunks/qe-reasoning-bank-DDSBHO6D.js +0 -2
  384. package/dist/cli/chunks/queen-coordinator-BQJ5O63C.js +0 -2
  385. package/dist/cli/chunks/router-C2RKWB7J.js +0 -2
  386. package/dist/cli/chunks/routing-feedback-RHATTSJ6.js +0 -2
  387. package/dist/cli/chunks/rvf-native-adapter-QG4CXHLL.js +0 -2
  388. package/dist/cli/chunks/safe-db-A4KQ2IDB.js +0 -2
  389. package/dist/cli/chunks/schedule-O7MLASQT.js +0 -2
  390. package/dist/cli/chunks/scheduler-HT7RNYQ2.js +0 -2
  391. package/dist/cli/chunks/sqlite-persistence-4NNKJ6CQ.js +0 -2
  392. package/dist/cli/chunks/unified-memory-CMNJVHOJ.js +0 -2
  393. package/dist/cli/chunks/unified-memory-hnsw-JQLU2KI6.js +0 -2
  394. package/dist/cli/chunks/unified-persistence-I25TEDIU.js +0 -2
  395. package/dist/cli/chunks/visual-security-AJJIEV5V.js +0 -2
  396. package/dist/cli/chunks/witness-chain-762QQBTN.js +0 -2
  397. package/dist/cli/chunks/workflow-orchestrator-ZGPYISKY.js +0 -2
@@ -21,6 +21,7 @@ import { PluginCache } from '../plugins/cache';
21
21
  import { CapturedExperienceBridge } from '../bridge/captured-experience-bridge.js';
22
22
  import { DreamScheduler } from '../learning/dream/dream-scheduler.js';
23
23
  import { createDreamEngine } from '../learning/dream/dream-engine.js';
24
+ import { createLLMRouterService, } from '../shared/llm/llm-router-service.js';
24
25
  // Import domain plugin factories
25
26
  import { createTestGenerationPlugin } from '../domains/test-generation/plugin';
26
27
  import { createTestExecutionPlugin } from '../domains/test-execution/plugin';
@@ -44,21 +45,25 @@ import '../domains/security-compliance';
44
45
  import '../domains/code-intelligence';
45
46
  import '../domains/quality-assessment';
46
47
  import { createEnterpriseIntegrationPlugin } from '../domains/enterprise-integration/plugin';
48
+ // NOTE: underlying createXxxPlugin signatures are updated in Phase 2.
49
+ // For Phase 1, the wrappers accept llmRouter but discard it — this
50
+ // keeps the kernel boot path internally consistent without forcing
51
+ // 13 simultaneous domain-level changes.
47
52
  const DOMAIN_FACTORIES = {
48
- 'test-generation': (eb, m, c) => createTestGenerationPlugin(eb, m, c),
49
- 'test-execution': (eb, m) => createTestExecutionPlugin(eb, m),
50
- 'coverage-analysis': (eb, m) => createCoverageAnalysisPlugin(eb, m),
51
- 'quality-assessment': (eb, m, c) => createQualityAssessmentPlugin(eb, m, c),
52
- 'defect-intelligence': (eb, m, c) => createDefectIntelligencePlugin(eb, m, c),
53
- 'requirements-validation': (eb, m, c) => createRequirementsValidationPlugin(eb, m, c),
54
- 'code-intelligence': (eb, m, c) => createCodeIntelligencePlugin(eb, m, c),
55
- 'security-compliance': (eb, m, c) => createSecurityCompliancePlugin(eb, m, c),
56
- 'contract-testing': (eb, m, c) => createContractTestingPlugin(eb, m, c),
57
- 'visual-accessibility': (eb, m, c) => createVisualAccessibilityPlugin(eb, m, c),
58
- 'chaos-resilience': (eb, m, c) => createChaosResiliencePlugin(eb, m, c),
59
- 'learning-optimization': (eb, m, c) => createLearningOptimizationPlugin(eb, m, c),
60
- 'enterprise-integration': (eb, m, c) => createEnterpriseIntegrationPlugin(eb, m, c),
61
- 'coordination': (eb, m, c) => createCoordinationPlugin(eb, m, c),
53
+ 'test-generation': (eb, m, c, llmRouter) => createTestGenerationPlugin(eb, m, c, undefined, llmRouter),
54
+ 'test-execution': (eb, m, _c, llmRouter) => createTestExecutionPlugin(eb, m, llmRouter),
55
+ 'coverage-analysis': (eb, m, _c, llmRouter) => createCoverageAnalysisPlugin(eb, m, llmRouter),
56
+ 'quality-assessment': (eb, m, c, llmRouter) => createQualityAssessmentPlugin(eb, m, c, undefined, llmRouter),
57
+ 'defect-intelligence': (eb, m, c, llmRouter) => createDefectIntelligencePlugin(eb, m, c, undefined, llmRouter),
58
+ 'requirements-validation': (eb, m, c, llmRouter) => createRequirementsValidationPlugin(eb, m, c, undefined, llmRouter),
59
+ 'code-intelligence': (eb, m, c, llmRouter) => createCodeIntelligencePlugin(eb, m, c, undefined, llmRouter),
60
+ 'security-compliance': (eb, m, c, llmRouter) => createSecurityCompliancePlugin(eb, m, c, undefined, llmRouter),
61
+ 'contract-testing': (eb, m, c, llmRouter) => createContractTestingPlugin(eb, m, c, undefined, llmRouter),
62
+ 'visual-accessibility': (eb, m, c, llmRouter) => createVisualAccessibilityPlugin(eb, m, c, undefined, llmRouter),
63
+ 'chaos-resilience': (eb, m, c, llmRouter) => createChaosResiliencePlugin(eb, m, c, undefined, llmRouter),
64
+ 'learning-optimization': (eb, m, c, llmRouter) => createLearningOptimizationPlugin(eb, m, c, undefined, llmRouter),
65
+ 'enterprise-integration': (eb, m, c, _llmRouter) => createEnterpriseIntegrationPlugin(eb, m, c),
66
+ 'coordination': (eb, m, c, _llmRouter) => createCoordinationPlugin(eb, m, c),
62
67
  };
63
68
  const DEFAULT_CONFIG = {
64
69
  maxConcurrentAgents: AGENT_CONSTANTS.MAX_CONCURRENT_AGENTS,
@@ -93,6 +98,10 @@ export class QEKernelImpl {
93
98
  // checkAndTriggerDream path so 10-second SQLite write transactions move
94
99
  // out of short-lived hook subprocesses into the long-lived kernel.
95
100
  _dreamScheduler;
101
+ // ADR-043: kernel singleton HybridRouter. Built during initialize() iff
102
+ // a provider key is in env or the project explicitly enables one.
103
+ _llmRouter;
104
+ _llmRouterBuild;
96
105
  constructor(config = {}) {
97
106
  this._config = { ...DEFAULT_CONFIG, ...config };
98
107
  this._startTime = new Date();
@@ -118,6 +127,15 @@ export class QEKernelImpl {
118
127
  get memory() {
119
128
  return this._memory;
120
129
  }
130
+ /**
131
+ * ADR-043: Get the LLM router built during initialize(). Returns
132
+ * undefined when llmRouter.enabled is false or no provider was
133
+ * available. Domain plugins receive this as their factory's 4th arg
134
+ * via DOMAIN_FACTORIES.
135
+ */
136
+ get llmRouter() {
137
+ return this._llmRouter;
138
+ }
121
139
  async initialize() {
122
140
  if (this._initialized) {
123
141
  return;
@@ -156,14 +174,20 @@ export class QEKernelImpl {
156
174
  // Re-create plugins with the real memory backend
157
175
  this._plugins = new DefaultPluginLoader(this._eventBus, this._memory, this._config.lazyLoading);
158
176
  }
177
+ // ADR-043: Build the kernel-singleton LLM router before plugin
178
+ // factories are registered, so the closure on the next loop can
179
+ // capture it. Builds iff configured/auto-detected; null otherwise.
180
+ await this._initializeLLMRouter(projectRoot);
159
181
  // Register domain factories for enabled domains
160
182
  for (const domain of this._config.enabledDomains) {
161
183
  const factory = DOMAIN_FACTORIES[domain];
162
184
  if (factory) {
163
185
  // Wrap factory to match PluginLoader signature (async)
164
186
  this._plugins.registerFactory(domain, async (eventBus, memory) => {
165
- // Create plugin synchronously, return as Promise
166
- return Promise.resolve(factory(eventBus, memory, this._coordinator));
187
+ // Create plugin synchronously, return as Promise.
188
+ // ADR-043: pass the kernel singleton llmRouter as 4th arg —
189
+ // domain factories forward it to coordinators/services.
190
+ return Promise.resolve(factory(eventBus, memory, this._coordinator, this._llmRouter));
167
191
  });
168
192
  }
169
193
  }
@@ -199,7 +223,9 @@ export class QEKernelImpl {
199
223
  if (typeof createPlugin !== 'function') {
200
224
  throw new Error(`Plugin "${manifest.name}" entry point must export a default function or "createPlugin" function`);
201
225
  }
202
- return createPlugin(eventBus, memory, this._coordinator);
226
+ // ADR-043: forward llmRouter so external plugins can
227
+ // opt into LLM enhancement on the same terms as built-ins.
228
+ return createPlugin(eventBus, memory, this._coordinator, this._llmRouter);
203
229
  });
204
230
  }
205
231
  }
@@ -310,6 +336,106 @@ export class QEKernelImpl {
310
336
  }
311
337
  this._initialized = true;
312
338
  }
339
+ /**
340
+ * ADR-043: Build the kernel-singleton HybridRouter.
341
+ *
342
+ * Behavior is gated, in order:
343
+ * 1. AQE_LLM_ROUTER_DISABLED env var (kill-switch): if set to a truthy
344
+ * value, ALWAYS skip — even when config.llmRouter.enabled === true.
345
+ * This is the env-only opt-out for users who upgrade with a
346
+ * provider key already in env and don't want billing surprises.
347
+ * 2. config.llmRouter.enabled:
348
+ * 'auto' (default): build iff at least one provider key is in env,
349
+ * or the project's llm-config.json enables a provider
350
+ * true: attempt to build; emit error event if no provider
351
+ * false: skip entirely (sets _llmRouter to undefined)
352
+ *
353
+ * On any error we publish a structured kernel.llm-router.init-failed
354
+ * event so monitoring catches misconfiguration. We also keep the
355
+ * console.warn for direct visibility in dev. The kernel still boots —
356
+ * a kernel that boots without LLMs is strictly better than a kernel
357
+ * that won't boot — but the failure is now observable.
358
+ */
359
+ async _initializeLLMRouter(projectRoot) {
360
+ // (1) Hard env kill-switch. Truthy values disable; falsy/empty pass.
361
+ // Same parse rule as src/mcp/tools/base.ts:isRouterKillSwitchSet
362
+ // so both code paths agree on what "disabled" means.
363
+ const killSwitch = (process.env.AQE_LLM_ROUTER_DISABLED ?? '').trim().toLowerCase();
364
+ if (killSwitch &&
365
+ killSwitch !== 'false' &&
366
+ killSwitch !== '0' &&
367
+ killSwitch !== 'no' &&
368
+ killSwitch !== 'off') {
369
+ this._llmRouter = undefined;
370
+ return;
371
+ }
372
+ const llmCfg = this._config.llmRouter ?? {};
373
+ const enabled = llmCfg.enabled ?? 'auto';
374
+ if (enabled === false) {
375
+ this._llmRouter = undefined;
376
+ return;
377
+ }
378
+ try {
379
+ const built = await createLLMRouterService({
380
+ projectRoot,
381
+ override: llmCfg.configOverride,
382
+ providerManager: llmCfg.providerManager,
383
+ });
384
+ if (!built) {
385
+ if (enabled === true) {
386
+ console.warn('[QEKernel] llmRouter.enabled=true but no provider available — ' +
387
+ 'continuing without LLM router (domain services will skip LLM enhancement)');
388
+ await this._publishLLMRouterEvent('init-no-provider', {
389
+ reason: 'no provider available in env or disk config',
390
+ });
391
+ }
392
+ this._llmRouter = undefined;
393
+ return;
394
+ }
395
+ this._llmRouterBuild = built;
396
+ this._llmRouter = built.router;
397
+ // Phase 5 wiring: register as shared singleton so MCP standalone
398
+ // tools see the same router instance (one cost tracker, one cache,
399
+ // one metric collector, one circuit breaker per provider).
400
+ try {
401
+ const { setSharedLLMRouter } = await import('../mcp/tools/base.js');
402
+ setSharedLLMRouter(built.router);
403
+ }
404
+ catch {
405
+ // MCP module not loaded — fine in CLI-only contexts.
406
+ }
407
+ }
408
+ catch (err) {
409
+ const msg = err instanceof Error ? err.message : String(err);
410
+ console.warn('[QEKernel] LLM router init failed; continuing without LLM enhancement:', msg);
411
+ await this._publishLLMRouterEvent('init-failed', {
412
+ error: msg,
413
+ stack: err instanceof Error ? err.stack : undefined,
414
+ });
415
+ this._llmRouter = undefined;
416
+ }
417
+ }
418
+ /**
419
+ * ADR-043: emit a structured event on the kernel event bus when the
420
+ * LLM router can't be built. Observability hook for monitoring and
421
+ * alerting — a silent warn is not enough for production systems where
422
+ * "tests run without LLM analysis" is a quality regression worth
423
+ * paging on.
424
+ */
425
+ async _publishLLMRouterEvent(type, payload) {
426
+ try {
427
+ await this._eventBus.publish({
428
+ id: randomUUID(),
429
+ type: `kernel.llm-router.${type}`,
430
+ timestamp: new Date(),
431
+ source: 'qe-kernel',
432
+ payload,
433
+ });
434
+ }
435
+ catch {
436
+ // Event bus publish failures during boot must not crash the kernel.
437
+ }
438
+ }
313
439
  async dispose() {
314
440
  // ADR-094: Stop the dream scheduler first so a dream-in-progress doesn't
315
441
  // try to write to a disposed memory backend.
@@ -332,6 +458,20 @@ export class QEKernelImpl {
332
458
  await this._coordinator.dispose();
333
459
  await this._eventBus.dispose();
334
460
  await this._memory.dispose();
461
+ // ADR-043: clear the shared LLM router singleton if we registered
462
+ // one. Prevents test isolation problems where a stale router from
463
+ // a previous kernel boot leaks into the next.
464
+ if (this._llmRouter) {
465
+ try {
466
+ const { resetSharedLLMRouter } = await import('../mcp/tools/base.js');
467
+ resetSharedLLMRouter();
468
+ }
469
+ catch {
470
+ // MCP module not loaded — fine.
471
+ }
472
+ this._llmRouter = undefined;
473
+ this._llmRouterBuild = undefined;
474
+ }
335
475
  this._initialized = false;
336
476
  }
337
477
  getDomainAPI(domain) {
@@ -78,6 +78,25 @@ export declare const MAX_Q_WEIGHT = 0.4;
78
78
  * decision. Adjust downward if cold-start latency proves problematic.
79
79
  */
80
80
  export declare const QWEIGHT_RAMP_VISITS = 20;
81
+ /**
82
+ * De-dilution cap for the domain-match denominator (#510 item 2).
83
+ *
84
+ * Domain score is `(domainMatch / denom) * 0.4`. The original `denom` was the
85
+ * full count of *detected* domains, but AQE's domain detector routinely emits
86
+ * 7-12 domains per task, so a perfect single-domain specialist scored
87
+ * `(1/11)*0.4 ≈ 0.04` — relevance washed out by detector breadth, leaving
88
+ * confidence dominated by the fixed performance term (measured easy task
89
+ * 37.3%, hard task 20.5%, with hard tasks mis-routing to high-performance
90
+ * but domain-irrelevant agents).
91
+ *
92
+ * Capping the denominator models the fact that a task has only a few *truly
93
+ * relevant* domains. With cap=3: a precise detector (1-2 domains) is
94
+ * unchanged, while a broad detector no longer dilutes a real match below
95
+ * usefulness. Proportionality across agents is preserved (an agent matching 2
96
+ * relevant domains still beats one matching 1). Tunable; raise toward the old
97
+ * behavior, lower to weight domain relevance more heavily.
98
+ */
99
+ export declare const DOMAIN_DENOM_CAP = 3;
81
100
  /**
82
101
  * Q-value lookup callback supplied by the caller (QEReasoningBank.routeTask).
83
102
  * Returns undefined when the (stateKey, agentType) pair has no recorded
@@ -99,6 +99,25 @@ export const MAX_Q_WEIGHT = 0.4;
99
99
  * decision. Adjust downward if cold-start latency proves problematic.
100
100
  */
101
101
  export const QWEIGHT_RAMP_VISITS = 20;
102
+ /**
103
+ * De-dilution cap for the domain-match denominator (#510 item 2).
104
+ *
105
+ * Domain score is `(domainMatch / denom) * 0.4`. The original `denom` was the
106
+ * full count of *detected* domains, but AQE's domain detector routinely emits
107
+ * 7-12 domains per task, so a perfect single-domain specialist scored
108
+ * `(1/11)*0.4 ≈ 0.04` — relevance washed out by detector breadth, leaving
109
+ * confidence dominated by the fixed performance term (measured easy task
110
+ * 37.3%, hard task 20.5%, with hard tasks mis-routing to high-performance
111
+ * but domain-irrelevant agents).
112
+ *
113
+ * Capping the denominator models the fact that a task has only a few *truly
114
+ * relevant* domains. With cap=3: a precise detector (1-2 domains) is
115
+ * unchanged, while a broad detector no longer dilutes a real match below
116
+ * usefulness. Proportionality across agents is preserved (an agent matching 2
117
+ * relevant domains still beats one matching 1). Tunable; raise toward the old
118
+ * behavior, lower to weight domain relevance more heavily.
119
+ */
120
+ export const DOMAIN_DENOM_CAP = 3;
102
121
  /**
103
122
  * Sigmoid mapping R → (0, 1) for Q-value normalization before blending.
104
123
  * A fresh row with q_value = 0 contributes 0.5 (neutral); negative q_values
@@ -265,7 +284,14 @@ qValueLookup) {
265
284
  const reasoning = [];
266
285
  // Domain match (0-0.4)
267
286
  const domainMatch = detectedDomains.filter((d) => profile.domains.includes(d)).length;
268
- const domainScore = domainMatch > 0 ? (domainMatch / detectedDomains.length) * 0.4 : 0;
287
+ // De-dilute by capping the denominator (#510 item 2): dividing by the full
288
+ // count of *detected* domains (7-12) washed out real matches. Cap models
289
+ // the few truly-relevant domains a task actually has. Math.min(...,1)
290
+ // guards the case where domainMatch exceeds the cap.
291
+ const domainDenom = Math.min(detectedDomains.length, DOMAIN_DENOM_CAP);
292
+ const domainScore = domainMatch > 0
293
+ ? Math.min(domainMatch / domainDenom, 1) * 0.4
294
+ : 0;
269
295
  score += domainScore * routingWeights.similarity;
270
296
  if (domainScore > 0) {
271
297
  reasoning.push(`Domain match: ${(domainScore * 100).toFixed(0)}%`);
@@ -101,42 +101,6 @@ export interface DreamSchedulerDependencies {
101
101
  /** Memory backend for persisting scheduler state (optional) */
102
102
  memoryBackend?: MemoryBackend;
103
103
  }
104
- /**
105
- * DreamScheduler manages automatic triggering of dream cycles.
106
- *
107
- * It follows the dependency injection pattern - all required dependencies
108
- * (DreamEngine, EventBus) must be provided via the constructor.
109
- *
110
- * @example
111
- * ```typescript
112
- * const scheduler = new DreamScheduler({
113
- * dreamEngine,
114
- * eventBus,
115
- * memoryBackend, // optional
116
- * });
117
- *
118
- * await scheduler.initialize();
119
- * scheduler.start();
120
- *
121
- * // Record experiences as they happen
122
- * scheduler.recordExperience({
123
- * id: 'exp-1',
124
- * agentType: 'tester',
125
- * domain: 'test-execution',
126
- * taskType: 'run-tests',
127
- * success: true,
128
- * duration: 5000,
129
- * timestamp: new Date(),
130
- * });
131
- *
132
- * // Manually trigger a dream
133
- * const result = await scheduler.triggerDream();
134
- *
135
- * // Stop and cleanup
136
- * scheduler.stop();
137
- * await scheduler.dispose();
138
- * ```
139
- */
140
104
  export declare class DreamScheduler {
141
105
  private readonly config;
142
106
  private readonly dreamEngine;
@@ -320,6 +284,17 @@ export declare class DreamScheduler {
320
284
  * Publish a dream completed event.
321
285
  */
322
286
  private publishDreamCompletedEvent;
287
+ /**
288
+ * #509: Reconcile the SessionStart-read `dream-scheduler:hook-state` row after
289
+ * a successful dream cycle. The post-task hook only ever INCREMENTS that row's
290
+ * experienceCount; this kernel scheduler is the entity that actually dreams
291
+ * (ADR-094) but historically never wrote it back, so the SessionStart readout
292
+ * showed lastDreamTime:null and a pendingExperiences counter that only grew.
293
+ * We stamp { lastDreamTime: now, experienceCount: 0, totalDreamsThisSession++ }
294
+ * using the SAME key + DEFAULT namespace the hook path uses. Best-effort: a
295
+ * failure here must never break a dream cycle.
296
+ */
297
+ private reconcileHookState;
323
298
  /**
324
299
  * Save scheduler state to memory backend.
325
300
  */
@@ -81,6 +81,17 @@ export const DEFAULT_DREAM_SCHEDULER_CONFIG = {
81
81
  * await scheduler.dispose();
82
82
  * ```
83
83
  */
84
+ /**
85
+ * kv_store key that the SessionStart hook reads for its dream readout and the
86
+ * post-task hook increments. Mirrors `DREAM_STATE_KEY` in
87
+ * cli/commands/hooks-handlers/hooks-dream-learning.ts — kept as a local literal
88
+ * (not imported) to avoid a learning→cli layering dependency. MUST match that
89
+ * value and use the DEFAULT namespace (the hook path passes no namespace).
90
+ * #509: this scheduler is the entity that actually dreams (ADR-094) but never
91
+ * reset this row, so SessionStart showed lastDreamTime:null + an ever-growing
92
+ * pendingExperiences. reconcileHookState() below stamps the truth per cycle.
93
+ */
94
+ const DREAM_HOOK_STATE_KEY = 'dream-scheduler:hook-state';
84
95
  export class DreamScheduler {
85
96
  config;
86
97
  dreamEngine;
@@ -351,6 +362,10 @@ export class DreamScheduler {
351
362
  this.totalDreamsCompleted++;
352
363
  // Clear experience buffer after successful dream
353
364
  this.clearExperienceBuffer();
365
+ // #509: reconcile the SessionStart-read hook-state row. The post-task hook
366
+ // only increments its experienceCount and nothing on the active dream path
367
+ // reset it, so the readout was perpetually stale. Best-effort.
368
+ await this.reconcileHookState();
354
369
  // Auto-apply high-confidence insights if enabled
355
370
  if (this.config.autoApplyHighConfidenceInsights) {
356
371
  await this.autoApplyInsights(result);
@@ -698,6 +713,35 @@ export class DreamScheduler {
698
713
  // ==========================================================================
699
714
  // Private: State Persistence
700
715
  // ==========================================================================
716
+ /**
717
+ * #509: Reconcile the SessionStart-read `dream-scheduler:hook-state` row after
718
+ * a successful dream cycle. The post-task hook only ever INCREMENTS that row's
719
+ * experienceCount; this kernel scheduler is the entity that actually dreams
720
+ * (ADR-094) but historically never wrote it back, so the SessionStart readout
721
+ * showed lastDreamTime:null and a pendingExperiences counter that only grew.
722
+ * We stamp { lastDreamTime: now, experienceCount: 0, totalDreamsThisSession++ }
723
+ * using the SAME key + DEFAULT namespace the hook path uses. Best-effort: a
724
+ * failure here must never break a dream cycle.
725
+ */
726
+ async reconcileHookState() {
727
+ if (!this.memoryBackend)
728
+ return;
729
+ try {
730
+ const prev = await this.memoryBackend.get(DREAM_HOOK_STATE_KEY);
731
+ const next = {
732
+ lastDreamTime: (this.lastDreamTime ?? new Date()).toISOString(),
733
+ experienceCount: 0,
734
+ sessionStartTime: prev?.sessionStartTime,
735
+ totalDreamsThisSession: (prev?.totalDreamsThisSession ?? 0) + 1,
736
+ };
737
+ await this.memoryBackend.set(DREAM_HOOK_STATE_KEY, next);
738
+ }
739
+ catch (err) {
740
+ logger.warn('Dream hook-state reconcile failed (non-critical)', {
741
+ error: err instanceof Error ? err.message : String(err),
742
+ });
743
+ }
744
+ }
701
745
  /**
702
746
  * Save scheduler state to memory backend.
703
747
  */
@@ -18,6 +18,12 @@ import type { Database as DatabaseType } from 'better-sqlite3';
18
18
  export interface ConsolidationResult {
19
19
  /** Experiences merged into survivors */
20
20
  merged: number;
21
+ /**
22
+ * Experiences suppressed from retrieval because they CONTRADICT a
23
+ * higher-quality near-duplicate (similar context, opposite outcome).
24
+ * Soft-suppressed (consolidated_into = 'contradicted'), not deleted.
25
+ */
26
+ contradicted: number;
21
27
  /** Experiences with quality recalculated */
22
28
  qualityUpdated: number;
23
29
  /** Experiences soft-archived (Phase 3 valueless + Phase 4 safety valve) */
@@ -54,6 +60,16 @@ export interface ConsolidationConfig {
54
60
  archiveQualityThreshold: number;
55
61
  /** Quality boost per merged experience */
56
62
  mergeQualityBoost: number;
63
+ /**
64
+ * Contradiction detection (#510 item 7). Two experiences with cosine
65
+ * similarity >= this threshold but a quality delta >= contradictionQualityDelta
66
+ * are treated as "same context, opposite outcome" — a conflict, not a
67
+ * duplicate. The lower-quality loser is suppressed from retrieval instead of
68
+ * merged, so it can't poison recall.
69
+ */
70
+ contradictionSimilarityThreshold: number;
71
+ /** Min quality gap that turns a near-duplicate into a contradiction (0-1). */
72
+ contradictionQualityDelta: number;
57
73
  }
58
74
  export declare class ExperienceConsolidator {
59
75
  private readonly config;
@@ -25,6 +25,8 @@ const DEFAULT_CONFIG = {
25
25
  archiveMinAgeDays: 30,
26
26
  archiveQualityThreshold: 0.15,
27
27
  mergeQualityBoost: 0.02,
28
+ contradictionSimilarityThreshold: 0.85,
29
+ contradictionQualityDelta: 0.4,
28
30
  };
29
31
  // ============================================================================
30
32
  // ExperienceConsolidator
@@ -59,6 +61,7 @@ export class ExperienceConsolidator {
59
61
  this.ensureInitialized();
60
62
  const totalResult = {
61
63
  merged: 0,
64
+ contradicted: 0,
62
65
  qualityUpdated: 0,
63
66
  archived: 0,
64
67
  hardDeleted: 0,
@@ -73,6 +76,7 @@ export class ExperienceConsolidator {
73
76
  for (const { domain, cnt } of targetDomains) {
74
77
  const result = await this.consolidateDomain(domain, cnt);
75
78
  totalResult.merged += result.merged;
79
+ totalResult.contradicted += result.contradicted;
76
80
  totalResult.qualityUpdated += result.qualityUpdated;
77
81
  totalResult.archived += result.archived;
78
82
  totalResult.hardDeleted += result.hardDeleted;
@@ -81,8 +85,9 @@ export class ExperienceConsolidator {
81
85
  // Count total active remaining
82
86
  const activeCount = this.db.prepare("SELECT COUNT(*) as cnt FROM captured_experiences WHERE consolidated_into IS NULL").get();
83
87
  totalResult.activeRemaining = activeCount.cnt;
84
- if (totalResult.merged > 0 || totalResult.archived > 0) {
88
+ if (totalResult.merged > 0 || totalResult.archived > 0 || totalResult.contradicted > 0) {
85
89
  console.log(`[ExperienceConsolidator] Consolidated: ${totalResult.merged} merged, ` +
90
+ `${totalResult.contradicted} contradicted, ` +
86
91
  `${totalResult.archived} archived, ${totalResult.activeRemaining} active`);
87
92
  }
88
93
  return totalResult;
@@ -94,14 +99,17 @@ export class ExperienceConsolidator {
94
99
  this.ensureInitialized();
95
100
  const result = {
96
101
  merged: 0,
102
+ contradicted: 0,
97
103
  qualityUpdated: 0,
98
104
  archived: 0,
99
105
  hardDeleted: 0,
100
106
  activeRemaining: 0,
101
107
  domainsProcessed: [domain],
102
108
  };
103
- // Phase 1: Cluster & Merge
104
- result.merged = await this.clusterAndMerge(domain);
109
+ // Phase 1: Cluster & Merge (+ contradiction suppression)
110
+ const clusterResult = await this.clusterAndMerge(domain);
111
+ result.merged = clusterResult.merged;
112
+ result.contradicted = clusterResult.contradicted;
105
113
  // Phase 2: Quality Reinforcement
106
114
  result.qualityUpdated = this.reinforceQuality(domain);
107
115
  // Phase 3: Archive Valueless
@@ -129,7 +137,7 @@ export class ExperienceConsolidator {
129
137
  if (flag) {
130
138
  console.log(`[ExperienceConsolidator] Domain ${domain} already bootstrapped`);
131
139
  return {
132
- merged: 0, qualityUpdated: 0, archived: 0,
140
+ merged: 0, contradicted: 0, qualityUpdated: 0, archived: 0,
133
141
  hardDeleted: 0, activeRemaining: 0, domainsProcessed: [domain],
134
142
  };
135
143
  }
@@ -165,7 +173,7 @@ export class ExperienceConsolidator {
165
173
  ORDER BY quality DESC
166
174
  `).all(domain);
167
175
  if (candidates.length < 2)
168
- return 0;
176
+ return { merged: 0, contradicted: 0 };
169
177
  // Build a temporary HNSW index for this domain
170
178
  const hnswIndex = new HNSWEmbeddingIndex({
171
179
  dimension: 384,
@@ -196,7 +204,9 @@ export class ExperienceConsolidator {
196
204
  // Track which IDs have been absorbed
197
205
  const absorbed = new Set();
198
206
  let mergeCount = 0;
207
+ let contradictionCount = 0;
199
208
  const markConsolidated = this.db.prepare("UPDATE captured_experiences SET consolidated_into = ? WHERE id = ?");
209
+ const markContradicted = this.db.prepare("UPDATE captured_experiences SET consolidated_into = 'contradicted' WHERE id = ?");
200
210
  const boostSurvivor = this.db.prepare(`
201
211
  UPDATE captured_experiences
202
212
  SET consolidation_count = consolidation_count + ?,
@@ -210,7 +220,7 @@ export class ExperienceConsolidator {
210
220
  `);
211
221
  // Iterate experiences by quality DESC
212
222
  for (const row of candidates) {
213
- if (mergeCount >= this.config.maxMergesPerRun)
223
+ if (mergeCount + contradictionCount >= this.config.maxMergesPerRun)
214
224
  break;
215
225
  if (absorbed.has(row.id))
216
226
  continue;
@@ -232,21 +242,42 @@ export class ExperienceConsolidator {
232
242
  namespace: 'experiences',
233
243
  });
234
244
  const mergedIds = [];
245
+ const contradictedIds = [];
235
246
  for (const { id: hnswId, distance } of neighbors) {
236
- if (mergeCount >= this.config.maxMergesPerRun)
247
+ if (mergeCount + contradictionCount >= this.config.maxMergesPerRun)
237
248
  break;
238
249
  const neighborId = idMap.get(hnswId);
239
250
  if (!neighborId || neighborId === row.id || absorbed.has(neighborId))
240
251
  continue;
241
252
  const similarity = 1 - distance;
242
- if (similarity < this.config.mergeSimilarityThreshold)
253
+ // Gate on the lower of the two thresholds so neither merge nor
254
+ // contradiction detection is starved if they are configured differently.
255
+ if (similarity < Math.min(this.config.mergeSimilarityThreshold, this.config.contradictionSimilarityThreshold))
243
256
  continue;
244
257
  // Find the neighbor in candidates
245
258
  const neighbor = candidates.find(c => c.id === neighborId);
246
259
  if (!neighbor)
247
260
  continue;
248
- // Only merge lower-quality, unused neighbors into the survivor
249
- if (neighbor.quality <= row.quality && neighbor.application_count === 0) {
261
+ // Contradiction (#510 item 7): same context (high similarity) but
262
+ // opposite outcome (large quality delta) => a conflict, not a duplicate.
263
+ // Suppress the lower-quality loser from retrieval even if it was applied
264
+ // (a used-but-low-quality contradictory experience is exactly the
265
+ // recall-poisoning case). Candidates are sorted quality DESC and absorbed
266
+ // ones are skipped, so when a gap exists `neighbor` is the strict loser.
267
+ const qualityDelta = Math.abs(row.quality - neighbor.quality);
268
+ if (similarity >= this.config.contradictionSimilarityThreshold
269
+ && qualityDelta >= this.config.contradictionQualityDelta) {
270
+ if (neighbor.quality < row.quality) {
271
+ absorbed.add(neighborId);
272
+ contradictedIds.push(neighborId);
273
+ contradictionCount++;
274
+ }
275
+ continue; // never merge a contradictory pair
276
+ }
277
+ // Only merge lower-quality, unused neighbors into the survivor (requires
278
+ // the normal merge similarity threshold).
279
+ if (similarity >= this.config.mergeSimilarityThreshold
280
+ && neighbor.quality <= row.quality && neighbor.application_count === 0) {
250
281
  absorbed.add(neighborId);
251
282
  mergedIds.push(neighborId);
252
283
  mergeCount++;
@@ -264,10 +295,23 @@ export class ExperienceConsolidator {
264
295
  });
265
296
  transaction();
266
297
  }
298
+ // Apply contradiction suppressions in a transaction. The loser is
299
+ // soft-suppressed (consolidated_into = 'contradicted'), so it is excluded
300
+ // from retrieval (WHERE consolidated_into IS NULL) but not deleted. The
301
+ // survivor is NOT boosted — a contradiction is a conflict, not a duplicate.
302
+ if (contradictedIds.length > 0) {
303
+ const tx = this.db.transaction(() => {
304
+ for (const loserId of contradictedIds) {
305
+ markContradicted.run(loserId);
306
+ }
307
+ logConsolidation.run(uuidv4(), domain, 'contradiction', JSON.stringify(contradictedIds), row.id, JSON.stringify({ count: contradictedIds.length, survivorQuality: row.quality }));
308
+ });
309
+ tx();
310
+ }
267
311
  }
268
312
  // Clean up HNSW index
269
313
  hnswIndex.clearIndex('experiences');
270
- return mergeCount;
314
+ return { merged: mergeCount, contradicted: contradictionCount };
271
315
  }
272
316
  // ============================================================================
273
317
  // Phase 2: Quality Reinforcement
@@ -42,6 +42,27 @@ export interface PatternLifecycleConfig {
42
42
  * Default lifecycle configuration
43
43
  */
44
44
  export declare const DEFAULT_LIFECYCLE_CONFIG: PatternLifecycleConfig;
45
+ /** Minimum usage_count before success_rate is trusted as an importance signal. */
46
+ export declare const EWC_MIN_USAGE_FOR_PROTECTION = 5;
47
+ /**
48
+ * Fraction of the base decay rate a fully-important pattern is shielded from.
49
+ * 0.9 => a success_rate=1.0 pattern decays at 10% of the base rate.
50
+ * Low-importance patterns (importance 0) decay EXACTLY as before (no regression).
51
+ */
52
+ export declare const EWC_DECAY_PROTECTION = 0.9;
53
+ /**
54
+ * Multiplier extending the stale window by importance.
55
+ * effectiveStaleDays = staleDaysThreshold * (1 + importance * EWC_STALE_PROTECTION_BONUS).
56
+ * 2 => a fully-important pattern survives 3x longer unused (e.g. 30d -> 90d)
57
+ * before stale-deprecation; importance-0 patterns are unchanged.
58
+ */
59
+ export declare const EWC_STALE_PROTECTION_BONUS = 2;
60
+ /**
61
+ * Importance proxy in [0,1] for EWC++ forgetting protection.
62
+ * Returns 0 (no protection) until a pattern has been used enough to trust its
63
+ * success rate, then equals the clamped success rate.
64
+ */
65
+ export declare function patternImportance(successRate: number, usageCount: number): number;
45
66
  /**
46
67
  * Experience aggregation for pattern candidate identification
47
68
  */