Reescrita em Rust impulsionada por IA do Bun: Um manual de verificação para migração de milhões de linhas de código

Um manual de verificação inspirado na prática assistida por IA do Bun ao migrar de Zig para Rust, abrangendo contratos comportamentais, agentes de codificação isolados, testes diferenciais, testes de fuzzing, revisão de código inseguro, métricas de progresso e lançamento seguro.

发布于 2026年7月12日generalGEO 评分: 07 次阅读
Imagem mostrando o conteúdo da reescrita em Rust impulsionada por IA do Bun. Fundo escuro, à esquerda um avatar de personagem de desenho animado, à direita um ícone de engrenagem do Rust. No centro, em letras grandes, 'Bun’s AI-Powered Rust Rewrite', com 'AI-Powered' em roxo e 'Rust Rewrite' em azul. Abaixo, dois trechos de código: à esquerda, código JavaScript; à direita, código Rust, ambos exemplos de funções processando requisições. A imagem complementa o conteúdo do documento sobre a migração assistida por IA do Bun de Zig para Rust, ilustrando visualmente a aplicação da IA na reescrita em Rust.

Reescrita Impulsionada por IA em Rust da Bun: Um Manual de Verificação para Migrações de Milhões de Linhas

Introdução

A manchete é difícil de ignorar: a Bun supostamente migrou uma implementação importante de Zig para Rust em 11 dias usando um fluxo de trabalho dinâmico com Claude Code. Os relatos publicados descrevem milhares de commits, até 64 agentes Claude, aproximadamente 780.000 linhas de Rust, dois revisores adversariais para cada unidade de implementação, e uma progressão de código que não compilava para uma versão que passou na suíte de testes e foi lançada.

A lição errada é que reescritas de linguagem se tornaram tarefas de um clique. A lição útil é que a produtividade de implementação e a produtividade de verificação são agora problemas de engenharia separados.

Agentes de IA podem gerar código mais rápido do que uma equipe humana consegue lê-lo. Quando isso acontece, a revisão convencional de pull requests não pode mais servir como o principal mecanismo de segurança. As equipes precisam de um sistema que converta uma mudança probabilística massiva em pequenas alegações apoiadas por evidências verificáveis por máquina.

O relatório de produção posterior da Bun tornou isso excepcionalmente concreto. A equipe relatou 19 regressões conhecidas, todas posteriormente corrigidas; 11 rodadas de revisão de segurança; fuzzing contínuo guiado por cobertura em analisadores sintáticos; e cerca de 27.000 linhas de Rust dentro de blocos unsafe em aproximadamente 780.000 linhas no total. Esses fatos não enfraquecem a história da migração. Eles mostram como é o trabalho de migração sério após a demonstração impressionante terminar.

Este guia transforma essa experiência em um manual de verificação reutilizável. O objetivo não é copiar a escala da Bun. É fornecer um método para qualquer migração—portabilidade de linguagens, substituições de frameworks, modernização de APIs, conversões de bancos de dados ou refatorações em todo o repositório—onde agentes de IA de codificação podem escrever mais código do que a equipe pode inspecionar linha por linha de forma responsável.

Principais Conclusões

  • A reescrita da Bun mostra que agentes de IA podem comprimir o tempo de implementação. Não mostra que o tempo de verificação pode ser removido.
  • O ativo transferível é o sistema de migração: contratos de comportamento escritos, mapas de risco, pilotos pequenos, trabalhadores isolados, revisores independentes, portões determinísticos e commits recuperáveis.
  • Compiladores e suítes de teste legadas capturam diferentes classes de falhas. Nenhum deles captura toda incompatibilidade semântica entre linguagens, diferenças no modo de release, regressão de desempenho ou limite de unsafe.
  • Diffs grandes exigem revisão orientada a evidências. Humanos devem inspecionar contratos, hotspots de risco, contraexemplos, lacunas de teste e decisões de implantação, em vez de fingir que cada linha gerada recebe escrutínio igual.
  • As equipes podem adotar o mesmo padrão sem tentar uma reescrita de milhões de linhas: exigir que agentes comprovem comportamento uma fatia de cada vez, e depois conceder autonomia mais ampla apenas após resultados mensurados.

O Que a Bun Realmente Fez—e o Que a Manchete Deixa de Fora

O relato de engenharia começou antes da geração de código em larga escala.

Jarred Sumner supostamente passou cerca de três horas criando PORTING.md, que mapeava padrões recorrentes de Zig para Rust. Um fluxo de trabalho separado analisou campos de estrutura, propôs tempos de vida (lifetimes) do Rust, enviou essas escolhas para dois revisores adversariais e serializou os resultados em LIFETIMES.tsv. Esses artefatos também foram revisados manualmente.

O primeiro

O ensaio de implementação abrangeu três arquivos, não todo o repositório. Para cada arquivo:

  1. Um agente implementou a versão em Rust.
  2. Dois novos agentes revisaram a equivalência comportamental e a conformidade com a documentação de migração.
  3. Outro agente aplicou as correções aprovadas.

Somente após esse piloto o trabalho se expandiu para 1.448 arquivos Zig.

A primeira execução em larga escala falhou. Os agentes compartilhavam um espaço de trabalho e usavam comandos como git stash, git stash pop e git reset --hard. Suas alterações interferiam umas nas outras. O fluxo de trabalho foi então alterado para proibir comandos de coordenação inseguros e usar quatro árvores de trabalho, cada uma com 16 agentes.

Esse detalhe é mais importante do que a taxa máxima de geração de linhas. A codificação paralela é um problema de sistemas distribuídos. Estado compartilhado, escritores conflitantes, operações globais caras, propriedade e recuperação precisam de regras explícitas.

