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
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".
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.
Loop do agente. Implemente um fluxo no LangGraph com acesso a ferramentas como:
run_build,read_file,edit_file,run_testegit_diff. O agente classifica o erro (dependência, sintaxe, teste, ferramenta de build) e aplica uma correção direcionada. Rode novamente.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.
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".
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.
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.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
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.
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.
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.
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.
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
- Amazon MigrationBench — o benchmark canônico de 2026
- Moderne.io OpenRewrite platform — a referência para o substrato determinístico
- OpenRewrite documentation — desenvolvimento de receitas
- Grit.io — DSL alternativa de codemod
- OpenAI sandboxed migration cookbook — a referência do SDK de agentes
- Google App Engine Py2 to Py3 migrator — benchmark alternativo de migração
- libcst — substrato determinístico em Python
- Daytona sandboxes — referência para sandboxes por branch