Curso / Lição 17
Lição 17 · Motor & método

A pipeline de gates

Uma run não "executa e termina". Ela atravessa uma sequência de gates — Scope, Council, Proof, Validator, Publish — e cada um pode detê-la. Uns são pré-voo, um fecha a run, outro é opcional, o último exige um humano. Juntos são a disciplina que transforma "o agente produziu algo" em "o agente produziu algo verificado". No fim você vai conseguir, de cabeça, dizer qual gate barra o quê — e por que o ReviewGate do ciclo de aprendizado (lições 4 e 8) é membro exato da mesma família.

Leia primeiro (fonte primária — no próprio repositório)
packages/coda/src · proof.ts · validator.ts · publish.ts + packages/mission/src/council-gate.ts + packages/forge/src/scope.ts

Cada número e cada linha de código desta lição foi lida literalmente desses arquivos (rodapé). Por que importa pra missão: os gates são o que faz a autonomia do Alembic ser segura — sem eles, "o agente fez" não significa "está certo".

Objetivos desta lição
  • Definir gate e fail-closed: o padrão é sempre "não prosseguir / estacionar para humano", nunca "assumir OK".
  • Nomear os cinco gates em ordem e dizer, para cada um, o que ele barra e quando (pré-voo, durante, no ship).
  • Explicar por que o Proof Gate lê o journal de eventos e não o checkpoint.
  • Distinguir Council Gate (pré-voo) de Validator Gate (pós-trabalho) e situar o ReviewGate (scoreThresholdGate) na mesma família.
0
gates em torno de uma run
0
proof não-zero que passa
0,7
limiar do ReviewGate (sedimentar)
T4
aciona o veto/parking humano

01 · O que é um "gate" — e o que "fail-closed" significa

Pense num gate como uma catraca de metrô: ela só abre se você apresentar a prova certa (o bilhete). Sem bilhete, ela fica fechada — esse é o padrão. Um gate de software faz o mesmo: ele recebe uma evidência, decide GO ou NO_GO, e na dúvida fica fechado. É isso que "fail-closed" quer dizer: se algo falha, dá erro, ou é ambíguo, o resultado padrão é não deixar passar, não "passar por garantia".

Por que fail-closed (e não fail-open): num sistema autônomo, o pior cenário não é "uma run boa foi barrada por engano" — é "uma run ruim foi entregue/publicada porque o gate, na dúvida, deixou passar". Barrar a mais é recuperável (um humano reabre); deixar passar a mais pode ser irreversível. Por isso todo gate aqui erra para o lado de fechar.

A FORMA UNIVERSAL DE UM GATE · um losango fail-closed (todos os 5 têm essa forma)
evidência entra a prova é suficiente? SIM · GO ✓ prossegue próximo gate NÃO / dúvida / erro ✗ fail-closed → err / estaciona p/ humano (o PADRÃO)

Guarde essa silhueta: nas seções seguintes, cada um dos cinco gates é uma instância dela. Muda qual evidência entra e qual pergunta o losango faz — a forma fail-closed é sempre a mesma.

A mesma ideia em duas camadas

Antes de descer ao código, fixe o conceito nos dois níveis. Clique para alternar entre a explicação simples e a precisa — é a mesma regra, contada para dois leitores diferentes.

Imagine uma fechadura de porta corta-fogo: quando falta energia, ela tranca sozinha — nunca destrava. O projetista escolheu o estado seguro como padrão. Um gate fail-closed é igual: se a evidência não chega, se um comando dá erro, se a resposta é ambígua, o gate assume "não passa". Você nunca precisa lembrar de "trancar"; o sistema já nasce trancado e só abre com a prova certa na mão.

Por quê? Porque os dois erros possíveis não são iguais. Barrar uma run boa por engano incomoda, mas é reversível: um humano olha e reabre. Deixar passar uma run ruim pode quebrar algo no mundo — e isso, às vezes, não tem volta. Na dúvida, o sistema prefere o erro que dá para desfazer.

Em termos de tipos, todo gate é uma função que devolve um Result<T, Error> (o contrato fail-closed de @alembic/contracts): o caminho de sucesso é explícito (ok(...)) e qualquer outro caminho — exceção capturada, evidência ausente, veredito negativo — colapsa para err(...). Não existe um terceiro estado "provavelmente ok". O chamador (o núcleo do harness) propaga o err e a run para; nenhum gate "degrada para aviso e segue".

