Files
claude-task-master/.taskmaster/docs/MIGRATION-ROADMAP.md
2025-09-01 21:27:17 +02:00

5.7 KiB

Task Master Migration Roadmap

Overview

Gradual migration from scripts-based architecture to a clean monorepo with separated concerns.

Architecture Vision

┌─────────────────────────────────────────────────┐
│                  User Interfaces                 │
├──────────┬──────────┬──────────┬────────────────┤
│  @tm/cli │ @tm/mcp  │ @tm/ext  │  @tm/web      │
│  (CLI)   │  (MCP)   │  (VSCode)│  (Future)     │
└──────────┴──────────┴──────────┴────────────────┘
                    │
                    ▼
        ┌──────────────────────┐
        │      @tm/core        │
        │  (Business Logic)    │
        └──────────────────────┘

Migration Phases

Phase 1: Core Extraction (In Progress)

Goal: Move all business logic to @tm/core

  • Create @tm/core package structure
  • Move types and interfaces
  • Implement TaskMasterCore facade
  • Move storage adapters
  • Move task services
  • Move AI providers
  • Move parser logic
  • Complete test coverage

Phase 2: CLI Package Creation 🚧 (Started)

Goal: Create @tm/cli as a thin presentation layer

  • Create @tm/cli package structure
  • Implement Command interface pattern
  • Create CommandRegistry
  • Build legacy bridge/adapter
  • Migrate list-tasks command
  • Migrate remaining commands one by one
  • Remove UI logic from core

Phase 3: Transitional Integration

Goal: Use new packages in existing scripts without breaking changes

// scripts/modules/commands.js gradually adopts new commands
import { ListTasksCommand } from '@tm/cli';
const listCommand = new ListTasksCommand();

// Old interface remains the same
programInstance
  .command('list')
  .action(async (options) => {
    // Use new command internally
    const result = await listCommand.execute(convertOptions(options));
  });

Phase 4: MCP Package

Goal: Separate MCP server as its own package

  • Create @tm/mcp package
  • Move MCP server code
  • Use @tm/core for all logic
  • MCP becomes a thin RPC layer

Phase 5: Complete Migration

Goal: Remove old scripts, pure monorepo

  • All commands migrated to @tm/cli
  • Remove scripts/modules/task-manager/*
  • Remove scripts/modules/commands.js
  • Update bin/task-master.js to use @tm/cli
  • Clean up dependencies

Current Transitional Strategy

1. Adapter Pattern (commands-adapter.js)

// Checks if new CLI is available and uses it
// Falls back to legacy implementation if not
export async function listTasksAdapter(...args) {
  if (cliAvailable) {
    return useNewImplementation(...args);
  }
  return useLegacyImplementation(...args);
}

2. Command Bridge Pattern

// Allows new commands to work in old code
const bridge = new CommandBridge(new ListTasksCommand());
const data = await bridge.run(legacyOptions); // Legacy style
const result = await bridge.execute(newOptions); // New style

3. Gradual File Migration

Instead of big-bang refactoring:

  1. Create new implementation in @tm/cli
  2. Add adapter in commands-adapter.js
  3. Update commands.js to use adapter
  4. Test both paths work
  5. Eventually remove adapter when all migrated

Benefits of This Approach

  1. No Breaking Changes: Existing CLI continues to work
  2. Incremental PRs: Each command can be migrated separately
  3. Parallel Development: New features can use new architecture
  4. Easy Rollback: Can disable new implementation if issues
  5. Clear Separation: Business logic (core) vs presentation (cli/mcp/etc)

Example PR Sequence

PR 1: Core Package Setup

  • Create @tm/core
  • Move types and interfaces
  • Basic TaskMasterCore implementation

PR 2: CLI Package Foundation

  • Create @tm/cli
  • Command interface and registry
  • Legacy bridge utilities

PR 3: First Command Migration

  • Migrate list-tasks to new system
  • Add adapter in scripts
  • Test both implementations

PR 4-N: Migrate Commands One by One

  • Each PR migrates 1-2 related commands
  • Small, reviewable changes
  • Continuous delivery

Final PR: Cleanup

  • Remove legacy implementations
  • Remove adapters
  • Update documentation

Testing Strategy

Dual Testing During Migration

describe('List Tasks', () => {
  it('works with legacy implementation', async () => {
    // Force legacy
    const result = await legacyListTasks(...);
    expect(result).toBeDefined();
  });

  it('works with new implementation', async () => {
    // Force new
    const command = new ListTasksCommand();
    const result = await command.execute(...);
    expect(result.success).toBe(true);
  });

  it('adapter chooses correctly', async () => {
    // Let adapter decide
    const result = await listTasksAdapter(...);
    expect(result).toBeDefined();
  });
});

Success Metrics

  • All commands migrated without breaking changes
  • Test coverage maintained or improved
  • Performance maintained or improved
  • Cleaner, more maintainable codebase
  • Easy to add new interfaces (web, desktop, etc.)

Notes for Contributors

  1. Keep PRs Small: Migrate one command at a time
  2. Test Both Paths: Ensure legacy and new both work
  3. Document Changes: Update this roadmap as you go
  4. Communicate: Discuss in PRs if architecture needs adjustment

This is a living document - update as the migration progresses!