mindkit 0.1.0

A generic sequential thinking toolkit for AI reasoning systems
Documentation
use mindkit::{ThinkInput, process_thinking};

#[test]
fn test_complete_thinking_session() {
    // Simulate a complete thinking session
    let thoughts = vec![
        // Initial analysis
        ThinkInput {
            thought: "Understanding the problem: we need to build a secure authentication system".to_string(),
            next_thought_needed: true,
            thought_number: 1,
            total_thoughts: 4,
            thought_type: Some("analytical".to_string()),
            is_revision: None,
            revises_thought: None,
            branch_from_thought: None,
            branch_id: None,
            needs_more_thoughts: None,
            custom_lens: None,
            confidence: Some(0.9),
        },
        // Apply security lens
        ThinkInput {
            thought: "Examining authentication flow for vulnerabilities".to_string(),
            next_thought_needed: true,
            thought_number: 2,
            total_thoughts: 4,
            thought_type: Some("analytical".to_string()),
            custom_lens: Some("security".to_string()),
            is_revision: None,
            revises_thought: None,
            branch_from_thought: None,
            branch_id: None,
            needs_more_thoughts: None,
            confidence: Some(0.85),
        },
        // Critical analysis
        ThinkInput {
            thought: "Current approach assumes all users have email addresses".to_string(),
            next_thought_needed: true,
            thought_number: 3,
            total_thoughts: 4,
            thought_type: Some("critical".to_string()),
            is_revision: None,
            revises_thought: None,
            branch_from_thought: None,
            branch_id: None,
            needs_more_thoughts: None,
            custom_lens: None,
            confidence: Some(0.875),  // Will be reduced to 70% by critical analysis
        },
        // Synthesis and conclusion
        ThinkInput {
            thought: "Combining insights: implement flexible auth with multiple providers and strong security".to_string(),
            next_thought_needed: false,
            thought_number: 4,
            total_thoughts: 4,
            thought_type: Some("synthesis".to_string()),
            is_revision: None,
            revises_thought: None,
            branch_from_thought: None,
            branch_id: None,
            needs_more_thoughts: None,
            custom_lens: None,
            confidence: Some(0.88),
        },
    ];

    let mut outputs = Vec::new();

    for input in thoughts {
        let result = process_thinking(input);
        assert!(!result.is_error);
        outputs.push(result.formatted_output);
    }

    // Verify the session flow
    assert_eq!(outputs.len(), 4);
    assert!(outputs[0].contains("πŸ’­ 1/4 [analytical]"));
    assert!(outputs[0].contains("90%"));
    assert!(outputs[1].contains("🎯 2/4 [analytical]"));
    assert!(outputs[1].contains("πŸ”Žsecurity"));
    assert!(outputs[1].contains("85%"));
    assert!(outputs[2].contains("πŸ” 3/4 [critical]"));
    assert!(outputs[2].contains("70%"));
    assert!(outputs[2].contains("ASSUMPTION DETECTED"));
    assert!(outputs[3].contains("πŸ”— 4/4 [synthesis]"));
    assert!(outputs[3].contains("88%"));
}

