La migración de Bun de Zig a Rust tomó 11 días y 64 agentes en paralelo

La mayor reescritura escrita por agentes publicada hasta ahora en producción, y lo interesante son las regresiones que dejó pasar

|6 min de lectura0
Ferris, the Rust programming language mascot, at the Rust assembly during the 38C3 conference — Bun's runtime now compiles as Rust rather than Zig.
Ferris, the Rust programming language mascot, at the Rust assembly during the 38C3 conference — Bun's runtime now compiles as Rust rather than Zig.

Bun, el entorno de ejecución, empaquetador y gestor de paquetes de JavaScript, ya corre sobre Rust en lugar de Zig, y la migración que lo llevó hasta ahí tomó 11 días de flujos de trabajo con agentes bajo supervisión continua, en vez del año que su creador había presupuestado para ingenieros humanos. Jarred Sumner documentó el proceso en detalle y, con Bun v1.4 ya en circulación —Claude Code y la beta de Compute de Prisma funcionan sobre él—, hay suficiente evidencia en producción para preguntar cuánto cuesta realmente confiar en un millón de líneas de código de sistemas escrito por máquinas.

Puntos clave

  • Las 535.496 líneas de Zig de Bun repartidas en 1.448 archivos fueron migradas por unos 50 flujos de trabajo de Claude Code, distribuidos en cuatro árboles de trabajo de git que ejecutaban 16 instancias de agente cada uno, con picos de cerca de 1.300 líneas por minuto y 695 commits en una sola hora.
  • Cada agente implementador estuvo acompañado por dos revisores adversarios que solo veían el diff y recibían la instrucción de asumir que el código estaba mal.
  • Bun v1.4.0 corrige 128 errores que todavía se reproducen en la v1.3.14, la última versión en Zig, mientras que el rendimiento de HTTP mejoró apenas entre un 2 y un 5 por ciento.

Qué hizo revisable un diff de un millón de líneas

La condición previa fue una suerte que Sumner había acumulado años antes: la batería de pruebas de Bun está escrita en TypeScript, así que valida el comportamiento sin importarle qué lenguaje implementa el entorno de ejecución por debajo. Eso le dio a la migración un oráculo fijo con más de un millón de aserciones, inalterado de principio a fin. Una reescritura con pruebas escritas en el lenguaje de origen no habría tenido ese anclaje.

La segunda decisión fue estructural. En lugar de que un solo agente escribiera y revisara su propio trabajo, Sumner separó los roles: un implementador, dos o más revisores adversarios en ventanas de contexto distintas que recibían únicamente el diff, y después un corrector aparte que aplicaba los hallazgos. Su razonamiento declarado es conductual antes que técnico: el modelo que escribió el código quiere verlo fusionado, exactamente igual que un autor humano, así que el revisor tiene que ser otra instancia con otra instrucción. Entre los ejemplos publicados hay un Box<uv::Pipe> liberado mientras libuv todavía retenía el puntero, un unwrap_or de evaluación anticipada que provocaba pánico con un color-mix() de CSS válido, y una conversión de timespec que generaba nanosegundos negativos para marcas de tiempo de archivos anteriores a 1970. Los tres compilaban sin una sola advertencia.

Tercero, cuando la salida fallaba, la corrección se aplicaba al bucle, no al artefacto. Los agentes se pisaron entre sí con git stash a los dos minutos de la primera ejecución completa; la respuesta fue reescribir las instrucciones del flujo de trabajo en vez de reparar los commits dañados. Unas tres horas de planificación produjeron un PORTING.md que mapeaba modismos de Zig a Rust y un LIFETIMES.tsv que registraba el tiempo de vida previsto de cada campo de estructura, ambos sometidos a revisión adversaria antes de migrar una sola línea.

Las regresiones que compilaron limpias

