""" Tests for haktarah — transform modality (prose → Prolog propositions). BUILD_KORBAN.md Verification §3: Feed it extracted vital content. Verify the Prolog propositions are syntactically valid and semantically grounded. Architecture §3.5: haktarah converts prose insights into Prolog-compatible propositions for the Talmudic Engine. """ import re from korban_processor.haktarah import ( haktarah, torah_ref_to_prolog, root_to_prolog, extract_claims, extract_connections, sanitize_prolog_string, ) from test.fixtures import CLEAN_TORAH_RESPONSE, LATIN_TORAH_RESPONSE # Valid Prolog term pattern: functor(args...) _PROLOG_TERM_PATTERN = re.compile(r"^\w+\(.*\)$") def is_valid_prolog_term(s: str) -> bool: """Check if a string looks like a valid Prolog term.""" return bool(_PROLOG_TERM_PATTERN.match(s.strip())) class TestTorahRefToProlog: def test_genesis_becomes_bereishit(self): result = torah_ref_to_prolog("Genesis 1:1") assert result == "verse(bereishit, 1, 1)" def test_bereishit_stays_bereishit(self): result = torah_ref_to_prolog("Bereishit 1:1") assert result == "verse(bereishit, 1, 1)" def test_exodus_becomes_shemot(self): result = torah_ref_to_prolog("Exodus 3:14") assert result == "verse(shemot, 3, 14)" def test_leviticus_becomes_vayikra(self): result = torah_ref_to_prolog("Leviticus 19:18") assert result == "verse(vayikra, 19, 18)" def test_numbers_becomes_bamidbar(self): result = torah_ref_to_prolog("Numbers 15:38") assert result == "verse(bamidbar, 15, 38)" def test_deuteronomy_becomes_devarim(self): result = torah_ref_to_prolog("Deuteronomy 6:4") assert result == "verse(devarim, 6, 4)" def test_abbreviated_gen(self): result = torah_ref_to_prolog("Gen. 1:1") assert result == "verse(bereishit, 1, 1)" def test_invalid_ref_returns_empty(self): result = torah_ref_to_prolog("not a reference") assert result == "" class TestRootToProlog: def test_dash_separated_hebrew_root(self): result = root_to_prolog("ר-א-ש") assert result.startswith('root("ראש"') assert "hebrew" in result def test_dot_separated_hebrew_root(self): result = root_to_prolog("ר.א.ש") assert result.startswith('root("ראש"') def test_root_keyword_with_hebrew(self): result = root_to_prolog("root ראש") assert "ראש" in result assert "hebrew" in result def test_transliterated_root(self): result = root_to_prolog("root shin") assert "shin" in result assert "transliterated" in result def test_invalid_root_returns_empty(self): result = root_to_prolog("not a root") assert result == "" class TestExtractClaims: def test_extracts_means_claim(self): text = "The root ר-א-ש means head or beginning." claims = extract_claims(text) assert len(claims) >= 1 assert any('claim(' in c for c in claims) def test_extracts_indicates_claim(self): text = "This passage indicates divine ownership of creation." claims = extract_claims(text) assert len(claims) >= 1 def test_claim_is_valid_prolog_term(self): text = "The root ר-א-ש means head or beginning." claims = extract_claims(text) for claim in claims: assert is_valid_prolog_term(claim), f"Not a valid Prolog term: {claim}" def test_no_claims_returns_empty(self): text = "This is a plain sentence without analytical markers." claims = extract_claims(text) # May be empty — that's fine for claim in claims: assert is_valid_prolog_term(claim) class TestExtractConnections: def test_extracts_connects_to(self): text = "The concept of Shabbat connects to creation cessation." conns = extract_connections(text) assert len(conns) >= 1 assert any('connection(' in c for c in conns) def test_connection_is_valid_prolog_term(self): text = "Rosh Hashana parallels Bereishit through the root ר-א-ש." conns = extract_connections(text) for conn in conns: assert is_valid_prolog_term(conn), f"Not a valid Prolog term: {conn}" class TestSanitizePrologString: def test_escapes_double_quotes(self): result = sanitize_prolog_string('He said "hello"') assert '\\"' in result def test_replaces_newlines(self): result = sanitize_prolog_string("line one\nline two") assert "\n" not in result def test_truncates_long_strings(self): long_str = "x" * 300 result = sanitize_prolog_string(long_str) assert len(result) <= 204 # 200 + "..." class TestHaktarah: def test_returns_list(self): result = haktarah(CLEAN_TORAH_RESPONSE) assert isinstance(result, list) def test_empty_input_returns_empty_list(self): result = haktarah("") assert result == [] def test_all_propositions_are_valid_prolog_terms(self): """BUILD_KORBAN verification §3: Prolog propositions are syntactically valid.""" result = haktarah(CLEAN_TORAH_RESPONSE) assert len(result) > 0 for prop in result: assert is_valid_prolog_term(prop), f"Invalid Prolog term: {prop}" def test_torah_refs_produce_verse_facts(self): """BUILD_KORBAN verification §3: semantically grounded.""" result = haktarah(LATIN_TORAH_RESPONSE) verse_props = [p for p in result if p.startswith("verse(")] assert len(verse_props) >= 3 # 5 books referenced def test_contains_bereishit_verse(self): result = haktarah(CLEAN_TORAH_RESPONSE) assert any("verse(bereishit," in p for p in result) def test_hebrew_roots_produce_root_facts(self): content = "The root ר-א-ש means beginning. Genesis 1:1 uses בְּרֵאשִׁית." result = haktarah(content) root_props = [p for p in result if p.startswith("root(")] assert len(root_props) >= 1 def test_stateless_between_calls(self): """Kiyyor principle: second call unaffected by first.""" result1a = haktarah(CLEAN_TORAH_RESPONSE) _ = haktarah(LATIN_TORAH_RESPONSE) result1b = haktarah(CLEAN_TORAH_RESPONSE) assert result1a == result1b