Skip to main content
Glama
test_save_detection.py17.1 kB
""" Unit tests for save detection in natural language activation. This module tests the detect_save_intent function with: - T022: Explicit save triggers ("remember this", "don't forget", "I prefer") - T023: Implicit signals (importance markers, entity count) - T024: Exclusion patterns (general questions, small talk) Tests focus on the decision-making logic, not the underlying pattern matching (which is tested in test_patterns.py). """ import pytest from cortexgraph.activation.config import ActivationConfig, ConfidenceThreshold, PatternLibrary from cortexgraph.activation.detectors import detect_save_intent from cortexgraph.activation.patterns import PatternMatcher @pytest.fixture def save_detection_config(): """Create configuration for save detection testing.""" patterns = PatternLibrary( explicit_save_triggers=["remember this", "don't forget", "i prefer"], explicit_recall_triggers=["what did i say", "remind me"], importance_markers=["critical", "must remember", "very important", "essential"], exclusion_patterns=["what is", "how do", "how does", "can you explain"], uncertainty_markers=["maybe", "might", "not sure", "perhaps"], case_sensitive=False, partial_match=True, ) thresholds = ConfidenceThreshold( auto_save_min=0.7, auto_recall_min=0.7, clarification_min=0.4, clarification_max=0.7, ) weights = { "explicit_save_request": 4.0, "explicit_recall_request": 5.0, "critical_marker": 3.5, "important_marker": 2.5, "uncertainty_marker": -2.0, "preference_statement": 3.0, "entity_count": 0.8, } return ActivationConfig( patterns=patterns, thresholds=thresholds, weights=weights, bias=-2.0, ) @pytest.fixture def save_detection_matcher(save_detection_config): """Create pattern matcher for save detection testing.""" return PatternMatcher(save_detection_config.patterns) # ============================================================================ # T022: EXPLICIT SAVE TRIGGERS # ============================================================================ class TestExplicitSaveTriggers: """Unit tests for explicit save trigger detection (T022). Explicit triggers are phrases that clearly indicate user intent to save: - "Remember this: ..." - "Don't forget: ..." - "I prefer [entity]" """ def test_remember_this_triggers_save(self, save_detection_config, save_detection_matcher): """'Remember this' should trigger save with high confidence.""" result = detect_save_intent( "Remember this: I use PostgreSQL for all my projects", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.7 assert result.phrase_signals.get("save_request") is True def test_dont_forget_triggers_save(self, save_detection_config, save_detection_matcher): """'Don't forget' should trigger save with high confidence.""" result = detect_save_intent( "Don't forget: my API key format is sk-xxx", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.7 assert result.phrase_signals.get("save_request") is True def test_i_prefer_with_entity_triggers_save( self, save_detection_config, save_detection_matcher ): """'I prefer [entity]' should trigger save. Note: The activation module's detect_save_intent correctly handles this via the 'preference_statement' signal. The MCP tool (analyze_message) needs to be updated to use this module (tracked in T026-T028). """ result = detect_save_intent( "I prefer PostgreSQL for my databases", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.5 assert "postgresql" in [e.lower() for e in result.suggested_entities] def test_explicit_trigger_case_insensitive(self, save_detection_config, save_detection_matcher): """Explicit triggers should work regardless of case.""" result = detect_save_intent( "REMEMBER THIS: I always use TypeScript", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.7 def test_explicit_trigger_with_multiple_entities( self, save_detection_config, save_detection_matcher ): """Explicit triggers with multiple entities should have higher confidence.""" result = detect_save_intent( "Remember this: I prefer PostgreSQL for databases and Redis for caching", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.7 # Should extract multiple entities assert len(result.suggested_entities) >= 2 # ============================================================================ # T023: IMPLICIT SAVE SIGNALS # ============================================================================ class TestImplicitSaveSignals: """Unit tests for implicit save signal detection (T023). Implicit signals suggest memory-worthy content without explicit request: - Importance markers ("critical", "must remember") - High entity count (multiple tech names) - Decision/preference statements """ def test_critical_marker_triggers_save(self, save_detection_config, save_detection_matcher): """'Critical' importance marker should trigger save.""" result = detect_save_intent( "This is critical: the API endpoint changed to /v2/users", save_detection_config, save_detection_matcher, ) assert result.should_save is True assert result.confidence >= 0.7 assert result.phrase_signals.get("critical_marker") is True def test_must_remember_marker_triggers_consideration( self, save_detection_config, save_detection_matcher ): """'Must remember' should trigger at least ask-level consideration. Note: With single importance marker and no entities, confidence lands in ask range (0.4-0.7) not auto-save (>0.7). This is by design - the system asks for confirmation rather than auto-saving. """ result = detect_save_intent( "I must remember to use environment variables for secrets", save_detection_config, save_detection_matcher, ) # Should be in ask range (0.4-0.7) or higher assert result.confidence >= 0.4 # Importance marker should be detected assert result.phrase_signals.get("importance_marker") is True def test_very_important_marker_triggers_consideration( self, save_detection_config, save_detection_matcher ): """'Very important' should at least reach ask threshold.""" result = detect_save_intent( "This is very important: always validate user input", save_detection_config, save_detection_matcher, ) # Should at least be in ask range or auto-save assert result.confidence >= 0.4 def test_high_entity_count_increases_confidence( self, save_detection_config, save_detection_matcher ): """Multiple tech entities should increase save confidence.""" # Low entity message result_low = detect_save_intent( "I use Python", save_detection_config, save_detection_matcher, ) # High entity message result_high = detect_save_intent( "I use Python, TypeScript, Rust, and Go for different projects", save_detection_config, save_detection_matcher, ) # Higher entity count should have higher confidence assert result_high.confidence > result_low.confidence assert len(result_high.suggested_entities) >= 3 def test_decision_keyword_boosts_confidence( self, save_detection_config, save_detection_matcher ): """Decision-related keywords should boost save confidence.""" result = detect_save_intent( "I've decided to use FastAPI for all my backend services", save_detection_config, save_detection_matcher, ) assert result.phrase_signals.get("decision_marker") is True # Should have reasonable confidence due to decision + entity assert result.confidence >= 0.4 def test_preference_keyword_boosts_confidence( self, save_detection_config, save_detection_matcher ): """Preference statements should boost save confidence.""" result = detect_save_intent( "My preference is to always use TypeScript over JavaScript", save_detection_config, save_detection_matcher, ) assert result.phrase_signals.get("decision_marker") is True def test_combined_signals_high_confidence(self, save_detection_config, save_detection_matcher): """Multiple positive signals should result in high confidence.""" result = detect_save_intent( "Remember this critical decision: I chose PostgreSQL and Redis", save_detection_config, save_detection_matcher, ) # Explicit trigger + critical marker + entities = very high confidence assert result.should_save is True assert result.confidence >= 0.9 # ============================================================================ # T024: EXCLUSION PATTERNS (SMALL TALK FILTERING) # ============================================================================ class TestExclusionPatterns: """Unit tests for exclusion pattern detection (T024). Exclusion patterns filter out messages that should NOT be saved: - General knowledge questions ("What is X?") - How-to questions ("How do I X?") - Small talk and casual conversation """ def test_what_is_question_excluded(self, save_detection_config, save_detection_matcher): """'What is X?' questions should NOT trigger save.""" result = detect_save_intent( "What is a database index?", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.confidence < 0.4 assert result.phrase_signals.get("exclusion_pattern") is True def test_how_do_question_excluded(self, save_detection_config, save_detection_matcher): """'How do I X?' questions should NOT trigger save.""" result = detect_save_intent( "How do I connect to PostgreSQL?", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.phrase_signals.get("exclusion_pattern") is True def test_how_does_question_excluded(self, save_detection_config, save_detection_matcher): """'How does X?' questions should NOT trigger save.""" result = detect_save_intent( "How does garbage collection work in Python?", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.phrase_signals.get("exclusion_pattern") is True def test_can_you_explain_excluded(self, save_detection_config, save_detection_matcher): """'Can you explain X?' questions should NOT trigger save.""" result = detect_save_intent( "Can you explain async/await in JavaScript?", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.phrase_signals.get("exclusion_pattern") is True def test_exclusion_overrides_entity_count(self, save_detection_config, save_detection_matcher): """Exclusion pattern should override positive entity signals.""" result = detect_save_intent( "What is the difference between PostgreSQL, MySQL, and SQLite?", save_detection_config, save_detection_matcher, ) # Despite having 3 entities, exclusion pattern should keep confidence low assert result.should_save is False assert result.confidence < 0.5 def test_exclusion_does_not_override_explicit_save( self, save_detection_config, save_detection_matcher ): """Explicit save trigger should still work even with exclusion pattern words. Note: This tests edge case where user says something like 'Remember this: what is my database preference?' - which is a recall, but if they say 'Remember this: my preference is PostgreSQL' that's a save. """ result = detect_save_intent( "Remember this: PostgreSQL is my database choice", save_detection_config, save_detection_matcher, ) # Explicit trigger should result in save assert result.should_save is True assert result.confidence >= 0.7 # ============================================================================ # UNCERTAINTY MARKERS # ============================================================================ class TestUncertaintyMarkers: """Unit tests for uncertainty marker detection. Uncertainty reduces confidence in save decision. """ def test_maybe_reduces_confidence(self, save_detection_config, save_detection_matcher): """'Maybe' should reduce save confidence.""" result_certain = detect_save_intent( "I use PostgreSQL for databases", save_detection_config, save_detection_matcher, ) result_uncertain = detect_save_intent( "Maybe I should use PostgreSQL for databases", save_detection_config, save_detection_matcher, ) assert result_uncertain.confidence < result_certain.confidence assert result_uncertain.phrase_signals.get("uncertainty_marker") is True def test_not_sure_reduces_confidence(self, save_detection_config, save_detection_matcher): """'Not sure' should reduce save confidence.""" result = detect_save_intent( "I'm not sure if PostgreSQL is the right choice", save_detection_config, save_detection_matcher, ) assert result.phrase_signals.get("uncertainty_marker") is True # Should have reduced confidence assert result.confidence < 0.7 # ============================================================================ # EDGE CASES # ============================================================================ class TestSaveDetectionEdgeCases: """Edge case tests for save detection.""" def test_empty_message_no_save(self, save_detection_config, save_detection_matcher): """Empty message should not trigger save.""" result = detect_save_intent( "", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.confidence < 0.5 def test_whitespace_only_no_save(self, save_detection_config, save_detection_matcher): """Whitespace-only message should not trigger save.""" result = detect_save_intent( " \n\t ", save_detection_config, save_detection_matcher, ) assert result.should_save is False def test_very_short_message_no_save(self, save_detection_config, save_detection_matcher): """Very short messages typically shouldn't trigger save.""" result = detect_save_intent( "Hi", save_detection_config, save_detection_matcher, ) assert result.should_save is False assert result.confidence < 0.5 def test_very_long_message_handled(self, save_detection_config, save_detection_matcher): """Very long messages should be handled without error.""" long_message = "Remember this: " + "PostgreSQL " * 500 result = detect_save_intent( long_message, save_detection_config, save_detection_matcher, ) # Should still work assert result.should_save is True assert result.confidence >= 0.5 def test_unicode_handled(self, save_detection_config, save_detection_matcher): """Unicode characters should be handled correctly.""" result = detect_save_intent( "Remember this: my café database uses PostgreSQL ☕", save_detection_config, save_detection_matcher, ) assert result.should_save is True

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prefrontalsys/mnemex'

If you have feedback or need assistance with the MCP directory API, please join our Discord server