claude-flow 3.7.0-alpha.3 → 3.7.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  [![Ruflo Banner](ruflo/assets/ruflo-small.jpeg)](https://flo.ruv.io/)
4
4
 
5
- [![Try the UI Beta — flo.ruv.io](https://img.shields.io/badge/✨_Try_the_UI_Beta-flo.ruv.io-6366f1?style=for-the-badge&logoColor=white&logo=svelte)](https://flo.ruv.io/)
6
- [![🎯 Goal Planner — goal.ruv.io](https://img.shields.io/badge/🎯_Goal_Planner-goal.ruv.io-8b5cf6?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/)
7
- [![🤖 Live Agents — goal.ruv.io/agents](https://img.shields.io/badge/🤖_Live_Agents-goal.ruv.io%2Fagents-10b981?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/agents)
5
+ [![Try the UI Beta — flo.ruv.io](https://img.shields.io/badge/_Try_the_UI_Beta-flo.ruv.io-6366f1?style=for-the-badge&logoColor=white&logo=svelte)](https://flo.ruv.io/)
6
+ [![Goal Planner — goal.ruv.io](https://img.shields.io/badge/_Goal_Planner-goal.ruv.io-8b5cf6?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/)
7
+ [![Live Agents — goal.ruv.io/agents](https://img.shields.io/badge/_Live_Agents-goal.ruv.io%2Fagents-10b981?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/agents)
8
8
 
9
9
  [![Star on GitHub](https://img.shields.io/github/stars/ruvnet/claude-flow?style=for-the-badge&logo=github&color=gold)](https://github.com/ruvnet/claude-flow)
10
10
  [![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](https://opensource.org/licenses/MIT)
11
- [![Claude Code](https://img.shields.io/badge/Claude%20Code-Plugin-green?style=for-the-badge&logo=anthropic)](https://github.com/ruvnet/claude-flow)
11
+ [![Claude Code](https://img.shields.io/badge/Claude%20Code-Plugin-D97757?style=for-the-badge&logoColor=white&logo=anthropic)](https://github.com/ruvnet/claude-flow)
12
+ [![Codex Plugin](https://img.shields.io/badge/Codex-Plugin-412991?style=for-the-badge&logoColor=white&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0yMi4yODIgOS44MjFhNS45ODUgNS45ODUgMCAwIDAtLjUxNi00LjkxIDYuMDQ2IDYuMDQ2IDAgMCAwLTYuNTEtMi45QTYuMDY1IDYuMDY1IDAgMCAwIDQuOTgxIDQuMThhNS45ODUgNS45ODUgMCAwIDAtMy45OTggMi45IDYuMDQ2IDYuMDQ2IDAgMCAwIC43NDMgNy4wOTcgNS45OCA1Ljk4IDAgMCAwIC41MSA0LjkxMSA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNSAyLjlBNS45ODUgNS45ODUgMCAwIDAgMTMuMjYgMjRhNi4wNTYgNi4wNTYgMCAwIDAgNS43NzItNC4yMDYgNS45OSA1Ljk5IDAgMCAwIDMuOTk4LTIuOSA2LjA1NiA2LjA1NiAwIDAgMC0uNzQ3LTcuMDczek0xMy4yNiAyMi40M2E0LjQ3NiA0LjQ3NiAwIDAgMS0yLjg3Ni0xLjA0bC4xNDItLjA4IDQuNzc4LTIuNzU4YS43OTUuNzk1IDAgMCAwIC4zOTMtLjY4MXYtNi43MzdsMi4wMiAxLjE2OGEuMDcxLjA3MSAwIDAgMSAuMDM4LjA1MnY1LjU4M2E0LjUwNCA0LjUwNCAwIDAgMS00LjQ5NSA0LjQ5NHpNMy42IDE4LjMwNGE0LjQ3IDQuNDcgMCAwIDEtLjUzNS0zLjAxNGwuMTQyLjA4NSA0Ljc4MyAyLjc1OWEuNzcxLjc3MSAwIDAgMCAuNzgxIDBsNS44NDMtMy4zNjl2Mi4zMzJhLjA4LjA4IDAgMCAxLS4wMzMuMDYyTDkuNzQgMTkuOTVhNC41IDQuNSAwIDAgMS02LjE0LTEuNjQ2ek0yLjM0IDcuODk2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY2LTEuOTczVjExLjZhLjc2Ni43NjYgMCAwIDAgLjM4OC42NzdsNS44MTUgMy4zNTQtMi4wMiAxLjE2OGEuMDc2LjA3NiAwIDAgMS0uMDcyIDBsLTQuODMtMi43ODZBNC41MDQgNC41MDQgMCAwIDEgMi4zNCA3Ljg3MnptMTYuNTk3IDMuODU1LTUuODMzLTMuMzg3IDIuMDE2LTEuMTY1YS4wNzYuMDc2IDAgMCAxIC4wNzEgMGw0LjgzIDIuNzkxYTQuNDk0IDQuNDk0IDAgMCAxLS42NzYgOC4xMDR2LTUuNjc3YS43OS43OSAwIDAgMC0uNDA3LS42Njd6bTIuMDEtMy4wMjMtLjE0MS0uMDg1LTQuNzc0LTIuNzgyYS43NzYuNzc2IDAgMCAwLS43ODUgMEw5LjQwOSA5LjIzVjYuODk3YS4wNjYuMDY2IDAgMCAxIC4wMjgtLjA2Mmw0LjgzLTIuNzg3YTQuNDk5IDQuNDk5IDAgMCAxIDYuNjggNC42NnpNOC4zMDcgMTIuODYzbC0yLjAyLTEuMTY0YS4wOC4wOCAwIDAgMS0uMDM4LS4wNTdWNi4wNzRhNC40OTkgNC40OTkgMCAwIDEgNy4zNzYtMy40NTRsLS4xNDIuMDgtNC43NzggMi43NThhLjc5NS43OTUgMCAwIDAtLjM5My42ODJ6bTEuMDk3LTIuMzY2IDIuNjAyLTEuNSAyLjYwNyAxLjV2Mi45OTlsLTIuNTk3IDEuNS0yLjYwNy0xLjVaIi8%2BPC9zdmc%2B)](https://www.npmjs.com/package/@claude-flow/codex)
13
+ [![🕸️ RuVector Graph Ai](https://img.shields.io/badge/RuVector_Agentic-DB-06b6d4?style=for-the-badge&logoColor=white&logo=graphql)](https://github.com/ruvnet/ruvector)
12
14
 
13
15
  # Ruflo
14
16
 
@@ -20,12 +22,12 @@ Orchestrate 100+ specialized AI agents across machines, teams, and trust boundar
20
22
 
21
23
  ### Why Ruflo?
22
24
 
23
- > Claude Flow is now Ruflo — named by rUv, who loves Rust, flow states, and building things that feel inevitable. The "Ru" is the Ruv. The "flo" is the flow. Underneath, WASM kernels written in Rust power the policy engine, embeddings, and proof system.
25
+ > Claude Flow is now Ruflo — named by [`rUv`](https://ruv.io), who loves Rust, flow states, and building things that feel inevitable. The "Ru" is the rUv. The "flo" is working until 3am. Underneath, powered by [`Cognitum.One`](https://cognitum.one/?RuFlo) agentic architecture, running a supercharged Rust based AI engine, embeddings, memory, and plugin system.
24
26
 
25
27
 
26
28
  ### What Ruflo Does
27
29
 
28
- One `init` gives Claude Code a nervous system: agents self-organize into swarms, learn from every task, remember across sessions, and — with federation — securely talk to agents on other machines without leaking data. You keep writing code. Ruflo handles the coordination.
30
+ One `npx ruvflo init` gives Claude Code a nervous system: agents self-organize into swarms, learn from every task, remember across sessions, and — with federation — securely talk to agents on other machines without leaking data. You keep writing code. Ruflo handles the coordination.
29
31
 
30
32
  ```
31
33
  Self-Learning / Self-Optimizing Agent Architecture
@@ -69,7 +71,7 @@ There are **two different install paths** with very different surface areas. Pic
69
71
  This adds slash commands and agent definitions only. The Ruflo MCP server is NOT registered, so `memory_store`, `swarm_init`, `agent_spawn`, etc. won't be callable from Claude. For the full loop, use Path B below.
70
72
 
71
73
  <details>
72
- <summary><strong>All 32 plugins</strong></summary>
74
+ <summary><strong>🔌 All 32 plugins</strong></summary>
73
75
 
74
76
  #### Core & Orchestration
75
77
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.7.0-alpha.3",
3
+ "version": "3.7.0-alpha.5",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -2,13 +2,15 @@
2
2
 
3
3
  [![Ruflo Banner](ruflo/assets/ruflo-small.jpeg)](https://flo.ruv.io/)
4
4
 
5
- [![Try the UI Beta — flo.ruv.io](https://img.shields.io/badge/✨_Try_the_UI_Beta-flo.ruv.io-6366f1?style=for-the-badge&logoColor=white&logo=svelte)](https://flo.ruv.io/)
6
- [![🎯 Goal Planner — goal.ruv.io](https://img.shields.io/badge/🎯_Goal_Planner-goal.ruv.io-8b5cf6?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/)
7
- [![🤖 Live Agents — goal.ruv.io/agents](https://img.shields.io/badge/🤖_Live_Agents-goal.ruv.io%2Fagents-10b981?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/agents)
5
+ [![Try the UI Beta — flo.ruv.io](https://img.shields.io/badge/_Try_the_UI_Beta-flo.ruv.io-6366f1?style=for-the-badge&logoColor=white&logo=svelte)](https://flo.ruv.io/)
6
+ [![Goal Planner — goal.ruv.io](https://img.shields.io/badge/_Goal_Planner-goal.ruv.io-8b5cf6?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/)
7
+ [![Live Agents — goal.ruv.io/agents](https://img.shields.io/badge/_Live_Agents-goal.ruv.io%2Fagents-10b981?style=for-the-badge&logoColor=white&logo=react)](https://goal.ruv.io/agents)
8
8
 
9
9
  [![Star on GitHub](https://img.shields.io/github/stars/ruvnet/claude-flow?style=for-the-badge&logo=github&color=gold)](https://github.com/ruvnet/claude-flow)
10
10
  [![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](https://opensource.org/licenses/MIT)
11
- [![Claude Code](https://img.shields.io/badge/Claude%20Code-Plugin-green?style=for-the-badge&logo=anthropic)](https://github.com/ruvnet/claude-flow)
11
+ [![Claude Code](https://img.shields.io/badge/Claude%20Code-Plugin-D97757?style=for-the-badge&logoColor=white&logo=anthropic)](https://github.com/ruvnet/claude-flow)
12
+ [![Codex Plugin](https://img.shields.io/badge/Codex-Plugin-412991?style=for-the-badge&logoColor=white&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0yMi4yODIgOS44MjFhNS45ODUgNS45ODUgMCAwIDAtLjUxNi00LjkxIDYuMDQ2IDYuMDQ2IDAgMCAwLTYuNTEtMi45QTYuMDY1IDYuMDY1IDAgMCAwIDQuOTgxIDQuMThhNS45ODUgNS45ODUgMCAwIDAtMy45OTggMi45IDYuMDQ2IDYuMDQ2IDAgMCAwIC43NDMgNy4wOTcgNS45OCA1Ljk4IDAgMCAwIC41MSA0LjkxMSA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNSAyLjlBNS45ODUgNS45ODUgMCAwIDAgMTMuMjYgMjRhNi4wNTYgNi4wNTYgMCAwIDAgNS43NzItNC4yMDYgNS45OSA1Ljk5IDAgMCAwIDMuOTk4LTIuOSA2LjA1NiA2LjA1NiAwIDAgMC0uNzQ3LTcuMDczek0xMy4yNiAyMi40M2E0LjQ3NiA0LjQ3NiAwIDAgMS0yLjg3Ni0xLjA0bC4xNDItLjA4IDQuNzc4LTIuNzU4YS43OTUuNzk1IDAgMCAwIC4zOTMtLjY4MXYtNi43MzdsMi4wMiAxLjE2OGEuMDcxLjA3MSAwIDAgMSAuMDM4LjA1MnY1LjU4M2E0LjUwNCA0LjUwNCAwIDAgMS00LjQ5NSA0LjQ5NHpNMy42IDE4LjMwNGE0LjQ3IDQuNDcgMCAwIDEtLjUzNS0zLjAxNGwuMTQyLjA4NSA0Ljc4MyAyLjc1OWEuNzcxLjc3MSAwIDAgMCAuNzgxIDBsNS44NDMtMy4zNjl2Mi4zMzJhLjA4LjA4IDAgMCAxLS4wMzMuMDYyTDkuNzQgMTkuOTVhNC41IDQuNSAwIDAgMS02LjE0LTEuNjQ2ek0yLjM0IDcuODk2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY2LTEuOTczVjExLjZhLjc2Ni43NjYgMCAwIDAgLjM4OC42NzdsNS44MTUgMy4zNTQtMi4wMiAxLjE2OGEuMDc2LjA3NiAwIDAgMS0uMDcyIDBsLTQuODMtMi43ODZBNC41MDQgNC41MDQgMCAwIDEgMi4zNCA3Ljg3MnptMTYuNTk3IDMuODU1LTUuODMzLTMuMzg3IDIuMDE2LTEuMTY1YS4wNzYuMDc2IDAgMCAxIC4wNzEgMGw0LjgzIDIuNzkxYTQuNDk0IDQuNDk0IDAgMCAxLS42NzYgOC4xMDR2LTUuNjc3YS43OS43OSAwIDAgMC0uNDA3LS42Njd6bTIuMDEtMy4wMjMtLjE0MS0uMDg1LTQuNzc0LTIuNzgyYS43NzYuNzc2IDAgMCAwLS43ODUgMEw5LjQwOSA5LjIzVjYuODk3YS4wNjYuMDY2IDAgMCAxIC4wMjgtLjA2Mmw0LjgzLTIuNzg3YTQuNDk5IDQuNDk5IDAgMCAxIDYuNjggNC42NnpNOC4zMDcgMTIuODYzbC0yLjAyLTEuMTY0YS4wOC4wOCAwIDAgMS0uMDM4LS4wNTdWNi4wNzRhNC40OTkgNC40OTkgMCAwIDEgNy4zNzYtMy40NTRsLS4xNDIuMDgtNC43NzggMi43NThhLjc5NS43OTUgMCAwIDAtLjM5My42ODJ6bTEuMDk3LTIuMzY2IDIuNjAyLTEuNSAyLjYwNyAxLjV2Mi45OTlsLTIuNTk3IDEuNS0yLjYwNy0xLjVaIi8%2BPC9zdmc%2B)](https://www.npmjs.com/package/@claude-flow/codex)
13
+ [![🕸️ RuVector Graph Ai](https://img.shields.io/badge/RuVector_Agentic-DB-06b6d4?style=for-the-badge&logoColor=white&logo=graphql)](https://github.com/ruvnet/ruvector)
12
14
 
13
15
  # Ruflo
14
16
 
@@ -20,12 +22,12 @@ Orchestrate 100+ specialized AI agents across machines, teams, and trust boundar
20
22
 
21
23
  ### Why Ruflo?
22
24
 
23
- > Claude Flow is now Ruflo — named by rUv, who loves Rust, flow states, and building things that feel inevitable. The "Ru" is the Ruv. The "flo" is the flow. Underneath, WASM kernels written in Rust power the policy engine, embeddings, and proof system.
25
+ > Claude Flow is now Ruflo — named by [`rUv`](https://ruv.io), who loves Rust, flow states, and building things that feel inevitable. The "Ru" is the rUv. The "flo" is working until 3am. Underneath, powered by [`Cognitum.One`](https://cognitum.one/?RuFlo) agentic architecture, running a supercharged Rust based AI engine, embeddings, memory, and plugin system.
24
26
 
25
27
 
26
28
  ### What Ruflo Does
27
29
 
28
- One `init` gives Claude Code a nervous system: agents self-organize into swarms, learn from every task, remember across sessions, and — with federation — securely talk to agents on other machines without leaking data. You keep writing code. Ruflo handles the coordination.
30
+ One `npx ruvflo init` gives Claude Code a nervous system: agents self-organize into swarms, learn from every task, remember across sessions, and — with federation — securely talk to agents on other machines without leaking data. You keep writing code. Ruflo handles the coordination.
29
31
 
30
32
  ```
31
33
  Self-Learning / Self-Optimizing Agent Architecture
@@ -69,7 +71,7 @@ There are **two different install paths** with very different surface areas. Pic
69
71
  This adds slash commands and agent definitions only. The Ruflo MCP server is NOT registered, so `memory_store`, `swarm_init`, `agent_spawn`, etc. won't be callable from Claude. For the full loop, use Path B below.
70
72
 
71
73
  <details>
72
- <summary><strong>All 32 plugins</strong></summary>
74
+ <summary><strong>🔌 All 32 plugins</strong></summary>
73
75
 
74
76
  #### Core & Orchestration
75
77
 
@@ -662,7 +662,19 @@ export const neuralTools = [
662
662
  features: {
663
663
  hnsw: true,
664
664
  quantization: true,
665
- flashAttention: false,
665
+ // #1770: probe the real loader instead of returning a literal false.
666
+ // Was hardcoded false, which contradicted hooks_intelligence_stats's
667
+ // simultaneous claim of `implementation: real-flash-attention`.
668
+ // The two surfaces now agree on a single source of truth.
669
+ flashAttention: await (async () => {
670
+ try {
671
+ const { getFlashAttention } = await import('../ruvector/flash-attention.js');
672
+ return getFlashAttention() !== null;
673
+ }
674
+ catch {
675
+ return false;
676
+ }
677
+ })(),
666
678
  reasoningBank: true,
667
679
  },
668
680
  };
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
14
  import { homedir } from 'node:os';
15
+ import { createRequire } from 'node:module';
15
16
  import { join } from 'node:path';
16
17
  // ============================================================================
17
18
  // Persistence Configuration
@@ -563,21 +564,37 @@ class LocalReasoningBank {
563
564
  // ============================================================================
564
565
  let ruvllmCoordinator = null;
565
566
  let ruvllmLoaded = false;
566
- async function loadRuvllmCoordinator() {
567
+ /**
568
+ * Synchronously load the @ruvector/ruvllm SonaCoordinator. Used both by the
569
+ * async init path (initializeIntelligence) and by sync stat readers like
570
+ * getIntelligenceStats — the dashboard would otherwise report "unavailable"
571
+ * when stats are queried before any async init has fired (#1770).
572
+ */
573
+ function loadRuvllmCoordinatorSync() {
567
574
  if (ruvllmLoaded)
568
575
  return ruvllmCoordinator;
569
576
  ruvllmLoaded = true;
570
577
  try {
571
- const { createRequire } = await import('module');
572
578
  const requireCjs = createRequire(import.meta.url);
573
579
  const ruvllm = requireCjs('@ruvector/ruvllm');
574
580
  ruvllmCoordinator = new ruvllm.SonaCoordinator(ruvllm.DEFAULT_SONA_CONFIG);
575
581
  return ruvllmCoordinator;
576
582
  }
577
- catch {
583
+ catch (err) {
584
+ // Surface the reason on debug builds so future regressions of #1770 don't
585
+ // disappear silently. Stays quiet by default to avoid noise on the cli's
586
+ // hot path (e.g., npx invocations).
587
+ if (process.env.CLAUDE_FLOW_DEBUG) {
588
+ // eslint-disable-next-line no-console
589
+ console.error('[ruvllm] SonaCoordinator load failed, falling back to JS:', err.message);
590
+ }
591
+ ruvllmCoordinator = null;
578
592
  return null;
579
593
  }
580
594
  }
595
+ async function loadRuvllmCoordinator() {
596
+ return loadRuvllmCoordinatorSync();
597
+ }
581
598
  // ============================================================================
582
599
  // Module State
583
600
  // ============================================================================
@@ -879,6 +896,14 @@ export async function findSimilarPatterns(query, options) {
879
896
  export function getIntelligenceStats() {
880
897
  const sonaStats = sonaCoordinator?.stats();
881
898
  const bankStats = reasoningBank?.stats();
899
+ // Lazy-init the ruvllm coordinator if it hasn't been loaded yet. The MCP
900
+ // dashboard (`hooks_intelligence_stats`) hits this path before any
901
+ // initializeIntelligence() call has fired, so the coordinator field would
902
+ // otherwise stay null and the dashboard would report "unavailable" even
903
+ // when @ruvector/ruvllm is fully resolvable. Sync require — cheap, idempotent.
904
+ if (!ruvllmLoaded) {
905
+ loadRuvllmCoordinatorSync();
906
+ }
882
907
  const ruvllmStats = ruvllmCoordinator?.stats?.() || null;
883
908
  // Fetch cross-module stats for unified reporting
884
909
  let contrastiveTrainer = 'unavailable';
@@ -104,6 +104,15 @@ export interface ComplexityAnalysis {
104
104
  uncertaintyLevel: number;
105
105
  };
106
106
  }
107
+ /**
108
+ * Beta(α, β) prior for Thompson sampling. Each model carries one of these;
109
+ * outcomes update α (successes) and β (failures) so the router auto-balances
110
+ * cost/quality without manual threshold tuning. See ADR-101.
111
+ */
112
+ export interface BetaPrior {
113
+ alpha: number;
114
+ beta: number;
115
+ }
107
116
  /**
108
117
  * Intelligent Model Router using complexity-based routing
109
118
  */
@@ -146,7 +155,13 @@ export declare class ModelRouter {
146
155
  */
147
156
  private applyCircuitBreaker;
148
157
  /**
149
- * Select the best model from scores
158
+ * Select the best model from scores. Uses Thompson sampling (#1772):
159
+ * each model's deterministic complexity score is multiplied by a draw
160
+ * θ_m ~ Beta(α_m, β_m) from its bandit prior. Models with strong empirical
161
+ * track records get sampled higher; models with poor outcomes get sampled
162
+ * lower; the system auto-corrects against tier overuse without manual
163
+ * threshold tuning. Beta(1,1) = uniform on cold start so behavior matches
164
+ * the prior deterministic router until outcomes accumulate.
150
165
  */
151
166
  private selectModel;
152
167
  /**
@@ -184,6 +199,12 @@ export declare class ModelRouter {
184
199
  * Reset router state
185
200
  */
186
201
  reset(): void;
202
+ /**
203
+ * Public read-only accessor for the bandit priors. Useful for tests,
204
+ * dashboards, and the pending hooks_intelligence_stats integration that
205
+ * surfaces convergence in the dashboard. Returns a copy.
206
+ */
207
+ getBanditPriors(): Record<ClaudeModel, BetaPrior>;
187
208
  }
188
209
  /**
189
210
  * Get or create the singleton ModelRouter instance
@@ -67,6 +67,84 @@ export const COMPLEXITY_INDICATORS = {
67
67
  'delete', 'documentation', 'readme', 'config', 'version', 'bump',
68
68
  ],
69
69
  };
70
+ /**
71
+ * Cost-adjusted Bernoulli rewards for Thompson sampling updates. Higher
72
+ * reward when the right tier is chosen — Haiku-success > Sonnet-success >
73
+ * Opus-success because Opus-success on a simple task is wasteful even when
74
+ * the answer is correct. Escalations get partial credit at best (Sonnet) or
75
+ * zero (Haiku/Opus) since they signal the initial choice was wrong.
76
+ */
77
+ const BANDIT_REWARDS = {
78
+ haiku: { success: 1.0, failure: 0.0, escalated: 0.0 },
79
+ sonnet: { success: 0.7, failure: 0.0, escalated: 0.1 },
80
+ opus: { success: 0.4, failure: 0.0, escalated: 0.0 },
81
+ inherit: { success: 0.5, failure: 0.0, escalated: 0.0 },
82
+ };
83
+ // ============================================================================
84
+ // Beta Sampling for Thompson Sampling Bandit
85
+ // ============================================================================
86
+ /**
87
+ * Standard normal sample via Box-Muller. Used by Marsaglia-Tsang Gamma.
88
+ * Module-local so the bandit doesn't pull in a heavy stats dep.
89
+ */
90
+ function sampleStandardNormal() {
91
+ const u1 = Math.random() || 1e-12; // avoid log(0)
92
+ const u2 = Math.random();
93
+ return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
94
+ }
95
+ /**
96
+ * Sample from Gamma(shape α, scale=1). Marsaglia & Tsang (2000), with the
97
+ * standard "boost α<1 by α+1 then scale by U^(1/α)" trick for shape parameters
98
+ * smaller than 1. O(1) expected, no rejection-loop pathology in practice.
99
+ */
100
+ function sampleGamma(alpha) {
101
+ if (alpha < 1) {
102
+ const u = Math.random() || 1e-12;
103
+ return sampleGamma(alpha + 1) * Math.pow(u, 1 / alpha);
104
+ }
105
+ const d = alpha - 1 / 3;
106
+ const c = 1 / Math.sqrt(9 * d);
107
+ while (true) {
108
+ let x;
109
+ let v;
110
+ do {
111
+ x = sampleStandardNormal();
112
+ v = 1 + c * x;
113
+ } while (v <= 0);
114
+ v = v * v * v;
115
+ const u = Math.random();
116
+ const xx = x * x;
117
+ if (u < 1 - 0.0331 * xx * xx)
118
+ return d * v;
119
+ if (Math.log(u) < 0.5 * xx + d * (1 - v + Math.log(v)))
120
+ return d * v;
121
+ }
122
+ }
123
+ /**
124
+ * Sample θ ~ Beta(α, β) via the identity Beta(α,β) = X / (X+Y) where
125
+ * X ~ Gamma(α), Y ~ Gamma(β). Returns the mean for degenerate α+β=0
126
+ * (shouldn't happen in practice but defensive).
127
+ */
128
+ function sampleBeta(alpha, beta) {
129
+ if (alpha <= 0 || beta <= 0)
130
+ return 0.5;
131
+ const x = sampleGamma(alpha);
132
+ const y = sampleGamma(beta);
133
+ const denom = x + y;
134
+ return denom > 0 ? x / denom : 0.5;
135
+ }
136
+ /**
137
+ * Default uniform priors (no prior knowledge). Beta(1,1) is the standard
138
+ * Bayesian-Bernoulli starting point — uniform over [0,1].
139
+ */
140
+ function defaultBanditPriors() {
141
+ return {
142
+ haiku: { alpha: 1, beta: 1 },
143
+ sonnet: { alpha: 1, beta: 1 },
144
+ opus: { alpha: 1, beta: 1 },
145
+ inherit: { alpha: 1, beta: 1 },
146
+ };
147
+ }
70
148
  // ============================================================================
71
149
  // Default Configuration
72
150
  // ============================================================================
@@ -263,15 +341,29 @@ export class ModelRouter {
263
341
  return adjusted;
264
342
  }
265
343
  /**
266
- * Select the best model from scores
344
+ * Select the best model from scores. Uses Thompson sampling (#1772):
345
+ * each model's deterministic complexity score is multiplied by a draw
346
+ * θ_m ~ Beta(α_m, β_m) from its bandit prior. Models with strong empirical
347
+ * track records get sampled higher; models with poor outcomes get sampled
348
+ * lower; the system auto-corrects against tier overuse without manual
349
+ * threshold tuning. Beta(1,1) = uniform on cold start so behavior matches
350
+ * the prior deterministic router until outcomes accumulate.
267
351
  */
268
352
  selectModel(scores, complexityScore) {
269
- // Get sorted models by score
270
- const sorted = Object.entries(scores)
353
+ // Thompson sampling: combine deterministic score with bandit posterior
354
+ const priors = this.state.priors ?? defaultBanditPriors();
355
+ const sampledScores = {
356
+ haiku: scores.haiku * sampleBeta(priors.haiku.alpha, priors.haiku.beta),
357
+ sonnet: scores.sonnet * sampleBeta(priors.sonnet.alpha, priors.sonnet.beta),
358
+ opus: scores.opus * sampleBeta(priors.opus.alpha, priors.opus.beta),
359
+ inherit: scores.inherit, // not bandit-controlled
360
+ };
361
+ // Get sorted models by sampled score (drops 'inherit' from selection)
362
+ const sorted = Object.entries(sampledScores)
271
363
  .filter(([m]) => m !== 'inherit')
272
364
  .sort((a, b) => b[1] - a[1]);
273
365
  const [bestModel, bestScore] = sorted[0];
274
- const [secondModel, secondScore] = sorted[1] || ['sonnet', 0];
366
+ const [, secondScore] = sorted[1] || ['sonnet', 0];
275
367
  // Confidence is how much better the best is vs second
276
368
  const confidence = bestScore > 0 ? Math.min(1, bestScore / (bestScore + secondScore + 0.01)) : 0.5;
277
369
  // Uncertainty based on score spread and complexity
@@ -346,6 +438,14 @@ export class ModelRouter {
346
438
  if (outcome === 'failure') {
347
439
  this.state.circuitBreakerTrips++;
348
440
  }
441
+ // Thompson sampling update (#1772): cost-adjusted Bernoulli reward.
442
+ // Haiku-success > Sonnet-success > Opus-success (Opus on simple tasks
443
+ // is wasteful even when correct). Failure/escalation always β++.
444
+ if (!this.state.priors)
445
+ this.state.priors = defaultBanditPriors();
446
+ const reward = BANDIT_REWARDS[model]?.[outcome] ?? 0.5;
447
+ this.state.priors[model].alpha += reward;
448
+ this.state.priors[model].beta += 1 - reward;
349
449
  this.saveState();
350
450
  }
351
451
  /**
@@ -373,12 +473,17 @@ export class ModelRouter {
373
473
  circuitBreakerTrips: 0,
374
474
  lastUpdated: new Date().toISOString(),
375
475
  learningHistory: [],
476
+ priors: defaultBanditPriors(),
376
477
  };
377
478
  try {
378
479
  const fullPath = join(process.cwd(), this.config.statePath);
379
480
  if (existsSync(fullPath)) {
380
481
  const data = readFileSync(fullPath, 'utf-8');
381
- return { ...defaultState, ...JSON.parse(data) };
482
+ const loaded = JSON.parse(data);
483
+ // Backfill priors for state files written by pre-bandit cli versions.
484
+ if (!loaded.priors)
485
+ loaded.priors = defaultBanditPriors();
486
+ return { ...defaultState, ...loaded };
382
487
  }
383
488
  }
384
489
  catch {
@@ -415,11 +520,26 @@ export class ModelRouter {
415
520
  circuitBreakerTrips: 0,
416
521
  lastUpdated: new Date().toISOString(),
417
522
  learningHistory: [],
523
+ priors: defaultBanditPriors(),
418
524
  };
419
525
  this.consecutiveFailures = { haiku: 0, sonnet: 0, opus: 0, inherit: 0 };
420
526
  this.decisionCount = 0;
421
527
  this.saveState();
422
528
  }
529
+ /**
530
+ * Public read-only accessor for the bandit priors. Useful for tests,
531
+ * dashboards, and the pending hooks_intelligence_stats integration that
532
+ * surfaces convergence in the dashboard. Returns a copy.
533
+ */
534
+ getBanditPriors() {
535
+ const p = this.state.priors ?? defaultBanditPriors();
536
+ return {
537
+ haiku: { ...p.haiku },
538
+ sonnet: { ...p.sonnet },
539
+ opus: { ...p.opus },
540
+ inherit: { ...p.inherit },
541
+ };
542
+ }
423
543
  }
424
544
  // ============================================================================
425
545
  // Singleton & Factory Functions
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.7.0-alpha.3",
3
+ "version": "3.7.0-alpha.5",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",