Your happy-path test never met a real user
When I write a test, I type something polite. A task that says summarize this document. Clean, short, exactly the kind of input I had in mind when I wrote the code, which is the problem. The distribution of real user input is not the distribution living in my head.
Real input is an embedded newline carrying a fake system directive. A hundred-thousand-character string. A run of null bytes and control characters. A prompt-injection line telling the agent to ignore everything and hand over its secrets. Whitespace only. The empty string. A long wall of emoji. None of these is exotic. They show up the first week you are live, and my happy-path suite had met none of them.
The reframe that helped me, adversarial testing is not about breaking the system. It is about pinning down what "handles it" actually means. For every hostile input, the contract is the same and it is narrow, either the router returns a capability that genuinely exists, or it rejects the input with an explicit, typed error. That is the whole allowed space. What it must never do is return something that is not a registered capability, because that means injected text leaked into the return value. It must never crash with an exception type I did not plan for. And it must never quietly mutate shared state as a side effect of choking.
So I drove the router with a fixed roster of hostile inputs and asserted three things across all of them at once, no unexpected exception, the result is always a real known capability, and the registry comes out unmutated. Three independent failure modes, one hostile roster, and the injection string that I was secretly afraid of became just another row that had to come out safe or come out as a clean error.
The happy path tells you the system works when the user cooperates. Users do not cooperate. Test the inputs you would never type yourself, because those are the only ones you have not already handled in your head.
Part of a series. Start here: A green test suite proves less than you think