# Migration System

This directory contains all migration files for the RewriteBar app. The migration system provides a centralized way to manage data migrations across different app versions using a context-based approach.

## How It Works

1. **MigrationService**: Central service that manages and executes all migrations
2. **Migration Protocol**: All migrations must conform to this protocol
3. **Context-based Execution**: Migrations are organized by context to prevent duplicate execution
4. **Version-based Execution**: Migrations are executed based on version comparison
5. **Automatic Registration**: Migrations are automatically registered when the app starts

## Creating a New Migration

1. Create a new Swift file in this directory
2. Implement the `Migration` protocol:

```swift
class YourMigration: Migration {
    let targetVersion: String = "2.17.0"  // Version this migration targets
    let description: String = "Description of what this migration does"
    
    // Define context - choose the appropriate context for your migration
    let context: MigrationContext = .app  // Options: .providerStore, .promptStore, .app
    
    func execute() -> Bool {
        // Your migration logic here
        puts("Starting your migration...")
        
        // Do the migration work
        // ...
        
        puts("✅ Migration completed successfully")
        return true
    }
}
```

3. Register the migration in `MigrationService.swift`:

```swift
private func registerMigrations() {
    // ... existing migrations ...
    migrations.append(YourMigration())
}
```

## Migration Guidelines

- **Version Format**: Use semantic versioning (e.g., "2.16.0")
- **Context Selection**: Choose the appropriate context for your migration to prevent duplicate execution
- **Idempotent**: Migrations should be safe to run multiple times
- **Descriptive**: Use clear descriptions for what the migration does
- **Error Handling**: Return `false` if migration fails, `true` if successful
- **Logging**: Use `puts()` for logging migration progress

## Context System

The migration system uses a context-based approach to organize and execute migrations efficiently:

### Available Contexts

- **`.providerStore`**: For migrations that modify provider configurations
- **`.promptStore`**: For migrations that modify prompt/command configurations  
- **`.app`**: For general app-level migrations that don't depend on specific stores

### How Contexts Work

1. **Context-based Execution**: Migrations are executed only in their appropriate context
2. **No Duplicate Execution**: Each migration runs exactly once in its designated context
3. **Automatic Filtering**: The system automatically filters migrations by context
4. **Clear Separation**: Migrations are organized by their purpose and dependencies

### Context Selection Guide

```swift
// Provider-related migrations (e.g., adding new AI providers)
let context: MigrationContext = .providerStore

// Prompt/command-related migrations (e.g., adding new default prompts)
let context: MigrationContext = .promptStore

// General app migrations (e.g., settings, UI changes)
let context: MigrationContext = .app
```

### Migration Execution Flow

1. **App Startup**: Runs `.app` context migrations
2. **PromptStore Load**: Runs `.promptStore` context migrations
3. **ProviderStore Load**: Runs `.providerStore` context migrations
4. **Version Tracking**: `lastMigratedVersion` is automatically updated when no pending migrations exist across ALL contexts
5. **Status Checking**: `runPendingMigrations(for: nil)` returns all pending migrations without executing

## Migration-Friendly Store Methods

Since store properties are `private(set)`, use these special migration methods:

### ProviderStore Migration Methods

```swift
// Add a new provider configuration (uses existing method)
providerStore.addConfig(newConfig)

// Add provider at specific index (for migrations that need ordering)
providerStore.addConfigAt(newConfig, at: index)
```

### PromptStore Migration Methods

```swift
// Update all prompts (uses existing savePrompts method)
promptStore.savePrompts(updatedPrompts, action: "migration")

// Initialize base prompts (uses existing initBasePrompts method)
promptStore.initBasePrompts()
```

### Example Migration Implementation

```swift
// Provider migration example
class NewProviderMigration: Migration {
    let targetVersion: String = "2.17.0"
    let description: String = "Add new AI provider"
    let context: MigrationContext = .providerStore
    
    func execute() -> Bool {
        let providerStore = ProviderStore.shared
        let newConfig = ProviderConfig(providerType: .newProvider)
        
        // For most cases, use the existing addConfig method
        providerStore.addConfig(newConfig)
        
        // Only use addConfigAt when you need specific ordering
        // providerStore.addConfigAt(newConfig, at: 0)
        
        return true
    }
}

// Prompt migration example
class NewPromptMigration: Migration {
    let targetVersion: String = "2.17.1"
    let description: String = "Add new default prompt"
    let context: MigrationContext = .promptStore
    
    func execute() -> Bool {
        let promptStore = CustomPromptStore.shared
        promptStore.initBasePrompts() // This will add any missing prompts
        
        return true
    }
}
```

### Testing and Development

```swift
// Test migrations for a specific context
MigrationService.shared.runPendingMigrations(for: .providerStore)
MigrationService.shared.runPendingMigrations(for: .promptStore)
MigrationService.shared.runPendingMigrations(for: .app)

// Check all pending migrations without executing
let pendingMigrations = MigrationService.shared.getMigrationStatus()
print("Pending migrations: \(pendingMigrations.pendingMigrationsCount)")
```

## Migration Types

### Provider Migrations
- Add new AI providers to the provider list
- Update provider configurations
- Example: `AppleIntelligenceProviderMigration`

### Prompt Migrations
- Add new default prompts
- Update prompt structures
- Example: `InitialPromptsMigration`, `CommandSlugsMigration`

### Settings Migrations
- Update user settings structure
- Migrate old settings to new format
- Add new default settings

## Best Practices

1. **Test Thoroughly**: Always test migrations with real data
2. **Backward Compatibility**: Ensure migrations don't break existing functionality
3. **Incremental**: Keep migrations small and focused
4. **Context Selection**: Choose the appropriate context for your migration
5. **Documentation**: Document what each migration does
6. **Version Management**: Use consistent version numbering
7. **Idempotent Design**: Ensure migrations can be run multiple times safely
8. **Clear Logging**: Use descriptive logging to track migration progress

## Current Migrations

### Provider Store Context (`.providerStore`)
- `AppleIntelligenceProviderMigration` (v2.16.0): Adds AppleIntelligenceProvider to provider configurations

### Prompt Store Context (`.promptStore`)
- `InitialPromptsMigration` (v2.0.4): Adds missing initial prompts
- `CommandSlugsMigration` (v2.4.0): Adds slugs to commands
- `HasCustomNameMigration` (v2.12.0): Adds hasCustomName flags to commands

### App Context (`.app`)
- No app-level migrations currently registered

## Migration Execution Summary

The migration system now uses a context-based approach that prevents duplicate execution:

- **App Startup**: Executes `.app` context migrations
- **PromptStore Load**: Executes `.promptStore` context migrations  
- **ProviderStore Load**: Executes `.providerStore` context migrations
- **Status Checking**: `runPendingMigrations(for: nil)` safely returns all pending migrations without executing them

This ensures each migration runs exactly once in its appropriate context, eliminating the previous issue of duplicate execution.
