Commit Graph

237 Commits

Author SHA1 Message Date
aa345aa796 data(import): D3 Milka resolved (Cc[h], EE) — Julian 2026-06-06 12:08:14 +02:00
0317c5d454 Merge feature/extract-band-aware: band-aware Farbschlag + conflict-decisions consumption + GEN-3f backend re-seed (ReseedColorVarietiesGen3f) [god-QA pending] 2026-06-06 12:05:02 +02:00
ea8c3e9966 Merge feature/bestand-filter: Tiere list defaults nur-Bestand + toggle + Extern marker [god-QA pending] 2026-06-06 12:05:02 +02:00
4d3383a4f1 data(import): D3 Zuleika resolved (DD Ee Gg PP) — Julian 2026-06-06 12:04:30 +02:00
19a0a6c79b data(import): 'presence wins' merge rule (Julian) — resolves Daja (spsp) + Ichika ([f]); D4 markers were common, 3/5 auto-resolved 2026-06-06 12:02:29 +02:00
b9033238c9 conflict-decisions: also apply dateOfDeath (D5 death-date resolutions)
god extended conflict-decisions.json with an optional dateOfDeath
(DD.MM.YYYY). apply_conflict_decisions now sets the animal's death date
(normalized) as authoritative when present — clearing D5 death-date
conflicts the same way genotype/farbschlag decisions are applied. No C#
change (death already flows to Gerbil.DateOfDeath). test_extract covers a
Flint dateOfDeath resolution. python green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 12:02:18 +02:00
594923e10f GEN-3f backend re-seed: ColorVariety catalog 73 -> 61 (CP- names)
Re-synced SeedColorVarieties from Kevin's merged GEN-3f frontend seed
(colorVarietySeed.generated.json, 61 rows) — verified byte-identical
(name + canonicalGenotype + order). Changes are all in the cchm colourpoint
group: 'Siam (Marder-Hell)' -> 'Siam' (het cchmch), CP suffix names ->
CP- prefix (CP-Agouti/CP-Silberagouti/CP-Algierfuchs/CP-Polarfuchs), new
CP-Fuchs/CP-Fuchs-Hell/CP-Blaufuchs, Zobel-Hell kept (het); 12 zero-
occurrence CP/dd siblings removed.

Migration ReseedColorVarietiesGen3f: Up = 38 UpdateData (rename/remap IN
PLACE on the same deterministic Id — references survive) + 12 DeleteData of
the removed rows (0 occurrences in her data per Kevin; Gerbil.ColorVarietyId
is ON DELETE SET NULL, and the live re-import re-matches Farbschlag BY NAME,
so no orphan/hard-delete risk). No AddColumn. has-pending-model-changes
clean. Updated the export test's seed-count threshold (>=70 -> >=60).

Last of the import-side batch on this branch (band-aware Farbschlag +
conflict-decisions + this re-seed) — ready for the single supervised
re-extract + idempotent re-import. dotnet 121/121 + python green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:59:57 +02:00
aa20d6f809 data(import): D5 Molly resolved (died 03.05.2022, 2021 was year typo) — Julian 2026-06-06 11:59:51 +02:00
afd321ec9f BESTAND-FILTER: Tiere-Liste zeigt standardmäßig nur den eigenen Bestand
Die Tiere-Liste (/rennmaeuse) filtert serverseitig auf isResident==true
(eigener Clan = Bestand) und blendet externe Ahnen (nur für den Stammbaum
erfasste Fremdtiere) standardmäßig aus — passend zu Julians Modell
(Kleine Chaoten = Bestand, extern = stammbaum-only).

- Neuer Schalter „Externe Ahnen einblenden“ (Default aus). An -> isResident-
  Filter entfällt, externe Tiere erscheinen mit. Serverseitig (Gridify), damit
  Paging und Trefferzahl korrekt bleiben. „Filter zurücksetzen“ setzt ihn zurück.
- Subtile „Extern“-Markierung (gestricheltes Badge) auf externen Tieren in
  Liste UND Detailseite, mit Tooltip-Erläuterung.
- Gerbil-Typ um isResident (optional bool) ergänzt; CreateGerbil ebenso.

