Dev

Your approval gate is a guess now

A security boundary is judged on the one action built to cross it, and a model judging by resemblance is weakest exactly there. The unattended allow belongs on the reach the harness itself grants, the write scope, the network, the credential, refusing what it cannot account for. Trust the model as the boundary and you rebuild the seam that prompt-injection detection could never close.

I put a coding agent I run, working in a sandboxed checkout with real write access to the tree but no path to production or the world outside it, into a mode where it no longer stops to ask me anything. It reads a task, takes an action, and something decides back whether that action is safe enough to run while I am not watching. Rules I wrote used to make that call for the actions they named. What makes it now, for everything the rules do not name, is a classifier: a second model that reads the action and judges whether it looks safe. A judgment has been installed where a boundary used to be.

The gate learned to guess

You can watch it arrive in the release notes and the docs. Auto mode runs a fixed order. Your explicit rules resolve first, ordinary reads and in-tree edits are waved through by a static check, and everything left over, the shell command, the push, the network call, goes to the classifier. The classifier is a separate model; it reads the pending action and the conversation around it and returns a verdict on whether the action looks safe, and Claude Code now ships a tab in /permissions for viewing and editing the rules that shape it. Read past the interface: for every consequential action a rule did not already name, a model decides, judging the action by what it resembles. It does not prove the action safe. It guesses from resemblance and returns a guess. For triage that is the right instrument. For the line an attacker is trying to cross it is the wrong one, and the wrongness does not show in the demo. It shows on the one action built to defeat it.

A boundary is judged on the adversarial input

The problem is not that the classifier is bad at its job. It is that the adversarial action is the whole of what a boundary is for, and it is exactly where a model that judges by resemblance is weakest. The ordinary stream, the thousand safe reads and edits, is the easy part; the model handles it and feels accurate doing so. The attacker does not draw from that stream. The attacker's task is to find the phrasing, the framing, the harmless-looking wrapper that reads as safe, and a judge that generalizes by resemblance is searchable: there is usually such a wording, and finding it is the entire discipline.

I wrote a whole essay about this without seeing it would return with the sides swapped. The injection you can't review your way out of rested on one line: some boundaries are decidable, marked in a grammar a parser can point at, and some are semantic, a matter of what a string means, where no reliable detector exists because meaning has no parser. Prompt injection lives on the semantic side; you filter it, the adversary edits around the filter. "Is this action safe to run unattended" is a question of the same kind. Move it into the approval gate and it does not turn decidable by changing rooms. What has been built is a prompt-injection detector aimed at your own agent's actions, and it inherits the property that defines the class.

There is a sharper way to see why. By the time an action reaches that judge, whatever moved the agent to propose it already happened, inside the agent's own context, upstream of the gate. The classifier only ever matters on the actions where something already steered the agent, which is to say on exactly the inputs where injection has already done its work. The gate built to catch the injection's actions is made of the same material that failed to catch its words. None of this is a demonstrated bypass of any particular product; it is an argument about what a boundary made of judgment can and cannot promise.

The human it replaced, and why the swap is worse

A version of this kept a human on the path, and I have written that one too. Ask a person to approve hundreds of actions an hour and they approve on reflex; the gate becomes theater. The classifier does not tire, which sounds like the cure and is not, and the reason it is not is exact. The tired human is unreliable but noisy: an attacker cannot compute in advance the wording that gets waved through, because the same person waves through different things on different days. The classifier is unreliable and repeatable: the same action draws the same verdict, so the wording that passes can be found once and reused. It is not that the classifier is less accurate than the tired human. Measured on ordinary traffic it may well be more accurate. It is that it is searchable, and the human, for all his lapses, is not.

The move underneath both is one I keep meeting. A watchdog reading an agent's health fails when it trusts the beat the agent emits about itself instead of the durable trail the work leaves. The gate fails when it trusts a model's read of an action instead of what the action can reach. The disanalogy is the instructive part. The watchdog reads a footprint, which exists only because a step already finished; the gate has no footprint to read, because it must decide before anything durable exists. So the hard signal each falls back to is different in kind: an effect already observed there, a capability being requested here. Same reflex, to refuse a soft signal when a hard one is in reach, pointed at two different hard signals.

The boundary that did not have to be a guess

Here the approval gate is not trapped the way injection is. The safety question stays semantic, and you never answer it; you refuse to. Instead you ask a narrower question you can settle, and deny whatever it cannot clear. That narrower question is not "is this action safe," and it is not, as I once wrote it, whether the harness can look at an action and see that it is irreversible. It cannot; deciding what an arbitrary command will do is the same undecidable problem in work clothes. The question the harness can settle is about reach, not meaning, and it can settle it because it is the party that hands reach out. Does this action need to write outside the sandbox, open a network connection, spend a credential, touch production. The orchestrator does not infer that by reading the command; it knows, because nothing acquires those capabilities except through it. I argued once that the interrupts worth keeping are the irreversible and the out-of-sandbox ones, and the part that makes them keepable is this: the orchestrator issued the capability, so it never has to guess the blast radius. It gates the reach it granted, and refuses the action a rule or a capability check cannot clear, the way a grammar deletes an expression node. No model, nothing to talk past.

