Phase 19: Capstone Projects

Capstone 09 Agente de migración de código (Lenguaje de nivel repuesto / actualización de tiempo de ejecución)

El MigrationBench de Amazon (Java 8 a 17) y el migrante Py2-to-Py3 de Google de App Engine establecen la barra de 2026. OpenRewrite de Moderne hace reescrituras deterministas de AST a escala. Grit tiene como objetivo el mismo problema con el estilo de codemod DSL. El patrón de producción combina ambas cosas: un sustrato determinista para las reescrituras seguras más una capa de agente para los casos ambiguos, una caja de arena para cada rama de construcción y un arnés de prueba que se vuelve verde antes de que se abra la PR. La piedra angular es migrar 50 repos reales y publicar una tasa de aprobación con una taxonomía de fracaso.

Type: Capstone

Languages: Python (agent), Java / Python (targets), TypeScript (dashboard)

Prerequisites: Phase 5 (NLP), Phase 7 (transformers), Phase 11 (LLM engineering), Phase 13 (tools), Phase 14 (agents), Phase 15 (autonomous), Phase 17 (infrastructure)

Phases exercised:P5 · P7 · P11 · P13 · P14 · P15 · P17

Time: 30 hours

El problema

La migración de código a gran escala es una de las aplicaciones de producción más limpias de agentes de codificación de 2026. La verdad de fondo es obvia (¿cumple la suite de pruebas después de la migración?), las recompensas son reales (una migración de flota Java-8 es un proyecto a escala de personal) y los puntos de referencia son públicos (subconjunto de MigrationBench 50-repo). El OpenRewrite de Moderne maneja el lado determinista. La capa de agente maneja todo lo que las recetas OpenRewrite no pueden: reescrituras ambigüas, derivación del sistema de construcción, sintaxis de cola larga, ruptura de dependencias transitivas.

Se construirá un agente que toma un repo Java 8 (o Python 2 repo) y produce una rama migrada de CI verde. Se medirá la tasa de aprobación, la preservación de la cobertura de prueba, el costo por repo y se construirá una taxonomía de fracaso. El lado a lado contra una línea de base determinista solo le dice dónde realmente vive el valor del agente.

Concepto

El oleoducto tiene dos capas.deterministic substrate(OpenRewrite para Java, libcst para Python) ejecuta la mayor parte de las reescrituras mecánicas de forma segura: importaciones, firmas de método, modificaciones de seguridad nula, prueba de recursos, reemplazos de API obsoletos. Es rápido y produce diferencias auditables.agent layer(OpenAI Agents SDK o LangGraph sobre Claude Opus 4.7 y GPT-5.4-Codex) maneja los casos en que las recetas no pueden: actualizaciones de archivos de construcción (Maven/Gradle/pyproject), conflictos de dependencias transitivas, fragmentos de prueba, anotaciones personalizadas.

Cada repo recibe una caja de arena Daytona con el tiempo de ejecución objetivo preinstalado. El agente itera: ejecuta la construcción, clasifica los fallos, aplica la corrección, repite. límites duros: 30 minutos por repo, $ 8 por repo, 20 giros de agente. Si todas las pruebas pasan y el delta de cobertura no es negativo, la rama abre un PR. Si no, el repo se presenta bajo una clase de fallo con evidencia.

La taxonomía de fallas es la entregable. En 50 repos, ¿qué se rompió? deps transitivos? anotaciones personalizadas? versiones de herramienta de construcción? flocos de prueba no relacionados con la migración? Cada clase recibe un recuento y una diferencia ejemplar.

Arquitectura

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

El establo

  • Substrato determinista: OpenRewrite (Java) o libcst (Python)
  • Agente: OpenAI Agents SDK o LangGraph sobre Claude Opus 4.7 + GPT-5.4-Codex
  • Sandbox: Daytona devcontainers por rama, tiempo de ejecución de objetivo preinstalado (Java 17 / Python 3.12)
  • Construir sistemas: Maven, Gradle, uv (Python)
  • Indicadores de referencia: Amazon MigrationBench 50 repo subconjunto (Java 8 a 17), Google App Engine Py2-to-Py3 repos
  • Arnes de prueba: corredor paralelo, cobertura a través de Jacoco (Java) o coverage.py (Python)
  • Observabilidad: Langfuse + trace bundle por repo con cada pieza diferente
  • Tablero de control: tablero de control de la taxonomía de fallos con recuentos por clase y diferencias ejemplares

