Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 93 additions & 16 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,103 @@ guide for package-specific conventions and workflows.

# Pull requests

**Never push branches or commits to the upstream repo (github.com/NVIDIA/cuda-python).
Treat it as read-only.** All branch creation and pushes must go to the contributor's
personal fork. Before pushing, confirm which remote points to the contributor's
personal fork (not `upstream`) by running `git remote -v`, then push there
(`git push <personal-fork-remote> <branch>`). Open the PR from that fork with
`gh pr create`. Do not use `git push upstream` or any command that writes to
the `upstream` remote.

When creating pull requests with `gh pr create`, always assign at least one
label and a milestone. CI enforces this via the `pr-metadata-check` workflow
and will block PRs that are missing labels or a milestone. Use `--label` and
`--milestone` flags, for example:
Treat the canonical repository used as the pull-request base as read-only by
default. Push branches and commits to an approved fork, which may be owned by
Comment on lines +17 to +18

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Treat the canonical repository used as the pull-request base as read-only by
default. Push branches and commits to an approved fork, which may be owned by
Treat the canonical repository used as the pull-request base as read-only. Push branches and commits to an approved fork, which may be owned by

either a personal account or an organization.

Before pushing:

- Run `git remote -v` and resolve the complete `OWNER/REPOSITORY` names of the
base repository and intended fork.
- Confirm that the push target is a fork of the base repository and is not the
base repository itself. Compare complete repository names; the owner alone
is not sufficient to distinguish them.
- Push using the explicit fork remote and branch, for example
`git push <fork-remote> <branch>`.

Do not push to the canonical repository unless the user explicitly requests,
in the current conversation, a push to a specific branch in that repository.
Comment on lines +31 to +32

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This opens up a window for mistakes. What's wrong with saying "Never push to the canonical repository"? The user can always do it by hand anyway. None of us should be running with write access to the canonical repository in our local checkouts -- that's too dangerous.

This can be necessary, for example, to test workflows that run only for
upstream branches. Before such a push, verify the exact `OWNER/REPOSITORY`,
remote, and destination branch. Authorization to push a test branch does not
authorize pushing to a default or protected branch, creating tags,
force-pushing, or deleting branches; those actions require separate explicit
authorization.

Use `gh pr create` when it can identify the fork unambiguously. Always select

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if the agent can identify the fork unambiguously, it is free to create a PR? Certainly that's not what's intended, but 100% can imagine the agent doing the wrong thing here.

the base repository explicitly with `--repo <base-owner>/<base-repository>`.
When the head is an organization-owned fork that `gh pr create` cannot
identify, create the pull request through the GraphQL API. Follow the
applicable pull-request template when preparing the body because the API does
not populate the template automatically.

For the API fallback, resolve these values from the remotes and intended PR:

```
gh pr create --title "..." --body "..." --label "bug" --milestone "v1.0"
BASE_REPO="<base-owner>/<base-repository>"
BASE_BRANCH="<base-branch>"
BASE_REPO_ID="<base-repository-node-id>"
HEAD_REPO="<fork-owner>/<fork-repository>"
HEAD_REPO_ID="<fork-repository-node-id>"
HEAD_BRANCH="<head-branch>"
BODY_FILE="<path-to-pr-body>"
```

If you are unsure which label or milestone to use, check the existing labels
and milestones on the repository with `gh label list` and `gh api
repos/{owner}/{repo}/milestones --jq '.[].title'`, and pick the best match.
Obtain the node IDs with `gh api "repos/${BASE_REPO}" --jq '.node_id'` and
`gh api "repos/${HEAD_REPO}" --jq '.node_id'`. Then create the PR with
`headRepositoryId` to identify the organization-owned fork:

```
gh api graphql \
-f repositoryId="${BASE_REPO_ID}" \
-f headRepositoryId="${HEAD_REPO_ID}" \
-f baseRefName="${BASE_BRANCH}" \
-f headRefName="${HEAD_BRANCH}" \
-f title="<title>" \
-F body="@${BODY_FILE}" \
-F draft=false \
-f query='
mutation CreatePullRequest(
$repositoryId: ID!
$headRepositoryId: ID!
$baseRefName: String!
$headRefName: String!
$title: String!
$body: String!
$draft: Boolean!
) {
createPullRequest(input: {
repositoryId: $repositoryId
headRepositoryId: $headRepositoryId
baseRefName: $baseRefName
headRefName: $headRefName
title: $title
body: $body
draft: $draft
}) {
pullRequest { number url }
}
}' \
--jq '.data.createPullRequest.pullRequest'
```
Comment on lines +59 to +95

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rationale for including detailed information about the GraphQL API here? Certainly the agent has access to the docs, and I worry this would bitrot.


Use `-F draft=true` instead when a draft pull request is intended.

Every pull request must have at least one assignee, one label, and a milestone,
regardless of how it was created. CI enforces this via the
`pr-metadata-check` workflow. With `gh pr create`, use the `--assignee`,
`--label`, and `--milestone` flags. After the API fallback, use the returned PR
number with the base repository explicitly:

```
gh pr edit <pr-number> --repo "${BASE_REPO}" \
--add-assignee "<assignee>" --add-label "<label>" \
--milestone "<milestone>"
```

If you are unsure which label or milestone to use, inspect the base repository
with `gh label list --repo "${BASE_REPO}"` and `gh api
"repos/${BASE_REPO}/milestones" --jq '.[].title'`, then pick the best match.
Comment on lines +111 to +113

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you are unsure which label or milestone to use, inspect the base repository
with `gh label list --repo "${BASE_REPO}"` and `gh api
"repos/${BASE_REPO}/milestones" --jq '.[].title'`, then pick the best match.
If you are unsure which label or milestone to use, don't guess. Flag it for the user and have them fill it in.



# General
Expand Down
Loading