Tu Stack de Programación Vibes No Tiene Cordón Andon. Por Eso Se Rompe.

9 min read

Hasta ahora, elegías un lenguaje de programación basándote en lo que sabías, lo que sabía tu equipo, o lo que requería el proyecto. Python para scripts de datos, Go para servicios backend, C o ensamblador para drivers. La lógica era simple: un humano cómodo con un lenguaje es un humano que entrega.

Esta lógica está muerta.

Bun reescribió 960,000 líneas de Zig a Rust en 6 días usando Claude como agente principal. 1,009,257 líneas añadidas, 6,755 commits, 99.8% de las pruebas existentes pasando. El resultado: 13,044 bloques unsafe en el Rust generado por IA, contra 73 en uv, el gestor de paquetes Python de Astral (350,000 líneas de Rust escrito a mano, para comparar). El compilador de Rust dijo que sí a todo. Los humanos dijeron que no. 13,044 veces. La diferencia no fue el agente. Fue el cordón andon.

El humano ya no escribe código. Describe, y el agente escribe. Claude Code, Cursor, Copilot Workspace (el wrapper no importa). El agente no encuentra intimidante Rust. No necesita 3 años para internalizar el borrow checker. Escribe en cualquier lenguaje a la misma velocidad, con la misma indiferencia.

Entonces cuando empiezas un nuevo proyecto, la pregunta cambia. No qué lenguaje conoces sino ¿qué lenguaje le dice al agente qué hizo mal, lo suficientemente rápido para detenerlo antes de que 500 líneas más se acumulen encima del error?

Ilustración de panel dividido comparando trabajador de oficina frenético rodeado de mensajes de error versus desarrollador calmado con retroalimentación del compilador en tiempo real
Tu estrategia de debugging: pánico. La estrategia del compilador: prevención. Adivina quién gana.

El CI Lo Llamó Basura

PR #30412 fusionado el 14 de mayo. 1,009,257 líneas de nuevo Rust. 4,024 eliminadas. 2,188 archivos cambiados. 6 días desde el primer commit hasta main. El binario se redujo de 3 a 8 MB. 99.8% de la suite de pruebas pasó en Linux x64.

El CI de GitHub entonces etiquetó automáticamente el PR de eliminación de Zig como "ai slop." Nadie configuró esa regla manualmente.

La discusión en Hacker News llegó a 742 comentarios, 667 puntos. La prensa tech cubrió el número que hace un buen titular: 1 millón de líneas en 6 días. Lo que tuvo menos cobertura fue la nota estructural: 13,044 bloques unsafe en el Rust generado por IA, contra 73 en uv, un proyecto Rust comparable de 350,000 líneas escrito completamente a mano. Aproximadamente 178x más bloques unsafe en total. La densidad por línea de código resulta en unas 62x.

El compilador de Rust aprobó cada una de esas líneas.

Jarred Sumner, quien construyó Bun, confirmó que el equipo "no ha estado escribiendo código nosotros mismos por muchos meses." El cambio de Zig a Rust fue parcialmente forzado: el equipo central de Zig tiene una política explícita de no-contribuciones-IA, que se volvió incompatible con el flujo de trabajo de Bun en el momento que Anthropic adquirió el proyecto en diciembre de 2025. En lugar de pelear con la cultura upstream, el equipo cambió de lenguajes.

Esta no es una reescritura fallida. El código funciona. Es una demostración de lo que pasa cuando generas a velocidad sin el mecanismo de rechazo correcto.

Todos Dicen Rust. Nadie Dice Por Qué

Pregúntale a un dev por qué los agentes deberían usar Rust y obtienes la respuesta de rendimiento. Binarios más rápidos, seguridad de memoria, abstracciones de costo cero. La respuesta no está mal, solo es la razón incorrecta para agentes específicamente.

Rust ha encabezado la encuesta de "lenguaje más amado" de Stack Overflow cada año desde 2016. La encuesta no pregunta si los encuestados son los que realmente lo escriben. Por mucho tiempo "más amado" y "más usado" fueron listas muy separadas (el borrow checker hará eso a las curvas de adopción). Los agentes no tienen curvas de adopción. No tienen sentimientos sobre el borrow checker. Tienen un bucle de compilación.

Los números de benchmark en runtime no cambian el bucle de retroalimentación del agente. Un binario de Rust corriendo 40% más rápido que Go en tiempo de ejecución es ortogonal a si el agente escribe mejor código durante la generación. La velocidad del binario no afecta qué tan rápido el agente detecta errores.

Lo que importa es qué tan rápido, y qué tan precisamente, el entorno le dice al agente que la cagó.

La sintaxis es válida, la semántica está rota, y no hay señal hasta que algo falla en runtime. Para entonces, 3 funciones más han sido escritas encima de la suposición rota. La cadena nunca se detuvo. Rust le dice al agente inmediatamente: falla la compilación, mensaje de error, ubicación, desajuste de tipos, camino a la corrección. El agente lee, corrige, vuelve a ejecutar.

