---
name: bigmind-migration
description: Scaffolds a new BigMind database schema migration (v_n to v_{n+1}), including the migration function, SCHEMA_VERSION bump, and test stubs. Use this skill when adding new tables or columns to the BigMind SQLite database.
---

# BigMind Migration

## When to use
- Adding a new table to BigMind
- Adding columns to an existing table
- Creating a new FTS5 virtual table

## When NOT to use
- Non-schema changes (just code, no DB structure changes)
- Dropping or renaming columns (requires extra deprecation care — discuss first)

## Inputs required
- **Current schema version** — check `SCHEMA_VERSION` in `db.py`
- **New version** — `current + 1`
- **Changes** — what tables/columns are being added

## Workflow

### Step 1 — Read current schema
```bash
grep -n "SCHEMA_VERSION" ~/.mcp/bigmind/bigmind/db.py
grep -n "_migrate_v" ~/.mcp/bigmind/bigmind/db.py
```
Know what version you're migrating FROM.

### Step 2 — Write migration function in `db.py`

Add after the last existing migration function:
```python
def _migrate_v{N}_to_v{N+1}(conn):
    """Add {description of change}."""
    cursor = conn.cursor()
    
    # Example: new table
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS {table_name} (
            id TEXT PRIMARY KEY,
            user_id TEXT NOT NULL,
            created_at TEXT NOT NULL DEFAULT (datetime('now')),
            -- other columns
            FOREIGN KEY (user_id) REFERENCES users(id)
        )
    """)
    
    # Example: FTS5 virtual table
    cursor.execute("""
        CREATE VIRTUAL TABLE IF NOT EXISTS {table_name}_fts
        USING fts5(content, tokenize='porter')
    """)
    
    conn.commit()
```

### Step 3 — Wire into `init_db()`

In the migration chain inside `init_db()`:
```python
SCHEMA_VERSION = {N+1}  # bump this

# In the migration section:
if current_version < {N+1}:
    _migrate_v{N}_to_v{N+1}(conn)
    current_version = {N+1}
```

### Step 4 — Write tests

In `tests/test_memory_store.py` (or a new test file):
```python
class TestMigration_v{N}_to_v{N+1}:
    def test_fresh_db_has_new_table(self, tmp_path):
        db_path = tmp_path / "test.db"
        conn = get_connection(str(db_path))
        init_db(conn)
        # Assert new table exists
        cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'")
        assert cursor.fetchone() is not None

    def test_existing_db_migrates_cleanly(self, tmp_path):
        # Create a v{N} db, then run init_db() and check migration ran
        ...
```

### Step 5 — Run full test suite
```bash
cd ~/.mcp/bigmind
uv run pytest tests/ -v
```
All tests must pass.

### Step 6 — Store migration fact
```
memory_store_fact("codebase", "BigMind schema migrated v{N}→v{N+1}: added {description}. Migration function: _migrate_v{N}_to_v{N+1}.")
```

## Troubleshooting
- **`IF NOT EXISTS` is your friend:** Always use it so the migration is idempotent
- **FTS5 table ordering:** Create the base table before the FTS5 virtual table that references it
- **Migration not running:** Check the `if current_version < X:` guard — verify `current_version` is read correctly from `PRAGMA user_version`
- **Test DB state:** Use `tmp_path` fixture for isolated test databases — never test against the real `memory.db`
