SwarmForge a fondo: cómo funciona realmente el enjambre de Uncle Bob
Seis agentes de IA, seis worktrees de git, una cola de mensajes duradera y un conjunto de barreras de calidad que son comandos de shell en lugar de buenas intenciones. La parte de tmux es lo menos interesante de todo.
El problema para el que está construido
Dale a un solo agente de programación una funcionalidad real y escribirá la implementación y las pruebas de un tirón, desde el mismo entendimiento y con los mismos puntos ciegos. Si leyó mal el requisito, las pruebas codifican esa mala lectura y pasan. Pídele a ese mismo agente que revise su trabajo y estará de acuerdo consigo mismo, porque el razonamiento que produjo el código sigue en su contexto y sigue pareciendo sólido. El volumen lo empeora en lugar de mejorarlo: la salida es plausible, abundante y barata, así que la persona que revisa se convierte en el cuello de botella y empieza a leer por encima. SwarmForge apuesta por una respuesta concreta a eso: la calidad no puede venir del autor, así que cada disciplina de revisión recibe su propio agente, su propio contexto, su propio árbol de trabajo y una comprobación que termina en cero o no termina.
La decisión de diseño que sostiene todo lo demás no es el paralelismo. Es que los roles se comunican solo a través de código commiteado. Un agente revisor nunca ve la explicación del autor sobre por qué el código está bien: ve un commit y un nombre de tarea, y ejecuta sus propias herramientas contra ellos.
Qué es, mecánicamente
SwarmForge es un armazón de shell y Babashka sobre primitivas que la mayoría de los equipos ya tiene. Cada rol es una ventana de tmux que ejecuta una CLI de agente contra su propio worktree de git bajo .worktrees/, así que nunca dos agentes tocan el mismo directorio de trabajo. El comportamiento viene de texto plano: una constitution.prompt que reclama precedencia sobre todo lo demás y le dice al agente que lea y obedezca cada archivo de swarmforge/constitution/articles/ al arrancar y en cada tarea, más un prompt de rol en swarmforge/roles/<role>.prompt. Los artículos compartidos cubren reglas de ingeniería, de traspaso y de flujo de trabajo; los artículos locales son donde un proyecto los sobrescribe. La comunicación es una cola basada en archivos que pertenece a un demonio, y los dos únicos tipos de mensaje que un agente puede enviar son un traspaso de git y una nota. El script ./swarm es solo un arranque delgado: descarga el archivo de scripts si falta el directorio y luego cede el paso a swarmforge/scripts/swarmforge.sh.
Tres formas de enjambre
Cada rama es una respuesta distinta a cuánto proceso merece una tarea. main es documental; las topologías ejecutables viven en las ramas pack. El flujo es un anillo, no una cola.
two-pack
coder → cleaner → coder
Un coder que trabaja test-first y un cleaner que hace limpieza, revisión de CRAP y DRY, y correcciones de arquitectura. El bucle más pequeño que aún separa escribir de juzgar, y la única forma cuyo coste se justifica con facilidad en trabajo ordinario.
four-pack
specifier → coder → refactorer → architect → specifier
Las especificaciones de aceptación en Gherkin entran al principio. Un refactorer limpia sin cambiar el comportamiento y sube la cobertura, y un architect revisa la estructura y la dirección de las dependencias antes de que el anillo vuelva a la especificación.
six-pack
specifier → coder → cleaner → architect → hardener → QA
Añade una pasada de endurecimiento que muta el código para encontrar dónde está ciega la suite, y un rol de QA independiente que verifica a través de la interfaz de usuario. Cuatro de los seis roles funcionan en modo lote para que las herramientas se amorticen sobre una banda de prioridad entera.
Cómo recorre el anillo un cambio de verdad
Este es el six-pack, y conviene leerlo como una tubería de criterios de salida más que como una lista de puestos. Cada fila es un prompt de rol del repositorio, y cada condición de salida es un comando que tiene que terminar bien.
specifier
→ coder- Recibe
- Una petición de la persona, en el worktree master
- Hace
- Escribe las especificaciones de aceptación en Gherkin y la especificación de la suite QA de extremo a extremo, pregunta donde la intención es ambigua, y poda los parámetros de ejemplo hasta los valores que de verdad afectan a la mutación de aceptación.
- Criterio de salida
- No commitea hasta que la persona aprueba explícitamente. Esa es la única barrera humana del anillo, y está al principio, donde resulta más barata.
coder
→ cleaner- Recibe
- Un traspaso de git con un commit y un nombre de tarea estable
- Hace
- Escribe pruebas unitarias enfocadas que expresan el comportamiento pedido y, en palabras del propio prompt del rol, fallarían ante una implementación equivocada plausible. Después escribe solo el código de producción necesario para que pasen. Las pruebas de aceptación generadas no se aceptan explícitamente como sustituto de las unitarias.
- Criterio de salida
- La verificación local pasa. No ejecuta mutación, CRAP ni DRY: eso pertenece a roles posteriores, para que el coder no pueda calificar su propio trabajo.
cleaner
→ architect- Recibe
- Un lote de traspasos de igual prioridad
- Hace
- Ejecuta primero la herramienta CRAP y baja la complejidad a 6 o menos, luego la herramienta DRY para quitar duplicación, luego la de mutación solo en modo escaneo y recuento —partiendo cualquier archivo que supere 100 sitios de mutación— y sube la cobertura donde es razonable.
- Criterio de salida
- Comportamiento intacto, pruebas en verde, complejidad y duplicación reducidas. Prohibido explícitamente ejecutar pruebas de mutación o añadir comportamiento.
architect
→ hardener- Recibe
- Un lote de commits ya limpios
- Hace
- Reparte el código en módulos con fronteras reales, mantiene las dependencias apuntando hacia dentro, caza ciclos y fugas de framework, y aísla la política de aplicación de la UI, el sistema de archivos, la base de datos y la red. Añade comprobaciones automáticas de arquitectura donde es práctico.
- Criterio de salida
- Comportamiento preservado y suite en verde. Prohibido ejecutar git merge a mano: la fusión ocurre solo a través de ready_for_next.sh.
hardener
→ QA- Recibe
- Un lote de commits revisados estructuralmente
- Hace
- Ejecuta la herramienta de mutación del lenguaje archivo por archivo, de forma diferencial contra los manifiestos existentes, con hasta ocho trabajadores en paralelo, y arregla los mutantes supervivientes antes de seguir. Después una pasada de mutación de aceptación Gherkin en nivel soft, después CRAP, después DRY, en ese orden exacto.
- Criterio de salida
- Cada herramienta de la cadena debe estar limpia antes de que corra la siguiente. Este es el rol que decide si las pruebas prueban algo.
QA
→ specifier- Recibe
- Un lote de commits endurecidos
- Hace
- Verificación final independiente: la especificación de aceptación, la suite de extremo a extremo conducida por la interfaz de usuario sin atajos de API, pruebas unitarias y de propiedades, y comprobaciones de release del proyecto. Reproduce cualquier fallo antes de cambiar código.
- Criterio de salida
- Vuelve a ejecutar CRAP y DRY antes de terminar. Si la suite de QA contradice al Gherkin o a las unitarias, se detiene y pregunta a una persona en lugar de elegir un ganador.
El transporte es la parte inusual
La mayoría de los marcos de agentes deja que los agentes hablen entre sí. SwarmForge se niega a propósito: un demonio posee la entrega, el sistema de archivos es la cola, y tmux solo sirve para dar un toque a una ventana inactiva.
La topología cabe en un archivo de configuración
confEl six-pack que se entrega pone cada rol en el mismo backend con el bypass de permisos activado y marca toda la mitad final del anillo como consumidora de lotes. El nombre del rol debe coincidir con el del archivo de prompt, que en este repositorio se escribe hardender.
# swarmforge/swarmforge.conf
# window-invisible <role> <agent> <worktree> [task|batch] [extra-cli-args...]
window-invisible specifier codex master --yolo
window-invisible coder codex coder --yolo
window-invisible cleaner codex cleaner batch --yolo
window-invisible architect codex architect batch --yolo
window-invisible hardender codex hardender batch --yolo
window-invisible QA codex QA batch --yolo La cola es un directorio, y la ubicación es el estado
textNo hay base de datos ni broker en memoria. La posición de un traspaso en el árbol es su estado, el nombre del archivo ordena por prioridad y luego por hora, y las cabeceras llevan el rastro de auditoría. Un enjambre caído se reanuda leyendo el disco.
.swarmforge/handoffs/
outbox/
tmp/ # drafts land here, then get renamed in atomically
sent/
failed/ # malformed or undeliverable, with diagnostics
inbox/
new/
in_process/
completed/
# filename sorts the queue for you
<priority>_<timestamp>_<sequence>_from_<sender>_to_<recipients>.handoff
# priority 00-99, lower first; UTC YYYYMMDDTHHMMSSZ Un agente solo puede pedir, nunca entregar
shEl agente escribe un borrador con cuatro cabeceras y llama al script de la barrera. No puede escribir id, from, recipient ni ninguna marca de tiempo: están reservadas, así que la procedencia en el rastro de auditoría no puede falsificarla lo que está siendo auditado. Tampoco teclea un SHA: el script canoniza y valida el commit como un objeto real e inequívoco de diez caracteres.
# ./tmp/handoff.txt — drafted inside the assigned worktree
type: git_handoff
to: hardender
priority: 00
task: task-1-cave-setup
# hand it to the protocol gate; the daemon does delivery
swarm_handoff.sh ./tmp/handoff.txt
# receiving side, driven by the role's mode in .swarmforge/roles.tsv
ready_for_next.sh # -> TASK: / BATCH: / NO_TASK, plus the payload
done_with_current.sh # -> stamps completed_at, then pulls the next item Las barreras que el hardener debe pasar, en orden
shEsto es lo que hace del enjambre algo más que un juego de rol. La constitución instala estas herramientas al arrancar, recién traídas de los repositorios del autor —crap4go, crap4java y crap4clj para complejidad, mutate4go, clj-mutate y mutate4java para mutación, y la familia dry4* para duplicación— y el prompt del rol fija el orden en que corren.
# hardener: nothing advances until the previous check is clean
mutate4go ./... # one file at a time, differential, <= 8 workers
gherkin-mutator --level soft # mutate the acceptance examples too
crap4go ./... # complexity against coverage
dry4go ./... # duplication
# then, and only then
swarm_handoff.sh ./tmp/handoff.txt # to: QA Por qué cada mecanismo tiene esa forma
Leídas como ingeniería, la mayoría de las decisiones que parecen raras son defensas contra modos de fallo concretos de los agentes.
El mensaje es un commit, no una explicación
Un traspaso de git lleva un nombre de tarea y un commit validado. No puede llevar el argumento del autor sobre por qué el código es bueno, porque un argumento invita al siguiente agente a estar de acuerdo con él. Un commit invita en cambio a verificar. Es la idea más transferible del proyecto.
Los avisos son genéricos y pueden perderse
La notificación de tmux del demonio solo dice que ha llegado correo y que se ejecute ready_for_next.sh si estás libre. Nunca nombra un archivo, así que un agente no puede elegir el elemento interesante y saltarse el orden de la cola, y un agente ocupado puede ignorarla sin riesgo porque terminar una tarea también trae la siguiente.
Las notas se limitan a ochenta caracteres y se desaconsejan
Un agente solo puede mandar una nota libre si una persona, el prompt del rol o la constitución lo indican explícitamente. Ante ambigüedad o contradicción, la instrucción es parar y preguntar a alguien. Es una negativa deliberada a dejar que los agentes negocien requisitos entre ellos, que es justo donde los montajes multiagente se descarrilan en silencio.
Cada rol tiene un worktree, no solo una rama
El aislamiento está en el sistema de archivos, así que toda la clase de fallos en que dos agentes editan el mismo archivo en el mismo instante no puede ocurrir. También deja cada rol inspeccionable por separado mientras trabaja, lo que importa más de lo que parece cuando intentas entender qué hizo un enjambre.
La mitad final del anillo consume lotes
Cleaner, architect, hardener y QA toman todos los traspasos de la misma prioridad como una unidad. Las corridas de mutación, de cobertura y las comprobaciones de arquitectura son caras por invocación y baratas por archivo extra, así que el lote es la diferencia entre una barrera que se ejecuta y una que se desactiva.
El estándar es un árbol de prompts con precedencia explícita
constitution.prompt reclama autoridad, los artículos llevan las reglas, los artículos locales las sobrescriben para el proyecto, los prompts de rol se colocan encima, y se le dice al agente que lo relea todo en cada tarea. Tu estándar de código deja de ser un documento sobre el trabajo y pasa a ser una entrada del trabajo.
El veredicto
La mitad valiosa de SwarmForge es la constitución y el orden de las barreras: roles con nombre y una sola responsabilidad, criterios de salida que son comandos ejecutables, y una regla dura de que quien escribe un cambio nunca lo califica. Esa mitad es genuinamente buena, es en espíritu independiente del lenguaje, y puedes implementarla este trimestre en la CI que ya operas, sin tmux por ningún lado. La otra mitad, el demonio y la cola de archivos duradera, está construida con esmero y resuelve sobre todo un problema que puedes evitar: si tus barreras corren en CI sobre un pull request, obtienes durabilidad, rastro de auditoría y orden por prioridad gratis, con herramientas que tu equipo ya mantiene.
Léelo como una implementación de referencia de un flujo de trabajo, no como una plataforma que adoptar. Empieza por el two-pack para notar si separar roles ayuda a tu trabajo, toma prestada la cadena de barreras en cualquier caso, y ve al anillo de seis roles solo cuando el coste de un defecto supere claramente el de seis ejecuciones de agente por cambio.
Lo que acierta
- + Las barreras de calidad son comandos con umbrales —mutación, CRAP, DRY, cobertura— en lugar de adjetivos en una guía de estilo
- + Quien revisa nunca ve el razonamiento del autor, solo un commit, y es la única manera de que una revisión hecha por un agente valga algo
- + El orden corresponde a una secuencia real de ingeniería: especificar, implementar, limpiar, reestructurar, endurecer, verificar de forma independiente
- + El aislamiento por worktree elimina la corrupción por edición concurrente por construcción, no por bloqueos
- + El estado de la cola vive en disco con un rastro de auditoría que los agentes son estructuralmente incapaces de falsificar, así que una caída se reanuda y una ejecución se reconstruye
- + La única barrera de aprobación humana está en el momento de la especificación, cuando cambiar de opinión es más barato
- + Todo es texto plano observable: ventanas que puedes leer, prompts que puedes editar, una cola que listas con ls
Lo que te cuesta
- − La configuración que se entrega ejecuta cada agente con bypass de permisos, así que todo el diseño supone que estás dispuesto a dejar a seis agentes ejecutar comandos sin supervisión en tu repositorio
- − Seis ejecuciones de agente por cambio es económicamente absurdo para trabajo pequeño, y nada en el anillo decide que una tarea merece menos proceso
- − La cadena de herramientas ejecutables son los propios proyectos crap4*, mutate4* y dry4* del autor para Go, Clojure y Java: fuera de esos lenguajes el contrato de arranque de la constitución no aplica y aportas tus equivalentes
- − Reinstalar esas herramientas desde GitHub en cada arranque es lento, dependiente de la red y una superficie de cadena de suministro que ahora es tuya
- − zsh, tmux y Babashka en macOS es el camino feliz; en Windows implica WSL y una capa adaptadora de terminal
- − La regla de reenvío obliga a un rol a pasar el trabajo aguas abajo haya cambiado algo o no, así que el anillo genera tráfico incluso cuando una etapa no hizo nada
- − Los prompts de rol no son cumplimiento forzoso: nada impide que un rol se salte su propia barrera salvo la frase que se lo prohíbe, así que las garantías reales valen lo que valga tu copia en CI
- − Está visiblemente en marcha: un panel, un indicador de calor, un vigilante de ventanas y ramas pack divergentes, con main deliberadamente no ejecutable
Qué tomar prestado aunque nunca lo ejecutes
Nunca dejes que el autor califique el trabajo
- - Ejecuta las herramientas de calidad en un paso separado, con contexto separado del que escribió el código
- - Dale al paso de revisión el diff y las herramientas, no la justificación del autor
- - En flujos con agentes esto no es higiene de proceso, es la diferencia entre una revisión y un sello
Convierte cada barrera en un código de salida
- - Complejidad, duplicación, cobertura y mutantes supervivientes tienen herramientas que devuelven distinto de cero
- - Fija el orden en que corren y detén la tubería en la primera que falle
- - Un agente actúa correctamente ante un comando que falla y de forma vaga ante un párrafo de consejos
Traspasos estrechos, validados y auditables
- - Una referencia de commit más una línea corta obliga a que la intención esté en el código y en el mensaje
- - Valida en la frontera para que una petición mal formada falle antes de que el paso siguiente gaste una ejecución
- - Mantén los campos de procedencia fuera del alcance del emisor si quieres que el rastro de auditoría signifique algo
Mantén el estándar donde ocurre el trabajo
- - Las reglas escritas como artículos de prompt se leen en cada tarea, al contrario que una página de wiki que nadie abre
- - Separa las reglas compartidas de las sobrescrituras locales para que la excepción de un equipo no sea la regla de todos
- - Versiónalas con el código y revisa sus cambios como código
El flujo de trabajo es la aportación
Quita tmux, Babashka y la instalación por tarball y queda una afirmación sobre la ingeniería de software: las disciplinas que mantienen el código habitable son separables, cada una merece su turno con sus propias instrucciones, y ninguna puede ejercerse con credibilidad por la parte que escribió el código. Eso era cierto antes de los agentes. Lo que los agentes cambian es lo que está en juego, porque el volumen de salida subió y la persona que revisa no se volvió más rápida.
Así que toma las partes que sobreviven a la traducción. Nombra tus pasadas y dale a cada una un solo trabajo. Convierte cada criterio de salida en un comando. Pon la barrera humana en el momento de la especificación. Niégale al autor de un cambio cualquier papel en juzgarlo. Que esa tubería sean seis ventanas de tmux, dos personas o un archivo de CI con cinco trabajos ordenados importa mucho menos que si las barreras existen y de verdad se ejecutan.
Artículos de ingeniería relacionados
Los roles hardener y cleaner se apoyan en dos prácticas que conviene entender por separado, sobre todo si juzgas código escrito por un agente.
Las pruebas de mutación son negativas. Las de TDD, positivas.
Por qué una ejecución de mutación solo informa de lo que una suite no detecta, cómo ejecutarla de forma asequible y cómo juzgar pruebas que un LLM escribió para su propio código.
La métrica CRAP: hallar complejidad sin probar
Para qué sirve CRAP, cómo lo usa QA para dirigir pruebas y poner barreras de release, y cómo juzgar si un LLM escribe código mantenible.
Preguntas frecuentes
¿Qué hace falta para ejecutar SwarmForge?
zsh, git, tmux y Babashka, más una CLI de agente configurada como Claude, Codex, Copilot o Grok. No hay servicio en la nube ni capa de orquestación que levantar: el enjambre son ventanas de tmux que puedes mirar, un worktree por rol en disco y una cola de archivos de texto.
¿Con qué rama debería empezar un equipo?
two-pack. Dos roles bastan para saber si separar el escribir del juzgar ayuda a tu trabajo, y el coste de un anillo de seis roles es muy difícil de justificar antes de saberlo. main es documental y no ejecuta ningún enjambre.
¿Es seguro ejecutar agentes con bypass de permisos?
Es la mayor pregunta operativa que el diseño te deja abierta. La configuración entregada pasa banderas de bypass a cada rol, y eso es lo que hace posible un anillo sin supervisión. Si lo pruebas, hazlo en un clon desechable o en un contenedor sin credenciales, y mantén las barreras de calidad reales en CI, donde el enjambre no pueda saltárselas.
¿Solo funciona para Go, Clojure y Java?
La orquestación es independiente del lenguaje; las barreras ejecutables no. La constitución nombra las herramientas de mutación, CRAP y DRY del propio autor para esos tres lenguajes. En otros stacks conservas la estructura de roles y sustituyes equivalentes, como Stryker o PIT para mutación y cualquier informe de complejidad más cobertura para el cálculo de CRAP.
¿Un enjambre de agentes elimina la necesidad de QA?
No, y el diseño no lo pretende. Asciende la QA a un rol con nombre, con scripts ejecutables y una regla explícita de parar y preguntar a una persona cuando la suite de QA contradice la especificación. Alguien sigue teniendo que saber qué le debe el producto a sus usuarios, y alguien sigue firmando la release.
¿Cuál es la idea que más merece copiarse?
Que el agente que escribió el código es el peor juez posible de ese código, y que la solución es un contexto separado con una herramienta que devuelve un código de salida. Todo lo demás en el repositorio es un detalle de implementación de esa frase.