Operacionalmente isso se traduz em três desfechos só: prossegue (próximo gate), falha a run fechada (err — ex.: Proof/Scope) ou estaciona para humano (t4-parked.jsonl — ex.: Validator/Publish). A assimetria é deliberada: é o ADR-0005 levado ao código — o passo irreversível exige a assinatura de uma pessoa; tudo que é reversível roda sozinho.

02 · A pipeline, em ordem

Aqui está o caminho inteiro de uma run, da rampa de entrada ao ship. Leia da esquerda para a direita: cada caixa é um gate, e abaixo da fileira está a anotação de onde o ReviewGate do ciclo de aprendizado se encaixa (seção 09).

OS CINCO GATES EM SEQUÊNCIA · da run ao ship · cada um pode parar tudo
① Scope materializa a run-dir rampa de entrada ② Council GO/NO_GO opcional pré-voo ③ Proof unit.proof[] · fail-closed determinístico ④ Validator council independente + painel verificador ⑤ Publish estaciona se fechado (gate humano) ↓ o ReviewGate do ciclo de aprendizado (scoreThresholdGate 0,7) é um gate da MESMA família os 5 acima governam o que uma RUN pode entregar; o ReviewGate governa o que uma run finalizada pode SEDIMENTAR em memória/skills (lições 4 e 8) regra de ouro de todos eles: o padrão é "não prosseguir / estacionar", nunca "assumir OK"
Pré-voo vs durante vs ship: ① Scope e ② Council acontecem antes do trabalho (preparam e autorizam). ③ Proof e ④ Validator acontecem depois que as units rodaram (verificam o que foi produzido). ⑤ Publish é o passo voltado para fora — o único que um humano assina.
Opcional ≠ supérfluo: o Council Gate é opcional (acionado por --council / config do plano), mas o mesmo princípio é imposto dentro do núcleo do harness — no fanout, um NO_GO faz curto-circuito antes de qualquer worker (seção 04).

03 · ① Scope Gate — materializa o diretório da run

A rampa de entrada. loadScope(input) (forge/src/scope.ts) copia o GOAL.md, o módulo de plano e o contrato de validação para um diretório de run content-addressed e semeia seu layout. Pense numa obra que recebe uma planta: antes de a primeira parede subir, o canteiro precisa estar montado — fundação, almoxarifado, diário de obra. O Scope Gate é esse canteiro.

SCOPE · de 3 entradas para o layout completo da run-dir (createNewScope, scope.ts:151–269)
GOAL.md alembic.plan.ts validation-contract loadScope() cria run-dir content-addressed runs/<id>/ semeada council/units/park/ workflows/course/reports/ + meta.json · tasks.json + index.json · run-state.json + LOOP-LOG.md + review.md meta.json guarda goal+planPath+contract → é a âncora do resume (próximo diagrama)

A regra-chave: um resume não pode trocar o escopo

Aqui está o ponto de segurança do Scope Gate. Quando você retoma uma run com --resume <run-id>, o goal/plan/contract de agora são comparados com o meta.json salvo. Se qualquer um diverge, ele retorna err('resume mismatch: …'). Você não consegue, por acidente, re-escopar uma run que está retomando — o que evita "continuar" uma run com objetivos diferentes dos originais.

FLUXOGRAMA · resume com escopo divergente é barrado (loadExistingScope, scope.ts:106–114)
--resume <run-id> lê o meta.json salvo goal == meta.goal? planPath bate? contract bate? TODOS sim ✓ retoma journal+cache mantidos QUALQUER diverge ✗ err('resume mismatch: …')
Lembre da Lição 16: determinismo + content-addressing fazem a run ser replayável. O meta.json é onde o escopo fica gravado — e o resume-mismatch é a invariante que impede você de "trocar a planta no meio da obra".

04 · ② Council Gate — veto de pré-voo opcional

runCouncilGate (mission/src/council-gate.ts) roda um board antes de o trabalho começar e retorna uma CouncilDecision agregada (lê consensus.decision). NO_GO significa que a missão não deve prosseguir. É a reunião que decide se o projeto sequer começa — não uma revisão do que ficou pronto. É opcional, mas o núcleo do harness impõe a mesma ideia internamente.

FLUXOGRAMA · no fanout, um NO_GO faz curto-circuito antes de qualquer worker (harness/src/core.ts:200–214)
fanout(phase) council roda primeiro decisão do board? NO_GO ✗ fase para · nenhum worker despachado ≠ NO_GO ✓ execute(swarm) aí sim os workers rodam "um board que não dá sinal verde não deve gerar trabalho autônomo" — comentário literal em core.ts
O board é deliberadamente plural: o DEFAULT_MISSION_BOARD_YAML tem três papéis — optimist, pragmatist e um contrarian (que empurra contra risco, ambiguidade e ações irreversíveis). A decisão não é de um modelo só; é um consenso. Isso é o tema inteiro da Lição 18.

