Files
ki-eit/09-dod-verify-und-ci.md
grok-bot 8e00712fb8 Kapitel-Review (MUSS): Metriken, Golden Paths und eBook neu.
Composite-Korridore und Primärquellen in Kap. 2 ehrlich kalibriert;
DoD/Verify, Surfaces und Anhänge in 04–16 geschärft; eBook 119 S. neu gebaut.
2026-08-10 22:11:27 +02:00

12 KiB
Raw Permalink Blame History

9. DoD, Verify und CI

Kern: Fertig ist, was Verify grün und Diff zum Auftrag passend ist — nicht was der Agent für „eigentlich schon gut“ hält. Commands müssen non-interactive und in Instructions / Package-Rules stehen.

Die Orakel-Logik (Tests, Types, Contracts) vertieft das Theorie-Schwesterbuch (Coding Agents in der Praxis, Kap. 10). Agent in CI: produktspezifisch (optional Copilot: Der Copilot-CLI-Harness, Teams/CI). Hier die Enterprise-Übersetzung: Tight-Loop vs. Heavy, Command-Matrix für Angular / Spring Boot / Quarkus, non-interactive Gates und CI als Mirror. DoD ist repo-seitig; der Harness muss Commands nur finden und ausführen können (Instructions/AGENTS.md; Surfaces: Anhang C).

Kapitel 5–8 haben pro Schicht und pro Slice schon Verify verlangt. Dieses Kapitel macht das Betriebssystem explizit: welche Commands wann, warum Full-Suite im Chat teuer ist, und warum „lokal grün“ ohne Runtime-Wahrheit (Kap. 4.1) nur Anekdote ist.

9.1 Die typische DoD-Session, die schiefgeht

Auftrag: „Bestellstatus in der Liste — Backend + ein Test.“ Der Agent patcht, startet nach dem ersten Tippfehler ./mvnw clean verify, wartet auf Testcontainers, holt 600 Zeilen Surefire in den Context und erklärt selbstbewusst, der Fix sei „eigentlich schon grün“. Parallel läuft irgendwo noch npm test im Watch-Mode — Exit-Code unklar, UI hat gefragt. Der Reviewer sieht am Ende: der scoped Test hätte in 20 Sekunden gereicht; die Security-Tests, die hätten mitlaufen sollen, standen nie in der DoD. CI wird später rot — anderes JDK-Image als der Laptop.

Du merkst den falschen Verify-Schnitt daran, dass:

  • die Session Minuten pro Loop verbrennt statt Sekunden,
  • Observations aus alten Full-Runs den nächsten Fix vergiften,
  • „fertig“ nur als Prosa im Chat steht, nicht als benannter Exit-Code,
  • lokal und CI andere Toolchains oder Scripts meinen.

Session-Hygiene zuerst

  1. Einen scoped Command benennen, der den Slice beweist — Exit-Code, nicht Prosa.
  2. Tight / Slice-DoD / Heavy und Runtime-Pin in drei Zeilen nachziehen (Kap. 4.1).
  3. Surefire-XML und Full-verify-Ballast aus dem Context; frische Session am benannten Command. Full-Suite bleibt Heavy (Kap. 2.1).

Tight-Loop und Heavy trennen — sonst verbrennt der Agent Zeit und Context.{width=90%}

9.2 Tight-Loop · Slice-DoD · Heavy

Tight-Loop ist der schnelle, scoped Check nach sinnvollen Patches: eine Testklasse, Lint, gezieltes Build-Fragment. Slice-DoD ist „dieser Slice ist baubar und zum Auftrag passend“: Tight bereits grün, plus Package/Build ohne Full-Suite, plus Scope-Check am Diff. Heavy ist CI, Nightly, vor Merge — volle Suite, Integration, e2e, Quality-Gates.

Verify vs. Scope (nicht vermischen):

Teil von Slice-DoD Wer Was „grün“ heißt
Verify Agent (Exit-Code) Tight-Commands + baubar (package / build -x test) non-interactive
Scope / Diff-Fit Review / HITL (Ampel) Diff = Auftrag; keine Drive-bys — nicht durch den Agent allein „abhakbar“

Slice-DoD = Tight grün ∧ baubar ∧ Diff-Fit. Ein Agent, der nur den Build meldet, hat nicht „DoD grün“ im Team-Sinn erledigt. Review-Checkliste: checklists/review-agent-diff-enterprise.md.

Agents, die nach jedem Edit mvn clean install oder die komplette e2e-Suite fahren, verbrennen Zeit und Context (Logs). Agents ohne jedes Verify raten. Beides ist teurer als drei benannte Commands im Repo.

