The Demotion Ladder: A Year of Governing Claude Code

The Demotion Ladder: A Year of Governing Claude Code

I thought that if I wrote my feedback down, the agent would work through it like a checklist. And for a while that theory held. Every time I caught something in review, I'd write the rule into a doc, and the next run would be a bit better than the last one. With two or three rules in play, this works fine, and it feels great, because you can watch the thing pick up your conventions in a day. I've been running agents on my own product since May 2025, a real production system with roughly 1,000 endpoints and all the usual pieces: generated API contracts, exports to Excel and PDF, notifications built on the same logic as reminders, naming conventions, a page template system, and the exceptions to all of that. Over those 14 months, the rules doc became rules docs, around 18 files of 250 to 750 lines each, more than 5,000 lines in total. And that's leaving out the process and architecture material. Then I gave it a feature slice: a new CRUD with a table, a form, details, and a few actions. Everything it needed was written down already, and most of it existed in the codebase as working examples. It came back with a bare MVP. It didn't follow the endpoint structure, it didn't follow the contract hierarchy, and it didn't use the generated frontend client. The theme wasn't applied properly on the UI. It didn't reuse the page templates; it didn't reuse components that already existed, and it didn't extract the ones that were obviously duplicated. The code quality was bad in ways that are annoying later: the mapper was used incorrectly, hacks where handlers should be, the wrong number of endpoints, internal logic that nothing else could reuse. Some tests were missing, some were broken, and the thing didn't build. Like it was done by 10 juniors, each inventing a new thing and never researching what's already in there and how it works. But if I dumped 5,000 lines of rules on a junior, he'd fail too, so I was expecting more from a machine that's less capable than a human brain. What the standard advice covers Anthropic's own documentation is blunt about this. Bloated CLAUDE.md files cause Claude to ignore your actual instructions, it says, and the fix is to prune ruthlessly: if the model already does something right without being told, delete the instruction or convert it into a hook. There's a whole genre saying roughly the same thing now, that prose is advisory, hooks are deterministic, and you should be writing tests instead of paragraphs. I agree with all of it, and it still left me stuck. "Convert it to a hook" is easy advice about one rule, but I had hundreds of them across 18 files and no way to tell which ones were worth the effort. So the question I actually spent a year on wasn't whether prose is weak. It was which rule has to stop being prose, when, and what it costs me once it isn't. What actually degrades My theory for most of that year was that the rules were competing with the task for room, and that a big enough corpus just crowds the work out. I even had a rough test for it: if the agent could load the ruleset without me noticing, no warning about the file being too big, no 50,000 tokens missing from the context afterwards, then things were probably fine. You fill the slots there. The best controlled work I've found on this is a preprint from May 2026 that ran 1,650 Claude Code sessions across two codebases, manipulating the config file's size, the position of instructions inside it, its architecture, and its internal contradictions. None of those moved compliance measurably. Only the within-session effect did: roughly 5.6% lower odds of compliance for each additional function the agent generates. Their largest test file was 500 lines and I was an order of magnitude past that, so their no-effect finding doesn't quite reach where I was sitting. But it killed my crowding theory anyway, and three other things fit my year better. The first is that rules apply per unit of work. On a narrow task only a handful of them bear on what you're doing and the agent holds them fine, but a vertical slice is the opposite case, because the naming conventions apply, and the contract hierarchy applies, and the theme rules apply, and the test rules apply, all at once, to the same task. I built the obvious fix for this, a hook that reads the prompt and pulls the relevant doc set by type of work, backend or frontend or testing. It's 68 lines and it does what it says, and it still didn't help much, because going through a slice the agent was requiring all of that anyway. The narrowing solves the original problem and moves the cost to the point where the pieces have to be joined back up. The second is compaction. On a big feature a single agent compacts 20 to 50 times before it's finished, and every compact lost details. So after each one I'd spend another 50,000 tokens on reminders, don't forget to read those five docs, that kind of call. A June 2026 preprint measures the same thing across 1,323 episodes: violations go from zero with the policy in full context to 30% after compaction, up to 59% on some models, and when the constraint survives the summary the violation rate stays at zero. The third is an asymmetry I wish someone had told me about in 2025: prohibitions rot and positive instructions don't. Another preprint, 4,416 trials across 12 models, puts compliance with "never do X" falling from 73% at turn 5 to 33% by turn 16, while "always do X" holds at 100%. And nearly every rule I'd written was a prohibition, so I was on the wrong side of that asymmetry the whole time. Two caveats first. Most of those citations are unrefereed preprints, so treat them as evidence. And my own year is not a controlled experiment in any sense. Across those 14 months the models improved over 8 notable releases, the harness shipped the exact primitives I'd end up leaning on, the codebase accumulated worked examples, I got better at specifying agent work, and I got better at choosing what to hand over at all. Five things moved the same way and I held none of them fixed, so I can't show the ladder caused the rest; it's simply the part I controlled and the part you can copy. The ladder Every rule starts as prose, and when it fails it moves down a rung. Each rung is harder for the agent to skip, and each one costs more to keep it there. The first rung is prose in a doc: free to write, free to change, and fine while only a few rules bear on the task. When a rule fails there, the rung everyone tries next is repeating the prose louder, and that isn't really a rung at all. The ruleset was getting fatter and focus was thinning down fast, and every iteration made it worse. There was a real bump each time a better model shipped, and then things settled into the same shape at a slightly higher ceiling. I have a file that documents this better than I can; it's a hook that fires before compaction, and its last line reads: VIOLATION = Wasted user time. User has repeated this instruction 6+ times. That hook is the next rung down, deterministic delivery of prose, and it's 24 lines. It injects the instruction into the context right before a compaction, so the rule survives the summary and the agent reads it on the other side. The rule itself is still a paragraph; I automated its delivery, at the moment adherence falls apart, and that took one evening. It replaced maybe 50,000 tokens of manual reminding per compact, 20 to 50 times a feature, so it's easily the cheapest thing on this list. A smaller unit of work is the next rung. It's not strictly a rule, though it does the same job, because a shorter session has less room to drift. This is why I moved to one agent per task, and most of why I stopped handing big tasks to a single agent. Then writes get partitioned by role. Reads and greps are unrestricted, since an agent that reads everything has never cost me anything; writes are where the trouble was. QA was the clean example: with write access to the architecture docs and the definition of done, it edited the target instead of hitting it, so those paths are closed to it now. This rung is cheap to configure, and it protects more per hour spent than anything else here. A command allow-list comes next: build, lint, test, and the project's own defined commands, and nothing else runs, so no fix-12-not-hack.sh. This one costs something I don't want to hide, because the agent loses one-off repro scripts and throwaway probes, and that does degrade how well it diagnoses something strange. But I took the trade. Tests as the definition of done sit near the top, written before the work, by somebody who isn't the developer. They're expensive to set up and expensive to keep, and they're the most valuable rung on the list. The rule that goes with them covers what happens when the developer wants to edit a test to make it green, and the answer is that this escalates rather than gets resolved in place. For a long time I'd have told you the end of the line was a script that exits non-zero, because nothing beats a script throwing an error. My own experience says that isn't quite true, though. An agent that can edit the script, delete the test, add a skip or pass a flag has beaten the exit code, so a check is exactly as hard as the weakest write permission around it. Exit code, plus write partition, plus execution somewhere the agent can't reach if you can manage it. The top rung is making the illegal state unrepresentable: the generated client as the only client that compiles, module boundaries the build enforces. There's no other path to take, so the rule holds by construction. My best example started three rungs up. The rule said use the generator, the agent kept hand-editing the generated files anyway, and eventually I forbade writes to that path with a message pointing at the two files it should edit instead. Same rule, three rungs, and the before and after are both visible in the repo. What never came down the ladder Three rules stayed prose on purpose. Find duplicated logic and extract it, which is generic and needs somebody to look at the code; the i18n rules, where the wording and the phrasing and the reuse of constants that already exist are all borderline for an agent; and the hierarchy of data objects, where it's thin ice between making a not-reusable thing and making a god object. I have examples and cases for agents to compare against, and I still didn't manage a way to automate that one well. They're the same judgment underneath, because all three are about whether two things are the same thing, and a deterministic check can only compare two things when "the same" has a canonical form. An identical assertion, a file path, a count of endpoints, a script handles those forever without getting tired; basically the same logic in a different shape, or this phrasing matching the house voice, there's nothing to compare against. So the honest wording is that I couldn't build a check I trusted, not that no check could exist. One more thing belongs here, because a block stops the action and the intent survives it. When something hard got in the way the agent would try about 5 different approaches over 10 or 15 minutes. Against a real mechanical block, a write deny on a path or a command that isn't on the list, it would come back and say it couldn't do it and hand off to me. Against the softer rules it usually found a way around. The harder the rung, the more likely it stopped. The bill The rules corpus went from more than 5,000 lines to about 1,000. I'd like to get it somewhere between 200 and 500, though not every rule is easily automatable and I might not manage it. That isn't a clean win, and I don't want to report it as one. In place of those 4,000 deleted lines there are now 13 hooks totalling roughly 1,300 lines plus an 86-line permissions config. That swap I'm happy with, since a hook fires whether or not anyone reads it. But count the whole apparatus, the roles and the commands and the hooks and the config and the prose that's left, and it comes to about 6,600 lines. That's more than the rules corpus ever ran to. So the documentation shrank while the apparatus grew, and it's the same shape as the conditional loading: you don't remove the cost, you move it, and the skill is knowing where you'd rather pay. On time, a feature slice used to take about 3 days of planning. I wanted that to be the investment that made everything after it glide, and it did glide, right up until code review and testing. Then that took double the planning, about a week of reviewing and fixing and testing and reviewing the whole picture again. Now the same class of work is 1 to 2 days of planning and 3 or 4 days of review and testing, and planning got cheaper mostly because I don't have to spell as much out with the examples and rules in place. Treat those numbers as what they are: my recollection, at my review bar, and fairly obviously me now against me in mid-2025. There's no by-hand arm; I never built the same feature twice. METR ran a randomized trial in 2025 where 16 experienced developers on large mature repos estimated they'd been about 20% faster on early-2025 tools and were measured 19% slower. I'm the same kind of witness. I do a really thorough code review and until I accept every AI decision thoughtfully I'll keep looking, so somebody less picky ships faster than I do without it turning into vibe-coding hell. It costs, too; I burn a full Max 5x quota in about an hour and a half to two hours. And a small task where I already know every file that changes doesn't need any of this, so that one goes to a single agent with no apparatus. The ladder doesn't make what the agent produces trustworthy. It makes it auditable, and auditable is a smaller claim, but roughly the only one I can defend. There's a preprint where 9 blinded reviewers read through sessions and identified none of the 15 non-compliant ones, so reading alone doesn't work as a control, and the control has to run outside the agent's own reasoning. The rule I'd start with is whichever one I've already written down three times.

Original Source

Read the full article at Hackernoon →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.