/resume broken for non-GitHub (ADO) and non-git sessions - GitHub-only repo gates
- Dominant language
- Shell
- Stars
- 11.2k
- Forks
- 1.9k
- Avg merge
- 14h 16m
- Merged PRs (30d)
- 6
Description
### Describe the bug
### Summary
`/resume` (and the remote-task → local handoff behind it) is effectively unusable for two
overlapping classes of session:
1. **Non-GitHub repos (e.g. Azure DevOps / ADO).** The resume git gates hard-code
GitHub and reject any repo whose host is not `github`.
2. **Non-git sessions.** A session created while the working directory was NOT a git
repository stores an empty/`'/'` repository and can never satisfy the picker's git gate.
Both funnel through the same root cause: **the resume/handoff code assumes the repository is
always GitHub-hosted.** Cross-machine sessions also can't be recovered, and `--connect`
silently starts an empty session instead of surfacing the problem.
### Environment
- GitHub Copilot CLI: **1.0.71-0** (still repros; originally filed against 1.0.69-0)
- OS: Windows 11
- Repro also relevant to earlier 1.0.6x per #3694
### Root cause (code-level, from the bundled `app.js`)
There are **two independent GitHub-only gates**. Stable string anchors are given so they can
be grepped across versions (minified identifiers are as of 1.0.71-0).
**Gate A — repo/branch match on the remote-steerable / repo-scoped path.**
```js
// function Dbr(...) — remote session → local
let m = r.hostType==="github" && r.repository===l, // r = your CURRENT checkout
f = !c || r.branch===c;
if(!m || !f){ ... throw new hF(y,w) } // hF.name = "ResumeRepoMismatchError"
```
`m` hard-codes `hostType==="github"`. For an ADO checkout (`hostType==="ado"`) `m` is **always
false**, so it always throws `ResumeRepoMismatchError` — surfaced as
`Repository mismatch …` / `--remote --resume must be run from … current checkout is …`.
**Gate B — the "Validating repository" step of the task → local handoff.**
```js
// handoff generator, step "validate-repo"
try { a = await this.handoffGitOperations.getRepositoryInfo(cwd); }
catch(f){ throw new Error(`Not in a git repository. Please navigate to your repository directory. ${Y(f)}`) }
```
`getRepositoryInfo` derives a **GitHub** `owner/name` from the git remotes:
```js
if(!o) throw new Error("Could not determine GitHub repository from git remotes");
```
ADO remotes yield no GitHub identity → it throws, and the handoff reports the two errors seen in
the UI:
```
Error: Not in a git repository. Please navigate to your repository directory.
Error: Failed to get repository info: Could not determine GitHub repository from git remotes
```
**Important:** every *other* step of the handoff is plain git and is ADO-safe —
`check-changes` (`git status`), `checkout-branch` (`git fetch origin ` + `git checkout`),
event replay, save. **Only the GitHub-name validation blocks it.** Softening Gate B lets an ADO
session complete the handoff and replay its full history (verified locally — see the workaround
comment below).
### The catch-22 for non-git sessions
A session created outside a git repo has an empty/`'/'` repository (upstream cause: #2655 —
cwd/branch/repository not persisted). The picker then enforces two mutually exclusive things:
1. Must be INSIDE a git repo, else `Error: Not in a git repository. …` (Gate B).
2. The repo must EQUAL the session's stored repo (`'/'`), else
`Error: Repository mismatch: You are in 'owner/name' but the remote session is for '/'.` (Gate A).
No directory satisfies both.
### Reproduction
ADO:
1. From an **ADO-cloned** repo, start a session, exit.
2. `copilot` → `/resume` → pick it → *"Validating repository" fails* with
"Not in a git repository / Could not determine GitHub repository from git remotes",
even though you ARE in the correct repo.
Non-git:
1. Run `copilot` in a NON-git folder, hold a conversation, exit.
2. From a git repo: `/resume` → "Repository mismatch … session is for '/'".
3. From a non-git folder: `/resume` → "Not in a git repository."
### Workarounds attempted (all fail without a patch)
- `copilot --resume=` → `No session, task, or name matched` when the session originated on
another machine (not in this machine's local store).
- `/resume` from a non-git dir → "Not in a git repository."
- `copilot --connect=` → bypasses the git gate BUT starts a brand-new empty session
(returns `NO-HISTORY`, emits a fresh `--resume=`); original transcript not recovered.
A **tested binary patch** that neutralizes Gate B (and Gate A) and restores ADO/non-git resume is
in the comment below.
### Impact
- **ADO / any non-GitHub host: remote sessions cannot be resumed locally at all.**
- Sessions created before a folder became a git repo are lost to `/resume`.
- Cross-machine continuation is broken.
- `--connect` failing silently (new empty session) hides the real problem.
### Suggested fixes
1. Don't require a **GitHub** identity to validate the working directory. When
`getRepositoryInfo` can't derive a GitHub `owner/name` (ADO, or no remote), fall back to the
remote session's own repository metadata and continue instead of throwing.
2. Gate A: treat `hostType!=="github"` (and empty/`'/'` repository) as "unscoped" and SKIP the
repository-match gate — allow resume from any directory, or match on the local git root rather
than a GitHub `owner/name`.
3. Don't hard-require a git repo to open the resume picker; git context should be optional
metadata, not a precondition.
4. When `--connect` can't attach to the requested session, error explicitly instead of spawning a
new empty session.
### Related finding (may deserve its own issue)
The `/resume` picker also **hides recent remote sessions** on Windows: `GET
/agents/tasks` returns them (paged `per_page=20`; the CLI fetches ~30), but
`enrichTasksWithDetails` drops any task whose native `shouldIncludeInSessionList` flag is false
(`if(!l.shouldIncludeInSessionList) continue;`). Result: sessions visible in the GitHub mobile
app don't appear in the CLI picker. Happy to split this out if preferred.
### Related issues
#3694 (repo-name mismatch, closed), #2655 (repo/cwd not persisted), #2446, #3671 (cloud-session
resume), #3908 (empty resume dir), #2836 (orphaned session folders), #1381 (rewind git gate),
#3931.
### Affected version
GitHub Copilot CLI: 1.0.71-0 (and 1.0.69-x)
### Expected behavior
Sessions on non-GitHub hosts (ADO) and non-git sessions should resume and replay their history.
Contributor guide
Research direction
Start by grepping the bundled app.js for the Gate A repository-match logic, the validate-repo handoff step, and getRepositoryInfo, then trace how /resume and --connect use those paths. Done means the stated ADO, non-git, and cross-machine resume scenarios are handled without losing session history, while failed --connect attempts report an explicit error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, github, javascript
- Domain
- cli, developer-experience
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100