# Resume and History System - Implementation Plan

## Overview

This document provides a detailed, actionable implementation plan for the Resume and History System. The system enables users to view historical conversation data, resume interrupted work, and rewind/restore to previous states in the Makima platform.

**Key Reference Documents:**
- Specification: Resume and History System Specification
- Requirements: Requirements Document
- User Stories: User Stories Document

---

## Phase 1: Database Schema

**Objective:** Create the foundational database structures for storing conversation snapshots, history events, and supporting task forking.

### Task 1.1: Create Database Migrations

**Files to Create:**
- `makima/migrations/20250118000000_history_tables.sql`

**Schema Changes:**

```sql
-- 1. Conversation Snapshots table
-- Stores conversation state at specific points for rewind capability
CREATE TABLE IF NOT EXISTS conversation_snapshots (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    checkpoint_id UUID REFERENCES task_checkpoints(id) ON DELETE SET NULL,
    snapshot_type VARCHAR(50) NOT NULL,  -- 'auto', 'manual', 'checkpoint'
    message_count INTEGER NOT NULL,
    conversation_state JSONB NOT NULL,  -- Full conversation at this point
    metadata JSONB,  -- Additional context (token count, cost, etc.)
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_conversation_snapshots_task ON conversation_snapshots(task_id);
CREATE INDEX idx_conversation_snapshots_checkpoint ON conversation_snapshots(checkpoint_id);
CREATE INDEX idx_conversation_snapshots_created ON conversation_snapshots(created_at DESC);

-- 2. History Events table
-- Unified event stream for timeline views
CREATE TABLE IF NOT EXISTS history_events (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    contract_id UUID REFERENCES contracts(id) ON DELETE CASCADE,
    task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    event_type VARCHAR(50) NOT NULL,  -- 'task', 'chat', 'checkpoint', 'phase', 'file'
    event_subtype VARCHAR(50),  -- Specific event: 'created', 'completed', 'message', etc.
    phase VARCHAR(50),  -- Contract phase when event occurred
    event_data JSONB NOT NULL,  -- Event-specific data
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_history_events_contract ON history_events(contract_id, created_at DESC);
CREATE INDEX idx_history_events_task ON history_events(task_id, created_at DESC);
CREATE INDEX idx_history_events_owner ON history_events(owner_id, created_at DESC);
CREATE INDEX idx_history_events_type ON history_events(event_type, created_at DESC);

-- 3. Alter task_checkpoints - add conversation snapshot reference
ALTER TABLE task_checkpoints
    ADD COLUMN conversation_snapshot_id UUID REFERENCES conversation_snapshots(id) ON DELETE SET NULL;

-- 4. Alter tasks - add forking fields
ALTER TABLE tasks
    ADD COLUMN forked_from_task_id UUID REFERENCES tasks(id) ON DELETE SET NULL,
    ADD COLUMN forked_at_checkpoint_id UUID REFERENCES task_checkpoints(id) ON DELETE SET NULL;

CREATE INDEX idx_tasks_forked_from ON tasks(forked_from_task_id) WHERE forked_from_task_id IS NOT NULL;

-- Comments for documentation
COMMENT ON TABLE conversation_snapshots IS 'Stores conversation state at specific points for rewind/resume capability';
COMMENT ON TABLE history_events IS 'Unified event stream for timeline views across contracts and tasks';
COMMENT ON COLUMN conversation_snapshots.snapshot_type IS 'Type: auto (periodic), manual (user-triggered), checkpoint (at git checkpoint)';
COMMENT ON COLUMN history_events.event_type IS 'Category: task, chat, checkpoint, phase, file';
```

**Complexity:** Medium
**Dependencies:** None
**Estimated Time:** 2-3 hours

---

## Phase 2: Repository Layer

**Objective:** Implement database access functions for conversation snapshots, history events, and enhanced checkpoint operations.

### Task 2.1: Core Models

**Files to Modify:**
- `makima/src/db/models.rs`

**New Types to Add:**

