claude-flow-novice 2.14.31 → 2.14.33

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 (57) hide show
  1. package/.claude/cfn-data/cfn-loop.db +0 -0
  2. package/.claude/commands/CFN_LOOP_TASK_MODE.md +1 -1
  3. package/.claude/skills/cfn-agent-discovery/agents-registry.json +10 -9
  4. package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +394 -0
  5. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +521 -0
  6. package/.claude/skills/cfn-docker-loop-orchestration/SKILL.md +449 -0
  7. package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +787 -0
  8. package/.claude/skills/cfn-docker-redis-coordination/SKILL.md +435 -0
  9. package/.claude/skills/cfn-docker-redis-coordination/coordinate.sh +635 -0
  10. package/.claude/skills/cfn-docker-skill-mcp-selection/SKILL.md +289 -0
  11. package/.claude/skills/cfn-docker-skill-mcp-selection/skill-mcp-selector.js +472 -0
  12. package/.claude/skills/cfn-loop-validation/config.json +2 -2
  13. package/.claude/skills/pre-edit-backup/backup.sh +107 -0
  14. package/README.md +95 -0
  15. package/claude-assets/agents/README-AGENT_LIFECYCLE.md +10 -37
  16. package/claude-assets/agents/README-VALIDATION.md +8 -0
  17. package/claude-assets/agents/cfn-dev-team/README.md +8 -0
  18. package/claude-assets/agents/cfn-dev-team/coordinators/README.md +9 -1
  19. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +71 -9
  20. package/claude-assets/agents/cfn-dev-team/developers/README.md +9 -1
  21. package/claude-assets/agents/cfn-dev-team/documentation/README-VALIDATION.md +8 -0
  22. package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +10 -0
  23. package/claude-assets/agents/cfn-dev-team/reviewers/README.md +9 -1
  24. package/claude-assets/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +10 -0
  25. package/claude-assets/agents/cfn-dev-team/test-agent.md +10 -0
  26. package/claude-assets/agents/cfn-dev-team/testers/README.md +9 -1
  27. package/claude-assets/agents/csuite/cto-agent.md +10 -0
  28. package/claude-assets/agents/custom/cfn-system-expert.md +128 -1
  29. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +5 -1
  30. package/claude-assets/agents/docker-team/csuite/c-suite-template.md +5 -1
  31. package/claude-assets/agents/docker-team/infrastructure/team-coordinator-template.md +5 -1
  32. package/claude-assets/agents/marketing_hybrid/cost_tracker.md +10 -0
  33. package/claude-assets/agents/marketing_hybrid/docker_deployer.md +10 -0
  34. package/claude-assets/agents/marketing_hybrid/zai_worker_spawner.md +10 -0
  35. package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +1 -1
  36. package/claude-assets/hooks/cfn-post-execution/memory-cleanup.sh +20 -0
  37. package/claude-assets/hooks/cfn-pre-execution/memory-check.sh +20 -0
  38. package/claude-assets/skills/cfn-agent-discovery/agents-registry.json +10 -9
  39. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +70 -10
  40. package/claude-assets/skills/cfn-loop-validation/config.json +2 -2
  41. package/claude-assets/skills/cfn-memory-management/SKILL.md +271 -0
  42. package/claude-assets/skills/cfn-memory-management/check-memory.sh +160 -0
  43. package/claude-assets/skills/cfn-memory-management/cleanup-memory.sh +197 -0
  44. package/claude-assets/skills/cfn-redis-data-extraction/SKILL.md +442 -0
  45. package/claude-assets/skills/cfn-redis-data-extraction/extract.sh +306 -0
  46. package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +2 -2
  47. package/claude-assets/skills/hook-pipeline/security-scanner.sh +102 -0
  48. package/claude-assets/skills/pre-edit-backup/backup.sh +107 -0
  49. package/dist/cli/agent-command.js +44 -2
  50. package/dist/cli/agent-command.js.map +1 -1
  51. package/dist/cli/config-manager.js +91 -109
  52. package/dist/cli/config-manager.js.map +1 -1
  53. package/dist/cli/index.js +29 -2
  54. package/dist/cli/index.js.map +1 -1
  55. package/package.json +22 -5
  56. package/scripts/deploy-production.sh +356 -0
  57. package/scripts/memory-leak-prevention.sh +306 -0
