Phase 12: Phase-Task Decomposition - 8 plans in 4 waves - 4 parallel, 4 sequential - Ready for execution
5.7 KiB
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 |
|
|
true |
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>
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' }),
})
);
});
});
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>