10 KiB
status, created, owner
| status | created | owner |
|---|---|---|
| approved | 2026-08-04 | product |
Remote Contribution Tasks
Why
Maintainers often need to help an external contributor finish a pull request or merge request. Today
they must manually reconstruct the target repository, contributor fork, head branch, and existing
review association before an agent can make a useful change. Kandev should accept the remote change
URL at task creation, prepare the contributor's exact branch, and push commits back to that branch
without making create_task_kandev materially larger.
What
- The existing
create_task_kandev.repositories[].repository_urlvalue accepts a canonical repository URL, GitHub pull request URL, or GitLab merge request URL. The tool adds no top-level or repository input properties; only the existing argument description changes. - Kandev recognizes
https://github.com/<owner>/<repo>/pull/<number>andhttps://<configured-gitlab-host>/<project>/-/merge_requests/<iid>. Query strings, fragments, embedded credentials, malformed paths, and unsupported providers are rejected. - The backend resolves the change through the workspace's provider identity. The caller cannot assert the source repository, head branch, head SHA, target branch, or collaboration permission.
- Only open changes with a live source branch are accepted. Kandev validates branch names as Git refs before invoking Git.
- The task remains attached to the target repository. A versioned, non-secret contribution binding on that task-repository attachment identifies the existing change and its source repository and branch.
- The prepared checkout starts at the provider-reported head SHA on the contributor's head branch.
origincontinues to mean the target repository; a dedicated contribution remote points at the source repository. Push operations for that attachment target the source branch without force. - A same-repository change uses the target remote for both read and write. A fork change is accepted only when the provider reports that maintainers may update the source branch.
- GitHub pull requests and GitLab merge requests are associated with the new task before agent launch, so existing review, CI, and watch surfaces treat the remote change as already existing and do not create a second pull or merge request.
- Provider title and body remain untrusted remote content. They are not copied into the task title, description, trusted system context, or initial prompt. The agent receives only structured, server-authored contribution identity and branch guidance.
- Ordinary repository URLs retain their current behavior, including default branch resolution,
normal
originpushes, and new-PR creation.
Decision: ADR-2026-08-04-remote-contribution-bindings.
Data model
The target task_repositories.metadata JSON object may contain remote_contribution:
{
"version": 1,
"provider": "github",
"kind": "pull_request",
"canonical_url": "https://github.com/acme/widget/pull/123",
"number": 123,
"state": "open",
"base_branch": "main",
"head_branch": "fix/widget",
"head_sha": "0123456789abcdef",
"source_repository": {
"host": "github.com",
"path": "contributor/widget",
"provider_id": "optional-provider-repository-id",
"remote_url": "https://github.com/contributor/widget.git"
},
"collaboration_allowed": true
}
provider is github or gitlab; kind is pull_request or merge_request; and number is the
GitHub PR number or GitLab project-scoped MR IID. The target repository is the attachment's existing
repository_id, not another copy inside the binding. source_repository.remote_url is canonical and
credential-free. The binding never stores access tokens, credential-helper state, lease IDs, provider
title/body, or other user-authored remote text.
The JSON field is versioned so later providers or collaboration attributes can be added without a database migration. Unknown versions fail closed during materialization and credential authorization.
API surface
The create_task_kandev input schema keeps the same property set. The existing field is documented as:
repository_url: Repository URL, GitHub pull request URL, or GitLab merge request URL.
The normal task response is unchanged. A provider-neutral internal resolver accepts the URL plus the resolved workspace, returns the target repository input and validated contribution binding, and exposes an association operation for the newly created task. Provider-specific API payloads do not cross that internal boundary.
Permissions
- Existing MCP authentication, workspace reachability, workflow, profile, and executor checks still apply.
- Provider reads use the workspace-scoped GitHub or GitLab automation identity. A private contribution is unavailable when that identity cannot read both the target change and source repository.
- In managed GitHub credential mode, the broker may issue a source-repository scope only when the exact
host and owner/repository match a validated
remote_contributionbinding on the session's linked task repository. The existing target-repository scope remains unchanged. - In executor credential mode, Kandev does not mint credentials. Runtime preparation performs a non-mutating push preflight with the executor's effective Git credentials before starting the agent.
- GitLab uses the configured workspace connection for provider validation and the existing executor credential policy for Git transport. Self-hosted MR URLs must match the configured origin exactly.
Failure modes
| Condition | Observable behavior |
|---|---|
| URL is malformed, credential-bearing, or unsupported | Task creation fails before persistence with an argument error. |
| Provider connection cannot read the change or source repository | Task creation fails before persistence with an authorization/not-found error that does not reveal cross-workspace data. |
| Change is closed, merged, or has no live head | Task creation fails before persistence and explains that only open contributions are supported. |
| Provider returns an invalid head/base ref or inconsistent target identity | Task creation fails closed before any Git command. |
| Fork does not allow maintainer collaboration | Task creation fails before persistence with provider-specific remediation guidance. |
| Task persists but the existing-change association fails | Kandev compensates the newly created task and returns failure; it does not launch an agent. |
| Checkout SHA no longer matches the source branch during preparation | Launch fails without checking out or pushing a different revision; retry resolves fresh provider state. |
| Effective Git credentials cannot dry-run a push to the source branch | The task remains durable, but the session does not start and exposes an actionable credential/collaboration error. |
| Contribution binding is missing, malformed, or an unknown version | Runtime preparation and managed source-scope issuance fail closed. |
| Agent attempts a normal create-PR action | Kandev reuses the existing association and does not open a second remote change. |
Persistence guarantees
The contribution binding and GitHub PR or GitLab MR association survive backend restarts. New and reset environments reconstruct the target checkout, contribution remote, upstream branch, and push routing from the binding. Credential leases and preflight results are ephemeral and are recomputed on each launch or resume. A moved or deleted source branch causes a later launch to fail visibly rather than silently falling back to the target repository.
Scenarios
Create from a same-repository GitHub pull request
GIVEN an open GitHub pull request whose source and target repository are the same
WHEN create_task_kandev receives its URL as repository_url
THEN Kandev creates a task on the target repository, checks out the exact head branch and SHA, links the
existing pull request, and pushes future commits to that head branch
Create from an editable GitHub fork pull request
GIVEN an open fork pull request whose author enabled maintainer edits
WHEN a maintainer creates a task from the pull request URL
THEN Kandev keeps origin on the target repository, configures the fork as the contribution remote,
authorizes only that validated source repository, and pushes normally to the contributor's head branch
Reject a non-editable GitHub fork pull request
GIVEN a fork pull request whose author disabled maintainer edits WHEN a maintainer creates a task from its URL THEN no task is created and the result explains that the contributor must allow maintainer edits
Create from an editable GitLab merge request
GIVEN an open merge request on the workspace's configured GitLab host whose source project permits
collaboration
WHEN create_task_kandev receives the merge request URL
THEN Kandev attaches the target project, checks out the source project branch, links the existing merge
request, and routes pushes to that source project
Reject stale provider state
GIVEN a contribution was resolved but its source branch moved before worktree preparation WHEN Kandev prepares the task THEN preparation fails rather than checking out the new head or pushing from the stale SHA
Preserve ordinary repository creation
GIVEN an ordinary GitHub, GitLab, or provider-neutral repository URL
WHEN it is passed as repository_url
THEN Kandev follows the existing repository task path without a contribution binding or source scope
Keep the MCP catalog compact
GIVEN the external MCP catalog before and after this feature
WHEN clients inspect create_task_kandev
THEN its input property names and count are unchanged and only the existing repository_url description
mentions pull and merge request URLs
Out of scope
- A new task-creation UI for pasting pull or merge request URLs.
- Creating tasks from issues, review comments, or arbitrary commit URLs.
- Azure DevOps or additional source-control providers.
- Multiple remote contributions in one create call.
- Force pushes, branch renames, retargeting, merging, or changing collaboration settings.
- Copying remote titles, bodies, comments, or diffs into trusted prompts.
- Guaranteeing write access after credentials or provider permissions change during a running session.