Piense en la última gran funcionalidad que lanzó. Sea honesto. ¿La metió en un pull request gigante o la dividió en solicitudes más pequeñas y acotadas? Durante años, ha tenido que decidir silenciosamente entre ver crecer un pull request hasta que revisarlo se vuelve una pesadilla, o dividirlo en una cadena de solicitudes más pequeñas que debe supervisar, sincronizar manualmente y desenredar cada vez que se introduce un cambio.

Ambas opciones tienen sus desventajas. Una es difícil de revisar, mientras que la otra es difícil de mantener. Su decisión ese día suele inclinarse hacia la opción menos dolorosa. Ahora sume los agentes de codificación. Son increíblemente productivos y se proyecta que impulsen una ganancia de productividad del 50% en todas las etapas del SDLC para 2028, según Gartner. Pero no pueden eliminar la elección de cómo estructurar sus pull requests; más bien, amplifican la necesidad de hacerlo correctamente. En este artículo, seguiremos un ejemplo de cómo utilizar pull requests apilados para simplificar las revisiones.

¿Cómo gestionar cambios complejos en asistentes de compras?

Supongamos que envía una instrucción para agregar una búsqueda de productos a un asistente de compras, se aleja y, minutos después, regresa para revisar, dirigir y aprobar. Pero mire de cerca lo que suele terminar en ese único pull request:

  • Un nuevo modelo de datos y sus datos semilla.
  • Una ruta de API y su validación.
  • La conexión del cliente, la interfaz de usuario (UI) y los estados de error o vacío.

Todo esto y más en un diff gigantesco de más de 1,000 líneas. Para los agentes entrenados principalmente en cómo se ha escrito el código tradicionalmente a lo largo de los años, este patrón es su forma predeterminada de entregar software. Veamos cómo ocurre.

Usted desea agregar la búsqueda de productos en una aplicación web existente y su estado inicial es:

  • Un asistente de IA simulado que muestra respuestas de un generador de líneas aleatorias.
  • Datos de productos inconsistentes, codificados y dispersos en los componentes.
  • Ningún módulo de catálogo, ni API, ni capa de datos: absolutamente nada.

Se abre un ticket para implementar la funcionalidad y un flujo típico sería crear una rama de características, asignarla a un agente de codificación (o múltiples agentes personalizados), obtener un primer borrador de todo el código de implementación y las pruebas actualizadas... usted lee el código (bueno, quizás lo lee). Luego, todavía necesita verificar manualmente el comportamiento de la funcionalidad, realizar las actualizaciones necesarias, enviar y abrir un pull request con su descripción generada por IA, larga pero superficial, asegurarse de que las comprobaciones de CI estén en verde, revisar el diff y solicitar revisores. Usted comienza...

<reviewer's hat> Revisor: 1,721 líneas cambiadas. Esta descripción no ayuda mucho. Revisaré esto más tarde. </reviewer's hat>

Y lo que sigue es familiar: el gran pull request se vuelve difícil de revisar, por lo que simplemente se queda ahí. Los revisores pierden el contexto y la calidad de la retroalimentación disminuye. Se vuelve aún más lento de fusionar. Esto inicia un proceso manual, desordenado y que consume mucho tiempo, propenso a conflictos antes de que la funcionalidad llegue a producción, y eventualmente termina siendo revisado superficialmente.

¿Qué son los pull requests apilados de GitHub?

Los pull requests apilados introducen una estructura de entrega diferente y mejor. El principio es simple: descomposición. En lugar de apuntar a un solo pull request que aborde el problema en su totalidad, usted desglosa la funcionalidad en capas lógicas e identifica la cadena de dependencias para llegar a su objetivo deseado. Esto le da a usted, y a sus agentes, una forma nativa de descomponer el trabajo que de otro modo terminaría en un pull request gigante, convirtiéndolo en una cadena de capas pequeñas, enfocadas e independientes.

Ese gran pull request que es difícil de revisar se convierte en una pila de solicitudes más pequeñas, ordenadas lógicamente, cada una limitada a un solo interés, lo suficientemente pequeña como para mantenerla en la mente de un revisor y con el contexto suficiente fluyendo naturalmente desde el pull request revisado anteriormente. Hagámoslo realidad.

¿Cómo estructurar la pila de trabajo?

