ADR 0167 — O modo automático libera o escopo de caminho, e só ele
Status
Accepted. Decidido pelo dono do produto em 2026-09-26 (AT-226), entre três opções: "com o modo automático ligado, o agente executa qualquer comando de terminal sem aprovação, inclusive fora da pasta do projeto". Revê, SÓ para agente em modo automático, o teto de escopo de caminho do ADR 0055. Não edita o 0055 nem o ADR 0102 (o teto de efeito externo/comando privilegiado, RN-418), que seguem valendo inteiros. A regra que nasce daqui é a RN-603; ela revê a RN-153 e a RN-154.
Context
O "modo automático" (RN-153) é a
curinga "*" em agent_autonomy: autonomia para qualquer tipo de ação de um
agente. Ele foi desenhado para NÃO furar teto nenhum de decide() — os tetos
agiam sobre current.policy === 'auto_approve', sem saber de onde a
permissividade veio (RN-154).
Um desses tetos é o de ESCOPO DE CAMINHO (ADR 0055): comando de terminal que
toca caminho fora da pasta do projeto nunca é auto-aprovável. Medido no banco
do dono em 2026-09-26, projeto exp001 (modo mounted, container de pé): com
o modo automático ligado nos dev agents, 51 comandos de terminal ainda
pediram aprovação, e 47 só porque citavam /work ou /tmp. O dev agent
roda DENTRO do container, onde a pasta do projeto é /work, e o escopo
compara o comando com a raiz do HOST — então tudo o que o agente escreve do
jeito certo para onde ele roda vira "fora da pasta do projeto". Nenhum dos 51
era git push, PR, deploy ou sudo.
Havia um segundo pedido pelo mesmo motivo, sem o nome de escopo: o comando
COMPOSTO (cd /work && npm test) com um segmento sem regra em
permissions.json recebe um require_approval SINTETIZADO pelo arquivo — que
existe para impedir um allow parcial de promover o comando inteiro — e esse
veredito sobrescrevia o auto_approve da autonomia.
O dono pediu: "uma vez que o usuário apertar o botão modo automático, aquele agente deve entender que pode executar qualquer comando… só deve novamente pedir para aprovar quando o usuário definir os agentes como manual novamente".
Decision
decide()passa a saber a ORIGEM da autonomia. O repositório (AgentAutonomyRepository.resolve) devolve o modo resolvido E se ele veio da regra específica do tipo ou da curinga. A precedência específica > curinga continua morando lá, uma vez só —findModevirou leitura deresolve, não uma segunda régua.decide()continua pura: recebectx.autonomyOrigin, e origem ausente vale como'especifica'(quem não a informa mantém o veredito de antes).- Modo automático é exatamente: curinga, resolvida como
auto_approve."*": require_approval(o toggle desligado) e"*": denynão ganham poder nenhum. Uma regra específica do tipo (terminal: require_approval) vence a curinga no repositório e chega com origem'especifica'— o modo automático não a atropela. - Em modo automático, o teto de escopo de caminho não se aplica. Nem o
require_approvalque o comando composto sintetiza por segmento sem regra: ele é o arquivo SEM opinião, e arquivo sem opinião nunca rebaixa um estágio anterior. UmaskESCRITO nopermissions.jsoncontinua valendo — é regra do usuário, e regra explícita vence a curinga, como no repositório. - Todo o resto fica byte a byte.
deny(dopermissions.json, dos padrões embutidos ou de autonomia específica) continua vencendo; o teto de efeito externo/comando privilegiado (git push, PR, deploy,sudo/doas, RN-418) roda ANTES do de escopo e não olha a origem; merge em branch protegida,instruction_patch,parallelize/raise_max_parallelecontainer_removeseguem nunca auto-aprováveis. - A tela diz, antes do clique, o que o botão libera e o que continua
pedindo. A nota do
ApprovalCardvale nas duas variantes (chat e fila de Aprovações), e o card do agente mostra uma frase sob o toggle — só quando a CURINGA está ligada, porque o toggle sobre o tipo representativo grava uma regra específica, que não libera o escopo.
Consequences
- Um agente em modo automático pode ler e escrever fora da pasta do projeto
sem perguntar. É o preço escolhido: o achado U (o agente lendo o código da
plataforma que o executa, ADR 0055) volta a ser possível PARA ESSE AGENTE,
por decisão explícita do usuário que ligou o modo. A contenção que sobra é a
do lugar onde o comando roda — o mount namespace do container
(
container/mounted, ADR 0134) ou a máquina do usuário (runner) — mais odenye os tetos de efeito. - Voltar o toggle do card do agente para "manual" regrava a curinga como
require_approvale restaura o teto de escopo na próxima proposta. - O toggle do card, quando NÃO há curinga gravada, continua editando o tipo
representativo (
autonomyActionTypeFor) — uma regra específica. Ligá-lo por ali não é modo automático e não libera o escopo; a tela não diz que libera. decide()deixa de ser cega à origem da autonomia, que era a prova por construção da RN-154. A prova continua valendo para todos os tetos menos o de escopo, e é travada por teste: cada um deles com a curinga ligada seguerequire_approval.
Alternatives considered
- Traduzir
/workpara a raiz do host antes do escopo. Resolveria os 47 doexp001, mas não o/tmpnem o que o dono pediu ("qualquer comando"). E a tradução mora no engine, depois da decisão, de propósito (ADR 0134). - Liberar o escopo para toda autonomia
auto_approve, específica ou não. Recusada:terminal: auto_approvepor tipo existe desde a Fase 8d com o escopo por cima, e mudar o sentido dela sem ninguém ter pedido reabriria o achado U em projetos que nunca ligaram o modo automático. - Deixar o
askescrito no arquivo ser ignorado também. Recusada: seria o modo automático atropelando regra explícita do usuário, o inverso da precedência que o repositório já aplica.