Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Use T3 Code with a self-hosted Azure DevOps Server/TFS repository, e.g. https://scm.example.com/tfs/Collection/Project/_git/Repo.
- Ask the agent to call link_pull_request with https://scm.example.com/tfs/Collection/Project/_git/Repo/pullrequest/123.
- Observe the rejection.
- Follow the tool's suggested fallback: host=scm.example.com, repository=tfs/Collection/Project/_git/Repo, number=123.
- Inspect the URL returned by link_pull_request and list_thread_pull_requests.
Expected behavior
Recognize the distinctive /_git//pullrequest/ URL shape on self-hosted Azure DevOps Server domains and preserve the supplied web URL, including its collection path. If provider support is unavailable, report that explicitly instead of silently synthesizing a GitHub URL.
Actual behavior
The full Azure DevOps Server URL is rejected with: "This is not a recognised pull request URL. Pass repository and number instead."
The fallback accepts the identity but returns https://scm.example.com/tfs/collection/project/_git/repo/pull/123, which is not an Azure DevOps PR route.
Verified in installed nightly code: parseChangeRequestUrl in packages/shared/src/changeRequestUrl.ts gates Azure URLs on dev.azure.com / *.visualstudio.com. The same hostname restriction is still present in public main inspected on 2026-09-30. resolveTarget in apps/server/src/mcp/toolkits/pullRequests/handlers.ts falls back to /pull/ for an unknown provider. detectSourceControlProviderFromRemoteUrl also classifies the custom server domain as unknown.
Related but distinct: #5272 concerned cloud Azure SSH remotes; #7647 concerns repository identity mismatch for cloud Azure details; #14041 concerns browser fallback after list-loading errors. I did not find an existing report of this self-hosted URL parsing/fallback bug.
The workspace PR list was also empty, but our project was a non-Git parent directory containing multiple repositories, so that screenshot is not evidence that URL parsing alone caused the empty list. A linked PR and a discovered repository are separate paths.
Full native PR listing is a separate limitation: the Azure provider uses az repos pr / az devops invoke, while Microsoft's CLI documentation explicitly supports Azure DevOps Services only, not Azure DevOps Server (https://learn.microsoft.com/en-us/azure/devops/cli/). Merely relaxing URL/provider detection must not be presented as working Server listing/authentication.
Impact
Major degradation or frequent failure
Version or commit
0.0.45-nightly.20260930.2468
Environment
Windows 11, T3 Code desktop nightly, Codex provider; self-hosted Azure DevOps Server/TFS on a custom HTTPS domain.
Logs or stack traces
link_pull_request({url: 'https://scm.example.com/tfs/Collection/Project/_git/Repo/pullrequest/123'})
=> This is not a recognised pull request URL. Pass repository and number instead.
link_pull_request({host: 'scm.example.com', repository: 'tfs/Collection/Project/_git/Repo', number: 123})
=> url: https://scm.example.com/tfs/collection/project/_git/repo/pull/123
Examples anonymized; the behavior was reproduced against a real server.Screenshots, recordings, or supporting files
No response
Workaround
Open the original Azure DevOps URL in the browser. A local modification accepting the distinctive Azure URL path allowed the full URL to be registered and preserved after restart; this verified the link-only fix. It does not implement self-hosted provider authentication, PR listing, or status synchronization.
Activity
juliusmarminge commentedon Sep 30, 2026
Triage
I confirmed this on current
main. It's a link-parsing bug, and it isn't a duplicate of #5272 (closed issue, cloud Azure SSH remotes), #7647 (open issue, cloud Azure repository identity), or #14041 (open issue, browser fallback when PR listing fails).Why the full URL is rejected. In
packages/shared/src/changeRequestUrl.ts,parseChangeRequestUrlonly accepts the/_git/<repo>/pullrequest/<id>shape ondev.azure.comand*.visualstudio.com. A self-hosted URL likehttps://scm.example.com/tfs/Collection/Project/_git/Repo/pullrequest/123comes back as null, solink_pull_requestreturns "This is not a recognised pull request URL. Pass repository and number instead." GitLab's/-/merge_requests/path is already trusted on any host because that shape is distinctive./_git/.../pullrequest/<id>is just as distinctive, and the regex already captures the collection prefix (tfs/Collection/...). The hostname check is the only thing dropping Azure DevOps Server.Why the fallback stores a GitHub-style URL.
detectSourceControlProviderFromRemoteUrlinpackages/shared/src/sourceControl.tsclassifies a custom domain asunknown. That makeschangeRequestUrlForreturn null, soresolveTargetinapps/server/src/mcp/toolkits/pullRequests/handlers.tsfalls back tohttps://${host}/${repository}/pull/${number}. That's exactly the.../_git/repo/pull/123URL you saw. The/pull/fallback is deliberate for unrecognized hosts (it's covered inhandlers.test.ts), but it's the wrong route when the path is clearly an Azure pull request. When a URL does parse, the original URL is kept, which fits what you saw with your local patch surviving a restart.Scope of a fix. Recognizing that path and keeping the supplied URL fixes linking. It won't make listing, status, or auth work: the Azure provider goes through
az repos pr/az devops invoke, and Microsoft documents that CLI as Azure DevOps Services only. So relaxing the host check shouldn't be presented as on-prem PR sync support.Thanks for the careful write-up and for separating the linking bug from the listing limitation.