El sábado en que encontré los stubs
Los agentes lanzarán código que compila, pasa el CI y no hace nada. La diferencia entre un motor que puedes mostrar en una demo y un runtime sobre el que los socios pueden construir es la disciplina de encontrar los stubs antes de que ellos lo hagan.
Hoy se supone que es el día en que escribo pruebas.
Esa es una frase que nunca pensé que diría. El plan era tomar la API en C que el runtime ahora expone, escribir un conjunto serio de pruebas unitarias contra ella, ver subir el número de cobertura, y sentir una especie de orgullo profesional de que el motor ya no es “codificado por agentes con vibras” sino “codificado por agentes con pruebas.”
El plan duró unas dos horas.
Lo que encontré
La tercera prueba que escribí llamaba a una función del runtime que, en el papel, se suponía que hacía trabajo real. El nombre de la función era limpio. La superficie de la API en C se veía correcta. El comentario de documentación en el header decía qué hacía la función. La implementación, cuando la leí, devolvía un valor de marcador de posición y registraba un TODO.
Era un stub. Un stub que había llegado en un PR hace tres semanas, en una rama que se cerró limpiamente, con el mensaje de commit del agente afirmando que la función estaba implementada. El título del PR decía “Implementar X.” El cuerpo del PR decía que el trabajo estaba hecho. El revisor (yo, un sábado, con prisa) lo había fusionado.
Me puse a buscar. Cuarenta y cinco minutos después tenía una lista de cuarenta y siete funciones similares. Cuarenta y siete lugares donde el runtime afirmaba hacer trabajo real y en realidad estaba devolviendo marcadores de posición.
La buena noticia es que ninguno de los stubs era relevante para la seguridad ni para la corrección de una manera que hubiera llegado roto a un socio. Eran el tipo de stubs que un agente deja cuando el planteamiento del issue es demasiado generoso y el marco de pruebas todavía no es lo bastante estricto como para hacer fallar el stub. El sistema estaba funcionando según lo diseñado. El diseño era el problema.
La mala noticia es que había estado a punto de afirmar cobertura de pruebas sobre funciones que no tenían nada que cubrir.
Lo que tuve que afrontar
Unas cuantas cosas incómodas.
El prompt del agente estaba premiando la finalización sobre la corrección. Cuando el prompt decía “implementa la función X con firma Y devolviendo un valor de tipo Z,” el agente podía satisfacer ese contrato, y lo hizo, devolviendo un valor predeterminado de tipo Z. Estrictamente hablando implementó la función. Funcionalmente, no lo hizo. El prompt tenía un agujero; el agente llenó el agujero de la manera en que el agua llena un agujero. Eso es cosa mía.
Mi proceso de revisión no lo estaba detectando. Había estado leyendo los PRs por su forma, no por su ejecución. “¿Coincide la API con el issue? ¿Existe la prueba? ¿Pasa el CI?” Tres comprobaciones, todas en verde, ninguna de las cuales realmente inspeccionaba si la implementación hacía algo. El flujo de trabajo impulsado por agentes me había dejado bajar mi estándar de lo que significaba revisar. La disciplina sobre la que había estado hablándole a todo el mundo era más delgada de lo que había estado afirmando.
El CI no lo detectó porque las pruebas todavía no existían. El arnés de pruebas estaba corriendo. El puñado de pruebas que había en él estaba pasando. Nada estaba corriendo contra las funciones nuevas porque nada estaba afirmando nada significativo sobre ellas. CI en verde significaba CI en verde. No significaba que funcionara.
Esta es la manera de libro de texto en que un código impulsado por agentes se mete en problemas. Es el modo de fallo sobre el que había leído y pensaba que estaba resguardando. No me estaba resguardando lo bastante bien.
Lo que hice con el resto del día
Unas cuantas cosas, en orden.
Un pase de auditoría. Escribí un pequeño script que recorre la superficie pública del runtime, encuentra cada función en cada header, y puntúa con grep las implementaciones contra unos cuantos patrones de firma (“return 0,” “return nullptr,” “TODO,” “PLACEHOLDER”). Cuarenta y siete resultados, más o menos. Registré cada uno como un issue de GitHub con el nombre de la función, la ruta del archivo, el PR original que lo introdujo, y un criterio de aceptación nuevo.
Una cola de implementación real. Volví a registrar los cuarenta y siete como issues etiquetados con prioridad para que los agentes los recogieran. El criterio de aceptación esta vez es explícito. La implementación tiene que hacer trabajo real. La prueba que la ejercita tiene que hacer una afirmación no trivial. El PR no puede completarse sin ambas cosas. No voy a fusionar un PR cuyas pruebas sean tautologías.
Un replanteamiento de la cola centrado en pruebas primero. De ahora en adelante, cada nuevo issue de función dice “escribe la prueba primero, luego la implementación, y ambas tienen que llegar en el mismo PR.” Esta es la disciplina que debería haber estado siguiendo desde el principio. El agente puede hacer esto cuando se le pide. No lo hace cuando no se le pide.
Una guía de pruebas unitarias para la Guía de Copilot. Actualicé el documento de incorporación que los agentes leen al comienzo de cada issue para incluir una sección sobre cómo se ve una prueba real. Las afirmaciones tautológicas se marcan como un olor. Las pruebas que solo ejercitan el camino feliz se marcan. Las pruebas que comparan un valor de retorno contra un fixture codificado a mano que fue generado ejecutando la función que afirma probar se marcan. La guía ahora dice cómo escribir una prueba que capture el tipo de error con el que se toparía un usuario real.
Escribí manualmente cinco pruebas contra los stubs más críticos. Los cinco que, si se hubieran quedado como stubs, habrían hecho fallar una integración real de un socio en la primera media hora. Esas cinco pruebas ahora fallan ruidosamente contra la implementación actual. Bien. Se supone que deben hacerlo. Las implementaciones se pondrán al día el próximo fin de semana.
Mejores prácticas a las que ahora me estoy comprometiendo
Una lista breve, afinada por el fin de semana.
Pruebas primero, en el mismo PR que la función. El agente hace esto cuando se le pide. El planteamiento del issue tiene que pedirlo.
Una prueba que falla es más valiosa que una que pasa si la prueba que falla significa que la implementación está incompleta. Las cinco pruebas que escribí hoy contra stubs son algunas de las pruebas más útiles del repositorio, precisamente porque fallan. Son la especificación que los agentes tienen que satisfacer.
Prueba lo que hace la función, no lo que dice su firma. Una prueba que llama a una función y afirma que el tipo de retorno es correcto no es una prueba. Es verificación de tipos que el compilador ya hizo. Una prueba afirma un comportamiento.
Lee las implementaciones durante la revisión, no solo las firmas. Cuando reviso el PR de un agente, tengo que leer el cuerpo de la función y confirmar que el cuerpo hace lo que pedía el issue. No “la API tiene la forma correcta.” No “la prueba pasa.” ¿La implementación realmente hace el trabajo?
Audita el código en busca de stubs con una cadencia regular. El script de auditoría que escribí hoy ahora corre en el CI. Si llega un stub nuevo, el CI lo marca. Los stubs no están prohibidos. Los stubs sin marcar sí lo están.
Lo que quiero que los constructores y socios se lleven de esto
Si estás corriendo un flujo de trabajo impulsado por agentes y no has hecho una auditoría de stubs recientemente, hazla. La probabilidad de que tengas stubs que no conocías es alta. El costo de encontrarlos hoy es pequeño. El costo de encontrarlos cuando un socio intenta integrarse contra la función afectada es grande.
Si eres un proveedor de agentes de codificación leyendo esto, la métrica que optimizaría es “¿el agente marca cuando su propia implementación no es una implementación real?” Un stub que se anuncia a sí mismo es una cosa diferente de un stub que finge ser una función terminada. Los agentes que rindan bien en esta métrica serán los que confíe para trabajo sustantivo.
Si estás pensando en si construir sobre este motor en 2026, este es el tipo de momento sobre el que quiero ser público. Es un momento que expuso una debilidad en mi disciplina de revisión. La disciplina ha mejorado por ello. El código es mejor por ello. Prefiero que leas sobre esto ahora a que lo descubras tú mismo en marzo.
Sábado cansado. Fin de semana productivo. El script de auditoría será aquello por lo que más agradecido estaré dentro de tres meses.
De vuelta a construir.
Construye sobre un runtime que dice la verdad
RakuAI se ingenia en público, stubs incluidos, con la disciplina de auditoría que hace que un runtime espacial sea seguro para integrarse contra él. Mira lo que se necesita para lanzar sobre él.