From 22572f410fbb5ec7621a17d53ce38e8d009fb17b Mon Sep 17 00:00:00 2001 From: Lukas May Date: Fri, 30 Jan 2026 20:58:23 +0100 Subject: [PATCH] docs(06): create phase plan Phase 06: Coordination - 3 plans in 3 waves - 06-01: Coordination Events & Port (Wave 1) - 06-02: CoordinationManager Adapter (Wave 2) - 06-03: tRPC & CLI Integration (Wave 3) - Ready for execution --- .planning/ROADMAP.md | 10 +- .../phases/06-coordination/06-01-PLAN.md | 136 ++++++++++ .../phases/06-coordination/06-02-PLAN.md | 203 +++++++++++++++ .../phases/06-coordination/06-03-PLAN.md | 239 ++++++++++++++++++ 4 files changed, 584 insertions(+), 4 deletions(-) create mode 100644 .planning/phases/06-coordination/06-01-PLAN.md create mode 100644 .planning/phases/06-coordination/06-02-PLAN.md create mode 100644 .planning/phases/06-coordination/06-03-PLAN.md 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 + + + +After completion, create `.planning/phases/06-coordination/06-01-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/06-coordination/06-02-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/06-coordination/06-03-SUMMARY.md` +