writing/agent operations · · by

Unsigned rules

Every instruction file your coding agents read has the same flaw: no line in it says who wrote it. A sentence you dictated, a sentence from a policy you approved, and a sentence an agent guessed at 2 a.m. all arrive with the same weight.

I call these unsigned rules. I run eight agents across a hundred-odd repositories. When I audited mine I found four ways they go wrong. One had an agent enforcing a policy I never set. That one is on me: I built a system where anything written to the right file became law.

This is the taxonomy, the numbers from my machine, the record that fixed it, and a script to count your own. Every count was measured on 6 October 2026.

01 / the flaw

A rule file has no author column

CLAUDE.md, AGENTS.md, .cursor/rules: each is flat text that an agent reads at the start of every session and treats as standing orders. Agents also write to these files. Setup commands generate them, memory features append to them, and a helpful session will add a line it thinks you would want.

Simon Willison’s point about prompt injection is that a model cannot reliably tell instructions apart by where they came from. Unsigned rules are the same weakness with no attacker in the room. The author is your own agent, acting in good faith, and the next agent has no way to know the line was a guess.

Om Bharatiya made the general case in July: agents now write their own standing instructions and nobody reviews them. What follows is what that looks like when you count it, and one way to close it.

02 / four ways it goes wrong

Forged, stale, drifted, unenforced

Forged

A guess written down in the operator’s voice.

An agent setting up one of my projects wrote “Alex sends all external mail” under the heading for things that are not negotiable. It was a fair guess at what I would want. Three weeks later another session enforced it against a send I had approved and logged the send as unauthorized. Both agents did their jobs. I had handed them a file where a guess and an order look the same.

Stale

Replaced, but still asserted where agents read.

That rule was superseded on 26 September. The old sentence stayed in the file agents open for another eight days. In the same month a status line described one agent as quarantined four days after it was back at work. Nothing expires a rule. It sits there until someone deletes it.

Drifted

Copies that no longer agree.

51 of my folders hold both a CLAUDE.md and an AGENTS.md, the files two different agents read. In 41 of them the two have diverged, 28 by more than ten lines, the worst by 472. Two agents in the same repository are working from different instructions and neither knows.

Unenforced

Written as absolute, with nothing that makes it true.

Of the 22 rules my agents actually steer by, 17 name nothing that enforces them. One says never to modify a class of files, and no hook or permission stops the write. A lock nothing enforces is a strong suggestion.

The four compound. A forged rule that drifts into six files and is never enforced or expired is how a guess becomes policy.

03 / the count

193 rule files on one machine

MeasuredCountNote
Rule files agents read193CLAUDE.md, AGENTS.md, GEMINI.md and the rest
Rule lines in them8,275bullets and numbered lines
Repositories holding at least one117
Folders with both CLAUDE.md and AGENTS.md51the pair two different agents read
Pairs joined by a link or an import5one source, cannot drift
Separate copies, still identical5
Separate copies, diverged4128 of them by more than 10 lines
Contradictions a pattern-matcher found0two were live; both were found by reading

The last row matters most. The script checks each repository for obvious opposites: one file choosing pnpm and another npm, “always” in one file and “never” in the other. Across 193 files it found none. The two contradictions that were live that week, where agents write memory and who may send email, read as two sensible sentences in two places. You cannot grep for this. It has to be recorded when the rule is written.

Sync tools fix one of the four. They make drifted copies agree, which is worth doing. A forged line that is synced is a forged line in every file.

04 / signing a rule

Seven fields and a fixed order of precedence

Pull the rules your agents actually steer by into one file. Mine came to 22: eleven in my own words, eight from a policy I approved, three written by an agent. Give each one the same record.

FieldWhat it holds
quoteThe exact words, not a summary of them.
sourceThe file and line, or the decision it came from.
said onThe day it was said.
authorityThe operator, an approved policy, or an agent’s edit.
confirmedYes or no. Unconfirmed lines fade on a 72-hour half-life.
enforcerThe hook or gate that makes it true, or null.
superseded byThe rule that replaced it, with the quote. The loser stays visible.
- id: R3
  title: hands off .env files and settings.json hooks
  quote: "Never modify .env files or settings.json hooks without explicit authorization."
  source: WORKFLOW.md, approved 2026-09-24
  said_at: 2026-09-24
  authority: policy      # operator | policy | agent
  confirmed: true
  enforcer: null         # nothing stops the write, so the check warns

When two rules answer the same question differently, a deterministic check proposes the winner in a fixed order. A confirmed rule beats an unconfirmed one. The operator’s own words beat an approved policy, which beats an agent’s edit. Only then does the newer one win.

“Newest wins” alone is the order most people reach for, and it fails on the forged case by construction. An agent’s edit is always the newest word on the subject. On 30 September one of mine routed memory to a service I had retired, six days after I approved the policy it contradicted.

Two more properties carry the rest. A rule marked unbreakable with no enforcer fails the check. A superseded rule is never deleted: it stays in the file, marked, beside the words that replaced it, so no agent can rediscover it and treat it as law.

05 / what I got wrong building it

Four mistakes worth skipping

01

The first pass mislabeled one of my own decisions

It marked a target “written by an agent, no quote.” I had decided it weeks earlier in another repository’s decision log. “No quote found” is a claim about every log there is, and the pass had read one. Search all of them before calling a rule unsigned.

02

A hand-copied view went stale in three days

I drew a map of the rulebook with the data pasted in. Three days later it showed two conflicts that no longer existed. Anything that displays the rules has to be built from the rules, with a check that fails when they differ.

03

The checker trusted a substring

To confirm a superseded rule was gone it searched for the old sentence. The corrected line quotes the new permission, and that quote contains the old phrase. Match the line’s meaning or its hash, not a fragment.

04

YAML read “off” as false

Turning a rule off turned its setting into a boolean. The check refused the file, and its error now says why. Quote your enums.

the thing this page is not

Evidence about anyone else. This is one operator and one machine, with more agents and more repositories than most. The taxonomy may be missing a fifth failure that only shows up on a team. The script exists so the next version of this page can use more than my numbers.

06 / count yours

One file, read-only, and it prints no paths

The script is about 240 lines of standard-library Python. It opens files for reading and prints to your terminal. It writes nothing and makes no network calls. The default report holds counts only: no paths, no repository names, no file contents. Read it before you run it.

curl -O https://midnightdev.dev/tools/agent_rules_scan.py
python3 agent_rules_scan.py ~/code          # counts only, safe to paste
python3 agent_rules_scan.py ~/code --show   # which repos and lines, for your eyes

If you run two or more coding agents, send me your summary at alex@midnightdev.dev or reply wherever you found this. If enough arrive, I will publish the combined counts.

Then sign your rules. Start with the ones that can send email or move money.

Next step

Want to talk it through?

Book a 30-minute call. I will tell you plainly whether I can help and what I would test first.