fix(evidence): filter active data in every search

This commit is contained in:
2026-07-12 05:40:45 +02:00
parent 92b1d3ccc3
commit 6656a69630
3 changed files with 118 additions and 35 deletions
+69
View File
@@ -250,6 +250,75 @@ def test_active_searcher_without_active_fails_closed_for_evidence(tmp_path):
assert wrapped.search([1.0], kinds=["memory"]) == ["legacy"]
def test_active_searcher_splits_default_and_mixed_kinds_before_global_limit(tmp_path):
from types import SimpleNamespace
from tht.search.evidence import ActiveEvidenceSearcher
store = CorpusStore(tmp_path / "corpus")
generation = store.stage(CorpusManifest(), {}, generation="gen:" + "a" * 32)
store.publish(generation)
calls = []
class Delegate:
def search(self, embedding, top_n=10, kinds=None, metadata_filter=None):
calls.append((kinds, metadata_filter))
if kinds == ["evidence"]:
return [SimpleNamespace(id="active", similarity=0.8)]
return [SimpleNamespace(id="memory", similarity=0.9)]
searcher = ActiveEvidenceSearcher(store, Delegate())
hits = searcher.search([1.0], top_n=1, kinds=["evidence", "memory"])
assert [hit.id for hit in hits] == ["memory"]
assert calls[0] == (["memory"], None)
# Empty manifest means no Evidence query, but the split remains explicit and safe.
assert all(call[0] != ["evidence"] for call in calls)
calls.clear()
searcher.search([1.0], top_n=1)
assert calls[0][0] == ["memory", "schema_column", "schema_table", "solved_question"]
assert all(call[0] is not None for call in calls)
def test_active_evidence_query_holds_lock_against_publish(tmp_path):
import threading
from types import SimpleNamespace
from tht.search.evidence import ActiveEvidenceSearcher
first_pipeline = pipeline(tmp_path, Source([(item("one", "a"), "old")]), vectors=Vectors())
first_pipeline.run()
store = first_pipeline.store
entered = threading.Event()
release = threading.Event()
published = threading.Event()
class Delegate:
def search(self, embedding, top_n=10, kinds=None, metadata_filter=None):
entered.set()
assert release.wait(5)
return [SimpleNamespace(id="active", similarity=1.0)]
search = threading.Thread(
target=lambda: ActiveEvidenceSearcher(store, Delegate()).search(
[1.0], kinds=["evidence"]
)
)
search.start()
assert entered.wait(5)
next_generation = store.stage(CorpusManifest(), {})
def publish():
with store.writer_lock():
store.publish(next_generation)
published.set()
publisher = threading.Thread(target=publish)
publisher.start()
assert not published.wait(0.1)
release.set()
search.join(5)
publisher.join(5)
assert published.is_set()
def test_unchanged_documents_skip_acquire_normalize_chunk_and_embed(tmp_path):
one = item("one", "a")
first_source = Source([(one, "hello")])