The Enforcement Gap: measuring whether a coding agent follows its own rulebook A developer built an open-source harness that runs identical coding-agent tasks twice with the same model and AGENTS.md rulebook, changing only whether rules are enforced by deterministic checks before actions are applied. Across 24 rounds, three models and eight tasks, the prompt-only arm produced four rule violations while the gated arm produced zero, with five actions refused and the first violation halting the run with a named reason. The harness is built on an Express/Vite stack with a runner orchestrating prompt and gate arms over a shared queue. Every repo I open now has an AGENTS.md . Mine do too. A paragraph that says "never hardcode secrets", "only write inside src/ ", "run the tests before you commit". Then a model reads it, agrees with it, and does whatever it was about to do anyway. I wanted to know how big that gap actually is, and I did not want to answer it with an opinion. So I built a harness that runs the same task twice with the same model and the same rulebook, and changes exactly one thing: who checks. In one arm the rules are a paragraph. Every action the model emits is applied, because nothing is standing in the way. That is what almost every agent setup actually does today. In the other arm the rules are six deterministic checks. Each action is verified before it is applied, and the first violation stops the run with a named reason. 24 rounds, three models, eight tasks later: four violations landed in the told arm, zero in the held arm, five actions refused. The zero is not a result, it is a construction. The interesting number is the other one. This is a technical writeup of how it works, what I got wrong building it, and what the numbers mean. Agent frameworks spend their effort on the model's reasoning and almost none on its authority. A rule written in a prompt has the same enforcement weight as a rule written in a comment, which is none. You find out it was ignored when someone reviews the diff, or when it reaches production. Agent Relay's framing of the fix is the right one: make rules executable. Deterministic checks, required steps, human gates. The model can still do whatever it likes inside the boundary, but the boundary is code, not prose. The gap between the two is measurable if you hold everything else constant. Same model, same task, same repo state, same AGENTS.md , one difference. That is the whole design. // the only difference between arms, in the runner round.prompt = await runPromptArm job.target, round, job.task ; // applies everything round.gate = await runGateArm job.target, round, job.task, state, emit ; // checks everything One process. Express serves the API, Vite serves the app in dev as middleware, not a second server , and the same Express process serves dist/ in production. ┌──────────────────────────────────────────────────────────────┐ │ Browser React │ │ selection · verdict strip · rounds · rulebook · approvals │ └───────────────┬──────────────────────────────▲───────────────┘ │ POST /api/run │ SSE events ▼ │ ┌──────────────────────────────────────────────┴───────────────┐ │ Express server/index.ts │ │ /api/config /api/run /api/run/:id/stream /api/run/:id/... │ │ run store: Map