Skip to content

test: git-remote coverage (2/4) — real-hook P0 tests, cross-machine fetch, explain fix#1637

Open
Soph wants to merge 7 commits into
soph/git-remote-tests-1-infrafrom
soph/git-remote-tests-2-p0
Open

test: git-remote coverage (2/4) — real-hook P0 tests, cross-machine fetch, explain fix#1637
Soph wants to merge 7 commits into
soph/git-remote-tests-1-infrafrom
soph/git-remote-tests-2-p0

Conversation

@Soph

@Soph Soph commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

https://entire.io/gh/entireio/cli/trails/758

Part 2 of the stack on #1636. The P0 test groups from the plan, plus two fixes they surfaced.

Tests

  • A-group (real pre-push hook, both backends): plain-push checkpoint sync with user-push assertions (A1), no-new-checkpoints no-op via remote digest (A2), branch-delete and tag-only pushes through the hook (A3), unreachable checkpoint target degrades gracefully under the real hook (A4), git-refs queue drain via real push (A6 slice).
  • C-group (cross-machine clone flows): production fetchMetadataBranchIfMissing exercised for real over HTTPS (C1 — previous clone tests substituted a raw git fetch), git-refs on-demand RefFetcher fetches exactly the needed ref and nothing else (C2), unreachable-remote reads surface the real fetch error (C3), authenticated HTTPS clone auto-fetch under both backends (C4).
  • G1 (e2e): resume_remote_test.go / explain_test.go clone tests now rely on the installed hook (AssertCheckpointsOnRemote) instead of explicit PushCheckpointRefs — a broken hook can no longer pass the e2e suite.

Fixes

  • Graceful-degradation test false-positive: the test staged the session's files after the stop hook, so neither backend condensed anything; git-branch passed only because the v1 branch was inherited from the clone. Reordered to stage-before-stop and the assertion now requires a new checkpoint ID.
  • fix: surface git-refs checkpoint fetch failures in explain fallback: matchCheckpointPrefixWithRemoteFallback discarded the FetchCheckpointRef error, reporting an unreachable remote identically to an absent checkpoint — re-masking the error class 7bbdad0 fixed at the store layer. The fallback now propagates the error (repos with no resolvable checkpoint source keep the clean not-found; the commit-ref prefetch stays best-effort; the v1-branch path keeps its historical fail-soft behavior). C3 asserts it hard.

Verification

  • mise run fmt && mise run lint clean per commit
  • mise run test:integration green (430 tests, 0 skips at tip)
  • mise run test:e2e:canary green under both E2E_CHECKPOINT_STORE values

🤖 Generated with Claude Code

https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq


Note

Medium Risk
Changes user-visible error handling on checkpoint explain and attribution when remotes are unreachable; behavior is more correct but could surprise scripts that only matched on “not found”.

Overview
Adds broad integration and e2e coverage for checkpoint sync and cross-machine reads: real git push through the installed pre-push hook (sync, no-op pushes, delete/tag shapes, unreachable checkpoint_remote, git-refs push-queue drain), HTTPS clone flows (fetchMetadataBranchIfMissing, tokenized auto-fetch, per-ref RefFetcher precision), plus e2e tests that assert checkpoints land on the remote via the hook instead of explicit PushCheckpointRefs.

Fixes misleading “checkpoint not found” when the remote fetch actually failed (regression 7bbdad0): matchCheckpointPrefixWithRemoteFallback now returns a third error value; git-refs FetchCheckpointRef failures and post-fetch re-list errors propagate through checkpoint explain, JSON export, and attribution remote enrichment. Repos with no resolvable remote still get a clean local not-found; the v1 metadata-branch path keeps prior fail-soft behavior.

Test harness / correctness tweaks: TestEnv helpers for config, tags, push-queue peek, and hook pushes with arbitrary args; graceful-degradation clone test stages files before stop and requires a new checkpoint ID (fixes a false positive from inherited v1 metadata).

Reviewed by Cursor Bugbot for commit 52f48e2. Configure here.

Soph and others added 5 commits July 4, 2026 20:59
Exercise the git-invoked pre-push hook end to end for both checkpoint
backends, closing the "real hook is never asserted" blind spot from the
git-remote test plan.

