Por qué fallan las fábricas de software
Dex, de HumanLayer, escribió Why Software Factories Fail con un subtítulo que ya lo dice casi todo: harness engineering is not enough. Estas son mis notas, y el motivo por el que me resonó tanto.
La tesis: la fábrica de software lights-off —aquella donde ningún humano lee ni escribe código— no funciona. Y no funciona no por falta de habilidad, ni por no haber configurado bien los linters, ni por no gastar suficientes tokens. Falla por una limitación estructural de cómo se entrenan y se evalúan los modelos.
El argumento en una frase
No hay penalización por erosionar la mantenibilidad de un codebase.
Todo lo demás se deriva de ahí.
Por qué RL no puede arreglarlo
Coge SWE-bench como ejemplo. Tareas de unos quince minutos, sacadas de repos open source. La recompensa es un bit:
FAIL_TO_PASS— ¿arreglaste lo que se pedía?PASS_TO_PASS— ¿lo hiciste sin romper nada más?
Cómo llegaste ahí no puntúa. Y de ahí salen los tics que todos reconocemos:
try/catchalrededor de todo, incluido unJSON.parse- casts perezosos que socavan el motivo mismo de tener tipos
- shotgun surgery: tocar once ficheros para un arreglo de una línea
- código que funciona hoy y será durísimo de cambiar en tres meses
El problema de fondo es de escalas de tiempo. Los tests dan feedback en segundos; la función de coste de una mala arquitectura se mide en semanas o meses. No hay forma de hacer backprop desde un incidente en producción hasta la decisión de diseño que lo causó. El loop rápido se puede optimizar con RL. El lento, sencillamente, no se ve.
Hay un corolario incómodo que cierra la puerta a la solución fácil:
Un modelo capaz de distinguir de forma fiable código bueno de código malo probablemente habría escrito la versión buena de entrada.
Por eso más agentes de review y más tokens suben el suelo, pero no mueven el techo. Actúan en inferencia; el techo lo fijó el entrenamiento.
Las señales
| Fuente | Señal |
|---|---|
| Faros AI (pre-merge) | +25% comentarios en PRs · +22,7% comentarios más largos · +31,3% de PRs mergeados sin review |
| Faros AI (producción) | Incidentes por PR +242,7% · incidentes mensuales +57,9% · bugs por desarrollador +54% |
| Matt Pocock | “los codebases se están rompiendo más rápido que nunca” |
Es correlación, no prueba, y el propio Dex lo reconoce. Lo que le da peso es que él mismo se estrelló: en julio de 2025 HumanLayer se fue full lights-off, solo specs y agentes en background. El patrón de fallo se repitió tres veces y siempre igual: aparece un bug que el agente no resuelve, terminas metiéndote a mano en un codebase que dejaste de leer hace tres meses, con el site caído y usuarios cabreados. A la tercera salió más barato reescribir desde cero.
Un matiz que me parece el dato más importante del artículo: “brownfield” ya no significa Java de diez años. Al ritmo actual, un codebase construido por agentes empieza a atascarse a los tres a seis meses.
Encender otra vez las luces
Si el juez tienes que ser tú, la respuesta no es “revisa más”, es front-loading alignment: mover las decisiones al momento en que cambiar de opinión todavía es barato. Nada de esto es nuevo —es planning y arquitectura de toda la vida— salvo que ahora el modelo redacta el borrador y tú discutes con él.
1. Product review. Un doc corto con dos acuerdos: el problema en términos del usuario, no técnicos, y qué aspecto tiene el éxito. Si es algo que el usuario ve, no lo describas: maquétalo. Un mockup HTML rústico zanja una discusión que tres párrafos solo alargan. No todo lo lleva: un tweak de copy o un bug con repro obvio siguen yendo oneshot.
2. System architecture. Cómo hablan entre sí servicios, endpoints, schemas y colas. Diagramas de secuencia, contratos, modelos de datos. Es donde se atajan los tics del modelo antes de que existan.
3. Program design. La fase que más se olvida: bajar de la arquitectura a la forma del código. Tipos, signatures, layout, call stacks. Lo que a ellos les funcionó no fue Mermaid sino pseudocódigo ligero, con sintaxis diff cuando lo interesante es lo que cambia:
entrypoint runCommand handleCreateResource ResourceClient.create(input) POST /resources renderResult legacyCreateFlowY diffs de árbol de ficheros, para no perder de vista dónde vive cada cosa:
src └── resource ├── resource-client.ts # NUEVO - envuelve las llamadas al contrato ├── resource-client.test.ts # NUEVO - cubre el mapeo request/response~ └── resource-route.ts # MODIFICADO - conecta la acción con la UICada uno de estos artefactos es una decisión que, si no la tomas aquí, la tomarás implícitamente durante el code review: el momento más caro posible para cambiar de opinión.
4. Vertical slices. Los modelos aman los planes horizontales en orden de stack: migraciones → servicios → API → frontend. El problema es que no puedes tocar nada hasta el final. Antes de la IA era rarísimo que alguien escribiera 500 líneas sin comprobar algo por el camino; ahora escribe 2000 sin pestañear. La alternativa son rebanadas verticales: contrato de API con datos mock que pruebas con curl, luego frontend contra el mock, luego servicios, luego base de datos. Revisar 100-200 líneas y corregir el rumbo es incomparablemente más barato que aterrizar al otro lado de 2000 sin idea de qué está roto.
30 minutos de planning ahorran horas de review.
La regla 80/20
Nada de esto aplica a todo. Aproximadamente el 40% de las tareas son pequeñas y van oneshot, quizá con una o dos rondas de feedback. Las medianas juntan producto y diseño de sistema en un solo doc, sin trocear. Solo las grandes pasan por todas las fases —y en refactors grandes se salta la de producto.
Lo que me llevo
Tres cosas, y ninguna es “usa menos IA”:
- La fábrica lights-off no se sostiene, y el motivo no es de configuración. Es que nadie está mirando, y la degradación es invisible hasta que es cara.
- Especificar por adelantado gana al revisar por detrás. No porque el review sobre, sino porque un PR que necesita un 50% de rework —lo normal en un oneshot— es carga intelectual y emocional para quien lo manda y para quien lo revisa. El problema no es que tengas demasiados PRs: es que tienes demasiados PRs malos.
- Lintear durante la edición, no después. El paper de SWE-Agent ya mostraba en 2024 que una edit tool con linting integrado cambia el comportamiento del agente de forma drástica. Un bot que comenta el PR al final llega tarde: el modelo ya construyó encima. Meter la señal dentro del loop de edición es de otro orden.
El artículo cierra con algo que agradezco, porque evita el derrotismo fácil. Lo que describe son constraints, nada más:
Puede que estés tan ocupado intentando ir 10-100x más rápido, y convenciéndote de que la calidad ya no importa, que te estés perdiendo la opción de abrazar las constraints e ir 2-3x más rápido, con seguridad.
Y el consejo final, en cuatro líneas: aprende bien las constraints, optimiza tus sistemas dentro de ellas, busca leverage, y lee el maldito código.
Fuentes