summaryrefslogblamecommitdiff
path: root/makima/docs/PLAN-task-branching.md
blob: cd35bc68d37a46997d9ed23a9bc5322c80e7c34a (plain) (tree)




































































































































































































                                                                                                                                                                                                                     
# Task Branching Feature for Makima

## Overview

Add the ability to branch/spin off tasks that resume from where another task ended, preserving both worktree state (file changes) and conversation context (what Claude discussed/discovered).

**Key requirement:** The branched task should "remember" what was previously discussed, enabling exploration of alternative approaches from the same starting point.

## Integration with Contracts

Tasks are grouped under **contracts** - organizational units with phases (research → specify → plan → execute → review). When branching:

- **Inherit contract**: Branched tasks stay in the same contract as the source task by default
- **Optional override**: User can choose to place the branch in a different contract
- **Phase awareness**: The branch inherits the contract's current phase context

## Architecture Summary

Since Claude Code is stateless (each invocation is fresh), we cannot replay the actual conversation. Instead, we:
1. Capture and store conversation turns (user messages + assistant responses)
2. When branching, inject a formatted transcript as context in the new task's plan
3. Copy the worktree state using existing `continue_from_task_id` mechanism

## Implementation Plan

### Phase 1: Capture Conversation History

**1.1 Database Migration**

Create `makima/migrations/20250111000000_add_task_conversations.sql`:

```sql
CREATE TABLE IF NOT EXISTS task_conversations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    turn_index INTEGER NOT NULL,
    role VARCHAR(32) NOT NULL,  -- 'user', 'assistant'
    content TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_task_conversations_task_id ON task_conversations(task_id);
```

**1.2 Capture User Messages**

Modify `makima/daemon/src/task/manager.rs`:
- When sending initial plan to Claude, emit a `ConversationTurn` message to server
- When forwarding user messages from `input_rx`, emit a `ConversationTurn` message

**1.3 Capture Assistant Responses**

Modify `makima/src/server/handlers/mesh_daemon.rs`:
- Aggregate `TaskOutputEntry` messages with `message_type='assistant'` into conversation turns
- Store in `task_conversations` table when a user message arrives (marks end of assistant turn)

**1.4 New Protocol Message**

Add to `makima/daemon/src/ws/protocol.rs` and `makima/src/server/protocol.rs`:
```rust
ConversationTurn {
    task_id: Uuid,
    turn_index: i32,
    role: String,  // "user" or "assistant"
    content: String,
}
```

### Phase 2: Branching Infrastructure

**2.1 Database Migration**

Create `makima/migrations/20250111000001_add_branching_fields.sql`:

```sql
ALTER TABLE tasks ADD COLUMN branched_from_task_id UUID REFERENCES tasks(id) ON DELETE SET NULL;
CREATE INDEX idx_tasks_branched_from ON tasks(branched_from_task_id) WHERE branched_from_task_id IS NOT NULL;
```

**2.2 Update Task Model**

Modify `makima/src/db/models.rs`:
```rust
pub struct Task {
    // ... existing fields ...
    pub branched_from_task_id: Option<Uuid>,
}

pub struct BranchTaskRequest {
    pub name: Option<String>,
    pub plan: String,
    pub include_conversation: bool,  // default true
    pub include_worktree: bool,      // default true
    pub contract_id: Option<Uuid>,   // if None, inherit from source task
}
```

**2.3 New Branch Endpoint**

Add to `makima/src/server/handlers/mesh.rs`:
- `POST /api/v1/mesh/tasks/{id}/branch` handler
- Validates source task exists and user has permission
- Fetches conversation history from `task_conversations`
- Creates new task with:
  - `branched_from_task_id` = source task ID
  - `continue_from_task_id` = source task ID (for worktree copying)
  - `contract_id` = request.contract_id OR source task's contract_id
  - Plan = formatted conversation context + new instructions

### Phase 3: Context Injection

**3.1 Format Conversation Transcript**

Add helper function in `makima/src/server/handlers/mesh.rs`:
```rust
fn format_conversation_context(turns: Vec<ConversationTurn>) -> String {
    // Format as:
    // ## Previous Conversation Context
    //
    // **User:** {message}
    // **Assistant:** {response}
    // ...
    //
    // ---
}
```

**3.2 Prepend to Branched Task Plan**

When creating a branched task, construct the plan as:
```
{formatted_conversation_context}

## New Instructions

{user's new plan}
```

### Phase 4: Frontend Integration

**4.1 API Client**

Add to `makima/frontend/src/lib/api.ts`:
```typescript
branchTask(id: string, request: BranchTaskRequest): Promise<Task>
```

**4.2 Branch Button**

Add to `makima/frontend/src/components/mesh/TaskDetail.tsx`:
- "Branch" button in task actions
- Opens dialog to enter new instructions
- Checkboxes for "Include conversation" and "Include file changes"
- Contract selector (defaults to current contract, allows choosing another)

**4.3 Tree Visualization (Optional)**

Show `branched_from_task_id` relationships in task list to visualize the branch tree.

**4.4 Contract Tasks View**

Update `makima/frontend/src/components/contracts/ContractDetail.tsx`:
- Show branched tasks in the Tasks tab with visual indicators
- Display branch relationships (e.g., "Branched from: Task X")

## Files to Modify

### Backend (Server)
- `makima/src/db/models.rs` - Add `BranchTaskRequest`, extend `Task`
- `makima/src/db/repository.rs` - Add conversation CRUD, branch query
- `makima/src/server/handlers/mesh.rs` - Add `branch_task` handler
- `makima/src/server/handlers/mesh_daemon.rs` - Store conversation turns
- `makima/src/server/protocol.rs` - Add `ConversationTurn` message

### Backend (Daemon)
- `makima/daemon/src/ws/protocol.rs` - Add `ConversationTurn` message
- `makima/daemon/src/task/manager.rs` - Emit user messages as conversation turns

### Migrations
- `makima/migrations/20250111000000_add_task_conversations.sql`
- `makima/migrations/20250111000001_add_branching_fields.sql`

### Frontend
- `makima/frontend/src/lib/api.ts` - Add `branchTask()` method and types
- `makima/frontend/src/components/mesh/TaskDetail.tsx` - Add Branch button/dialog
- `makima/frontend/src/components/contracts/ContractDetail.tsx` - Show branch relationships in Tasks tab

## Key Design Decisions

1. **Conversation as context, not replay** - We prepend a transcript to the plan rather than trying to inject messages into Claude Code (which only accepts user messages)

2. **Separate from parent-child hierarchy** - Using `branched_from_task_id` instead of `parent_task_id` to distinguish from orchestrator/subtask relationships

3. **Reuse existing worktree mechanism** - Set `continue_from_task_id` to copy files from source task

4. **Opt-in conversation/worktree** - Both are configurable per-branch request

5. **Contract inheritance** - Branched tasks inherit the source task's contract by default, but can be placed in a different contract if needed (e.g., branching research findings into a new execute-phase contract)