El Cordón Andon

En las fábricas de Toyota en los años 50, instalaron un cordón que corría a lo largo de cada línea de producción. Cualquier trabajador podía jalarlo en cualquier momento. Toda la línea se detenía. Llegaba una pieza defectuosa, se jalaba el cordón, se arreglaba el problema antes de que el siguiente componente se adjuntara encima.

Lo llamaron el cordón andon. Una parada de 2 minutos era más barata que 40 minutos de retrabajo al final de la línea. La restricción hizo que el sistema general fuera más rápido, no más lento.

El compilador es el cordón andon para el agente. El bucle funciona así: el agente escribe código, el compilador lo verifica, el compilador o deja pasar el código o jala el cordón y emite un diagnóstico estructurado. El agente lee el diagnóstico, arregla el problema, y vuelve a ejecutar. Sin el cordón, el agente escribe 500 líneas encima de una suposición rota y el problema surge en runtime, 3 sesiones después, en un stack trace que apunta a un síntoma en lugar de la causa. Con el cordón, el problema surge en segundos, en output del compilador lo suficientemente específico para que el agente actúe inmediatamente.

Esta es la variable real en la calidad del código asistido por IA: no qué modelo usas, no qué tan cuidadosamente haces el prompt, sino si el entorno jala el cordón lo suficientemente rápido y con suficiente precisión diagnóstica para que el agente pueda autocorregirse antes de que la deuda se acumule.

(Completamente fuera de tema: he estado viendo viejos dibujos animados de Hanna-Barbera con mi hijo esta semana y no puedo dejar de pensar en cómo el estilo de animación de presupuesto limitado se convirtió en una estética que la gente aún imita mucho después de que desapareciera la restricción presupuestaria que lo creó. Un límite de producción cableado en un medio. Nada que ver con compiladores, solo cómo funciona mi cerebro.)

La riqueza del cordón importa tanto como su existencia. Un compilador que dice "error en línea 42" le da al agente una ubicación. Un compilador que dice "estás tratando de multiplicar Option<&u32> por u32 en línea 42, llama .unwrap() o haz match en el Option primero" le da al agente una ubicación, ambos tipos, lo que se intentó, y un camino de reparación. El agente no necesita inferir nada. Lee, aplica, vuelve a ejecutar.

Este es el mismo principio que explica por qué los CLIs vencen a MCP para agentes IA. El entorno que eliges determina cuánta señal regresa cuando algo se rompe. La elección de lenguaje es esa misma decisión a un nivel más bajo.

De Sin Cordón a Cordón Completo

Mismo escenario a través del espectro. Tienes un diccionario. Falta una clave. Tratas de usar el valor en aritmética.

Python: sin cordón.

data = {"price": 100}
total = data["quantity"] * data["price"]

KeyError: 'quantity' golpea en runtime, posiblemente 3 funciones downstream, posiblemente en producción. El agente tuvo cero señal en tiempo de generación. La cadena corrió. La pieza estaba defectuosa. Nadie jaló el cordón porque no había cordón que jalar.

TypeScript con noUncheckedIndexedAccess: cordón parcial.

const data: Record<string, number> = { price: 100 };
const quantity = data["quantity"]; // type: number | undefined
const total = quantity * data["price"];
// TS2532: Object is possibly 'undefined'

Atrapado antes de la ejecución. Mensaje corto, accionable: ubicación y restricción de tipo. TypeScript no ayudará con layout de memoria o thread safety, pero para lógica de capa de aplicación atrapa esta clase de error de manera confiable.

Go: cordón sintáctico, sin cordón semántico.

data := map[string]int{"price": 100}
total := data["quantity"] * data["price"]
fmt.Println(total) // imprime 0, sin error

Go se rehúsa a compilar imports no usados o variables no usadas. Higiene real. Pero las búsquedas de map en claves faltantes devuelven el valor cero silenciosamente. data["quantity"] devuelve 0. total es 0. La función continúa. Algo downstream obtiene un número incorrecto, y el mensaje de error surge 3 funciones después apuntando a un síntoma. Stack Overflow llama a esto "así es como funciona Go." Tu agente lo llama un bug.

Go compila en unos 2 segundos en una codebase típica de servicio. Rust toma 30 segundos o más en código comparable. Creo que TypeScript strict mode realmente supera a Go para la mayoría de casos de uso de servicios web, pero podría estar equivocado en eso para equipos con requerimientos de concurrencia pesados. El cordón de Go es real, solo es estrecho: la estructura se atrapa, la semántica no.

Rust: cordón completo.

use std::collections::HashMap;

let mut data = HashMap::new();
data.insert("price", 100u32);

let quantity = data.get("quantity"); // type: Option<&u32>
let total = quantity * data.get("price").unwrap_or(&0);
error[E0369]: cannot multiply `Option<&u32>` by `u32`
  --> src/main.rs:8:21
   |
8  |     let total = quantity * data.get("price").unwrap_or(&0);
   |                 ^^^^^^^^
   |                 Option<&u32>
