# Revue de code et recette humaine

> Comment review scope, anchor et gate rendent une revue vérifiable, les règles intégrées, et comment une personne déroule une recette lue, triée et soumise à la porte. Pourquoi un tag en exige une.

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

Documentation BMAD+ › [Concepts](https://bmad-plus.rochetta.fr/fr/docs/concepts/) › Revue de code et recette humaine

Deux sortes de preuve s’ajoutent aux tests automatisés. Une revue de code vérifiable montre ce qui a été relu, où se trouve chaque constat et pourquoi la revue s’est arrêtée. Une recette humaine montre qu’une personne a vu la chaîne fonctionner à l’écran. Ce sont deux preuves que l’on peut relire après coup, et toutes deux refusent de dire « tout va bien » quand la preuve est incomplète. Cette page s’adresse aux relecteurs, aux responsables d’équipe et à quiconque décide si une version part.

<a id="review-why"></a>
## Pourquoi une revue a besoin de preuves

Une revue écrite en prose ne se distingue pas d’une revue qui a lu douze fichiers sur quarante et n’a rien trouvé. BMAD+ laisse la revue elle-même à l’agent hôte (il n’appelle aucun modèle) et ajoute les trois choses que seul du code peut garantir.

1. Ce qui doit être relu est calculé, scellé par un hash et listé, avec une raison nommée pour chaque fichier écarté.
2. L’endroit d’un constat vient d’une citation textuelle du code, localisée par la CLI. Un numéro de ligne donné par un modèle n’est jamais cru.
3. Le verdict découle de la couverture (chaque fichier sélectionné pris en compte), jamais du nombre de constats.

<a id="review-flow"></a>
## Le déroulement d’une revue : scope, anchor, gate

L’identifiant que vous passez (`demo-1` ci-dessous) nomme un dossier, `_bmad-output/review/<id>/`, où vit toute la preuve. Le terminal montre une exécution réelle sur un projet Git de deux commits : le second a réécrit une fonction avec une boucle décalée d’un cran et a aussi commité un fichier `.env`.

**review scope, rules, puis un gate qui dit incomplete**

```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
# Code de sortie 2. Le fichier `.env` a été écarté comme secret avant qu’un motif puisse le ramener.
```

Sortie capturée lors d’une exécution réelle. Source: bmad-plus 0.23.0, 2026-10-18

L’agent hôte relit maintenant. Il lit `scope.json` et `checklist.md` (les règles de revue qui s’appliquent aux fichiers sélectionnés, chacune une fois, avec les fichiers qu’elle couvre) et écrit deux fichiers : `findings.json` et `coverage.json`. Un constat cite le code ; le fichier est lié au périmètre par son hash.

**findings.json (un constat confirmé ; le hash du périmètre est abrégé)**

```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 (chaque fichier sélectionné doit y figurer)**

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

**anchor, puis gate avec un fichier de contrôle pour la 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
# Code de sortie 1. Au premier essai, le constat n’avait pas de champ evidence : le gate disait « incomplete » avec la raison « a confirmed finding needs evidence » jusqu’à son ajout.
```

Sortie capturée lors d’une exécution réelle. Source: bmad-plus 0.23.0, 2026-10-18

<a id="review-commands"></a>
### Commandes et codes de sortie

**bmad-plus review**

| Commande | Ce qu’elle fait | Sortie |
| --- | --- | --- |
| `review scope ID` | Résout les références, calcule le diff depuis la base de fusion, sélectionne les fichiers, écrit `scope.json` et `checklist.md`. Options : `--base REF` (défaut `HEAD~1`, ou `HEAD` avec `--workspace`), `--head REF` (défaut `HEAD`), `--workspace` (arbre de travail y compris fichiers non suivis), `--include GLOB`, `--exclude GLOB` (répétables), `--effort low\|medium\|high`. | 0 ; 3 en cas d’erreur |
| `review anchor ID` | Valide `findings.json`, localise chaque citation `existing_code` dans la version de tête et écrit `findings.anchored.json`. Les identifiants dans le texte cité deviennent `[REDACTED]`. | 0 tout localisé ; 1 invalide ou non localisé |
| `review gate ID` | Valide constats et couverture par rapport au hash du périmètre et en déduit le verdict. `--emit-check FILE.json` écrit aussi un document de contrôle pour la CI. | 0 clean ; 1 findings ; 2 incomplete ; 3 erreur |
| `review continue ID` | Reprend une revue interrompue sur le même périmètre scellé et écrit `continue.json` avec ce qui reste dû. | 0 ; 3 si le code, les règles ou un fichier sélectionné ont bougé |
| `review compare ID --since EARLIER` | Classe les constats de deux revues du même travail en nouveaux, persistants, résolus, réfutés et non relus. | 0 ; 3 en cas d’erreur |
| `review rules [PATH]` | Liste les règles effectives, ou celles qui s’appliquent à un chemin. | 0 ; 3 en cas d’erreur |

<a id="review-selection"></a>
### Ce qui est sélectionné et ce qui est écarté

Chaque fichier écarté porte une raison : `secret` (`.env*`, clés, certificats, `credentials/`, `secrets/`, `.npmrc`, `.netrc` ; vérifié en premier, aucun motif d’inclusion ne les ramène), `binary`, `deleted`, `excluded-by-pattern`, `generated-or-vendored` (fichiers de verrouillage, `node_modules`, `dist`, `build`, fichiers minifiés ; un motif d’inclusion peut les ramener) et `not-included`. Les fichiers sélectionnés sont découpés en unités ordonnées par dossier, de 8 fichiers et 400 lignes modifiées au plus, pour que des relecteurs en parallèle se partagent le travail de façon déterministe. Le dossier de revue lui-même ne fait jamais partie du changement.

`--effort` fixe la profondeur avant la lecture : `low` est une passe ; `medium` (par défaut) est deux passes et une passe de réfutation ; `high` est trois passes et une passe de réfutation. Un changement de 150 lignes ou plus est survolé avant d’être lu, et un changement de 400 lignes ou plus en plusieurs unités est relu en unités parallèles. L’effort est scellé dans l’identité du périmètre.

<a id="review-verdicts"></a>
### Comment le verdict est établi

**Verdicts de review gate**

| Verdict | Quand | Sortie |
| --- | --- | --- |
| `incomplete` | La couverture ou les constats manquent ou sont invalides ; ils répondent à un autre périmètre ; un fichier sélectionné n’est pas pris en compte ou a échoué ; le journal d’exécution dit que la revue s’est arrêtée avant la fin ou a abandonné une unité ; un constat ouvert n’est pas ancré. | 2 |
| `findings` | Le périmètre est entièrement couvert et au moins un constat est ouvert (confirmé ou non résolu). | 1 |
| `clean` | Le périmètre est entièrement couvert et aucun constat n’est ouvert. Cela veut dire « aucun constat ouvert dans un périmètre entièrement couvert » ; ce n’est pas une preuve que le code est correct, et la commande le dit. | 0 |

- Les constats utilisent des vocabulaires fermés : gravité `critical`, `high`, `medium` ou `low` ; confiance `high`, `medium` ou `low` ; état `confirmed`, `refuted` ou `unresolved` ; dix catégories (correctness, security, data-loss, concurrency, performance et d’autres). Une valeur inconnue est une erreur, jamais corrigée. Un constat réfuté garde son motif cité ; un constat confirmé garde sa preuve.
- L’ancrage compare des lignes consécutives entières après normalisation des espaces. Une correspondance est localisée, plusieurs sont ambiguës, aucune est non localisée. Un constat ouvert non localisé garde le gate à `incomplete` : citez un extrait exact plus long.
- Une revue peut consigner pourquoi elle s’est arrêtée (champ `run.stop` de `coverage.json` : completed, budget, time-limit, failure-streak, interrupted). Tout sauf `completed` garde le gate à `incomplete`, même si tous les fichiers sont listés : une revue arrêtée n’est jamais clean. Trois échecs de suite sur la même unité l’abandonnent pour cette revue.
- `review continue` refuse (sortie 3, statut `moved`) quand le commit, les règles ou un fichier sélectionné ont changé ; la réponse est alors un nouveau périmètre et `review compare`. Dans `compare`, un constat est identifié par son chemin, sa catégorie et sa citation normalisée, jamais par la ligne ou l’id, et un constat disparu n’est compté résolu que si la revue ultérieure a terminé son fichier ; sinon il est « non relu ».
- Plancher de masquage : avant l’écriture de `findings.anchored.json`, les valeurs ressemblant à des identifiants dans les champs cités (blocs de clé privée, identifiants dans les URL, en-têtes d’autorisation, tokens bearer, valeurs de clés nommées comme des identifiants, formes de tokens connues) deviennent `[REDACTED]`. C’est un plancher, pas un scanner : un secret sans forme reconnaissable peut passer.

<a id="review-rules"></a>
## Les règles intégrées

Une règle est un document Markdown lié à des motifs de chemin ; `checklist.md` liste chaque règle qui s’applique à au moins un chemin sélectionné, une fois, avec les fichiers qu’elle couvre. Une règle est une consigne de relecture, pas un constat. Une règle peut nommer un `group` (une famille) pour que des relecteurs parallèles prennent une unité par groupe.

**Les huit règles livrées avec BMAD+**

| Règle | Groupe | S’applique à |
| --- | --- | --- |
| `general` | code | Tous les fichiers : appelants, comportement supprimé, limites, erreurs, confiance, tests. |
| `javascript-typescript` | code | Fichiers JS, TS, JSX, TSX, Vue et Svelte. |
| `python` | code | Fichiers Python. |
| `sql-and-migrations` | data | Fichiers SQL et de migration. |
| `shell` | code | Scripts shell. |
| `ci-workflows` | delivery | Fichiers de workflow CI. |
| `containers` | delivery | Fichiers de construction de conteneurs. |
| `configuration` | delivery | Fichiers de configuration. |

Un projet ajoute, remplace ou désactive des règles dans `_bmad/review-rules.yaml` (schéma `bmad-plus/review-rules/1`) : une règle est `{id, title, globs, doc}` avec un document Markdown situé dans `_bmad/` de 64 Ko au plus, et `disable: [id]` en retire une. Une clé inconnue, un id en double, un document hors de `_bmad/` et la désactivation d’une règle inconnue sont refusés, jamais ignorés. Le jeu de règles est haché dans le périmètre : un fichier de constats répond donc à un seul jeu de règles. Avec le pack Shield installé, six règles de conformité s’ajoutent : `shield-access-control`, `shield-personal-data`, `shield-cryptography`, `shield-logging`, `shield-ai-integrations` et `shield-change-and-supply-chain`. Chacune nomme les contrôles auxquels elle se rattache, comme `ISO27001:A.8.5`, `SOC2:CC6.1`, `GDPR:Art.32` ou `NIS2:Art.21(2)(d)`.

<a id="review-ci"></a>
### Soumettre les pull requests à la porte en CI

Deux workflows GitHub Actions prêts à copier se trouvent dans `docs/recipes/ci-review/`. `review-scope.yml` scelle le périmètre et publie la liste de contrôle dans le résumé du job et comme artefact (ni agent, ni modèle). `review-gate.yml` scelle le périmètre, fait écrire `findings.json` et `coverage.json` à l’agent hôte installé et connecté sur un runner auto-hébergé, vérifie que rien d’autre que ces deux fichiers n’a changé dans le dossier de revue ni rien en dehors dans l’extraction, puis ancre et passe la porte ; le job échoue sur une revue incomplète ou des constats ouverts. Les deux ne tournent que pour les pull requests du même dépôt, avec des permissions en lecture seule et tout épinglé. `gate --emit-check` écrit un document dont le bloc `github` a la forme d’un check run, avec 50 annotations au plus sur des lignes ancrées (`critical` et `high` en échec, `medium` en avertissement, `low` en notice).

<a id="example-review-sealed-scope"></a>
### Relire du travail non commité dans un seul dossier

À utiliser quand le changement n’est pas encore commité ou qu’un seul dossier compte. `--base HEAD --workspace` compare l’arbre de travail, fichiers non suivis compris, au dernier commit, et `--include` restreint le périmètre.

**Dans votre assistant IA**

```text
Sentinel, relis mon travail non commité dans src/billing uniquement. Scelle le périmètre avec bmad-plus review scope billing-1 --base HEAD --workspace --include "src/billing/**" --effort medium et applique les règles de la liste de contrôle. Cite le code de chaque constat mot pour mot, prends en compte chaque fichier sélectionné dans coverage.json, lance review anchor et review gate, et dis-moi exactement quels fichiers ont été écartés et pourquoi. Si le gate répond incomplete, dis ce qui manque au lieu de parler de clean.
```

**Ce que vous devriez obtenir** `_bmad-output/review/billing-1/` contient `scope.json` et `checklist.md`, puis `findings.json`, `findings.anchored.json` et `coverage.json` une fois la revue écrite. Le compte rendu donne le verdict (`incomplete`, `findings` ou `clean`) avec le chiffre de couverture, liste chaque constat ouvert avec son code cité, et nomme les fichiers écartés : un `.env` à côté du code est écarté comme `secret`, un fichier hors de `src/billing` comme `not-included`.

<a id="acceptance"></a>
## La recette humaine

Les tests automatisés prouvent que les pièces se comportent. Une recette prouve qu’une personne a vu la chaîne fonctionner à l’écran : celui qui écrit, celui qui lit, l’écran, le geste. La compétence Core `bmad-plus-uat` (pilotée par Sentinel ; commandes `uat`, alias `recette`) transforme une livraison en une page autonome qu’un testeur non technique parcourt pas à pas. Ses coches deviennent un résultat JSON que l’agent lit, trie et sur lequel il applique la porte.

1. **Écrire la spec** Un fichier JSON `_bmad-output/uat/specs/<product>-<version>.json` (schéma `bmad-plus/uat-spec/2`). Une vraie séquence d’étapes, chacune avec `where`, `do` et `expect` ; un clic par ligne `do`, un fait vérifiable par attente ; les libellés d’écran mot pour mot, copiés du code ; un témoin (ce sur quoi repose le test) avec la requête en lecture seule qui prouve son état ; `writes: true` plus un contrôle `verify` sur chaque étape qui persiste quelque chose.
2. **Vérifier et construire** `uat lint` vérifie les libellés par rapport à vos fichiers source, le balisage, le budget (15 étapes et 30 minutes par défaut) et les témoins. `uat build` écrit la page, qui porte le SHA-256 de la spec pour qu’un résultat dise toujours à quelle révision il a répondu.

   ```sh
   npx bmad-plus uat lint ID --src src
   npx bmad-plus uat build ID
   ```
3. **Remettre la page** En local, `uat serve` n’écoute que sur 127.0.0.1 et écrit les réponses directement dans le projet à chaque coche. Ailleurs, envoyez le fichier HTML ; le testeur enregistre le JSON et vous le chargez avec `uat import`. Dans Claude Code ou claude.ai, la page peut être publiée comme artefact dont la base de données garde les réponses. Dites clairement où vivent les réponses, et quelles étapes écrivent pour de vrai.

   ```sh
   npx bmad-plus uat serve ID --port 4173
   ```
4. **Lire le résultat** `uat read` affiche, pour chaque résultat, le testeur, les dates, les nombres de réussis, échoués, bloqués, ignorés et restants, les avertissements de périmé ou de non signé, et chaque échec avec le texte de l’attente et la note du testeur.

   ```sh
   npx bmad-plus uat read ID
   ```
5. **Trier, confirmer les écritures, passer la porte** Classez chaque attente échouée ou bloquée dans `triage/<id>.json`, exécutez en lecture seule le `verify` de chaque étape d’écriture réussie et consignez-le, puis lancez `uat gate`.

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

**lint, build, puis un gate sans résultat (la spec d’exemple livrée)**

```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
# Code de sortie 2 : awaiting. Le fichier de spec est l’exemple livré dans la compétence uat de Core (templates/example-uat-spec.json).
```

Sortie capturée lors d’une exécution réelle. Source: bmad-plus 0.23.0, 2026-10-18

<a id="uat-gate-and-triage"></a>
### Verdicts de la porte, classes de tri et types de vérification

**Codes de sortie de uat read et uat gate**

| Code | Verdict de `uat gate` | `uat read` |
| --- | --- | --- |
| 0 | `passed` : le résultat est terminé, à jour, complet et trié. | Aucune étape échouée. |
| 1 | `failed`. | Au moins un échec. |
| 2 | `awaiting` : pas encore de résultat terminé. | Aucun résultat. |
| 3 | `stale` : le résultat répondait à une autre révision de la spec. | Périmé. |

**Tri : classer chaque échec avant de corriger quoi que ce soit**

| Classe | Signe | Suite |
| --- | --- | --- |
| `product` | L’écran diffère de ce que le code devait afficher. | Une tâche de correction sur la story et une étape de rejeu dans la recette de la version suivante. |
| `recipe` | L’écran montre le résultat voulu ; l’attente le décrivait mal. | Amender la spec, reconstruire (nouvelle empreinte), rejouer les étapes concernées, et dire qu’aucun changement de produit n’était nécessaire. |
| `data` | Le témoin n’est plus dans l’état supposé. | Relancer la requête du témoin, le réinitialiser ou le renommer, rejouer. |
| `undecided` | Pas de note, ou non attribuable. | Demander au testeur ce qu’il a vu ; ne jamais deviner. La porte reste rouge. |

Une décision est consignée pour chaque échec trié : `fix`, `amend-spec`, `remeasure`, `accept-risk` (avec un responsable nommé) ou `ask-tester`. Les contrôles `verify` ont un type : `sql`, `http`, `command` ou `manual`. Une coche sur une étape d’écriture n’est pas une écriture : son `verify` est exécuté en lecture seule et consigné dans `writeChecks`, car une étape cochée neuf fois sur neuf s’est un jour révélée n’avoir rien écrit. La porte dit ce qu’elle établit : « human-observed: complete, current and triaged ». Elle n’établit pas que le testeur a regardé au bon endroit.

<a id="uat-config"></a>
### Les réglages uat

**Le bloc uat de _bmad/config.yaml**

| Clé | Défaut | Sens |
| --- | --- | --- |
| `mode` | `advisory` | `advisory` construit et propose la page, ne bloque jamais. `gate` fait attendre la livraison jusqu’à ce que la porte soit réussie. `off` ne produit aucune recette et le rapport de livraison le dit. Un bloc absent vaut `advisory`. |
| `granularity` | `delivery` | Une recette par livraison. |
| `environment` | nom et url vides | L’environnement de test visé par la recette (demandé à l’installation). |
| `page_budget` | 15 étapes, 30 minutes | Au-delà, découper en pages ordonnées. |
| `dir` | `_bmad-output/uat` | Où vivent specs, pages, résultats et tri. |

<a id="why-a-tag-needs-a-run"></a>
## Pourquoi un tag de version exige une recette acceptée

BMAD+ applique la règle à lui-même. Le 2026-09-16, une commande (`studio list`) s’est révélée cassée dans une vraie installation, depuis des semaines. La suite de tests était verte, le contrat d’installation passait et la CI était verte. Ce qu’aucun d’eux ne faisait, c’était installer le produit et l’utiliser comme le fait une personne. Depuis la 0.17.0, une version n’atteint pas npm tant qu’une personne n’a pas installé le candidat dans un dossier vide, parcouru la page de recette, et que chaque échec n’a pas été classé. La recette de la 0.23.0 a été déroulée dans un projet vide le 2026-10-18 : 28 attentes sur 28 réussies, chaque étape d’écriture confirmée en lecture seule. Un premier passage de cette recette avait révélé un défaut de désinstallation qui laissait derrière lui les compétences de design copiées ; il a été corrigé avant le tag. Les résultats eux-mêmes restent sur la machine du mainteneur, car ils portent des chemins locaux ; le CHANGELOG consigne le défaut qu’il a révélé.

- Dans le dépôt BMAD+, `npm run uat:spec` échoue quand la version de `package.json` n’a pas de recette, et `npm run uat:gate` échoue sauf si le dernier résultat est terminé, répond à la révision courante, ne laisse rien sans réponse, a chaque échec classé avec une décision et chaque étape d’écriture réussie confirmée en lecture seule. Un hook de pré-push impose les deux lors d’un push de tag `v*`.
- Une attente bloquée exige un rejeu ou une décision explicite `accept-risk` par un responsable nommé. Une recette cochée uniquement pour faire passer la porte est pire que pas de recette : si une étape ne peut pas être exécutée, la réponse est « blocked » avec la raison.
- Votre projet peut faire pareil avec deux scripts livrés dans la compétence uat (`templates/`) : `uat-spec-present.mjs` (une version sans recette est refusée, avant le push) et `uat-release-gate.mjs` (sortie 0 réussi, 1 échoué, 2 pas de résultat terminé, 3 autre révision, 4 la porte n’a pas pu s’exécuter, ce qui n’est pas un succès). BMAD+ n’installe aucun hook de cycle de vie : ces scripts sont la couche qu’une consigne ou un agent ne peut pas contourner ; branchez-les là où ils mordent.

<a id="example-acceptance-build-recipe"></a>
### Préparer une page de recette pour un formulaire de réservation en préproduction

À utiliser quand une version arrive sur un site de préproduction et qu’un collègue non technique doit la confirmer à l’écran. Préférez des données de test jetables : l’étape qui crée une réservation écrit pour de vrai.

**Dans votre assistant IA**

```text
Sentinel, écris la recette du formulaire de réservation que nous venons de livrer en préproduction. Le testeur travaille à l’accueil, ce n’est pas un développeur : une étape par geste, un fait vérifiable par attente, les libellés d’écran copiés du code. Pour l’étape qui crée une réservation, ajoute la requête en lecture seule que tu lanceras ensuite pour prouver que la ligne existe. Lance uat lint avec --src src, puis uat build, et montre-moi les garanties que le build liste. Dis-moi le fichier ou le lien, la durée, quelles étapes écrivent et où les réponses seront stockées.
```

**Ce que vous devriez obtenir** Une spec dans `_bmad-output/uat/specs/`, une page construite dans `_bmad-output/uat/pages/uat-<id>.html`, la ligne de lint (« N steps, M expectations, K on-screen labels checked against F source files »), une requête `verify` sur l’étape de réservation, la liste des garanties de la page et une déclaration claire de l’endroit où vivent les réponses. La page n’est pas remise si lint ou build échoue.

<a id="example-acceptance-read-and-triage"></a>
### Lire un résultat terminé et classer chaque échec

À utiliser quand le testeur a terminé ou s’est arrêté. Le fichier de résultat est dans `_bmad-output/uat/results/<id>/`, ou importé avec `uat import`.

**Dans votre assistant IA**

```text
Sentinel, lis le dernier résultat de recette avec uat read. Classe chaque attente échouée ou bloquée comme product, recipe, data ou undecided dans le fichier de tri et interroge-moi sur celles que tu ne sais pas attribuer. Exécute en lecture seule le contrôle verify de chaque étape d’écriture réussie et consigne le résultat. Lance ensuite uat gate et rapporte son verdict, le testeur et ce qui reste ouvert. Ne marque aucune étape non jouée comme réussie.
```

**Ce que vous devriez obtenir** Un fichier de tri avec une classe et une décision par échec, des entrées `writeChecks` pour les étapes d’écriture, et une ligne de porte comme `<id>: passed (run <runId> by <tester>)` avec le code de sortie 0, ou `failed`, `awaiting` ou `stale` avec les raisons. Un échec non tranché garde la porte rouge jusqu’à la réponse du testeur.

**Voir aussi**

- [Référence : bmad-plus review](https://bmad-plus.rochetta.fr/fr/docs/reference/cli-review/)
- [Référence : bmad-plus uat](https://bmad-plus.rochetta.fr/fr/docs/reference/cli-uat/)
- [Référence : bmad-plus assurance](https://bmad-plus.rochetta.fr/fr/docs/reference/cli-assurance/)
- [Nexus et vérification avant acceptation](https://bmad-plus.rochetta.fr/fr/docs/concepts/nexus-orchestration/)
- [Référence : config.yaml](https://bmad-plus.rochetta.fr/fr/docs/reference/config-yaml/)

[Documentation BMAD+](https://bmad-plus.rochetta.fr/fr/docs/) · [Concepts](https://bmad-plus.rochetta.fr/fr/docs/concepts/)

[Code sur GitHub](https://github.com/lrochetta/BMAD-PLUS)
