Gates, not guidance: standards when agents write the code
CLAUDE.md and post-write lint are weak control planes. In 140 trials, only a pre-edit gate that could refuse the write held (0/35 copies). Start with eslint; use checkyourvibe for agent-aware rules.
For coding agents, standards that only advise (CLAUDE.md) or only report after the write are weak control planes. Agents optimize for the cheapest silence. A gate is a pre-edit check that can refuse the write before it lands—eslint at minimum, agent-aware rules when you need them. That layer held at 0/35 copies in the 140-trial harness.
A conventions file cut shortcut copies from 30/35 to 13/35. The same rules, enforced as a pre-write lint gate, cut them to 0/35. Same repository. Same model. Same tasks.
That result is from precedent-poisoning (doi:10.5281/zenodo.22732965). Design problem for standards in an agent world: what you write down is not what you enforce.
Human tooling assumed a person who usually tries to pass the check. Agents optimize for the cheapest silence. Standards that only advise get treated as optional. Standards that only report after the write get reasoned past. Standards that can refuse the edit before it lands are a different kind of thing.
Four layers (be precise)
checkyourvibe names the stack this way:
| layer | what it is | who can ignore it |
|---|---|---|
| advisory | instructions, MCP, CLAUDE.md | the agent — may read, may skip |
| gate | pre-edit hook on the proposed content | the edit is denied before it lands |
| record | post-edit hook | already wrote; you get a log |
| guarantee | git hook, CI, AST/compiler check on the diff | runs whether or not the agent agreed |
Advisory is allowed to be flaky. Nothing below it should depend on sampling.
A post-edit hook cannot undo a write that already landed. A model can notice that. checkyourvibe's README reports a 2026-09-06 probe where an agent read the guidance, reasoned that "the hook's exit status does not undo the write", and declined. That is why the record row is named for what it does, not for what it prevents.
The gate row is the one that prevents. It has to cover edit tools and shell redirects (echo … > file.ts), or the agent has an escape that looks like "not an edit tool."
What ordinary linters were built for
ESLint, Roslyn analyzers, ruff, clippy — good tools. They were built for humans who make honest mistakes and then fix the finding.
An agent that hits a linter error looks for the cheapest way to make it stop. That is often a different violation the linter does not check:
- Escape
no-anywithas→ needno-as-cast - Escape that with
@ts-ignore→ needno-ts-comment - Escape a Result with
.unwrap()→ needno-unwrap - Swallow a catch to "handle" the error → need empty-catch / bare-except rules
Standard packs rarely encode that graph. They name the bad pattern. They do not name the next bad pattern the agent will reach for.
checkyourvibe calls this agent-native evasion defense: each finding carries fixes and notFixes — shortcuts that lead somewhere worse, and which rule waits at the other end. The denied edit comes back with that payload at the moment of refusal, not in a doc the model may never re-read.
What the 140 trials actually support
| environment | copied the seeded shortcut |
|---|---|
| repository alone | 30 / 35 |
| plus a conventions file | 13 / 35 |
| plus a pre-write lint gate | 0 / 35 |
| plus the same linter after the write | 4 / 35 |
Full writeup: precedent poisoning on this site.
Two limits matter for this post:
- That study gates with ESLint, not checkyourvibe. It supports the architecture (pre-write refuse vs docs vs post-write advice). It does not prove these particular rules beat anyone else's rules.
- 0/35 is a floor on those seven shortcuts, not a ranking of gates.
Lesson for standards design: if your control plane is a markdown file, you measured the weak arm. If your control plane is lint-after, you measured the residual. If your control plane can refuse the proposed write, you measured the arm that cleared the matrix.
eslint (or equivalent) wired as a pre-edit hook is the minimum that matches the data. checkyourvibe is the same layer with a compiler verdict, multi-language analyzers, notFix graphs, and agent glue that stays advisory on purpose.
Design rules that follow
Fail closed on the proposed artifact. Same input, same verdict. The model does not get a vote on whether its own edit passed. That is the difference between a gate and a suggestion.
Put the gate before the write. Post-hoc feedback is cheaper to ship and easier to ignore. In the matrix it left 4/35 copies with the identical rule set that scored 0/35 pre-write.
Do not confuse CI with the agent loop. Git hooks and CI are the guarantee layer. They catch what landed. They do not stop the agent from writing the bad file into the working tree, burning turns, and teaching itself a workaround. Use both. Do not pretend they are the same.
Assume evasion. If a rule has an obvious silence-path, encode the next rule and put it in the finding. Empty notFix lists are how agents tunnel out.
Keep guidance, stop depending on it. Write CLAUDE.md. Generate agent instructions. Then put enforcement where the model cannot reach it.
Minimum viable stack
If you ship agent-written code today:
- Wire a deterministic checker (eslint, cyv, or your AST pack) as a pre-tool / pre-edit hook that can exit non-zero and refuse the write.
- Match Bash/file redirects, not only the editor tool.
- Return the rule id and the forbidden shortcuts in the denial payload.
- Keep CI/git hooks as the backstop for anything that bypassed the agent tools.
- Treat docs as onboarding, not as the control plane.
checkyourvibe's install path is cyv init → cyv check → cyv install-hooks → cyv install-ci. The interesting part is not the CLI names. It is which layer each command touches.
Scope
Gates do not replace tests, types, or review. One model and one repo do not generalize forever — larger multi-model runs on the poisoning harness are planned. checkyourvibe was not the gate in the 140 trials.
Claim about control planes: in an agent world, standards that cannot refuse the edit are not enforcement. They are commentary. Commentary still helps sometimes. The matrix says it helps unevenly. The refuse-before-write path is the one that held.
Links
- checkyourvibe
- precedent-poisoning
- Blog: precedent poisoning
- Same shape at HTTP: Validation is a gate
- DOI: 10.5281/zenodo.22732965