# Code-Review und menschliche Abnahme

> Wie review scope, anchor und gate ein Code-Review prüfbar machen, die eingebauten Regeln und wie ein Mensch ein Abnahmeprotokoll durchspielt, das gelesen, klassifiziert und geprüft wird.

Canonical: https://bmad-plus.rochetta.fr/de/docs/concepts/code-review-and-acceptance/
Language: de
BMAD+ version: 0.23.1
Documentation reviewed: 2026-10-19
Author: Laurent Rochetta
License: MIT

BMAD+ Dokumentation › [Konzepte](https://bmad-plus.rochetta.fr/de/docs/concepts/) › Code-Review und menschliche Abnahme

Zwei Arten von Beleg kommen zu den automatisierten Tests hinzu. Ein prüfbares Code-Review zeigt, was geprüft wurde, wo jeder Befund liegt und warum das Review endete. Ein menschlicher Abnahmelauf (auf Französisch recette, das Wort, das das Werkzeug für die Seite nutzt) zeigt, dass ein Mensch die Kette auf dem Bildschirm funktionieren sah. Beides sind Belege, die man danach lesen kann, und beide weigern sich, „alles gut“ zu sagen, wenn der Beleg unvollständig ist. Diese Seite richtet sich an Reviewer, Teamleiter und alle, die entscheiden, ob eine Version ausgeliefert wird.

<a id="review-why"></a>
## Warum ein Review Belege braucht

Ein in Prosa geschriebenes Review ist nicht von einem zu unterscheiden, das zwölf von vierzig Dateien las und nichts fand. BMAD+ überlässt das Review selbst dem Host-Agent (es ruft kein Modell auf) und fügt die drei Dinge hinzu, die nur Code garantieren kann.

1. Was geprüft werden muss, wird berechnet, mit einem Hash versiegelt und aufgelistet, mit benanntem Grund für jede ausgelassene Datei.
2. Wo ein Befund liegt, ergibt sich aus einem wörtlichen Zitat des Codes, das die CLI lokalisiert. Die Zeilennummer eines Modells wird nie geglaubt.
3. Das Urteil folgt aus der Abdeckung (jede ausgewählte Datei berücksichtigt), nie aus der Zahl der Befunde.

<a id="review-flow"></a>
## Der Review-Ablauf: scope, anchor, gate

Die Kennung, die du übergibst (unten `demo-1`), benennt einen Ordner, `_bmad-output/review/<id>/`, in dem alle Belege liegen. Das Terminal zeigt einen echten Lauf in einem Git-Projekt mit zwei Commits: Der zweite schrieb eine Funktion mit einer um eins verschobenen Schleife um und committete außerdem eine `.env`-Datei.

**review scope, rules und ein Gate, das incomplete meldet**

```text
$ npx bmad-plus review scope demo-1 --base HEAD~1 --effort high
/work/demo/app4/_bmad-output/review/demo-1/scope.json
1 file(s) to review, 4 changed lines, 1 unit(s) — scope d29789f5ea88
  excluded 1 × secret
checklist: /work/demo/app4/_bmad-output/review/demo-1/checklist.md
plan: high effort, 3 pass(es), refutation pass
Every selected file must end in coverage.json as completed, failed or waived (with a reason).
$ npx bmad-plus review rules src/cart.js
rule set 77b96cb6389d (built-in)
src/cart.js gets 2 rule(s):
  general                  code         builtin  **
  javascript-typescript    code         builtin  **/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx} **/*.{vue,svelte}
$ npx bmad-plus review gate demo-1
demo-1: incomplete — coverage 0/1 completed (0 waived), 0 open finding(s), 0 refuted
  - no coverage.json: which files were reviewed is not established
  - no findings.json: write it even when there is nothing to report
  - 1 selected file(s) never accounted for: src/cart.js
# Exit-Code 2. Die Datei `.env` wurde als Geheimnis ausgeschlossen, bevor ein Muster sie zurückbringen konnte.
```

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-18

Jetzt prüft der Host-Agent. Er liest `scope.json` und `checklist.md` (die auf die ausgewählten Dateien anwendbaren Review-Regeln, jede einmal, mit den Dateien, die sie abdeckt) und schreibt zwei Dateien: `findings.json` und `coverage.json`. Ein Befund zitiert den Code; die Datei ist per Hash an den Scope gebunden.

**findings.json (ein bestätigter Befund; der Scope-Hash ist gekürzt)**

```json
{
  "schema": "bmad-plus/review-findings/1",
  "scopeSha256": "d29789f5ea88...",
  "findings": [
    {
      "id": "F1",
      "path": "src/cart.js",
      "existing_code": "for (let i = 0; i <= items.length; i++) sum += items[i].price;",
      "content": "The loop runs one step past the end: items[items.length] is undefined, so reading .price throws.",
      "category": "correctness",
      "severity": "high",
      "confidence": "high",
      "disposition": "confirmed",
      "evidence": "With items = [{price: 1}], i reaches 1 and items[1] is undefined, so items[1].price throws.",
      "trigger": "Any non-empty cart.",
      "consequence": "total() throws a TypeError."
    }
  ]
}
```

**coverage.json (jede ausgewählte Datei muss vorkommen)**

```json
{
  "schema": "bmad-plus/review-coverage/1",
  "scopeSha256": "d29789f5ea88...",
  "items": [ { "path": "src/cart.js", "outcome": "completed" } ]
}
```

**anchor, dann gate mit einer Check-Datei für CI**

```text
$ npx bmad-plus review anchor demo-1
/work/demo/app4/_bmad-output/review/demo-1/findings.anchored.json — 1 located, 0 ambiguous, 0 unlocated
$ npx bmad-plus review gate demo-1 --emit-check _bmad-output/review/demo-1/check.json
demo-1: findings — coverage 1/1 completed (0 waived), 1 open finding(s), 0 refuted
  check: /work/demo/app4/_bmad-output/review/demo-1/check.json
# Exit-Code 1. Im ersten Versuch fehlte dem Befund das Feld evidence: Das Gate meldete „incomplete“ mit dem Grund „a confirmed finding needs evidence“, bis es ergänzt wurde.
```

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-18

<a id="review-commands"></a>
### Befehle und Exit-Codes

**bmad-plus review**

| Befehl | Was er tut | Exit |
| --- | --- | --- |
| `review scope ID` | Löst die Refs auf, bildet den Diff ab der Merge-Basis, wählt Dateien aus und schreibt `scope.json` und `checklist.md`. Optionen: `--base REF` (Standard `HEAD~1`, mit `--workspace` `HEAD`), `--head REF` (Standard `HEAD`), `--workspace` (Arbeitsbaum samt nicht verfolgter Dateien), `--include GLOB`, `--exclude GLOB` (wiederholbar), `--effort low\|medium\|high`. | 0; 3 bei Fehler |
| `review anchor ID` | Validiert `findings.json`, lokalisiert jedes `existing_code`-Zitat in der Head-Version und schreibt `findings.anchored.json`. Zugangsdaten im zitierten Text werden zu `[REDACTED]`. | 0 alles lokalisiert; 1 ungültig oder nicht lokalisiert |
| `review gate ID` | Validiert Befunde und Abdeckung gegen den Scope-Hash und leitet das Urteil ab. `--emit-check FILE.json` schreibt zusätzlich ein CI-Check-Dokument. | 0 clean; 1 findings; 2 incomplete; 3 Fehler |
| `review continue ID` | Setzt ein unterbrochenes Review auf demselben versiegelten Scope fort und schreibt `continue.json` mit dem, was noch aussteht. | 0; 3, wenn Code, Regeln oder eine ausgewählte Datei sich bewegt haben |
| `review compare ID --since EARLIER` | Sortiert die Befunde zweier Reviews derselben Arbeit in neu, bestehend, gelöst, widerlegt und nicht geprüft. | 0; 3 bei Fehler |
| `review rules [PATH]` | Listet die wirksamen Regeln oder die, die für einen Pfad gelten. | 0; 3 bei Fehler |

<a id="review-selection"></a>
### Was ausgewählt und was ausgelassen wird

Jede ausgelassene Datei trägt einen Grund: `secret` (`.env*`, Schlüssel, Zertifikate, `credentials/`, `secrets/`, `.npmrc`, `.netrc`; zuerst geprüft, kein Include-Muster bringt sie zurück), `binary`, `deleted`, `excluded-by-pattern`, `generated-or-vendored` (Lockfiles, `node_modules`, `dist`, `build`, minifizierte Dateien; ein Include-Muster kann sie zurückbringen) und `not-included`. Ausgewählte Dateien werden nach Verzeichnis in geordnete Einheiten zu höchstens 8 Dateien und 400 geänderten Zeilen geschnitten, damit parallele Reviewer die Arbeit deterministisch teilen. Der Review-Ordner selbst ist nie Teil der Änderung.

`--effort` legt die Tiefe vor dem Lesen fest: `low` ist ein Durchgang; `medium` (Standard) sind zwei Durchgänge und ein Widerlegungsdurchgang; `high` sind drei Durchgänge und ein Widerlegungsdurchgang. Eine Änderung ab 150 Zeilen wird vor dem Lesen überblickt, und eine Änderung ab 400 Zeilen mit mehreren Einheiten wird in parallelen Einheiten geprüft. Der Aufwand ist in der Scope-Identität versiegelt.

<a id="review-verdicts"></a>
### Wie das Urteil abgeleitet wird

**Urteile von review gate**

| Urteil | Wann | Exit |
| --- | --- | --- |
| `incomplete` | Abdeckung oder Befunde fehlen oder sind ungültig; sie beantworten einen anderen Scope; eine ausgewählte Datei ist nicht berücksichtigt oder fehlgeschlagen; das Laufprotokoll sagt, das Review endete vorzeitig oder gab eine Einheit auf; ein offener Befund ist nicht verankert. | 2 |
| `findings` | Der Scope ist vollständig abgedeckt und mindestens ein Befund ist offen (bestätigt oder ungeklärt). | 1 |
| `clean` | Der Scope ist vollständig abgedeckt und kein Befund ist offen. Es heißt „kein offener Befund in einem vollständig abgedeckten Scope“; es ist kein Beweis, dass der Code korrekt ist, und der Befehl sagt das. | 0 |

- Befunde nutzen geschlossene Vokabulare: Schweregrad `critical`, `high`, `medium` oder `low`; Konfidenz `high`, `medium` oder `low`; Disposition `confirmed`, `refuted` oder `unresolved`; zehn Kategorien (correctness, security, data-loss, concurrency, performance und weitere). Ein unbekannter Wert ist ein Fehler und wird nie umgebogen. Ein widerlegter Befund behält seine zitierte Begründung; ein bestätigter seinen Beleg.
- Das Verankern vergleicht ganze aufeinanderfolgende Zeilen nach Normalisierung der Leerraumzeichen. Ein Treffer ist located, mehrere sind ambiguous, keiner ist unlocated. Ein offener, nicht lokalisierter Befund hält das Gate auf `incomplete`: Zitiere einen längeren exakten Ausschnitt.
- Ein Review kann festhalten, warum es endete (Feld `run.stop` in `coverage.json`: completed, budget, time-limit, failure-streak, interrupted). Alles außer `completed` hält das Gate auf `incomplete`, auch wenn jede Datei gelistet ist: Ein abgebrochenes Review ist nie clean. Drei Fehlversuche in Folge an derselben Einheit geben sie für dieses Review auf.
- `review continue` lehnt ab (Exit 3, Status `moved`), wenn Commit, Regeln oder eine ausgewählte Datei sich geändert haben; die Antwort ist dann ein neuer Scope und `review compare`. In `compare` wird ein Befund durch Pfad, Kategorie und normalisiertes Zitat identifiziert, nie durch Zeile oder ID, und ein verschwundener Befund zählt nur als gelöst, wenn das spätere Review seine Datei abschloss; sonst ist er „nicht geprüft“.
- Schwärzungs-Untergrenze: Bevor `findings.anchored.json` geschrieben wird, werden zugangsdatenartige Werte in den zitierten Feldern (Private-Key-Blöcke, URL-Zugangsdaten, Authorization-Header, Bearer-Tokens, Werte von Schlüsseln mit Credential-Namen, bekannte Token-Formen) zu `[REDACTED]`. Es ist eine Untergrenze, kein Scanner: Ein Geheimnis ohne erkennbare Form kann durchrutschen.

<a id="review-rules"></a>
## Die eingebauten Regeln

Eine Regel ist ein an Pfadmuster gebundenes Markdown-Dokument; `checklist.md` listet jede Regel, die für mindestens einen ausgewählten Pfad gilt, einmal, mit den abgedeckten Dateien. Eine Regel ist eine Aufforderung hinzusehen, kein Befund. Eine Regel kann eine `group` (Familie) benennen, damit parallele Reviewer je Gruppe eine Einheit nehmen.

**Die acht mit BMAD+ gelieferten Regeln**

| Regel | Gruppe | Gilt für |
| --- | --- | --- |
| `general` | code | Jede Datei: Aufrufer, entferntes Verhalten, Grenzen, Fehler, Vertrauen, Tests. |
| `javascript-typescript` | code | JS-, TS-, JSX-, TSX-, Vue- und Svelte-Dateien. |
| `python` | code | Python-Dateien. |
| `sql-and-migrations` | data | SQL- und Migrationsdateien. |
| `shell` | code | Shell-Skripte. |
| `ci-workflows` | delivery | CI-Workflow-Dateien. |
| `containers` | delivery | Container-Build-Dateien. |
| `configuration` | delivery | Konfigurationsdateien. |

Ein Projekt ergänzt, ersetzt oder deaktiviert Regeln in `_bmad/review-rules.yaml` (Schema `bmad-plus/review-rules/1`): Eine Regel ist `{id, title, globs, doc}` mit einem Markdown-Dokument in `_bmad/` von höchstens 64 KB, und `disable: [id]` entfernt eine. Unbekannte Schlüssel, doppelte IDs, ein Dokument außerhalb von `_bmad/` und das Deaktivieren einer unbekannten Regel werden abgelehnt, nie ignoriert. Der Regelsatz fließt in den Scope-Hash ein, eine Befunddatei beantwortet also genau einen Regelsatz. Mit installiertem Shield-Pack kommen sechs Compliance-Regeln hinzu: `shield-access-control`, `shield-personal-data`, `shield-cryptography`, `shield-logging`, `shield-ai-integrations` und `shield-change-and-supply-chain`. Jede nennt die Kontrollen, auf die sie sich bezieht, etwa `ISO27001:A.8.5`, `SOC2:CC6.1`, `GDPR:Art.32` oder `NIS2:Art.21(2)(d)`.

<a id="review-ci"></a>
### Pull Requests in der CI absichern

Zwei kopierfertige GitHub-Actions-Workflows liegen in `docs/recipes/ci-review/`. `review-scope.yml` versiegelt den Scope und veröffentlicht die Checkliste in der Job-Zusammenfassung und als Artefakt (kein Agent, kein Modell). `review-gate.yml` versiegelt den Scope, lässt den auf einem selbst gehosteten Runner installierten und angemeldeten Host-Agent `findings.json` und `coverage.json` schreiben, prüft, dass im Review-Ordner nur diese beiden Dateien und im Checkout außerhalb nichts geändert wurde, und verankert und prüft dann; der Job scheitert bei unvollständigem Review oder offenen Befunden. Beide laufen nur für Pull Requests desselben Repositorys, mit Nur-Lese-Rechten und allem festgenagelt. `gate --emit-check` schreibt ein Dokument, dessen `github`-Block die Form eines Check-Runs hat, mit höchstens 50 Annotationen an verankerten Zeilen (`critical` und `high` als Fehler, `medium` als Warnung, `low` als Hinweis).

<a id="example-review-sealed-scope"></a>
### Nicht committete Arbeit in einem Ordner prüfen

Nutze es, wenn die Änderung noch nicht committet ist oder nur ein Ordner zählt. `--base HEAD --workspace` vergleicht den Arbeitsbaum samt nicht verfolgter Dateien mit dem letzten Commit, und `--include` schränkt den Scope ein.

**In deinem KI-Assistenten**

```text
Sentinel, prüfe meine nicht committete Arbeit nur in src/billing. Versiegele den Scope mit bmad-plus review scope billing-1 --base HEAD --workspace --include "src/billing/**" --effort medium und wende die Regeln der Checkliste an. Zitiere den Code jedes Befunds wörtlich, berücksichtige jede ausgewählte Datei in coverage.json, führe review anchor und review gate aus und sag mir genau, welche Dateien ausgelassen wurden und warum. Meldet das Gate incomplete, sag, was fehlt, statt es clean zu nennen.
```

**Das solltest du erhalten** `_bmad-output/review/billing-1/` enthält `scope.json` und `checklist.md`, danach `findings.json`, `findings.anchored.json` und `coverage.json`, sobald das Review geschrieben ist. Der Bericht nennt das Urteil (`incomplete`, `findings` oder `clean`) mit der Abdeckungszahl, listet jeden offenen Befund mit zitiertem Code auf und nennt die ausgelassenen Dateien: Eine `.env` neben dem Code wird als `secret` ausgeschlossen, eine Datei außerhalb von `src/billing` als `not-included`.

<a id="acceptance"></a>
## Menschliche Abnahme: das Protokoll

Automatisierte Tests beweisen, dass die Teile sich verhalten. Ein Abnahmeprotokoll beweist, dass ein Mensch die Kette auf dem Bildschirm funktionieren sah: Schreiber, Leser, Bildschirm, Geste. Der Core-Skill `bmad-plus-uat` (von Sentinel gesteuert; Befehle `uat`, Alias `recette`) macht aus einer Auslieferung eine eigenständige Seite, die ein nicht technischer Tester Schritt für Schritt durchspielt. Seine Häkchen werden zu einem JSON-Lauf, den der Agent liest, klassifiziert und gatet.

1. **Die Spezifikation schreiben** Eine JSON-Datei `_bmad-output/uat/specs/<product>-<version>.json` (Schema `bmad-plus/uat-spec/2`). Eine echte Schrittfolge, jeder Schritt mit `where`, `do` und `expect`; ein Klick pro `do`-Zeile, ein prüfbarer Fakt pro Erwartung; Bildschirmbeschriftungen wortgleich aus dem Code; ein Zeuge (worauf der Test beruht) mit der Nur-Lese-Abfrage, die seinen Zustand belegt; `writes: true` plus eine `verify`-Prüfung bei jedem Schritt, der etwas persistiert.
2. **Prüfen und bauen** `uat lint` prüft die Beschriftungen gegen deine Quelldateien, das Markup, das Budget (standardmäßig 15 Schritte und 30 Minuten) und die Zeugen. `uat build` schreibt die Seite, die den SHA-256 der Spezifikation trägt, damit ein Lauf immer sagt, welche Revision er beantwortete.

   ```sh
   npx bmad-plus uat lint ID --src src
   npx bmad-plus uat build ID
   ```
3. **Die Seite übergeben** Lokal lauscht `uat serve` nur auf 127.0.0.1 und schreibt die Antworten bei jedem Häkchen direkt ins Projekt. Anderswo schickst du die HTML-Datei; der Tester speichert das JSON und du lädst es mit `uat import`. In Claude Code oder claude.ai kann die Seite als Artefakt veröffentlicht werden, dessen Datenbank die Antworten behält. Sag klar, wo die Antworten liegen und welche Schritte wirklich schreiben.

   ```sh
   npx bmad-plus uat serve ID --port 4173
   ```
4. **Den Lauf lesen** `uat read` gibt je Lauf den Tester, die Daten, die Zahlen bestandener, fehlgeschlagener, blockierter, übersprungener und offener Schritte, Warnungen zu veraltet oder unsigniert und jeden Fehler mit Erwartungstext und Notiz des Testers aus.

   ```sh
   npx bmad-plus uat read ID
   ```
5. **Klassifizieren, Schreibvorgänge bestätigen, Gate** Klassifiziere jede fehlgeschlagene oder blockierte Erwartung in `triage/<id>.json`, führe das `verify` jedes bestandenen Schreibschritts schreibgeschützt aus und halte es fest, dann führe `uat gate` aus.

   ```sh
   npx bmad-plus uat gate ID
   ```

**lint, build, dann ein Gate ohne Lauf (die mitgelieferte Beispielspezifikation)**

```text
$ npx bmad-plus uat lint example-1.0.0
example-1.0.0: 3 steps, 5 expectations, 8 on-screen labels
  no error
$ npx bmad-plus uat build example-1.0.0
/work/demo/app4/_bmad-output/uat/pages/uat-example-1.0.0.html — 3 steps, 83 KiB, spec a4a4850b284d
opens in English; the tester can switch to any of the 10 languages on the page
carries the 17 page guarantees: hidden-before-start, no-answer-before-run, verified-local-write, honest-save-status, save-on-every-change, restore-before-capabilities, newer-copy-wins, revision-guard, other-tab-notice, unreadable-draft-kept, progress-accessible, storage-explained, finished-is-not-accepted, unload-guard, utf8-and-escaped-diacritics, export-is-the-run, no-third-party-requests
$ npx bmad-plus uat gate example-1.0.0
example-1.0.0: awaiting
  - no run yet
# Exit-Code 2: awaiting. Die Spezifikationsdatei ist das im Core-Skill uat mitgelieferte Beispiel (templates/example-uat-spec.json).
```

Ausgabe eines echten Laufs. Quelle: bmad-plus 0.23.0, 2026-10-18

<a id="uat-gate-and-triage"></a>
### Gate-Urteile, Triage-Klassen und Verify-Arten

**Exit-Codes von uat read und uat gate**

| Code | Urteil von `uat gate` | `uat read` |
| --- | --- | --- |
| 0 | `passed`: Der Lauf ist abgeschlossen, aktuell, vollständig und klassifiziert. | Kein fehlgeschlagener Schritt. |
| 1 | `failed`. | Mindestens ein Fehler. |
| 2 | `awaiting`: noch kein abgeschlossener Lauf. | Kein Lauf. |
| 3 | `stale`: Der Lauf beantwortete eine andere Revision der Spezifikation. | Veraltet. |

**Triage: jeden Fehler klassifizieren, bevor etwas repariert wird**

| Klasse | Anzeichen | Folge |
| --- | --- | --- |
| `product` | Der Bildschirm weicht von dem ab, was der Code darstellen sollte. | Eine Korrekturaufgabe an der Story und ein Wiederholungsschritt im Protokoll der nächsten Version. |
| `recipe` | Der Bildschirm zeigt das gewünschte Ergebnis; die Erwartung beschrieb es falsch. | Spezifikation ändern, neu bauen (neuer Fingerabdruck), betroffene Schritte wiederholen und sagen, dass keine Produktänderung nötig war. |
| `data` | Der Zeuge ist nicht mehr im angenommenen Zustand. | Die Abfrage des Zeugen erneut ausführen, ihn zurücksetzen oder umbenennen, wiederholen. |
| `undecided` | Keine Notiz oder nicht zuordenbar. | Den Tester fragen, was er sah; nie raten. Das Gate bleibt rot. |

Für jeden klassifizierten Fehler wird eine Entscheidung festgehalten: `fix`, `amend-spec`, `remeasure`, `accept-risk` (mit benanntem Verantwortlichen) oder `ask-tester`. `verify`-Prüfungen haben eine Art: `sql`, `http`, `command` oder `manual`. Ein Häkchen bei einem Schreibschritt ist kein Schreibvorgang: Sein `verify` wird schreibgeschützt ausgeführt und in `writeChecks` festgehalten, denn ein neunmal von neun abgehakter Schritt hatte sich einmal als folgenlos erwiesen. Das Gate sagt, was es feststellt: „human-observed: complete, current and triaged“. Es stellt nicht fest, dass der Tester an der richtigen Stelle hinsah.

<a id="uat-config"></a>
### Die uat-Einstellungen

**Der uat-Block in _bmad/config.yaml**

| Schlüssel | Standard | Bedeutung |
| --- | --- | --- |
| `mode` | `advisory` | `advisory` baut und bietet die Seite an, blockiert nie. `gate` lässt die Auslieferung auf ein bestandenes Gate warten. `off` erzeugt kein Protokoll, und der Auslieferungsbericht sagt das. Ein fehlender Block gilt als `advisory`. |
| `granularity` | `delivery` | Ein Protokoll pro Auslieferung. |
| `environment` | Name und url leer | Die Testumgebung, auf die das Protokoll zielt (bei der Installation abgefragt). |
| `page_budget` | 15 Schritte, 30 Minuten | Darüber in geordnete Seiten aufteilen. |
| `dir` | `_bmad-output/uat` | Wo Spezifikationen, Seiten, Ergebnisse und Triage liegen. |

<a id="why-a-tag-needs-a-run"></a>
## Warum ein Release-Tag einen akzeptierten Lauf braucht

BMAD+ wendet die Regel auf sich selbst an. Am 2026-09-16 wurde festgestellt, dass ein Befehl (`studio list`) in einer echten Installation kaputt war, und zwar seit Wochen. Die Testsuite war grün, der Installationsvertrag bestand und die CI war grün. Was keiner von ihnen tat: das Produkt installieren und so benutzen, wie ein Mensch es tut. Seit 0.17.0 erreicht eine Version npm erst, wenn ein Mensch den Kandidaten in einem leeren Ordner installiert, die Protokollseite durchgespielt und jeder Fehler klassifiziert wurde. Das Protokoll von 0.23.0 wurde am 2026-10-18 in einem leeren Projekt gespielt: 28 von 28 Erwartungen bestanden, jeder Schreibschritt schreibgeschützt bestätigt. Ein erster Lauf dieses Protokolls hatte einen Deinstallationsfehler aufgedeckt, der die kopierten Design-Skills zurückließ; er wurde vor dem Tag behoben. Die Läufe selbst bleiben auf dem Rechner des Maintainers, weil sie lokale Pfade enthalten; das CHANGELOG hält den aufgedeckten Fehler fest.

- Im BMAD+-Repository scheitert `npm run uat:spec`, wenn die Version in `package.json` kein Protokoll hat, und `npm run uat:gate` scheitert, sofern der letzte Lauf nicht abgeschlossen ist, nicht die aktuelle Revision beantwortet, etwas unbeantwortet lässt, nicht jeden Fehler mit Entscheidung klassifiziert hat und nicht jeden bestandenen Schreibschritt schreibgeschützt bestätigt hat. Ein Pre-Push-Hook erzwingt beides bei einem Push eines `v*`-Tags.
- Eine blockierte Erwartung braucht eine Wiederholung oder eine ausdrückliche `accept-risk`-Entscheidung eines benannten Verantwortlichen. Ein Protokoll, das nur abgehakt wurde, damit das Gate besteht, ist schlimmer als keines: Kann ein Schritt nicht gespielt werden, lautet die Antwort „blocked“ mit Grund.
- Dein Projekt kann dasselbe mit zwei im Skill uat mitgelieferten Skripten tun (`templates/`): `uat-spec-present.mjs` (eine Version ohne Protokoll wird vor dem Push abgelehnt) und `uat-release-gate.mjs` (Exit 0 bestanden, 1 fehlgeschlagen, 2 kein abgeschlossener Lauf, 3 andere Revision, 4 das Gate konnte nicht laufen, was kein Bestehen ist). BMAD+ installiert keinen Lifecycle-Hook; diese Skripte sind die Schicht, die eine Anweisung oder ein Agent nicht überspringen kann; hänge sie dort ein, wo sie greifen.

<a id="example-acceptance-build-recipe"></a>
### Eine Abnahmeseite für ein Buchungsformular auf Staging vorbereiten

Nutze es, wenn eine Version auf einer Staging-Seite ankommt und jemand ohne technischen Hintergrund sie auf dem Bildschirm bestätigen muss. Bevorzuge Wegwerf-Testdaten: Der Schritt, der eine Buchung anlegt, schreibt wirklich.

**In deinem KI-Assistenten**

```text
Sentinel, schreibe das Abnahmeprotokoll (recette) für das Buchungsformular, das wir gerade auf Staging ausgeliefert haben. Getestet wird von jemandem von der Rezeption, nicht von einem Entwickler: ein Schritt pro Geste, ein prüfbarer Fakt pro Erwartung, Bildschirmbeschriftungen aus dem Code kopiert. Ergänze für den Schritt, der eine Buchung anlegt, die schreibgeschützte Abfrage, die du danach ausführst, um zu belegen, dass die Zeile existiert. Führe uat lint mit --src src aus, dann uat build, und zeige mir die Garantien, die der Build listet. Nenne mir Datei oder Link, die Dauer, welche Schritte schreiben und wo die Antworten gespeichert werden.
```

**Das solltest du erhalten** Eine Spezifikation in `_bmad-output/uat/specs/`, eine gebaute Seite in `_bmad-output/uat/pages/uat-<id>.html`, die Lint-Zeile („N steps, M expectations, K on-screen labels checked against F source files“), eine `verify`-Abfrage im Buchungsschritt, die Liste der Seitengarantien und eine klare Aussage, wo die Antworten liegen. Die Seite wird nicht übergeben, wenn Lint oder Build scheitert.

<a id="example-acceptance-read-and-triage"></a>
### Einen abgeschlossenen Lauf lesen und jeden Fehler klassifizieren

Nutze es, wenn der Tester fertig ist oder aufgehört hat. Die Ergebnisdatei liegt in `_bmad-output/uat/results/<id>/` oder wird mit `uat import` importiert.

**In deinem KI-Assistenten**

```text
Sentinel, lies den letzten Abnahmelauf mit uat read. Klassifiziere jede fehlgeschlagene oder blockierte Erwartung in der Triage-Datei als product, recipe, data oder undecided und frage mich nach allem, was du nicht zuordnen kannst. Führe die verify-Prüfung jedes bestandenen Schreibschritts schreibgeschützt aus und halte das Ergebnis fest. Führe dann uat gate aus und berichte das Urteil, den Tester und was offen bleibt. Markiere keinen nicht durchgeführten Schritt als bestanden.
```

**Das solltest du erhalten** Eine Triage-Datei mit einer Klasse und einer Entscheidung je Fehler, `writeChecks`-Einträge für die Schreibschritte und eine Gate-Zeile wie `<id>: passed (run <runId> by <tester>)` mit Exit-Code 0 oder `failed`, `awaiting` bzw. `stale` samt Gründen. Ein ungeklärter Fehler hält das Gate rot, bis der Tester antwortet.

**Siehe auch**

- [Referenz: bmad-plus review](https://bmad-plus.rochetta.fr/de/docs/reference/cli-review/)
- [Referenz: bmad-plus uat](https://bmad-plus.rochetta.fr/de/docs/reference/cli-uat/)
- [Referenz: bmad-plus assurance](https://bmad-plus.rochetta.fr/de/docs/reference/cli-assurance/)
- [Nexus und Verifikation vor der Akzeptanz](https://bmad-plus.rochetta.fr/de/docs/concepts/nexus-orchestration/)
- [Referenz: config.yaml](https://bmad-plus.rochetta.fr/de/docs/reference/config-yaml/)

[BMAD+ Dokumentation](https://bmad-plus.rochetta.fr/de/docs/) · [Konzepte](https://bmad-plus.rochetta.fr/de/docs/concepts/)

[Quellcode auf GitHub](https://github.com/lrochetta/BMAD-PLUS)
