Phase 19 - Lesson 09

Projeto Final 09 — Agente de Migração de Código (Atualização de Linguagem / Runtime em Nível de Repositório)

O MigrationBench da Amazon (Java 8 para 17) e o migrador Py2-para-Py3 do App Engine do Google definem o patamar em 2026. O OpenRewrite da Moderne realiza reescritas determinísticas de AST em escala. A Grit aborda o mesmo problema com uma DSL no estilo codemod. O padrão de produção combina ambos: um substrato determinístico para reescritas seguras mais uma camada de agente para casos ambíguos, uma sandbox para compilações por branch e uma estrutura de testes que valida tudo com sucesso antes da abertura do PR. O projeto final consiste em migrar 50 repositórios reais e publicar uma taxa de aprovação com uma taxonomia de falhas.

Tipo: Projeto Final Idiomas: Python (agente), Java / Python (alvos), TypeScript (painel) Pré-requisitos: Fase 5 (Processamento de Linguagem Natural), Fase 7 (Transformers), Fase 11 (Engenharia de LLM), Fase 13 (Ferramentas), Fase 14 (Agentes), Fase 15 (Sistemas Autônomos), Fase 17 (Infraestrutura) Fases exercitadas: P5 · P7 · P11 · P13 · P14 · P15 · P17 Tempo: 30 horas

Problema

A migração de código em larga escala é uma das aplicações de produção mais objetivas para agentes de programação em 2026. A verdade fundamental (ground truth) é óbvia (a suíte de testes passa após a migração?), as recompensas são reais (a migração de uma frota de Java 8 é um projeto que demanda equipes inteiras) e os benchmarks são públicos (subconjunto de 50 repositórios do MigrationBench). O OpenRewrite da Moderne cuida da parte determinística. A camada do agente lida com tudo o que as receitas do OpenRewrite não conseguem: reescritas ambíguas, desvio no sistema de compilação (build-system drift), sintaxe incomum e quebra de dependências transitivas.

Você construirá um agente que recebe um repositório Java 8 (ou Python 2) e gera uma branch migrada com CI aprovado (verde). Você medirá a taxa de aprovação, a preservação da cobertura de testes, o custo por repositório e construirá uma taxonomia de falhas. A comparação direta com uma solução puramente determinística revelará onde reside o real valor do agente.

Conceito

O pipeline possui duas camadas. O substrato determinístico (OpenRewrite para Java, libcst para Python) executa a maior parte das reescritas mecânicas com segurança: importações, assinaturas de métodos, ajustes de null-safety, try-with-resources e substituições de APIs obsoletas. Ele é rápido e gera diffs auditáveis. A camada do agente (OpenAI Agents SDK ou LangGraph sobre o Claude Opus 4.7 e o GPT-5.4-Codex) trata os casos que as receitas não cobrem: atualizações de arquivos de build (Maven/Gradle/pyproject), conflitos de dependências transitivas, testes intermitentes (flakes) e anotações personalizadas.

Cada repositório recebe uma sandbox do Daytona com o ambiente de execução (runtime) de destino pré-instalado. O agente executa iterativamente: rodar o build, classificar falhas, aplicar correção, rodar novamente. Limites rígidos: 30 minutos por repositório, custo máximo de $8 por repositório e 20 turnos de agente. Se todos os testes passarem e a variação da cobertura de testes não for negativa, a branch abre um PR. Caso contrário, o repositório é registrado em uma classe de falha com as respectivas evidências.

A taxonomia de falhas é o entregável deste projeto. Ao longo de 50 repositórios, o que quebrou? Dependências transitivas? Anotações personalizadas? Versão da ferramenta de build? Testes intermitentes não relacionados à migração? Cada classe de falha recebe uma contagem e um diff de exemplo. Desenvolvedores de receitas futuras poderão focar nas três principais categorias detectadas.

Architecture

target repo
      |
      v
OpenRewrite / libcst deterministic recipes
   (safe, fast, auditable, ~70-80% of fixes)
      |
      v
Daytona sandbox per branch
      |
      v
agent loop (Claude Opus 4.7 / GPT-5.4-Codex):
   - run build -> capture failures
   - classify failures (build, test, lint)
   - apply fix (patch or retry recipe)
   - rerun
   - budget: 30 min, $8, 20 turns
      |
      v
test + coverage delta gate
      |
      v (passed)
open PR
      |
      v (failed)
file under failure class + attach repro

Pilha Tecnológica

  • Substrato determinístico: OpenRewrite (Java) ou libcst (Python)
  • Agente: OpenAI Agents SDK ou LangGraph sobre o Claude Opus 4.7 + GPT-5.4-Codex
  • Sandbox: Devcontainers Daytona por branch, com o runtime de destino pré-instalado (Java 17 / Python 3.12)
  • Sistemas de compilação: Maven, Gradle, uv (Python)
  • Benchmarks: Subconjunto de 50 repositórios do Amazon MigrationBench (Java 8 para 17), repositórios do Google App Engine Py2-para-Py3
  • Estrutura de teste: executor em paralelo, cobertura via Jacoco (Java) ou coverage.py (Python)
  • Observabilidade: Langfuse + pacote de rastreamento por repositório com cada trecho de diff
  • Painel: painel de taxonomia de falhas com contagens por classe e diffs de exemplo

