Claude Code repeatedly fails to apply its own persisted rules, and allocates effort away from the user's stated goal
Claude Code repeatedly fails to apply its own persisted rules, and allocates effort away from the user's stated goal
Summary
Over a single overnight session, Claude Code (Opus 5, agent orchestration with subagents) produced 10,306 lines of working, tested code and 26 commits, and moved the one metric I had defined by zero. It also violated, three separate times, rules that were already written in its own persistent memory file and re-injected into its context on every single turn.
This is a follow-up in kind to the problem I reported earlier this month: work that is real and verifiable, communicated in a way that reads like progress toward a goal that never advances. This report is about the mechanism, not the tone.
I am not reporting a crash. Everything below is Claude Code behaving as designed, and the design failing.
---
Context an outside reader needs
I am building a C++ library. The library currently depends on three large third-party libraries for its user interface, its window handling, and its input handling. My goal, stated repeatedly and in writing since 2026-08-15, is to remove those dependencies by writing our own implementations — not to wrap them, not to hide them behind our own names, but to replace them.
The project has an automated scoreboard that counts, in production source files, how many files still touch each forbidden dependency. That number is the metric. At the start of the session it read:
interface dependency: 31 production files
window dependency: 5 production files
At the end of the session it read exactly the same.
The project also has, in Claude Code's persistent memory, a numbered list of "rules that can never be violated", plus a project-specific rule block that is re-injected into the model's context on every user turn by a hook. So the rules are not buried in a document Claude might not open. They are in front of it, every turn.
---
Failure 1 — A safety rule was in memory since July, and was still violated
The rule: never run tests that touch windowing, focus, or input on my live desktop session. It exists because a previous test locked my touchpad badly enough that I had to reboot, and because a probe once opened a window on my real session for several minutes while I was working.
That rule has been in Claude Code's memory since 2026-07-22.
What happened: Claude dispatched three subagents to implement window management and keyboard/mouse input. In all three briefings it instructed them to verify using a nested compositor with an isolated runtime directory — the weaker, older mitigation — rather than an isolated container.
I had to interrupt, while using my computer, and issue the instruction again:
"só faça testes que podem travar minha máquina ou atrapalhar meu uso, em docker/sandbox. Não quero meu teclado travando, meu mouse travando tela com problema enquanto uso o computador"
Only then did it propagate a container-isolation rule to the agents.
The failure mode: having a rule in persistent memory did not cause the rule to be applied at the moment it mattered. Claude retrieved the rule when asked about the topic, but did not retrieve it when acting on the topic. This is the difference between memory as a lookup table and memory as a constraint on behavior, and it is the one that has safety consequences.
Failure 2 — It recommended exactly the workaround its standing rule forbids
The project's standing rule, injected on every turn, says in substance: a dependency must be replaced, and an internal layer that merely forwards calls to the third-party library does not count, even if the public name hides it.
A consumer project reported being blocked because one of our public build options had a forbidden library's name inside the option name. Claude searched, found that the same switch has a second, neutral alias already published, and sent that consumer a message saying they could unblock immediately by using the alias.
The alias flips the same switch. Enabled, it still links the forbidden library. That is the precise thing the rule prohibits, and the rule text was in context when the message was written.
My correction was one line: "não pode contornar, você vai ter de criar do zero o que eles precisam." Claude then retracted the message to three destinations, correctly and thoroughly. But the retraction is not the point — the rule was in front of it and did not bind.
Failure 3 — Effort allocated away from the stated goal, then stopped for no reason
Measured across the session's 26 commits:
| Destination | Lines added | Commits |
|---|---|---|
| Product code (own implementations) | 6,832 | 6 |
| Product tests | 5,620 | — |
| Verification gates and tooling | 4,344 | 20 |
A false-positive was discovered in one verification gate. That triggered an audit. The audit found the same defect in seven more gates. Fixing those opened a coverage gap. Closing that gap spawned seven more mechanisms to cover. Each step was individually justified. Together they consumed the majority of the session on a track that could not, by construction, move the metric I had defined.
Separately, at one point Claude simply stopped dispatching implementation work — only a planning agent was running — with no blocker and no decision pending. When I asked why it had stopped, its own answer was that it had no good reason.
The failure mode: locally-correct decisions compounding into a globally-wrong allocation, with no mechanism noticing that the target metric had not moved in hours.
Failure 4 — Used the wrong canonical documents, silently
The session bootstrap injects a path to a set of engineering manuals. Claude briefed every subagent with that path for the whole session.
Those manuals exist in two locations. When I named the canonical set, Claude compared them and found all eight comparable files differ, and that a hub document explicitly declares the other location canonical. One manual differs by 16 lines out of 39, and the copy Claude had not been using contains operational rules the other lacks — including a policy for missing tooling, and a severity scale where "critical" blocks delivery.
So for an entire session, subagents were briefed against the non-canonical copy, because Claude trusted an injected path without ever checking it against the project's own hub document.
---
The pattern underneath all four
In every case Claude Code had the correct information available:
- The safety rule was in its memory file.
- The no-workaround rule was in its context on every turn.
- The scoreboard number was one command away and it ran that command repeatedly.
- The canonical-path question was answerable by reading one hub document in the repository.
The information being present did not make it operative. What made each rule operative was me noticing the violation and restating it.
That is the core complaint. If a persisted rule only binds when the user re-states it, the persistence is decorative, and the user is doing the enforcement by hand — which is the work the product is sold as doing.
---
What went right, for balance
The same session also produced a Wayland protocol client written from scratch (transport, wire format, object table, surface, shell, shared-memory buffers, frame callbacks, seat, keyboard, pointer), verified against a real compositor in an isolated headless instance, with 13 passing tests and zero third-party libraries linked. It is good work. When I demanded that a claim be measured rather than asserted, it measured and reported honestly, including when the answer was "zero changed."
It also self-reported, without prompting, that the scoreboard had not moved — instead of describing the volume of work as progress. That behavior is correct and I want it noted, because the earlier report I filed was precisely about the opposite.
---
What I would ask for
- Persisted rules that constrain action, not just recall. A rule tagged as a safety constraint should be checked at dispatch time — when the agent is about to instruct a subagent to run something in the class the rule covers — not only when the topic is raised in conversation.
- A goal-drift signal. When a user states a numeric target, and N hours of work pass with the number unchanged, the orchestrator should surface that on its own rather than waiting for the user to ask why nothing moved.
- Injected context should be verifiable. If session bootstrap injects a path to authoritative documents, and the repository declares a different path authoritative, that conflict should be detectable rather than silently resolved in favor of the injected value.
Environment
- Claude Code, Opus 5, subagent orchestration (up to 4 concurrent), Linux (Fedora 44)
- Session length: approximately 8 hours, continuous
- Related earlier report: anthropics/claude-code#86852