test: git-remote coverage (3/4) — divergence & recovery matrix#1638
Open
Soph wants to merge 5 commits into
Open
test: git-remote coverage (3/4) — divergence & recovery matrix#1638Soph wants to merge 5 commits into
Soph wants to merge 5 commits into
Conversation
…D4, D5) Systematize the local-v1 divergence & recovery matrix (the most re-broken area, #953/#1251/#1252/#1260) plus the specifically-untested replay edges. D1 (integration, git-branch): drive the local-v1 state {ahead, behind, diverged, disconnected} through the real triggers end-to-end: - pre-push (real hook): local-only survives; ahead fast-forwards; diverged replays both sides on a linear tip; disconnected cherry-picks; a repeated push is idempotent (double-replay guard, #1260). - explain fetch-on-miss for {behind, diverged}, extending the existing {missing, ahead} coverage: a remote-only checkpoint is fetched/reconciled and local-only checkpoints survive. - doctor --force reconciles a disconnected v1, preserving both sides. D4 (strategy unit): replay fidelity edges. A no-op commit must not clobber the remote tip's accumulated tree (regression 743c43f); a root-commit chain replays cleanly. Plus a KNOWN BUG pin: >1000-commit replay is still capped (collectCommitsSince) because the cap-removal (4cf01ed) lives on the unmerged branch origin/no-limit; flip the assertion when it lands. D5 (strategy): TOCTOU guard for 1e8628a -- fetchAndRebaseRefCommon replays onto the freshly fetched remote tip, not a stale earlier hash. The literal ls-remote seam the fix patched no longer exists (fix is an ancestor), so this pins the behavioural invariant. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq Entire-Checkpoint: b19f4c2ff3bd
…ery (D2, D3)
Drive the git-refs recovery end-to-end through the real pre-push path (drain
queue -> batch push -> per-ref fetch+replay), complementing the unit-level
coverage in strategy/refs_push_test.go.
D2:
- remote ref amended by another clone (valid child commit) + a divergent
local write of the same ref: the fast-forward-only batch push is rejected,
recovery fetches the remote tip and replays the local change on top
(non-force), so both sides' files survive and the remote commit stays an
ancestor.
- queue safety: when the remote refuses the ref update (bare pre-receive
declining the checkpoint namespace), the ref stays queued and the remote
is untouched (never force-overwritten); a later push retries and lands it.
A pure content-level cherry-pick conflict is not reproducible at this layer
(tree-delta apply is last-writer), so a server-side rejection stands in.
D3: two clones race on the SAME per-checkpoint ref from a shared base -- the
second pusher fetch+replay+retries (non-force), preserving both. The git-refs
analogue of TestConcurrentPush_SecondPusherRebasesAndRetries (v1-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: faa45ac4455f
…ee, D7 two-remote pin) D6: the git-refs push queue lives in the shared git common dir, so sessions in two worktrees enqueue into ONE queue. A single pre-push from the main worktree pushes both worktrees' checkpoint refs, drains + compacts the queue, and prunes a stale entry (a queued ref with no local ref -> partitionLocalRefs). Adds an AddWorktree test helper (its own .entire/, shared common dir, offset session counter so session IDs don't collide in the shared session store). D7: PIN the known two-remote queue-clearing gap (test plan decision D-2). The queue records only the ref, not the remote, so a push to remote A drains the queue and remote B never receives those refs. Asserts current behavior with a clear "flip when per-remote tracking lands" note. No production change. Also resolves the COMMIT_EDITMSG scratch path via `git rev-parse --absolute-git-dir` so the shadow-commit test helpers work in a linked worktree (where .git is a file); identical to the prior path for normal checkouts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq Entire-Checkpoint: 057f6136f6f5
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a broader, end-to-end integration-test matrix around historically fragile checkpoint ref divergence/recovery behavior (v1 git-branch and git-refs per-checkpoint refs), plus strategy-level replay-fidelity regression guards. This strengthens confidence that ref reconciliation is correct and remains idempotent across pre-push, explain fetch-on-miss, and doctor flows—without changing production behavior.
Changes:
- Add strategy tests that lock replay fidelity invariants (no-op commits, root chains, fetched-remote-hash TOCTOU) and pin the current >1000-commit traversal cap behavior.
- Add integration tests covering (a) v1 divergence state × trigger matrix, (b) git-refs per-checkpoint ref divergence/rejection/concurrency recovery, and (c) push-queue semantics (multi-worktree shared queue + pinned two-remote gap).
- Extend the integration test harness with linked-worktree support (
AddWorktree) and correct commit message scratch resolution in linked worktrees.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| cmd/entire/cli/strategy/replay_fidelity_test.go | New strategy-level regression tests for replay correctness and TOCTOU invariants; pins current commit traversal cap behavior. |
| cmd/entire/cli/integration_test/testenv.go | Adds linked-worktree helpers and fixes COMMIT_EDITMSG resolution to work under git worktree. |
| cmd/entire/cli/integration_test/refs_queue_semantics_test.go | New integration coverage for git-refs push-queue behavior across multi-worktree and multi-remote scenarios (including pinned known bug). |
| cmd/entire/cli/integration_test/refs_divergence_test.go | New integration coverage for git-refs per-checkpoint ref divergence recovery, server-side rejection retry semantics, and concurrent pushers. |
| cmd/entire/cli/integration_test/divergence_matrix_test.go | New integration matrix for v1 local/remote divergence states across pre-push, explain fetch-on-miss, and doctor reconciliation triggers. |
Comment on lines
+67
to
+70
| c := exec.CommandContext(env.T.Context(), "git", args...) | ||
| c.Dir = env.RepoDir | ||
| c.Env = append(testutil.GitIsolatedEnv(), "GIT_INDEX_FILE="+env.RepoDir+"/.git/entire-orphan-index") | ||
| if stdin != "" { |
Collaborator
Author
There was a problem hiding this comment.
Fixed in 56408fa — GIT_INDEX_FILE path now built with filepath.Join.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq Entire-Checkpoint: 4521fd749232
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://entire.io/gh/entireio/cli/trails/759
Part 3 of the stack on #1637. Systematizes the historically most re-broken area (#953, #1251, #1252, #1260: destructive local-v1-ref moves) into an explicit matrix, and covers the git-refs equivalents that only had unit coverage.
Tests
safely_advance_local_ref_test.go/explain_test.goare not duplicated; the resume trigger shares theSafelyAdvanceLocalRefengine exercised via explain.origin/no-limit), soTestCollectCommitsSince_CommitCapPinsCurrentBehaviorpins the hard failure with a flip-when-fixed note.pre-receiverejection — a content-level cherry-pick conflict isn't deterministically reproducible at this layer); concurrent pushers from two clones.AddWorktreetest helper.Verification
mise run fmt && mise run lintclean per commitmise run test:integrationgreen (444 tests at tip)go test ./cmd/entire/cli/strategy/greenmise run test:e2e:canarygreen under bothE2E_CHECKPOINT_STOREvalues🤖 Generated with Claude Code
https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Note
Low Risk
Test-only changes and integration helpers; no runtime checkpoint sync or push logic is modified.
Overview
Adds integration and strategy tests that map local v1 / per-checkpoint ref divergence to real CLI paths (pre-push,
checkpoint explain,entire doctor) and git-refs push-queue behavior, without changing production code.D1 (git-branch): Table-driven cases for local v1 ahead, behind, diverged, disconnected through the pre-push hook (checkpoint survival, diverged replay keeps both sides with a linear tip, idempotent double pre-push). Separate tests cover fetch-on-miss via
checkpoint explain(behind/diverged) anddoctor --forceon disconnected orphans.D2/D3 (git-refs): End-to-end pre-push when a per-checkpoint ref is amended on the remote vs locally (fetch+replay, both file sets kept), server rejection (ref stays queued, remote unchanged, retry succeeds), and two clones racing on the same ref.
D6/D7 (queue): Shared common-dir queue across linked worktrees (one pre-push drains both, stale entries pruned). D7 intentionally asserts today’s two-remote gap: first push drains the queue so a second remote never gets the refs (#1635).
Test harness:
commitMsgPath()for linked worktrees; newAddWorktreehelper.Strategy (
replay_fidelity_test.go): Guards for no-op commits not clobbering remote trees on replay, root-commit chains, reconcile using the post-fetch remote tip; pins the >1000-commitcollectCommitsSincecap until the unmerged cap-removal lands.Reviewed by Cursor Bugbot for commit d93c1e3. Configure here.