diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index cdaaf07..3c23a41 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -113,11 +113,13 @@ Plans:
**Goal**: Merge agent outputs into integration branch in dependency order, bounce conflicts back to agents
**Depends on**: Phase 5
**Requirements**: COORD-01, COORD-02
-**Research**: Unlikely (git merge patterns, but conflict detection needs care)
-**Plans**: TBD
+**Research**: Unlikely (programmatic coordination - gastown reference shows merge orchestration is code, not agent loop)
+**Plans**: 3 plans in 3 waves
Plans:
-- [ ] 06-01: TBD
+- [ ] 06-01: Coordination Events & Port (Wave 1)
+- [ ] 06-02: CoordinationManager Adapter (Wave 2)
+- [ ] 06-03: tRPC & CLI Integration (Wave 3)
### Phase 7: File System UI
**Goal**: Bidirectional sync between SQLite state and filesystem — agent messages as files, user responds via files
@@ -144,7 +146,7 @@ Phases execute in numeric order: 1 → 1.1 → 2 → 3 → 4 → 5 → 6 → 7
| 3. Git Integration | 2/2 | Complete | 2026-01-30 |
| 4. Agent Lifecycle | 4/4 | Complete | 2026-01-30 |
| 5. Task Dispatch | 5/5 | Complete | 2026-01-30 |
-| 6. Coordination | 0/? | Not started | - |
+| 6. Coordination | 0/3 | Not started | - |
| 7. File System UI | 0/? | Not started | - |
---
diff --git a/.planning/phases/06-coordination/06-01-PLAN.md b/.planning/phases/06-coordination/06-01-PLAN.md
new file mode 100644
index 0000000..6c2beb6
--- /dev/null
+++ b/.planning/phases/06-coordination/06-01-PLAN.md
@@ -0,0 +1,136 @@
+---
+phase: 06-coordination
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified: [src/coordination/types.ts, src/coordination/index.ts, src/events/types.ts, src/events/index.ts]
+autonomous: true
+---
+
+
+Add coordination domain events and CoordinationManager port interface.
+
+Purpose: Establish the contract for merge coordination following hexagonal architecture patterns.
+Output: Coordination types, CoordinationManager interface, and four merge lifecycle events.
+
+
+
+@~/.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 - git integration provides merge capability
+@.planning/phases/03-git-integration/03-01-SUMMARY.md
+@.planning/phases/03-git-integration/03-02-SUMMARY.md
+
+# Existing patterns to follow
+@src/events/types.ts
+@src/dispatch/types.ts
+@src/git/types.ts
+
+
+
+
+
+ Task 1: Add coordination domain events to event types
+ src/events/types.ts, src/events/index.ts
+
+Add four coordination events following existing event patterns:
+
+1. MergeQueuedEvent - when a completed task is queued for merge
+ - payload: { taskId, agentId, worktreeId, priority }
+
+2. MergeStartedEvent - when merge attempt begins
+ - payload: { taskId, agentId, worktreeId, targetBranch }
+
+3. MergeCompletedEvent - when merge succeeds
+ - payload: { taskId, agentId, worktreeId, targetBranch }
+
+4. MergeConflictedEvent - when merge has conflicts (triggers bounce-back)
+ - payload: { taskId, agentId, worktreeId, targetBranch, conflictingFiles: string[] }
+
+Add all four to DomainEventMap union type. Export from index.ts.
+
+ npm run build passes, grep shows all four events in types.ts
+ Four merge events added to DomainEventMap, exported from events module
+
+
+
+ Task 2: Create CoordinationManager port interface
+ src/coordination/types.ts, src/coordination/index.ts
+
+Create src/coordination/ module following same pattern as src/dispatch/:
+
+**types.ts:**
+
+1. MergeQueueItem type:
+ - taskId: string
+ - agentId: string
+ - worktreeId: string
+ - priority: 'low' | 'medium' | 'high'
+ - queuedAt: Date
+ - dependsOn: string[] (task IDs that must merge first)
+
+2. MergeStatus type: 'queued' | 'in_progress' | 'merged' | 'conflict'
+
+3. MergeResult type (mirrors git MergeResult but with task context):
+ - taskId: string
+ - success: boolean
+ - conflicts?: string[]
+ - message: string
+
+4. CoordinationManager interface:
+ - queueMerge(taskId: string): Promise
+ Queue a completed task for merge. Extracts agent/worktree from task.
+
+ - getNextMergeable(): Promise
+ Returns next task ready to merge (all dependencies already merged).
+
+ - processMerges(targetBranch: string): Promise
+ Process all ready merges in dependency order. Returns results.
+
+ - handleConflict(taskId: string, conflicts: string[]): Promise
+ Create conflict-resolution task and assign back to agent.
+
+ - getQueueState(): Promise<{
+ queued: MergeQueueItem[];
+ inProgress: MergeQueueItem[];
+ merged: string[]; // task IDs
+ conflicted: Array<{ taskId: string; conflicts: string[] }>;
+ }>
+
+**index.ts:**
+Export all types and interface.
+
+Include JSDoc comments explaining the port-adapter pattern.
+
+ npm run build passes, src/coordination/index.ts exports CoordinationManager
+ CoordinationManager port interface created with full type definitions
+
+
+
+
+
+Before declaring plan complete:
+- [ ] npm run build succeeds
+- [ ] Four merge events exist in src/events/types.ts
+- [ ] CoordinationManager interface exists in src/coordination/types.ts
+- [ ] All types exported from respective index.ts files
+
+
+
+- All tasks completed
+- All verification checks pass
+- No TypeScript errors
+- Patterns match existing EventBus, DispatchManager, WorktreeManager
+
+
+
diff --git a/.planning/phases/06-coordination/06-02-PLAN.md b/.planning/phases/06-coordination/06-02-PLAN.md
new file mode 100644
index 0000000..40add40
--- /dev/null
+++ b/.planning/phases/06-coordination/06-02-PLAN.md
@@ -0,0 +1,203 @@
+---
+phase: 06-coordination
+plan: 02
+type: execute
+wave: 2
+depends_on: ["06-01"]
+files_modified: [src/coordination/manager.ts, src/coordination/manager.test.ts, src/coordination/index.ts]
+autonomous: true
+---
+
+
+Implement DefaultCoordinationManager adapter with dependency-ordered merging and conflict bounce-back.
+
+Purpose: Orchestrate merges in dependency order and handle conflicts by creating resolution tasks.
+Output: Working CoordinationManager implementation with comprehensive tests.
+
+
+
+@~/.claude/get-shit-done/workflows/execute-plan.md
+@~/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+
+# This plan's dependency
+@.planning/phases/06-coordination/06-01-SUMMARY.md
+
+# Interfaces we implement/use
+@src/coordination/types.ts
+@src/git/types.ts
+@src/agent/types.ts
+@src/db/schema.ts
+
+# Patterns to follow
+@src/dispatch/manager.ts
+@src/git/manager.ts
+
+
+
+
+
+ Task 1: Implement DefaultCoordinationManager with dependency-ordered merging
+ src/coordination/manager.ts
+
+Create DefaultCoordinationManager class implementing CoordinationManager:
+
+**Constructor dependencies (optional injection, same pattern as DispatchManager):**
+- worktreeManager?: WorktreeManager
+- taskRepository?: TaskRepository
+- agentRepository?: AgentRepository
+- eventBus?: EventBus
+
+**State:**
+- mergeQueue: Map (in-memory, same as DispatchManager)
+- mergedTasks: Set (tracks successfully merged task IDs)
+- conflictedTasks: Map (taskId -> conflicting files)
+
+**queueMerge(taskId):**
+1. Look up task from repository to get dependencies
+2. Look up agent assigned to task to get worktreeId
+3. Create MergeQueueItem with dependsOn from task dependencies
+4. Add to mergeQueue
+5. Emit MergeQueuedEvent
+
+**getNextMergeable():**
+1. Filter queue for items where ALL dependsOn tasks are in mergedTasks
+2. Sort by priority (high > medium > low), then by queuedAt (FIFO)
+3. Return first item or null
+
+**processMerges(targetBranch):**
+1. Loop while getNextMergeable() returns items:
+ a. Mark item as in_progress
+ b. Emit MergeStartedEvent
+ c. Call worktreeManager.merge(item.worktreeId, targetBranch)
+ d. If success:
+ - Add taskId to mergedTasks
+ - Remove from queue
+ - Emit MergeCompletedEvent
+ e. If conflict:
+ - Add to conflictedTasks
+ - Remove from queue
+ - Emit MergeConflictedEvent
+ - Call handleConflict()
+2. Return all MergeResults
+
+**handleConflict(taskId, conflicts):**
+1. Create a new task in the same plan as original task:
+ - name: "Resolve merge conflicts for {originalTaskName}"
+ - description: "Conflicts in: {conflicts.join(', ')}"
+ - type: 'auto'
+ - dependsOn: [] (no dependencies - can start immediately)
+2. Assign new task to same agent that had the conflict
+3. Emit TaskQueuedEvent for the new conflict-resolution task
+
+**getQueueState():**
+Return current state of all tracking structures.
+
+ npm run build passes
+ DefaultCoordinationManager implements all CoordinationManager methods
+
+
+
+ Task 2: Implement conflict bounce-back task creation
+ src/coordination/manager.ts
+
+Enhance handleConflict to properly create conflict-resolution tasks:
+
+1. Generate unique task ID (nanoid or uuid pattern from existing code)
+2. Create task via taskRepository.create() with:
+ - planId: same as original task's planId
+ - name: "Resolve conflicts: {originalTask.name}"
+ - description: Include:
+ - List of conflicting files
+ - Original task context
+ - Instructions: "Resolve merge conflicts in the listed files, then mark task complete"
+ - type: 'auto'
+ - priority: 'high' (conflicts should be resolved quickly)
+ - status: 'pending'
+
+3. Create message to agent via message system (if messageRepository available):
+ - senderType: 'user' (system-generated)
+ - recipientType: 'agent'
+ - recipientId: original agent ID
+ - type: 'info'
+ - content: Conflict details and resolution instructions
+ - requiresResponse: false
+
+4. Update original task status to 'blocked' with reason
+
+This enables the agent to pick up conflict resolution work automatically.
+
+ npm run build passes
+ Conflict bounce-back creates new task and notifies agent
+
+
+
+ Task 3: Write tests for CoordinationManager
+ src/coordination/manager.test.ts, src/coordination/index.ts
+
+Create comprehensive tests following patterns from src/dispatch/manager.test.ts:
+
+**Test categories:**
+
+1. Queue management:
+ - queueMerge adds item to queue
+ - queueMerge emits MergeQueuedEvent
+ - getQueueState returns correct counts
+
+2. Dependency ordering:
+ - getNextMergeable returns null when dependencies not met
+ - getNextMergeable returns item when all dependencies merged
+ - processMerges handles dependency chain correctly (A -> B -> C)
+
+3. Priority ordering:
+ - High priority merges before medium/low
+ - Same priority follows FIFO
+
+4. Conflict handling:
+ - processMerges detects conflicts from WorktreeManager
+ - handleConflict creates new task
+ - MergeConflictedEvent emitted with correct payload
+ - Conflicted task tracked in getQueueState
+
+5. Success path:
+ - processMerges completes clean merges
+ - MergeCompletedEvent emitted
+ - Merged tasks tracked correctly
+
+**Test setup:**
+- Mock WorktreeManager (return success or conflict as needed)
+- Mock repositories (in-memory or jest mocks)
+- Use EventEmitterBus for event verification
+
+Export DefaultCoordinationManager from index.ts.
+
+ npm test -- src/coordination passes with all tests green
+ 14+ tests covering queue, dependencies, conflicts, and success paths
+
+
+
+
+
+Before declaring plan complete:
+- [ ] npm run build succeeds
+- [ ] npm test -- src/coordination passes
+- [ ] DefaultCoordinationManager exported from src/coordination/index.ts
+- [ ] All four merge events emitted at correct lifecycle points
+
+
+
+- All tasks completed
+- All verification checks pass
+- No TypeScript errors
+- Tests cover dependency ordering and conflict bounce-back
+- Patterns match DispatchManager implementation style
+
+
+
diff --git a/.planning/phases/06-coordination/06-03-PLAN.md b/.planning/phases/06-coordination/06-03-PLAN.md
new file mode 100644
index 0000000..3e5e8d7
--- /dev/null
+++ b/.planning/phases/06-coordination/06-03-PLAN.md
@@ -0,0 +1,239 @@
+---
+phase: 06-coordination
+plan: 03
+type: execute
+wave: 3
+depends_on: ["06-02"]
+files_modified: [src/trpc/routers/coordination.ts, src/trpc/routers/index.ts, src/cli/commands/merge.ts, src/cli/commands/coordinate.ts, src/cli/index.ts]
+autonomous: true
+---
+
+
+Add tRPC procedures and CLI commands for merge coordination.
+
+Purpose: Expose coordination capabilities through the CLI for user interaction.
+Output: tRPC router for coordination and CLI commands (cw merge, cw coordinate).
+
+
+
+@~/.claude/get-shit-done/workflows/execute-plan.md
+@~/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+
+# This plan's dependencies
+@.planning/phases/06-coordination/06-01-SUMMARY.md
+@.planning/phases/06-coordination/06-02-SUMMARY.md
+
+# Patterns to follow
+@src/trpc/routers/task.ts
+@src/trpc/routers/dispatch.ts
+@src/cli/commands/dispatch.ts
+@src/cli/commands/agent.ts
+
+
+
+
+
+ Task 1: Add coordination tRPC procedures
+ src/trpc/routers/coordination.ts, src/trpc/routers/index.ts
+
+Create coordination router following patterns from dispatch.ts and task.ts:
+
+**src/trpc/routers/coordination.ts:**
+
+```typescript
+import { z } from 'zod';
+import { router, publicProcedure } from '../trpc';
+
+export const coordinationRouter = router({
+ // Queue a completed task for merge
+ queueMerge: publicProcedure
+ .input(z.object({ taskId: z.string() }))
+ .mutation(async ({ ctx, input }) => {
+ // ctx.coordinationManager optional same pattern as other managers
+ if (!ctx.coordinationManager) {
+ throw new Error('CoordinationManager not available');
+ }
+ await ctx.coordinationManager.queueMerge(input.taskId);
+ return { success: true };
+ }),
+
+ // Process all ready merges
+ processMerges: publicProcedure
+ .input(z.object({
+ targetBranch: z.string().default('main')
+ }))
+ .mutation(async ({ ctx, input }) => {
+ if (!ctx.coordinationManager) {
+ throw new Error('CoordinationManager not available');
+ }
+ const results = await ctx.coordinationManager.processMerges(input.targetBranch);
+ return { results };
+ }),
+
+ // Get merge queue status
+ status: publicProcedure
+ .query(async ({ ctx }) => {
+ if (!ctx.coordinationManager) {
+ throw new Error('CoordinationManager not available');
+ }
+ return ctx.coordinationManager.getQueueState();
+ }),
+
+ // Get next mergeable task (for inspection)
+ nextMergeable: publicProcedure
+ .query(async ({ ctx }) => {
+ if (!ctx.coordinationManager) {
+ throw new Error('CoordinationManager not available');
+ }
+ return ctx.coordinationManager.getNextMergeable();
+ }),
+});
+```
+
+**src/trpc/routers/index.ts:**
+Add coordinationRouter to appRouter.
+
+**src/trpc/context.ts (if exists):**
+Add coordinationManager?: CoordinationManager to context type.
+
+ npm run build passes, coordinationRouter exported
+ Coordination tRPC procedures available: queueMerge, processMerges, status, nextMergeable
+
+
+
+ Task 2: Add CLI commands for merge coordination
+ src/cli/commands/merge.ts, src/cli/commands/coordinate.ts, src/cli/index.ts
+
+Create CLI commands following patterns from dispatch.ts and agent.ts:
+
+**src/cli/commands/merge.ts:**
+
+```typescript
+// cw merge queue - Queue a task for merge
+// cw merge status - Show merge queue status
+// cw merge next - Show next mergeable task
+
+import { Command } from 'commander';
+import { createTRPCClient } from '../trpc-client';
+
+export function createMergeCommand(): Command {
+ const merge = new Command('merge')
+ .description('Manage merge queue');
+
+ merge
+ .command('queue ')
+ .description('Queue a completed task for merge')
+ .action(async (taskId) => {
+ const client = createTRPCClient();
+ await client.coordination.queueMerge.mutate({ taskId });
+ console.log(`Task ${taskId} queued for merge`);
+ });
+
+ merge
+ .command('status')
+ .description('Show merge queue status')
+ .action(async () => {
+ const client = createTRPCClient();
+ const state = await client.coordination.status.query();
+ console.log('Merge Queue Status:');
+ console.log(` Queued: ${state.queued.length}`);
+ console.log(` In Progress: ${state.inProgress.length}`);
+ console.log(` Merged: ${state.merged.length}`);
+ console.log(` Conflicted: ${state.conflicted.length}`);
+
+ if (state.conflicted.length > 0) {
+ console.log('\nConflicts:');
+ for (const c of state.conflicted) {
+ console.log(` ${c.taskId}: ${c.conflicts.join(', ')}`);
+ }
+ }
+ });
+
+ merge
+ .command('next')
+ .description('Show next task ready to merge')
+ .action(async () => {
+ const client = createTRPCClient();
+ const next = await client.coordination.nextMergeable.query();
+ if (next) {
+ console.log(`Next mergeable: ${next.taskId} (priority: ${next.priority})`);
+ } else {
+ console.log('No tasks ready to merge');
+ }
+ });
+
+ return merge;
+}
+```
+
+**src/cli/commands/coordinate.ts:**
+
+```typescript
+// cw coordinate [--target ] - Process all ready merges
+
+import { Command } from 'commander';
+import { createTRPCClient } from '../trpc-client';
+
+export function createCoordinateCommand(): Command {
+ return new Command('coordinate')
+ .description('Process all ready merges in dependency order')
+ .option('-t, --target ', 'Target branch for merges', 'main')
+ .action(async (options) => {
+ const client = createTRPCClient();
+ console.log(`Processing merges to ${options.target}...`);
+
+ const { results } = await client.coordination.processMerges.mutate({
+ targetBranch: options.target
+ });
+
+ const succeeded = results.filter(r => r.success).length;
+ const conflicted = results.filter(r => !r.success).length;
+
+ console.log(`\nResults:`);
+ console.log(` Merged: ${succeeded}`);
+ console.log(` Conflicts: ${conflicted}`);
+
+ if (conflicted > 0) {
+ console.log('\nConflicted tasks (bounce-back tasks created):');
+ for (const r of results.filter(r => !r.success)) {
+ console.log(` ${r.taskId}: ${r.conflicts?.join(', ')}`);
+ }
+ }
+ });
+}
+```
+
+**src/cli/index.ts:**
+Register both commands with the CLI program.
+
+ npm run build passes, cw merge --help and cw coordinate --help work
+ CLI commands available: cw merge (queue/status/next), cw coordinate
+
+
+
+
+
+Before declaring plan complete:
+- [ ] npm run build succeeds
+- [ ] cw merge --help shows subcommands
+- [ ] cw coordinate --help shows options
+- [ ] tRPC coordination router accessible via client
+
+
+
+- All tasks completed
+- All verification checks pass
+- No TypeScript errors
+- CLI commands follow existing patterns (dispatch, agent)
+- COORD-01 and COORD-02 requirements satisfied
+
+
+