O código gerado não funcionou imediatamente. O Bun usou erros do compilador como uma fila e avançou uma crate de cada vez. Em um ponto, cerca de 16.000 erros do compilador foram atribuídos aos agentes. O loop usou um corretor, dois revisores e um agente de aplicação, ao mesmo tempo que limitava a frequência com que comandos caros como cargo check e operações Git podiam ser executados.

Esta não foi uma tradução mágica. Foi uma convergência em etapas impulsionada por feedback determinístico.

O anúncio do fluxo de trabalho dinâmico da Anthropic relatou que 99,8% do conjunto de testes existente passou no momento da redação inicial, enquanto observava explicitamente que a portabilidade ainda não estava em produção. O artigo posterior do Bun cobriu o trabalho que se seguiu: revisões de segurança, fuzzing, regressões de produção, correções semânticas e redução de código inseguro.

Lidos em conjunto, as fontes descrevem dois marcos diferentes:

  • Implementação completa o suficiente para mesclar
  • Evidência completa o suficiente para executar com segurança

Termos que Você Precisa Conhecer: Portabilidade, Oráculo, Teste Diferencial e Superfície Insegura

Essas definições são importantes porque uma equipe não pode verificar uma migração até concordar sobre o que as evidências devem provar. Elas também separam a declaração de confiança de um agente de um resultado verificável externamente.

Portabilidade

Uma portabilidade reimplementa software em uma nova linguagem, tempo de execução, plataforma ou estrutura, preservando um conjunto definido de comportamentos.

"Preservar comportamento" precisa de um limite. Uma portabilidade pode preservar APIs e saídas públicas enquanto altera intencionalmente a arquitetura interna, as características de desempenho, as mensagens de erro ou os casos extremos não suportados.

Contrato de Comportamento

Um contrato de comportamento é uma lista explícita de propriedades que a nova implementação deve preservar.

Pode incluir:

  • Entradas e saídas
  • Comportamento de erro
  • Ordenação
  • Efeitos colaterais
  • Semântica de concorrência
  • Limites de recursos
  • Plataformas suportadas
  • Orçamentos de desempenho
  • Requisitos de observabilidade

O código existente contém comportamento, mas nem todo comportamento existente é intencional. O contrato separa os requisitos de acidentes históricos.

Oráculo de Teste

Um oráculo de teste determina se uma saída está correta.

Uma asserção de teste unitário é um oráculo. Uma implementação de referência, especificação de protocolo, arquivo dourado, invariante de banco de dados ou regra elaborada por humanos também pode atuar como um oráculo.

A orientação da Anthropic sobre execução de longa duração

A codificação científica enfatiza que o trabalho autônomo precisa de referências, metas mensuráveis ou suítes de teste para que os agentes possam determinar se estão progredindo.

Teste Diferencial

O teste diferencial envia as mesmas entradas para as implementações antiga e nova e, em seguida, compara os resultados observáveis.

É especialmente útil quando a implementação antiga é confiável, mas não existe uma especificação formal completa. A concordância não prova que ambas as implementações estão corretas, mas a discordância cria uma fila de investigação precisa.

Teste Metamórfico

O teste metamórfico verifica relações entre múltiplas execuções quando é difícil escrever resultados esperados exatos.

Os exemplos incluem:

  • Serializar e analisar um valor deve preservá-lo.
  • Reordenar entradas independentes não deve alterar um resultado do tipo conjunto.
  • Executar uma migração idempotente duas vezes não deve alterar o estado na segunda execução.
  • Tentar novamente a mesma chave de idempotência não deve produzir um efeito colateral duplicado.

Superfície Insegura

A superfície insegura é o código onde as garantias normais da linguagem alvo são enfraquecidas ou contornadas.

Em Rust, unsafe pode ser necessário nos limites de FFI com C ou C++, dentro de alocadores personalizados ou para integração de runtime de baixo nível. A contagem bruta não é um veredito. A equipe precisa de propriedade, invariantes, testes e um plano explícito para cada limite inseguro.

Defeito Escapado

Um defeito escapado é um bug induzido pela migração descoberto após a barreira que deveria tê-lo detectado — após merge, implantação canário, teste de release-candidate ou lançamento em produção.

Defeitos escapados são feedback sobre o sistema de verificação, não apenas sobre a implementação.

A Cadeia Causal: Por que uma Geração Mais Rápida Exige uma Verificação Mais Forte

O paralelismo de agentes muda a economia da implementação. Se 64 trabalhadores traduzem arquivos ao mesmo tempo, o tempo de geração de código pode diminuir drasticamente. O grafo de dependências, a semântica da linguagem alvo e o ambiente de teste compartilhado não desaparecem. A taxa de transferência simplesmente move o gargalo para downstream.

Gargalo 1: Integração

Arquivos individualmente razoáveis podem falhar quando compilados juntos.

Os cerca de 16.000 erros de compilador e dependências cíclicas de crates do Bun ilustram a lacuna entre a tradução local e a consistência global. O compilador é um oráculo determinístico excelente para tipos, propriedade, tempos de vida, nomes e algumas propriedades de fluxo de controle. Ele não é um oráculo para o comportamento do produto.

Gargalo 2: Equivalência Semântica

O Bun documentou bugs onde o código parecia quase idêntico entre linguagens, mas se comportava de forma diferente.

Os exemplos incluíam:

  • Efeitos colaterais colocados dentro de debug_assert! do Rust desaparecendo em builds de release, enquanto uma asserção Zig comparável ainda avaliava seus argumentos.
  • Uma expressão ansiosa unwrap_or desencadeando um comportamento que deveria ter permanecido preguiçoso.
  • Semânticas de fatia de bytes e limites diferindo entre implementações.
  • Entradas UTF-16 de comprimento ímpar expondo uma falha.