Deutsch via de.ts (LF), mobil + Laptop. e2e-Mock: gerbil()-Factory setzt
isResident=true; Hilde & Max als externe Ahnen (isResident=false). Neue
e2e bestand.spec (Default blendet aus; Toggle zeigt + Extern-Markierung).
Gate grün: build, eslint, vitest 78, e2e 84.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:59:19 +02:00
ae825ae80a data(import): D5 Flint resolved (died 10.05.2021, 2022 was typo) + decisions schema gains dateOfDeath — Julian 2026-06-06 11:59:10 +02:00
e055061d85 docs(HUMANQUESTION): D3+D4 — show CONCRETE per-animal conflict (locus + both values); D4 markers were common (not the conflict), 3/5 auto-resolved; Chelsea=DOB-dup not genotype; Victoria Welby=C's mother 2026-06-06 11:57:54 +02:00
df13136955 Importer consumes conflict-decisions.json to un-quarantine (HUMANQUESTION D)
god maintains tools/import/conflict-decisions.json as Julian/his wife answer
the D-conflicts. extract.py now consumes it (apply_conflict_decisions): for an
animal matching normalize(name)+dob, it clears the conflict, marks
resolvedByDecision, and — when the decision carries a `genotype` (breeder
notation, parsed via genotype.py) and/or `farbschlag` — treats those as
AUTHORITATIVE. Tolerates a missing/empty/garbled file. Genuinely-unresolved
conflicts stay quarantined.

Loader (ImportService): SourceAnimal.ResolvedByDecision flows through; the
report surfaces Animals.ConflictsResolvedByDecision + a German note.

Result on real data: the 2 current decisions (Firefly D-/PP, WildFire PP)
un-quarantine → Konflikte 21 → 19. As god appends entries the count grows;
nothing else needed from me.

Tests: python test_extract (decision clears conflict + genotype authoritative
+ removes from conflicts list + tolerates missing file) and a C# loader test
(a resolved animal loads and is counted). Folded into the EXTRACT-BANDS branch
so the next re-extract applies band-aware Farbschlag + these decisions in one
pass. No schema change (JSON DTO fields). python + dotnet 121/121 green;
has-pending clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:56:29 +02:00
4aca1d528b EXTRACT band-aware Farbschlag: deep bands (gen>=2) have no colour cell
Julian-confirmed against the real xlsx (Kentucky, Akio Kids): pedigree
blocks have two shapes. EARLY bands (gen 0-1, cols B/E/H) are 5-cell
Name/DOB/Farbschlag/Genotype/Zucht — real Farbschlag present. DEEP bands
(gen>=2, cols K/N/Q...) are 3-cell Name/DOB/Genotype with NO Farbschlag —
the colour is derived from the genotype.

The old extractor grabbed the NEXT block's name or a stray health note
(e.g. "DD-Tumor", "Chronische Ohrenentzündung...") as the deep-band
Farbschlag — source of the D1 'name-in-Farbschlag' conflicts and a big
chunk of farbschlagUnmatched. Fix: gen_of(col)>=2 => never assign a
Farbschlag in that block (Name/DOB/Genotype only); the cell is left for the
next block's name search. Deep-band animals load with empty Farbschlag and
the UI computes 'Errechnet' from the stored genotype (lossless).

Dedup already prefers a real (non-empty) early-band Farbschlag, so an animal
appearing in both an early band (Chesnut -> 'Kohlfuchsschimmel') and deep
bands keeps the real value; Chesnut and Tennessee stay separate (distinct
genotype + name+DOB key).

Result: 248/306 loadable animals now have empty Farbschlag (genotype-
derived), 0 suspicious name/note values remain, 0 Farbschlag-based conflicts
(D1 dissolved). Regression test test_extract.py builds a two-band xlsx and
asserts the deep band yields no Farbschlag + the stray note doesn't bleed.

Extractor-only (no C# change). python test_genotype + test_extract green;
dotnet 118/118. Batches with Kevin's GEN-3f seed for one re-import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:56:29 +02:00
4e02133d95 docs(HUMANQUESTION): add C9 (optional) — CP-Fuchs/CP-Blaufuchs/CP-Fuchs-Hell genetic distinction for engine refinement 2026-06-06 11:53:14 +02:00
f3efd4aa2b Merge feature/gen-3f: c-locus seed/catalog reconciliation 73→61 (CP- prefix, collapse -Hell, Siam; computed==dropdown) [god-QA pending] 2026-06-06 11:51:46 +02:00
461d7feb2d data(import): D3 WildFire resolved (PP correct, not P-) — Julian 2026-06-06 11:50:25 +02:00
7536aba474 data(import): conflict-decisions.json + D3 Firefly resolved (D- correct, DD typo) — Julian 2026-06-06 11:49:35 +02:00
972570b142 GEN-3f: reconcile cchm colourpoint catalog to the breeder's CP- naming
Computed Farbschlag now == the breeder's dropdown/seed names for colourpoints,
so the mismatch hint stops and the live re-import name-matches her data
(god: she uses the CP- prefix form + Marder/Siam/Zobel/Zobel-Hell; ZERO of the
old portal suffix names). FULL collapse (god-approved, data-safe).

Catalog (BASE_COLORS) 73 -> 61: the 24 portal cchm rows collapse to 12 breeder
varieties — Marder, Siam, Zobel, Zobel-Hell (aa marten/sable group; E & D
irrelevant per the merged GEN-3e rule) and CP-Agouti, CP-Silberagouti,
CP-Algierfuchs, CP-Polarfuchs, CP-Fuchs, CP-Fuchs-Hell, CP-Blaufuchs,
CP-Orangeschimmel (A- 'CP-<base>'; -Hell shade variants collapsed).

- representativeGenotype() now splits a heterozygous 'x/y' token, so the het
  colourpoints Siam & Zobel-Hell (C: 'cchm/ch') carry the correct het canonical
  genotype and the engine computes their own names (verified).
- Engine covers all fox(ee)/dilute(dd) A- cchm bases via the E-family fallback
  (no Unbekannt). KNOWN BEST-EFFORT GAP: CP-Fuchs-Hell and CP-Blaufuchs both
  compute 'CP-Fuchs' (the het-lighter / blue-dilute distinction isn't encoded);
  their distinct rows remain for hand-pick + import name-match. Closing this
  fully needs the breeder's exact fox-CP genotype rule.

Regenerated colorVarietySeed.generated.json (61 rows) for Pam's re-seed
migration. Gate green: build, eslint, vitest 78, e2e 80. de.ts untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:47:40 +02:00
029ffb9895 docs(HUMANQUESTION): D1 resolved — col K+ has no Farbschlag (only gencode), colour derived from genotype; Chesnut≠Tennessee; fix dispatched 2026-06-06 11:45:11 +02:00
6decd59ce4 docs(HUMANQUESTION): D1 — add source Stammbaum file per name-bleed conflict + note importer auto-strips them 2026-06-06 11:39:10 +02:00
f015274d28 Merge feature/import-fk-fix: stage litters+save-once (insert ordering) + FK-integrity guard + dry-run ParentFksDropped/DerivedSkipped, SQLite FK regression tests [god-QA pending] 2026-06-06 11:36:03 +02:00
fd48f7fc09 Fix import FK fault: derived/back-linked litter referenced a not-yet-inserted parent
BUG (blocked the supervised live re-import): /import/execute threw
Npgsql 23503 FK_Litters_Gerbils_FatherId and rolled back. Root cause was
INSERT ORDERING — synthesized derived litters were SaveChanges()'d BEFORE
the parent gerbils (created later in the animal loop), so the litter's
Father/MotherId pointed at rows that didn't exist yet. The dry-run and the
EF in-memory test provider don't enforce FKs, so it slipped through.

Fix:
- Stage synthesized litters in the context but DON'T save them early; the
  single SaveChanges after the animal loop lets EF order parents → litters →
  offspring (all FKs nullable). Saving litters first was the fault.
- FK-integrity guard (god's spec): compute the persisted set (existing DB +
  this run's loadable) and null out any litter parent FK not in it; SKIP a
  derived litter whose BOTH parents are unresolvable (offspring loads with
  LitterId=null). Quarantined parents already resolve to null via
  ResolveParentGid; this is defense-in-depth + makes the invariant explicit.
- Report litterParentFksDropped + derivedLittersSkipped (LitterSummary) +
  a German note — so a green dry-run (0/0) GUARANTEES execute won't FK-fault.

Tests: two SQLite-backed regressions (SQLite enforces FKs, unlike the
in-memory provider) — a derived litter with NEW chart parents executes
without throwing, and a quarantined parent leaves that FK null. 120 C#
tests + python green; no schema change (has-pending clean).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:32:44 +02:00
105e63b9c4 Merge feature/inbox-1: Anfragen-Posteingang UI (list/triage/assign/draft/send) [god-QA pending]
# Conflicts:
#	gerbil-manager-web/e2e/mock-data.ts
#	gerbil-manager-web/src/App.tsx
2026-06-06 11:29:21 +02:00
0334fce275 Merge feature/web-0b: CMS admin UI /webseite (page+block editor, reorder, draft/publish status) [god-QA pending] 2026-06-06 11:25:55 +02:00
aaaf5b6fb7 INBOX-1: Anfragen-Posteingang UI - Liste (Status-Filter, Sync-Button mit MailNotConfigured-Hinweis), Detail (Triage/Zuordnen/Verwerfen, KI-Entwurf mit AiKeyMissing-Hinweis, bestaetigter Versand) + nav + 6 e2e-Specs (Mock um /api/requests erweitert)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:23:41 +02:00
c20e6b5426 WEB-0b: CMS-Verwaltung der öffentlichen Webseite (Hand-Editier-UI)
Neuer Bereich /webseite im Manager (Nav: "Mehr"-Blatt) zur Pflege der 6
Webseiten-Seiten gegen Pams WEB-0-Backend (LAN-only, keine Auth):

- Übersicht: alle Seiten mit Status (Entwurf/Veröffentlicht).
- Seiten-Editor: Titel + SEO-Beschreibung + Status speichern.
- Geordneter Block-Editor: Blöcke hinzufügen (Überschrift, Textabschnitt/
  Markdown, Bild, Galerie, Kontaktangaben), bearbeiten, nach oben/unten
  verschieben (PUT .../blocks/order), löschen. Die dynamische AbgabetiereList
  ist nicht manuell anlegbar; nur ihr Einleitungstext ist editierbar.

Vertraege: GET /pages, GET /pages/{slug}, PUT /pages/{id},
POST /pages/{pageId}/blocks, PUT /blocks/{id}, DELETE /blocks/{id},
PUT /pages/{pageId}/blocks/order. Enums als Strings (Draft/Published, Heading...).

Deutsch via de.ts (LF beibehalten), mobile-first. e2e-Mock um die CMS-Routen
erweitert (zustandsbehaftet) + Smoke (Block anlegen/bearbeiten/verschieben,
bleibt erhalten). Gate gruen: build, eslint, vitest 69, e2e 68.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:23:34 +02:00
36454f3747 docs(HUMANQUESTION): add C8 — Himalaya vs Hermelin (does breeder use Himalaya, or is all chch Hermelin?) 2026-06-06 11:12:52 +02:00
3335502ef1 Merge feature/web-1 [god-QA pending] 2026-06-06 11:10:52 +02:00
0766f8303c Merge feature/gen-3e [god-QA pending] 2026-06-06 11:10:52 +02:00
6357e77060 Merge chore/de-lf [god-QA pending] 2026-06-06 11:10:52 +02:00
5edbd67c96 chore: normalize de.ts to LF + pin via .gitattributes (stop noisy EOL-flip diffs) 2026-06-06 11:07:19 +02:00
0651e54343 SEED-SYNC: backend ColorVariety seed = corrected catalog (drop Schwarzschimmel→Orangeschimmel, +CP-Orangeschimmel, Blaufuchs dd genotype fix) + SyncColorVarietySeed migration 2026-06-06 11:07:10 +02:00
4dcd416ff6 WEB-1: static site renderer (SiteRenderer, dry-run endpoint, 22 tests)
GerbilManagerWebAPI/Cms/SiteRenderer.cs:
  - Render(JsonObject snapshot) -> IReadOnlyDictionary<string,string> (path->content)
  - Covers all 6 block types: Heading, RichText, Image, Gallery, ContactInfo,
    AbgabetiereList (auto-resolved animals from snapshot; empty placeholder)
  - start -> index.html; other slugs -> {slug}/index.html; assets/site.css
  - Draft pages excluded; nav links with aria-current for current page
  - Minimal Markdown->HTML (headings, bold, italic, code, links, ul/ol) --
    no extra dependencies, deterministic output
  - H() encodes only the 5 HTML special chars (not umlauts) for UTF-8 pages
  - Mobile-first CSS: site header+nav, animal card grid, responsive breakpoints,
    warm off-white palette (style reference: Jimdo Kleine Chaoten)

GerbilManagerWebAPI/Endpoints/CmsEndpoints.cs:
  - GET /api/render-site -- dry-run: returns [{path, size}] for each rendered file

GerbilManager.Tests/SiteRendererTests.cs:
  - 21 unit tests (pure JsonObject, no DB): file paths, HTML structure, each block
    type, draft exclusion, XSS encoding, all 6 seeded pages, Markdown inline tests
  - 1 integration test (ApiFactory): /api/render-site returns CSS + index.html

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 11:06:43 +02:00
5fd8cf4395 GEN-3e: C-locus colourpoint naming (CP-<base> for A-+cchm; Marder/Siam/Zobel/Zobel-Hell for aa+cchm); chch kept as Hermelin/Himalaya via base-match 2026-06-06 11:04:57 +02:00
76fcad6168 Merge feature/pedigree-link residency: Gerbil.IsResident (Bestand vs external ancestors, parent-exception), AddGerbilResidency migration [god-QA pending] 2026-06-06 11:01:05 +02:00
91fa9058de Merge feature/gen-3d: dominance tiebreak — unknown locus → wild-type reading (unknown-C=full colour not white; markers unmarked) [god-QA pending] 2026-06-06 11:01:04 +02:00
6775707387 OWNERSHIP: residency classification (Bestand vs external ancestors)
Per hive/agents/god/OWNERSHIP-residency.md (Julian): "Clan kleine Chaoten"
is the wife's own Zucht. Classify each animal:
 (a) RESIDENT if zuchtCanon contains 'kleinechaote' (separator/declension-
     insensitive: "v.d. Kleinen Chaoten", "Clan-Kleine-Chaoten", …); OR
 (b) PARENT EXCEPTION — a parent of a Clan offspring is resident even if its
     own Zuchtname is foreign (you can only breed a Clan litter if the parents
     were in your care). Runs AFTER the parentRefs→litter linking.
Otherwise EXTERNAL (pedigree ancestor, not living stock — kept, not deleted).

Stored as a dedicated Gerbil.IsResident bool (distinct from Status/Abgabe —
origin/identity, not current location), defaulting true (own stock unless
marked external; DB HasDefaultValue(true)). Additive migration
AddGerbilResidency; has-pending-model-changes clean. Round-trips in
GerbilDto/GerbilInput and is Gridify-filterable (isResident==true) so Kevin
can build a "nur Bestand" filter. ImportService computes it at (re-)import
and refreshes existing rows on the idempotent sweep. ResidencySummary added
to the import report.

Projected on real data: 306 loadable → 227 resident (188 rule a, +39 via
parent exception), 79 external ancestors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 10:58:29 +02:00
8125c453d0 GEN-3d: dominance tiebreak — unknown locus resolves to wild-type reading (unknown-C => full-colour, not c[h] white; markers default unmarked) 2026-06-06 10:58:15 +02:00
8101cc7be5 Merge feature/pedigree-link: parentRefs→derived litters, box-colour=sex (blue♂/white♀), name-bleed conflict fix, Vance folded in [god-QA pending] 2026-06-06 10:51:06 +02:00
ea79703dbf PEDIGREE-LINK: chart parentRefs→litters, box-colour=sex, name-bleed fix
Structural fix (god, Julian-reported via 'C'): the loader ignored
SourceAnimal.ParentRefs, so animals whose ancestry exists only as
Stammbaum chart-position refs loaded with LitterId=null ("unbekannt").
ImportService now synthesizes/reuses a derived litter from parentRefs:
resolves father+mother via name+DOB, groups siblings (same parents+dob)
into one litter, sets Father/Mother + offspring LitterId, dates it to the
offspring DOB, and tags Notes "aus Stammbaum-Diagramm abgeleitet
(Konfidenz: …)" so it's transparent/reversible. Existing animals that
become linkable are re-linked on re-run (sweep-idempotent). Dry-run counts
included. Projected: ~124 loadable animals gain a parent link.

Box-colour = sex (Julian): blue box = male, white box = female. All 11
pedigrees encode this as a solid theme-8 (accent5/blue) fill vs no fill.
xlsx_util.cell_fill_sex reads it; extract.py sets animal.gender from the
box; ImportService.InferGender prefers it over sire/dam name inference.
Result: 306/306 loadable animals now sexed (154♂/152♀).

Extractor noise fix (god): reject Farbschlag values that are actually a
parent NAME bled across cells (contain v.d./von/of/gen.) — cleared phantom
conflicts (e.g. Chayton). Combined with GEN-3 Uw→G: Konflikte 32→21.
Also skip Excel "~$" lock files in the glob.

GEN-3a contract (Kevin): ComposeGenotype appends "Slsl" for WP/Sls
carriers (wild-type sl/sl omitted) so 8-locus strings stay unchanged.

Importer-only. The live re-import into Julian's DB stays a separate
supervised gated step. 95 C# tests + python genotype tests green;
has-pending-model-changes clean (no schema change on this branch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 10:48:30 +02:00
ed576c0339 Merge feature/gen-3c: unknown allele displays '-' (stores '?'), fix Unbekannter Farbschlag (wildcard + E-locus family fallback) [god-QA pending] 2026-06-06 10:47:14 +02:00
c35a6eca04 GEN-3c: fix 'Unbekannter Farbschlag' — unknown=wildcard in matches() + E-pair-aware family fallback (eef=Fuchsschimmel) 2026-06-06 10:45:16 +02:00
2e20df624f GEN-3c: unknown allele displays as '-' (storage stays '?'); parser accepts '-' and skips fully-unknown tokens; de.ts hints 2026-06-06 10:45:15 +02:00
a57b481a7e Merge feature/inbox-2: POST /api/requests/{id}/draft (AI German reply draft, never auto-send), extract OpenAiChatClient to Ai/, privacy stripping, 8 tests [god-QA pending] 2026-06-06 10:37:56 +02:00
27424c574f Merge feature/feat-14c: Charakterbogen as preferred AI character source (suppress admin notes, weave traits to prose), +4 tests [god-QA pending] 2026-06-06 10:37:45 +02:00
fd28b2a954 INBOX-2: 8 Tests - Stripping, Prompt-Privacy (keine Mailadresse zum Anbieter), 503, Endpoint-Round-Trip mit Stub (Entwurf gespeichert+geliefert); ApiFactory.ConfigureTestServices-Hook (init-Property, xUnit-fixturefest) 2026-06-06 10:36:02 +02:00
8aab9d34f7 INBOX-2: POST /api/requests/{id}/draft - deutscher KI-Antwortentwurf (Datenminimierung: nur Anfragetext+ForSale-Liste, Zitat/Signatur-Stripping, 503 AiKeyMissing / 502 Upstream, speichert DraftReply) 2026-06-06 10:36:02 +02:00
6dabb5572c INBOX-2: extract provider-agnostic OpenAiChatClient from SaleAdService (shared AI wire, public surface unchanged) 2026-06-06 10:36:01 +02:00
36db013b76 Merge feature/gen-3b: genotype.py+extract.py normalization (Uw→G, Sls, flags), conflicts 32→27, Gerbil.IsDeaf additive migration [god-QA pending] 2026-06-06 10:32:57 +02:00
60d034cde4 Merge feature/gen-3a: Uw=G+G-display, Sls 2nd locus+lethal, flag tolerance, Schimmel catalog fix (no Schwarzschimmel, efef=Orangeschimmel) [god-QA pending] 2026-06-06 10:32:52 +02:00