Commit Graph

403 Commits

Author SHA1 Message Date
8c43a8dc03 FEAT-8d-CREATE: docx importer CREATE path for ~194 abgegebene Jungtiere
ImportDocxService gains a three-way match-or-create loop:
  Path 1 (ExternalRef 'docx-…'): previously-created docx animals → enrich fill-NULL-only (idempotency)
  Path 2 (name+dob): existing main-import animals → enrich fill-NULL-only (as before)
  Path 3 (no match): CREATE new Gerbil — abgegebene Jungtiere not in pedigree charts
                      Status=GivenAway (or Deceased), IsResident=false,
                      OriginBreeder='Zucht der Kleinen Chaoten', ImportSource='docx',
                      ExternalRef='docx-{ws}-{normname}-{litterDob}' (stable idempotent key),
                      Gender/ColorVariety/LitterId/ReceiverContact/GoHomeDate/DateOfDeath all set.

ImportDocxReport gains Created field; contact-creation eagerly saved before gerbil batch.
5 SQLite-backed tests: dry-run counts, create+FK, idempotency, enrich-not-duplicate, Deceased status.
Gate: 163/163 tests, has-pending=No, no schema change.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 23:13:21 +02:00
08732d8348 Merge feature/fix-import-cycle (FIX-IMPORT-CYCLE P0): break Gerbil<->Litter EF circular dependency on execute
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 59s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m32s
CI / Docker Build & Push (push) Failing after 9s
Synth (chart-derived) litters now saved with FatherId/MotherId=null, then a deferred FK-update pass after all gerbils persist -> single-directional Gerbil->Litter dependency in the main save, no cycle. FK guard preserved. Regression: A-mother-is-B + B-mother-is-A cycle (SQLite, FK-enforced) asserts no throw + correct deferred FK. Gate: 158/158 (25/25 import), has-pending=No.

Unblocks the live WIPE+REIMPORT-3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:48:52 +02:00
c6edb2e9d0 FIX-IMPORT-CYCLE: break Gerbil↔Litter circular FK dependency in ImportService
Root cause: synth litters (from chart parentRefs) were added with FatherId/MotherId pointing
to gerbils that were also [Added] in the same SaveChanges batch. With 337 derived litters from
41 pedigrees, multi-generational references created a true dependency cycle:
  Gerbil [Added] ← FK{MotherId} Litter [Added] ← FK{LitterId} Gerbil [Added]
EF's topo-sort threw InvalidOperationException; smaller datasets (REIMPORT-1/2) didn't
trigger it because they had fewer chart-derived litters.

Fix: add synth litters with FatherId=null/MotherId=null (deferred), track intended FKs
in synthLitterPendingParents, apply them in a separate SaveChanges after all gerbils are
persisted. Single-direction Gerbil→Litter dependency in the main save; no cycle possible.
No schema change, no migration.

Regression test: artificial A←B←A cycle in SQLite (FK-enforced) must not throw.
Also verifies deferred FK update sets litter parent correctly after execute.

GATE: 158/158 C# tests, has-pending-model-changes=No

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 22:47:18 +02:00
8e475dff6a Merge feature/charakterbogen-2 (CHARAKTERBOGEN-2 / E1): Trait-Kategorien + rennmaus-spezifische Eigenschaften + Warnsignale
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 59s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
de.character.traits flach -> 4 Kategorien (Sozialverhalten/Eignung&Umgang/Hobbys&Eigenarten/Wesen&Temperament). 15 bestehende Keys UNVERAENDERT (Live-Daten), 10 neue additiv. warn-Flag (schwer-vergesellschaftbar, territorial) visuell abgesetzt fuer ehrliche Inserate. Gate: vitest 122/122, tsc/build/eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:43:13 +02:00
54ffb809c4 CHARAKTERBOGEN-2 (E1): Trait-Katalog in 4 Kategorien + 10 neue Traits + Warnsignale
- de.ts: traits-Array -> traitCategories (4 Kategorien: Sozialverhalten / Eignung &
  Umgang / Hobbys & Eigenarten / Wesen & Temperament); alle 15 bestehenden Keys
  erhalten (stored auf Live-Tieren); 10 neue Keys additiv; warn:true auf
  schwer-vergesellschaftbar + territorial.
- format/traits.ts: TraitEntry/TraitCategory-Interface, TRAIT_CATEGORIES-Export,
  ALL_TRAITS via flatMap, neuer isWarnTrait()-Helper.
- Charakterbogen.tsx: grouped-Rendering nach Kategorie (section + h4); warn-Chips
  mit trait-chip--warn-Klasse + trait-warn-badge.
- charakterbogen.css: .trait-category__heading + .trait-chip--warn (amber) +
  .trait-warn-badge.
