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:
@@ -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 | - |
|
||||
|
||||
---
|
||||
|
||||
111
.planning/phases/12-phase-task-decomposition/12-01-PLAN.md
Normal file
111
.planning/phases/12-phase-task-decomposition/12-01-PLAN.md
Normal 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>
|
||||
112
.planning/phases/12-phase-task-decomposition/12-02-PLAN.md
Normal file
112
.planning/phases/12-phase-task-decomposition/12-02-PLAN.md
Normal 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>
|
||||
126
.planning/phases/12-phase-task-decomposition/12-03-PLAN.md
Normal file
126
.planning/phases/12-phase-task-decomposition/12-03-PLAN.md
Normal 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>
|
||||
140
.planning/phases/12-phase-task-decomposition/12-04-PLAN.md
Normal file
140
.planning/phases/12-phase-task-decomposition/12-04-PLAN.md
Normal 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>
|
||||
217
.planning/phases/12-phase-task-decomposition/12-05-PLAN.md
Normal file
217
.planning/phases/12-phase-task-decomposition/12-05-PLAN.md
Normal 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>
|
||||
165
.planning/phases/12-phase-task-decomposition/12-06-PLAN.md
Normal file
165
.planning/phases/12-phase-task-decomposition/12-06-PLAN.md
Normal 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>
|
||||
179
.planning/phases/12-phase-task-decomposition/12-07-PLAN.md
Normal file
179
.planning/phases/12-phase-task-decomposition/12-07-PLAN.md
Normal 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>
|
||||
258
.planning/phases/12-phase-task-decomposition/12-08-PLAN.md
Normal file
258
.planning/phases/12-phase-task-decomposition/12-08-PLAN.md
Normal 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>
|
||||
Reference in New Issue
Block a user