Commit Graph

516 Commits

Author SHA1 Message Date
8aaddea4ef fix(tickets): Tab + Scrollposition überleben Browser-Zurück
Zwei Ursachen, warum es auf der Tickets-Seite nicht ging (am echten Firefox/Chromium
gegen die Live-App verifiziert):

1) Tab ging verloren: der gewählte Filter-Tab (z. B. „Geschlossen") war reiner
   Component-State und sprang nach „Zurück" (Remount) auf „Offen" zurück — also war man
   in der falschen, kurzen Liste. Jetzt wird der Tab in der Session gemerkt und
   wiederhergestellt (userPicked startet weiterhin false, damit ?focus=-Deep-Links
   weiter funktionieren).

2) Scroll-Save-Heuristik zu unzuverlässig: Beim Wegnavigieren schrumpft der Inhalt von
   .app-main → der Container klemmt auf eine kleinere Position → dieses scroll-Event
   überschrieb die gemerkte Stelle. Erkennung präzisiert: nur verwerfen, wenn Position
   UND scrollHeight gleichzeitig SINKEN (= Inhalt geschrumpft/Seitenwechsel). Eine echte
   Nutzer-Scrollung verkleinert die scrollHeight nie — damit kein fälschliches Verwerfen
   echter Positionen mehr (vorherige „Höhe geändert"-Heuristik schluckte zu viel).

Tests: scroll-restore.spec erweitert (realistisches 2-Schritt-Scrollen + Tickets-Tab
überlebt Zurück), desktop+phone grün; vitest 149 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:54:55 +02:00
54cc493230 test(e2e): Scroll-Wiederherstellung der Rennmausliste (desktop + phone)
Deckt die Regression ab, die zuletzt durchrutschte:
- Liste scrollen → Tier öffnen → Browser-Zurück → Position bleibt erhalten.
- Position überlebt App-Hintergrund/Wiederanzeige (visibilitychange).
Läuft im phone-Projekt (390x844, Touch) UND desktop, am echten Scroll-Container .app-main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:33:17 +02:00
bb1b8f8c76 fix(ux): Scrollposition nicht durch Seitenwechsel-Kollaps auf 0 überschreiben
Echte Ursache (per Firefox/Chromium gegen die Live-App verifiziert): Beim Wegklicken
eines Listeneintrags wird die Seite ausgehängt → der Inhalt von .app-main kollabiert →
der Container springt auf scrollTop 0 → das löste ein scroll-Event aus, das 0 als neue
Position speicherte und die gemerkte Stelle ZERSTÖRTE, kurz bevor wir wegnavigierten.

Fix:
- scroll-Events ignorieren, wenn der Container gerade NICHT scrollbar ist
  (scrollHeight ~ clientHeight = Inhalt kollabiert/Seitenwechsel) → kein „unechter" 0-Save.
- Wiederherstellung hält den Schutz über die gesamte Settling-Phase: bei jeder DOM-Änderung
  Position erneut setzen, erst nach ~350 ms Ruhe freigeben (gegen Reflow-Races beim Nachladen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:28:32 +02:00
00a3919c9f fix(ux): Scroll-Wiederherstellung am echten Scroll-Container (.app-main), nicht am Fenster
Die App scrollt NICHT das Fenster: .app-shell ist height:100dvh/overflow:hidden, der
Inhaltsbereich .app-main hat overflow-y:auto. window.scrollY/scrollTo waren daher
wirkungslos (am Desktop sichtbar). Der Hook arbeitet jetzt auf .app-main (scrollTop/
scrollTo, Scroll-Listener am Container) und beobachtet den Inhalt per MutationObserver,
um nach dem Nachladen exakt zur gemerkten Position zu springen. Fallback auf window,
falls der Container fehlt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:06:56 +02:00
b0e92c363a fix(ux): zuverlässige Scroll-Wiederherstellung für Infinite-Scroll-Listen
Zwei Probleme bei der großen Rennmausliste (und allen Infinite-Scroll-Listen) nach
Zurück-Navigation behoben:

1) Event- statt Timer-basiert: Die Scroll-Wiederherstellung hängt sich jetzt per
   ResizeObserver an die Höhenänderung der Seite (Liste ist wieder da) und springt dann
   zur gemerkten Position — statt auf einen festen Timer zu warten. Bricht bei eigener
   Scroll-Eingabe ab; Sicherheitsnetz nach 15 s.

2) Infinite-Scroll baut Höhe wieder auf: useInfiniteList merkt sich (optionaler
   restoreKey) die geladene Seitenzahl je Query und lädt sie nach einer Zurück-
   Navigation wieder nach — sonst war die Liste nur 1 Seite hoch und die Position
   unerreichbar. Aktiviert für Rennmäuse, Kontakte, Würfe, Becken, Anfragen, Verträge.

