# Contract Management System Specification

**Version**: 1.0.0
**Status**: Draft
**Author**: AI Assistant
**Date**: 2025-01-31

## Executive Summary

This specification addresses critical issues in the current contract management system:

1. **Manual Completion Required** - Contracts stay 'active' indefinitely
2. **No Phase Readiness Validation** - No automatic checking before phase advancement
3. **Supervisor State Restoration Broken** - Context lost after daemon crash
4. **Version Conflicts Silent** - Phase changes can fail silently
5. **No Deliverable Validation** - Can mark non-existent deliverables as complete
6. **Phase Guard Supervisor Bypass** - Supervisors can bypass phase_guard setting

---

## 1. Contract Lifecycle State Machine

### 1.1 Current State (ContractStatus)

The current implementation uses three states:
- `active` - Contract is being worked on
- `completed` - Contract finished successfully
- `archived` - Contract archived (soft delete)

### 1.2 Proposed State Machine

```
                    ┌─────────────────────────────────────────────┐
                    │                                             │
                    ▼                                             │
┌────────┐    ┌─────────┐    ┌──────────────────┐    ┌────────────┴───┐
│ created ├───►│ active  ├───►│ waiting_for_input├───►│ completing     │
└────────┘    └────┬────┘    └────────┬─────────┘    └───────┬────────┘
                   │                  │                       │
                   │                  │                       ▼
                   │                  │               ┌───────────────┐
                   │                  │               │  completed    │
                   │                  │               └───────────────┘
                   │                  │                       │
                   ▼                  ▼                       ▼
              ┌─────────┐      ┌──────────┐          ┌───────────────┐
              │ paused  │      │ blocked  │          │  archived     │
              └────┬────┘      └────┬─────┘          └───────────────┘
                   │                │                       ▲
                   └────────────────┴───────────────────────┤
                                                            │
                   ┌────────┐                               │
                   │ failed ├───────────────────────────────┘
                   └────────┘
```

### 1.3 State Definitions

```rust
/// Contract lifecycle states
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ContractStatus {
    /// Contract created but not yet started
    Created,
    /// Contract is actively being worked on
    Active,
    /// Waiting for user input (phase confirmation, question, etc.)
    WaitingForInput,
    /// Contract is paused by user request
    Paused,
    /// Contract is blocked on external dependency
    Blocked,
    /// All phases complete, running final validation
    Completing,
    /// Contract completed successfully
    Completed,
    /// Contract failed with errors
    Failed,
    /// Contract archived (soft delete)
    Archived,
}
```

### 1.4 State Transitions

| From State | To State | Guard Conditions | Trigger |
|------------|----------|------------------|---------|
| Created | Active | Has supervisor task | Supervisor starts |
| Active | WaitingForInput | Pending question exists | Supervisor asks question |
| Active | Paused | - | User requests pause |
| Active | Blocked | Has external blocker | Blocker detected |
| Active | Completing | Final phase, all deliverables met | Auto-completion check |
| WaitingForInput | Active | Question answered | User responds |
| WaitingForInput | Paused | - | Timeout or user pause |
| Paused | Active | - | User resumes |
| Blocked | Active | Blocker resolved | Blocker cleared |
| Completing | Completed | All cleanup done | Completion confirmed |
| Completing | Active | Completion rejected | User rejects |
| Any | Failed | Unrecoverable error | Error detected |
| Completed | Archived | - | User archives |
| Failed | Archived | - | User archives |

### 1.5 Timeout and Stale Detection

```rust
/// Configuration for contract timeout and stale detection
pub struct ContractTimeoutConfig {
    /// Time after last supervisor activity before contract is considered stale
    pub stale_threshold: Duration,  // Default: 30 minutes

    /// Time to wait for user input before timing out
    pub input_timeout: Duration,  // Default: 24 hours

    /// Time before completing contracts are auto-completed
    pub completion_grace_period: Duration,  // Default: 5 minutes

    /// Time before archived contracts are deleted
    pub archive_retention: Duration,  // Default: 30 days
}

impl Default for ContractTimeoutConfig {
    fn default() -> Self {
        Self {
            stale_threshold: Duration::from_secs(30 * 60),
            input_timeout: Duration::from_secs(24 * 60 * 60),
            completion_grace_period: Duration::from_secs(5 * 60),
            archive_retention: Duration::from_secs(30 * 24 * 60 * 60),
        }
    }
}
```

### 1.6 Database Schema Changes