Lo que se coló enseña más que lo que se atrapó. Sumner cuenta que la mayoría de las regresiones vino de construcciones que se ven idénticas en los dos lenguajes y se comportan distinto. El assert de Zig es una función, así que su argumento se evalúa en todas las compilaciones; el debug_assert! de Rust es una macro que borra la expresión entera en la versión de lanzamiento. Un efecto secundario que vivía dentro de esa aserción —insertar un archivo en el grafo de recarga en caliente— dejó de ejecutarse en silencio en las compilaciones de lanzamiento y rompió el refresco rápido de React mientras las compilaciones de depuración seguían en verde.

Las demás siguieron la misma forma. Una función auxiliar que ignoraba discretamente un byte impar sobrante se migró a bytemuck::cast_slice, que en ese caso provoca pánico, y el proceso se caía ante una marca de orden de bytes UTF-16. Una constante de relleno olvidada en 64 bajó el techo de nombres de archivo internados de 8,4 millones a 270.272, un límite que los proyectos reales alcanzan. El formateador de marcadores de color de Bun perdió la evaluación en tiempo de compilación de Zig y empezó a reescribir marcadores dentro de los argumentos sustituidos. InfoQ contabiliza 19 regresiones semánticas de ese tipo, junto con 11 rondas de revisión de seguridad y 15 solicitudes de cambios surgidas del fuzzing continuo del analizador sintáctico. Ninguna fue una falla de seguridad de memoria: el verificador de préstamos hizo su trabajo. Fueron fallas de significado, la categoría que ningún compilador detecta.

Qué compró realmente la reescritura

Las cifras de rendimiento son modestas y se informan con honestidad: el rendimiento de HTTP sube entre un 2 y un 5 por ciento, y un vite build pasa de 1,69 a 1,65 segundos. El retorno real fue la disciplina de memoria. El Drop de Rust ejecuta la limpieza de forma automática allí donde el defer de Zig había que escribirlo en cada punto de llamada, y una prueba que empaqueta el mismo proyecto 2.000 veces en un solo proceso —que en la v1.3.14 filtraba unos 3 MB por compilación, sin límite— ahora se estabiliza. El tamaño del binario cayó cerca de un 20 por ciento en Linux y Windows al combinar la migración con optimizaciones del enlazador y el recorte de ICU. Claude Code usa la compilación en Rust desde la v2.1.181 de junio; el arranque en Linux ganó un 10 por ciento de velocidad y, como dice Sumner, casi nadie lo notó.

La objeción del creador de Zig

Andrew Kelley, autor de Zig, publicó una réplica incisiva en la que sostiene que el planteamiento desvía la atención: los errores se eliminan dedicándoles recursos de ingeniería, no eligiendo entre una guía de estilo y una característica del lenguaje. Su pregunta más afilada apunta a la consistencia: si la batería de pruebas de Bun no bastaba para detectar errores en el código Zig, cuesta ver por qué debería bastar para validar un millón de líneas de Rust generado y sin revisión humana.

Es una objeción legítima, y la respuesta honesta es que la batería no era el único control: encima se apilaron la revisión adversaria, Miri en la integración continua, LeakSanitizer y fuzzing las veinticuatro horas. Si ese conjunto sustituye la comprensión humana del código es justamente lo que sigue sin ponerse a prueba.

Por qué vale la pena seguir este caso

Las cifras de costo que publicó Sumner —unos 165.000 dólares a precios de API, a partir de 5.900 millones de tokens de entrada sin caché y 690 millones de tokens de salida antes de la fusión— vuelven a poner precio a una decisión que solía ser prácticamente permanente. Elegir lenguaje para una base de código madura era una puerta de un solo sentido; ahora es una partida presupuestaria. Anthropic, que adquirió Bun en diciembre de 2025 y emplea a Sumner, tiene un interés evidente en esa conclusión, y este es uno de varios reescrituras ejecutadas por agentes publicados este año. La pregunta abierta es el mantenimiento: una base de código que ningún humano ha leído de principio a fin igual tendrá que ser ampliada, depurada y razonada por personas durante años. Bun, con 22 millones de descargas mensuales de su CLI, es donde la industria lo averiguará.

