Lição 04 · Alembic Completo v3 · Coda, Mission e Forge: os gates ← índice
Alembic Completo v3 · Módulo 3 · A execução

Coda, Mission e Forge: os gates

Uma run do Alembic não "termina" — ela atravessa cancelas: Scope → Council → Proof → Validator → Publish. Cada unit.proof[] vira comando real que precisa sair 0; trabalho arriscado estaciona em T4 até um humano decidir; e o plano inteiro é determinístico por construção — a VM recusa Date.now() e Math.random() antes de executar uma linha. É a materialização do Proof Gate do loop-engineering: nenhum progresso sem prova.

1

O pipeline de 5 gates

Cada gate tem dono e arquivo: ① Scope (packages/forge/src/scope.ts:37, loadScope) copia GOAL.md, plan module e contrato para o run-dir — a run carrega o próprio escopo; ② Council (packages/mission/src/council-gate.ts:79, runCouncilGate) é o GO/NO_GO opcional de pré-voo; ③ Proof (packages/coda/src/proof.ts:26, runProofGate) exige exit 0 de cada prova; ④ Validator (packages/coda/src/validator.ts:105, runValidatorGate) escrutina por milestone com quem NÃO construiu; ⑤ Publish (packages/coda/src/publish.ts:63, runPublishGate) gera e publica o curso visual-teach.

fusao · 17-the-gate-pipeline · s0

Pense como… as eclusas de um canal: o barco (a run) só sobe de nível quando a câmara anterior FECHOU e encheu por completo — não existe "meio-eclusa". Onde quebra: eclusa atrasa todo barco igualmente; aqui o Council e o Validator podem ser dispensados por configuração (skipScrutiny/skipUserTesting) quando o risco não justifica.

#GateFunção · quem falha fechadoFonte
ScopeMaterializa GOAL.md + plan + contrato no run-dirforge/src/scope.ts:37
CouncilGO/NO_GO opcional de pré-voomission/src/council-gate.ts:79
ProofCada unit.proof[] com exit 0 — senão errcoda/src/proof.ts:26
ValidatorEscrutínio independente por milestonecoda/src/validator.ts:105
PublishGera e publica o curso visual-teachcoda/src/publish.ts:63
2

Proof Gate: prova é comando com exit 0

No plan module, cada string de unit.proof[] vira uma task bash -c que depende da unit. O gate (runProofGate) então: lê os estados do journal de eventos append-only — e não do checkpoint, porque "the gate reads task states from the append-only event journal so it survives checkpoint overwrites" (proof.ts:22–24); filtra as tasks com metadata.kind === 'proof' (proof.ts:43–49); agrega por unit e persiste units/<id>/proof-results.jsonl (proof.ts:75–88); e se QUALQUER prova falhou, retorna err com o resumo — a run falha fechada (proof.ts:90–96).

unit u1 proof: ["pnpm -r typecheck", "pnpm -w test"] tasks bash -c metadata.kind='proof' dependem da unit events.jsonl journal APPEND-ONLY checkpoint.json sobrescrito — NÃO é a fonte runProofGate agrega por unit e grava units/<id>/proof-results.jsonl todas done? ok : err (fecha a run) exit ≠ 0 em UMA prova ⇒ Proof Gate failed: unit=… command="…" (proof.ts:90–96)
proof.ts: a fonte de verdade é o journal append-only (sobrevive a sobrescritas de checkpoint entre runSwarm); a saída é persistida por unit e o gate falha fechado.
3

T4 park: o humano no circuito

Nem tudo deve rodar sozinho. No swarm, classifyPark (packages/swarm/src/park.ts:38) inspeciona cada task antes da execução; o que cair na regra — tier T4 ou marcador legal/segurança (park.ts:17) — é estacionado e journalado, nunca descartado (orchestrator.ts:245–260). O resgate é um ciclo de comandos com trilha de auditoria: alembic propose <run-id> reabre os parkeados como proposta; alembic approve --task-id registra a decisão em approvals.jsonl no run-dir; alembic reject registra em rejections.jsonl. A decisão humana também é um registro append-only.

Cache SHA-256 e replay

Determinismo paga dividendos aqui: a chave de cache de h.agent()/h.swarm() é sha256(JSON estável de {prompt, opts}) (computeCacheKey, packages/vm/src/cache.ts:20–21), guardada em <runDir>/workflows/<wf-id>/cache.json (cache.ts:23–24). Mesmo prompt + mesmas opts = mesmo resultado sem nova chamada; --no-cache pula leitura e escrita. E como TUDO relevante vive em events.jsonl + cache, alembic replay <run-id> re-executa/retoma a run a partir do disco; --resume valida goal/plan/contrato contra o meta.json antes de reutilizar o run-dir.

4

A VM recusa o não-determinístico

Antes de importar seu alembic.plan.ts, runPlan (packages/vm/src/run-plan.ts:53–65) lê o FONTE e roda o cheque de determinismo: para .ts, um sweep por regex (checkDeterminismTs, run-plan.ts:16–28) proíbe Date.now(), new Date() e Math.random(); para JS, o checkDeterminism de @alembic/mission parseia com Acorn. Reprovou → a run morre com "plan module … is non-deterministic" antes de qualquer efeito.

