remem-ai 0.6.61

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

fn finding(findings: &mut Vec<String>, detail: impl std::fmt::Display) {
    findings.push(format!(
        "v076_dream_poisoning_quarantine critical shape mismatch: {detail}"
    ));
}

pub(super) fn require_primary_key(
    conn: &Connection,
    findings: &mut Vec<String>,
    table: &str,
    column: &str,
) -> Result<()> {
    let mut stmt = conn.prepare(&format!("PRAGMA table_info(\"{table}\")"))?;
    let rows = stmt.query_map([], |row| {
        Ok((row.get::<_, String>(1)?, row.get::<_, i64>(5)?))
    })?;
    let mut actual = rows
        .filter_map(|row| match row {
            Ok((name, position)) if position > 0 => Some(Ok((position, name))),
            Ok(_) => None,
            Err(error) => Some(Err(error)),
        })
        .collect::<std::result::Result<Vec<_>, _>>()?;
    actual.sort_unstable();
    if actual != [(1, column.to_string())] {
        finding(findings, format!("{table}.{column} must be PRIMARY KEY"));
    }
    Ok(())
}

pub(super) fn require_unique_columns(
    conn: &Connection,
    findings: &mut Vec<String>,
    table: &str,
    expected: &[&str],
) -> Result<()> {
    let mut stmt = conn.prepare(&format!("PRAGMA index_list(\"{table}\")"))?;
    let indexes = stmt.query_map([], |row| {
        Ok((
            row.get::<_, String>(1)?,
            row.get::<_, i64>(2)? != 0,
            row.get::<_, i64>(4)? != 0,
        ))
    })?;
    let mut found = false;
    for index in indexes {
        let (name, unique, partial) = index?;
        if unique && !partial && index_columns(conn, &name)? == expected {
            found = true;
        }
    }
    if !found {
        finding(
            findings,
            format!("{table} missing UNIQUE({})", expected.join(",")),
        );
    }
    Ok(())
}

pub(super) fn require_restrict_foreign_key(
    conn: &Connection,
    findings: &mut Vec<String>,
    table: &str,
    from: &str,
    target: &str,
    to: &str,
) -> Result<()> {
    let mut stmt = conn.prepare(&format!("PRAGMA foreign_key_list(\"{table}\")"))?;
    let rows = stmt.query_map([], |row| {
        Ok((
            row.get::<_, String>(2)?,
            row.get::<_, String>(3)?,
            row.get::<_, String>(4)?,
            row.get::<_, String>(6)?,
        ))
    })?;
    let mut found = false;
    for row in rows {
        let (actual_target, actual_from, actual_to, on_delete) = row?;
        if (
            actual_target,
            actual_from,
            actual_to,
            on_delete.to_ascii_uppercase(),
        ) == (
            target.to_string(),
            from.to_string(),
            to.to_string(),
            "RESTRICT".to_string(),
        ) {
            found = true;
        }
    }
    if !found {
        finding(
            findings,
            format!("{table}.{from} missing REFERENCES {target}({to}) ON DELETE RESTRICT"),
        );
    }
    Ok(())
}

pub(super) fn require_index_columns(
    conn: &Connection,
    findings: &mut Vec<String>,
    index: &str,
    expected: &[&str],
) -> Result<()> {
    let actual = index_columns(conn, index)?;
    if actual != expected {
        finding(
            findings,
            format!("index {index} columns {actual:?}, expected {expected:?}"),
        );
    }
    Ok(())
}

fn index_columns(conn: &Connection, index: &str) -> Result<Vec<String>> {
    let mut stmt = conn.prepare(&format!("PRAGMA index_info(\"{index}\")"))?;
    let columns = stmt
        .query_map([], |row| row.get::<_, String>(2))?
        .collect::<std::result::Result<Vec<_>, _>>()?;
    Ok(columns)
}

pub(super) fn require_sql_fragments(
    conn: &Connection,
    findings: &mut Vec<String>,
    object_type: &str,
    name: &str,
    fragments: &[&str],
) -> Result<()> {
    let sql = conn
        .query_row(
            "SELECT sql FROM sqlite_master WHERE type = ?1 AND name = ?2",
            [object_type, name],
            |row| row.get::<_, String>(0),
        )
        .optional()?;
    let Some(sql) = sql else {
        return Ok(());
    };
    let normalized = sql
        .to_ascii_lowercase()
        .split_whitespace()
        .collect::<Vec<_>>()
        .join(" ");
    for fragment in fragments {
        if !normalized.contains(fragment) {
            finding(
                findings,
                format!("{object_type} {name} missing SQL contract `{fragment}`"),
            );
        }
    }
    Ok(())
}