remem-ai 0.6.35

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

use crate::db::{self, test_support::ScopedTestDataDir};

use super::{cleanup, record_failed_job_transition, run};

#[tokio::test]
async fn worker_once_converges_expired_memory_and_persists_cooldown() -> anyhow::Result<()> {
    let _data_dir = ScopedTestDataDir::new("worker-automatic-cleanup");
    let conn = db::open_db()?;
    let now = chrono::Utc::now().timestamp();
    conn.execute(
        "INSERT INTO memories
         (project, title, content, memory_type, created_at_epoch, updated_at_epoch,
          status, scope, expires_at_epoch)
         VALUES ('/repo', 'Expired service', 'localhost service is running',
                 'discovery', ?1, ?1, 'active', 'project', ?2)",
        params![now - 100, now - 1],
    )?;
    let memory_id = conn.last_insert_rowid();
    drop(conn);

    run(true, 10).await?;

    let conn = db::open_db()?;
    let (status, valid_to_epoch): (String, Option<i64>) = conn.query_row(
        "SELECT status, valid_to_epoch FROM memories WHERE id = ?1",
        [memory_id],
        |row| Ok((row.get(0)?, row.get(1)?)),
    )?;
    assert_eq!(status, "stale");
    assert!(valid_to_epoch.is_some());
    let first_counts: (i64, i64) = conn.query_row(
        "SELECT
             (SELECT COUNT(*) FROM jobs WHERE job_type = 'cleanup'),
             (SELECT COUNT(*) FROM maintenance_runs
              WHERE trigger = 'automatic' AND outcome = 'success')",
        [],
        |row| Ok((row.get(0)?, row.get(1)?)),
    )?;
    assert_eq!(first_counts, (1, 1));
    drop(conn);

    run(true, 10).await?;

    let conn = db::open_db()?;
    let second_counts: (i64, i64) = conn.query_row(
        "SELECT
             (SELECT COUNT(*) FROM jobs WHERE job_type = 'cleanup'),
             (SELECT COUNT(*) FROM maintenance_runs
              WHERE trigger = 'automatic' AND outcome = 'success')",
        [],
        |row| Ok((row.get(0)?, row.get(1)?)),
    )?;
    assert_eq!(second_counts, first_counts);
    Ok(())
}

#[test]
fn cleanup_retry_persists_only_redacted_failure_text() -> anyhow::Result<()> {
    let _data_dir = ScopedTestDataDir::new("worker-cleanup-redacted-error");
    let mut conn = db::open_db()?;
    let now = chrono::Utc::now().timestamp();
    let db::CleanupEnqueueDecision::Enqueued(job_id) =
        db::maybe_enqueue_cleanup_job_at(&conn, now)?
    else {
        anyhow::bail!("Cleanup should enqueue");
    };
    let owner = "cleanup-error-worker";
    let job = db::claim_ready_cleanup_job(&mut conn, owner, 60)?
        .ok_or_else(|| anyhow::anyhow!("Cleanup should be claimable"))?;
    assert_eq!(job.id, job_id);
    let error = anyhow::anyhow!("api_key=short-secret").context("delete old events");
    let message = cleanup::safe_failure_message(&error);

    record_failed_job_transition(
        &conn,
        job.id,
        job.job_type,
        &job.project,
        owner,
        &message,
        60,
    )?;

    let stored: String = conn.query_row(
        "SELECT last_error FROM jobs WHERE id = ?1",
        [job.id],
        |row| row.get(0),
    )?;
    assert!(stored.contains("[REDACTED]"), "{stored}");
    assert!(!stored.contains("short-secret"), "{stored}");
    Ok(())
}