Files
Codewalkers/.planning/phases/12-phase-task-decomposition/12-07-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

5.7 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
12-phase-task-decomposition 07 execute 4
12-01
12-02
12-03
src/agent/mock-manager.test.ts
src/db/repositories/drizzle/drizzle-plan-repository.test.ts
true
Add unit tests for decompose mode schemas, MockAgentManager decompose scenarios, and PlanRepository extensions.

Purpose: Ensure mode-specific functionality works correctly before E2E testing.

Output: Test coverage for decompose mode, PlanRepository methods.

<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 patterns from Phase 11

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

Source test files

@src/agent/mock-manager.test.ts @src/db/repositories/drizzle/drizzle-task-repository.test.ts

Task 1: Add MockAgentManager decompose mode tests src/agent/mock-manager.test.ts Add tests for decompose mode scenarios following breakdown mode test patterns:
describe('decompose mode', () => {
  it('should spawn agent in decompose mode', async () => {
    const agent = await manager.spawn({
      name: 'decomposer',
      taskId: 'plan-1',
      prompt: 'Decompose this plan',
      mode: 'decompose',
    });
    expect(agent.mode).toBe('decompose');
  });

  it('should complete with tasks on decompose_complete', async () => {
    manager.setScenario('decomposer', {
      status: 'decompose_complete',
      tasks: [
        { number: 1, name: 'Task 1', description: 'First task', type: 'auto', dependencies: [] },
        { number: 2, name: 'Task 2', description: 'Second task', type: 'auto', dependencies: [1] },
      ],
    });

    await manager.spawn({ name: 'decomposer', taskId: 'plan-1', prompt: 'test', mode: 'decompose' });
    await vi.advanceTimersByTimeAsync(100);

    // Verify agent:stopped event with decompose_complete reason
    expect(emittedEvents).toContainEqual(
      expect.objectContaining({
        type: 'agent:stopped',
        payload: expect.objectContaining({ reason: 'decompose_complete' }),
      })
    );
  });

  it('should pause on questions in decompose mode', async () => {
    manager.setScenario('decomposer', {
      status: 'questions',
      questions: [{ id: 'q1', question: 'How many tasks?' }],
    });

    await manager.spawn({ name: 'decomposer', taskId: 'plan-1', prompt: 'test', mode: 'decompose' });
    await vi.advanceTimersByTimeAsync(100);

    // Verify agent pauses for questions
    expect(emittedEvents).toContainEqual(
      expect.objectContaining({
        type: 'agent:stopped',
        payload: expect.objectContaining({ reason: 'questions' }),
      })
    );
  });
});
npm test passes with new decompose tests MockAgentManager decompose mode tests cover spawn, complete, and questions scenarios Task 2: Add PlanRepository extension tests src/db/repositories/drizzle/drizzle-plan-repository.test.ts Add tests for new PlanRepository methods:
describe('findByPhaseId', () => {
  it('should return plans for a phase ordered by number', async () => {
    // Create phase
    const phase = await phaseRepo.create({ initiativeId: initiative.id, number: 1, name: 'Phase 1' });

    // Create plans out of order
    await planRepo.create({ phaseId: phase.id, number: 3, name: 'Plan 3' });
    await planRepo.create({ phaseId: phase.id, number: 1, name: 'Plan 1' });
    await planRepo.create({ phaseId: phase.id, number: 2, name: 'Plan 2' });

    const plans = await planRepo.findByPhaseId(phase.id);

    expect(plans).toHaveLength(3);
    expect(plans[0].number).toBe(1);
    expect(plans[1].number).toBe(2);
    expect(plans[2].number).toBe(3);
  });

  it('should return empty array for phase with no plans', async () => {
    const phase = await phaseRepo.create({ initiativeId: initiative.id, number: 1, name: 'Phase 1' });
    const plans = await planRepo.findByPhaseId(phase.id);
    expect(plans).toEqual([]);
  });
});

describe('getNextNumber', () => {
  it('should return 1 for phase with no plans', async () => {
    const phase = await phaseRepo.create({ initiativeId: initiative.id, number: 1, name: 'Phase 1' });
    const nextNumber = await planRepo.getNextNumber(phase.id);
    expect(nextNumber).toBe(1);
  });

  it('should return max + 1 for phase with plans', async () => {
    const phase = await phaseRepo.create({ initiativeId: initiative.id, number: 1, name: 'Phase 1' });
    await planRepo.create({ phaseId: phase.id, number: 1, name: 'Plan 1' });
    await planRepo.create({ phaseId: phase.id, number: 5, name: 'Plan 5' });

    const nextNumber = await planRepo.getNextNumber(phase.id);
    expect(nextNumber).toBe(6);
  });
});

Create test file if it doesn't exist, following pattern from drizzle-task-repository.test.ts. npm test passes with PlanRepository tests PlanRepository findByPhaseId and getNextNumber tested

Before declaring plan complete: - [ ] npm run build succeeds - [ ] npm test passes all tests including new ones - [ ] Decompose mode scenarios tested (spawn, complete, questions) - [ ] PlanRepository methods tested (findByPhaseId, getNextNumber)

<success_criteria>

  • All tasks completed
  • All verification checks pass
  • No errors or warnings introduced
  • Unit test coverage for Phase 12 features </success_criteria>
After completion, create `.planning/phases/12-phase-task-decomposition/12-07-SUMMARY.md`