Ingeniería con IA · Proceso de ingeniería
Tiempo de lectura · 7 min
Plan First: por qué nuestros agentes no empiezan programando
Cómo StackLiberate usa un flujo Plan First con agentes: exploración del repositorio, invariantes, análisis de efectos, comportamiento explícito ante fallos, implementación acotada y aprobación humana antes de cambiar código.

Los agentes de programación son muy buenos para empezar.
Dales una solicitud de funcionalidad y acceso a un repositorio y, en segundos, pueden encontrar archivos, proponer cambios, escribir código, actualizar pruebas y seguir avanzando.
Esa velocidad es útil.
También puede optimizar lo equivocado.
En una base de código madura, la pregunta difícil rara vez es:
¿Podemos producir código que parezca implementar esta función?
Las preguntas más difíciles son:
- ¿A qué parte del sistema pertenece realmente este comportamiento?
- ¿Qué contrato existente ya lo regula?
- ¿Qué estado es la fuente de autoridad?
- ¿Qué otros recorridos dependen del mismo comportamiento?
- ¿Qué debe pasar si la operación falla a la mitad?
- ¿Qué garantías existentes deben mantenerse?
- ¿Cómo sabremos que la implementación es correcta más allá del caso exitoso?
Para cambios importantes en StackLiberate, normalmente queremos responder esas preguntas antes de que un agente modifique código de producción.
Llamamos a ese enfoque Plan First.
No es una ceremonia añadida para frenar a la IA.
Es nuestra forma de hacer útil la IA en software donde la corrección local no basta.
Una implementación rápida puede ocultar una comprensión incompleta
Los agentes de programación actuales son muy capaces de recorrer repositorios desconocidos.
El problema es que encontrar un punto plausible de implementación no equivale a entender el sistema.
Una función puede parecer propia de un componente React cuando su contrato real está en el estado del proyecto. Un cambio de backend puede parecer aislado mientras una exportación depende de la misma representación. Una modificación aparentemente inofensiva puede funcionar en la sesión actual y eludir el historial de versiones, la recarga u otro límite del ciclo de vida.
La primera implementación que encuentra un agente puede ser perfectamente razonable de forma aislada y aun así ser incorrecta para la arquitectura.
Esto es especialmente peligroso porque el resultado suele verse bien.
Compila.
La interfaz se comporta correctamente.
Las pruebas pueden pasar.
La diferencia de código puede incluso estar limpia.
Pero la implementación aún puede introducir otra fuente de verdad, duplicar una responsabilidad existente, debilitar un límite ante fallos o resolver una representación del producto y dejar otra atrás.
El agente no escribió necesariamente código malo.
Resolvió un problema más pequeño que el que tenía el sistema.
Plan First amplía ese problema antes de empezar la implementación.
La exploración precede a la modificación
Para trabajo no trivial, nuestra primera solicitud a un agente suele ser deliberadamente de solo lectura.
Queremos que inspeccione.
Esto puede incluir rastrear:
- La interacción del usuario que inicia la operación.
- El estado o representación que la transporta.
- Los límites de validación existentes.
- La persistencia y el historial.
- El comportamiento de recarga o reconstrucción.
- Los recorridos de renderizado relacionados.
- El comportamiento de exportación o publicación.
- Las pruebas e invariantes existentes.
Las superficies concretas cambian según la función. El principio no.
Antes de decidir cómo cambiar un sistema, establece cómo funciona actualmente.
Suena obvio al describir el trabajo de ingeniería humano. Con agentes importa más porque pueden pasar de una comprensión incompleta a cientos de líneas de implementación casi sin fricción.
Eliminar esa fricción es una de las ventajas de la IA.
A veces reintroducimos deliberadamente un poco.
Planificamos según contratos, no archivos
Un plan de implementación débil es una lista de archivos:
Modificar componente A. Añadir función B. Actualizar prueba C.Puede ser útil después, pero aún no es un plan de arquitectura.
Un plan más sólido describe los contratos que el cambio debe preservar.
Por ejemplo:
Intención del usuario ↓ Operación admitida ↓ Transición de estado autoritativa ↓ Persistencia ↓ Reconstrucción ↓ Resultado visibleUna vez comprendido el contrato, los archivos son detalles de implementación.
Esto cambia cómo razona el agente.
En lugar de preguntar:
¿Dónde puedo poner código para que esto funcione?
el plan pregunta:
¿Qué límite existente debe ser responsable de este comportamiento?
Esa distinción nos ha evitado aceptar implementaciones cómodas localmente pero incorrectas estructuralmente.
El objetivo no es la pureza teórica. Es evitar una arquitectura más difícil de entender con cada función añadida.
Las invariantes concretan el plan
«Ten cuidado» no es un requisito de ingeniería útil.
Tampoco «no rompas nada».
Antes de implementar, intentamos identificar invariantes explícitas: propiedades que deben seguir siendo ciertas después del cambio.
Algunas son específicas de una función. Otras describen expectativas generales del producto.
Una invariante puede exigir que una fuente de verdad existente conserve su autoridad. Otra, que una operación sobreviva a una recarga. Un cambio puede necesitar preservar Deshacer, rechazar estado obsoleto, seguir siendo exportable o no tocar rutas ajenas.
Estas afirmaciones dan límites al agente.
También dan al revisor algo más útil que una inspección visual.
En lugar de preguntar si una diferencia de código parece razonable, podemos preguntar:
¿La implementación preserva las invariantes acordadas antes de que existiera el código?
Así la revisión compara contra un diseño explícito en lugar de negociar con la implementación que produjo el agente.
El alcance de los efectos es parte de la función
Los agentes son muy buenos para hacer que un cambio parezca acotado.
A veces lo está.
Otras veces, la diferencia visible es pequeña pero sus efectos sobre el comportamiento son mucho mayores.
Antes de programar, pedimos al agente identificar qué podría afectar la función:
- Componentes compartidos.
- Transiciones de estado.
- Persistencia.
- Datos existentes.
- Límites de autenticación o propiedad.
- Renderizado.
- Exportación.
- Descubrimiento público.
- Otros trabajos en curso.
El objetivo no es crear un grafo exhaustivo de dependencias para cada botón.
Es descubrir acoplamientos inesperados antes de modificarlos.
Esto importa especialmente cuando varias ramas o agentes trabajan al mismo tiempo. Un cambio técnicamente correcto aún puede ser inseguro si reescribe sin cuidado una superficie compartida de la que depende otra función.
A veces el mejor plan no es la implementación más ingeniosa.
Es la que tiene el menor alcance de efectos justificado.
El comportamiento ante fallos pertenece al plan
Los casos exitosos son fáciles de describir.
El usuario actúa. La solicitud tiene éxito. La interfaz se actualiza.
El software real pasa mucho tiempo fuera de esa secuencia.
Las solicitudes llegan tarde. El estado cambia. Una dependencia no está disponible. Falla la validación. El usuario sale de la página. Una operación tiene éxito en un lugar y falla en otro.
Por eso un plan debe responder más que qué pasa cuando todo funciona.
Queremos saber:
- ¿Qué tiene autoridad si dos representaciones discrepan?
- ¿Qué se puede reintentar?
- ¿Qué debe bloquearse ante un fallo?
- ¿Qué permanece intacto tras un rechazo?
- ¿Puede una operación parcialmente completada dejar estado duradero?
- ¿Cómo se recupera el usuario?
No todas las funciones requieren mecanismos de sistemas distribuidos.
La mayoría no.
Pero todas tienen una semántica de fallos, tanto si la diseñamos como si la heredamos accidentalmente.
Planificar obliga a hacerla visible antes de que la implementación encarezca cambiarla.
Revisamos el plan antes de que el código nos condicione
Hay otra razón para separar planificación e implementación: el código genera apego.
Cuando un agente produce una solución sofisticada, existe la tentación natural de repararla en lugar de cuestionar si debería existir.
A los humanos también nos pasa.
Un cambio grande que funciona transforma la conversación de:
¿Cuál es la arquitectura correcta?
a:
¿Cómo hacemos aceptable esta arquitectura?
Plan First mantiene esa decisión al principio.
El agente propone:
- Su comprensión del sistema actual.
- La transición de estado prevista.
- Los contratos involucrados.
- Los archivos que probablemente cambiarán.
- El comportamiento ante fallos.
- Las pruebas y la validación.
- El alcance de los efectos.
- La estrategia de reversión.
Así una persona puede rechazar la dirección cuando hacerlo aún cuesta poco.
A veces el resultado es simplemente:
Aprobado. Impleméntalo.
Otras veces una suposición es incorrecta y el plan cambia.
A veces la exploración revela que la función debe usar infraestructura que ya existe.
Y a veces la decisión correcta es no construir la función todavía.
Los cuatro resultados son valiosos.
Aprobar no significa ejecutar a ciegas
Una vez aprobado el plan, el agente tiene mucha más libertad.
En ese momento queremos velocidad.
Puede recorrer los archivos pertinentes, implementar el cambio acotado, añadir pruebas, validar e informar hallazgos inesperados.
Pero la aprobación no permite rediseñar el sistema en silencio.
Si implementar revela que una suposición del plan era falsa, es información nueva.
La respuesta adecuada suele ser detenerse y actualizar el plan en lugar de improvisar otra arquitectura a mitad del trabajo.
Esto crea una división sencilla:
La planificación define el cambio previsto. La implementación descubre si coincide con la realidad.
Los agentes son especialmente eficaces cuando ambas fases se informan mutuamente sin volverse indistinguibles.
Los planes deben ser proporcionales
Plan First no significa escribir un RFC por cada cambio de texto.
Una errata no necesita exploración arquitectónica.
Un pequeño arreglo de estilo aislado puede requerir solo identificar el componente correcto y comprobar su adaptación a pantallas.
La profundidad del plan debe crecer con la incertidumbre y el alcance de los efectos.
Somos más deliberados cuando el trabajo involucra:
- Estado persistente.
- Contratos compartidos.
- Autenticación.
- Concurrencia.
- Historial de versiones.
- Edición estructural.
- Migraciones de datos.
- Publicación o exportación.
- Comunicación entre límites del sistema.
- Comportamiento existente con impacto importante en usuarios.
Planificar busca reducir la incertidumbre costosa.
Si la incertidumbre ya es baja, el plan debe ser breve.
La IA hace más importante la arquitectura
Uno de los efectos más interesantes de los agentes es que implementar se ha vuelto más barato.
Eso cambia dónde aporta más valor el esfuerzo de ingeniería.
Cuando producir otras cien líneas de código competente es fácil, la habilidad escasa pasa a ser decidir:
- Qué cien líneas deben existir.
- Dónde deben estar.
- Qué estado pueden cambiar.
- Qué garantías deben preservar.
- Cómo interactúan con lo ya construido.
Es decir, implementar más rápido aumenta el valor de la arquitectura.
Ahora una mala decisión puede implementarse de forma impecable y a una velocidad extraordinaria.
Una buena también.
La diferencia se decide cada vez más antes de la primera edición.
El agente forma parte del ciclo de ingeniería
No tratamos a los agentes como autocompletado ni como propietarios autónomos de la arquitectura.
Ocupan una posición más útil entre esos extremos.
Un agente puede investigar un repositorio, rastrear comportamientos entre capas, cuestionar supuestos, enumerar fallos, proponer un diseño acotado, implementarlo, validarlo y explicar los cambios.
Una persona puede aportar intención de producto, fijar prioridades, rechazar complejidad innecesaria, cuestionar atajos, aprobar límites arquitectónicos y decidir si el comportamiento final es aceptable.
El resultado no es «la IA programa y las personas miran».
Es un ciclo de ingeniería en el que distintos tipos de razonamiento ocurren en distintas etapas.
Para nosotros suele ser:
Intención ↓ Exploración de solo lectura ↓ Plan ↓ Revisión y aprobación ↓ Implementación acotada ↓ Validación ↓ Revisión de ingenieríaDespués el ciclo se repite cuando aparece información nueva.
Empieza más despacio para avanzar más rápido
La forma más rápida de empezar una función suele ser programar de inmediato.
La forma más rápida de terminar una función compleja con fiabilidad puede ser otra.
Unos minutos identificando límites de estado, contratos existentes, comportamiento ante fallos y alcance de efectos pueden evitar horas desenredando una implementación que resolvió con elegancia el problema equivocado.
Los agentes permiten implementar a una velocidad que hace poco era inusual.
Queremos esa velocidad.
Pero resulta más valiosa una vez fijada la dirección.
Por eso nuestros agentes suelen empezar con una instrucción inusual:
No cambies nada todavía.
Primero, entiende el sistema.
Después, muéstranos el plan.
Entonces construimos.