Skip to content

miner(repo-clone): a fresh clone never checks out baseBranch #9682

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

ensureRepoClonedUnlocked in packages/loopover-miner/lib/repo-clone.ts has two branches, and its own docstring (lines 301-304) says both must land on the base branch: "First use: git clone. Subsequent use: git fetch origin + hard-reset the base branch to origin/<baseBranch>, so every attempt branches off fresh content".

Fresh-clone branch:

const cloned = await runGit(["clone", cloneUrl, repoPath], cloneBaseDir, timeoutMs);
if (!cloned.ok) return { ok: false, repoPath, error: cloned.stderr || "git_clone_failed" };
return { ok: true, repoPath };

Existing-clone branch runs git checkout <baseBranch> then git reset --hard origin/<baseBranch>.

A plain git clone creates exactly one local branch — the origin's default HEAD. No local branch exists for any other base. The consumer, packages/loopover-miner/lib/attempt-worktree.ts:89, then calls addWorktree, which runs git worktree add -b <attemptBranch> <path> <baseBranch> (packages/loopover-engine/src/miner/worktree-plan.ts:80-84). With -b supplied, the trailing argument is a plain commit-ish that must resolve through normal rev-parse rules; a bare develop does not resolve from refs/remotes/origin/develop alone. So:

This is reachable in production: attempt-cli.ts:578 passes { baseBranch: parsed.base } — the PR's real base branch — and attempt-worktree.ts:88 hard-defaults to "main", which fails on the very first attempt against any master-default repo. The existing test is explicitly named "respects a non-default baseBranch on the fetch+reset path" (test/unit/miner-repo-clone.test.ts:112); the first-use path with a base other than the origin's HEAD is untested.

Requirements

  • After a successful git clone, the fresh-clone branch must run git checkout <baseBranch> in repoPath before returning { ok: true, repoPath }.
  • A failing checkout must return { ok: false, repoPath, error: checkedOut.stderr || "git_checkout_failed" } — the identical failure shape the existing-clone branch already returns at line 336.
  • The fresh-clone branch must NOT additionally run git fetch or git reset --hard (a just-cloned repo is already at origin's tip; adding them would change the command sequence the existing tests assert).
  • The isUnsafeGitArgValue(baseBranch) guard at line 317 must continue to run before any git invocation.

⚠️ Required pattern: reuse the existing-clone branch's own checkout call and error shape verbatim (packages/loopover-miner/lib/repo-clone.ts:335-336). It does NOT satisfy this issue to pass --branch <baseBranch> to git clone (that fails outright when the branch is not the default and produces a different, unmapped error), to change addWorktree in the engine to resolve origin/<baseBranch>, or to make attempt-worktree.ts retry on failure.

Deliverables

  • The fresh-clone branch in ensureRepoClonedUnlocked runs git checkout <baseBranch> after a successful clone and returns { ok: false, repoPath, error: ... || "git_checkout_failed" } on failure.
  • A new named regression test in test/unit/miner-repo-clone.test.ts asserts that, on the first-use path with baseBranch: "develop", the injected runGit receives ["checkout", "develop"] after ["clone", ...].
  • A second new case asserts a failing checkout on the fresh-clone path returns { ok: false, error: "git_checkout_failed" } (or git's stderr).
  • A third new case asserts the fresh-clone path does NOT invoke ["fetch", "origin"] or ["reset", "--hard", ...].

All Deliverables above are required in a single PR. A PR that satisfies only some of them — for example adding the checkout without the "no fetch/reset on the fresh path" assertion, which pins the exact command sequence — does not resolve this issue.

Test Coverage Requirements

packages/loopover-miner/lib/**/*.ts IS inside Codecov's coverage.include in vitest.config.ts, so the 99%+ branch-counted codecov/patch gate applies exactly as for src/**. Both arms of the new checkout result (ok / !ok) need a test, and the fix needs a named regression test that fails against the current code.

Expected Outcome

The very first attempt against a repo whose base branch is not the origin's default HEAD succeeds, instead of returning blocked_worktree_preparation_failed and only working from the second attempt onward.

Links & Resources

packages/loopover-miner/lib/repo-clone.ts:301-342, packages/loopover-miner/lib/attempt-worktree.ts:85-94, packages/loopover-engine/src/miner/worktree-plan.ts:73-88, test/unit/miner-repo-clone.test.ts:112.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions