You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#29 introduced two families of local recovery refs written before an auto-rollback's git reset --hard:
refs/heads/attempt-preserve/<run_id>-<sha> branches parking committed work (preserve_commits), and
refs/attempt-preserve-dirty/<run_id>-<baseline>-<attempt> refs parking the uncommitted working-tree snapshot (snapshot_worktree via _preserve_attempt_worktree).
#32 added bounded retention for family 1 (ScmPolicy.preserve_keep, pruned at run start) and explicitly fenced family 2 out of its scope.
Problem
Nothing ever removes the refs/attempt-preserve-dirty/* refs. Every dirty auto-rollback attempt creates one (keyed by attempt number, so retries each add a new ref), and they accumulate unbounded exactly like the branches did.
Scope / severity: low. Same as #32: these refs are local-only (never pushed) and, living outside refs/heads/, they don't even clutter git branch output — so the nuisance is smaller. But they still add ref-walking overhead forever and hold snapshot commits alive against git gc indefinitely.
Proposed resolution
Extend the run-start bounded retention to this family:
Reuse the existing scm.preserve_keep budget (simplest — one knob governs both recovery-ref families), or add a sibling field if independent tuning is wanted.
These are not branches, so delete via git update-ref -d (or batched git update-ref --stdin), not git branch -D.
for-each-ref --sort=-committerdate refs/attempt-preserve-dirty/ works unchanged: each ref points at the snapshot commit created at preservation time, so committer date is the park time here.
Background
#29 introduced two families of local recovery refs written before an auto-rollback's
git reset --hard:refs/heads/attempt-preserve/<run_id>-<sha>branches parking committed work (preserve_commits), andrefs/attempt-preserve-dirty/<run_id>-<baseline>-<attempt>refs parking the uncommitted working-tree snapshot (snapshot_worktreevia_preserve_attempt_worktree).#32 added bounded retention for family 1 (
ScmPolicy.preserve_keep, pruned at run start) and explicitly fenced family 2 out of its scope.Problem
Nothing ever removes the
refs/attempt-preserve-dirty/*refs. Every dirty auto-rollback attempt creates one (keyed by attempt number, so retries each add a new ref), and they accumulate unbounded exactly like the branches did.Scope / severity: low. Same as #32: these refs are local-only (never pushed) and, living outside
refs/heads/, they don't even cluttergit branchoutput — so the nuisance is smaller. But they still add ref-walking overhead forever and hold snapshot commits alive againstgit gcindefinitely.Proposed resolution
Extend the run-start bounded retention to this family:
scm.preserve_keepbudget (simplest — one knob governs both recovery-ref families), or add a sibling field if independent tuning is wanted.git update-ref -d(or batchedgit update-ref --stdin), notgit branch -D.for-each-ref --sort=-committerdate refs/attempt-preserve-dirty/works unchanged: each ref points at the snapshot commit created at preservation time, so committer date is the park time here.Acceptance criteria
refs/attempt-preserve-dirty/*refs are pruned to a bounded count at run start, keeping the most recently created.0/disabled keeps every ref (consistent withpreserve_keepsemantics).refs/attempt-preserve-dirty/*— neverrefs/heads/*(the Cap the lifecycle of attempt-preserve/* recovery refs (follow-up to #29) #32 prune already ownsrefs/heads/attempt-preserve/*).Notes
Non-blocking follow-up to #32; surfaced during its review as the symmetric gap for the second ref family.