@@ -0,0 +1,472 @@
1
+ /**
2
+ * Skill-based MCP Selection System
3
+ * Automatically selects MCP servers based on agent skills and requirements
4
+ */
5
+
6
+ const fs = require('fs').promises;
7
+ const path = require('path');
8
+ const AgentTokenManager = require('../cli/agent-token-manager.js');
9
+
10
+ class SkillMCPSelector {
11
+ constructor(options = {}) {
12
+ this.tokenManager = new AgentTokenManager(options);
13
+ this.agentConfigPath = options.agentConfigPath || './config/agent-whitelist.json';
14
+ this.skillConfigPath = options.skillConfigPath || './config/skill-requirements.json';
15
+ this.mcpServersPath = options.mcpServersPath || './config/mcp-servers.json';
16
+
17
+ this.agentWhitelist = new Map();
18
+ this.skillRequirements = new Map();
19
+ this.mcpServers = new Map();
20
+ }
21
+
22
+ async initialize() {
23
+ await this.tokenManager.initialize();
24
+ await this.loadConfigurations();
25
+ console.log('[SkillMCPSelector] Initialized successfully');
26
+ }
27
+
28
+ async loadConfigurations() {
29
+ // Load agent whitelist
30
+ const agentConfig = await this.loadJson(this.agentConfigPath);
31
+ this.agentWhitelist.clear();
32
+ for (const agent of agentConfig.agents) {
33
+ this.agentWhitelist.set(agent.type, agent);
34
+ }
35
+
36
+ // Load skill requirements
37
+ const skillConfig = await this.loadJson(this.skillConfigPath);
38
+ this.skillRequirements.clear();
39
+ for (const [tool, requirements] of Object.entries(skillConfig.tools)) {
40
+ this.skillRequirements.set(tool, requirements);
41
+ }
42
+
43
+ // Load MCP server configurations
44
+ try {
45
+ const mcpConfig = await this.loadJson(this.mcpServersPath);
46
+ for (const [name, config] of Object.entries(mcpConfig.servers)) {
47
+ this.mcpServers.set(name, config);
48
+ }
49
+ } catch (error) {
50
+ console.warn('[SkillMCPSelector] MCP servers config not found, using defaults');
51
+ this.initializeDefaultMCPServers();
52
+ }
53
+ }
54
+
55
+ async loadJson(filePath) {
56
+ const resolvedPath = path.resolve(filePath);
57
+ const content = await fs.readFile(resolvedPath, 'utf8');
58
+ return JSON.parse(content);
59
+ }
60
+
61
+ initializeDefaultMCPServers() {
62
+ // Default MCP server configurations
63
+ const defaultServers = {
64
+ 'playwright': {
65
+ name: 'playwright',
66
+ displayName: 'Playwright Browser Automation',
67
+ description: 'Browser automation and screenshot capabilities',
68
+ containerImage: 'claude-flow-novice:mcp-playwright',
69
+ tools: ['take_screenshot', 'search_google', 'navigate_and_interact'],
70
+ skills: ['browser-automation', 'screenshot-capture', 'web-interaction'],
71
+ resourceRequirements: {
72
+ memoryMB: 1024,
73
+ cpuUnits: 2
74
+ }
75
+ },
76
+ 'redis': {
77
+ name: 'redis',
78
+ displayName: 'Redis Database',
79
+ description: 'Redis key-value store operations',
80
+ containerImage: 'claude-flow-novice:mcp-redis',
81
+ tools: ['redis_get', 'redis_set', 'redis_keys'],
82
+ skills: ['redis-operations', 'cache-management'],
83
+ resourceRequirements: {
84
+ memoryMB: 256,
85
+ cpuUnits: 1
86
+ }
87
+ },
88
+ 'postgres': {
89
+ name: 'postgres',
90
+ displayName: 'PostgreSQL Database',
91
+ description: 'PostgreSQL database operations',
92
+ containerImage: 'claude-flow-novice:mcp-postgres',
93
+ tools: ['postgres_query', 'postgres_schema', 'postgres_migrate'],
94
+ skills: ['database-design', 'sql-operations'],
95
+ resourceRequirements: {
96
+ memoryMB: 512,
97
+ cpuUnits: 2
98
+ }
99
+ },
100
+ 'security-scanner': {
101
+ name: 'security-scanner',
102
+ displayName: 'Security Scanner',
103
+ description: 'Security vulnerability scanning and analysis',
104
+ containerImage: 'claude-flow-novice:mcp-security',
105
+ tools: ['security_scan', 'vulnerability_check', 'compliance_validate'],
106
+ skills: ['security-auditing', 'vulnerability-scanning'],
107
+ resourceRequirements: {
108
+ memoryMB: 1536,
109
+ cpuUnits: 4
110
+ }
111
+ }
112
+ };
113
+
114
+ for (const [name, config] of Object.entries(defaultServers)) {
115
+ this.mcpServers.set(name, config);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Determine which MCP servers an agent needs based on their skills
121
+ */
122
+ selectMCPServers(agentType, agentSkills = null) {
123
+ const agentConfig = this.agentWhitelist.get(agentType);
124
+ if (!agentConfig) {
125
+ throw new Error(`Unknown agent type: ${agentType}`);
126
+ }
127
+
128
+ // Use provided skills or fall back to agent config
129
+ const skills = agentSkills || agentConfig.skills;
130
+
131
+ // Determine required MCP servers based on skills
132
+ const requiredMCPServers = new Set();
133
+ const skillToMCPServerMap = this.getSkillToMCPServerMapping();
134
+
135
+ // Map skills to required MCP servers
136
+ for (const skill of skills) {
137
+ if (skillToMCPServerMap.has(skill)) {
138
+ const servers = skillToMCPServerMap.get(skill);
139
+ servers.forEach(server => requiredMCPServers.add(server));
140
+ }
141
+ }
142
+
143
+ // Add explicitly allowed MCP servers from agent config
144
+ if (agentConfig.allowedMcpServers) {
145
+ agentConfig.allowedMcpServers.forEach(server => requiredMCPServers.add(server));
146
+ }
147
+
148
+ // Convert to array and sort by priority
149
+ const selectedServers = Array.from(requiredMCPServers)
150
+ .filter(server => this.mcpServers.has(server))
151
+ .sort((a, b) => {
152
+ const priorityA = this.mcpServers.get(a).priority || 999;
153
+ const priorityB = this.mcpServers.get(b).priority || 999;
154
+ return priorityA - priorityB;
155
+ });
156
+
157
+ return {
158
+ agentType,
159
+ agentSkills: skills,
160
+ selectedMCPServers,
161
+ serverDetails: selectedServers.map(server => this.mcpServers.get(server)),
162
+ totalMemoryRequired: selectedServers.reduce((sum, server) =>
163
+ sum + (this.mcpServers.get(server).resourceRequirements?.memoryMB || 512), 0),
164
+ totalCPURequired: selectedServers.reduce((sum, server) =>
165
+ sum + (this.mcpServers.get(server).resourceRequirements?.cpuUnits || 1), 0)
166
+ };
167
+ }
168
+
169
+ /**
170
+ * Get mapping from skills to required MCP servers
171
+ */
172
+ getSkillToMCPServerMapping() {
173
+ const skillMap = new Map();
174
+
175
+ // Build mapping from MCP server configurations
176
+ for (const [serverName, serverConfig] of this.mcpServers.entries()) {
177
+ for (const skill of serverConfig.skills || []) {
178
+ if (!skillMap.has(skill)) {
179
+ skillMap.set(skill, new Set());
180
+ }
181
+ skillMap.get(skill).add(serverName);
182
+ }
183
+ }
184
+
185
+ // Also add mappings from tool requirements
186
+ for (const [toolName, toolConfig] of this.skillRequirements.entries()) {
187
+ for (const skill of toolConfig.requiredSkills || []) {
188
+ // Find MCP servers that provide this tool
189
+ for (const [serverName, serverConfig] of this.mcpServers.entries()) {
190
+ if (serverConfig.tools?.includes(toolName)) {
191
+ if (!skillMap.has(skill)) {
192
+ skillMap.set(skill, new Set());
193
+ }
194
+ skillMap.get(skill).add(serverName);
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ return skillMap;
201
+ }
202
+
203
+ /**
204
+ * Generate tokens for selected MCP servers
205
+ */
206
+ async generateMCPTokens(agentType, selectedServers, options = {}) {
207
+ const tokens = [];
208
+
209
+ for (const serverName of selectedServers) {
210
+ try {
211
+ const serverConfig = this.mcpServers.get(serverName);
212
+ if (!serverConfig) {
213
+ console.warn(`[SkillMCPSelector] Server configuration not found: ${serverName}`);
214
+ continue;
215
+ }
216
+
217
+ // Generate server-specific token
218
+ const tokenData = await this.tokenManager.registerAgentToken(agentType, {
219
+ expiresIn: options.expiresIn || '24h',
220
+ description: `Token for ${serverConfig.displayName}`,
221
+ createdBy: 'skill-mcp-selector',
222
+ mcpServer: serverName
223
+ });
224
+
225
+ tokens.push({
226
+ serverName,
227
+ displayName: serverConfig.displayName,
228
+ token: tokenData.token,
229
+ expiresAt: tokenData.expiresAt,
230
+ containerImage: serverConfig.containerImage,
231
+ connectionInfo: this.generateConnectionInfo(serverName, serverConfig, tokenData.token)
232
+ });
233
+
234
+ console.log(`[SkillMCPSelector] Generated token for ${agentType} → ${serverName}`);
235
+ } catch (error) {
236
+ console.error(`[SkillMCPSelector] Failed to generate token for ${serverName}:`, error);
237
+ }
238
+ }
239
+
240
+ return tokens;
241
+ }
242
+
243
+ /**
244
+ * Generate connection information for MCP server
245
+ */
246
+ generateConnectionInfo(serverName, serverConfig, token) {
247
+ const baseInfo = {
248
+ serverName,
249
+ token,
250
+ authentication: {
251
+ type: 'token-based',
252
+ header: 'x-agent-token',
253
+ agentTypeHeader: 'x-agent-type'
254
+ }
255
+ };
256
+
257
+ // Add server-specific connection details
258
+ if (serverConfig.connectionType === 'docker') {
259
+ return {
260
+ ...baseInfo,
261
+ type: 'docker-container',
262
+ containerName: `mcp-${serverName}`,
263
+ containerImage: serverConfig.containerImage,
264
+ dockerArgs: [
265
+ 'run', '--rm', '--init',
266
+ '--name', `mcp-${serverName}`,
267
+ '--memory', `${serverConfig.resourceRequirements?.memoryMB || 512}m`,
268
+ '--cpus', `${serverConfig.resourceRequirements?.cpuUnits || 1}`,
269
+ '-e', `MCP_SERVER=${serverName}`,
270
+ '-e', `MCP_AUTH_REQUIRED=true`,
271
+ '-e', `MCP_REDIS_URL=${process.env.MCP_REDIS_URL || 'redis://localhost:6379'}`,
272
+ serverConfig.containerImage,
273
+ 'node', `/app/mcp-${serverName}-server.js`
274
+ ]
275
+ };
276
+ } else {
277
+ return {
278
+ ...baseInfo,
279
+ type: 'http-endpoint',
280
+ url: serverConfig.url || `http://localhost:${3000 + this.mcpServers.size}`,
281
+ headers: {
282
+ 'Content-Type': 'application/json',
283
+ 'x-agent-token': token,
284
+ 'x-agent-type': 'dynamic'
285
+ }
286
+ };
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Get complete MCP configuration for an agent
292
+ */
293
+ async getAgentMCPConfiguration(agentType, agentSkills = null, options = {}) {
294
+ try {
295
+ // Select required MCP servers
296
+ const selection = this.selectMCPServers(agentType, agentSkills);
297
+
298
+ // Generate tokens for selected servers
299
+ const tokens = await this.generateMCPTokens(
300
+ agentType,
301
+ selection.selectedMCPServers,
302
+ options
303
+ );
304
+
305
+ return {
306
+ agentType,
307
+ agentSkills: selection.agentSkills,
308
+ mcpConfiguration: {
309
+ mcpServers: tokens.reduce((config, tokenInfo) => {
310
+ config[tokenInfo.serverName] = {
311
+ command: 'docker',
312
+ args: tokenInfo.connectionInfo.dockerArgs,
313
+ env: {
314
+ 'MCP_SERVER': tokenInfo.serverName,
315
+ 'MCP_AUTH_REQUIRED': 'true',
316
+ 'AGENT_TOKEN': tokenInfo.token
317
+ }
318
+ };
319
+ return config;
320
+ }, {})
321
+ },
322
+ selection,
323
+ tokens,
324
+ resourceSummary: {
325
+ totalMemoryMB: selection.totalMemoryRequired,
326
+ totalCPUUnits: selection.totalCPUUnits,
327
+ serverCount: selection.selectedMCPServers.length
328
+ }
329
+ };
330
+ } catch (error) {
331
+ console.error(`[SkillMCPSelector] Failed to get MCP configuration for ${agentType}:`, error);
332
+ throw error;
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Generate Docker Compose configuration for agent with MCP servers
338
+ */
339
+ async generateDockerComposeConfiguration(agentType, agentSkills = null, options = {}) {
340
+ const config = await this.getAgentMCPConfiguration(agentType, agentSkills, options);
341
+
342
+ const dockerCompose = {
343
+ version: '3.8',
344
+ services: {},
345
+ networks: {
346
+ 'mcp-network': {
347
+ driver: 'bridge'
348
+ }
349
+ }
350
+ };
351
+
352
+ // Add agent service
353
+ dockerCompose.services[`${agentType}-agent`] = {
354
+ image: 'claude-flow-novice:agent-container',
355
+ container_name: `agent-${agentType}-${Date.now()}`,
356
+ networks: ['mcp-network'],
357
+ environment: {
358
+ 'AGENT_TYPE': agentType,
359
+ 'AGENT_MODE': 'containerized',
360
+ 'MCP_AUTH_ENABLED': 'true',
361
+ 'REDIS_URL': process.env.MCP_REDIS_URL || 'redis://redis:6379'
362
+ },
363
+ volumes: [
364
+ '${PWD}/.claude:/app/.claude:ro',
365
+ '${PWD}/screenshots:/app/screenshots'
366
+ ],
367
+ mem_limit: `${config.resourceSummary.totalMemoryMB + 512}m`,
368
+ depends_on: config.selection.selectedMCPServers.map(server => `mcp-${server}`).join(' ')
369
+ };
370
+
371
+ // Add MCP server services
372
+ for (const tokenInfo of config.tokens) {
373
+ const serverName = `mcp-${tokenInfo.serverName}`;
374
+ const serverConfig = this.mcpServers.get(tokenInfo.serverName);
375
+
376
+ dockerCompose.services[serverName] = {
377
+ image: tokenInfo.containerImage,
378
+ container_name: `${serverName}-${Date.now()}`,
379
+ networks: ['mcp-network'],
380
+ environment: {
381
+ 'MCP_SERVER': tokenInfo.serverName,
382
+ 'MCP_AUTH_REQUIRED': 'true',
383
+ 'MCP_REDIS_URL': process.env.MCP_REDIS_URL || 'redis://redis:6379',
384
+ 'AGENT_TOKEN': tokenInfo.token
385
+ },
386
+ volumes: [
387
+ '${PWD}/screenshots:/app/screenshots'
388
+ ],
389
+ mem_limit: `${serverConfig.resourceRequirements?.memoryMB || 512}m`,
390
+ cpus: `${(serverConfig.resourceRequirements?.cpuUnits || 1) / 4}`
391
+ };
392
+ }
393
+
394
+ // Add Redis service if not present
395
+ if (!dockerCompose.services.redis) {
396
+ dockerCompose.services.redis = {
397
+ image: 'redis:7-alpine',
398
+ container_name: 'mcp-redis',
399
+ networks: ['mcp-network'],
400
+ volumes: ['redis-data:/data'],
401
+ mem_limit: '256m'
402
+ };
403
+ dockerCompose.volumes = {
404
+ 'redis-data': {}
405
+ };
406
+ }
407
+
408
+ return dockerCompose;
409
+ }
410
+
411
+ /**
412
+ * Get statistics about skill-MCP mappings
413
+ */
414
+ getStatistics() {
415
+ const skillMap = this.getSkillToMCPServerMapping();
416
+
417
+ return {
418
+ totalAgents: this.agentWhitelist.size,
419
+ totalMCPServers: this.mcpServers.size,
420
+ totalSkills: skillMap.size,
421
+ agentTypes: Array.from(this.agentWhitelist.keys()),
422
+ mcpServerNames: Array.from(this.mcpServers.keys()),
423
+ skillCoverage: Array.from(skillMap.entries()).map(([skill, servers]) => ({
424
+ skill,
425
+ requiredServers: Array.from(servers),
426
+ serverCount: servers.size
427
+ }))
428
+ };
429
+ }
430
+
431
+ /**
432
+ * Validate agent-MCP configuration
433
+ */
434
+ validateConfiguration(agentType, mcpConfiguration) {
435
+ const agentConfig = this.agentWhitelist.get(agentType);
436
+ if (!agentConfig) {
437
+ return { valid: false, errors: [`Unknown agent type: ${agentType}`] };
438
+ }
439
+
440
+ const errors = [];
441
+ const warnings = [];
442
+
443
+ // Check required MCP servers
444
+ const requiredServers = agentConfig.allowedMcpServers || [];
445
+ const configuredServers = Object.keys(mcpConfiguration.mcpServers || {});
446
+
447
+ for (const server of requiredServers) {
448
+ if (!configuredServers.includes(server)) {
449
+ errors.push(`Required MCP server missing: ${server}`);
450
+ }
451
+ }
452
+
453
+ // Check for unauthorized servers
454
+ for (const server of configuredServers) {
455
+ if (!requiredServers.includes(server)) {
456
+ warnings.push(`Potentially unauthorized MCP server: ${server}`);
457
+ }
458
+ }
459
+
460
+ return {
461
+ valid: errors.length === 0,
462
+ errors,
463
+ warnings
464
+ };
465
+ }
466
+
467
+ async shutdown() {
468
+ await this.tokenManager.shutdown();
469
+ }
470
+ }
471
+
472
+ module.exports = SkillMCPSelector;
@@ -55,12 +55,12 @@
55
55
  "security-specialist",
56
56
  "tester",
57
57
  "analyst",
58
- "architect"
58
+ "system-architect"
59
59
  ],
60
60
  "productOwnerStructure": "team",
61
61
  "planningConsensus": {
62
62
  "enabled": true,
63
- "architectTypes": ["architect", "system-architect", "security-specialist"],
63
+ "architectTypes": ["system-architect", "security-specialist"],
64
64
  "threshold": 0.85
65
65
  },
66
66
  "productOwnerTeam": {
@@ -0,0 +1,107 @@
1
+ #!/bin/bash
2
+
3
+ ##############################################################################
4
+ # Pre-Edit Backup Script - Creates safe file backups before modifications
5
+ # Version: 1.0.0
6
+ ##############################################################################
7
+
8
+ set -euo pipefail
9
+
10
+ # Function to create backup of a file before editing
11
+ create_backup() {
12
+ local file_path="$1"
13
+ local agent_id="${2:-unknown}"
14
+ local project_root="${3:-$(pwd)}"
15
+
16
+ # Validate inputs
17
+ if [[ -z "$file_path" ]]; then
18
+ echo "Error: File path is required" >&2
19
+ exit 1
20
+ fi
21
+
22
+ # Check if file exists
23
+ if [[ ! -f "$file_path" ]]; then
24
+ echo "Warning: File does not exist: $file_path" >&2
25
+ # Create empty backup path for new files
26
+ echo "$project_root/.backups/$agent_id/new-file-$(date +%s)-$(echo "$file_path" | tr '/' '_' | tr ' ' '_')"
27
+ return 0
28
+ fi
29
+
30
+ # Create backup directory structure
31
+ local backup_dir="$project_root/.backups/$agent_id"
32
+ local timestamp=$(date +%s)
33
+ local file_hash=$(md5sum "$file_path" | cut -d' ' -f1)
34
+ local backup_name="${timestamp}_${file_hash}"
35
+
36
+ # Create full backup path
37
+ local full_backup_path="$backup_dir/$backup_name"
38
+
39
+ # Create backup directory
40
+ mkdir -p "$full_backup_path"
41
+
42
+ # Copy original file to backup location
43
+ cp "$file_path" "$full_backup_path/original"
44
+
45
+ # Store backup metadata
46
+ cat > "$full_backup_path/metadata.json" << EOF
47
+ {
48
+ "timestamp": "$timestamp",
49
+ "agent_id": "$agent_id",
50
+ "original_file": "$file_path",
51
+ "file_hash": "$file_hash",
52
+ "backup_path": "$full_backup_path",
53
+ "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
54
+ }
55
+ EOF
56
+
57
+ # Create revert script
58
+ cat > "$full_backup_path/revert.sh" << EOF
59
+ #!/bin/bash
60
+ # Revert script for $file_path
61
+ set -euo pipefail
62
+
63
+ echo "Reverting file: $file_path"
64
+ cp "$full_backup_path/original" "$file_path"
65
+ echo "✅ File reverted successfully"
66
+ EOF
67
+
68
+ chmod +x "$full_backup_path/revert.sh"
69
+
70
+ # Output backup path for caller
71
+ echo "$full_backup_path"
72
+
73
+ echo "✅ Backup created: $full_backup_path" >&2
74
+ }
75
+
76
+ # Main execution
77
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
78
+ # Script called directly
79
+ if [[ $# -lt 1 ]]; then
80
+ echo "Usage: $0 <file_path> [--agent-id <id>] [--project-root <path>]" >&2
81
+ exit 1
82
+ fi
83
+
84
+ file_path="$1"
85
+ agent_id="unknown"
86
+ project_root="$(pwd)"
87
+
88
+ # Parse optional arguments
89
+ while [[ $# -gt 0 ]]; do
90
+ case $1 in
91
+ --agent-id)
92
+ agent_id="$2"
93
+ shift 2
94
+ ;;
95
+ --project-root)
96
+ project_root="$2"
97
+ shift 2
98
+ ;;
99
+ *)
100
+ # Skip unknown arguments
101
+ shift
102
+ ;;
103
+ esac
104
+ done
105
+
106
+ create_backup "$file_path" "$agent_id" "$project_root"
107
+ fi
package/README.md CHANGED
@@ -21,6 +21,18 @@ npx cfn-loop "Implement JWT authentication system" --mode=standard
21
21
  # Or spawn agents directly
22
22
  npx cfn-spawn backend-developer --task-id auth-task
23
23
  ```
24
+ **Installation:**
25
+ ```bash
26
+ npm install claude-flow-novice
27
+ npx cfn-init # Copy namespace-isolated files
28
+ ```
29
+
30
+ **Collision Risk:** ~0.01% (user custom files preserved)
31
+
32
+ **Package:** 573 KB tarball, 2.4 MB unpacked, 303 files (68% reduction from v2.0.0)
33
+
34
+ **Agent Discovery:** Recursive search through `.claude/agents/**/*.md` finds both cfn-dev-team and user custom agents
35
+
24
36
 
25
37
  **What happens on install**:
26
38
  - Copies 23 agents to `.claude/agents/cfn-dev-team/`
@@ -171,6 +183,89 @@ User Task Description
171
183
 
172
184
  ---
173
185
 
186
+ ### CFN Loop Execution Modes
187
+
188
+ **User selects mode. Main Chat executes the specified slash command.**
189
+
190
+ **Default: Task Mode** (default mode when user doesn't specify)
191
+
192
+ **Available modes:**
193
+
194
+ **1. Task Mode (Default):**
195
+ ```bash
196
+ /cfn-loop-task "Task description" --mode=standard
197
+ ```
198
+ - Main Chat spawns ALL agents via Task()
199
+ - NO coordinator agent
200
+ - Cost: $0.150/iteration
201
+ - Full visibility in Main Chat
202
+ - Use: Debugging, learning, short tasks (<5 min)
203
+
204
+ **2. CLI Mode (Production):**
205
+ ```bash
206
+ /cfn-loop-cli "Task description" --mode=standard
207
+ ```
208
+ - Main Chat spawns ONLY cfn-v3-coordinator
209
+ - Coordinator spawns workers via CLI (background)
210
+ - Cost: $0.054/iteration (64% savings vs Task)
211
+ - Use: Production, long tasks, cost-sensitive
212
+
213
+ **Mode selection guidance for users:**
214
+ - "execute cfn loop on X" → `/cfn-loop-task` (default)
215
+ - "use task mode on X" → `/cfn-loop-task`
216
+ - "use cli mode on X" → `/cfn-loop-cli`
217
+ - "production cfn loop on X" → `/cfn-loop-cli`
218
+
219
+ **Architecture patterns:**
220
+ - CLI: Main Chat → cfn-v3-coordinator → orchestrate.sh → CLI workers (background)
221
+ - Task: Main Chat → Task() agents (no coordinator, full visibility)
222
+
223
+ **Cost breakdown:**
224
+ - CLI mode: $0.054/iteration (Z.ai routing for workers)
225
+ - Task mode: $0.150/iteration (Anthropic for all agents)
226
+
227
+ **Context Storage:**
228
+ - CLI mode: Coordinator stores context in persistence layer for agents to retrieve
229
+ - Task mode: Main Chat passes context directly to each Task() spawn (no persistence needed)
230
+ - CLI agents read from context: coordination protocols retrieve task context
231
+
232
+ **Reference:**
233
+ - Implementation details: `planning/cfn-v3/DUAL_MODE_IMPLEMENTATION.md`
234
+ - **Task Mode guide**: `.claude/commands/cfn/CFN_LOOP_TASK_MODE.md` (agent specialization, sprint workflow, backlog management)
235
+
236
+ ### Custom Routing (Z.ai Provider Integration)
237
+
238
+ **Provider Routing Model:**
239
+ - **Task() agents** → Use Main Chat provider (Anthropic)
240
+ - **CLI-spawned agents** → Use custom routing (Z.ai when enabled)
241
+
242
+ **Enable Custom Routing (One-Time Setup):**
243
+ ```bash
244
+ /custom-routing-activate
245
+ ```
246
+
247
+ **Switch Provider to Z.ai or Claude Subscription**
248
+ ```bash
249
+ /switch-api status
250
+ ```
251
+ ```bash
252
+ /switch-api zai
253
+ ```
254
+ ```bash
255
+ /switch-api max
256
+ ```
257
+
258
+ **Cost Impact:**
259
+ ```
260
+ Without Custom Routing:
261
+ - CLI agents use Anthropic ($3-15/1M tokens)
262
+
263
+ With Custom Routing:
264
+ - CLI agents use Z.ai ($0.50/1M tokens)
265
+ - ~5x cost reduction per CLI agent call
266
+ - Combined with CLI spawning: 95-98% total savings vs Task tool
267
+ ```
268
+
174
269
  ## 🧠 AI-Driven Intelligence (43 Modular Skills)
175
270
 
176
271
  ### Phase 1: Foundation (5 Skills)