```rust
// ConversationSnapshot model
#[derive(Debug, Clone, FromRow, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ConversationSnapshot {
    pub id: Uuid,
    pub task_id: Uuid,
    pub checkpoint_id: Option<Uuid>,
    pub snapshot_type: String,  // 'auto', 'manual', 'checkpoint'
    pub message_count: i32,
    #[sqlx(json)]
    pub conversation_state: serde_json::Value,
    #[sqlx(json)]
    pub metadata: Option<serde_json::Value>,
    pub created_at: DateTime<Utc>,
}

// HistoryEvent model
#[derive(Debug, Clone, FromRow, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct HistoryEvent {
    pub id: Uuid,
    pub owner_id: Uuid,
    pub contract_id: Option<Uuid>,
    pub task_id: Option<Uuid>,
    pub event_type: String,
    pub event_subtype: Option<String>,
    pub phase: Option<String>,
    #[sqlx(json)]
    pub event_data: serde_json::Value,
    pub created_at: DateTime<Utc>,
}

// Unified ConversationMessage for API responses
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ConversationMessage {
    pub id: String,
    pub role: String,  // 'user', 'assistant', 'system', 'tool'
    pub content: String,
    pub timestamp: DateTime<Utc>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_calls: Option<Vec<ToolCallInfo>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_input: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_result: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_error: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub token_count: Option<i32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cost_usd: Option<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ToolCallInfo {
    pub id: String,
    pub name: String,
    pub input: serde_json::Value,
}

// Query filters for history
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct HistoryQueryFilters {
    pub phase: Option<String>,
    pub event_types: Option<Vec<String>>,
    pub from: Option<DateTime<Utc>>,
    pub to: Option<DateTime<Utc>>,
    pub limit: Option<i32>,
    pub cursor: Option<String>,
}

// Resume request types
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ResumeSupervisorRequest {
    pub target_daemon_id: Option<Uuid>,
    pub resume_mode: String,  // 'continue', 'restart_phase', 'from_checkpoint'
    pub checkpoint_id: Option<Uuid>,
    pub additional_context: Option<String>,
}

#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ResumeFromCheckpointRequest {
    pub task_name: Option<String>,
    pub plan: String,
    pub include_conversation: Option<bool>,
    pub target_daemon_id: Option<Uuid>,
}

// Rewind request types
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct RewindTaskRequest {
    pub checkpoint_id: Option<Uuid>,
    pub checkpoint_sha: Option<String>,
    pub preserve_mode: String,  // 'discard', 'create_branch', 'stash'
    pub branch_name: Option<String>,
}

#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct RewindConversationRequest {
    pub to_message_id: Option<String>,
    pub to_timestamp: Option<DateTime<Utc>>,
    pub by_message_count: Option<i32>,
    pub rewind_code: Option<bool>,
}

// Fork request type
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ForkTaskRequest {
    pub fork_from_type: String,  // 'checkpoint', 'timestamp', 'message_id'
    pub fork_from_value: String,
    pub new_task_name: String,
    pub new_task_plan: String,
    pub include_conversation: Option<bool>,
    pub create_branch: Option<bool>,
    pub branch_name: Option<String>,
}
```

**Complexity:** Medium
**Dependencies:** Phase 1 complete
**Estimated Time:** 2-3 hours

### Task 2.2: Repository Functions

**Files to Modify:**
- `makima/src/db/repository.rs`

**Functions to Add:**

```rust
// ============================================================================
// Conversation Snapshots
// ============================================================================

/// Create a new conversation snapshot
pub async fn create_conversation_snapshot(
    pool: &PgPool,
    task_id: Uuid,
    checkpoint_id: Option<Uuid>,
    snapshot_type: &str,
    message_count: i32,
    conversation_state: serde_json::Value,
    metadata: Option<serde_json::Value>,
) -> Result<ConversationSnapshot, sqlx::Error>

/// Get a conversation snapshot by ID
pub async fn get_conversation_snapshot(
    pool: &PgPool,
    id: Uuid,
) -> Result<Option<ConversationSnapshot>, sqlx::Error>

/// Get conversation snapshot at a specific checkpoint
pub async fn get_conversation_at_checkpoint(
    pool: &PgPool,
    checkpoint_id: Uuid,
) -> Result<Option<ConversationSnapshot>, sqlx::Error>

/// List conversation snapshots for a task
pub async fn list_conversation_snapshots(
    pool: &PgPool,
    task_id: Uuid,
    limit: Option<i32>,
) -> Result<Vec<ConversationSnapshot>, sqlx::Error>

/// Delete conversation snapshots older than retention period
pub async fn cleanup_old_snapshots(
    pool: &PgPool,
    retention_days: i32,
) -> Result<u64, sqlx::Error>

// ============================================================================
// History Events
// ============================================================================

/// Record a new history event
pub async fn record_history_event(
    pool: &PgPool,
    owner_id: Uuid,
    contract_id: Option<Uuid>,
    task_id: Option<Uuid>,
    event_type: &str,
    event_subtype: Option<&str>,
    phase: Option<&str>,
    event_data: serde_json::Value,
) -> Result<HistoryEvent, sqlx::Error>

/// Get contract history timeline
pub async fn get_contract_history(
    pool: &PgPool,
    contract_id: Uuid,
    owner_id: Uuid,
    filters: &HistoryQueryFilters,
) -> Result<(Vec<HistoryEvent>, i64), sqlx::Error>

/// Get task history
pub async fn get_task_history(
    pool: &PgPool,
    task_id: Uuid,
    owner_id: Uuid,
    filters: &HistoryQueryFilters,
) -> Result<(Vec<HistoryEvent>, i64), sqlx::Error>

/// Get unified timeline for an owner
pub async fn get_timeline(
    pool: &PgPool,
    owner_id: Uuid,
    filters: &HistoryQueryFilters,
) -> Result<(Vec<HistoryEvent>, i64), sqlx::Error>

// ============================================================================
// Task Conversation Retrieval
// ============================================================================

/// Get task conversation messages (reconstructed from task_events)
pub async fn get_task_conversation(
    pool: &PgPool,
    task_id: Uuid,
    include_tool_calls: bool,
    include_tool_results: bool,
    limit: Option<i32>,
) -> Result<Vec<ConversationMessage>, sqlx::Error>

/// Get supervisor conversation (from supervisor_states)
pub async fn get_supervisor_conversation(
    pool: &PgPool,
    contract_id: Uuid,
) -> Result<Option<(SupervisorState, Vec<TaskSummary>)>, sqlx::Error>

// ============================================================================
// Checkpoint Operations
// ============================================================================

/// Create checkpoint with conversation snapshot
pub async fn create_checkpoint_with_snapshot(
    pool: &PgPool,
    task_id: Uuid,
    checkpoint_number: i32,
    commit_sha: &str,
    branch_name: &str,
    message: &str,
    files_changed: Option<serde_json::Value>,
    lines_added: Option<i32>,
    lines_removed: Option<i32>,
    conversation_state: serde_json::Value,
) -> Result<(TaskCheckpoint, ConversationSnapshot), sqlx::Error>

/// Get checkpoint diff information (requires daemon interaction for actual diff)
pub async fn get_checkpoint_info(
    pool: &PgPool,
    checkpoint_id: Uuid,
) -> Result<Option<(TaskCheckpoint, Option<TaskCheckpoint>)>, sqlx::Error>

// ============================================================================
// Fork Operations
// ============================================================================

/// Create forked task
pub async fn create_forked_task(
    pool: &PgPool,
    owner_id: Uuid,
    source_task_id: Uuid,
    checkpoint_id: Option<Uuid>,
    req: &CreateTaskRequest,
) -> Result<Task, sqlx::Error>
```

