diff --git a/tests/test_conflicts.py b/tests/test_conflicts.py index 4c84726..ea40f55 100644 --- a/tests/test_conflicts.py +++ b/tests/test_conflicts.py @@ -67,6 +67,23 @@ def test_chunks_from_one_document_are_not_a_conflict_with_themselves(): assert detect_conflicts([_hit("hr-policy"), _hit("hr-policy")]) == [] +def test_chunks_from_two_official_documents_are_reported_once(): + """Retrieval returns chunks, not documents. One disagreement must not be printed once per + chunk pair.""" + hits = [ + _hit("hr-policy"), + _hit("hr-policy"), + _hit("finance-policy"), + _hit("finance-policy"), + ] + assert len(detect_conflicts(hits)) == 1 + + +def test_official_chunks_do_not_duplicate_an_informal_conflict(): + hits = [_hit("hr-policy"), _hit("hr-policy"), _hit("notes", official=False)] + assert len(detect_conflicts(hits)) == 1 + + def test_a_single_source_of_truth_produces_no_conflict(): assert detect_conflicts([_hit("hr-policy")]) == [] diff --git a/vaultrag/conflicts.py b/vaultrag/conflicts.py index 6947e48..ab52115 100644 --- a/vaultrag/conflicts.py +++ b/vaultrag/conflicts.py @@ -49,11 +49,16 @@ def detect_conflicts(hits: list[Hit]) -> list[Conflict]: """ out: list[Conflict] = [] official = [h for h in hits if h.is_official] + seen: set[frozenset[str]] = set() for i, a in enumerate(official): for b in official[i + 1 :]: if a.doc_id == b.doc_id: continue + pair = frozenset((a.doc_id, b.doc_id)) + if pair in seen: + continue + seen.add(pair) out.append( Conflict( doc_a=a.doc_id, @@ -70,6 +75,10 @@ def detect_conflicts(hits: list[Hit]) -> list[Conflict]: for a in official: for b in unofficial: if a.doc_id != b.doc_id: + pair = frozenset((a.doc_id, b.doc_id)) + if pair in seen: + break + seen.add(pair) out.append( Conflict( doc_a=a.doc_id,