Mi router mandó un reporte de bug a la skill equivocada
Le escribí a mi propio router "el test de checkout falla de forma intermitente" y me dijo que corriera /proof.
Skill equivocada. Esa frase es un reporte de bug. La skill para un reporte de bug es /reproduce, que no deja que nadie toque el código hasta que exista un test que falle. /proof es para el otro extremo del trabajo, cuando estás a punto de decir "listo". Mi router acababa de recomendar la vuelta de la victoria a alguien que todavía no encontraba el bug.
Y salió con exit 0. Éxito. Verde. Nada en la salida sugería que algo andaba mal.
La tabla de regex
/compass es el router de la suite. Me encantaría decirte que entiende tu tarea. Lo que hace es machear palabras clave. El patrón de /reproduce era \b(bug|regression|reproduce|failing|broken|debug)\b. Mi frase decía "falla" ("fails"), y "fails" no es "failing". "Fail" y "flaky" tampoco entran. Mientras tanto, la palabra "test" se coló directito al patrón de /proof y se agarró el volante.
Yo escribí esa tabla. La escribí con mi propia manera de hablar, porque era la que se me ocurrió, y le llamé enrutamiento. Cambia la frase a "el test de checkout está fallando" ("is failing") y va a /reproduce perfecto. El router funcionaba exactamente para la persona que lo construyó. Felicidades a mí.
Lo encontré en una corrida real contra ultimate-harness, no en un test unitario, lo cual te dice cuánto valían mis tests unitarios para esta pregunta en particular. El write-up lo registró como un problema de forma de las keywords. El arreglo: esa frase ya rutea a /reproduce, y agregué tests de falsos positivos, porque ensanchar un regex es como creas el siguiente misroute.
El re-verify que no re-verificaba
Misma corrida, otra skill. /proof tiene una rama de perf: dos checks sobre la misma carga de trabajo, y una razón entre ellos que tiene que quedar por debajo de un límite. Corrí lo real con el pool forks de vitest como baseline y threads como el cambio. Una corrida pasó con 1.02 y un límite de 1.5.
Luego me dio desconfianza de mi propia documentación, que decía que el check "re-verifica". Así que abrí el result.json de la corrida terminada y edité la razón a 0.5. La cifra real, de 1114 ms y 1131 ms, era 1.02.
El comando de check dijo ok.
Comparaba la razón registrada contra el límite. Nunca recalculaba la razón a partir de los tiempos registrados. "Re-verifica" era una palabra más bonita de lo que la cosa merecía. Ahora recalcula desde los tiempos, así que mi 0.5 falsificado ya no sobrevive. La documentación sigue diciendo, con exactitud, que el gate es local y no es a prueba de manipulación. Si puedes editar el archivo, puedes mentirle a un gate local; lo que cambió es que ahora la mentira tiene que ser consistente.
(Una nota al margen sobre esa tabla de perf, porque si no me van a acusar de escoger solo lo que me conviene: la misma carga midió 1.44x en una primera corrida en frío y de 1.02 a 1.08x en corridas en caliente. Esa primera falla fue ruido de caché, no una regresión, y así lo dije en el write-up.)
El aviso que nunca se imprimió
/relay pasa un checkpoint de una sesión a otra. Si el workspace cambió desde que se escribió el checkpoint, el receptor debería ver una línea STALE. Lo probé como lo haría un usuario: hice un commit vacío después del offer y luego corrí los comandos.
inject imprimió STALE: workspace changed since checkpoint, verify before acting. El archivo ack decía "stale": true. Bien. Pero la documentación te decía que corrieras read y buscaras esa línea, y read nunca la imprimió. Ni una vez. Revisé el código fuente para asegurarme de que no me lo estaba imaginando.
Peor aún, la documentación decía que esperaras la línea de relay en el panel receptor, pero ese panel no tenía nada que leer hasta que hacía ack del offer, porque la asignación se escribía en el momento del ack. La documentación describía un estado que todavía no existía. Un aviso que existe en tres lugares y no en el único al que te mandan las instrucciones es un aviso que no existe.
Ahora la asignación se escribe al momento del offer, y tanto read como ack reportan si está caduco.
Lo que me llevo
Tres bugs, una sola forma. En cada uno, el código hacía algo más chico que la frase que lo describía. "Rutea tu tarea." "Re-verifica." "Imprime STALE." El comportamiento estaba bien en el camino que yo había imaginado y mal en el que no.
Ninguno tronó. Eso es lo fastidioso. Los crashes se arreglan el primer día. Estos eran silenciosos, salían con exit 0 o decían ok, y se habrían quedado ahí viéndose confiables.
Solo los encontré porque corrí las skills en un repo real y luego traté de romper mi propia evidencia. Inténtalo antes de decirle a alguien que tu tooling de agentes funciona. La suite está en github.com/luci-efe/skills, y extractos de las corridas de /compass, /proof y /relay están en los ejemplos.
npx skills@latest add luci-efe/skills
Fernando Ramos, co-CEO de Agentic Engineering. Más en ferramos.com.