claude-flow 3.42.5 → 3.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.claude/.proven-config-version +1 -0
  2. package/.claude/helpers/router.cjs +66 -23
  3. package/.claude/proven-config.json +42 -0
  4. package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
  5. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  6. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
  7. package/package.json +3 -3
  8. package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
  9. package/v3/@claude-flow/cli/dist/src/commands/doctor.js +22 -1
  10. package/v3/@claude-flow/cli/dist/src/commands/hooks.js +9 -3
  11. package/v3/@claude-flow/cli/dist/src/init/executor.js +2 -1
  12. package/v3/@claude-flow/cli/dist/src/init/helper-refresh.js +5 -0
  13. package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +11 -10
  14. package/v3/@claude-flow/cli/dist/src/mcp-tools/capability-brain.js +4 -2
  15. package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.d.ts +36 -0
  16. package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +291 -189
  17. package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +42 -0
  18. package/v3/@claude-flow/cli/dist/src/memory/graph-edge-writer.d.ts +10 -0
  19. package/v3/@claude-flow/cli/dist/src/memory/graph-edge-writer.js +77 -1
  20. package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.d.ts +6 -0
  21. package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +76 -28
  22. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +3 -0
  23. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +53 -11
  24. package/v3/@claude-flow/cli/dist/src/ruvector/router-embedder.d.ts +58 -0
  25. package/v3/@claude-flow/cli/dist/src/ruvector/router-embedder.js +141 -0
  26. package/v3/@claude-flow/cli/dist/src/ruvector/typesafe-router.d.ts +119 -0
  27. package/v3/@claude-flow/cli/dist/src/ruvector/typesafe-router.js +245 -0
  28. package/v3/@claude-flow/cli/dist/src/services/policy-runtime.js +40 -11
  29. package/v3/@claude-flow/cli/package.json +5 -1
@@ -0,0 +1 @@
1
+ sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319
@@ -1,7 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Claude Flow Agent Router
4
- * Routes tasks to optimal agents based on learned patterns
4
+ *
5
+ * Static keyword router that suggests an agent for a task description.
6
+ * NOTE: This is *not* a learned model. It is a heuristic table; "confidence"
7
+ * is reported as a heuristic prior, not a calibrated probability.
8
+ *
9
+ * #2257 fix: patterns are now word-boundary-anchored so short tokens like
10
+ * `cd`, `ci`, `ui`, `add`, `structure` no longer match inside unrelated
11
+ * words (`decision`, `infrastructure`, `address`, `addendum`). Default
12
+ * confidence dropped from 0.8 to 0.6 to better reflect that this is a
13
+ * static heuristic, not a learned classifier.
5
14
  */
6
15
 
