Tres capas Shipped · probado sólo en Claude Code

Cada capa está ahí porque la de encima puede fallar

Un fichero se puede ignorar. Un hook puede no estar. Un pull request no puede ser ninguna de las dos cosas, pero llega demasiado tarde para detener nada. Ninguna de las tres basta, y ésa es toda la razón de que haya tres.

acme-webafter cycle start CC-58

$ cycle start CC-58

<!-- cc:begin -->

### You are working on CC-58 — Export times out on large boards

Branch `task/CC-58-export-times-out-on-large-boards`. Access expires in about 8 hours.

What it must NOT do. No change to the export format.

No protected zone is open to this task.

<!-- cc:end -->

cycle start escribe la task en un CLAUDE.local.md ignorado por git, junto al mapa de zones de AGENTS.md, y cycle submit la vuelve a sacar.

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.

Pull request · commitcycleCommitCycle's own CI

CC-42: add an index on tasks.updated_at

task/CC-42-add-an-index-on-tasks-updated-at → main

  • ✓ static, test, evals, apps — typecheck, unit tests, evals, builds
  • ◌✓scope — Is this pull request inside what its task declared?

Advisory here: this repository’s plan cannot make a check required.

La capa 3 vuelve a comprobar el diff contra lo que declaró la task. Hoy corre en el propio CI de CommitCycle, en modo consultivo; nada la instala en el tuyo.

Capa 1 — el contexto, que aconseja

El bloque de AGENTS.md lleva el mapa de zones, el board, la nota de entrega que espera y la regla de deploy; la task en sí — qué está abierto y qué está cerrado — se escribe en el gate en un CLAUDE.local.md ignorado por git, que carga Claude Code — si otros editores lo cargan no se ha comprobado nunca — y se retira al entregar. Es honesto en su propio texto sobre ser un consejo: nothing is stopping you, so this one is on you.

Capa 2 — el hook, que deniega

Un hook previo a la llamada a la herramienta responde antes de que ocurra la escritura. El nuestro sólo restringe: puede denegar, y desde CC-1142 nunca responde allow, así que los avisos de permisos del propio harness siguen aplicándose. Lo que importa más que el mecanismo:

Conviene decirlo claro: este mecanismo es commodity. Claude Code, Codex, Cursor, Augment, Factory y Devin CLI exponen todos un hook que puede devolver deny, y en el que probablemente usas es gratis. Lo que no es commodity es el modelo que consulta — owners, caducidad y permisos acotados a una task declarada.

La admisión que hace creíble el resto

Medimos el harness contra sesiones reales el 2026-08-03, y es fail-open en los cuatro modos de fallo: crash, timeout, salida malformada, no instalado. Eso no es una nota al pie — es la razón por la que las otras dos capas existen con la forma que tienen. Un wrapper puede cerrar tres de esos modos negándose por su cuenta cuando el hook no puede responder — pero sólo si la failure policy del repositorio está en closed. Desde CC-1143 el valor por defecto es open: las llamadas siguen y se avisa a la sesión. El cuarto — no instalado en absoluto — es invisible desde dentro de la máquina, así que sólo CI puede verlo, y sólo donde el check corre.

Capa 3 — CI, que recalcula

El check de CI lee el mapa de zones desde el propio checkout del pull request y recalcula qué zones tocó de verdad el diff, frente a lo que declaró la task — la declaración, no el grant, así que las aprobaciones y la caducidad no se comprueban. Es la única capa que podría ver trabajo producido donde CommitCycle nunca se instaló.

Sus propios límites, dichos en voz alta: sólo corre en el propio repositorio de CommitCycle, y nada lo instala en el tuyo. Ahí, en un plan personal privado gratuito, la protección de ramas responde 403, así que corre en modo aviso, lo dice y no puede detener un merge. Un board que no responde lo convierte en un skip que igualmente pasa, y en un pull request del mismo repositorio la rama puede reescribir el workflow que la comprueba. Un modo que impone y un check run desde el board están construidos y sin activar.

Dónde se detiene el conjunto

Cómo se reparten el trabajo las capas está en la documentación (en inglés), y el mapa que leen las tres es el mapa de zones.