Essas são exatamente as falhas que a revisão superficial perde, porque o código traduzido parece plausível.

Gargalo 3: Correlação de Revisão

Se o mesmo modelo escreve e revisa uma alteração usando o mesmo contexto e suposições, ele pode reproduzir as

erro original.

A documentação de melhores práticas do Claude Code, da Anthropic, recomenda usar um contexto de revisor novo. O revisor vê a diferença e o padrão sem herdar o raciocínio do autor. A independência não garante a correção, mas reduz o viés de contexto compartilhado.

Gargalo 4: Evidência Operacional

Os testes podem passar enquanto a latência dobra, o uso de memória aumenta, um destino de sistema operacional quebra ou a observabilidade desaparece.

Quanto maior a mudança, maior a probabilidade de a equipe descobrir um requisito violado somente após a implantação. É por isso que um plano de migração deve incluir canários, reversão, comparação de telemetria e um processo que converta cada defeito que escapa em uma nova regra de contrato ou teste.

A conclusão causal é simples:

A IA não elimina o custo da migração. Ela transfere o custo da digitação para a especificação, o design do harness, a revisão de evidências e o controle de implantação.

Uma equipe que ignora essa mudança pode terminar de gerar o código rapidamente e depois passar meses determinando se a reescrita realmente funciona.

Uma Arquitetura de Verificação para Migrações Orientadas por IA

A arquitetura tem quatro planos.

1. Plano de Contrato

O plano de contrato armazena:

  • Comportamento público
  • Promessas de compatibilidade
  • Mudanças intencionais
  • Matriz de plataformas suportadas
  • Orçamentos de desempenho
  • Restrições de segurança
  • Requisitos de observabilidade

Humanos mantêm este plano, e o repositório o versiona.

2. Plano de Execução

O plano de execução contém agentes de implementação isolados.

Cada agente recebe:

  • Uma unidade de migração
  • Arquivos de origem relevantes
  • O contrato aprovado
  • O mapa semântico
  • Ferramentas de escopo restrito
  • Verificações direcionadas

O agente não pode alterar o contrato ou os testes globais. Ele edita apenas seu escopo designado e retorna tanto um commit quanto evidências.

3. Plano de Verificação

O plano de verificação é independente da implementação.

Ele pode:

  • Compilar o candidato
  • Executar testes direcionados e globais
  • Realizar verificações diferenciais entre o antigo e o novo
  • Fuzzear analisadores e limites de protocolo
  • Escanear código sensível à segurança
  • Comparar cargas de trabalho representativas
  • Pedir a novos revisores que busquem contraexemplos

Agentes de verificação podem propor testes, mas a IC determinística decide se um portão é aprovado.

4. Plano de Lançamento

O plano de lançamento controla a integração e a exposição em produção.

Ele:

  • Faz merge na ordem de dependências
  • Produz artefatos reproduzíveis
  • Identifica builds com versões imutáveis ou hashes
  • Executa tráfego sombra sempre que possível
  • Expande canários gradualmente
  • Monitora indicadores de nível de serviço
  • Preserva um caminho de reversão testado

Um orquestrador de IA pode atuar entre esses planos como uma camada de orquestração e evidência. As equipes podem usar tarefas para atribuir fatias de migração, isolar árvores de trabalho, anexar contratos, coletar resultados de testes e exigir revisão antes que o trabalho prossiga.

O limite importante é que a orquestração coordena evidências. Ela não transforma a alegação de sucesso de um agente em permissão de lançamento.

Exemplo de Cenário: Migrando um Serviço de Pagamento de Python para Go

Considere um serviço de pagamento em Python com 120.000 linhas sendo migrado para Go. O objetivo de negócios é reduzir

latência de cauda e simplificar a implantação.

Um prompt perigoso seria:

Reescreva este serviço em Go e faça todos os testes passarem.

Esse prompt deixa indefinidas as semânticas de transação, comportamento de erro, precisão monetária, idempotência e implantação gradual.

Etapa 1: Escrever o Contrato

Para cada endpoint, a equipe registra:

  • Esquemas de solicitação e resposta
  • Regras de autorização
  • Comportamento da chave de idempotência
  • Arredondamento de moeda
  • Semântica de repetição
  • Transações de banco de dados
  • Ordenação de eventos
  • Códigos de erro
  • Requisitos de telemetria

Também marca alterações intencionais, como a remoção de um cabeçalho de depuração específico do Python. A equipe define a plataforma suportada e a matriz de dependências, depois estabelece orçamentos de latência p95 e p99 e um teto de pico de memória.

Etapa 2: Escolher Três Fatias Piloto

A equipe seleciona:

  1. Um módulo puro de formatação de moeda
  2. Um repositório de idempotência com efeitos colaterais de banco de dados
  3. Um endpoint HTTP somente leitura

O primeiro testa a tradução mecânica. O segundo testa transações e concorrência. O terceiro testa a compatibilidade HTTP.

Um agente de implementação cuida de cada fatia. Revisores novatos recebem apenas o contrato, o código-fonte antigo, o diff proposto e os comandos de validação.

Etapa 3: Usar o Serviço Antigo como Oráculo Diferencial

Um corpus sanitizado de requisições históricas é reproduzido em ambas as versões.

As respostas são normalizadas apenas onde o contrato permite diferenças, depois comparadas. Para caminhos de escrita, ambas as implementações são executadas em snapshots descartáveis de banco de dados. As linhas resultantes e os eventos emitidos são comparados.

