dedup: 'presence wins' — present-vs-absent token is not a conflict (Julian)
Breeder merge rule: when two source variants of the SAME animal differ ONLY by a token PRESENT in one and ABSENT in the other — a whole locus (e.g. spsp charted in one source, omitted in another) or a modifier on the same base allele (e^f vs e, the [f] marker) — keep the present token; that is NOT a conflict. Genuine VALUE contradictions still quarantine: different base alleles (Ee↔ee), unknown-vs-filled (D-↔DD), different modifiers (c[h]↔c[chm]), C-↔Cc[h], P-↔Pp. Replaces the old `len(distinct normalized geno keys) > 1` test with _genotype_conflict() (per-locus, per-allele compatibility; '?'-vs-filled is a contradiction, modifier-present-vs-absent and whole-locus-absence are not). Markers/flags (WP/DP/WFNZ/hörend) are already tags/flags, never genotype, so they never reach conflict detection; empty Farbschlag/death already don't conflict (only non-empty values are compared). Clears Daja (keep spsp), Ichika (keep ee[f]) and the D4 marker cases: Konflikte 19 -> 15. test_extract covers spsp/[f] present-vs-absent = no conflict and the four genuine-contradiction shapes. python + dotnet 121/121 green; extractor-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -104,6 +104,23 @@ check("missing decisions file tolerated (returns 0)",
|
||||
try: os.remove(dec_path)
|
||||
except OSError: pass
|
||||
|
||||
# --- "presence wins" conflict rule (Julian) ---
|
||||
# present-vs-absent (whole locus or [f] modifier) is NOT a conflict; differing filled values are.
|
||||
check("spsp present vs locus absent -> no conflict",
|
||||
not e._genotype_conflict([{"Sp": ["sp", "sp"]}, {}]))
|
||||
check("ee[f] vs ee ([f] modifier present/absent) -> no conflict",
|
||||
not e._genotype_conflict([{"E": ["e", "e^f"]}, {"E": ["e", "e"]}]))
|
||||
check("DD vs D- (unknown vs filled) -> conflict",
|
||||
e._genotype_conflict([{"D": ["D", "D"]}, {"D": ["D", "?"]}]))
|
||||
check("Ee vs ee (different base allele) -> conflict",
|
||||
e._genotype_conflict([{"E": ["E", "e"]}, {"E": ["e", "e"]}]))
|
||||
check("C- vs Cc[h] -> conflict",
|
||||
e._genotype_conflict([{"C": ["C", "?"]}, {"C": ["C", "c^h"]}]))
|
||||
check("c[h] vs c[chm] (different modifiers) -> conflict",
|
||||
not e._alleles_compatible("c^h", "c^chm"))
|
||||
check("identical genotypes -> no conflict",
|
||||
not e._genotype_conflict([{"A": ["A", "a"]}, {"A": ["A", "a"]}]))
|
||||
|
||||
# --- name-bleed guard (a parent name is not a Farbschlag) ---
|
||||
check("v.d. name rejected", e.looks_like_animal_name("Tennessee von den Kleinen Chaoten"))
|
||||
check("gen.+v.d. name rejected", e.looks_like_animal_name("Victoria Welby gen. Welby v.d. Kleinen Chaoten"))
|
||||
|
||||
Reference in New Issue
Block a user