```sql
-- Add new status column options and tracking fields
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    status_changed_at TIMESTAMPTZ DEFAULT NOW();

-- Track last activity for stale detection
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    last_activity_at TIMESTAMPTZ DEFAULT NOW();

-- Track pending input
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    waiting_for TEXT;  -- 'question', 'phase_confirmation', 'completion_confirmation'

-- Track blockers
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    blocked_reason TEXT;

-- Track failure reason
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    failure_reason TEXT;

-- Index for status queries
CREATE INDEX idx_contracts_status ON contracts(status);
CREATE INDEX idx_contracts_last_activity ON contracts(last_activity_at);
```

### 1.7 API Changes

```rust
/// Request to change contract state
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChangeStatusRequest {
    pub target_status: ContractStatus,
    /// Required for some transitions
    pub reason: Option<String>,
    /// For blocking states, what is blocking
    pub blocker: Option<String>,
}

/// Response for status change
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ChangeStatusResponse {
    pub success: bool,
    pub previous_status: ContractStatus,
    pub new_status: ContractStatus,
    /// If transition failed, why
    pub rejection_reason: Option<String>,
}
```

---

## 2. Automatic Completion Detection

### 2.1 Current Problem

Contracts currently require manual `supervisor_complete()` calls. Supervisors may exit without completing contracts, leaving them active indefinitely.

### 2.2 Proposed Solution: Completion Gates

#### 2.2.1 Phase Completion Gates

```rust
/// Gate that must be satisfied before advancing to next phase
pub struct PhaseCompletionGate {
    /// Required deliverables for this phase
    pub required_deliverables: Vec<String>,
    /// Required tasks to be completed
    pub required_tasks: TaskRequirement,
    /// Optional custom validation function
    pub custom_validator: Option<Box<dyn Fn(&Contract) -> bool>>,
    /// Whether to auto-advance when gate is satisfied
    pub auto_advance: bool,
}

/// Task completion requirements
pub enum TaskRequirement {
    /// No task requirements
    None,
    /// All spawned tasks must complete
    AllComplete,
    /// At least N tasks must complete
    MinComplete(usize),
    /// Specific named tasks must complete
    NamedTasks(Vec<String>),
}
```

#### 2.2.2 Contract Completion Detection

```rust
/// Contract completion detector
pub struct CompletionDetector {
    /// Phase-specific gates
    phase_gates: HashMap<String, PhaseCompletionGate>,
}

impl CompletionDetector {
    /// Check if current phase is ready to advance
    pub fn check_phase_readiness(
        &self,
        contract: &Contract,
        tasks: &[TaskSummary],
    ) -> PhaseReadinessResult {
        let gate = match self.phase_gates.get(&contract.phase) {
            Some(g) => g,
            None => return PhaseReadinessResult::NoGate,
        };

        let mut missing = Vec::new();

        // Check deliverables
        let completed = contract.get_completed_deliverables(&contract.phase);
        for req in &gate.required_deliverables {
            if !completed.contains(req) {
                missing.push(format!("Deliverable: {}", req));
            }
        }

        // Check tasks
        match &gate.required_tasks {
            TaskRequirement::None => {},
            TaskRequirement::AllComplete => {
                let incomplete = tasks.iter()
                    .filter(|t| !t.is_supervisor && t.status != "done")
                    .count();
                if incomplete > 0 {
                    missing.push(format!("{} tasks incomplete", incomplete));
                }
            },
            TaskRequirement::MinComplete(n) => {
                let complete = tasks.iter()
                    .filter(|t| !t.is_supervisor && t.status == "done")
                    .count();
                if complete < *n {
                    missing.push(format!("Need {} tasks complete, have {}", n, complete));
                }
            },
            TaskRequirement::NamedTasks(names) => {
                for name in names {
                    let found = tasks.iter()
                        .find(|t| &t.name == name && t.status == "done");
                    if found.is_none() {
                        missing.push(format!("Task '{}' not complete", name));
                    }
                }
            }
        }

        if missing.is_empty() {
            PhaseReadinessResult::Ready
        } else {
            PhaseReadinessResult::NotReady { missing }
        }
    }

    /// Check if contract should auto-complete
    pub fn check_contract_completion(&self, contract: &Contract) -> bool {
        // Must be in terminal phase
        if contract.phase != contract.terminal_phase_id() {
            return false;
        }

        // Terminal phase gate must be satisfied
        matches!(
            self.check_phase_readiness(contract, &[]),
            PhaseReadinessResult::Ready
        )
    }
}

/// Result of phase readiness check
pub enum PhaseReadinessResult {
    /// Phase is ready to advance
    Ready,
    /// Phase is not ready, with list of missing items
    NotReady { missing: Vec<String> },
    /// No gate defined for this phase
    NoGate,
}
```