05 · ③ Proof Gate — a espinha determinística

Este é o gate que faz "funciona" significar algo. Cada string unit.proof[] numa missão compila para uma task de comando bash -c que depende da task da unit (compiler.ts:140–157). O Proof Gate lê os estados dessas tasks e falha a run fechada em qualquer saída não-zero. É a diferença entre "o agente disse que fez" e "um comando real saiu 0".

Preveja antes de continuar
Numa missão, uma unit tem proof: ['pnpm -r typecheck', 'pnpm -w test']. Quantas tasks essa unit gera no spec compilado, e que tipo de comando cada proof vira?
Três tasks: 1 task de worker (a unit) + 2 tasks de proof. Cada proof vira ['bash', '-c', '<a string>'] com dependsOn: [unit.id] e metadata.kind: 'proof' (compiler.ts:140–157). Se você chutou "uma task que roda os dois comandos", repare: cada proof é sua própria task, indexada por proofIndex — por isso o gate consegue dizer exatamente qual proof falhou.

Como a unit vira tasks (a compilação)

COMPILAÇÃO · uma unit com 2 proofs → 1 task de worker + 2 tasks bash -c (compiler.ts:107–161)
unit u1 proof:[typecheck, test] task u1 (worker) roleHint:'worker' task u1-proof-0 ['bash','-c','pnpm -r typecheck'] task u1-proof-1 ['bash','-c','pnpm -w test'] dependsOn:[u1] metadata.kind:'proof' unitId · proofIndex ↑ é por isso que o gate sabe QUAL proof falhou

O código do gate, condensado

O laço do gate é deliberadamente curto: toda task kind: 'proof' precisa ter saído 0 (status === 'done'); qualquer falha entra num resumo e o gate retorna err. Sem retry, sem degradar para aviso.

// packages/coda/src/proof.ts:55–96 (condensado) — falha fechado, lê o journal
const results = proofTasks.map((task) => {
  const state = stateById.get(task.id);                       // estado vindo do journal
  const outcome = state?.status === 'done' ? 'complete' : 'failed';
  return { unitId: task.metadata.unitId, proofIndex: task.metadata.proofIndex, outcome };
});
// persiste em units/<unitId>/proof-results.jsonl, depois:
const failed = results.filter((r) => r.outcome === 'failed');
if (failed.length > 0) return err(new Error(`Proof Gate failed: ${summary}`)); // run falha fechada

Por que ler o journal e não o checkpoint? (comparativo)

Um detalhe sutil e crucial: o gate lê os estados das tasks do journal de eventos (store.readEvents()), não do checkpoint. O journal é append-only: nada nele é sobrescrito. O checkpoint, sim — uma chamada posterior de runSwarm que compartilha o store pode reescrever o checkpoint.json. Veja o contraste:

JOURNAL (append-only) vs CHECKPOINT (sobrescrito) · por que o gate confia no journal
checkpoint.json sobrescrito a cada runSwarm runSwarm #1 grava: proof = done runSwarm #2 SOBRESCREVE o arquivo ✗ estado do proof pode sumir ler daqui seria frágil events.jsonl (journal) append-only · nada é apagado #1 anexa: task-state proof=done #2 ANEXA mais eventos (não apaga) ✓ todo task-state retido o gate lê DAQUI → robusto Mesmo proof, duas fontes — o registro durável é o journal. Resultados persistem em units/<unitId>/proof-results.jsonl.
A encarnação do "nenhum claim sem prova"
Este é o Proof Gate em nível de motor da disciplina que você viu por todo o curso: nenhum claim conta sem um comando real saindo 0. As outras checagens (Validator) são qualitativas; esta é determinística — ou o comando saiu 0, ou não saiu.

06 · ④ Validator Gate — quem constrói não valida

runValidatorGate (coda/src/validator.ts) roda um council independente de validadores mais um painel verificador (verifyPanel) sobre a evidência de cada milestone. A frase que abre o arquivo diz tudo: "Who builds must not validate." O agente que produziu o trabalho nunca é o que assina embaixo. É como um artigo revisado por pares: o autor não é o revisor.

SEPARAÇÃO · o worker produz; um board SEPARADO revisa a evidência (validator.ts:21–27, 98–148)
worker produz a evidência council de validadores verifyPanel (verificador) ↑ independentes do worker verified E não estacionado? sim ✓ emite approved=true NO_GO / rejeitado → estaciona p/ humano

