Tests vs comprobaciones de comprensión para código con IA
Los tests no detectan el mayor riesgo del código de IA: no entenderlo. Comparamos gates de comprensión con tests y linters, y cuándo gana cada uno.

Este escenario es cada vez más común: tu agente de programación escribe 600 líneas repartidas en cuatro archivos, los tests pasan, el linter está contento y tú haces merge. Dos semanas después se rompe en producción y miras el diff como si lo hubiera escrito un desconocido, porque, en la práctica, así fue. El fallo no estaba en el código. Estaba en la distancia entre el código y tu modelo mental de él. Esa distancia es lo que intentan cerrar las comprobaciones de comprensión de código con IA, gates que te hacen preguntas sobre un diff antes de que se envíe. Esta semana se hizo popular Sphinx, un Git hook de código abierto que hace exactamente eso: antes de que tu push se complete, lee el diff y te pregunta qué hace el código cuando las cosas salen mal.
Como ex ingeniero de ML, mi primer instinto fue ser escéptico. ¿Otro gate? ¿Otro ritual? Pero cuanto más pienso en los modos de fallo que realmente veo en código generado por agentes, más creo que esta idea apunta a algo que los tests, por su diseño, no pueden cubrir. Así que hagamos la comparación honesta: comprobaciones de comprensión frente a la red de seguridad automática que ya tienes (tests, linters, type checkers, CI), y cuándo gana cada una realmente.
Lo que verifican realmente los tests y linters
Las comprobaciones automáticas responden a una sola pregunta: ¿el código se comporta como esperan los checks? Es un bucle que se cierra por completo dentro de la máquina. Un test codifica la creencia de alguien sobre el comportamiento correcto, el código lo cumple o no, y en el momento del merge no hace falta ninguna comprensión humana. Esto es una ventaja. Es lo que permite que cien ingenieros envíen cambios al mismo repositorio sin leer el trabajo de los demás.
El problema está en la suposición que subyace a ese modelo: que quien hace el merge tiene un modelo mental preciso de lo que el código debería hacer, y que la suite de tests lo refleja. Con código escrito a mano, esa suposición suele cumplirse: lo escribiste, peleaste con él, sabes dónde están los problemas. Con código generado por agentes se rompe en silencio. Describiste un objetivo, el agente produjo una implementación y los tests pasan porque el agente también escribió esos tests. La marca verde ahora certifica que el código del agente coincide con los tests del agente. Tu comprensión nunca estuvo en el bucle.
Es la misma trampa de la que escribí en por qué los benchmarks de IA no capturan la mayor parte del trabajo real: una métrica solo puede certificar lo que mide. Una suite de tests mide la conformidad de comportamiento en los casos que alguien pensó en codificar. No dice nada sobre si la lógica de reintentos cobra dos veces a un cliente en un timeout de Stripe, si el agente eligió por completo el endpoint equivocado o si el “arreglo” tapa una race condition tragándose una excepción. Son fallos de comprensión, y pasan sin problema por el CI.
Lo que las comprobaciones de comprensión detectan y los tests no
Una comprobación de comprensión invierte la dirección de la verificación. En lugar de preguntar “¿el código funciona?”, pregunta “¿la persona que envía esto sabe qué hace cuando las cosas salen mal?”. El ejemplo ilustrativo de Sphinx es muy bueno: tu handler de webhooks ahora guarda el ID del evento de Stripe antes de llamar a charge(). ¿Qué pasa en un reintento tras un timeout? Si dices “el cliente se cobra dos veces”, te equivocas: el ID guardado corta el reintento. Pero entonces viene la pregunta siguiente: si charge() falla, ¿qué hace el siguiente reintento? Se salta el cobro. El cliente nunca paga, y ningún test falla, porque es un patrón de idempotencia que parece correcto aplicado en el orden equivocado.
Fíjate en qué tipo de bug es. No es un error de sintaxis, de tipos ni una aserción que falla. Es un fallo de diseño que solo aparece con una secuencia de fallos concreta, y la única forma barata de detectarlo antes de producción es que una persona razone sobre la ruta de fallo. Los tests podrían detectarlo, si alguien hubiera escrito un test para “el cobro falla después de persistir el ID del evento”. Pero la persona que escribiría ese test es la que entendió el riesgo del orden, y si esa persona existiera, no estaríamos aquí. Las comprobaciones de comprensión buscan exactamente el entendimiento que habría escrito el test que faltaba.
Hay un segundo beneficio, menos sobre detectar bugs y más sobre revertir una pérdida lenta de habilidad. Muchos desarrolladores describen la misma experiencia: pelear con un agente hasta conseguir un resultado que funcione consume energía real, pero no deja nada aprendido. Envías más y entiendes menos, y la brecha se acumula. Un cuestionario en el momento del push obliga a reconstruir, aunque sea superficialmente, la lógica del diff, y eso suele bastar para convertir “código que aprobé” en “código que es mío”. Ya he argumentado que las herramientas de IA están cambiando sin hacer ruido cómo piensan los desarrolladores; estos gates son de las primeras herramientas que empujan en la dirección contraria.
Cuándo ganan los tests automatizados
No idealicemos el gate humano. Los tests ganan con claridad en varios terrenos, y fingir lo contrario es la forma más rápida de acabar con un cuestionario como única red de seguridad.
- Detección de regresiones a escala. Ningún modelo mental sobrevive a un refactor de 30.000 líneas. Los tests reverifican miles de comportamientos por commit por unos céntimos. Una comprobación de comprensión puede cubrir quizá tres preguntas de un solo diff.
- Corrección mecánica. Errores de índice, formatos de cadena mal escritos, zonas horarias mal gestionadas: las máquinas comprueban esto de forma exhaustiva mucho mejor que una persona respondiendo preguntas con prisa.
- Repetibilidad. Un test se ejecuta igual para siempre. La calidad de una pregunta de quiz depende del modelo que la generó y de lo despierto que estés a las 5 de la tarde un viernes.
- Confianza al refactorizar. Cuando el comportamiento no debería cambiar en absoluto, los tests son la única comprobación que sirve. Entender el código no te ayuda a verificar que no lo cambiaste.
También hay un tipo de código donde las comprobaciones de comprensión solo añaden fricción sin aportar valor: boilerplate generado, migraciones mecánicas, actualizaciones de dependencias, cambios de configuración. Hacerme un examen sobre lo que hace un reformateo de Prettier es un impuesto, no un gate. Cualquier herramienta de este tipo necesita una buena respuesta para los diffs de bajo riesgo, o la gente la esquivará. Y es revelador que Sphinx lo anticipe con una vía de escape, sphinx yolo, que registra cada salto. Ese registro importa más de lo que parece: un gate que todos esquivan en silencio es peor que no tener gate.

