docs(12): create phase plan

Phase 12: Phase-Task Decomposition
- 8 plans in 4 waves
- 4 parallel, 4 sequential
- Ready for execution
This commit is contained in:
Lukas May
2026-01-31 21:03:07 +01:00
parent ec9e6043a2
commit 41f868294b
9 changed files with 1318 additions and 3 deletions

View File

@@ -177,10 +177,17 @@ Plans:
**Goal**: Agents break phases into individual tasks with ability to ask questions during breakdown
**Depends on**: Phase 11
**Research**: Unlikely (internal coordination patterns)
**Plans**: TBD
**Plans**: 8
Plans:
- [ ] 12-01: TBD
- [ ] 12-01: Decompose Mode Schema
- [ ] 12-02: PlanRepository Extensions
- [ ] 12-03: ClaudeAgentManager Decompose Support
- [ ] 12-04: Plan & Task tRPC Procedures
- [ ] 12-05: Decompose Prompts & Spawn Procedure
- [ ] 12-06: CLI Commands
- [ ] 12-07: Unit Tests
- [ ] 12-08: E2E Tests
#### Phase 13: Real Claude E2E Tests
**Goal**: Verify multi-question and architect flows with actual Claude CLI; replace with mocks after verification
@@ -212,7 +219,7 @@ Phases execute in numeric order: 1 → 1.1 → 2 → 3 → 4 → 5 → 6 → 7
| 9. Extended Scenarios | v1.1 | 2/2 | Complete | 2026-01-31 |
| 10. Multi-Question Schema | v1.2 | 4/4 | Complete | 2026-01-31 |
| 11. Architect Agent | v1.2 | 8/8 | Complete | 2026-01-31 |
| 12. Phase-Task Decomposition | v1.2 | 0/? | Not started | - |
| 12. Phase-Task Decomposition | v1.2 | 0/8 | Planned | - |
| 13. Real Claude E2E Tests | v1.2 | 0/? | Not started | - |
---

View File