O critério de emissão é estrito: no código, approved é true apenas quando panel.verdict === 'verified' && panel.parkedTier === undefined. Verificado e não estacionado. Qualquer outra coisa — NO_GO, painel rejected, ou um tier que precisa de aprovação — estaciona para revisão humana.

A costura fusion para T4: a primeira coisa que runValidatorGate faz é if (options.t4 && options.fusion) return options.fusion(options) (validator.ts:108–110). Unidades T4 / alto-risco podem ser desviadas para um validador de fusão de alta confiança; quando ausente, o painel verificador trata todos os tiers. O gate é injetado por unit nos casos T4 ou que têm proof (validator.ts:256–257).

07 · ⑤ Publish Gate — estaciona quando fechado

Qualquer publicação voltada para fora — o curso visual-teach, um manifesto — deve passar por este gate (coda/src/publish.ts). É o único passo irreversível da pipeline (uma vez público, não volta), então é deliberadamente o que um humano assina. É o botão vermelho com tampa: a tampa é o gate.

FLUXOGRAMA · approved decide: publica (gist obrigatório + Pages opcional) ou estaciona (publish.ts:63–103)
runPublishGate(artefato) aprovação humana já dada? approved? false ✗ anexa a t4-parked.jsonl → decision:'parked' true gist (OBRIGATÓRIO) sem gist publisher → err Pages (se fornecido) decision:'published'
Isso é o ADR-0005 em código: "The human gate sits at ship / irreversible spend." A pipeline roda autônoma por todo o caminho reversível (uma Signal é um registro, um plano é texto, código vai para uma branch descartável); o último gate humano fica no ship. Fechado, o artefato espera em t4-parked.jsonl — e você o reabre com alembic approve/propose.

Por que o gate humano fica exatamente aqui

A posição do ⑤ Publish não é arbitrária — ela cai na fronteira entre o que se desfaz e o que não se desfaz. Tudo à esquerda dessa linha é reversível e roda sozinho; o ship é o primeiro passo irreversível, e por isso é o único que pede uma pessoa (ADR-0005).

A LINHA DA IRREVERSIBILIDADE · tudo reversível roda autônomo; o ship pede um humano (ADR-0005)
ZONA REVERSÍVEL · roda autônoma IRREVERSÍVEL Signal é só um registro plano é só texto código branch descartável ⑤ GATE HUMANO a fronteira ship público → não volta gasto real deploy/ads erro recuperável: um humano reabre com alembic approve/propose default fail-closed → T4-park "o último gate humano fica no ship e em qualquer gasto real" — ADR-0005

08 · Simulador: passe uma run pelos cinco gates

Agora teste a sua intuição. Clique em cada gate para alternar o veredito dele entre GO e NO_GO. O contador mostra quantos gates a run passou antes de ser barrada, e o diagrama acende até onde ela chegou. Lembre da regra fail-closed: o primeiro NO_GO já para tudo.

✓ a run passou todos os gates e foi entregue.

Repare: pôr o ② Council em NO_GO para a run no gate 1 (ela nem chega ao Proof) — exatamente o curto-circuito do fanout. E mesmo todos os 4 primeiros em GO, um ⑤ Publish fechado estaciona em vez de publicar.

Leia o simulador · 3 cenários para conferir sua intuição
1
Tudo GO. 5/5 passados → a run roda, prova, é validada e publica. O caminho feliz.
2
③ Proof em NO_GO. 2/5 → Scope e Council passaram, mas um proof saiu não-zero: o gate retorna err e a run falha fechada. Validator e Publish nem rodam.
3
Só ⑤ Publish em NO_GO. 4/5 → trabalho feito e verificado, mas sem aprovação humana o artefato estaciona em t4-parked.jsonl. Nada foi publicado — e nada se perdeu.

09 · O ReviewGate do aprendizado é da mesma família

Aqui a lição fecha o ciclo com as lições 4 e 8. O passo de aprendizado do pacote de fusão é protegido por um ReviewGate — e ele é um membro exato desta família de gates. Os cinco gates acima governam o que uma run pode entregar; o ReviewGate governa o que uma run finalizada pode sedimentar em memória e skills. Mesma filosofia fail-closed, aplicada ao auto-aperfeiçoamento do motor: aprenda só com vitórias validadas.

