"""#232 — the source_kind selector must not silently hide a corpus. `search_precedent_library` defaulted to source_kind='external_upload' all the way down the stack, so 104 appeals-committee decisions (29% of the corpus) were unreachable through the entry point the writing agents actually call. These tests pin the selector semantics; the end-to-end retrieval check lives in scripts/test_retrieval_by_name.py (needs a live DB). """ import pytest from legal_mcp.services.db import _source_kind_clause def test_empty_selector_means_no_filter(): """'' and 'all' must produce no predicate — the whole corpus.""" assert _source_kind_clause("") == "" assert _source_kind_clause("all") == "" assert _source_kind_clause(" ") == "" def test_named_kinds_produce_equality_predicate(): assert _source_kind_clause("internal_committee", "cl.") == ( "cl.source_kind = 'internal_committee'" ) assert _source_kind_clause("external_upload") == "source_kind = 'external_upload'" def test_all_committees_expands_to_both_shapes(): """Committee decisions live under two historical shapes — cover both.""" clause = _source_kind_clause("all_committees", "cl.") assert "cl.source_kind = 'internal_committee'" in clause assert "cl.source_type = 'appeals_committee'" in clause assert clause.startswith("(") and clause.endswith(")") def test_unknown_selector_raises_rather_than_reaching_sql(): """The value is f-string-interpolated, so the whitelist is the guard.""" with pytest.raises(ValueError, match="source_kind"): _source_kind_clause("'; DROP TABLE case_law; --") with pytest.raises(ValueError): _source_kind_clause("internal") def test_default_of_the_search_entry_points_is_whole_corpus(): """A regression guard on the defaults themselves — this is the bug.""" import inspect from legal_mcp.services import hybrid_search, precedent_library from legal_mcp.services import db as db_mod from legal_mcp.tools import precedent_library as plib_tool for fn in ( db_mod.search_precedent_library_semantic, db_mod.search_precedent_library_lexical, db_mod.list_external_case_law, hybrid_search.search_precedent_library_hybrid, precedent_library.search_library, precedent_library.list_precedents, plib_tool.search_precedent_library, plib_tool.precedent_library_list, ): default = inspect.signature(fn).parameters["source_kind"].default assert default == "", ( f"{fn.__module__}.{fn.__qualname__} defaults source_kind to " f"{default!r} — that hides a corpus from every caller (#232)" )