Ebene Wann Ziel Beispiele
Tight-Loop nach sinnvollen Patches schnell, scoped, oft lokal eine Testklasse, ESLint aufs Projekt, tsc/ng build dev
Slice-DoD vor „done“ am Slice Tight grün + baubar + Scope-Check package / build -x test + Diff vs. Auftrag (Scope = Review)
Heavy CI, Nightly, vor Merge volle Suite, Integration, e2e, Quality-Gates full mvn verify, Testcontainers, Playwright/Cypress

Tight-Loop, Slice-DoD und Heavy: Trigger, Commands und Wechselregeln.{width=90%}

Transfer: Die Namen müssen im Team gleich heißen — in Instructions, im Task-Prompt und im Review. Sonst meint der Agent „DoD“, der Reviewer „Heavy“, und niemand hat gelogen.

Framework-Beispiele: Kap. 5.3 (Angular), 6.3 (Spring), 7 (Quarkus). Slice-Reihenfolge: Kap. 8.2.

9.3 Command-Matrix (Muster — anpassen)

Die Matrix ist Muster, kein Dogma. Tragt eure Wrapper-Pfade (mvnw/gradlew), Module (-pl :api), npm-/Nx-Scripts und Runtime-Pin (Kap. 4.1) in Package-AGENTS.md und Root-Instructions/AGENTS.md (Surfaces: Anhang C) ein. Snapshot: Anhang B. Vorlagen: templates/agents-md-*.md, optional Surface-Beispiele templates/copilot-instructions-*.md, Skill templates/skill-verify-stack/.

Angular

# Tight-Loop
npm test -- --watch=false --browsers=ChromeHeadless   # oder Jest/Vitest-Script
npm run lint
# optional scoped:
npx nx test my-app --watch=false --testPathPattern=feature-x

# Slice-DoD
npm run build
# Diff-Review: nur Dateien des Slices

# Heavy
npm run test:e2e   # non-interactive CI-Config

Spring Boot (Maven)

# Tight-Loop
./mvnw -q -Dtest=UserServiceTest test
# mehrere Klassen im Tight: -Dtest=UserServiceTest,UserControllerTest
./mvnw -q spotless:check   # oder checkstyle

# Slice-DoD (Tight bereits grün + baubar + Diff = Auftrag)
./mvnw -q -DskipTests package

# Heavy
./mvnw -q verify           # inkl. Failsafe/Integration

Spring Boot (Gradle)

# Tight-Loop
./gradlew test --tests com.example.UserServiceTest
# mehrere Klassen: zwei --tests-Flags (kein Komma)
./gradlew test --tests com.example.UserServiceTest --tests com.example.UserControllerTest
./gradlew spotlessCheck

# Slice-DoD (Tight bereits grün + baubar + Diff = Auftrag)
./gradlew build -x test    # oder assemble nach Team-Standard

# Heavy
./gradlew build            # inkl. Integrationstests nach Team-Setup

Quarkus

# Tight-Loop (Maven; -q analog Spring)
./mvnw -q -Dtest=GreetingResourceTest test
# Gradle: ./gradlew test --tests com.example.GreetingResourceTest
# Avoid im Agent-Loop: quarkusDev / Continuous Testing (Mensch-Tempo ≠ Exit-Code-DoD)

# Slice-DoD (Tight bereits grün + baubar + Diff = Auftrag / Review)
./mvnw -q -DskipTests package
# Gradle: ./gradlew build -x test

# Heavy
./mvnw -q verify
# Native nur mit Auftrag:
# ./mvnw package -Dnative

Warum die Matrix hier steht: Kap. 5–7 nennen Verify im Vorbeigehen. Ohne eine Stelle, an der Angular, Spring Boot und Quarkus nebeneinander stehen, driftet das Team in drei private „so teste ich“-Varianten — und der Agent erbt die lauteste aus dem Chat.

Multi-module: Maven -pl … -am, Gradle Projektpfade. Surefire-XML, target/, dist/, Coverage-HTML: aus dem Context halten (Ignore-Grenzen Kap. 4).

9.4 Non-interactive ist Pflicht

Ohne Exit-Code, den der Agent lesen kann, gibt es keinen autonomen Loop — nur Theater mit Watch-Mode und „bei mir war grün“.

Problem Fix
CLI fragt y/N Flags (-B, --yes, headless browser, CI=true)
Test öffnet UI Headless / CI-Config
Snapshot-Update interaktiv in Agent-DoD verbieten oder explizit freigeben
Docker braucht TTY CI-taugliche Compose-Profile

Du merkst interaktive DoD daran, dass die Session hängt oder der Agent „angenommen ja“ weiterarbeitet, während der Prozess auf Enter wartet. Fix: denselben Command mit CI=true (oder eurem CI-Äquivalent) einmal selbst fahren und den Flags-Satz in Instructions schreiben.

