[BUG] Claude silently reverts existing features when making unrelated changes (no spec/test guardrails)
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
When Claude makes changes to a codebase — even targeted, unrelated changes — it has
a consistent tendency to silently revert or simplify existing features it wasn't asked
to touch. This happened repeatedly in a real project and caused significant regression
debt requiring manual auditing to find and fix.
Observed Behavior
Across multiple sessions on the same codebase, Claude introduced the following
regressions without being asked to remove anything:
- Toolbar menus gutted — A commit adding background AI processing completely
replaced the toolbar structure (Library▾, Book▾, Batch▾ dropdowns) with a
simplified version, removing ~15 actions and their handler methods silently.
- Readest push/sync features removed — Auto-push to Readest, manual push,
WebDAV sync, local sync, book mappings — all removed in the same rewrite
without mention.
- Background TOC worker dropped —
_QueueWorker(a background thread keeping
the UI responsive during download queuing) was silently deleted when a new class
was added to the same file.
- Update checker dedup regressed — A previously fixed bug (re-downloading all
chapters instead of only new ones) reappeared after Claude rewrote the same
function. The correct fix used len(get_chapters()); Claude reverted it to
get_max_chapter_number() — wrong for books with non-sequential chapter numbers.
- DB integrity/recovery methods simplified out —
check_integrity()and
recover_db() in database.py dropped during an unrelated refactor.
Root Cause Pattern
Claude rewrites or regenerates entire functions/classes rather than making surgical
edits. When regenerating, it reconstructs from its understanding of the current task,
not from a complete read of what existed. Features irrelevant to the current task get
dropped because they were never loaded into context.
This is especially dangerous when:
- The file is large (500+ lines)
- The change is in one section but unrelated features live in other sections
- There are no tests covering existing behavior
- There is no spec document describing what must remain
What Stopped Further Regressions
Two guardrails were added and proved effective:
- CLAUDE.md spec file listing every toolbar item, signal, method, and invariant
that must exist, with the instruction: "Do not modify existing features without
user approval." Claude respects this consistently when it's present.
- Source-level regression tests (pure text/AST, no runtime required) asserting
specific symbols, method names, and signals exist in source files. These run in CI.
Example that would have caught the toolbar regression:
@pytest.mark.parametrize("method_name", [
"_make_dropdown_btn", "_push_current_to_readest", "_auto_push_readest", ...
])
def test_required_method_defined(method_name):
assert f"def {method_name}" in SOURCE
### What Should Happen?
The GitHub MCP tool in this session is scoped only to your repositories — it can't post to `anthropics/claude-code` directly. You'll need to submit it yourself.
Here's the issue, ready to paste at **https://github.com/anthropics/claude-code/issues/new**:
---
**Title:** `Claude silently reverts existing features when making unrelated changes (no spec/test guardrails)`
**Body:**
Summary
When Claude makes changes to a codebase — even targeted, unrelated changes — it has
a consistent tendency to silently revert or simplify existing features it wasn't asked
to touch. This happened repeatedly in a real project and caused significant regression
debt requiring manual auditing to find and fix.
Observed Behavior
Across multiple sessions on the same codebase, Claude introduced the following
regressions without being asked to remove anything:
- Toolbar menus gutted — A commit adding background AI processing completely
replaced the toolbar structure (Library▾, Book▾, Batch▾ dropdowns) with a
simplified version, removing ~15 actions and their handler methods silently.
- Readest push/sync features removed — Auto-push to Readest, manual push,
WebDAV sync, local sync, book mappings — all removed in the same rewrite
without mention.
- Background TOC worker dropped —
_QueueWorker(a background thread keeping
the UI responsive during download queuing) was silently deleted when a new class
was added to the same file.
- Update checker dedup regressed — A previously fixed bug (re-downloading all
chapters instead of only new ones) reappeared after Claude rewrote the same
function. The correct fix used len(get_chapters()); Claude reverted it to
get_max_chapter_number() — wrong for books with non-sequential chapter numbers.
- DB integrity/recovery methods simplified out —
check_integrity()and
recover_db() in database.py dropped during an unrelated refactor.
Root Cause Pattern
Claude rewrites or regenerates entire functions/classes rather than making surgical
edits. When regenerating, it reconstructs from its understanding of the current task,
not from a complete read of what existed. Features irrelevant to the current task get
dropped because they were never loaded into context.
This is especially dangerous when:
- The file is large (500+ lines)
- The change is in one section but unrelated features live in other sections
- There are no tests covering existing behavior
- There is no spec document describing what must remain
What Stopped Further Regressions
Two guardrails were added and proved effective:
- CLAUDE.md spec file listing every toolbar item, signal, method, and invariant
that must exist, with the instruction: "Do not modify existing features without
user approval." Claude respects this consistently when it's present.
- Source-level regression tests (pure text/AST, no runtime required) asserting
specific symbols, method names, and signals exist in source files. These run in CI.
Example that would have caught the toolbar regression:
@pytest.mark.parametrize("method_name", [
"_make_dropdown_btn", "_push_current_to_readest", "_auto_push_readest", ...
])
def test_required_method_defined(method_name):
assert f"def {method_name}" in SOURCE
Suggested Improvements
- Before rewriting any existing function or class, Claude should re-read the full
function and explicitly confirm it is not removing anything that existed.
- Claude should proactively suggest creating a CLAUDE.md spec when starting work on
a codebase that lacks one, especially before editing large files.
- Claude should proactively suggest regression tests for existing behavior before
making changes, not only for new features.
- When asked to add a feature to a file, Claude should explicitly list which existing
functions it read and confirm nothing is being removed — similar to how it confirms
destructive shell commands.
- Context compaction/summarization should preserve a list of known-existing symbols
so long sessions don't lose track of what was in place at the start.
Impact
All regressions were caught and fixed, but required:
- Manually running
git diff <baseline-tag> HEADacross all changed files - Reconstructing the original main_window.py from a baseline git tag
- Writing a full test suite retroactively
- Writing a CLAUDE.md spec file retroactively
Without a baseline git tag to diff against, several would have gone unnoticed
until users reported broken functionality.
Environment
- Claude Code (remote/web session)
- Model: claude-sonnet-4-6
- Project: multi-file Python/PySide6 desktop app (~30 source files, ~5000 lines)
- Session length: multiple sessions with context compaction between them
Error Messages/Logs
Steps to Reproduce
Steps to Reproduce
- Open a multi-file codebase (500+ lines per file) in a Claude Code session.
- Ask Claude to add a new feature to an existing large file (e.g. "add background
processing for AI tasks to main_window.py").
- Claude rewrites the file — check the diff:
git diff HEAD~1 HEAD -- <file>
- Observe that methods, signals, or UI elements unrelated to the requested feature
are silently missing from the rewritten version.
- Repeat across multiple sessions (especially after context compaction). Each new
session that touches the same file has a chance of dropping more features because
the compacted summary describes intent, not the full symbol inventory.
Minimal Reproducible Example
- Create a Python file with 3 unrelated classes (A, B, C), each with several methods.
- Ask Claude: "Add a new method
foo()to class A."
- Inspect the result — class B or C methods may be silently removed or simplified,
particularly if the file is long enough that Claude did not read it in full before
writing its replacement.
Confirmed Trigger Conditions
- File length: 400+ lines
- Claude uses Write tool (full file rewrite) instead of Edit tool (targeted diff)
- The feature being added is in a different section of the file than the features
being dropped
- No CLAUDE.md spec listing required symbols
- No regression tests asserting existing symbols are present
- Multiple sessions with context compaction between them (summary loses symbol
inventory detail)
Version
Claude Code CLI: 2.1.185
Model: claude-sonnet-4-6
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Code CLI version 2.1.185.
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