#### 2.2.3 Auto-Completion Flow

```
┌─────────────────────────────────────────────────────────────────────┐
│                    AUTO-COMPLETION FLOW                             │
└─────────────────────────────────────────────────────────────────────┘

1. Task completes (status = "done")
           │
           ▼
2. Check if any phase gate is now satisfied
           │
           ├─ NO ──► Return, wait for more tasks
           │
           ▼ YES
3. Is auto_advance enabled for phase?
           │
           ├─ NO ──► Notify user, wait for manual advance
           │
           ▼ YES
4. Is phase_guard enabled?
           │
           ├─ YES ─► Set status = WaitingForInput, ask for confirmation
           │
           ▼ NO
5. Auto-advance to next phase
           │
           ▼
6. Is this the terminal phase?
           │
           ├─ NO ──► Continue working
           │
           ▼ YES
7. All terminal deliverables complete?
           │
           ├─ NO ──► Continue working
           │
           ▼ YES
8. Set status = Completing
           │
           ▼
9. Cleanup worktrees, stop supervisor
           │
           ▼
10. Set status = Completed
```

### 2.3 Database Schema Changes

```sql
-- Track auto-completion state
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    auto_complete_enabled BOOLEAN DEFAULT TRUE;

-- Track when completion was detected
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS
    completion_detected_at TIMESTAMPTZ;
```

### 2.4 API Endpoints

```rust
/// Check phase readiness
/// GET /api/v1/contracts/{id}/phase-readiness
pub async fn check_phase_readiness(
    contract_id: Uuid,
) -> PhaseReadinessResponse;

/// Force completion check
/// POST /api/v1/contracts/{id}/check-completion
pub async fn check_completion(
    contract_id: Uuid,
) -> CompletionCheckResponse;

/// Enable/disable auto-completion
/// PUT /api/v1/contracts/{id}/auto-complete
pub async fn set_auto_complete(
    contract_id: Uuid,
    enabled: bool,
) -> ContractSummary;
```

---

## 3. Supervisor Status Reporting

### 3.1 Current Problem

The `supervisor_states` table exists but:
- State is not reliably persisted during daemon operations
- Restoration after crash doesn't properly resume context
- No clear indication of supervisor's current activity

### 3.2 Proposed Supervisor States

```rust
/// Supervisor execution states
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SupervisorState {
    /// Supervisor is starting up
    Initializing,
    /// Supervisor is idle, no pending work
    Idle,
    /// Supervisor is actively working (LLM processing)
    Working,
    /// Supervisor is waiting for user input
    WaitingForUser,
    /// Supervisor is waiting for child tasks
    WaitingForTasks,
    /// Supervisor is blocked on external resource
    Blocked,
    /// Supervisor has completed its work
    Completed,
    /// Supervisor has failed
    Failed,
    /// Supervisor was interrupted
    Interrupted,
}
```

### 3.3 Heartbeat Mechanism

```rust
/// Heartbeat message from supervisor to server
#[derive(Debug, Serialize, Deserialize)]
pub struct SupervisorHeartbeat {
    pub task_id: Uuid,
    pub contract_id: Uuid,
    pub state: SupervisorState,
    pub phase: String,
    /// What the supervisor is currently doing
    pub current_activity: String,
    /// Progress percentage (0-100)
    pub progress: u8,
    /// IDs of tasks supervisor is waiting on
    pub pending_task_ids: Vec<Uuid>,
    /// Timestamp
    pub timestamp: DateTime<Utc>,
}

/// Heartbeat configuration
pub struct HeartbeatConfig {
    /// How often to send heartbeats
    pub interval: Duration,  // Default: 30 seconds
    /// How long before a supervisor is considered dead
    pub timeout: Duration,  // Default: 2 minutes
}
```

### 3.4 State Persistence

```rust
/// Enhanced supervisor state for persistence
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SupervisorPersistentState {
    /// Current supervisor state
    pub state: SupervisorState,
    /// Current contract phase
    pub phase: String,
    /// Conversation history for resumption
    pub conversation_history: Vec<ConversationMessage>,
    /// Currently pending questions
    pub pending_questions: Vec<PendingQuestion>,
    /// Tasks spawned by this supervisor
    pub spawned_task_ids: Vec<Uuid>,
    /// Tasks we're waiting on
    pub waiting_on_task_ids: Vec<Uuid>,
    /// Last checkpoint created
    pub last_checkpoint: Option<CheckpointInfo>,
    /// Current activity description
    pub current_activity: String,
    /// Error if in failed state
    pub error: Option<String>,
    /// Timestamps
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}
```

