diff options
| author | soryu <soryu@soryu.co> | 2026-01-11 05:52:14 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-15 00:21:16 +0000 |
| commit | 87044a747b47bd83249d61a45842c7f7b2eae56d (patch) | |
| tree | ef2000ce79ffcc2723ef841acef5aa1deb1d5378 /makima/docs | |
| parent | 077820c4167c168072d217a1b01df840463a12a8 (diff) | |
| download | soryu-87044a747b47bd83249d61a45842c7f7b2eae56d.tar.gz soryu-87044a747b47bd83249d61a45842c7f7b2eae56d.zip | |
Contract system
Diffstat (limited to 'makima/docs')
| -rw-r--r-- | makima/docs/PLAN-task-branching.md | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/makima/docs/PLAN-task-branching.md b/makima/docs/PLAN-task-branching.md new file mode 100644 index 0000000..cd35bc6 --- /dev/null +++ b/makima/docs/PLAN-task-branching.md @@ -0,0 +1,197 @@ +# 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) |
