---
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>