- A1: extend the seed test to assert the user branch itself arrives (the
  user push is unaffected by the checkpoint sync).
- A2: a push carrying only a non-checkpointed commit is a fast no-op
  (RemoteCheckpointState digest unchanged).
- A3: `git push --delete` (zero-sha stdin) and a tag-only push run through
  the real hook without crashing and exit 0.
- A4: checkpoints routed to a genuinely unreachable target (a missing repo
  on the in-process HTTPS server) degrade gracefully; the user push still
  lands the feature branch. Local-path origins can't express this (URL
  derivation falls back to origin), hence the HTTPS setup.
- A6 (git-refs slice): a real push drains the per-checkpoint push queue;
  the v1 alternates rebase scenario has no git-refs equivalent.

Adds GitPushArgsWithHooks, GitTag, PushQueueRefs, and SetGitConfig helpers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: 0d5ed27f5bb0
Cover the clone → fetch → read paths for both checkpoint backends.

- C1 (git-branch, HTTPS): exercise the production
  fetchMetadataBranchIfMissing path — a clone that lacks the local v1
  branch fetches it during pre-push settings resolution, no manual git
  fetch. Runs over HTTPS because local-path origins can't derive a
  checkpoint URL.
- C2 (git-refs): a clone with no checkpoint refs reads a checkpoint; the
  on-demand RefFetcher fetches EXACTLY that ref, leaving an unrelated
  checkpoint's ref absent until it too is read.
- C3 (git-refs): unreachable remote + locally-missing ref. Documents a
  KNOWN BUG (regression class 7bbdad0): explain's git-refs prefix-match
  remote fallback (explain_export.go:216-227) discards the
  FetchCheckpointRef error and reports "checkpoint not found", masking an
  unreachable remote as an absent checkpoint. The test self-heals: it skips
  while the masking is present and asserts once fixed. No production change.