**Complexity:** Complex
**Dependencies:** Task 2.1 complete
**Estimated Time:** 4-5 hours

---

## Phase 3: API Endpoints

**Objective:** Implement REST API endpoints for history viewing, resume operations, and rewind/fork functionality.

### Task 3.1: History Endpoints

**Files to Create/Modify:**
- `makima/src/server/handlers/history.rs` (new file)
- `makima/src/server/handlers/mod.rs` (add module)
- `makima/src/server/mod.rs` (add routes)

**Endpoints to Implement:**

| Method | Path | Handler Function |
|--------|------|------------------|
| GET | `/api/v1/contracts/{id}/history` | `get_contract_history` |
| GET | `/api/v1/contracts/{id}/supervisor/conversation` | `get_supervisor_conversation` |
| GET | `/api/v1/mesh/tasks/{id}/conversation` | `get_task_conversation` |
| GET | `/api/v1/mesh/tasks/{id}/checkpoints/{cid}/diff` | `get_checkpoint_diff` |
| GET | `/api/v1/timeline` | `get_timeline` |

**Implementation Details:**

```rust
// makima/src/server/handlers/history.rs

/// GET /api/v1/contracts/{id}/history
/// Returns contract history timeline with filtering and pagination
#[utoipa::path(
    get,
    path = "/api/v1/contracts/{id}/history",
    params(
        ("id" = Uuid, Path, description = "Contract ID"),
        HistoryQueryFilters
    ),
    responses(
        (status = 200, body = ContractHistoryResponse),
        (status = 404, description = "Contract not found"),
    ),
    tag = "history"
)]
pub async fn get_contract_history(
    State(state): State<AppState>,
    Path(contract_id): Path<Uuid>,
    Query(filters): Query<HistoryQueryFilters>,
    auth: AuthenticatedUser,
) -> Result<Json<ContractHistoryResponse>, ApiError>

/// GET /api/v1/contracts/{id}/supervisor/conversation
/// Returns full supervisor conversation with spawned task references
#[utoipa::path(
    get,
    path = "/api/v1/contracts/{id}/supervisor/conversation",
    responses(
        (status = 200, body = SupervisorConversationResponse),
        (status = 404, description = "Supervisor not found"),
    ),
    tag = "history"
)]
pub async fn get_supervisor_conversation(
    State(state): State<AppState>,
    Path(contract_id): Path<Uuid>,
    auth: AuthenticatedUser,
) -> Result<Json<SupervisorConversationResponse>, ApiError>

/// GET /api/v1/mesh/tasks/{id}/conversation
/// Returns task conversation history
#[utoipa::path(
    get,
    path = "/api/v1/mesh/tasks/{id}/conversation",
    params(
        ("id" = Uuid, Path, description = "Task ID"),
        ("include_tool_calls" = Option<bool>, Query),
        ("include_tool_results" = Option<bool>, Query),
        ("limit" = Option<i32>, Query),
    ),
    responses(
        (status = 200, body = TaskConversationResponse),
        (status = 404, description = "Task not found"),
    ),
    tag = "history"
)]
pub async fn get_task_conversation(
    State(state): State<AppState>,
    Path(task_id): Path<Uuid>,
    Query(params): Query<TaskConversationParams>,
    auth: AuthenticatedUser,
) -> Result<Json<TaskConversationResponse>, ApiError>

/// GET /api/v1/mesh/tasks/{id}/checkpoints/{cid}/diff
/// Returns checkpoint diff (delegates to daemon for git diff)
pub async fn get_checkpoint_diff(
    State(state): State<AppState>,
    Path((task_id, checkpoint_id)): Path<(Uuid, Uuid)>,
    auth: AuthenticatedUser,
) -> Result<Json<CheckpointDiffResponse>, ApiError>

/// GET /api/v1/timeline
/// Returns unified timeline for authenticated user
pub async fn get_timeline(
    State(state): State<AppState>,
    Query(filters): Query<TimelineQueryFilters>,
    auth: AuthenticatedUser,
) -> Result<Json<TimelineResponse>, ApiError>
```

