@claude-flow/cli 3.32.3 → 3.32.4

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 (683) hide show
  1. package/.claude/helpers/helpers.manifest.json +2 -2
  2. package/catalog-manifest.json +2 -2
  3. package/dist/src/agenticow/speculative-exploration.d.ts +148 -0
  4. package/dist/src/agenticow/speculative-exploration.js +218 -0
  5. package/dist/src/appliance/gguf-engine.d.ts +91 -0
  6. package/dist/src/appliance/gguf-engine.js +425 -0
  7. package/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
  8. package/dist/src/appliance/ruvllm-bridge.js +292 -0
  9. package/dist/src/appliance/rvfa-builder.d.ts +44 -0
  10. package/dist/src/appliance/rvfa-builder.js +329 -0
  11. package/dist/src/appliance/rvfa-distribution.d.ts +97 -0
  12. package/dist/src/appliance/rvfa-distribution.js +370 -0
  13. package/dist/src/appliance/rvfa-format.d.ts +111 -0
  14. package/dist/src/appliance/rvfa-format.js +393 -0
  15. package/dist/src/appliance/rvfa-runner.d.ts +69 -0
  16. package/dist/src/appliance/rvfa-runner.js +237 -0
  17. package/dist/src/appliance/rvfa-signing.d.ts +123 -0
  18. package/dist/src/appliance/rvfa-signing.js +347 -0
  19. package/dist/src/auth/client.d.ts +89 -0
  20. package/dist/src/auth/client.js +242 -0
  21. package/dist/src/auth/constants.d.ts +7 -0
  22. package/dist/src/auth/constants.js +7 -0
  23. package/dist/src/auth/scopes.d.ts +14 -0
  24. package/dist/src/auth/scopes.js +21 -0
  25. package/dist/src/auth/security-bridge.d.ts +36 -0
  26. package/dist/src/auth/security-bridge.js +42 -0
  27. package/dist/src/auth/session.d.ts +20 -0
  28. package/dist/src/auth/session.js +32 -0
  29. package/dist/src/auth/state.d.ts +19 -0
  30. package/dist/src/auth/state.js +53 -0
  31. package/dist/src/auth/types.d.ts +27 -0
  32. package/dist/src/auth/types.js +11 -0
  33. package/dist/src/autopilot-state.d.ts +77 -0
  34. package/dist/src/autopilot-state.js +271 -0
  35. package/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts +18 -0
  36. package/dist/src/benchmarks/gaia-agent-planning.smoke.js +253 -0
  37. package/dist/src/benchmarks/gaia-agent.d.ts +198 -0
  38. package/dist/src/benchmarks/gaia-agent.js +651 -0
  39. package/dist/src/benchmarks/gaia-causal-memory.d.ts +133 -0
  40. package/dist/src/benchmarks/gaia-causal-memory.js +281 -0
  41. package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +22 -0
  42. package/dist/src/benchmarks/gaia-causal-memory.smoke.js +300 -0
  43. package/dist/src/benchmarks/gaia-convergence.d.ts +138 -0
  44. package/dist/src/benchmarks/gaia-convergence.js +260 -0
  45. package/dist/src/benchmarks/gaia-convergence.smoke.d.ts +19 -0
  46. package/dist/src/benchmarks/gaia-convergence.smoke.js +246 -0
  47. package/dist/src/benchmarks/gaia-critic.d.ts +123 -0
  48. package/dist/src/benchmarks/gaia-critic.js +312 -0
  49. package/dist/src/benchmarks/gaia-critic.smoke.d.ts +21 -0
  50. package/dist/src/benchmarks/gaia-critic.smoke.js +327 -0
  51. package/dist/src/benchmarks/gaia-decomposer.d.ts +125 -0
  52. package/dist/src/benchmarks/gaia-decomposer.js +350 -0
  53. package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +21 -0
  54. package/dist/src/benchmarks/gaia-decomposer.smoke.js +228 -0
  55. package/dist/src/benchmarks/gaia-e2e-smoke.d.ts +27 -0
  56. package/dist/src/benchmarks/gaia-e2e-smoke.js +136 -0
  57. package/dist/src/benchmarks/gaia-extract.smoke.d.ts +45 -0
  58. package/dist/src/benchmarks/gaia-extract.smoke.js +242 -0
  59. package/dist/src/benchmarks/gaia-hardness/features.d.ts +46 -0
  60. package/dist/src/benchmarks/gaia-hardness/features.js +170 -0
  61. package/dist/src/benchmarks/gaia-hardness/predictor.d.ts +105 -0
  62. package/dist/src/benchmarks/gaia-hardness/predictor.js +260 -0
  63. package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +20 -0
  64. package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +235 -0
  65. package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +51 -0
  66. package/dist/src/benchmarks/gaia-hardness/train-data-loader.js +179 -0
  67. package/dist/src/benchmarks/gaia-judge.d.ts +88 -0
  68. package/dist/src/benchmarks/gaia-judge.js +437 -0
  69. package/dist/src/benchmarks/gaia-loader.d.ts +87 -0
  70. package/dist/src/benchmarks/gaia-loader.js +326 -0
  71. package/dist/src/benchmarks/gaia-tools/file_read.d.ts +35 -0
  72. package/dist/src/benchmarks/gaia-tools/file_read.js +403 -0
  73. package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +126 -0
  74. package/dist/src/benchmarks/gaia-tools/grounded_query.js +225 -0
  75. package/dist/src/benchmarks/gaia-tools/index.d.ts +32 -0
  76. package/dist/src/benchmarks/gaia-tools/index.js +36 -0
  77. package/dist/src/benchmarks/gaia-tools/types.d.ts +62 -0
  78. package/dist/src/benchmarks/gaia-tools/types.js +12 -0
  79. package/dist/src/benchmarks/gaia-tools/web_search.d.ts +30 -0
  80. package/dist/src/benchmarks/gaia-tools/web_search.js +210 -0
  81. package/dist/src/benchmarks/gaia-voting.d.ts +88 -0
  82. package/dist/src/benchmarks/gaia-voting.js +297 -0
  83. package/dist/src/benchmarks/gaia-voting.smoke.d.ts +20 -0
  84. package/dist/src/benchmarks/gaia-voting.smoke.js +332 -0
  85. package/dist/src/benchmarks/pretrain/index.d.ts +58 -0
  86. package/dist/src/benchmarks/pretrain/index.js +404 -0
  87. package/dist/src/business-pods/bbs-budget-tracker.d.ts +139 -0
  88. package/dist/src/business-pods/bbs-budget-tracker.js +358 -0
  89. package/dist/src/business-pods/domain-affinity-policy.d.ts +47 -0
  90. package/dist/src/business-pods/domain-affinity-policy.js +65 -0
  91. package/dist/src/business-pods/pod-schema.d.ts +96 -0
  92. package/dist/src/business-pods/pod-schema.js +225 -0
  93. package/dist/src/commands/advisor.d.ts +15 -0
  94. package/dist/src/commands/advisor.js +94 -0
  95. package/dist/src/commands/agent-wasm.d.ts +14 -0
  96. package/dist/src/commands/agent-wasm.js +333 -0
  97. package/dist/src/commands/agent.d.ts +8 -0
  98. package/dist/src/commands/agent.js +927 -0
  99. package/dist/src/commands/analyze.d.ts +19 -0
  100. package/dist/src/commands/analyze.js +2047 -0
  101. package/dist/src/commands/announcements.d.ts +17 -0
  102. package/dist/src/commands/announcements.js +0 -0
  103. package/dist/src/commands/appliance-advanced.d.ts +9 -0
  104. package/dist/src/commands/appliance-advanced.js +215 -0
  105. package/dist/src/commands/appliance.d.ts +8 -0
  106. package/dist/src/commands/appliance.js +404 -0
  107. package/dist/src/commands/auth.d.ts +15 -0
  108. package/dist/src/commands/auth.js +244 -0
  109. package/dist/src/commands/autopilot.d.ts +15 -0
  110. package/dist/src/commands/autopilot.js +407 -0
  111. package/dist/src/commands/benchmark.d.ts +10 -0
  112. package/dist/src/commands/benchmark.js +460 -0
  113. package/dist/src/commands/claims.d.ts +10 -0
  114. package/dist/src/commands/claims.js +620 -0
  115. package/dist/src/commands/cleanup.d.ts +13 -0
  116. package/dist/src/commands/cleanup.js +250 -0
  117. package/dist/src/commands/completions.d.ts +10 -0
  118. package/dist/src/commands/completions.js +539 -0
  119. package/dist/src/commands/config.d.ts +8 -0
  120. package/dist/src/commands/config.js +428 -0
  121. package/dist/src/commands/daemon.d.ts +59 -0
  122. package/dist/src/commands/daemon.js +1733 -0
  123. package/dist/src/commands/deployment.d.ts +10 -0
  124. package/dist/src/commands/deployment.js +672 -0
  125. package/dist/src/commands/doctor.d.ts +10 -0
  126. package/dist/src/commands/doctor.js +1902 -0
  127. package/dist/src/commands/eject.d.ts +33 -0
  128. package/dist/src/commands/eject.js +195 -0
  129. package/dist/src/commands/embeddings.d.ts +18 -0
  130. package/dist/src/commands/embeddings.js +1623 -0
  131. package/dist/src/commands/funnel.d.ts +18 -0
  132. package/dist/src/commands/funnel.js +302 -0
  133. package/dist/src/commands/gaia-bench.d.ts +40 -0
  134. package/dist/src/commands/gaia-bench.js +597 -0
  135. package/dist/src/commands/guidance.d.ts +8 -0
  136. package/dist/src/commands/guidance.js +556 -0
  137. package/dist/src/commands/hive-mind.d.ts +11 -0
  138. package/dist/src/commands/hive-mind.js +1319 -0
  139. package/dist/src/commands/hooks.d.ts +8 -0
  140. package/dist/src/commands/hooks.js +4606 -0
  141. package/dist/src/commands/index.d.ts +118 -0
  142. package/dist/src/commands/index.js +366 -0
  143. package/dist/src/commands/init.d.ts +13 -0
  144. package/dist/src/commands/init.js +1297 -0
  145. package/dist/src/commands/issues.d.ts +21 -0
  146. package/dist/src/commands/issues.js +567 -0
  147. package/dist/src/commands/mcp.d.ts +11 -0
  148. package/dist/src/commands/mcp.js +732 -0
  149. package/dist/src/commands/memory-backup.d.ts +11 -0
  150. package/dist/src/commands/memory-backup.js +46 -0
  151. package/dist/src/commands/memory-distill.d.ts +27 -0
  152. package/dist/src/commands/memory-distill.js +374 -0
  153. package/dist/src/commands/memory.d.ts +8 -0
  154. package/dist/src/commands/memory.js +1596 -0
  155. package/dist/src/commands/metaharness.d.ts +39 -0
  156. package/dist/src/commands/metaharness.js +215 -0
  157. package/dist/src/commands/migrate.d.ts +8 -0
  158. package/dist/src/commands/migrate.js +742 -0
  159. package/dist/src/commands/neural.d.ts +10 -0
  160. package/dist/src/commands/neural.js +4331 -0
  161. package/dist/src/commands/performance.d.ts +10 -0
  162. package/dist/src/commands/performance.js +583 -0
  163. package/dist/src/commands/plugins.d.ts +11 -0
  164. package/dist/src/commands/plugins.js +826 -0
  165. package/dist/src/commands/process.d.ts +10 -0
  166. package/dist/src/commands/process.js +694 -0
  167. package/dist/src/commands/progress.d.ts +11 -0
  168. package/dist/src/commands/progress.js +259 -0
  169. package/dist/src/commands/providers.d.ts +10 -0
  170. package/dist/src/commands/providers.js +502 -0
  171. package/dist/src/commands/proxy-lifecycle.d.ts +12 -0
  172. package/dist/src/commands/proxy-lifecycle.js +232 -0
  173. package/dist/src/commands/proxy.d.ts +21 -0
  174. package/dist/src/commands/proxy.js +398 -0
  175. package/dist/src/commands/route.d.ts +16 -0
  176. package/dist/src/commands/route.js +822 -0
  177. package/dist/src/commands/ruvector/backup.d.ts +11 -0
  178. package/dist/src/commands/ruvector/backup.js +747 -0
  179. package/dist/src/commands/ruvector/benchmark.d.ts +11 -0
  180. package/dist/src/commands/ruvector/benchmark.js +490 -0
  181. package/dist/src/commands/ruvector/import.d.ts +18 -0
  182. package/dist/src/commands/ruvector/import.js +373 -0
  183. package/dist/src/commands/ruvector/index.d.ts +29 -0
  184. package/dist/src/commands/ruvector/index.js +129 -0
  185. package/dist/src/commands/ruvector/init.d.ts +11 -0
  186. package/dist/src/commands/ruvector/init.js +467 -0
  187. package/dist/src/commands/ruvector/migrate.d.ts +11 -0
  188. package/dist/src/commands/ruvector/migrate.js +498 -0
  189. package/dist/src/commands/ruvector/optimize.d.ts +11 -0
  190. package/dist/src/commands/ruvector/optimize.js +505 -0
  191. package/dist/src/commands/ruvector/pg-utils.d.ts +14 -0
  192. package/dist/src/commands/ruvector/pg-utils.js +41 -0
  193. package/dist/src/commands/ruvector/setup.d.ts +18 -0
  194. package/dist/src/commands/ruvector/setup.js +765 -0
  195. package/dist/src/commands/ruvector/status.d.ts +11 -0
  196. package/dist/src/commands/ruvector/status.js +479 -0
  197. package/dist/src/commands/security.d.ts +10 -0
  198. package/dist/src/commands/security.js +1012 -0
  199. package/dist/src/commands/session.d.ts +8 -0
  200. package/dist/src/commands/session.js +757 -0
  201. package/dist/src/commands/settings.d.ts +19 -0
  202. package/dist/src/commands/settings.js +180 -0
  203. package/dist/src/commands/spinner.d.ts +16 -0
  204. package/dist/src/commands/spinner.js +329 -0
  205. package/dist/src/commands/start.d.ts +8 -0
  206. package/dist/src/commands/start.js +418 -0
  207. package/dist/src/commands/status.d.ts +8 -0
  208. package/dist/src/commands/status.js +608 -0
  209. package/dist/src/commands/swarm.d.ts +8 -0
  210. package/dist/src/commands/swarm.js +891 -0
  211. package/dist/src/commands/task.d.ts +8 -0
  212. package/dist/src/commands/task.js +675 -0
  213. package/dist/src/commands/transfer-store.d.ts +13 -0
  214. package/dist/src/commands/transfer-store.js +428 -0
  215. package/dist/src/commands/update.d.ts +8 -0
  216. package/dist/src/commands/update.js +276 -0
  217. package/dist/src/commands/verify.d.ts +19 -0
  218. package/dist/src/commands/verify.js +261 -0
  219. package/dist/src/commands/version.d.ts +42 -0
  220. package/dist/src/commands/version.js +106 -0
  221. package/dist/src/commands/workflow.d.ts +8 -0
  222. package/dist/src/commands/workflow.js +617 -0
  223. package/dist/src/config/harness-feedback-applier.d.ts +50 -0
  224. package/dist/src/config/harness-feedback-applier.js +122 -0
  225. package/dist/src/config/proven-config-refresh.d.ts +39 -0
  226. package/dist/src/config/proven-config-refresh.js +154 -0
  227. package/dist/src/config/proven-config-rvfa.d.ts +23 -0
  228. package/dist/src/config/proven-config-rvfa.js +73 -0
  229. package/dist/src/config/proven-config.d.ts +86 -0
  230. package/dist/src/config/proven-config.js +176 -0
  231. package/dist/src/config-adapter.d.ts +15 -0
  232. package/dist/src/config-adapter.js +186 -0
  233. package/dist/src/encryption/vault.d.ts +94 -0
  234. package/dist/src/encryption/vault.js +172 -0
  235. package/dist/src/fs-secure.d.ts +86 -0
  236. package/dist/src/fs-secure.js +133 -0
  237. package/dist/src/funnel/advisor-tip.d.ts +58 -0
  238. package/dist/src/funnel/advisor-tip.js +92 -0
  239. package/dist/src/funnel/attribution.d.ts +37 -0
  240. package/dist/src/funnel/attribution.js +101 -0
  241. package/dist/src/funnel/consent.d.ts +22 -0
  242. package/dist/src/funnel/consent.js +58 -0
  243. package/dist/src/funnel/credit-errors.d.ts +31 -0
  244. package/dist/src/funnel/credit-errors.js +88 -0
  245. package/dist/src/funnel/credit-notifier.d.ts +44 -0
  246. package/dist/src/funnel/credit-notifier.js +74 -0
  247. package/dist/src/funnel/disclosure.d.ts +47 -0
  248. package/dist/src/funnel/disclosure.js +109 -0
  249. package/dist/src/funnel/enrollment.d.ts +36 -0
  250. package/dist/src/funnel/enrollment.js +64 -0
  251. package/dist/src/funnel/environment.d.ts +17 -0
  252. package/dist/src/funnel/environment.js +39 -0
  253. package/dist/src/funnel/event-transport.d.ts +51 -0
  254. package/dist/src/funnel/event-transport.js +199 -0
  255. package/dist/src/funnel/events.d.ts +42 -0
  256. package/dist/src/funnel/events.js +150 -0
  257. package/dist/src/funnel/index.d.ts +21 -0
  258. package/dist/src/funnel/index.js +21 -0
  259. package/dist/src/funnel/insights.d.ts +50 -0
  260. package/dist/src/funnel/insights.js +120 -0
  261. package/dist/src/funnel/local-signals.d.ts +20 -0
  262. package/dist/src/funnel/local-signals.js +77 -0
  263. package/dist/src/funnel/message-transport.d.ts +51 -0
  264. package/dist/src/funnel/message-transport.js +149 -0
  265. package/dist/src/funnel/messages.d.ts +55 -0
  266. package/dist/src/funnel/messages.js +160 -0
  267. package/dist/src/funnel/payout.d.ts +40 -0
  268. package/dist/src/funnel/payout.js +60 -0
  269. package/dist/src/funnel/power-saver-notifier.d.ts +44 -0
  270. package/dist/src/funnel/power-saver-notifier.js +92 -0
  271. package/dist/src/funnel/precedence.d.ts +16 -0
  272. package/dist/src/funnel/precedence.js +85 -0
  273. package/dist/src/funnel/promo.d.ts +41 -0
  274. package/dist/src/funnel/promo.js +144 -0
  275. package/dist/src/funnel/rate-limit-notifier.d.ts +55 -0
  276. package/dist/src/funnel/rate-limit-notifier.js +102 -0
  277. package/dist/src/funnel/rotation.d.ts +19 -0
  278. package/dist/src/funnel/rotation.js +70 -0
  279. package/dist/src/funnel/state.d.ts +13 -0
  280. package/dist/src/funnel/state.js +52 -0
  281. package/dist/src/funnel/toggle-cooldown.d.ts +17 -0
  282. package/dist/src/funnel/toggle-cooldown.js +32 -0
  283. package/dist/src/funnel/types.d.ts +98 -0
  284. package/dist/src/funnel/types.js +26 -0
  285. package/dist/src/index.d.ts +81 -0
  286. package/dist/src/index.js +609 -0
  287. package/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
  288. package/dist/src/infrastructure/in-memory-repositories.js +264 -0
  289. package/dist/src/init/claudemd-generator.d.ts +16 -0
  290. package/dist/src/init/claudemd-generator.js +368 -0
  291. package/dist/src/init/executor.d.ts +41 -0
  292. package/dist/src/init/executor.js +2142 -0
  293. package/dist/src/init/helper-refresh.d.ts +79 -0
  294. package/dist/src/init/helper-refresh.js +347 -0
  295. package/dist/src/init/helper-signing.d.ts +37 -0
  296. package/dist/src/init/helper-signing.js +67 -0
  297. package/dist/src/init/helpers-generator.d.ts +87 -0
  298. package/dist/src/init/helpers-generator.js +1456 -0
  299. package/dist/src/init/index.d.ts +13 -0
  300. package/dist/src/init/index.js +15 -0
  301. package/dist/src/init/mcp-generator.d.ts +26 -0
  302. package/dist/src/init/mcp-generator.js +126 -0
  303. package/dist/src/init/memory-package-resolver.d.ts +53 -0
  304. package/dist/src/init/memory-package-resolver.js +118 -0
  305. package/dist/src/init/settings-generator.d.ts +14 -0
  306. package/dist/src/init/settings-generator.js +462 -0
  307. package/dist/src/init/statusline-generator.d.ts +28 -0
  308. package/dist/src/init/statusline-generator.js +177 -0
  309. package/dist/src/init/types.d.ts +331 -0
  310. package/dist/src/init/types.js +276 -0
  311. package/dist/src/log-filters.d.ts +46 -0
  312. package/dist/src/log-filters.js +107 -0
  313. package/dist/src/mcp-client.d.ts +92 -0
  314. package/dist/src/mcp-client.js +397 -0
  315. package/dist/src/mcp-server.d.ts +163 -0
  316. package/dist/src/mcp-server.js +751 -0
  317. package/dist/src/mcp-tools/agent-execute-core.d.ts +115 -0
  318. package/dist/src/mcp-tools/agent-execute-core.js +587 -0
  319. package/dist/src/mcp-tools/agent-tools.d.ts +9 -0
  320. package/dist/src/mcp-tools/agent-tools.js +837 -0
  321. package/dist/src/mcp-tools/agentbbs-tools.d.ts +28 -0
  322. package/dist/src/mcp-tools/agentbbs-tools.js +394 -0
  323. package/dist/src/mcp-tools/agentdb-tools.d.ts +35 -0
  324. package/dist/src/mcp-tools/agentdb-tools.js +1473 -0
  325. package/dist/src/mcp-tools/agenticow-loader.d.ts +59 -0
  326. package/dist/src/mcp-tools/agenticow-loader.js +105 -0
  327. package/dist/src/mcp-tools/agenticow-speculate-tools.d.ts +24 -0
  328. package/dist/src/mcp-tools/agenticow-speculate-tools.js +209 -0
  329. package/dist/src/mcp-tools/agenticow-tools.d.ts +36 -0
  330. package/dist/src/mcp-tools/agenticow-tools.js +360 -0
  331. package/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
  332. package/dist/src/mcp-tools/analyze-tools.js +346 -0
  333. package/dist/src/mcp-tools/auto-install.d.ts +83 -0
  334. package/dist/src/mcp-tools/auto-install.js +131 -0
  335. package/dist/src/mcp-tools/autopilot-tools.d.ts +12 -0
  336. package/dist/src/mcp-tools/autopilot-tools.js +231 -0
  337. package/dist/src/mcp-tools/browser-intent-tools.d.ts +162 -0
  338. package/dist/src/mcp-tools/browser-intent-tools.js +548 -0
  339. package/dist/src/mcp-tools/browser-session-tools.d.ts +27 -0
  340. package/dist/src/mcp-tools/browser-session-tools.js +398 -0
  341. package/dist/src/mcp-tools/browser-tools.d.ts +21 -0
  342. package/dist/src/mcp-tools/browser-tools.js +760 -0
  343. package/dist/src/mcp-tools/business-pod-tools.d.ts +20 -0
  344. package/dist/src/mcp-tools/business-pod-tools.js +169 -0
  345. package/dist/src/mcp-tools/claims-tools.d.ts +12 -0
  346. package/dist/src/mcp-tools/claims-tools.js +863 -0
  347. package/dist/src/mcp-tools/config-tools.d.ts +8 -0
  348. package/dist/src/mcp-tools/config-tools.js +411 -0
  349. package/dist/src/mcp-tools/coordination-tools.d.ts +13 -0
  350. package/dist/src/mcp-tools/coordination-tools.js +729 -0
  351. package/dist/src/mcp-tools/daa-tools.d.ts +13 -0
  352. package/dist/src/mcp-tools/daa-tools.js +534 -0
  353. package/dist/src/mcp-tools/embeddings-tools.d.ts +9 -0
  354. package/dist/src/mcp-tools/embeddings-tools.js +904 -0
  355. package/dist/src/mcp-tools/github-tools.d.ts +9 -0
  356. package/dist/src/mcp-tools/github-tools.js +659 -0
  357. package/dist/src/mcp-tools/guidance-tools.d.ts +15 -0
  358. package/dist/src/mcp-tools/guidance-tools.js +639 -0
  359. package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
  360. package/dist/src/mcp-tools/hive-mind-tools.js +953 -0
  361. package/dist/src/mcp-tools/hooks-tools.d.ts +65 -0
  362. package/dist/src/mcp-tools/hooks-tools.js +4836 -0
  363. package/dist/src/mcp-tools/http-fetch-tools.d.ts +55 -0
  364. package/dist/src/mcp-tools/http-fetch-tools.js +329 -0
  365. package/dist/src/mcp-tools/index.d.ts +34 -0
  366. package/dist/src/mcp-tools/index.js +40 -0
  367. package/dist/src/mcp-tools/managed-agent-tools.d.ts +22 -0
  368. package/dist/src/mcp-tools/managed-agent-tools.js +357 -0
  369. package/dist/src/mcp-tools/memory-tools.d.ts +14 -0
  370. package/dist/src/mcp-tools/memory-tools.js +1330 -0
  371. package/dist/src/mcp-tools/metaharness-tools.d.ts +51 -0
  372. package/dist/src/mcp-tools/metaharness-tools.js +684 -0
  373. package/dist/src/mcp-tools/neural-tools.d.ts +54 -0
  374. package/dist/src/mcp-tools/neural-tools.js +1168 -0
  375. package/dist/src/mcp-tools/performance-tools.d.ts +16 -0
  376. package/dist/src/mcp-tools/performance-tools.js +675 -0
  377. package/dist/src/mcp-tools/progress-tools.d.ts +14 -0
  378. package/dist/src/mcp-tools/progress-tools.js +348 -0
  379. package/dist/src/mcp-tools/request-tracker.d.ts +17 -0
  380. package/dist/src/mcp-tools/request-tracker.js +27 -0
  381. package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
  382. package/dist/src/mcp-tools/ruvllm-tools.js +355 -0
  383. package/dist/src/mcp-tools/security-tools.d.ts +18 -0
  384. package/dist/src/mcp-tools/security-tools.js +556 -0
  385. package/dist/src/mcp-tools/session-tools.d.ts +8 -0
  386. package/dist/src/mcp-tools/session-tools.js +517 -0
  387. package/dist/src/mcp-tools/swarm-tools.d.ts +37 -0
  388. package/dist/src/mcp-tools/swarm-tools.js +390 -0
  389. package/dist/src/mcp-tools/system-tools.d.ts +13 -0
  390. package/dist/src/mcp-tools/system-tools.js +688 -0
  391. package/dist/src/mcp-tools/task-tools.d.ts +8 -0
  392. package/dist/src/mcp-tools/task-tools.js +487 -0
  393. package/dist/src/mcp-tools/terminal-tools.d.ts +8 -0
  394. package/dist/src/mcp-tools/terminal-tools.js +306 -0
  395. package/dist/src/mcp-tools/testgen-tools.d.ts +26 -0
  396. package/dist/src/mcp-tools/testgen-tools.js +168 -0
  397. package/dist/src/mcp-tools/tool-loop-guardrail.d.ts +31 -0
  398. package/dist/src/mcp-tools/tool-loop-guardrail.js +71 -0
  399. package/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
  400. package/dist/src/mcp-tools/transfer-tools.js +447 -0
  401. package/dist/src/mcp-tools/types.d.ts +8 -0
  402. package/dist/src/mcp-tools/types.js +8 -0
  403. package/dist/src/mcp-tools/validate-input.d.ts +9 -0
  404. package/dist/src/mcp-tools/validate-input.js +9 -0
  405. package/dist/src/mcp-tools/wasm-agent-tools.d.ts +13 -0
  406. package/dist/src/mcp-tools/wasm-agent-tools.js +840 -0
  407. package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
  408. package/dist/src/mcp-tools/workflow-tools.js +884 -0
  409. package/dist/src/memory/bge-embedder.d.ts +25 -0
  410. package/dist/src/memory/bge-embedder.js +121 -0
  411. package/dist/src/memory/cross-encoder-rerank.d.ts +33 -0
  412. package/dist/src/memory/cross-encoder-rerank.js +123 -0
  413. package/dist/src/memory/embedding-policy.d.ts +21 -0
  414. package/dist/src/memory/embedding-policy.js +30 -0
  415. package/dist/src/memory/embedding-quantization.d.ts +62 -0
  416. package/dist/src/memory/embedding-quantization.js +156 -0
  417. package/dist/src/memory/ewc-consolidation.d.ts +305 -0
  418. package/dist/src/memory/ewc-consolidation.js +611 -0
  419. package/dist/src/memory/graph-edge-writer.d.ts +95 -0
  420. package/dist/src/memory/graph-edge-writer.js +217 -0
  421. package/dist/src/memory/hybrid-retrieval.d.ts +77 -0
  422. package/dist/src/memory/hybrid-retrieval.js +192 -0
  423. package/dist/src/memory/intelligence.d.ts +405 -0
  424. package/dist/src/memory/intelligence.js +1316 -0
  425. package/dist/src/memory/lucene-bm25.d.ts +19 -0
  426. package/dist/src/memory/lucene-bm25.js +308 -0
  427. package/dist/src/memory/memory-bridge.d.ts +537 -0
  428. package/dist/src/memory/memory-bridge.js +2460 -0
  429. package/dist/src/memory/memory-initializer.d.ts +556 -0
  430. package/dist/src/memory/memory-initializer.js +3021 -0
  431. package/dist/src/memory/neural-package-bridge.d.ts +48 -0
  432. package/dist/src/memory/neural-package-bridge.js +87 -0
  433. package/dist/src/memory/rabitq-index.d.ts +60 -0
  434. package/dist/src/memory/rabitq-index.js +242 -0
  435. package/dist/src/memory/sona-optimizer.d.ts +267 -0
  436. package/dist/src/memory/sona-optimizer.js +779 -0
  437. package/dist/src/memory/structured-distill.d.ts +48 -0
  438. package/dist/src/memory/structured-distill.js +125 -0
  439. package/dist/src/output.d.ts +9 -0
  440. package/dist/src/output.js +9 -0
  441. package/dist/src/parser.d.ts +89 -0
  442. package/dist/src/parser.js +516 -0
  443. package/dist/src/plugins/manager.d.ts +133 -0
  444. package/dist/src/plugins/manager.js +415 -0
  445. package/dist/src/plugins/store/discovery.d.ts +99 -0
  446. package/dist/src/plugins/store/discovery.js +1224 -0
  447. package/dist/src/plugins/store/index.d.ts +76 -0
  448. package/dist/src/plugins/store/index.js +141 -0
  449. package/dist/src/plugins/store/search.d.ts +46 -0
  450. package/dist/src/plugins/store/search.js +230 -0
  451. package/dist/src/plugins/store/types.d.ts +279 -0
  452. package/dist/src/plugins/store/types.js +7 -0
  453. package/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
  454. package/dist/src/plugins/tests/demo-plugin-store.js +126 -0
  455. package/dist/src/plugins/tests/standalone-test.d.ts +12 -0
  456. package/dist/src/plugins/tests/standalone-test.js +188 -0
  457. package/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
  458. package/dist/src/plugins/tests/test-plugin-store.js +206 -0
  459. package/dist/src/production/circuit-breaker.d.ts +101 -0
  460. package/dist/src/production/circuit-breaker.js +241 -0
  461. package/dist/src/production/error-handler.d.ts +92 -0
  462. package/dist/src/production/error-handler.js +299 -0
  463. package/dist/src/production/index.d.ts +23 -0
  464. package/dist/src/production/index.js +18 -0
  465. package/dist/src/production/monitoring.d.ts +161 -0
  466. package/dist/src/production/monitoring.js +356 -0
  467. package/dist/src/production/rate-limiter.d.ts +80 -0
  468. package/dist/src/production/rate-limiter.js +201 -0
  469. package/dist/src/production/retry.d.ts +48 -0
  470. package/dist/src/production/retry.js +179 -0
  471. package/dist/src/prompt.d.ts +44 -0
  472. package/dist/src/prompt.js +501 -0
  473. package/dist/src/proxy/install.d.ts +29 -0
  474. package/dist/src/proxy/install.js +135 -0
  475. package/dist/src/proxy/lifecycle.d.ts +61 -0
  476. package/dist/src/proxy/lifecycle.js +249 -0
  477. package/dist/src/proxy/paths.d.ts +34 -0
  478. package/dist/src/proxy/paths.js +70 -0
  479. package/dist/src/proxy/release.d.ts +47 -0
  480. package/dist/src/proxy/release.js +138 -0
  481. package/dist/src/proxy/token-bridge.d.ts +5 -0
  482. package/dist/src/proxy/token-bridge.js +61 -0
  483. package/dist/src/proxy/verify.d.ts +44 -0
  484. package/dist/src/proxy/verify.js +68 -0
  485. package/dist/src/runtime/headless.d.ts +60 -0
  486. package/dist/src/runtime/headless.js +284 -0
  487. package/dist/src/runtime/parent-death-watchdog.d.ts +42 -0
  488. package/dist/src/runtime/parent-death-watchdog.js +70 -0
  489. package/dist/src/ruvector/agent-wasm.d.ts +228 -0
  490. package/dist/src/ruvector/agent-wasm.js +463 -0
  491. package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
  492. package/dist/src/ruvector/ast-analyzer.js +277 -0
  493. package/dist/src/ruvector/codemods/engine.d.ts +45 -0
  494. package/dist/src/ruvector/codemods/engine.js +291 -0
  495. package/dist/src/ruvector/codemods/scope-analysis.d.ts +29 -0
  496. package/dist/src/ruvector/codemods/scope-analysis.js +162 -0
  497. package/dist/src/ruvector/coverage-router.d.ts +160 -0
  498. package/dist/src/ruvector/coverage-router.js +531 -0
  499. package/dist/src/ruvector/coverage-tools.d.ts +33 -0
  500. package/dist/src/ruvector/coverage-tools.js +157 -0
  501. package/dist/src/ruvector/diff-classifier.d.ts +175 -0
  502. package/dist/src/ruvector/diff-classifier.js +699 -0
  503. package/dist/src/ruvector/diskann-backend.d.ts +78 -0
  504. package/dist/src/ruvector/diskann-backend.js +310 -0
  505. package/dist/src/ruvector/enhanced-model-router.d.ts +172 -0
  506. package/dist/src/ruvector/enhanced-model-router.js +577 -0
  507. package/dist/src/ruvector/graph-analyzer.d.ts +187 -0
  508. package/dist/src/ruvector/graph-analyzer.js +929 -0
  509. package/dist/src/ruvector/graph-backend.d.ts +79 -0
  510. package/dist/src/ruvector/graph-backend.js +220 -0
  511. package/dist/src/ruvector/index.d.ts +38 -0
  512. package/dist/src/ruvector/index.js +86 -0
  513. package/dist/src/ruvector/lora-adapter.d.ts +292 -0
  514. package/dist/src/ruvector/lora-adapter.js +710 -0
  515. package/dist/src/ruvector/model-prices.d.ts +50 -0
  516. package/dist/src/ruvector/model-prices.js +72 -0
  517. package/dist/src/ruvector/model-router.d.ts +408 -0
  518. package/dist/src/ruvector/model-router.js +1162 -0
  519. package/dist/src/ruvector/neural-router.d.ts +182 -0
  520. package/dist/src/ruvector/neural-router.js +825 -0
  521. package/dist/src/ruvector/output-verifier.d.ts +83 -0
  522. package/dist/src/ruvector/output-verifier.js +277 -0
  523. package/dist/src/ruvector/q-learning-router.d.ts +227 -0
  524. package/dist/src/ruvector/q-learning-router.js +721 -0
  525. package/dist/src/ruvector/router-calibrator.d.ts +65 -0
  526. package/dist/src/ruvector/router-calibrator.js +120 -0
  527. package/dist/src/ruvector/router-parallel-recorder.d.ts +127 -0
  528. package/dist/src/ruvector/router-parallel-recorder.js +183 -0
  529. package/dist/src/ruvector/router-trajectory.d.ts +194 -0
  530. package/dist/src/ruvector/router-trajectory.js +281 -0
  531. package/dist/src/ruvector/run-transcript-recorder.d.ts +154 -0
  532. package/dist/src/ruvector/run-transcript-recorder.js +209 -0
  533. package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
  534. package/dist/src/ruvector/ruvllm-wasm.js +379 -0
  535. package/dist/src/ruvector/semantic-router.d.ts +77 -0
  536. package/dist/src/ruvector/semantic-router.js +178 -0
  537. package/dist/src/ruvector/task-embedder.d.ts +56 -0
  538. package/dist/src/ruvector/task-embedder.js +237 -0
  539. package/dist/src/ruvector/trajectory-tree.d.ts +113 -0
  540. package/dist/src/ruvector/trajectory-tree.js +237 -0
  541. package/dist/src/ruvector/vector-db.d.ts +73 -0
  542. package/dist/src/ruvector/vector-db.js +301 -0
  543. package/dist/src/ruvector/wasm-embedder.d.ts +13 -0
  544. package/dist/src/ruvector/wasm-embedder.js +143 -0
  545. package/dist/src/security/builtin-aidefence.d.ts +34 -0
  546. package/dist/src/security/builtin-aidefence.js +86 -0
  547. package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
  548. package/dist/src/services/agentic-flow-bridge.js +95 -0
  549. package/dist/src/services/ai-job-dedup.d.ts +61 -0
  550. package/dist/src/services/ai-job-dedup.js +136 -0
  551. package/dist/src/services/checkpoint-gate.d.ts +140 -0
  552. package/dist/src/services/checkpoint-gate.js +223 -0
  553. package/dist/src/services/claim-service.d.ts +204 -0
  554. package/dist/src/services/claim-service.js +818 -0
  555. package/dist/src/services/config-file-manager.d.ts +37 -0
  556. package/dist/src/services/config-file-manager.js +224 -0
  557. package/dist/src/services/container-worker-pool.d.ts +204 -0
  558. package/dist/src/services/container-worker-pool.js +589 -0
  559. package/dist/src/services/daemon-autostart.d.ts +17 -0
  560. package/dist/src/services/daemon-autostart.js +102 -0
  561. package/dist/src/services/distill-oracle.d.ts +190 -0
  562. package/dist/src/services/distill-oracle.js +349 -0
  563. package/dist/src/services/distill-tuning.d.ts +111 -0
  564. package/dist/src/services/distill-tuning.js +510 -0
  565. package/dist/src/services/evolve-proof.d.ts +253 -0
  566. package/dist/src/services/evolve-proof.js +343 -0
  567. package/dist/src/services/fable-harness.d.ts +208 -0
  568. package/dist/src/services/fable-harness.js +388 -0
  569. package/dist/src/services/git-workspace-identity.d.ts +42 -0
  570. package/dist/src/services/git-workspace-identity.js +99 -0
  571. package/dist/src/services/global-ai-budget.d.ts +135 -0
  572. package/dist/src/services/global-ai-budget.js +415 -0
  573. package/dist/src/services/harness-benchmark.d.ts +68 -0
  574. package/dist/src/services/harness-benchmark.js +94 -0
  575. package/dist/src/services/harness-canary.d.ts +60 -0
  576. package/dist/src/services/harness-canary.js +69 -0
  577. package/dist/src/services/harness-corpus-harvester.d.ts +51 -0
  578. package/dist/src/services/harness-corpus-harvester.js +74 -0
  579. package/dist/src/services/harness-flywheel-generations.d.ts +115 -0
  580. package/dist/src/services/harness-flywheel-generations.js +360 -0
  581. package/dist/src/services/harness-flywheel-runtime.d.ts +25 -0
  582. package/dist/src/services/harness-flywheel-runtime.js +92 -0
  583. package/dist/src/services/harness-flywheel.d.ts +48 -0
  584. package/dist/src/services/harness-flywheel.js +207 -0
  585. package/dist/src/services/harness-frozen-eval.d.ts +22 -0
  586. package/dist/src/services/harness-frozen-eval.js +66 -0
  587. package/dist/src/services/harness-hosts.d.ts +40 -0
  588. package/dist/src/services/harness-hosts.js +88 -0
  589. package/dist/src/services/harness-improvement-ledger.d.ts +63 -0
  590. package/dist/src/services/harness-improvement-ledger.js +101 -0
  591. package/dist/src/services/harness-loop.d.ts +53 -0
  592. package/dist/src/services/harness-loop.js +85 -0
  593. package/dist/src/services/harness-qualification.d.ts +66 -0
  594. package/dist/src/services/harness-qualification.js +143 -0
  595. package/dist/src/services/harness-replay.d.ts +37 -0
  596. package/dist/src/services/harness-replay.js +92 -0
  597. package/dist/src/services/harness-verify.d.ts +33 -0
  598. package/dist/src/services/harness-verify.js +26 -0
  599. package/dist/src/services/harness-worker.d.ts +23 -0
  600. package/dist/src/services/harness-worker.js +66 -0
  601. package/dist/src/services/headless-worker-executor.d.ts +358 -0
  602. package/dist/src/services/headless-worker-executor.js +1269 -0
  603. package/dist/src/services/index.d.ts +13 -0
  604. package/dist/src/services/index.js +11 -0
  605. package/dist/src/services/memory-backup.d.ts +53 -0
  606. package/dist/src/services/memory-backup.js +198 -0
  607. package/dist/src/services/memory-distillation.d.ts +41 -0
  608. package/dist/src/services/memory-distillation.js +277 -0
  609. package/dist/src/services/native-training.d.ts +68 -0
  610. package/dist/src/services/native-training.js +141 -0
  611. package/dist/src/services/registry-api.d.ts +58 -0
  612. package/dist/src/services/registry-api.js +146 -0
  613. package/dist/src/services/repo-supervisor.d.ts +70 -0
  614. package/dist/src/services/repo-supervisor.js +228 -0
  615. package/dist/src/services/ruvector-training.d.ts +222 -0
  616. package/dist/src/services/ruvector-training.js +693 -0
  617. package/dist/src/services/swarm-memory-branches.d.ts +135 -0
  618. package/dist/src/services/swarm-memory-branches.js +213 -0
  619. package/dist/src/services/weight-eft.d.ts +305 -0
  620. package/dist/src/services/weight-eft.js +296 -0
  621. package/dist/src/services/worker-daemon.d.ts +439 -0
  622. package/dist/src/services/worker-daemon.js +1865 -0
  623. package/dist/src/services/worker-queue.d.ts +194 -0
  624. package/dist/src/services/worker-queue.js +513 -0
  625. package/dist/src/services/workspace-lease.d.ts +55 -0
  626. package/dist/src/services/workspace-lease.js +191 -0
  627. package/dist/src/suggest.d.ts +53 -0
  628. package/dist/src/suggest.js +200 -0
  629. package/dist/src/transfer/anonymization/index.d.ts +25 -0
  630. package/dist/src/transfer/anonymization/index.js +175 -0
  631. package/dist/src/transfer/deploy-seraphine.d.ts +13 -0
  632. package/dist/src/transfer/deploy-seraphine.js +205 -0
  633. package/dist/src/transfer/export.d.ts +25 -0
  634. package/dist/src/transfer/export.js +113 -0
  635. package/dist/src/transfer/index.d.ts +12 -0
  636. package/dist/src/transfer/index.js +31 -0
  637. package/dist/src/transfer/ipfs/client.d.ts +109 -0
  638. package/dist/src/transfer/ipfs/client.js +307 -0
  639. package/dist/src/transfer/ipfs/upload.d.ts +95 -0
  640. package/dist/src/transfer/ipfs/upload.js +413 -0
  641. package/dist/src/transfer/models/seraphine.d.ts +72 -0
  642. package/dist/src/transfer/models/seraphine.js +373 -0
  643. package/dist/src/transfer/serialization/cfp.d.ts +49 -0
  644. package/dist/src/transfer/serialization/cfp.js +183 -0
  645. package/dist/src/transfer/storage/gcs.d.ts +82 -0
  646. package/dist/src/transfer/storage/gcs.js +272 -0
  647. package/dist/src/transfer/storage/index.d.ts +6 -0
  648. package/dist/src/transfer/storage/index.js +6 -0
  649. package/dist/src/transfer/store/discovery.d.ts +84 -0
  650. package/dist/src/transfer/store/discovery.js +382 -0
  651. package/dist/src/transfer/store/download.d.ts +70 -0
  652. package/dist/src/transfer/store/download.js +334 -0
  653. package/dist/src/transfer/store/index.d.ts +84 -0
  654. package/dist/src/transfer/store/index.js +153 -0
  655. package/dist/src/transfer/store/publish.d.ts +76 -0
  656. package/dist/src/transfer/store/publish.js +294 -0
  657. package/dist/src/transfer/store/registry.d.ts +58 -0
  658. package/dist/src/transfer/store/registry.js +285 -0
  659. package/dist/src/transfer/store/search.d.ts +54 -0
  660. package/dist/src/transfer/store/search.js +232 -0
  661. package/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
  662. package/dist/src/transfer/store/tests/standalone-test.js +190 -0
  663. package/dist/src/transfer/store/types.d.ts +193 -0
  664. package/dist/src/transfer/store/types.js +6 -0
  665. package/dist/src/transfer/test-seraphine.d.ts +6 -0
  666. package/dist/src/transfer/test-seraphine.js +105 -0
  667. package/dist/src/transfer/tests/test-store.d.ts +7 -0
  668. package/dist/src/transfer/tests/test-store.js +214 -0
  669. package/dist/src/transfer/types.d.ts +245 -0
  670. package/dist/src/transfer/types.js +6 -0
  671. package/dist/src/types.d.ts +13 -0
  672. package/dist/src/types.js +13 -0
  673. package/dist/src/update/checker.d.ts +34 -0
  674. package/dist/src/update/checker.js +191 -0
  675. package/dist/src/update/executor.d.ts +33 -0
  676. package/dist/src/update/executor.js +217 -0
  677. package/dist/src/update/index.d.ts +33 -0
  678. package/dist/src/update/index.js +64 -0
  679. package/dist/src/update/rate-limiter.d.ts +20 -0
  680. package/dist/src/update/rate-limiter.js +96 -0
  681. package/dist/src/update/validator.d.ts +17 -0
  682. package/dist/src/update/validator.js +123 -0
  683. package/package.json +1 -1
