Zones

Nombra los paths que harían daño. Todo lo demás queda abierto.

La mayor parte de un repositorio es segura para que un agente la cambie. Unas pocas partes no lo son — el schema, los contracts, lo que diga tu historial de incidentes. Una zone es cómo dices cuál es cuál, en un fichero que revisas como código — y, en modo governance, los únicos paths que CommitCycle bloquea. El modo por defecto, memory, no tiene zones e impone una sola cosa: editar requiere una task activa.

dash.commitcycle.com/boardCC

✓ gate: four fields answered, no high-risk zone to approve

REQ-7 · schema · write · CC-42

Reason: the board query needs an index

Instead: hand the DDL to the owner

1 hour4 hoursUntil the task closes

✓ Approved — schema is open to CC-42 for 4 hours

En la consola una task cruza el gate hacia In Progress, y el owner de una zone responde a un access request — por una hora, cuatro, o hasta que la task se cierre.

Claude Code — ~/acme-webplugin · commitcycle

> add an index on tasks.updated_at — the board query is slow

● Write(apps/api/migrations/0042_tasks_updated_at.sql)

⎿ PreToolUse:Write — ✗ Denied by CC

zone schema · risk high

owner ana@acme.dev

task CC-42 declared no protected zones

reason path is in a zone the task never asked for

● The schema zone is closed to CC-42. Asking its owner rather than looking for another way in.

● Bash(cycle request-access --zone schema --mode write --reason "the board query needs an index" --alternative "hand the DDL to the owner")

⎿ REQ-7 is with the zone owner

approve or deny: https://dash.commitcycle.com/requests

El hook rechaza la escritura antes de que ocurra, nombra la zone y su owner, y el agente pide acceso en vez de buscar otro camino. Claude Code es donde se ha visto funcionar este bloqueo.

Cuatro cosas, y una de ellas es una persona

Los path patterns dicen dónde. Un risk level dice cuánto cuidado. Una default policy dice quién puede leerla cuando no se ha concedido nada — escribir siempre necesita un grant. Y un owner dice a quién preguntar — que es el atributo que convierte un muro en una vía de entrada.

  • Path patterns — las mismas formas glob que usan los rulesets de GitHub, nada nuevo que aprender
  • Risk level — high, medium, low. High significa que se pregunta al owner antes de empezar el trabajo
  • Default policy — deny cierra también la lectura; read-only y open la dejan legible. En cualquier caso, escribir necesita un grant
  • Owner — una persona real, en un fichero, no en la memoria de nadie
.zones/zones.yml · committed
# El mapa propio de CommitCycle, recortado. Cuatro zones en el fichero real, no treinta,
# todas legibles desde el 2026-10-10 — escribir en cualquiera sigue necesitando un grant.
zones:
  - id: schema
    risk: high
    owner: paulo@commitcycle.com
    paths:
      - "apps/api/migrations/**"
      - "apps/api/src/db/schema/**"
    default_policy: open

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

  - id: brand
    risk: medium
    default_policy: open

# Todo lo que no está aquí queda sin proteger, a propósito.

El acceso llega como un grant, y se va solo

Mover una task a In Progress es lo que lo emite. Aparte de ese gate, sólo un owner que responde a un access request abre una zone, y cycle renew sólo vuelve a emitir el mismo alcance — no hay ningún comando open-zone, y nadie tiene que acordarse de cerrar nada.

Atado a una task

Abre las zones que esa task declaró, y nada adyacente. El cambio vecino tentador es justo el que los non-goals existen para nombrar.

Atado a una rama

La garantía es por checkout: dos agentes en un mismo directorio comparten una rama, y con ella una task y un grant. Éste es el fallo que este mismo producto sufrió primero (D-43, aún propuesta); la respuesta por ahora es un worktree por agente.

Caduca en ocho horas como mucho

El gate lo emite para ocho horas como mucho. Un owner que aprobó una zone de alto riesgo para una hora o cuatro adelanta la caducidad de todo el grant para que coincida (CC-1327).

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

Al agente se le dice por qué en la misma respuesta que se lo deniega, así que pide acceso en lugar de intentar otra vía. Un bloqueo que sólo dice que no acaba siendo esquivado.

Access requestwaiting · 2 min

CC-42 quiere schema