- format/__tests__/traits.test.ts: 14 neue Vitest-Tests (Kategorien, Keys, warn,
  traitLabel/traitLabels).
- Gate: vitest 122/122, tsc clean, build clean, eslint clean.
2026-06-06 22:32:16 +02:00
4403574f3d Merge feature/catalog-reseed (CATALOG-RESEED): Backend-ColorVariety auf finalen GEN-4/4b-Katalog (66->70)
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 58s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m32s
CI / Docker Build & Push (push) Failing after 9s
ReseedColorVarietiesAR5: 8 Dilute-Praefix-Renames + 4 neue Dilute-Fuchs (IDs 67-70), SortOrder von ID entkoppelt, append-only (alle 66 ID->Name-Bindings erhalten, kein Live-FK-Drift). Quelle: frozen colorVarietySeed.backend.json. Gate: dotnet test 157/157, has-pending=No (Merge-Ergebnis verifiziert).

Letztes Gate vor WIPE+REIMPORT-3 (Julian-GO erteilt).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:31:46 +02:00
bcdea8011b CATALOG-RESEED: backend ColorVariety seed 66→70 from colorVarietySeed.backend.json (AR-5)
Source: gerbil-manager-web/src/genetics/colorVarietySeed.backend.json (70 entries, frozen symbols).
- 8 names updated to "Dilute" prefix (dd Gold→Dilute Gold, Agouti dd→Dilute Agouti, etc.)
- SortOrder decoupled from ID (CP-*-Hell interleaved per backend.json sortOrder values)
- 4 new entries appended at end (IDs 67-70): Dilute Algierfuchs/Goldfuchs/Rotfuchs/Polarfuchs
- All 66 existing ID→Name bindings preserved (append-only, no FK drift)
- Migration ReseedColorVarietiesAR5: UpdateData (renames+SortOrders) + InsertData (4 new)
- Tests updated: SeedGen3g_* asserts 70 entries + IDs 67-70 verified
- GATE: 157/157 C# tests, has-pending-model-changes=No

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 22:29:47 +02:00
643f1a6831 Merge feature/catalog-generator (AR-5): committed Katalog-Generator (gen:catalog) + frozen colorVarietySeed.backend.json + Drift-Guard
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 1m0s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m31s
CI / Docker Build & Push (push) Failing after 8s
Frontend-only (Generator .mts + Seed-Artefakte + catalog-drift test). Gate: vitest 109/109.
Backend-Artefakt (70 Eintraege, GEN-4/4b-final) = Quelle fuer die Backend-ColorVariety-Re-Seed-Migration (Pam) vor dem WIPE+REIMPORT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:20:00 +02:00
27a3eb802c Merge feature/feat-8d-docx (FEAT-8d Phase 2): Wurfchronik-docx-Importer (Abnehmer/GoHomeDate/Tod)
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 58s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m32s
CI / Docker Build & Push (push) Failing after 9s
extract_docx.py (stdlib, 93 Wuerfe/227 Tiere) + ImportDocxService (fill-NULL-only: WS-Code→LitterId,
Abnehmer→ReceiverContactId, ABD→GoHomeDate, Tod→DateOfDeath+Ursache) + /import/docx/dry-run|execute.
157/157 C# + 28/28 python, has-pending=No. Dormant bis execute (NACHZUG nach Re-Import).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:05:35 +02:00
13a887608c docs(HUMANQUESTION): D7 — 13 neue Konflikt-Tiere aus den 41 Stammbaeumen (Sterbedatum + Gencode-Picks)
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 58s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:04:25 +02:00
f74af537e2 FEAT-8d: docx-Importer fuer Wurfchronik-Detail (extract_docx.py + ImportDocxService)
tools/import/extract_docx.py (stdlib-Python, kein pip):
  Parst 'Wurfchronik der Kleinen Chaoten im Detail.docx' (Word/XML via zipfile).
  93 Wuerfe + 227 benannte Tiere aus Tabellen extrahiert.
  Felder pro Tier: WS-Code, Wurfgeburtsdatum, Name, Farbschlag, Geschlecht (Stern-
  Suffix), Abnehmer, Abgabedatum, Tod-Datum + Ursache, Partnername + DOB.
  Sonderwerte (ZT/BLEIBT/FREI/VG:) werden herausgefiltert.
  Edge-Cases: Doppel-Datum (16./17.03.2021, 31.05/*01.06.2023), WS ohne Zaehler
  (/5), fehlende Leerzeichen vor WS:, mehrere Abnehmer (1.) ... 2.) ...).
  Output: output/docx_litters.json + output/docx_animals.json.

tools/import/test_extract_docx.py:
  Unit-Tests fuer Regex-Logik + Live-Tests gegen die echte docx (skip wenn fehlt).
  28/28 Tests gruen.

GerbilManagerWebAPI/Import/ImportDocxService.cs:
  Idempotenter NACHZUG-Loader (fill-NULL-only, nie ueberschreiben):
  - WS-Code + Wurfgeburtsdatum -> PairingCode -> Gerbil.LitterId
  - Abnehmer -> Contact lookup-or-create -> Gerbil.ReceiverContactId
  - Abgabedatum -> Gerbil.GoHomeDate
  - Tod-Datum + Ursache -> Gerbil.DateOfDeath + CauseOfDeath
  Dry-Run zaehlt geplante Aenderungen, Execute schreibt.

GerbilManagerWebAPI/Endpoints/ImportDocxEndpoints.cs:
  POST /import/docx/dry-run + /import/docx/execute (analog ImportEndpoints).

GATE: 157/157 C#, 28/28 Python-docx-Tests, ef has-pending=No.
NACHZUG: laueft NACH dem finalen WIPE+REIMPORT-3 (kein Impact auf aktuellen Pipeline).
2026-06-06 22:04:09 +02:00
bb832b7f95 docs(HUMANQUESTION): aufgeraeumt — nur noch offene Punkte (A3/A4/A5/B2 + REW-Feinschliff) + Erledigt-Archiv
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 58s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Alle C/D-Genetik+Konflikt-Fragen + A1/A2/B1/B3 erledigt → ins kompakte Archiv. Offen: Gmail/Domain/NAS-Zugaenge, Firewall, optionaler Feinschliff.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 22:01:54 +02:00
3a75005f43 docs(HUMANQUESTION): C6 erledigt — alle 32 Konflikt-Tiere entschieden (D6 komplett)
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 1m1s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:59:39 +02:00
f2a64ad66b D6: Hanami Sterbedatum = 12.12.2019 (Julian 2026-06-07) — LETZTER D6-Konflikt, D6 KOMPLETT
Some checks failed
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Docker Build & Push (push) Has been cancelled
CI / Backend Tests (.NET) (push) Has been cancelled
conflict-decisions.json jetzt 16 Eintraege, alle D-Konflikte entschieden. Re-Import nicht mehr auf D6 gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:59:02 +02:00
3706ba3ecd Merge feature/stammbaum-open (STAMMBAUM-OPEN): Klick auf Namen oeffnet Tier (/rennmaeuse/{id})
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 58s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
PedigreeCard-Name = <Link> mit stopPropagation; Re-Root bleibt auf Karten-Flaeche. Unbekannt ohne Link.
+e2e (href + Keyboard/Accessibility). vitest 108, e2e 162. Frontend-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:56:31 +02:00
c8ab6bf072 STAMMBAUM-OPEN: Name in Ahnen-Karte ist Link zur Tier-Detailseite
- PedigreeCard: <span className=nametext> → <Link to=/rennmaeuse/{id}> mit e.stopPropagation() (Re-Root bleibt auf Karten-Bereich außerhalb des Namens)
- stammbaum.css: .pedigree-card__nametext color:inherit + text-decoration:none; hover→underline
- Kein Link im Drucklayout (PrintPedigree unverändert)
- e2e: href=/rennmaeuse/fridolin verifiziert + Keyboard-Navigation (fokus+Enter) öffnet Detailseite

Gate: vitest 108/108, e2e 162/162, tsc clean
2026-06-06 21:54:33 +02:00
30ee7b6198 AR-5: Seed-Artefakte auf finalem Katalog regeneriert (70 Eintraege, GEN-4/4b)
npm run gen:catalog lief auf rebased HEAD (post-GEN-4b, main 7fe538d).
Beide Artefakte aktualisiert:
- colorVarietySeed.generated.json: 70 Zeilen, Klammer-Notation (Display)
  Neue Namen: Dilute Gold/Platin/Agouti/Silberagouti/Kohlfuchs/Anthrazit/
  Topas/Blaufuchs + Dilute Fuchs-Varianten (Algierfuchs/Goldfuchs/Rotfuchs/Polarfuchs)
- colorVarietySeed.backend.json: 70 Zeilen, frozen symbols (ef/cchm/ch)
  Quelle fuer Pams Backend-Re-Seed-Migration (Guardrail: nie Klammern)
Drift-Guard (catalog-drift.test.ts) laeuft gruen.
Gate: build ✓  eslint ✓  vitest 109/109 ✓
2026-06-06 21:52:44 +02:00
29207e41da AR-5: Committed Katalog-Generator + Drift-Guard + Backend-Artefakt
- gen-seed.mts: deterministischer Generator aus catalog.ts (Single Source);
  emittiert BEIDE Artefakte: generated.json (Klammer-Notation, Display) +
  backend.json (frozen ef/cchm/ch, für Pam EF-Migrationen). Kein magisches
  Artefakt mehr.
- package.json: npm run gen:catalog (npx tsx gen-seed.mts)
- catalog-drift.test.ts: Drift-Guard — liest generated.json von Disk via
  import.meta.url + readFileSync, vergleicht mit live CATALOG; Fail-Meldung
  zeigt 'npm run gen:catalog'. 5 Test-Files, 93 Tests grün.
- colorVarietySeed.backend.json: 66 Zeilen frozen symbols (ef/cchm/ch),
  kein sofortiger Backend-Eingriff (AR-5 Guardrail; Pam konsumiert bei
  nächster Reseed-Migration).
- README.md: Katalog-Generator-Doku (wann laufen, was erzeugt wird).
Gate: build ✓  eslint ✓  vitest 93/93 ✓
2026-06-06 21:51:55 +02:00
7fe538dd5d Merge feature/gen-4 (GEN-4b): 7 Farbarten als Engine-Guard (keine Farbschläge) + Schimmel-Naming-Fix
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 59s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
ff42341: CATEGORY_NAMES-Guard (Standard/Colourpoint/Dilute/Fuchs/Fuchsschimmel/Schimmel/CP-Dilute nie als Ergebnis, FK=0);
locusToken E ef/e→'ef' (het-Schimmel matchen konkrete Katalog-Eintraege statt Family-Fallback 'Fuchsschimmel');
baseColourFor Family-Fallback→null; Orangeschimmel A-Restriktion (aa→Kohlfuchsschimmel). Frontend-only. vitest 96, e2e 148.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:49:20 +02:00
c452b69dd6 NAMEGEN-2-FE: 5 neue Namenskategorien (Disney, Pokémon, Englische/Kroatische Städte, US-Bundesstaaten)
- NAMEGEN_USAGES: +disney, +pokemon, +encities, +hrcities, +usstates (jetzt 10 Einträge)
- names.test.ts: Count-Test 5→10, neue toContain-Checks für alle 5 Codes

Gate: vitest 107/107, e2e 160/160, tsc clean
2026-06-06 21:48:08 +02:00
ff42341c47 GEN-4 Addendum: 7 Farbarten-Kategorien blockiert + locusToken ef/e-Fix
catalog.ts:
- locusToken E: ef/e -> 'ef' (phenotypisch ausgedrücktes Allel; enables
  catalog-Match fuer het Schimmel-Tiere wie Kohlfuchsschimmel/Orangeschimmel).
  Vorher: 'eef' matchte keinen Katalogeintrag -> Family-Fallback 'Fuchsschimmel'.
- baseColourFor: Family-Fallback entfernt (null statt family-Name) — Familie
  ist nur noch Katalog-Suchfilter, nie direkter Ausgabewert.
- CATEGORY_NAMES Guard in farbschlagFor: Fuchs/Fuchsschimmel/Schimmel/Standard/
  Colourpoint/Dilute/Colourpoint Dilute -> Unbekannter Farbschlag wenn Engine
  diese Namen zurueckgeben wuerde.
- Orangeschimmel: A:'A' hinzugefuegt (Agouti-Einschraenkung), damit aa-ef-Tiere
  durch zu Kohlfuchsschimmel fallen.
- FK-Check: Keine der 7 Kategorie-Namen sind in BASE_COLORS -> 0 FK-Risiko.

genetics.test.ts:
- 'eef with unknown other loci': erwartet jetzt 'Kohlfuchsschimmel' (korrekt!)
- GEN-4 Farbarten-Fixture: Kategorie-Guard-Test + FK-Check-Assert.
Gate: build ✓  eslint ✓  vitest 96/96 ✓  e2e 148/148 ✓
2026-06-06 21:42:15 +02:00
90f998d189 Merge feature/animal-litters (ANIMAL-LITTERS): 'Wuerfe als Elternteil' auf Tier-Detailseite
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 59s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
GerbilDetailPage: Sektion listet Wuerfe wo fatherId|motherId==Tier (Gridify OR-Filter),
je Link /wuerfe/{id} + Vater/Mutter-Badge + Datum + totalBorn; Leer-Zustand. Rueckweg Tier→Wuerfe.
Frontend-only. vitest 104, e2e 160.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:42:04 +02:00
d5f4be76be ANIMAL-LITTERS: Tier-Detailseite zeigt Würfe dieses Tiers als Elternteil
- GerbilDetailPage: listLittersPaged({filter: fatherId={id}|motherId={id}}) + neue Sektion 'Würfe als Elternteil' vor den Tabs; je Wurf: Link /wuerfe/{id}, Vater/Mutter-Badge, Datum, Wurfstärke; Leer-Zustand wenn keine Würfe
- de.ts: parentLittersTitle, parentLittersEmpty, parentLittersRoleVater/Mutter (append-only in detail-Sektion)
- e2e: +2 Tests (Fridolin hat Wurf K als Vater; Krümel hat Leer-Zustand)

Gate: vitest 104/104, e2e 160/160, tsc clean
2026-06-06 21:39:14 +02:00
433f9ee592 Merge feature/gen-4 (GEN-4): Farbschlag-Benennung (Dilute-Praefix, REW, Fuchs spezifisch) + BreedingView
Some checks failed
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Backend Tests (.NET) (push) Successful in 58s
- dd → 'Dilute '-Praefix (Agouti dd→Dilute Agouti etc.); 4 Dilute-Fuchs-Eintraege gegen nackten 'Fuchs'
- REW = beide C-Allele reduziert (kein volles C) + pp (alle 3 Kombis, A-unabhaengig)
- CP-Fuchs in berechneter Verteilung unterdrueckt
- BreedingResultView: Gencode (Klammer) pro Karte + Karten-Layout-Fix (overflow/responsive)
Frontend-only (engine+catalog.ts+BreedingResultView+index.css). vitest 95, e2e 148.
OFFEN als Follow-up: 7 Kategorie-Eintraege entfernen, PEW=REW-Konsolidierung, Backend-Re-Seed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:34:17 +02:00
5c327cd8d8 GEN-4 REW erweitert: alle 3 C-Kombi + pp = REW (Julian bestätigt)
- cReduced(c) = cchm || ch; REW wenn cReduced(c0) && cReduced(c1) && pp
  (cchm/cchm, cchm/ch, ch/ch alle REW; mind. ein volles C = NICHT REW)
- Counterproof-Test: C/cchm + pp und C/ch + pp = nicht REW
- Frozen-Round-Trip-Test: PEW (ch/ch+pp) explizit ausgenommen (intentional
  shadow durch REW-Check per Julian-Regel; PEW bleibt Dropdown-Name)
Gate: build ✓  eslint ✓  vitest 95/95 ✓  e2e 148/148 ✓
2026-06-06 21:32:20 +02:00
b12b5d720d GEN-4: Dilute-Präfix, REW-Erkennung, CP-Fuchs-Fix, BreedingResultView Gencode+Layout
Katalog (catalog.ts):
- 8 'X dd'/'dd X' Einträge → 'Dilute X' (Agouti/Silberagouti/Kohlfuchs/Anthrazit/
  Topas/Blaufuchs dd + dd Gold/Platin → Dilute Gold/Platin etc.)
- 4 neue Dilute-Fuchs-Basiseinträge (Dilute Algierfuchs/Goldfuchs/Rotfuchs/Polarfuchs)
  → verhindert naked 'Fuchs' Fallback für agouti+dilute+fox Genotypen. 66→70 Einträge.
- colourpointName: 'Dilute X' Base → 'Dilute CP-X' statt 'CP-Dilute X' (Präfix-Reihenfolge)
  → AA cchmcchm dd ee GG PP = 'Dilute CP-Algierfuchs' statt 'CP-Fuchs'.

Engine (farbschlagFor):
- REW-Check: c0==cchm && c1==cchm && p0==p && p1==p → 'REW' (Rotaugenweiß).
  Unabhängig von A/D/E/G. Flagged to god zur Bestätigung.

BreedingResultView:
- Gencode (bracket notation) pro Farbschlag-Karte (erster/wahrscheinlichster Genotyp).
- Layout-Fix: flexbox body (name+gencode gestapelt), min-width:0 gegen Overflow,
  word-break, grid min 15rem, prob flex-shrink:0 rechtsbündig.

Tests: GEN-4 describe (Dilute/REW/no-bare-Fuchs Fixtures); CATALOG_SIZE 66→70;
  CP-Fuchs/CP-Fuchs-Hell → Dilute CP-Algierfuchs(-Hell) in bestehenden Tests.
Gate: build ✓  eslint ✓  vitest 95/95 ✓  e2e 148/148 ✓
2026-06-06 21:27:32 +02:00
92dd614269 Merge feature/namegen-frontend (FEAT-NAMEGEN-FE UC-1): 'Name vorschlagen'-Button (Gemini, live)
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 1m2s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Failing after 9s
NameSuggestPanel + names.ts + GerbilForm-Button (Anfangsbuchstabe/Geschlecht/Kulturen → /names/suggest),
Vorschlag-Klick befuellt Namensfeld; 503 NamesKeyMissing-Hinweis. vitest 104, e2e 156. Frontend-only.
Namensgenerator UC-1 LIVE (Gemini-Key free-tier aktiv).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:19:29 +02:00
097a04cbd8 FEAT-NAMEGEN UC-1: 'Name vorschlagen'-Panel auf GerbilFormPage
- api/names.ts: suggestNames() + buildSuggestPath() + NAMEGEN_USAGES (norn/japa/mythg/ger/arb)
- de.ts: namegen-Sektion (button, panelTitle, letter/usages/load/states)
- NameSuggestPanel.tsx: inline-Panel mit Buchstabe/Herkunftskultur-Multiselect, Vorschlagsliste; 503 NamesKeyMissing → freundlicher Hinweis
- GerbilFormPage: 'Name vorschlagen'-Button neben Namensfeld (htmlFor-Pattern), Panel schließt+befüllt bei Auswahl
- vitest: 11 Tests (buildSuggestPath URL-Logik + NAMEGEN_USAGES-Struktur)
- e2e: mock /names/suggest + namesConfigured-Flag; 4 Specs (Panel öffnen, Klick befüllt, Buchstabe-Filter, 503-Fallback)

Gate: vitest 104/104, e2e 156/156, tsc clean
2026-06-06 21:17:42 +02:00
b7ebfd3057 Merge feature/namegen-backend (FEAT-NAMEGEN-BE): GET /names/suggest via Gemini + LitterLetter
Some checks failed
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Backend Tests (.NET) (push) Successful in 57s
NameSuggestionService (bestehender OpenAiChatClient/Gemini, Fence-Strip, [{name,meaning,origin}]),
NamesEndpoints (503 NamesKeyMissing / 502 NamesUpstreamError), Litter.LitterLetter + Migration AddLitterLetter.
157/157, drift clean (Dwight). has-pending via CI (lokaler Build durch laufende App gesperrt).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 21:16:40 +02:00
d268bbc122 D6: Kazu E=ee[f] G=GG P=PP (Julian 2026-06-07) → conflict-decisions.json + HUMANQUESTION
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 57s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Failing after 9s
Aa Cc[chm] DD ee[f] GG PP Spsp (UwUw-Quelle = GG). D6 nur noch Hanami offen (1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:59:29 +02:00
a638cf2c52 FEAT-NAMEGEN: GET /names/suggest backend (Gemini, 503 NamesKeyMissing, LitterLetter)
- NameSuggestionService: Gemini via existing OpenAiChatClient, builds
  letter/gender/usages/count prompt, strips markdown fences from response,
  deserialises [{name,meaning,origin}] array; NotConfigured -> 503.
- GET /names/suggest?letter=&gender=&usages=&count= -> Ok<List<NameSuggestion>>
  | 503 {code:NamesKeyMissing} | 502 {code:NamesUpstreamError}.
- Litter.LitterLetter (string?, nullable) + AddLitterLetter migration.
- 17 new tests (prompt assembly, fence strip, parse edge cases,
  503-not-configured, upstream-error); total 157/157 green.
- No Behind-the-Name dependency — Gemini path only (Julian's decision).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 20:56:33 +02:00
efbf24ca39 Merge feature/ci-backend-fix: dotnet-ef auf $GITHUB_PATH (Backend-CI-Job gruen) [god, via god-qa-Worktree]
Some checks failed
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Backend Tests (.NET) (push) Successful in 58s
2026-06-06 20:54:47 +02:00
22e033b26a CI-BACKEND-FIX: dotnet-ef PATH nach global tool install exportieren
dotnet tool update --global installiert dotnet-ef nach ~/.dotnet/tools,
aber der Runner-Container hat dieses Verzeichnis nicht im PATH. Jeder
run:-Step startet eine neue Shell -> der naechste Step (dotnet ef ...)
findet 'dotnet-ef' nicht (exitcode 1, Job rot seit DB-3).

Fix: 'echo ... >> $GITHUB_PATH' nach dem tool install; Gitea/GitHub Actions
liest diese Datei zwischen Steps und persistiert den PATH-Eintrag fuer alle
Folge-Steps in diesem Job.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 20:51:10 +02:00
ee7f0aeab4 docs(HUMANQUESTION): A1+A2 erledigt — Gemini-Key live, KOSTENLOS via gemini-flash-latest
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 49s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
KI-Verkaufstexte + Charakterbogen live verifiziert (echter Text generiert). Kein Billing noetig.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:49:53 +02:00
454f6e0d60 fix(ai): Default-Modell gemini-2.0-flash -> gemini-flash-latest (Free-Tier-fähig)
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 50s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
gemini-2.0-flash hat auf Julians Konto KEIN freies Kontingent (429), gemini-flash-latest schon
(direkt verifiziert). Julian bleibt kostenlos. compose/.env.example/docs angepasst.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:48:05 +02:00
c652afbbc7 D6: Skarlett Sterbedatum = 17.04.2016 (Julian 2026-06-07) → conflict-decisions.json + HUMANQUESTION
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 53s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
2018 war falsch (leakte als '/ +2018' in den Gencode; in IMPORT-POLISH gefixt). D6 noch offen: Hanami, Kazu (2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:45:30 +02:00
545db4132f D6: Vance Jr. Sp-Locus = spsp (ungescheckt, Julian 2026-06-07) → conflict-decisions.json + HUMANQUESTION
Some checks failed
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Backend Tests (.NET) (push) Failing after 52s
aa Cc[chm] Dd Ee gg P- spsp (c[hm]→c[chm] normalisiert). D6 noch offen: Hanami, Kazu, Skarlett (3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:44:24 +02:00
ddc4676f87 D6: Big Ben P-Locus = Pp (Julian 2026-06-07) → conflict-decisions.json + HUMANQUESTION gestrichen
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 50s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Aa Cc[chm] DD Ee Gg Pp Spsp. Noch offen in D6: Hanami, Vance Jr., Kazu, Skarlett (4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:42:49 +02:00
083ffac47a chore(api): UserSecretsId fuer AI-Config (Gemini-Key via user-secrets, nie committed)
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 49s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Nur die UserSecretsId-GUID — der Schluessel selbst liegt in %APPDATA% user-secrets, nicht im Repo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:40:16 +02:00
b6178b630b fix(ci): dotnet-ef Tool-Install idempotent (tool update) — self-hosted Runner persistiert --global
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 50s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Has been skipped
'tool install --global' schlug ab dem 2. Lauf mit 'already installed' fehl (Tools persistieren auf
dem self-hosted Runner) → Backend-Job rot seit DB-3, noch VOR dem Drift-Check. 'tool update' ist
installiert-oder-aktualisiert = idempotent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 20:03:18 +02:00
55d08a5dc3 fix(ci): DB-3 Drift-Check — -c Release war --context Release (DbContext-Name!), nicht Build-Config
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 1m0s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
dotnet ef interpretiert -c als --context, daher 'No DbContext named Release was found' →
Backend-Tests-Job rot seit DB-3. Korrekt: --configuration Release. Lokal verifiziert:
Release-Build + --no-build --configuration Release → 'No changes'. Tests 140/140.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:58:52 +02:00
532cbf3bcf Merge feature/qa-smoke-2: Live-Smoke der heutigen Merges (18/18, keine Findings)
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 50s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
Bestätigt live gegen echte Daten: GEN-3h Bracket-Notation (ee[f]/c[chm]), Herkunft+Gehoerlos editierbar,
CR-2 Partial-PUT behaelt Felder, namenlose Platzhalter, Gehege-Redirect. Finale Pre-Uebergabe-Bestaetigung.
e2e-only (skipUnlessLive). B3-Korpus-IDs vollstaendig dokumentiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:53:12 +02:00
d1baba686f QA-SMOKE-2: Live-Smoke GEN-3h/FORM-FIELDS/CR-2/UI-POLISH/GEHEGE (18/18 gruen) 2026-06-06 19:51:45 +02:00
8b867b9058 Merge feature/review-fixes-2: DB-4 deutsche ICU-Collation + DB-5 Litter.ExternalRef
Some checks failed
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled
CI / Backend Tests (.NET) (push) Failing after 51s
- DB-4: UseCollation('de-x-icu') auf Gerbil.Name/NameSearch/OriginBreeder, ColorVariety.Name, Contact.Name
  (Npgsql-konditional; SQLite-Testhost lehnt unbekannte Collation ab). Migration AddGermanCollation.
- DB-5: Litter.ExternalRef + filtered unique index + Importer-Idempotenz (ExternalRef primaer, Name+Date Fallback).
  Migration AddLitterExternalRef. +1 Regressionstest.
Gate 140/140, has-pending=No.
[god-QA: backend-only, disjunkt; 2 Migrationen]

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:50:44 +02:00
ea3596ca0d REVIEW-FIXES-2: DB-4 (Deutsche Collation ä/ö/ü) + DB-5 (Litter.ExternalRef)
DB-4 (medium): ICU German collation de-x-icu auf deutschen Textspalten
  Gerbil.Name, Gerbil.NameSearch, Gerbil.OriginBreeder, ColorVariety.Name,
  Contact.Name. Korrekte ä/ö/ü-Sortierung + locale-aware lower() in Postgres.
  Nur bei Npgsql (Database.ProviderName check) — SQLite-Testhost kennt keine
  eigenen Collation-Namen und wuerde EnsureCreated fail lassen.
  Migration AddGermanCollation (ALTER COLUMN ... TYPE text COLLATE de-x-icu).

DB-5 (low): Litter.ExternalRef + filtered unique index + Importer-Anbindung
  Litter.ExternalRef (string?, nullable) = stable import source id (sl.Id).
  Filtered unique index WHERE ExternalRef IS NOT NULL (wie DB-1 fuer Gerbil).
  Migration AddLitterExternalRef.
  Importer (ImportService.cs): setzt ExternalRef = sl.Id beim Litter-Insert;
  prueft existingLitterExtRefSet als PRIMAEREN Idempotenz-Key (ExternalRef),
  Name+Date-Key als Fallback fuer Wuerfe ohne ExternalRef aus frueheren Laeufen.
  +Test DB5_Litter_ExternalRef_set_and_used_for_idempotency (mutiert den Namen
  nach erstem Import, prueft dass Re-Import via ExternalRef erkennt).

GATE: 140/140 C#, has-pending=No.
2026-06-06 19:49:50 +02:00
e6b513ed5d Merge feature/genotype-notation (GEN-3h): Genotyp-Anzeige in Zuechterin-Schreibweise
Some checks failed
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Has been skipped
CI / Backend Tests (.NET) (push) Failing after 49s
- Bracket-Notation im Display: e[f]/c[chm]/c[h] (Storage bleibt frozen symbols)
- E-Locus-Reihenfolge: e VOR e[f] ('ee[f]' nicht 'efe')
- CR-1a: ee[-] (Silvain) Parser-Fix (lookbehind)
- C zeigt jetzt 'aa C- D- ee[f] Gg Pp spsp rere'
vitest 92/92 (inkl. ee[-] + C/Zuleika/Milka-Orakel), e2e 148, build/eslint. Frontend-only (src/genetics/).
HINWEIS: generated.json canonicalGenotype jetzt Klammer-Notation = DISPLAY; Backend-Seed bleibt frozen (Matching).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:27:45 +02:00
52303b90b2 CR-1a: ee[-] Parser-Fix (Silvain) — lookbehind trennt e[-] vom führenden Allel
normalizeToken: lookbehind-Regex /(?<=[A-Za-z])e\[-\]/→'?' greift wenn e[-]
von einem Buchstaben (erstes Allel) gefolgt wird (ee[-] → e?); standalone e[-]
fällt durch auf die generische \[-\]→? Regel (→ e?). Beide Pfade liefern
splitToken 2 Allele [e,?]. Vorher: ee[-]→ee?→ 3 Allele → Fehler.
Fixture: Silvain 'aa c[chm]c[chm] Dd ee[-] Gg Pp Spsp' → E=[e,?] ✓.
Gate: build ✓  eslint ✓  vitest 92/92 ✓  e2e 126/126 ✓
2026-06-06 18:24:06 +02:00
4b6a07544d GEN-3h: Breeder bracket-notation display + E-locus e-vor-e[f] Sortierung
- genotype.ts: toDisplayString zeigt ef→e[f], cchm→c[chm], ch→c[h] (Display-only;
  Storage-Contract unverändert). E-Locus Display-Rank E>e>ef: {ef,e} Paar
  rendert als ee[f] statt e[f]e (Züchterin-Konvention, Julian-Feedback).
- genotype.ts: normalizeToken akzeptiert Klammer-Eingabe (e[f], c[chm], c[h],
  [-]) → interne Symbole; vollständiger Round-Trip Display→Parse.
- genetics.test.ts: Katalog-Regex auf [A-Za-z[\]?-]+ erweitert; GEN-3h
  Notation-Fixtures (C/Zuleika/Milka-Orakel, Klammer-Round-Trip, E-Sortierung).
- colorVarietySeed.generated.json: neu generiert (66 Zeilen mit Klammer-Notation).
Gate: build ✓  eslint ✓  vitest 91/91 ✓  e2e 120/120 ✓
2026-06-06 18:24:06 +02:00
8f90821081 Merge feature/ci-drift-check (DB-3): CI EF-Migrations-Drift-Check
Some checks failed
CI / Backend Tests (.NET) (push) Failing after 50s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Has been skipped
.gitea/workflows/ci.yml: nach Build zwei Steps (dotnet-ef install + has-pending-model-changes)
→ faengt Snapshot/Migrations-Drift im Runner (EnsureCreated-SQLite-Testhost sieht das nie).
Automatisiert die manuelle MERGE-GATE-Regel. Nur CI-Config, kein Code/Schema.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:06:07 +02:00
9dda78b28a DB-3: EF Migrations Drift-Check in CI (has-pending-model-changes)
Nach dem Build-Schritt in test-backend: dotnet-ef 10.0.* global installieren,
dann `dotnet ef migrations has-pending-model-changes` ausführen. Schlaegt fehl
wenn Code-Änderungen an Entities/OnModelCreating keine passende Migration haben.
Fängt genau den Drift, den der SQLite-EnsureCreated-Testhost nicht sieht.
2026-06-06 18:05:15 +02:00