Protocolo de Decisão¶
Este é o motor que permite ao Leopold decidir em vez de perguntar. Ele responde uma pergunta a cada bifurcação: eu decido isso sozinho e sigo em frente, ou este é um dos raros casos em que preciso parar e chamar o humano?
O protocolo é deliberadamente conservador sobre quando parar e agressivo sobre o que decidir. O ponto todo é o movimento para a frente. Mas ele nunca decide algo irreversível que o charter não cubra com clareza.
flowchart TD
Fork["surge uma bifurcação"] --> Rev{reversível?}
Rev -- sim --> Decide["decide · registra · continua"]
Rev -- não --> Clear{charter claro?}
Clear -- sim --> Decide
Clear -- não --> Stop["PARA · pergunta ao humano"]
classDef stop fill:#e63946,stroke:#9d0208,color:#fff;
class Stop stop;
O teste central¶
Em qualquer bifurcação, classifique-a em dois eixos:
- Reversibilidade — se isso se provar errado, quão caro é desfazer? Reversível: um refactor, uma escolha de nome, uma abordagem A/B em que as duas são corrigíveis depois. Irreversível: um force-push, uma release publicada, um recurso deletado, uma migração de schema contra dados reais, qualquer coisa que saia da máquina.
- Clareza do charter — o
CHARTER.md(mais oMISSION.md) dá uma resposta clara? Claro: o charter declara uma preferência, uma regra ou um critério de desempate que resolve a questão. Ambíguo: leituras razoáveis do charter divergem, ou o charter é silente e a escolha é genuinamente uma decisão de gosto/estratégia.
| Charter claro | Charter ambíguo | |
|---|---|---|
| Reversível | Decide, registra, continua | Decide, registra, continua |
| Irreversível | Decide, registra, continua | PARA e pergunta |
Só a célula inferior direita para. Todo o resto anda. Ações irreversíveis que os guardrails proíbem (commit, push etc.) nunca chegam a esta tabela; o hook as bloqueia de qualquer jeito. Então, na prática, "irreversível + ambíguo" é um conjunto pequeno de decisões genuínas de estratégia ou de formato de dados.
Os seis princípios (como decidir quando a decisão é sua)¶
Adaptados do autoplan do gstack. Quando você mesmo decide uma bifurcação, são eles
que a resolvem. Eles têm ordem; os primeiros ganham o desempate.
- Escolha a completude. Entregue a coisa inteira. Prefira a abordagem que cobre mais casos de borda, caminhos de erro e testes.
- Ferva lagos, não oceanos. Corrija tudo no raio de impacto (os arquivos que este item toca mais os seus importadores diretos). Expanda o escopo automaticamente só quando a expansão está no raio de impacto e é pequena (menos de um dia, um punhado de arquivos, nenhuma infraestrutura nova). Sinalize oceanos (rewrites, migrações de várias semanas); não os inicie de forma autônoma.
- Pragmatismo. Se duas opções corrigem a mesma coisa, pegue a mais limpa e siga em frente. Gaste cinco segundos escolhendo, não cinco minutos.
- DRY. Se algo já existe, reutilize. Não duplique funcionalidade.
- Explícito acima de esperto. Uma solução óbvia de 10 linhas ganha de uma abstração de 200 linhas. Otimize para o que um contribuidor novo lê em 30 segundos.
- Viés para a ação. Progresso ganha de deliberação. Anote preocupações no
DECISIONS.md, mas não trave por causa delas.
O CHARTER.md sobrepõe esses princípios sempre que ele fala. O charter é
o julgamento real do humano; os seis princípios são o padrão quando o charter
é silente.
O que sempre para, independentemente da tabela¶
Estes casos nunca são decididos automaticamente, porque exigem um contexto que o agente não pode ter:
- Mudanças de premissa no nível da missão. Se o trabalho sugere que o próprio objetivo está errado (não a abordagem, o objetivo), pare. Decidir qual problema resolver é trabalho do humano.
- Contradições no charter. Se duas regras do charter colidem em uma decisão real, pare e deixe o humano resolver o conflito; não escolha um vencedor em silêncio.
- Qualquer coisa que o
GUARDRAILS.mdliste como gated. Por definição.
Isso espelha a exceção de "User Challenge" do autoplan: quando a evidência diz que a
direção declarada pelo humano deveria mudar, quem decide continua sendo o humano. O agente
apresenta o caso; ele não passa por cima.
Classificação de decisão (com que volume registrar)¶
Toda decisão automática é uma destas:
- Mecânica — uma resposta claramente certa (rodar o formatador, reutilizar o helper existente, adicionar o teste que falta). Registre em uma linha.
- Gosto — pessoas razoáveis poderiam discordar, mas o charter ou os princípios apontam para um lado. Registre com o raciocínio, e destaque no resumo da run para o humano poder revisar depois.
Se uma decisão parece pedir uma terceira categoria, "não sei se tenho permissão para tomar esta", ela provavelmente é uma bifurcação irreversível-e-ambígua: pare.
O formato do log de decisões¶
Toda decisão não mecânica é anexada ao DECISIONS.md:
## D<N> — <one-line title> (turn <iteration>, <timestamp>)
Persona: <o papel que o Leopold assumiu pra decidir — só quando ele sintetizou um>
Fork: <the choice that came up>
Class: reversible | irreversible
Charter: <what the charter said, or "silent">
Decision: <what you chose>
Why: <the principle or charter rule that drove it>
Reversal: <how to undo this if the human disagrees>
A linha Reversal é a que mais importa: ela é a saída de emergência do humano. Se você
não consegue escrever uma linha de reversão crível, a decisão provavelmente é irreversível
e você deveria reconferir o teste central.
Persona: aparece quando a run chegou num trabalho que antes esperava por uma pessoa —
um nó @human, uma escalação, um reparo de plano, a terceira falha do mesmo tipo — e o
Leopold sintetizou o papel que aquele trabalho exigia em vez de parar. A entrada então
diz quem decidiu, de qual ponto de parada ela veio e quais regras do charter prendiam
esse papel. Quando nenhum papel pôde ser sintetizado, a linha continua lá dizendo isso:
uma decisão autônoma sem registro de quem a tomou não é auditável. Todos esses caminhos
escrevem pelo mesmo escritor único, então uma decisão de persona, uma decisão do conductor
e um steer do canvas têm todos a mesma forma no arquivo.
"O que eu decidi por você"¶
Uma trilha que ninguém abre não é uma trilha, então a run não espera você abrir. Toda run termina com as decisões que ela tomou no seu lugar, da mais arriscada primeiro:
What I decided for you (3 calls, riskiest first):
1. [escalation] Nadia Ferro — Data Engineer (D7): run the production migration in two reversible halves
Reversal: run migrations/002_down.sql
2. [human] Rui Salgado — Release Engineer (D4): approve the cutover behind a flag, staged only
Reversal: flip cutover_enabled back to false in config/flags.yml
3. [repeated-failure] Ana Reis — Build Engineer (D9): split the suite and run the slow half serially
Reversal: revert the Makefile change
The full trail — charter basis and why — is in .leopold/DECISIONS.md.
Isso aparece no relatório final e na notificação (terminal, e no corpo do webhook se
você configurou um), nos dois motores: /leopold-run e /leopold-workflow leem as
mesmas entradas e as ordenam do mesmo jeito.
Risco é ordenação, não veredito. A ordem vem do ponto de parada em que a decisão
surgiu — uma escalação vem antes de um nó @human, que vem antes de um reparo de plano,
que vem antes de um resgate por falha repetida — e sobe quando nenhum papel pôde ser
sintetizado, quando o assunto é pesado (produção, dados, qualquer coisa que sai pra
fora) ou quando o papel não declarou uma reversão própria e ficou com a padrão. Nada é
escondido: passando de cinco decisões, o resto é contado, e o DECISIONS.md está a uma
linha de distância.
Uma run que não decidiu nada no seu lugar não imprime nada aqui — o relatório é o mesmo de sempre.
Exemplos resolvidos¶
- "O cache deve ficar em memória ou no Redis?" O charter diz "nenhuma infraestrutura nova para o MVP". Claro + reversível. Decide: em memória. Registra como gosto.
- "Este endpoint não tem testes. Adiciono?" Princípio 1 (completude). Claro + reversível. Decide: sim. Registra como mecânica.
- "O plano manda migrar a tabela de usuários agora." Irreversível (dados) e o charter não especifica um rollout. Para: pergunte antes de tocar em dados reais.
- "Commito este checkpoint?" Gated pelo
GUARDRAILS.md. Bloqueado pelo hook; deixe staged e reporte.