@@ -0,0 +1,1162 @@
1
+ /**
2
+ * Intelligent Model Router — lexical complexity heuristic + Thompson bandit
3
+ *
4
+ * Dynamically routes requests to the optimal Claude model (haiku/sonnet/opus)
5
+ * based on task complexity, uncertainty, and online-learned routing outcomes.
6
+ *
7
+ * Mechanism (shipped):
8
+ * - Complexity score = blend of lexical, semantic-depth, task-scope, and
9
+ * uncertainty heuristics (see `computeLexicalComplexity` and friends).
10
+ * Pure JS arithmetic — no model load, no tensor math.
11
+ * - Model selection = Thompson-sampling Beta-Bernoulli bandit with
12
+ * complexity-bucketed Beta(α,β) priors, persisted to
13
+ * `.swarm/model-router-state.json` and updated by `recordOutcome` after
14
+ * each routing decision.
15
+ * - Uncertainty quantification + a circuit breaker drive escalation when
16
+ * the bandit's confidence is low or downstream failures are observed.
17
+ *
18
+ * Routing Strategy:
19
+ * - Haiku: high confidence, low complexity (fast, cheap)
20
+ * - Sonnet: medium confidence, moderate complexity (balanced)
21
+ * - Opus: low confidence, high complexity (most capable)
22
+ *
23
+ * Note (#2329): An earlier design (ADR-026 + this file's previous header)
24
+ * described a Tiny-Dancer / FastGRNN neural router with embedding-based
25
+ * complexity scoring. That path was never wired in directly.
26
+ *
27
+ * Note (ADR-148, #2334): The cost-optimal neural router is now wired as an
28
+ * optional, gated addition via `./neural-router.ts` (which uses
29
+ * `@metaharness/router`, optionally accelerated by `@ruvector/tiny-dancer`).
30
+ * It is double-gated on `CLAUDE_FLOW_ROUTER_NEURAL=1` + an embedding being
31
+ * supplied + a corpus/artifact being loadable. When any gate is closed the
32
+ * shipped heuristic + bandit path runs unchanged and the result carries
33
+ * `routedBy: 'heuristic'` (default) or `'bandit-fallback'` (neural enabled
34
+ * but declined). When all gates are open and a backend resolves, the result
35
+ * carries `routedBy: 'metaharness-knn' | 'metaharness-krr' | 'fastgrnn'`.
36
+ *
37
+ * @module model-router
38
+ */
39
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
40
+ import { dirname, join } from 'path';
41
+ // ----------------------------------------------------------------------------
42
+ // Lazy module loaders — initialised once per process. The dynamic-import calls
43
+ // keep these modules off the critical-path-cold-start, but we want subsequent
44
+ // route() calls to pay only a Map lookup, not a new Promise per call.
45
+ // ----------------------------------------------------------------------------
46
+ let _neuralRouterMod = null;
47
+ function loadNeuralRouter() {
48
+ if (_neuralRouterMod === null)
49
+ _neuralRouterMod = import('./neural-router.js');
50
+ return _neuralRouterMod;
51
+ }
52
+ let _trajectoryMod = null;
53
+ function loadTrajectoryRecorder() {
54
+ if (_trajectoryMod === null)
55
+ _trajectoryMod = import('./router-trajectory.js');
56
+ return _trajectoryMod;
57
+ }
58
+ // ADR-150 iter 11–12 — parallel-decision recorder for the SelfEvolvingRouter
59
+ // promotion gate. Dynamic-imported lazily so the routing hot path never
60
+ // pays the load cost when CLAUDE_FLOW_ROUTER_PARALLEL_LOG is unset.
61
+ let _parallelRecorderMod = null;
62
+ function loadParallelRecorder() {
63
+ if (_parallelRecorderMod === null)
64
+ _parallelRecorderMod = import('./router-parallel-recorder.js');
65
+ return _parallelRecorderMod;
66
+ }
67
+ let _altsCache = null;
68
+ let _altsProbeDone = false;
69
+ function loadOpenRouterAlts() {
70
+ if (_altsProbeDone)
71
+ return _altsCache;
72
+ _altsProbeDone = true;
73
+ try {
74
+ // Probe candidate paths: explicit env override, then asset locations
75
+ // relative to this file (src dev) and the dist build.
76
+ const explicit = process.env.CLAUDE_FLOW_ROUTER_OPENROUTER_ALTS;
77
+ const candidates = [];
78
+ if (explicit)
79
+ candidates.push(explicit);
80
+ // Probe asset dirs without using import.meta.url so this stays compatible
81
+ // with both CJS and ESM consumers of the compiled .js.
82
+ candidates.push(join(process.cwd(), 'v3', '@claude-flow', 'cli', 'assets', 'model-router', 'openrouter-alts.json'));
83
+ candidates.push(join(process.cwd(), 'assets', 'model-router', 'openrouter-alts.json'));
84
+ for (const p of candidates) {
85
+ if (existsSync(p)) {
86
+ _altsCache = JSON.parse(readFileSync(p, 'utf8'));
87
+ return _altsCache;
88
+ }
89
+ }
90
+ }
91
+ catch {
92
+ // Silent — alts are optional.
93
+ }
94
+ return null;
95
+ }
96
+ /** Return the resolved provider + OpenRouter model for the picked tier. */
97
+ function resolveExecutionProvider(model) {
98
+ const explicit = process.env.CLAUDE_FLOW_ROUTER_PROVIDER?.toLowerCase();
99
+ // Default: anthropic unless explicitly set to openrouter, or OPENROUTER_API_KEY
100
+ // is the only credential present (matches agent-execute-core's selection).
101
+ const hasOpenRouter = !!process.env.OPENROUTER_API_KEY;
102
+ const hasAnthropic = !!process.env.ANTHROPIC_API_KEY;
103
+ const wantOR = explicit === 'openrouter' ||
104
+ (!hasAnthropic && hasOpenRouter && explicit !== 'anthropic');
105
+ if (!wantOR)
106
+ return { provider: 'anthropic' };
107
+ const alts = loadOpenRouterAlts();
108
+ if (!alts)
109
+ return { provider: 'openrouter' }; // OR provider but no alt slug
110
+ const entry = alts.tiers[model];
111
+ if (!entry?.openrouter_alt)
112
+ return { provider: 'openrouter' };
113
+ return { provider: 'openrouter', openrouterModel: entry.openrouter_alt };
114
+ }
115
+ /**
116
+ * Model capabilities and characteristics
117
+ */
118
+ export const MODEL_CAPABILITIES = {
119
+ haiku: {
120
+ maxComplexity: 0.4,
121
+ costMultiplier: 0.04, // ~25x cheaper than Opus
122
+ speedMultiplier: 3.0, // ~3x faster than Sonnet
123
+ description: 'Fast, cost-effective for simple tasks',
124
+ },
125
+ sonnet: {
126
+ maxComplexity: 0.7,
127
+ costMultiplier: 0.2, // ~5x cheaper than Opus
128
+ speedMultiplier: 1.5, // ~1.5x faster than Opus
129
+ description: 'Balanced capability and cost',
130
+ },
131
+ opus: {
132
+ maxComplexity: 1.0,
133
+ costMultiplier: 1.0, // Baseline
134
+ speedMultiplier: 1.0, // Baseline
135
+ description: 'Most capable for complex reasoning',
136
+ },
137
+ inherit: {
138
+ maxComplexity: 1.0,
139
+ costMultiplier: 1.0,
140
+ speedMultiplier: 1.0,
141
+ description: 'Use parent model selection',
142
+ },
143
+ };
144
+ /**
145
+ * Complexity indicators for task classification
146
+ */
147
+ export const COMPLEXITY_INDICATORS = {
148
+ high: [
149
+ 'architect', 'design', 'refactor', 'optimize', 'security', 'audit',
150
+ 'complex', 'analyze', 'investigate', 'debug', 'performance', 'scale',
151
+ 'distributed', 'concurrent', 'algorithm', 'system', 'integration',
152
+ ],
153
+ medium: [
154
+ 'implement', 'feature', 'add', 'update', 'modify', 'fix', 'test',
155
+ 'review', 'validate', 'check', 'improve', 'enhance', 'extend',
156
+ ],
157
+ low: [
158
+ 'simple', 'typo', 'comment', 'format', 'rename', 'move', 'copy',
159
+ 'delete', 'documentation', 'readme', 'config', 'version', 'bump',
160
+ ],
161
+ };
162
+ /**
163
+ * Cost-adjusted Bernoulli rewards for Thompson sampling updates. Higher
164
+ * reward when the right tier is chosen — Haiku-success > Sonnet-success >
165
+ * Opus-success because Opus-success on a simple task is wasteful even when
166
+ * the answer is correct. Escalations get partial credit at best (Sonnet) or
167
+ * zero (Haiku/Opus) since they signal the initial choice was wrong.
168
+ */
169
+ const BANDIT_REWARDS = {
170
+ haiku: { success: 1.0, failure: 0.0, escalated: 0.0 },
171
+ sonnet: { success: 0.7, failure: 0.0, escalated: 0.1 },
172
+ opus: { success: 0.4, failure: 0.0, escalated: 0.0 },
173
+ inherit: { success: 0.5, failure: 0.0, escalated: 0.0 },
174
+ };
175
+ function complexityBucket(score) {
176
+ if (score < 0.4)
177
+ return 'low'; // haiku territory
178
+ if (score < 0.7)
179
+ return 'med'; // sonnet territory
180
+ return 'high'; // opus territory
181
+ }
182
+ // ============================================================================
183
+ // Beta Sampling for Thompson Sampling Bandit
184
+ // ============================================================================
185
+ /**
186
+ * Standard normal sample via Box-Muller. Used by Marsaglia-Tsang Gamma.
187
+ * Module-local so the bandit doesn't pull in a heavy stats dep.
188
+ */
189
+ function sampleStandardNormal() {
190
+ const u1 = Math.random() || 1e-12; // avoid log(0)
191
+ const u2 = Math.random();
192
+ return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
193
+ }
194
+ /**
195
+ * Sample from Gamma(shape α, scale=1). Marsaglia & Tsang (2000), with the
196
+ * standard "boost α<1 by α+1 then scale by U^(1/α)" trick for shape parameters
197
+ * smaller than 1. O(1) expected, no rejection-loop pathology in practice.
198
+ */
199
+ function sampleGamma(alpha) {
200
+ if (alpha < 1) {
201
+ const u = Math.random() || 1e-12;
202
+ return sampleGamma(alpha + 1) * Math.pow(u, 1 / alpha);
203
+ }
204
+ const d = alpha - 1 / 3;
205
+ const c = 1 / Math.sqrt(9 * d);
206
+ while (true) {
207
+ let x;
208
+ let v;
209
+ do {
210
+ x = sampleStandardNormal();
211
+ v = 1 + c * x;
212
+ } while (v <= 0);
213
+ v = v * v * v;
214
+ const u = Math.random();
215
+ const xx = x * x;
216
+ if (u < 1 - 0.0331 * xx * xx)
217
+ return d * v;
218
+ if (Math.log(u) < 0.5 * xx + d * (1 - v + Math.log(v)))
219
+ return d * v;
220
+ }
221
+ }
222
+ /**
223
+ * Sample θ ~ Beta(α, β) via the identity Beta(α,β) = X / (X+Y) where
224
+ * X ~ Gamma(α), Y ~ Gamma(β). Returns the mean for degenerate α+β=0
225
+ * (shouldn't happen in practice but defensive).
226
+ */
227
+ export function sampleBeta(alpha, beta) {
228
+ if (alpha <= 0 || beta <= 0)
229
+ return 0.5;
230
+ const x = sampleGamma(alpha);
231
+ const y = sampleGamma(beta);
232
+ const denom = x + y;
233
+ return denom > 0 ? x / denom : 0.5;
234
+ }
235
+ /**
236
+ * Default uniform priors (no prior knowledge). Beta(1,1) is the standard
237
+ * Bayesian-Bernoulli starting point — uniform over [0,1].
238
+ */
239
+ function defaultBanditPriors() {
240
+ return {
241
+ haiku: { alpha: 1, beta: 1 },
242
+ sonnet: { alpha: 1, beta: 1 },
243
+ opus: { alpha: 1, beta: 1 },
244
+ inherit: { alpha: 1, beta: 1 },
245
+ };
246
+ }
247
+ /** Uniform priors for every complexity bucket (cold start). */
248
+ function defaultBucketedPriors() {
249
+ return { low: defaultBanditPriors(), med: defaultBanditPriors(), high: defaultBanditPriors() };
250
+ }
251
+ /** ADR-149 — empty per-modelId shadow priors. Each bucket starts as `{}`; entries
252
+ * populate on first `recordOutcomeByModelId(task, modelId, outcome)` call. */
253
+ function defaultBucketedPriorsById() {
254
+ return { low: {}, med: {}, high: {} };
255
+ }
256
+ function clonePriors(p) {
257
+ return { haiku: { ...p.haiku }, sonnet: { ...p.sonnet }, opus: { ...p.opus }, inherit: { ...p.inherit } };
258
+ }
259
+ /**
260
+ * Forward-migrate a persisted `priors` field of any layout to the bucketed
261
+ * shape, never throwing (ADR-142):
262
+ * - missing/garbage → fresh uniform buckets
263
+ * - already bucketed (has `low.haiku`) → kept, backfilling any missing bucket
264
+ * - flat per-model (v1 bandit) → seed ALL buckets from it (lossless: prior
265
+ * learning becomes a shared starting point that then diverges per bucket)
266
+ */
267
+ function migratePriors(p) {
268
+ if (!p || typeof p !== 'object')
269
+ return defaultBucketedPriors();
270
+ const obj = p;
271
+ if (obj.low && typeof obj.low === 'object' && obj.low.haiku) {
272
+ return {
273
+ low: obj.low,
274
+ med: obj.med ?? clonePriors(obj.low),
275
+ high: obj.high ?? clonePriors(obj.low),
276
+ };
277
+ }
278
+ if (obj.haiku && typeof obj.haiku.alpha === 'number') {
279
+ const flat = obj;
280
+ return { low: clonePriors(flat), med: clonePriors(flat), high: clonePriors(flat) };
281
+ }
282
+ return defaultBucketedPriors();
283
+ }
284
+ // ============================================================================
285
+ // Default Configuration
286
+ // ============================================================================
287
+ // #2250 — env override for maxUncertainty so callers can suppress the
288
+ // escalation without recompiling. Parsed once at module load; invalid /
289
+ // out-of-range values fall through to the default below.
290
+ function envMaxUncertainty() {
291
+ const raw = process.env.CLAUDE_FLOW_MAX_UNCERTAINTY;
292
+ if (!raw)
293
+ return undefined;
294
+ const n = Number(raw);
295
+ if (!Number.isFinite(n) || n < 0 || n > 1)
296
+ return undefined;
297
+ return n;
298
+ }
299
+ const DEFAULT_CONFIG = {
300
+ confidenceThreshold: 0.85,
301
+ maxUncertainty: envMaxUncertainty() ?? 0.15,
302
+ enableCircuitBreaker: true,
303
+ circuitBreakerThreshold: 5,
304
+ statePath: '.swarm/model-router-state.json',
305
+ autoSaveInterval: 1, // Save after every decision for CLI persistence
306
+ enableCostOptimization: true,
307
+ preferSpeed: true,
308
+ };
309
+ // Posterior mean of a Beta(α,β) prior — used by the #2250 escalation guard
310
+ // to detect when the bandit has *learned* the escalation target is worse.
311
+ function priorMean(p) {
312
+ return p.alpha / (p.alpha + p.beta);
313
+ }
314
+ // ============================================================================
315
+ // Model Router Implementation
316
+ // ============================================================================
317
+ /**
318
+ * Intelligent Model Router using complexity-based routing
319
+ */
320
+ export class ModelRouter {
321
+ config;
322
+ state;
323
+ decisionCount = 0;
324
+ consecutiveFailures = {
325
+ haiku: 0,
326
+ sonnet: 0,
327
+ opus: 0,
328
+ inherit: 0,
329
+ };
330
+ /**
331
+ * ADR-148 — in-memory counters surfaced via `getStats()` and read by the
332
+ * `hooks_intelligence_stats` MCP tool. Process-local, not persisted (these
333
+ * are operational metrics, not authoritative state — see ADR-074/086).
334
+ */
335
+ routedByCounts = {
336
+ heuristic: 0,
337
+ 'bandit-fallback': 0,
338
+ hybrid: 0,
339
+ };
340
+ neuralBackendCounts = {
341
+ 'metaharness-knn': 0,
342
+ 'metaharness-krr': 0,
343
+ fastgrnn: 0,
344
+ };
345
+ abDisagreements = 0;
346
+ abComparisons = 0;
347
+ constructor(config = {}) {
348
+ this.config = { ...DEFAULT_CONFIG, ...config };
349
+ this.state = this.loadState();
350
+ }
351
+ /**
352
+ * Route a task to the optimal model.
353
+ *
354
+ * When `embedding` is supplied and `CLAUDE_FLOW_ROUTER_NEURAL=1` is set,
355
+ * the cost-optimal neural backend (ADR-148) is consulted first; its
356
+ * decision is used when its `metBar` clears the configured quality bar
357
+ * and `routedBy` reflects which backend produced the decision. Otherwise
358
+ * the shipped heuristic + Thompson bandit path runs (byte-identical to
359
+ * the pre-ADR-148 behavior) and the result carries `routedBy:
360
+ * 'bandit-fallback'` (neural was enabled but declined) or
361
+ * `'heuristic'` (neural was disabled).
362
+ */
363
+ async route(task, embedding) {
364
+ const startTime = performance.now();
365
+ // Analyze task complexity
366
+ const complexity = this.analyzeComplexity(task, embedding);
367
+ // ADR-148 — optional neural cost-optimal path (gated, opt-in).
368
+ //
369
+ // Hybrid math: we use the neural's per-candidate predicted quality as a
370
+ // weighted prior on the bandit's Beta(α,β) posterior, rather than
371
+ // overriding the bandit's pick. With weight=w (env-tunable, default 5)
372
+ // each candidate's Beta becomes Beta(α + q*w, β + (1-q)*w). Cold start
373
+ // → neural dominates (α+β ≈ 2 + w); many real outcomes → bandit
374
+ // dominates (α+β >> w). The persistent bandit state is unchanged.
375
+ //
376
+ // `bandit-fallback` is reserved for the case where neural was enabled
377
+ // but the backend returned no decision at all (artifact load failed,
378
+ // dim mismatch, etc.). In that case we route via pure bandit.
379
+ let neuralPrior = null;
380
+ let neuralBackend = undefined;
381
+ let neuralModelId = undefined;
382
+ let neuralDeclined = false;
383
+ // iter 46 — capture iter 45's ensemble-disagreement diagnostic so we can
384
+ // persist it to the trajectory below; downstream tuners (future) can
385
+ // analyze the distribution to recommend an iter 44 threshold.
386
+ let neuralEnsembleDisagreement = undefined;
387
+ if (embedding && embedding.length > 0 && process.env.CLAUDE_FLOW_ROUTER_NEURAL === '1') {
388
+ try {
389
+ const { tryCostOptimalRoute } = await loadNeuralRouter();
390
+ // ADR-149 iter 15 — pass the task's complexity bucket through so
391
+ // the neural-router's per-modelId Thompson (when gated on) can
392
+ // use the bucket-specific prior instead of marginalising.
393
+ const nr = await tryCostOptimalRoute(embedding, { complexityBucket: complexityBucket(complexity.score) });
394
+ if (nr) {
395
+ // ADR-149: capture the concrete picked model id (the cost-optimal
396
+ // pick across all candidates, not just within a tier).
397
+ neuralModelId = nr.modelId;
398
+ neuralEnsembleDisagreement = nr.ensembleDisagreement;
399
+ // Build per-tier quality map for the bandit prior. The neural
400
+ // backend returns per-model alternatives (e.g. 7 distinct slugs);
401
+ // for the Beta-prior bump we collapse to tier by taking the MAX
402
+ // predicted quality within each tier — the tier whose best
403
+ // candidate is best overall is the tier the bandit should favor.
404
+ // Then we apply rank-based scaling [1.0, 0.5, 0.2] across the
405
+ // three tiers so the Beta bumps are well-separated (raw KRR
406
+ // outputs are typically in a narrow band — see ADR-148 phase 1).
407
+ const sorted = [...nr.alternatives].sort((a, b) => b.predictedQuality - a.predictedQuality);
408
+ if (!sorted.find(s => s.model === nr.model)) {
409
+ sorted.unshift({ model: nr.model, modelId: nr.modelId, predictedQuality: nr.predictedQuality, costPerMTok: 0 });
410
+ }
411
+ // Collapse per-model alternatives → per-tier MAX quality, preserving
412
+ // first-occurrence order (which is best-quality first thanks to the sort).
413
+ const tierMaxQ = {};
414
+ const tierOrder = [];
415
+ for (const a of sorted) {
416
+ if (tierMaxQ[a.model] === undefined) {
417
+ tierMaxQ[a.model] = a.predictedQuality;
418
+ tierOrder.push(a.model);
419
+ }
420
+ else if (a.predictedQuality > (tierMaxQ[a.model] ?? 0)) {
421
+ tierMaxQ[a.model] = a.predictedQuality;
422
+ }
423
+ }
424
+ const rankQ = [1.0, 0.5, 0.2];
425
+ const qualities = {};
426
+ for (let i = 0; i < tierOrder.length && i < rankQ.length; i++) {
427
+ qualities[tierOrder[i]] = rankQ[i];
428
+ }
429
+ const weight = parseFloat(process.env.CLAUDE_FLOW_ROUTER_NEURAL_WEIGHT ?? '5') || 5;
430
+ neuralPrior = { qualities, weight };
431
+ neuralBackend = nr.routedBy;
432
+ }
433
+ else {
434
+ neuralDeclined = true;
435
+ }
436
+ }
437
+ catch {
438
+ // Silent — neural path is best-effort.
439
+ }
440
+ }
441
+ const scores = this.computeModelScores(complexity);
442
+ const adjustedScores = this.applyCircuitBreaker(scores);
443
+ // A/B mode: compute the pure-bandit pick alongside the hybrid pick so
444
+ // we can log disagreement. Both samples are drawn from the same Beta
445
+ // posteriors but with/without the neural prior bump — useful for
446
+ // measuring real lift before flipping defaults.
447
+ //
448
+ // iter 37 — TWO knobs:
449
+ // CLAUDE_FLOW_ROUTER_AB=1 → A/B on every call (orig)
450
+ // CLAUDE_FLOW_ROUTER_AB_SAMPLE_RATE=<0..1> → A/B on a sampled subset,
451
+ // keyed deterministically by task_hash so the same task always falls
452
+ // in or out of the sample. Lets production accumulate ab_pair data
453
+ // passively at low overhead (e.g. 0.05 = 5% of decisions).
454
+ // Both set → SAMPLE_RATE wins (more specific).
455
+ const rateRaw = process.env.CLAUDE_FLOW_ROUTER_AB_SAMPLE_RATE;
456
+ const rate = rateRaw ? Math.max(0, Math.min(1, parseFloat(rateRaw) || 0)) : 0;
457
+ const allOn = process.env.CLAUDE_FLOW_ROUTER_AB === '1';
458
+ let inSample = false;
459
+ if (rate > 0) {
460
+ // Deterministic sample by FNV-1a-32 of the task text. Same task always
461
+ // gets the same A/B decision across re-runs (reproducible tests, stable
462
+ // population over time). Inlined to avoid the async router-trajectory
463
+ // import on the hot path.
464
+ let h = 0x811c9dc5 >>> 0;
465
+ for (let i = 0; i < task.length; i++) {
466
+ h ^= task.charCodeAt(i);
467
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
468
+ }
469
+ inSample = (h % 10000) / 10000 < rate;
470
+ }
471
+ const abEnabled = (rate > 0 ? inSample : allOn) && neuralPrior !== null;
472
+ let abPair;
473
+ if (abEnabled) {
474
+ // Pre-compute the bandit-only pick. Single extra Thompson sample per
475
+ // call — independent draws are noisy but cheap (~3 Beta samples ≈
476
+ // <10 μs). For a per-call disagreement signal one draw is fine; over
477
+ // N decisions the rate stabilises.
478
+ const banditOnly = this.selectModel(adjustedScores, complexity.score, undefined);
479
+ const picked = this.selectModel(adjustedScores, complexity.score, neuralPrior ?? undefined);
480
+ abPair = {
481
+ bandit_pick: banditOnly.model,
482
+ hybrid_pick: picked.model,
483
+ disagree: banditOnly.model !== picked.model,
484
+ };
485
+ this.abComparisons++;
486
+ if (abPair.disagree)
487
+ this.abDisagreements++;
488
+ // ADR-150 iter 12 — opt-in parallel-decision recorder. No-op when
489
+ // CLAUDE_FLOW_ROUTER_PARALLEL_LOG is unset (the default), so this
490
+ // adds zero overhead to the default routing path. Fire-and-forget
491
+ // dynamic-import + recordPair; never blocks the route() return.
492
+ if (process.env.CLAUDE_FLOW_ROUTER_PARALLEL_LOG === '1') {
493
+ loadParallelRecorder().then((mod) => {
494
+ try {
495
+ mod.recordPair({
496
+ task,
497
+ bandit: {
498
+ pick: banditOnly.model,
499
+ predictedQuality: banditOnly.confidence,
500
+ predictedCostUsd: 0, // bandit doesn't price; analyzer uses outcome
501
+ backend: 'thompson-bandit',
502
+ },
503
+ ser: {
504
+ pick: picked.model,
505
+ predictedQuality: picked.confidence,
506
+ predictedCostUsd: 0,
507
+ backend: neuralPrior ? 'metaharness-router-hybrid' : 'bandit-only',
508
+ },
509
+ });
510
+ }
511
+ catch {
512
+ // ADR-150 rule #3 — never throw from the routing path.
513
+ }
514
+ }).catch(() => { });
515
+ }
516
+ var pickedForResult = picked; // eslint-disable-line no-var
517
+ }
518
+ else {
519
+ var pickedForResult = this.selectModel(adjustedScores, complexity.score, neuralPrior ?? undefined); // eslint-disable-line no-var
520
+ }
521
+ const model = pickedForResult.model;
522
+ const confidence = pickedForResult.confidence;
523
+ const uncertainty = pickedForResult.uncertainty;
524
+ const routedBy = neuralPrior
525
+ ? 'hybrid'
526
+ : neuralDeclined ? 'bandit-fallback' : 'heuristic';
527
+ const inferenceTimeUs = (performance.now() - startTime) * 1000;
528
+ // ADR-148 phase 2 — resolve OpenRouter alt for the picked tier when the
529
+ // execution provider is OpenRouter. Free of side effects on the bandit;
530
+ // purely advisory metadata for downstream agent-execute-core.
531
+ //
532
+ // ADR-149 — when the neural backend returned a concrete `modelId` that
533
+ // is NOT an Anthropic slug, we override the provider to 'openrouter'
534
+ // and use the modelId as the openrouterModel. Otherwise consumers
535
+ // dispatching on `model` would call the Anthropic SDK for a model id
536
+ // the SDK can't reach (e.g. 'inclusionai/ling-2.6-flash'), losing the
537
+ // cost-optimal pick. When the neural picked an Anthropic id we keep
538
+ // the standard provider resolution since the Anthropic SDK can serve it.
539
+ let exec = resolveExecutionProvider(model);
540
+ if (neuralModelId && !neuralModelId.startsWith('anthropic/')) {
541
+ exec = { provider: 'openrouter', openrouterModel: neuralModelId };
542
+ }
543
+ // Build result
544
+ const result = {
545
+ model,
546
+ confidence,
547
+ uncertainty,
548
+ complexity: complexity.score,
549
+ reasoning: this.buildReasoning(model, complexity, confidence),
550
+ alternatives: Object.entries(adjustedScores)
551
+ .filter(([m]) => m !== model)
552
+ .map(([m, score]) => ({ model: m, score }))
553
+ .sort((a, b) => b.score - a.score),
554
+ inferenceTimeUs,
555
+ costMultiplier: MODEL_CAPABILITIES[model].costMultiplier,
556
+ routedBy,
557
+ ...(neuralBackend ? { neuralBackend } : {}),
558
+ provider: exec.provider,
559
+ ...(exec.openrouterModel ? { openrouterModel: exec.openrouterModel } : {}),
560
+ // ADR-149: surface the concrete neural pick when present. Prefer the
561
+ // explicit OpenRouter alt (resolveExecutionProvider) for execution,
562
+ // but expose the model id the neural backend chose so observers and
563
+ // consumers can see the cost-optimal decision.
564
+ ...(neuralModelId ? { modelId: neuralModelId } : {}),
565
+ };
566
+ // Track decision (in-memory bandit state)
567
+ this.trackDecision(task, result);
568
+ // ADR-148 — opt-in DRACO-shaped trajectory collection
569
+ if (process.env.CLAUDE_FLOW_ROUTER_TRAJECTORY === '1') {
570
+ try {
571
+ const { recordDecision } = await loadTrajectoryRecorder();
572
+ recordDecision({
573
+ task, embedding, complexity: complexity.score,
574
+ model, confidence, uncertainty, routedBy,
575
+ neuralBackend, abPair,
576
+ provider: exec.provider,
577
+ openrouterModel: exec.openrouterModel,
578
+ ensembleDisagreement: neuralEnsembleDisagreement,
579
+ });
580
+ }
581
+ catch {
582
+ // Silent — trajectory recording must never break routing.
583
+ }
584
+ }
585
+ return result;
586
+ }
587
+ /**
588
+ * Analyze task complexity
589
+ */
590
+ analyzeComplexity(task, embedding) {
591
+ const taskLower = task.toLowerCase();
592
+ const words = taskLower.split(/\s+/);
593
+ // Find complexity indicators
594
+ const indicators = {
595
+ high: COMPLEXITY_INDICATORS.high.filter(ind => taskLower.includes(ind)),
596
+ medium: COMPLEXITY_INDICATORS.medium.filter(ind => taskLower.includes(ind)),
597
+ low: COMPLEXITY_INDICATORS.low.filter(ind => taskLower.includes(ind)),
598
+ };
599
+ // Compute feature scores
600
+ const lexicalComplexity = this.computeLexicalComplexity(task);
601
+ const semanticDepth = this.computeSemanticDepth(indicators, embedding);
602
+ const taskScope = this.computeTaskScope(task, words);
603
+ const uncertaintyLevel = this.computeUncertaintyLevel(task);
604
+ // Weighted combination
605
+ const score = Math.min(1, Math.max(0, lexicalComplexity * 0.2 +
606
+ semanticDepth * 0.35 +
607
+ taskScope * 0.25 +
608
+ uncertaintyLevel * 0.2));
609
+ return {
610
+ score,
611
+ indicators,
612
+ features: {
613
+ lexicalComplexity,
614
+ semanticDepth,
615
+ taskScope,
616
+ uncertaintyLevel,
617
+ },
618
+ };
619
+ }
620
+ /**
621
+ * Compute lexical complexity from text features
622
+ */
623
+ computeLexicalComplexity(task) {
624
+ const words = task.split(/\s+/);
625
+ const avgWordLength = words.reduce((sum, w) => sum + w.length, 0) / Math.max(1, words.length);
626
+ const sentenceLength = words.length;
627
+ // Normalize: longer sentences with longer words = more complex
628
+ const lengthScore = Math.min(1, sentenceLength / 50);
629
+ const wordScore = Math.min(1, (avgWordLength - 3) / 7); // 3-10 char words
630
+ return lengthScore * 0.4 + wordScore * 0.6;
631
+ }
632
+ /**
633
+ * Compute semantic depth from indicators and embedding
634
+ */
635
+ computeSemanticDepth(indicators, embedding) {
636
+ // Weight by indicator presence
637
+ const highWeight = indicators.high.length * 0.3;
638
+ const mediumWeight = indicators.medium.length * 0.15;
639
+ const lowWeight = indicators.low.length * -0.1;
640
+ let baseScore = Math.min(1, Math.max(0, 0.3 + highWeight + mediumWeight + lowWeight));
641
+ // Boost with embedding variance if available
642
+ if (embedding && embedding.length > 0) {
643
+ const mean = embedding.reduce((a, b) => a + b, 0) / embedding.length;
644
+ const variance = embedding.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / embedding.length;
645
+ // Higher variance suggests more nuanced semantics
646
+ baseScore = baseScore * 0.7 + Math.min(1, variance * 10) * 0.3;
647
+ }
648
+ return baseScore;
649
+ }
650
+ /**
651
+ * Compute task scope from content analysis
652
+ */
653
+ computeTaskScope(task, words) {
654
+ // Multi-file indicators
655
+ const multiFilePatterns = [
656
+ /multiple files?/i, /across.*modules?/i, /refactor.*codebase/i,
657
+ /all.*files/i, /entire.*project/i, /system.*wide/i,
658
+ ];
659
+ const hasMultiFile = multiFilePatterns.some(p => p.test(task)) ? 0.4 : 0;
660
+ // Code generation indicators
661
+ const codeGenPatterns = [
662
+ /implement/i, /create.*feature/i, /build.*system/i,
663
+ /design.*api/i, /write.*tests/i, /add.*functionality/i,
664
+ ];
665
+ const hasCodeGen = codeGenPatterns.some(p => p.test(task)) ? 0.3 : 0;
666
+ // Word count contribution
667
+ const wordCountScore = Math.min(0.3, words.length / 100);
668
+ return hasMultiFile + hasCodeGen + wordCountScore;
669
+ }
670
+ /**
671
+ * Compute uncertainty level from task phrasing
672
+ */
673
+ computeUncertaintyLevel(task) {
674
+ const uncertainPatterns = [
675
+ /not sure/i, /might/i, /maybe/i, /possibly/i, /investigate/i,
676
+ /figure out/i, /unclear/i, /unknown/i, /debug/i, /strange/i,
677
+ /weird/i, /issue/i, /problem/i, /error/i, /bug/i,
678
+ ];
679
+ const matchCount = uncertainPatterns.filter(p => p.test(task)).length;
680
+ return Math.min(1, matchCount * 0.2);
681
+ }
682
+ /**
683
+ * Compute scores for each model
684
+ */
685
+ computeModelScores(complexity) {
686
+ const { score } = complexity;
687
+ // Base scoring: inverse relationship with complexity
688
+ // Low complexity → haiku scores high
689
+ // High complexity → opus scores high
690
+ return {
691
+ haiku: Math.max(0, 1 - score * 2), // Drops off quickly as complexity rises
692
+ sonnet: 1 - Math.abs(score - 0.5) * 2, // Peaks at medium complexity
693
+ opus: Math.min(1, score * 1.5), // Rises with complexity
694
+ inherit: 0.1, // Low baseline unless explicitly needed
695
+ };
696
+ }
697
+ /**
698
+ * Apply circuit breaker adjustments
699
+ */
700
+ applyCircuitBreaker(scores) {
701
+ if (!this.config.enableCircuitBreaker) {
702
+ return scores;
703
+ }
704
+ const adjusted = { ...scores };
705
+ for (const model of Object.keys(adjusted)) {
706
+ if (this.consecutiveFailures[model] >= this.config.circuitBreakerThreshold) {
707
+ // Circuit is open - heavily penalize this model
708
+ adjusted[model] *= 0.1;
709
+ }
710
+ else if (this.consecutiveFailures[model] > 0) {
711
+ // Partial penalty for recent failures
712
+ adjusted[model] *= 1 - (this.consecutiveFailures[model] / this.config.circuitBreakerThreshold) * 0.5;
713
+ }
714
+ }
715
+ return adjusted;
716
+ }
717
+ /**
718
+ * Select the best model from scores. Uses Thompson sampling (#1772):
719
+ * each model's deterministic complexity score is multiplied by a draw
720
+ * θ_m ~ Beta(α_m, β_m) from its bandit prior. Models with strong empirical
721
+ * track records get sampled higher; models with poor outcomes get sampled
722
+ * lower; the system auto-corrects against tier overuse without manual
723
+ * threshold tuning. Beta(1,1) = uniform on cold start so behavior matches
724
+ * the prior deterministic router until outcomes accumulate.
725
+ */
726
+ selectModel(scores, complexityScore,
727
+ /**
728
+ * Optional neural prior (ADR-148 hybrid math). When supplied, each
729
+ * candidate's Beta(α, β) prior is perturbed by `weight` pseudo-counts of
730
+ * the neural's predicted quality before sampling. Cold start → neural
731
+ * dominates; many real outcomes → bandit dominates. The persistent
732
+ * bandit state is NOT modified — this is a per-call posterior bump only.
733
+ */
734
+ neuralPrior) {
735
+ // Thompson sampling: combine deterministic score with bandit posterior,
736
+ // keyed by complexity bucket (ADR-142) so learning is task-type-local.
737
+ const bucketed = this.state.priors ?? defaultBucketedPriors();
738
+ const priors = bucketed[complexityBucket(complexityScore)] ?? defaultBanditPriors();
739
+ // Apply the optional neural prior: Beta(α + q*w, β + (1-q)*w). Per-call,
740
+ // does not persist. Clamp `q` into [0, 1] so a bogus backend reading
741
+ // cannot push the prior into invalid territory.
742
+ const bump = (a, b, q, w) => {
743
+ if (q === undefined || w <= 0)
744
+ return { alpha: a, beta: b };
745
+ const clamped = Math.min(1, Math.max(0, q));
746
+ return { alpha: a + clamped * w, beta: b + (1 - clamped) * w };
747
+ };
748
+ const w = neuralPrior?.weight ?? 0;
749
+ const ph = bump(priors.haiku.alpha, priors.haiku.beta, neuralPrior?.qualities.haiku, w);
750
+ const ps = bump(priors.sonnet.alpha, priors.sonnet.beta, neuralPrior?.qualities.sonnet, w);
751
+ const po = bump(priors.opus.alpha, priors.opus.beta, neuralPrior?.qualities.opus, w);
752
+ const sampledScores = {
753
+ haiku: scores.haiku * sampleBeta(ph.alpha, ph.beta),
754
+ sonnet: scores.sonnet * sampleBeta(ps.alpha, ps.beta),
755
+ opus: scores.opus * sampleBeta(po.alpha, po.beta),
756
+ inherit: scores.inherit, // not bandit-controlled
757
+ };
758
+ // Get sorted models by sampled score (drops 'inherit' from selection)
759
+ const sorted = Object.entries(sampledScores)
760
+ .filter(([m]) => m !== 'inherit')
761
+ .sort((a, b) => b[1] - a[1]);
762
+ const [bestModel, bestScore] = sorted[0];
763
+ const [, secondScore] = sorted[1] || ['sonnet', 0];
764
+ // Confidence is how much better the best is vs second
765
+ const confidence = bestScore > 0 ? Math.min(1, bestScore / (bestScore + secondScore + 0.01)) : 0.5;
766
+ // Uncertainty based on score spread and complexity
767
+ const scoreSpread = bestScore - secondScore;
768
+ const uncertainty = Math.max(0, 1 - scoreSpread - confidence * 0.5);
769
+ // Escalate if uncertainty is too high.
770
+ //
771
+ // #2250 — `uncertainty` here is structurally ~0.6-0.7 for low-complexity
772
+ // tasks (formula: `1 - scoreSpread - confidence*0.5`, where `scoreSpread`
773
+ // is a raw 0-1 difference between bandit-sampled scores that rarely
774
+ // exceeds 0.1). With `maxUncertainty = 0.15` the gate fires on
775
+ // ~every trivial route, promoting `sonnet→opus` and `haiku→sonnet`
776
+ // even when the Thompson sampler has *already* suppressed the higher
777
+ // tier (e.g. opus `Beta(3.8, 17.2)`, mean ≈ 0.18). The learned
778
+ // suppression is computed and then discarded one line later.
779
+ //
780
+ // Guard: skip the escalation when EITHER (a) the bandit has confidently
781
+ // learned the escalation target performs WORSE than the selected model,
782
+ // OR (b) the bandit has a confident, decent posterior on the selected
783
+ // model — i.e. the Thompson sampler picked this tier on real evidence,
784
+ // not a coin flip. Cold-start priors (Beta(1,1), α+β=2, mean=0.5) fail
785
+ // both checks, so unlearned routers still escalate as before.
786
+ let model = bestModel;
787
+ if (uncertainty > this.config.maxUncertainty && bestModel !== 'opus') {
788
+ const escalateTo = bestModel === 'haiku' ? 'sonnet' : 'opus';
789
+ const selectedMean = priorMean(priors[bestModel]);
790
+ const targetMean = priorMean(priors[escalateTo]);
791
+ const targetWorse = targetMean < selectedMean - 0.10;
792
+ // Treat the selected model as trusted once the bandit has accumulated
793
+ // ~5 effective observations AND its mean is at least 0.45 (neutral-or-
794
+ // better). Both thresholds chosen to keep cold-start behavior identical
795
+ // while honoring any non-trivial learning.
796
+ const selectedSamples = priors[bestModel].alpha + priors[bestModel].beta;
797
+ const selectedTrusted = selectedSamples >= 5 && selectedMean >= 0.45;
798
+ // ADR-148 — additional trust path: when the neural prior agrees with
799
+ // the bandit's pick (i.e. neuralPrior.qualities[bestModel] is the
800
+ // highest), the neural backend's signal is treated as a vote of
801
+ // confidence that lets us skip escalation. Without this, cold-start
802
+ // installations stay stuck in the structurally-high-uncertainty
803
+ // regime (#2250) and the neural's clear preference never reaches
804
+ // the final pick. The neural prior's top is computed as the max
805
+ // quality over the supplied candidates.
806
+ let neuralEndorsesPick = false;
807
+ if (neuralPrior) {
808
+ let bestNeuralQ = -1;
809
+ let neuralTop = null;
810
+ for (const [m, q] of Object.entries(neuralPrior.qualities)) {
811
+ if (q > bestNeuralQ) {
812
+ bestNeuralQ = q;
813
+ neuralTop = m;
814
+ }
815
+ }
816
+ if (neuralTop === bestModel)
817
+ neuralEndorsesPick = true;
818
+ }
819
+ if (!targetWorse && !selectedTrusted && !neuralEndorsesPick) {
820
+ model = escalateTo;
821
+ }
822
+ }
823
+ return { model, confidence, uncertainty };
824
+ }
825
+ /**
826
+ * Build human-readable reasoning
827
+ */
828
+ buildReasoning(model, complexity, confidence) {
829
+ const parts = [];
830
+ parts.push(`Complexity: ${(complexity.score * 100).toFixed(0)}%`);
831
+ if (complexity.indicators.high.length > 0) {
832
+ parts.push(`High-complexity indicators: ${complexity.indicators.high.join(', ')}`);
833
+ }
834
+ parts.push(`Confidence: ${(confidence * 100).toFixed(0)}%`);
835
+ parts.push(`Model: ${model} - ${MODEL_CAPABILITIES[model].description}`);
836
+ if (this.config.enableCostOptimization) {
837
+ parts.push(`Cost: ${MODEL_CAPABILITIES[model].costMultiplier}x baseline`);
838
+ }
839
+ return parts.join(' | ');
840
+ }
841
+ /**
842
+ * Track routing decision for learning
843
+ */
844
+ trackDecision(task, result) {
845
+ this.decisionCount++;
846
+ this.state.totalDecisions++;
847
+ this.state.modelDistribution[result.model] =
848
+ (this.state.modelDistribution[result.model] || 0) + 1;
849
+ // ADR-148 — operational counters for hooks_intelligence_stats.
850
+ this.routedByCounts[result.routedBy]++;
851
+ if (result.neuralBackend)
852
+ this.neuralBackendCounts[result.neuralBackend]++;
853
+ // Update running averages
854
+ const n = this.state.totalDecisions;
855
+ this.state.avgComplexity =
856
+ (this.state.avgComplexity * (n - 1) + result.complexity) / n;
857
+ this.state.avgConfidence =
858
+ (this.state.avgConfidence * (n - 1) + result.confidence) / n;
859
+ // Auto-save periodically
860
+ if (this.decisionCount % this.config.autoSaveInterval === 0) {
861
+ this.saveState();
862
+ }
863
+ }
864
+ /**
865
+ * Record outcome for learning
866
+ */
867
+ recordOutcome(task, model, outcome) {
868
+ // Update circuit breaker state
869
+ if (outcome === 'failure') {
870
+ this.consecutiveFailures[model]++;
871
+ }
872
+ else {
873
+ this.consecutiveFailures[model] = 0;
874
+ }
875
+ // Re-derive this task's complexity bucket from the task string (the MCP
876
+ // outcome payload carries no complexity), using the SAME analyzeComplexity
877
+ // path route() uses so record-time and select-time buckets match.
878
+ const taskScore = this.analyzeComplexity(task).score;
879
+ const bucket = complexityBucket(taskScore);
880
+ // Track in history (record THIS task's score, not the running average)
881
+ this.state.learningHistory.push({
882
+ task: task.slice(0, 100),
883
+ model,
884
+ complexity: taskScore,
885
+ outcome,
886
+ timestamp: new Date().toISOString(),
887
+ });
888
+ // Keep history bounded
889
+ if (this.state.learningHistory.length > 100) {
890
+ this.state.learningHistory = this.state.learningHistory.slice(-100);
891
+ }
892
+ if (outcome === 'failure') {
893
+ this.state.circuitBreakerTrips++;
894
+ }
895
+ // Thompson sampling update (#1772): cost-adjusted Bernoulli reward.
896
+ // Haiku-success > Sonnet-success > Opus-success (Opus on simple tasks
897
+ // is wasteful even when correct). Failure/escalation always β++.
898
+ if (!this.state.priors)
899
+ this.state.priors = defaultBucketedPriors();
900
+ const bp = this.state.priors[bucket] ?? (this.state.priors[bucket] = defaultBanditPriors());
901
+ const reward = BANDIT_REWARDS[model]?.[outcome] ?? 0.5;
902
+ bp[model].alpha += reward;
903
+ bp[model].beta += 1 - reward;
904
+ this.saveState();
905
+ }
906
+ /**
907
+ * ADR-149 — record an outcome keyed by the CONCRETE model id (e.g.
908
+ * 'inclusionai/ling-2.6-flash') rather than the tier label. Updates the
909
+ * shadow `priorsById` state without affecting `priors` (tier priors).
910
+ *
911
+ * This is the per-model learning signal the bandit needs to eventually
912
+ * distinguish GPT-4.1 from Sonnet within the 'sonnet' tier. Selection
913
+ * currently still uses tier priors; this state accumulates so a future
914
+ * refactor can switch the selector over once there's enough data.
915
+ *
916
+ * Cost-adjusted reward semantics: cheap models get the highest reward on
917
+ * success (their successes are most cost-efficient). We map modelId to
918
+ * its closest tier for the reward table — the routing math doesn't have
919
+ * a per-modelId reward configuration yet.
920
+ */
921
+ recordOutcomeByModelId(task, modelId, outcome) {
922
+ if (!modelId || typeof modelId !== 'string')
923
+ return;
924
+ const taskScore = this.analyzeComplexity(task).score;
925
+ const bucket = complexityBucket(taskScore);
926
+ if (!this.state.priorsById)
927
+ this.state.priorsById = defaultBucketedPriorsById();
928
+ let perBucket = this.state.priorsById[bucket];
929
+ if (!perBucket) {
930
+ perBucket = {};
931
+ this.state.priorsById[bucket] = perBucket;
932
+ }
933
+ if (!perBucket[modelId])
934
+ perBucket[modelId] = { alpha: 1, beta: 1 };
935
+ // Reward proxy: derive a tier-equivalent for cost weighting. Substring
936
+ // match keeps it cheap and accurate for the candidates in the registry.
937
+ const id = modelId.toLowerCase();
938
+ const tierProxy = id.includes('haiku') || id.includes('ling-') || id.includes('flash-lite')
939
+ || id.includes('nemotron-nano') || id.includes('ministral')
940
+ || id.includes('llama-3.2-3b') || id.includes('llama-3.1-8b')
941
+ ? 'haiku'
942
+ : id.includes('opus') ? 'opus' : 'sonnet';
943
+ const reward = BANDIT_REWARDS[tierProxy]?.[outcome] ?? 0.5;
944
+ perBucket[modelId].alpha += reward;
945
+ perBucket[modelId].beta += 1 - reward;
946
+ // Bump the schema version on first per-modelId write so downstream
947
+ // tooling can see v3 was reached (the version field stays at 3 once set).
948
+ if ((this.state.version ?? 0) < 3)
949
+ this.state.version = 3;
950
+ this.saveState();
951
+ }
952
+ /**
953
+ * Get router statistics
954
+ */
955
+ getStats() {
956
+ return {
957
+ totalDecisions: this.state.totalDecisions,
958
+ modelDistribution: { ...this.state.modelDistribution },
959
+ avgComplexity: this.state.avgComplexity,
960
+ avgConfidence: this.state.avgConfidence,
961
+ circuitBreakerTrips: this.state.circuitBreakerTrips,
962
+ consecutiveFailures: { ...this.consecutiveFailures },
963
+ routedByCounts: { ...this.routedByCounts },
964
+ neuralBackendCounts: { ...this.neuralBackendCounts },
965
+ ab: {
966
+ comparisons: this.abComparisons,
967
+ disagreements: this.abDisagreements,
968
+ disagreementRate: this.abComparisons > 0 ? this.abDisagreements / this.abComparisons : 0,
969
+ },
970
+ stateVersion: this.state.version ?? 2,
971
+ ...(this.state.priorsById ? { priorsById: this.state.priorsById } : {}),
972
+ };
973
+ }
974
+ /**
975
+ * Load state from disk
976
+ */
977
+ loadState() {
978
+ const defaultState = {
979
+ totalDecisions: 0,
980
+ modelDistribution: { haiku: 0, sonnet: 0, opus: 0, inherit: 0 },
981
+ avgComplexity: 0.5,
982
+ avgConfidence: 0.8,
983
+ circuitBreakerTrips: 0,
984
+ lastUpdated: new Date().toISOString(),
985
+ learningHistory: [],
986
+ version: 2,
987
+ priors: defaultBucketedPriors(),
988
+ };
989
+ try {
990
+ const fullPath = join(process.cwd(), this.config.statePath);
991
+ if (existsSync(fullPath)) {
992
+ const data = readFileSync(fullPath, 'utf-8');
993
+ const loaded = JSON.parse(data);
994
+ // ADR-142: forward-migrate priors of ANY layout (missing / flat v1 /
995
+ // already-bucketed) to the bucketed shape without data loss or throwing.
996
+ loaded.priors = migratePriors(loaded.priors);
997
+ loaded.version = 2;
998
+ return { ...defaultState, ...loaded };
999
+ }
1000
+ }
1001
+ catch {
1002
+ // Ignore load errors
1003
+ }
1004
+ return defaultState;
1005
+ }
1006
+ /**
1007
+ * Save state to disk
1008
+ */
1009
+ saveState() {
1010
+ try {
1011
+ const fullPath = join(process.cwd(), this.config.statePath);
1012
+ const dir = dirname(fullPath);
1013
+ if (!existsSync(dir)) {
1014
+ mkdirSync(dir, { recursive: true });
1015
+ }
1016
+ this.state.lastUpdated = new Date().toISOString();
1017
+ writeFileSync(fullPath, JSON.stringify(this.state, null, 2));
1018
+ }
1019
+ catch {
1020
+ // Ignore save errors in non-critical scenarios
1021
+ }
1022
+ }
1023
+ /**
1024
+ * Reset router state
1025
+ */
1026
+ reset() {
1027
+ this.state = {
1028
+ totalDecisions: 0,
1029
+ modelDistribution: { haiku: 0, sonnet: 0, opus: 0, inherit: 0 },
1030
+ avgComplexity: 0.5,
1031
+ avgConfidence: 0.8,
1032
+ circuitBreakerTrips: 0,
1033
+ lastUpdated: new Date().toISOString(),
1034
+ learningHistory: [],
1035
+ version: 2,
1036
+ priors: defaultBucketedPriors(),
1037
+ };
1038
+ this.consecutiveFailures = { haiku: 0, sonnet: 0, opus: 0, inherit: 0 };
1039
+ this.decisionCount = 0;
1040
+ this.saveState();
1041
+ }
1042
+ /**
1043
+ * Public read-only accessor for the bandit priors. Useful for tests,
1044
+ * dashboards, and the pending hooks_intelligence_stats integration that
1045
+ * surfaces convergence in the dashboard. Returns a copy.
1046
+ */
1047
+ getBanditPriors(bucket = 'med') {
1048
+ const bucketed = this.state.priors ?? defaultBucketedPriors();
1049
+ const p = bucketed[bucket] ?? defaultBanditPriors();
1050
+ return {
1051
+ haiku: { ...p.haiku },
1052
+ sonnet: { ...p.sonnet },
1053
+ opus: { ...p.opus },
1054
+ inherit: { ...p.inherit },
1055
+ };
1056
+ }
1057
+ /** All bucketed priors (copy) — for dashboards/tests. */
1058
+ getBucketedPriors() {
1059
+ const b = this.state.priors ?? defaultBucketedPriors();
1060
+ return {
1061
+ low: clonePriors(b.low ?? defaultBanditPriors()),
1062
+ med: clonePriors(b.med ?? defaultBanditPriors()),
1063
+ high: clonePriors(b.high ?? defaultBanditPriors()),
1064
+ };
1065
+ }
1066
+ }
1067
+ // ============================================================================
1068
+ // Singleton & Factory Functions
1069
+ // ============================================================================
1070
+ let modelRouterInstance = null;
1071
+ /**
1072
+ * Get or create the singleton ModelRouter instance
1073
+ */
1074
+ export function getModelRouter(config) {
1075
+ if (!modelRouterInstance) {
1076
+ modelRouterInstance = new ModelRouter(config);
1077
+ }
1078
+ return modelRouterInstance;
1079
+ }
1080
+ /**
1081
+ * Reset the singleton instance
1082
+ */
1083
+ export function resetModelRouter() {
1084
+ modelRouterInstance = null;
1085
+ }
1086
+ /**
1087
+ * Create a new ModelRouter instance (non-singleton)
1088
+ */
1089
+ export function createModelRouter(config) {
1090
+ return new ModelRouter(config);
1091
+ }
1092
+ // ============================================================================
1093
+ // Convenience Functions
1094
+ // ============================================================================
1095
+ /**
1096
+ * Quick route function for common use case
1097
+ */
1098
+ export async function routeToModel(task) {
1099
+ const router = getModelRouter();
1100
+ const result = await router.route(task);
1101
+ return result.model;
1102
+ }
1103
+ /**
1104
+ * Route with full result
1105
+ */
1106
+ export async function routeToModelFull(task, embedding) {
1107
+ const router = getModelRouter();
1108
+ return router.route(task, embedding);
1109
+ }
1110
+ /**
1111
+ * Analyze task complexity without routing
1112
+ */
1113
+ export function analyzeTaskComplexity(task) {
1114
+ const router = getModelRouter();
1115
+ return router.analyzeComplexity(task, undefined);
1116
+ }
1117
+ /**
1118
+ * Get model router statistics
1119
+ */
1120
+ export function getModelRouterStats() {
1121
+ const router = getModelRouter();
1122
+ return router.getStats();
1123
+ }
1124
+ /**
1125
+ * Record routing outcome for learning
1126
+ */
1127
+ export function recordModelOutcome(task, model, outcome) {
1128
+ const router = getModelRouter();
1129
+ router.recordOutcome(task, model, outcome);
1130
+ }
1131
+ /**
1132
+ * ADR-149 — record an outcome keyed by the concrete model id rather than
1133
+ * the tier label. Updates the shadow `priorsById` state. Selection logic
1134
+ * still uses tier priors; this data accumulates for a future per-modelId
1135
+ * selector refactor.
1136
+ *
1137
+ * Safe to call alongside `recordModelOutcome` — they update independent
1138
+ * state slices so double-counting is impossible.
1139
+ */
1140
+ export function recordModelOutcomeByModelId(task, modelId, outcome) {
1141
+ const router = getModelRouter();
1142
+ router.recordOutcomeByModelId(task, modelId, outcome);
1143
+ }
1144
+ /**
1145
+ * ADR-149 iter 14 — read-only access to the per-modelId Beta priors. The
1146
+ * neural-router consumes this to apply per-model Thompson sampling on top
1147
+ * of its predicted-quality vector when CLAUDE_FLOW_ROUTER_BANDIT_PER_MODEL=1.
1148
+ * Returns the legacy bucketed priors (`priorsById[bucket][modelId]`) when
1149
+ * present, else null.
1150
+ */
1151
+ export function getModelRouterPriorsById() {
1152
+ const router = getModelRouter();
1153
+ const stats = router.getStats();
1154
+ return stats.priorsById ?? null;
1155
+ }
1156
+ /**
1157
+ * Re-export the complexity-bucket helper so the neural-router (which gets
1158
+ * the task text via the route() call) can map a complexity score to the
1159
+ * matching bandit bucket.
1160
+ */
1161
+ export { complexityBucket };
1162
+ //# sourceMappingURL=model-router.js.map