aidaemon 0.11.12

A personal AI agent that runs as a background daemon, accessible via Telegram, Slack, or Discord, with tool use, MCP integration, and persistent memory
Documentation
use super::*;
use crate::traits::Task;

fn completed_task(
    id: &str,
    description: &str,
    result: &str,
    completed_at: &str,
    task_order: i32,
) -> Task {
    Task {
        id: id.to_string(),
        goal_id: "goal_123".to_string(),
        description: description.to_string(),
        status: "completed".to_string(),
        priority: "medium".to_string(),
        task_order,
        parallel_group: None,
        depends_on: None,
        agent_id: None,
        context: None,
        result: Some(result.to_string()),
        error: None,
        blocker: None,
        idempotent: true,
        retry_count: 0,
        max_retries: 3,
        created_at: completed_at.to_string(),
        started_at: None,
        completed_at: Some(completed_at.to_string()),
    }
}

#[test]
fn low_signal_task_lead_reply_detects_synth_done() {
    assert!(is_low_signal_task_lead_reply("Done."));
    assert!(is_low_signal_task_lead_reply(
        "Done — Check the disk usage of my projects directory..."
    ));
}

#[test]
fn low_signal_task_lead_reply_detects_brief_complete_goal_echo() {
    assert!(is_low_signal_task_lead_reply(
        "Goal goal_123 completed: Goal completed successfully"
    ));
}

#[test]
fn low_signal_task_lead_reply_allows_concrete_multiline_results() {
    let concrete = "Goal goal_123 completed: Finished disk usage audit\n\nFinal task result:\n1.2G /Users/me/projects/aidaemon/target";
    assert!(!is_low_signal_task_lead_reply(concrete));
}

#[test]
fn goal_completion_response_detects_verification_pending_reply() {
    let reply = "I completed part of the request, but I haven't verified the final outcome yet.\n\nI need a final read-only check before I can claim success.";
    assert!(goal_completion_response_indicates_incomplete_work(reply));
}

#[test]
fn goal_completion_response_detects_deferred_action_reply() {
    assert!(goal_completion_response_indicates_incomplete_work(
        "I'll start building the website."
    ));
}

#[test]
fn incomplete_live_work_summary_detects_attempt_only_reply() {
    let reply = "I've attempted to search the live API, but encountered API errors.\n\nWhat I tried:\n- Multiple attempts with different geographic parameters\n\nCurrent status:\nNo results retrieved yet. The API is rejecting the parameters I attempted.";
    assert!(looks_like_incomplete_live_work_summary(reply));
    assert!(goal_completion_response_indicates_incomplete_work(reply));
}

#[test]
fn incomplete_live_work_summary_allows_concrete_results() {
    let reply = "I queried ClinicalTrials.gov and found an actively recruiting skin cancer study in Fairfax, Virginia.";
    assert!(!looks_like_incomplete_live_work_summary(reply));
}

#[test]
fn false_capability_denial_detects_live_search_fallback_text() {
    let reply = "I can guide you on how to find skin cancer clinical trials, but I cannot perform a live search of current databases.";
    assert!(looks_like_false_capability_denial_after_tool_success(reply));
}

#[test]
fn false_capability_denial_detects_memory_record_denial() {
    let reply = "I don't have that in my records, but I can help you add it.";
    assert!(looks_like_false_capability_denial_after_tool_success(reply));
}

#[test]
fn evidence_grounding_challenge_detects_made_up_question() {
    let reply = "Since the returned errors, does it mean you made them up?";
    assert!(looks_like_evidence_grounding_challenge(reply));
}

#[test]
fn evidence_grounding_challenge_detects_exact_output_request() {
    let reply = "Show me the exact output from the tool.";
    assert!(looks_like_evidence_grounding_challenge(reply));
}

#[test]
fn evidence_grounding_challenge_detects_test_failure_verification() {
    let reply = "Did that test actually fail?";
    assert!(looks_like_evidence_grounding_challenge(reply));
}

#[test]
fn evidence_grounding_challenge_detects_blocker_followup() {
    let reply = "Disabled? Why?";
    assert!(looks_like_evidence_grounding_challenge(reply));
}

#[test]
fn evidence_grounding_challenge_ignores_generic_followup() {
    let reply = "What does it mean?";
    assert!(!looks_like_evidence_grounding_challenge(reply));
}

#[test]
fn goal_completion_response_allows_concrete_finished_reply() {
    let reply = "I audited the disk usage and found 1.2G in /Users/me/projects/aidaemon/target.";
    assert!(!goal_completion_response_indicates_incomplete_work(reply));
}

#[test]
fn goal_task_results_summary_includes_recent_tasks_and_omission_count() {
    let tasks = vec![
        completed_task("task_1", "Step 1", "Result one", "2026-02-17T09:00:00Z", 1),
        completed_task("task_2", "Step 2", "Result two", "2026-02-17T09:01:00Z", 2),
        completed_task(
            "task_3",
            "Step 3",
            "Result three",
            "2026-02-17T09:02:00Z",
            3,
        ),
        completed_task("task_4", "Step 4", "Result four", "2026-02-17T09:03:00Z", 4),
    ];

    let summary = build_goal_task_results_summary(&tasks, "fallback");
    assert!(summary.contains("4/4 tasks completed."));
    assert!(summary.contains("Step 4"));
    assert!(summary.contains("Step 3"));
    assert!(summary.contains("Step 2"));
    assert!(summary.contains("(+1 earlier completed task result omitted)"));
}

#[test]
fn goal_task_results_summary_returns_fallback_when_no_results() {
    let mut task = completed_task("task_1", "Step 1", " ", "2026-02-17T09:00:00Z", 1);
    task.result = Some("   ".to_string());
    let summary = build_goal_task_results_summary(&[task], "fallback summary");
    assert_eq!(summary, "fallback summary");
}

#[test]
fn salvageable_task_lead_result_returns_substantive_answer() {
    let reply = "Here is the summary of the source files in src/agent/loop/:\n\n* main_loop.rs: orchestrates the turn lifecycle.\n* llm_phase.rs: handles the LLM call.";
    let salvaged = salvageable_task_lead_result(Some(reply));
    assert_eq!(salvaged.as_deref(), Some(reply));
}

#[test]
fn salvageable_task_lead_result_rejects_none_and_empty() {
    assert!(salvageable_task_lead_result(None).is_none());
    assert!(salvageable_task_lead_result(Some("   ")).is_none());
}

#[test]
fn salvageable_task_lead_result_rejects_low_signal_reply() {
    assert!(salvageable_task_lead_result(Some("Done.")).is_none());
    assert!(salvageable_task_lead_result(Some("Goal completed successfully")).is_none());
}

#[test]
fn salvageable_task_lead_result_rejects_incomplete_work_reply() {
    let reply = "I completed part of the request, but I haven't verified the final outcome yet.\n\nI need a final read-only check before I can claim success.";
    assert!(salvageable_task_lead_result(Some(reply)).is_none());
}