Files
bikoret/kushya_generator/test/test_kushya_api.py
T
Scott KarpandClaude Fable 5.1 c0d0555aed the name: Bikoret — code, contracts, images
Headers X-Bikoret-Key / -Rebuke / -Verdict / -Bedikah; the `bikoret`
object and the "— bikoret …" fringe on a gate reply; environment
variables BIKORET_*; the image user and paths (/home/bikoret,
/tmp/bikoret, /var/lib/bikoret/manna, /etc/bikoret/secrets,
/opt/bikoret/spec); the tmp-bikoret pod volume; local databases
bikoret_dev/_test. Kubernetes resource names, the shorashim_app role and
the domain are unchanged (Tamid §1.1, "the names that still carry the
old word"). Doorpost c963c4fe…. Elixir 604/0, L3 10/0, korban 295,
Prolog bedikah 44/44. Gitea repo renamed heaviness510/bikoret (old URL
redirects).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 22:13:36 +00:00

125 lines
4.7 KiB
Python

"""
Tests for the kushya generator API.
These tests use mocked external callers; no real API requests are made.
"""
import sys
from pathlib import Path
from unittest.mock import patch
# Add parent inference/ dir
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "inference"))
# Add the bikoret repo's korban_processor src to sys.path
sys.path.insert(
0,
str(Path(__file__).resolve().parent.parent.parent / "korban_processor" / "src"),
)
from kushya_api import KushyaResult, generate_kushya, _extract_refs # noqa: E402
# ============================================================
# Backend selection
# ============================================================
def test_fallback_returns_no_kushya_with_explanation():
"""The fallback path honestly reports no challenge — never invents one."""
result = generate_kushya("Some interpretation.", backend="fallback")
assert isinstance(result, KushyaResult)
assert result.kushya is None
assert result.backend == "fallback"
assert "does not invent" in (result.notes or "")
def test_fine_tuned_without_endpoint_falls_back_in_auto():
"""auto mode skips fine_tuned when no endpoint is configured, then
skips external when not available, ending in fallback."""
# We expect the Korban Processor's external model call to either succeed
# (if API key is present) or fail (if not) — either way, the result has
# a clear backend. Mock to ensure deterministic behavior.
from korban_processor.external_offering import consult_external_model # noqa: F401
with patch("kushya_api.consult_external_model") as mock_consult:
mock_consult.side_effect = RuntimeError("simulated API failure")
result = generate_kushya("Some interpretation.", backend="auto")
assert result.kushya is None
assert result.backend in ("fallback", "external")
def test_fine_tuned_explicit_without_endpoint_raises():
"""When backend='fine_tuned' is forced but no endpoint is configured,
we raise rather than silently falling through."""
import pytest
with pytest.raises(ValueError, match="fine_tuned_endpoint"):
generate_kushya("Some interpretation.", backend="fine_tuned")
# ============================================================
# External backend — mocked, exercises the full eish-zarah path
# ============================================================
def test_external_backend_returns_kushya_via_korban_processor():
"""When external consultation succeeds, the result is recorded with
'external' backend and a notes field that emphasizes it is testimony,
not ruling."""
from kushya_api import _try_external
fake_consultation = type("FakeConsultation", (), {})()
fake_consultation.raw_response = type(
"FakeResponse", (), {"content": "raw response with a question?"}
)()
fake_consultation.processed = type(
"FakeProcessed",
(),
{"vital_content": "What about Shemot 35:3 — does the prohibition extend to passive heating?"},
)()
with patch("kushya_api.consult_external_model", return_value=fake_consultation):
result = _try_external("Cooking on Shabbat is forbidden.", allow_fallback=True)
assert result.kushya
assert result.backend == "external"
assert "testimony" in (result.notes or "").lower()
assert "Shemot 35:3" in result.torah_refs
def test_external_backend_handles_empty_vital_content():
"""If zerikah extracts nothing vital from external response, we
record None — we do not pretend an empty kushya is real."""
from kushya_api import _try_external
fake_consultation = type("FakeConsultation", (), {})()
fake_consultation.raw_response = type("FakeResp", (), {"content": "Great question!"})()
fake_consultation.processed = type("FakeProc", (), {"vital_content": ""})()
with patch("kushya_api.consult_external_model", return_value=fake_consultation):
result = _try_external("Some interp.", allow_fallback=True)
assert result.kushya is None
assert result.backend == "external"
assert "no vital content" in (result.notes or "").lower()
# ============================================================
# Reference extraction
# ============================================================
def test_extract_refs_finds_torah_citations():
text = "What about Shemot 35:3 and also Vayikra 18:5?"
refs = _extract_refs(text)
assert "Shemot 35:3" in refs
assert "Vayikra 18:5" in refs
def test_extract_refs_handles_verse_ranges():
text = "Devarim 21:1-9 and Bereishit 1:1"
refs = _extract_refs(text)
assert any("Devarim 21:1" in r for r in refs)
assert "Bereishit 1:1" in refs
def test_extract_refs_returns_empty_for_no_citations():
assert _extract_refs("This text has no Torah references.") == []