Todos los artículos

Cuando leer código de IA no es revisarlo

Escuchar el artículo (experimental) · 09:57

00:00 / 09:57

Un campo denso de líneas de código que fluyen hacia la oscuridad, con un punto de control iluminado donde unas pocas líneas se elevan a la luz y se leen mientras el resto pasa sin leer

Hay un programador que puedo imaginar con nitidez, porque una versión de él está en todas partes ahora mismo, y tiene un flujo de trabajo que parece responsable. Deja que el modelo escriba el código y lee el diff antes de aceptarlo. Está revisando. Salvo que los diffs se vuelven cada vez más largos, la lectura cada vez más rápida, y una tarde se da cuenta de que ha estado aceptando código que ahora no sabría cambiar si tuviera que hacerlo. Los proyectos que construyó en gran parte la máquina son aquellos por los que apenas sabe moverse. Un proyecto que escribió a mano hace tres años todavía se siente como su propia casa. En algún punto de todo eso, leer dejó de ser revisar, y nada lo anunció.

A veces leer es todo el trabajo

Esto es lo que se equivoca la versión extrema de esa advertencia. Para buena parte de lo que aceptas en un día, leer el diff es todo el trabajo, y ejecutarlo tú mismo sería puro teatro. Un renombrado que el compilador ya ha validado. La subida de versión de una dependencia. Un valor de configuración, un cambio de texto, un comentario. Boilerplate que has escrito cien veces y puedes comprobar por su forma. Un bloque de tests generados, donde leer es de todos modos la pasada más valiosa, porque leer es lo que atrapa el test que no comprueba nada y aun así pasa en verde.

Leer con cuidado no es un instrumento débil. Mucho antes de todo esto, la inspección de código encontraba más defectos por hora que las pruebas, y lo sigue haciendo. Así que la cuestión no es "ejecuta siempre el código". La cuestión es que leer y ejecutar son ciegos ante bugs distintos, y casi toda la discusión que la gente tiene es en realidad una discusión sobre en qué ceguera están viviendo.

La verdadera prueba es si puedes predecirlo

La pregunta nunca fue leer frente a ejecutar. Es si puedes predecir qué hace el código sin ejecutarlo.

Para una categoría de cambios sí puedes, y leer basta. Para otra, la corrección no está en el texto que tienes delante. Vive entre líneas, en el entrelazado de dos hilos que el diff solo puede mostrarte de uno en uno. Vive bajo carga, en la consulta que va bien con diez filas y es fatal con diez millones. Vive en el límite, en el off-by-one y en la ruta de error por la que el caso feliz pasa de largo. Vive al otro lado del cable, en si la pieza nueva está siquiera conectada a lo que la llama. Vive en el espacio negativo, en la comprobación de autorización que no está y en la excepción que se traga en silencio, es decir, en una línea que nunca aparece en el diff porque nunca se escribió. No puedes llegar leyendo a un bug que solo existe en tiempo de ejecución.

La IA hace que "parece correcto" signifique menos

La IA agudiza esto de una forma muy concreta. Quien revisa aprueba código a partir de señales que hacen las veces de corrección. Se lee como código idiomático. Se ve seguro de sí mismo. Se parece a código que funcionó antes. Un modelo de lenguaje es una máquina afinada para producir exactamente esas señales. Se le da muy bien parecer correcto.

Así que el atajo más viejo de la revisión, "esto tiene buena pinta", nunca ha sido una prueba más débil de que la cosa esté bien. El pulido no tranquiliza. Es el riesgo, porque apunta justo a la parte de ti que iba a dejar pasar el cambio. Hay investigación que muestra que la gente a la que se le da un asistente capaz escribió código menos seguro y se sintió más segura de que lo era. La confianza se mueve en dirección contraria al peligro, y el código generado y limpio es la entrada más desarmante que se le puede poner delante a quien revisa.

La máquina también puede ejecutarlo

