Rehearsal Pattern: ensayar antes de mutar sistemas
Una automatización útil acaba tocando algo que importa: instala paquetes, reescribe configuración, sincroniza repositorios o materializa estado en una máquina. En ese momento deja de ser solamente código y se convierte en una operación. La pregunta relevante ya no es solo si el programa puede ejecutar el cambio, sino si una persona —o un agente— puede entender qué va a ocurrir antes de autorizarlo.
Llamo Rehearsal Pattern a una práctica operacional que separa deliberadamente el conocimiento de una operación de su capacidad de mutar. Primero observa el estado, después ensaya o previsualiza la intención, valida las condiciones, solicita aprobación explícita, ejecuta una mutación acotada y finalmente comprueba el resultado. Es el nombre que utilizo en este proyecto para esa secuencia; no lo presento como un patrón formal reconocido ni como un estándar de la industria.
El problema: una interfaz demasiado poderosa
Los scripts de mantenimiento suelen comenzar pequeños. Una orden actualiza una herramienta; otra aplica una configuración. Con el tiempo incorporan red, credenciales, gestores de paquetes y varios sistemas operativos. Si la misma entrada sirve para inspeccionar y para cambiar, un error de contexto puede convertir una consulta rutinaria en una mutación difícil de reconstruir.
El riesgo no procede únicamente de comandos destructivos. Una operación legítima también puede ejecutarse sobre el checkout equivocado, asumir dependencias ausentes, usar una versión inesperada o actuar sobre un alcance mayor del previsto. Una salida exitosa tampoco demuestra por sí sola que el estado final sea correcto. Por eso un simple mensaje de confirmación al principio es insuficiente: antes de aprobar necesitamos evidencia legible sobre el estado y la intención.
Esta distinción es especialmente importante en automatización agéntica. Un agente puede encadenar pasos con mucha más velocidad que una persona, pero esa velocidad amplifica una premisa equivocada. La capacidad de razonar sobre una operación no debería implicar automáticamente permiso para ejecutarla.
Ensayar antes de cambiar
Un rehearsal no es necesariamente una simulación perfecta. A veces existe un --dry-run que calcula el plan de una operación mutante sin aplicarlo. Otras veces el mecanismo disponible es un --check de solo lectura que comprueba preparación o deriva. Ambos aportan evidencia previa, pero no significan lo mismo: el primero previsualiza una acción; el segundo valida estado. Confundirlos produce expectativas falsas.
El patrón funciona cuando la interfaz hace visible esa diferencia. Los diagnósticos deben ser seguros por defecto. La intención de mutar debe aparecer en la propia invocación, no esconderse tras un comportamiento implícito. La confirmación debe llegar después de inspeccionar el alcance. Y la verificación posterior debe ser una fase propia, porque una operación aceptada puede completarse parcialmente o dejar un estado inesperado.
El flujo del patrón
La secuencia que aplico es esta:
- Observar. Leer el estado efectivo, el origen de configuración, las versiones y las condiciones del entorno sin escribir.
- Ensayar. Obtener un plan o una señal de deriva mediante el modo de preview que la operación soporte realmente.
- Validar. Ejecutar preflight checks que puedan bloquear el cambio si faltan prerrequisitos o el contexto no coincide.
- Aprobar. Expresar de forma inequívoca que se acepta una mutación concreta y su alcance.
- Mutar de forma acotada. Ejecutar el backend previsto, evitando que la aprobación se convierta en permiso general para otras operaciones.
- Verificar. Volver a observar y ejecutar comprobaciones capaces de detectar un resultado incompleto o divergente.
No todas las herramientas pueden implementar las seis fases dentro de un único comando. Lo importante es que el recorrido completo exista y que los límites entre lectura, intención y escritura permanezcan explícitos.
Cómo aparece en Dotfiles y devx
El proyecto Dotfiles utiliza esta idea para mantener una estación Ubuntu/WSL2. Su interfaz actual ofrece diagnósticos de solo lectura y un flujo de actualización protegido. Un recorrido representativo es:
devx dotfiles doctor
devx dotfiles update --check
devx dotfiles update --apply --yes
devx dotfiles doctor --strict
Cada línea tiene una semántica distinta. doctor inspecciona la preparación y la alineación del origen de configuración. Con --strict sigue siendo de solo lectura, pero convierte los avisos de readiness en un estado de salida fallido. update --check delega en el preflight de actualización y no es un ensayo completo de todas las escrituras futuras. La variante --apply es el camino mutante protegido: rechaza la ejecución sin --yes, repite el preflight y no lanza el backend si esa comprobación falla.
El flag --yes permite confirmación no interactiva; no significa “todo está permitido”. En la política del proyecto, los agentes no deben añadirlo sin una instrucción humana explícita para esa operación concreta. Además, determinadas acciones amplias o sensibles continúan fuera de la superficie mutante de devx, aunque técnicamente pudieran envolverse con una confirmación.
Agentes y límites de mutación
Para un agente, rehearsal ofrece una estructura de control comprensible. Puede recopilar evidencia con operaciones de lectura, comparar el estado con la intención y preparar una propuesta sin cruzar el límite de escritura. Cuando una persona autoriza el cambio, la autorización puede referirse a una orden y un alcance concretos. Después, el agente puede ejecutar comprobaciones de resultado sin interpretar el éxito del proceso como prueba suficiente.
Esta separación también mejora la experiencia de desarrollo para humanos. Los mismos comandos sirven como vocabulario compartido en documentación, tests y revisiones. Un fallo en preflight explica por qué no comenzó la mutación; un fallo en post-check indica que el resultado requiere atención. La observabilidad deja de ser un añadido y pasa a formar parte de la interfaz.
El límite sigue siendo social y técnico a la vez. Ningún nombre de flag impide que un backend esté mal implementado. Los permisos del proceso, el aislamiento, las credenciales y la revisión del alcance continúan siendo controles independientes.
Qué reduce y qué no garantiza
Rehearsal reduce el riesgo al mover errores detectables a una fase anterior y al hacer explícita la transición hacia la escritura. También mejora el diagnóstico: sabemos si falló la observación, el preflight, la aprobación, la ejecución o la verificación.
Pero el patrón no garantiza automáticamente idempotencia. Ejecutar dos veces una mutación puede producir dos efectos si el backend no fue diseñado para converger. Tampoco aporta transaccionalidad: varios pasos pueden completar solo una parte del cambio. No crea por sí mismo un rollback, ni demuestra la corrección de la intención, ni asegura la ausencia de efectos secundarios durante un check o un dry-run defectuoso.
Esas propiedades deben existir y probarse en cada operación concreta. El rehearsal no sustituye backups, aislamiento, permisos mínimos, tests ni recuperación. Su aportación es más modesta y más práctica: convierte una mutación opaca en una decisión informada, acotada y verificable.