- C4 (both, HTTPS): reading a checkpoint from a fresh authenticated clone
  auto-fetches its data with the token (v1 branch on miss for git-branch,
  the exact per-checkpoint ref for git-refs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: 5d532318e7a7
The remote clone tests pushed checkpoints explicitly via PushCheckpointRefs
right after the user push, which would mask a broken pre-push hook. Replace
those calls with AssertCheckpointsOnRemote so a plain `git push` must sync
checkpoints through the installed hook end to end (A5/G1 in spirit).

No prompt text changed, so the vogon canary parser is unaffected. Verified
green under both E2E_CHECKPOINT_STORE values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: cfbc41e5de4b
Root-caused the git-refs KNOWN BUG skip: it was a harness artifact, not a
backend divergence. The test staged the session's file changes after the
stop hook, so the "no files modified during session" gate skipped
condensation on BOTH backends. git-branch still passed only because the
assertion (v1 branch exists) was satisfied by the checkpoint inherited
from origin via the plain clone; git-refs correctly reported no local
checkpoint (per-checkpoint refs are not fetched by a default clone).

Stage before stop like a real agent session (and like the
createCheckpointedCommit helper), drop the skip, and assert a NEW
checkpoint ID was condensed so inherited clone data can never satisfy
the check again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: 8429f8830bfd
matchCheckpointPrefixWithRemoteFallback discarded the FetchCheckpointRef
error in its git-refs branch, so an unreachable remote was reported
identically to a genuinely absent checkpoint ("checkpoint not found") —
re-masking exactly the error class 7bbdad0 fixed at the store layer.

The fallback now returns the fetch error and callers surface it as
"checkpoint <id> not found locally; fetching from remote failed: ...".
A repo with no resolvable checkpoint source skips the fetch entirely
(local absence is authoritative there), the commit-ref prefetch path
deliberately keeps ignoring it (the downstream store read surfaces real
failures with correct absent-vs-error semantics), and the v1-branch
fallback keeps its historical fail-soft behavior for now.

Converts the self-healing KNOWN BUG skip in
TestGitRefsClone_UnreachableRemoteMissingRefSurfacesRealError into hard
regression assertions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: ca56eea65fe0
@Soph Soph requested a review from a team as a code owner July 4, 2026 21:26
Copilot AI review requested due to automatic review settings July 4, 2026 21:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (part 2/4 of the #1636 stack) expands integration + e2e coverage around git-remote checkpoint behavior—especially “real git push through installed pre-push hook” flows and cross-machine clone/read fetch paths—and fixes a production bug where checkpoint explain could incorrectly mask an unreachable-remote fetch failure as “checkpoint not found”.

Changes:

  • Adds integration tests for real-hook pushes (sync, no-op, delete/tag shapes, unreachable checkpoint_remote degradation, git-refs push-queue drain) and HTTPS clone/read auto-fetch flows.
  • Adds git-refs clone read coverage to ensure the on-demand RefFetcher fetches exactly the needed checkpoint ref and surfaces real remote fetch errors.
  • Updates explain/prefix-match remote fallback to propagate git-refs fetch errors (instead of reporting “not found”), and updates e2e clone tests to assert hook-driven remote checkpoint sync.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
e2e/tests/resume_remote_test.go Switches clone flow to assert hook-driven remote checkpoint sync instead of explicitly pushing checkpoint refs.
e2e/tests/explain_test.go Same as above for explain-from-clone e2e coverage.
cmd/entire/cli/integration_test/testenv.go Adds integration test helpers (git config/tag, push queue peek, push-with-hooks args).
cmd/entire/cli/integration_test/remote_operations_test.go Fixes graceful-degradation test ordering and strengthens assertion to require a new checkpoint.
cmd/entire/cli/integration_test/refs_fetch_test.go New C2/C3 git-refs clone/read tests for exact-ref fetch and unreachable-remote error surfacing.
cmd/entire/cli/integration_test/real_hook_push_test.go Adds A2/A3/A4/A6 integration coverage around real pre-push hook behavior.
cmd/entire/cli/integration_test/http_remote_test.go Adds HTTPS cross-machine clone → fetch/read tests (C1/C4).
cmd/entire/cli/git_operations.go Updates FetchCheckpointRef contract comment to require surfacing fetch failures.
cmd/entire/cli/explain.go Propagates remote fetch failures from the prefix-match fallback instead of returning not-found.
cmd/entire/cli/explain_export.go Threads fallback errors through export + commit-ref prefetch behavior; updates fallback helper signature.
cmd/entire/cli/attribution.go Ensures attribution refresh path sees remote fallback errors (instead of treating as not-found).

Comment on lines +2034 to +2035
queuePath := filepath.Join(env.RepoDir, ".git", "entire-checkpoint-push-queue.jsonl")
data, err := os.ReadFile(queuePath) //nolint:gosec // G304: path built from test env, not user input

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a9b0334 — PushQueueRefs now resolves the common dir via git rev-parse --path-format=absolute --git-common-dir, matching production (checkpoint/pushqueue.go), so it's correct from linked worktrees.

Comment on lines +2062 to +2066
// GitPushArgsWithHooks installs the pre-push hook and runs `git push <args>`
// (WITHOUT --no-verify) so the real hook fires exactly as git runs it, then
// returns the combined output and any error instead of failing the test. Use it
// for push shapes GitPushWithHooks can't express — a `--delete` (zero-sha stdin),
// a tag-only push, or an expected graceful-degradation exit code.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded in a9b0334. One nuance: the wrapper forwarding only the remote name is not a fidelity gap — it matches the production hook template (strategy/hooks.go runs entire hooks git pre-push "$1"), and stdin is inherited via exec. The docs now state that explicitly instead of the blanket "exactly as git runs it".

Soph and others added 2 commits July 5, 2026 10:10
- PushQueueRefs: resolve the git common dir via rev-parse like production
  (checkpoint/pushqueue.go) instead of hard-coding RepoDir/.git, so the
  helper is correct from linked worktrees
- clarify InstallRealPrePushHook/GitPushArgsWithHooks docs: the wrapper
  forwards only the remote name, matching the production hook template

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012yi3hHGAGepwfrfjPETjGq
Entire-Checkpoint: 283495b6edfd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants