Skip to content

fix: recover portable checkouts from stale index locks and missing source databases - #128

Merged
steipete merged 3 commits into
mainfrom
portable-stale-lock-recovery
Jul 27, 2026
Merged

fix: recover portable checkouts from stale index locks and missing source databases#128
steipete merged 3 commits into
mainfrom
portable-stale-lock-recovery

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Incident

A maintainer Mac portable-store checkout was silently broken for nine days: a crashed Git process left a zero-byte stale .git/index.lock, and the tracked source database had been locally deleted. The ordinary refresh path reported the checkout dirty forever, while the missing database surfaced as a permanent stat error that never reached repair.

Fix

The refresh path now removes only verified-stale locks using the existing conservative helper: the lock must be aged and unheld according to lsof. Fast-forward pulls also run through the stale-lock retry helper.

A missing source database on a repair-eligible checkout now routes through the standard reset-pull/reclone repair chain, with the healthy-mirror fallback preserved.

Recovery failures degrade to a healthy runtime mirror, including when a reclone completes without restoring the database; a dedicated regression test covers this case.

Recovery attempts back off for 15 minutes, so an unrecoverable source serves the healthy mirror quietly instead of re-cloning on every read. A regression test verifies that repeated reads do not create additional checkout backups.

Whether reset/pull failures should escalate to reclone is deferred to a tracked follow-up covering both the long-standing corruption path and the new missing-source path symmetrically.

Proof

  • Three new regression tests cover stale-lock recovery, continued rejection of a dirty checkout without a lock, and missing-source repair.
  • Dedicated regressions cover healthy-mirror fallback after an incomplete reclone and the 15-minute recovery backoff across repeated reads.
  • GOWORK=off go test ./... passes.
  • Autoreview completed with every finding either fixed or explicitly adjudicated by the maintainer; there are no unreviewed findings.

steipete added 3 commits July 26, 2026 19:52
…urce databases

The ordinary read/refresh path treated a checkout with a stale
.git/index.lock as dirty forever, silently blocking refreshes (observed
9 days on a maintainer Mac); it now removes verified-stale locks (aged,
unheld per lsof) and retries, and the fast-forward pull uses the same
stale-lock retry. A missing portable source database previously
surfaced as a permanent stat error; for repair-eligible checkouts it
now routes through the standard reset-pull/reclone repair with the
healthy-mirror fallback preserved.
…ecoverable

Review follow-up: the repair/reclone chain for a missing source database
now degrades to the healthy runtime mirror on any failure - including a
reclone that completes without restoring the database - instead of only
covering the initial repair error.
Review follow-up: an unrecoverable missing source previously re-ran
reset/pull plus a full reclone (accumulating checkout backups) on every
runtime open. Recovery attempts now honor a 15-minute backoff keyed on
the recorded repair timestamp; a restored source bypasses the gate
because the stat succeeds before it is consulted.
@clawsweeper

clawsweeper Bot commented Jul 27, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix: recover portable checkouts from stale index locks and missing source databases This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@steipete
steipete merged commit c090a86 into main Jul 27, 2026
11 checks passed
osolmaz pushed a commit to osolmaz/gitcrawl that referenced this pull request Jul 29, 2026
…urce databases (openclaw#128)

The ordinary read/refresh path treated a checkout with a stale
.git/index.lock as dirty forever, silently blocking refreshes (observed
9 days on a maintainer Mac); it now removes verified-stale locks (aged,
unheld per lsof) and retries, and the fast-forward pull uses the same
stale-lock retry. A missing portable source database previously
surfaced as a permanent stat error; for repair-eligible checkouts it
now routes through the standard reset-pull/reclone repair with the
healthy-mirror fallback preserved.

Review follow-up: the repair/reclone chain for a missing source database
now degrades to the healthy runtime mirror on any failure - including a
reclone that completes without restoring the database - instead of only
covering the initial repair error.

Review follow-up: an unrecoverable missing source previously re-ran
reset/pull plus a full reclone (accumulating checkout backups) on every
runtime open. Recovery attempts now honor a 15-minute backoff keyed on
the recorded repair timestamp; a restored source bypasses the gate
because the stat succeeds before it is consulted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant