claude-flow 3.6.14 → 3.6.16

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.
@@ -0,0 +1 @@
1
+ {"sessionId":"36428a63-dfb2-42a4-a159-cf8be916193e","pid":86429,"procStart":"Sun May 3 19:17:47 2026","acquiredAt":1777840775529}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.6.14",
3
+ "version": "3.6.16",
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",
@@ -70,7 +70,18 @@
70
70
  },
71
71
  "overrides": {
72
72
  "hono": ">=4.11.4",
73
- "@ruvector/rvf-wasm": "0.1.5"
73
+ "@ruvector/rvf-wasm": "0.1.5",
74
+ "@hono/node-server": ">=1.19.10",
75
+ "flatted": ">=3.4.0",
76
+ "tar": ">=7.5.0",
77
+ "picomatch": ">=4.0.3",
78
+ "path-to-regexp": ">=8.2.1",
79
+ "undici": ">=7.18.0",
80
+ "minimatch": ">=10.0.0",
81
+ "@isaacs/brace-expansion": ">=5.0.1",
82
+ "cacache": ">=20.0.0",
83
+ "make-fetch-happen": ">=15.0.0",
84
+ "express-rate-limit": ">=8.4.1"
74
85
  },
75
86
  "devDependencies": {
76
87
  "@openai/codex": "^0.98.0",
@@ -10,14 +10,30 @@
10
10
 
11
11
  import { randomUUID } from 'crypto';
12
12
 
13
- // Suppress noisy [AgentDB Patch] warnings from agentic-flow's runtime patch
14
- // These are cosmetic the patch tries to fix agentdb v1.x imports but we use v3
13
+ // Suppress the SPECIFIC cosmetic "[AgentDB Patch] Controller index not found"
14
+ // warning from agentic-flow's runtime patch these are emitted because the
15
+ // patch was written for agentdb v1.x and we use v3, where the controllers
16
+ // dist directory is laid out differently. The warning surfaces on every
17
+ // command and the audit (audit_1776483149979) flagged a too-broad suppression
18
+ // as a security risk because it could hide legitimate [AgentDB Patch] warnings.
19
+ //
20
+ // Tight match: must include both the prefix AND the specific "Controller
21
+ // index not found" text. Anything else (including future [AgentDB Patch]
22
+ // warnings about real issues) flows through unchanged. Also patch
23
+ // console.log because the underlying code uses it (the previous filter
24
+ // only caught console.warn and was therefore a no-op).
15
25
  const _origWarn = console.warn;
26
+ const _origLog = console.log;
27
+ const _isCosmeticAgentdbPatchNoise = (msg) =>
28
+ msg.includes('[AgentDB Patch]') && msg.includes('Controller index not found');
16
29
  console.warn = (...args) => {
17
- const msg = String(args[0] ?? '');
18
- if (msg.includes('[AgentDB Patch]')) return;
30
+ if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
19
31
  _origWarn.apply(console, args);
20
32
  };
33
+ console.log = (...args) => {
34
+ if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
35
+ _origLog.apply(console, args);
36
+ };
21
37
 
22
38
  // Check if we should run in MCP server mode
23
39
  // Conditions:
@@ -9,12 +9,23 @@
9
9
 
10
10
  import { randomUUID } from 'crypto';
11
11
 
12
- // Suppress [AgentDB Patch] warnings (cosmetic, from agentic-flow v1.x compat patch)
12
+ // Suppress the SPECIFIC cosmetic "[AgentDB Patch] Controller index not found"
13
+ // noise. Tight match (both prefix AND "Controller index not found") so other
14
+ // [AgentDB Patch] warnings about real issues still flow through. Also patch
15
+ // console.log because the underlying call site uses it. See bin/cli.js for
16
+ // the same rationale.
13
17
  const _origWarn = console.warn;
18
+ const _origLog = console.log;
19
+ const _isCosmeticAgentdbPatchNoise = (msg) =>
20
+ msg.includes('[AgentDB Patch]') && msg.includes('Controller index not found');
14
21
  console.warn = (...args) => {
15
- if (String(args[0] ?? '').includes('[AgentDB Patch]')) return;
22
+ if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
16
23
  _origWarn.apply(console, args);
17
24
  };
25
+ console.log = (...args) => {
26
+ if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
27
+ _origLog.apply(console, args);
28
+ };
18
29
 
19
30
  import { listMCPTools, callMCPTool, hasTool } from '../dist/src/mcp-client.js';
20
31
 
@@ -634,15 +634,40 @@ export const coordinationTools = [
634
634
  const agents = input.agents || Object.keys(store.nodes);
635
635
  const strategy = input.strategy || 'parallel';
636
636
  const orchestrationId = `orch-${Date.now()}`;
637
+ // ADR-093 F7: this tool only schedules an orchestration record — it
638
+ // does not actually execute. Previously it returned a hardcoded
639
+ // `estimatedCompletion: "50ms"` which was misleading. Now we return
640
+ // an honest stub-status with a note pointing callers at agent_spawn
641
+ // / Task tool / hive-mind tools for real orchestration. Persist the
642
+ // record so callers can list/inspect what was scheduled.
643
+ const orchestration = {
644
+ id: orchestrationId,
645
+ task,
646
+ strategy,
647
+ agents,
648
+ status: 'scheduled',
649
+ scheduledAt: new Date().toISOString(),
650
+ topology: store.topology.type,
651
+ };
652
+ const orchStore = store;
653
+ if (!Array.isArray(orchStore.orchestrations))
654
+ orchStore.orchestrations = [];
655
+ orchStore.orchestrations.push(orchestration);
656
+ if (orchStore.orchestrations.length > 100) {
657
+ orchStore.orchestrations = orchStore.orchestrations.slice(-100);
658
+ }
659
+ saveCoordStore(orchStore);
637
660
  return {
638
661
  success: true,
639
662
  orchestrationId,
640
663
  task,
641
664
  strategy,
642
665
  agents,
643
- status: 'initiated',
666
+ status: 'scheduled',
644
667
  topology: store.topology.type,
645
- estimatedCompletion: `${agents.length * (strategy === 'sequential' ? 100 : 50)}ms`,
668
+ // Honest stub: no executor wired up yet. Don't lie about completion time.
669
+ executor: 'none',
670
+ _note: 'coordination_orchestrate currently records the orchestration request but does not execute it. For real multi-agent execution use agent_spawn + the Task tool, or hive-mind_spawn for queen-led coordination.',
646
671
  };
647
672
  },
648
673
  },
@@ -2988,40 +2988,90 @@ export const hooksIntelligenceAttention = {
2988
2988
  }
2989
2989
  }
2990
2990
  else if (mode === 'flash') {
2991
- // Try Flash Attention
2991
+ // Try Flash Attention. ADR-093 F10: previously this attended over
2992
+ // synthetic cosine-derived keys/values with constant-vector values,
2993
+ // which produced uniform 0.333 weights and labels like "Flash
2994
+ // attention target #1/2/3". Now we attend over actual stored
2995
+ // patterns when available — real semantic content yields non-uniform
2996
+ // weights and human-readable labels.
2992
2997
  const flash = await getFlashAttention();
2993
2998
  if (flash) {
2994
2999
  try {
2995
3000
  const embResult = await getQueryEmbedding(query, 384);
2996
3001
  embeddingSource = embResult.source;
2997
3002
  const q = embResult.embedding;
3003
+ // Pull real stored patterns to attend over. If none exist yet,
3004
+ // fall back to the synthetic harness but mark it honestly.
3005
+ const realPatterns = [];
3006
+ try {
3007
+ const { searchEntries: searchFn } = await import('../memory/memory-initializer.js');
3008
+ const hits = await searchFn({ query, limit: topK });
3009
+ if (Array.isArray(hits)) {
3010
+ for (const h of hits.slice(0, topK)) {
3011
+ const content = h.content ?? h.value ?? '';
3012
+ const id = String(h.id ?? h.key ?? `pattern-${realPatterns.length}`);
3013
+ realPatterns.push({ id, content: String(content) });
3014
+ }
3015
+ }
3016
+ }
3017
+ catch { /* memory not initialized — fall through to synthetic */ }
3018
+ const useReal = realPatterns.length > 0;
2998
3019
  const keys = [];
2999
3020
  const values = [];
3000
- // Generate some keys/values
3001
- for (let k = 0; k < topK; k++) {
3002
- const key = new Float32Array(384);
3003
- const value = new Float32Array(384);
3004
- for (let i = 0; i < 384; i++) {
3005
- key[i] = Math.cos((k + 1) * (i + 1) * 0.01);
3006
- value[i] = k + 1;
3021
+ const labels = [];
3022
+ if (useReal) {
3023
+ // Build keys from real pattern embeddings (re-embed if no vector cached)
3024
+ for (let k = 0; k < realPatterns.length; k++) {
3025
+ const p = realPatterns[k];
3026
+ let keyEmbedding;
3027
+ if (p.embedding && p.embedding.length === 384) {
3028
+ keyEmbedding = new Float32Array(p.embedding);
3029
+ }
3030
+ else {
3031
+ const enc = await getQueryEmbedding(p.content.slice(0, 1024), 384);
3032
+ keyEmbedding = enc.embedding;
3033
+ }
3034
+ const value = new Float32Array(384);
3035
+ // Value carries pattern identity strength — magnitude = recency proxy (k position)
3036
+ const strength = 1 / (k + 1);
3037
+ for (let i = 0; i < 384; i++)
3038
+ value[i] = keyEmbedding[i] * strength;
3039
+ keys.push(keyEmbedding);
3040
+ values.push(value);
3041
+ const label = p.content.length > 0
3042
+ ? `${p.id}: ${p.content.slice(0, 60)}${p.content.length > 60 ? '…' : ''}`
3043
+ : p.id;
3044
+ labels.push(label);
3045
+ }
3046
+ }
3047
+ else {
3048
+ // No real patterns — surface a synthetic harness honestly.
3049
+ for (let k = 0; k < topK; k++) {
3050
+ const key = new Float32Array(384);
3051
+ const value = new Float32Array(384);
3052
+ for (let i = 0; i < 384; i++) {
3053
+ key[i] = Math.cos((k + 1) * (i + 1) * 0.01);
3054
+ value[i] = k + 1;
3055
+ }
3056
+ keys.push(key);
3057
+ values.push(value);
3058
+ labels.push(`(synthetic harness) pattern #${k + 1}`);
3007
3059
  }
3008
- keys.push(key);
3009
- values.push(value);
3010
3060
  }
3011
3061
  const attentionResult = flash.attention([q], keys, values);
3012
3062
  // Compute softmax weights from output magnitudes
3013
3063
  const outputMags = attentionResult.output[0]
3014
- ? Array.from(attentionResult.output[0]).slice(0, topK).map(v => Math.abs(v))
3015
- : new Array(topK).fill(1);
3064
+ ? Array.from(attentionResult.output[0]).slice(0, keys.length).map(v => Math.abs(v))
3065
+ : new Array(keys.length).fill(1);
3016
3066
  const sumMags = outputMags.reduce((a, b) => a + b, 0) || 1;
3017
- for (let i = 0; i < topK; i++) {
3067
+ for (let i = 0; i < keys.length; i++) {
3018
3068
  results.push({
3019
3069
  index: i,
3020
3070
  weight: outputMags[i] / sumMags,
3021
- pattern: `Flash attention target #${i + 1}`,
3071
+ pattern: labels[i],
3022
3072
  });
3023
3073
  }
3024
- implementation = 'real-flash-attention';
3074
+ implementation = useReal ? 'real-flash-attention+memory' : 'real-flash-attention+synthetic-harness';
3025
3075
  }
3026
3076
  catch {
3027
3077
  // Fall back to placeholder
@@ -222,10 +222,38 @@ export const neuralTools = [
222
222
  continue;
223
223
  const embedding = await generateEmbedding(text, 384);
224
224
  const patternId = `${modelId}-train-${i}`;
225
+ // ADR-093 F11: extract a meaningful label instead of dumping raw
226
+ // training JSON as the pattern name. Audit reported neural_predict
227
+ // returned `label: <raw training data JSON>` because the previous
228
+ // fallback was `text.slice(0, 100)` where text was `JSON.stringify(entry)`.
229
+ let label;
230
+ if (typeof entry === 'string') {
231
+ label = entry.slice(0, 80);
232
+ }
233
+ else if (entry && typeof entry === 'object') {
234
+ const e = entry;
235
+ // Prefer common semantic fields over a JSON dump
236
+ const labelField = e.label ?? e.category ?? e.class ?? e.tag ?? e.intent ?? e.name ?? e.title;
237
+ if (typeof labelField === 'string' && labelField.length > 0) {
238
+ label = labelField.slice(0, 80);
239
+ }
240
+ else {
241
+ const summaryField = e.text ?? e.input ?? e.task ?? e.description ?? e.content;
242
+ if (typeof summaryField === 'string' && summaryField.length > 0) {
243
+ label = `${summaryField.slice(0, 60)}${summaryField.length > 60 ? '…' : ''}`;
244
+ }
245
+ else {
246
+ // Last resort: reduce to a stable short hash-like id
247
+ label = `${modelType}:entry-${i}`;
248
+ }
249
+ }
250
+ }
251
+ else {
252
+ label = `${modelType}:entry-${i}`;
253
+ }
225
254
  store.patterns[patternId] = {
226
255
  id: patternId,
227
- name: typeof entry === 'object' && entry !== null && 'label' in entry
228
- ? String(entry.label) : text.slice(0, 100),
256
+ name: label,
229
257
  type: modelType,
230
258
  embedding,
231
259
  metadata: { modelId, epoch: epochs, index: i, raw: entry },
@@ -294,36 +322,67 @@ export const neuralTools = [
294
322
  const startTime = performance.now();
295
323
  const embedding = await generateEmbedding(inputText, 384);
296
324
  const latency = Math.round(performance.now() - startTime);
297
- // Search stored patterns via real cosine similarity
325
+ // ADR-093 F11: real classifier head over stored patterns. Previously
326
+ // confidence was the raw cosine similarity (often clamped to 0 when
327
+ // stored embeddings were stale or zero-vectored). Now we run k-NN
328
+ // with cosine distance and apply a temperature-controlled softmax
329
+ // over the top-K so confidence is a proper distribution that sums
330
+ // to 1, and we surface enough metadata to trust the result.
298
331
  const storedPatterns = Object.values(store.patterns);
299
332
  let predictions;
300
333
  if (storedPatterns.length > 0) {
301
- // Real nearest-neighbor prediction using stored pattern embeddings
302
- predictions = storedPatterns
303
- .map(p => ({
304
- label: p.name || p.type || p.id,
305
- confidence: Math.max(0, cosineSimilarity(embedding, p.embedding)),
306
- patternId: p.id,
307
- }))
308
- .sort((a, b) => b.confidence - a.confidence)
334
+ // Step 1: k-NN with cosine
335
+ const scored = storedPatterns
336
+ .map(p => {
337
+ const sim = cosineSimilarity(embedding, p.embedding);
338
+ return {
339
+ patternId: p.id,
340
+ label: p.name || p.type || p.id,
341
+ cosineSimilarity: sim,
342
+ };
343
+ })
344
+ .sort((a, b) => b.cosineSimilarity - a.cosineSimilarity)
309
345
  .slice(0, topK);
346
+ // Step 2: temperature-softmax over the top-K so confidence sums to 1.
347
+ // Temperature 0.1 sharpens differences between similar candidates.
348
+ const tau = 0.1;
349
+ const exps = scored.map(s => Math.exp(s.cosineSimilarity / tau));
350
+ const z = exps.reduce((a, b) => a + b, 0) || 1;
351
+ predictions = scored.map((s, i) => ({
352
+ label: s.label,
353
+ patternId: s.patternId,
354
+ cosineSimilarity: Number(s.cosineSimilarity.toFixed(4)),
355
+ confidence: Number((exps[i] / z).toFixed(4)),
356
+ }));
310
357
  }
311
358
  else {
312
- // No patterns stored — no predictions possible
359
+ // No patterns stored — no predictions possible. Be honest about it
360
+ // instead of returning empty silently.
313
361
  predictions = [];
314
362
  }
363
+ const topConfidence = predictions[0]?.confidence ?? 0;
364
+ const topSimilarity = predictions[0]?.cosineSimilarity ?? 0;
315
365
  return {
316
366
  success: true,
317
367
  _realEmbedding: !!realEmbeddings,
318
368
  _embeddingSource: embeddingServiceName,
319
369
  embeddingProvider: embeddingServiceName,
320
370
  _hasStoredPatterns: storedPatterns.length > 0,
371
+ _classifierHead: storedPatterns.length > 0 ? 'knn-cosine+softmax(tau=0.1)' : 'none',
321
372
  modelId: model?.id || 'default',
322
373
  input: inputText,
323
374
  predictions,
375
+ // Surface cosineSimilarity separately so callers know whether the
376
+ // softmax confidence reflects true match strength.
377
+ topPrediction: predictions[0]?.label ?? null,
378
+ topConfidence,
379
+ topSimilarity,
324
380
  embedding: embedding.slice(0, 8), // Preview of embedding
325
381
  embeddingDims: embedding.length,
326
382
  latency,
383
+ ...(storedPatterns.length === 0 ? {
384
+ _note: 'No patterns stored. Train with neural_train(modelType, trainingData) before predicting.',
385
+ } : {}),
327
386
  };
328
387
  },
329
388
  },
@@ -74,7 +74,27 @@ export const performanceTools = [
74
74
  const freeMem = os.freemem();
75
75
  // Calculate real CPU usage percentage from load average
76
76
  const cpuPercent = (loadAvg[0] / cpus.length) * 100;
77
- // Generate current metrics with REAL values
77
+ // ADR-093 F8: replace hardcoded latency fixtures (50/40/100/200) with
78
+ // an actual self-measured latency probe. Throughput now reflects real
79
+ // metric collection cadence (calls/min over the stored history) rather
80
+ // than an arbitrary +1/+10 increment per call.
81
+ const probeStart = process.hrtime.bigint();
82
+ // Tiny CPU+memory work that mirrors a typical MCP tool call
83
+ let probeAcc = 0;
84
+ for (let i = 0; i < 1000; i++)
85
+ probeAcc += Math.sqrt(i);
86
+ const probeNs = Number(process.hrtime.bigint() - probeStart);
87
+ const selfLatencyMs = probeNs / 1e6;
88
+ const recent = store.metrics.slice(-10);
89
+ const recentLatencies = recent.map(m => m.latency.avg).filter(n => Number.isFinite(n));
90
+ recentLatencies.push(selfLatencyMs);
91
+ const sorted = [...recentLatencies].sort((a, b) => a - b);
92
+ const pct = (p) => sorted.length === 0 ? selfLatencyMs : sorted[Math.min(sorted.length - 1, Math.floor((p / 100) * sorted.length))];
93
+ const avg = recentLatencies.reduce((s, n) => s + n, 0) / Math.max(1, recentLatencies.length);
94
+ // Throughput from real cadence: count metric samples in the last 60s.
95
+ const cutoff = Date.now() - 60_000;
96
+ const samplesInLastMinute = store.metrics.filter(m => new Date(m.timestamp).getTime() >= cutoff).length + 1;
97
+ const opsPerSecond = samplesInLastMinute / 60;
78
98
  const currentMetrics = {
79
99
  timestamp: new Date().toISOString(),
80
100
  cpu: { usage: Math.min(cpuPercent, 100), cores: cpus.length },
@@ -84,17 +104,20 @@ export const performanceTools = [
84
104
  heap: Math.round(memUsage.heapUsed / 1024 / 1024),
85
105
  },
86
106
  latency: {
87
- avg: store.metrics.length > 0 ? store.metrics.slice(-10).reduce((s, m) => s + m.latency.avg, 0) / Math.min(store.metrics.length, 10) : 50,
88
- p50: store.metrics.length > 0 ? store.metrics.slice(-10).reduce((s, m) => s + m.latency.p50, 0) / Math.min(store.metrics.length, 10) : 40,
89
- p95: store.metrics.length > 0 ? store.metrics.slice(-10).reduce((s, m) => s + m.latency.p95, 0) / Math.min(store.metrics.length, 10) : 100,
90
- p99: store.metrics.length > 0 ? store.metrics.slice(-10).reduce((s, m) => s + m.latency.p99, 0) / Math.min(store.metrics.length, 10) : 200,
107
+ avg: Number(avg.toFixed(3)),
108
+ p50: Number(pct(50).toFixed(3)),
109
+ p95: Number(pct(95).toFixed(3)),
110
+ p99: Number(pct(99).toFixed(3)),
91
111
  },
92
112
  throughput: {
93
- requests: store.metrics.length > 0 ? store.metrics[store.metrics.length - 1].throughput.requests + 1 : 1,
94
- operations: store.metrics.length > 0 ? store.metrics[store.metrics.length - 1].throughput.operations + 10 : 10,
113
+ requests: store.metrics.length + 1,
114
+ operations: Number(opsPerSecond.toFixed(2)),
95
115
  },
96
116
  errors: { count: 0, rate: 0 },
97
117
  };
118
+ // probeAcc kept reachable to prevent V8 dead-code elimination of the loop
119
+ if (probeAcc < 0)
120
+ currentMetrics.errors.count = -1;
98
121
  store.metrics.push(currentMetrics);
99
122
  // Keep last 100 metrics
100
123
  if (store.metrics.length > 100) {
@@ -93,47 +93,116 @@ async function getRegistry(dbPath) {
93
93
  finally {
94
94
  console.log = origLog;
95
95
  }
96
- // Wire intelligence module as the learning backend
97
- // AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db handle
98
- // which ControllerRegistry doesn't expose. Instead, use the local intelligence
99
- // module (SONA + LocalReasoningBank + file persistence) for learning.
96
+ // Wire intelligence module as the learning backend.
97
+ // AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db
98
+ // handle which ControllerRegistry doesn't expose. Instead, use the
99
+ // local intelligence module (SONA + LocalReasoningBank + file
100
+ // persistence) for learning.
101
+ //
102
+ // PERF: parallelize the two independent post-init paths
103
+ // (intelligence module load + agentdb import). Previously these
104
+ // ran serially, adding ~50-150ms to cold start. Both can resolve
105
+ // concurrently because they touch disjoint controller slots.
100
106
  try {
101
- const intelligence = await import('./intelligence.js');
102
- const initResult = await intelligence.initializeIntelligence();
103
107
  const reg = registry;
104
- if (initResult.reasoningBankEnabled) {
105
- const rb = intelligence.getReasoningBank();
106
- if (rb && !reg.get('reasoningBank')) {
107
- if (typeof reg.set === 'function')
108
- reg.set('reasoningBank', rb);
109
- else
110
- reg._controllers = { ...(reg._controllers || {}), reasoningBank: rb };
108
+ const intelligencePromise = (async () => {
109
+ try {
110
+ const intelligence = await import('./intelligence.js');
111
+ const initResult = await intelligence.initializeIntelligence();
112
+ if (initResult.reasoningBankEnabled) {
113
+ const rb = intelligence.getReasoningBank();
114
+ if (rb && !reg.get('reasoningBank')) {
115
+ if (typeof reg.set === 'function')
116
+ reg.set('reasoningBank', rb);
117
+ else
118
+ reg._controllers = { ...(reg._controllers || {}), reasoningBank: rb };
119
+ }
120
+ }
121
+ if (initResult.sonaEnabled) {
122
+ const sona = intelligence.getSonaCoordinator();
123
+ if (sona && !reg.get('learningSystem')) {
124
+ if (typeof reg.set === 'function')
125
+ reg.set('learningSystem', sona);
126
+ else
127
+ reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
128
+ }
129
+ }
111
130
  }
112
- }
113
- if (initResult.sonaEnabled) {
114
- const sona = intelligence.getSonaCoordinator();
115
- if (sona && !reg.get('learningSystem')) {
116
- if (typeof reg.set === 'function')
117
- reg.set('learningSystem', sona);
118
- else
119
- reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
131
+ catch { /* intelligence module not available — learning stays unwired */ }
132
+ })();
133
+ const agentdbPromise = (async () => {
134
+ // Single import shared across SkillLibrary + SemanticRouter probe.
135
+ let agentdb = null;
136
+ try {
137
+ agentdb = (await import('agentdb'));
120
138
  }
121
- }
122
- // SkillLibrary from AgentDB (no db required)
123
- try {
124
- const agentdb = await import('agentdb');
125
- if (agentdb.SkillLibrary && !reg.get('skills')) {
126
- const sk = new agentdb.SkillLibrary();
127
- if (typeof reg.set === 'function')
128
- reg.set('skills', sk);
129
- else
130
- reg._controllers = { ...(reg._controllers || {}), skills: sk };
139
+ catch {
140
+ return; /* AgentDB not available */
131
141
  }
132
- }
133
- catch { /* AgentDB not available */ }
142
+ // SkillLibrary (no db required)
143
+ try {
144
+ const SkillCtor = agentdb.SkillLibrary;
145
+ if (SkillCtor && !reg.get('skills')) {
146
+ const sk = new SkillCtor();
147
+ if (typeof reg.set === 'function')
148
+ reg.set('skills', sk);
149
+ else
150
+ reg._controllers = { ...(reg._controllers || {}), skills: sk };
151
+ }
152
+ }
153
+ catch { /* SkillLibrary optional */ }
154
+ // ADR-093 F9: probe multiple router class names across agentdb
155
+ // alpha versions (alpha.10 had SemanticRouter; alpha.11+ removed
156
+ // it in favor of @ruvector/router; future versions may
157
+ // reintroduce). Wire only if .route() is callable.
158
+ try {
159
+ const candidates = ['SemanticRouter', 'IntentRouter', 'TaskRouter'];
160
+ let routerInstance = null;
161
+ for (const name of candidates) {
162
+ const Ctor = agentdb[name];
163
+ if (typeof Ctor === 'function') {
164
+ try {
165
+ const inst = (() => {
166
+ try {
167
+ return new Ctor({ dimension: 384 });
168
+ }
169
+ catch {
170
+ return new Ctor();
171
+ }
172
+ })();
173
+ if (inst && typeof inst.route === 'function') {
174
+ routerInstance = inst;
175
+ break;
176
+ }
177
+ }
178
+ catch { /* try next candidate */ }
179
+ }
180
+ }
181
+ if (routerInstance && !reg.get('semanticRouter')) {
182
+ if (typeof reg.set === 'function')
183
+ reg.set('semanticRouter', routerInstance);
184
+ else
185
+ reg._controllers = { ...(reg._controllers || {}), semanticRouter: routerInstance };
186
+ }
187
+ }
188
+ catch { /* router optional */ }
189
+ })();
190
+ // Run both in parallel; settle either way so a single failing
191
+ // path doesn't tear down the rest of the post-init wiring.
192
+ await Promise.allSettled([intelligencePromise, agentdbPromise]);
193
+ // Other disabled controllers remain disabled and tracked in
194
+ // ADR-093 F9 for future enablement:
195
+ // - mutationGuard (write protection — needs config)
196
+ // - attestationLog (needs sqlite db handle the registry does
197
+ // not currently expose)
198
+ // - gnnService (graph neural net — heavy deps, needs WASM/CUDA)
199
+ // - guardedVectorBackend (secured vector backend variant —
200
+ // needs key material)
201
+ // - rvfOptimizer (RVF format optimizer — needs RVF storage)
202
+ // - graphAdapter (graph DB adapter — needs graph DB)
134
203
  }
135
204
  catch {
136
- // Intelligence module not available learning stays unwired
205
+ // Top-level catchregistry stays usable even if post-init wiring fails wholesale.
137
206
  }
138
207
  registryInstance = registry;
139
208
  bridgeAvailable = true;
@@ -1545,13 +1614,22 @@ export async function bridgeSemanticRoute(params) {
1545
1614
  return null;
1546
1615
  try {
1547
1616
  const router = registry.get('semanticRouter');
1548
- if (!router)
1549
- return { route: null, error: 'SemanticRouter not available' };
1617
+ if (!router) {
1618
+ // ADR-093 F9: surface an actionable error pointing callers at the
1619
+ // alternative routing surfaces that DO work, instead of just
1620
+ // saying "not available".
1621
+ return {
1622
+ route: null,
1623
+ error: 'SemanticRouter not available in current agentdb build',
1624
+ recommendation: 'Use bridgeRouteTask (registers as `agentdb_route` MCP tool) for keyword+pattern routing, or hooks_model-route for ADR-026 model selection.',
1625
+ controller: 'none',
1626
+ };
1627
+ }
1550
1628
  const result = await router.route(params.input);
1551
1629
  return { route: result, controller: 'semanticRouter' };
1552
1630
  }
1553
1631
  catch (e) {
1554
- return { route: null, error: e.message };
1632
+ return { route: null, error: e.message, controller: 'error' };
1555
1633
  }
1556
1634
  }
1557
1635
  // ===== RaBitQ data export =====
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.6.14",
3
+ "version": "3.6.16",
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",