---
name: makemigrations
description: Create SQLite migrations for MemoryLane storage schema changes. Use when interfaces or persisted fields change in src/main/storage/index.ts, when a new column/index/table/trigger is needed, or when the user asks to add a migration similar to 0001_initial_schema.ts.
---

# Create Storage Migration

## Purpose

Keep runtime storage schema in sync with `src/main/storage/index.ts` by adding forward-only migrations in `src/main/storage/migrations/`.

## When to Use

Use this skill when any persisted shape changes, especially:

- `StoredActivity` or `ActivitySummary` field changes in `src/main/storage/index.ts`
- SQL statements in `StorageService` change selected/inserted columns
- New filters require indexes
- Legacy table/data needs migration into current tables

## Rules

1. Never edit or reorder existing migration files after they ship.
2. Always add a new migration with a monotonically increasing 4-digit prefix (`0003_*`, `0004_*`, ...).
3. Migration must be idempotent where possible (`IF EXISTS` / `IF NOT EXISTS`).
4. Migration must be safe on partially migrated user data.
5. Register the new migration in `src/main/storage/migrations/index.ts`.

## Workflow

Copy this checklist and execute in order:

```text
Migration Progress
- [ ] 1) Identify schema delta from index.ts changes
- [ ] 2) Create next migration file in src/main/storage/migrations/
- [ ] 3) Implement migration.up(db) with safe SQL
- [ ] 4) Register migration in src/main/storage/migrations/index.ts
- [ ] 5) Add/update storage migration tests
- [ ] 6) Run tests and lint for touched files
```

### 1) Identify schema delta

Map TypeScript/API changes to SQLite changes:

- Added persisted field -> `ALTER TABLE ... ADD COLUMN` (or backfill strategy)
- Removed field -> usually keep column; stop reading/writing it first, remove later with explicit migration plan
- Renamed field -> add new column + backfill + dual-read/write strategy if needed
- New query pattern -> add index
- New text search shape -> update FTS table/trigger strategy
- Vector shape/dimension changes -> explicit data migration strategy

### 2) Create migration file

Name pattern:

- File: `src/main/storage/migrations/000X_descriptive_name.ts`
- Export: `export const migration: Migration`
- `name` must match file stem exactly (example: `0003_add_window_title_index`)

Template:

```typescript
import Database from 'better-sqlite3'
import type { Migration } from '../migrator'

export const migration: Migration = {
  name: '000X_descriptive_name',
  up(db: Database.Database): void {
    // schema/data updates
  },
}
```

### 3) Implement safe SQL

Preferred patterns:

- `db.exec(...)` for DDL batches
- `db.prepare(...).run()` for parameterized DML
- Guard checks using `sqlite_master` when needed
- Wrap multi-step data migrations in `db.transaction(() => { ... })()`

For data moves:

- Use `INSERT OR IGNORE` where duplicate IDs may exist
- Backfill defaults for new NOT NULL columns
- Drop legacy objects only after successful copy

### 4) Register migration

Update `src/main/storage/migrations/index.ts`:

- Add import for the new migration
- Append to `migrations` array at the end (preserve order)

### 5) Tests

Update `src/main/storage/storage.test.ts` (or related tests) to cover:

- Fresh DB applies all migrations successfully
- Existing DB at previous schema upgrades correctly
- Backfilled/default values are correct
- Expected indexes/tables/triggers exist after migration

### 6) Validate

Run relevant checks:

```bash
npm test -- src/main/storage/storage.test.ts
npm run lint
```

If tests are broad or expensive, run targeted tests first, then full suite when requested.

## Examples in Repo

- Baseline schema setup: `src/main/storage/migrations/0001_initial_schema.ts`
- Legacy data migration + cleanup: `src/main/storage/migrations/0002_migrate_context_events.ts`