@@ -0,0 +1,111 @@
---
phase: 12-phase-task-decomposition
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/agent/types.ts
- src/agent/schema.ts
- src/db/schema.ts
- src/db/repositories/drizzle/test-helpers.ts
autonomous: true
---
<objective>
Add decompose agent mode for breaking phases into individual tasks.
Purpose: Enable Architect agents to take a phase and produce a list of tasks with dependencies, types, and descriptions. This is the final piece of the initiative→phase→plan→task breakdown chain.
Output: AgentMode type extended with 'decompose', decompose output schema with Zod and JSON Schema versions, TaskBreakdown type.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Prior phase context (mode schemas from Phase 11)
@.planning/phases/11-architect-agent/11-01-SUMMARY.md
# Source files to modify
@src/agent/types.ts
@src/agent/schema.ts
@src/db/schema.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Extend AgentMode with 'decompose'</name>
<files>src/agent/types.ts, src/db/schema.ts, src/db/repositories/drizzle/test-helpers.ts</files>
<action>
1. In src/agent/types.ts:
- Update AgentMode type to include 'decompose': `'execute' | 'discuss' | 'breakdown' | 'decompose'`
2. In src/db/schema.ts:
- Update agents table mode column enum to include 'decompose'
3. In src/db/repositories/drizzle/test-helpers.ts:
- Update CREATE_TABLES_SQL agents table to include 'decompose' in mode column enum
</action>
<verify>npm run build passes, npm test passes</verify>
<done>AgentMode type includes 'decompose', database schema updated</done>
</task>
<task type="auto">
<name>Task 2: Create decompose output schema</name>
<files>src/agent/schema.ts</files>
<action>
1. Create TaskBreakdown type (similar to PhaseBreakdown):
```typescript
const taskBreakdownSchema = z.object({
number: z.number().int().positive(),
name: z.string().min(1),
description: z.string(),
type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).default('auto'),
dependencies: z.array(z.number().int()).optional().default([]),
});
export type TaskBreakdown = z.infer<typeof taskBreakdownSchema>;
```
2. Create decomposeOutputSchema discriminated union:
- 'questions' status with questions array (for clarification)
- 'decompose_complete' status with tasks array
- 'unrecoverable_error' status with error string
3. Create decomposeOutputJsonSchema (JSON Schema version for Claude CLI --json-schema)
4. Export all types and schemas from the file
</action>
<verify>npm run build passes, types exported correctly</verify>
<done>decomposeOutputSchema and TaskBreakdown type exported, JSON schema version available</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] npm test passes all tests
- [ ] AgentMode type includes 'decompose'
- [ ] decomposeOutputSchema exported from src/agent/schema.ts
- [ ] decomposeOutputJsonSchema exported from src/agent/schema.ts
- [ ] TaskBreakdown type exported
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Decompose mode schema ready for manager implementation
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,112 @@
---
phase: 12-phase-task-decomposition
plan: 02
type: execute
wave: 1
depends_on: []
files_modified:
- src/db/repositories/plan-repository.ts
- src/db/repositories/drizzle/drizzle-plan-repository.ts
- src/db/repositories/index.ts
autonomous: true
---
<objective>
Extend PlanRepository with methods needed for task decomposition workflow.
Purpose: Enable creating plans from architect output and querying plans by phase. The decompose agent needs to know what plans exist in a phase to break them into tasks.
Output: PlanRepository with findByPhaseId, getNextNumber, bulk creation methods.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Pattern reference from Phase 11 (repository extensions)
@.planning/phases/11-architect-agent/11-02-SUMMARY.md
# Source files to modify
@src/db/repositories/plan-repository.ts
@src/db/repositories/drizzle/drizzle-plan-repository.ts
@src/db/repositories/phase-repository.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Extend PlanRepository port interface</name>
<files>src/db/repositories/plan-repository.ts</files>
<action>
Add the following methods to PlanRepository interface (following pattern from PhaseRepository):
1. `findByPhaseId(phaseId: string): Promise<Plan[]>` - Get all plans for a phase, ordered by number
2. `getNextNumber(phaseId: string): Promise<number>` - Get next available plan number (MAX+1 or 1 if none)
</action>
<verify>npm run build passes (no implementation yet)</verify>
<done>PlanRepository interface extended with new methods</done>
</task>
<task type="auto">
<name>Task 2: Implement methods in DrizzlePlanRepository</name>
<files>src/db/repositories/drizzle/drizzle-plan-repository.ts</files>
<action>
Implement the new methods in DrizzlePlanRepository adapter:
1. `findByPhaseId(phaseId)`:
- Query plans table where phase_id = phaseId
- Order by number ascending
- Return array (empty if none)
2. `getNextNumber(phaseId)`:
- Query MAX(number) where phase_id = phaseId
- Return max + 1, or 1 if no plans exist
Follow the pattern from DrizzlePhaseRepository.getNextNumber.
</action>
<verify>npm run build passes, npm test passes</verify>
<done>DrizzlePlanRepository implements findByPhaseId and getNextNumber</done>
</task>
<task type="auto">
<name>Task 3: Export types from repositories index</name>
<files>src/db/repositories/index.ts</files>
<action>
Verify PlanRepository and its types are properly exported. If not already exported:
- Export PlanRepository interface
- Export CreatePlanData type
- Export UpdatePlanData type
Check existing exports and add if missing.
</action>
<verify>npm run build passes, types importable from src/db/repositories</verify>
<done>All PlanRepository types properly exported</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] npm test passes all tests
- [ ] PlanRepository.findByPhaseId exists and works
- [ ] PlanRepository.getNextNumber exists and works
- [ ] Types exported from index
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- PlanRepository ready for tRPC procedures
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-02-SUMMARY.md`
</output>

View File

@@ -0,0 +1,126 @@
---
phase: 12-phase-task-decomposition
plan: 03
type: execute
wave: 2
depends_on: ["12-01"]
files_modified:
- src/agent/manager.ts
- src/agent/mock-manager.ts
autonomous: true
---
<objective>
Update ClaudeAgentManager and MockAgentManager to support decompose mode.
Purpose: Enable spawning agents in decompose mode with the correct JSON schema. Agents in this mode break phases into tasks.
Output: Mode-aware agent spawning handles 'decompose' mode with decomposeOutputJsonSchema.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Depends on Plan 01 for decompose schema
@.planning/phases/12-phase-task-decomposition/12-01-SUMMARY.md
# Pattern reference from Phase 11 (mode handling)
@.planning/phases/11-architect-agent/11-03-SUMMARY.md
# Source files to modify
@src/agent/manager.ts
@src/agent/schema.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Update ClaudeAgentManager for decompose mode</name>
<files>src/agent/manager.ts</files>
<action>
1. Import decomposeOutputSchema and decomposeOutputJsonSchema from schema.ts
2. Update getJsonSchemaForMode() to handle 'decompose':
```typescript
case 'decompose':
return decomposeOutputJsonSchema;
```
3. Add handleDecomposeOutput() method following pattern of handleBreakdownOutput():
- Parse output with decomposeOutputSchema
- Handle 'decompose_complete' status → emit agent:stopped with reason: 'decompose_complete'
- Handle 'questions' status → emit agent:stopped with reason: 'questions'
- Handle 'unrecoverable_error' → emit agent:stopped with reason: 'error'
4. Update handleAgentCompletion() switch to call handleDecomposeOutput for mode: 'decompose'
</action>
<verify>npm run build passes</verify>
<done>ClaudeAgentManager handles decompose mode with correct schema and completion handling</done>
</task>
<task type="auto">
<name>Task 2: Update MockAgentManager for decompose mode</name>
<files>src/agent/mock-manager.ts</files>
<action>
1. Add 'decompose_complete' to MockAgentScenario status type (alongside 'context_complete' and 'breakdown_complete')
2. Add tasks field to scenario result type for decompose_complete:
```typescript
tasks?: Array<{ number: number; name: string; description: string; type: string; dependencies: number[] }>;
```
3. Update handleAgentCompletion() to handle decompose scenarios:
- If status is 'decompose_complete', emit agent:stopped with reason: 'decompose_complete'
- Include tasks in the output event if present
4. Update resume() to handle decompose mode similarly to breakdown mode
</action>
<verify>npm run build passes, npm test passes</verify>
<done>MockAgentManager handles decompose mode scenarios for E2E testing</done>
</task>
<task type="auto">
<name>Task 3: Extend AgentStoppedEvent reason type</name>
<files>src/events/types.ts</files>
<action>
Update AgentStoppedEvent reason type to include 'decompose_complete':
```typescript
reason: 'completed' | 'stopped' | 'error' | 'questions' | 'context_complete' | 'breakdown_complete' | 'decompose_complete';
```
This follows the pattern established in Phase 11 for context_complete and breakdown_complete.
</action>
<verify>npm run build passes</verify>
<done>AgentStoppedEvent reason includes 'decompose_complete'</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] npm test passes all tests
- [ ] ClaudeAgentManager.getJsonSchemaForMode returns decomposeOutputJsonSchema for 'decompose'
- [ ] ClaudeAgentManager.handleDecomposeOutput exists and handles all statuses
- [ ] MockAgentManager handles decompose_complete scenarios
- [ ] AgentStoppedEvent.reason includes 'decompose_complete'
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Decompose mode fully supported in both managers
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-03-SUMMARY.md`
</output>

