"""Pattern desk: embedded scar recall + strategy gating in the scouting desk.""" from __future__ import annotations import hashlib import importlib import numpy as np import pytest def _idx(w: str) -> int: # Stable across processes (unlike hash()), so threshold tests aren't flaky. return int.from_bytes(hashlib.md5(w.encode()).digest()[:4], "little") % 256 def _fake_embed(texts): out = [] for t in texts: v = np.zeros(256, dtype=np.float32) for w in t.lower().split(): v[_idx(w)] += 1.0 out.append((v if v.any() else np.full(256, 1e-6, dtype=np.float32)).tolist()) return out @pytest.fixture def mods(tmp_path, monkeypatch): monkeypatch.setenv("LYRA_DB_PATH", str(tmp_path / "test.db")) from lyra import llm monkeypatch.setattr(llm, "embed", _fake_embed) import lyra.memory as memory importlib.reload(memory) import lyra.poker as poker importlib.reload(poker) import lyra.scouting as scouting importlib.reload(scouting) return poker, scouting def test_scar_recall_finds_similar_past_leak(mods): poker, _ = mods old = poker.start_session(stakes="1/3", buy_in=300) poker.log_ritual("scar", "overvalued top pair and stacked off on a wet board", classification="punt", session_id=old) poker.end_session(200, session_id=old) hits = poker.recall_similar_rituals("stacked off top pair wet board again") assert hits and hits[0]["classification"] == "punt" def test_recall_excludes_current_session(mods): poker, _ = mods sid = poker.start_session(stakes="1/3", buy_in=300) poker.log_ritual("scar", "punted river bluff into the nut flush", session_id=sid) assert poker.recall_similar_rituals("river bluff nut flush punt", exclude_session=sid) == [] def test_pattern_pass_only_fires_on_strategic_talk(mods): poker, scouting = mods old = poker.start_session(stakes="1/3", buy_in=300) poker.log_ritual("scar", "punting river bluffs into missed draws again", classification="punt", session_id=old) poker.end_session(200, session_id=old) poker.start_session(stakes="1/3", buy_in=300, venue="Meadows") # A routine, non-strategic line pays no embed and surfaces nothing. assert scouting.scout("stack is 350 now", venue="Meadows") is None # A real strategy question in the same shape recalls the leak. (The test stub # embeds by shared tokens; real embeddings match on meaning/paraphrase.) note = scouting.scout( "why do i keep punting river bluffs into missed draws", venue="Meadows") assert note and "punting river bluffs" in note