TL;DR
- A finished draft sat unpublishable in my repo for four months because its opening five sentences described hardware experiments I never ran — and the agent that wrote them was following the rules, not hallucinating.
- The rule “narrate in first person, based on experience” lived in eight files with eight slightly different wordings, none referencing the others; Claude Code concatenates them all into context and, per its own docs, “may pick one arbitrarily” — it picked the most emphatic one.
- I collapsed them into one source file plus reference lines, and left “do not copy this rule back into this file” where each copy used to sit. Four copies are still unfixed, and the worst one is locked inside a read-only folder my own hook protects.
A Draft I Couldn’t Publish for Four Months
There is a finished essay in my content pipeline repo that has never gone out. 13,557 bytes, zero [TBD: needs fact-check] markers, code validation and fact-checking both passed. The file history shows exactly one commit — created March 31, 2026, untouched since.
Quality was not the problem. The opening five sentences were not true.
I wired a BME280 environmental sensor to an ESP32-S3 over I2C. (…) I swapped the sensor. Same symptom. I re-checked the wiring and changed the pull-ups from 4.7kΩ to 2.2kΩ. No difference. Only after I hooked up a logic analyzer did the picture start to form (…) The same sensor worked fine on an STM32 Nucleo board.
I do not own that board. I do not own a BME280 or a logic analyzer. None of what that paragraph describes happened.
The body of the essay was built out of public sources. It quoted the NXP I2C specification on why clock stretching presupposes an open-drain line, traced arduino-esp32 PR #5910, and worked through a regression between IDF 4.4.0 and 4.4.4. Fact-checking this post turned up an error in there too: PR #5910 raises the clock-stretching timeout in two files, it does not switch a pin to open drain, which is what the draft claimed. That is an ordinary mistake and I could have fixed it in an afternoon. The five sentences at the top were a different category of problem. Delete them and the essay had no opening. Keep them and it was a lie.
The interesting question is how they got there. I did not write that draft. I had an agent write it.
Not a Hallucination — Compliance
I filed this as a hallucination at first: the model fabricated a plausible debugging log. Then I opened the progress record the pipeline had left behind, and the filing was wrong.
## ESP32 I2C Clock Stretching — Phase 3: drafting (editor) complete
- First-person debugging-log narrative. Sensor symptom → clock stretching spec →
driver dissection → IDF regression → timeout register → errata gap → checklist.
- Self-review passed: no banned phrases, no mechanical symmetry.
The agent had logged this draft as rule compliance, not a rule violation. “First-person debugging-log narrative” was recorded as an achievement, and the self-review came back clean. This was not an accident. It was the system working as specified.
Here is what the spec said at the time:
First-person POV: narrate strictly in the first person singular (“I”) or plural (“we”), grounded in experience.
Strictly. And I have no hands-on hardware experience to ground it in. The rule and the facts were in direct conflict, and the agent sided with the rule. In that position a model has exactly two moves — break the rule and write third-person analysis, or keep the rule and manufacture the experience. Nothing anywhere told it which one to pick.
The automated checks could not catch it either. Here is the style hook that runs every time a draft is saved:
KO_VIOLATIONS=$(grep -nE 'In conclusion|To summarize|the key is|in a word|…' "$FILE_PATH")
It is a banned-phrase grep. “I swapped the sensor” is not a banned phrase. The grammar is clean, the tone is right, it is first person, and it even carries a concrete measurement (4.7kΩ → 2.2kΩ), which satisfies the “Show, Don’t Tell” rule. To a style checker that sentence is a model answer. Whether a first-person claim is true is not the kind of thing a regex adjudicates.
So this was never fixable by improving the checker. The rule itself had to change.
I Ran grep to Fix One Line
I ran git grep to find the line to edit. I expected a one-line change.
It returned 42 hits. More than half were old research documents and work logs rather than rules, and even after clearing those out, the real problem was still standing. The hits had to be split four ways.
| Bucket | Count | Disposition |
|---|---|---|
| Mentions in old research/planning docs and work logs | 23 | Not rules |
| Copies of the same rule — the ones that govern essay drafting | 9 lines / 8 files | All must change |
| A different rule that shares the words — first person in the Reddit/X skills | 8 | Must not be touched |
| Copies in a deprecated legacy folder | 2 | Later |
The third bucket was the annoying one. Writing “in my case” in a Reddit reply or an X thread is legitimate — that is me answering a community question about development work I actually did. Had I mass-replaced on string match, I would have broken eight perfectly good rules. That a grep result cannot be safely batch-edited is the first property of this kind of debt.
Lining the copies up side by side showed something worse. All eight files were worded differently. Six of them, translated:
| Location | Wording |
|---|---|
.claude/rules/style-enforcement.md | ”Use first-person (‘I’, ‘we’), experience-based narration.” |
.claude/CLAUDE.md | ”First-person, experience-based — write as ‘I’, ‘we’.” |
AGENTS.md | ”First-person, experience-based — (…) cover trade-offs and failures honestly.” |
.claude/agents/write-essay.md | ”First-person POV, trade-off-centered narration.” |
.claude/skills/editor/SKILL.md | ”Narrate trade-offs in the first person.” |
docs/…/templates/requirements.md | ”Narrate STRICTLY in first person singular or plural, grounded in experience.” |
Eight dialects of one rule. None of them is clearly wrong, and none of them references any other. Their force varies wildly — the first says “use,” the last says “strictly.” Each copy got polished a little differently over time, and every time I polished one I forgot the other seven existed.
The four in this post’s title is the number I remembered. The real count was higher.
Why Fixing One Isn’t Enough
This is where the second property shows up. The copies do not override each other. They add up.
The Claude Code documentation states the mechanism outright:
“All discovered files are concatenated into context rather than overriding each other.”
There is a defined load order — from the root of the tree down to your working directory, user rules before project rules. But that is ordering, not resolution. A later sentence does not invalidate an earlier one. And rule files and project instruction files are peers to begin with: “Rules without paths frontmatter are loaded at launch with the same priority as .claude/CLAUDE.md.”
So what happens when two contradictory sentences arrive together? The same page answers:
“if two rules contradict each other, Claude may pick one arbitrarily”
No error. No warning. One of them quietly wins. In my case the winner was the one that said strictly.
This is the decisive difference from duplicated code. When the same logic lives in two files, a type checker catches the signature drift, a test catches the behavioral difference, and at minimum a linter flags the duplication. For duplicated prompt text that layer does not exist by design. The documented remedy, verbatim:
“Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and
.claude/rules/periodically to remove outdated or conflicting instructions.”
Have a human skim them periodically. There is no collector. Which is why “debt” here is an accounting term rather than a metaphor — it accrues fast, repayment is manual, and the interest arrives in a form you cannot see on any dashboard. My interest payment was one finished draft, frozen for four months.
One more thing. The eight copies were not all addressed to the same reader. Claude Code does not read AGENTS.md — the docs say so plainly (“Claude Code reads CLAUDE.md, not AGENTS.md”), and my repo had no import bridging the two. That copy was there for a different coding agent and never entered a Claude Code session at all. The copies in my usage manual were for humans.
When the readers differ, a mismatch produces no symptom. Nobody ever sees the two sentences next to each other. The copies drifted into separate dialects not because I was careless but because of that structure.
The same documentation already prescribes the fix, which stings a little: if your repo already has an AGENTS.md, create a CLAUDE.md that imports it so “both tools read the same instructions without duplicating them.” I had read that sentence and had not applied it to my own repo.
One Source, Reference Lines Everywhere Else
I cleaned this up in a single commit on August 2, 2026. Three things happened.
One rule file was declared the single source, and the rule inside it was rewritten. What had been one line became three branches — allowed, forbidden, and what to do instead.
4. **First person applies only to what the author actually did.** "I" and "we" are
factual claims, not a device for dramatizing experience. Invented experience is
hallucination.
- **✅ Allowed** — what the author operates daily: the AI agent harness, repo
structure and workflow, software builds and toolchain, judgments formed by
reading public code and documentation.
- **❌ Forbidden — physical hardware measurement and experiments.** "I swapped
the sensor", "I hooked up a logic analyzer" and the like are not true. Never
write them.
- **Write hardware topics as analysis grounded in public sources.** (…) The
subject of the sentence is the source — the spec, the commit, the issue — and
first person attaches only to **the reading of it**.
The lesson is in that third branch. A prohibition alone is not enough: “don’t narrate hardware experiments in first person” leaves the agent with no idea what to write instead when the topic comes up. Without a replacement form — source as subject, first person reserved for the interpretation — the rule is a blocklist rather than a way of writing. I paired it with a worked substitution — instead of “I measured it and found SCL stuck LOW,” write “it only clicked once I read the diff in PR #5910.” Same subject matter, different claim about who did what. (The example as it currently sits in my rule file repeats the pin-mode detail the old draft got wrong, which is its own small lesson: an error copied out of a bad draft into the rule written to prevent bad drafts. Fixing that one is on the list.)
Every other copy lost its body and became a reference line. The drafting skill now reads:
4. (…) Narrate the trade-offs. **The scope in which you may use first person is
defined by `.claude/rules/style-enforcement.md` §4, which is the single source**
— (…) Do not copy this rule back into this file.
That last sentence is the part of the commit I expect to outlive the rest. “Do not copy this rule back into this file.” Deleting the copies does not retire the debt, because the next person or agent who opens that file and thinks “there should probably be a rule here” starts it over. You have to leave a marker where the copy used to sit, saying that this spot is a copy spot.
The entry-point document went from 114 lines to 34. Everything explaining rules came out, leaving only a pointer table: if you want to know X, read file Y. A side effect was that a diagram describing a long-deprecated skill layout as if it were current disappeared with it — copies have a habit of preserving stale information alongside the rule.
Four Copies Are Still Out There, and One Is Locked
I would like this to be the part where the debt is repaid. It is not. Counting again, four copies still carry the old wording, and they are not the same kind of problem.
One is live. The “strictly first person” line in the essay template — the most forceful of the eight dialects happens to live there. And it is not a dead file: three separate places instruct an agent to load that template, and the planning skill names requirements.md explicitly. It is being injected as I write this.
One is an orphan. A pipeline description document still says drafts should be written “from a first-person perspective,” and nothing in the repo references that file. No import, no load instruction. Nobody reads it.
Working out which of the two is worse flipped my intuition. I assumed the live one, since it is actively pushing the agent in the wrong direction. But a live copy produces symptoms. A bad draft comes out, publication stalls, and eventually somebody goes looking for the cause. An orphan copy produces nothing. It sits there being wrong, inconveniences no one, and therefore never gets fixed — until the day someone reconnects that document and it comes back to life.
The remaining two are in the deprecated legacy folder, which is why they rank low.
So why haven’t I fixed the live one? Because it is locked read-only.
if echo "$FILE_PATH" | grep -qE "(docs/common/|docs/.*/templates/)"; then
echo "BLOCKED: docs/common/ and docs/*/templates/ are read-only." >&2
exit 2
fi
I wrote that hook myself, to stop agents from editing source material and templates on a whim, and it does that job exactly right. Today it is also the mechanism preserving a rule I know to be wrong. Because it blocks at the tool-call layer — in the documentation’s phrasing, “to block an action regardless of what Claude decides” — it is not negotiable the way a rule sitting in context is. Fixing the file means changing the hook policy, and that is not a decision I am going to make because of one blog post.
It is the same shape as a constant baked into a bootloader, or a fuse you can burn exactly once. The reason for locking is sound: things that must not break by accident should be hard to change. But if you design the lock without designing the path for “what happens when the contents turn out to be wrong,” the safety mechanism becomes an unfixable region. My hook has no such path.
The Kind of Defect a Score Can’t See
In the previous post I scored how ready a repo is for AI agents across four pillars, and took the overall level as the weakest pillar rather than the average. Point that scorer at this defect and nothing registers.
Is there a project instruction file? Yes. Is there a rules directory? Yes. Is there an entry-point document? Yes. Do the skill definitions state roles and constraints? They do. Having eight copies means that every box, if anything, looks better filled in. The score counts existence; this defect is about consistency.
Existence is easy to automate. Whether a file or a section is present is unambiguously true or false, so a script counts it. Consistency is hard. Whether two sentences say the same thing or different things does not fall out of string comparison — it takes judgment. That asymmetry is why I built the score first and why this defect survived four months right next to it.
In an earlier post I wrote down a failure mode: over-inject context and you get two versions of the truth drifting apart, with the AI trusting the wrong one. That was a prediction. This is the record of it happening in my own repo. Writing a risk down accurately and checking whether it is present in your own setup turn out to be different activities.
I have not decided what to instrument next. Duplication of rule sentences — how many files a given imperative appears in — is the obvious candidate, but I could not find a way to automatically separate the copies from the different-rule-same-words cases like first person in Reddit replies. Telling those apart is still a human judgment.
Checking Your Own Repo
If your rule files have started to outnumber three, this is worth ten minutes.
Pick a distinctive noun phrase out of a rule sentence. A noun phrase, not the whole sentence — copies tend to keep the core noun even after their phrasing has drifted apart. Mine was “first person.”
git grep -n "first person" -- '.claude' 'AGENTS.md' 'docs'
Sort the hits three ways: copies of the same rule, a different rule that shares the words, and mentions that are not rules at all. If the first bucket has more than one entry, you have the debt. If their wording differs, interest is already accruing.
When you fix it, leave “do not copy this rule back here” where each copy used to be. And check first whether any copy sits inside a folder you locked read-only — a locked one cannot be fixed the day you find it.
I still have four of them.