**Complexity:** Medium
**Dependencies:** Phase 2 complete
**Estimated Time:** 4-5 hours

### Task 3.2: Resume Endpoints

**Files to Modify:**
- `makima/src/server/handlers/mesh_supervisor.rs`
- `makima/src/server/handlers/mesh.rs`

**Endpoints to Implement:**

| Method | Path | Handler Function |
|--------|------|------------------|
| POST | `/api/v1/contracts/{id}/supervisor/resume` | `resume_supervisor` |
| POST | `/api/v1/mesh/tasks/{id}/checkpoints/{cid}/resume` | `resume_from_checkpoint` |
| POST | `/api/v1/mesh/tasks/{id}/continue` | `continue_task` (enhanced) |

**Implementation Details:**

```rust
// makima/src/server/handlers/mesh_supervisor.rs

/// POST /api/v1/contracts/{id}/supervisor/resume
/// Resume interrupted supervisor with specified mode
#[utoipa::path(
    post,
    path = "/api/v1/contracts/{id}/supervisor/resume",
    request_body = ResumeSupervisorRequest,
    responses(
        (status = 200, body = ResumeSupervisorResponse),
        (status = 404, description = "Contract/supervisor not found"),
        (status = 409, description = "Supervisor already running"),
    ),
    tag = "supervisor"
)]
pub async fn resume_supervisor(
    State(state): State<AppState>,
    Path(contract_id): Path<Uuid>,
    auth: AuthenticatedUser,
    Json(req): Json<ResumeSupervisorRequest>,
) -> Result<Json<ResumeSupervisorResponse>, ApiError>

// makima/src/server/handlers/mesh.rs

/// POST /api/v1/mesh/tasks/{id}/checkpoints/{cid}/resume
/// Create new task starting from specific checkpoint
#[utoipa::path(
    post,
    path = "/api/v1/mesh/tasks/{id}/checkpoints/{cid}/resume",
    request_body = ResumeFromCheckpointRequest,
    responses(
        (status = 201, body = ResumeFromCheckpointResponse),
        (status = 404, description = "Task/checkpoint not found"),
    ),
    tag = "mesh"
)]
pub async fn resume_from_checkpoint(
    State(state): State<AppState>,
    Path((task_id, checkpoint_id)): Path<(Uuid, Uuid)>,
    auth: AuthenticatedUser,
    Json(req): Json<ResumeFromCheckpointRequest>,
) -> Result<Json<ResumeFromCheckpointResponse>, ApiError>

/// POST /api/v1/mesh/tasks/{id}/continue (enhanced)
/// Enhanced with resume mode and context options
pub async fn continue_task(
    State(state): State<AppState>,
    Path(task_id): Path<Uuid>,
    auth: AuthenticatedUser,
    Json(req): Json<ContinueTaskRequest>,  // Enhanced request type
) -> Result<Json<Task>, ApiError>
```

**Complexity:** Complex
**Dependencies:** Task 3.1 complete
**Estimated Time:** 5-6 hours

### Task 3.3: Rewind and Fork Endpoints

**Files to Modify:**
- `makima/src/server/handlers/mesh.rs`
- `makima/src/server/handlers/mesh_supervisor.rs`

**Endpoints to Implement:**

| Method | Path | Handler Function |
|--------|------|------------------|
| POST | `/api/v1/mesh/tasks/{id}/rewind` | `rewind_task` |
| POST | `/api/v1/contracts/{id}/supervisor/conversation/rewind` | `rewind_conversation` |
| POST | `/api/v1/mesh/tasks/{id}/fork` | `fork_task` |
| POST | `/api/v1/mesh/tasks/{id}/checkpoints/{cid}/branch` | `branch_from_checkpoint` |

**Implementation Details:**

