Three layers Shipped · one harness adapter
Each layer is there because the one above it can fail
A file can be ignored. A hook can be absent. A pull request cannot be either, but it arrives too late to stop anything. None of the three is sufficient, which is the entire reason there are three.
Layer 1 — context, which advises
The AGENTS.md block tells the agent what the task is, what is open and what is shut. It is generated at the gate so it cannot drift, and it is honest in its own text about being advice: nothing is stopping you, so this one is on you.
Layer 2 — the hook, which denies
A pre-tool-call hook answers allow, ask or deny before the write happens. Two properties matter more than the mechanism:
- The hot path never touches the network. The decision is local, so an outage cannot open a zone — the backend was never in the deny path to begin with.
- Bash is contained, not classified. Guessing what a shell command will do is a losing game, so commands run against a git snapshot and out-of-zone changes are reverted byte-for-byte. 25/25 escape vectors contained, 0/20 false positives — against a corpus we chose ourselves; the live false-positive eval has not run.
- 68–83 ms at p95 against a 100 ms budget — and p99 touched 102 ms in one case. The margin is thin and the levers are named.
Worth saying plainly: this mechanism is commodity. Claude Code, Codex, Cursor, Augment, Factory and Devin CLI all expose a hook that can return deny, and in the one you are probably using it is free. What is not commodity is the model it consults — owners, expiry, and permission scoped to a declared task.
The admission that makes the rest credible
We measured the harness against real sessions and it is fail-open in all four failure modes: crash, timeout, malformed output, not installed. That is not a footnote — it is the reason the other two layers exist in the shape they do. A wrapper closes three of those modes by refusing on its own behalf when the hook cannot answer, and the fourth — never installed at all — is invisible from inside the machine, so only CI can see it.
A skeptical reader would find this out anyway. Printing it beside the numbers it undermines is the most useful thing this page can do.
Layer 3 — CI, which recomputes
The required status check reads the same zone map on the pull request and recomputes which zones the diff actually touched, against what the task declared. It is the only layer that can see work produced where CommitCycle was never installed.
Its own limit, stated: on a private personal free plan branch protection answers403, so this layer runs advisory there and says so rather than reporting an enforcement it did not perform.
Where the arrangement stops
- Layer 2 needs one adapter per harness. The zone model is agent-agnostic and layers 1 and 3 are agnostic today — but the enforcement point is not. One adapter ships; the others are thin and unwritten.
- An enterprise can block the hook outright. Managed settings exist for exactly that, and a policy that locks hook sources locks ours out with everyone else's.
- None of this arbitrates between agents. Each is confined to its own task and branch; two that disagree still disagree.
How the layers divide the work is in the docs, and the map all three read is the zone map.