agentic-qe 3.8.14 → 3.9.0

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 (338) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +28 -0
  3. package/dist/adapters/a2ui/integration/agui-sync.js +2 -1
  4. package/dist/boot/fast-paths.d.ts +24 -0
  5. package/dist/boot/fast-paths.js +43 -0
  6. package/dist/boot/parallel-prefetch.d.ts +26 -0
  7. package/dist/boot/parallel-prefetch.js +36 -0
  8. package/dist/cli/bundle.js +12 -9431
  9. package/dist/cli/chunks/adapter-WBR5NXS3.js +2 -0
  10. package/dist/cli/chunks/agent-booster-wasm-PQYB7VRU.js +2 -0
  11. package/dist/cli/chunks/agent-handler-QDAB5NQS.js +33 -0
  12. package/dist/cli/chunks/aqe-learning-engine-TK4JQCGT.js +2 -0
  13. package/dist/cli/chunks/audit-S7JUYYVP.js +3 -0
  14. package/dist/cli/chunks/base-2WXOSMBQ.js +2 -0
  15. package/dist/cli/chunks/better-sqlite3-7KY2RDXO.js +2 -0
  16. package/dist/cli/chunks/brain-handler-PPEGDCN4.js +68 -0
  17. package/dist/cli/chunks/branch-enumerator-XK4V5W7L.js +7 -0
  18. package/dist/cli/chunks/browser-PALA5PL3.js +4 -0
  19. package/dist/cli/chunks/browser-workflow-42F7GK5T.js +2 -0
  20. package/dist/cli/chunks/chunk-24FKIJNC.js +15 -0
  21. package/dist/cli/chunks/chunk-263XS447.js +2 -0
  22. package/dist/cli/chunks/chunk-2BZFNEN2.js +4 -0
  23. package/dist/cli/chunks/chunk-2E5NQNSU.js +180 -0
  24. package/dist/cli/chunks/chunk-2I7J3O6V.js +2 -0
  25. package/dist/cli/chunks/chunk-3ADGXLTM.js +14 -0
  26. package/dist/cli/chunks/chunk-3IHG3WOY.js +12 -0
  27. package/dist/cli/chunks/chunk-3IUNFTIF.js +2 -0
  28. package/dist/cli/chunks/chunk-3JPRUND5.js +2 -0
  29. package/dist/cli/chunks/chunk-3NZLZHJI.js +2 -0
  30. package/dist/cli/chunks/chunk-3THRQEZ2.js +95 -0
  31. package/dist/cli/chunks/chunk-3ZOONQG6.js +2 -0
  32. package/dist/cli/chunks/chunk-4B6NCELM.js +2 -0
  33. package/dist/cli/chunks/chunk-4I2IOUS4.js +2 -0
  34. package/dist/cli/chunks/chunk-4VBTXZRM.js +2 -0
  35. package/dist/cli/chunks/chunk-4VUPRTVX.js +3 -0
  36. package/dist/cli/chunks/chunk-4YOMLWEK.js +70 -0
  37. package/dist/cli/chunks/chunk-4YS3IJ45.js +2 -0
  38. package/dist/cli/chunks/chunk-5SKGFSKD.js +2 -0
  39. package/dist/cli/chunks/chunk-5T2ZQWKF.js +27 -0
  40. package/dist/cli/chunks/chunk-62ADTHV7.js +2 -0
  41. package/dist/cli/chunks/chunk-6EOS7KX2.js +2 -0
  42. package/dist/cli/chunks/chunk-6SVX4DJC.js +6 -0
  43. package/dist/cli/chunks/chunk-72WOAVK6.js +2 -0
  44. package/dist/cli/chunks/chunk-7R6YMLVS.js +3 -0
  45. package/dist/cli/chunks/chunk-7VDBAVTY.js +2 -0
  46. package/dist/cli/chunks/chunk-AFLLQ5PP.js +15 -0
  47. package/dist/cli/chunks/chunk-AKE543X2.js +2 -0
  48. package/dist/cli/chunks/chunk-B36CDR4U.js +2 -0
  49. package/dist/cli/chunks/chunk-B6LLWYQ6.js +2 -0
  50. package/dist/cli/chunks/chunk-BDIEMZ22.js +91 -0
  51. package/dist/cli/chunks/chunk-BGXNSCXX.js +4 -0
  52. package/dist/cli/chunks/chunk-BLBRY5UD.js +2 -0
  53. package/dist/cli/chunks/chunk-BPWXXEH2.js +3029 -0
  54. package/dist/cli/chunks/chunk-BR26T7ZS.js +180 -0
  55. package/dist/cli/chunks/chunk-BTREG4IW.js +2 -0
  56. package/dist/cli/chunks/chunk-BULKFVYX.js +2 -0
  57. package/dist/cli/chunks/chunk-BXAXGEFC.js +24 -0
  58. package/dist/cli/chunks/chunk-CL6POIX4.js +2 -0
  59. package/dist/cli/chunks/chunk-CS2KS7LP.js +2 -0
  60. package/dist/cli/chunks/chunk-CWFB6BSA.js +316 -0
  61. package/dist/cli/chunks/chunk-DRT3WKQW.js +2 -0
  62. package/dist/cli/chunks/chunk-EHDQJQ6Y.js +27 -0
  63. package/dist/cli/chunks/chunk-ESVQ6MEB.js +2 -0
  64. package/dist/cli/chunks/chunk-FEKY7T6Q.js +2 -0
  65. package/dist/cli/chunks/chunk-FGA7VIFR.js +7 -0
  66. package/dist/cli/chunks/chunk-FIA6X7UL.js +2 -0
  67. package/dist/cli/chunks/chunk-GAOJV3OX.js +2 -0
  68. package/dist/cli/chunks/chunk-GKNNSCLC.js +5 -0
  69. package/dist/cli/chunks/chunk-GPQ57KA4.js +2 -0
  70. package/dist/cli/chunks/chunk-GRUUQAR6.js +2 -0
  71. package/dist/cli/chunks/chunk-HRO6OZQD.js +2 -0
  72. package/dist/cli/chunks/chunk-HY6PMO5W.js +66 -0
  73. package/dist/cli/chunks/chunk-IAV2JMIX.js +167 -0
  74. package/dist/cli/chunks/chunk-IFNIIK34.js +21 -0
  75. package/dist/cli/chunks/chunk-IGJPMN4I.js +3 -0
  76. package/dist/cli/chunks/chunk-J3KWWR6Z.js +1 -0
  77. package/dist/cli/chunks/chunk-JBANAPWG.js +2 -0
  78. package/dist/cli/chunks/chunk-JJO7Y4H3.js +604 -0
  79. package/dist/cli/chunks/chunk-JRYGQO2W.js +2 -0
  80. package/dist/cli/chunks/chunk-JXM26HEE.js +2 -0
  81. package/dist/cli/chunks/chunk-JZSDOIXA.js +2 -0
  82. package/dist/cli/chunks/chunk-KP5NUODU.js +3 -0
  83. package/dist/cli/chunks/chunk-LHJQD2VU.js +750 -0
  84. package/dist/cli/chunks/chunk-LNQIY6BP.js +2 -0
  85. package/dist/cli/chunks/chunk-MDUHYUHF.js +2 -0
  86. package/dist/cli/chunks/chunk-MV6CMOJQ.js +65 -0
  87. package/dist/cli/chunks/chunk-MZOFWJTM.js +2 -0
  88. package/dist/cli/chunks/chunk-N2NS2PHA.js +45 -0
  89. package/dist/cli/chunks/chunk-N4TL73TH.js +314 -0
  90. package/dist/cli/chunks/chunk-N5UXCLFI.js +2 -0
  91. package/dist/cli/chunks/chunk-NZ2VCPN4.js +2 -0
  92. package/dist/cli/chunks/chunk-OF4D7MYI.js +2 -0
  93. package/dist/cli/chunks/chunk-OI5NGQO2.js +2 -0
  94. package/dist/cli/chunks/chunk-OLHKGP35.js +2 -0
  95. package/dist/cli/chunks/chunk-QOVHWZEP.js +1 -0
  96. package/dist/cli/chunks/chunk-RFSN6IDA.js +79 -0
  97. package/dist/cli/chunks/chunk-RTGGL7D7.js +4 -0
  98. package/dist/cli/chunks/chunk-RU5WAHB7.js +3 -0
  99. package/dist/cli/chunks/chunk-SUSEVMZT.js +2 -0
  100. package/dist/cli/chunks/chunk-TLHP5EII.js +2 -0
  101. package/dist/cli/chunks/chunk-TWUWL5EJ.js +2 -0
  102. package/dist/cli/chunks/chunk-U5RN7YQW.js +2 -0
  103. package/dist/cli/chunks/chunk-UFUVUO3J.js +2 -0
  104. package/dist/cli/chunks/chunk-UQHYFOBX.js +16 -0
  105. package/dist/cli/chunks/chunk-VOS4NQSF.js +2 -0
  106. package/dist/cli/chunks/chunk-VSVXUTJN.js +256 -0
  107. package/dist/cli/chunks/chunk-WBQSXPBI.js +2 -0
  108. package/dist/cli/chunks/chunk-WGMPEW2T.js +2 -0
  109. package/dist/cli/chunks/chunk-WIEC7VKK.js +2 -0
  110. package/dist/cli/chunks/chunk-WJ3DLOXF.js +14 -0
  111. package/dist/cli/chunks/chunk-X3KI6JOY.js +9 -0
  112. package/dist/cli/chunks/chunk-X5IJGWYG.js +2 -0
  113. package/dist/cli/chunks/chunk-XIBDETCS.js +146 -0
  114. package/dist/cli/chunks/chunk-XLRQYLWW.js +2 -0
  115. package/dist/cli/chunks/chunk-XO6PVK2P.js +3 -0
  116. package/dist/cli/chunks/chunk-XRE2HCWG.js +3 -0
  117. package/dist/cli/chunks/chunk-XT2V2322.js +2 -0
  118. package/dist/cli/chunks/chunk-Y7BHKZFJ.js +18 -0
  119. package/dist/cli/chunks/chunk-YAGODYIG.js +59 -0
  120. package/dist/cli/chunks/chunk-YANUP2RO.js +2 -0
  121. package/dist/cli/chunks/chunk-YPFOCNOE.js +30 -0
  122. package/dist/cli/chunks/chunk-YR6ZZGH7.js +81 -0
  123. package/dist/cli/chunks/chunk-YVA65UZL.js +2 -0
  124. package/dist/cli/chunks/chunk-YW2THB5Q.js +2 -0
  125. package/dist/cli/chunks/chunk-ZAPS3UGQ.js +20 -0
  126. package/dist/cli/chunks/chunk-ZDATDCYN.js +2 -0
  127. package/dist/cli/chunks/ci-J374KDLI.js +81 -0
  128. package/dist/cli/chunks/ci-output-7JN7F6CI.js +2 -0
  129. package/dist/cli/chunks/claude-flow-setup-245JLJCN.js +2 -0
  130. package/dist/cli/chunks/client-MCSNSH2C.js +2 -0
  131. package/dist/cli/chunks/cline-installer-LBA2M5N3.js +4 -0
  132. package/dist/cli/chunks/code-U4N4WONM.js +38 -0
  133. package/dist/cli/chunks/code-index-extractor-A57Z6BO4.js +3 -0
  134. package/dist/cli/chunks/codex-installer-UXMK2N4T.js +8 -0
  135. package/dist/cli/chunks/completions-W66BSCOE.js +1364 -0
  136. package/dist/cli/chunks/complexity-analyzer-AB4OZARV.js +2 -0
  137. package/dist/cli/chunks/continuedev-installer-LRFZ2SJM.js +14 -0
  138. package/dist/cli/chunks/copilot-installer-CQ3JYBIB.js +3 -0
  139. package/dist/cli/chunks/cost-tracker-4F723RB6.js +2 -0
  140. package/dist/cli/chunks/coverage-4PUEQXAY.js +27 -0
  141. package/dist/cli/chunks/cross-domain-router-OWR5IJ5G.js +2 -0
  142. package/dist/cli/chunks/cursor-installer-JZEDEDHA.js +3 -0
  143. package/dist/cli/chunks/daemon-B7TWGHXQ.js +19 -0
  144. package/dist/cli/chunks/dag-attention-scheduler-JWO6XI6A.js +2 -0
  145. package/dist/cli/chunks/detect-L6ZZHUSX.js +2 -0
  146. package/dist/cli/chunks/domain-handler-FT5FLZWL.js +25 -0
  147. package/dist/cli/chunks/domain-transfer-5Y4FGJAJ.js +2 -0
  148. package/dist/cli/chunks/dream-4TDBIYED.js +2 -0
  149. package/dist/cli/chunks/esm-node-2PKHKOTS.js +2 -0
  150. package/dist/cli/chunks/eval-GHMPFGWV.js +15 -0
  151. package/dist/cli/chunks/fast-paths-B3R647KN.js +2 -0
  152. package/dist/cli/chunks/feature-flags-DWS7ARSX.js +2 -0
  153. package/dist/cli/chunks/feature-flags-IVQ3AL4Q.js +2 -0
  154. package/dist/cli/chunks/file-discovery-QFPA6GMV.js +2 -0
  155. package/dist/cli/chunks/fleet-EKOKMOMW.js +43 -0
  156. package/dist/cli/chunks/gnn-wrapper-OYC55N5E.js +2 -0
  157. package/dist/cli/chunks/heartbeat-handler-MBBS4IBU.js +48 -0
  158. package/dist/cli/chunks/heartbeat-scheduler-XDGMOT7X.js +2 -0
  159. package/dist/cli/chunks/hnsw-index-YO7CT23I.js +2 -0
  160. package/dist/cli/chunks/hnswlib-node-56YWVXFE.js +2 -0
  161. package/dist/cli/chunks/hooks-L5VLZGEK.js +101 -0
  162. package/dist/cli/chunks/hypergraph-engine-A4Y2ZRAG.js +2 -0
  163. package/dist/cli/chunks/hypergraph-handler-3HDGB5SZ.js +35 -0
  164. package/dist/cli/chunks/impact-analyzer-UEIGXSZ4.js +2 -0
  165. package/dist/cli/chunks/init-handler-JDET6WUN.js +68 -0
  166. package/dist/cli/chunks/init-wizard-JWZUGIPJ.js +2 -0
  167. package/dist/cli/chunks/kernel-YNDTVKIW.js +2 -0
  168. package/dist/cli/chunks/kilocode-installer-GZZG5AFW.js +4 -0
  169. package/dist/cli/chunks/kiro-installer-IWNY5TKH.js +74 -0
  170. package/dist/cli/chunks/knowledge-graph-NGJKFTSN.js +2 -0
  171. package/dist/cli/chunks/learning-722ZNSZ6.js +107 -0
  172. package/dist/cli/chunks/llm-router-DNAV746L.js +30 -0
  173. package/dist/cli/chunks/load-Y3GCUFM4.js +2 -0
  174. package/dist/cli/chunks/load-test-GZUBXFF3.js +2 -0
  175. package/dist/cli/chunks/mcp-LKPIBZ3W.js +2 -0
  176. package/dist/cli/chunks/memory-L57MLFOP.js +32 -0
  177. package/dist/cli/chunks/memory-backend-3NQIZUXE.js +2 -0
  178. package/dist/cli/chunks/memory-handlers-MDZQ7HVW.js +2 -0
  179. package/dist/cli/chunks/opencode-installer-4HUB36H5.js +3 -0
  180. package/dist/cli/chunks/orchestrator-QHSBB2UC.js +371 -0
  181. package/dist/cli/chunks/pipeline-D3QER35Z.js +19 -0
  182. package/dist/cli/chunks/platform-T4E7Q3RD.js +2 -0
  183. package/dist/cli/chunks/plugin-JHW2YPRC.js +27 -0
  184. package/dist/cli/chunks/prime-radiant-advanced-wasm-G7CFNNQV.js +2 -0
  185. package/dist/cli/chunks/protocol-executor-SPUVRDWT.js +2 -0
  186. package/dist/cli/chunks/protocol-handler-2BQQ4HDM.js +20 -0
  187. package/dist/cli/chunks/prove-UQ6JFT73.js +3 -0
  188. package/dist/cli/chunks/qe-reasoning-bank-3HBK2FVD.js +2 -0
  189. package/dist/cli/chunks/quality-JRZYMC77.js +7 -0
  190. package/dist/cli/chunks/queen-coordinator-RW3NKO5A.js +2 -0
  191. package/dist/cli/chunks/real-embeddings-GK63VF35.js +2 -0
  192. package/dist/cli/chunks/roocode-installer-F4E2LAYR.js +4 -0
  193. package/dist/cli/chunks/router-RJGHWDQ3.js +2 -0
  194. package/dist/cli/chunks/routing-feedback-ZXBXFKX6.js +2 -0
  195. package/dist/cli/chunks/routing-handler-VNKFUUGB.js +20 -0
  196. package/dist/cli/chunks/ruvector-commands-2TLNHC3A.js +8 -0
  197. package/dist/cli/chunks/rvf-dual-writer-MQW2SJLT.js +2 -0
  198. package/dist/cli/chunks/rvf-native-adapter-LKFKTMUN.js +2 -0
  199. package/dist/cli/chunks/safe-db-G22E5ROA.js +2 -0
  200. package/dist/cli/chunks/schedule-Y7VVCPYV.js +2 -0
  201. package/dist/cli/chunks/scheduler-AUQIFQB7.js +2 -0
  202. package/dist/cli/chunks/security-EBEG2OPU.js +14 -0
  203. package/dist/cli/chunks/shared-rvf-dual-writer-BVSCQAFS.js +2 -0
  204. package/dist/cli/chunks/sqlite-persistence-JAVHUGGL.js +2 -0
  205. package/dist/cli/chunks/status-handler-VZ32M4G4.js +45 -0
  206. package/dist/cli/chunks/structural-health-K6LRCKV6.js +2 -0
  207. package/dist/cli/chunks/sync-MHSHNLIM.js +23 -0
  208. package/dist/cli/chunks/task-handler-JNOIBZ2G.js +49 -0
  209. package/dist/cli/chunks/task-handlers-P5DSUKND.js +2 -0
  210. package/dist/cli/chunks/test-DO22BNIL.js +33 -0
  211. package/dist/cli/chunks/test-scheduling-VLRQZEFL.js +15 -0
  212. package/dist/cli/chunks/token-bootstrap-4VJKGVMK.js +2 -0
  213. package/dist/cli/chunks/token-usage-LG3PXRXH.js +25 -0
  214. package/dist/cli/chunks/transformers-GY7SIKEU.js +2 -0
  215. package/dist/cli/chunks/tree-sitter-wasm-parser-FT2KB66N.js +2 -0
  216. package/dist/cli/chunks/types-QJGNBKP2.js +2 -0
  217. package/dist/cli/chunks/unified-memory-XYGENQUT.js +2 -0
  218. package/dist/cli/chunks/unified-memory-hnsw-MVEGQBF3.js +2 -0
  219. package/dist/cli/chunks/unified-persistence-PFRCWEUG.js +2 -0
  220. package/dist/cli/chunks/validate-VQCRSVNQ.js +21 -0
  221. package/dist/cli/chunks/validate-swarm-A5DHAWTP.js +14 -0
  222. package/dist/cli/chunks/vibium-RZBSL4EB.js +2 -0
  223. package/dist/cli/chunks/visual-security-V47BLGJM.js +2 -0
  224. package/dist/cli/chunks/web-tree-sitter-7C4NXEOF.js +2 -0
  225. package/dist/cli/chunks/windsurf-installer-ES3KPQG3.js +7 -0
  226. package/dist/cli/chunks/witness-chain-BR63P4A7.js +2 -0
  227. package/dist/cli/chunks/workflow-JETHX4ML.js +51 -0
  228. package/dist/cli/chunks/workflow-orchestrator-7PZMX3JZ.js +2 -0
  229. package/dist/cli/chunks/wrappers-WP5RH745.js +2 -0
  230. package/dist/cli/commands/daemon.d.ts +13 -0
  231. package/dist/cli/commands/daemon.js +224 -0
  232. package/dist/cli/commands/hooks-handlers/hooks-shared.js +2 -1
  233. package/dist/cli/commands/plugin.d.ts +12 -0
  234. package/dist/cli/commands/plugin.js +135 -0
  235. package/dist/cli/commands/workflow.d.ts +10 -0
  236. package/dist/cli/commands/workflow.js +587 -0
  237. package/dist/cli/handlers/brain-handler.js +13 -8
  238. package/dist/cli/handlers/heartbeat-handler.d.ts +1 -0
  239. package/dist/cli/handlers/heartbeat-handler.js +20 -10
  240. package/dist/cli/handlers/hypergraph-handler.js +3 -3
  241. package/dist/cli/handlers/init-handler.js +10 -9
  242. package/dist/cli/handlers/interfaces.d.ts +4 -4
  243. package/dist/cli/index.js +159 -638
  244. package/dist/cli/lazy-registry.d.ts +27 -0
  245. package/dist/cli/lazy-registry.js +70 -0
  246. package/dist/context/compaction/context-budget.d.ts +71 -0
  247. package/dist/context/compaction/context-budget.js +120 -0
  248. package/dist/context/compaction/index.d.ts +96 -0
  249. package/dist/context/compaction/index.js +259 -0
  250. package/dist/context/compaction/llm-caller-adapter.d.ts +14 -0
  251. package/dist/context/compaction/llm-caller-adapter.js +47 -0
  252. package/dist/context/compaction/tier1-microcompact.d.ts +33 -0
  253. package/dist/context/compaction/tier1-microcompact.js +47 -0
  254. package/dist/context/compaction/tier2-session-summary.d.ts +72 -0
  255. package/dist/context/compaction/tier2-session-summary.js +172 -0
  256. package/dist/context/compaction/tier3-llm-compact.d.ts +65 -0
  257. package/dist/context/compaction/tier3-llm-compact.js +166 -0
  258. package/dist/context/compaction/tier4-reactive.d.ts +54 -0
  259. package/dist/context/compaction/tier4-reactive.js +129 -0
  260. package/dist/coordination/consensus/providers/claude-provider.d.ts +1 -0
  261. package/dist/coordination/consensus/providers/claude-provider.js +23 -3
  262. package/dist/hooks/cross-phase-hooks.d.ts +11 -0
  263. package/dist/hooks/cross-phase-hooks.js +73 -9
  264. package/dist/hooks/security/config-snapshot.d.ts +21 -0
  265. package/dist/hooks/security/config-snapshot.js +33 -0
  266. package/dist/hooks/security/exit-codes.d.ts +28 -0
  267. package/dist/hooks/security/exit-codes.js +33 -0
  268. package/dist/hooks/security/index.d.ts +15 -0
  269. package/dist/hooks/security/index.js +15 -0
  270. package/dist/hooks/security/ssrf-guard.d.ts +25 -0
  271. package/dist/hooks/security/ssrf-guard.js +69 -0
  272. package/dist/kernel/kernel.js +35 -0
  273. package/dist/kernel/memory-backend.js +3 -1
  274. package/dist/mcp/bundle.js +405 -351
  275. package/dist/mcp/entry.js +132 -77
  276. package/dist/mcp/middleware/batch-executor.d.ts +46 -0
  277. package/dist/mcp/middleware/batch-executor.js +150 -0
  278. package/dist/mcp/middleware/microcompact.d.ts +97 -0
  279. package/dist/mcp/middleware/microcompact.js +179 -0
  280. package/dist/mcp/middleware/middleware-chain.d.ts +37 -0
  281. package/dist/mcp/middleware/middleware-chain.js +60 -0
  282. package/dist/mcp/protocol-server.d.ts +11 -0
  283. package/dist/mcp/protocol-server.js +130 -35
  284. package/dist/mcp/services/session-durability-middleware.d.ts +22 -0
  285. package/dist/mcp/services/session-durability-middleware.js +64 -0
  286. package/dist/mcp/services/session-resume.d.ts +29 -0
  287. package/dist/mcp/services/session-resume.js +221 -0
  288. package/dist/mcp/services/session-store.d.ts +84 -0
  289. package/dist/mcp/services/session-store.js +163 -0
  290. package/dist/mcp/tool-registry.d.ts +9 -0
  291. package/dist/mcp/tool-registry.js +30 -1
  292. package/dist/mcp/types.d.ts +1 -0
  293. package/dist/plugins/cache.d.ts +44 -0
  294. package/dist/plugins/cache.js +149 -0
  295. package/dist/plugins/index.d.ts +15 -0
  296. package/dist/plugins/index.js +15 -0
  297. package/dist/plugins/lifecycle.d.ts +67 -0
  298. package/dist/plugins/lifecycle.js +175 -0
  299. package/dist/plugins/manifest.d.ts +45 -0
  300. package/dist/plugins/manifest.js +173 -0
  301. package/dist/plugins/resolver.d.ts +37 -0
  302. package/dist/plugins/resolver.js +80 -0
  303. package/dist/plugins/security.d.ts +23 -0
  304. package/dist/plugins/security.js +125 -0
  305. package/dist/plugins/sources/github.d.ts +17 -0
  306. package/dist/plugins/sources/github.js +77 -0
  307. package/dist/plugins/sources/local.d.ts +20 -0
  308. package/dist/plugins/sources/local.js +32 -0
  309. package/dist/plugins/sources/npm.d.ts +18 -0
  310. package/dist/plugins/sources/npm.js +82 -0
  311. package/dist/shared/llm/retry.d.ts +5 -2
  312. package/dist/shared/llm/retry.js +7 -3
  313. package/dist/shared/prompt-cache-latch.d.ts +41 -0
  314. package/dist/shared/prompt-cache-latch.js +63 -0
  315. package/dist/shared/retry-engine.d.ts +77 -0
  316. package/dist/shared/retry-engine.js +194 -0
  317. package/dist/workers/daemon.d.ts +8 -0
  318. package/dist/workers/daemon.js +13 -0
  319. package/dist/workers/quality-daemon/ci-monitor.d.ts +55 -0
  320. package/dist/workers/quality-daemon/ci-monitor.js +147 -0
  321. package/dist/workers/quality-daemon/coverage-delta.d.ts +72 -0
  322. package/dist/workers/quality-daemon/coverage-delta.js +135 -0
  323. package/dist/workers/quality-daemon/git-watcher.d.ts +51 -0
  324. package/dist/workers/quality-daemon/git-watcher.js +209 -0
  325. package/dist/workers/quality-daemon/index.d.ts +119 -0
  326. package/dist/workers/quality-daemon/index.js +343 -0
  327. package/dist/workers/quality-daemon/nightly-consolidation.d.ts +74 -0
  328. package/dist/workers/quality-daemon/nightly-consolidation.js +136 -0
  329. package/dist/workers/quality-daemon/notification-service.d.ts +67 -0
  330. package/dist/workers/quality-daemon/notification-service.js +178 -0
  331. package/dist/workers/quality-daemon/persistent-memory.d.ts +31 -0
  332. package/dist/workers/quality-daemon/persistent-memory.js +30 -0
  333. package/dist/workers/quality-daemon/priority-queue.d.ts +97 -0
  334. package/dist/workers/quality-daemon/priority-queue.js +126 -0
  335. package/dist/workers/quality-daemon/test-suggester.d.ts +50 -0
  336. package/dist/workers/quality-daemon/test-suggester.js +121 -0
  337. package/dist/workers/worker-manager.js +2 -1
  338. package/package.json +1 -1
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Agentic QE v3 - Tier 4: Reactive Compaction (IMP-08)
3
+ *
4
+ * Last-resort compaction triggered by 413 errors or context overflow
5
+ * detection. Aggressively peels the oldest conversation rounds until
6
+ * the estimated token count drops below the recovery target.
7
+ *
8
+ * This tier is destructive — it drops messages entirely (no summary).
9
+ * It exists to recover from situations where the context window is
10
+ * critically full and the session would otherwise fail.
11
+ */
12
+ import { estimateTokensPadded } from '../../mcp/middleware/microcompact';
13
+ // ============================================================================
14
+ // Defaults
15
+ // ============================================================================
16
+ const DEFAULT_RECOVERY_TARGET = 30_000;
17
+ const DEFAULT_MIN_PRESERVED = 4;
18
+ // ============================================================================
19
+ // Tier4Reactive
20
+ // ============================================================================
21
+ export class Tier4Reactive {
22
+ recoveryTarget;
23
+ minPreserved;
24
+ constructor(options = {}) {
25
+ this.recoveryTarget = options.recoveryTarget ?? DEFAULT_RECOVERY_TARGET;
26
+ this.minPreserved = options.minPreservedMessages ?? DEFAULT_MIN_PRESERVED;
27
+ }
28
+ /**
29
+ * Aggressively peel oldest messages until under the recovery target.
30
+ *
31
+ * Algorithm:
32
+ * 1. Compute total tokens.
33
+ * 2. If already under target, return early.
34
+ * 3. Walk forward from the oldest message, dropping messages until
35
+ * remaining tokens are at or below recoveryTarget.
36
+ * 4. Never drop below minPreservedMessages from the tail.
37
+ * 5. When dropping a tool_result, also drop its paired tool_use (and vice versa).
38
+ */
39
+ compact(messages, trigger = 'context_overflow') {
40
+ if (messages.length === 0) {
41
+ return {
42
+ tier: 4,
43
+ survivingMessages: [],
44
+ survivingTokens: 0,
45
+ droppedCount: 0,
46
+ tokensSaved: 0,
47
+ trigger,
48
+ };
49
+ }
50
+ // Annotate tokens
51
+ const annotated = messages.map(m => ({
52
+ ...m,
53
+ estimatedTokens: m.estimatedTokens ?? estimateTokensPadded(m.content),
54
+ }));
55
+ const totalTokens = annotated.reduce((s, m) => s + m.estimatedTokens, 0);
56
+ // Already under target?
57
+ if (totalTokens <= this.recoveryTarget) {
58
+ return {
59
+ tier: 4,
60
+ survivingMessages: messages,
61
+ survivingTokens: totalTokens,
62
+ droppedCount: 0,
63
+ tokensSaved: 0,
64
+ trigger,
65
+ };
66
+ }
67
+ // Build pair map: toolUseId -> indices of both tool_use and tool_result
68
+ const pairMap = new Map();
69
+ for (let i = 0; i < annotated.length; i++) {
70
+ const m = annotated[i];
71
+ if (m.toolUseId) {
72
+ const existing = pairMap.get(m.toolUseId) ?? [];
73
+ existing.push(i);
74
+ pairMap.set(m.toolUseId, existing);
75
+ }
76
+ }
77
+ // Mark messages for dropping
78
+ const dropped = new Set();
79
+ let remainingTokens = totalTokens;
80
+ // The tail we must preserve
81
+ const preserveFrom = Math.max(0, annotated.length - this.minPreserved);
82
+ for (let i = 0; i < annotated.length; i++) {
83
+ if (remainingTokens <= this.recoveryTarget)
84
+ break;
85
+ if (i >= preserveFrom)
86
+ break; // Don't touch the preserved tail
87
+ if (dropped.has(i))
88
+ continue;
89
+ // Drop this message
90
+ dropped.add(i);
91
+ remainingTokens -= annotated[i].estimatedTokens;
92
+ // If part of a pair, drop the partner too
93
+ if (annotated[i].toolUseId) {
94
+ const partners = pairMap.get(annotated[i].toolUseId) ?? [];
95
+ for (const partnerIdx of partners) {
96
+ if (!dropped.has(partnerIdx) && partnerIdx < preserveFrom) {
97
+ dropped.add(partnerIdx);
98
+ remainingTokens -= annotated[partnerIdx].estimatedTokens;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ const surviving = annotated.filter((_, i) => !dropped.has(i));
104
+ const survivingTokens = surviving.reduce((s, m) => s + m.estimatedTokens, 0);
105
+ return {
106
+ tier: 4,
107
+ survivingMessages: surviving,
108
+ survivingTokens,
109
+ droppedCount: dropped.size,
110
+ tokensSaved: totalTokens - survivingTokens,
111
+ trigger,
112
+ };
113
+ }
114
+ /**
115
+ * Convenience: check if a given HTTP status or error message indicates
116
+ * a context overflow that should trigger reactive compaction.
117
+ */
118
+ static isContextOverflow(statusOrMessage) {
119
+ if (typeof statusOrMessage === 'number') {
120
+ return statusOrMessage === 413;
121
+ }
122
+ const lower = statusOrMessage.toLowerCase();
123
+ return lower.includes('context_length_exceeded')
124
+ || lower.includes('maximum context length')
125
+ || lower.includes('too many tokens')
126
+ || lower.includes('413');
127
+ }
128
+ }
129
+ //# sourceMappingURL=tier4-reactive.js.map
@@ -61,6 +61,7 @@ export declare class ClaudeModelProvider extends BaseModelProvider {
61
61
  private readonly config;
62
62
  private readonly apiKey;
63
63
  private readonly baseUrl;
64
+ private readonly cacheLatch;
64
65
  /**
65
66
  * Create a new Claude provider
66
67
  *
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { toErrorMessage, toError } from '../../../shared/error-utils.js';
11
11
  import { BaseModelProvider, } from '../model-provider';
12
+ import { PromptCacheLatch } from '../../../shared/prompt-cache-latch.js';
12
13
  // ============================================================================
13
14
  // Claude Model Provider Implementation
14
15
  // ============================================================================
@@ -49,6 +50,8 @@ export class ClaudeModelProvider extends BaseModelProvider {
49
50
  config;
50
51
  apiKey;
51
52
  baseUrl;
53
+ // IMP-05: Prompt cache latch — stabilizes API params to maximize cache hits
54
+ cacheLatch = new PromptCacheLatch();
52
55
  /**
53
56
  * Create a new Claude provider
54
57
  *
@@ -87,11 +90,28 @@ export class ClaudeModelProvider extends BaseModelProvider {
87
90
  if (this.disposed) {
88
91
  throw new Error('Provider has been disposed');
89
92
  }
90
- const model = options?.model || this.config.defaultModel;
91
- const maxTokens = options?.maxTokens || 4096;
93
+ const requestedModel = options?.model || this.config.defaultModel;
94
+ const requestedMaxTokens = options?.maxTokens || 4096;
92
95
  const temperature = options?.temperature ?? 0.7;
93
96
  const timeout = options?.timeout || this.config.defaultTimeout;
94
- const systemPrompt = options?.systemPrompt || this.getDefaultSystemPrompt();
97
+ const requestedSystem = options?.systemPrompt || this.getDefaultSystemPrompt();
98
+ // IMP-05: Latch stable params to prevent prompt cache busting.
99
+ // If caller explicitly overrides, reset and re-latch.
100
+ if (this.cacheLatch.has('model') && this.cacheLatch.get('model') !== requestedModel) {
101
+ this.cacheLatch.reset('model');
102
+ }
103
+ if (this.cacheLatch.has('max_tokens') && this.cacheLatch.get('max_tokens') !== requestedMaxTokens) {
104
+ this.cacheLatch.reset('max_tokens');
105
+ }
106
+ if (this.cacheLatch.has('system') && this.cacheLatch.get('system') !== requestedSystem) {
107
+ this.cacheLatch.reset('system');
108
+ }
109
+ this.cacheLatch.latch('model', requestedModel);
110
+ this.cacheLatch.latch('max_tokens', requestedMaxTokens);
111
+ this.cacheLatch.latch('system', requestedSystem);
112
+ const model = this.cacheLatch.get('model');
113
+ const maxTokens = this.cacheLatch.get('max_tokens');
114
+ const systemPrompt = this.cacheLatch.get('system');
95
115
  const request = {
96
116
  model,
97
117
  max_tokens: maxTokens,
@@ -26,6 +26,17 @@ export declare class CrossPhaseHookExecutor {
26
26
  private querySignalsForInjection;
27
27
  formatSignalsForInjection(signals: CrossPhaseSignal[]): string;
28
28
  private getRecommendations;
29
+ /**
30
+ * IMP-07: When AQE_HOOKS_MANAGED_ONLY is set, only hooks whose names start
31
+ * with "managed:" are allowed to execute. All other hooks are filtered out.
32
+ */
33
+ private filterManagedHooks;
34
+ /**
35
+ * IMP-07: SSRF guard — if a target string looks like a URL (has a scheme),
36
+ * validate it against the SSRF blocklist. Returns true when the URL is
37
+ * blocked and the caller should abort the action.
38
+ */
39
+ private isBlockedUrl;
29
40
  private checkConditions;
30
41
  private evaluateCondition;
31
42
  private getValueFromPath;
@@ -11,6 +11,7 @@ import { readFileSync, existsSync } from 'fs';
11
11
  import { join } from 'path';
12
12
  import { parse as parseYaml } from 'yaml';
13
13
  import { getCrossPhaseMemory, } from '../memory/cross-phase-memory.js';
14
+ import { captureHooksConfigSnapshot, validateHookUrl, classifyHookExit, } from './security/index.js';
14
15
  // =============================================================================
15
16
  // Hook Executor
16
17
  // =============================================================================
@@ -27,17 +28,24 @@ export class CrossPhaseHookExecutor {
27
28
  // Initialization
28
29
  // ---------------------------------------------------------------------------
29
30
  async initialize() {
31
+ // IMP-07: Policy flag — globally disable all hook execution
32
+ if (process.env.AQE_HOOKS_DISABLED === 'true') {
33
+ console.log('[CrossPhaseHooks] All hooks disabled via AQE_HOOKS_DISABLED');
34
+ return false;
35
+ }
30
36
  if (!existsSync(this.configPath)) {
31
37
  console.warn(`[CrossPhaseHooks] Config not found: ${this.configPath}`);
32
38
  return false;
33
39
  }
34
40
  try {
35
41
  const content = readFileSync(this.configPath, 'utf-8');
36
- this.config = parseYaml(content);
37
- if (!this.config.enabled) {
42
+ const parsed = parseYaml(content);
43
+ if (!parsed.enabled) {
38
44
  console.log('[CrossPhaseHooks] Hooks disabled in config');
39
45
  return false;
40
46
  }
47
+ // IMP-07: Deep-freeze config so it cannot be mutated at runtime
48
+ this.config = captureHooksConfigSnapshot(parsed);
41
49
  await this.memory.initialize();
42
50
  console.log(`[CrossPhaseHooks] Initialized with ${Object.keys(this.config.hooks).length} hooks`);
43
51
  return true;
@@ -53,8 +61,11 @@ export class CrossPhaseHookExecutor {
53
61
  async onAgentComplete(agentName, result) {
54
62
  if (!this.config)
55
63
  return;
56
- const matchingHooks = Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'agent-complete' &&
57
- hook.trigger.agent === agentName);
64
+ // IMP-07: Runtime kill-switch check
65
+ if (process.env.AQE_HOOKS_DISABLED === 'true')
66
+ return;
67
+ const matchingHooks = this.filterManagedHooks(Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'agent-complete' &&
68
+ hook.trigger.agent === agentName));
58
69
  for (const [hookName, hook] of matchingHooks) {
59
70
  if (this.checkConditions(hook.trigger.conditions, result)) {
60
71
  console.log(`[CrossPhaseHooks] Executing hook: ${hookName}`);
@@ -65,9 +76,12 @@ export class CrossPhaseHookExecutor {
65
76
  async onPhaseStart(phaseName, context = {}) {
66
77
  if (!this.config)
67
78
  return {};
79
+ // IMP-07: Runtime kill-switch check
80
+ if (process.env.AQE_HOOKS_DISABLED === 'true')
81
+ return {};
68
82
  const injectedSignals = {};
69
- const matchingHooks = Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'phase-start' &&
70
- hook.trigger.phase === phaseName);
83
+ const matchingHooks = this.filterManagedHooks(Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'phase-start' &&
84
+ hook.trigger.phase === phaseName));
71
85
  for (const [hookName, hook] of matchingHooks) {
72
86
  console.log(`[CrossPhaseHooks] Executing phase-start hook: ${hookName}`);
73
87
  for (const action of hook.actions) {
@@ -87,8 +101,11 @@ export class CrossPhaseHookExecutor {
87
101
  async onPhaseEnd(phaseName, result) {
88
102
  if (!this.config)
89
103
  return;
90
- const matchingHooks = Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'phase-end' &&
91
- hook.trigger.phase === phaseName);
104
+ // IMP-07: Runtime kill-switch check
105
+ if (process.env.AQE_HOOKS_DISABLED === 'true')
106
+ return;
107
+ const matchingHooks = this.filterManagedHooks(Object.entries(this.config.hooks).filter(([_, hook]) => hook.trigger.event === 'phase-end' &&
108
+ hook.trigger.phase === phaseName));
92
109
  for (const [hookName, hook] of matchingHooks) {
93
110
  console.log(`[CrossPhaseHooks] Executing phase-end hook: ${hookName}`);
94
111
  await this.executeActions(hook.actions, result);
@@ -103,7 +120,19 @@ export class CrossPhaseHookExecutor {
103
120
  await this.executeAction(action, context);
104
121
  }
105
122
  catch (err) {
106
- console.error(`[CrossPhaseHooks] Action failed:`, err);
123
+ // IMP-07: Classify exit codes when error carries one
124
+ const exitCode = err?.exitCode;
125
+ if (typeof exitCode === 'number') {
126
+ const classification = classifyHookExit(exitCode);
127
+ if (classification === 'model_blocking') {
128
+ console.error(`[CrossPhaseHooks] Model-blocking hook failure (exit ${exitCode}):`, err);
129
+ throw err; // Propagate blocking failures
130
+ }
131
+ console.warn(`[CrossPhaseHooks] Hook ${classification} (exit ${exitCode}):`, err);
132
+ }
133
+ else {
134
+ console.error(`[CrossPhaseHooks] Action failed:`, err);
135
+ }
107
136
  }
108
137
  }
109
138
  }
@@ -158,6 +187,9 @@ export class CrossPhaseHookExecutor {
158
187
  async executeNotifyAgent(action, context) {
159
188
  if (!action.target || !action.message)
160
189
  return;
190
+ // IMP-07: SSRF guard — block if target looks like a URL pointing to private IP
191
+ if (await this.isBlockedUrl(action.target))
192
+ return;
161
193
  console.log(`[CrossPhaseHooks] Notify ${action.target}: ${action.message}`);
162
194
  this.emit('agent-notification', {
163
195
  target: action.target,
@@ -169,6 +201,9 @@ export class CrossPhaseHookExecutor {
169
201
  async executeInvokeAgent(action, context) {
170
202
  if (!action.target)
171
203
  return;
204
+ // IMP-07: SSRF guard — block if target looks like a URL pointing to private IP
205
+ if (await this.isBlockedUrl(action.target))
206
+ return;
172
207
  console.log(`[CrossPhaseHooks] Invoke agent: ${action.target}`);
173
208
  this.emit('agent-invocation', {
174
209
  agent: action.target,
@@ -235,6 +270,35 @@ export class CrossPhaseHookExecutor {
235
270
  // ---------------------------------------------------------------------------
236
271
  // Helpers
237
272
  // ---------------------------------------------------------------------------
273
+ /**
274
+ * IMP-07: When AQE_HOOKS_MANAGED_ONLY is set, only hooks whose names start
275
+ * with "managed:" are allowed to execute. All other hooks are filtered out.
276
+ */
277
+ filterManagedHooks(hooks) {
278
+ if (process.env.AQE_HOOKS_MANAGED_ONLY !== 'true')
279
+ return hooks;
280
+ const filtered = hooks.filter(([name]) => name.startsWith('managed:'));
281
+ if (filtered.length < hooks.length) {
282
+ console.log(`[CrossPhaseHooks] AQE_HOOKS_MANAGED_ONLY: filtered ${hooks.length - filtered.length} non-managed hooks`);
283
+ }
284
+ return filtered;
285
+ }
286
+ /**
287
+ * IMP-07: SSRF guard — if a target string looks like a URL (has a scheme),
288
+ * validate it against the SSRF blocklist. Returns true when the URL is
289
+ * blocked and the caller should abort the action.
290
+ */
291
+ async isBlockedUrl(target) {
292
+ // Only validate strings that look like URLs (contain "://")
293
+ if (!target.includes('://'))
294
+ return false;
295
+ const result = await validateHookUrl(target);
296
+ if (!result.safe) {
297
+ console.warn(`[CrossPhaseHooks] SSRF blocked: ${result.reason}`);
298
+ return true;
299
+ }
300
+ return false;
301
+ }
238
302
  checkConditions(conditions, context) {
239
303
  if (!conditions || conditions.length === 0)
240
304
  return true;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Hook Configuration Snapshot
3
+ *
4
+ * Deep-freezes hook configuration at startup so it cannot be mutated
5
+ * at runtime. Uses structuredClone to detach from the original, then
6
+ * recursively freezes every nested object and array.
7
+ *
8
+ * @module hooks/security/config-snapshot
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ /**
12
+ * Deep-freeze an object and all nested objects.
13
+ * Returns a Readonly<T> that throws on mutation attempts.
14
+ */
15
+ export declare function deepFreeze<T extends object>(obj: T): Readonly<T>;
16
+ /**
17
+ * Capture an immutable snapshot of hook configuration.
18
+ * Uses structuredClone to detach from original, then deep-freezes.
19
+ */
20
+ export declare function captureHooksConfigSnapshot<T extends object>(config: T): Readonly<T>;
21
+ //# sourceMappingURL=config-snapshot.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Hook Configuration Snapshot
3
+ *
4
+ * Deep-freezes hook configuration at startup so it cannot be mutated
5
+ * at runtime. Uses structuredClone to detach from the original, then
6
+ * recursively freezes every nested object and array.
7
+ *
8
+ * @module hooks/security/config-snapshot
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ /**
12
+ * Deep-freeze an object and all nested objects.
13
+ * Returns a Readonly<T> that throws on mutation attempts.
14
+ */
15
+ export function deepFreeze(obj) {
16
+ const props = Object.getOwnPropertyNames(obj);
17
+ for (const prop of props) {
18
+ const val = obj[prop];
19
+ if (val && typeof val === 'object' && !Object.isFrozen(val)) {
20
+ deepFreeze(val);
21
+ }
22
+ }
23
+ return Object.freeze(obj);
24
+ }
25
+ /**
26
+ * Capture an immutable snapshot of hook configuration.
27
+ * Uses structuredClone to detach from original, then deep-freezes.
28
+ */
29
+ export function captureHooksConfigSnapshot(config) {
30
+ const snapshot = structuredClone(config);
31
+ return deepFreeze(snapshot);
32
+ }
33
+ //# sourceMappingURL=config-snapshot.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Hook Exit Code Semantics
3
+ *
4
+ * Defines exit-code conventions for hook processes so the runtime
5
+ * can distinguish success, user-visible errors, and model-blocking
6
+ * failures that should halt agent execution.
7
+ *
8
+ * @module hooks/security/exit-codes
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ export declare const HOOK_EXIT_CODES: {
12
+ /** Hook completed successfully. */
13
+ readonly SUCCESS: 0;
14
+ /** Hook failed with user-visible error (non-blocking). */
15
+ readonly USER_VISIBLE: 1;
16
+ /** Hook failed and must block the model from proceeding. */
17
+ readonly MODEL_BLOCKING: 2;
18
+ };
19
+ export type HookExitCode = typeof HOOK_EXIT_CODES[keyof typeof HOOK_EXIT_CODES];
20
+ /**
21
+ * Classify a numeric process exit code into a semantic category.
22
+ *
23
+ * - 0 -> 'success'
24
+ * - 2 -> 'model_blocking' (halts agent execution)
25
+ * - anything else -> 'user_error' (logged, non-blocking)
26
+ */
27
+ export declare function classifyHookExit(code: number): 'success' | 'user_error' | 'model_blocking';
28
+ //# sourceMappingURL=exit-codes.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Hook Exit Code Semantics
3
+ *
4
+ * Defines exit-code conventions for hook processes so the runtime
5
+ * can distinguish success, user-visible errors, and model-blocking
6
+ * failures that should halt agent execution.
7
+ *
8
+ * @module hooks/security/exit-codes
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ export const HOOK_EXIT_CODES = {
12
+ /** Hook completed successfully. */
13
+ SUCCESS: 0,
14
+ /** Hook failed with user-visible error (non-blocking). */
15
+ USER_VISIBLE: 1,
16
+ /** Hook failed and must block the model from proceeding. */
17
+ MODEL_BLOCKING: 2,
18
+ };
19
+ /**
20
+ * Classify a numeric process exit code into a semantic category.
21
+ *
22
+ * - 0 -> 'success'
23
+ * - 2 -> 'model_blocking' (halts agent execution)
24
+ * - anything else -> 'user_error' (logged, non-blocking)
25
+ */
26
+ export function classifyHookExit(code) {
27
+ if (code === 0)
28
+ return 'success';
29
+ if (code === 2)
30
+ return 'model_blocking';
31
+ return 'user_error';
32
+ }
33
+ //# sourceMappingURL=exit-codes.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hook Security Module
3
+ *
4
+ * Re-exports all security primitives for the hook system:
5
+ * - Config snapshot (deep-freeze at startup)
6
+ * - SSRF guard (private IP / DNS rebinding protection)
7
+ * - Exit code semantics (success / user_error / model_blocking)
8
+ *
9
+ * @module hooks/security
10
+ * @see IMP-07 Hook Security Hardening
11
+ */
12
+ export { captureHooksConfigSnapshot, deepFreeze } from './config-snapshot.js';
13
+ export { validateHookUrl, isPrivateIp, type SsrfValidationResult } from './ssrf-guard.js';
14
+ export { HOOK_EXIT_CODES, classifyHookExit, type HookExitCode } from './exit-codes.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hook Security Module
3
+ *
4
+ * Re-exports all security primitives for the hook system:
5
+ * - Config snapshot (deep-freeze at startup)
6
+ * - SSRF guard (private IP / DNS rebinding protection)
7
+ * - Exit code semantics (success / user_error / model_blocking)
8
+ *
9
+ * @module hooks/security
10
+ * @see IMP-07 Hook Security Hardening
11
+ */
12
+ export { captureHooksConfigSnapshot, deepFreeze } from './config-snapshot.js';
13
+ export { validateHookUrl, isPrivateIp } from './ssrf-guard.js';
14
+ export { HOOK_EXIT_CODES, classifyHookExit } from './exit-codes.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * SSRF Guard for Hook URLs
3
+ *
4
+ * Blocks hooks from hitting private/internal IP ranges.
5
+ * Validates both direct IP addresses and DNS-resolved addresses
6
+ * to prevent DNS rebinding attacks.
7
+ *
8
+ * @module hooks/security/ssrf-guard
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ export interface SsrfValidationResult {
12
+ safe: boolean;
13
+ reason?: string;
14
+ }
15
+ /**
16
+ * Check if an IP address is in a private/reserved range.
17
+ */
18
+ export declare function isPrivateIp(ip: string): boolean;
19
+ /**
20
+ * Validate a hook URL for SSRF safety.
21
+ * Blocks private IPs both as direct addresses and via DNS resolution.
22
+ * Disabled via AQE_HOOKS_SSRF_DISABLED=true (dev mode only).
23
+ */
24
+ export declare function validateHookUrl(url: string): Promise<SsrfValidationResult>;
25
+ //# sourceMappingURL=ssrf-guard.d.ts.map
@@ -0,0 +1,69 @@
1
+ /**
2
+ * SSRF Guard for Hook URLs
3
+ *
4
+ * Blocks hooks from hitting private/internal IP ranges.
5
+ * Validates both direct IP addresses and DNS-resolved addresses
6
+ * to prevent DNS rebinding attacks.
7
+ *
8
+ * @module hooks/security/ssrf-guard
9
+ * @see IMP-07 Hook Security Hardening
10
+ */
11
+ import { isIP } from 'net';
12
+ import { lookup } from 'dns/promises';
13
+ const PRIVATE_RANGES = [
14
+ /^10\./,
15
+ /^172\.(1[6-9]|2\d|3[01])\./,
16
+ /^192\.168\./,
17
+ /^127\./,
18
+ /^0\./,
19
+ /^169\.254\./,
20
+ /^::1$/,
21
+ /^fc00:/,
22
+ /^fe80:/,
23
+ /^fd[0-9a-f]{2}:/i,
24
+ ];
25
+ /**
26
+ * Check if an IP address is in a private/reserved range.
27
+ */
28
+ export function isPrivateIp(ip) {
29
+ return PRIVATE_RANGES.some(r => r.test(ip));
30
+ }
31
+ /**
32
+ * Validate a hook URL for SSRF safety.
33
+ * Blocks private IPs both as direct addresses and via DNS resolution.
34
+ * Disabled via AQE_HOOKS_SSRF_DISABLED=true (dev mode only).
35
+ */
36
+ export async function validateHookUrl(url) {
37
+ if (process.env.AQE_HOOKS_SSRF_DISABLED === 'true') {
38
+ return { safe: true };
39
+ }
40
+ let parsed;
41
+ try {
42
+ parsed = new URL(url);
43
+ }
44
+ catch {
45
+ return { safe: false, reason: `Invalid URL: ${url}` };
46
+ }
47
+ // Strip IPv6 brackets — URL.hostname wraps IPv6 as "[::1]" but
48
+ // isIP() and our regex patterns expect the bare address "::1".
49
+ const hostname = parsed.hostname.replace(/^\[|\]$/g, '');
50
+ // Direct IP check
51
+ if (isIP(hostname)) {
52
+ if (isPrivateIp(hostname)) {
53
+ return { safe: false, reason: `Private IP blocked: ${hostname}` };
54
+ }
55
+ return { safe: true };
56
+ }
57
+ // DNS resolution check (prevents DNS rebinding)
58
+ try {
59
+ const resolved = await lookup(hostname);
60
+ if (isPrivateIp(resolved.address)) {
61
+ return { safe: false, reason: `DNS resolves to private IP: ${resolved.address}` };
62
+ }
63
+ }
64
+ catch (err) {
65
+ return { safe: false, reason: `DNS lookup failed for ${hostname}: ${err.message}` };
66
+ }
67
+ return { safe: true };
68
+ }
69
+ //# sourceMappingURL=ssrf-guard.js.map
@@ -15,6 +15,8 @@ import { findProjectRoot } from './unified-memory.js';
15
15
  import { initializeUnifiedPersistence } from './unified-persistence.js';
16
16
  import * as path from 'path';
17
17
  import * as fs from 'fs';
18
+ import { PluginLifecycleManager } from '../plugins/lifecycle';
19
+ import { PluginCache } from '../plugins/cache';
18
20
  // Import domain plugin factories
19
21
  import { createTestGenerationPlugin } from '../domains/test-generation/plugin';
20
22
  import { createTestExecutionPlugin } from '../domains/test-execution/plugin';
@@ -149,6 +151,39 @@ export class QEKernelImpl {
149
151
  agentId: 'qe-kernel',
150
152
  });
151
153
  this._eventBus.registerMiddleware(antiDriftMiddleware);
154
+ // IMP-09: Discover and register external plugins from cache
155
+ try {
156
+ const pluginCacheDir = path.join(dataDir, 'plugins');
157
+ const pluginCache = new PluginCache({ cacheDir: pluginCacheDir });
158
+ const pluginLifecycle = new PluginLifecycleManager({ cache: pluginCache });
159
+ const resolution = pluginLifecycle.resolveLoadOrder();
160
+ for (const resolved of resolution.ordered) {
161
+ const manifest = resolved.manifest;
162
+ const cachedPlugin = pluginCache.get(manifest.name, manifest.version);
163
+ if (!cachedPlugin)
164
+ continue;
165
+ const entryPointPath = path.join(cachedPlugin.path, manifest.entryPoint);
166
+ // Register a factory for each domain the plugin provides
167
+ for (const domain of manifest.domains) {
168
+ const domainName = domain;
169
+ if (DOMAIN_FACTORIES[domainName])
170
+ continue; // don't override built-in domains
171
+ const loader = this._plugins;
172
+ loader.registerFactory(domainName, async (eventBus, memory) => {
173
+ // Dynamically import the plugin entry point at load time
174
+ const pluginModule = await import(entryPointPath);
175
+ const createPlugin = pluginModule.default ?? pluginModule.createPlugin;
176
+ if (typeof createPlugin !== 'function') {
177
+ throw new Error(`Plugin "${manifest.name}" entry point must export a default function or "createPlugin" function`);
178
+ }
179
+ return createPlugin(eventBus, memory, this._coordinator);
180
+ });
181
+ }
182
+ }
183
+ }
184
+ catch {
185
+ // External plugin loading is best-effort — don't block kernel startup
186
+ }
152
187
  // Load plugins based on configuration
153
188
  if (!this._config.lazyLoading) {
154
189
  await this._plugins.loadAll();
@@ -56,7 +56,9 @@ export class InMemoryBackend {
56
56
  return value !== undefined;
57
57
  }
58
58
  async search(pattern, limit = MEMORY_CONSTANTS.DEFAULT_SEARCH_LIMIT) {
59
- const regex = new RegExp(pattern.replace(/\*/g, '.*'));
59
+ // Escape regex-special chars first, then convert glob wildcards to regex
60
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
61
+ const regex = new RegExp(escaped.replace(/\*/g, '.*'));
60
62
  const results = [];
61
63
  for (const key of this.store.keys()) {
62
64
  if (regex.test(key)) {