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