exo-temporal 0.1.1

Temporal memory coordinator with causal structure for EXO-AI cognitive substrate
Documentation
//! Unit tests for exo-temporal memory coordinator

#[cfg(test)]
mod causal_cone_query_tests {
    use super::*;
    // use exo_temporal::*;

    #[test]
    fn test_causal_query_past_cone() {
        // Test querying past causal cone
        // let mut memory = TemporalMemory::new();
        //
        // let now = SubstrateTime::now();
        // let past1 = memory.store(pattern_at(now - 1000), &[]).unwrap();
        // let past2 = memory.store(pattern_at(now - 500), &[past1]).unwrap();
        // let future1 = memory.store(pattern_at(now + 500), &[]).unwrap();
        //
        // let results = memory.causal_query(
        //     &query,
        //     now,
        //     CausalConeType::Past
        // );
        //
        // assert!(results.iter().all(|r| r.timestamp <= now));
        // assert!(results.iter().any(|r| r.id == past1));
        // assert!(results.iter().any(|r| r.id == past2));
        // assert!(!results.iter().any(|r| r.id == future1));
    }

    #[test]
    fn test_causal_query_future_cone() {
        // Test querying future causal cone
        // let results = memory.causal_query(
        //     &query,
        //     reference_time,
        //     CausalConeType::Future
        // );
        //
        // assert!(results.iter().all(|r| r.timestamp >= reference_time));
    }

    #[test]
    fn test_causal_query_light_cone() {
        // Test light-cone constraint (relativistic causality)
        // let velocity = 1.0;  // Speed of light
        // let results = memory.causal_query(
        //     &query,
        //     reference_time,
        //     CausalConeType::LightCone { velocity }
        // );
        //
        // // Verify |delta_x| <= c * |delta_t|
        // for result in results {
        //     let dt = (result.timestamp - reference_time).abs();
        //     let dx = distance(result.position, query.position);
        //     assert!(dx <= velocity * dt);
        // }
    }

    #[test]
    fn test_causal_distance_calculation() {
        // Test causal distance in causal graph
        // let p1 = memory.store(pattern1, &[]).unwrap();
        // let p2 = memory.store(pattern2, &[p1]).unwrap();
        // let p3 = memory.store(pattern3, &[p2]).unwrap();
        //
        // let distance = memory.causal_graph.distance(p1, p3);
        // assert_eq!(distance, 2);  // Two hops
    }
}

#[cfg(test)]
mod memory_consolidation_tests {
    use super::*;

    #[test]
    fn test_short_term_to_long_term() {
        // Test memory consolidation
        // let mut memory = TemporalMemory::new();
        //
        // // Fill short-term buffer
        // for i in 0..100 {
        //     memory.store(pattern(i), &[]).unwrap();
        // }
        //
        // assert!(memory.short_term.should_consolidate());
        //
        // // Trigger consolidation
        // memory.consolidate();
        //
        // // Verify short-term is cleared
        // assert!(memory.short_term.is_empty());
        //
        // // Verify salient patterns moved to long-term
        // assert!(memory.long_term.size() > 0);
    }

    #[test]
    fn test_salience_filtering() {
        // Test that only salient patterns are consolidated
        // let mut memory = TemporalMemory::new();
        //
        // let high_salience = pattern_with_salience(0.9);
        // let low_salience = pattern_with_salience(0.1);
        //
        // memory.store(high_salience.clone(), &[]).unwrap();
        // memory.store(low_salience.clone(), &[]).unwrap();
        //
        // memory.consolidate();
        //
        // // High salience should be in long-term
        // assert!(memory.long_term.contains(&high_salience));
        //
        // // Low salience should not be
        // assert!(!memory.long_term.contains(&low_salience));
    }

    #[test]
    fn test_salience_computation() {
        // Test salience scoring
        // let memory = setup_test_memory();
        //
        // let pattern = sample_pattern();
        // let salience = memory.compute_salience(&pattern);
        //
        // // Salience should be between 0 and 1
        // assert!(salience >= 0.0 && salience <= 1.0);
    }

    #[test]
    fn test_salience_access_frequency() {
        // Test access frequency component of salience
        // let mut memory = setup_test_memory();
        // let p_id = memory.store(pattern, &[]).unwrap();
        //
        // // Access multiple times
        // for _ in 0..10 {
        //     memory.retrieve(p_id);
        // }
        //
        // let salience = memory.compute_salience_for(p_id);
        // assert!(salience > baseline_salience);
    }

    #[test]
    fn test_salience_recency() {
        // Test recency component
    }

    #[test]
    fn test_salience_causal_importance() {
        // Test causal importance component
        // Patterns with many dependents should have higher salience
    }

    #[test]
    fn test_salience_surprise() {
        // Test surprise component
    }
}

#[cfg(test)]
mod anticipation_tests {
    use super::*;

    #[test]
    fn test_anticipate_sequential_pattern() {
        // Test predictive pre-fetch from sequential patterns
        // let mut memory = setup_test_memory();
        //
        // // Establish pattern: A -> B -> C
        // memory.store_sequence([pattern_a, pattern_b, pattern_c]);
        //
        // // Query A, then B
        // memory.query(&pattern_a);
        // memory.query(&pattern_b);
        //
        // // Anticipate should predict C
        // let hints = vec![AnticipationHint::SequentialPattern];
        // memory.anticipate(&hints);
        //
        // // Verify C is pre-fetched in cache
        // assert!(memory.prefetch_cache.contains_key(&hash(pattern_c)));
    }