tsc/eslint/vitest grün; e2e (Listen + Navigation, 41) grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:01:28 +02:00
7262b34ae9 fix(ux): Scrollposition übersteht auch Dev-Server-Hot-Reload (Vite HMR)
Bei einem HMR-/Fast-Refresh-Update rendert die Seite kurz neu (Liste kollabiert →
Sprung nach oben), ohne Navigation/pagehide. Jetzt vor `vite:beforeUpdate`/
`vite:beforeFullReload` sichern und nach `vite:afterUpdate` wiederherstellen (nur Dev;
import.meta.hot ist in Produktion undefiniert). Restore-Fenster auf 4 s erhöht, damit
auch langsam nachladende Listen die Position noch erreichen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:52:16 +02:00
ebc70cc0b8 feat(ux): globale Scroll-Wiederherstellung für ALLE Listen/Seiten
Neuer Hook useScrollRestoration (einmal im AppShell gemountet) erhält die
Scrollposition je Route über:
- Zurück/Vorwärts-Navigation (POP restauriert, PUSH startet oben),
- Bildschirm-Sperre / App-Hintergrund (visibilitychange, pagehide/pageshow) —
  damit das Handy nach dem Entsperren nicht mehr oben landet.

Robust gegen nachladende Listen (rAF-Nachjustierung bis ~2,5 s, während die Liste
wächst), bricht bei eigener Scroll-Eingabe ab, Deep-Links (?focus=, #anchor) haben
Vorrang. Die bisher nur in der Tickets-Seite eingebaute Logik wurde durch den
globalen Hook ersetzt.

tsc/eslint/vitest grün; e2e (navigation/listen/tickets, 42) grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:48:02 +02:00
f9e672c707 fix(tickets): Scrollposition übersteht Handy-Sperre/Hintergrund (nicht mehr Sprung nach oben)
Bisher wurde die Scrollposition nur einmal beim Mount wiederhergestellt — sperrte das
Handy und kam zurück, war die Seite oben. Jetzt:
- Position wird beim Ausblenden sicher gesichert (visibilitychange→hidden, pagehide),
  nicht nur bei Scroll-Events.
- Wiederherstellung beim Wiederanzeigen (visibilitychange→visible, pageshow) UND nach
  dem Laden — mit mehreren rAF-Versuchen gegen nachwachsende Inhalte.
- Schutz gegen den Aufwach-Sprung nach oben: während des Wiederherstellens werden
  Scroll-Speicherungen blockiert, damit ein vom Browser ausgelöster 0-Sprung die
  gemerkte Position nicht überschreibt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:41:05 +02:00
fe79be2eee feat(import): isResident-Override + Vorfahren Bentley/Alexandria/Bugatti
- Neuer isResident-Override im Import (merge_and_resolve, NACH dem Dedup, damit die
  Zusammenführung ihn nicht überschreibt). Matcht über externalRef (präzise, auch für
  namenlose Tiere) oder normalize(call-name)+dob. Ein Nicht-Bestandstier verliert den
  eigenen Zucht-Breeder.
- conflict-decisions.json: Bentley, Alexandria, Bugatti = nur Vorfahren (isResident=false),
  bestätigt von der Züchterin (Tickets 09bcac78 / 45cc501b).
- Regressionstests ergänzt/aktualisiert (Bentley/Alexandria/Bugatti isResident; Danielle
  Vater Makoto; Catelyn Eddard×Milena; Gaida Zhuāngzǐ×Zaibunissa). Alle python test_*.py grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:29:25 +02:00
41ee4ee3ab fix(import): Eltern für Danielle, Catelyn, Gaida (Triage-Antworten der Züchterin)
- Danielle: Vater Makoto ergänzt (Mutter Ella war schon gesetzt) — Geschwisterverpaarung.
- Catelyn: Eltern Eddard Stark of Sunset Glow × Milena.
- Gaida: Eltern über Geburtsdatum gefunden — Zhuāngzǐ × Zaibunissa (beide *21.02.2020,
  Geschwisterverpaarung, Kinder von Nisha × Zenon).

Per conflict-decisions.json (re-ingest verifiziert: Eltern live korrekt). Tickets
4692fd5c / 7bbc045c / ba63325a geschlossen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:18:06 +02:00
f7a1a7724b feat(tickets): Web-Push-Benachrichtigungen (PWA)
- Die Züchterin kann auf der Tickets-Seite Push-Benachrichtigungen aktivieren
  (🔔-Schalter). Service Worker ist BEWUSST push-only (kein fetch/Caching), damit das
  Laden der App nie beeinträchtigt wird.
- Backend: WebPush-Bibliothek + VAPID; PushNotifier sendet an alle Abos, räumt veraltete
  (404/410) auf. Endpoints: GET /push/vapid-public-key, POST /push/subscribe|unsubscribe.
- Ausgelöst über ein notify-Flag auf PUT /feedback: NUR die KI setzt es (z. B. neue
  Rückfrage / Ticket gelöst) → keine Selbst-Pushes durch Aktionen der Züchterin. Text wird
  aus dem Status abgeleitet, Klick öffnet das Ticket (?focus=).
- Schalter/Logik blenden sich aus, wenn das Gerät kein Push kann oder der Server keine
  VAPID-Schlüssel hat (z. B. e2e-Mock).

Migration WebPushSubscriptions. VAPID-Schlüssel in appsettings.json (lokale Single-User-App
im Heimnetz — bewusste, vertretbare Vereinfachung). Tests: 264 Backend grün (+Push-Endpoints),
e2e Tickets Desktop grün, vitest 149.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:32:26 +02:00
750619d3d7 feat(tickets): Foto-/Datei-Anhänge an Tickets
- Anhänge im Melde-Fenster (beim Erstellen) und direkt an bestehenden Tickets:
  Vorschaubilder, Öffnen im neuen Tab, Entfernen.
- Bytes liegen in eigener Tabelle (FeedbackAttachment, lose FeedbackId ohne FK →
  übersteht den Ingest-Wipe); GET /feedback liefert nur Metadaten (id/Name/Typ/Größe),
  die Bytes über /feedback/attachments/{id}. Größenlimit 10 MB.
- Endpoints: POST /feedback/{id}/attachments (base64), GET /feedback/attachments/{id}
  (Bytes), DELETE /feedback/attachments/{id}.

Migration FeedbackAttachments. Tests: 262 Backend grün (+Upload/Serve/Delete +Validierung),
e2e Tickets Desktop+Phone grün (+Foto-Upload), vitest 149.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:24:02 +02:00
48b138bbfd feat(tickets): Volltextsuche + Kategorien, 👍/👎-Rückmeldung & ähnliche gelöste Tickets
- Suche: Volltext über Nachricht/Frage/Antwort/Changelog/Name/Kategorie, plus
  Kategorie-Filter (KI-gesetzte Kategorie als Chip + Auswahlmenü), je innerhalb der
  aktiven Ansicht.
- 👍/👎 auf gelösten Tickets: 👍 speichert die Rückmeldung, 👎 öffnet das Ticket
  wieder (zurück in die Rückfragen) und bittet um die fehlende Info.
- Melde-Fenster: schlägt beim Tippen ähnliche bereits gelöste Tickets vor
  (Wort-Überlappung + Bonus bei gleichem Tier/Wurf/Kontakt) — Self-Service.

Backend: Feedback.Category + Feedback.Helpful (+ PUT-Handling), Migration
FeedbackCategoryAndHelpful (beide nullable). Tests: 260 Backend grün, e2e Tickets
Desktop +4 (Suche/Kategorie/👍/👎), vitest 149.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:14:07 +02:00
c0a7b1a5ee feat(tickets): Wiederöffnen→Rückfrage mit Zeitstempel + Soft-Delete-Papierkorb + Scroll-Erhalt
Wiederöffnen eines gelösten Tickets:
- landet jetzt in „Rückfragen" (NeedsInfo) statt „Offen".
- War es ein echt gelöstes Ticket OHNE Rückfrage, wird um mehr Infos gebeten und
  „Wieder geöffnet am" (ReopenedAt) gestempelt.
- Hatte es bereits eine offene Rückfrage (z. B. manuell gelöste Rückfrage), kehrt es
  ohne neuen Hinweis und ohne Zeitstempel in genau diese Frage zurück.

Löschen über die UI = Soft-Delete:
- Tickets wandern in die neue Kategorie „Gelöscht" (Papierkorb) statt entfernt zu werden.
- Von dort wiederherstellbar (POST /feedback/{id}/restore → DeletedAt = null).
- Countdown „Wird in N Tagen endgültig gelöscht"; nach 30 Tagen endgültige Löschung
  (lazy beim Abruf in GET /feedback).

Außerdem: Scrollposition bleibt beim Zurück-Navigieren (z. B. nach Klick auf einen
Tier-Link) erhalten, statt an den Seitenanfang zu springen.

EF-Migration FeedbackReopenedAndSoftDelete (ReopenedAt, DeletedAt — beide nullable).
Tests: 260 Backend grün (+2 Reopen-Fälle, CRUD auf Soft-Delete umgestellt), e2e Tickets
Desktop+Phone grün (+Soft-Delete/Restore/Reopen), vitest 149.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:02:04 +02:00
a0fa33da42 feat(tickets): Erst-Text nach Antwort sperren, nur neueste Antwort editierbar
Sobald ein Ticket eine Antwort hat, ist der ursprüngliche Ticket-Text nicht
mehr bearbeitbar. Editierbar ist dann nur noch die neueste Antwort — und auch
die nur, bis die KI darauf reagiert hat (Status verlässt „Answered"). Ältere
Antworten im Verlauf (thread) bleiben wie bisher schreibgeschützt.

Regressionstest + Answered-Mock-Ticket ergänzt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 10:32:04 +02:00
6b264a9b71 fix(import): Farbschlag aus Genotyp ableiten + Mamta-Eltern — Ticket-Triage
genotype.py: Python-Port von genotypeToFarbschlag (0 Abw. über 3402 Genotypen).
resolve_color_and_genotype: bei vorhandenem Genotyp gewinnt der berechnete Farbschlag
(Goldfuchs≠Gold, Dilute Agouti/Anthrazit, Blaufuchs statt -schimmel bei (schimmel),
spsp statt Schecke). Mamta Mini: Ee + Eltern Geely×Gaida am Wurf. Regressionstests je Fall.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 10:08:13 +02:00
26977d73ff docs(mempalace): Subagenten müssen MemPalace zu Aufgabenbeginn abfragen
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:43:12 +02:00
12f5de00a0 docs: Genetik-Engine immer voll mit Tests absichern (Konvention) + E-Locus-Regel
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:36:12 +02:00
0540498e85 Merge branch 'worktree-agent-a7281df1f2cc3f1f1'
# Conflicts:
#	gerbil-manager-web/src/genetics/catalog.ts
#	gerbil-manager-web/src/genetics/genotype.ts
#	gerbil-manager-web/src/genetics/punnett.ts
2026-06-23 09:29:42 +02:00
a87d1ec865 fix(api): API-Host im Dev-Modus aus window.location ableiten (LAN/Handy-Zugriff)
Statt fest http://localhost:5179 (auf dem Handy = das Handy selbst) nutzt der
Client im Dev-Modus den Host, von dem die Seite geladen wurde → 192.168.x.y:5179.
e2e/Rechner bleiben bei localhost.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:18:55 +02:00
8c1ee75b81 fix(genetics): Engine-Fixes Ticket-Triage (Goldfuchsschimmel, Dilute CP-Blaufuchs, Eltern-Inferenz, Punnett, uw[d])
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:05:35 +02:00
aa4552ff84 docs(triage): Genetik-Vorlauf-Notizen als Referenz für Engine-Fixes
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 1m8s
CI / Frontend Tests (Node/Vite) (push) Failing after 4m55s
CI / Docker Build & Push (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 08:34:54 +02:00
18d74ff3f3 docs(triage): Ticket-Triage-Matrix (Lauf 56 Tickets)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 08:29:12 +02:00
72ad706ca6 fix(import): Eltern-/Herkunft-/Dubletten-Korrekturen — Ticket-Triage Cluster
Akane (Roni=Vater male + Mutter Fumi), Sunny (Bill+Melly), Danielle (Mutter Ella,
motherDob-Disambiguierung), Cherry Berry (female), Black-Forest-Label vereinheitlicht,
namenloser Bock entdoppelt (mergeExternalRefs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 08:25:43 +02:00
a66739e84d feat(import): „Was wird (nicht) importiert"-Hinweis auf der RPRO3-Import-Seite
Klarstellung für die Züchterin: übernommen werden Tiere/Stammbäume/Genotypen/
Würfe/Kontakte/Gehege+Reinigung/Erwerb/Reservierung/Rücknahmen/Warteliste/
Ausstellungen; (noch) nicht: Finanzen, Termine, Tierarzt-Stammdaten, Tagebuch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 07:24:59 +02:00
00dba91a5c feat(tickets): Kurz-Verweise (Shortlinks) im Ticket-Text auflösen
Die KI kann im Text `tier:<8hex>` / `kontakt:` / `wurf:` / `gehege:` schreiben;
Frontend löst per POST /refs/resolve (Präfix-Match, DB-agnostisch) zu Name +
internem Link auf. Reine KI-Schreibhilfe — kein Nutzer-Button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 07:23:03 +02:00
c7b054e909 feat(import): RPRO3-Importer um 6 Feature-Tabellen erweitern
becken→Gehege-Reinigung, herktier→Erwerb, abgeben/abstat→Reservierung,
getback→Rücknahmen, nachfrage→Warteliste, ausz→Ausstellungen.
Deterministische GUIDs, idempotenter Re-Import.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 07:05:01 +02:00
00dc724605 test(e2e): Gewicht-Tab-Button im Tabpanel ansprechen (Erwerb-Sektion-Kollision)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:15:23 +02:00
156ede120e Merge branch 'worktree-agent-ae59040b377a324cb'
# Conflicts:
#	GerbilManagerWebAPI/ApplicationContext.cs
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/e2e/mock-data.ts
#	gerbil-manager-web/src/pages/GerbilDetailPage.tsx
#	gerbil-manager-web/src/strings/de.ts
2026-06-22 23:10:18 +02:00
db2c29769e Merge branch 'worktree-agent-a02f88e8490625846'
# Conflicts:
#	GerbilManagerWebAPI/ApplicationContext.cs
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/e2e/mock-data.ts
#	gerbil-manager-web/src/App.tsx
#	gerbil-manager-web/src/components/AppShell.tsx
#	gerbil-manager-web/src/strings/de.ts
2026-06-22 23:07:22 +02:00
ae7d171131 Merge branch 'worktree-agent-a0e6f31173772c798'
# Conflicts:
#	GerbilManagerWebAPI/ApplicationContext.cs
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/e2e/mock-data.ts
#	gerbil-manager-web/src/strings/de.ts
2026-06-22 23:02:17 +02:00
6a64698601 Merge branch 'worktree-agent-a36d202be311b9289'
# Conflicts:
#	GerbilManagerWebAPI/ApplicationContext.cs
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/e2e/mock-data.ts
2026-06-22 22:57:16 +02:00
1469a7f3dc Merge branch 'worktree-agent-a5f48334696288159'
# Conflicts:
#	gerbil-manager-web/e2e/mock-data.ts
2026-06-22 22:54:50 +02:00
6123b8ef9e Merge branch 'worktree-agent-a9d8edbd439109a45' 2026-06-22 22:53:33 +02:00
0b0ebd5fad Merge branch 'worktree-agent-a1dfa0392b5ace900'
# Conflicts:
#	gerbil-manager-web/e2e/mock-data.ts
#	gerbil-manager-web/src/App.tsx
2026-06-22 22:53:10 +02:00
4ec0f787dd feat(tickets): Markdown in Texten + Editier-Regeln für Rückfragen
- Ticket-Texte (Frage/Antwort/Nachricht/Changelog/Verlauf) rendern eine
  Markdown-Teilmenge: **fett**, `code`, Aufzählungen, Links, Tier-/Ticket-IDs
- Offene Rückfrage (NeedsInfo): nicht bearbeitbar — die Züchterin soll antworten
- Beantwortet (Answered): Antwort nachträglich änderbar, bevor die KI übernimmt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:51:00 +02:00
d380a0c2ef feat(ausstellungen): Ausstellungs-/Auszeichnungsergebnisse je Tier
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:19 +02:00
40c92c70d4 feat(abgabe): Reservierungs-/Abgabe-Status (verfügbar/reserviert/abgegeben)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:19 +02:00
4e7cd21b70 feat(gehege): Reinigungszyklus (Maße, Kapazität, letzte/nächste Reinigung)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:19 +02:00
3ad276637c feat(import): RennmausPro-III-Backup-Importer (analyze+execute, Dedup, Fotos)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:19 +02:00
b4dc37de78 feat(ruecknahmen): zurückgenommene Tiere erfassen
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:18 +02:00
d25d2ee152 feat(warteliste): Nachfrage/Warteliste für Interessenten
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:18 +02:00
55e79cda51 feat(tier): Erwerb/Kauf je Tier (Datum, Preis, Notiz)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:43:18 +02:00
23f028123d fix(tickets): beantwortete Rückfragen stehen wieder unter „Offen"
Bisher landeten beantwortete Tickets (Answered) in „Rückfragen". Sobald die
Züchterin geantwortet hat, ist sie fertig → das Ticket gehört in „Offen"
(von der KI zu erledigen). „Rückfragen" zeigt jetzt nur noch NeedsInfo
(wartet auf ihre Antwort).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:42:04 +02:00
4e30dc7fe3 feat(import): RennmausPro-III-Analyse — Abgleich, Dedup, Feature-Gap, Ticket-Generierung
- compare_rpro3.py: RPRO3-SQLite ↔ aktueller Stand (Dedup Name+DOB+Farbe+Herkunft)
- rpro3-vergleich.md / rpro3-feature-gap.md: erzeugte Reports
- rpro3_tickets.py / rpro3_post_tickets.py: 413 Rückfrage-Tickets mit Herkunft + Links

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:38:24 +02:00
c15dd78bc7 feat(pwa): installierbar als App-Icon (Manifest + Icons)
Web-App-Manifest, App-Icons (192/512 + maskable, Rennmaus-Motiv) und
apple-touch-icon/theme-color in index.html → "Zum Startbildschirm hinzufügen".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:38:24 +02:00
dcf0e40f9b feat(tickets): Rückfragen-Dialog, Verlinkungen, Entwurfssicherung + PWA-Vorbereitung
- Feedback: fixNote (Changelog), agentContext (intern), thread (Q&A-Verlauf);
  3 gefilterte Ansichten (Rückfragen/Offen/Geschlossen)
- Tickets-Text: klickbare Tier-Links (ID→Name), Ticket→Ticket-Links (?focus=),
  Markdown-Links; Antwort-Entwurf pro Ticket in localStorage
- "Fehler melden": Entwurf übersteht App-Wechsel/Schließen (ein gemeinsamer Entwurf)
- entityName als Hyperlink zum referenzierten Datensatz

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:38:23 +02:00
b9021fe577 chore: Postman-Collection entfernt, GerbilERM.drawio nach docs/ verschoben
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:17:04 +02:00
ce1704c3b7 fix(import): Stammbaum-/Eltern-/isResident-Tickets der Züchterin (18)
Import-Logik:
- Externe Gründer (Zooladen/„von Privat"/„from …, <Land>") bekommen keine
  erfundenen Chart-Eltern mehr → Bill, Cooky, Zadar haben korrekt unbekannte
  Eltern (is_external_origin). [#5,#13,#28]
- Hagrid: externe Zucht wird nicht mehr als Bestand markiert (isResident=false)
  + Leerhüllen-Dedup → ein Datensatz mit Eltern Snickers × Milka. [#17,#18,#20a]
- Gender-Index: eindeutiges Geschlecht schlägt unbekanntes Duplikat → Rollen-
  Auflösung repariert (Vance→Mutter Enya, Zac→Vater Vance/Mutter Dorie). [#33,#35]
- „Eltern: X + Y"-Wurfnotizen werden geparst (~46 Würfe); v.d.↔von-den-Namens-
  kanon (Theodore→BlackFire). [#9,#11,#30]

Daten-Overrides (conflict-decisions.json, jetzt auch Gender + exakte Eltern):
- Mozart→weiblich [#2], Yuki=Camaro×Izumi [#23], Gold-Mutter=Chelsea [#36],
  Arya=Vance×Sansa (Geschwisterverpaarung) [#16], Tony→Sammy [#12],
  Odelia [#15], Jamie→Danny [#31], Silver=Taro×Beatrice [#11].

Frontend: GerbilDetailPage blendet für isResident=false Würfe + Charakter aus
(Hinweis nonResidentNote). [#17,#20b]

Tests: test_extract/test_merge_resolve erweitert; vitest 135, playwright tiere 34 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:16:53 +02:00
9c6ca2118a docs(skill): internes agentContext-Feld am Ticket (Züchterin-unsichtbar)
Da Subagenten sitzungsgebunden sind, dient ein internes, in der Züchterin-UI
NICHT sichtbares Feld `agentContext` als Arbeitsgedächtnis: der Agent legt dort
Befunde/Ursache/Plan/„worauf gewartet wird"/erledigte Teilschritte ab und setzt
beim Wiederaufgreifen (Answered) genau dort an — statt neu zu untersuchen.
Trennung: agentContext technisch/intern; Frage/Antwort/fixNote bleiben
laienverständlich. PUT {agentContext} aktualisiert ohne Status-Wechsel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:14:47 +02:00