Re-inject user-marked critical rules before each turn — gating rules decay between turns while format rules hold
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Seven existing reports describe this same symptom and were all closed without a substantive response: #15443, #19635, #21119, #32163, #32775, #34197, #46724. They frame it as "Claude ignores CLAUDE.md" — one undifferentiated problem. It isn't one problem, and that framing may be part of why it keeps getting closed.
#46724 made the distinction that matters, and it holds up in my own sessions:
- Rules that HOLD: output format, technical constraints, safety limits — anything with an externally checkable criterion.
- Rules that FAIL: gating rules ("stop and ask before producing X"), post-action rules, and rules that point to another document.
The failure mode is specific: the instruction is loaded, the model can quote it accurately when asked, and it reverts to default behaviour while working. Quoting the rule and following the rule are decoupled.
Four concrete cases
All from my own sessions. In every one, the rule was loaded and visible in context at the moment it was broken. Ordered by how hard they are to explain away.
1. The rule was inside the document being executed. A user-authored closing protocol contains an explicit anti-duplication rule: "a factual value lives in ONE file; other files reference it, they do not copy it." While executing that same protocol, in the same session, the model wrote one count into three separate files. The copies had already diverged before the session ended. The rule was not in some other document — it was in the file being followed at that moment.
2. A numbered gating step, skipped. The same protocol has three steps, where step 2 is "present the list and wait for explicit approval before writing anything." The model executed step 3 and wrote to disk without ever presenting step 2. An explicit, numbered, unambiguous stop-and-wait, simply passed over.
3. Account-level preference, dropped at turn 2. A three-tier epistemic labeling convention (verified fact / inference / synthesis) lives in account preferences — the always-loaded slot, not a file that has to be requested. The model applied it in turn 1, dropped it in turn 2, and did not resume until explicitly asked roughly 35 turns later.
4. Protocol loaded on request, violated in the next message. A behavioural protocol was loaded at the start of a session at the user's explicit request. It states verbatim: "Default: compress, prose, minimal formatting. Not more structure and not more bullets." The very next substantive response used headers, bold emphasis, a table and separated blocks. Not 30 turns later — the first response after loading it.
Note the asymmetry. In those same sessions, format-level and technical constraints with a checkable criterion were followed without incident. What failed was always a rule that gates an action or governs a process.
Proposed Solution
Let users mark a small number of rules as critical, and re-inject those before each user turn instead of once at session start.
Concretely: a marker in CLAUDE.md — for example a <critical> block, or a frontmatter list of rule IDs — whose contents are re-inserted immediately before each user message rather than only at session start. Scoped to a small budget (a handful of lines, not the whole file) so the context cost stays bounded and predictable.
This is a placement change rather than a new capability. The rules are already being loaded; they are just being loaded once, at exactly the point where the published evidence says the decay begins.
Li et al., "Measuring and Controlling Instruction (In)Stability in Language Model Dialogs" (COLM 2024, arXiv:2402.10962) identify the mechanism: attention to system-prompt tokens decays as the dialog grows, and the drop is sharp BETWEEN turns, not within a turn. That matches case 3 above exactly — the rule survives the turn it was loaded in and degrades from the next user message onward.
They test mitigations. System Prompt Repetition — re-injecting the instruction before each user turn — sustains stability through 16 turns. It costs context window, and it works. This request is that mitigation, exposed as a user-controlled flag rather than left to the user to do by hand.
Alternative Solutions
A pre-response hook. This would be the stronger fix, but it does not exist today. The only hooks that can see the assistant's final text are Stop and SubagentStop, and both fire after the text has already been emitted. They can force a correction round, but the user has already read the bad answer. #32163 requested something in this direction and was closed as not planned.
Repeating the rules manually in every message. Available today, and it is exactly what the paper's SPR mitigation does — but done by hand it is unusable in practice: it makes every message longer, and it requires the user to remember to do the thing the tool was supposed to remember for them.
Writing the rules more times, in more files. Tried, does not work. Case 4 above had the rule loaded on explicit request in that same session; case 1 had it inside the very document being executed. More copies do not help, which is consistent with the decay being an attention-weight effect rather than an absence-of-information problem.
Stop-hook validators. There are community implementations that compare the model's final claims against a log of what it actually did (e.g. AlethiaQuizForge/claude-guard-hooks). They are post-hoc correctors, not preventers, and the most complete one I found is archived and publishes no metrics.
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
Scenario, from a real session:
- The user keeps a three-tier epistemic labeling convention in account preferences: every claim gets tagged as verified fact, inference, or synthesis. This is the always-loaded slot — no file to request, no command to run.
- Turn 1: the model applies the labels correctly.
- Turn 2: the labels are gone.
- They stay gone for roughly 35 turns, across work where the fact/inference distinction is the entire point of the convention.
- The user notices and asks for them back. The model resumes immediately and can quote the rule verbatim — it was in context the whole time.
With this feature, the user marks that one convention as critical. It gets re-injected before each turn. The cost is a few dozen tokens per turn; the benefit is that the single rule the user cares most about survives past turn 1.
The general shape: the rules a user marks as critical are precisely the ones whose violation is expensive and hard to notice in the moment. Those are exactly the ones currently most likely to decay, because they are process rules with no externally checkable criterion — nothing in the output contradicts the model when it stops following them.
Additional Context
Prior reports of the same underlying issue, all closed without a substantive response: #15443, #19635, #21119, #32163, #32775, #34197, #46724. Four closed as "not planned", two as duplicates.
Published work on the mechanism: Li, Liu, Bashkansky, Bau, Viégas, Pfister, Wattenberg — "Measuring and Controlling Instruction (In)Stability in Language Model Dialogs", COLM 2024, arXiv:2402.10962. Relevant findings:
- attention to system-prompt tokens decays over the course of a dialog;
- the decay is a between-turn effect and is stable within a turn;
- System Prompt Repetition sustains instruction stability through 16 turns, at the cost of context window;
- all mitigations tested show an inverse relationship between raw task performance and instruction stability — which is an argument for making this user-controlled and opt-in rather than always-on.
Why the narrow scope matters: this request is deliberately small — a few user-marked lines, not the whole CLAUDE.md. Re-injecting an entire memory file every turn would be prohibitive in both cost and context. Re-injecting five lines is not, and the evidence above suggests those five lines are where most of the value is.
Showing cached comments. Read the full discussion on GitHub ↗
4 Comments
The hold-vs-fail split is the useful diagnosis: format rules have an external check; gating rules ("stop and ask", "wait for approval", "cite the other doc") don't — so they compete as preferences and lose mid-session. Quoting the rule proves load, not currency.
A numbered stop-and-wait step that gets skipped is a missing decision status: judgment open | approved | rejected+why — not another CLAUDE.md line. Same for the anti-duplication rule inside the protocol being executed: nothing marked "value X already lives in file A" as current, so copies won.
Re-injection helps if what gets re-injected is status the next turn must cite, not a longer reminder. Curious which gating failure costs you more day to day — skipped approval steps, or rules that point at another document.
Data point that supports the proposal but complicates the taxonomy.
The hold-vs-fail split here puts output format on the safe side:
I have a counterexample that is about as pure a format rule as can be written, and it failed. Not a gating rule, not a pointer to another document, not a process rule. A single mechanical character prohibition in global
~/.claude/CLAUDE.md:Trivially checkable, no judgment required, no competing preference to lose against. It was obeyed perfectly for the first half of a session and then broken 159 times in the second half.
The session
2095 events over 4 days,
claude-opus-5[1m], no compaction at any point, resumed on four separate days.Searching the transcript for the CLAUDE.md body:
Injected once, at event 13. Not re-injected on any of the four resumes. No compaction, so no implicit refresh either.
Dose-response against context depth
Violations per 1000 characters of assistant prose, bucketed by quintile of the session:
| quintile | assistant msgs | em/en dashes | chars | dashes / 1k chars |
|---|---|---|---|---|
| Q1 | 28 | 0 | 24,540 | 0.00 |
| Q2 | 29 | 0 | 14,185 | 0.00 |
| Q3 | 28 | 25 | 13,906 | 1.80 |
| Q4 | 29 | 64 | 23,130 | 2.77 |
| Q5 | 29 | 74 | 28,783 | 2.57 |
Severity within a single message scales with depth too: 3 dashes in the first offending message, 6 near the middle, 9 and then 14 in single messages near the end.
Anyone can run this against their own transcripts:
Why this matters for the proposal
Two things follow.
1. The scope is wider than the taxonomy suggests. If format rules also decay, then "externally checkable" is not what protects a rule - depth is. The hold/fail split may be measuring how long each session happened to run rather than a property of the rules. That argues for re-injection being the general fix rather than a special case for gating rules, and against scoping the
<critical>budget so tightly that mechanical style rules are assumed not to need it.2. It is continuous, not binary. The monotonic curve says this is an attention-weight effect, exactly as Li et al. describe, not a discrete "the rule fell out of context" event. The rule is present and quotable at event 2092; it is simply outweighed. Worth noting the prior is doing real work here - em-dashes are strongly favoured in this register of prose - so the failure is best read as the prior overwhelming a distant instruction, which is what you would predict if attention to those tokens has decayed.
One more supporting detail for the "placement, not capability" framing: compaction appears to mask this. This session never compacted and so never got the implicit refresh. That may be why the symptom is under-reported - sessions that compact regularly keep getting the rule re-inserted for free.
Cost, measured
I priced the workaround on this same session, since the context-budget objection comes up in the thread. A
UserPromptSubmithook that readstranscript_pathfrom stdin and echoes the rule past a size threshold:| strategy | extra tokens | % of session token spend |
|---|---|---|
| inject on every prompt (52x) | +683,325 | 0.47% |
| inject only past the decay threshold | +270,000 | 0.18% |
Baseline for comparison was 146,391,016 cumulative cache-read tokens. The re-injected text rides as cache-read, the cheapest tier. A depth-gated trigger also skips the 19 prompts that occurred while compliance was still perfect, which is where the unconditional version wastes its budget.
0.18% to fix from outside the tool suggests the in-tool version is affordable at a far smaller budget than the
<critical>block proposal assumes.Environment: Claude Code 2.1.278, macOS 27.0, model
opus[1m].@bragboy — this is the right kind of counterexample. If a pure mechanical format rule still decays continuously with depth (0 → ~1.8 → ~2.7 dashes/1k chars across quintiles, never compacted), then “externally checkable” is not what protects a rule — attention/dose is.
That pushes re-injection toward a general depth-gated mechanism, not a gating-rules-only special case. Keeping the hold/fail split as a first cut is still useful; format HOLDs look more like “usually survive short sessions” than “immune.”
The measured ~0.18% token cost for threshold-gated inject is also a strong answer to the budget objection — cheaper than treating
<critical>as a scarce VIP lane for gating rules alone.thank you very much i will do it and see the results!
El mar, 22 sept 2026 a las 9:12, stonianua @.***>)
escribió: