@claude-flow/cli 3.32.26 → 3.32.29

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 (36) hide show
  1. package/.claude/helpers/.helpers-version +1 -1
  2. package/.claude/helpers/helpers.manifest.json +2 -2
  3. package/catalog-manifest.json +4 -4
  4. package/dist/src/commands/index.d.ts +1 -0
  5. package/dist/src/commands/index.js +5 -3
  6. package/dist/src/commands/memory.js +49 -5
  7. package/dist/src/commands/metaharness.js +25 -5
  8. package/dist/src/commands/policy.d.ts +4 -0
  9. package/dist/src/commands/policy.js +107 -0
  10. package/dist/src/index.js +18 -0
  11. package/dist/src/mcp-client.js +25 -1
  12. package/dist/src/mcp-tools/capability-brain.d.ts +134 -0
  13. package/dist/src/mcp-tools/capability-brain.js +697 -0
  14. package/dist/src/mcp-tools/guidance-tools.d.ts +2 -0
  15. package/dist/src/mcp-tools/guidance-tools.js +369 -37
  16. package/dist/src/mcp-tools/index.d.ts +4 -1
  17. package/dist/src/mcp-tools/index.js +3 -1
  18. package/dist/src/mcp-tools/memory-tools.js +26 -0
  19. package/dist/src/mcp-tools/metaharness-tools.js +27 -1
  20. package/dist/src/mcp-tools/policy-tools.d.ts +3 -0
  21. package/dist/src/mcp-tools/policy-tools.js +121 -0
  22. package/dist/src/memory/memory-bridge.d.ts +11 -0
  23. package/dist/src/memory/memory-bridge.js +100 -21
  24. package/dist/src/memory/memory-initializer.d.ts +22 -1
  25. package/dist/src/memory/memory-initializer.js +184 -39
  26. package/dist/src/services/bounded-worker-pool.d.ts +28 -0
  27. package/dist/src/services/bounded-worker-pool.js +90 -0
  28. package/dist/src/services/harness-flywheel-runtime.d.ts +2 -0
  29. package/dist/src/services/harness-flywheel-runtime.js +18 -0
  30. package/dist/src/services/harness-flywheel.d.ts +4 -1
  31. package/dist/src/services/harness-flywheel.js +27 -6
  32. package/dist/src/services/policy-runtime.d.ts +38 -0
  33. package/dist/src/services/policy-runtime.js +340 -0
  34. package/package.json +22 -6
  35. package/plugins/ruflo-metaharness/scripts/smoke.sh +22 -14
  36. package/plugins/ruflo-metaharness/scripts/test-mcp-tools.mjs +3 -1
@@ -7,6 +7,8 @@
7
7
  * @module @claude-flow/cli/mcp-tools/guidance
8
8
  */
9
9
  import { type MCPTool } from './types.js';
10
+ import { type CapabilityToolMetadata } from './capability-brain.js';
11
+ export declare function configureGuidanceToolProvider(provider: () => readonly CapabilityToolMetadata[]): void;
10
12
  /**
11
13
  * All guidance tools
12
14
  */
@@ -9,30 +9,41 @@
9
9
  import { getProjectCwd } from './types.js';
10
10
  import { validateIdentifier, validateText } from './validate-input.js';
11
11
  import { existsSync, readFileSync, readdirSync } from 'node:fs';
12
- import { join, dirname } from 'node:path';
12
+ import { join, dirname, relative } from 'node:path';
13
13
  import { fileURLToPath } from 'node:url';
14
+ import { buildCapabilityBrain, recommendCapabilities, } from './capability-brain.js';
14
15
  const __filename = fileURLToPath(import.meta.url);
15
16
  const __dirname = dirname(__filename);
16
- const CLI_ROOT = join(__dirname, '../../..');
17
17
  /**
18
18
  * Find the project root by looking for .claude/ directory.
19
19
  * Tries CWD first (most common), then walks up from the CLI package location.
20
20
  */
21
21
  function findProjectRoot() {
22
- // Strategy 1: CWD (most reliable when invoked by user)
23
- if (existsSync(join(getProjectCwd(), '.claude'))) {
24
- return getProjectCwd();
22
+ const cwd = getProjectCwd();
23
+ let cwdIsCliPackage = false;
24
+ const cwdManifest = join(cwd, 'package.json');
25
+ if (existsSync(cwdManifest)) {
26
+ try {
27
+ const manifest = JSON.parse(readFileSync(cwdManifest, 'utf-8'));
28
+ cwdIsCliPackage = manifest.name === '@claude-flow/cli';
29
+ }
30
+ catch {
31
+ // An invalid project manifest is not a reason to hide discoverable files.
32
+ }
25
33
  }
26
- // Strategy 2: Walk up from CLI package location
27
- // CLI is at v3/@claude-flow/cli/ project root is 4 levels up
28
- const fromPackage = join(CLI_ROOT, '../../../..');
29
- if (existsSync(join(fromPackage, '.claude'))) {
30
- return fromPackage;
34
+ // User projects with a local .claude directory remain the primary root.
35
+ // Exclude the CLI package's own shipped .claude assets during repository
36
+ // development; otherwise ecosystem discovery silently stops at the package.
37
+ if (!cwdIsCliPackage && existsSync(join(cwd, '.claude'))) {
38
+ return cwd;
31
39
  }
32
- // Strategy 3: Walk up from CWD
33
- let dir = getProjectCwd();
40
+ // Walk up to a Git/workspace root. Worktrees use a .git file, so existsSync
41
+ // is intentionally used instead of requiring a directory.
42
+ let dir = cwd;
34
43
  for (let i = 0; i < 10; i++) {
35
- if (existsSync(join(dir, '.claude')))
44
+ if (existsSync(join(dir, '.git')))
45
+ return dir;
46
+ if (!(cwdIsCliPackage && dir === cwd) && existsSync(join(dir, '.claude')))
36
47
  return dir;
37
48
  const parent = dirname(dir);
38
49
  if (parent === dir)
@@ -40,9 +51,20 @@ function findProjectRoot() {
40
51
  dir = parent;
41
52
  }
42
53
  // Fallback: CWD
43
- return getProjectCwd();
54
+ return cwd;
44
55
  }
45
56
  const PROJECT_ROOT = findProjectRoot();
57
+ /**
58
+ * Injected by mcp-client after every MCP tool has been registered. Keeping the
59
+ * provider here avoids guidance importing the registry and creating a cycle.
60
+ */
61
+ let liveToolProvider = () => [];
62
+ export function configureGuidanceToolProvider(provider) {
63
+ liveToolProvider = provider;
64
+ }
65
+ function getCapabilityBrain() {
66
+ return buildCapabilityBrain(liveToolProvider());
67
+ }
46
68
  const CAPABILITY_CATALOG = {
47
69
  'agent-management': {
48
70
  name: 'Agent Management',
@@ -285,9 +307,6 @@ const WORKFLOW_TEMPLATES = {
285
307
  };
286
308
  // ── Dynamic Discovery ───────────────────────────────────────
287
309
  function discoverAgents() {
288
- const agentsDir = join(PROJECT_ROOT, '.claude/agents');
289
- if (!existsSync(agentsDir))
290
- return [];
291
310
  const agents = [];
292
311
  function walk(dir) {
293
312
  try {
@@ -306,27 +325,125 @@ function discoverAgents() {
306
325
  }
307
326
  catch { /* ignore */ }
308
327
  }
309
- walk(agentsDir);
328
+ const roots = [
329
+ join(PROJECT_ROOT, '.claude/agents'),
330
+ join(PROJECT_ROOT, '.agents/agents'),
331
+ ];
332
+ const pluginsDir = join(PROJECT_ROOT, 'plugins');
333
+ if (existsSync(pluginsDir)) {
334
+ for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
335
+ if (entry.isDirectory())
336
+ roots.push(join(pluginsDir, entry.name, 'agents'));
337
+ }
338
+ }
339
+ for (const root of roots) {
340
+ if (existsSync(root))
341
+ walk(root);
342
+ }
310
343
  return [...new Set(agents)].sort();
311
344
  }
312
345
  function discoverSkills() {
313
- const skillsDir = join(PROJECT_ROOT, '.claude/skills');
314
- if (!existsSync(skillsDir))
315
- return [];
316
346
  const skills = [];
317
- try {
318
- const entries = readdirSync(skillsDir, { withFileTypes: true });
319
- for (const entry of entries) {
320
- if (entry.isDirectory()) {
321
- const skillFile = join(skillsDir, entry.name, 'SKILL.md');
322
- if (existsSync(skillFile)) {
323
- skills.push(entry.name);
347
+ function walk(dir) {
348
+ try {
349
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
350
+ const target = join(dir, entry.name);
351
+ if (entry.isDirectory()) {
352
+ walk(target);
353
+ }
354
+ else if (entry.name === 'SKILL.md') {
355
+ const content = readFileSync(target, 'utf-8');
356
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
357
+ skills.push(nameMatch
358
+ ? nameMatch[1].trim().replace(/^["']|["']$/g, '')
359
+ : relative(PROJECT_ROOT, dirname(target)));
324
360
  }
325
361
  }
326
362
  }
363
+ catch {
364
+ // Missing or unreadable optional capability roots are reported by absence.
365
+ }
366
+ }
367
+ const roots = [
368
+ join(PROJECT_ROOT, '.claude/skills'),
369
+ join(PROJECT_ROOT, '.agents/skills'),
370
+ ];
371
+ const pluginsDir = join(PROJECT_ROOT, 'plugins');
372
+ if (existsSync(pluginsDir)) {
373
+ for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
374
+ if (entry.isDirectory())
375
+ roots.push(join(pluginsDir, entry.name, 'skills'));
376
+ }
377
+ }
378
+ for (const root of roots) {
379
+ if (existsSync(root))
380
+ walk(root);
327
381
  }
328
- catch { /* ignore */ }
329
- return skills.sort();
382
+ return [...new Set(skills)].sort();
383
+ }
384
+ function discoverPlugins() {
385
+ const pluginsDir = join(PROJECT_ROOT, 'plugins');
386
+ if (!existsSync(pluginsDir))
387
+ return [];
388
+ const plugins = [];
389
+ for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
390
+ if (!entry.isDirectory())
391
+ continue;
392
+ const manifestPath = join(pluginsDir, entry.name, '.claude-plugin', 'plugin.json');
393
+ if (!existsSync(manifestPath))
394
+ continue;
395
+ try {
396
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
397
+ plugins.push({
398
+ id: entry.name,
399
+ name: manifest.name ?? entry.name,
400
+ version: manifest.version ?? 'unknown',
401
+ description: manifest.description ?? '',
402
+ manifest: relative(PROJECT_ROOT, manifestPath),
403
+ });
404
+ }
405
+ catch {
406
+ plugins.push({
407
+ id: entry.name,
408
+ name: entry.name,
409
+ version: 'unknown',
410
+ manifest: relative(PROJECT_ROOT, manifestPath),
411
+ invalidManifest: true,
412
+ });
413
+ }
414
+ }
415
+ return plugins.sort((left, right) => String(left.id).localeCompare(String(right.id), 'en-US'));
416
+ }
417
+ function discoverPackages() {
418
+ const packagesDir = join(PROJECT_ROOT, 'v3', '@claude-flow');
419
+ if (!existsSync(packagesDir))
420
+ return [];
421
+ const packages = [];
422
+ for (const entry of readdirSync(packagesDir, { withFileTypes: true })) {
423
+ if (!entry.isDirectory())
424
+ continue;
425
+ const manifestPath = join(packagesDir, entry.name, 'package.json');
426
+ if (!existsSync(manifestPath))
427
+ continue;
428
+ try {
429
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
430
+ packages.push({
431
+ name: manifest.name ?? entry.name,
432
+ version: manifest.version ?? 'unknown',
433
+ description: manifest.description ?? '',
434
+ manifest: relative(PROJECT_ROOT, manifestPath),
435
+ });
436
+ }
437
+ catch {
438
+ packages.push({
439
+ name: entry.name,
440
+ version: 'unknown',
441
+ manifest: relative(PROJECT_ROOT, manifestPath),
442
+ invalidManifest: true,
443
+ });
444
+ }
445
+ }
446
+ return packages.sort((left, right) => String(left.name).localeCompare(String(right.name), 'en-US'));
330
447
  }
331
448
  // ── MCP Tool Definitions ────────────────────────────────────
332
449
  const guidanceCapabilities = {
@@ -349,6 +466,7 @@ const guidanceCapabilities = {
349
466
  handler: async (params) => {
350
467
  const area = params.area;
351
468
  const format = params.format || 'summary';
469
+ const brain = getCapabilityBrain();
352
470
  if (area) {
353
471
  const v = validateIdentifier(area, 'area');
354
472
  if (!v.valid)
@@ -356,14 +474,42 @@ const guidanceCapabilities = {
356
474
  }
357
475
  if (area) {
358
476
  const cap = CAPABILITY_CATALOG[area];
359
- if (!cap) {
360
- const available = Object.keys(CAPABILITY_CATALOG).join(', ');
477
+ const brainDomain = brain.domains.find((domain) => domain.id === area);
478
+ if (!cap && !brainDomain) {
479
+ const available = [
480
+ ...Object.keys(CAPABILITY_CATALOG),
481
+ ...brain.domains.map((domain) => domain.id),
482
+ ].filter((value, index, all) => all.indexOf(value) === index).join(', ');
361
483
  return { content: [{ type: 'text', text: JSON.stringify({ error: `Unknown area: ${area}`, available }, null, 2) }], isError: true };
362
484
  }
363
- return { content: [{ type: 'text', text: JSON.stringify(cap, null, 2) }] };
485
+ return {
486
+ content: [{
487
+ type: 'text',
488
+ text: JSON.stringify({
489
+ ...(cap ?? {}),
490
+ legacyCatalogStatus: cap ? 'compatibility-only; tool names may be deprecated aliases' : undefined,
491
+ legacyToolResolution: cap ? cap.tools.map((name) => ({
492
+ name,
493
+ registered: brain.domains.some((entry) => entry.tools.some((tool) => tool.name === name)),
494
+ })) : undefined,
495
+ capabilityBrain: brainDomain,
496
+ }, null, 2),
497
+ }],
498
+ };
364
499
  }
365
500
  if (format === 'detailed') {
366
- return { content: [{ type: 'text', text: JSON.stringify(CAPABILITY_CATALOG, null, 2) }] };
501
+ return {
502
+ content: [{
503
+ type: 'text',
504
+ text: JSON.stringify({
505
+ legacyCatalog: {
506
+ status: 'compatibility-only; use capabilityBrain for live routing',
507
+ areas: CAPABILITY_CATALOG,
508
+ },
509
+ capabilityBrain: brain,
510
+ }, null, 2),
511
+ }],
512
+ };
367
513
  }
368
514
  const summary = Object.entries(CAPABILITY_CATALOG).map(([key, val]) => ({
369
515
  area: key,
@@ -374,7 +520,30 @@ const guidanceCapabilities = {
374
520
  skillCount: val.skills.length,
375
521
  whenToUse: val.whenToUse,
376
522
  }));
377
- return { content: [{ type: 'text', text: JSON.stringify({ areas: summary, totalAreas: summary.length }, null, 2) }] };
523
+ return {
524
+ content: [{
525
+ type: 'text',
526
+ text: JSON.stringify({
527
+ areas: summary,
528
+ totalAreas: summary.length,
529
+ live: {
530
+ schemaVersion: brain.schemaVersion,
531
+ registeredToolCount: brain.coverage.registeredToolCount,
532
+ classifiedToolCount: brain.coverage.classifiedToolCount,
533
+ coveragePercent: brain.coverage.coveragePercent,
534
+ fallbackClassifiedTools: brain.coverage.fallbackClassifiedTools,
535
+ domains: brain.domains.map((domain) => ({
536
+ id: domain.id,
537
+ name: domain.name,
538
+ registeredToolCount: domain.tools.length,
539
+ health: domain.health,
540
+ authority: domain.authority,
541
+ risk: domain.risk,
542
+ })),
543
+ },
544
+ }, null, 2),
545
+ }],
546
+ };
378
547
  },
379
548
  };
380
549
  const guidanceRecommend = {
@@ -397,6 +566,8 @@ const guidanceRecommend = {
397
566
  if (!v.valid)
398
567
  return { content: [{ type: 'text', text: JSON.stringify({ error: v.error }, null, 2) }], isError: true };
399
568
  }
569
+ const brain = getCapabilityBrain();
570
+ const capabilityRecommendation = recommendCapabilities(brain, task);
400
571
  const matches = [];
401
572
  for (const route of TASK_ROUTES) {
402
573
  if (route.pattern.test(task)) {
@@ -430,12 +601,14 @@ const guidanceRecommend = {
430
601
  { area: 'hooks-automation', reason: 'Use hooks for task routing and learning' },
431
602
  ],
432
603
  tip: 'Use guidance_capabilities for a full list of all capability areas.',
604
+ capabilityBrain: capabilityRecommendation,
433
605
  }, null, 2),
434
606
  }],
435
607
  };
436
608
  }
437
609
  const primaryWorkflow = recommendations[0]?.workflow;
438
610
  const template = primaryWorkflow ? WORKFLOW_TEMPLATES[primaryWorkflow] : undefined;
611
+ const liveToolNames = new Set(brain.domains.flatMap((domain) => domain.tools.map((tool) => tool.name)));
439
612
  return {
440
613
  content: [{
441
614
  type: 'text',
@@ -445,7 +618,8 @@ const guidanceRecommend = {
445
618
  area: r.area,
446
619
  name: r.capability.name,
447
620
  description: r.capability.description,
448
- tools: r.capability.tools,
621
+ tools: r.capability.tools.filter((name) => liveToolNames.has(name)),
622
+ unregisteredLegacyToolRefs: r.capability.tools.filter((name) => !liveToolNames.has(name)),
449
623
  agents: r.capability.agents,
450
624
  skills: r.capability.skills,
451
625
  })),
@@ -455,6 +629,7 @@ const guidanceRecommend = {
455
629
  agents: template.agents,
456
630
  topology: template.topology,
457
631
  } : undefined,
632
+ capabilityBrain: capabilityRecommendation,
458
633
  }, null, 2),
459
634
  }],
460
635
  };
@@ -468,7 +643,7 @@ const guidanceDiscover = {
468
643
  properties: {
469
644
  type: {
470
645
  type: 'string',
471
- enum: ['agents', 'skills', 'all'],
646
+ enum: ['agents', 'skills', 'plugins', 'packages', 'all'],
472
647
  description: 'What to discover. Default: all.',
473
648
  },
474
649
  },
@@ -484,6 +659,18 @@ const guidanceDiscover = {
484
659
  const skills = discoverSkills();
485
660
  result.skills = { count: skills.length, names: skills };
486
661
  }
662
+ if (type === 'plugins' || type === 'all') {
663
+ const plugins = discoverPlugins();
664
+ result.plugins = { count: plugins.length, entries: plugins };
665
+ }
666
+ if (type === 'packages' || type === 'all') {
667
+ const packages = discoverPackages();
668
+ result.packages = { count: packages.length, entries: packages };
669
+ }
670
+ result.capabilityBrain = {
671
+ registeredTools: getCapabilityBrain().coverage.registeredToolCount,
672
+ note: 'Filesystem discovery reports installed artifacts; it does not prove configuration, health, or authorization.',
673
+ };
487
674
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
488
675
  },
489
676
  };
@@ -625,10 +812,155 @@ const guidanceQuickRef = {
625
812
  return { content: [{ type: 'text', text: JSON.stringify(ref, null, 2) }] };
626
813
  },
627
814
  };
815
+ const guidanceBrain = {
816
+ name: 'guidance_brain',
817
+ description: 'Query Ruflo’s live capability brain. Covers every registered MCP tool, separates registration from configuration/reachability/health/authorization, recommends capabilities for a task, and returns the validated implementation loop.',
818
+ inputSchema: {
819
+ type: 'object',
820
+ properties: {
821
+ mode: {
822
+ type: 'string',
823
+ enum: ['overview', 'capabilities', 'coverage', 'ecosystem', 'recommend', 'implementation-loop'],
824
+ description: 'Brain view. Default: overview.',
825
+ },
826
+ task: {
827
+ type: 'string',
828
+ description: 'Required for recommend mode.',
829
+ },
830
+ domain: {
831
+ type: 'string',
832
+ description: 'Optional capability domain filter for capabilities mode.',
833
+ },
834
+ },
835
+ },
836
+ handler: async (params) => {
837
+ const mode = params.mode ?? 'overview';
838
+ const task = params.task;
839
+ const domain = params.domain;
840
+ const brain = getCapabilityBrain();
841
+ if (domain) {
842
+ const validation = validateIdentifier(domain, 'domain');
843
+ if (!validation.valid) {
844
+ return {
845
+ content: [{ type: 'text', text: JSON.stringify({ error: validation.error }, null, 2) }],
846
+ isError: true,
847
+ };
848
+ }
849
+ }
850
+ let result;
851
+ switch (mode) {
852
+ case 'overview':
853
+ result = {
854
+ schemaVersion: brain.schemaVersion,
855
+ generatedAt: brain.generatedAt,
856
+ truthModel: brain.truthModel,
857
+ coverage: brain.coverage,
858
+ domainCount: brain.domains.length,
859
+ cliCommandCount: brain.cliCommands.length,
860
+ cliCommands: brain.cliCommands,
861
+ registeredDomains: brain.domains
862
+ .filter((entry) => entry.health.registered)
863
+ .map((entry) => ({
864
+ id: entry.id,
865
+ name: entry.name,
866
+ toolCount: entry.tools.length,
867
+ maturity: entry.maturity,
868
+ authority: entry.authority,
869
+ risk: entry.risk,
870
+ health: entry.health,
871
+ })),
872
+ implementationLoop: brain.implementationLoop.map((step) => step.id),
873
+ };
874
+ break;
875
+ case 'capabilities': {
876
+ const capabilities = domain
877
+ ? brain.domains.filter((entry) => entry.id === domain)
878
+ : brain.domains;
879
+ if (domain && capabilities.length === 0) {
880
+ return {
881
+ content: [{
882
+ type: 'text',
883
+ text: JSON.stringify({
884
+ error: `Unknown capability domain: ${domain}`,
885
+ available: brain.domains.map((entry) => entry.id),
886
+ }, null, 2),
887
+ }],
888
+ isError: true,
889
+ };
890
+ }
891
+ result = { schemaVersion: brain.schemaVersion, truthModel: brain.truthModel, capabilities };
892
+ break;
893
+ }
894
+ case 'coverage':
895
+ result = {
896
+ schemaVersion: brain.schemaVersion,
897
+ coverage: brain.coverage,
898
+ assignments: brain.domains.map((entry) => ({
899
+ domain: entry.id,
900
+ tools: entry.tools.map((tool) => tool.name),
901
+ })),
902
+ };
903
+ break;
904
+ case 'ecosystem': {
905
+ const agents = discoverAgents();
906
+ const skills = discoverSkills();
907
+ const plugins = discoverPlugins();
908
+ const packages = discoverPackages();
909
+ result = {
910
+ schemaVersion: brain.schemaVersion,
911
+ agents: { count: agents.length, names: agents },
912
+ skills: { count: skills.length, names: skills },
913
+ plugins: { count: plugins.length, entries: plugins },
914
+ packages: { count: packages.length, entries: packages },
915
+ cliCommands: { count: brain.cliCommands.length, names: brain.cliCommands },
916
+ availabilityNote: 'Installed or catalogued artifacts are not necessarily configured, reachable, healthy, or authorized.',
917
+ };
918
+ break;
919
+ }
920
+ case 'recommend': {
921
+ const validation = validateText(task, 'task');
922
+ if (!validation.valid) {
923
+ return {
924
+ content: [{ type: 'text', text: JSON.stringify({ error: validation.error }, null, 2) }],
925
+ isError: true,
926
+ };
927
+ }
928
+ result = recommendCapabilities(brain, task);
929
+ break;
930
+ }
931
+ case 'implementation-loop':
932
+ result = {
933
+ schemaVersion: brain.schemaVersion,
934
+ steps: brain.implementationLoop,
935
+ invariants: [
936
+ 'Recall precedes implementation.',
937
+ 'Testing and validation precede optimization.',
938
+ 'Benchmarks compare a source-bound candidate with a source-bound baseline.',
939
+ 'Learning and optimization cannot authorize promotion.',
940
+ 'Publishing requires separate authorization and immutable artifact evidence.',
941
+ ],
942
+ };
943
+ break;
944
+ default:
945
+ return {
946
+ content: [{
947
+ type: 'text',
948
+ text: JSON.stringify({
949
+ error: `Unknown mode: ${mode}`,
950
+ available: ['overview', 'capabilities', 'coverage', 'ecosystem', 'recommend', 'implementation-loop'],
951
+ }, null, 2),
952
+ }],
953
+ isError: true,
954
+ };
955
+ }
956
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
957
+ },
958
+ };
628
959
  /**
629
960
  * All guidance tools
630
961
  */
631
962
  export const guidanceTools = [
963
+ guidanceBrain,
632
964
  guidanceCapabilities,
633
965
  guidanceRecommend,
634
966
  guidanceDiscover,
@@ -20,9 +20,12 @@ export { transferTools } from './transfer-tools.js';
20
20
  export { securityTools } from './security-tools.js';
21
21
  export { embeddingsTools } from './embeddings-tools.js';
22
22
  export { claimsTools } from './claims-tools.js';
23
+ export { policyTools } from './policy-tools.js';
23
24
  export { wasmAgentTools } from './wasm-agent-tools.js';
24
25
  export { ruvllmWasmTools } from './ruvllm-tools.js';
25
- export { guidanceTools } from './guidance-tools.js';
26
+ export { configureGuidanceToolProvider, guidanceTools, } from './guidance-tools.js';
27
+ export { buildCapabilityBrain, CAPABILITY_DOMAINS, classifyCapabilityTool, IMPLEMENTATION_LOOP, recommendCapabilities, RUFLO_CLI_COMMANDS, } from './capability-brain.js';
28
+ export type { AvailabilityState, CapabilityAuthority, CapabilityBrain, CapabilityDomain, CapabilityDomainDefinition, CapabilityHealth, CapabilityMaturity, CapabilityRecommendation, CapabilityRisk, CapabilityToolMetadata, ImplementationLoopStep, } from './capability-brain.js';
26
29
  export { autopilotTools } from './autopilot-tools.js';
27
30
  export { metaharnessTools } from './metaharness-tools.js';
28
31
  export { testgenTools } from './testgen-tools.js';
@@ -19,9 +19,11 @@ export { transferTools } from './transfer-tools.js';
19
19
  export { securityTools } from './security-tools.js';
20
20
  export { embeddingsTools } from './embeddings-tools.js';
21
21
  export { claimsTools } from './claims-tools.js';
22
+ export { policyTools } from './policy-tools.js';
22
23
  export { wasmAgentTools } from './wasm-agent-tools.js';
23
24
  export { ruvllmWasmTools } from './ruvllm-tools.js';
24
- export { guidanceTools } from './guidance-tools.js';
25
+ export { configureGuidanceToolProvider, guidanceTools, } from './guidance-tools.js';
26
+ export { buildCapabilityBrain, CAPABILITY_DOMAINS, classifyCapabilityTool, IMPLEMENTATION_LOOP, recommendCapabilities, RUFLO_CLI_COMMANDS, } from './capability-brain.js';
25
27
  export { autopilotTools } from './autopilot-tools.js';
26
28
  // ADR-150 — MetaHarness MCP tools (score / genome / mcp-scan / threat-model / oia-audit)
27
29
  export { metaharnessTools } from './metaharness-tools.js';