FLUXOGRAMA · só uma proposta com score ≥ 0,7 sedimenta (scoreThresholdGate, hermes/learning/gate.ts:24–36)
proposta (run finalizada) com um score 0..1 score ≥ 0,7? (limiar inclusivo) sim ✓ sedimenta MEMORY.md / USER.md não ✗ rejeitada e registrada com motivo
Por que é "a mesma família" e não "outra coisa"
O scoreThresholdGate(0,7) é o baseline conservador; o keystone (ADR-0018) troca-o pelo próprio Validator Gate da coda via createValidatorReviewGate — ou seja, o gate de aprendizado pode literalmente ser o Validator Gate da seção 04. Por isso a matriz de fusão chama o ciclo de aprendizado de CLONE que "compõe com o validator gate" em vez de substituí-lo (ADR-0006 + ADR-0018).

10 · Council vs Validator — o comparativo que mais confunde

Os dois rodam um council; por isso é fácil achar que são a mesma coisa. Não são. Um decide se começar; o outro decide se o que foi produzido pode entregar. Veja lado a lado:

COUNCIL GATE vs VALIDATOR GATE · pré-voo (antes) vs revisão (depois)
② Council Gate QUANDO · antes do trabalho (pré-voo) SOBRE · o goal / o spec DECIDE · começar a missão? opcional · curto-circuita o fanout ④ Validator Gate QUANDO · depois do trabalho SOBRE · a evidência produzida DECIDE · o que foi feito pode emitir? independente · quem constrói não valida

Toda a família num mapa só

Council e Validator são dois membros de uma família de seis. Este mapa comparativo posiciona todos eles em duas dimensões: quando agem (pré-voo → durante → ship → pós-run) e como falham fechado (param a run com err, ou estacionam para um humano). Repare no padrão: os dois últimos da linha — Publish e ReviewGate — são os que tocam o irreversível e o auto-aperfeiçoamento, e ambos escalam para humano.

MAPA DA FAMÍLIA · 6 gates × (quando atua) × (modo de falha fechada)
tempo na vida de uma run → ↑ falha a run (err) ↓ estaciona p/ humano pré-voo durante / pós-units ship pós-run ① Scope resume mismatch → err ③ Proof proof não-zero → err ② Council NO_GO → nem começa ④ Validator ≠verified → estaciona ⑤ Publish approved=false → estaciona ReviewGate score < 0,7 → não sedimenta determinísticos / estruturais — sem julgamento humano qualitativos — escalam para uma pessoa

E para fixar a família inteira de uma vez, a tabela abaixo cruza os cinco gates por quando, o que barra e onde no código:

GateQuandoO que barra (fail-closed)Fonte
① Scoperampa de entradaresume que troca o escopo → err('resume mismatch')forge/src/scope.ts
② Councilpré-voo (opcional)NO_GO → missão não começa; fanout não despacha workermission/src/council-gate.ts
③ Proofdepois das unitsqualquer proof[] não-zero → err, run falha fechadacoda/src/proof.ts
④ Validatordepois das unitsverified & não-estacionado é a única emissão; senão estacionacoda/src/validator.ts
⑤ Publishno shipapproved=falset4-parked.jsonl (gate humano, ADR-0005)coda/src/publish.ts
ReviewGatepós-run (aprendizado)score < 0,7 (ou Validator NO_GO) → não sedimentacoda/src/learning-gate.ts

11 · Caso resolvido: um proof falha numa run real

Junte tudo num caso concreto. Uma unit u1 tem proof: ['pnpm -r typecheck', 'pnpm -w test']; o typecheck quebra. Siga o que cada gate faz — passo a passo — e depois um exercício é seu.

Exemplo resolvido · o typecheck de u1 sai não-zero — onde a run para?
1
① Scope. A run-dir é materializada; goal/plan/contract copiados; não é resume, então sem mismatch. passa.
2
② Council. Suponha que o board deu GO de pré-voo (ou o gate estava desligado). passa. Os workers são despachados.
3
compilação. u1 virou 3 tasks: a worker + u1-proof-0 (typecheck) + u1-proof-1 (test), ambas dependsOn:[u1].
4
③ Proof. O gate lê o journal: u1-proof-0 tem status ≠ 'done'outcome:'failed'. Persiste tudo em units/u1/proof-results.jsonl e retorna err('Proof Gate failed: unit=u1 index=0 …').
5
Veredito. A run falha fechada no gate 3. ④ Validator e ⑤ Publish não rodam — sem prova determinística, não há nada para validar nem publicar.
Agora você: mesma unit, mas todos os proofs saem 0 e é uma unidade T4. Qual gate ainda pode estacioná-la para um humano, e por quê? Pense antes de revelar.
O ④ Validator Gate (e depois o ⑤ Publish). Mesmo com proofs verdes, T4 desvia para a costura fusion (validator.ts:108–110); e a emissão só ocorre com verified & parkedTier === undefined — um tier irreversível parka. Se chegar a publicar, o ⑤ Publish ainda exige approved=true (ADR-0005). Lição: proofs verdes são necessários, não suficientes — o lado qualitativo e o gate humano continuam valendo.
"Proof e Validator são redundantes." Não. Proof é determinístico (um comando saiu 0?); Validator é qualitativo e independente (a evidência convence um board que não a produziu?). Um não substitui o outro — são camadas complementares.
"Publish só escreve o artefato." Só se o gate estiver aberto. Fechado, ele estaciona em t4-parked.jsonl para um humano — a ação irreversível é deliberadamente a que exige uma pessoa.

