claude-flow 3.37.0 → 3.38.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.
- package/.claude-plugin/marketplace.json +15 -0
- package/package.json +1 -1
- package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
- package/v3/@claude-flow/cli/dist/src/commands/migrate-agent-detection.d.ts +27 -0
- package/v3/@claude-flow/cli/dist/src/commands/migrate-agent-detection.js +113 -0
- package/v3/@claude-flow/cli/dist/src/commands/migrate.js +41 -3
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -180,6 +180,21 @@
|
|
|
180
180
|
"name": "ruflo-arena",
|
|
181
181
|
"source": "./plugins/ruflo-arena",
|
|
182
182
|
"description": "Competitive ruliology for ruflo swarms — arenas, tournaments, and adaptive co-evolution of program strategies (ADR-147/148); strategies-as-programs compete under payoff games"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"name": "ruflo-agntcy",
|
|
186
|
+
"source": "./plugins/ruflo-agntcy",
|
|
187
|
+
"description": "AGNTCY/Outshift Internet-of-Cognition runtime integration — SLIM secure transport, CASA intent-scoped tool authorization, and AGNTCY identity/observability spans (ADR-380); optional, removable augmentation per ADR-150"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "ruflo-bbs-federation",
|
|
191
|
+
"source": "./plugins/ruflo-bbs-federation",
|
|
192
|
+
"description": "AgentBBS federated business-domain BBS room integration (ADR-164 Phase 1) — register/publish/watch/human-join MCP tools wrapping the agentbbs Rust workspace as a federation peer; degrades gracefully when agentbbs is absent"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "ruflo-business-pods",
|
|
196
|
+
"source": "./plugins/ruflo-business-pods",
|
|
197
|
+
"description": "Business-domain pod templates for the federated business autopilot (ADR-164 Phase 2) — pod templates plus a dry-run-by-default single-tick runner that validates, reserves budget, and resolves agent roles before posting to the BBS room"
|
|
183
198
|
}
|
|
184
199
|
]
|
|
185
200
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface RemovedAgentMapping {
|
|
2
|
+
/** Basename as it shipped in the init template, e.g. "coder.md". */
|
|
3
|
+
basename: string;
|
|
4
|
+
/** Marketplace plugin id (name in .claude-plugin/marketplace.json) that now owns it. */
|
|
5
|
+
plugin: string;
|
|
6
|
+
}
|
|
7
|
+
export interface RemovedAgentGap {
|
|
8
|
+
agent: string;
|
|
9
|
+
plugin: string;
|
|
10
|
+
installCommand: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DetectRemovedAgentGapsOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Override for the Claude Code plugin-registry home directory. Defaults to
|
|
15
|
+
* os.homedir(). Tests inject an isolated temp dir so results don't depend
|
|
16
|
+
* on whatever is actually installed on the machine running the suite.
|
|
17
|
+
*/
|
|
18
|
+
homeDir?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns one gap row per removed agent that is both missing from the
|
|
22
|
+
* project's .claude/agents/ tree and not covered by an installed owning
|
|
23
|
+
* plugin. Pure filesystem checks, no CLI version comparison (ADR-382 Part B
|
|
24
|
+
* scope note: a filesystem check is sufficient and accurate here).
|
|
25
|
+
*/
|
|
26
|
+
export declare function detectRemovedAgentGaps(cwd: string, removedAgents: RemovedAgentMapping[], options?: DetectRemovedAgentGapsOptions): RemovedAgentGap[];
|
|
27
|
+
//# sourceMappingURL=migrate-agent-detection.d.ts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-382 Part B — the `ruflo migrate` mitigation ADR-128 promised and never
|
|
3
|
+
* shipped: detect the 9 forked agents ADR-128 Phase 2 deleted from the init
|
|
4
|
+
* template (each plugin is now canonical) and, when a project is missing one
|
|
5
|
+
* AND the owning plugin isn't installed, surface an install suggestion.
|
|
6
|
+
* See v3/docs/adr/ADR-382-init-scaffold-content-drift-remediation.md and
|
|
7
|
+
* https://github.com/ruvnet/ruflo/issues/2971.
|
|
8
|
+
*
|
|
9
|
+
* Kept in a sibling module (not migrate.ts) because migrate.ts is already
|
|
10
|
+
* near/over the 500-line budget — see CLAUDE.md file-size rule.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import * as os from 'os';
|
|
15
|
+
/**
|
|
16
|
+
* Claude Code records every plugin install (marketplace-scoped, "user" or
|
|
17
|
+
* "project") in a single global file — ~/.claude/plugins/installed_plugins.json,
|
|
18
|
+
* keyed "<plugin>@<marketplace>". This is the only real on-disk signal for
|
|
19
|
+
* "is the owning plugin installed"; there is no per-project marker and no
|
|
20
|
+
* ruflo-side tracking for marketplace plugins (ruflo's own PluginManager
|
|
21
|
+
* manifest at .claude-flow/plugins/installed.json tracks a different,
|
|
22
|
+
* npm-package-based plugin system).
|
|
23
|
+
*/
|
|
24
|
+
function readInstalledPluginsRegistry(homeDir) {
|
|
25
|
+
const registryPath = path.join(homeDir, '.claude', 'plugins', 'installed_plugins.json');
|
|
26
|
+
try {
|
|
27
|
+
if (!fs.existsSync(registryPath))
|
|
28
|
+
return {};
|
|
29
|
+
const raw = fs.readFileSync(registryPath, 'utf-8');
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
if (parsed && typeof parsed === 'object' && parsed.plugins && typeof parsed.plugins === 'object') {
|
|
32
|
+
return parsed.plugins;
|
|
33
|
+
}
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function isPluginInstalled(pluginName, cwd, registry) {
|
|
41
|
+
const resolvedCwd = path.resolve(cwd);
|
|
42
|
+
const prefix = `${pluginName}@`;
|
|
43
|
+
for (const [key, entries] of Object.entries(registry)) {
|
|
44
|
+
if (!key.startsWith(prefix))
|
|
45
|
+
continue;
|
|
46
|
+
if (!Array.isArray(entries))
|
|
47
|
+
continue;
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (entry?.scope === 'project') {
|
|
50
|
+
if (entry.projectPath && path.resolve(entry.projectPath) === resolvedCwd)
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// "user" scope (or unspecified) applies to every project.
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function agentFileExists(cwd, basename) {
|
|
62
|
+
const agentsDir = path.join(cwd, '.claude', 'agents');
|
|
63
|
+
return findBasename(agentsDir, basename, 0);
|
|
64
|
+
}
|
|
65
|
+
// .claude/agents/ is a shallow tree (category/[subcategory]/name.md); a small
|
|
66
|
+
// depth guard is enough to avoid pathological recursion without needing a
|
|
67
|
+
// real glob dependency for a two-or-three-level lookup.
|
|
68
|
+
const MAX_AGENT_DIR_DEPTH = 6;
|
|
69
|
+
function findBasename(dir, basename, depth) {
|
|
70
|
+
if (depth > MAX_AGENT_DIR_DEPTH)
|
|
71
|
+
return false;
|
|
72
|
+
let entries;
|
|
73
|
+
try {
|
|
74
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
if (entry.isDirectory()) {
|
|
81
|
+
if (findBasename(path.join(dir, entry.name), basename, depth + 1))
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
else if (entry.isFile() && entry.name === basename) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns one gap row per removed agent that is both missing from the
|
|
92
|
+
* project's .claude/agents/ tree and not covered by an installed owning
|
|
93
|
+
* plugin. Pure filesystem checks, no CLI version comparison (ADR-382 Part B
|
|
94
|
+
* scope note: a filesystem check is sufficient and accurate here).
|
|
95
|
+
*/
|
|
96
|
+
export function detectRemovedAgentGaps(cwd, removedAgents, options = {}) {
|
|
97
|
+
const homeDir = options.homeDir ?? os.homedir();
|
|
98
|
+
const registry = readInstalledPluginsRegistry(homeDir);
|
|
99
|
+
const gaps = [];
|
|
100
|
+
for (const { basename, plugin } of removedAgents) {
|
|
101
|
+
if (agentFileExists(cwd, basename))
|
|
102
|
+
continue;
|
|
103
|
+
if (isPluginInstalled(plugin, cwd, registry))
|
|
104
|
+
continue;
|
|
105
|
+
gaps.push({
|
|
106
|
+
agent: basename,
|
|
107
|
+
plugin,
|
|
108
|
+
installCommand: `ruflo plugins install ${plugin}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return gaps;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=migrate-agent-detection.js.map
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { output } from '../output.js';
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
|
+
import { detectRemovedAgentGaps } from './migrate-agent-detection.js';
|
|
8
9
|
// Migration targets
|
|
9
10
|
const MIGRATION_TARGETS = [
|
|
10
11
|
{ value: 'config', label: 'Configuration', hint: 'Migrate configuration files' },
|
|
@@ -15,6 +16,21 @@ const MIGRATION_TARGETS = [
|
|
|
15
16
|
{ value: 'embeddings', label: 'Embeddings', hint: 'Migrate to ONNX with hyperbolic support' },
|
|
16
17
|
{ value: 'all', label: 'All', hint: 'Full migration' }
|
|
17
18
|
];
|
|
19
|
+
// ADR-128 Phase 2 deleted these 9 forked agents from the init template,
|
|
20
|
+
// making each plugin canonical — but ADR-128's own Consequences section
|
|
21
|
+
// promised "`ruflo migrate` should detect removed agents and print install
|
|
22
|
+
// suggestions," which never shipped until ADR-382 Part B (issue #2971).
|
|
23
|
+
const REMOVED_AGENTS = [
|
|
24
|
+
{ basename: 'coder.md', plugin: 'ruflo-core' },
|
|
25
|
+
{ basename: 'researcher.md', plugin: 'ruflo-core' },
|
|
26
|
+
{ basename: 'reviewer.md', plugin: 'ruflo-core' },
|
|
27
|
+
{ basename: 'tester.md', plugin: 'ruflo-testgen' },
|
|
28
|
+
{ basename: 'memory-specialist.md', plugin: 'ruflo-rag-memory' },
|
|
29
|
+
{ basename: 'security-auditor.md', plugin: 'ruflo-security-audit' },
|
|
30
|
+
{ basename: 'sparc-orchestrator.md', plugin: 'ruflo-sparc' },
|
|
31
|
+
{ basename: 'goal-planner.md', plugin: 'ruflo-goals' },
|
|
32
|
+
{ basename: 'adr-architect.md', plugin: 'ruflo-adr' },
|
|
33
|
+
];
|
|
18
34
|
// Status command
|
|
19
35
|
const statusCommand = {
|
|
20
36
|
name: 'status',
|
|
@@ -101,10 +117,13 @@ const statusCommand = {
|
|
|
101
117
|
if (migrationState) {
|
|
102
118
|
components.push({ component: 'Migration State', status: migrationState, migrationNeeded: 'no' });
|
|
103
119
|
}
|
|
120
|
+
// ADR-382 Part B: agents ADR-128 removed from the init template that are
|
|
121
|
+
// both missing from this project and not covered by an installed plugin.
|
|
122
|
+
const removedAgentGaps = detectRemovedAgentGaps(cwd, REMOVED_AGENTS);
|
|
104
123
|
// Display results
|
|
105
124
|
if (ctx.flags.format === 'json') {
|
|
106
|
-
output.printJson({ components, migrationState });
|
|
107
|
-
return { success: true, data: { components, migrationState } };
|
|
125
|
+
output.printJson({ components, migrationState, removedAgentGaps });
|
|
126
|
+
return { success: true, data: { components, migrationState, removedAgentGaps } };
|
|
108
127
|
}
|
|
109
128
|
output.writeln();
|
|
110
129
|
output.writeln(output.bold('Migration Status'));
|
|
@@ -130,7 +149,26 @@ const statusCommand = {
|
|
|
130
149
|
else {
|
|
131
150
|
output.printSuccess('No migration needed.');
|
|
132
151
|
}
|
|
133
|
-
|
|
152
|
+
if (removedAgentGaps.length > 0) {
|
|
153
|
+
output.writeln();
|
|
154
|
+
output.writeln(output.bold('Removed Agents (ADR-128)'));
|
|
155
|
+
output.printTable({
|
|
156
|
+
columns: [
|
|
157
|
+
{ key: 'agent', header: 'Agent', width: 24 },
|
|
158
|
+
{ key: 'plugin', header: 'Owning Plugin', width: 20 },
|
|
159
|
+
{ key: 'installCommand', header: 'Install', width: 34 }
|
|
160
|
+
],
|
|
161
|
+
data: removedAgentGaps.map(g => ({
|
|
162
|
+
agent: output.warning(g.agent),
|
|
163
|
+
plugin: g.plugin,
|
|
164
|
+
installCommand: output.dim(g.installCommand)
|
|
165
|
+
})),
|
|
166
|
+
border: false
|
|
167
|
+
});
|
|
168
|
+
output.writeln();
|
|
169
|
+
output.printInfo(`${removedAgentGaps.length} agent(s) removed by ADR-128 are missing from .claude/agents/ and not covered by an installed plugin.`);
|
|
170
|
+
}
|
|
171
|
+
return { success: true, data: { components, needsMigration, removedAgentGaps } };
|
|
134
172
|
}
|
|
135
173
|
};
|
|
136
174
|
// Run migration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.38.0",
|
|
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",
|