    #[test]
    fn test_anticipate_temporal_cycle() {
        // Test time-of-day pattern anticipation
    }

    #[test]
    fn test_anticipate_causal_chain() {
        // Test causal dependency prediction
        // If A causes B and C, querying A should pre-fetch B and C
    }

    #[test]
    fn test_anticipate_cache_hit() {
        // Test that anticipated queries hit cache
        // let mut memory = setup_test_memory_with_anticipation();
        //
        // // Trigger anticipation
        // memory.anticipate(&hints);
        //
        // // Query anticipated item
        // let start = now();
        // let result = memory.query(&anticipated_query);
        // let duration = now() - start;
        //
        // // Should be faster due to cache hit
        // assert!(duration < baseline_duration / 2);
    }
}

#[cfg(test)]
mod causal_graph_tests {
    use super::*;

    #[test]
    fn test_causal_graph_add_edge() {
        // Test adding causal edge
        // let mut graph = CausalGraph::new();
        // let p1 = PatternId::new();
        // let p2 = PatternId::new();
        //
        // graph.add_edge(p1, p2);
        //
        // assert!(graph.has_edge(p1, p2));
    }

    #[test]
    fn test_causal_graph_forward_edges() {
        // Test forward edge index (cause -> effects)
        // graph.add_edge(p1, p2);
        // graph.add_edge(p1, p3);
        //
        // let effects = graph.forward.get(&p1);
        // assert_eq!(effects.len(), 2);
    }

    #[test]
    fn test_causal_graph_backward_edges() {
        // Test backward edge index (effect -> causes)
        // graph.add_edge(p1, p3);
        // graph.add_edge(p2, p3);
        //
        // let causes = graph.backward.get(&p3);
        // assert_eq!(causes.len(), 2);
    }

    #[test]
    fn test_causal_graph_shortest_path() {
        // Test shortest path calculation
    }

    #[test]
    fn test_causal_graph_out_degree() {
        // Test out-degree for causal importance
    }
}

#[cfg(test)]
mod temporal_knowledge_graph_tests {
    use super::*;

    #[test]
    fn test_tkg_add_temporal_fact() {
        // Test adding temporal fact to TKG
        // let mut tkg = TemporalKnowledgeGraph::new();
        // let fact = TemporalFact {
        //     subject: entity1,
        //     predicate: relation,
        //     object: entity2,
        //     timestamp: SubstrateTime::now(),
        // };
        //
        // tkg.add_fact(fact);
        //
        // assert!(tkg.has_fact(&fact));
    }

    #[test]
    fn test_tkg_temporal_query() {
        // Test querying facts within time range
    }

    #[test]
    fn test_tkg_temporal_relations() {
        // Test temporal relation inference
    }
}

#[cfg(test)]
mod short_term_buffer_tests {
    use super::*;

    #[test]
    fn test_short_term_insert() {
        // Test inserting into short-term buffer
        // let mut buffer = ShortTermBuffer::new(capacity: 100);
        // let id = buffer.insert(pattern);
        // assert!(buffer.contains(id));
    }

    #[test]
    fn test_short_term_capacity() {
        // Test buffer capacity limits
        // let mut buffer = ShortTermBuffer::new(capacity: 10);
        //
        // for i in 0..20 {
        //     buffer.insert(pattern(i));
        // }
        //
        // assert_eq!(buffer.len(), 10);  // Should maintain capacity
    }

    #[test]
    fn test_short_term_eviction() {
        // Test eviction policy (FIFO or LRU)
    }

    #[test]
    fn test_short_term_should_consolidate() {
        // Test consolidation trigger
        // let mut buffer = ShortTermBuffer::new(capacity: 100);
        //
        // for i in 0..80 {
        //     buffer.insert(pattern(i));
        // }
        //
        // assert!(buffer.should_consolidate());  // > 75% full
    }
}

#[cfg(test)]
mod long_term_store_tests {
    use super::*;

    #[test]
    fn test_long_term_integrate() {
        // Test integrating pattern into long-term storage
    }

    #[test]
    fn test_long_term_search() {
        // Test search in long-term storage
    }

    #[test]
    fn test_long_term_decay() {
        // Test strategic decay of low-salience
        // let mut store = LongTermStore::new();
        //
        // store.integrate(high_salience_pattern(), 0.9);
        // store.integrate(low_salience_pattern(), 0.1);
        //
        // store.decay_low_salience(0.2);  // Threshold
        //
        // // High salience should remain
        // // Low salience should be decayed
    }
}

#[cfg(test)]
mod edge_cases_tests {
    use super::*;

    #[test]
    fn test_empty_antecedents() {
        // Test storing pattern with no causal antecedents
        // let mut memory = TemporalMemory::new();
        // let id = memory.store(pattern, &[]).unwrap();
        // assert!(memory.causal_graph.backward.get(&id).is_none());
    }

    #[test]
    fn test_circular_causality() {
        // Test detecting/handling circular causal dependencies
        // Should this be allowed or prevented?
    }

    #[test]
    fn test_time_travel_query() {
        // Test querying with reference_time in the future
    }

    #[test]
    fn test_concurrent_consolidation() {
        // Test concurrent access during consolidation
    }
}