### 3.5 Database Schema Changes

```sql
-- Enhance supervisor_states table
ALTER TABLE supervisor_states ADD COLUMN IF NOT EXISTS
    state VARCHAR(50) NOT NULL DEFAULT 'initializing';

ALTER TABLE supervisor_states ADD COLUMN IF NOT EXISTS
    current_activity TEXT;

ALTER TABLE supervisor_states ADD COLUMN IF NOT EXISTS
    progress INTEGER DEFAULT 0;

ALTER TABLE supervisor_states ADD COLUMN IF NOT EXISTS
    error_message TEXT;

ALTER TABLE supervisor_states ADD COLUMN IF NOT EXISTS
    spawned_task_ids UUID[] DEFAULT ARRAY[]::UUID[];

-- Create heartbeat tracking table
CREATE TABLE IF NOT EXISTS supervisor_heartbeats (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    supervisor_task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    contract_id UUID NOT NULL REFERENCES contracts(id) ON DELETE CASCADE,
    state VARCHAR(50) NOT NULL,
    phase VARCHAR(50) NOT NULL,
    current_activity TEXT,
    progress INTEGER DEFAULT 0,
    pending_task_ids UUID[] DEFAULT ARRAY[]::UUID[],
    timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Keep only recent heartbeats
    CONSTRAINT heartbeat_ttl CHECK (timestamp > NOW() - INTERVAL '24 hours')
);

CREATE INDEX idx_heartbeats_supervisor ON supervisor_heartbeats(supervisor_task_id);
CREATE INDEX idx_heartbeats_timestamp ON supervisor_heartbeats(timestamp);
```

### 3.6 Restoration Protocol

```
┌─────────────────────────────────────────────────────────────────────┐
│                SUPERVISOR RESTORATION PROTOCOL                       │
└─────────────────────────────────────────────────────────────────────┘

1. Daemon restarts or task is assigned to new daemon
           │
           ▼
2. Load supervisor state from supervisor_states table
           │
           ├─ NOT FOUND ──► Start fresh, log warning
           │
           ▼ FOUND
3. Validate state consistency
           │
           ├─ INVALID ──► Start from last checkpoint
           │
           ▼ VALID
4. Restore conversation history
           │
           ▼
5. Check for pending questions
           │
           ├─ HAS PENDING ──► Re-deliver questions to user
           │
           ▼ NO PENDING
6. Check for waiting tasks
           │
           ├─ HAS WAITING ──► Resume waiting state
           │
           ▼ NO WAITING
7. Send restoration context to Claude
           │
           ▼
8. Resume execution from last state
```

### 3.7 API Endpoints

```rust
/// Get supervisor status
/// GET /api/v1/contracts/{id}/supervisor/status
pub async fn get_supervisor_status(
    contract_id: Uuid,
) -> SupervisorStatusResponse;

/// Get supervisor heartbeat history
/// GET /api/v1/contracts/{id}/supervisor/heartbeats
pub async fn get_heartbeats(
    contract_id: Uuid,
    limit: Option<i32>,
) -> HeartbeatListResponse;

/// Force supervisor state sync
/// POST /api/v1/contracts/{id}/supervisor/sync
pub async fn sync_supervisor_state(
    contract_id: Uuid,
) -> SyncResponse;
```

---

## 4. Contract Monitoring Dashboard

### 4.1 Real-Time Status Updates

#### 4.1.1 WebSocket Events

```rust
/// Contract monitoring events
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContractMonitorEvent {
    /// Contract status changed
    StatusChanged {
        contract_id: Uuid,
        old_status: ContractStatus,
        new_status: ContractStatus,
        reason: Option<String>,
    },
    /// Phase changed
    PhaseChanged {
        contract_id: Uuid,
        old_phase: String,
        new_phase: String,
    },
    /// Supervisor state changed
    SupervisorStateChanged {
        contract_id: Uuid,
        supervisor_task_id: Uuid,
        old_state: SupervisorState,
        new_state: SupervisorState,
    },
    /// Supervisor heartbeat received
    Heartbeat {
        contract_id: Uuid,
        state: SupervisorState,
        activity: String,
        progress: u8,
    },
    /// Contract became stale
    StaleDetected {
        contract_id: Uuid,
        last_activity: DateTime<Utc>,
        stale_duration: Duration,
    },
    /// Task completed
    TaskCompleted {
        contract_id: Uuid,
        task_id: Uuid,
        task_name: String,
        success: bool,
    },
    /// Deliverable marked complete
    DeliverableCompleted {
        contract_id: Uuid,
        phase: String,
        deliverable_id: String,
    },
    /// Question asked (needs user attention)
    QuestionAsked {
        contract_id: Uuid,
        question_id: Uuid,
        question: String,
        question_type: String,
    },
}
```