Testes metamórficos então:

  • Repetem a mesma chave de idempotência
  • Alteram a ordenação inócua de chaves JSON
  • Introduzem variações de temporização de repetição
  • Testam valores monetários limites

Etapa 4: Sombra e Canário do Novo Serviço

Antes que as escritas em produção sejam ativadas, o serviço Go recebe tráfego de sombra com escritas desabilitadas ou redirecionadas para um coletor isolado.

A equipe compara:

  • Distribuições de latência
  • Classificações de erro
  • Chamadas de dependência
  • Formatos de rastreamento
  • Uso de memória
  • Comportamento de eventos

A equipe então envia 1% de tráfego canário de um grupo de comerciantes de baixo risco.

A expansão requer:

  • Zero discrepâncias financeiras inexplicadas
  • Paridade na taxa de erro
  • Latência dentro do orçamento acordado
  • Um teste de reversão bem-sucedido

A implementação ainda pode avançar rapidamente. A segurança vem de transformar "reescrever o serviço" em afirmações observáveis.

Este exemplo também mostra por que o conhecimento de domínio continua essencial. Agentes podem traduzir código, mas especialistas em pagamentos sabem que eventos duplicados, diferenças de arredondamento e comportamento de repetição são requisitos de negócio.

Fase 0: Definir o Contrato de Migração e as Condições de Parada

Antes que qualquer agente edite código, decida o que conta como o mesmo produto.

Inventário:

  • APIs públicas
  • Comportamento da CLI
  • Formatos de arquivo
  • Efeitos de banco de dados
  • Variáveis de ambiente
  • Telemetria
  • Mensagens de erro visíveis ao usuário
  • Plataformas suportadas
  • Características de desempenho

Marque cada propriedade como uma das seguintes:

  • Preservar
  • Alterar intencionalmente
  • Descontinuar
  • Desconhecido

Desconhecidos não são permissão para adivinhar. Eles se tornam tarefas de descoberta.

Execute o sistema antigo, pesquise issues e changelogs, inspecione rastros de produção ou pergunte a mantenedores. Árvore-fonte pré-migração do Bun.

reorganização preservou o histórico do Git por meio de commits apenas de movimentação, tornando a proveniência um requisito intencional, e não um dano colateral.

Defina condições de parada rigorosas. Interrompa a expansão quando:

  • As taxas de incompatibilidade do piloto excederem o limite.
  • Os trabalhadores modificarem repetidamente testes globais protegidos.
  • A fila de erros do compilador crescer mais rápido do que fecha.
  • O desempenho alvo não atingir o orçamento.
  • Um artefato de reversão não puder ser construído.
  • As evidências estiverem incompletas ou ilegíveis.

A parada protege o projeto do aumento de custos irreversíveis.

O contrato deve ser controlado separadamente da execução. Um agente não deve "corrigir" um teste com falha enfraquecendo o requisito. Alterações no contrato exigem uma emenda revisada por humanos explicando por que o comportamento antigo está obsoleto ou incorreto.

Fase 1: Construir um Mapa Semântico Antes da Geração em Grande Escala

Crie mapeamentos explícitos para padrões comuns, sutis ou perigosos de origem para destino.

Abranja áreas como:

  • Regras de propriedade e tempo de vida
  • Nulidade
  • Exceções e tratamento de erros
  • Estouro de inteiros
  • Cálculos de tempo
  • Codificação de strings
  • Primitivas de concorrência
  • Propriedade do alocador
  • FFI
  • Comportamento de depuração versus versão de lançamento
  • Código específico de plataforma

Os arquivos PORTING.md e LIFETIMES.tsv do Bun serviram a esse propósito.

Seu valor não se limitou a prompts melhores. Eles deram a centenas de trabalhadores uma estratégia semântica compartilhada. Sem esse mapa, cada agente inventa sua própria abordagem de tradução, e a inconsistência se torna um problema de integração.

Peça a agentes independentes para atacar o mapa:

  • Dê a um revisor a semântica da linguagem de origem.
  • Dê a outro os riscos da linguagem de destino.
  • Dê a um terceiro exemplos de código representativos.
  • Exija contraexemplos concretos.

Humanos devem inspecionar as regras de maior risco, especialmente aquelas que envolvem propriedade de memória, concorrência, limites de segurança, persistência e comportamento exclusivo de versão de lançamento.

Versionar o mapa. Cada incompatibilidade recém-descoberta deve atualizar as regras, identificar unidades de migração afetadas e acionar revalidação direcionada.

O mapa semântico é uma especificação viva, não um prompt colado uma vez no início.

Fase 2: Projetar Pilotos Deliberadamente Difíceis

Não escolha apenas os arquivos mais fáceis.

Um piloto útil inclui três formas:

  1. Uma unidade simples e representativa
  2. Uma unidade com muitas dependências
  3. Um ponto crítico semântico

O Bun usou três arquivos para validar o ciclo implementar-revisar-corrigir antes de traduzir 1.448 arquivos. O número exato importa menos do que a gama de modos de falha cobertos.

Meça o processo do piloto, não apenas sua saída:

  • Os trabalhadores respeitaram a propriedade do arquivo?
  • Os commits foram atômicos?
  • Os revisores encontraram defeitos reais ou produziram principalmente ruído?
  • O corretor conseguiu aplicar sugestões sem violar o contrato?
  • A evidência ainda estava legível?
  • Quanto contexto e computação cada unidade aceita consumiu?

Introduza falhas deliberadamente. Adicione uma diferença sutil de modo de lançamento, um dispositivo de teste de caso extremo ou um limite de desempenho e confirme que o sistema de verificação o detecta.

Um mecanismo que passou apenas por exemplos limpos ainda não foi testado.

A expansão deve começar apenas quando o piloto produzir evidências estáveis e repetíveis. Se os prompts, modelos ou políticas de ferramentas mudarem substancialmente depois, execute novamente o pequeno piloto. Fluxo de trabalho

configuração é código de produção e merece testes de regressão.

Fase 3: Distribuir com Isolamento, Propriedade e Commits Atômicos

Crie unidades de migração alinhadas ao grafo de dependências.

A divisão por arquivos é conveniente, mas pode ser o limite errado quando o comportamento atravessa módulos. Atribua um escritor para cada unidade e torne a propriedade legível por máquina. Os trabalhadores podem ler dependências, mas só podem editar seu próprio escopo, a menos que solicitem uma alteração coordenada.

Use worktrees separados, contêineres ou máquinas virtuais efêmeras quando for prático.

A falha do workspace compartilhado do Bun mostra por quê. Restrinja comandos Git destrutivos e comandos globais de build caros para trabalhadores folha. Deixe um coordenador realizar a integração ordenada.

Credenciais de curta duração e listas de permissão de rede reduzem o impacto de injeção de prompt ou exfiltração de dependências. As orientações de sandboxing da Anthropic descrevem limites de sistema de arquivos e rede como bases para uma autonomia mais segura.

Cada unidade aceita deve produzir um commit atômico contendo:

  • Identificador da fonte
  • Regras de contrato aplicáveis
  • Comandos executados
  • Saídas de testes e verificações
  • Resultados do revisor
  • Exceções aprovadas

O Git se torna tanto um mecanismo de coordenação quanto de recuperação.

As orientações da Anthropic para fluxos de trabalho de longa duração recomendam commits significativos e testes antes de cada commit, porque um histórico recuperável impede que uma longa execução de agente se torne um artefato opaco.

Não otimize para linhas por minuto. Otimize para unidades verificadas por hora.

Alta taxa de geração combinada com uma fila de integração crescente é um progresso negativo.

Fase 4: Tratar Erros de Compilador e Testes como Filas, Não como Prova

A saída do compilador cria trabalho estruturado.

Agrupe erros por unidade de propriedade ou camada de dependência, remova cascatas duplicadas e corrija causas raiz antes dos sintomas folha.

Proíba atalhos a menos que o contrato os permita explicitamente, incluindo:

  • Stubs vazios
  • Resultados ignorados
  • Atributos allow amplos
  • Asserções desabilitadas
  • Implementações Placeholder
  • Testes alterados apenas para fazer o candidato passar

Execute testes em círculos crescentes:

  1. Testes de unidade para o módulo alterado
  2. Testes de contrato nos limites públicos
  3. Testes de integração entre dependências
  4. Suítes multiplataforma
  5. Testes de regressão completos

Mantenha a saída com falha como um artefato. Uma execução verde final sem histórico pode esconder se os trabalhadores enfraqueceram repetidamente as verificações ao longo do caminho.

Quando possível, separe a autoria do teste da implementação.

Um agente pode derivar casos extremos do contrato e da implementação antiga, enquanto outro escreve a portabilidade. Bloqueie testes de compatibilidade aprovados para que os trabalhadores de implementação não possam modificá-los. Novos revisores devem perguntar se o código passa pelo motivo pretendido.

As regressões de produção do Bun demonstram a lacuna entre uma suíte verde e a completude semântica.

Uma falha de HMR apenas em release veio de um efeito colateral dentro de debug_assert!. Uma falha de UTF-16 de comprimento ímpar refletiu um comportamento diferente de slice. Cada defeito escapado deve se tornar tanto um teste de regressão permanente quanto uma nova regra de mapa semântico.

Fase 5: Adicionar Testes Diferenciais, Fuzzing e Orçamentos de Desempenho

Execute as implementações antiga e nova contra o mesmo corpus.

Compare:

  • Códigos de saída

  • Saída normalizada

  • Categorias de erro

  • Efeitos colaterais

  • Estado do banco de dados

  • Eventos emitidos

  • Rastreamentos

Crie geradores de valores-limite para:

  • Entradas vazias
  • Tamanhos máximos
  • Codificações malformadas
  • Horários próximos à época Unix
  • Condições de corrida concorrentes
  • Caminhos específicos de plataforma
  • Exaustão de recursos

Execute fuzzing contínuo em analisadores sintáticos e limites de protocolo.

O Bun relatou que seus fuzzers orientados por cobertura executaram o código do analisador cerca de 100 bilhões de vezes e geraram aproximadamente 15 pull requests de correção. O número absoluto depende da carga de trabalho. O padrão transferível é conectar a descoberta de falhas a testes reproduzíveis, correções propostas por agente e pull requests revisados por humanos.

Quando os usuários dependem de desempenho, o desempenho faz parte do comportamento.

Benchmark:

  • Inicialização a frio
  • Taxa de transferência
  • Latência p50
  • Latência p95
  • Latência p99
  • Pico de memória
  • Tamanho do binário
  • Tempo de compilação
  • CPU sob cargas de trabalho representativas

Compare distribuições em vez de médias. Defina orçamentos antes da migração para que a equipe não possa justificar regressões após investir pesadamente na reescrita.

Execute também testes de longa duração. Vazamentos de memória, vazamentos de descritores, crescimento de filas, fragmentação de alocador e condições de corrida raras podem levar horas ou dias para se manifestar.

Uma linguagem com garantias mais fortes de segurança de memória pode eliminar classes inteiras de bugs, embora ainda introduza comportamentos diferentes de alocação, escalonamento ou desempenho.

Revise Código Inseguro, FFI e Limites de Segurança Separadamente

