genotype.py:
- Uw/uw aliased to G/g (same locus) so the D2 conflict group + pure-Uw
cases stop being conflicts (Gg == Uwuw).
- Sls/WP recognized as a SECOND spotting locus (S(l)s(l)=WP het); carried
into mapped8locus alongside Sp (Sp+Sls = Superschecke).
- dea/Dea/taub/hörend -> hearing/deaf phenotype FLAG (not a locus).
- WFNZ/RV/GV/DP -> provenance/breeding tags (not genotype, not conflicts).
- test_genotype.py: zero-dep unit tests for all four.
extract.py: surface deaf+tags on animals; dedup conflict detection now
compares the NORMALIZED genotype key (mapped8locus) instead of the raw
string, so Uw=G no longer triggers a conflict. Result: Konflikte 32 -> 27,
Zucht-Splits stays 0. Dedup identity = name + DOB + Zucht.
Backend: Gerbil.IsDeaf (bool?) + additive migration AddGerbilDeafFlag
(has-pending-model-changes clean) + GerbilDto/GerbilInput round-trip.
ImportService sets IsDeaf from animal.deaf and preserves Sls + tags + deaf
in RawImportData (kept out of the 8-locus compact Genotype contract until
GEN-3a adopts them).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- survivedToGoHome: unlabeled Tabelle1 col E detected positionally; value-
adaptive row parsing recovers it from schema-shifted Tabelle2 rows too
(118 recovered, 79 confirmed by the E=F-TG-s identity)
- breakdown G -> males/females/stillborn/diedLater ('s' = died before Abgabe)
- validation: E = F - TG - s; 113 mismatches as German review-report warnings
- (name, Zucht) canonicalisation: [brackets] == of/von suffix ([ZdkC] ==
von den Kleinen Chaoten); Zucht = dedup discriminator (0 splits in data)
- animal->litter matching via DOB+(Vater,Mutter): 95 high-confidence,
40 date-only, 9 ambiguous; litterRef in animals.json
- regenerated report: 889 raw -> 574 unique (279 dated), 32 conflicts
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>