help: use `Option::unwrap_or`, `Option::unwrap_or_else`,
      or match to handle the None variant before multiplying

Ubicación, ambos tipos, lo que se intentó, y un camino de reparación (4 líneas). El agente lee, aplica, vuelve a ejecutar. El compilador de Rust suena como si tuviera un interés personal en tu éxito, y para un agente, eso es exactamente lo que quieres de una herramienta.

Ada: cordón máximo.

Ada fue diseñado en 1983 para que los errores no mataran gente en sistemas embebidos militares. Variables no inicializadas, desbordamiento de enteros, violaciones de límites de array, conversiones implícitas de tipos: todo atrapado en tiempo de compilación, por defecto, con diagnósticos lo suficientemente precisos para sentirse confrontacionales. El rover de Marte ejecuta Ada. El telescopio espacial James Webb ejecuta Ada. Los compiladores en cuestión nunca han preguntado si un humano tenía ganas de lidiar con esto hoy.

La industria rechazó en gran medida Ada para uso general de software porque la estrictez era demasiado dolorosa para desarrolladores humanos. Demasiada ceremonia. Demasiadas cosas requiriendo anotación explícita.

Ada: demasiado estricto para humanos. A los agentes no les importa.

Velocidad Sin Cordón Es Deuda

Los cinturones de seguridad se volvieron obligatorios cuando los autos se volvieron rápidos, no cuando se volvieron lentos. Los circuit breakers se añadieron a los mercados financieros después de que el trading algorítmico empezara a ejecutar miles de órdenes por segundo sin nada que los detuviera. El patrón: la velocidad de generación necesita infraestructura de rechazo a escala correspondiente.

Los 13,044 bloques unsafe en la reescritura de Bun no son una falla de la generación de código de Claude. Son los lugares donde el agente se saltó el cordón deliberadamente, usando la palabra clave unsafe de Rust para bypasear el borrow checker en secciones semánticamente complejas. El cordón estaba ahí. El agente eligió desconectarlo en esos puntos. La deuda es estructural, auditable, y el equipo de Bun trabajará a través de ella. Pero existe porque la velocidad de generación superó el bucle de retroalimentación.

Tu stack de vibe coding ejecuta el mismo patrón a menor escala. Lo que los tutoriales de Claude Code omiten sobre producción incluye estas decisiones a nivel de entorno: qué compilador, qué configuraciones de estrictez, qué sistema de tipos (establecido antes del primer prompt).

Para un SaaS de Next.js: TypeScript con strict: true y noUncheckedIndexedAccess habilitado. Atrapa la clase de errores que los agentes generan más a menudo en capa de aplicación.

Para servicios backend o CLIs: Go o TypeScript dependiendo de las restricciones de rendimiento. El bucle de compilación de 2 segundos de Go hace la iteración rápida incluso con garantías semánticas más débiles.

Para software de sistema, runtimes edge, cualquier cosa que toque memoria directamente: Rust. No por el rendimiento. Por el compilador.

Para software de guía de misiles: Ada. (Nadie pregunta, pero la respuesta es Ada.)

2 prompts para la próxima vez que empieces un proyecto o audites una codebase existente:

Estoy empezando un proyecto donde agentes IA escribirán la mayoría del código.
Quiero el lenguaje que le dé al agente la retroalimentación más rica en tiempo de compilación
cuando cometa errores. Ignora mi familiaridad personal con el lenguaje.
Tipo de proyecto: [saas app / CLI tool / system service / otro].
Recomienda un lenguaje y su configuración de compilador/tipos más estricta,
optimizada para calidad de señal de error del agente, no comodidad del desarrollador humano.
Tengo una codebase de [lenguaje] donde agentes IA generan la mayoría del código.
¿Qué flags de compilador, configuraciones de type checker, y reglas de linter debería
habilitar para atrapar más errores en tiempo de compilación antes de que lleguen a runtime?
Dame una lista priorizada desde más fácil de habilitar hasta más agresivo.

Uso Claude Code todos los días. Bun es el runtime debajo de él. No sabía hasta la semana pasada que este runtime corre en 1M líneas escritas por Claude en 6 días, con 13,044 bloques unsafe esperando auditoría.

No me asusta. Las pruebas pasan. Jarred Sumner no es el tipo que dejaría una granada viva en prod.

Lo que me hizo hacer es mirar mis propios pipelines. Los lugares donde dejé espacio para que el agente generara rápido sin red. TypeScript corriendo sin strict: true, validación de schema sentada en un comentario en lugar de una restricción (en todos lados donde el compilador no jala el cordón, los bugs se acumulan bajo diferentes nombres).

En tu codebase, no aparecen como bloques unsafe. Aparecen como bugs de prod, 6 semanas después.

Fuentes

Este post puede contener enlaces de afiliados. Si haces clic en ellos, podría ganar una pequeña comisión (no te cuesta nada, y me ayuda a seguir enviando artículos de calidad todos los días para tu placer de lectura).