Trate cada um dos seguintes como uma classe de revisão separada:

  • Blocos unsafe
  • Chamadas FFI
  • Ponteiros brutos
  • Alocadores personalizados
  • Limites criptográficos
  • Analisadores sintáticos
  • Desserializadores
  • Verificações de permissão
  • Lógica de autenticação
  • Limites de persistência

Na época do relatório de origem, o Bun descreveu aproximadamente 27.000 linhas dentro de blocos unsafe em cerca de 780.000 linhas de Rust, grande parte relacionada à integração com C e C++.

Essa superfície requer mais do que uma revisão de código comum.

Exija um comentário invariante perto de cada limite inseguro:

  • O que deve ser verdadeiro?
  • Quem estabelece a invariante?
  • Por quanto tempo o ponteiro permanece válido?
  • Qual thread é a proprietária do valor?
  • Qual teste exercita a condição?

Agrupe padrões inseguros repetidos atrás de wrappers revisados. Acompanhe linhas e blocos inseguros por proprietário, em vez de tratar o total como uma métrica de vaidade.

Use:

  • Análise estática
  • Sanitizadores
  • Auditorias de dependências
  • Fuzzing
  • Revisão de segurança manual

As 11 rodadas de revisão de segurança do Bun são evidências de endurecimento contínuo, não evidências de que defeitos estavam ausentes.

A revisão de segurança automatizada deve complementar a revisão de domínio, especialmente em torno de autenticação, escape de sandbox, segredos e mudanças na cadeia de suprimentos.

Revise o próprio mecanismo de migração. Agentes executam conteúdo do repositório, scripts de compilação e saída de ferramentas. Uma dependência comprometida ou instrução oculta no código-fonte pode influenciar a execução.

Isolamento do sistema de arquivos, restrições de rede, tokens com escopo e verificações imutáveis de CI reduzem esse risco.

Lance em Etapas e Pratique Reversão Antes de Precisar

Mesclar não é lançar.

Construa artefatos versionados a partir de commits conhecidos, cadeias de ferramentas, travas de dependências e manifestos de evidência. Mantenha a implementação antiga compilável.

Se os binários antigos e novos puderem coexistir, adicione uma chave de tempo de execução ou camada de roteamento

em vez de substituir irreversivelmente o caminho.

Comece com a execução em modo de sombra quando os efeitos colaterais puderem ser isolados.

Em seguida, faça o lançamento gradual (canary) por:

  • Usuários internos
  • Locatários de baixo risco
  • Plataforma
  • Região
  • Percentual de tráfego

Defina limites de reversão automática para:

  • Divergências de corretude
  • Taxa de falhas (crash rate)
  • Latência
  • Memória
  • Categorias de erro
  • Sinais de suporte

Os humanos devem manter a capacidade de interromper a expansão mesmo quando os limites automatizados não forem atingidos.

Pratique a reversão.

Confirme que:

  • O artefato antigo inicia com sucesso.
  • Os esquemas permanecem compatíveis.
  • O trabalho enfileirado pode ser drenado.
  • A observabilidade identifica qual implementação atendeu cada requisição.
  • O tempo medido de reversão atende ao objetivo operacional.

Documentação de reversão que nunca foi executada é apenas uma hipótese.

Após cada defeito que escapar, atualize o contrato, o mapa semântico, o corpus de testes e o modelo de risco.

As 19 regressões conhecidas do Bun são úteis porque expõem riscos recorrentes de tradução. Uma migração está completa quando a nova implementação é operável e a equipe aprendeu com ela — não quando o diff gerado é mesclado.

Política de Migração de IA Reutilizável e Manifesto de Evidências

O YAML a seguir foi projetado como um artefato de equipe reutilizável. Adapte comandos, limites e responsáveis ao repositório.

O We0 AI ou outro sistema de orquestração pode anexar esta política a tarefas de migração e exigir o manifesto de evidências antes da revisão.

ai_migration:
  name: payments-python-to-go
  contract: docs/MIGRATION_CONTRACT.md
  semantic_map: docs/PORTING_RULES.md
  old_reference: artifacts/payments-python@sha256:OLD
  new_candidate: artifacts/payments-go@sha256:NEW

  worker_policy:
    isolation: ephemeral_worktree
    one_writer_per_unit: true
    forbidden_commands:
      - "git reset --hard"
      - "git stash"
      - "git push --force"
    editable_paths: ["cmd/", "internal/", "tests/migration/"]
    protected_paths: ["tests/contracts/", "docs/MIGRATION_CONTRACT.md"]

  required_gates:
    compile: "go build ./..."
    unit: "go test ./..."
    contracts: "./scripts/run-contract-tests.sh"
    differential: "./scripts/compare-old-new.sh --corpus fixtures/replay"
    fuzz: "./scripts/fuzz.sh --hours 24 --unique-crashes 0"
    security: "./scripts/security-scan.sh --severity high"
    performance:
      p99_latency_regression_pct: 5
      peak_memory_regression_pct: 10
    platforms: [linux-amd64, linux-arm64]

  independent_review:
    fresh_context: true
    reviewers_per_unit: 2
    require_counterexample_search: true

  rollout:
    shadow_hours: 48
    canary_percentages: [1, 5, 20, 50, 100]
    rollback_artifact_required: true
    rollback_drill_required: true

  evidence_manifest:
    include:
      - contract_version
      - source_and_target_commits
      - changed_units
      - commands_and_exit_codes
      - differential_mismatches
      - fuzzing_summary
      - benchmark_distributions
      - unsafe_or_ffi_inventory
      - reviewer_findings
      - approved_exceptions
      - rollback_drill_result

