Files
Codewalkers/.planning/phases/12-phase-task-decomposition/12-08-PLAN.md
Lukas May 41f868294b docs(12): create phase plan
Phase 12: Phase-Task Decomposition
- 8 plans in 4 waves
- 4 parallel, 4 sequential
- Ready for execution
2026-01-31 21:03:07 +01:00

7.7 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
12-phase-task-decomposition 08 execute 4
12-05
12-06
12-07
src/test/harness.ts
src/test/e2e/decompose-workflow.test.ts
true
Add TestHarness support for decompose mode and E2E tests for the full decomposition workflow.

Purpose: Validate the complete workflow from plan creation through task decomposition and persistence.

Output: E2E tests proving decompose mode works end-to-end.

<execution_context> @/.claude/get-shit-done/workflows/execute-plan.md @/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md

Test infrastructure from Phase 11

@.planning/phases/11-architect-agent/11-08-SUMMARY.md

TestHarness

@src/test/harness.ts @src/test/e2e/architect-workflow.test.ts

Task 1: Add TestHarness decompose mode helpers src/test/harness.ts Add decompose scenario helpers to TestHarness following architect mode pattern:
/**
 * Set decompose complete scenario for an agent.
 * Agent will complete with task array when spawned.
 */
setArchitectDecomposeComplete(agentName: string, tasks: Array<{
  number: number;
  name: string;
  description: string;
  type?: string;
  dependencies?: number[];
}>) {
  this.mockAgentManager.setScenario(agentName, {
    status: 'decompose_complete',
    tasks: tasks.map(t => ({
      ...t,
      type: t.type || 'auto',
      dependencies: t.dependencies || [],
    })),
  });
}

/**
 * Set decompose questions scenario for an agent.
 * Agent will pause with questions when spawned.
 */
setArchitectDecomposeQuestions(agentName: string, questions: Array<{
  id: string;
  question: string;
  options?: Array<{ label: string }>;
}>) {
  this.mockAgentManager.setScenario(agentName, {
    status: 'questions',
    questions,
  });
}

Also add convenience methods for creating plans in tests:

async createPlan(phaseId: string, name: string, description?: string) {
  return this.caller.createPlan({ phaseId, name, description });
}

async getTasksForPlan(planId: string) {
  return this.caller.listTasks({ planId });
}
npm run build passes TestHarness has decompose scenario helpers and plan convenience methods Task 2: Add decompose mode E2E tests src/test/e2e/decompose-workflow.test.ts Create E2E test file for decompose workflow:
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { TestHarness } from '../harness.js';

describe('Decompose Workflow', () => {
  let harness: TestHarness;

  beforeEach(async () => {
    vi.useFakeTimers();
    harness = await TestHarness.create();
  });

  afterEach(async () => {
    await harness.cleanup();
    vi.useRealTimers();
  });

  describe('spawn decompose agent', () => {
    it('should spawn agent in decompose mode and complete with tasks', async () => {
      // Setup: Create initiative -> phase -> plan
      const initiative = await harness.createInitiative('Test Project');
      const phases = await harness.createPhasesFromBreakdown(initiative.id, [
        { number: 1, name: 'Phase 1', description: 'First phase', dependencies: [] },
      ]);
      const plan = await harness.createPlan(phases[0].id, 'Auth Plan', 'Implement auth');

      // Set decompose scenario
      harness.setArchitectDecomposeComplete('decomposer', [
        { number: 1, name: 'Create schema', description: 'User table', type: 'auto', dependencies: [] },
        { number: 2, name: 'Create endpoint', description: 'Login API', type: 'auto', dependencies: [1] },
      ]);

      // Spawn decompose agent
      await harness.caller.spawnArchitectDecompose({
        name: 'decomposer',
        planId: plan.id,
      });

      // Advance timers for async completion
      await harness.advanceTimers(100);

      // Verify agent completed
      const events = harness.getEmittedEvents();
      expect(events).toContainEqual(
        expect.objectContaining({
          type: 'agent:stopped',
          payload: expect.objectContaining({
            name: 'decomposer',
            reason: 'decompose_complete',
          }),
        })
      );
    });

    it('should pause on questions and resume', async () => {
      const initiative = await harness.createInitiative('Test Project');
      const phases = await harness.createPhasesFromBreakdown(initiative.id, [
        { number: 1, name: 'Phase 1', description: 'First phase', dependencies: [] },
      ]);
      const plan = await harness.createPlan(phases[0].id, 'Complex Plan');

      // Set questions scenario
      harness.setArchitectDecomposeQuestions('decomposer', [
        { id: 'q1', question: 'How granular should tasks be?' },
      ]);

      await harness.caller.spawnArchitectDecompose({
        name: 'decomposer',
        planId: plan.id,
      });

      await harness.advanceTimers(100);

      // Verify paused on questions
      const events = harness.getEmittedEvents();
      expect(events).toContainEqual(
        expect.objectContaining({
          type: 'agent:stopped',
          payload: expect.objectContaining({
            reason: 'questions',
          }),
        })
      );

      // Set completion scenario for resume
      harness.setArchitectDecomposeComplete('decomposer', [
        { number: 1, name: 'Task 1', description: 'Single task', type: 'auto' },
      ]);

      // Resume with answer
      await harness.mockAgentManager.resume('decomposer', { q1: 'Very granular' });
      await harness.advanceTimers(100);

      // Verify completed after resume
      const finalEvents = harness.getEmittedEvents();
      expect(finalEvents.filter(e => e.type === 'agent:stopped')).toHaveLength(2);
    });
  });

  describe('task persistence', () => {
    it('should create tasks from decomposition output', async () => {
      const initiative = await harness.createInitiative('Test Project');
      const phases = await harness.createPhasesFromBreakdown(initiative.id, [
        { number: 1, name: 'Phase 1', description: 'First phase', dependencies: [] },
      ]);
      const plan = await harness.createPlan(phases[0].id, 'Auth Plan');

      // Create tasks from decomposition
      await harness.caller.createTasksFromDecomposition({
        planId: plan.id,
        tasks: [
          { number: 1, name: 'Schema', description: 'Create tables', type: 'auto', dependencies: [] },
          { number: 2, name: 'API', description: 'Create endpoints', type: 'auto', dependencies: [1] },
          { number: 3, name: 'Verify', description: 'Test flow', type: 'checkpoint:human-verify', dependencies: [2] },
        ],
      });

      // Verify tasks created
      const tasks = await harness.getTasksForPlan(plan.id);
      expect(tasks).toHaveLength(3);
      expect(tasks[0].name).toBe('Schema');
      expect(tasks[1].name).toBe('API');
      expect(tasks[2].type).toBe('checkpoint:human-verify');
    });
  });
});
npm test passes with new E2E tests E2E tests cover decompose spawn, Q&A flow, and task persistence Before declaring plan complete: - [ ] npm run build succeeds - [ ] npm test passes all tests including new E2E tests - [ ] Decompose mode completion tested - [ ] Decompose Q&A flow tested - [ ] Task persistence from decomposition tested

<success_criteria>

  • All tasks completed
  • All verification checks pass
  • No errors or warnings introduced
  • Full E2E coverage for decompose workflow </success_criteria>
After completion, create `.planning/phases/12-phase-task-decomposition/12-08-SUMMARY.md`