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>
182 lines
10 KiB
Markdown
182 lines
10 KiB
Markdown
---
|
||
name: ticket-triage
|
||
description: >-
|
||
Fehlerberichte (Tickets) der Züchterin abarbeiten: neue Tickets per Subagent
|
||
triagieren, Rückfragen an die Tickets hängen, beantwortete Tickets wieder
|
||
aufgreifen, Fixes gebündelt umsetzen und beim Schließen dokumentieren, was
|
||
gefixt wurde. Nutze diesen Skill, wenn der Nutzer „Tickets abarbeiten /
|
||
triagieren", „Fehlerberichte bearbeiten" o. Ä. verlangt.
|
||
---
|
||
|
||
# Ticket-Triage & Abarbeitung
|
||
|
||
Tickets entstehen über das „Fehler melden"-Feature (`POST /feedback`) und werden
|
||
unter **Hilfe → Meine Tickets** (`/hilfe/tickets`) verwaltet. Dieser Skill
|
||
automatisiert das Triagieren, Rückfragen-Stellen, Umsetzen und Schließen.
|
||
|
||
## Status-Lebenszyklus (Feedback.Status)
|
||
|
||
| Status | Bedeutung | Wer ist dran |
|
||
|---|---|---|
|
||
| `Open` | Neues Ticket, noch nicht triagiert | **KI** (triagieren) |
|
||
| `NeedsInfo` | KI hat eine **Rückfrage** angehängt | Züchterin (antworten) |
|
||
| `Answered` | Züchterin hat geantwortet | **KI** (wieder aufgreifen, umsetzen) |
|
||
| `Resolved` | Erledigt — mit `fixNote` (Changelog) | — |
|
||
|
||
**Zu bearbeiten sind `Open` (neu) und `Answered` (KI wieder dran).** `NeedsInfo`
|
||
wartet auf die Züchterin, `Resolved` ist fertig — beide überspringen.
|
||
|
||
## Voraussetzungen
|
||
|
||
- App läuft (Aspire): `dotnet run --project GerbilManager.AppHost`; API auf
|
||
http://localhost:5179. Siehe `CLAUDE.md` (Architektur, Import→DB-Workflow,
|
||
Domänenwissen: 6-Jahre-Lebensspanne, Geschwisterverpaarung, Genotyp/E-Locus,
|
||
`isResident`).
|
||
- Feedback überlebt den Import-Ingest (FK-freie Spalten) — Tickets bleiben
|
||
erhalten, auch wenn die DB neu befüllt wird.
|
||
|
||
## Ablauf
|
||
|
||
### 1. Tickets holen & einteilen
|
||
`curl -s http://localhost:5179/feedback` (neueste zuerst). Encoding-Falle: über
|
||
eine Datei holen (`curl -o raw.json`) und mit `python … .decode('utf-8')` lesen,
|
||
nicht via Windows-stdin-Pipe (sonst Mojibake). Test-/Dummy-Tickets ausschließen.
|
||
Filtere auf `status in (Open, Answered)`. Bei `Answered` zusätzlich das Feld
|
||
`answer` (Antwort der Züchterin) mitnehmen — darauf basiert die Umsetzung.
|
||
|
||
### 2. Triage per Subagent (ein Agent pro Ticket)
|
||
Nutze die **Workflow-Orchestrierung** (`pipeline`) — einen Triage-Agenten pro
|
||
Ticket. args ASCII-sicher halten (nur id/context/gerbilId/litterId übergeben; die
|
||
deutschen Nachrichten holt der Agent selbst aus `GET /feedback`). Defensive im
|
||
Script: `const tickets = Array.isArray(args) ? args : JSON.parse(args)`.
|
||
|
||
Jeder Triage-Agent:
|
||
1. liest `CLAUDE.md` + `docs/ticket-triage.md` (falls vorhanden),
|
||
2. holt seinen Ticket-Text (+ `answer` bei `Answered`) aus `GET /feedback`,
|
||
3. untersucht die echten Daten über die API (`GET /gerbils/{id}`, `/litters/{id}`,
|
||
Eltern verfolgen; `provenance` zeigt Import-Herkunft inkl. verworfener Werte),
|
||
4. liefert strukturiert (StructuredOutput-Schema): `ticketId, title, category,
|
||
rootCause, recommendation, fixLayer (import-data|import-logic|backend|frontend|
|
||
genetics-engine), affectedAreas[], overlapKey (Cluster-Slug), effort (S/M/L),
|
||
confidence, needsUserInfo`,
|
||
5. **terminale Aktion am Ticket selbst** (jeder Triage-Agent schließt seinen
|
||
Vorgang ab, lässt nichts offen liegen): braucht es Infos von der Züchterin →
|
||
**Rückfrage ordentlich stellen** (siehe 3); ist die Ursache rein eine Daten-/
|
||
Code-Korrektur ohne Rückfrage → an den passenden Umsetzungs-Cluster (4)
|
||
übergeben (NICHT selbst querschnittlich Dateien ändern).
|
||
|
||
Sammle alle Ergebnisse in **eine Datei** `docs/ticket-triage.md` (Cluster-/
|
||
Überschneidungs-Matrix + offene Rückfragen) — token-schonend per Python aus dem
|
||
Workflow-Ergebnis generieren, nicht 70 KB in den Kontext laden.
|
||
|
||
### 3. Rückfragen ordentlich stellen (durch den Triage-Agenten)
|
||
Wenn ein Ticket Infos der Züchterin braucht, hängt der Triage-Agent die Rückfrage
|
||
**direkt selbst** ans Ticket:
|
||
`PUT /feedback/{id}` mit `{"question": "<Rückfrage>"}` → Status wird `NeedsInfo`.
|
||
Anforderungen an eine gute Rückfrage: **eine konkrete Frage** (kein Sammelsurium),
|
||
in **einfacher, freundlicher Sprache** für die Züchterin (keine Code-/Fachbegriffe),
|
||
mit dem nötigen Kontext (welches Tier/welcher Wurf, was unklar ist), und mit einer
|
||
klaren Handlungsaufforderung (z. B. „Wie heißt die Mutter von X?"). Die Züchterin
|
||
beantwortet es in der App; beim nächsten Lauf erscheint es als `Answered` und wird
|
||
wieder aufgegriffen.
|
||
|
||
### 4. Umsetzen — gebündelt nach Cluster (Überschneidungen vermeiden!)
|
||
Die Triage-Matrix zeigt, welche Tickets sich Dateien teilen. Bündele nach
|
||
**datei-disjunkten Workstreams**, damit parallele Subagenten nicht kollidieren:
|
||
- **Genetik-Engine** → `gerbil-manager-web/src/genetics/**`, `tools/import/genotype.py`.
|
||
- **Stammbaum-Import** (Eltern/Dedup/Gender/`isResident`) → `tools/import/extract.py`,
|
||
`merge_and_resolve.py`, `conflict-decisions.json`.
|
||
- **Frontend-Anzeige** (z. B. Nicht-Bestandstiere ausblenden) → `GerbilDetailPage.tsx`,
|
||
`de.ts`.
|
||
Gemeinsam genutzte Dateien (`de.ts`, `GerbilDetailPage.tsx`) gehören **genau einem**
|
||
Workstream — sonst sequenziell. Datenkorrekturen, die die Züchterin nennt, als
|
||
Override in `conflict-decisions.json` kodieren (data-driven, re-ingest-stabil).
|
||
Subagenten committen NICHT und re-ingesten NICHT — das koordiniert der Haupt-Loop.
|
||
|
||
### 5. Import neu einspielen (bei Daten-/Import-Änderungen)
|
||
`python tools/import/extract.py` → `extract_contracts.py` → `merge_and_resolve.py`,
|
||
dann `POST /import/ingest-resolved` (wischt + lädt neu). Danach betroffene Tickets
|
||
gegen die API verifizieren.
|
||
|
||
### 6. Ticket schließen — MIT Changelog (durch den bearbeitenden Subagenten)
|
||
Der Subagent/Cluster, der den Fix umgesetzt hat, schließt **seine** Tickets selbst
|
||
ab — aber erst **nachdem der Fix verifiziert und (bei Daten-/Import-Fixes) live
|
||
eingespielt ist** (Schritt 5), damit „erledigt" auch stimmt:
|
||
`PUT /feedback/{id}` mit `{"status": "Resolved", "fixNote": "<verständliche
|
||
Erklärung, was korrigiert wurde>"}`.
|
||
**Die `fixNote` ist ein Changelog AUSSCHLIESSLICH für die Züchterin (Laiin) —
|
||
kein technisches Geschwafel.** Harte Regel:
|
||
- Schreib, **was sich für SIE sichtbar geändert hat**, in Alltagssprache; 1–3 Sätze.
|
||
- KEINE Dateinamen, Funktionen, Feldnamen, IDs, Status-Codes, „Resolver/Migration/
|
||
Genotyp-Parser/isResident/conflict-decisions" o. Ä. Nenne Tiere/Würfe bei ihrem
|
||
**Namen**, nicht per ID.
|
||
- Sag ggf., was sie tun soll (z. B. „Seite neu laden").
|
||
|
||
Gut: „Die Mutter von **Yuki** war falsch — sie ist jetzt **Izumi** (vorher stand
|
||
da Benjiro). Bitte den Stammbaum neu laden."
|
||
Gut: „**Hagrid** wird nicht mehr als dein eigenes Tier geführt, sondern nur noch
|
||
als Vorfahre — seine Würfe und der Charakter-Bereich werden nicht mehr angezeigt."
|
||
Schlecht (NICHT so): „assign_parent_roles korrigiert, motherId via
|
||
conflict-decisions.json gesetzt, re-ingest." / „isResident=false gesetzt."
|
||
|
||
### Abschluss-Regel (wichtig)
|
||
**Kein bearbeitetes Ticket bleibt offen liegen.** Jedes `Open`/`Answered`-Ticket
|
||
endet nach einem Lauf in genau einem Endzustand:
|
||
- **`NeedsInfo`** — Rückfrage wurde ordentlich gestellt (Info fehlt), oder
|
||
- **`Resolved`** — Fix umgesetzt + verifiziert, mit `fixNote`-Changelog.
|
||
Kann ein Ticket weder gefixt noch sinnvoll erfragt werden, stelle trotzdem eine
|
||
klärende Rückfrage (NeedsInfo) statt es offen zu lassen.
|
||
|
||
## Mehrrundige Rückfragen & Kontext-Kontinuität
|
||
|
||
Der Dialog kann mehrere Runden haben: `Open → (Rückfrage) NeedsInfo → (Antwort)
|
||
Answered → (KI prüft) ggf. neue Rückfrage NeedsInfo → Answered → … → Resolved`.
|
||
Jede **weitere Antwort** der Züchterin bringt das Ticket wieder auf `Answered` und
|
||
damit erneut in die Bearbeitung (Schritt 1 filtert `Answered` immer mit ein).
|
||
|
||
**Kontext-Träger ist das Ticket, nicht der Subagent.** Subagenten sind
|
||
sitzungsgebunden — antwortet die Züchterin später (neue Session), existiert der
|
||
ursprüngliche Agent nicht mehr. Daher MUSS der gesamte Verlauf am Ticket hängen
|
||
(Frage/Antwort je Runde) + der Triage-Eintrag in `docs/ticket-triage.md`. Beim
|
||
Wiederaufgreifen eines `Answered`-Tickets lädt der Subagent diesen vollständigen
|
||
Verlauf + die frühere Triage und macht **mit demselben Kontext** weiter (statt bei
|
||
null neu zu untersuchen) — praktisch „derselbe Vorgang, fortgesetzt".
|
||
|
||
**Innerhalb derselben Session** kann man stattdessen denselben Subagenten direkt
|
||
fortsetzen (SendMessage an seine Agent-ID, Kontext bleibt erhalten) — nur dann ist
|
||
echte Agent-Kontinuität möglich.
|
||
|
||
Das Datenmodell unterstützt Mehrrunden über einen **Verlauf/Thread** am Ticket
|
||
(mehrere Frage/Antwort-Einträge mit Autor + Zeit), nicht nur ein einzelnes
|
||
Frage/Antwort-Paar — so geht bei weiteren Antworten nichts verloren.
|
||
|
||
### Internes Agenten-Kontextfeld (für die Züchterin unsichtbar)
|
||
|
||
Das Ticket hat ein **internes Kontextfeld** (`agentContext`, NICHT in der Züchterin-
|
||
UI sichtbar) — das **Arbeitsgedächtnis** des Agenten. Damit ersetzt das Ticket den
|
||
sitzungsgebundenen Subagenten-Kontext:
|
||
- **Schreiben:** Bei jeder Bearbeitung legt der Agent dort seinen Arbeitsstand ab
|
||
(kompaktes JSON/Markdown): Befunde, vermutete Ursache, geprüfte Hypothesen,
|
||
betroffene Dateien/Daten, der Plan, **worauf gewartet wird** (welche Info die
|
||
Rückfrage klären soll) und schon erledigte Teilschritte.
|
||
- **Lesen:** Beim Wiederaufgreifen eines `Answered`-Tickets liest der Agent zuerst
|
||
`agentContext` (+ Verlauf + Triage-Eintrag) und setzt **dort an, wo er aufgehört
|
||
hat** — keine Neu-Untersuchung von null.
|
||
- **Trennung:** `agentContext` ist intern/technisch (darf IDs/Dateinamen/Hypothesen
|
||
enthalten); die **sichtbaren** Felder bleiben laienverständlich (Frage, Antwort,
|
||
`fixNote`). `agentContext` wird in der Tickets-Seite NICHT angezeigt.
|
||
- `PUT /feedback/{id}` mit `{"agentContext": "<arbeitsstand>"}` aktualisiert es,
|
||
ohne den Status zu ändern.
|
||
|
||
## Verifikation vor „fertig"
|
||
- Code-Fixes: `npx tsc --noEmit`, `npx vitest run`, betroffene `npx playwright test`,
|
||
`dotnet build`/`dotnet test`, Python-`test_*.py` — grün.
|
||
- Daten-Fixes: in `resolved_import.json` stichprobenartig prüfen, dann re-ingest +
|
||
API-Check des konkreten Tiers/Wurfs.
|
||
- Jedes erledigte Ticket auf `Resolved` mit `fixNote` gesetzt.
|
||
|
||
## Hinweise
|
||
- Pro Ticket genau ein Triage-Agent; Umsetzung gebündelt nach Cluster.
|
||
- Encoding: deutsche Texte als UTF-8 (Datei, nicht stdin-Pipe).
|
||
- Nichts committen, bis der Haupt-Loop verifiziert hat; auf `main` arbeiten.
|