# Commits y entrega

## R8 — Un commit por naturaleza

Stagear rutas explícitas, revisar el diff staged y crear un Conventional Commit en inglés. No usar
`git add .`, `git add -A`, force ni trailers de IA.

**Y no reescribir historia que otro ya leyó.** Lo que se protege es eso, no el comando: un `--amend`
sobre un commit publicado es la misma reescritura que un force-push y se frena igual; sobre uno que no
salió de tu máquina es la corrección, y prohibirlo no impide el resultado —`git reset --soft HEAD~1` y
volver a commitear produce exactamente lo mismo— sino el comando que lo nombra. Una regla que se cumple
mejor esquivándola se termina esquivando siempre.

Dónde corta un commit lo decide la naturaleza del diff, no su tamaño ni un conteo. Una tarea suele
tener una sola, y por eso un commit por tarea es lo habitual; cuando tiene dos, se hacen dos. Un
refactor y el arreglo de traducción que lo acompaña, juntos en un commit, ya no se pueden revertir
por separado, y quien revise tiene que volver a separarlos a mano.

La unidad de aceptación y de evidencia sigue siendo la tarea: su entrada de DONE registra todos los
commits que produjo, separados por `;`. Partir el diff no parte la aceptación.

**La prohibición de firmas de IA cubre todo lo que este trabajo publica**, no sólo el mensaje del commit:
el título y el cuerpo del pull request, y los comentarios que se dejen ahí. Y casi nunca es algo que
alguien tipea — lo agrega la herramienta, sola, al final del texto que uno escribió—, así que cumplirla
es revisar la salida antes de publicarla y no acordarse de no escribirla.

El motor la comprueba donde tiene forma, y sólo ahí: un `git commit`, o un `gh` que publica texto en un
pull request o un issue, cuyo texto trae la firma de un asistente como línea propia se frena. Un mensaje en un
archivo que no se puede leer, el que sale de otro programa por una tubería, o una herramienta que firme de otro modo, no
lo ve nadie más que quien revisa. Y es de las
que el proyecto puede decidir distinto: una empresa que quiere dejar constancia de lo que hizo un agente lo
declara con `runner.allowAiSignature`, y ahí la firma pasa.

## R9 — El artefacto manda

Tests verdes no reemplazan build, paquete, imagen o migración cuando son parte del artefacto entregable.

Verde tampoco prueba lo que la tarea prometió. El criterio de aceptación que ningún test asercia no está
cubierto, y el que dice cubrirlo sin aserciar esa propiedad tampoco lo cubre. Eso se ve leyendo el fuente
del test, no su salida: un exit code no distingue la prueba que sostiene el criterio de la que lo nombra.
Y una prueba que nunca se vio fallar no muestra que su aserción funcione: el rojo previo es lo único que
la separa de una que pasa haga lo que haga el código.

Cuatro cosas de cómo se prueba no admiten excepción, y por eso viajan acá: **la mutación se declara por escrito**
en la aceptación que la pide —qué se rompe y qué prueba tiene que ponerse roja—; **una quita no se entrega sin su
aserción de ausencia**, vista en rojo devolviendo lo quitado; **una quita casi nunca se ve como una quita**: una
bandera que se pone o una variable que se exporta «para que deje de…» lo es, y cambiar quién hace algo, o cómo,
también, y se sostiene sólo con la salida de antes y la de después sobre el mismo caso; y **una confirmación que
estorba casi siempre está cuidando algo**: antes de callarla se establece qué protege, y se le quita a la herramienta
el motivo de preguntar, no la pregunta. Cómo se cumplen, y la deprecación, viven en R29 (`proof.md`): se lee al
escribir o revisar una aceptación, una prueba, o un cambio que quita o reemplaza algo.

## R10 — Publicación humana por defecto

Push, PR, merge, tags, deploy y rollback requieren la autorización configurada para el proyecto.

El motor comprueba el push contra `runner.allowPush` —que no llega a la rama viva
sin `runner.pushToLiveBranches`, ni a un subagente— o contra la orden que la persona da en el chat
nombrando el remoto y la rama. Reescribir historia publicada
no entra en esa autorización y se frena siempre — también cuando la reescritura es un `--amend`, que el
guard distingue mirando si algún remoto alcanza al commit.

Los otros cinco los comprueba donde tienen una forma reconocible en un comando, y en ningún otro lado. Se
frenan hasta que una persona los apruebe: actuar sobre un PR con `gh` —mergear, aprobar, cerrar, comentar—,
abrirlo sin nombrar el destino, disparar un workflow o una release, y desplegar con `terraform`, `tofu`,
`kubectl`, `helm`, `pulumi` o `cdk`, más los comandos que el proyecto declare en `deployCommands`. Un deploy
por un script que nadie declaró, o por un botón, no tiene forma: ése lo sostienen esta regla y el review,
no un guard.

Decirlo es parte de la regla y no una nota al pie. Una norma que se presenta como comprobada donde no
lo está enseña a no creerle al resto: quien descubre que puede desplegar sin que nada lo frene concluye
que la línea de arriba es decorativa, y esa conclusión se lleva puesto también lo que sí se comprueba.
Que el límite lo sostenga una persona no lo hace más blando; lo hace visible.

**Y la autorización dice si se publica, nunca a dónde.** Eso se decide aparte y se comprueba: lo que se
publica va al repositorio en el que se está trabajando. Si ese remoto es un fork, va al fork —y la rama
se corta de la suya, no de la del original—, porque una rama cortada del principal es la antesala de
mandarle el PR.

No se deduce del contexto. Que la herramienta resuelva sola el repositorio de origen no es una
autorización, y tampoco lo son que el cambio «obviamente tenga que llegar ahí», que el fork tenga
configurado el original por defecto, ni que un PR anterior haya ido a parar allá. Saltar al principal
—abrir, aprobar, mergear, cerrar o comentar— se pide con todas las letras y para ese caso concreto.

Es de las pocas que no tiene vuelta atrás. Un PR mal apuntado es trabajo publicado en el repositorio de
otro equipo: lo ven, les llega la notificación, y cerrarlo no deshace nada de eso.