Ejecutar el código ya no es solo algo que haces a mano. El agente puede ejecutarlo por ti y devolverte los logs, una captura, un párrafo que explica qué cambió y por qué está seguro. Eso es real, y para muchos cambios es todo lo que hay: los tests pasaron en verde mientras mirabas, la captura muestra el botón en su sitio, y terminas antes de lo que habrías terminado tú solo.

Pero fíjate en lo que pasó ahí. Esa evidencia la produjo el mismo tipo de sistema que escribió el código, apuntando al mismo objetivo, que es parecer correcto. Un log en verde que no viste correr es una afirmación, no un hecho. Puedes incluso poner al agente a vigilar los logs, la base de datos, las llamadas que salieron, y preguntarle si todo cuadró, y eso sí es una palanca real. También es donde he cazado a un modelo que no miraba de verdad, respondiendo con lo que esperaba encontrar. Así que ceder la ejecución al agente no elimina la revisión. La sube un nivel, del diff a la evidencia. Cuando te diga que los logs muestran X, abre los logs y encuentra X. Trata el "funcionó, aquí está la prueba" como una afirmación por confirmar, igual que comprobarías una cifra antes de dejar que el párrafo de un modelo se quede con ella. Es la misma comprobación que un investigador se salta cuando una cita inventada acaba en un artículo publicado.

Lo que lleva a la parte que casi tiene gracia. Para un montón de cambios pequeños, lo más rápido y fiable que puedes hacer es ejecutarlo tú mismo. Leer un muro de logs y un resumen seguro de sí mismo puede costarte más que abrir la cosa y mirarla con tus propios ojos. Ejecutarlo no es la opción lenta y aplicada a la que recurres cuando leer falla. La mitad de las veces es la rápida.

El fallo que casi todos sufren es el volumen

El fallo que casi todos sufren en realidad no tiene nada de sutil. Es el volumen.

Pasadas unas pocas centenas de líneas, cualquier revisión humana degenera en un vistazo, y un agente te dará unas cuantas centenas de líneas cada vez que se lo pidas. Revisar y nada más es lo más agotador que ofrece este trabajo, porque estás reconstruyendo la intención de otro, en un estilo que no es el tuyo, a un ritmo que no marcaste tú. Así que se hunde, en silencio, en la aceptación. Nadie decide dejar de revisar. Empiezas a ver el código en lugar de entenderlo, y desde dentro esas dos cosas se sienten idénticas. La restricción que importa no es cuánto puede escribir el modelo. Es cuánto puedes sostener tú de verdad. Deja que escriba más allá de eso y ya no estás revisando, diga lo que diga la pantalla que estás haciendo.

Ajusta la profundidad al alcance del impacto

Eso convierte la disciplina en algo más útil que "lee con más atención". Ajusta la profundidad de la revisión al alcance del impacto, y a cuán reversible es el cambio.

Un cambio pequeño y acotado que es fácil de revertir merece una lectura rápida y un merge. Una migración, una interfaz pública, un borrado, cualquier cosa que toque dinero o accesos, se gana la revisión lenta: ejecutarlo, rastrearlo, intentar romperlo, ya lo hagas tú mismo o hagas que el agente muestre su trabajo y luego compruebes qué hizo en realidad, sin importar quién ni qué lo escribió. Leer basta justo cuando las formas en que el cambio puede fallar son las que tus otras barreras ya atrapan: el compilador, los tipos, los tests que corren en CI los ejecutes o no a mano. Deja de bastar en el momento en que el fallo que de verdad te haría daño es uno que solo se revelaría ejecutando la cosa. Aplicar el mismo escrutinio a cada diff no es diligencia. Es negarse a decidir dónde está el riesgo.

Lo que cedes