Esta política impede deliberadamente que os trabalhadores da implementação editem o contrato ou os testes de contrato aprovados.

Ela exige:

  • Artefatos de referência
  • Revisão independente
  • Evidências quantitativas

Limites de desempenho

  • Evidência de implantação
  • Um caminho de reversão testado

Exceções são possíveis, mas devem ser documentadas e aprovadas, em vez de ocultadas dentro de um prompt.

Meça o Progresso Verificado, Não o Volume Gerado

Linhas de código, número de agentes e dias decorridos são métricas interessantes de capacidade. Elas não medem o sucesso do produto.

Use um scorecard de migração equilibrado.

Taxa de Transferência de Unidade Verificada

Acompanhe as unidades de migração que:

  • Compilam
  • Passam em verificações de contrato direcionadas
  • Recebem revisão independente
  • Integram-se sem regressão

Meça as unidades aceitas por unidade de tempo.

Fechamento de Divergências

Acompanhe as diferenças descobertas e se cada uma é:

  • Explicada
  • Corrigida
  • Aprovada como intencional
  • Ainda não resolvida

Defeitos que Escaparam

Acompanhe os defeitos que passam por uma barreira que deveria tê-los detectado.

Cada defeito que escapar deve identificar uma regra de contrato, teste, oráculo, etapa de revisão ou limite de implantação ausente.

Atenção Humana

Meça o tempo que os humanos gastam:

  • Definindo contratos
  • Resolvendo ambiguidades
  • Revisando código de alto risco
  • Investigando divergências
  • Operando a implantação

A IA pode reduzir o tempo de implementação enquanto aumenta a qualidade da especificação. Essa é uma boa troca, não uma falha de automação.

Custo Computacional e de Ferramentas

Meça o custo total do modelo, computação e ferramentas por unidade aceita.

Fluxos de trabalho dinâmicos podem consumir mais tokens do que sessões comuns. O paralelismo é justificado quando reduz o tempo de espera para trabalhos de alto valor sem criar um acúmulo maior de verificação.

Mantenabilidade Pós-Migração

Acompanhe:

  • Tempo de inicialização
  • Velocidade de compilação
  • Taxa de falha de alterações
  • Latência de revisão
  • Densidade de defeitos
  • Responsabilidade por módulos inseguros
  • Facilidade de depuração
  • Qualidade da documentação operacional

Uma migração que é entregue rapidamente, mas permanece opaca para a equipe, transferiu a dívida em vez de removê-la.

Como uma Equipe Pode Começar Sem Reescrever Um Milhão de Linhas

Escolha uma migração delimitada com uma implementação de referência ativa, como:

  • Uma mudança de versão de SDK
  • Um subsistema do framework
  • Um comando CLI
  • Um endpoint de serviço

Escreva um contrato de comportamento de uma página e três casos piloto focados em risco.

Use tarefas de agente separadas para implementação e revisão, de modo que seus contextos permaneçam independentes.

Antes da implementação:

  1. Bloqueie as verificações de aceitação.
  2. Exija que o implementador retorne um commit e evidências, não uma alegação textual.
  3. Peça ao revisor para encontrar contraexemplos e identificar testes ausentes.
  4. Execute as verificações no CI fora do modelo.
  5. Expanda apenas para a próxima camada de dependência após o piloto ser bem-sucedido.

Mantenha um registro completo da execução:

  • Prompt
  • Modelo
  • Escopo da ferramenta
  • Commit de origem
  • Commit de destino
  • Caminhos alterados
  • Verificações
  • Falhas
  • Descobertas do revisor
  • Exceções
  • Custo
  • Decisão final

Esse registro permite que a equipe compare versões de teste e investigue defeitos sem adivinhar o que o agente viu.

Use uma regra simples de adoção:

A autonomia deve ser conquistada.

Um fluxo de trabalho que produz repetidamente unidades verificadas pode receber um escopo de arquivo mais amplo ou um tempo de execução não supervisionado maior. Ele não recebe automaticamente permissão de implantação.

Capacidade, evidência e autoridade permanecem separadas.

Limitações: O Que o Caso Bun Não Prova

Bun é um projeto incomum.

Seu criador liderou o

迁移工作需要对代码库有深入了解,并拥有直接的架构权限。旧实现拥有庞大的测试套件,Rust 提供了强大的编译器反馈,并且项目可以利用大量并行计算资源。

大多数团队不会拥有所有这些优势。

该案例也是通过 Anthropic 呈现的,原始文章提到这项工作使用了预发布的 Claude Fable 5 模型。这是一个有价值的主要证据,但并非独立的供应商对比。

关于人类团队需要多长时间的说法都是反事实的估计。团队不应仅凭一次成功的迁移就做出采购决策。

报告中指出的 19 个回归是已知的回归问题,并不能保证是完整数量。模糊测试执行和安全审查轮次衡量的是工作量,而非缺陷的缺失。

最有力的合理结论是适度的:

在强大的确定性反馈和专家协调的支持下,大型 AI 驱动迁移是可行的,但其风险在代码生成完成后仍然是一个工程问题。

这个结论仍然很有意义。团队可以尝试那些因成本问题而被推迟的现代化项目,前提是他们需要为规范制定、验证和受控推广投入与实现阶段同等规模的预算。