fusao · 28-determinism-and-replay · s1
Conservador de propósito O sweep de .ts é regex sobre o texto — pega Date.now() até dentro de comentário ou string. O doc assume o trade-off: "a false positive is safer than allowing non-determinism into a resumable plan" (run-plan.ts:12–14). Precisa de tempo ou aleatório? Receba um clock/seed injetado pelos hooks — nunca do ambiente.
5

--coordinated: veredito multi-lente ADITIVO

O flag --coordinated de alembic run liga um irmão do Validator: runCoordinatedValidatorGate (packages/coda/src/coordinated-validator.ts:476). Primeiro assessRiskTier (:167) classifica a unit em trivial | lite | full (riskTierSchema, :53); o tier escolhe as lentes (LENSES_BY_TIER, :140) que rodam sobre o mesmo artefato, além dos cheques determinísticos (runDeterministicChecks, :242); os achados deduplicados (dedupeFindings, :195) viram nota PERFECT | VERIFIED | PARTIAL | FAILED (:61) e daí um veredito pass | needs-review | fail (:57), gravado em units/<id>/coordinated-verdict.json. O ponto de arquitetura: é aditivo — nunca muda a decisão do council e nunca falha a run (offline por default; sem adapter, roda só o piso determinístico). Observabilidade extra, zero risco novo.

unit diff + goal assessRiskTier trivial · lite · full lentes por tier LENSES_BY_TIER + cheques determinísticos · offline ok achados → dedupeFindings PERFECT/VERIFIED/ PARTIAL/FAILED → pass/needs-review/fail coordinated- verdict.json ADITIVO: nunca muda a decisão do council, nunca falha a run — só registra
coordinated-validator.ts: risco → lentes → nota → veredito por unit; um segundo par de olhos que observa sem poder de veto.
6

Forge: 7 passos de prompt cru a escopo executável

alembic forge "<prompt>" roda o front-end de 7 passos registrados em packages/forge/src/front-end/index.ts:22–28: grill (afia escopo + critérios de aceite em SCOPE.md) → research (contexto/restrições) → prototype (decisão registrada de prototipar ou não) → prdissuesgoal (GOAL.md com done-when) → review. O resultado materializa um diretório de escopo com GOAL.md + alembic.plan.ts + contrato — exatamente o trio que o Scope Gate copia para dentro da run e que alembic run --goal GOAL.md --plan alembic.plan.ts --yes executa.

5
gates: Scope, Council, Proof, Validator, Publish
7
passos do forge: grill → … → review
19
ADRs em docs/adr/ registrando as decisões
7

Cheque seu modelo mental

Uma das provas de unit.proof[] sai com exit 1. O que o Proof Gate faz?
Correto: proof.ts:90–96 — qualquer prova sem status done entra em failed e o gate retorna err('Proof Gate failed: unit=… command=…'). Antes disso ele SEMPRE persiste units/<id>/proof-results.jsonl (a evidência fica, mesmo na falha). Não há retry no gate: prova é determinística ou não é prova.
Seu alembic.plan.ts tem Date.now() — mas só dentro de um comentário. O que o runPlan faz?
Correto: para .ts o cheque é checkDeterminismTs — regex sobre o texto-fonte (run-plan.ts:16–28), que "may flag occurrences inside comments/strings, but a false positive is safer" (run-plan.ts:12–14). O caminho Acorn/AST existe, mas para módulos JS via checkDeterminism de @alembic/mission. Apague o comentário e siga.
Camada técnica — comandos copy-paste

O ciclo completo de uma run com gates (o --coordinated é aditivo e offline):

# rodar um escopo Forge (Scope → … → Publish)
alembic run --goal GOAL.md --plan alembic.plan.ts --yes
alembic run --goal GOAL.md --plan alembic.plan.ts --coordinated --yes

# o ciclo T4: reabrir, aprovar, rejeitar (tudo vira journal)
alembic propose <run-id>
alembic approve <run-id> --task-id <unit-id>
alembic reject  <run-id> --task-id <unit-id>

# retomar/replayar do disco (events.jsonl + cache SHA-256)
alembic replay <run-id>
alembic run --goal GOAL.md --plan alembic.plan.ts --resume <run-id> --no-cache --yes

# ver a recusa de não-determinismo na fonte
sed -n '16,28p' packages/vm/src/run-plan.ts

# evidências de uma run
cat <runDir>/units/<unit-id>/proof-results.jsonl
cat <runDir>/units/<unit-id>/coordinated-verdict.json

Regra de leitura: prova persiste MESMO quando falha — o run-dir é o dossiê completo, não só o troféu.

O que levar desta lição
Pergunta de acompanhamento sugerida: "quem garante que os flags e caminhos que digitei chegam íntegros até esses gates?" — Última lição: a superfície CLI — 33 comandos, 47 formas, o padrão args→commands→index, e a doutrina que faz um comando errado custar $0.