remem-ai 0.6.90

Local-first coding agent memory for Claude Code and OpenAI Codex
Documentation
use anyhow::Result;
use rusqlite::Connection;

use super::run_migrations;

#[test]
fn preference_rule_state_migration_creates_rows_and_indexes() -> Result<()> {
    let conn = Connection::open_in_memory()?;
    conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;")?;
    run_migrations(&conn)?;

    for name in [
        "memory_preference_reinforcements",
        "preference_rule_overrides",
        "preference_rule_diagnostics",
        "idx_memory_preference_reinforcements_rank",
        "idx_memory_preference_reinforcements_eligible",
        "idx_preference_rule_overrides_project",
        "idx_preference_rule_overrides_source",
        "idx_preference_rule_diagnostics_project_event",
        "idx_preference_rule_diagnostics_rule",
    ] {
        let exists: bool = conn.query_row(
            "SELECT 1 FROM sqlite_master WHERE name = ?1",
            [name],
            |_| Ok(true),
        )?;
        assert!(
            exists,
            "{name} should exist after preference rule migration"
        );
    }

    conn.execute(
        "INSERT INTO memories
         (id, project, title, content, memory_type, created_at_epoch, updated_at_epoch, status)
         VALUES (1, '/repo', 'Preference', 'Use bun instead of npm.', 'preference', 10, 10, 'active')",
        [],
    )?;
    assert!(conn
        .prepare(
            "SELECT machine_checkable, risk_class
             FROM memory_preference_reinforcements LIMIT 0"
        )
        .is_ok());
    conn.execute(
        "INSERT INTO memory_preference_reinforcements
         (memory_id, reinforcement_count, last_reinforced_at_epoch,
          created_at_epoch, updated_at_epoch)
         VALUES (1, 3, 20, 10, 20)",
        [],
    )?;
    let machine_checkable: i64 = conn.query_row(
        "SELECT machine_checkable
         FROM memory_preference_reinforcements WHERE memory_id = 1",
        [],
        |row| row.get(0),
    )?;
    assert_eq!(machine_checkable, 0);
    conn.execute(
        "INSERT INTO preference_rule_overrides
         (project, rule_id, source_memory_id, disabled, action_override, updated_at_epoch)
         VALUES ('/repo', 'pref-1-1', 1, 0, 'warn', 30)",
        [],
    )?;
    conn.execute(
        "INSERT INTO preference_rule_diagnostics
         (project, event_kind, status, rule_id, rule_count, occurred_at_epoch)
         VALUES ('/repo', 'compile', 'ok', 'pref-1-1', 1, 40)",
        [],
    )?;
    Ok(())
}

#[test]
fn preference_rule_state_schema_validates_actions_and_counts() -> Result<()> {
    let conn = Connection::open_in_memory()?;
    conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;")?;
    run_migrations(&conn)?;

    let err = conn
        .execute(
            "INSERT INTO memory_preference_reinforcements
             (memory_id, reinforcement_count, last_reinforced_at_epoch,
              created_at_epoch, updated_at_epoch)
             VALUES (99, 0, 20, 10, 20)",
            [],
        )
        .expect_err("reinforcement count must be positive");
    assert!(err.to_string().contains("CHECK"), "{err}");

    let err = conn
        .execute(
            "INSERT INTO memory_preference_reinforcements
             (memory_id, reinforcement_count, last_reinforced_at_epoch,
              created_at_epoch, updated_at_epoch, machine_checkable, risk_class)
             VALUES (98, 1, 20, 10, 20, 0, 'critical')",
            [],
        )
        .expect_err("risk class must stay closed");
    assert!(err.to_string().contains("CHECK"), "{err}");

    let err = conn
        .execute(
            "INSERT INTO preference_rule_overrides
             (project, rule_id, action_override, updated_at_epoch)
             VALUES ('/repo', 'pref-1-1', 'audit', 30)",
            [],
        )
        .expect_err("action override must stay closed");
    assert!(err.to_string().contains("CHECK"), "{err}");

    let err = conn
        .execute(
            "INSERT INTO preference_rule_diagnostics
             (project, event_kind, status, rule_count, occurred_at_epoch)
             VALUES ('/repo', 'compile', 'ok', -1, 40)",
            [],
        )
        .expect_err("rule count must be non-negative");
    assert!(err.to_string().contains("CHECK"), "{err}");
    Ok(())
}