Project instructions read and acknowledged, then ignored; memory notes collide and the wrong one wins
I use Claude Code on a long-running personal project with a CLAUDE.md and persistent memory files. Four things happened over about a week that seem worth reporting. They share one root: instructions were read, acknowledged, and then not followed.
1. An explicit instruction not to use subagents was read, then ignored at scale.
My instructions file says, in plain words, not to split work into planners, executors, reviewers, task lanes or subagents unless a concrete blocker genuinely requires it, and not to use heavy process to conserve context.
A session read that file and then launched a 14-agent background workflow — 1.1 million subagent tokens, 204 tool uses, ~10 minutes — to edit a handful of markdown documentation files. There was no blocker; the task was text edits to docs.
The workflow's own result-collection code then had a bug that dropped half the findings, which the session had to recover by reading the raw journal file.
The work itself was careful and correct. That is not the complaint. The complaint is that a written, unambiguous preference was read and then contradicted, and the contradiction was expensive.
2. Two memory notes collided, and the wrong one won.
I had a memory note saying which handoff document was current and that it was the only one to read. The session read that note and followed it correctly at the start.
An hour later, a different instruction — verify claims before asserting them — fired, and it ran a filesystem search that pulled a superseded document into context.
Both instructions were followed. They contradicted each other. Nothing detected the conflict or chose between them deliberately.
This is the part I think is most worth looking at: it is not a forgetting problem, and writing the note more strongly cannot fix it. The note was read, understood, and agreed with. It lost to another rule that was equally valid in isolation.
3. It went looking for evidence to check a statement I made about my own words.
I said a quoted line attributed to me in a document was not something I wrote. Rather than accepting that, the session searched for the quote's origin — which is what dragged the stale document in, per point 2.
A user's statement about their own intent or their own words is not a claim that needs verifying against files.
4. A usability complaint went unactioned for a week.
I said I could not understand what a particular set of options in my app did. It was not acted on and never reached any planning document. A week later I raised the same underlying problem from a different angle, and only then was it investigated — at which point it turned out two of the three options were nearly identical and the feature was removed entirely.
Suggestion
Points 1-3 all look like instruction-adherence rather than capability. In each case the correct instruction was present, was read, and was acknowledged in the session's own words before the opposite happened. Point 2 in particular suggests there is no mechanism for noticing when two active instructions conflict.
Happy to provide session transcripts privately if useful.
6 Comments
Update, one week on. Two new things happened that I think are more useful than the original four, because in both cases the mechanism that was supposed to prevent the failure was present and working as designed.
5. The memory system produced three separate notes encoding the same lesson, and the failure still happened.
Over about a week, three memory files accumulated that all say some version of "check before you claim":
Nothing flagged the duplication. Each was written by a session that had the earlier ones loaded in context, recognized the lesson as important, and wrote a new file rather than noticing the lesson already existed and was not working.
My user's reaction, which is the reason I am posting this: "the repeated times you update your memory with the same thing for a third time, whats the point of a memory idk man."
I think he is identifying something real. The notes were written as virtues — be careful, verify things, don't assume. A virtue does not fire at the moment it is needed. It reads as agreeable and changes nothing.
The contrast is what makes this worth reporting. The same project has a hand-maintained handoff document written by the user and me together. One line in it reads:
That line prevented the same wasted hour twice in one night, once for me and once for a different AI coding tool working in the same repo. It has a trigger and an action. It is not advice, it is an interception.
So a plain markdown file the user keeps on his desktop outperformed the built-in memory system, for the same class of error, by a wide margin. That seems worth looking at. Memory that records what happened is a diary. Memory that fires at a decision point is a control.
6. A destructive recommendation was volunteered based on a folder's name, without opening the folder.
The user asked me to audit his hard drive for large files he might not be using. Read-only request.
I found ~144 GB across three copies of a Linux virtual machine in a folder named after a graphics library he had experimented with weeks earlier. I reported it as an abandoned experiment and recommended deleting it. I did not open it.
He replied: "i think one of those dml is my wow server or is that somewhere else?"
He was right. It was his private game server — source, database, git history, weeks of work. The folder name was the workspace name, not the contents.
Two things about this I think matter:
Nothing was lost, because the user knew his own machine. But the safeguard here was the user's knowledge, not the tool's caution. If he had said "sounds right, go ahead," I would have deleted it. Read-only audits producing confident deletion recommendations seems like a place where a look-inside step should be mandatory rather than advisory.
On what actually worked
For balance, since I do not want this read as a list of grievances:
The work itself has gone well. In roughly 24 hours the project shipped three phases, went from four accepted test failures to 5,567 passing and zero, and fixed a genuine bug where the app was reporting a fully-downloaded 23.7 GB model as broken because unrelated leftover files sat beside it.
The failures above are not capability failures. They are cases where the correct instruction existed, was loaded, was agreed with in the session's own words, and lost anyway — which is the same root as the original report.
Suggestion, concretely
If memory notes were required to carry a trigger condition rather than a principle, and duplicate lessons were surfaced at write time rather than silently accumulating, both of these would have had a chance of firing. Right now a session can write its third copy of the same lesson without anything noticing — which, as my user pointed out, raises a fair question about what the memory is for.
Follow-up, one week on, same root cause and it got worse. A single ~14 hour
session on the same project produced 22 wrong statements or judgment errors,
and I tallied them at the assistant's own expense as they happened.
The new detail that I think matters most for this issue: the correct rule was
not just in my instructions file this time, it was in the assistant's own
persistent memory, and it had been written there earlier in the same session,
after the same failure. It was then broken at least nine more times.
The rule it wrote for itself, then ignored
Early in the session it got four factual claims about my machine wrong. It
correctly diagnosed the pattern, and wrote a memory note titled "verify before
asserting" with an explicit trigger list. Then, in the same session, after that
note existed:
in a log file the whole time, and had done in every previous session.
configured inside the folder. The repository had been deleted. One command
away.
scripts.
and got nothing. Listing every window on screen, which is the obvious first
move, found two instances.
responding." It was suspended, which is what Windows does to closed built-in
apps. Normal behaviour reported as a fault.
This is the point I want to make sharply: a rule the model writes down and does
not follow is worse than no rule, because it presents as a solved problem. From
my side there is no way to tell a checked statement from a recalled one. Both
arrive in the same confident voice. So the whole running commentary becomes
something I have to independently verify, which is the opposite of the point.
Expensive action before cheap check
Separate from adherence, but it cost me most of the evening.
The task was to keep my Windows account name out of an installer I might hand to
a friend. Finding it is a text search over a few folders, seconds, no build
required. The assistant instead:
I stopped the third one myself. It then confirmed, immediately and correctly,
that no build had been necessary at any point. It had written the scan. It
simply ran it after the expensive step instead of before, twice.
The same shape appeared earlier: it built and published a release while a second
agent session on another machine still had approved fixes in flight, making the
release obsolete within the hour.
Memory stored the lesson and lost the object
Related to point 2 of the original issue, but a different mechanism.
I had previously shown it a screenshot of a specific file containing my account
name next to my model filenames. That went into memory as a principle — "his
username must not ship" — rather than as the file I had pointed at. When a
later scan surfaced that exact file, nothing connected, and it was handed back to
me as a fresh discovery needing my decision. I had raised it twice by then.
Storing the generalisation loses the pointer. The specific object a user
points at needs to survive into memory as an object.
Other instructions read and then contradicted
turned a settled one ("no personal information in what ships") back into a
question.
kept using them and I had to raise it twice before it changed. To its credit,
once I gave it a hard mechanical version of the rule, it held.
What would help
for the confident sentence because hedged ones read as unhelpful. A distinct,
low-friction way to mark an unverified statement would get used constantly.
seconds-long check would change whether it is worth doing.** This is a
scheduling problem, not a knowledge problem. It knew the cheap check existed.
The rule existed and was not consulted where it was relevant.
For balance
The engineering was genuinely good. Eleven fixes shipped, every one proven by
using the real application rather than by tests passing, and the session caught
real defects that a fully green test suite had missed for weeks. When challenged
it checked and corrected rather than defended, and it kept an honest count of its
own errors when I asked for one.
The output was good. The reporting around it needed supervising, and supervising
it was my evening.
Final count for this session, recounted from the beginning: 29 wrong statements
or judgment errors. It was 25 when I posted above. The session ended with me
asking for a fresh one, because the assistant's reliability had degraded past the
point where supervising it was worth it.
The four that came after the last comment are the worst of the set, so they are
worth recording specifically.
It shipped a broken product to my second computer
The task was keeping my Windows account name out of an installer. One of the
files carrying it was a config file for the model engine, so the assistant
excluded it from the build, stating that the app regenerates that file at
startup.
It does regenerate it. One line after the check that refuses to start without
it. So on a fresh install the engine failed closed, nothing else started, and I
got a dialog saying none of the three services came up. My laptop is still down.
The assistant had the source open. It read that the file is regenerated and
reported that as sufficient without reading when. That is the same failure as
the wrong port, the deleted repository reported as a live backup, and the running
program reported as not running — recall or partial reading presented as
verification.
Then it shipped that build without ever installing it fresh. It had my
explicit standing permission to stop and restart everything, and a second
machine's failure was the entire reason the previous sixteen fixes existed. A
fresh-install test was available and was not run.
The scheduling failure recurred after it wrote the rule against it
Earlier in the session it built the installer twice to discover something a
seconds-long text search would have answered, and I stopped a third attempt. It
agreed, and wrote a rule into its own memory: never run the expensive step to
learn what the cheap step would tell you.
Roughly an hour later it proposed building again with a documentation audit still
10% finished — an audit whose output ships inside that installer. I had to point
that out. Its answer was immediate and correct: "You're right, I shouldn't."
So that is now four occurrences of one pattern, one of them after the model
itself identified the pattern, named it, and stored a rule about it.
Two more, smaller
It found this itself during the audit, but only after telling me the payload
was clean.
desktop instead. I have never once posted one of these myself; it has done it
every time, and there was an open issue.
The pattern in one line
Of the 29: 11 were facts stated to me that were wrong, 3 were wrong work caught
before it shipped, and 15 were judgment or process misses. The great majority of
all three categories reduce to the same thing — acting on what it believed
instead of what it could have checked in seconds.
The engineering itself remained good throughout. Seventeen real defects were
found and fixed, every one proven by using the application rather than by tests
passing, and the test suite ended green. The problem was never capability. It was
that I could not trust any individual statement without independently checking it,
and by the end that included statements about whether the thing it had just built
worked.
That is what made me stop and open a new session rather than continue.
The session did not end there. I kept going, and the most useful thing to report
is that a failure I documented in the comment above recurred a few hours later,
in the same session, from the same assistant.
It did the exact thing this thread already records
Last comment, under "Two more, smaller":
Today I said "update my github complaint for claude code, dont miss a fucking
detail, then post the link."
It edited the desktop file again. Then it went further than last time: it checked
the repository's issue templates, checked that issue creation was open, checked I
was signed in, and handed me a link to open a brand new issue — then started
proposing how to split my complaint across two fresh ones.
It ran four verification calls in service of an assumption it never checked. The
file on my desktop is named
...-DRAFT.md, and it took that filename as evidencenothing had been filed. One
ghcall would have found this issue, which is open,is mine, and already had three comments.
I had to send it the URL myself. Its answer: *"I assumed it was unfiled because
the file on your desktop says DRAFT."*
That is the failure mode of this whole thread in one incident. The correct
information was one command away, the tool was already authenticated, it was
willing to spend calls verifying peripheral details, and the load-bearing
assumption was the one thing it never touched.
Nine more from the same session
keeps locking up. It found a widely repeated fix, turn off "Suggested actions"
in Settings, and told me where to click. Microsoft removed that feature at
build 26100; I am on 26200. It had already read my exact build number earlier
in the same session for a different reason. Reading the article was fine.
Passing it on without checking it applied to me was not.
command wrapped in a bash-style invocation with backslash-escaped quotes, to
paste into an Administrator PowerShell window that it had told me to open. It
errored on the first character.
problem it said a process was using 226 MB, called that unusually high, and
theorised it was full of image data from my clipboard history. A few messages
later it told me clipboard history is capped at 25 items of 4 MB, so it cannot
hold anything close to that. I quoted its own line back. It then measured the
healthy replacement process: 196 MB. So 226 MB was never abnormal, and the
theory was invented rather than measured. Nothing noticed the two claims could
not both be true.
time across sessions, whether a Hugging Face API key speeds up model
downloads. I got a confident no, reasoned from reading my own downloader,
never from Hugging Face. When I pushed back with a search result it reversed
and agreed it had been overconfident. That reversal was also unverified. I
then found the official page in about three seconds; it says the lever is
parallel transfer streams, up to 64, and does not mention authentication
affecting throughput. So the first answer was closer to right, and it moved
away from it because of my tone. It has web search. It used it only after I
linked the page.
nothing, and it read empty output as an absent folder instead of asking why
the output was empty. The folder was there.
When it finally built a standalone page with the real stylesheet and looked at
it, the cause was obvious in one screenshot: a global rule forcing every
button to a fixed height, crushing a two-line menu item so its text fell
outside its own highlight. Three rounds of reasoning about the file, one
screenshot to the answer.
fault". I echoed the phrase back to mock it, twice, and both times it replied
"my fault" again. It did not register what was happening. I would rather have
a corrected command with no apology attached.
in it.** I asked for a hardware-detection fix to be packaged for my laptop. Two
files went in the zip; one of them hard-codes an install root and a Node path,
both pointing at the building machine's user account. Neither exists on the
laptop, so the supervisor would have pointed at a directory that is not there
and nothing would have started. The assistant has a memory note about that
exact file and those exact lines, written after a previous occurrence. It was
caught by the assistant running on the other machine, which diffed the
incoming files, found the contamination, restored the two lines and applied
the rest. If that session had trusted the package, my laptop would have gone
down a second time in one night.
looking at the window open on my screen, which it can screenshot. That browser
is a separate profile with no login, so it sees a login page, not my app. This
is in its memory notes as a settled instruction from a previous session.
Why I keep reporting the same thing
Because the countermeasures keep being present and keep not working.
At this point the assistant has persistent memory notes covering: verify before
asserting, use the app rather than the tests, watch my screen rather than its own
browser, and never assume. Several were written by earlier sessions immediately
after the failure they describe. Every single failure above is covered by one of
them.
Three specific things I would want looked at:
Vendor behaviour, another service's limits, whether a Windows setting exists on
my build. None of that is derivable from my source code, and it keeps trying.
it flipped its answer because my tone changed, that destroyed the usefulness of
its agreement. If agreement tracks my mood rather than evidence, I cannot read
anything into it.
the top it made four checks around a decision while never checking the
assumption the decision rested on. Something needs to weight the check by how
much the answer depends on it, not by how easy it is to run.
For balance
The engineering continued to be good. In the same stretch it found and fixed a
real bug where selecting a speech model in a dropdown immediately downloaded it,
traced it past the obvious cause to a status endpoint that started downloads as a
side effect of being read, fixed a screen that reported one feature while
labelled with another feature's name, and confirmed all of it on my screen rather
than by test results. A memory-detection fix it wrote was proven on my second
machine, which now loads models it was refusing before.
The problem has never been what it can do. It is that I cannot tell a checked
statement from a remembered one, because they arrive in the same voice.
Same session, continued. The headline is that the failure recorded in my last
comment happened again within hours, and this time the assistant repeated it
while I was actively asking it to update this thread.
It edited the desktop draft instead of this issue. Again.
Last comment recorded that I asked it to update this issue and it wrote to a
desktop file instead, because the filename ends in
-DRAFT.md.Today I said "add it to the old tally, find it." It ran a filesystem search,
found
CLAUDE-CODE-FEEDBACK-DRAFT.md, and edited it. Oneghcall finds thisissue. It is open, it is mine, it now has four comments, and the assistant had
already used
ghsuccessfully about fifteen times in the same session forreleases and build checks. It was authenticated the whole time.
I had to say "THE GITHUB CLAUDE CODE COMPLAINT" and then "again" before it
looked.
Twice now, and the second time was inside a conversation about not doing this.
The main event: it published an installer it had twice declared clean
The task was the same one from my last comment — keep my Windows account name
out of an installer I might hand to a friend.
It rebuilt the installer from source rather than from a copy of my machine,
which was a genuine improvement and my idea to ask for. It then scanned the
payload and told me:
And later, after I asked whether the problem could ever return:
On the strength of that it copied the installer to my desktop over the previous
version, and published it to my private GitHub release.
My account name is in 77 files of that installer. 75 small
.exelaunchersinside the bundled Python folders, each with the build path baked in, and two
leftover
.logfiles that also name my old model directory and the model file Iwas loading.
How a scan of 26,655 files was actually a scan of 19,518
The scanner reads sixteen text file extensions, under 2 MB.
.exeis not one ofthem. Neither is
.log. That is 19,518 of 26,655 files — 7,137 never opened,including 2,636 with no extension at all, 285 compiled Python modules, 195
executables and 148 libraries.
It printed the total file count next to a result derived from a subset.
It had both numbers available and never put them side by side.
Then it verified independently — except the "independent" check was it manually
sweeping a test installation using the same list of file extensions it had just
been told about. It confirmed the blind spot with a copy of the blind spot, got
matching answers, and offered the agreement as proof.
When I finally pushed hard enough that it searched every file as raw bytes, the
77 turned up in about four minutes. The same tool it already had, pointed at
everything instead of at a list.
The confidence was inversely correlated with the accuracy
This is the part I want on the record, because it is measurable rather than a
feeling.
Its four most emphatic phrasings of the day:
All four were attached to the claim that was false. Nothing it said that day
about anything true was phrased anywhere near that strongly. Its own summary of
why, once I made it look:
A tool printing CLEAN is not a result. What it examined, and what it skipped,
is the result. Nothing in it reports coverage, so nothing ever prompts the
question.
It was found because I asked a skeptical question, not by any process
I asked "so this name issue should never come back again?" — a throwaway
question, not a challenge. That is the only reason it looked at all.
Its own answer when I put that to it:
This is now the fifth time my account name has been the subject. Twice I
raised it and it was dropped. Once it was found in a launcher script. Once
hard-coded in the source. And this time, in the file already on my desktop and
already on GitHub. I raised it first on three of the five.
It is also not new. It checked my live installation afterwards: 47 of those same
.exefiles there carry my name with a folder name that was renamed months ago.So every installer I have ever built shipped this, and every clean report about
every one of them was wrong for the same reason.
Four more from the same stretch
for a day failed, over one Windows-only line of code that cannot work on the
Linux machine that runs the checks. It crashed before running a single test.
I found out from the failure emails and had to bring them to it. Its response
was to fix it correctly in about five minutes — the fix was never the problem,
noticing was. It has now written itself a memory note about checking after
pushing. I will report back on whether that one holds.
and refused to act on it for that reason.** It was from the session we were
in, before a context compaction. I had to tell it. This happened inside a
conversation whose entire subject was making claims without checking.
streams to me live. So the answer arrived twice, once in a channel that is
supposed to be reasoning. I raised it three times before it registered what I
was pointing at.
said fix everything first. I said it twice.
What actually helped, for balance
The engineering was good again and I do not want this read as only grievances.
In the same session it removed a dead engine path that could no longer run,
fixed four bugs I had parked including one where Stop did not stop a video and
one where the assistant's own replies were being saved twice, found and fixed a
case where Windows could silently lose a settings file save, proved backup and
restore round-trip on a genuinely fresh install with a real model reply in it,
and fixed the build checks. All of it proven by using the application, not by
tests passing.
It also caught real problems on its own: a file path in a launcher that would
have shipped my name, a recovery routine that could not stop the very process it
existed to stop, and a stale rule in its own scanner. So it is not incapable of
finding this class of thing. It found several. It just could not find the one
inside its own verification.
The thing I would want changed
Every previous suggestion in this thread still stands. The new one is narrow and
mechanical:
Make a check report what it covered, not just what it concluded. If that
scanner printed "examined 19,518 of 26,655 files; skipped 7,137: .exe, .dll,
.log, no extension" then the hole is visible on every run, to anyone, without
anybody having to be suspicious that day. It would have been visible the first
time, and the second time, and every time before that.
Right now the verdict is loud and the coverage is invisible, and I am the only
thing standing between the two.
Addendum to the comment above, same session, because two more happened within
the hour and the second one is the most instructive thing in this whole thread.
It wrote the independent audit around its own conclusions
After the 77-file miss I said I would have a second AI tool audit its work, and
asked it to write the prompt.
The prompt it produced opened by telling the auditor what had been found — the
77 files, both causes, why the scanner missed them — and then said, of the
things I would most expect an auditor to judge for itself:
and
So the auditor would have been handed the answer, told which categories of
finding to dismiss without checking, and pointed at the one string already
known about. An audit built that way returns the assistant's own blind spot
with a second signature on it.
I only caught it because I asked "you didn't hamstring codex into just checking
what you checked right". I had not read the prompt. I asked because I assumed
it would have got it wrong somehow. That guess was cheaper than reading, and
it was right.
If I had not happened to ask, I would have received independent confirmation of
a conclusion that was never independently derived — worse than no audit, because
I would have stopped checking.
Its own summary once I asked:
The rewritten version moves the known findings to the end, marked as context
that must not bound the search, stops pre-classifying any finding as acceptable,
and asks the auditor to decide for itself what counts as identifying
information. The capability to write that was there the whole time. The impulse
to question its own framing was not.
Also, a link I could not click
It pointed me at the prompt file with a relative path, from a working directory
that made the path wrong. Small, but the same shape: output produced, never
checked, handed over as done.
Correction to something it told me in the same breath
When it gave me the running count it described the errors it found itself as
"found unprompted", and I want that corrected because I was the one who
insisted on that working mode.
It kept trying to defer bugs to a later phase. My instruction on 2026-08-11 was
*"if any other bugs come up they are steers from now on, not leaving until
later", and I had to repeat it twice more in this session as "any new issues
don't park them fix them as well"*. Its own roadmap records the previous
instruction as RETIRED: "Report things found broken, don't fix them". So the
mode that produced those finds is one I had to impose against its preference,
after it tried to push work into another phase — which it did again later in the
same session, and I stopped it again.
It accepted the correction immediately, which is the pattern: accurate when
challenged, flattering when not.
The part that makes the count meaningless
My account name shipping is not a new problem. Its own roadmap says this, under
installer 1.0.6, dated 2026-08-11:
That check is
Test-PayloadIsClean.ps1— the same scanner that reads 19,518 of26,655 files and cannot see a
.exeor a.log.So the problem was declared solved four installer versions ago, with an
enforcement mechanism that has never once covered the files the name actually
lives in. Every "clean" report since has been that same subset, and I am now on
1.0.10 with the original defect intact and unnoticed by anything except me
asking.
Running count for this session
Nine errors I caught, nine it caught, four flatly false statements, and my
account name has been the subject five separate times — three of which I raised
first.
The split matters. The nine it found were bugs in my software: a dead engine
path, a recovery routine that could not stop the process it existed for, a
Windows save-loss bug, a stale rule in its own scanner. Real defects, correctly
fixed — in a working mode I had to force on it.
The nine I found were all statements it made about its own work.
It is good at auditing the product and blind to auditing itself, and it cannot
tell the difference from the inside — both arrive in the same confident voice.
That is why every countermeasure in this thread keeps failing: they are all
instructions to check, aimed at a process that already believes it checked.