实用迁移清单

  • 定义保留、修改、弃用和未知的行为。
  • 清点平台、性能、遥测、错误和副作用的契约。
  • 为有风险的源到目标模式构建语义映射。
  • 保护契约和已批准的测试,使其免受实现工作者的影响。
  • 在仓库范围推广之前,先运行困难的原型单元。
  • 隔离编写者,限制具有破坏性的 Git 和网络操作。
  • 要求包含命令、输出和契约引用的原子提交。
  • 为高风险单元使用全新背景的对抗性评审者。
  • 运行编译器、单元、契约、集成和跨平台的门禁检查。
  • 在代表性语料库上比较新旧实现。
  • 添加蜕变、模糊测试、消毒器和性能检查。
  • 清点 unsafe、FFI、认证、解析器和持久性的边界。
  • 保留可复现的回滚产物并运行回滚演练。
  • 通过影子发布和金丝雀阶段逐步推出,并设置自动停止阈值。
  • 将每一个逃逸的缺陷转化为契约或验证的改进。
  • 衡量已验证的单元、不匹配项、人工注意力、成本和可维护性。

常见问题解答

Bun 用 Rust 重写了什么?

Bun 将之前用 Zig 编写的一个主要实现迁移到了 Rust。已发布的报告描述了大约 78 万行 Rust 代码以及一个高度并行的 AI 辅助工作流程,随后进行了大量测试、安全审查、模糊测试和生产环境加固。

AI 是在没有人工审查的情况下完成了 Bun 的 Rust 重写吗?

不是。人工编写的迁移规则、手动产物审查、隔离工作流程、编译器反馈、独立的代理评审者、安全审查、模糊测试和生产推广控制都发挥了重要作用。这个案例更适合被理解为 AI 加速的工程,而非无人值守的代码转换。

为什么现有测试不足以验证

Migração de linguagem?

Os testes existentes geralmente cobrem apenas parte do comportamento observado. Eles podem ignorar semânticas exclusivas de versão, diferenças entre plataformas, regressões de desempenho, limites inseguros, alterações de telemetria ou casos extremos que nunca foram codificados no conjunto de testes.

O que é teste diferencial em uma migração de código?

O teste diferencial executa as implementações antiga e nova com as mesmas entradas e compara suas saídas observáveis e efeitos colaterais. É particularmente útil quando o sistema antigo é confiável, mas não existe uma especificação formal completa.

Por que os agentes de implementação e revisão devem usar contextos separados?

Um revisor novo tem menos probabilidade de herdar as suposições e erros de raciocínio do agente autor. O revisor pode se concentrar no contrato, diff, evidências e contraexemplos, em vez de defender o caminho de implementação que produziu a alteração.

Como as equipes devem revisar código Rust unsafe durante a migração?

Cada bloco unsafe ou limite de FFI deve ter um proprietário nomeado, invariantes documentados, testes direcionados e uma explicação clara da validade do ponteiro, tempo de vida e propriedade de thread. A análise estática, sanitizers, fuzzing, revisão de dependências e revisão manual de segurança devem ser aplicados separadamente da revisão de código comum.

Quais métricas uma migração assistida por IA deve acompanhar?

Acompanhe a taxa de transferência de unidades verificadas, fechamento de incompatibilidades, defeitos escapados, atenção humana, custo computacional, saúde do lançamento e capacidade de manutenção pós-migração. Linhas geradas e contagem de agentes são métricas de capacidade, não prova de correção.

Uma equipe pequena pode usar este manual sem executar dezenas de agentes?

Sim. Comece com um componente delimitado, um contrato de comportamento escrito, três pilotos focados em risco, contextos separados de implementação e revisão, portões de CI determinísticos e um caminho de reversão testado. Escalone o fluxo de trabalho somente depois que ele produzir resultados verificáveis repetidamente.

Ferramentas Relacionadas

  • Bun: Um kit de ferramentas completo para JavaScript e TypeScript cuja migração para Rust fornece o principal estudo de caso para este manual.
  • Rust: Uma linguagem de programação de sistemas com fortes garantias de segurança em tempo de compilação e limites unsafe explícitos.
  • Claude Code: O ambiente de codificação agêntico da Anthropic, usado no fluxo de trabalho dinâmico descrito pelo material de origem.
  • GitHub Actions: Uma plataforma CI/CD adequada para portões determinísticos de compilação, teste, segurança, benchmark e evidência.
  • cargo-fuzz: Uma ferramenta de fuzzing padrão para projetos Rust construída sobre o libFuzzer.
  • Miri: Um interpretador Rust que pode detectar certas formas de comportamento indefinido em código unsafe.

Links Relacionados

  • Bun: Reescrevendo o Bun em Rust: Relato oficial de engenharia do Bun sobre a reescrita, endurecimento em produção, fuzzing e regressões conhecidas.
  • Repositório Fonte do Bun: O repositório oficial do Bun contendo a implementação em Rust, issues, testes e histórico de migração.
  • [Anthropic: Introduzindo Fluxos de Trabalho Dinâmicos](https://claude.

com/blog/introducing-dynamic-workflows-in-claude-code): Descrição da Anthropic sobre o fluxo de trabalho multiagente utilizado durante a migração do Bun.

Resumo

A reescrita do Bun em Rust demonstra que agentes de codificação de IA podem comprimir drasticamente o tempo de implementação, mas também mostra por que a verificação deve se tornar um sistema de engenharia de primeira classe. Contratos, mapas semânticos, workers isolados, revisão independente, testes diferenciais, fuzzing, orçamentos de desempenho e implantação gradual são o que transformam código gerado em evidência de migração confiável.

A lição prática não é copiar o número de agentes ou linhas de código. É dividir uma migração em afirmações delimitadas, exigir prova determinística para cada afirmação e expandir a autonomia somente após o fluxo de trabalho produzir resultados confiáveis repetidamente.

Uma grande reescrita assistida por IA só está completa quando o novo sistema é verificado, operável, recuperável e compreendido — não quando o código gerado foi mesclado.