# bmad-plus uat

> Referencia de bmad-plus uat (alias recette): lint, build, serve, import, read, gate y order para las recetas de aceptación humana, con opciones, códigos de salida y ejemplos.

Canonical: https://bmad-plus.rochetta.fr/es/docs/reference/cli-uat/
Language: es
BMAD+ version: 0.23.1
Documentation reviewed: 2026-10-19
Author: Laurent Rochetta
License: MIT

Documentación de BMAD+ › [Referencia](https://bmad-plus.rochetta.fr/es/docs/reference/) › bmad-plus uat

`bmad-plus uat` (alias `bmad-plus recette`) gestiona las recetas de aceptación humana. Una receta (recette, en francés) es una especificación JSON de pasos que una persona reproduce en pantalla. El comando valida la especificación, construye una página HTML autónoma para quien prueba, guarda sus respuestas como una ejecución JSON, lista los fallos y deriva de ella un veredicto de puerta. Úsalo cuando una entrega deba verla funcionar una persona y no solo las pruebas automáticas. Sentinel lo maneja por ti; tú lo necesitas para automatizar el proceso, conectar un paso de CI o comprobar lo que afirma el agente.

> **Nota · Qué demuestra la puerta y qué no** La puerta establece que una ejecución está terminada, vigente, completamente respondida y clasificada. No establece nunca que quien probó miró en el sitio correcto, por eso cada veredicto lleva la etiqueta «observado por una persona». Una puerta en passed puede apoyarse aún en fallos: solo hace falta que estén clasificados, cada uno con una decisión.

<a id="synopsis"></a>
## Sinopsis

**En el terminal de tu proyecto**

```sh
npx bmad-plus uat <action> [target] [options]
npx bmad-plus recette <action> [target] [options]
```

`action` es una de las siete acciones de abajo. `target` es el id de una receta (el comando busca `<dir>/specs/<id>.json` y después cualquier especificación de esa carpeta cuyo `id` coincida) o la ruta de un archivo `.json`. `order` no lleva objetivo.

**Las siete acciones**

| Acción | Qué hace | Escribe |
| --- | --- | --- |
| `lint` | Valida la especificación: esquema, claves desconocidas, marcado, ids de pasos y de expectativas, testigos, presupuesto de 15 pasos / 30 minutos. Con `--src`, comprueba que cada etiqueta de pantalla citada existe en un archivo fuente. | nada |
| `build` | Hace primero el lint y se niega ante cualquier error; después escribe la página de quien prueba. | `<dir>/pages/uat-<id>.html` |
| `serve` | Sirve la página construida en 127.0.0.1 y guarda cada respuesta que envía la página. Funciona hasta que pulsas Ctrl+C. | `<dir>/results/<id>/<runId>.json` |
| `import` | Guarda un JSON de resultados exportado desde la página (archivo o entrada estándar). | `<dir>/results/<id>/<runId>.json` |
| `read` | Lista cada ejecución y cada expectativa fallida o bloqueada con su texto y la nota de quien probó. | nada |
| `gate` | Deriva el veredicto: passed, failed, awaiting o stale. `--emit-check` escribe además un verificador autónomo. | `<dir>/checks/gate-<id>.cjs` (solo con `--emit-check`) |
| `order` | Calcula el orden de juego de todas las recetas de `<dir>/specs` a partir de su `after` y de los testigos compartidos. | `<dir>/ORDER.md` |

**Opciones**

| Opción | Argumento | Por defecto | Efecto |
| --- | --- | --- | --- |
| `-d, --directory` | `<path>` | carpeta actual | Carpeta del proyecto. |
| `--dir` | `<path>` | `_bmad-output/uat` | Carpeta de recetas dentro del proyecto: `specs/`, `pages/`, `results/`, `triage/`, `checks/`. |
| `--src` | `<path>` | ninguno | Carpeta de código fuente analizada en busca de etiquetas de pantalla (lint, build). Repetible. |
| `--language` | `<code>` | ver abajo | Idioma de la página: un código (`fr`), un nombre (`Français`) o una etiqueta de configuración regional. |
| `--input` | `<file>` | ninguno | solo import: archivo de resultados a guardar; `-` lee la entrada estándar. Obligatorio en `import`. |
| `--port` | `<number>` | `4173` | solo serve: puerto, enlazado únicamente a 127.0.0.1. |
| `--emit-check` | ninguno | desactivado | solo gate: escribe también el verificador de Nexus `checks/gate-<id>.cjs`. |
| `--json` | ninguno | desactivado | Salida legible por máquina, con `schemaVersion: 1`. |

Idioma de la página, por orden de prioridad: el campo `language` de la receta, luego `--language`, luego el `communication_language` leído de `_bmad/config.yaml` y por último el inglés. La página incluye siempre los diez idiomas del instalador (en, fr, es, de, pt-br, ru, zh, he, ja, it) y quien prueba puede cambiar desde la propia página.

<a id="reads-writes"></a>
## Qué lee y qué escribe

- Lee: las especificaciones de `<dir>/specs` (se rechazan por encima de 4 MiB o si el archivo es un enlace simbólico), `_bmad/config.yaml` (solo build, para `communication_language`), los resultados de `<dir>/results/<id>/` y el archivo de triaje `<dir>/triage/<id>.json`.
- Con `--src`: lee solo archivos fuente con estas extensiones: ts, tsx, js, jsx, mjs, cjs, vue, svelte, html, htm, php, py, rb, java, kt, cs, go, json, yaml, yml, md. Omite enlaces simbólicos, carpetas que empiezan por punto, `node_modules`, `.git`, `dist`, `build`, `coverage`, `.next`, `.nuxt`, `vendor`, `__pycache__`, `.venv`, `venv`, `target` y `out`, ignora archivos de más de 512 KiB y se detiene tras 20000 archivos.
- Escribe: solo los archivos nombrados en la tabla de arriba. Los valores con aspecto de credencial pegados en una nota de quien prueba se sustituyen por `[REDACTED]` antes de que la ejecución llegue al disco (`import` y `serve`); la ejecución anota cuántas sustituciones hubo en `redactions`.
- Red: ninguna, salvo `serve`, que escucha solo en 127.0.0.1. La propia página construida no pide nada a otro origen. Quien prueba desde otra máquina usa la página como archivo o como artefacto y devuelve el JSON para `import`.
- `serve` responde solo a los nombres de host `127.0.0.1:<port>` y `localhost:<port>` (cualquier otra cabecera Host recibe HTTP 403), rechaza un cuerpo de petición de más de 4 MiB y responde HTTP 409 cuando una copia más antigua de una ejecución sustituiría a otra más reciente.

<a id="gate-rules"></a>
## Cómo decide la puerta

La puerta toma la ejecución terminada más reciente de la receta. Si no hay ninguna, el estado es awaiting. Si esa ejecución respondió a otra revisión de la especificación (su `specSha256` difiere del actual), el estado es stale. En otro caso el estado es failed mientras se aplique al menos una de las razones siguientes, y passed cuando no se aplica ninguna.

- Una expectativa nunca recibió respuesta (los pasos opcionales se omiten).
- Una expectativa fallida o bloqueada no tiene entrada en `<dir>/triage/<id>.json`, o su clase es `undecided`, o su decisión no es una de `fix`, `amend-spec`, `remeasure`, `accept-risk`, `ask-tester`.
- Una decisión es `accept-risk` sin `decidedBy`.
- Una expectativa está bloqueada y su decisión no es `accept-risk`: no se observó nada, así que hay que repetirla o que alguien con nombre acepte el riesgo.
- Un paso con `writes: true` pasó, pero el triaje no tiene una entrada `writeChecks` con `verified: true` y un texto `evidence`: una marca en un paso que escribe es una observación, la prueba de solo lectura es la que decide.

**Vocabulario del triaje**

| Clase | Significado | Decisión habitual |
| --- | --- | --- |
| `product` | La pantalla difiere de lo que el código debía mostrar. | `fix` |
| `recipe` | La pantalla es correcta, la expectativa la describía mal. | `amend-spec` |
| `data` | El testigo ya no está en el estado supuesto. | `remeasure` |
| `undecided` | Sin nota o no atribuible: preguntar a quien probó. Mantiene la puerta en rojo. | `ask-tester` |

<a id="exit-codes"></a>
## Códigos de salida

**Código de salida por acción**

| Acción | 0 | 1 | 2 | 3 |
| --- | --- | --- | --- | --- |
| `lint` | sin errores | al menos un error, o cualquier fallo | - | - |
| `build` | página escrita | error de lint, plantilla que perdió una garantía, o cualquier fallo | - | - |
| `import` | ejecución guardada | cualquier fallo | - | - |
| `read` | ejecuciones leídas, nada falló | una expectativa fallida o bloqueada, o cualquier fallo | aún no hay ejecución (awaiting) | la ejecución más reciente respondió a otra revisión (stale) |
| `gate` | passed | failed (o cualquier fallo) | awaiting | stale |
| `order` | orden escrito | un ciclo, ninguna especificación en la carpeta, o cualquier fallo | - | - |

Un fallo es cualquier error lanzado: acción desconocida, objetivo ausente, especificación no encontrada, archivo ilegible, `--input` ausente. Imprime `uat: <message>` por la salida de error, o `{"schemaVersion":1,"status":"error","message":...}` con `--json`, y sale con 1. Un script de entrega que deba distinguir una puerta fallida (1) de una puerta que no pudo ejecutarse usa la puerta de proyecto `uat-release-gate.mjs`, que añade el código 4 para el segundo caso.

<a id="real-output"></a>
## Ejemplos de salida

El primer bloque se reprodujo con la especificación de ejemplo que se entrega en la habilidad `bmad-plus-uat`; los bloques `read` y `gate` se componen a partir de las plantillas de mensajes del comando, se marcan como simulados y reutilizan el caso de prueba de `tests/unit/uat-cli.test.js`. El número de archivos, los tamaños y los hashes dependen de tu proyecto.

**Validar y construir una receta**

```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/app/_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 lint example-1.0.0 --src src
example-1.0.0: 3 steps, 5 expectations, 8 on-screen labels
  error   step 0-setup: do: the label "Folders" is in no source file — copy it from the component, accents included or not
  error   step 1-nominal: where: the label "Technical" is in no source file — copy it from the component, accents included or not
# Siguen otros cuatro errores del mismo tipo y el comando sale con 1: aquí `src` es una carpeta vacía, así que no se encuentra ninguna etiqueta de la especificación. `--src` debe apuntar a las carpetas que de verdad contienen las etiquetas de tus pantallas.
```

Salida capturada de una ejecución real. Fuente: Reproducido con el paquete 0.23.0 y la especificación de ejemplo de la habilidad bmad-plus-uat, en un proyecto desechable; la ruta del proyecto se sustituye por /work/app

**Leer una ejecución y pedir la puerta** (Simulado)

```text
$ npx bmad-plus uat read demo-1.0.0

■ Demo 1.0.0 — Sarah — 2026-09-16 08:00, finished
  1 passed · 1 failed · 0 blocked · 0 skipped · 0 to do   (_bmad-output/uat/results/demo-1.0.0/20260916-sarah-aaaa.json)
  ✗ 1-confirm/a (failed) — Confirm
      expectation: The line reads OPCO confirmed.
      seen instead: the line still reads OPCO to confirm
# Código de salida 1: existe un fallo.
$ npx bmad-plus uat gate demo-1.0.0
demo-1.0.0: failed (run 20260916-sarah-aaaa by Sarah)
  - 1-confirm/a is failed and not triaged
# Código de salida 1. Cuando el fallo se clasifica en triage/demo-1.0.0.json (clase product, decisión fix), el mismo comando imprime «demo-1.0.0: passed ...» y sale con 0.
```

Transcripción ilustrativa, no capturada de una ejecución real. Fuente: tools/cli/commands/uat.js (plantillas de read y gate); tests/unit/uat-cli.test.js (caso de prueba demo-1.0.0, ejecución 20260916-sarah-aaaa)

<a id="errors"></a>
## Errores y qué hacer

**Mensajes que imprime uat**

| Mensaje | Causa | Qué hacer |
| --- | --- | --- |
| `uat: an id or a spec file is required` | No se indicó objetivo en una acción que lo exige. | Pasa el id de la receta o la ruta del archivo `.json`. |
| `uat: no spec with the id "<id>" in <dir>/specs` | Ningún archivo de la carpeta specs lleva ese `id`. | Revisa `--dir` y `--directory`; la coincidencia es por el campo `id`, no solo por el nombre del archivo. |
| `step <id>: ...` o `unknown key at spec level: "<key>" ...` (listados como `error`) | Una errata o un campo ausente en la especificación: las claves desconocidas se rechazan, no se ignoran. | Corrige la especificación y repite `lint`. |
| `the label "<text>" is in no source file` | Una etiqueta de pantalla citada no aparece en las carpetas dadas con `--src`. | Copia la etiqueta del componente, con o sin acentos. Sin `--src` esta comprobación no se ejecuta. |
| `<id>: not built, N error(s)` | `build` ejecuta el lint y se niega a escribir la página ante cualquier error. | Corrige los errores listados. |
| `the page template ... lost a guarantee — not built` | La plantilla de la página ya no cumple una de las 17 garantías. | Reinstala o actualiza BMAD+; no edites la plantilla a mano. |
| `no page at <file> — run "bmad-plus uat build <id>" first` | `serve` necesita una página construida. | Ejecuta `build` y luego `serve`. |
| `--input <file> or --input - is required` | `import` sin `--input`. | Pasa el JSON exportado, o `-` para la entrada estándar. |
| `these results answer <a>, not <b>` | La ejecución importada pertenece a otra receta. | Impórtala con el id al que responde. |
| `unsupported results schema: ...` o `results without runId` | El archivo no es una ejecución exportada por la página. | Exporta de nuevo desde la página, o usa la exportación del artefacto. |
| `<id>: no run yet` (código 2) | No hay JSON en `<dir>/results/<id>/`. | Sirve o envía la página y luego haz `import` de las respuestas. |
| `unknown action "<x>" (lint, build, serve, import, read, gate, order)` | Acción mal escrita. | Usa una de las siete acciones. |

<a id="examples"></a>
## Ejemplos

<a id="example-cli-uat-write-and-build"></a>
### Que Sentinel escriba y construya la receta

Una versión está lista para el entorno de pruebas. Quieres una página que pueda recorrer un compañero no técnico.

**En tu asistente de IA**

```text
Sentinel, escribe la receta de aceptación de esta entrega en nuestro entorno de pruebas. Valídala con lint sobre src, construye la página y dime qué pasos escriben de verdad.
```

**Lo que deberías obtener** Sentinel escribe la especificación en `_bmad-output/uat/specs/<id>.json`, ejecuta `bmad-plus uat lint <id> --src src` y corrige lo que señale, y después ejecuta `bmad-plus uat build <id>`, que escribe `_bmad-output/uat/pages/uat-<id>.html` y lista las garantías de la página. Te entrega el enlace o el archivo, la duración y los pasos marcados `writes: true`, cada uno con su comprobación `verify` de solo lectura. Si la CLI no está disponible, lo dice en lugar de afirmar que la página está construida.

<a id="example-cli-uat-read-and-gate"></a>
### Leer la ejecución, clasificar, pedir la puerta

Quien probó terminó la página y devolvió el JSON.

**En tu asistente de IA**

```text
Sentinel, importa el archivo de resultados results.json para la receta demo-1.0.0, lee la ejecución, clasifica cada fallo y dime si la puerta pasa.
```

**Lo que deberías obtener** Sentinel ejecuta `uat import demo-1.0.0 --input results.json` y luego `uat read demo-1.0.0`, que imprime cada expectativa fallida o bloqueada con su texto y la nota de quien probó. Escribe una clase y una decisión para cada una en `_bmad-output/uat/triage/demo-1.0.0.json`, te pregunta cuando una nota no explica el fallo (la clase `undecided` mantiene la puerta en rojo) y por último informa de `uat gate demo-1.0.0` con el estado y el código de salida (0 passed, 1 failed, 2 awaiting, 3 stale). Etiqueta la evidencia como observada por una persona.

**Conectar la puerta a un script de entrega (puerta de proyecto copiada de templates/)**

```sh
node scripts/uat-release-gate.mjs || exit 1
# deploy only below this line
```

La habilidad incluye dos puertas de proyecto en `.agents/skills/bmad-plus-uat/templates/`: `uat-spec-present.mjs` falla cuando ninguna receta nombra la versión de `package.json`, y `uat-release-gate.mjs` ejecuta `uat gate` con la CLI instalada en el proyecto (0 passed, 1 failed, 2 ninguna ejecución terminada, 3 otra revisión, 4 la puerta no pudo ejecutarse, lo cual no es un éxito).

**Véase también**

- [Resumen de la CLI](https://bmad-plus.rochetta.fr/es/docs/reference/cli-overview/)
- [nexus: ejecuciones duraderas que pueden usar la puerta como comprobación](https://bmad-plus.rochetta.fr/es/docs/reference/cli-nexus/)
- [review: la misma idea de evidencia para la revisión de código](https://bmad-plus.rochetta.fr/es/docs/reference/cli-review/)
- [El bloque uat de config.yaml](https://bmad-plus.rochetta.fr/es/docs/reference/config-yaml/)
- [Solución de problemas](https://bmad-plus.rochetta.fr/es/docs/faq/troubleshooting/)

[Documentación de BMAD+](https://bmad-plus.rochetta.fr/es/docs/) · [Referencia](https://bmad-plus.rochetta.fr/es/docs/reference/)

[Código en GitHub](https://github.com/lrochetta/BMAD-PLUS)