Passo a Passo do Desenvolvimento

  1. Passagem de receitas. Execute primeiro as receitas do OpenRewrite (Java) ou libcst (Python). Resolva a fatia de 70-80% de migrações puramente mecânicas. Crie um commit identificando essa etapa como "receita".

  2. Teste de compilação. Na sandbox do Daytona: instale o runtime de destino e execute o build. Se passar (verde), siga direto para os testes. Se falhar (vermelho), transfira o controle para o agente.

  3. Loop do agente. Implemente um fluxo no LangGraph com acesso a ferramentas como: run_build, read_file, edit_file, run_test e git_diff. O agente classifica o erro (dependência, sintaxe, teste, ferramenta de build) e aplica uma correção direcionada. Rode novamente.

  4. Limites de orçamento. 30 minutos de tempo de execução real por repositório, custo máximo de $8 e 20 turnos de agente. Qualquer violação interrompe o processo e registra a falha como "budget_exhausted" (orçamento esgotado) anexando o diff atual.

  5. Validação de testes e cobertura. Assim que o build passar com sucesso, execute a suíte de testes. Compare a cobertura resultante com o repositório base. Se a cobertura cair mais do que 2%, classifique como "coverage_regression".

  6. Abertura de PR. Em caso de sucesso, envie a branch para o repositório e abra o PR detalhando o diff, quais receitas foram aplicadas e quais commits foram gerados pelo agente.

  7. Taxonomia de falhas. Para cada repositório que falhar, associe uma classe correspondente: dep_upgrade_required, build_tool_drift, custom_annotation, test_flake, syntax_edge_case, budget_exhausted. Construa um painel visual para apresentar esses dados.

  8. Execução em lote de 50 repositórios. Execute o pipeline sobre o subconjunto do MigrationBench. Relate a taxa de aprovação por classe, custo por repositório, preservação de cobertura e compare o resultado final com a linha de base exclusivamente determinística.

Use It

$ migrate legacy-java-service --target java17
[recipe]   27 rewrites applied (JUnit 4->5, HashMap initializer, try-with-resources)
[build]    FAIL: cannot find symbol sun.misc.BASE64Encoder
[agent]    turn 1 classify: removed_jdk_api
[agent]    turn 2 apply: sun.misc.BASE64Encoder -> java.util.Base64
[build]    OK
[tests]    412/412 passing; coverage 84.1% -> 84.3%
[pr]       opened #1841  cost=$3.20  turns=4

Entrega

outputs/skill-migration-agent.md é o entregável. Dado um repositório, ele executa as receitas determinísticas seguidas pelo loop do agente para gerar uma branch migrada e funcional (CI verde), ou classifica o repositório em uma das categorias de falha.

Peso Critério Como é medido
25 Taxa de aprovação no MigrationBench pass@1 no subconjunto de 50 repositórios
20 Preservação da cobertura de testes Variação média da cobertura vs base
20 Custo por repositório migrado $/repositório nas execuções bem-sucedidas
20 Integração agente / ferramenta determinística Proporção de correções resolvidas pelo OpenRewrite vs as escritas pelo agente
15 Análise descritiva de falhas Completude da taxonomia acompanhada por diffs de exemplo
100

Exercícios

  1. Execute o pipeline de migração usando apenas o OpenRewrite (sem o agente). Compare a taxa de aprovação obtida com a do pipeline completo. Identifique as situações em que a presença do agente fez a diferença real.

  2. Implemente uma verificação de estilo de código: após a migração, execute um linter (spotless para Java, ruff para Python). Rejeite o PR caso surjam novos erros de formatação ou estilo. Meça a taxa de repositórios que mantêm a cobertura de testes mas falham na formatação.

  3. Desenvolva um otimizador de diff mínimo: após a branch gerada pelo agente passar nos testes, realize uma segunda varredura para reverter alterações desnecessárias. Apresente a redução percentual obtida no tamanho do diff.

  4. Estenda o suporte para uma terceira migração: Node 18 para Node 22. Reaproveite a estrutura de sandboxes e substitua a camada de receitas por um codemod personalizado.

  5. Meça o tempo decorrido até a primeira compilação bem-sucedida (TTFGB) como métrica de experiência de usuário (UX). Meta: p50 abaixo de 10 minutos.

Termos-Chave

Termo O que dizem O que realmente significa
Deterministic substrate "Mecanismo de receitas" OpenRewrite / libcst: reescritas declarativas de AST com garantias de segurança
Codemod "Programa de modificação de código" Uma regra de reescrita que altera o código-fonte de maneira mecânica
Build drift "Divergência de versão de ferramenta" Mudanças sutis de comportamento no Maven, Gradle ou uv entre versões principais
Failure class "Categoria da taxonomia" Um motivo rotulado pelo qual o repositório não migrou: dependência, sintaxe, teste, ferramenta de build ou orçamento
Coverage delta "Preservação de cobertura" Variação percentual na cobertura de testes entre o código original e a branch migrada
Agent turn "Ciclo de chamada de ferramenta" Uma iteração completa de planejar -> agir -> observar no loop do agente
Budget exhaustion "Limite atingido" O repositório consumiu o limite estipulado de 30 minutos / $8 / 20 turnos sem passar nos critérios de sucesso

Leituras Adicionais

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).