Construye el mismo

  1. Recipe pass.ejecuta OpenRewrite (Java) o libcst (Python) recetas primero. Captura el 70-80% de las migraciones que son mecánicas. Compromete como "recepta" compromete.
  1. Build trial.Sandbox Daytona: instalar el tiempo de ejecución del objetivo, ejecutar la construcción. si verde, saltar a las pruebas. si rojo, entregar al agente.
  1. Agent loop.LangGraph con herramientas: run_build¿ Qué ?read_file¿ Qué ?edit_file¿ Qué ?run_test¿ Qué ?git_diffEl agente clasifica el fallo (profundidad, sintaxis, prueba, herramienta de construcción) y aplica una corrección dirigida.
  1. Budget caps.30 minutos de tiempo por repo, 8 dólares, 20 vueltas de agente. Cualquier violación se detiene y archivos bajo "budget_exhausted" con la diferencia actual.
  1. Test + coverage gate.Después de que la construcción se vuelva verde, ejecuta la suite de pruebas. Compara la cobertura con la repo base. Si la cobertura cayó más del 2%, archivo bajo "cobreza_regressión".
  1. PR open.En el éxito, empuje la rama, abra la PR con la diferencia y un resumen de cuáles recetas se aplicaron y cuál compromete al agente autor.
  1. Failure taxonomy.Para cada repo fallido, etiquete con una clase: dep_upgrade_required¿ Qué ?build_tool_drift¿ Qué ?custom_annotation¿ Qué ?test_flake¿ Qué ?syntax_edge_case¿ Qué ?budget_exhaustedConstruye un tablero de control.
  1. 50-repo run.Ejecutar en el subconjunto MigrationBench. Informar por clase tasa de aprobación, costo por repo, cobertura-preservación, y una comparación-versus-determinista-solo línea de base.

Usalo

$ 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

Envío

outputs/skill-migration-agent.mdSe le da un repo, ejecuta recetas deterministas, luego un bucle de agente para producir una rama migrada verde, o archivando el repo bajo una clase de taxonomía.

WeightCriterionHow it is measured
25MigrationBench pass rate50-repo subset pass@1
20Test-coverage preservationMean coverage delta vs base
20Cost per migrated repo$/repo on passing runs
20Agent / deterministic-tool integrationFraction of fixes that OpenRewrite handled vs agent authored
15Failure analysis write-upTaxonomy completeness with exemplars
100

Los ejercicios

  1. Ejecutar la tubería de migración con OpenRewrite solamente (sin agente). Comparar la tasa de paso con la tubería completa. Identificar los casos en los que el agente solo es la diferencia.
  1. Implemente una verificación de "limpieza de linte": después de la migración, ejecute un linter de estilo (sin manchas para Java, ruff para Python). Falle en la PR si aparecen nuevos errores de linte. Mide la tasa de cobertura conservada pero regresada por estilo.
  1. Añadir un optimizador de "diferencia mínima": después de que la rama del agente haya superado las pruebas, corregir los cambios innecesarios con un segundo paso.
  1. Extensión a una tercera migración: nodo 18 a nodo 22. Reutilice el envase de la caja de arena; intercambiar la capa de receta por un código personalizado.
  1. Mide el tiempo de la primera construcción verde (TTFGB) como una métrica UX. Objetivo: p50 en menos de 10 minutos.

Términos clave

TermWhat people sayWhat it actually means
Deterministic substrate"Recipe engine"OpenRewrite / libcst: declarative AST rewrites with safety guarantees
Codemod"Code-modifying program"A rewrite rule that changes source code mechanically
Build drift"Tool version skew"Subtle Maven / Gradle / uv behavior changes between major versions
Failure class"Taxonomy bucket"A labeled reason a repo did not migrate: dep, syntax, test, build-tool, budget
Coverage delta"Coverage preservation"Change in test coverage % from base to migrated branch
Agent turn"Tool-call round"One plan -> act -> observe cycle in the agent loop
Budget exhaustion"Hit the ceiling"The repo consumed its 30-min / $8 / 20-turn limit without passing

Leer más

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.