¡Hola Devs! El secreto sucio del vibe coding
Le pides un prompt al agente, y en 30 segundos tienes una UI hermosa. Luego pides una feature más… y la app se cae a pedazos sin hacer ruido. No con un crash — con una falla conductual silenciosa.
El caso clásico: pides un cupón de descuento en tu e-commerce. El agente crea el input, el botón Aplicar, el toast de éxito. Escribes SAVE20, la pantalla muestra "¡Descuento aplicado!" — y el nuevo total nunca se persistió, nunca se renderizó, nunca se escribió en ningún lado. La interfaz te está mintiendo. 😱
Esta es la parte que nadie menciona en el hype del vibe coding. La falla no se ve. Para encontrarla tienes que clickear por todos lados, leer logs y, al final, leer el código generado — lo cual destruye por completo la promesa de no leer código.
Por qué lo obvio no te salva
- LLM como juez: pedirle al agente que se debuggee a sí mismo da alucinaciones con mucha confianza. Los modelos de frontera se pierden en edge cases y no ven el flujo entre handlers.
- Tests unitarios: escribes más código para revisar código generado. Quien no programa no puede hacerlo, y casi nunca cubre la integración UI → backend.
- Análisis estático a mano: es determinista y preciso, pero la curva de aprendizaje es brutal — tendrías que escribir queries CodeQL tú mismo.
Hay un cuarto camino, y es de lo que va este post. ¡Vamos a darle! 🚀

FlowCheck: expresa la intención en la UI, verifica en el código
FlowCheck es un lenguaje de restricciones más un pipeline de análisis estático. La idea central: describes el comportamiento clickeando tu propia app, y la herramienta compila eso en queries CodeQL contra el código generado.
Paso 1 — Apunta a lo que importa
Le pasas el path de tu app. FlowCheck la abre en una pestaña con un overlay:
Cuando hago [acción], se actualizan estos componentes: [componente].
Clickas los elementos reales de la UI — el input del cupón, el total, la capa de storage — igual que interactuarías con tu app de todos modos.
Paso 2 — La restricción se vuelve formal
El template compila a una restricción probabilística:
P(evento | condición) = [0, 1]
Léelo así: la probabilidad de que ocurra el evento, dada la condición, es 1 (siempre) o 0 (nunca). Para el bug del cupón:
P(w(total) | A(promo-input)) = 1
O sea: cada vez que se aplique el cupón, el total tiene que escribirse.
Paso 3 — Compilando a CodeQL
FlowCheck parsea la AST de la restricción, extrae la acción, el tipo de evento (ej: escritura) y el elemento objetivo. Luego mapea esos componentes de UI a sources y sinks en la base de datos relacional de CodeQL sobre tu código, y emite dos checks:
path_exists // ¿existe ALGÚN camino alcanzable de la acción a la escritura?
all_paths_write // ¿la escritura ocurre en TODO camino de ejecución desde la acción?
El segundo es el killer. La mayoría de las fallas silenciosas no son "no existe camino" — son "existe en el branch feliz, pero no en el condicional".
Paso 4 — Verificación determinista
CodeQL corre las queries. Si una restricción se viola, FlowCheck te dice qué aspecto falló y las líneas exactas donde se rompe el flujo. Sin modelo en medio, sin alucinación, cero falsos positivos en la evaluación de los autores.
Los números
Armaron cuatro apps inspiradas en Amazon, Twitter, Airbnb y Slack usando Claude Code, inyectaron 30 bugs sutiles de flujo de datos y escribieron restricciones para cada uno.
| Método | Bugs atrapados (de 30) |
|---|---|
| FlowCheck | 30 / 30 (100%) |
| Claude Opus 4.7 (mejor prompt) | 26 / 30 (87%) |
| DeepSeek V3 | por debajo |
| Gemini Pro | por debajo |
El hallazgo más interesante: agregar detalle al prompt no siempre ayuda. Con más contexto, los modelos leen el código más a fondo — y luego se vuelven más dispuestos a confiar en él, justificando bugs como diseño intencional en vez de señalarlos. Es un modo de falla que ningún prompt engineering arregla.
Los modelos fallaron consistentemente en flujos entre handlers. En el clon de Amazon, la acción "aplicar cupón" limpiaba el resumen del carrito mientras el handler de checkout todavía intentaba leerlo. Como ningún handler referenciaba al otro, el modelo los evaluó aislados y nunca trazó el flujo entre ellos.

Dónde tiene límites este enfoque
Seamos honestos con las fronteras, porque el paper también lo es.
- La cobertura de restricciones es tuya. FlowCheck atrapa el 100% de las fallas objetivo — las que se te ocurrió expresar. Un bug en un comportamiento que nunca especificaste es invisible para la herramienta.
- Solo forma de flujo de datos. El pipeline está armado sobre source → sink. Un error puramente lógico (descuento mal calculado, off-by-one en paginación) no es violación de flujo y no se atrapa.
- Sesgo al ecosistema JS/TS. El soporte de CodeQL es más fuerte en apps web JS/TS. Si tu app tiene backend pesado en Python o Go, el mileage varía.
- Fricción de setup. Todavía tienes que correr la herramienta, apuntarla a un build y dejar que CodeQL indexe el código. No es una extensión del navegador de un click.
Tip práctico para tu flujo
No lo veas como "reemplazar leer código". Velo como protección de regresión para la intención. Escribe cinco restricciones para los flujos que te cuestan dinero en silencio — checkout, auth, persistencia, estado de pago — y córrelas después de cada iteración del agente. Ahí está el ROI.
Si te gusta pensar en cómo se comportan los pipelines generados por IA a escala, la misma lección aplica a infraestructura: verifica el flujo de datos, no la vibra. Una buena lectura complementaria es este deep dive sobre escalar pipelines de procesamiento de media en Netflix, donde el mismo principio — instrumenta el flujo, no confíes en la superficie — aparece en un contexto muy distinto.
Y si quieres ver qué pasa cuando la capa de cómputo se vuelve drásticamente más rápida, vale la pena checar este análisis de Presto acelerado por GPU en NVIDIA GB200 NVL72 — analytics más rápido hace el loop de verificación más corto, no opcional.

Conclusión
El vibe coding no se va a ir, y las fallas silenciosas tampoco. La jugada ganadora no es "confiar más en el agente" ni "leer cada línea" — es hacer que la intención sea verificable por máquina. El aporte de FlowCheck es demostrar que un lenguaje de restricciones a nivel de UI puede compilar a análisis estático determinista y ganarle a los modelos de frontera en su propio juego.
Qué estudiar después
- Fundamentos de CodeQL — incluso un entendimiento superficial de taint tracking source/sink ya te hace mucho mejor razonando sobre código generado.
- Property-based testing — la misma filosofía (expresa invariantes, deja que la máquina encuentre violaciones) aplicada en runtime en vez de análisis estático.
- Especificación de restricciones para no-programadores — área de investigación abierta, y es el cuello de botella real para que el vibe coding se vuelva mainstream.
El paper completo y el repo están abiertos — el estudio es la 근거자료 detrás de todo lo de arriba, y el repo acepta stars e issues. 🔥