STATE.md corruption: stale file-history snapshot re-injected into working tree at context/compaction boundaries
Summary
A version-controlled markdown file we actively edit (.planning/STATE.md, part of the get-shit-done planning workflow) has been silently overwritten in the working tree — with no edit from the agent, no tool call, no user action — by what appears to be a stale snapshot from Claude Code's own internal file-history store. This has now happened 8 times across sessions in the same repo, most recently caught live (diffed and stashed as evidence) rather than only found pre-existing at session start.
Environment
- Claude Code CLI (exact version not captured at time of report; happy to provide on request)
- macOS (Darwin 25.5.0)
- Repo uses
get-shit-done(GSD) planning workflow — ruled out as the cause (see below)
Observed corruption signature (consistent across instances)
milestone_namefrontmatter field flattened to the literal string"milestone"(losing its real value, e.g."V1 Launch Hardening (Phase 9.1)")total_phasesandpercentfrontmatter fields reverted to old/wrong numeric values (e.g.total_phases: 12when the current correct value is6;percent: 25when correct is50)- Prose sentences truncated mid-word
- A
Resume file:line wiped to literalNone last_updatedtimestamp sometimes patched to a current timestamp while surrounding prose is stale/truncated — i.e. only some fields get "refreshed," others get reverted to old content
Why we believe this is a Claude Code bug, not a workflow (GSD) bug
- No hook in
~/.claude/hooks/writes or restores STATE.md content — audited all hooks in the project, including the two most plausible candidates (a context monitor and a session-state hook), both read-only. - No script in the GSD tool's
bin/lib/matches the corrupted template/output shape. - The corrupted text is a near-verbatim match for a real STATE.md snapshot from a specific earlier session (days prior), which strongly suggests it's being read from somewhere Claude Code caches file edit history (e.g. an internal file-history/checkpoint store keyed by session id + path hash), not generated fresh.
- Corruption events have repeatedly coincided with a context-exhaustion / compaction / pause-work boundary — i.e. right when a session is running low on context and some checkpoint/state-save code path may run.
- Checked
get-shit-done(GSD)'s own GitHub issues for a match — nothing corresponds to this exact signature.
Impact
- Silent data corruption of a file we rely on for cross-session continuity. If a corrupted diff is committed without being caught (we now
git diffSTATE.md before every commit specifically because of this), it destroys real project history/decisions and misleads future sessions about project state. - Happened again live during a routine
/resume-style workflow in this session, immediately after a context-usage warning fired (~75-79% usage), while performing an unrelated small doc edit to the same file — no compaction was requested by the user, but this may be an internal auto-compaction trigger.
What we'd like
- Guidance on whether this matches a known internal code path (checkpoint/compaction writing a stale cached version of a tracked file back into the working tree).
- If reproducible on your end, a fix; if not obviously reproducible, any pointers on what diagnostic info to capture next time it happens live (we can capture
git diffoutput, but don't have visibility into Claude Code's internal file-history store to compare it directly).
Reproduction is inconsistent
We don't have a minimal repro — it has occurred unpredictably over ~8 sessions in the same fairly large repo (Next.js app, extensive .planning/ markdown docs, long-running sessions with heavy tool use and occasional context compaction). We can provide the actual corrupted diffs (currently preserved via git stash) if that would help.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