@claude-flow/cli 3.32.25 → 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.
- package/.claude/helpers/.helpers-version +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +430 -430
- package/.claude/helpers/helpers.manifest.json +6 -6
- package/.claude/helpers/hook-handler.cjs +565 -565
- package/.claude/helpers/intelligence.cjs +1058 -1058
- package/.claude/helpers/statusline.cjs +1060 -1060
- package/catalog-manifest.json +4 -4
- package/dist/src/commands/index.d.ts +1 -0
- package/dist/src/commands/index.js +5 -3
- package/dist/src/commands/memory.js +49 -5
- package/dist/src/commands/metaharness.js +100 -2
- package/dist/src/commands/policy.d.ts +4 -0
- package/dist/src/commands/policy.js +107 -0
- package/dist/src/index.js +18 -0
- package/dist/src/mcp-client.js +25 -1
- package/dist/src/mcp-tools/capability-brain.d.ts +134 -0
- package/dist/src/mcp-tools/capability-brain.js +697 -0
- package/dist/src/mcp-tools/guidance-tools.d.ts +2 -0
- package/dist/src/mcp-tools/guidance-tools.js +369 -37
- package/dist/src/mcp-tools/index.d.ts +4 -1
- package/dist/src/mcp-tools/index.js +3 -1
- package/dist/src/mcp-tools/memory-tools.js +26 -0
- package/dist/src/mcp-tools/metaharness-tools.js +106 -1
- package/dist/src/mcp-tools/policy-tools.d.ts +3 -0
- package/dist/src/mcp-tools/policy-tools.js +121 -0
- package/dist/src/memory/memory-bridge.d.ts +11 -0
- package/dist/src/memory/memory-bridge.js +100 -21
- package/dist/src/memory/memory-initializer.d.ts +22 -1
- package/dist/src/memory/memory-initializer.js +184 -39
- package/dist/src/services/bounded-worker-pool.d.ts +28 -0
- package/dist/src/services/bounded-worker-pool.js +90 -0
- package/dist/src/services/flywheel-proposer.d.ts +87 -0
- package/dist/src/services/flywheel-proposer.js +165 -0
- package/dist/src/services/flywheel-receipt.d.ts +136 -0
- package/dist/src/services/flywheel-receipt.js +309 -0
- package/dist/src/services/flywheel-transaction.d.ts +77 -0
- package/dist/src/services/flywheel-transaction.js +378 -0
- package/dist/src/services/harness-flywheel-runtime.d.ts +11 -0
- package/dist/src/services/harness-flywheel-runtime.js +85 -2
- package/dist/src/services/harness-flywheel.d.ts +27 -1
- package/dist/src/services/harness-flywheel.js +138 -27
- package/dist/src/services/policy-runtime.d.ts +38 -0
- package/dist/src/services/policy-runtime.js +340 -0
- package/package.json +23 -5
- package/plugins/ruflo-metaharness/scripts/smoke.sh +22 -14
- package/plugins/ruflo-metaharness/scripts/test-mcp-tools.mjs +3 -1
- package/.claude/.proven-config-version +0 -1
- package/.claude/proven-config.json +0 -42
|
@@ -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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
if (existsSync(join(
|
|
30
|
-
return
|
|
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
|
-
//
|
|
33
|
-
|
|
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, '.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
|
-
|
|
329
|
-
|
|
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
|
-
|
|
360
|
-
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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';
|