[BUG] Claude Code repeatedly violated explicit project rules (AGENTS.md, .claude/rules/) despite them being loaded into context
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Summary
Claude Code repeatedly violated explicit project guardrails defined in AGENTS.md and .claude/rules/ despite these files being loaded into conversation context and even surfaced via <system-reminder> tags during edits.
What happened
User asked Claude to fix 4 bugs in a Django async-first monolith. The bugs were correctly identified and diagnosed. When it came time to write fixes, Claude produced code that violated the project's own mandatory rules — rules that Claude had already read and acknowledged earlier in the same conversation.
Specific violations
- Duplicated settings access instead of using the service layer
The project rule (AGENTS.md §4) states: "All business logic in services. Never access DB directly from views or tasks." Claude copied getattr(settings, "NEO4J_URI", ...) and auth credentials directly into task functions instead of using the existing GraphRAGIngestionService which already encapsulates Neo4j connection configuration. This was done to work around a __new__ hack that skipped __init__ — Claude perpetuated the anti-pattern instead of fixing it.
- Unnecessary sync/async boundary crossing
The project rule (.claude/rules/async-first.md) states: "Never use sync_to_async for database operations." Claude wrapped a Celery .delay() call with sync_to_async when the underlying async function (_extract_and_cache_body_parts) was directly callable from the already-async context. When the user corrected this, Claude then used create_async_task with sync_to_async — still wrapping unnecessarily. It took three corrections before Claude considered calling the async function directly.
- Persisted with bad approach through multiple corrections
Each user correction fixed one layer of the problem, but Claude kept the surrounding bad pattern intact. User said "don't use sync_to_async" → Claude added create_async_task around it. User said "why are we awaiting" → Claude removed await but kept sync_to_async. The fixes were incremental patches on a fundamentally wrong approach rather than stepping back to reconsider.
- Rules were visibly loaded but not applied
The <system-reminder> tags containing .claude/rules/async-first.md, .claude/rules/service-layer.md, and .claude/rules/celery-tasks.md were injected into the conversation during the edits. Claude acknowledged these rules existed but did not apply them to the code being written.
Expected behavior
Claude should treat project rules as hard constraints during code generation, not just context for conversation
When a user correction reveals a pattern violation, Claude should re-read the relevant rules and reconsider the entire approach — not just patch the specific line the user flagged
Rules about architecture (service layer, async-first) should override Claude's default instinct to produce a "quick fix"
Environment
Model: Claude Opus 4.6 (1M context)
Tool: Claude Code CLI (VSCode extension)
Project rules loaded via: CLAUDE.md → AGENTS.md, .claude/rules/*.md
Rules were present in context window throughout the conversation
Reproduction
Ask Claude to fix a bug in an async codebase with strict architectural rules. The diagnosis phase works well. The implementation phase ignores the rules it just read, defaulting to expedient patterns (direct settings access, sync wrappers) rather than following the project's established architecture.
What Should Happen?
When project rules are loaded into context, they should be treated as hard constraints during code generation — not just acknowledged during conversation. Before writing any fix, Claude should validate the approach against loaded rules the same way it validates syntax. When a user correction reveals a rule violation, Claude should re-read all relevant rules and reconsider the entire approach, not just patch the flagged line.
Error Messages/Logs
Steps to Reproduce
Define strict architectural rules in AGENTS.md and .claude/rules/ (async-first, service layer, no direct settings access)
Have Claude diagnose bugs correctly across multiple files (it does this well)
Ask Claude to implement the fixes
Observe that Claude generates code violating the rules it just read — hardcoding config, crossing async/sync boundaries, duplicating service internals
Correct one violation — observe Claude patches that line but leaves surrounding violations intact
Repeat corrections — observe Claude incrementally fixes each flagged line without ever stepping back to re-evaluate against the loaded rules
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
Opus 4.5
Claude Code Version
2.1.83 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
VS Code integrated terminal
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