- Kap. 12 906→1340, 13 1345→1875, 14 1068→1841 (Korridore) - Kap. 17 2170→2550 mit 17.7 Betrieb nach 17.6 (17.8 = alte Matrix) - Kap. 20 942→1536; VPN-251/250/244; Freeze 17.5–17.6 unberührt - Wörter 55 718→58 429 (+2 711) - Bericht audits/behebungsplan-ap4-2026-11-07.md
13 KiB
14. Effektive Aufgabenformulierung
Der Task-Prompt ist dein Steuerknüppel. Zu vage → der Agent rät. Zu restriktiv → der Agent wird zum teuren Diktiergerät und findet oft schlechtere Lösungen als mit klarem Zielraum. Zwischen „fix it somehow“ und „ändere Zeile 88 exakt so“ liegt der produktive Bereich: Outcome, Grenzen, Messlatte.
These 5: Formuliert Aufgaben nicht zu restriktiv. Besser: klares Ziel + Nebenbedingungen + Ausschlüsse nennen und den Agent eine Lösung ausarbeiten lassen.
Kombiniert mit These 4: Die DoD muss agent-prüfbar sein.
Template: Anhang A · templates/task-prompt-template.md (Buch-Repo)
14.1 Die Leitformel
Die Stufen 0–4 sind dieselben wie in Kap. 20.2. Die Figur beschriftet 3/4 mit dem Hebel (Metriken; Richtlinien als Code), die Tabelle dort mit dem Reife-Namen (systematisch / produktisiert) — kein zweites Reifegrad-Modell.
These 5 hat drei Felder. Die Leitformel hängt die DoD aus These 4 daran:
Ziel (Outcome)
+ Nebenbedingungen
+ Ausschlüsse
+ Definition of Done (Checks)
Kontextquellen (in der Figur der fünfte Block) und erlaubte Aktionen sind optional: sie schärfen den Start, sie sind nicht die Formel.
Das ist genug Struktur für Autonomie — und genug Grenze gegen Chaos. Fehlt das Ziel, rät der Agent. Fehlen Ausschlüsse, expandiert er. Fehlt die DoD, behauptet er Fertigstellung (Kap. 10). Die drei Felder sind These 5; die DoD ist These 4. Wer nur das Ziel nennt, hat These 5 halb. Wer den Weg diktiert (exakte Zeilen, exakte Hilfsfunktionen in exakter Reihenfolge), hat sie verletzt — der Agent wird zum Diktiergerät und findet oft die schlechtere Lösung.
14.2 Ziel: Outcome, nicht Aktivität
Ticket: „Refactore den Auth-Service.“ Drei Stunden später: Diff hübsch, Login-Sperre nach Fehlversuchen immer noch offen — weil nie jemand den Zustand danach formuliert hat. Der Agent soll den Lösungsraum nutzen, den Training und Repo hergeben — nicht deine vorweggenommene Implementierung nachbauen (außer Compliance verlangt es). Aktivität klingt produktiv und misst nichts:
| Schwach (Aktivität) | Stark (Outcome) |
|---|---|
| „Refactore den Auth-Service“ | „Login sperrt nach 5 Fehlversuchen für 10 Min; bestehendes Token-Format bleibt“ |
| „Schreib Tests“ | „calculateTax deckt DE/AT-Grenzfälle ab; die 6 Fälle grün und scheitern ohne Feature. Die globale Coverage-Prozentzahl zählt nicht; Diff-Coverage und Assertions, die ohne Feature scheitern, zählen“ |
| „Verbessere Performance“ | „GET /search p95 < 200ms auf Fixture X; Algorithmus egal, API stabil“ |
In der Praxis reicht oft schon der Wechsel von Verb („refactore“) zu Zustand danach („… bleibt / gilt / antwortet“), und der Diff wird messbarer.
14.3 Nebenbedingungen vs. Micro-Management
Gute Nebenbedingungen
Nebenbedingungen begrenzen den Lösungsraum, ohne die genaue Umsetzung vorzuschreiben: keine neuen Dependencies ohne Freigabe; Public API stabil lassen; Fehlerformat wie bei CreateOrg; Thread-Safety / idempotent; bestehende RateLimiter-Util nutzen, wenn vorhanden.
Micro-Management (meist Avoid)
Exakte Zeilennummern und finaler Code im Prompt. „Benutze genau diese 4 Hilfsfunktionen in genau dieser Reihenfolge.“ Architektur-Diktat ohne sachlichen Grund („unbedingt Hexagonal mit 12 Ports“).
Ausnahme: Pair-Programming-Modus, Lehr-Kontext, oder gesetzliche/protokollharte Schritte. Dann ist Restriktion Absicht — kennzeichnet sie. Sonst verwechselst du Steuerung mit Diktat und zahlst mit schlechteren Lösungen.
Dieselbe Rate-Limit-Anforderung, zwei Formulierungen. Nebenbedingung: „Public API bleibt; bestehende RateLimiter-Util nutzen, wenn vorhanden; keine neue Dependency ohne Freigabe.“ Micro-Management: „Schreib class SlidingWindowLimiter in rateLimit.ts Zeile 12, nutze genau Map<string, number[]>, exportiere check(ip: string): boolean.“ Die Nebenbedingung lässt den Agent die vorhandene Util finden. Das Diktat erzeugt eine zweite Implementierung neben der Util, weil der Prompt den Namen vorschreibt. These 5 steuert den Raum; Zeilennummern steuern die Tastatur.
14.4 Ausschlüsse: der unterschätzte Hebel
Ohne Ausschlüsse expandiert der Agent gerne: „gleich Docs“, „gleich UI“, „gleich Migration auf das neue Framework“. Adjektive im Zielsatz („nur das Nötige“) helfen selten. Explizite Ausschluss-Listen helfen oft.
Do this:
## Ausschlüsse
- Keine UI
- Keine DB-Migration (in-memory ok)
- Kein Redis in Slice 1
- Keine Änderungen an packages/legacy/**
Ausschlüsse machen vertikale Slices (Kap. 8) im Prompt sichtbar und Surgical Changes (Kap. 13) durchsetzbar, bevor der Diff wächst.
Warum Adjektive scheitern: „nur das Nötige“ ist für das Modell kein Filter, sondern Stil. Der Training-Default bleibt vollständig — Docs, UI, Migration, weil vollständig hilfreich wirkt. Eine Ausschlussliste ist ein harter Stopp vor dem Tool-Call: der Pfad packages/legacy/** steht nicht in der erlaubten Diff-Menge. Der Agent kann ihn trotzdem anfassen; dann ist das ein Review-Fund gegen den Prompt, kein Interpretationsspiel. Deshalb gehören Ausschlüsse in denselben Block wie die DoD, nicht in den Zielsatz.
14.5 DoD im Task: messbar und erreichbar
Siehe Kap. 10. Im Task-Prompt gehören: Verhaltenschecks, exakte Kommandos, Scope-Checks (git diff --name-only), Stop/Eskalation.
Mini-Beispiel:
## DoD
- [ ] `pnpm --filter auth test` exit 0
- [ ] `pnpm lint` exit 0
- [ ] `git diff --name-only` nur unter `apps/api/src/auth/**` und Tests
- [ ] Stop & frage, wenn Public-API anderer Packages nötig scheint
Vermeide DoDs, die Implementierung diktieren („Funktion muss helperFoo heißen“), außer der Name ist der Contract. Die DoD misst Erfolg; sie ist kein zweites Micro-Management hinter dem Zielsatz.
14.6 Side-by-Side: schlecht / besser
Beispiel A — Bugfix
Zu vage:
Login ist kaputt, fix it.
Zu restriktiv:
In auth.js Zeile 88 ändere sleep(100) zu sleep(50) und benenne variable tmp in tmp2 um…
Gut:
## Ziel
Nutzer können sich wieder anmelden, wenn das Passwort korrekt ist.
Repro: … (Schritte / Screenshot / Log-Zeile)
## Nebenbedingungen
- Keine API-Contract-Änderung
- Bestehende Session-Cookies kompatibel
## Ausschlüsse
- Password-Reset-Flow
- UI-Redesign
## DoD
- [ ] Repro schlägt nicht mehr fehl
- [ ] `pnpm --filter auth test` exit 0
- [ ] Manueller Smoke: Login + Logout (Checkliste)
Beispiel B — Feature
Zu vage: „Add CSV export.“
Gut:
## Ziel
Admins exportieren die gefilterte Rechnungsliste als CSV (aktuelle Filter der Liste).
## Nebenbedingungen
- Max. 10k Zeilen; darüber 400 mit bestehendem Error-Format
- Gleiche Authz wie Listen-Endpoint
## Ausschlüsse
- Excel, E-Mail-Versand, async Jobs
## DoD
- [ ] Integrationstest: 200, Content-Type text/csv, Header-Zeile korrekt
- [ ] Integrationstest: unauthorized → 403
- [ ] `make test-invoices` exit 0
Beispiel C — Upstream-Timeout
Zu vage: „Mach den HTTP-Client robuster.“
Zu restriktiv:
In client.ts Zeile 40 setze timeout: 8000 und retry: 3 mit
exponential backoff, benutze genau p-retry, benenne die
Hilfsfunktion waitWithJitter.
Gut:
## Ziel
`GET /upstream/status` bricht nach 2 s ab und liefert das
bestehende Error-Format; der Aufrufer hängt nicht.
## Nebenbedingungen
- Public API und Error-Shape bleiben.
- Bestehende Retry-Util nutzen, wenn vorhanden; sonst Stdlib.
## Ausschlüsse
- Keine neue Retry-Library ohne Freigabe.
- Kein Circuit-Breaker, kein Dashboard, keine anderen Endpoints.
## DoD
- [ ] Test: Upstream > 2 s → Error-Format, Exit 0 der Suite
- [ ] Test: Upstream < 2 s → 200 unverändert
- [ ] `pnpm --filter api test` exit 0
- [ ] `git diff --name-only` nur unter `apps/api/src/http/**` und Tests
Drei Fehlerklassen, drei Kosten. Vage füllt der Agent den Lösungsraum mit dem Training-Default — oft eine Retry-Library, obwohl ein Timeout gereicht hätte. Du reviewst dann eine Lösung für ein anderes Problem. Restriktiv nimmt These 5 zurück: Zeilennummern und Pflicht-Dependencies machen dich zum Diktiergerät; der Agent darf den Stack nicht mehr ausarbeiten und liefert oft die schlechtere Variante. Gut ist der Erfolgsraum: Zustand danach, harte Grenzen, Orakel. Der Weg bleibt verhandelbar — genau das, was These 5 verlangt.
Was im Loop passiert, wenn du die drei Varianten von Beispiel C abschickst:
- Vage. Explore ist kurz, der erste Plan heißt „Resilience“. Der Diff zieht
p-retryein, wickelt drei Endpoints ein, schreibt einen HelperwaitWithJitter. Die DoD war nie genannt — „robuster“ ist grün, sobald irgendetwas retried. Review-Last: du musst die Library wieder rausschneiden. - Restriktiv. Der Agent patched Zeile 40 exakt. Timeout 8000 statt 2 s, weil du 8000 diktiert hast.
p-retrykommt trotzdem, weil du sie genannt hast — auch wennAbortSignalin der Stdlib reicht. Ein bestehender Helper wird ignoriert, weil der Prompt ihn nicht erwähnt. Du besitzt jede Zeile und zahlst den schlechteren Weg. - Gut. Explore findet die Retry-Util oder die Stdlib. Der Agent wählt einen Weg, der Error-Shape und Public API hält. Verify ist
pnpm --filter api testplusgit diff --name-only. Scope-Creep (Dashboard, andere Endpoints) ist per Ausschluss schon tot, bevor der Diff wächst.
Dieselbe Mechanik in A und B: „Login ist kaputt, fix it“ endet in einem Redesign des Reset-Flows. „Zeile 88, sleep(50)“ endet in einem Rename ohne Diagnose. „Add CSV export“ ohne Ausschlüsse endet in Excel und E-Mail. Die Leitformel ist nicht höflicher — sie ist der billigste Weg, These 5 und These 4 in einem Prompt zu verdrahten.
Der Unterschied ist selten „mehr Worte“. Es ist messbarer Outcome plus harte Grenzen.
14.7 Wie viel Kontext in den Prompt?
Genug, um den Lösungsraum zu begrenzen — nicht den halben Incident-Thread. Besser: Pfade und „lies X“ als Auftrag an den Agent (aktuelle HEAD-Wahrheit) statt 200 Zeilen Paste von gestern. Was im Repo liegt, soll der Agent lesen; was nur im Chat lebt, mutiert und veraltet (Kap. 4 und 10).
Eine brauchbare Menge ist oft: Ziel in 1–3 Sätzen, drei bis fünf Nebenbedingungen, eine Ausschlussliste, vier DoD-Haken, zwei Pfade zum Lesen. Alles darüber ist meist Micro-Management oder Incident-Dump. Fehlt eines der vier Leitformel-Felder, ist „mehr Kontext“ die falsche Kompensation — du füllst das Fenster und lässt den Erfolgsraum leer. These 2 gilt hier in der hässlichen Variante: der Prompt ist Context. Müll im Prompt steuert den Diff genauso wie Müll im Repo.
14.8 Ton und Sprache
Direkt, outcome-orientiert. Bullet Points schlagen Prosa-Romane. Eine Primäraufgabe pro Prompt (Slices). Explizite Erlaubnis und Verbote für Commit/Push. Der Prompt steuert den Loop; er ist keine Team-Diskussion im Entwurfsstadium.
Ein Prompt mit zwei gleichrangigen Hauptzielen („CSV-Export und Login-Fix“) zwingt den Agent, Scope zu mischen. Zwei Slices, zwei Prompts, zwei DoDs sind billiger als ein gemischter Diff. Commit/Push explizit verbieten, wenn der Slice nur Explore oder Plan ist — sonst committet der Harness den Zwischenstand, sobald die Permission das zulässt (These 1: das Modell erzeugt Text, der Harness führt aus).
14.9 Task-Prompt-Checkliste
- Outcome in 1–3 Sätzen
- Nur echte Nebenbedingungen
- Ausschlüsse genannt
- DoD agent-prüfbar
- Nicht unnötig implementierungsdiktierend
- Ein Slice, nicht das Epic
- Kontextquellen / Nicht-anfassen
Wenn ein Punkt fehlt, fehlt meist genau die Fehlerklasse, die der Agent als Nächstes produziert.
Die Checkliste ist der Teach-back vor Execute (Kap. 11): du hörst, was fehlt, bevor der erste Write läuft. Fehlt die DoD, stoppt Alignment hier — nicht erst im Review, wenn der Diff schon steht.
Key Takeaways
- Leitformel: Ziel + Nebenbedingungen + Ausschlüsse + DoD.
- Outcome schlägt Aktivitätsliste; DoD schlägt Bauchgefühl.
- Zu restriktiv und zu vage sind beide teuer — in unterschiedliche Richtungen.
- Du definierst den Erfolgsraum; der Agent arbeitet die Lösung aus.
Praktische nächste Schritte
- Task-Prompt-Template aus Anhang A in die Snippet-Library.
- Ein aktuelles Ticket in die Leitformel umschreiben; Micro-Schritte streichen.
- Prüfbare DoD-Kommandos ergänzen.
- Weiter: Kapitel 15.