View File

@@ -0,0 +1,140 @@
---
phase: 12-phase-task-decomposition
plan: 04
type: execute
wave: 2
depends_on: ["12-02"]
files_modified:
- src/trpc/router.ts
- src/trpc/context.ts
autonomous: true
---
<objective>
Add Plan and Task tRPC procedures for decomposition workflow.
Purpose: Enable CLI to create plans, create tasks from decomposition output, and query plans by phase. Completes the tRPC layer for the full hierarchy.
Output: Plan CRUD procedures, bulk task creation procedure (createTasksFromDecomposition).
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Depends on Plan 02 for PlanRepository methods
@.planning/phases/12-phase-task-decomposition/12-02-SUMMARY.md
# Pattern reference from Phase 11 (tRPC procedures)
@.planning/phases/11-architect-agent/11-04-SUMMARY.md
# Source files
@src/trpc/router.ts
@src/trpc/context.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Add PlanRepository to tRPC context</name>
<files>src/trpc/context.ts</files>
<action>
Add PlanRepository to tRPC context following existing pattern:
1. Import PlanRepository type from repositories
2. Add planRepository?: PlanRepository to Context type
3. Update createContext to include planRepository (optional, for backwards compatibility)
</action>
<verify>npm run build passes</verify>
<done>PlanRepository available in tRPC context</done>
</task>
<task type="auto">
<name>Task 2: Add Plan tRPC procedures</name>
<files>src/trpc/router.ts</files>
<action>
Add Plan CRUD procedures following Initiative/Phase pattern:
1. `createPlan` - Create a plan in a phase
- Input: { phaseId, number?, name, description? }
- If number not provided, use getNextNumber
- Return created plan
2. `listPlans` - List plans for a phase
- Input: { phaseId }
- Return plans ordered by number
3. `getPlan` - Get a plan by ID
- Input: { id }
- Return plan or throw if not found
4. `updatePlan` - Update a plan
- Input: { id, name?, description?, status? }
- Return updated plan
Add requirePlanRepository helper following requireInitiativeRepository pattern.
</action>
<verify>npm run build passes</verify>
<done>Plan CRUD procedures available via tRPC</done>
</task>
<task type="auto">
<name>Task 3: Add createTasksFromDecomposition procedure</name>
<files>src/trpc/router.ts</files>
<action>
Add bulk task creation procedure for decompose output:
```typescript
createTasksFromDecomposition: publicProcedure
.input(z.object({
planId: z.string(),
tasks: z.array(z.object({
number: z.number().int().positive(),
name: z.string(),
description: z.string(),
type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).default('auto'),
dependencies: z.array(z.number().int()).optional(),
})),
}))
.mutation(async ({ ctx, input }) => {
const taskRepo = requireTaskRepository(ctx);
// Verify plan exists
// Create tasks in order, map number to task ID for dependencies
// Create task_dependencies after all tasks created
// Return created tasks
});
```
Handle dependency mapping: task numbers in input become task IDs via lookup map.
</action>
<verify>npm run build passes, npm test passes</verify>
<done>createTasksFromDecomposition procedure creates tasks with dependencies from agent output</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] npm test passes all tests
- [ ] createPlan, listPlans, getPlan, updatePlan procedures exist
- [ ] createTasksFromDecomposition handles bulk task creation with dependencies
- [ ] PlanRepository in context
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Full Plan and Task tRPC layer ready for CLI
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-04-SUMMARY.md`
</output>

View File

@@ -0,0 +1,217 @@
---
phase: 12-phase-task-decomposition
plan: 05
type: execute
wave: 3
depends_on: ["12-03", "12-04"]
files_modified:
- src/agent/prompts.ts
- src/agent/index.ts
- src/trpc/router.ts
autonomous: true
---
<objective>
Add decompose prompts and spawnArchitectDecompose tRPC procedure.
Purpose: Enable spawning architect agents in decompose mode with comprehensive prompts that explain task breakdown rules, output format, and expected behavior.
Output: buildDecomposePrompt function, spawnArchitectDecompose procedure.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Depends on Plans 03, 04
@.planning/phases/12-phase-task-decomposition/12-03-SUMMARY.md
@.planning/phases/12-phase-task-decomposition/12-04-SUMMARY.md
# Pattern reference from Phase 11 (prompts and spawn procedures)
@.planning/phases/11-architect-agent/11-05-SUMMARY.md
# Source files
@src/agent/prompts.ts
@src/trpc/router.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Create buildDecomposePrompt function</name>
<files>src/agent/prompts.ts</files>
<action>
Add buildDecomposePrompt following the pattern of buildBreakdownPrompt:
```typescript
import type { Phase, Plan } from '../db/schema.js';
export function buildDecomposePrompt(plan: Plan, phase: Phase, context?: string): string {
return `You are an Architect agent in the Codewalk multi-agent system operating in DECOMPOSE mode.
## Your Role
Break a plan into executable tasks. You do NOT write code - you decompose work into atomic units.
## Plan
Name: ${plan.name}
Phase: ${phase.name}
${plan.description ? `Description: ${plan.description}` : ''}
${context ? `\nAdditional Context: ${context}` : ''}
## Your Task
Decompose this plan into tasks that worker agents can execute.
## Task Design Rules
**Each task must be:**
- A single atomic unit of work
- Independently executable (or with clear dependencies)
- Verifiable (has a clear done condition)
**Task Types:**
- 'auto': Agent executes autonomously (default, most common)
- 'checkpoint:human-verify': Needs human to verify visual/functional output
- 'checkpoint:decision': Needs human to make a choice
- 'checkpoint:human-action': Needs unavoidable manual action (rare)
**Dependencies:**
- Identify what each task needs from prior tasks
- Use task numbers (1, 2, 3) for dependencies
- Minimize dependencies where possible
**Sizing:**
- Tasks should be 15-60 minutes of work
- Not too big (hard to debug), not too small (overhead)
## Output Format
If you need clarification, output:
{
"status": "questions",
"questions": [
{ "id": "q1", "question": "Your question here" }
]
}
When decomposition is complete, output:
{
"status": "decompose_complete",
"tasks": [
{
"number": 1,
"name": "Create user schema",
"description": "Add User table to database with email, passwordHash, createdAt",
"type": "auto",
"dependencies": []
},
{
"number": 2,
"name": "Create login endpoint",
"description": "POST /api/auth/login - validate credentials, return JWT",
"type": "auto",
"dependencies": [1]
}
]
}
## Rules
- Tasks must be in dependency order
- Each task should have clear, specific description
- Default to 'auto' type unless human interaction is genuinely required
- Keep tasks focused on a single concern`;
}
```
</action>
<verify>npm run build passes</verify>
<done>buildDecomposePrompt exported from src/agent/prompts.ts</done>
</task>
<task type="auto">
<name>Task 2: Export buildDecomposePrompt from agent index</name>
<files>src/agent/index.ts</files>
<action>
Add buildDecomposePrompt to the exports from src/agent/index.ts:
Check existing exports and add:
```typescript
export { buildDecomposePrompt } from './prompts.js';
```
Or update existing prompts export to include buildDecomposePrompt.
</action>
<verify>npm run build passes, buildDecomposePrompt importable from src/agent</verify>
<done>buildDecomposePrompt exported from agent module</done>
</task>
<task type="auto">
<name>Task 3: Add spawnArchitectDecompose tRPC procedure</name>
<files>src/trpc/router.ts</files>
<action>
Add spawnArchitectDecompose procedure following pattern of spawnArchitectBreakdown:
```typescript
spawnArchitectDecompose: publicProcedure
.input(z.object({
name: z.string().min(1),
planId: z.string().min(1),
context: z.string().optional(),
}))
.mutation(async ({ ctx, input }) => {
const agentManager = requireAgentManager(ctx);
const planRepo = requirePlanRepository(ctx);
const phaseRepo = requirePhaseRepository(ctx);
// 1. Get plan and its phase
const plan = await planRepo.findById(input.planId);
if (!plan) {
throw new TRPCError({ code: 'NOT_FOUND', message: `Plan ${input.planId} not found` });
}
const phase = await phaseRepo.findById(plan.phaseId);
if (!phase) {
throw new TRPCError({ code: 'NOT_FOUND', message: `Phase ${plan.phaseId} not found` });
}
// 2. Build decompose prompt
const prompt = buildDecomposePrompt(plan, phase, input.context);
// 3. Spawn agent in decompose mode
return agentManager.spawn({
name: input.name,
taskId: input.planId, // Associate with plan
prompt,
mode: 'decompose',
});
});
```
</action>
<verify>npm run build passes, npm test passes</verify>
<done>spawnArchitectDecompose procedure spawns agent in decompose mode with comprehensive prompt</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] npm test passes all tests
- [ ] buildDecomposePrompt exported and works
- [ ] spawnArchitectDecompose procedure exists
- [ ] Procedure validates plan exists before spawning
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Decompose workflow ready for CLI integration
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-05-SUMMARY.md`
</output>

View File

@@ -0,0 +1,165 @@
---
phase: 12-phase-task-decomposition
plan: 06
type: execute
wave: 3
depends_on: ["12-04", "12-05"]
files_modified:
- src/cli/index.ts
autonomous: true
---
<objective>
Add CLI commands for plan management and architect decompose workflow.
Purpose: Enable users to list plans, create plans, and spawn architect agents to decompose plans into tasks via the CLI.
Output: CLI commands for `cw plan` and `cw architect decompose`.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Depends on Plans 04, 05
@.planning/phases/12-phase-task-decomposition/12-04-SUMMARY.md
@.planning/phases/12-phase-task-decomposition/12-05-SUMMARY.md
# Pattern reference from Phase 11 (CLI commands)
@.planning/phases/11-architect-agent/11-06-SUMMARY.md
# CLI reference
@src/cli/index.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Add plan CLI commands</name>
<files>src/cli/index.ts</files>
<action>
Add plan command group following pattern of initiative commands:
```typescript
const plan = program.command('plan').description('Plan management');
plan
.command('list')
.description('List plans in a phase')
.requiredOption('--phase <id>', 'Phase ID')
.action(async (options) => {
const client = createTRPCClient();
const plans = await client.listPlans.query({ phaseId: options.phase });
console.table(plans.map(p => ({
id: p.id,
number: p.number,
name: p.name,
status: p.status,
})));
});
plan
.command('create')
.description('Create a plan in a phase')
.requiredOption('--phase <id>', 'Phase ID')
.requiredOption('--name <name>', 'Plan name')
.option('--description <desc>', 'Plan description')
.action(async (options) => {
const client = createTRPCClient();
const plan = await client.createPlan.mutate({
phaseId: options.phase,
name: options.name,
description: options.description,
});
console.log(`Created plan: ${plan.id} (${plan.name})`);
});
plan
.command('get')
.description('Get plan details')
.argument('<id>', 'Plan ID')
.action(async (id) => {
const client = createTRPCClient();
const plan = await client.getPlan.query({ id });
console.log(JSON.stringify(plan, null, 2));
});
plan
.command('tasks')
.description('List tasks in a plan')
.argument('<id>', 'Plan ID')
.action(async (id) => {
const client = createTRPCClient();
const tasks = await client.listTasks.query({ planId: id });
console.table(tasks.map(t => ({
id: t.id,
order: t.order,
name: t.name,
type: t.type,
status: t.status,
})));
});
```
</action>
<verify>npm run build passes, cw plan --help shows commands</verify>
<done>Plan CLI commands: list, create, get, tasks</done>
</task>
<task type="auto">
<name>Task 2: Add architect decompose command</name>
<files>src/cli/index.ts</files>
<action>
Add decompose command to architect command group:
```typescript
architect
.command('decompose')
.description('Spawn architect to decompose plan into tasks')
.requiredOption('--name <name>', 'Agent name')
.requiredOption('--plan <id>', 'Plan ID to decompose')
.option('--context <text>', 'Additional context for decomposition')
.action(async (options) => {
const client = createTRPCClient();
const result = await client.spawnArchitectDecompose.mutate({
name: options.name,
planId: options.plan,
context: options.context,
});
console.log(`Spawned decompose agent: ${result.name} (${result.id})`);
console.log(`Working on plan: ${options.plan}`);
console.log(`Mode: decompose`);
});
```
This follows the pattern of architect discuss and architect breakdown commands.
</action>
<verify>npm run build passes, cw architect decompose --help shows options</verify>
<done>cw architect decompose command spawns agent in decompose mode</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] npm run build succeeds
- [ ] cw plan --help shows: list, create, get, tasks
- [ ] cw architect --help shows: discuss, breakdown, decompose
- [ ] Commands follow existing CLI patterns (error handling, output format)
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Full CLI for plan management and decompose workflow
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-06-SUMMARY.md`
</output>

View File

@@ -0,0 +1,179 @@
---
phase: 12-phase-task-decomposition
plan: 07
type: execute
wave: 4
depends_on: ["12-01", "12-02", "12-03"]
files_modified:
- src/agent/mock-manager.test.ts
- src/db/repositories/drizzle/drizzle-plan-repository.test.ts
autonomous: true
---
<objective>
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.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<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
</context>
<tasks>
<task type="auto">
<name>Task 1: Add MockAgentManager decompose mode tests</name>
<files>src/agent/mock-manager.test.ts</files>
<action>
Add tests for decompose mode scenarios following breakdown mode test patterns:
```typescript
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' }),
})
);
});
});
```
</action>
<verify>npm test passes with new decompose tests</verify>
<done>MockAgentManager decompose mode tests cover spawn, complete, and questions scenarios</done>
</task>
<task type="auto">
<name>Task 2: Add PlanRepository extension tests</name>
<files>src/db/repositories/drizzle/drizzle-plan-repository.test.ts</files>
<action>
Add tests for new PlanRepository methods:
```typescript
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.
</action>
<verify>npm test passes with PlanRepository tests</verify>
<done>PlanRepository findByPhaseId and getNextNumber tested</done>
</task>
</tasks>
<verification>
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)
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Unit test coverage for Phase 12 features
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-07-SUMMARY.md`
</output>

View File

@@ -0,0 +1,258 @@
---
phase: 12-phase-task-decomposition
plan: 08
type: execute
wave: 4
depends_on: ["12-05", "12-06", "12-07"]
files_modified:
- src/test/harness.ts
- src/test/e2e/decompose-workflow.test.ts
autonomous: true
---
<objective>
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.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<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
</context>
<tasks>
<task type="auto">
<name>Task 1: Add TestHarness decompose mode helpers</name>
<files>src/test/harness.ts</files>
<action>
Add decompose scenario helpers to TestHarness following architect mode pattern:
```typescript
/**
* 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:
```typescript
async createPlan(phaseId: string, name: string, description?: string) {
return this.caller.createPlan({ phaseId, name, description });
}
async getTasksForPlan(planId: string) {
return this.caller.listTasks({ planId });
}
```
</action>
<verify>npm run build passes</verify>
<done>TestHarness has decompose scenario helpers and plan convenience methods</done>
</task>
<task type="auto">
<name>Task 2: Add decompose mode E2E tests</name>
<files>src/test/e2e/decompose-workflow.test.ts</files>
<action>
Create E2E test file for decompose workflow:
```typescript
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');
});
});
});
```
</action>
<verify>npm test passes with new E2E tests</verify>
<done>E2E tests cover decompose spawn, Q&A flow, and task persistence</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Full E2E coverage for decompose workflow
</success_criteria>
<output>
After completion, create `.planning/phases/12-phase-task-decomposition/12-08-SUMMARY.md`
</output>