aidens-integration-tests 0.1.0

E2E integration tests proving the unified agent framework
Documentation
use aidens_contracts::{CanonicalToolSideEffectClass, JobStateV1};
use aidens_daemon_kit::DaemonControllerV1;
use chrono::Utc;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};

fn temp_root(name: &str) -> PathBuf {
    let nonce = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("system clock should be after unix epoch")
        .as_nanos();
    let root = std::env::temp_dir().join(format!(
        "aidens-phase-07-{name}-{}-{nonce}",
        std::process::id()
    ));
    let _ = std::fs::remove_dir_all(&root);
    root
}

fn cleanup(root: &Path) {
    let _ = std::fs::remove_dir_all(root);
}

#[test]
fn daemon_namespace_isolated() {
    let root = temp_root("namespace-isolated");
    let ns_a = DaemonControllerV1::namespace(&root, "same-app-name", "owner-a");
    let ns_b = DaemonControllerV1::namespace(&root, "same-app-name", "owner-b");

    assert_ne!(ns_a.namespace_id, ns_b.namespace_id);
    assert_eq!(ns_a.queue_root, ns_b.queue_root);

    let daemon_a = DaemonControllerV1::open(&root, ns_a.clone(), "owner-a").unwrap();
    let daemon_b = DaemonControllerV1::open(&root, ns_b.clone(), "owner-b").unwrap();

    let a = daemon_a
        .enqueue_schedule_occurrence(
            "daily",
            "same-logical-time",
            Utc::now(),
            serde_json::json!({"task":"refresh"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap();
    let b = daemon_b
        .enqueue_schedule_occurrence(
            "daily",
            "same-logical-time",
            Utc::now(),
            serde_json::json!({"task":"refresh"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap();

    assert!(a.enqueued);
    assert!(b.enqueued);
    assert_ne!(
        a.job.as_ref().unwrap().job_id,
        b.job.as_ref().unwrap().job_id
    );
    assert_eq!(daemon_a.snapshot().unwrap().jobs.len(), 1);
    assert_eq!(daemon_b.snapshot().unwrap().jobs.len(), 1);
    assert_eq!(
        daemon_a.snapshot().unwrap().namespace.namespace_id,
        ns_a.namespace_id
    );
    assert_eq!(
        daemon_b.snapshot().unwrap().namespace.namespace_id,
        ns_b.namespace_id
    );

    cleanup(&root);
}

#[test]
fn schedule_no_duplicate_storm() {
    let root = temp_root("duplicate-storm");
    let ns = DaemonControllerV1::namespace(&root, "schedule-storm", "daemon-a");
    let daemon = DaemonControllerV1::open(&root, ns, "daemon-a").unwrap();

    let first_schedule = daemon
        .enqueue_schedule_occurrence(
            "hourly",
            "2026-04-29T12:00:00Z",
            Utc::now(),
            serde_json::json!({"task":"sync"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap();
    assert!(first_schedule.enqueued);

    for _ in 0..10 {
        let duplicate = daemon
            .enqueue_schedule_occurrence(
                "hourly",
                "2026-04-29T12:00:00Z",
                Utc::now(),
                serde_json::json!({"task":"sync"}),
                CanonicalToolSideEffectClass::ReadOnly,
            )
            .unwrap();
        assert!(!duplicate.enqueued);
        assert!(duplicate.duplicate_suppression_receipt.is_some());
    }

    let first_wake = daemon
        .enqueue_wake_signal(
            "filesystem",
            "repo-change",
            serde_json::json!({"path":"Cargo.toml"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap();
    assert!(first_wake.enqueued);

    for _ in 0..10 {
        let duplicate = daemon
            .enqueue_wake_signal(
                "filesystem",
                "repo-change",
                serde_json::json!({"path":"Cargo.toml"}),
                CanonicalToolSideEffectClass::ReadOnly,
            )
            .unwrap();
        assert!(!duplicate.enqueued);
        assert!(duplicate.duplicate_suppression_receipt.is_some());
    }

    let snapshot = daemon.snapshot().unwrap();
    assert_eq!(snapshot.jobs.len(), 2);
    assert_eq!(
        snapshot.logical_job_count_for("schedule:"),
        0,
        "logical lookup must require the exact idempotency key"
    );

    cleanup(&root);
}

#[test]
fn restart_does_not_reenqueue_completed_jobs() {
    let root = temp_root("restart-completed");
    let ns = DaemonControllerV1::namespace(&root, "restart-completed", "daemon-a");
    let daemon = DaemonControllerV1::open(&root, ns.clone(), "daemon-a").unwrap();

    let enqueued = daemon
        .enqueue_schedule_occurrence(
            "once",
            "completed-logical-job",
            Utc::now(),
            serde_json::json!({"task":"done-once"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap()
        .job
        .unwrap();
    let lease = daemon.acquire_next("daemon-a", 30).unwrap().unwrap().lease;
    daemon.complete(&enqueued.job_id, &lease).unwrap();

    let restarted = DaemonControllerV1::open(&root, ns, "daemon-a").unwrap();
    let duplicate = restarted
        .enqueue_schedule_occurrence(
            "once",
            "completed-logical-job",
            Utc::now(),
            serde_json::json!({"task":"done-once"}),
            CanonicalToolSideEffectClass::ReadOnly,
        )
        .unwrap();

    assert!(!duplicate.enqueued);
    assert!(duplicate.duplicate_suppression_receipt.is_some());
    assert!(restarted.acquire_next("daemon-a", 30).unwrap().is_none());

    let snapshot = restarted.snapshot().unwrap();
    assert_eq!(snapshot.jobs.len(), 1);
    assert_eq!(
        snapshot.job(&enqueued.job_id).unwrap().state,
        JobStateV1::Completed
    );

    cleanup(&root);
}