diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 7469e35..8fc1025 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -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 | - | --- diff --git a/.planning/phases/12-phase-task-decomposition/12-01-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-01-PLAN.md new file mode 100644 index 0000000..a9809ea --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-01-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Extend AgentMode with 'decompose' + src/agent/types.ts, src/db/schema.ts, src/db/repositories/drizzle/test-helpers.ts + +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 + + npm run build passes, npm test passes + AgentMode type includes 'decompose', database schema updated + + + + Task 2: Create decompose output schema + src/agent/schema.ts + +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; + ``` + +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 + + npm run build passes, types exported correctly + decomposeOutputSchema and TaskBreakdown type exported, JSON schema version available + + + + + +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 + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Decompose mode schema ready for manager implementation + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-01-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-02-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-02-PLAN.md new file mode 100644 index 0000000..dcea11d --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-02-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Extend PlanRepository port interface + src/db/repositories/plan-repository.ts + +Add the following methods to PlanRepository interface (following pattern from PhaseRepository): + +1. `findByPhaseId(phaseId: string): Promise` - Get all plans for a phase, ordered by number +2. `getNextNumber(phaseId: string): Promise` - Get next available plan number (MAX+1 or 1 if none) + + npm run build passes (no implementation yet) + PlanRepository interface extended with new methods + + + + Task 2: Implement methods in DrizzlePlanRepository + src/db/repositories/drizzle/drizzle-plan-repository.ts + +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. + + npm run build passes, npm test passes + DrizzlePlanRepository implements findByPhaseId and getNextNumber + + + + Task 3: Export types from repositories index + src/db/repositories/index.ts + +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. + + npm run build passes, types importable from src/db/repositories + All PlanRepository types properly exported + + + + + +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 + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- PlanRepository ready for tRPC procedures + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-02-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-03-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-03-PLAN.md new file mode 100644 index 0000000..1c4ea41 --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-03-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Update ClaudeAgentManager for decompose mode + src/agent/manager.ts + +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' + + npm run build passes + ClaudeAgentManager handles decompose mode with correct schema and completion handling + + + + Task 2: Update MockAgentManager for decompose mode + src/agent/mock-manager.ts + +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 + + npm run build passes, npm test passes + MockAgentManager handles decompose mode scenarios for E2E testing + + + + Task 3: Extend AgentStoppedEvent reason type + src/events/types.ts + +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. + + npm run build passes + AgentStoppedEvent reason includes 'decompose_complete' + + + + + +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' + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Decompose mode fully supported in both managers + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-03-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-04-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-04-PLAN.md new file mode 100644 index 0000000..545a880 --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-04-PLAN.md @@ -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 +--- + + +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). + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Add PlanRepository to tRPC context + src/trpc/context.ts + +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) + + npm run build passes + PlanRepository available in tRPC context + + + + Task 2: Add Plan tRPC procedures + src/trpc/router.ts + +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. + + npm run build passes + Plan CRUD procedures available via tRPC + + + + Task 3: Add createTasksFromDecomposition procedure + src/trpc/router.ts + +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. + + npm run build passes, npm test passes + createTasksFromDecomposition procedure creates tasks with dependencies from agent output + + + + + +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 + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Full Plan and Task tRPC layer ready for CLI + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-04-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-05-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-05-PLAN.md new file mode 100644 index 0000000..a56846b --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-05-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Create buildDecomposePrompt function + src/agent/prompts.ts + +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`; +} +``` + + npm run build passes + buildDecomposePrompt exported from src/agent/prompts.ts + + + + Task 2: Export buildDecomposePrompt from agent index + src/agent/index.ts + +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. + + npm run build passes, buildDecomposePrompt importable from src/agent + buildDecomposePrompt exported from agent module + + + + Task 3: Add spawnArchitectDecompose tRPC procedure + src/trpc/router.ts + +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', + }); + }); +``` + + npm run build passes, npm test passes + spawnArchitectDecompose procedure spawns agent in decompose mode with comprehensive prompt + + + + + +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 + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Decompose workflow ready for CLI integration + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-05-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-06-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-06-PLAN.md new file mode 100644 index 0000000..dc2df4c --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-06-PLAN.md @@ -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 +--- + + +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`. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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 + + + + + + Task 1: Add plan CLI commands + src/cli/index.ts + +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 ', '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 ', 'Phase ID') + .requiredOption('--name ', 'Plan name') + .option('--description ', '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('', '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('', '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, + }))); + }); +``` + + npm run build passes, cw plan --help shows commands + Plan CLI commands: list, create, get, tasks + + + + Task 2: Add architect decompose command + src/cli/index.ts + +Add decompose command to architect command group: + +```typescript +architect + .command('decompose') + .description('Spawn architect to decompose plan into tasks') + .requiredOption('--name ', 'Agent name') + .requiredOption('--plan ', 'Plan ID to decompose') + .option('--context ', '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. + + npm run build passes, cw architect decompose --help shows options + cw architect decompose command spawns agent in decompose mode + + + + + +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) + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Full CLI for plan management and decompose workflow + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-06-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-07-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-07-PLAN.md new file mode 100644 index 0000000..732a264 --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-07-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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: + +```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' }), + }) + ); + }); +}); +``` + + 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: + +```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. + + 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) + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Unit test coverage for Phase 12 features + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-07-SUMMARY.md` + diff --git a/.planning/phases/12-phase-task-decomposition/12-08-PLAN.md b/.planning/phases/12-phase-task-decomposition/12-08-PLAN.md new file mode 100644 index 0000000..ece7d7e --- /dev/null +++ b/.planning/phases/12-phase-task-decomposition/12-08-PLAN.md @@ -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 +--- + + +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. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.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: + +```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 }); +} +``` + + 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: + +```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'); + }); + }); +}); +``` + + 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 + + + +- All tasks completed +- All verification checks pass +- No errors or warnings introduced +- Full E2E coverage for decompose workflow + + + +After completion, create `.planning/phases/12-phase-task-decomposition/12-08-SUMMARY.md` +