¿Qué hace auto-dev — una flota continua que implementa y fusiona issues?
Qué hace esto
implement-issue convierte un issue planificado en un PR listo; merge-pr fusiona un PR. auto-dev los supervisa a escala: N workers en segundo plano poseen cada uno un issue de principio a fin (implement-issue <N> → merge-pr <PR>); en el momento en que el PR de un worker se fusiona, se retira y se lanza un nuevo worker con el siguiente issue en cola, de modo que N issues permanecen en vuelo sin que tengas que supervisarlos.
El valor está en la orquestación que un simple "ejecutarlos en un bucle" no tiene:
- Evitación de conflictos — cada worker concurrente recibe un issue en un área de código diferente, por lo que las ramas rara vez chocan.
- Ordenación — issues pequeños y autocontenidos primero (victorias rápidas, menos conflictos), luego medianos. Los L/XL y los de QA manual se excluyen por defecto.
- Fusión obligatoria — a los workers les encanta parar en "PR listo" (medio trabajo). auto-dev verifica el estado real de fusión desde GitHub en cada señal y vuelve a impulsar cualquier worker que se haya estancado.
- Captura de cambios fuera de alcance — un worker que se topa con un error no relacionado lo corrige en línea solo bajo la excepción de
implement-issue(local a un archivo que su PR ya modifica y pequeño, en su propio commit) y, de lo contrario, lo archiva mediantecreate-issueen lugar de dejarlo caer, contra la barra de archivo compartida (../_shared/filing-bar.md) para que una flota de N workers no archive con N estándares diferentes. El backlog se mantiene fiel y drenable (#410). - Higiene del ciclo de vida — los agentes terminados se apagan; un archivo de estado sobrevive a reinicios para que la flota se pueda reanudar.
Contrato de autonomía
El usuario inicia esto y se va — observa cómo se vacía un backlog, no aprueba cada paso. Ejecútalo manos libres: elige el valor razonable por defecto, decláralo, sigue adelante. Detente solo ante bloqueadores genuinos:
ghno está autenticado, o careces de permisos de push/fusión.- No hay issues elegibles (cola vacía después de filtrar) — informa que el backlog está drenado.
- Un bloqueo real y honesto de un worker (pruebas que no puede poner en verde, un conflicto de ambos lados reescribiendo la misma lógica, una aprobación requerida que no puede darse a sí mismo). Reportarlo; no forzar una fusión.
Nunca finjas progreso: una casilla de verificación, un cambio a "listo" o una fusión afirman que el trabajo está hecho — respalda cada uno con evidencia, como requieren las habilidades hijas. La fusión squash es el único acto irreversible — ocurre solo a través de merge-pr en un PR verde y fusionable, nunca mediante una anulación --admin aquí.
Entradas
- Concurrencia
N— workers simultáneos. Por defecto 3 (3–4 es el punto óptimo; más = más contención y más áreas que mantener separadas). - Ordenación — por defecto esfuerzo pequeño→medio. Respeta lo que haya dicho el usuario.
- Conjunto elegible — por defecto: issues abiertos que (a) tengan un plan de implementación, (b) sean tareas de código (no "QA"/"verificar a mano" manuales), (c) estén dentro del techo de esfuerzo (por defecto ≤ medio). Respeta el filtrado ("solo issues
studio", "etiquetadospriority: high"). - Latido — normalmente se lanza mediante
loopen modo dinámico, por lo que la activación a su propio ritmo del bucle es el latido. Si se invoca directamente, arma tu propia activación. - Nivel de modelo — por defecto escalonado, no todo Opus (ver Economía de tokens): el modelo más barato capaz para tareas mecánicas/documentación, medio para errores típicos, el superior reservado para trabajo transversal/difícil + escalada de fallos. La palanca de coste más grande. Respeta una anulación ("todo en Opus", "Sonnet para todo").
Economía de tokens: ejecuta la flota barata
El coste de una ejecución larga es ~83% lectura de caché de contexto por turno, ~16% salida — pagas por volumen de contexto × turnos, no por pensar. Aplica estas reglas; la justificación completa + mediciones en references/token-economics.md.
Medido en una ejecución real de 19 fusiones (un repositorio .NET/Blazor, N=3, 21 sesiones de worker, 863M tokens): 224 turnos/sesión · contexto 30K → 350K · 181K contexto promedio por turno · 0.55 llamadas a herramientas por turno. La lectura de caché fue el 98.3% de los tokens. Coste = Σ sobre turnos del tamaño del contexto, por lo que los turnos tardíos cuestan ~10× los tempranos y el recuento de turnos es superlineal — impulsa ambos factores a la vez. Clasifica las palancas por eso, no por intuición.
Ese titular cuenta las sesiones de workers — y el orquestador fue un tercio de la factura. Plegar la transcripción del supervisor en el mismo resumen: una sesión, 551 mensajes de asistente, ~210K de contexto promedio por mensaje, 33% del coste equivalente de lista de la ejecución — más que todas las sesiones de worker de nivel superior combinadas — y nunca se compactó una vez en las 19 fusiones. El gasto de los workers está sesgado de la misma manera: las 3 mejores de 37 sesiones de worker fueron el 32% de todo el coste de los workers, y la peor fue un issue
effort: mediumen el nivel medio, por lo que ni la etiqueta ni el nivel lo predijeron. Ambas mediciones, y los dos presupuestos contados que las acotan, están en references/token-economics.md § Session length.
1. Divide cada worker en dos subagentes: implementar, luego fusionar — la única palanca que funcionó de forma medible. Verificado A/B, ~11% de todos los tokens de worker. Fase 1 (/auto-dev-worker <N>) se detiene en un PR listo; fase 2 (/auto-dev-merge <PR>) lo fusiona en un contexto nuevo.
| fase de fusión | turnos | ctx/turno promedio | cacheRead |
|---|---|---|---|
| antes (18 workers, dentro de la sesión de implementación) | 27 promedio | 247K | 6.6M por worker |
| después (fase 2 v2, sesión nueva) | 24 | 71K | 1.7M |
Recuentos de turnos casi idénticos, por lo que el contexto por turno es toda la diferencia: −74% en la fase de fusión, ≈11% del gasto total del worker. Pasa el número de PR entre fases a través de un archivo que el prompt de la fase 1 nombra (fallback a analizar la línea del informe, luego gh pr list --head). Beneficio adicional: ambas cuñas posteriores a la finalización observadas en la ejecución de referencia ocurrieron en los turnos tardíos de una sesión larga — las sesiones más cortas se acuñan menos.
2. Agrupación de llamadas a herramientas — PROBADO Y NO FUNCIONÓ. No esperes una ganancia aquí. Se añadió una regla de agrupación estricta con ejemplos al prompt del worker y se midió A/B: la densidad pasó de 0.556 → 0.537 llamadas por turno (fase 1) — es decir, sin cambio. Mantén la regla (no cuesta nada) pero no presupuestes ahorros para ella. El diagnóstico: una densidad por debajo de 1.0 no significa que las llamadas que podrían agruparse no lo estén. ~45% de los turnos no hacen ninguna llamada a herramienta — son turnos de razonamiento/narración — y la mayoría del resto son genuinamente secuenciales (editar → compilar → leer error → corregir). El desperdicio recuperable son turnos que no producen ninguna llamada a herramienta, que es un problema de verbosidad de salida, no un problema de agrupación. Si atacas esto, ataca la verbosidad (longitud de pensamiento, narración entre pasos), y mide las llamadas/turno para verificar que lo has movido.
3. Mantén la salida de comandos grandes fuera del contexto — medido 4,262 tokens → ~2 por ejecución completa de pruebas. La salida completa de dotnet test es de ~17K caracteres y se relee en cada turno posterior. Indica: registra en un archivo, pon solo EXIT + conteos en contexto, grepea el archivo solo en caso de fallo. Prohíbe explícitamente canalizar el comando a través de tail/head — eso trunca la evidencia y aún cuesta turnos. Alcance honesto: la reducción por ejecución es exacta y verificada, pero la ganancia agregada depende de la frecuencia con que un worker ejecute la suite. El resultado Bash individual más grande cayó de 25.2K → 10.5K caracteres en el A/B, mientras que el volumen total de resultados de herramientas por turno apenas se movió (722 → 710 caracteres) — porque el issue del A/B era una tarea de documentación que rara vez ejecuta pruebas. Espera el beneficio real en issues con muchas pruebas.
4. Escala el modelo según la tarea — real pero dependiente del nivel, según token-economics.md: débil entre medio y pequeño ($0.419/Mtok vs $0.168/Mtok ≈ 2.5×); fuerte entre superior y medio ($2.376/Mtok vs $0.419/Mtok ≈ 5.7×). Vale la pena priorizar para trabajo transversal; menos impactante para errores rutinarios. Enruta por etiquetas de issue (adapta los nombres al trío pequeño/medio/superior del runtime, ej. Haiku/Sonnet/Opus):
| Forma del issue (por etiqueta) | Nivel |
|---|---|
docs/plantillas/manifiesto, regeneración de formato e instantáneas, priority:low+effort:S protecciones de una línea | pequeño (ej. Haiku) |
la mayoría de errores: emisor/validador/analizador, protecciones, TypeScript de estudio, CLI, LSP — effort:S/M; issues grandes por defecto | medio (ej. Sonnet) |
| un nivel inferior falló al poner en verde este issue | superior (ej. Opus), escalada reactiva (una vez) |
| transversal (muchas áreas/emisores), ambiguo/diseño — trabajo que un mantenedor sabe que es difícil | superior (ej. Opus), último recurso predictivo |
El orquestador (tú) se mantiene en el modelo superior, pero mantén su contexto por turno pequeño (palanca 2).
5. Reduce lo que se relee en cada turno.
- Recorta el preámbulo fijo — se paga en cada turno de cada worker.
CLAUDE.mda 44KB (~11K tok) costó 52M tokens en una ejecución de un solo archivo; mueve el material de referencia de deploy/secrets/kubectl a documentos enlazados y deja un puntero. - Sin TaskList por issue — crece sin límite y se reinyecta en cada turno. El archivo de estado es tu única memoria de trabajo.
- Compacta deliberadamente, con una cadencia contada — no por una sensación. El entero de cadencia tiene un único hogar, references/token-economics.md § The two budgets; el Paso 4 lo dispara desde el contador de fusiones del archivo de estado, el mismo campo contado que la cadencia de reencuesta ya usa. No repitas el número aquí —
tests/auto-dev-cost-budgets/test.shfalla la compilación si lo haces. Por qué contado: el coste es Σ(contexto × turnos), por lo que la cola de una ejecución es superlineal, y la regla que esto reemplaza — un porcentaje/contexto una cadencia tan floja que nunca se disparó dentro de una ejecución de 19 fusiones — no acotó nada y costó $213 en una sola sesión. Siempre compacta con una directiva de enfoque, ej./compact keep the slot→issue/PR map, merge counter, queue order, filed follow-ups. Primera acción después de cualquier compact //clear/loopre-fire: vuelve a leer el archivo de estado. - Mantén los INFORMES FINALES de los workers breves — se releen en cada turno de reconciliación posterior.
- Delega lecturas pesadas a subagentes
Exploredesechables — el volcado de archivo muere con el subagente en lugar de montar tu contexto. - Lanza la sesión del SUPERVISOR ligera — los subagentes heredan el conjunto MCP del supervisor, por lo que cada servidor conectado a tu sesión monta cada turno de cada worker. La eliminación MCP por worker ya no está disponible (la herramienta Agent no tiene configuración MCP por creación); recórtalo una vez, donde lo lanzas.
6. Toma menos turnos (cada ida y vuelta relee todo el contexto).
- Agrupa llamadas a herramientas independientes en un solo turno (lecturas/greps/
ghparalelos). - Deja que los scripts colapsen consulta+clasifica —
scripts/survey.sh,scripts/reconcile.sh. - No sondees con cadencia corta a menos que una fusión sea inminente — una activación innecesaria relee todo, y una pasada la TTL de caché de ~5 min paga una escritura de caché completa (1.25×), no una lectura (0.1×).
- Acota la sesión, no solo el turno. La agrupación se probó A/B y no se movió (palanca 2), por lo que la optimización por turno está casi agotada y la longitud de la sesión es la variable que queda — las 3 mejores de 37 sesiones de worker fueron el 32% de todo el coste de los workers, y ni la etiqueta de esfuerzo ni el nivel predijeron cuáles tres. Por lo tanto, los workers de la Fase 1 llevan un presupuesto de turnos (el entero vive en references/token-economics.md § The two budgets, no aquí) y entregan en él con
STATUS: PARTIAL; el Paso 4 los reanuda en un subagente nuevo, que es donde está el ahorro — una reanudación deSendMessagemantiene el contexto que el presupuesto existe para descartar. Este es el mecanismo de la palanca 1, la única victoria verificada de la sección, aplicada en una costura de longitud en lugar de una costura de fase.
Mídelo — nunca afirmes que una palanca funciona sin un A/B. Tres scripts, todos tomando un directorio de transcripciones de sesión .jsonl:
scripts/usage_report.py— tokens + equivalente en $ por modelo. Rastrea tokens/fusión y $/fusión. ⚠️ Agrega TODO el directorio del proyecto incluyendo ejecuciones pasadas — primero haz un symlink de una ejecución a un directorio temporal, manteniendo la estructura: el archivo<sid>.jsonlde la sesión del supervisor más su directorio<sid>/subagents/(<proj>/<sid>/subagents/agent-*.jsonles donde vive cada transcripción de worker, por lo que la flota de una ejecución se encuentra bajo un id — elige el id del archivo de estado o de las marcas de tiempo degh; mtime no es fiable). Un montón plano de symlinksagent-*.jsonlse lee como0 sub-agenty no empareja nada.scripts/analyze_cache.py— turnos/sesión, contexto al inicio vs pico, contexto promedio por turno, y volumen de resultados de herramientas por herramienta. Aquí es donde ves por qué una sesión es cara.scripts/measure_phase2.py— empareja las transcripciones de subagentes de fase 1 y fase 2 de cada issue (por elISSUE:de sus líneas de informe) y divide el coste en fase de implementación vs fase de fusión; en una transcripción previa a 2.0, encuentra el turno de entrega de fusión dentro de la sesión. Esto es lo que demostró la palanca 1.
Dos métricas llevan la mayor parte de la señal: contexto promedio por turno (¿están hinchados los turnos tardíos?) y llamadas a herramientas por turno (¿están haciendo algún trabajo los turnos? línea base ~0.55 — ver palanca 2).
Cómo funciona
┌─────────────────────── auto-dev (tú, el supervisor) ───────────────────────┐
│ archivo de estado: cola (pequeño→medio), espacios en vuelo, completados, archivados │
│ en cada señal → reconciliar vs GitHub → finalizar fusionados + rellenar → mantener N funcionando │
└───────────────────────────────────────────────────────────────────────────────┘
│ despacho (aislado por área) ▲ informe estructurado / notificación inactiva
▼ │
Worker A ─ implement-issue → [listo] ⇢ NUEVO subagente ─ merge-pr ─ informe ┐
Worker B ─ implement-issue → merge-pr ─ informe ─┤ N agentes en segundo plano, un issue cada uno,
Worker C ─ implement-issue → merge-pr ─ informe ─┘ retirados al fusionar, reemplazados desde la cola
Los workers son subagentes en segundo plano generados con la herramienta Agent. Comunícate a través de sus informes estructurados — el mensaje final de un subagente es su informe, entregado a ti cuando regresa — mediante notificaciones inactivas, y por SendMessage a uno que aún se está ejecutando; nunca leas sus archivos de transcripción sin procesar (<proj>/<tu-sesión>/subagents/agent-*.jsonl) — la salida de un worker es un registro enorme que explotará tu contexto. Confía en el informe