diff --git a/src/atocore/memory/service.py b/src/atocore/memory/service.py index 81e73d0..fdff6cd 100644 --- a/src/atocore/memory/service.py +++ b/src/atocore/memory/service.py @@ -50,6 +50,9 @@ MEMORY_STATUSES = [ "graduated", # Phase 5: memory has become an entity; content frozen, forward pointer in properties ] +DEFAULT_CONTEXT_MEMORY_LIMIT = 30 +QUERY_CONTEXT_MEMORY_LIMIT = 120 + @dataclass class Memory: @@ -909,12 +912,13 @@ def get_memories_for_context( # ``_rank_memories_for_query`` via Python's stable sort. pool: list[Memory] = [] seen_ids: set[str] = set() + candidate_limit = QUERY_CONTEXT_MEMORY_LIMIT if query_tokens is not None else DEFAULT_CONTEXT_MEMORY_LIMIT for mtype in memory_types: for mem in get_memories( memory_type=mtype, project=project, min_confidence=0.5, - limit=30, + limit=candidate_limit, ): if mem.id in seen_ids: continue diff --git a/tests/test_memory.py b/tests/test_memory.py index fd41692..9b41a46 100644 --- a/tests/test_memory.py +++ b/tests/test_memory.py @@ -498,6 +498,66 @@ def test_project_memory_ranking_prefers_multiple_intent_hits(isolated_db): assert "Zygo" in text +def test_project_memory_query_ranks_beyond_confidence_prefilter(isolated_db): + """Query-time ranking should see older low-confidence but exact-intent memories.""" + from atocore.memory.service import create_memory, get_memories_for_context + + for idx in range(35): + create_memory( + "project", + f"High confidence p06 filler memory {idx}: Polisher Control planning note.", + project="p06-polisher", + confidence=0.9, + ) + create_memory( + "project", + "Use Tailscale mesh for RPi remote access to provide SSH, file transfer, and NAT traversal without port forwarding.", + project="p06-polisher", + confidence=0.5, + ) + + text, _ = get_memories_for_context( + memory_types=["project"], + project="p06-polisher", + budget=360, + query="how do we access the polisher machine remotely", + ) + + assert "Tailscale" in text + + +def test_project_memory_query_prefers_exact_cam_fact(isolated_db): + from atocore.memory.service import create_memory, get_memories_for_context + + create_memory( + "project", + "Polisher Control firmware spec document titled 'Fulum Polisher Machine Control Firmware Spec v1' lives in PKM.", + project="p06-polisher", + confidence=0.9, + ) + create_memory( + "project", + "Polisher Control doc must cover manual mode for Norman as a required deliverable per the plan.", + project="p06-polisher", + confidence=0.9, + ) + create_memory( + "project", + "Cam amplitude and offset are mechanically set by operator and read via encoders; no actuators control them.", + project="p06-polisher", + confidence=0.5, + ) + + text, _ = get_memories_for_context( + memory_types=["project"], + project="p06-polisher", + budget=300, + query="how is cam amplitude controlled on the polisher", + ) + + assert "encoders" in text + + def test_expire_stale_candidates_keeps_reinforced(isolated_db): from atocore.memory.service import create_memory, expire_stale_candidates from atocore.models.database import get_connection