#[test]
fn test_revision_workflow() {
    // Start with an initial thought
    let initial = ThinkInput {
        thought: "The solution is to use a simple password check".to_string(),
        next_thought_needed: true,
        thought_number: 1,
        total_thoughts: 3,
        thought_type: Some("analytical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.8),
    };

    let result1 = process_thinking(initial);
    assert!(!result1.is_error);

    // Apply critical thinking
    let critical = ThinkInput {
        thought: "Simple password checks are vulnerable to attacks".to_string(),
        next_thought_needed: true,
        thought_number: 2,
        total_thoughts: 3,
        thought_type: Some("critical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: Some("security".to_string()),
        confidence: Some(0.9),
    };

    let result2 = process_thinking(critical);
    assert!(!result2.is_error);
    assert!(result2.formatted_output.contains("πŸ”"));

    // Revise the initial thought
    let revision = ThinkInput {
        thought: "Actually, we need multi-factor authentication with rate limiting".to_string(),
        next_thought_needed: false,
        thought_number: 3,
        total_thoughts: 3,
        thought_type: None, // Let revision icon take precedence
        is_revision: Some(true),
        revises_thought: Some(1),
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.95),
    };

    let result3 = process_thinking(revision);
    assert!(!result3.is_error);
    assert!(result3.formatted_output.contains("πŸ”„"));
    assert!(result3.formatted_output.contains("β†Ί#1"));
}

#[test]
fn test_branching_exploration() {
    // Main thought line
    let main_thought = ThinkInput {
        thought: "Implementing REST API for the service".to_string(),
        next_thought_needed: true,
        thought_number: 1,
        total_thoughts: 2,
        thought_type: Some("analytical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.85),
    };

    let result1 = process_thinking(main_thought);
    assert!(!result1.is_error);

    // Branch to explore GraphQL alternative
    let branch1 = ThinkInput {
        thought: "Alternative: GraphQL might provide better flexibility".to_string(),
        next_thought_needed: true,
        thought_number: 2,
        total_thoughts: 3,
        thought_type: Some("analytical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: Some(1),
        branch_id: Some("graphql-exploration".to_string()),
        needs_more_thoughts: Some(true),
        custom_lens: None,
        confidence: Some(0.7),
    };

    let result2 = process_thinking(branch1);
    assert!(!result2.is_error);
    assert!(result2.formatted_output.contains("🌿"));
    assert!(
        result2
            .formatted_output
            .contains("β””#1[graphql-exploration]")
    );
    assert!(result2.formatted_output.contains("(+)"));

    // Continue on branch
    let branch2 = ThinkInput {
        thought: "GraphQL would reduce over-fetching and under-fetching issues".to_string(),
        next_thought_needed: false,
        thought_number: 3,
        total_thoughts: 3,
        thought_type: Some("validation".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: Some("graphql-exploration".to_string()),
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.82),
    };

    let result3 = process_thinking(branch2);
    assert!(!result3.is_error);
    assert!(result3.formatted_output.contains("βœ“"));
}

#[test]
fn test_expanding_thought_session() {
    // Start with an underestimated session
    let mut thought_number = 1;
    let mut total_thoughts = 2;

    let thought1 = ThinkInput {
        thought: "Starting to analyze the problem".to_string(),
        next_thought_needed: true,
        thought_number,
        total_thoughts,
        thought_type: Some("analytical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.6),
    };

    let result1 = process_thinking(thought1);
    assert!(!result1.is_error);
    assert!(result1.formatted_output.contains("1/2"));

    // Realize we need more thoughts
    thought_number = 2;
    let thought2 = ThinkInput {
        thought: "This is more complex than initially thought".to_string(),
        next_thought_needed: true,
        thought_number,
        total_thoughts,
        thought_type: Some("critical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: Some(true),
        custom_lens: None,
        confidence: Some(0.5),
    };

    let result2 = process_thinking(thought2);
    assert!(!result2.is_error);
    assert!(result2.formatted_output.contains("(+)"));

    // Continue beyond original estimate
    thought_number = 3;
    total_thoughts = 3; // Auto-adjusted
    let thought3 = ThinkInput {
        thought: "Breaking down into smaller sub-problems".to_string(),
        next_thought_needed: true,
        thought_number,
        total_thoughts,
        thought_type: Some("analytical".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.7),
    };

    let result3 = process_thinking(thought3);
    assert!(!result3.is_error);
    assert!(result3.formatted_output.contains("3/3"));

    // And even more
    thought_number = 4;
    total_thoughts = 4; // Auto-adjusted again
    let thought4 = ThinkInput {
        thought: "Final synthesis of all sub-solutions".to_string(),
        next_thought_needed: false,
        thought_number,
        total_thoughts,
        thought_type: Some("synthesis".to_string()),
        is_revision: None,
        revises_thought: None,
        branch_from_thought: None,
        branch_id: None,
        needs_more_thoughts: None,
        custom_lens: None,
        confidence: Some(0.9),
    };

    let result4 = process_thinking(thought4);
    assert!(!result4.is_error);
    assert!(result4.formatted_output.contains("4/4"));
}

#[test]
fn test_multi_lens_analysis() {
    let lenses = vec![
        (
            "Need to handle memory allocation",
            "rust",
            "ownership and borrowing",
        ),
        (
            "Processing user input from forms",
            "security",
            "Validate and sanitize",
        ),
        (
            "Need to iterate through the list",
            "performance",
            "algorithmic complexity",
        ),
    ];

    for (thought, lens, expected_text) in lenses {
        let input = ThinkInput {
            thought: thought.to_string(),
            next_thought_needed: true,
            thought_number: 1,
            total_thoughts: 1,
            thought_type: Some("analytical".to_string()),
            custom_lens: Some(lens.to_string()),
            is_revision: None,
            revises_thought: None,
            branch_from_thought: None,
            branch_id: None,
            needs_more_thoughts: None,
            confidence: None,
        };

        let result = process_thinking(input);
        assert!(!result.is_error);
        assert!(result.formatted_output.contains(&format!("πŸ”Ž{}", lens)));
        assert!(result.formatted_output.contains(expected_text));
    }
}