"""
Recollection rendering tests — hit path, zero-hit path, pending-conflict marker,
and prompt injection position.
"""
import pytest
from festinger import cache
from festinger.recollection import (
query_edges, render_hit, render_zero_hit,
build_recollection_block, inject_recollection,
)
from tests.helpers import reset_cache, add_soas, add_urd
class TestHitPath:
def setup_method(self):
reset_cache()
self.michigan = add_soas(101, "michigan", saliency=1.5)
self.usa = add_soas(102, "usa", saliency=0.8)
self.geography = add_soas(5, "geography", saliency=0.0)
self.state = add_soas(103, "state", saliency=0.7)
self.type_dim = add_soas(1, "type", saliency=0.0)
add_urd(concept_id=101, parent_id=102, dim_id=5, is_isa=False, confidence=0.9)
add_urd(concept_id=101, parent_id=103, dim_id=1, is_isa=True, confidence=0.9)
def test_query_returns_both_edges(self):
edges = query_edges(101, confidence_floor=0.5, recency_days=90)
assert len(edges) == 2
def test_render_hit_format(self):
edges = query_edges(101, confidence_floor=0.5, recency_days=90)
line = render_hit("michigan", edges, concept_id=101)
assert line.startswith("michigan:")
assert "[geography] usa" in line
assert "[type] state" in line
def test_pending_conflict_adds_question_mark(self):
cache.pending_conflicts.add(101)
edges = query_edges(101, confidence_floor=0.5, recency_days=90)
line = render_hit("michigan", edges, concept_id=101)
# All dim labels should have ? when concept has pending conflict
assert "[geography?]" in line or "[type?]" in line
def test_confidence_floor_filters_edges(self):
# Add a low-confidence edge
add_urd(concept_id=101, parent_id=5, dim_id=5, is_isa=False, confidence=0.2)
edges = query_edges(101, confidence_floor=0.6, recency_days=90)
# Should not include the 0.2 confidence edge
low_conf = [e for e in edges if e.confidence < 0.6]
assert low_conf == []
def test_block_contains_recollection_tags(self):
block = build_recollection_block([101], confidence_floor=0.5, recency_days=90)
assert block is not None
assert block.startswith("")
assert block.endswith("")
class TestZeroHitPath:
def setup_method(self):
reset_cache()
add_soas(201, "ramanujan", saliency=1.5)
# No URD edges for ramanujan
def test_zero_hit_render(self):
line = render_zero_hit("ramanujan")
assert "ramanujan" in line
assert "no recollection" in line
assert "gutask iknowthat" in line
def test_zero_hit_in_block(self):
block = build_recollection_block([201], confidence_floor=0.5, recency_days=90)
assert block is not None
assert "? ramanujan" in block
assert "gutask iknowthat" in block
def test_block_is_none_when_no_salient_concepts(self):
block = build_recollection_block([], confidence_floor=0.5, recency_days=90)
assert block is None
class TestPromptInjection:
def setup_method(self):
reset_cache()
add_soas(101, "michigan", saliency=1.5)
add_soas(102, "usa", saliency=0.8)
add_soas(5, "geography", saliency=0.0)
add_urd(concept_id=101, parent_id=102, dim_id=5, is_isa=False, confidence=0.9)
def _block(self):
return build_recollection_block([101], confidence_floor=0.5, recency_days=90)
def test_injected_into_existing_system_message(self):
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me about michigan."},
]
block = self._block()
result = inject_recollection(messages, block)
system = next(m for m in result if m["role"] == "system")
assert system["content"].startswith("")
assert "You are a helpful assistant." in system["content"]
def test_injected_at_position_0_when_no_system_message(self):
messages = [{"role": "user", "content": "Tell me about michigan."}]
block = self._block()
result = inject_recollection(messages, block)
assert result[0]["role"] == "system"
assert "" in result[0]["content"]
assert result[1]["role"] == "user"
def test_original_messages_not_mutated(self):
original = [
{"role": "system", "content": "You are helpful."},
{"role": "user", "content": "michigan?"},
]
inject_recollection(original, self._block())
# Original list and dicts must be unchanged
assert original[0]["content"] == "You are helpful."
def test_user_message_preserved_after_injection(self):
messages = [
{"role": "system", "content": "System prompt."},
{"role": "user", "content": "michigan?"},
]
result = inject_recollection(messages, self._block())
user_msgs = [m for m in result if m["role"] == "user"]
assert user_msgs[0]["content"] == "michigan?"