```rust
// makima/src/server/handlers/mesh.rs

/// POST /api/v1/mesh/tasks/{id}/rewind
/// Rewind task code to specified checkpoint
#[utoipa::path(
    post,
    path = "/api/v1/mesh/tasks/{id}/rewind",
    request_body = RewindTaskRequest,
    responses(
        (status = 200, body = RewindTaskResponse),
        (status = 404, description = "Task/checkpoint not found"),
        (status = 409, description = "Task is running"),
    ),
    tag = "mesh"
)]
pub async fn rewind_task(
    State(state): State<AppState>,
    Path(task_id): Path<Uuid>,
    auth: AuthenticatedUser,
    Json(req): Json<RewindTaskRequest>,
) -> Result<Json<RewindTaskResponse>, ApiError>

/// POST /api/v1/mesh/tasks/{id}/fork
/// Fork task from historical point
#[utoipa::path(
    post,
    path = "/api/v1/mesh/tasks/{id}/fork",
    request_body = ForkTaskRequest,
    responses(
        (status = 201, body = ForkTaskResponse),
        (status = 404, description = "Task not found"),
    ),
    tag = "mesh"
)]
pub async fn fork_task(
    State(state): State<AppState>,
    Path(task_id): Path<Uuid>,
    auth: AuthenticatedUser,
    Json(req): Json<ForkTaskRequest>,
) -> Result<Json<ForkTaskResponse>, ApiError>

/// POST /api/v1/mesh/tasks/{id}/checkpoints/{cid}/branch
/// Create git branch from checkpoint without starting task
pub async fn branch_from_checkpoint(
    State(state): State<AppState>,
    Path((task_id, checkpoint_id)): Path<(Uuid, Uuid)>,
    auth: AuthenticatedUser,
    Json(req): Json<CreateBranchFromCheckpointRequest>,
) -> Result<Json<BranchCreatedResponse>, ApiError>

// makima/src/server/handlers/mesh_supervisor.rs

/// POST /api/v1/contracts/{id}/supervisor/conversation/rewind
/// Rewind supervisor conversation to specified point
pub async fn rewind_conversation(
    State(state): State<AppState>,
    Path(contract_id): Path<Uuid>,
    auth: AuthenticatedUser,
    Json(req): Json<RewindConversationRequest>,
) -> Result<Json<RewindConversationResponse>, ApiError>
```

**Complexity:** Complex
**Dependencies:** Task 3.2 complete
**Estimated Time:** 5-6 hours

---

## Phase 4: CLI Commands

**Objective:** Implement command-line interface for history viewing, resume, and rewind operations.

### Task 4.1: History Commands

**Files to Modify:**
- `makima/src/daemon/cli/mod.rs`
- `makima/src/daemon/cli/contract.rs`
- `makima/src/daemon/cli/supervisor.rs`

**New Commands:**

```rust
// makima/src/daemon/cli/mod.rs

/// Contract subcommands - add history commands
#[derive(Subcommand, Debug)]
pub enum ContractCommand {
    // ... existing commands ...

    /// View contract history timeline
    History(contract::HistoryArgs),
}

/// Supervisor subcommands - add history and resume commands
#[derive(Subcommand, Debug)]
pub enum SupervisorCommand {
    // ... existing commands ...

    /// View task conversation history
    TaskHistory(supervisor::TaskHistoryArgs),

    /// List checkpoints with details
    CheckpointList(supervisor::CheckpointListArgs),

    /// View checkpoint diff
    CheckpointDiff(supervisor::CheckpointDiffArgs),

    /// Resume supervisor after interruption
    Resume(supervisor::ResumeArgs),
}
```

**Implementation - Contract History:**

```rust
// makima/src/daemon/cli/contract.rs

#[derive(Args, Debug)]
pub struct HistoryArgs {
    /// Filter by phase (research, specify, plan, execute, review)
    #[arg(long)]
    pub phase: Option<String>,

    /// Filter from date (ISO 8601 format)
    #[arg(long)]
    pub from: Option<String>,

    /// Filter to date (ISO 8601 format)
    #[arg(long)]
    pub to: Option<String>,

    /// Maximum entries to return
    #[arg(long, default_value = "50")]
    pub limit: i32,

    /// Output format (table, json)
    #[arg(long, default_value = "table")]
    pub format: String,
}

pub async fn handle_history(args: &HistoryArgs) -> Result<()> {
    // 1. Get contract context from environment
    // 2. Call /api/v1/contracts/{id}/history with filters
    // 3. Format and display results
}
```

**Implementation - Task History:**

```rust
// makima/src/daemon/cli/supervisor.rs

#[derive(Args, Debug)]
pub struct TaskHistoryArgs {
    /// Task ID to view history for
    pub task_id: Uuid,

    /// Include tool calls in output
    #[arg(long, default_value = "true")]
    pub tool_calls: bool,

    /// Maximum messages to return
    #[arg(long)]
    pub limit: Option<i32>,

    /// Output format (table, json, chat)
    #[arg(long, default_value = "chat")]
    pub format: String,
}

pub async fn handle_task_history(args: &TaskHistoryArgs) -> Result<()> {
    // 1. Call /api/v1/mesh/tasks/{id}/conversation
    // 2. Format as chat-style output or JSON
}

#[derive(Args, Debug)]
pub struct CheckpointListArgs {
    /// Task ID to list checkpoints for
    pub task_id: Uuid,

    /// Include diff summary
    #[arg(long)]
    pub with_diff: bool,
}

#[derive(Args, Debug)]
pub struct CheckpointDiffArgs {
    /// Task ID
    pub task_id: Uuid,

    /// Checkpoint number
    pub checkpoint_number: i32,
}
```