9.5 CI als Mirror, nicht als Überraschung

CI soll dieselben Commands ausführen wie in Instructions/AGENTS.md — oder eine dokumentierte Obermenge. Drift („lokal grün, CI rot“) ist Context- und Vertrauensgift. Oft steckt der Drift nicht im Script-Namen, sondern in der Runtime: anderes Node/JDK-Image als der lokale Pin, anderer Wrapper-Pfad, stilles Host-Tool. Mirror heißt: dieselbe Toolchain-Wahrheit (Kap. 4.1) und dieselben Task-Einstiege — nicht nur ähnliche YAML-Zeilen.

Nightly darf teurer sein (Mutation, Full e2e); das gehört als Heavy gelabelt, nicht als Tight-Loop. Wer Nightly-Last in den Chat-Loop holt, kauft sich Context-Rot und verliert den Tight-Loop.

Agent in CI (programmatische Läufe, Token- und Permission-Policy) ist produktspezifisch — optional für Copilot: Der Copilot-CLI-Harness (Teams/CI). Hier gilt nur: derselbe Verify-Command und dieselbe Runtime-Annahme wie lokal — keine zweite „Agent-Wahrheit“.

Do this Avoid that
CI-YAML und Instructions dieselben Einstiege „lokal npm test, CI nx test anderes Projekt“ still
Image/Pin = lokaler Pin (oder dokumentierte Abweichung) Host-JDK 21, CI-Image 17, „bei mir grün“
Heavy in Nightly/PR-Gate benennen Full e2e als Tight-Loop im Agent-Prompt

9.6 DoD-Checkliste pro Slice (kopierbar)

Kurzform für Task und Review — stack-spezifisch ausbauen:

  • Akzeptanzkriterien des Task-Prompts erfüllt
  • Tight-Loop-Verify grün (genannte Commands)
  • Kein Scope-Creep im Diff
  • Keine Secrets / keine Debug-permitAll-Reste
  • Bei API-Änderung: Contract/OpenAPI mitgezogen
  • Heavy nur wenn Slice/Policy es verlangt

Lebende Listen: checklists/dod-angular.md, checklists/dod-spring.md, checklists/dod-quarkus.md. Review-Ampel am Diff: checklists/review-agent-diff-enterprise.md.

Mini-Beispiel (Anschluss Kap. 8): Outcome „Status in der Liste“. Backend-DoD: ./mvnw -q -Dtest=OrderControllerTest test. Frontend-DoD: npm test -- --watch=false --include=order-list + Lint. Heavy: e2e nur wenn Policy es verlangt. Diff: Contract + Controller/Test + List-Component — nicht die Payment-Domain.

9.7 Do this / Avoid that

Do this Avoid that
Scoped -Dtest= / --tests / testPathPattern Immer Full Suite im Chat-Loop
Commands und Runtime-Pin in Instructions/AGENTS.md + CI aligned Drei inoffizielle „so teste ich privat“-Varianten; Host-JDK vs. CI-Image still
Log-Noise maskieren / nur Assertion+Stack-Kopf 800-Zeilen Surefire-Dump im Context behalten
Failures als Signal nutzen „baut schon irgendwie“ und weiterfeature
Tight / Slice-DoD / Heavy im Task-Prompt benennen „mach fertig und teste ordentlich“ ohne Command
Einmal CI=true / CI-Container gegen denselben Pin Nur interaktive Dev-Scripts als Agent-DoD

Key Takeaways

  • Kanon Tight-Loop · Slice-DoD · Heavy trennen und benennen — nicht „DoD“ und „Heavy“ synonym.
  • Non-interactive Commands mit klaren Exit-Codes sind die Voraussetzung für Agent-Loops.
  • Verify-Commands ohne Runtime-Wahrheit (Kap. 4.1) sind unvollständige DoD.
  • DoD = Kriterien + Verify + Diff-Fit — nicht Bauchgefühl.
  • CI ist Mirror derselben Wahrheit — nicht eine zweite Testphilosophie.

Praktische nächste Schritte

  1. Pro App/Service in Instructions/AGENTS.md: Runtime/Einstieg + drei Zeilen Tight / Slice-DoD / Heavy.
  2. Einmal selbst im CI-Container oder mit CI=true laufen lassen — gegen denselben Pin wie lokal.
  3. Checklisten checklists/dod-angular.md (usw.) an eure Scripts hängen.
  4. Nächsten Slice-Task mit benannten Commands schreiben (Vorlage Kap. 8 / templates/task-prompt-fullstack-slice.md).
  5. Danach Kap. 10 — Instructions, Skills und MCP so schneiden, dass Verify und Boundaries auffindbar bleiben.