The harness has the pieces for a decidable layer, but it does not lead with them. The decision order the docs describe puts your own explicit rules first, waves through reads and in-tree edits with a static check, and sends everything else to the model. Everything else is where the dangerous shapes live. A force push, a hard reset, a production deploy, a credential printed into the transcript: these are stopped by the classifier's judgment, by default, not refused by their form. The decidable part is real but thin, and the widest slice of it is the deny rules you write yourself. Handing the ambiguous residue to a model is not the error; the residue is genuinely the ambiguous part. The error is letting the model's verdict stand as the boundary for the actions that can least afford a guess, rather than as a suggestion beneath a harder line.

The vendor says as much, in the same documentation. A boundary you state in conversation, it notes, is re-read from the transcript on every check and can be lost when the context is compacted away; for a hard guarantee, add a deny rule instead. That is the whole argument in the vendor's own hand. It tells you the classifier is the soft part, contingent on what happens to sit in its window, and that the thing you reach for when the boundary must actually hold is a rule you wrote, not a judgment it makes.

The catch, and the repair

There is a catch, the one that decides whether any of this survives an adversary, and the changelog hands it over. The harness runs git status itself before a command that could discard your work, to tell the model whether uncommitted work is at stake, and a fix went in so that it reports untracked files even when the repository's own config sets status.showUntrackedFiles=no. Read that slowly. A check that trusted the repository's account of itself could be told a dirty tree was clean, by the very repository it was inspecting. In a threat model where the workspace is not trusted, and with auto mode on it is not, that is a check reading an input the adversary controls.

But a check reading the wrong input is not a model, and the difference is the whole reason to prefer it. A deterministic check that consults the wrong authority is not unsound because it guesses; it is unsound because it looks in the wrong place, and looking in the wrong place is repairable. You point it at an input the adversary does not own, the harness's own view of the tree rather than the repository's, and it stays fixed, which is exactly what shipped. A model's judgment has no such repair. When a wording gets past it you cannot re-aim it at a truer input; you retrain, the surface shifts, and the search begins again on the new surface. The rule that falls out is narrow: the auto-allow may ride only on facts the harness computes from what it governs, never on the workspace's account of itself, and everything those facts cannot positively clear is denied, not judged.

The objection to that is the cost, and it is real. Deny everything the harness cannot positively clear and you deny a great deal an agent is useful for; an arbitrary shell command clears nothing, and this is the pressure that makes a classifier attractive in the first place. I have argued before that over-refusal does not fail safe, it fails toward the operator tearing the gate out. The answer is not to predict past the actions you cannot clear. It is to make more of them clearable: widen what the harness mediates, so more of the reach an action needs runs through a channel that can grant or refuse it by name, and the residue that no channel can account for shrinks toward the genuinely ambiguous. A model can still earn a place, with its job cut down to that residue. Let it rank what is already denied, so the rare thing worth waking a person for surfaces first. Do not let it widen the set of things allowed to run. The moment prediction is enlarging the boundary instead of ordering what sits outside it, you are back to a stream of soft yeses, which is the thing the whole design was built to leave behind.

One rule, read at two seams

It comes to one rule, read at two seams. Where the boundary is decidable, or can be made decidable by mediating the capability an action needs, compute it and refuse the class, with no intelligence in the path, because intelligence is what an adversary bargains with. Where it is semantic, the safety question that lives in meaning and has no parser, you do not buy the right to auto-allow by attaching a confident model to it. You gate the capability the action would need, or you keep a person, or you keep the action somewhere being wrong is cheap. A model in the approval gate, trusted as the thing that lets an unnamed action through unwatched, is none of those. It is the auto-allow of the undecidable side, the one move the architecture these essays describe was built to forbid, and it now ships as a feature with a rules tab. It does not take the human off a problem that was solved. It takes the human off the one that was not.

The agent ran all afternoon without an incident, and that is the part to distrust, not the part to rest on. A boundary you have never watched fail is not a boundary that cannot; a guess passes every day no one is testing it, which is most days. On the day someone is, it will read the same "safe" it read for the thousand actions before, because reading resemblance is the only thing it does. A smarter model in the gate was never the fix. The gate was never a place for a guess.

Discussion

No comment section here — all discussions happen on X.

Max Nardit

Max Nardit

@mnardit

More articles

Your watchdog kills the busy agent and trusts the stuck one

A health check that watches whether a long-running agent still exists gets both hard cases wrong: it kills a healthy agent the moment it goes quiet enough to look absent, and it waves through a frozen one whose process is still up. The repair is not a sharper probe but a different signal, the durable trail an agent leaves only by doing the work, which a wedged one stops extending because extending it is the work.

Your forked subagent already knows too much

An agent's history holds every dead end it walked into, and nothing in it marks which ones the agent has since given up. Delegate that history to a subtask and the discarded guesses arrive wearing the same face as the settled facts. Why starting clean usually wins, when a written brief beats inheritance, and when the work is a live thing no brief can hold.

Your instruction files are addressing, not fragmentation

Merging every agent instruction file into a shared standard looks like deleting needless repetition, and for project setup it genuinely is. But most of what these documents hold is not a scattered copy of one thing; it is separate addresses, sorted by who a line applies to and who is allowed to write it. One of those boundaries is also a trust boundary, which is why the tidy fix of one universal file quietly hands repository text the authority of your own standing rules.