**Complexity:** Medium
**Dependencies:** Phase 3 complete
**Estimated Time:** 3-4 hours

### Task 4.2: Resume and Rewind Commands

**Files to Modify:**
- `makima/src/daemon/cli/supervisor.rs`
- `makima/src/daemon/cli/contract.rs`

**New Commands:**

```rust
// makima/src/daemon/cli/supervisor.rs

#[derive(Args, Debug)]
pub struct ResumeArgs {
    /// Resume mode: continue, restart_phase, from_checkpoint
    #[arg(long, default_value = "continue")]
    pub mode: String,

    /// Checkpoint ID (required for from_checkpoint mode)
    #[arg(long)]
    pub checkpoint: Option<Uuid>,

    /// Additional context to inject
    #[arg(long)]
    pub context: Option<String>,
}

pub async fn handle_resume(args: &ResumeArgs) -> Result<()> {
    // 1. Get contract context
    // 2. Call /api/v1/contracts/{id}/supervisor/resume
    // 3. Display result and new supervisor task info
}

#[derive(Args, Debug)]
pub struct TaskResumeArgs {
    /// Task ID to resume
    pub task_id: Uuid,

    /// Resume mode: with_context, clean_restart, from_checkpoint
    #[arg(long, default_value = "with_context")]
    pub mode: String,

    /// Checkpoint SHA (for from_checkpoint mode)
    #[arg(long)]
    pub checkpoint: Option<String>,
}

#[derive(Args, Debug)]
pub struct TaskResumeFromArgs {
    /// Source task ID
    pub task_id: Uuid,

    /// Checkpoint number to resume from
    #[arg(long)]
    pub checkpoint: i32,

    /// Plan for the new task
    #[arg(long)]
    pub plan: String,

    /// Name for the new task
    #[arg(long)]
    pub name: Option<String>,
}

#[derive(Args, Debug)]
pub struct TaskRewindArgs {
    /// Task ID to rewind
    pub task_id: Uuid,

    /// Checkpoint number to rewind to
    #[arg(long)]
    pub checkpoint: i32,

    /// Preserve mode: discard, create_branch, stash
    #[arg(long, default_value = "create_branch")]
    pub preserve: String,

    /// Branch name (for create_branch mode)
    #[arg(long)]
    pub branch_name: Option<String>,
}

#[derive(Args, Debug)]
pub struct TaskForkArgs {
    /// Source task ID
    pub task_id: Uuid,

    /// Checkpoint number to fork from
    #[arg(long)]
    pub checkpoint: i32,

    /// Name for the new task
    #[arg(long)]
    pub name: String,

    /// Plan for the new task
    #[arg(long)]
    pub plan: String,

    /// Include conversation history
    #[arg(long, default_value = "true")]
    pub include_conversation: bool,
}

#[derive(Args, Debug)]
pub struct ConversationRewindArgs {
    /// Number of messages to rewind
    #[arg(long)]
    pub by_messages: Option<i32>,

    /// Message ID to rewind to
    #[arg(long)]
    pub to_message: Option<String>,

    /// Also rewind code to matching checkpoint
    #[arg(long)]
    pub rewind_code: bool,
}
```

**Update CLI Commands enum:**

```rust
// makima/src/daemon/cli/mod.rs

#[derive(Subcommand, Debug)]
pub enum SupervisorCommand {
    // ... existing commands ...

    /// Resume supervisor after interruption
    Resume(supervisor::ResumeArgs),

    /// Resume task with context
    TaskResume(supervisor::TaskResumeArgs),

    /// Resume from specific checkpoint
    TaskResumeFrom(supervisor::TaskResumeFromArgs),

    /// Rewind task code to checkpoint
    TaskRewind(supervisor::TaskRewindArgs),

    /// Fork task from historical point
    TaskFork(supervisor::TaskForkArgs),

    /// Rewind supervisor conversation
    RewindConversation(supervisor::ConversationRewindArgs),
}
```

**Complexity:** Medium
**Dependencies:** Task 4.1 complete
**Estimated Time:** 4-5 hours

---

## Phase 5: Daemon Integration

**Objective:** Extend daemon protocol and handlers to support rewind operations and conversation snapshots.

### Task 5.1: Protocol Extensions

**Files to Modify:**
- `makima/src/daemon/ws/protocol.rs`
- `makima/src/server/protocol.rs` (if separate)

**New Commands to Add:**