12 · Como isso se encaixa

Você dissecou os cinco gates por dentro. Agora dê um passo atrás: onde essa pipeline liga no resto da máquina? Os gates não são um módulo isolado — são a membrana que envolve toda execução. À esquerda deles está tudo que produz uma run (o loop fechado escolhe a unidade, a cintura estreita roteia, o swarm executa); os gates ficam no meio, peneirando; e à direita está o que sai aprovado — o artefato entregue e o combustível que volta para o ciclo de aprendizado. Repare que o ReviewGate do aprendizado é a mesma silhueta fail-closed (seção 09): a pipeline não termina o ciclo, ela o guarda em dois pontos.

A PIPELINE DE GATES NA TUBULAÇÃO · o que ALIMENTA → ESTES gates → o que eles LIBERAM · clique para percorrer
o que PRODUZ a run loop fechado escolhe a unidade (Lição 04) cintura estreita roteia (Lição 14) swarm executa as units (Lição 19) trabalho produzido ESTES gates (Lição 17) ① Scope · materializa a run-dir ② Council · veto de pré-voo (Lição 18) ③ Proof · unit.proof[] fail-closed ④ Validator · council independente ⑤ Publish · gate humano (Lição 10 · T4) cada um fail-closed · o 1º NO_GO para tudo só o aprovado artefato entregue código mesclado / curso publicado ReviewGate (Lição 08) mesma família fail-closed só vitória validada sedimenta a run aprovada também ALIMENTA o aprendizado → Upstream = quem produz (Lições 04 · 14 · 19). Esta peça = a membrana de 5 gates. Downstream = o que sai aprovado. O ⑤ Publish e o ReviewGate são os dois gates que escalam para um humano — os outros falham a run com err. É a mesma disciplina fail-closed peneirando a run em DOIS pontos: o que pode ENTREGAR, e o que pode SEDIMENTAR.

Onde você está na metodologia: as Lições 01–03 montaram o motor, a engenharia reversa do Hermes e a matriz de fusão; as Lições 14–19 detalham a cintura estreita, o funil, esta pipeline de gates, o Council e o swarm que executam uma run. Esta Lição 17 é a peça que decide se o que foi executado pode seguir adiante — em cada fronteira (começar, entregar, publicar, sedimentar). Para ver as 30 peças no mesmo mapa e como cada uma liga na seguinte, abra o mapa interativo da metodologia.

As peças que esta pipeline conecta — cada link abre o mergulho na peça vizinha, e a frase diz por que elas se tocam:
  • Lição 04 · O loop fechadoo ciclo que vem DEPOIS: ele só roda sobre uma run que passou Proof + Validator, e reusa o próprio Validator Gate desta lição como ReviewGate (ADR-0018) — por isso auto-aplicar foi rejeitado, pra não contornar o gate.
  • Lição 08 · reviewAndLearno passe gated detalhado: o scoreThresholdGate(0,7) da seção 09 esmiuçado linha a linha, e como o keystone o troca pelo Validator Gate da coda — a prova de que o ReviewGate é da MESMA família.
  • Lição 10 · ClarifyGateway (T4)o mecanismo do gate humano: quando o ④ Validator ou o ⑤ Publish estacionam algo, é a fronteira T4 que segura — o passo irreversível que pede uma pessoa (ADR-0005).
  • Lição 18 · Council & Verifiero board plural por dentro: o ② Council Gate e o painel verificador do ④ Validator são instâncias dele — optimist, pragmatist e contrarian deliberando, nunca um modelo só.
  • Lição 14 · A cintura estreitao que ALIMENTA os gates upstream: os contratos do @alembic/contracts que roteiam o trabalho até as units cujos proof[] o ③ Proof Gate depois verifica.

13 · Na prática

