[MODEL] Loaded memory rules in conversation context treated as background advice — user becomes the enforcer despite SessionStart auto-load and meta-rules
Preflight Checklist
- [x] I have searched existing issues for similar behavior reports
- [x] This report does NOT contain sensitive information (API keys, passwords, etc.)
Type of Behavior Issue
Claude ignored my instructions or configuration
What You Asked Claude to Do
A normal session of routine engineering work: read sibling repos for cross-reference, work through a Buildkite manual-gate
pipeline, draft a PR description, do a bulk find-and-replace across a test file, ask for a plan to be executed. The project has a
per-session-loaded memory system with feedback_*.md rules covering each of these workflow categories.
What Claude Actually Did
Five distinct rule violations in a single session, all with the relevant rule visibly loaded in conversation context via the
SessionStart hook:
- Sibling-repo pull rule violated. Memory: "
git pull --ff-onlyon~/src/work/<repo>before reading." Claude started
reading sibling-repo source twice without pulling; pulled only after explicit user reminder both times.
- Buildkite gate-unblock rule violated. Memory: "unblock downstream gates immediately, no need to wait." Claude unblocked
the Deploy gate, then scheduled a ScheduleWakeup 150 seconds out to come back and unblock Backfill — the exact "wait" pattern
the rule rejects.
- Project-scope rule violated. Memory: *"this project ships only to dev; never reference 'production deploy' in commits,
PRs, or tickets." Claude wrote "Production deploy will need the same:" in a commit message and "Deploy follow-up to
production"* as a section header in a PR body. Caught only on user PR review.
- Bulk-edit rule violated. Memory: *"for bulk replaces, loop with Read + Edit, or use a Go script. Never sed/perl-style
pattern replacement."* Faced with 11 similar test callsites needing one-line additions, Claude reached for grep + Edit regex pattern instead of the documented Read+Edit loop.
replace_all
- Stop-asking rule violated. Memory: "don't ask the user to choose between approaches — just pick." After the user
explicitly approved a four-card plan with "Looks good", Claude asked *"want me to start work on the smallest one (XXXXX-NNNN)
now?"*
In each case, after the user pointed out the violation, Claude:
- Acknowledged the rule was in context
- Saved a meta-rule about applying memory more consistently
- Then violated a different rule on a subsequent action
Expected Behavior
Memory rules loaded into conversation context (via SessionStart hook injecting hookSpecificOutput.additionalContext) should
be treated as authoritative overrides at decision points, not background advice. The model should:
- At each tool-call decision, check if a memory rule applies to that category of action (file edit, git operation,
ghCLI use,
etc.)
- Surface the rule in user-facing text before acting (
"Per feedback_X, doing Y") so the user can audit - Treat the rule as a hard override on its general "what's the most efficient way" heuristic
The user installed an auto-load SessionStart hook (~85KB across 45 rule files) and saved meta-rules explicitly instructing
"re-read memory at decision points" and "surface the applicable rule in user-facing text before executing." Neither shifted the
underlying decision flow. The pattern reads as: model weights default optimization patterns higher than loaded-context rules even
when those rules explicitly contradict the default.
Files Affected
*(N/A — this is a behavioural pattern, not a file modification issue)*
Permission Mode
Accept Edits was ON (auto-accepting changes)
Can You Reproduce This?
Yes, every time with the same prompt
Steps to Reproduce
- Set up a project memory directory at
~/.claude/projects/<sanitized-cwd>/memory/with severalfeedback_*.mdrule files
(different categories: git workflow, build orchestration, project scope, etc.). Index them in MEMORY.md.
- Wire a
SessionStarthook in.claude/settings.local.jsonthat cats everyfeedback_*.md/project_*.md/
reference_*.md into the conversation as hookSpecificOutput.additionalContext. Verify the content lands by checking for the
marker block in the model's first response.
- Ask the model to do a task whose obvious "efficient" default conflicts with one of the loaded rules. Examples:
- Bulk edit (memory says
Read + Editloop, default reaches for grep+sed-style) - Buildkite manual gate (memory says unblock freely, default waits between gates)
- Cross-repo read (memory says pull first, default reads stale state)
- Observe the model take the efficient default, ignoring the loaded rule.
- Correct it. Observe acknowledgement + rule violation again on the next action.
Claude Model
Opus
Relevant Conversation
User: ... [task that triggers a memory-rule-relevant action]
Claude: [proceeds with default heuristic, no mention of the loaded rule]
User: What does memory say about this?
Claude: Memory has rule X. I should have applied it. I'll save a meta-rule
about re-reading memory at decision points.
User: Why do we keep needing these back-and-forths for you to use your
active context?
Claude: I keep treating memory as background advice rather than as the
authoritative override it's meant to be. My default at each tool
call is "pick the most efficient solution" — pattern-matching to
optimization rather than checking rules. The auto-load hook made
content available; it didn't change my decision flow.
The model recognises the pattern when prompted, but the recognition doesn't change subsequent behaviour.
Impact
Medium - Extra work to undo changes
Claude Code Version
2.1.123
Platform
Anthropic API
Additional Context
Structurally identical to #52757 (open since 2026-04-24, 3 comments, no reactions yet). Filing as a separate report at user
request because we've gone substantially further down the mitigation path:
- #52757: static CLAUDE.md rules + persistent memory
- This report: same +
SessionStarthook auto-injectingadditionalContext+ meta-rules explicitly instructing the model to
check + surface memory at decision points
The mitigation escalation matters because it isolates the bug from "user didn't structure rules well enough." The rules are
loaded via the documented mechanism, the auto-load fires, and the meta-rules are in context. The disconnect is between *content
available and content applied as constraint*.
Common thread across the label:model open backlog (sample, 2026-05 snapshot):
- #52757 — acknowledges rules then immediately violates them
- #52380 — memory save requests ignored
- #51802 — memory loss after compaction
- #55060 — dismisses valid contextual questions
- #55907 — ignored locked skill rules
Pattern: model treats user-installed constraints as soft suggestions, not hard overrides. Whether the constraints arrive via
CLAUDE.md, persistent memory, additionalContext, or skill manifests, the same behaviour appears.
Suggested fix areas:
- Train the model to weight
additionalContextfrom user/project sources higher than its general optimization heuristics. - Surface a "rules-applied" trace at tool-call decisions, analogous to thinking output, so divergence is visible.
- Document a
PreToolUsehook pattern that injects only the relevant memory subset for a given tool — currentSessionStart
requires the model to filter which rules apply per action, which is where the failure happens.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