```rust
// makima/src/daemon/ws/protocol.rs

/// Command from server to daemon
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum DaemonCommand {
    // ... existing commands ...

    /// Rewind task worktree to a specific checkpoint
    RewindToCheckpoint {
        #[serde(rename = "taskId")]
        task_id: Uuid,
        #[serde(rename = "checkpointSha")]
        checkpoint_sha: String,
        /// How to preserve current state: 'discard', 'create_branch', 'stash'
        #[serde(rename = "preserveMode")]
        preserve_mode: String,
        /// Branch name for create_branch mode
        #[serde(rename = "branchName")]
        branch_name: Option<String>,
    },

    /// Create a conversation snapshot for a task
    CreateConversationSnapshot {
        #[serde(rename = "taskId")]
        task_id: Uuid,
    },

    /// Get git diff between two commits
    GetCheckpointDiff {
        #[serde(rename = "taskId")]
        task_id: Uuid,
        /// SHA of the checkpoint to diff
        #[serde(rename = "checkpointSha")]
        checkpoint_sha: String,
        /// SHA of the previous checkpoint (for comparison)
        #[serde(rename = "previousSha")]
        previous_sha: Option<String>,
    },
}

/// Message from daemon to server
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum DaemonMessage {
    // ... existing messages ...

    /// Response to RewindToCheckpoint command
    RewindResult {
        #[serde(rename = "taskId")]
        task_id: Uuid,
        success: bool,
        message: String,
        /// Reference to preserved state (branch name or stash ref)
        #[serde(rename = "preservedAs")]
        preserved_as: Option<PreservedState>,
    },

    /// Response to CreateConversationSnapshot command
    ConversationSnapshotCreated {
        #[serde(rename = "taskId")]
        task_id: Uuid,
        #[serde(rename = "snapshotId")]
        snapshot_id: Uuid,
        #[serde(rename = "messageCount")]
        message_count: i32,
    },

    /// Response to GetCheckpointDiff command
    CheckpointDiffResult {
        #[serde(rename = "taskId")]
        task_id: Uuid,
        success: bool,
        diff: Option<GitDiffInfo>,
        error: Option<String>,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PreservedState {
    /// Type: 'branch' or 'stash'
    #[serde(rename = "type")]
    pub state_type: String,
    /// Branch name or stash reference
    pub reference: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GitDiffInfo {
    pub files: Vec<FileDiffInfo>,
    pub stats: DiffStats,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FileDiffInfo {
    pub path: String,
    /// Action: 'added', 'modified', 'deleted'
    pub action: String,
    pub additions: i32,
    pub deletions: i32,
    /// Diff hunks (optional, may be truncated for large files)
    pub hunks: Option<Vec<DiffHunk>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DiffHunk {
    pub header: String,
    pub lines: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DiffStats {
    pub files_changed: i32,
    pub insertions: i32,
    pub deletions: i32,
}
```

**Complexity:** Medium
**Dependencies:** None (can be done in parallel with Phase 3-4)
**Estimated Time:** 2-3 hours

### Task 5.2: Daemon Handlers

**Files to Modify:**
- `makima/src/daemon/task/manager.rs`
- `makima/src/daemon/worktree/manager.rs`

**Handlers to Implement:**

```rust
// makima/src/daemon/task/manager.rs

impl TaskManager {
    /// Handle rewind to checkpoint command
    pub async fn handle_rewind_to_checkpoint(
        &mut self,
        task_id: Uuid,
        checkpoint_sha: &str,
        preserve_mode: &str,
        branch_name: Option<&str>,
    ) -> Result<RewindResult, DaemonError> {
        // 1. Validate task exists and is not running
        // 2. Get worktree path for task
        // 3. Based on preserve_mode:
        //    - 'discard': git reset --hard {sha}
        //    - 'create_branch': git branch {name} && git reset --hard {sha}
        //    - 'stash': git stash && git reset --hard {sha}
        // 4. Return result with preserved reference
    }

    /// Handle conversation snapshot creation
    pub async fn handle_create_conversation_snapshot(
        &mut self,
        task_id: Uuid,
    ) -> Result<SnapshotResult, DaemonError> {
        // 1. Get task state including conversation
        // 2. Send to server for storage
        // 3. Return snapshot ID
    }

    /// Handle checkpoint diff request
    pub async fn handle_get_checkpoint_diff(
        &mut self,
        task_id: Uuid,
        checkpoint_sha: &str,
        previous_sha: Option<&str>,
    ) -> Result<GitDiffInfo, DaemonError> {
        // 1. Get worktree path for task
        // 2. Run git diff command
        // 3. Parse and return diff info
    }
}
```

**Files to Modify:**
- `makima/src/daemon/worktree/manager.rs`

**Helper Functions:**

```rust
// makima/src/daemon/worktree/manager.rs

impl WorktreeManager {
    /// Reset worktree to specific commit
    pub async fn reset_to_commit(
        &self,
        worktree_path: &Path,
        commit_sha: &str,
    ) -> Result<(), WorktreeError>

    /// Create branch from current state
    pub async fn create_branch(
        &self,
        worktree_path: &Path,
        branch_name: &str,
    ) -> Result<(), WorktreeError>

    /// Stash current changes
    pub async fn stash_changes(
        &self,
        worktree_path: &Path,
    ) -> Result<String, WorktreeError>  // Returns stash ref

    /// Get diff between two commits
    pub async fn get_diff(
        &self,
        worktree_path: &Path,
        from_sha: &str,
        to_sha: &str,
    ) -> Result<String, WorktreeError>

    /// Parse git diff output into structured format
    pub fn parse_diff(diff_output: &str) -> Result<GitDiffInfo, ParseError>
}
```

