#1926 routed persistent checkpoint ref updates through a cross-process flock plus native git update-ref <ref> <new> <old>, which closed #1917 for the checkpoint store's own writers.
Two writers in strategy still update those same refs outside that lock, using go-git's CheckAndSetReference:
cmd/entire/cli/strategy/manual_commit_opf_rewrite.go:815 - CAS on refs/heads/entire/checkpoints/v1
cmd/entire/cli/strategy/manual_commit_opf_refs.go:169 - CAS on the per-checkpoint refs
Both compare-and-swap, so this is not the unconditional-update defect from #1917. The problem is that go-git's CheckAndSetReference does not interoperate with native git's .lock files - the reason documented at cmd/entire/cli/checkpoint/shadow_ref.go:53. So a pre-push OPF rewrite and a post-commit condensation can now race on the same ref through two mutually invisible CAS mechanisms.
The author of #1926 called this out in that PR's description as remaining scope.
Needs its own reproduction before a fix - #1917's does not cover it, since both sides here verify an expected old value.
#1926 routed persistent checkpoint ref updates through a cross-process flock plus native
git update-ref <ref> <new> <old>, which closed #1917 for the checkpoint store's own writers.Two writers in
strategystill update those same refs outside that lock, using go-git'sCheckAndSetReference:cmd/entire/cli/strategy/manual_commit_opf_rewrite.go:815- CAS onrefs/heads/entire/checkpoints/v1cmd/entire/cli/strategy/manual_commit_opf_refs.go:169- CAS on the per-checkpoint refsBoth compare-and-swap, so this is not the unconditional-update defect from #1917. The problem is that go-git's
CheckAndSetReferencedoes not interoperate with native git's.lockfiles - the reason documented atcmd/entire/cli/checkpoint/shadow_ref.go:53. So a pre-push OPF rewrite and a post-commit condensation can now race on the same ref through two mutually invisible CAS mechanisms.The author of #1926 called this out in that PR's description as remaining scope.
Needs its own reproduction before a fix - #1917's does not cover it, since both sides here verify an expected old value.