fix(cleanup): fail closed before deleting shadow history - #2385
Open
MuskanPaliwal wants to merge 5 commits into
Open
fix(cleanup): fail closed before deleting shadow history#2385MuskanPaliwal wants to merge 5 commits into
MuskanPaliwal wants to merge 5 commits into
Conversation
Entire-Checkpoint: 01M27FNYWAG56R5H9CV0BCZSZK
Entire-Checkpoint: 01M27XEBHFT7E8K000W92QZ05E
Entire-Checkpoint: 01M282EWYTJR6CC1QPSK5CW3PJ
Entire-Checkpoint: 01M287AR8Y7EZMJ3CRXDGFQYV8
MuskanPaliwal
marked this pull request as ready for review
September 11, 2026 12:51
Entire-Checkpoint: 01M2AW38T6Y7300KGQ45Z0VPHS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2378
Related to #2350 and #2358.
Entire keeps uncondensed checkpoint commits reachable through shadow branches. Cleanup could mistake incomplete safety evidence for proof that a branch was unused: expired state with pending work could be removed, a ref read failure could be treated as absence, and malformed records could be omitted from cleanup inventory. Each path could leave shadow-only checkpoint history unreachable.
Why cleanup could orphan history
Session state older than seven days was purged based on age even when it still recorded uncondensed checkpoint work. Separately, go-git can report an unreadable loose ref as not found, and session discovery treated that result as proof that the ref was absent. Once either state record disappeared, later cleanup saw no session protecting the shadow branch.
The cleanup inventory was also tolerant by default, so an unreadable state record could disappear from the evidence used to authorize deletion. Finally, the last protection check happened before a separate ref-deletion operation, leaving a state-change window between check and deletion.
Make destructive decisions fail closed
State expiration now preserves records that still carry pending checkpoint content. Reference absence must be positively established; ambiguous ref errors preserve the associated state.
Ordinary session discovery remains tolerant: it logs and skips an unreadable unrelated state instead of blocking healthy session linking. Destructive paths use a strict inventory so omitted state cannot authorize deletion.
Post-push cleanup now performs its final protection check inside a prepared native Git compare-and-swap transaction. Git holds the ref lock while the guard runs, and any uncertain or failed safety check aborts before the deletion commits. Doctor and reset cleanup use the same strict-inventory boundary.
The deliberate trade-off is that uncertainty may retain stale state or a shadow branch. That is preferable to making uncondensed checkpoint history unreachable.
Verification
mise run checkpassed on the final tree, including:Regression coverage includes expired uncondensed sessions, unreadable refs, malformed session state, tolerant commit linking, and guarded ref deletion on files and reftable storage.