**Complexity:** Complex
**Dependencies:** Task 5.1 complete
**Estimated Time:** 4-5 hours

### Task 5.3: Checkpoint Enhancement

**Files to Modify:**
- `makima/src/daemon/task/manager.rs`
- `makima/src/server/handlers/mesh_daemon.rs`

**Changes:**

1. **Update checkpoint creation to include conversation state:**

```rust
// When creating a checkpoint, also capture current conversation
pub async fn create_checkpoint_with_conversation(
    &mut self,
    task_id: Uuid,
    message: &str,
) -> Result<(TaskCheckpoint, ConversationSnapshot), DaemonError> {
    // 1. Create git commit (existing logic)
    // 2. Capture current conversation state
    // 3. Create checkpoint record with snapshot reference
}
```

2. **Update task spawning to handle fork/resume scenarios:**

```rust
// When spawning task with forked_from_task_id or checkpoint_sha:
// - If checkpoint_sha: create worktree at that specific commit
// - If include_conversation: inject conversation history into plan
```

**Complexity:** Medium
**Dependencies:** Task 5.2 complete
**Estimated Time:** 3-4 hours

---

## Implementation Summary

### Phase Dependencies

```
Phase 1 (Database)
    └─> Phase 2 (Repository)
            └─> Phase 3 (API Endpoints)
                    └─> Phase 4 (CLI Commands)

Phase 5 (Daemon) can be done in parallel with Phases 3-4
```

### Estimated Total Time

| Phase | Tasks | Estimated Hours |
|-------|-------|-----------------|
| Phase 1: Database Schema | 1 task | 2-3 hours |
| Phase 2: Repository Layer | 2 tasks | 6-8 hours |
| Phase 3: API Endpoints | 3 tasks | 14-17 hours |
| Phase 4: CLI Commands | 2 tasks | 7-9 hours |
| Phase 5: Daemon Integration | 3 tasks | 9-12 hours |
| **Total** | **11 tasks** | **38-49 hours** |

### Task Breakdown by Complexity

| Complexity | Count | Tasks |
|------------|-------|-------|
| Simple | 1 | Phase 1 Migration |
| Medium | 6 | Models, History Endpoints, CLI History, CLI Resume, Protocol, Checkpoint Enhancement |
| Complex | 4 | Repository Functions, Resume Endpoints, Rewind/Fork Endpoints, Daemon Handlers |

### Files to Create

1. `makima/migrations/20250118000000_history_tables.sql`
2. `makima/src/server/handlers/history.rs`

### Files to Modify

**Database Layer:**
- `makima/src/db/models.rs`
- `makima/src/db/repository.rs`

**API Layer:**
- `makima/src/server/handlers/mod.rs`
- `makima/src/server/handlers/mesh.rs`
- `makima/src/server/handlers/mesh_supervisor.rs`
- `makima/src/server/mod.rs`

**CLI Layer:**
- `makima/src/daemon/cli/mod.rs`
- `makima/src/daemon/cli/contract.rs`
- `makima/src/daemon/cli/supervisor.rs`

**Daemon Layer:**
- `makima/src/daemon/ws/protocol.rs`
- `makima/src/daemon/task/manager.rs`
- `makima/src/daemon/worktree/manager.rs`
- `makima/src/server/handlers/mesh_daemon.rs`

---

## Testing Strategy

### Unit Tests
- Repository functions: CRUD operations for snapshots and events
- Model serialization/deserialization
- Diff parsing functions

### Integration Tests
- API endpoint tests with mock database
- CLI command execution tests
- Daemon command handling tests

### End-to-End Tests
- Complete workflow: Create task -> Checkpoint -> Rewind -> Resume
- Fork workflow: Create task -> Checkpoint -> Fork -> Verify state
- History viewing across contract lifecycle

### Manual Testing Checklist
- [ ] Create conversation snapshot at checkpoint
- [ ] View contract history timeline with filters
- [ ] View task conversation history
- [ ] Resume interrupted supervisor (all modes)
- [ ] Resume task from specific checkpoint
- [ ] Rewind code with branch preservation
- [ ] Rewind conversation to message
- [ ] Fork task from checkpoint
- [ ] CLI commands output correctly formatted

---

## Security Considerations

1. **Owner verification**: All operations verify owner_id authorization
2. **Tool key authentication**: Supervisor operations require valid tool keys
3. **Data isolation**: Users cannot access other users' history
4. **Audit logging**: Log all rewind/fork operations for traceability

## Performance Considerations

1. **Pagination**: All list endpoints support cursor-based pagination
2. **Index usage**: Queries use appropriate indexes (contract_id, task_id, created_at)
3. **Snapshot cleanup**: Implement retention policy for old snapshots
4. **Response limits**: Cap response sizes for conversation history
