remem-ai 0.5.210

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

use super::database::table_count;
use super::types::{Check, Status};

pub(super) fn check_memory_poisoning_defense(conn: Option<&Connection>) -> Check {
    let Some(conn) = conn else {
        return Check::new(
            "Memory poisoning defense",
            Status::Warn,
            "cannot open database",
        );
    };

    let quarantined = match quarantined_candidate_count(conn) {
        Ok(count) => count,
        Err(err) => {
            return Check::new(
                "Memory poisoning defense",
                Status::Warn,
                format!("cannot load poisoning quarantine stats: {err}"),
            );
        }
    };
    let drop_count = match table_count(conn, "memory_poisoning_injection_drops") {
        Ok(count) => count,
        Err(err) => {
            return Check::new(
                "Memory poisoning defense",
                Status::Warn,
                format!("cannot load poisoning injection drop stats: {err}"),
            );
        }
    };

    let mut detail = format!(
        "pattern_set_version={}, quarantined={}, injection_drops={}",
        crate::memory::poisoning::INSTRUCTION_PATTERN_SET_VERSION,
        quarantined,
        drop_count
    );
    match top_quarantine_patterns(conn) {
        Ok(patterns) if !patterns.is_empty() => {
            detail.push_str(&format!("; patterns={}", patterns.join(", ")));
        }
        Err(err) => {
            detail.push_str(&format!("; cannot load pattern breakdown: {err}"));
        }
        _ => {}
    }
    if drop_count > 0 {
        match latest_poisoning_drop(conn) {
            Ok(Some(drop)) => {
                detail.push_str(&format!(
                    "; latest_drop=memory:{} pattern={}@v{} title={}",
                    drop.memory_id,
                    drop.pattern_id,
                    drop.pattern_version,
                    crate::db::truncate_str(&drop.title.unwrap_or_default(), 80)
                ));
            }
            Ok(None) => {}
            Err(err) => {
                detail.push_str(&format!("; cannot load latest drop: {err}"));
            }
        }
    }

    if quarantined > 0 || drop_count > 0 {
        Check::new("Memory poisoning defense", Status::Warn, detail)
    } else {
        Check::new("Memory poisoning defense", Status::Ok, detail)
    }
}

fn quarantined_candidate_count(conn: &Connection) -> Result<i64, rusqlite::Error> {
    conn.query_row(
        "SELECT COUNT(*) FROM memory_candidates WHERE review_status = 'quarantined'",
        [],
        |row| row.get(0),
    )
}

fn top_quarantine_patterns(conn: &Connection) -> Result<Vec<String>, rusqlite::Error> {
    let mut stmt = conn.prepare(
        "SELECT COALESCE(quarantine_pattern_id, '<missing>'), COUNT(*)
         FROM memory_candidates
         WHERE review_status = 'quarantined'
         GROUP BY COALESCE(quarantine_pattern_id, '<missing>')
         ORDER BY COUNT(*) DESC, COALESCE(quarantine_pattern_id, '<missing>') ASC
         LIMIT 3",
    )?;
    let rows = stmt.query_map([], |row| {
        let pattern: String = row.get(0)?;
        let count: i64 = row.get(1)?;
        Ok(format!("{pattern}:{count}"))
    })?;
    let mut patterns = Vec::new();
    for row in rows {
        patterns.push(row?);
    }
    Ok(patterns)
}

struct LatestPoisoningDrop {
    memory_id: i64,
    pattern_id: String,
    pattern_version: i64,
    title: Option<String>,
}

fn latest_poisoning_drop(
    conn: &Connection,
) -> Result<Option<LatestPoisoningDrop>, rusqlite::Error> {
    conn.query_row(
        "SELECT memory_id, pattern_id, pattern_version, title
         FROM memory_poisoning_injection_drops
         ORDER BY created_at_epoch DESC, id DESC
         LIMIT 1",
        [],
        |row| {
            Ok(LatestPoisoningDrop {
                memory_id: row.get(0)?,
                pattern_id: row.get(1)?,
                pattern_version: row.get(2)?,
                title: row.get(3)?,
            })
        },
    )
    .optional()
}