"""Tests for the admission control module. Tests the AdmissionController scoring logic across all four axes: type_score, novelty_score, utility_score, size_score, and the threshold-based admit/reject decision. """ from __future__ import annotations from mnemosyne.admission import AdmissionController, AdmissionScore, DEFAULT_THRESHOLD # ── Type score ─────────────────────────────────────────────────────────── def test_admission_score_design_decision(): """design_decision has the highest type weight (0.9).""" ctrl = AdmissionController() score = ctrl.score("x" * 300, "design_decision", has_duplicate=False) assert score.type_score == 0.9 def test_admission_score_conversation_phase(): """conversation_phase has the lowest type weight (0.3).""" ctrl = AdmissionController() score = ctrl.score("x" * 300, "conversation_phase", has_duplicate=False) assert score.type_score == 0.3 def test_admission_unknown_type_default(): """Unknown object types default to 0.3.""" ctrl = AdmissionController() score = ctrl.score("x" * 300, "totally_unknown_type", has_duplicate=False) assert score.type_score == 0.3 # ── Novelty score ──────────────────────────────────────────────────────── def test_admission_duplicate_penalized(): """Duplicates get novelty_score=0.2 instead of 1.0.""" ctrl = AdmissionController() score_unique = ctrl.score("x" * 300, "file_context", has_duplicate=False) score_dup = ctrl.score("x" * 300, "file_context", has_duplicate=True) assert score_unique.novelty_score == 1.0 assert score_dup.novelty_score == 0.2 assert score_dup.total < score_unique.total # ── Utility score ──────────────────────────────────────────────────────── def test_admission_utility_code_blocks(): """Content with code blocks gets utility boost.""" ctrl = AdmissionController() content_with_code = "Here is code:\n```python\ndef foo(): pass\n```\n" + "x" * 200 content_plain = "Just some plain text without code blocks. " + "x" * 200 score_code = ctrl.score(content_with_code, "file_context", has_duplicate=False) score_plain = ctrl.score(content_plain, "file_context", has_duplicate=False) assert score_code.utility_score > score_plain.utility_score def test_admission_utility_entities(): """Content with many key_entities gets utility boost.""" ctrl = AdmissionController() entities = ["foo.py", "bar.py", "baz.py"] score_with = ctrl.score("x" * 300, "file_context", has_duplicate=False, key_entities=entities) score_without = ctrl.score("x" * 300, "file_context", has_duplicate=False, key_entities=[]) assert score_with.utility_score > score_without.utility_score # ── Size score ─────────────────────────────────────────────────────────── def test_admission_size_small_penalized(): """Very small content (< 100 chars) gets penalized size_score.""" ctrl = AdmissionController() score = ctrl.score("tiny", "file_context", has_duplicate=False) assert score.size_score < 1.0 assert score.size_score == len("tiny") / 100 def test_admission_size_large_penalized(): """Very large content (> 50k chars) gets penalized size_score.""" ctrl = AdmissionController() score = ctrl.score("x" * 80000, "file_context", has_duplicate=False) assert score.size_score < 1.0 assert score.size_score >= 0.3 def test_admission_size_normal(): """Normal-sized content (100-50k chars) gets size_score=1.0.""" ctrl = AdmissionController() score = ctrl.score("x" * 500, "file_context", has_duplicate=False) assert score.size_score == 1.0 # ── Threshold decisions ────────────────────────────────────────────────── def test_admission_threshold_admit(): """High-value content is admitted.""" ctrl = AdmissionController() # design_decision (0.9 type) + unique (1.0 novelty) + code + entities + length content = "```python\ndef important(): pass\n```\n" + "x" * 300 admitted, score = ctrl.should_admit( content, "design_decision", has_duplicate=False, key_entities=["foo.py", "bar.py", "baz.py"], ) assert admitted is True assert score.total >= DEFAULT_THRESHOLD def test_admission_threshold_reject(): """Low-value duplicate conversation_phase is rejected.""" ctrl = AdmissionController() # conversation_phase (0.3 type) + duplicate (0.2 novelty) + tiny content admitted, score = ctrl.should_admit("hi", "conversation_phase", has_duplicate=True) assert admitted is False assert score.total < DEFAULT_THRESHOLD # ── Stats tracking ─────────────────────────────────────────────────────── def test_admission_stats_tracking(): """Stats correctly count admitted and rejected objects.""" ctrl = AdmissionController() assert ctrl.stats == {"admitted": 0, "rejected": 0} # Admit a high-value object ctrl.should_admit( "```python\ndef foo(): pass\n```\n" + "x" * 300, "design_decision", has_duplicate=False, key_entities=["a.py", "b.py", "c.py"], ) assert ctrl.stats["admitted"] == 1 # Reject a low-value object ctrl.should_admit("hi", "conversation_phase", has_duplicate=True) assert ctrl.stats["rejected"] == 1 assert ctrl.stats["admitted"] == 1 # ── Edge cases ─────────────────────────────────────────────────────────── def test_admission_empty_content(): """Empty content gets size_score=0 and low utility.""" ctrl = AdmissionController() score = ctrl.score("", "file_context", has_duplicate=False) assert score.size_score == 0.0 assert score.utility_score == 0.0