Reason
La migración necesita el índice del org
Scope
write · apps/api/migrations/**
Expires
4 horas tras la aprobación
Approve for 4hDeny

Just-in-time: el grant caduca solo. Nadie tiene que acordarse de cerrarlo, que es justo el paso en el que falla cualquier proceso de acceso.

Bloquear es commodity. El modelo de debajo no lo es.

Mejor decirlo antes de que lo descubras tú: denegar una tool call en el momento ya lo tienen Claude Code, Codex, Cursor, Augment, Factory y Devin CLI, y es gratis en el que ya estés usando. Si eso fuera el producto, no necesitarías esta página.

Lo que ninguno de ellos tiene es el modelo que consulta esa denegación. Sus reglas son por máquina y permanentes. No hay un owner a quien preguntar, ni un momento de aprobación, ni caducidad, ni noción de una task a la que el permiso pueda estar atado.

Las reglas de todos los demás

Una lista de paths. Fijada una vez, cierta para siempre, igual para cualquier trabajo, sin nadie asociado.

Una zone más un grant

Path × owner × risk × esta task × esta rama × ocho horas como mucho, y un registro de quién lo abrió y por qué.

Contra CODEOWNERS y los rulesets de rama la diferencia es el cuándo: mismo vocabulario, preguntado después de que el cambio ya existe, impuesto en el host. Una zone se comprueba en la escritura, en tu portátil, sin conexión — y el check de CI que recalcula el diff después corre sólo en el propio repositorio de CommitCycle.

Qué se midió, y qué no demuestra

Cada cifra aquí lleva su límite en la misma frase.

  • 25/25 vectores de escape de Bash contenidos — las escrituras de shell corren contra un snapshot de git y los cambios en paths protegidos que la task no tiene abiertos se revierten byte a byte. La contención se cierra cuando la llamada vuelve, así que lo que un comando deja corriendo — un comando en segundo plano (el hook pregunta antes), uno en primer plano que agota su timeout, un cmd & dentro de otro — se le escapa hasta que el cierre comprueba el diff contra las zones (CC-1379). Medido el 2026-08-03 (CC-3). Los paths ignorados por git no se ven, así que un .env dentro de una zone no tiene contención. El corpus lo eligió el propio autor. El eval de falsos positivos en vivo no ha corrido.
  • 0/20 falsos positivos sobre ese mismo guard. Mismo corpus autoelegido. Veinte comandos no son veinte tasks reales.
  • 8/20 falsos positivos en el allowlist conservador — el enfoque que rechazamos, y la razón por la que ganó la contención. Mismo corpus autoelegido. Lo que se midió es el 40%; que costaría la instalación es nuestra lectura, no una medición.
  • 68–83 ms en p95 para la decisión, contra un presupuesto de 100 ms. Medido el 2026-08-03 con la primera versión del hook, en una máquina en reposo. El p99 tocó 102 ms en un caso. CC-1377 lo volvió a medir en octubre de 2026 en dos VM en la nube: en la más lenta, wrapper y núcleo llegaron a 211–228 ms en p95 (carga 0,74–1,04), y el coste del hook sobre un proceso node lanzado por shell fue de 84–111 ms allí frente a 44–48 ms en la más rápida, con el mismo código. Dos hosts, no un estudio.

Dónde se detienen las zones

  • Confinan a cada agente; no arbitran entre ellos. Dos agentes que discrepan siguen discrepando — cada checkout simplemente queda sujeto a su propia task y su propia rama.
  • Sin proteger es lo normal, y debe serlo. Un gate demasiado celoso cuesta más que uno que falta, así que todo lo que no declares queda simplemente abierto.
  • Los topics nunca imponen. Las zones imponen paths; las disciplinas que una task declara sólo aconsejan. Las dos cosas nunca se mezclan.
  • El registro sobrevive. El mapa es un fichero en tu repositorio y, por defecto, también lo son los registros de las tasks y el audit record que escribe un cierre desde la CLI; el board guarda una copia de cada audit record, y la única copia del que escribió un cierre desde la consola o un merge. Los grants son estado local de corta vida que caduca con el trabajo. Desinstala CommitCycle y te quedas con los ficheros, y cycle export --audits imprime el historial del board, registros incluidos, en Markdown.

Preguntas que responde esta página

¿Cómo evito que un agente de código en IA edite ciertos ficheros?

Declara esos paths como una zone con un owner y un risk level. El agente sólo obtiene acceso a las zones que su task declaró, en la rama a la que esa task está atada, y el acceso caduca por sí solo. Todo lo que no declares queda sin proteger, que es lo correcto para la mayor parte de un repo.

¿En qué se diferencia esto de CODEOWNERS?

CODEOWNERS es el mismo vocabulario aplicado después del hecho, en el host: pide una revisión una vez que el cambio ya existe. Una zone se comprueba en el momento de la escritura, en tu máquina, y lleva una caducidad y un alcance de task que CODEOWNERS no contempla.