What happened?
The persistent git-refs checkpoint backend has a read-modify-write race.
When two independent writers update the same checkpoint, both can read the same
checkpoint tip, build different child commits, and successfully update the
checkpoint ref. Because the final ref update is unconditional and does not
verify the expected old commit, the later writer can silently hide the earlier
writer's mutation.
I reproduced this deterministically on the official stable release v0.9.0
and on the latest fetched public main. Both ref writes returned success, but
the first writer's summary disappeared while the second writer's attribution
remained visible.
This can silently lose checkpoint data such as summaries, transcripts,
attribution, assets, or attached sessions even though the writers report
success.
Steps to reproduce
I added the following local regression test to
cmd/entire/cli/checkpoint/refs_store_test.go:
TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutation
The test performs this deterministic interleaving:
- Create a checkpoint.
- Read its current parent once.
- Build a summary mutation from that parent.
- Build an attribution mutation from the same parent.
- Write the summary commit successfully.
- Write the attribution commit successfully afterward.
- Read the checkpoint.
- Observe that attribution remains but the summary is absent.
Run:
go test ./cmd/entire/cli/checkpoint -run '^TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutation$' -count=1 -v
The test passes because it successfully observes the lost-update behavior; it
does not mean the defect is fixed.
Entire CLI version
Entire CLI v0.9.0
OS and architecture
Windows amd64 (build 26200.8875)
Agent
Codex
Terminal
PowerShell 5.1 through the Codex desktop integrated shell
Logs / debug output
=== RUN TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutation
--- PASS: TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutation (1.88s)
PASS
ok github.com/entireio/cli/cmd/entire/cli/checkpoint 5.479s
Additional context
Validated against official stable release v0.9.0:
8b77ad43132d18f7958825c9dcd26544ab8f5d92
Also validated against the latest fetched public main revision:
dd2e87a02ef853b32a85e7094e1944fe320739a3
Environment details:
- Stable test Go version:
1.26.4
- Latest-main test Go version:
1.26.5
- Git:
2.46.0.windows.1
- Shell: PowerShell
5.1.26100.8875
- Validation worktree: detached worktree at the exact revision above
- Production source changes: none; only the local regression test was added
The likely cause is that gitRefsStore.setRef advances the checkpoint ref with
an unconditional SetReference. The read/build/set sequence has no
checkpoint-scoped lock and does not use an expected-old-value compare-and-swap.
Two writers can therefore build valid commits from the same parent while the
last ref update silently makes the first mutation unreachable through normal
checkpoint reads.
Expected behavior: both independent mutations should remain reachable, or one
writer should receive an explicit conflict and retry or fail clearly.
What happened?
The persistent
git-refscheckpoint backend has a read-modify-write race.When two independent writers update the same checkpoint, both can read the same
checkpoint tip, build different child commits, and successfully update the
checkpoint ref. Because the final ref update is unconditional and does not
verify the expected old commit, the later writer can silently hide the earlier
writer's mutation.
I reproduced this deterministically on the official stable release
v0.9.0and on the latest fetched public
main. Both ref writes returned success, butthe first writer's summary disappeared while the second writer's attribution
remained visible.
This can silently lose checkpoint data such as summaries, transcripts,
attribution, assets, or attached sessions even though the writers report
success.
Steps to reproduce
I added the following local regression test to
cmd/entire/cli/checkpoint/refs_store_test.go:TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutationThe test performs this deterministic interleaving:
Run:
go test ./cmd/entire/cli/checkpoint -run '^TestGitRefsStore_ForcedConcurrentBackfillsLoseOneMutation$' -count=1 -vThe test passes because it successfully observes the lost-update behavior; it
does not mean the defect is fixed.
Entire CLI version
Entire CLI v0.9.0
OS and architecture
Windows amd64 (build 26200.8875)
Agent
Codex
Terminal
PowerShell 5.1 through the Codex desktop integrated shell
Logs / debug output
Additional context
Validated against official stable release
v0.9.0:8b77ad43132d18f7958825c9dcd26544ab8f5d92Also validated against the latest fetched public
mainrevision:dd2e87a02ef853b32a85e7094e1944fe320739a3Environment details:
1.26.41.26.52.46.0.windows.15.1.26100.8875The likely cause is that
gitRefsStore.setRefadvances the checkpoint ref withan unconditional
SetReference. The read/build/set sequence has nocheckpoint-scoped lock and does not use an expected-old-value compare-and-swap.
Two writers can therefore build valid commits from the same parent while the
last ref update silently makes the first mutation unreachable through normal
checkpoint reads.
Expected behavior: both independent mutations should remain reachable, or one
writer should receive an explicit conflict and retry or fail clearly.