docs(05): create phase 5 plan - task dispatch
Phase 05: Task Dispatch - 5 plans in 3 waves - 3 parallel (Wave 1), 1 sequential (Wave 2), 1 sequential (Wave 3) - Ready for execution Requirements covered: - AGENT-06: Message queue for agent questions - TASK-01: Task status visibility - TASK-04: Dependency-ordered dispatch - TASK-05: Work queue for agents
This commit is contained in:
116
.planning/phases/05-task-dispatch/05-01-PLAN.md
Normal file
116
.planning/phases/05-task-dispatch/05-01-PLAN.md
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
phase: 05-task-dispatch
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified: [src/db/schema.ts, src/db/repositories/message-repository.ts, src/db/repositories/drizzle/message.ts, src/db/repositories/drizzle/message.test.ts, src/db/repositories/index.ts, src/db/repositories/drizzle/index.ts]
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add message schema and repository for persisting agent questions.
|
||||
|
||||
Purpose: AGENT-06 requires agents to surface questions to users. When an agent pauses on AskUserQuestion, the question needs to persist in the database so users can query pending messages and respond later.
|
||||
Output: messages table, MessageRepository port/adapter with full CRUD and tests.
|
||||
</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
|
||||
|
||||
@src/db/schema.ts
|
||||
@src/db/repositories/task-repository.ts
|
||||
@src/db/repositories/drizzle/task.ts
|
||||
@src/db/repositories/drizzle/agent.ts
|
||||
@src/events/types.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add messages table to schema</name>
|
||||
<files>src/db/schema.ts</files>
|
||||
<action>
|
||||
Add messages table after agents table. Schema:
|
||||
- id: text primary key
|
||||
- agentId: text NOT NULL foreign key to agents.id with SET NULL on delete (message persists even if agent deleted)
|
||||
- type: text enum ['question', 'info', 'error'] NOT NULL default 'question'
|
||||
- content: text NOT NULL (the question or message text)
|
||||
- status: text enum ['pending', 'read', 'responded'] NOT NULL default 'pending'
|
||||
- response: text nullable (user's response when status is 'responded')
|
||||
- createdAt: integer timestamp NOT NULL
|
||||
- updatedAt: integer timestamp NOT NULL
|
||||
|
||||
Add relations: message belongs to agent (nullable after delete).
|
||||
Export Message and NewMessage types.
|
||||
|
||||
Follow existing patterns: use sqliteTable, relations, InferSelectModel/InferInsertModel.
|
||||
</action>
|
||||
<verify>npm run build passes, no TypeScript errors</verify>
|
||||
<done>messages table in schema with types exported</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Create MessageRepository port and adapter</name>
|
||||
<files>src/db/repositories/message-repository.ts, src/db/repositories/drizzle/message.ts, src/db/repositories/drizzle/message.test.ts, src/db/repositories/index.ts, src/db/repositories/drizzle/index.ts</files>
|
||||
<action>
|
||||
Create MessageRepository following TaskRepository pattern exactly:
|
||||
|
||||
1. Port interface (message-repository.ts):
|
||||
- CreateMessageData type (omit id, createdAt, updatedAt)
|
||||
- UpdateMessageData type (partial of create data)
|
||||
- MessageRepository interface with:
|
||||
- create(data: CreateMessageData): Promise<Message>
|
||||
- findById(id: string): Promise<Message | null>
|
||||
- findByAgentId(agentId: string): Promise<Message[]>
|
||||
- findPending(): Promise<Message[]> (status = 'pending')
|
||||
- update(id: string, data: UpdateMessageData): Promise<Message>
|
||||
- delete(id: string): Promise<void>
|
||||
|
||||
2. Drizzle adapter (drizzle/message.ts):
|
||||
- DrizzleMessageRepository class implementing port
|
||||
- Use nanoid for id generation
|
||||
- Fetch after insert to get schema defaults
|
||||
- Order by createdAt DESC for lists
|
||||
|
||||
3. Tests (drizzle/message.test.ts):
|
||||
- Use createTestDatabase helper
|
||||
- Test create, findById, findByAgentId, findPending, update, delete
|
||||
- Test pending filter returns only pending messages
|
||||
- Test response field update when marking as responded
|
||||
|
||||
4. Re-export from index files (same pattern as AgentRepository)
|
||||
</action>
|
||||
<verify>npm test -- src/db/repositories/drizzle/message.test.ts passes</verify>
|
||||
<done>MessageRepository port/adapter with passing tests</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] npm run build succeeds
|
||||
- [ ] npm test passes all tests including new message tests
|
||||
- [ ] messages table accessible via DrizzleMessageRepository
|
||||
- [ ] findPending returns only pending messages
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- messages table added to schema with proper types
|
||||
- MessageRepository port interface defined
|
||||
- DrizzleMessageRepository adapter implemented
|
||||
- All tests pass
|
||||
- Exports wired up in index files
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-task-dispatch/05-01-SUMMARY.md`
|
||||
</output>
|
||||
122
.planning/phases/05-task-dispatch/05-02-PLAN.md
Normal file
122
.planning/phases/05-task-dispatch/05-02-PLAN.md
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
phase: 05-task-dispatch
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified: [src/trpc/router.ts, src/trpc/context.ts, src/cli/index.ts]
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add task visibility via tRPC and CLI.
|
||||
|
||||
Purpose: TASK-01 requires users to see status of all tasks at a glance. Expose existing TaskRepository through tRPC endpoints and CLI commands for task listing and status viewing.
|
||||
Output: tRPC task procedures, CLI `cw task list` and `cw task get` commands.
|
||||
</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
|
||||
|
||||
@src/trpc/router.ts
|
||||
@src/trpc/context.ts
|
||||
@src/cli/index.ts
|
||||
@src/db/repositories/task-repository.ts
|
||||
@src/db/schema.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add task tRPC procedures</name>
|
||||
<files>src/trpc/router.ts, src/trpc/context.ts</files>
|
||||
<action>
|
||||
1. Add TaskRepository to TRPCContext (optional, same pattern as agentManager):
|
||||
- Add taskRepository?: TaskRepository to context type
|
||||
- Add requireTaskRepository helper function
|
||||
|
||||
2. Add task procedures to appRouter:
|
||||
|
||||
listTasks: publicProcedure
|
||||
.input(z.object({ planId: z.string().optional() }))
|
||||
.query(...)
|
||||
- If planId provided, return tasks for that plan (ordered by order field)
|
||||
- If no planId, return all tasks (need to add findAll to TaskRepository first - OR use a simple "list all" query)
|
||||
- Actually, for simplicity: require planId. Users query by plan.
|
||||
- Return array of Task objects
|
||||
|
||||
getTask: publicProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(...)
|
||||
- Return single task or throw NOT_FOUND
|
||||
|
||||
updateTaskStatus: publicProcedure
|
||||
.input(z.object({
|
||||
id: z.string(),
|
||||
status: z.enum(['pending', 'in_progress', 'completed', 'blocked'])
|
||||
}))
|
||||
.mutation(...)
|
||||
- Update task status
|
||||
- Return updated task
|
||||
|
||||
Follow existing patterns from agent procedures. Use Zod schemas for input validation.
|
||||
</action>
|
||||
<verify>npm run build passes, npm test -- src/trpc/router.test.ts passes</verify>
|
||||
<done>Task tRPC procedures available: listTasks, getTask, updateTaskStatus</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add task CLI commands</name>
|
||||
<files>src/cli/index.ts</files>
|
||||
<action>
|
||||
Add task subcommands to the existing 'task' command group:
|
||||
|
||||
1. cw task list --plan <planId>
|
||||
- Call listTasks tRPC procedure
|
||||
- Display tasks as table: name, status, type, priority
|
||||
- Show count of pending/in_progress/completed
|
||||
|
||||
2. cw task get <taskId>
|
||||
- Call getTask tRPC procedure
|
||||
- Display full task details: id, name, description, type, priority, status, order, timestamps
|
||||
|
||||
3. cw task status <taskId> <status>
|
||||
- Call updateTaskStatus tRPC procedure
|
||||
- Validate status is one of: pending, in_progress, completed, blocked
|
||||
- Confirm status update
|
||||
|
||||
Replace the placeholder "not implemented" action with real commands.
|
||||
Follow existing CLI patterns (error handling, client creation, output formatting).
|
||||
</action>
|
||||
<verify>cw task list --plan test-id shows error (expected - no server), cw task --help shows commands</verify>
|
||||
<done>CLI task commands functional: list, get, status</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] npm run build succeeds
|
||||
- [ ] npm test passes
|
||||
- [ ] cw task --help shows list, get, status commands
|
||||
- [ ] Task procedures added to router
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- tRPC task procedures (listTasks, getTask, updateTaskStatus) added
|
||||
- TaskRepository optional in context (same pattern as AgentManager)
|
||||
- CLI task commands: list, get, status
|
||||
- All existing tests still pass
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-task-dispatch/05-02-SUMMARY.md`
|
||||
</output>
|
||||
165
.planning/phases/05-task-dispatch/05-03-PLAN.md
Normal file
165
.planning/phases/05-task-dispatch/05-03-PLAN.md
Normal file
@@ -0,0 +1,165 @@
|
||||
---
|
||||
phase: 05-task-dispatch
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified: [src/dispatch/types.ts, src/dispatch/index.ts, src/events/types.ts, src/events/index.ts]
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
Define DispatchManager port interface and dispatch events.
|
||||
|
||||
Purpose: TASK-04 and TASK-05 require dependency-ordered task dispatch and work queue. Define the port interface that the adapter will implement, plus domain events for dispatch lifecycle.
|
||||
Output: DispatchManager port interface, dispatch domain events, exported from dispatch module.
|
||||
</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
|
||||
|
||||
@src/agent/types.ts
|
||||
@src/git/types.ts
|
||||
@src/events/types.ts
|
||||
@src/db/schema.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Create DispatchManager port interface</name>
|
||||
<files>src/dispatch/types.ts, src/dispatch/index.ts</files>
|
||||
<action>
|
||||
Create src/dispatch/ directory with types.ts and index.ts.
|
||||
|
||||
In types.ts, define:
|
||||
|
||||
1. QueuedTask type:
|
||||
- taskId: string
|
||||
- priority: 'low' | 'medium' | 'high'
|
||||
- queuedAt: Date
|
||||
- dependsOn: string[] (task IDs that must complete first)
|
||||
|
||||
2. DispatchResult type:
|
||||
- success: boolean
|
||||
- taskId: string
|
||||
- agentId?: string (assigned agent if dispatched)
|
||||
- reason?: string (why dispatch failed if not success)
|
||||
|
||||
3. DispatchManager port interface:
|
||||
/**
|
||||
* DispatchManager Port Interface
|
||||
*
|
||||
* Manages task dispatch queue with dependency ordering.
|
||||
*
|
||||
* Covers requirements:
|
||||
* - TASK-04: Dependency-ordered dispatch
|
||||
* - TASK-05: Work queue for available agents
|
||||
*/
|
||||
interface DispatchManager {
|
||||
/**
|
||||
* Queue a task for dispatch.
|
||||
* Task will be dispatched when all dependencies complete.
|
||||
*/
|
||||
queue(taskId: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get next dispatchable task.
|
||||
* Returns task with all dependencies complete, highest priority first.
|
||||
* Returns null if no tasks ready.
|
||||
*/
|
||||
getNextDispatchable(): Promise<QueuedTask | null>;
|
||||
|
||||
/**
|
||||
* Dispatch next available task to an agent.
|
||||
* Finds available agent, assigns task, spawns agent.
|
||||
* Returns dispatch result.
|
||||
*/
|
||||
dispatchNext(): Promise<DispatchResult>;
|
||||
|
||||
/**
|
||||
* Mark a task as complete.
|
||||
* Triggers re-evaluation of dependent tasks.
|
||||
*/
|
||||
completeTask(taskId: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Mark a task as blocked.
|
||||
* Task will not be dispatched until unblocked.
|
||||
*/
|
||||
blockTask(taskId: string, reason: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get current queue state.
|
||||
* Returns all queued tasks with their dispatch readiness.
|
||||
*/
|
||||
getQueueState(): Promise<{
|
||||
queued: QueuedTask[];
|
||||
ready: QueuedTask[];
|
||||
blocked: Array<{ taskId: string; reason: string }>;
|
||||
}>;
|
||||
}
|
||||
|
||||
Export all types from index.ts.
|
||||
</action>
|
||||
<verify>npm run build passes, types importable from src/dispatch</verify>
|
||||
<done>DispatchManager port interface defined and exported</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add dispatch domain events</name>
|
||||
<files>src/events/types.ts, src/events/index.ts</files>
|
||||
<action>
|
||||
Add dispatch events to events/types.ts, following existing patterns:
|
||||
|
||||
1. TaskQueuedEvent:
|
||||
type: 'task:queued'
|
||||
payload: { taskId: string; priority: string; dependsOn: string[] }
|
||||
|
||||
2. TaskDispatchedEvent:
|
||||
type: 'task:dispatched'
|
||||
payload: { taskId: string; agentId: string; agentName: string }
|
||||
|
||||
3. TaskCompletedEvent:
|
||||
type: 'task:completed'
|
||||
payload: { taskId: string; agentId: string; success: boolean; message: string }
|
||||
|
||||
4. TaskBlockedEvent:
|
||||
type: 'task:blocked'
|
||||
payload: { taskId: string; reason: string; blockedBy?: string[] }
|
||||
|
||||
Add all four to DomainEventMap union type.
|
||||
No changes needed to index.ts (types auto-exported).
|
||||
</action>
|
||||
<verify>npm run build passes, events compile without errors</verify>
|
||||
<done>Dispatch events added to DomainEventMap</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] npm run build succeeds
|
||||
- [ ] npm test passes
|
||||
- [ ] DispatchManager interface importable from src/dispatch
|
||||
- [ ] Dispatch events in DomainEventMap
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- src/dispatch/types.ts with DispatchManager interface
|
||||
- QueuedTask, DispatchResult types defined
|
||||
- Four dispatch events added to events/types.ts
|
||||
- All types properly exported
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-task-dispatch/05-03-SUMMARY.md`
|
||||
</output>
|
||||
174
.planning/phases/05-task-dispatch/05-04-PLAN.md
Normal file
174
.planning/phases/05-task-dispatch/05-04-PLAN.md
Normal file
@@ -0,0 +1,174 @@
|
||||
---
|
||||
phase: 05-task-dispatch
|
||||
plan: 04
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["05-01", "05-03"]
|
||||
files_modified: [src/dispatch/manager.ts, src/dispatch/manager.test.ts, src/dispatch/index.ts]
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement DispatchManager adapter with dependency checking and queue management.
|
||||
|
||||
Purpose: TASK-04 requires dependency-ordered dispatch, TASK-05 requires work queue. Implement the DispatchManager adapter that checks task dependencies before dispatch and manages the work queue.
|
||||
Output: DispatchManager adapter with dependency algorithm, queue management, and tests.
|
||||
</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
|
||||
|
||||
@.planning/phases/05-task-dispatch/05-01-SUMMARY.md
|
||||
@.planning/phases/05-task-dispatch/05-03-SUMMARY.md
|
||||
|
||||
@src/dispatch/types.ts
|
||||
@src/db/schema.ts
|
||||
@src/db/repositories/task-repository.ts
|
||||
@src/agent/types.ts
|
||||
@src/events/types.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Implement dependency checking algorithm</name>
|
||||
<files>src/dispatch/manager.ts</files>
|
||||
<action>
|
||||
Create DefaultDispatchManager class implementing DispatchManager interface.
|
||||
|
||||
Constructor dependencies (inject via constructor):
|
||||
- taskRepository: TaskRepository
|
||||
- messageRepository: MessageRepository (from 05-01)
|
||||
- agentManager: AgentManager
|
||||
- eventBus: EventBus
|
||||
|
||||
Implement core dependency algorithm:
|
||||
|
||||
1. queue(taskId):
|
||||
- Fetch task and its dependencies from task_dependencies table
|
||||
- Add to internal queue (use Map<string, QueuedTask>)
|
||||
- Emit TaskQueuedEvent
|
||||
|
||||
2. getNextDispatchable():
|
||||
- Get all queued tasks
|
||||
- For each, check if ALL dependencies have status='completed'
|
||||
- Filter to only ready tasks (all deps complete)
|
||||
- Sort by priority (high > medium > low), then by queuedAt (oldest first)
|
||||
- Return first or null
|
||||
|
||||
3. completeTask(taskId):
|
||||
- Update task status to 'completed' via taskRepository
|
||||
- Remove from queue
|
||||
- Emit TaskCompletedEvent
|
||||
- Note: dependent tasks automatically become ready on next getNextDispatchable call
|
||||
|
||||
4. blockTask(taskId, reason):
|
||||
- Update task status to 'blocked' via taskRepository
|
||||
- Emit TaskBlockedEvent
|
||||
|
||||
Use simple in-memory queue (Map). Production could use persistent queue but in-memory is fine for v1.
|
||||
</action>
|
||||
<verify>npm run build passes</verify>
|
||||
<done>Dependency checking algorithm implemented</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Implement dispatchNext and queue state</name>
|
||||
<files>src/dispatch/manager.ts</files>
|
||||
<action>
|
||||
Complete DispatchManager implementation:
|
||||
|
||||
1. dispatchNext():
|
||||
- Call getNextDispatchable() to get next task
|
||||
- If null, return { success: false, taskId: '', reason: 'No dispatchable tasks' }
|
||||
- Find available agent (status='idle') via agentManager.list()
|
||||
- If no available agent, return { success: false, taskId, reason: 'No available agents' }
|
||||
- Get task details from taskRepository
|
||||
- Spawn agent with task: agentManager.spawn({ name: generateAgentName(), taskId, prompt: task.description || task.name })
|
||||
- Update task status to 'in_progress'
|
||||
- Emit TaskDispatchedEvent
|
||||
- Return { success: true, taskId, agentId }
|
||||
|
||||
2. getQueueState():
|
||||
- Return { queued: [...allQueuedTasks], ready: [...readyTasks], blocked: [...blockedTasks] }
|
||||
- Uses internal queue state
|
||||
|
||||
Helper: generateAgentName():
|
||||
- Generate unique name for agent (e.g., 'agent-${nanoid(6)}' or use Vancouver neighborhood names: 'gastown', 'yaletown', 'kitsilano', etc.)
|
||||
- For v1: simple 'agent-${taskId.slice(0,6)}' is fine
|
||||
|
||||
Handle edge cases:
|
||||
- Task not found: throw error
|
||||
- Circular dependencies: not checked in v1 (assume valid DAG)
|
||||
</action>
|
||||
<verify>npm run build passes</verify>
|
||||
<done>dispatchNext and getQueueState implemented</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Add tests and wire up exports</name>
|
||||
<files>src/dispatch/manager.test.ts, src/dispatch/index.ts</files>
|
||||
<action>
|
||||
Create manager.test.ts with tests:
|
||||
|
||||
1. Setup:
|
||||
- Create in-memory database with createTestDatabase helper
|
||||
- Create mock/real repositories and EventBus
|
||||
- Create test tasks with dependencies
|
||||
|
||||
2. Test cases:
|
||||
- queue adds task to queue and emits event
|
||||
- getNextDispatchable returns null when queue empty
|
||||
- getNextDispatchable returns task when dependencies complete
|
||||
- getNextDispatchable returns null when dependencies incomplete
|
||||
- getNextDispatchable respects priority ordering
|
||||
- completeTask updates status and emits event
|
||||
- blockTask updates status and emits event
|
||||
- dispatchNext returns failure when no tasks ready
|
||||
- dispatchNext returns failure when no agents available
|
||||
- getQueueState returns correct state
|
||||
|
||||
3. Test dependency scenario:
|
||||
- Task A (no deps)
|
||||
- Task B (depends on A)
|
||||
- Task C (depends on A)
|
||||
- Queue all three
|
||||
- Only A should be dispatchable
|
||||
- Complete A
|
||||
- B and C should become dispatchable
|
||||
|
||||
Update index.ts to export DefaultDispatchManager class.
|
||||
</action>
|
||||
<verify>npm test -- src/dispatch/manager.test.ts passes</verify>
|
||||
<done>Tests pass, DispatchManager exported</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] npm run build succeeds
|
||||
- [ ] npm test passes all tests
|
||||
- [ ] Dependency ordering works correctly
|
||||
- [ ] Queue state accurately reflects task readiness
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- DefaultDispatchManager implements DispatchManager interface
|
||||
- Dependency checking prevents premature dispatch
|
||||
- Priority ordering respected
|
||||
- All dispatch events emitted correctly
|
||||
- Tests cover core scenarios
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-task-dispatch/05-04-SUMMARY.md`
|
||||
</output>
|
||||
174
.planning/phases/05-task-dispatch/05-05-PLAN.md
Normal file
174
.planning/phases/05-task-dispatch/05-05-PLAN.md
Normal file
@@ -0,0 +1,174 @@
|
||||
---
|
||||
phase: 05-task-dispatch
|
||||
plan: 05
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on: ["05-02", "05-04"]
|
||||
files_modified: [src/trpc/router.ts, src/trpc/context.ts, src/cli/index.ts]
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add message and dispatch tRPC procedures and CLI commands.
|
||||
|
||||
Purpose: Complete AGENT-06 (message visibility) and TASK-04/TASK-05 (dispatch control) with user-facing interfaces. Users can view pending agent questions and control task dispatch.
|
||||
Output: tRPC message and dispatch procedures, CLI commands for messages and dispatch.
|
||||
</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
|
||||
|
||||
@.planning/phases/05-task-dispatch/05-01-SUMMARY.md
|
||||
@.planning/phases/05-task-dispatch/05-02-SUMMARY.md
|
||||
@.planning/phases/05-task-dispatch/05-04-SUMMARY.md
|
||||
|
||||
@src/trpc/router.ts
|
||||
@src/trpc/context.ts
|
||||
@src/cli/index.ts
|
||||
@src/db/repositories/message-repository.ts
|
||||
@src/dispatch/types.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add message and dispatch tRPC procedures</name>
|
||||
<files>src/trpc/router.ts, src/trpc/context.ts</files>
|
||||
<action>
|
||||
1. Add to TRPCContext:
|
||||
- messageRepository?: MessageRepository
|
||||
- dispatchManager?: DispatchManager
|
||||
- Add requireMessageRepository and requireDispatchManager helpers
|
||||
|
||||
2. Add message procedures to appRouter:
|
||||
|
||||
listMessages: publicProcedure
|
||||
.input(z.object({ agentId: z.string().optional(), status: z.enum(['pending', 'read', 'responded']).optional() }))
|
||||
.query(...)
|
||||
- If agentId, filter by agent
|
||||
- If status, filter by status
|
||||
- Return array of Message objects
|
||||
|
||||
getMessage: publicProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(...)
|
||||
- Return single message or throw NOT_FOUND
|
||||
|
||||
respondToMessage: publicProcedure
|
||||
.input(z.object({ id: z.string(), response: z.string() }))
|
||||
.mutation(...)
|
||||
- Update message with response and status='responded'
|
||||
- Return updated message
|
||||
|
||||
3. Add dispatch procedures:
|
||||
|
||||
queueTask: publicProcedure
|
||||
.input(z.object({ taskId: z.string() }))
|
||||
.mutation(...)
|
||||
- Call dispatchManager.queue(taskId)
|
||||
- Return { success: true }
|
||||
|
||||
dispatchNext: publicProcedure
|
||||
.mutation(...)
|
||||
- Call dispatchManager.dispatchNext()
|
||||
- Return DispatchResult
|
||||
|
||||
getQueueState: publicProcedure
|
||||
.query(...)
|
||||
- Call dispatchManager.getQueueState()
|
||||
- Return queue state object
|
||||
|
||||
completeTask: publicProcedure
|
||||
.input(z.object({ taskId: z.string() }))
|
||||
.mutation(...)
|
||||
- Call dispatchManager.completeTask(taskId)
|
||||
- Return { success: true }
|
||||
</action>
|
||||
<verify>npm run build passes</verify>
|
||||
<done>Message and dispatch tRPC procedures added</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add message and dispatch CLI commands</name>
|
||||
<files>src/cli/index.ts</files>
|
||||
<action>
|
||||
1. Add message command group:
|
||||
|
||||
const messageCommand = program
|
||||
.command('message')
|
||||
.description('View agent messages and questions');
|
||||
|
||||
cw message list [--agent <agentId>] [--status <status>]
|
||||
- Call listMessages tRPC
|
||||
- Display as table: id (short), agent, type, content (truncated), status, createdAt
|
||||
- Show "(pending)" count prominently
|
||||
|
||||
cw message read <messageId>
|
||||
- Call getMessage tRPC
|
||||
- Display full message content
|
||||
- If pending, show prompt to respond
|
||||
|
||||
cw message respond <messageId> <response>
|
||||
- Call respondToMessage tRPC
|
||||
- Confirm response recorded
|
||||
- Suggest resuming agent if appropriate
|
||||
|
||||
2. Add dispatch command group:
|
||||
|
||||
const dispatchCommand = program
|
||||
.command('dispatch')
|
||||
.description('Control task dispatch queue');
|
||||
|
||||
cw dispatch queue <taskId>
|
||||
- Call queueTask tRPC
|
||||
- Confirm task queued
|
||||
|
||||
cw dispatch next
|
||||
- Call dispatchNext tRPC
|
||||
- Show result: which task dispatched to which agent, or why it failed
|
||||
|
||||
cw dispatch status
|
||||
- Call getQueueState tRPC
|
||||
- Show: queued count, ready count, blocked count
|
||||
- List ready tasks with their priority
|
||||
|
||||
cw dispatch complete <taskId>
|
||||
- Call completeTask tRPC
|
||||
- Confirm task completed
|
||||
|
||||
Follow existing CLI patterns for error handling and output formatting.
|
||||
</action>
|
||||
<verify>cw message --help and cw dispatch --help show commands</verify>
|
||||
<done>Message and dispatch CLI commands functional</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] npm run build succeeds
|
||||
- [ ] npm test passes
|
||||
- [ ] cw message --help shows list, read, respond
|
||||
- [ ] cw dispatch --help shows queue, next, status, complete
|
||||
- [ ] All tRPC procedures added
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- Message tRPC procedures: listMessages, getMessage, respondToMessage
|
||||
- Dispatch tRPC procedures: queueTask, dispatchNext, getQueueState, completeTask
|
||||
- CLI message commands: list, read, respond
|
||||
- CLI dispatch commands: queue, next, status, complete
|
||||
- All requirements (AGENT-06, TASK-01, TASK-04, TASK-05) have user-facing interfaces
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-task-dispatch/05-05-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user