Hot Path: Factory ADW Loop (o meta-ciclo que evolui o Alembic)
Este é o caminho mais meta do sistema: o próprio Alembic usando o engine para melhorar a si mesmo. pnpm factory executa um loop ADW (Plan → Implement + Review paralelo em worktrees isolados → Publish PR) sobre issues GitHub `ready-for-agent`, com sandboxes Docker, gates completos (typecheck/build/test/impeccable) e prompts versionados em `.factory/`.
Visão Geral do Loop ADW (SVG)
Estágios do Loop ADW (Stepper)
Estágio 1 — Entrada do Loop (.factory/run.ts:22)
22|for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
23| console.log(`=== Iteration ${iteration}...`);
25| const plan = await factory.run({ ... plan-prompt.md });
...
152| await factory.run({ ... merge-prompt.md });
168|}
Estágio 2 — Planner (.factory/run.ts:26 + plan-prompt.md)
26|const plan = await factory.run({
27| sandbox: docker(),
28| name: "Planner",
29| agent: AGENT, // claude-opus-4-8
30| promptFile: "./.factory/plan-prompt.md",
31|});
33|const planMatch = plan.stdout.match(/<plan>(.*?)<\/plan>/);
38|const { issues } = JSON.parse(...);
Estágio 3 — Execução Paralela com Limite (.factory/run.ts:52)
52|let running = 0;
53|const queue = [];
54|const acquire = () => running < MAX_PARALLEL ? ... : new Promise...
68|const settled = await Promise.allSettled(
69| issues.map(async (issue) => {
70| await acquire();
71| try {
72| await using sandbox = await factory.createSandbox({...});
83| const result = await sandbox.run({ implement-prompt.md ... });
95| if (result.commits.length > 0) await sandbox.run({ review-prompt.md });
...
Estágio 4 — Implementer (por issue)
83|const result = await sandbox.run({
84| name: "Implementer #" + issue.number,
85| agent: AGENT,
86| promptFile: "./.factory/implement-prompt.md",
87| promptArgs: { ISSUE_NUMBER, ISSUE_TITLE, BRANCH },
});
Estágio 5 — Reviewer (apenas se houve commits)
95|await sandbox.run({
96| name: "Reviewer #" + issue.number,
97| promptFile: "./.factory/review-prompt.md",
98| promptArgs: { ... },
});
Estágio 6 — Publisher (merge-prompt.md)
153|await factory.run({
154| sandbox: docker(),
155| name: "Publisher",
156| promptFile: "./.factory/merge-prompt.md",
157| promptArgs: { BRANCHES, ISSUES },
});
Anotações Linha-a-Linha Críticas
| Arquivo:linha | O que faz | Importância |
|---|---|---|
.factory/run.ts:22 | Loop principal de iterações | Controla todo o ciclo de auto-evolução |
.factory/run.ts:72 | factory.createSandbox + worktree + docker | Isolamento (invariante de segurança) |
.factory/run.ts:83 | sandbox.run para Implementer | Executa o agente com prompt + args |
.factory/run.ts:95 | Reviewer só roda se houve commits | Economia + qualidade |
packages/factory/src/Orchestrator.ts | Motor genérico por trás de factory.run | Effect layers, streaming, timers, resume |
.factory/CODING_STANDARDS.md | Invariantes que o Reviewer caça | Consistência do projeto |
Como Verificar (verify) Este Hot Path
# Requer .factory/.env com ANTHROPIC_API_KEY + GH_TOKEN # e imagem Docker construída pnpm factory # Observar: # - Planner emite <plan> com issues # - Workers em sandboxes paralelas (MAX_PARALLEL=4) # - Commits só acontecem após gates completos (typecheck + build + test + pnpm detect) # - Reviewer roda adversarial (caça invariantes) # - Publisher abre PRs (nunca força push em main protegida)
Para inspeção mais profunda, adicione logs ou pause após cada fase e inspecione os worktrees criados em `/tmp` ou equivalente.
Common Confusions + Practice Task
Confusão: "O Factory é só um script externo". Falso. Ele é um cidadão de primeira classe do sistema: usa o mesmo harness, council, adapters e invariantes que o engine de destilação. É a prova viva de que o motor é suficientemente poderoso para se auto-melhorar.
Prática: 1. Leia .factory/run.ts completo (linhas 22-170). 2. Compare o acquire/release de concorrência (linhas 52-66) com o TaskQueue do swarm (packages/swarm/src/queue.ts). 3. Abra packages/factory/src/Orchestrator.ts e veja como o "run" genérico abstrai o que o .factory/run.ts orquestra em alto nível (Effect layers, streaming, resume, sandbox lifecycle). 4. Crie uma issue de teste com label ready-for-agent e rode pnpm factory (em ambiente seguro) — observe o fluxo completo de Planner → Implementer → Reviewer → Publisher.
Exercício de compreensão profunda: Por que o Reviewer só roda se o Implementer produziu commits? Qual o risco de rodar Reviewer sempre? Como o sistema garante que o CODING_STANDARDS.md (Result nunca-lança, no any, 2 spaces, named exports, ≤50 loc/fn, conventional commits) é realmente respeitado em produção?
Este hot path é único porque é o único lugar onde o engine consome a si mesmo de forma sistemática para produzir melhorias no código-base. Entender suas linhas é entender como o Alembic pretende se manter vivo e evoluindo com mínima intervenção humana.
Fontes chave para estudo adicional: packages/factory/src/run.ts (API pública run + orchestrate), packages/factory/src/Orchestrator.ts:1 (loop de iterações com timers e streaming), packages/factory/src/SandboxFactory.ts (criação de worktrees isolados + bind mounts), .factory/plan-prompt.md, .factory/implement-prompt.md e .factory/review-prompt.md (os contratos reais dados aos agentes), e .factory/CODING_STANDARDS.md (o documento que o Reviewer usa como régua). Este ciclo fecha o loop de auto-melhoria do projeto.