7
16
  const AGENT_CAPABILITIES = {
@@ -15,41 +24,73 @@ const AGENT_CAPABILITIES = {
15
24
  devops: ['ci-cd', 'docker', 'deployment', 'infrastructure'],
16
25
  };
17
26
 
18
- const TASK_PATTERNS = {
19
- 'implement|create|build|add|write code': 'coder',
20
- 'test|spec|coverage|unit test|integration': 'tester',
21
- 'review|audit|check|validate|security': 'reviewer',
22
- 'research|find|search|documentation|explore': 'researcher',
23
- 'design|architect|structure|plan': 'architect',
24
- 'api|endpoint|server|backend|database': 'backend-dev',
25
- 'ui|frontend|component|react|css|style': 'frontend-dev',
26
- 'deploy|docker|ci|cd|pipeline|infrastructure': 'devops',
27
- };
27
+ // Each entry is an array of tokens. Tokens are alternation-friendly:
28
+ // - multi-word phrases ("unit test") match as phrases
29
+ // - single tokens are wrapped with \b … \b word boundaries at match time
30
+ const TASK_PATTERNS = [
31
+ // Code patterns
32
+ { tokens: ['implement', 'create', 'build', 'add', 'write code', 'refactor', 'debug'], agent: 'coder' },
33
+ { tokens: ['test', 'tests', 'testing', 'spec', 'specs', 'coverage', 'unit test', 'integration test'], agent: 'tester' },
34
+ { tokens: ['review', 'audit', 'check', 'validate', 'security'], agent: 'reviewer' },
35
+ { tokens: ['research', 'find', 'search', 'documentation', 'explore'], agent: 'researcher' },
36
+ { tokens: ['design', 'architect', 'architecture', 'structure', 'plan'], agent: 'architect' },
37
+
38
+ // Domain patterns
39
+ { tokens: ['api', 'endpoint', 'server', 'backend', 'database'], agent: 'backend-dev' },
40
+ { tokens: ['ui', 'frontend', 'component', 'react', 'css', 'style'], agent: 'frontend-dev' },
41
+ // 'cd' / 'ci' are kept but require word boundaries via \b — they will not
42
+ // match inside "decision" or "specific". 'cd' as a literal command in a
43
+ // task description ("set up cd pipeline") still matches.
44
+ { tokens: ['deploy', 'docker', 'ci', 'cd', 'ci/cd', 'pipeline', 'infrastructure', 'devops'], agent: 'devops' },
45
+ ];
46
+
47
+ function escapeRegex(s) {
48
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
49
+ }
50
+
51
+ // Build an anchored alternation regex from a token list.
52
+ // - multi-word phrases (containing whitespace or '/') match literally
53
+ // - single tokens are wrapped with \b boundaries so 'cd' won't match "decide"
54
+ function buildPattern(tokens) {
55
+ const alternatives = tokens.map((tok) => {
56
+ const escaped = escapeRegex(tok.toLowerCase());
57
+ if (/\s|\//.test(tok)) {
58
+ // Phrase: whitespace/'/' on each side acts as a natural boundary
59
+ return escaped;
60
+ }
61
+ return `\\b${escaped}\\b`;
62
+ });
63
+ return new RegExp(`(?:${alternatives.join('|')})`, 'i');
64
+ }
65
+
66
+ const COMPILED_PATTERNS = TASK_PATTERNS.map((entry) => ({
67
+ agent: entry.agent,
68
+ tokens: entry.tokens,
69
+ regex: buildPattern(entry.tokens),
70
+ }));
28
71
 
29
72
  function routeTask(task) {
30
- const taskLower = task.toLowerCase();
73
+ const taskLower = String(task ?? '').toLowerCase();
31
74
 
32
- for (const [pattern, agent] of Object.entries(TASK_PATTERNS)) {
33
- const regex = new RegExp(pattern, 'i');
34
- if (regex.test(taskLower)) {
75
+ for (const entry of COMPILED_PATTERNS) {
76
+ if (entry.regex.test(taskLower)) {
35
77
  return {
36
- agent,
37
- confidence: 0.8,
38
- reason: `Matched pattern: ${pattern}`,
78
+ agent: entry.agent,
79
+ // Heuristic prior, not a learned probability — see file header.
80
+ confidence: 0.6,
81
+ reason: `Matched keyword(s) from: ${entry.tokens.join('|')}`,
39
82
  };
40
83
  }
41
84
  }
42
85
 
43
86
  return {
44
87
  agent: 'coder',
45
- confidence: 0.5,
46
- reason: 'Default routing - no specific pattern matched',
88
+ confidence: 0.3,
89
+ reason: 'Default routing - no specific keyword matched',
47
90
  };
48
91
  }
49
92
 
50
- module.exports = { routeTask, AGENT_CAPABILITIES, TASK_PATTERNS };
51
-
52
- // CLI - only run when executed directly
93
+ // CLI
53
94
  if (require.main === module) {
54
95
  const task = process.argv.slice(2).join(' ');
55
96
  if (task) {
@@ -60,3 +101,5 @@ if (require.main === module) {
60
101
  console.log('\nAvailable agents:', Object.keys(AGENT_CAPABILITIES).join(', '));
61
102
  }
62
103
  }
104
+
105
+ module.exports = { routeTask, AGENT_CAPABILITIES, TASK_PATTERNS, buildPattern };
@@ -0,0 +1,42 @@
1
+ {
2
+ "adoptedAt": 1790188792465,
3
+ "championId": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
4
+ "manifest": {
5
+ "schema": "ruflo.proven-config/v1",
6
+ "policy": {
7
+ "ref": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
8
+ "value": {
9
+ "alpha": 0.3,
10
+ "subjectWeight": 1,
11
+ "mmrLambda": 0.5,
12
+ "bodyWeight": 1.5,
13
+ "typePenaltyFactor": 0.5
14
+ }
15
+ },
16
+ "layer": "framework/node-cli",
17
+ "compatibility": {
18
+ "ruflo": ">=3.24.0"
19
+ },
20
+ "benchmark": {
21
+ "corpus": "ADR-081-labelled-v1",
22
+ "corpusHash": "sha256:2f700b5c363e20a3bd88ce2bc9b87bbbbaa61732c6177894c6ec37890f888982"
23
+ },
24
+ "receipt": {
25
+ "heldOutDelta": 0.07381404928570845,
26
+ "redblue": "PASS",
27
+ "drift": 0,
28
+ "canary": {
29
+ "rollbackRate": 0,
30
+ "latencyP95": 244.612458000076,
31
+ "costPerTask": 0
32
+ },
33
+ "receiptCoverage": 1
34
+ },
35
+ "platform": [
36
+ "linux",
37
+ "macOS",
38
+ "windows"
39
+ ]
40
+ },
41
+ "previous": ""
42
+ }
File without changes
@@ -159,14 +159,14 @@ export declare const SpawnAgentSchema: z.ZodObject<{
159
159
  timeout: z.ZodOptional<z.ZodNumber>;
160
160
  }, "strip", z.ZodTypeAny, {
161
161
  type: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
162
- id?: string | undefined;
163
162
  config?: Record<string, unknown> | undefined;
164
163
  timeout?: number | undefined;
164
+ id?: string | undefined;
165
165
  }, {
166
166
  type: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
167
- id?: string | undefined;
168
167
  config?: Record<string, unknown> | undefined;
169
168
  timeout?: number | undefined;
169
+ id?: string | undefined;
170
170
  }>;
171
171
  /**
172
172
  * Task input schema
@@ -181,13 +181,13 @@ export declare const TaskInputSchema: z.ZodObject<{
181
181
  taskId: string;
182
182
  content: string;
183
183
  agentType: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
184
- priority?: "low" | "medium" | "high" | "critical" | undefined;
184
+ priority?: "critical" | "high" | "medium" | "low" | undefined;
185
185
  metadata?: Record<string, unknown> | undefined;
186
186
  }, {
187
187
  taskId: string;
188
188
  content: string;
189
189
  agentType: "coder" | "reviewer" | "tester" | "planner" | "researcher" | "security-architect" | "security-auditor" | "memory-specialist" | "swarm-specialist" | "integration-architect" | "performance-engineer" | "core-architect" | "test-architect" | "queen-coordinator" | "project-coordinator";
190
- priority?: "low" | "medium" | "high" | "critical" | undefined;
190
+ priority?: "critical" | "high" | "medium" | "low" | undefined;
191
191
  metadata?: Record<string, unknown> | undefined;
192
192
  }>;
193
193
  /**
@@ -234,16 +234,16 @@ export declare const ExecutorConfigSchema: z.ZodObject<{
234
234
  cwd: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
235
235
  allowSudo: z.ZodDefault<z.ZodBoolean>;
236
236
  }, "strip", z.ZodTypeAny, {
237
- timeout: number;
238
237
  allowedCommands: string[];
238
+ timeout: number;
239
239
  maxBuffer: number;
240
240
  allowSudo: boolean;
241
241
  blockedPatterns?: string[] | undefined;
242
242
  cwd?: string | undefined;
243
243
  }, {
244
244
  allowedCommands: string[];
245
- timeout?: number | undefined;
246
245
  blockedPatterns?: string[] | undefined;
246
+ timeout?: number | undefined;
247
247
  maxBuffer?: number | undefined;
248
248
  cwd?: string | undefined;
249
249
  allowSudo?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.42.5",
3
+ "version": "3.44.0",
4
4
  "workspaces": [
5
5
  "v3/@claude-flow/codex",
6
6
  "v3/@claude-flow/mcp",
@@ -98,8 +98,8 @@
98
98
  "@claude-flow/plugin-gastown-bridge": "^0.1.3",
99
99
  "@ruvector/attention": "^0.1.3",
100
100
  "@ruvector/core": "^0.1.30",
101
- "@ruvector/router": "^0.1.30",
102
- "@ruvector/router-linux-x64-gnu": "^0.1.30",
101
+ "@ruvector/router": "^0.1.31",
102
+ "@ruvector/router-linux-x64-gnu": "^0.1.31",
103
103
  "@ruvector/sona": "^0.1.5",
104
104
  "agentdb": "^3.0.0-alpha.17",
105
105
  "agentic-flow": "^2.0.14",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 6,
4
- "generatedAt": "2026-09-21T19:42:33.000Z",
5
- "gitSha": "9c61c86f",
4
+ "generatedAt": "2026-09-23T18:40:54.000Z",
5
+ "gitSha": "0a96fb88",
6
6
  "catalog": {
7
7
  "agents": 167,
8
8
  "tools": 418,
@@ -2059,6 +2059,26 @@ async function checkMetaharness() {
2059
2059
  };
2060
2060
  }
2061
2061
  }
2062
+ // Opt-in @ruvector/typesafe task router (optional peer). `--component typesafe` only.
2063
+ async function checkTypesafeRouter() {
2064
+ const name = '@ruvector/typesafe router';
2065
+ const { readTypesafeConfig } = await import('../ruvector/typesafe-router.js');
2066
+ const cfg = readTypesafeConfig();
2067
+ const gate = cfg.enabled ? `enabled (${cfg.embedder === 'hash' ? 'hash embedder, uncalibrated' : 'onnx embedder'})` : 'disabled (set CLAUDE_FLOW_ROUTER_TYPESAFE=1)';
2068
+ try {
2069
+ const { createRequire } = await import('module');
2070
+ const pj = createRequire(import.meta.url)('@ruvector/typesafe/package.json');
2071
+ return { name, status: 'pass', message: `v${pj.version ?? '?'} installed; ${gate}` };
2072
+ }
2073
+ catch {
2074
+ return {
2075
+ name,
2076
+ status: cfg.enabled ? 'warn' : 'pass',
2077
+ message: `Not installed; ${gate} — hooks_route uses the built-in router`,
2078
+ ...(cfg.enabled ? { fix: 'npm install @ruvector/typesafe # optional peer' } : {}),
2079
+ };
2080
+ }
2081
+ }
2062
2082
  async function checkClaudeCode() {
2063
2083
  try {
2064
2084
  const version = await runCommand('claude --version');
@@ -2252,7 +2272,7 @@ export const doctorCommand = {
2252
2272
  {
2253
2273
  name: 'component',
2254
2274
  short: 'c',
2255
- description: 'Check specific component (version, node, npm, config, daemon, memory, api, git, mcp, mcp-overhead, claude, disk, typescript, agentic-flow, encryption, federation, funnel, proxy, auth, metaharness)',
2275
+ description: 'Check specific component (version, node, npm, config, daemon, memory, api, git, mcp, mcp-overhead, claude, disk, typescript, agentic-flow, encryption, federation, funnel, proxy, auth, typesafe, metaharness)',
2256
2276
  type: 'string'
2257
2277
  },
2258
2278
  {
@@ -2435,6 +2455,7 @@ export const doctorCommand = {
2435
2455
  // a user would actually debug them (is it installed? running? exposed?).
2436
2456
  'proxy': [checkProxySponsoredConsent, checkProxyBinary, checkProxyProcess, checkProxyBindAddress],
2437
2457
  'auth': checkAuth, // ADR-306
2458
+ 'typesafe': checkTypesafeRouter, // opt-in @ruvector/typesafe task router
2438
2459
  };
2439
2460
  let checksToRun = allChecks;
2440
2461
  if (component && componentMap[component]) {
@@ -1811,6 +1811,12 @@ const postTaskCommand = {
1811
1811
  }
1812
1812
  output.writeln();
1813
1813
  output.printSuccess(`Task outcome recorded: ${success ? 'SUCCESS' : 'FAILED'}`);
1814
+ // #3353: only show observed learning results; say so when degraded.
1815
+ const lu = result.learningUpdates;
1816
+ if (lu.available === false) {
1817
+ output.writeln();
1818
+ output.printWarning(`Learning degraded: ${lu.reason ?? 'feedback not recorded'} — no pattern updates were observed`);
1819
+ }
1814
1820
  output.writeln();
1815
1821
  output.writeln(output.bold('Learning Updates'));
1816
1822
  output.printTable({
@@ -1819,10 +1825,10 @@ const postTaskCommand = {
1819
1825
  { key: 'value', header: 'Value', width: 20, align: 'right' }
1820
1826
  ],
1821
1827
  data: [
1822
- { metric: 'Patterns Updated', value: result.learningUpdates.patternsUpdated },
1823
- { metric: 'New Patterns', value: result.learningUpdates.newPatterns },
1828
+ { metric: 'Patterns Updated', value: lu.patternsUpdated },
1829
+ { metric: 'New Patterns', value: lu.newPatterns ?? 'unknown' },
1830
+ { metric: 'Trajectory Recorded', value: result.trajectory ? (result.trajectory.recorded ? 'yes' : 'no') : 'unknown' },
1824
1831
  { metric: 'Duration', value: `${(result.duration / 1000).toFixed(1)}s` },
1825
- { metric: 'Trajectory ID', value: result.learningUpdates.trajectoryId }
1826
1832
  ]
1827
1833
  });
1828
1834
  return { success: true, data: result };
@@ -499,7 +499,7 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
499
499
  const sourceHelpersForUpgrade = findSourceHelpersDir();
500
500
  if (sourceHelpersForUpgrade) {
501
501
  // Keep in sync with helper-refresh.ts:CRITICAL_HELPERS.
502
- const criticalHelpers = ['auto-memory-hook.mjs', 'hook-handler.cjs', 'intelligence.cjs', 'statusline.cjs'];
502
+ const criticalHelpers = ['auto-memory-hook.mjs', 'hook-handler.cjs', 'intelligence.cjs', 'statusline.cjs', 'router.js'];
503
503
  for (const helperName of criticalHelpers) {
504
504
  const targetPath = path.join(targetDir, '.claude', 'helpers', helperName);
505
505
  const sourcePath = path.join(sourceHelpersForUpgrade, helperName);
@@ -524,6 +524,7 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
524
524
  'hook-handler.cjs': generateHookHandler(),
525
525
  'intelligence.cjs': generateIntelligenceStub(),
526
526
  'auto-memory-hook.mjs': generateAutoMemoryHook(),
527
+ 'router.js': generateAgentRouter(), // ADR-389
527
528
  };
528
529
  for (const [helperName, content] of Object.entries(generatedCritical)) {
529
530
  const targetPath = path.join(targetDir, '.claude', 'helpers', helperName);
@@ -71,6 +71,10 @@ export const CRITICAL_HELPERS = [
71
71
  // statusline.cjs is here so the funnel disclosure row (ADR-301) reaches
72
72
  // existing installs on the next `ruflo` command, not only fresh `ruflo init`.
73
73
  'statusline.cjs',
74
+ // router.js is loaded by hook-handler.cjs to label each prompt with an agent.
75
+ // Without it here, installs kept the pre-#2257 substring router forever
76
+ // ("latest" -> tester). ADR-389 / #3401.
77
+ 'router.js',
74
78
  ];
75
79
  function errorCode(error) {
76
80
  return typeof error === 'object' && error !== null && 'code' in error
@@ -309,6 +313,7 @@ async function writeCriticalHelpers(helpersDir, version, opts = {}) {
309
313
  'hook-handler.cjs': gen.generateHookHandler(),
310
314
  'intelligence.cjs': gen.generateIntelligenceStub(),
311
315
  'auto-memory-hook.mjs': gen.generateAutoMemoryHook(),
316
+ 'router.js': gen.generateAgentRouter(), // ADR-389
312
317
  // Fallback needs the same generator inputs `ruflo init` uses. We match the
313
318
  // hardcoded default (maxAgents 15) because the fallback fires when the
314
319
  // installed package is unresolvable — no way to read the user's project
@@ -283,7 +283,7 @@ const AGENT_CAPABILITIES = {
283
283
  // the whitespace acts as a natural boundary.
284
284
  const TASK_PATTERNS = [
285
285
  { tokens: ['implement', 'create', 'build', 'add', 'write code', 'refactor', 'debug'], agent: 'coder' },
286
- { tokens: ['test', 'tests', 'spec', 'coverage', 'unit test', 'integration test'], agent: 'tester' },
286
+ { tokens: ['test', 'tests', 'testing', 'spec', 'specs', 'coverage', 'unit test', 'integration test'], agent: 'tester' },
287
287
  { tokens: ['review', 'audit', 'check', 'validate', 'security'], agent: 'reviewer' },
288
288
  { tokens: ['research', 'find', 'search', 'documentation', 'explore'], agent: 'researcher' },
289
289
  { tokens: ['design', 'architect', 'architecture', 'structure', 'plan'], agent: 'architect' },
@@ -329,15 +329,16 @@ function routeTask(task) {
329
329
  };
330
330
  }
331
331
 
332
- // CLI
333
- const task = process.argv.slice(2).join(' ');
334
-
335
- if (task) {
336
- const result = routeTask(task);
337
- console.log(JSON.stringify(result, null, 2));
338
- } else {
339
- console.log('Usage: router.js <task description>');
340
- console.log('\\nAvailable agents:', Object.keys(AGENT_CAPABILITIES).join(', '));
332
+ // CLI — only when executed directly, not when require()d by hook-handler.cjs
333
+ if (require.main === module) {
334
+ const task = process.argv.slice(2).join(' ');
335
+ if (task) {
336
+ const result = routeTask(task);
337
+ console.log(JSON.stringify(result, null, 2));
338
+ } else {
339
+ console.log('Usage: router.js <task description>');
340
+ console.log('\\nAvailable agents:', Object.keys(AGENT_CAPABILITIES).join(', '));
341
+ }
341
342
  }
342
343
 
343
344
  module.exports = { routeTask, AGENT_CAPABILITIES, TASK_PATTERNS, buildPattern };
@@ -125,7 +125,7 @@ export const CAPABILITY_DOMAINS = [
125
125
  {
126
126
  id: 'guidance',
127
127
  name: 'Capability Guidance',
128
- prefixes: ['guidance_'],
128
+ prefixes: ['guidance_', 'seraphina_'],
129
129
  description: 'Live capability inventory, task routing, workflow guidance, and system discovery.',
130
130
  taskSignals: ['guidance', 'discover', 'capability', 'what can ruflo do'],
131
131
  commands: ['guidance compile', 'guidance retrieve', 'guidance gates', 'guidance optimize'],
@@ -430,7 +430,7 @@ export const CAPABILITY_DOMAINS = [
430
430
  id: 'business-collaboration',
431
431
  name: 'AgentBBS & Business Pods',
432
432
  // Metadata classification only; execution remains behind the existing loadAgentbbs guard.
433
- prefixes: ['agentbbs_', 'business_pod_', 'federation_bbs_'],
433
+ prefixes: ['agentbbs_', 'business_pod_', 'federation_bbs_', 'x_federation_'],
434
434
  description: 'Federated business rooms, domain-affinity routing, and business-pod validation.',
435
435
  taskSignals: ['business pod', 'bbs', 'room', 'domain affinity'],
436
436
  commands: [],
@@ -551,6 +551,8 @@ const TOOL_OWNERSHIP = [
551
551
  { prefixes: ['testgen_'], packageOwner: '@claude-flow/cli', pluginOwner: 'ruflo-testgen' },
552
552
  { prefixes: ['managed_agent_', 'wasm_agent_', 'wasm_gallery_'], packageOwner: '@claude-flow/cli', pluginOwner: 'ruflo-agent' },
553
553
  { prefixes: ['guidance_'], packageOwner: '@claude-flow/guidance', pluginOwner: 'ruflo-core' },
554
+ { prefixes: ['seraphina_'], packageOwner: '@claude-flow/cli', pluginOwner: 'ruflo-core' },
555
+ { prefixes: ['x_federation_'], packageOwner: '@claude-flow/cli', pluginOwner: 'ruflo-x-gateway' },
554
556
  ];
555
557
  function ownershipForTool(toolName, definition) {
556
558
  const explicit = TOOL_OWNERSHIP.find((entry) => entry.prefixes.some((prefix) => toolName.startsWith(prefix)));
@@ -3,6 +3,7 @@
3
3
  * Provides intelligent hooks functionality via MCP protocol
4
4
  */
5
5
  import { type MCPTool } from './types.js';
6
+ import { type RouterEmbedderKind } from '../ruvector/router-embedder.js';
6
7
  /**
7
8
  * Strip extended-thinking blocks from text before it enters a learning
8
9
  * trajectory (hermes-agent think_scrubber pattern). Claude models with extended
@@ -13,11 +14,46 @@ import { type MCPTool } from './types.js';
13
14
  * the tag names untouched.
14
15
  */
15
16
  export declare function scrubReasoningBlocks(text: string): string;
17
+ /** Test hook: drop the cached semantic index so the next route rebuilds it. */
18
+ export declare function resetSemanticRouterForTests(): void;
19
+ /** Exported for tests. */
20
+ export declare function suggestAgentsForTask(task: string): {
21
+ agents: string[];
22
+ confidence: number;
23
+ };
16
24
  export declare const hooksPreEdit: MCPTool;
17
25
  export declare const hooksPostEdit: MCPTool;
18
26
  export declare const hooksPreCommand: MCPTool;
19
27
  export declare const hooksPostCommand: MCPTool;
20
28
  export declare const hooksRoute: MCPTool;
29
+ /** Result of {@link routeTaskForBench}. */
30
+ export interface BenchRouteResult {
31
+ primaryAgent: string;
32
+ confidence: number;
33
+ /** Matched pattern name, or 'keyword-fallback'. */
34
+ pattern: string;
35
+ /** Embedder actually used ('hash' if MiniLM was requested but unavailable). */
36
+ embedder: RouterEmbedderKind;
37
+ embedderReason?: string;
38
+ /** routing.method of the underlying route ('semantic-native' | 'semantic-pure-js' | 'keyword'). */
39
+ method: string;
40
+ }
41
+ /**
42
+ * INTERNAL / BENCH-ONLY (ADR-391). Not a public API; may change without notice.
43
+ *
44
+ * Routes `task` through the same local path `hooks_route` uses (semantic index +
45
+ * keyword fallback) with an explicit embedder, without the MCP layer. It skips
46
+ * the two steps that are neither ADR-391 candidate A nor B: the AgentDB
47
+ * pre-route (`bridgeRouteTask`, which answers first when its confidence > 0.5)
48
+ * and the opt-in typesafe wrapper (CLAUDE_FLOW_ROUTER_TYPESAFE). With those
49
+ * inactive, `primaryAgent` equals `hooks_route`'s `primaryAgent.type`.
50
+ *
51
+ * Switching `embedder` between calls rebuilds the index; benchmark in blocks.
52
+ */
53
+ export declare function routeTaskForBench(task: string, opts: {
54
+ embedder: RouterEmbedderKind;
55
+ context?: string;
56
+ }): Promise<BenchRouteResult>;
21
57
  export declare const hooksMetrics: MCPTool;
22
58
  export declare const hooksList: MCPTool;
23
59
  export declare const hooksPreTask: MCPTool;