diff --git a/cmd/entire/cli/integration_test/http_remote_test.go b/cmd/entire/cli/integration_test/http_remote_test.go index f8bd2e38c..76bf477fa 100644 --- a/cmd/entire/cli/integration_test/http_remote_test.go +++ b/cmd/entire/cli/integration_test/http_remote_test.go @@ -446,3 +446,138 @@ func TestHTTPS_PushFailsWithoutToken(t *testing.T) { } assertRemoteHasCheckpointCommit(t, bareDir, checkpointID) } + +// TestHTTPS_EnableBootstrapsMetadataFromCheckpointRemote reproduces +// https://github.com/entireio/cli/issues/1374: when a second device clones a +// repo whose checkpoint data lives on a configured checkpoint_remote (a +// separate repo from origin), `entire enable` must populate the local +// entire/checkpoints/v1 branch from that remote instead of minting an +// unrelated empty orphan. The orphan made `entire checkpoint list` return +// nothing and caused non-fast-forward rejections on later fetches. +func TestHTTPS_EnableBootstrapsMetadataFromCheckpointRemote(t *testing.T) { + t.Parallel() + + srv := startGitHTTPSServer(t, "testorg/main-repo", "testorg/checkpoints") + env := NewFeatureBranchEnv(t) + + mainBare := srv.BareDirs["testorg/main-repo"] + checkpointBare := srv.BareDirs["testorg/checkpoints"] + httpsURL := srv.URL + "/testorg/main-repo.git" + seedBareRepo(t, env, mainBare, httpsURL) + + checkpointRemoteSettings := map[string]any{ + "strategy_options": map[string]any{ + "checkpoint_remote": map[string]any{ + "provider": "github", + "repo": "testorg/checkpoints", + }, + }, + } + + // Device A: create a checkpoint and push — metadata routes to the + // checkpoint remote, never to origin. + cloneA := cloneFromBareWithHTTPS(t, env, mainBare, httpsURL) + cloneA.ExtraEnv = srv.tokenEnv("clone-a-token") + cloneA.GitCheckoutNewBranch("feature/clone-a") + cloneA.PatchSettings(checkpointRemoteSettings) + checkpointA := createCheckpointedCommit(t, cloneA, "Work in clone A", "a.go", "package a", "Work from A") + cloneA.RunPrePush("origin") + + if !cloneA.BranchExistsOnRemote(checkpointBare, paths.MetadataBranchName) { + t.Fatal("precondition: checkpoint branch should be on checkpoint remote after push") + } + if cloneA.BranchExistsOnRemote(mainBare, paths.MetadataBranchName) { + t.Fatal("precondition: checkpoint branch should NOT be on origin") + } + + // Device B: fresh clone of origin (which has no metadata branch) with the + // same checkpoint_remote configured. No token — fetch (upload-pack) is + // unauthenticated; only push requires one. + cloneB := cloneFromBareWithHTTPS(t, env, mainBare, httpsURL) + cloneB.ExtraEnv = srv.sslEnv() + cloneB.PatchSettings(checkpointRemoteSettings) + + cloneB.RunCLI("enable", "--agent", "claude-code", "--telemetry=false") + + // The local metadata branch must match the checkpoint remote tip — not be + // a fresh empty orphan with unrelated history. + if !cloneB.BranchExists(paths.MetadataBranchName) { + t.Fatal("local metadata branch should exist after enable") + } + remoteTip := revParse(t, checkpointBare, "refs/heads/"+paths.MetadataBranchName) + localTip := revParse(t, cloneB.RepoDir, "refs/heads/"+paths.MetadataBranchName) + if localTip != remoteTip { + t.Errorf("local metadata branch tip = %s, want checkpoint remote tip %s (empty-orphan bug: enable did not fetch from checkpoint_remote)", localTip, remoteTip) + } + + // The fetched branch must contain device A's checkpoint metadata. + summaryA := CheckpointSummaryPath(checkpointA) + if _, found := cloneB.ReadFileFromBranch(paths.MetadataBranchName, summaryA); !found { + t.Errorf("local metadata branch should contain checkpoint A summary at %s", summaryA) + } +} + +// TestHTTPS_ReEnableRecoversFromEmptyMetadataOrphan covers the recovery path +// after a bootstrap that found nothing on the checkpoint remote: device B +// enables before any checkpoint exists (the bootstrap fetch legitimately +// finds no branch, so EnsureSetup mints the empty orphan), device A then +// pushes checkpoint data, and a second `entire enable` on device B must +// replace the empty orphan with the fetched branch — not skip the fetch +// because a local branch already exists. +func TestHTTPS_ReEnableRecoversFromEmptyMetadataOrphan(t *testing.T) { + t.Parallel() + + srv := startGitHTTPSServer(t, "testorg/main-repo", "testorg/checkpoints") + env := NewFeatureBranchEnv(t) + + mainBare := srv.BareDirs["testorg/main-repo"] + checkpointBare := srv.BareDirs["testorg/checkpoints"] + httpsURL := srv.URL + "/testorg/main-repo.git" + seedBareRepo(t, env, mainBare, httpsURL) + + checkpointRemoteSettings := map[string]any{ + "strategy_options": map[string]any{ + "checkpoint_remote": map[string]any{ + "provider": "github", + "repo": "testorg/checkpoints", + }, + }, + } + + // Device B: enable while the checkpoint remote has no metadata branch yet. + // The bootstrap fetch finds nothing and the empty orphan is minted — the + // expected fallback for a brand-new checkpoint remote. + cloneB := cloneFromBareWithHTTPS(t, env, mainBare, httpsURL) + cloneB.ExtraEnv = srv.sslEnv() + cloneB.PatchSettings(checkpointRemoteSettings) + cloneB.RunCLI("enable", "--agent", "claude-code", "--telemetry=false") + if !cloneB.BranchExists(paths.MetadataBranchName) { + t.Fatal("precondition: enable should mint a local metadata branch") + } + + // Device A: create a checkpoint and push it to the checkpoint remote. + cloneA := cloneFromBareWithHTTPS(t, env, mainBare, httpsURL) + cloneA.ExtraEnv = srv.tokenEnv("clone-a-token") + cloneA.GitCheckoutNewBranch("feature/clone-a") + cloneA.PatchSettings(checkpointRemoteSettings) + checkpointA := createCheckpointedCommit(t, cloneA, "Work in clone A", "a.go", "package a", "Work from A") + cloneA.RunPrePush("origin") + if !cloneA.BranchExistsOnRemote(checkpointBare, paths.MetadataBranchName) { + t.Fatal("precondition: checkpoint branch should be on checkpoint remote after push") + } + + // Device B: re-running enable must recover — the empty orphan must not + // permanently block the checkpoint-remote bootstrap. + cloneB.RunCLI("enable", "--agent", "claude-code", "--telemetry=false") + + remoteTip := revParse(t, checkpointBare, "refs/heads/"+paths.MetadataBranchName) + localTip := revParse(t, cloneB.RepoDir, "refs/heads/"+paths.MetadataBranchName) + if localTip != remoteTip { + t.Errorf("local metadata branch tip = %s, want checkpoint remote tip %s (empty orphan blocked re-bootstrap)", localTip, remoteTip) + } + + summaryA := CheckpointSummaryPath(checkpointA) + if _, found := cloneB.ReadFileFromBranch(paths.MetadataBranchName, summaryA); !found { + t.Errorf("local metadata branch should contain checkpoint A summary at %s", summaryA) + } +} diff --git a/cmd/entire/cli/strategy/checkpoint_remote.go b/cmd/entire/cli/strategy/checkpoint_remote.go index 2c782fba7..ef961b24f 100644 --- a/cmd/entire/cli/strategy/checkpoint_remote.go +++ b/cmd/entire/cli/strategy/checkpoint_remote.go @@ -4,12 +4,14 @@ import ( "context" "fmt" "log/slog" + "os" "strings" "time" "github.com/entireio/cli/cmd/entire/cli/checkpoint" "github.com/entireio/cli/cmd/entire/cli/checkpoint/remote" "github.com/entireio/cli/cmd/entire/cli/logging" + "github.com/entireio/cli/cmd/entire/cli/paths" "github.com/entireio/cli/cmd/entire/cli/settings" "github.com/go-git/go-git/v6/plumbing" @@ -82,11 +84,12 @@ func resolvePushSettings(ctx context.Context, pushRemoteName string) pushSetting ps.checkpointURL = checkpointURL - // If the v1 checkpoint branch doesn't exist locally, try to fetch it from the URL. - // This is a one-time operation — once the branch exists locally, subsequent pushes - // skip the fetch entirely. Only fetch the metadata branch; trails are always pushed - // to the user's push remote, not the checkpoint remote. - if err := fetchMetadataBranchIfMissing(ctx, checkpointURL); err != nil { + // If the v1 checkpoint branch doesn't exist locally (or is only the empty + // bootstrap orphan), try to fetch it from the URL. Once the branch has + // checkpoint data, subsequent pushes skip the fetch entirely. Only fetch + // the metadata branch; trails are always pushed to the user's push + // remote, not the checkpoint remote. + if _, err := fetchMetadataBranchIfMissing(ctx, checkpointURL); err != nil { logging.Warn(ctx, "checkpoint-remote: failed to fetch metadata branch", slog.String("error", err.Error()), ) @@ -162,29 +165,82 @@ func fetchURLIntoTmpRef(ctx context.Context, remoteURL, srcRef, tmpRef, label st return fmt.Errorf("fetch %s from %s failed: %w", label, redactedURL, fetchErr) } -// fetchMetadataBranchIfMissing fetches the primary metadata ref from a URL only if it doesn't exist locally. -// This avoids network calls on every push — once the branch exists locally, this is a no-op. -// Fetch failures are silently swallowed (returns nil): the push will handle creating the -// branch on the remote. Only fatal errors (opening repo, creating local branch) are returned. -func fetchMetadataBranchIfMissing(ctx context.Context, remoteURL string) error { +// bootstrapMetadataFromCheckpointRemote populates the local metadata branch +// from the configured checkpoint_remote when it doesn't exist locally yet, +// or exists only as the empty orphan minted by a previous failed bootstrap. +// +// On a fresh clone of a repo whose checkpoints live in a separate repo, +// neither the local branch nor origin's remote-tracking ref exists — without +// this fetch, EnsureMetadataBranch would mint an unrelated empty orphan that +// hides existing checkpoints and rejects later fetches as non-fast-forward +// (issue #1374). Best-effort: on failure the caller falls back to orphan +// creation (the remote branch legitimately doesn't exist before the first +// push from any device). +func bootstrapMetadataFromCheckpointRemote(ctx context.Context) { + if !remote.Configured(ctx) { + return + } + checkpointURL, err := remote.FetchURL(ctx) + if err != nil { + logging.Warn(ctx, "checkpoint-remote: could not resolve fetch URL for metadata branch bootstrap", + slog.String("error", err.Error()), + ) + return + } + fetched, err := fetchMetadataBranchIfMissing(ctx, checkpointURL) + if err != nil { + logging.Warn(ctx, "checkpoint-remote: metadata branch bootstrap failed", + slog.String("error", err.Error()), + ) + return + } + if fetched { + fmt.Fprintf(os.Stderr, "✓ Created local branch '%s' from checkpoint remote\n", paths.MetadataBranchName) + } +} + +// fetchMetadataBranchIfMissing fetches the primary metadata ref from a URL +// only if it doesn't exist locally with real data. This avoids network calls +// on every push — once the branch has checkpoint data, this is a no-op. +// +// An empty bootstrap orphan does not count as existing: it means a previous +// bootstrap couldn't reach the checkpoint remote (no token, network down, +// branch not pushed yet) and EnsureSetup fell back to orphan creation — +// fetching again is the recovery path, and SafelyAdvanceLocalRef discards +// the no-op orphan commit during the promote. +// +// Returns true when the branch was actually fetched. Fetch failures are +// logged but swallowed (returns nil error): the remote branch legitimately +// doesn't exist before the first push from any device, and push will create +// it. Only failures to open the repository are returned. +func fetchMetadataBranchIfMissing(ctx context.Context, remoteURL string) (bool, error) { repo, err := OpenRepository(ctx) if err != nil { - return fmt.Errorf("failed to open repository: %w", err) + return false, fmt.Errorf("failed to open repository: %w", err) } defer repo.Close() - // Check if branch already exists locally - if so, nothing to do + // Skip the network call when the branch already has checkpoint data. refs := checkpoint.ResolveCommittedRefs(ctx) - if _, err := repo.Reference(refs.Primary, true); err == nil { - return nil // Branch exists locally, skip fetch - } - - // Branch doesn't exist locally - try to fetch it from the URL. - // Fetch failures are not fatal: push will create it on the remote when it succeeds. + if ref, refErr := repo.Reference(refs.Primary, true); refErr == nil { + empty, emptyErr := isEmptyMetadataBranch(repo, ref) + if emptyErr != nil || !empty { + return false, nil // Branch has data (or is unreadable) — skip fetch + } + // Empty bootstrap orphan — fall through and try the fetch again. + } + + // Branch is missing (or an empty orphan) — try to fetch it from the URL. + // Not fatal on failure, but log it: a silent swallow here made auth and + // network problems invisible while EnsureSetup fell back to minting an + // empty orphan. if err := FetchMetadataBranch(ctx, remoteURL); err != nil { - return nil + logging.Warn(ctx, "checkpoint-remote: metadata branch fetch failed, continuing without it", + slog.String("error", err.Error()), + ) + return false, nil } logging.Info(ctx, "checkpoint-remote: fetched metadata branch from URL") - return nil + return true, nil } diff --git a/cmd/entire/cli/strategy/checkpoint_remote_test.go b/cmd/entire/cli/strategy/checkpoint_remote_test.go index 8a55657ab..2e21cea68 100644 --- a/cmd/entire/cli/strategy/checkpoint_remote_test.go +++ b/cmd/entire/cli/strategy/checkpoint_remote_test.go @@ -109,49 +109,59 @@ func TestIsURL(t *testing.T) { } } -// Not parallel: uses t.Chdir() -func TestFetchBranchIfMissing_CreatesLocalFromRemote(t *testing.T) { +// createMetadataBranchWithData creates an entire/checkpoints/v1 orphan branch +// in repoDir containing fileName, then switches back to the original branch. +func createMetadataBranchWithData(t *testing.T, repoDir, fileName, content string) { + t.Helper() ctx := context.Background() - // Set up a "remote" repo with a branch - remoteDir := t.TempDir() - testutil.InitRepo(t, remoteDir) - testutil.WriteFile(t, remoteDir, "f.txt", "init") - testutil.GitAdd(t, remoteDir, "f.txt") - testutil.GitCommit(t, remoteDir, "init") - // Get the default branch name before switching branchCmd := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD") - branchCmd.Dir = remoteDir + branchCmd.Dir = repoDir branchCmd.Env = testutil.GitIsolatedEnv() branchOut, err := branchCmd.Output() require.NoError(t, err) defaultBranch := strings.TrimSpace(string(branchOut)) - // Create an orphan branch in the remote repo (simulating entire/checkpoints/v1) - cmd := exec.CommandContext(ctx, "git", "checkout", "--orphan", "entire/checkpoints/v1") - cmd.Dir = remoteDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) + runGit := func(args ...string) { + cmd := exec.CommandContext(ctx, "git", args...) + cmd.Dir = repoDir + cmd.Env = testutil.GitIsolatedEnv() + require.NoError(t, cmd.Run()) + } - cmd = exec.CommandContext(ctx, "git", "rm", "-rf", ".") - cmd.Dir = remoteDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) + runGit("checkout", "--orphan", "entire/checkpoints/v1") + runGit("rm", "-rf", ".") - testutil.WriteFile(t, remoteDir, "metadata.json", `{"test": true}`) - testutil.GitAdd(t, remoteDir, "metadata.json") + testutil.WriteFile(t, repoDir, fileName, content) + testutil.GitAdd(t, repoDir, fileName) - cmd = exec.CommandContext(ctx, "git", "-c", "commit.gpgsign=false", "commit", "-m", "checkpoint data") - cmd.Dir = remoteDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) + runGit("-c", "commit.gpgsign=false", "commit", "-m", "checkpoint data") + runGit("checkout", defaultBranch) +} - // Go back to the default branch - cmd = exec.CommandContext(ctx, "git", "checkout", defaultBranch) - cmd.Dir = remoteDir +// revParseRef resolves ref in repoDir to a commit hash. +func revParseRef(t *testing.T, repoDir, ref string) string { + t.Helper() + cmd := exec.CommandContext(context.Background(), "git", "rev-parse", ref) + cmd.Dir = repoDir cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) + out, err := cmd.Output() + require.NoError(t, err) + return strings.TrimSpace(string(out)) +} + +// Not parallel: uses t.Chdir() +func TestFetchBranchIfMissing_CreatesLocalFromRemote(t *testing.T) { + ctx := context.Background() + + // Set up a "remote" repo with a metadata branch containing data + remoteDir := t.TempDir() + testutil.InitRepo(t, remoteDir) + testutil.WriteFile(t, remoteDir, "f.txt", "init") + testutil.GitAdd(t, remoteDir, "f.txt") + testutil.GitCommit(t, remoteDir, "init") + createMetadataBranchWithData(t, remoteDir, "metadata.json", `{"test": true}`) // Set up local repo localDir := t.TempDir() @@ -166,7 +176,9 @@ func TestFetchBranchIfMissing_CreatesLocalFromRemote(t *testing.T) { assert.False(t, testutil.BranchExists(t, localDir, "entire/checkpoints/v1")) // Fetch using the remote dir as a URL (local path) - require.NoError(t, fetchMetadataBranchIfMissing(ctx, remoteDir)) + fetched, err := fetchMetadataBranchIfMissing(ctx, remoteDir) + require.NoError(t, err) + assert.True(t, fetched, "should report the branch was fetched") // Verify the branch now exists locally assert.True(t, testutil.BranchExists(t, localDir, "entire/checkpoints/v1")) @@ -176,51 +188,21 @@ func TestFetchBranchIfMissing_CreatesLocalFromRemote(t *testing.T) { func TestFetchBranchIfMissing_NoOpWhenBranchExistsLocally(t *testing.T) { ctx := context.Background() - // Set up local repo with the branch already existing + // Set up local repo with the branch already existing (with real data) localDir := t.TempDir() testutil.InitRepo(t, localDir) testutil.WriteFile(t, localDir, "f.txt", "init") testutil.GitAdd(t, localDir, "f.txt") testutil.GitCommit(t, localDir, "init") - - // Get the default branch name before switching - branchCmd := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD") - branchCmd.Dir = localDir - branchCmd.Env = testutil.GitIsolatedEnv() - branchOut, err := branchCmd.Output() - require.NoError(t, err) - defaultBranch := strings.TrimSpace(string(branchOut)) - - // Create the branch locally - cmd := exec.CommandContext(ctx, "git", "checkout", "--orphan", "entire/checkpoints/v1") - cmd.Dir = localDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) - - cmd = exec.CommandContext(ctx, "git", "rm", "-rf", ".") - cmd.Dir = localDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) - - testutil.WriteFile(t, localDir, "data.json", `{"local": true}`) - testutil.GitAdd(t, localDir, "data.json") - - cmd = exec.CommandContext(ctx, "git", "-c", "commit.gpgsign=false", "commit", "-m", "local checkpoint") - cmd.Dir = localDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) - - // Switch back to the default branch - cmd = exec.CommandContext(ctx, "git", "checkout", defaultBranch) - cmd.Dir = localDir - cmd.Env = testutil.GitIsolatedEnv() - require.NoError(t, cmd.Run()) + createMetadataBranchWithData(t, localDir, "data.json", `{"local": true}`) t.Chdir(localDir) // Should be a no-op since branch exists locally (no network call). // Use a nonexistent path — if it tried to fetch, it would fail. - require.NoError(t, fetchMetadataBranchIfMissing(ctx, "/nonexistent/repo.git")) + fetched, err := fetchMetadataBranchIfMissing(ctx, "/nonexistent/repo.git") + require.NoError(t, err) + assert.False(t, fetched, "should report no fetch happened") } // Not parallel: uses t.Chdir() @@ -243,13 +225,65 @@ func TestFetchBranchIfMissing_NoOpWhenBranchNotOnRemote(t *testing.T) { t.Chdir(localDir) - err := fetchMetadataBranchIfMissing(ctx, remoteDir) + fetched, err := fetchMetadataBranchIfMissing(ctx, remoteDir) require.NoError(t, err) + assert.False(t, fetched, "should report no fetch happened") // Branch should still not exist locally assert.False(t, testutil.BranchExists(t, localDir, "entire/checkpoints/v1")) } +// Not parallel: uses t.Chdir() +// +// A first `entire enable` whose checkpoint-remote fetch fails (no token, +// network down, remote branch not pushed yet) falls back to minting an empty +// local orphan. That orphan must not permanently close the bootstrap window: +// a later attempt with the remote reachable must still fetch the real branch +// and point the local ref at it. +func TestFetchBranchIfMissing_RecoversFromEmptyLocalOrphan(t *testing.T) { + ctx := context.Background() + + // Set up a "remote" repo with a metadata branch containing data + remoteDir := t.TempDir() + testutil.InitRepo(t, remoteDir) + testutil.WriteFile(t, remoteDir, "f.txt", "init") + testutil.GitAdd(t, remoteDir, "f.txt") + testutil.GitCommit(t, remoteDir, "init") + createMetadataBranchWithData(t, remoteDir, "metadata.json", `{"test": true}`) + + // Set up local repo + localDir := t.TempDir() + testutil.InitRepo(t, localDir) + testutil.WriteFile(t, localDir, "f.txt", "init") + testutil.GitAdd(t, localDir, "f.txt") + testutil.GitCommit(t, localDir, "init") + + t.Chdir(localDir) + + // Simulate the failed first bootstrap: the fetch is a no-op against an + // unreachable remote, then EnsureSetup falls through to + // EnsurePrimaryRef, which mints the empty orphan. + fetched, err := fetchMetadataBranchIfMissing(ctx, "/nonexistent/repo.git") + require.NoError(t, err) + require.False(t, fetched) + + repo, err := OpenRepository(ctx) + require.NoError(t, err) + defer repo.Close() + require.NoError(t, EnsurePrimaryRef(ctx, repo)) + require.True(t, testutil.BranchExists(t, localDir, "entire/checkpoints/v1")) + + // Retry with the remote reachable (e.g. a second `entire enable` after + // fixing auth, or after a teammate's first checkpoint push). + fetched, err = fetchMetadataBranchIfMissing(ctx, remoteDir) + require.NoError(t, err) + assert.True(t, fetched, "empty local orphan must not block the checkpoint-remote bootstrap") + + remoteTip := revParseRef(t, remoteDir, "refs/heads/entire/checkpoints/v1") + localTip := revParseRef(t, localDir, "refs/heads/entire/checkpoints/v1") + assert.Equal(t, remoteTip, localTip, "local metadata branch should match the checkpoint remote tip") +} + // Not parallel: uses t.Chdir() func TestResolvePushSettings_NoConfig(t *testing.T) { tmpDir := t.TempDir() diff --git a/cmd/entire/cli/strategy/common.go b/cmd/entire/cli/strategy/common.go index dab295d99..b10c9bec7 100644 --- a/cmd/entire/cli/strategy/common.go +++ b/cmd/entire/cli/strategy/common.go @@ -67,6 +67,14 @@ func EnsureSetup(ctx context.Context) error { return err } + // When checkpoints live in a separate checkpoint_remote repo, a fresh + // clone has neither the local metadata branch nor an origin + // remote-tracking ref. Fetch from the checkpoint remote before opening + // the repo handle below, so EnsureMetadataBranch doesn't mint an + // unrelated empty orphan (issue #1374) and the handle sees the fetched + // packfiles. + bootstrapMetadataFromCheckpointRemote(ctx) + // Ensure the entire/checkpoints/v1 orphan branch exists for permanent session storage repo, err := OpenRepository(ctx) if err != nil { @@ -453,6 +461,11 @@ func resolveAgentType(ctxAgentType types.AgentType, state *SessionState) types.A // Primary is in Push (i.e. origin tracks it) and the local ref is missing or // empty, creates/updates the local ref from origin's remote-tracking ref. // Otherwise creates an empty orphan. +// +// Note: this function only consults local refs. When a checkpoint_remote is +// configured, EnsureSetup fetches the metadata branch from it first (see +// bootstrapMetadataFromCheckpointRemote) so this function doesn't mint an +// unrelated empty orphan on a fresh clone. func EnsurePrimaryRef(ctx context.Context, repo *git.Repository) error { refs := checkpoint.ResolveCommittedRefs(ctx) primaryName := refs.Primary.Short()