claude-flow 3.6.14 → 3.6.15
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/.claude/scheduled_tasks.lock +1 -0
- package/package.json +13 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js +27 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +65 -15
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +71 -12
- package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +30 -7
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +62 -3
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -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.
|
|
3
|
+
"version": "3.6.15",
|
|
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",
|
|
@@ -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: '
|
|
666
|
+
status: 'scheduled',
|
|
644
667
|
topology: store.topology.type,
|
|
645
|
-
|
|
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
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
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,
|
|
3015
|
-
: new Array(
|
|
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 <
|
|
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:
|
|
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:
|
|
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
|
-
//
|
|
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
|
-
//
|
|
302
|
-
|
|
303
|
-
.map(p =>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
//
|
|
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:
|
|
88
|
-
p50:
|
|
89
|
-
p95:
|
|
90
|
-
p99:
|
|
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
|
|
94
|
-
operations:
|
|
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) {
|
|
@@ -131,6 +131,56 @@ async function getRegistry(dbPath) {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
catch { /* AgentDB not available */ }
|
|
134
|
+
// ADR-093 F9: post-init injection of low-risk disabled controllers.
|
|
135
|
+
// Try multiple constructor names because the agentdb API renamed
|
|
136
|
+
// SemanticRouter across alpha versions (alpha.10 had SemanticRouter,
|
|
137
|
+
// alpha.11+ removed it in favor of @ruvector/router separately;
|
|
138
|
+
// future versions may reintroduce). If the cwd's agentdb has a
|
|
139
|
+
// viable router-shaped controller, wire it; otherwise leave it
|
|
140
|
+
// unbound and let bridgeSemanticRoute return its actionable error.
|
|
141
|
+
try {
|
|
142
|
+
const agentdb = await import('agentdb');
|
|
143
|
+
const candidates = ['SemanticRouter', 'IntentRouter', 'TaskRouter'];
|
|
144
|
+
let routerInstance = null;
|
|
145
|
+
for (const name of candidates) {
|
|
146
|
+
const Ctor = agentdb[name];
|
|
147
|
+
if (typeof Ctor === 'function') {
|
|
148
|
+
try {
|
|
149
|
+
// Try with dimension config first (newer router classes), then no-args
|
|
150
|
+
const inst = (() => {
|
|
151
|
+
try {
|
|
152
|
+
return new Ctor({ dimension: 384 });
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return new Ctor();
|
|
156
|
+
}
|
|
157
|
+
})();
|
|
158
|
+
if (inst && typeof inst.route === 'function') {
|
|
159
|
+
routerInstance = inst;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch { /* try next candidate */ }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (routerInstance && !reg.get('semanticRouter')) {
|
|
167
|
+
if (typeof reg.set === 'function')
|
|
168
|
+
reg.set('semanticRouter', routerInstance);
|
|
169
|
+
else
|
|
170
|
+
reg._controllers = { ...(reg._controllers || {}), semanticRouter: routerInstance };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch { /* SemanticRouter optional — bridgeSemanticRoute will surface "not available" */ }
|
|
174
|
+
// Other disabled controllers remain disabled and tracked in
|
|
175
|
+
// ADR-093 F9 for future enablement:
|
|
176
|
+
// - mutationGuard (write protection — needs config)
|
|
177
|
+
// - attestationLog (needs sqlite db handle the registry does
|
|
178
|
+
// not currently expose)
|
|
179
|
+
// - gnnService (graph neural net — heavy deps, needs WASM/CUDA)
|
|
180
|
+
// - guardedVectorBackend (secured vector backend variant —
|
|
181
|
+
// needs key material)
|
|
182
|
+
// - rvfOptimizer (RVF format optimizer — needs RVF storage)
|
|
183
|
+
// - graphAdapter (graph DB adapter — needs graph DB)
|
|
134
184
|
}
|
|
135
185
|
catch {
|
|
136
186
|
// Intelligence module not available — learning stays unwired
|
|
@@ -1545,13 +1595,22 @@ export async function bridgeSemanticRoute(params) {
|
|
|
1545
1595
|
return null;
|
|
1546
1596
|
try {
|
|
1547
1597
|
const router = registry.get('semanticRouter');
|
|
1548
|
-
if (!router)
|
|
1549
|
-
|
|
1598
|
+
if (!router) {
|
|
1599
|
+
// ADR-093 F9: surface an actionable error pointing callers at the
|
|
1600
|
+
// alternative routing surfaces that DO work, instead of just
|
|
1601
|
+
// saying "not available".
|
|
1602
|
+
return {
|
|
1603
|
+
route: null,
|
|
1604
|
+
error: 'SemanticRouter not available in current agentdb build',
|
|
1605
|
+
recommendation: 'Use bridgeRouteTask (registers as `agentdb_route` MCP tool) for keyword+pattern routing, or hooks_model-route for ADR-026 model selection.',
|
|
1606
|
+
controller: 'none',
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1550
1609
|
const result = await router.route(params.input);
|
|
1551
1610
|
return { route: result, controller: 'semanticRouter' };
|
|
1552
1611
|
}
|
|
1553
1612
|
catch (e) {
|
|
1554
|
-
return { route: null, error: e.message };
|
|
1613
|
+
return { route: null, error: e.message, controller: 'error' };
|
|
1555
1614
|
}
|
|
1556
1615
|
}
|
|
1557
1616
|
// ===== RaBitQ data export =====
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.15",
|
|
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",
|