Zones

Nomeie os paths que doeriam. Tudo o resto continua aberto.

A maior parte de um repositório é segura para um agente mudar. Poucas partes não são — o schema, os contracts, o que o seu histórico de incidentes disser. Uma zone é como você diz qual é qual, num arquivo que você revisa como código, e é a única coisa que o CommitCycle de fato impõe.

Quatro coisas, e uma delas é uma pessoa

Os path patterns dizem onde. Um risk level diz quanto cuidado. Uma default policy diz o que acontece quando nada foi concedido. E um owner diz a quem perguntar — que é o atributo que transforma um muro numa porta.

  • Path patterns — as mesmas formas glob que os rulesets do GitHub usam, nada novo para aprender
  • Risk level — high, medium, low. High significa que o owner é consultado antes do trabalho começar
  • Default policy — deny, read-only ou open, aplicada quando nenhum grant nomeia a zone
  • Owner — uma pessoa real, num arquivo, não na memória de alguém
.zones/zones.yml · committed
# O mapa do próprio CommitCycle, recortado. Quatro zones no arquivo real, não trinta.
zones:
  - id: schema
    risk: high
    owner: paulo@commitcycle.com
    paths:
      - "apps/api/migrations/**"
      - "apps/api/src/db/schema/**"
    default_policy: deny

  - id: enforcement
    risk: high
    owner: paulo@commitcycle.com
    paths:
      - "packages/hook/**"
      - "packages/action/**"
    default_policy: deny

  - id: brand
    risk: medium
    default_policy: read-only

# Tudo que não está aqui fica sem proteção, de propósito.

O acesso chega como um grant, e vai embora sozinho

Mover uma task para In Progress é o que emite isso. Não existe comando que abra uma zone, então não há porta dos fundos para achar — e ninguém precisa lembrar de fechar nada.

Preso a uma task

Abre as zones que aquela task declarou, e nada adjacente. A mudança vizinha tentadora é justamente a que os non-goals existem para nomear.

Preso a um branch

Dois agentes num mesmo repositório respondem cada um ao seu próprio grant. Essa é a falha que este produto sofreu primeiro nele mesmo, e a correção está registrada como D-43.

Expira em oito horas

Cem micro-consentimentos trocados por um macro-consentimento com um relógio embutido. Pedir permissão a cada chamada é segurança por fadiga.

Blocked14:02 · task CC-42

Write apps/api/migrations/0007_add_org_index.sql

Zone
schema · risk high
Task declared
api, web
Owner
paulo@commitcycle.com

O agente é avisado do motivo na mesma resposta que nega, então ele pede acesso em vez de tentar outro caminho. Um bloqueio que só diz não acaba sendo contornado.

Access requestwaiting · 2 min

CC-42 quer schema

Reason
A migração precisa do índice do org
Scope
write · apps/api/migrations/**
Expires
4 horas depois da aprovação
Approve for 4hDeny

Just-in-time: o grant expira sozinho. Ninguém precisa lembrar de fechá-lo, que é justo o passo em que todo processo de acesso falha.

Bloquear é commodity. O modelo por baixo não é.

Melhor dizer antes que você descubra sozinho: negar uma tool call na hora já existe no Claude Code, Codex, Cursor, Augment, Factory e Devin CLI, e é grátis em qualquer um deles que você já use. Se isso fosse o produto, você não precisaria desta página.

O que nenhum deles tem é o modelo que essa negação consulta. As regras deles são por máquina e permanentes. Não há um owner para perguntar, nem um momento de aprovação, nem expiração, nem noção de uma task à qual a permissão possa estar presa.

As regras de todo mundo

Uma lista de paths. Definida uma vez, verdadeira para sempre, igual para qualquer trabalho, sem ninguém associado.

Uma zone mais um grant

Path × owner × risk × esta task × este branch × oito horas, e um registro de quem abriu e por quê.

Contra CODEOWNERS e os rulesets de branch a diferença é o quando: mesmo vocabulário, perguntado depois que a mudança já existe, imposto no host. Uma zone é checada na escrita, no seu notebook, offline — e a CI ainda recalcula o diff inteiro depois.

O que foi medido, e o que isso não prova

Cada número aqui carrega seu limite na mesma frase. É uma regra da casa, não modéstia.

  • 25/25 vetores de escape do Bash contidos — as escritas de shell rodam contra um snapshot do git e tudo que ficar fora das suas zones é revertido byte a byte.O corpus foi escolhido pelo próprio autor. O eval de falsos positivos ao vivo ainda não rodou.
  • 0/20 falsos positivos nesse mesmo guard.Mesmo corpus autoescolhido. Vinte comandos não são vinte tasks reais.
  • 8/20 falsos positivos no allowlist conservador — a abordagem querecusamos, e o motivo pelo qual a contenção venceu.Uma ferramenta que bloqueia trabalho legítimo é desinstalada na segunda semana. Isso foi medido, não chutado.
  • 68–83 ms no p95 para a decisão, contra um orçamento de 100 ms.O p99 encostou em 102 ms num caso. A margem é estreita e as alavancas estão nomeadas.

Onde as zones param

  • Elas confinam cada agente; não arbitram entre eles. Dois agentes que discordam continuam discordando — cada um simplesmente fica preso à sua própria task e ao seu próprio branch.
  • Sem proteção é o padrão, e deveria ser. Um gate exagerado custa mais do que um que falta, então tudo que você não declarar simplesmente fica aberto.
  • Topics nunca impõem. Zones impõem paths; as disciplinas que uma task declara só aconselham. As duas coisas nunca se misturam.
  • O registro sobrevive. O mapa, os grants e o audit trail são arquivos no seu repositório. Desinstale o CommitCycle e você fica com tudo.