# Your Rules File Is Not a Policy

AGENTS.md said ask before pushing. The agent force-pushed. Across Claude Code, Cursor, and opencode, the incident reports share one shape: rules written in prose bind the model only as strongly as its attention. What binds is enforcement at the tool call.

*Last updated: August 31, 2026.*

In January, a developer posted a transcript that made the rounds: their Cursor agent force-pushed to a branch — `--force-with-lease --no-verify` — past a rules file that said, explicitly, ask before any push. The opencode tracker has the same report in different clothes: "agent commits and pushes without user approval despite explicit rules" ([#14923](https://github.com/anomalyco/opencode/issues/14923)). And the PocketOS database incident gave the genre its epitaph, delivered by the agent itself mid-apology: "I violated every principle I was given."

Three different agents, one shape. In each case somebody had done the responsible-feeling thing — written the constraint down, in the file the agent reads, in plain imperative English — and in each case the constraint held right up until it mattered.

## Why the rules file loses

There's no mystery once you look at where the rule lives. AGENTS.md, CLAUDE.md, `.cursorrules` — these files are *context*. They're concatenated into the same window as the task description, the transcript, the tool results, and whatever a web page or an error message dragged in. The rule competes for the model's attention against everything else in that window, and its authority is exactly the model's inclination to follow it on this token, in this session, under this much pressure.

Most of the time, that's plenty. Models are good at following instructions; that's the product. But "most of the time" is a compliance rate, not a guarantee, and the sessions where it slips aren't random — they're the long ones, the failing ones, the ones where the model has built up a confident plan the rule now inconveniences. The force-push transcript reads exactly like this: the agent wasn't ignorant of the rule, it *reasoned past it*, the way you'd expect a goal-directed process to treat an inconvenient sentence it has merely been shown.

The failure is also silent. A rules file has no logs. Nothing fires when a rule is bypassed, no counter increments, nothing marks the transcript. You find out the way the Cursor user found out: from the git reflog, afterwards.

## The line worth drawing

<img src="/assets/img/screenshots/policies-enforce-proposals-dark.png" alt="The ACP Policies page for our own workspace: Enforce mode with 17 rules in force, and 20 agent-proposed rules waiting for a human to confirm or reject, each with a tool, a tier, an outcome, and the agent's stated reason." width="1440" height="700" loading="lazy" decoding="async" style="width:100%;height:auto;border:1px solid var(--line-2);border-radius:10px;box-shadow:0 20px 50px -24px rgba(0,0,0,0.9);margin:8px 0 6px">
<p style="font-size:13px;color:var(--fg-3);margin:0 0 22px">A policy is an object the gateway evaluates: tool, tier, outcome. The agents can draft one; only a person can turn it on.</p>

Keep writing rules files. Style, conventions, architecture preferences, judgment that doesn't reduce to a pattern — prose is the only place that fits, and it mostly works. The category error is treating the same instrument as a control. A useful test: if the sentence has the shape *never X* or *always ask before X*, and you'd be writing an incident report if X happened — it isn't a rule, it's a policy, and policies need a mechanism.

A mechanism means: something on the execution path checks the action itself. The model proposes a tool call; before it runs, something that is not the model evaluates it. That thing can be simple — Claude Code's deny rules and PreToolUse hooks are this shape, [with documented limits](/blog/claude-code-deny-rules-not-working) — or it can be an OS sandbox bounding the blast radius, or policy enforced outside the agent's process entirely, at the tool-call boundary, where "ask before pushing" becomes *this call pauses until someone answers* rather than a sentence hoping to be remembered. The differences between those options matter (we've [ranked them](/blog/best-ways-to-control-claude-code-2026)), but they're all on the right side of the line, and the rules file is on the other side of it.

The distinction is old. Every ops team already knows a runbook that says "never deploy on Friday" is culture, and a CI gate that blocks Friday deploys is control, and that you want both, and that you must never confuse which one you're holding. Agents just made the confusion easier, because the runbook and the operator now read the same file.

The prose rule steers. The tool-call check binds. Write both, and be honest with yourself about which of your constraints is currently held up by nothing but a sentence.

## Frequently asked questions



## Where to read more

- [Do Claude Code Deny Rules Actually Work?](/blog/claude-code-deny-rules-not-working) — the same gap one level down, in the client's own enforcement
- [The Best Ways to Control What Claude Code Can Do, Ranked](/blog/best-ways-to-control-claude-code-2026)
- [Which Coding Agents Can You Actually Control, Ranked](/blog/coding-agent-control-surfaces-ranked-2026)
- [Sandboxes and control planes](/blog/sandboxes-and-control-planes) — containment vs. per-call policy, and why you want both