Bajo el coste técnico hay otro más callado. Aceptar código que no has entendido te desplaza, clic a clic, de autor de tu producto a consumidor de él. Te quedas con el crédito y te quedas con la responsabilidad, el pager sigue sonando para ti, pero has cedido el entendimiento en el que se apoyan ambos. La gente cuenta que construye una app en una tarde y se queda con una extraña sensación de vacío, y luego pasa dos semanas haciendo que funcione de verdad y vuelve a sentirse ella misma. Eso no es nostalgia. Es la diferencia entre ser dueño de la cosa que lleva tu nombre y tener en la mano una copia que no puedes abrir.

Construyo herramientas que apuestan por completo por la generación. Una convierte una frase en un plan y abre sus propias pull requests. Otra gobierna flotas enteras de agentes. No estoy aquí para decirle a nadie que escriba menos código con IA. Pero cada una de esas herramientas da por hecho, en el extremo final, a una persona que revisa con la profundidad que el cambio merece, y una barrera por la que solo echas un vistazo no es una barrera. La máquina puede producir el diff. No puede producir la parte en la que tú lo entendiste.

Así que revisa a ojo cuanto quieras, para los cambios en los que la vista es todo lo que hay. Solo mantén una línea clara entre el diff que has entendido y el diff que solo has visto. El primero es tuyo. El segundo se vuelve tuyo en el momento en que se rompe, y le dará igual que pareciera correcto.

Preguntas que responde este artículo

  • ¿Basta con leer el diff para revisar código generado por IA?

    Para buena parte de lo que aceptas en un día sí, y ejecutarlo sería puro teatro: un renombrado que el compilador ya ha validado, la subida de versión de una dependencia, un valor de configuración, un cambio de texto, boilerplate que compruebas por su forma. Los tests generados son el caso más claro, porque leer es lo que atrapa el test que no comprueba nada y aun así pasa en verde. Deja de bastar cuando la corrección no está en el texto que tienes delante: el entrelazado de dos hilos, la consulta que va bien con diez filas y es fatal con diez millones, la ruta de error por la que el caso feliz pasa de largo, o la comprobación de autorización que nunca aparece en el diff porque nunca se escribió.

  • El agente ha ejecutado los tests y me da los logs en verde y una captura, ¿para qué voy a comprobar nada más?

    Porque esa evidencia la produjo el mismo tipo de sistema que escribió el código, apuntando al mismo objetivo, que es parecer correcto. Un log en verde que no viste correr es una afirmación, no un hecho. Ceder la ejecución al agente no elimina la revisión, la sube un nivel, del diff a la evidencia: cuando te diga que los logs muestran algo, abre los logs y encuéntralo. He cazado a un modelo que no miraba de verdad y respondía con lo que esperaba encontrar, y es la misma comprobación que se salta un investigador cuando una cita inventada acaba en un artículo publicado.

  • ¿Cuánto código de IA puedo revisar de verdad antes de que deje de ser revisión?

    Menos del que te dará un agente, porque te da unas cuantas centenas de líneas cada vez que se lo pides y, pasado ese punto, cualquier revisión humana degenera en un vistazo. Revisar y nada más es lo más agotador que ofrece este trabajo, porque estás reconstruyendo la intención de otro, en un estilo que no es el tuyo, a un ritmo que no marcaste tú. Nadie decide dejar de revisar. Empiezas a ver el código en lugar de entenderlo, y desde dentro esas dos cosas se sienten idénticas.

  • ¿No es más seguro revisarlo todo con la misma profundidad?

    No. Aplicar el mismo escrutinio a cada diff no es diligencia, es negarse a decidir dónde está el riesgo. Ajusta la profundidad al alcance del impacto y a cuán reversible es el cambio: un cambio pequeño y acotado que es fácil de revertir merece una lectura rápida y un merge, mientras que una migración, una interfaz pública, un borrado o cualquier cosa que toque dinero o accesos se gana la revisión lenta, en la que lo ejecutas, lo rastreas e intentas romperlo. Ejecutarlo tú mismo tampoco es el recurso aplicado al que se recurre al final, porque abrir la cosa y mirarla suele ser más rápido que leer un muro de logs y un resumen seguro de sí mismo.