Cuándo ganan las comprobaciones de comprensión
Las comprobaciones de comprensión ganan justo donde la persona es el eslabón más débil, que en el desarrollo asistido por agentes ocurre más a menudo de lo que nos gustaría admitir.
- Razonamiento sobre rutas de fallo. Reintentos, timeouts, escrituras parciales, transacciones distribuidas: las rutas de código que solo se ejecutan cuando algo más ya está roto. Los agentes se manejan bien en el camino feliz y son descuidados con el camino triste.
- Diffs de alto radio de impacto. Pagos, autenticación, migraciones de datos, cualquier cosa que toque sistemas que deberían resistir una catástrofe. El coste de una respuesta incorrecta aquí supera con creces dos minutos de molestia del cuestionario.
- Código que no escribiste y apenas revisaste. El PR de 1.500 líneas de un compañero que no es desarrollador, la rama nocturna autónoma del agente. Un profesional contó que usó un prompt de “hazme un quiz sobre este PR” solo para mantenerse concentrado en la revisión estructurada de justamente este tipo de cambios.
- Onboarding y mantenimiento de habilidades. Si tu equipo envía código de agentes más rápido de lo que alguien aprende el dominio, un gate de comprensión es el mecanismo de presión más barato que existe.
El hilo común: las comprobaciones de comprensión se justifican cuando el diff es relevante y el modelo mental de la persona es dudoso. Es un nicho concreto, no una solución universal.
Los modos de fallo del propio gate
Te haría un flaco favor sin la lista honesta de cómo puede salir mal, porque los escépticos tienen razón en varias cosas.
Primero, la fatiga de confirmación. Ya hemos estado aquí: banners de cookies, diálogos de “¿estás seguro?”, preguntas de seguridad que todo el mundo acepta sin leer. Un gate que se activa en cada push entrena a la gente para responder rápido en lugar de pensar, y en un mes el cuestionario es teatro ritual. La mitigación está en acotarlo: ejecutarlo en ramas protegidas y rutas de alto riesgo, no en cada commit de una rama de funcionalidad.
Segundo, la calidad de las preguntas. El cuestionario lo genera un LLM que lee el diff, así que hereda sus fallos: preguntas superficiales, “respuestas correctas” equivocadas, obsesión con el cambio obvio mientras se pasa por alto el sutil. Un revisor comentó que su versión le ayudó a estructurar la revisión, pero no detectó malas decisiones como llamar al endpoint equivocado. Una pregunta mala es peor que ninguna, porque certifica una comprensión que nunca se puso a prueba. Es una limitación real y no creo que se pueda resolver del todo; es la misma razón por la que el diseño del harness del agente importa más que el modelo elegido en tantas de estas herramientas.
Tercero, y esto me hizo reír porque es verdad: alguien acabará apuntando un agente al gate para que responda las preguntas por él. El diseño de la herramienta muestra que se ha previsto: tus respuestas nunca llegan al agente de programación y los secretos permanecen cerrados. Pero nada impide que un desarrollador decidido pegue la pregunta en una ventana de chat. En ese punto, la herramienta mide la disposición a hacer trampa, y eso es un problema de cultura que ningún hook puede resolver.
Un gate de comprensión no verifica el código. Verifica que una persona con contexto y responsabilidad se involucró de verdad con él, algo que los flujos de trabajo con agentes eliminaron en silencio.
Integrar el gate en un flujo de trabajo real
Si quieres probarlo, tienes dos opciones prácticas. La ruta de poca fricción es una skill basada en prompts en tu agente actual: “hazme un quiz sobre la rama actual antes de abrir el PR”. Varias personas lo han montado exactamente así y dicen que funciona bien para estructurar la revisión, pero ten en cuenta que depende de que decidas ejecutarlo, y eso falla justo cuando vas más apurado.
La ruta obligatoria es un Git hook. Sphinx se instala en un minuto: npm install -g sphinx-understand, luego sphinx install, que conecta Git y tus agentes de programación y pregunta qué modelo debe revisar. Funciona con Claude Code, Codex, Cursor y otros, o con Git a secas, y puede usar cualquier endpoint compatible con OpenAI. Si prefieres montar el tuyo, el esqueleto es un hook pre-push:
#!/usr/bin/env bash
# .git/hooks/pre-push — quiz gate for protected branches
protected_branch="main"
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" != "$protected_branch" ]; then
exit 0 # only gate the branches that matter
fi
diff=$(git diff origin/main...HEAD)
if [ -z "$diff" ]; then
exit 0
fi
# Send the diff to your model of choice, get a scenario question,
# check the answer. Pseudocode for the core loop:
question=$(quiz_generate "$diff")
echo "$question"
read -r answer
if ! quiz_verify "$diff" "$question" "$answer"; then
echo "Not quite — here's why. Push blocked; try again."
exit 1
fi
Dos decisiones de diseño importan más que el código. Aplica el gate a ramas, no a pushes: actívalo en los pushes a main y a las ramas de release, e idealmente también en “solicitar revisión”, porque detectar el código de baja calidad antes de que consuma la atención de un compañero es, probablemente, el punto de mayor valor. Y registra cada bypass. La vía de escape es necesaria; el registro de auditoría es lo que la mantiene honesta.
Considera también dónde encaja esto frente a la revisión humana. He escrito sobre cómo cada capa de revisión ralentiza a un equipo, y lo sostengo, así que no lo añadas encima de todo lo demás. Úsalo para reemplazar la primera pasada, la más superficial: la de “¿el autor sabe siquiera qué hace esto?”. Esa es la pasada que las comprobaciones de comprensión automatizan de verdad.
La recomendación
Los tests y las comprobaciones de comprensión no son competidores: verifican cosas distintas. Los tests verifican el código; las comprobaciones de comprensión verifican a la persona responsable de él. El desarrollo asistido por agentes rompió la suposición implícita de que ambas cosas eran lo mismo, y estos gates son un parche pragmático, no un gimmick.
Mi recomendación: mantén tu suite de tests como red de seguridad principal, porque nada de esto la sustituye, y añade un gate de comprensión de forma acotada, en ramas protegidas y rutas de alto riesgo, con una vía de escape registrada. Si escribes la mayor parte del código a mano, no lo necesitas; el valor del gate crece con la parte de tu diff que no escribiste tú. Y si el cuestionario empieza a sentirse como una tarea que esquivas, eso también es una señal: significa que envías código que no entiendes lo bastante rápido como para que una pausa de dos minutos te parezca cara. Piénsalo. La versión incómoda de la tesis de esta herramienta es la correcta: puedes externalizar el pensamiento, pero la comprensión tiene que seguir siendo tuya, porque a las 3 de la mañana, cuando el bucle de reintentos cobre a alguien sin que nadie lo note, el agente no está de guardia. Lo estás tú.


