test(search): pin _cc's TM2C2 formula directly

_rrf had a pinned unit test but _cc did not, so a sabotaged _cc returning a
constant score for every chunk still passed the existing (indirect,
end-to-end) CC test. Add a direct test of the alpha*sem_norm +
(1-alpha)*lex_norm formula and its per-channel-missing fallbacks.

Verified: with _cc temporarily replaced by "return 0.42 for every chunk",
this test fails while test_cc_fusion_returns_results_too still passes;
restored, both pass.

Test: tests/test_search.py::test_cc_formula_is_pinned
This commit is contained in:
Markus committed 2026-09-12 18:39:00 +00:00
1 parent ba0817c2ef
commit 0bdda896f9
1 file changed
+22
+22
View File
@@ -145,6 +145,28 @@ def test_rrf_formula_is_pinned():
assert scores[2] == pytest.approx(1 / 62)
def test_cc_formula_is_pinned():
"""Direct unit test of TM2C2: alpha*sem_norm + (1-alpha)*lex_norm, with
lex_norm = s/max(s) (theoretical min 0) and sem_norm = (cos+1)/(max+1)
(theoretical min -1) (§8, defect 9). Without this, a sabotaged `_cc` that
just returns a constant still passed the existing (indirect) CC test."""
from mdmem.search import _cc
lex = {1: 10.0, 2: 5.0}
sem = {1: 0.5, 2: 0.9}
scores = _cc(lex, sem, alpha=0.5)
assert scores[1] == pytest.approx(0.5 * ((0.5 + 1.0) / (0.9 + 1.0)) + 0.5 * (10.0 / 10.0))
assert scores[2] == pytest.approx(0.5 * ((0.9 + 1.0) / (0.9 + 1.0)) + 0.5 * (5.0 / 10.0))
# a chunk with only a lexical score: sem_norm falls back to 0
only_lex = _cc({3: 4.0}, {}, alpha=0.3)
assert only_lex[3] == pytest.approx(0.7 * 1.0)
# a chunk with only a semantic score: lex_norm falls back to 0
only_sem = _cc({}, {5: -0.2}, alpha=0.3)
assert only_sem[5] == pytest.approx(0.3 * ((-0.2 + 1.0) / (-0.2 + 1.0)))
async def test_debug_ranks_reflect_the_filtered_set_not_the_raw_channel(svc):
"""lex_rank/sem_rank must match the ranking `_fuse` actually used (over the
post-filter subset), not the ranking over the unfiltered lex/sem dicts."""