Chega de diagrama — eis a pipeline como comandos reais. Você não chama cada gate à mão: eles disparam, em ordem, quando você executa uma run com escopo. O comando canônico é o mesmo da Lição 04, só que aqui o foco é assistir os gates dispararem:

# Executa uma run com escopo: os 5 gates disparam em ordem (Scope → Council → Proof → Validator → Publish).
# --offline mantem tudo hermetico e $0 (adapter offline deterministico); --yes nao para para confirmar.
alembic run --goal GOAL.md --plan alembic.plan.ts --offline --yes

# saida tipica (resumida) — cada gate anuncia seu veredito; o 1o NO_GO faz a run falhar fechada:
#   scope: run-dir materializada em .alembic/runs/<run-id>/
#   proof gate: 2/2 ok          ← cada unit.proof[] saiu 0
#   validator gate: verified    ← council independente aprovou a evidencia
#   run complete: ok
# se um proof sair nao-zero, em vez disso:
#   proof gate: FAILED unit=u1 index=0   → a run para aqui (err), Validator/Publish nem rodam

O ③ Proof Gate não é uma flag — ele nasce do unit.proof[] que você escreve no plano. Cada string vira uma task bash -c que depende da unit (seção 05). É assim que você declara "o que prova esta unidade":

// dentro de alembic.plan.ts — cada string de proof[] vira uma task bash -c que o ③ Proof Gate verifica.
const result = await h.mission({
  title: 'mission title',
  tier: 'T2',
  units: [
    {
      id: 'u1',
      title: 'Implement feature X',
      proof: ['pnpm -r typecheck', 'pnpm -w test'],   // ← 2 proofs → 2 tasks → o gate exige saida 0 em ambas
    },
  ],
  milestones: [{ id: 'm1', title: 'Milestone one' }],
});

E para ligar o passe coordenado do Validador — a peça ADITIVA da seção 06 que roda o veredito multi-lente por tier de risco além do council gate (offline por padrão), sem nunca mudar a decisão nem fazer a run falhar — basta a flag --coordinated:

# Adiciona o passe coordenado do Validador (ADITIVO): grava um veredito sibling por unit,
# mas NUNCA muda a decisao do council gate e NUNCA faz a run falhar (offline por padrao).
alembic run --goal GOAL.md --plan alembic.plan.ts --coordinated --offline --yes

# cada unit ganha um arquivo extra de veredito:
#   .alembic/runs/<run-id>/units/<unit-id>/coordinated-verdict.json

Fonte da forma exata: apps/cli/src/args.ts (as flags offline, coordinated, yes de runArgsSchema) e a seção "Gate pipeline" do CLAUDE.md — o --coordinated roda runCoordinatedValidatorGate sobre as mesmas units e grava units/<id>/coordinated-verdict.json, ADITIVO ao council gate. [uncertain] as linhas de saída acima são ilustrativas da forma "gate: veredito" (não verbatim de um log) — o que é garantido pelo código é o comportamento: Proof falha fechado em saída não-zero e o coordinated-verdict.json é gravado por unit.

EXPERIMENTE · assista os 5 gates dispararem numa run real (offline, $0)
  1. Clone e entre no repo, depois garanta o build verde:
    git clone <repo> alembic && cd alembic · pnpm -r typecheck && pnpm -r build && pnpm -w test
  2. Gere um escopo mínimo (cria GOAL.md + alembic.plan.ts + contrato), cujo plano já traz uma unit com proof[]:
    alembic plan "um passo trivial que so roda um teste"
  3. Rode a run, hermética, e assista os gates:
    alembic run --goal GOAL.md --plan alembic.plan.ts --offline --yes
  4. O que procurar na saída: os vereditos em ordem (scope → proof → validator). Se um proof falhar, a run para naquele ponto e o Validator/Publish não rodam — esse é o fail-closed da seção 05.
  5. O que procurar no dir da run: abra .alembic/runs/<run-id>/ e veja units/<unit-id>/proof-results.jsonl (o registro durável de cada proof, seção 05). Se você passou --coordinated, abra também units/<unit-id>/coordinated-verdict.json.
  6. Prove o fail-closed: edite o plano para um proof[] que falha de propósito (ex.: 'bash -c "exit 1"') e rode de novo. O ③ Proof Gate retorna err e a run inteira falha fechada — nada à direita dele roda.