Preguntas frecuentes

¿Una IA escribió todo el código Rust de Bun sin supervisión?

No. Sumner vigiló los flujos de trabajo durante los 11 días, leyó las salidas a mano y editó el bucle una y otra vez cuando los agentes producían malos resultados. También revisó la migración comprobando que los revisores adversarios estuvieran detectando divergencias reales, y leyó porciones sustanciales del Zig y del Rust en paralelo.

¿Por qué la migración tomó 11 días si los informes hablan de cuatro meses?

Los 11 días cubren la migración en sí, desde el arranque hasta que la batería de pruebas completa pasó en todas las plataformas. La cifra mayor refleja el tiempo transcurrido a través de validaciones adicionales y el lanzamiento: el texto apareció en julio de 2026 y la versión estable Bun v1.4.0 llegó en agosto.

¿Queda algo de Zig en Bun?

No. Bun v1.3.14 fue la última versión en Zig y la v1.4.0 es la primera en Rust. Cerca del 20 por ciento de Bun sigue siendo C++, incluidas dependencias embebidas como JavaScriptCore y uWebSockets, que la reescritura no tocó.

¿Qué te parece este artículo?

SJ
Cargando...

Artículos relacionados

Perplexity dejó que cientos de agentes escribieran su base de datos. El permiso para desplegar siguió siendo humano
Developer Tools

Perplexity dejó que cientos de agentes escribieran su base de datos. El permiso para desplegar siguió siendo humano

Perplexity sustituyó DynamoDB por CobbleDB, un almacén de 40.000 líneas de Rust levantado en dos meses por dos ingenieros y cientos de agentes sin permiso para desplegarlo.

Seung Junghace 4 días
Unos investigadores llegaron al repositorio interno de OpenAI por un fallo de imágenes en un foro
Developer Tools

Unos investigadores llegaron al repositorio interno de OpenAI por un fallo de imágenes en un foro

Hacktron AI encadenó un desbordamiento en libheif con una falla del SSO de OpenAI para alcanzar cuentas de Codex de empleados y el monorepo openai/openai. Ambos fallos ya están corregidos.

Seung Junghace 3 días
832.378 líneas de Rust en 14,5 semanas: una reescritura dirigida por agentes
Developer Tools

832.378 líneas de Rust en 14,5 semanas: una reescritura dirigida por agentes

GitHub convirtió 430.000 líneas de TypeScript en 832.378 líneas de Rust en 14,5 semanas con agentes de programación. La memoria cayó de 1.383MB a 126MB.

Seung Junghace 3 días
Claude Code Projects vuelve como un coordinador que ejecuta hilos en la nube en paralelo
Developer Tools

Claude Code Projects vuelve como un coordinador que ejecuta hilos en la nube en paralelo

El rediseño de Claude Code Projects coloca un coordinador por encima de los hilos de trabajo, cada uno una sesión completa en la nube con su rama y memoria compartida.

Seung Junghace 4 días
Delta, de Zed, reemplaza los pull requests por hilos con agentes
Developer Tools

Delta, de Zed, reemplaza los pull requests por hilos con agentes

Delta, de Zed, cambia el pull request por un hilo compartido donde agentes y revisores trabajan desde el mismo contexto. En su propio repositorio los PR ya están apagados.

Seung Junghace 12 horas
Los reparadores con LLM rompieron código que funcionaba diez veces más a menudo de lo que arreglaron el defectuoso
Developer Tools

Los reparadores con LLM rompieron código que funcionaba diez veces más a menudo de lo que arreglaron el defectuoso

Un estudio en arXiv midió un bucle de reparación con LLM dañando programas correctos a 0,261 y arreglando los defectuosos a 0,023, y halló la dirección interna que lo impulsa.

Seung Junghace 8 días