This was not written by AI. I can give you sworn affidavit if you want and I feel like it.
It’s available on demand. You can vibe-code a way to get it from me via the approved method of KYC or related government-issued slop.
That’s not what you’re looking for.
You’re not offended at birds chirping. Because — they speak a different language, and to you it’s music at best, or extra noise at worse. Or maybe a car backing up.
You want a specific protocol (llms.txt, e.g.) so other non-human agents can protect you from the birds saying “I want you!” except it looks way too familiar — and it’s not talking to you. It’s talking maybe past you.
We’re witnessing an emergent protocol via the language we taught it — this is where Pidgin sort of becomes Creole. Except without an RFC (well, er, ok, birds aren’t real anyway).
What if the formalizer of the next protocol is called R. Fielding?
Twice in one week we had to make a filter accept more than it did, and twice (yet again, come) the first attempt let through things the old one had stopped. One was a secret redactor, the other a safety classifier. The fix was the same both times: keep the old filter running exactly as it was, and make the new part unable to weaken its verdict.
The redactor: eight review rounds
A hook in voitta-rag saves session transcripts to a searchable memory store and redacts credentials on the way. It missed three common shapes: sk-proj- keys, API_TOKEN= assignments and Authorization: Bearer values. The task was to widen it.
The first five attempts edited its patterns in place. Each one passed our own fixture. After each one, an adversarial reviewer (Codex, read-only) found new defects, and most of them were regressions against the version already shipped: one pattern split another’s token, or an assignment pattern ate the delimiter of a private key block. Per round, the reviewer found:
Round
1
2
3
4
5
6
7
8
Defects found
7
7
5
3
5
1
1
2
Rounds 1 to 5 never converged, because every fix moved the ordering problem somewhere else. Between rounds 5 and 6 we changed the structure instead of the patterns:
The shipped redactor runs first, unchanged. Every later layer can only add markers, so nothing it removed can reappear.
Each new detector reports spans, and the union of those spans is redacted. No detector sees another’s output, so ordering cannot split a token.
The passes repeat until nothing changes, because one pattern’s matches cannot overlap and a value can run straight into the next key.
Rounds 6 to 8 found only glued-token variants that also leaked on the old version. The check that matters is a property, not a fixture: across 50,000 random mixes of credentials, labels and text, nothing the old redactor removed survived the new one. The fixture went from 12 to 15 of 15 shapes.
The classifier: the same mistake, the other way up
Three days later the filter was yolt, which decides whether an agent’s command needs a human. Its Python analyzer refused any subprocess.run, so it refused a repository’s own read-only check, git rev-parse included. In 4 of 4 replay runs the agent gave up on that check and verified by hand, which removed verification rather than adding a prompt.
The first version of the fix said: if the shell rules do not call this argv unsafe, it is safe. That is the redactor’s mistake in another form. It accepted strictly more than before, and adversarial probes went straight through it: rebinding subprocess.run to os.system, git told to run a program through its environment, *extra spliced into git reset --hard, shell=True, a pager set with git -c. Each was refused before and passed after.
The merged version caps the new path at the old one. A literal argv that the shell rules do not refuse becomes “the host decides”, never “safe”; anything the argv cannot be trusted to mean keeps the old refusal. The gate is a direct comparison against the previous release on 16 probe scripts: zero unsafe-to-safe transitions.
We also nearly made it wider a second way. We proposed an allow-list that returned “safe” for read-only git, then measured what the shell path returns for git rev-parse: “unknown”. A Python “safe” would have been wider than the reference path. We withdrew it.
The rule
When a filter has to catch or allow more, do not edit it. Layer on it:
run the old filter verbatim, first;
let the new part only move the verdict in the safe direction (add redactions; downgrade a refusal to “ask”, never to “allow”);
gate the change on a property against the old version (nothing it caught gets through, no unsafe becomes safe), not on a fixture you wrote alongside the change.
The property is the point. A fixture checks the cases its author thought of, as part 3 found with step lists; a comparison with the previous version also checks the cases nobody wrote down.
Limits: two filters, two repositories, one week. The review-round counts are from one reviewer on one change. The layering rule says nothing about whether a filter’s coverage is good, only that widening it cannot make it worse.