mcp: re-pointing origin after a repo transfer breaks the local-remote link with no recovery #726

Open
opened 2026-10-05 15:41:55 +00:00 by hexajon · 2 comments
Owner

I transferred a repo to a new org on the forge, then could not re-point the local clone's origin through the MCP tools without breaking the local-to-remote link. There is no sanctioned recovery, which is the real problem: a caller on the MCP surface should never be able to strand a clone.

What happens

  1. The repo is transferred (owner change) on the forge. The local clone still points at the old owner, so every madt_* write returns a 301 ("repo moved - update your remote").
  2. madt_remote_add is the only remote-wiring tool, and it REFUSES to re-point an existing origin: "remote 'origin' already exists - use 'git remote set-url'". So there is no MCP way to re-point in place.
  3. Following that guidance, origin is removed and re-added (git remote remove origin, then madt_remote_add). The re-added origin reports "per-repo credentials configured", but the clone can no longer fetch: madt_fetch reports "already up to date" and never populates refs/remotes/origin/*; madt_pull fails with "no upstream branch configured"; after setting the upstream by hand, origin/main still does not resolve. The local fetch refspec is correct (+refs/heads/*:refs/remotes/origin/*), so this is not a refspec problem.
  4. There is no way back through the MCP tools: madt_remote_add refuses the existing origin, madt_fetch/madt_pull no-op, and raw git fetch or a credentialed git remote set-url are blocked by the credential-safety hooks. The clone is stranded behind the remote.

Why this matters

A routine transfer-then-re-point must never leave a clone unable to sync, and a caller working only through the sanctioned surface must never be able to break the local-to-remote link with no recovery. Today it can, and the only exit is a raw-git command that the guards themselves block.

Ask

  • A typed re-point / repair: let madt_remote_add (or a new madt_remote_set) re-point an existing origin, preserving a working fetch refspec and remote-tracking, so no remove-and-re-add is needed.
  • Detect a moved repo (the 301 on write) and reconcile the remote in one call.
  • Ensure madt_fetch populates refs/remotes/origin/* for a freshly re-pointed origin; today it reports "already up to date" and populates nothing.
  • The guard set must never leave the only recovery path as a raw-git command the same guards block.
I transferred a repo to a new org on the forge, then could not re-point the local clone's origin through the MCP tools without breaking the local-to-remote link. There is no sanctioned recovery, which is the real problem: a caller on the MCP surface should never be able to strand a clone. ## What happens 1. The repo is transferred (owner change) on the forge. The local clone still points at the old owner, so every madt_* write returns a 301 ("repo moved - update your remote"). 2. `madt_remote_add` is the only remote-wiring tool, and it REFUSES to re-point an existing origin: "remote 'origin' already exists - use 'git remote set-url'". So there is no MCP way to re-point in place. 3. Following that guidance, origin is removed and re-added (`git remote remove origin`, then `madt_remote_add`). The re-added origin reports "per-repo credentials configured", but the clone can no longer fetch: `madt_fetch` reports "already up to date" and never populates `refs/remotes/origin/*`; `madt_pull` fails with "no upstream branch configured"; after setting the upstream by hand, `origin/main` still does not resolve. The local fetch refspec is correct (`+refs/heads/*:refs/remotes/origin/*`), so this is not a refspec problem. 4. There is no way back through the MCP tools: `madt_remote_add` refuses the existing origin, `madt_fetch`/`madt_pull` no-op, and raw `git fetch` or a credentialed `git remote set-url` are blocked by the credential-safety hooks. The clone is stranded behind the remote. ## Why this matters A routine transfer-then-re-point must never leave a clone unable to sync, and a caller working only through the sanctioned surface must never be able to break the local-to-remote link with no recovery. Today it can, and the only exit is a raw-git command that the guards themselves block. ## Ask - A typed re-point / repair: let `madt_remote_add` (or a new `madt_remote_set`) re-point an existing origin, preserving a working fetch refspec and remote-tracking, so no remove-and-re-add is needed. - Detect a moved repo (the 301 on write) and reconcile the remote in one call. - Ensure `madt_fetch` populates `refs/remotes/origin/*` for a freshly re-pointed origin; today it reports "already up to date" and populates nothing. - The guard set must never leave the only recovery path as a raw-git command the same guards block.
Author
Owner

Update: the clone recovered with a plain madtea pull (CLI), which fast-forwarded the 4 missing commits. The MCP path did not: on the same clone, madt_fetch reported "already up to date" and populated no tracking refs, and madt_pull failed with "no upstream". So the broken part is the MCP fetch/pull path for a re-pointed origin, not the clone or its refspec - the CLI fetch/pull works on it. That narrows the fix: make madt_fetch/madt_pull match the CLI for a freshly re-pointed origin.

Update: the clone recovered with a plain `madtea pull` (CLI), which fast-forwarded the 4 missing commits. The MCP path did not: on the same clone, `madt_fetch` reported "already up to date" and populated no tracking refs, and `madt_pull` failed with "no upstream". So the broken part is the MCP fetch/pull path for a re-pointed origin, not the clone or its refspec - the CLI fetch/pull works on it. That narrows the fix: make `madt_fetch`/`madt_pull` match the CLI for a freshly re-pointed origin.
Author
Owner

Full reproduction trail, so the detail is not lost:

  1. madt_finish merged the branch on the forge both times (the "this merge landed UNGUARDED" warning fired), but then printed "failed to return to main: exit status 1" and left the local checkout on the old main with the branch's committed changes reverted in the working tree. So a madt_finish whose clone cannot sync merges remotely yet half-fails locally, silently, twice in a row.
  2. Re-pointing origin: madt_remote_add refused ("remote 'origin' already exists - use 'git remote set-url'"), so origin was removed and re-added; the re-add reported "Per-repo credentials configured".
  3. madt_fetch then reported "Already up to date - origin" repeatedly and created no refs/remotes/origin/*.
  4. madt_pull failed with "no upstream branch configured". Setting the upstream by hand (git branch --set-upstream-to=origin/main main) succeeded, but origin/main still did not resolve ("fatal: Needed a single revision").
  5. The local fetch refspec was already correct: git config --get-all remote.origin.fetch returned +refs/heads/:refs/remotes/origin/. So the MCP no-op is not a missing or wrong refspec.
  6. Recovery: a plain CLI madtea pull fast-forwarded the 4 missing commits cleanly; the MCP madt_fetch/madt_pull never did on that same clone.

So two distinct defects: (a) madt_remote_add cannot re-point an existing origin; (b) after a remove-and-re-add, the MCP madt_fetch/madt_pull path neither populates tracking refs nor fast-forwards, though the CLI path does and the refspec is correct. Separately, madt_finish should not report a landed merge while failing to leave the local checkout on an updated main.

Full reproduction trail, so the detail is not lost: 1. `madt_finish` merged the branch on the forge both times (the "this merge landed UNGUARDED" warning fired), but then printed "failed to return to main: exit status 1" and left the local checkout on the old main with the branch's committed changes reverted in the working tree. So a `madt_finish` whose clone cannot sync merges remotely yet half-fails locally, silently, twice in a row. 2. Re-pointing origin: `madt_remote_add` refused ("remote 'origin' already exists - use 'git remote set-url'"), so origin was removed and re-added; the re-add reported "Per-repo credentials configured". 3. `madt_fetch` then reported "Already up to date - origin" repeatedly and created no refs/remotes/origin/*. 4. `madt_pull` failed with "no upstream branch configured". Setting the upstream by hand (git branch --set-upstream-to=origin/main main) succeeded, but origin/main still did not resolve ("fatal: Needed a single revision"). 5. The local fetch refspec was already correct: git config --get-all remote.origin.fetch returned +refs/heads/*:refs/remotes/origin/*. So the MCP no-op is not a missing or wrong refspec. 6. Recovery: a plain CLI `madtea pull` fast-forwarded the 4 missing commits cleanly; the MCP `madt_fetch`/`madt_pull` never did on that same clone. So two distinct defects: (a) `madt_remote_add` cannot re-point an existing origin; (b) after a remove-and-re-add, the MCP `madt_fetch`/`madt_pull` path neither populates tracking refs nor fast-forwards, though the CLI path does and the refspec is correct. Separately, `madt_finish` should not report a landed merge while failing to leave the local checkout on an updated main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#726
No description provided.