#### 4.1.2 Subscription API

```rust
/// Subscribe to contract monitoring events
/// WS /api/v1/contracts/monitor
pub async fn monitor_contracts(
    ws: WebSocket,
    filter: ContractMonitorFilter,
) -> Result<(), Error>;

#[derive(Debug, Deserialize)]
pub struct ContractMonitorFilter {
    /// Filter by specific contract IDs
    pub contract_ids: Option<Vec<Uuid>>,
    /// Filter by status
    pub statuses: Option<Vec<ContractStatus>>,
    /// Include stale detection events
    pub include_stale: bool,
    /// Include heartbeat events
    pub include_heartbeats: bool,
}
```

### 4.2 Stale Contract Detection

```rust
/// Stale contract detector service
pub struct StaleContractDetector {
    pool: PgPool,
    config: ContractTimeoutConfig,
}

impl StaleContractDetector {
    /// Run stale detection loop
    pub async fn run(&self, event_tx: Sender<ContractMonitorEvent>) {
        let mut interval = tokio::time::interval(Duration::from_secs(60));

        loop {
            interval.tick().await;

            let stale = self.detect_stale_contracts().await;
            for (contract_id, last_activity) in stale {
                let _ = event_tx.send(ContractMonitorEvent::StaleDetected {
                    contract_id,
                    last_activity,
                    stale_duration: Utc::now() - last_activity,
                }).await;
            }
        }
    }

    /// Detect stale contracts
    async fn detect_stale_contracts(&self) -> Vec<(Uuid, DateTime<Utc>)> {
        let threshold = Utc::now() - self.config.stale_threshold;

        sqlx::query_as::<_, (Uuid, DateTime<Utc>)>(
            r#"
            SELECT id, last_activity_at
            FROM contracts
            WHERE status = 'active'
              AND last_activity_at < $1
            "#
        )
        .bind(threshold)
        .fetch_all(&self.pool)
        .await
        .unwrap_or_default()
    }
}
```

### 4.3 Batch Operations

```rust
/// Batch operation types
#[derive(Debug, Deserialize)]
#[serde(tag = "operation", rename_all = "snake_case")]
pub enum BatchOperation {
    /// Archive completed contracts older than threshold
    ArchiveOld {
        older_than: Duration,
        status_filter: Vec<ContractStatus>,
    },
    /// Pause all active contracts
    PauseAll {
        reason: String,
    },
    /// Resume all paused contracts
    ResumeAll,
    /// Delete archived contracts older than threshold
    CleanupArchived {
        older_than: Duration,
    },
    /// Restart stale supervisors
    RestartStale {
        stale_threshold: Duration,
    },
}

/// Batch operation result
#[derive(Debug, Serialize)]
pub struct BatchOperationResult {
    pub operation: String,
    pub affected_count: usize,
    pub affected_ids: Vec<Uuid>,
    pub errors: Vec<BatchOperationError>,
}

#[derive(Debug, Serialize)]
pub struct BatchOperationError {
    pub contract_id: Uuid,
    pub error: String,
}
```

### 4.4 Dashboard API

```rust
/// Get dashboard summary
/// GET /api/v1/contracts/dashboard
pub async fn get_dashboard() -> DashboardResponse;

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DashboardResponse {
    /// Count by status
    pub status_counts: HashMap<ContractStatus, usize>,
    /// Count by phase (for active contracts)
    pub phase_counts: HashMap<String, usize>,
    /// Stale contracts
    pub stale_contracts: Vec<StaleContractInfo>,
    /// Contracts waiting for input
    pub waiting_for_input: Vec<WaitingContractInfo>,
    /// Recent activity
    pub recent_events: Vec<ContractMonitorEvent>,
    /// Resource usage
    pub resource_usage: ResourceUsage,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StaleContractInfo {
    pub id: Uuid,
    pub name: String,
    pub phase: String,
    pub last_activity: DateTime<Utc>,
    pub stale_duration_secs: i64,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WaitingContractInfo {
    pub id: Uuid,
    pub name: String,
    pub waiting_for: String,  // 'question', 'phase_confirmation', etc.
    pub waiting_since: DateTime<Utc>,
    pub question: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ResourceUsage {
    pub active_supervisors: usize,
    pub running_tasks: usize,
    pub pending_tasks: usize,
    pub active_daemons: usize,
    pub total_worktrees: usize,
}
```

---

## 5. Improved CLI Commands

### 5.1 Contract Listing with Filters

```bash
# List all contracts
makima contracts list

# List with status filter
makima contracts list --status active
makima contracts list --status completed,failed

# List stale contracts
makima contracts list --stale
makima contracts list --stale --threshold 30m

# List contracts waiting for input
makima contracts list --waiting

# List by phase
makima contracts list --phase execute

# Combine filters
makima contracts list --status active --phase plan --stale

# Output formats
makima contracts list --format json
makima contracts list --format table
makima contracts list --format compact
```

#### Implementation

```rust
#[derive(Debug, Args)]
pub struct ListContractsArgs {
    /// Filter by status (comma-separated)
    #[arg(long)]
    pub status: Option<String>,

    /// Show only stale contracts
    #[arg(long)]
    pub stale: bool,

    /// Stale threshold (e.g., "30m", "1h")
    #[arg(long, default_value = "30m")]
    pub threshold: String,

    /// Show contracts waiting for input
    #[arg(long)]
    pub waiting: bool,

    /// Filter by phase
    #[arg(long)]
    pub phase: Option<String>,

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

    /// Limit results
    #[arg(long, short = 'n')]
    pub limit: Option<usize>,
}
```

### 5.2 Cleanup Command

```bash
# Archive completed contracts older than 7 days
makima contracts cleanup --archive --older-than 7d

# Delete archived contracts older than 30 days
makima contracts cleanup --delete-archived --older-than 30d

# Dry run (show what would be affected)
makima contracts cleanup --archive --older-than 7d --dry-run

# Force cleanup without confirmation
makima contracts cleanup --archive --older-than 7d --force

# Cleanup stale worktrees
makima contracts cleanup --worktrees

# Full cleanup: archive old, delete archived, clean worktrees
makima contracts cleanup --all --older-than 7d
```

#### Implementation

```rust
#[derive(Debug, Args)]
pub struct CleanupContractsArgs {
    /// Archive completed/failed contracts
    #[arg(long)]
    pub archive: bool,

    /// Delete archived contracts
    #[arg(long)]
    pub delete_archived: bool,

    /// Clean up orphaned worktrees
    #[arg(long)]
    pub worktrees: bool,

    /// Run all cleanup operations
    #[arg(long)]
    pub all: bool,

    /// Threshold for cleanup (e.g., "7d", "30d")
    #[arg(long, default_value = "7d")]
    pub older_than: String,

    /// Dry run - show what would be affected
    #[arg(long)]
    pub dry_run: bool,

    /// Skip confirmation prompts
    #[arg(long)]
    pub force: bool,
}
```

### 5.3 Monitor Command

```bash
# Real-time monitoring dashboard
makima contracts monitor

# Monitor specific contracts
makima contracts monitor <contract-id> <contract-id>

# Monitor with filters
makima contracts monitor --status active
makima contracts monitor --stale

# Quiet mode - only show important events
makima contracts monitor --quiet

# JSON output for scripting
makima contracts monitor --format json
```

#### Implementation

```rust
#[derive(Debug, Args)]
pub struct MonitorContractsArgs {
    /// Contract IDs to monitor (empty = all)
    pub contract_ids: Vec<Uuid>,

    /// Filter by status
    #[arg(long)]
    pub status: Option<String>,

    /// Only show stale contracts
    #[arg(long)]
    pub stale: bool,

    /// Quiet mode - only important events
    #[arg(long, short)]
    pub quiet: bool,

    /// Output format
    #[arg(long, default_value = "tui")]
    pub format: MonitorFormat,
}

#[derive(Debug, Clone, ValueEnum)]
pub enum MonitorFormat {
    /// Terminal UI dashboard
    Tui,
    /// Plain text output
    Text,
    /// JSON stream
    Json,
}
```

### 5.4 Additional Commands

```bash
# Resume a paused contract
makima contracts resume <contract-id>

# Pause an active contract
makima contracts pause <contract-id> --reason "Waiting for external review"

# Force advance phase
makima contracts advance <contract-id> --phase execute --force

# Restart stale supervisor
makima contracts restart-supervisor <contract-id>

# Show contract details
makima contracts show <contract-id> --verbose

# Check contract health
makima contracts health <contract-id>

# Export contract history
makima contracts export <contract-id> --format json --output contract.json
```

---

## 6. Bug Fixes

### 6.1 Version Conflicts (Silent Failures)

**Problem**: Phase changes can fail silently when version conflicts occur.

**Solution**: Implement explicit version checking and conflict reporting.

```rust
/// Result type for phase changes with explicit conflict handling
pub enum PhaseChangeResult {
    Success(Contract),
    VersionConflict {
        expected: i32,
        actual: i32,
        current_phase: String,
    },
    ValidationFailed {
        reason: String,
        missing_requirements: Vec<String>,
    },
    Unauthorized,
    NotFound,
}

/// Enhanced phase change handler
pub async fn change_phase_with_validation(
    pool: &PgPool,
    contract_id: Uuid,
    owner_id: Uuid,
    new_phase: &str,
    expected_version: Option<i32>,
) -> Result<PhaseChangeResult, Error> {
    // Start transaction
    let mut tx = pool.begin().await?;

    // Get current contract with lock
    let contract = sqlx::query_as::<_, Contract>(
        "SELECT * FROM contracts WHERE id = $1 AND owner_id = $2 FOR UPDATE"
    )
    .bind(contract_id)
    .bind(owner_id)
    .fetch_optional(&mut *tx)
    .await?;

    let contract = match contract {
        Some(c) => c,
        None => return Ok(PhaseChangeResult::NotFound),
    };

    // Check version if provided
    if let Some(expected) = expected_version {
        if contract.version != expected {
            return Ok(PhaseChangeResult::VersionConflict {
                expected,
                actual: contract.version,
                current_phase: contract.phase.clone(),
            });
        }
    }

    // Validate phase transition
    let validation = validate_phase_transition(&contract, new_phase);
    if !validation.valid {
        return Ok(PhaseChangeResult::ValidationFailed {
            reason: validation.reason,
            missing_requirements: validation.missing,
        });
    }

    // Update phase
    let updated = sqlx::query_as::<_, Contract>(
        r#"
        UPDATE contracts
        SET phase = $1, version = version + 1, updated_at = NOW()
        WHERE id = $2
        RETURNING *
        "#
    )
    .bind(new_phase)
    .bind(contract_id)
    .fetch_one(&mut *tx)
    .await?;

    tx.commit().await?;

    Ok(PhaseChangeResult::Success(updated))
}
```

### 6.2 Deliverable Validation

**Problem**: Can mark non-existent deliverables as complete.

**Solution**: Validate deliverable IDs before marking complete.

```rust
/// Validate deliverable exists for contract type and phase
pub fn validate_deliverable(
    contract_type: &str,
    phase: &str,
    deliverable_id: &str,
    phase_config: Option<&PhaseConfig>,
) -> Result<(), DeliverableValidationError> {
    let deliverables = if let Some(config) = phase_config {
        get_phase_deliverables_from_config(phase, config)
    } else {
        get_phase_deliverables_for_type(phase, contract_type)
    };

    let valid_ids: Vec<&str> = deliverables
        .deliverables
        .iter()
        .map(|d| d.id.as_str())
        .collect();

    if !valid_ids.contains(&deliverable_id) {
        return Err(DeliverableValidationError::InvalidDeliverable {
            deliverable_id: deliverable_id.to_string(),
            phase: phase.to_string(),
            valid_ids: valid_ids.into_iter().map(String::from).collect(),
        });
    }

    Ok(())
}

#[derive(Debug, thiserror::Error)]
pub enum DeliverableValidationError {
    #[error("Invalid deliverable '{deliverable_id}' for {phase} phase. Valid IDs: {valid_ids:?}")]
    InvalidDeliverable {
        deliverable_id: String,
        phase: String,
        valid_ids: Vec<String>,
    },
}
```

### 6.3 Phase Guard Bypass

**Problem**: Supervisors can bypass phase_guard setting.

**Solution**: Enforce phase_guard at the API level, not just in supervisor logic.

```rust
/// Enhanced phase change with phase_guard enforcement
pub async fn change_phase_enforced(
    pool: &PgPool,
    contract_id: Uuid,
    owner_id: Uuid,
    request: ChangePhaseRequest,
    is_supervisor: bool,
) -> Result<PhaseChangeResponse, Error> {
    let contract = get_contract_for_owner(pool, contract_id, owner_id).await?
        .ok_or_else(|| Error::NotFound)?;

    // Phase guard is enforced for EVERYONE, including supervisors
    if contract.phase_guard && !request.confirmed.unwrap_or(false) {
        // Must return phase review info, regardless of caller
        return Ok(PhaseChangeResponse::RequiresConfirmation {
            current_phase: contract.phase,
            next_phase: request.phase,
            deliverables: get_phase_deliverables(&contract.phase),
            message: "Phase guard is enabled. User confirmation required.".to_string(),
        });
    }

    // Proceed with phase change
    // ...
}
```

---

## 7. Migration Plan

### 7.1 Phase 1: Database Schema (Week 1)

1. Add new columns to `contracts` table
2. Add new columns to `supervisor_states` table
3. Create `supervisor_heartbeats` table
4. Create indexes
5. Backfill `last_activity_at` from existing data

```sql
-- Migration 001: Contract status enhancements
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS status_changed_at TIMESTAMPTZ DEFAULT NOW();
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS last_activity_at TIMESTAMPTZ DEFAULT NOW();
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS waiting_for TEXT;
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS blocked_reason TEXT;
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS failure_reason TEXT;
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS auto_complete_enabled BOOLEAN DEFAULT TRUE;
ALTER TABLE contracts ADD COLUMN IF NOT EXISTS completion_detected_at TIMESTAMPTZ;

CREATE INDEX IF NOT EXISTS idx_contracts_status ON contracts(status);
CREATE INDEX IF NOT EXISTS idx_contracts_last_activity ON contracts(last_activity_at);

-- Backfill last_activity_at from updated_at
UPDATE contracts SET last_activity_at = updated_at WHERE last_activity_at IS NULL;
```

### 7.2 Phase 2: Core Logic (Week 2)

1. Implement `ContractStatus` enum with new states
2. Implement state transition validation
3. Implement `CompletionDetector`
4. Update phase change handlers with validation
5. Implement deliverable validation

### 7.3 Phase 3: Supervisor Enhancements (Week 3)

1. Implement `SupervisorState` enum
2. Implement heartbeat mechanism
3. Implement state persistence
4. Implement restoration protocol
5. Update supervisor API endpoints

### 7.4 Phase 4: Monitoring (Week 4)

1. Implement WebSocket monitoring events
2. Implement stale detection service
3. Implement batch operations
4. Implement dashboard API

### 7.5 Phase 5: CLI (Week 5)

1. Implement `contracts list` with filters
2. Implement `contracts cleanup`
3. Implement `contracts monitor`
4. Implement additional helper commands

### 7.6 Phase 6: Testing & Rollout (Week 6)

1. Unit tests for all new components
2. Integration tests for state machines
3. Load testing for monitoring
4. Staged rollout with feature flags
5. Documentation updates

---

## 8. Appendix

### 8.1 Configuration Options

```toml
[contracts]
# Timeout configuration
stale_threshold_minutes = 30
input_timeout_hours = 24
completion_grace_period_minutes = 5
archive_retention_days = 30

# Auto-completion
auto_complete_enabled = true
auto_advance_phases = true

# Heartbeat
heartbeat_interval_seconds = 30
heartbeat_timeout_seconds = 120

# Monitoring
monitor_ws_buffer_size = 1000
stale_detection_interval_seconds = 60
```

### 8.2 Error Codes

| Code | Description |
|------|-------------|
| `CONTRACT_NOT_FOUND` | Contract does not exist |
| `INVALID_TRANSITION` | State transition not allowed |
| `VERSION_CONFLICT` | Optimistic locking conflict |
| `PHASE_GUARD_REQUIRED` | Phase guard confirmation needed |
| `INVALID_DELIVERABLE` | Deliverable ID not valid for phase |
| `SUPERVISOR_NOT_FOUND` | No supervisor for contract |
| `SUPERVISOR_DEAD` | Supervisor heartbeat timeout |
| `VALIDATION_FAILED` | Phase requirements not met |

### 8.3 Metrics

The following metrics should be tracked:

- `contracts_by_status` (gauge) - Count of contracts by status
- `contracts_stale_count` (gauge) - Number of stale contracts
- `phase_transitions_total` (counter) - Phase changes by from/to
- `completion_detections_total` (counter) - Auto-completions detected
- `supervisor_heartbeats_total` (counter) - Heartbeats received
- `supervisor_restarts_total` (counter) - Supervisor restarts
- `batch_operations_total` (counter) - Batch operations by type