Analicemos los pasos involucrados al descomponer el problema y organizar la pila por capas. Primero, y muy importante, establezca la base de la pila. Esto importa porque las comprobaciones de CI y las reglas de fusión a lo largo del ciclo de vida de gestión de la pila se evalúan contra esta base. Luego, identifique la unidad fundamental de trabajo y colóquela más cerca de la base (la más baja en la pila), colocando el trabajo dependiente por encima.

Capa de Pila (L#) / RamaQué entregarDependencia
L1 (feat/catalog-data)Catálogo tipado, datos semilla, validación y módulo de acceso a datosmain (base)
L2 (feat/search-api)Endpoint validado /api/products/searchfeat/catalog-data
L3 (feat/chat-grounding)El chat llama a la API y responde con datos realesfeat/search-api
L4 (feat/grounded-ui)Tarjetas de citación de productos + estadoL3 (feat/chat-grounding)

Ahora los intereses independientes están claros: datos, API, conexión y UX, lo que hace posible asignar diferentes audiencias de revisión para cada uno. Los datos son revisados por un propietario de datos, la UX por un propietario de UI. El soporte nativo de GitHub para pull requests apilados se puede iniciar desde la UI de pull request y se extiende sin problemas al terminal con la CLI gh stack.

Instale la extensión CLI de pull requests apilados ejecutando: gh extension install github/gh-stack

En tiempos antiguos, usted estaría listo para comenzar a trabajar. Hoy no es así. Hay agentes trabajando junto a usted. Estos agentes necesitan aprender cómo funcionan las pilas y cómo crearlas y gestionarlas en su nombre. La habilidad gh-stack les enseña esto.

gh skill install github/gh-stack

O, si prefiere: npx skills add github/gh-stack

Para la funcionalidad específica del ejemplo anterior, su flujo de trabajo de desarrollo tiene agentes personalizados, cada uno con flujos de trabajo definidos y que siguen una disciplina de alcance estricta para lograr el objetivo de pull requests pequeños y de un solo alcance.

Capa / RamaAgente
L1 (feat/catalog-data)Agente modelador de datos
L2 (feat/search-api)Agente de backend
L3 (feat/chat-grounding)Agente de frontend
L4 (feat/grounded-ui)Agente de frontend

La última parte de la configuración es confirmar que existe CI. Como se mencionó anteriormente, cada pull request se evaluará contra la base de la pila y estas comprobaciones se ejecutarán para cada capa. Ahora comienza el trabajo.

¿Cómo ejecutar el flujo de trabajo por capas?

La mayoría de los flujos de trabajo de agentes hoy en día están automatizados y se ejecutan de forma autónoma en bucles, pero para fines ilustrativos, cubriremos cada paso a la vez. En este punto, todos los agentes están familiarizados con cómo funcionan los pull requests apilados, por lo que un flujo típico sería:

Invocar al Agente Modelador de Datos con una instrucción apropiada. El agente inicializa una nueva pila y establece la primera rama (feat/catalog-data) con main como base usando gh init stack. Verifica, trabaja y ejecuta la validación. Si las comprobaciones están en verde, se confirma la capa; de lo contrario, se itera. Nota para el futuro: ¿Son correctos los tipos? ¿Están validados los datos? ¿Es seguro el ayudante de consulta?

En la segunda capa, el Agente de Backend añade la siguiente capa (feat/search-api) sobre la capa uno, usando feat/catalog-data como base para importar el módulo de acceso a datos completado con gh stack add. Verifica, trabaja y ejecuta la validación. El desarrollador prueba la API manualmente. Si todo funciona, se confirma la capa.

Para la tercera capa, se invoca al Agente de Frontend con una instrucción apropiada. El agente añade la siguiente capa (feat/chat-grounding) sobre la capa dos. Su base es feat/search-api, que se ramificará con el módulo de acceso a datos y la API validada. Verifica, trabaja y ejecuta pruebas de navegador con Playwright.

Finalmente, en la cuarta capa, notará que la capa tres y la cuatro, a pesar de tener el mismo autor (Agente de Frontend), están estratificadas de manera distinta. Esto es deliberado. El propietario de la UI no debería tener que verificar el flujo de datos subyacente y viceversa; esta estructura permite esa independencia. Así, el agente de frontend agrega la capa feat/grounded-ui sobre la capa anterior.

Vía GitHub Blog.