Faça na mão · qual comando/peça para cada intenção?
1
"Quero ver os gates dispararem numa run."alembic run --goal GOAL.md --plan alembic.plan.ts --yes (adicione --offline para hermético e $0).
2
"Quero que esta unidade só passe se um comando sair 0." → declare o comando em unit.proof[] no alembic.plan.ts; o ③ Proof Gate o compila numa task bash -c e exige saída 0.
3
"Quero uma segunda lente de validação por tier de risco, sem mudar a decisão." → adicione --coordinated: grava coordinated-verdict.json por unit, aditivo e não-fatal.
Agora você: rodou alembic run … --coordinated --yes e o coordinated-verdict.json de uma unit veio com um veredito negativo, mas a run terminou verde mesmo assim. Bug ou esperado? Decida antes de revelar.
Esperado. O passe --coordinated é aditivo: ele só registra um veredito sibling em units/<id>/coordinated-verdict.json e nunca muda a decisão do council gate nem faz a run falhar (CLAUDE.md, "Gate pipeline"). Quem barra de verdade são o ③ Proof e o ④ Validator — o coordenado é observabilidade extra, não um gate fail-closed a mais. Lição: nem toda checagem é um gate: distinga o que decide (fail-closed) do que apenas registra.

Fixe os conceitos (flashcards)

Clique pra virar. Tente lembrar a resposta antes de virar — recuperar fixa mais que reler.

Conceito
O que "fail-closed" significa num gate?
clique pra virar ↻
Resposta
Na dúvida/falha/erro, o padrão é NÃO prosseguir (err / estaciona p/ humano) — nunca "assumir OK". Barrar a mais é recuperável; deixar passar a mais pode ser irreversível.
Proof Gate
Por que ele lê o journal e não o checkpoint?
clique pra virar ↻
Resposta
O checkpoint.json é sobrescrito por uma chamada posterior de runSwarm que compartilha o store; o events.jsonl é append-only e retém todo task-state. O journal é o registro durável.
Validator Gate
Qual é a condição exata de emissão?
clique pra virar ↻
Resposta
approved === truepanel.verdict === 'verified' && panel.parkedTier === undefined. Verificado E não-estacionado. Senão: parka p/ humano.
ReviewGate
O que ele governa, e qual o limiar default?
clique pra virar ↻
Resposta
O que uma run finalizada pode SEDIMENTAR em memória/skills. Default scoreThresholdGate(0,7) (inclusivo); o keystone troca pelo próprio Validator Gate da coda. "Aprenda só com vitórias validadas."

Revisão cumulativa — recupere de memória

Antes de clicar: responda de cabeça. As opções têm tamanhos parecidos — sem pista pela forma.

1. O comando proof[] de uma unit sai com código não-zero. O que o Proof Gate faz?
Correto: b. Toda task metadata.kind === 'proof' deve estar done (saída 0); qualquer falha entra num resumo e o gate retorna err, falhando a run fechada. a contradiz o fail-closed: proofs são a espinha determinística, não degradam para avisos. c inventa um retry que não existe no código — não há repetição. d erra o escopo: o gate avalia todos os proofs e falha se qualquer um falhou; não há "pular e seguir".
2. Por que o Proof Gate lê os estados das tasks do journal de eventos em vez do checkpoint?
Correto: c. Um store compartilhado pode ter seu checkpoint.json sobrescrito por uma chamada posterior de runSwarm, mas o events.jsonl append-only retém todo evento task-state. a e b inventam motivos (criptografia, tamanho) que não aparecem no código. d é falso: o checkpoint existe — o ponto é justamente que ele é sobrescrito, e por isso o gate não confia nele.
3. O Validator Gate existe além do Proof Gate. O que ele acrescenta que os proofs não dão?
Correto: d. Proofs são checagens determinísticas de comando; o Validator Gate adiciona uma revisão qualitativa independente ("who builds must not validate"), estacionando para um humano em NO_GO ou painel rejeitado. a erra: as camadas são complementares (uma determinística, outra qualitativa). b inventa — o gate revisa a evidência, não re-executa os proofs. c confunde com o swarm: o Validator não acelera nada, ele julga.
4. O Council Gate e o Validator Gate ambos rodam um council. Qual é a diferença essencial?
Correto: a. O Council Gate delibera antes do trabalho sobre o goal (NO_GO → não começa, curto-circuita o fanout); o Validator Gate revisa depois a evidência produzida. b é falso: rodam em momentos e sobre objetos diferentes. c inverte a ordem inteira da pipeline. d troca os papéis: é o Council Gate que é opcional (--council); o Validator roda nas units T4/com-proof.
💬 Travou em algo? Eu sou seu professor neste curso — pergunte. "Quando vale a pena ligar o Council Gate?", "Como um proof vira uma task de verdade?", "O que exatamente parka um T4 no Validator?". É só dizer.