Skip to content

fix(cleanup): fail closed before deleting shadow history - #2385

Open
MuskanPaliwal wants to merge 5 commits into
entireio:mainfrom
MuskanPaliwal:fix-session-cleanup-safety
Open

fix(cleanup): fail closed before deleting shadow history#2385
MuskanPaliwal wants to merge 5 commits into
entireio:mainfrom
MuskanPaliwal:fix-session-cleanup-safety

Conversation

@MuskanPaliwal

Copy link
Copy Markdown
Contributor

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 check passed on the final tree, including:

  • formatting and lint
  • race-enabled unit and integration tests
  • 56 Vogon canaries
  • 4 Roger-Roger canaries

Regression coverage includes expired uncondensed sessions, unreadable refs, malformed session state, tolerant commit linking, and guarded ref deletion on files and reftable storage.

Entire-Checkpoint: 01M27FNYWAG56R5H9CV0BCZSZK
Entire-Checkpoint: 01M27XEBHFT7E8K000W92QZ05E
Entire-Checkpoint: 01M282EWYTJR6CC1QPSK5CW3PJ
Entire-Checkpoint: 01M287AR8Y7EZMJ3CRXDGFQYV8
@MuskanPaliwal
MuskanPaliwal marked this pull request as ready for review September 11, 2026 12:51
@MuskanPaliwal
MuskanPaliwal requested a review from a team as a code owner September 11, 2026 12:51
Entire-Checkpoint: 01M2AW38T6Y7300KGQ45Z0VPHS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Cleanup can make uncondensed checkpoint commits unreachable after state expiry or a ref read failure

1 participant