v3/implementation/migration/v3-migration-roadmap.md
Project: Claude-Flow v2.x → v3.0 Migration Timeline: 20 weeks (5 months) Team Size: 2-3 core developers + community contributors Start Date: 2026-01-06 (planned) Target Release: 2026-06-01
Transform Claude-Flow from a monolithic orchestration system into a modular, agentic-flow-native platform with clear domain boundaries, plugin extensibility, and superior performance.
In Scope:
Out of Scope (Defer to v3.1+):
Phase 1: Foundation [Weeks 1-4] ████░░░░░░░░░░░░░░░░
Phase 2: Core Domains [Weeks 5-12] ░░░░████████░░░░░░░░
Phase 3: Plugin System [Weeks 13-16] ░░░░░░░░░░░░████░░░░
Phase 4: Integration [Weeks 17-20] ░░░░░░░░░░░░░░░░████
Goal: Establish v3 architecture foundation
Deliverables:
Key Metrics:
Goal: Implement four core bounded contexts
Deliverables:
Key Metrics:
Goal: Extract specialized features as plugins
Deliverables:
Key Metrics:
Goal: Test, optimize, document, release
Deliverables:
Key Metrics:
Objectives:
Tasks:
Day 1-2: Environment Setup
# Create v3 branch
git checkout -b v3-development
# Create directory structure
mkdir -p src-v3/{shared-kernel,infrastructure,agent-lifecycle,task-execution,memory-management,coordination}
# Set up package.json for v3
cp package.json package-v3.json
# Update scripts for dual build
Day 3-4: Shared Kernel
// src-v3/shared-kernel/types/
- agent-types.ts // AgentId, AgentType, AgentStatus
- task-types.ts // TaskId, TaskType, TaskStatus
- memory-types.ts // MemoryEntry, MemoryQuery
- event-types.ts // DomainEvent base classes
// src-v3/shared-kernel/events/
- agent-events.ts // AgentSpawned, AgentTerminated
- task-events.ts // TaskCreated, TaskCompleted
- system-events.ts // SystemStarted, SystemShutdown
// src-v3/shared-kernel/errors/
- domain-errors.ts // DomainError base class
- application-errors.ts // ValidationError, NotFoundError
Day 5: Testing Setup
# Install Vitest
npm install -D vitest vite @vitest/ui
# Create vitest.config.ts
# Set up test utilities
# Create first test: shared-kernel.test.ts
Deliverables:
Success Criteria:
npm run test # All tests pass
npm run typecheck # No TypeScript errors
npm run lint # No linting errors
Objectives:
Tasks:
Event Bus (Day 1-2)
// src-v3/infrastructure/event-bus/event-bus.ts
export class EventBus implements IEventBus {
private handlers = new Map<string, EventHandler[]>();
emit(event: DomainEvent): void {
const handlers = this.handlers.get(event.type) || [];
handlers.forEach(handler => handler(event));
}
on(eventType: string, handler: EventHandler): void {
const handlers = this.handlers.get(eventType) || [];
handlers.push(handler);
this.handlers.set(eventType, handlers);
}
// off, once, etc.
}
// Tests
- event-bus.test.ts
- event-handler.test.ts
Logging Service (Day 2-3)
// src-v3/infrastructure/logging/logger.ts
export class Logger implements ILogger {
constructor(
private config: LogConfig,
private transports: ILogTransport[]
) {}
info(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
error(message: string, error?: Error): void;
debug(message: string, meta?: any): void;
}
// Transports
- ConsoleTransport
- FileTransport
- StructuredLogTransport (JSON)
// Tests
- logger.test.ts
- transports.test.ts
Persistence Layer (Day 3-4)
// src-v3/infrastructure/persistence/
- connection-pool.ts // Database connection pooling
- migrations.ts // Schema migrations
- repositories/
- base-repository.ts // Generic repository pattern
// Tests
- connection-pool.test.ts
- migrations.test.ts
- base-repository.test.ts
Configuration (Day 5)
// src-v3/infrastructure/config/config-manager.ts
export class ConfigManager {
private config: ClaudeFlowConfig;
load(path?: string): Promise<void>;
get<T>(key: string): T;
set(key: string, value: any): void;
validate(): ValidationResult;
}
// Config schema
- config-schema.ts
- default-config.ts
// Tests
- config-manager.test.ts
- config-validation.test.ts
Deliverables:
Objectives:
Plugin Interface (Day 1)
// src-v3/infrastructure/plugins/plugin-interface.ts
export interface ClaudeFlowPlugin {
readonly name: string;
readonly version: string;
readonly dependencies?: string[];
initialize(context: PluginContext): Promise<void>;
shutdown(): Promise<void>;
// Optional hooks
registerAgentTypes?(): AgentTypeDefinition[];
registerTaskTypes?(): TaskTypeDefinition[];
registerMCPTools?(): MCPTool[];
registerCLICommands?(): Command[];
registerMemoryBackends?(): MemoryBackendFactory[];
}
export interface PluginContext {
eventBus: IEventBus;
logger: ILogger;
config: ConfigManager;
services: {
agentService?: AgentLifecycleService;
taskService?: TaskExecutionService;
memoryService?: MemoryService;
};
}
Plugin Loader (Day 2-3)
// src-v3/infrastructure/plugins/plugin-loader.ts
export class PluginLoader {
private plugins = new Map<string, ClaudeFlowPlugin>();
private initialized = new Set<string>();
async loadPlugin(plugin: ClaudeFlowPlugin): Promise<void> {
// Validate plugin
this.validatePlugin(plugin);
// Check dependencies
await this.checkDependencies(plugin);
// Initialize plugin
await plugin.initialize(this.createContext());
// Register plugin
this.plugins.set(plugin.name, plugin);
this.initialized.add(plugin.name);
this.logger.info(`Plugin loaded: ${plugin.name}`);
}
async unloadPlugin(name: string): Promise<void> {
const plugin = this.plugins.get(name);
if (!plugin) return;
// Shutdown plugin
await plugin.shutdown();
// Unregister
this.plugins.delete(name);
this.initialized.delete(name);
}
getPlugin(name: string): ClaudeFlowPlugin | undefined;
listPlugins(): ClaudeFlowPlugin[];
}
Example Plugin (Day 4)
// src-v3/plugins/example/example-plugin.ts
export class ExamplePlugin implements ClaudeFlowPlugin {
readonly name = 'example';
readonly version = '1.0.0';
async initialize(context: PluginContext): Promise<void> {
context.logger.info('Example plugin initializing...');
// Register custom agent type
context.services.agentService?.registerAgentType({
type: 'example-agent',
capabilities:
});
// Subscribe to events
context.eventBus.on('task:created', this.handleTaskCreated);
}
async shutdown(): Promise<void> {
// Cleanup
}
registerMCPTools(): MCPTool[] {
return [{
name: 'example/hello',
description: 'Example tool',
handler: async () => ({ message: 'Hello from plugin!' })
}];
}
private handleTaskCreated(event: TaskCreated): void {
// Handle event
}
}
Tests (Day 5)
// plugin-loader.test.ts
describe('PluginLoader', () => {
it('should load plugin successfully');
it('should validate plugin interface');
it('should check dependencies');
it('should handle initialization errors');
it('should unload plugin cleanly');
it('should prevent duplicate plugins');
});
// example-plugin.test.ts
describe('ExamplePlugin', () => {
it('should initialize correctly');
it('should register agent types');
it('should provide MCP tools');
it('should handle events');
});
Deliverables:
Objectives:
CI/CD Setup (Day 1-2)
# .github/workflows/v3-ci.yml
name: Claude-Flow v3 CI
on:
push:
branches: [v3-development]
pull_request:
branches: [v3-development]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Type check
run: npm run typecheck:v3
- name: Lint
run: npm run lint:v3
- name: Test
run: npm run test:v3
- name: Coverage
run: npm run coverage:v3
build:
runs-on: ubuntu-latest
steps:
- name: Build v3
run: npm run build:v3
- name: Package
run: npm pack
benchmark:
runs-on: ubuntu-latest
steps:
- name: Run benchmarks
run: npm run benchmark:v3
- name: Compare with v2
run: npm run benchmark:compare
Documentation (Day 3-4)
docs/
├── v3/
│ ├── README.md # v3 overview
│ ├── getting-started.md # Quick start guide
│ ├── architecture/
│ │ ├── overview.md
│ │ ├── domains.md # Domain descriptions
│ │ ├── plugin-system.md
│ │ └── adrs/ # Architecture decisions
│ ├── guides/
│ │ ├── agent-lifecycle.md
│ │ ├── task-execution.md
│ │ ├── memory-management.md
│ │ ├── plugin-development.md
│ │ └── migration-from-v2.md
│ ├── api/
│ │ ├── mcp-tools.md # MCP tool reference
│ │ ├── cli-commands.md # CLI reference
│ │ └── typescript-api.md # Programmatic API
│ └── contributing/
│ ├── setup.md
│ ├── coding-standards.md
│ └── testing.md
API Documentation (Day 4-5)
# Install TypeDoc
npm install -D typedoc
# Generate API docs
npx typedoc --out docs/api src-v3/
# Generate MCP tool schema
npm run mcp:generate-schema
Migration Planning (Day 5)
# docs/v3/guides/migration-from-v2.md
## Overview
Step-by-step guide for migrating from v2 to v3
## Breaking Changes
- [List all breaking changes]
## Migration Checklist
- [ ] Update configuration file
- [ ] Migrate custom agents
- [ ] Update CLI scripts
- [ ] Migrate data
- [ ] Test thoroughly
## Automated Migration Tool
```bash
npx claude-flow migrate v2-to-v3
[Troubleshooting guide]
**Deliverables:**
- [ ] CI/CD pipeline running
- [ ] Documentation structure complete
- [ ] API docs auto-generated
- [ ] Migration guide drafted
- [ ] Benchmarking suite set up
**Phase 1 Complete! 🎉**
At this point, we have:
- ✅ Solid foundation for v3
- ✅ Shared kernel types and events
- ✅ Infrastructure layer
- ✅ Plugin system core
- ✅ Testing and CI/CD
- ✅ Documentation framework
**Checkpoint Metrics:**
- Lines of code: ~5,000
- Test coverage: >90%
- Build time: <10s
- CI/CD: Green
- Documentation: 70% complete
---
### Sprints 5-6 (Weeks 5-6): Agent Lifecycle Domain
**Goal:** Implement complete agent lifecycle management
**Domain Model (Sprint 5, Day 1-2)**
```typescript
// src-v3/agent-lifecycle/domain/models/agent.ts
export class Agent extends AggregateRoot {
private constructor(
readonly id: AgentId,
private type: AgentType,
private status: AgentStatus,
private capabilities: AgentCapabilities,
private metrics: AgentMetrics
) {
super();
}
static create(template: AgentTemplate): Agent {
const agent = new Agent(
AgentId.generate(),
template.type,
AgentStatus.Initializing,
template.capabilities,
AgentMetrics.initial()
);
agent.addDomainEvent(new AgentCreated(agent.id, agent.type));
return agent;
}
spawn(): void {
if (this.status !== AgentStatus.Initializing) {
throw new InvalidStateTransition('Cannot spawn non-initializing agent');
}
this.status = AgentStatus.Idle;
this.addDomainEvent(new AgentSpawned(this.id, new Date()));
}
assignTask(taskId: TaskId): void {
if (this.status !== AgentStatus.Idle) {
throw new AgentNotAvailable(this.id);
}
this.status = AgentStatus.Busy;
this.addDomainEvent(new TaskAssignedToAgent(this.id, taskId));
}
completeTask(): void {
this.status = AgentStatus.Idle;
this.metrics.tasksCompleted++;
this.addDomainEvent(new AgentTaskCompleted(this.id));
}
terminate(): void {
this.status = AgentStatus.Terminated;
this.addDomainEvent(new AgentTerminated(this.id, new Date()));
}
reportHealth(): AgentHealth {
return new AgentHealth(
this.id,
this.calculateHealthScore(),
this.metrics,
new Date()
);
}
private calculateHealthScore(): number {
// Calculate based on metrics
const successRate = this.metrics.tasksCompleted /
(this.metrics.tasksCompleted + this.metrics.tasksFailed);
return successRate * this.metrics.uptime / this.metrics.totalTime;
}
}
Repository Interface (Sprint 5, Day 2-3)
// src-v3/agent-lifecycle/domain/interfaces/agent-repository.ts
export interface IAgentRepository {
save(agent: Agent): Promise<void>;
findById(id: AgentId): Promise<Agent | null>;
findByType(type: AgentType): Promise<Agent[]>;
findByStatus(status: AgentStatus): Promise<Agent[]>;
findAll(): Promise<Agent[]>;
delete(id: AgentId): Promise<void>;
}
Application Service (Sprint 5, Day 3-5)
// src-v3/agent-lifecycle/application/services/agent-lifecycle-service.ts
export class AgentLifecycleService {
constructor(
private agentRepository: IAgentRepository,
private agenticFlowClient: IAgenticFlowClient,
private eventBus: IEventBus,
private logger: ILogger
) {}
async spawnAgent(template: AgentTemplate): Promise<AgentId> {
this.logger.info('Spawning agent', { type: template.type });
// Create domain model
const agent = Agent.create(template);
// Use agentic-flow to spawn actual agent
await this.agenticFlowClient.spawnAgent({
id: agent.id.value,
type: template.type,
capabilities: template.capabilities
});
// Spawn in domain
agent.spawn();
// Save to repository
await this.agentRepository.save(agent);
// Publish domain events
agent.getDomainEvents().forEach(event => {
this.eventBus.emit(event);
});
this.logger.info('Agent spawned', { agentId: agent.id.value });
return agent.id;
}
async terminateAgent(agentId: AgentId): Promise<void> {
const agent = await this.agentRepository.findById(agentId);
if (!agent) {
throw new AgentNotFoundError(agentId);
}
// Terminate in agentic-flow
await this.agenticFlowClient.terminateAgent(agentId.value);
// Terminate in domain
agent.terminate();
// Save state
await this.agentRepository.save(agent);
// Publish events
agent.getDomainEvents().forEach(event => {
this.eventBus.emit(event);
});
}
async getAgentHealth(agentId: AgentId): Promise<AgentHealth> {
const agent = await this.agentRepository.findById(agentId);
if (!agent) {
throw new AgentNotFoundError(agentId);
}
return agent.reportHealth();
}
async scaleAgentPool(poolId: string, targetSize: number): Promise<void> {
// Implementation for pool scaling
}
}
Infrastructure Repository (Sprint 6, Day 1-2)
// src-v3/agent-lifecycle/infrastructure/repositories/agent-repository.ts
export class AgentRepository implements IAgentRepository {
constructor(
private db: Database,
private mapper: AgentMapper
) {}
async save(agent: Agent): Promise<void> {
const data = this.mapper.toPersistence(agent);
await this.db.run(`
INSERT OR REPLACE INTO agents (
id, type, status, capabilities, metrics, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?)
`, [
data.id,
data.type,
data.status,
JSON.stringify(data.capabilities),
JSON.stringify(data.metrics),
data.createdAt,
data.updatedAt
]);
}
async findById(id: AgentId): Promise<Agent | null> {
const row = await this.db.get(`
SELECT * FROM agents WHERE id = ?
`, [id.value]);
if (!row) return null;
return this.mapper.toDomain(row);
}
// ... other methods
}
// Mapper
export class AgentMapper {
toPersistence(agent: Agent): AgentPersistence {
// Map domain model to persistence model
}
toDomain(data: AgentPersistence): Agent {
// Reconstruct domain model from data
}
}
API Layer - CLI (Sprint 6, Day 2-3)
// src-v3/agent-lifecycle/api/cli/spawn-agent-command.ts
export class SpawnAgentCommand implements Command {
constructor(
private agentService: AgentLifecycleService,
private outputter: IOutputter
) {}
async execute(args: SpawnAgentArgs): Promise<void> {
const spinner = this.outputter.spinner('Spawning agent...');
try {
const template = this.createTemplate(args);
const agentId = await this.agentService.spawnAgent(template);
spinner.succeed(`Agent spawned: ${agentId.value}`);
this.outputter.table([
['Agent ID', agentId.value],
['Type', template.type],
['Status', 'idle'],
['Capabilities', template.capabilities.join(', ')]
]);
} catch (error) {
spinner.fail('Failed to spawn agent');
throw error;
}
}
private createTemplate(args: SpawnAgentArgs): AgentTemplate {
return {
type: args.type as AgentType,
capabilities: this.parseCapabilities(args.capabilities),
// ... more fields
};
}
}
API Layer - MCP (Sprint 6, Day 3-4)
// src-v3/agent-lifecycle/api/mcp/agent-tools.ts
export function createAgentTools(
agentService: AgentLifecycleService
): MCPTool[] {
return [
{
name: 'agent/spawn',
description: 'Spawn a new agent',
inputSchema: {
type: 'object',
properties: {
type: {
type: 'string',
enum: ['researcher', 'coder', 'analyst', /* ... */]
},
capabilities: {
type: 'array',
items: { type: 'string' }
}
},
required: ['type']
},
handler: async (input, context) => {
const template = this.parseTemplate(input);
const agentId = await agentService.spawnAgent(template);
return {
agentId: agentId.value,
status: 'spawned'
};
}
},
{
name: 'agent/terminate',
description: 'Terminate an agent',
inputSchema: {
type: 'object',
properties: {
agentId: { type: 'string' }
},
required: ['agentId']
},
handler: async (input) => {
await agentService.terminateAgent(AgentId.from(input.agentId));
return { status: 'terminated' };
}
},
{
name: 'agent/health',
description: 'Get agent health',
inputSchema: {
type: 'object',
properties: {
agentId: { type: 'string' }
},
required: ['agentId']
},
handler: async (input) => {
const health = await agentService.getAgentHealth(
AgentId.from(input.agentId)
);
return health.toJSON();
}
}
];
}
Tests (Sprint 6, Day 4-5)
// Domain tests
describe('Agent', () => {
it('should create agent from template');
it('should spawn successfully');
it('should transition to busy when task assigned');
it('should return to idle when task completed');
it('should calculate health score correctly');
it('should emit domain events');
});
// Service tests
describe('AgentLifecycleService', () => {
it('should spawn agent via agentic-flow');
it('should save agent to repository');
it('should publish domain events');
it('should handle spawn errors');
it('should terminate agent cleanly');
});
// Integration tests
describe('Agent Lifecycle Integration', () => {
it('should spawn, assign task, and terminate agent');
it('should track agent metrics correctly');
it('should handle concurrent spawns');
});
Deliverables (Sprints 5-6):
[Similar detailed breakdown for task execution domain]
[Similar detailed breakdown for memory domain]
[Similar detailed breakdown for coordination]
Architect (1)
Backend Developer (1-2)
DevOps/Infrastructure (0.5)
Documentation (2-3)
Testing (2-3)
Plugins (5-10)
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| agentic-flow breaking changes | Medium | High | Pin version, maintain adapter layer |
| Performance regression | Low | High | Continuous benchmarking |
| Migration complexity | High | Medium | Automated tools, gradual rollout |
| Plugin system bugs | Medium | Medium | Extensive testing, beta program |
| Data migration failures | Low | Critical | Backup/restore, rollback plan |
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Scope creep | High | Medium | Strict prioritization, defer to v3.1 |
| Resource shortage | Medium | High | Community involvement, phased delivery |
| Timeline slippage | Medium | Medium | Buffer time, cut scope if needed |
| Adoption resistance | Low | High | Clear benefits, migration support |
any typesCurrent v2:
Target v3:
Reduction Strategies:
Benchmark Suite:
// benchmarks/agent-spawn.bench.ts
import { bench, describe } from 'vitest';
describe('Agent Spawn Performance', () => {
bench('spawn single agent', async () => {
await agentService.spawnAgent(template);
});
bench('spawn 10 agents parallel', async () => {
await Promise.all(
Array(10).fill(null).map(() =>
agentService.spawnAgent(template)
)
);
});
bench('spawn 100 agents parallel', async () => {
// ...
});
});
// Run benchmarks
npm run benchmark
npm run benchmark:compare -- --base=v2 --compare=v3
Target Performance:
| Operation | v2 | v3 Target | Improvement |
|---|---|---|---|
| Agent spawn | 500ms | <100ms | 5x |
| Task assign | 50ms | <10ms | 5x |
| Memory query (indexed) | 25ms | <5ms | 5x |
| Swarm init (10 agents) | 5s | <1s | 5x |
Automated Migration Script:
#!/bin/bash
# scripts/migrate-v2-to-v3.sh
# Backup v2 data
echo "Backing up v2 data..."
cp claude-flow.db claude-flow-v2-backup.db
# Migrate configuration
echo "Migrating configuration..."
node scripts/migrate-config.js
# Migrate database schema
echo "Migrating database..."
node scripts/migrate-database.js
# Validate migration
echo "Validating migration..."
node scripts/validate-migration.js
echo "Migration complete! Review logs at migration.log"
Migration Guide Template:
# Migrating from v2 to v3
## Overview
This guide helps you migrate your claude-flow installation from v2 to v3.
## Prerequisites
- Node.js 20+
- Backup of v2 data
- v2.x running successfully
## Step 1: Backup
```bash
# Backup data
cp claude-flow.db backup/
cp -r .claude/ backup/
npm install [email protected]
npx claude-flow migrate config
npx claude-flow migrate data
npx claude-flow test-migration
npx claude-flow activate v3
If issues occur:
npx claude-flow rollback v2
---
**Document Owner:** Architecture Team
**Last Updated:** 2026-01-03
**Next Review:** End of Phase 1 (Week 4)
---
**End of Migration Roadmap**