docs(agents): respect assignments, and claim work before starting it - #3040
Conversation
Three PRs today duplicated work that was already claimed. The one that matters: issue #2951 was filed by an external contributor, assigned to them, and implemented in #2952 — and #2970 arrived fifteen hours later implementing the same thing. They objected, correctly. The cost is not the wasted effort. It is that someone who did everything right watched the project duplicate their work. The rule has three parts, and the third is the one that was missing: check assignees, check for an open PR referencing the issue, and assign yourself BEFORE writing code rather than when opening the PR. An assignment made at PR time claims nothing, because the window it needed to cover has already closed. Check again just before opening, since a claim can appear while you work. Also states who keeps the work when a duplicate happens: the person who was assigned, not whoever is further along. And that a duplicate is enumerated before it is closed, so what it uniquely holds is not lost.
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 37 minutes Limit details: You’ve used the included review currently available. Your 96 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_92e7c11b-4086-49ef-a3ab-9ae44f322387) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1503523c77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| 1. `gh issue view <n> --json assignees,title` — **if someone else is assigned, it is theirs.** Do not start. If you think it is stalled or you have context they lack, say so in a comment and let them answer. | ||
| 2. `gh pr list --search "<n>"` — an open PR referencing the issue is a claim even when nobody is assigned. | ||
| 3. If both are clear, `gh issue edit <n> --add-assignee <you>` **before** writing code, not when you open the PR. An assignment made at PR time claims nothing; the window it needed to cover has already closed. |
There was a problem hiding this comment.
Detect concurrent assignees immediately after claiming
When two agents start the same unassigned issue concurrently, both can pass the initial checks before either edit completes. The local gh issue edit --help describes --add-assignee as adding users, so both edits succeed and both agents proceed; the prescribed recheck occurs only after the duplicated implementation work is already done. Re-read the assignees immediately after the edit and require the claimant to be the sole assignee, or use another claim operation that detects this race.
AGENTS.md reference: AGENTS.md:L176-L180
Useful? React with 👍 / 👎.
| Before touching an issue: | ||
|
|
||
| 1. `gh issue view <n> --json assignees,title` — **if someone else is assigned, it is theirs.** Do not start. If you think it is stalled or you have context they lack, say so in a comment and let them answer. | ||
| 2. `gh pr list --search "<n>"` — an open PR referencing the issue is a claim even when nobody is assigned. |
There was a problem hiding this comment.
Search for an exact issue reference
For a common issue number or one that also appears as a version, count, or unrelated identifier, gh pr list --search "<n>" performs a general search rather than resolving PR-to-issue links. As gh pr list --help documents, this is a search query with a default 30-result limit, and its default output does not expose the matching text or linked issues; agents can therefore treat an unrelated hit as a claim or miss the real claim outside the capped results. Use structured link fields or require inspection of exact #<n> references before deciding the issue is claimed.
AGENTS.md reference: AGENTS.md:L174-L177
Useful? React with 👍 / 👎.
The first version said "if someone else is assigned, it is theirs, do not start", which forbids the cases that are actually fine and gives no way to tell them apart from the case that is not. Two things make it help rather than a takeover: They accepted an offer. Comment saying what you would do and wait for a yes. Silence is not a yes. An assignee who is mid-development and reads "we have already built this in parallel" is being told, not asked, which is exactly what happened on #2670. It has genuinely gone quiet: no commits and no word for about a week, and even then comment first, wait a couple of days, and reassign explicitly rather than working in the shadows. Also lists what needs no permission at all, since the first version could be read as discouraging it: reviewing their PR, diagnosing a failing check and posting the cause, answering a question, reporting a defect in shipped code. And what is not help however good the code: a parallel implementation announced afterwards, an unraised branch duplicating their work, pushing to their branch, a competing PR. If you already built something before noticing, say so, hand it over, and let them decide. That is recoverable. Landing it is not. Applies to us as much as to any bot.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a0f10904-7639-4db2-bbce-fd73f4bb25c4) |
|
Ran the CodeRabbit CLI against this branch, since the check on the PR is a false green (its comment is the "Review limit reached" notice, so no hosted review ran). One finding, and I am rejecting it. Finding: change "announcing it afterwards" to "afterward", to match the repository's American English style. Rejected: the premise is wrong. This repo's prose is British English, and the specific word already favours the form I used, 5 to 1: (counts over
Changing this one instance would move it away from the surrounding convention rather than toward it, so nothing to do here. Not a criticism of the tool: American English is the safer default guess for a repository it has not measured. It just happens to be measurable in this one, and the measurement disagrees. Everything else on this PR is green, with every code lane correctly skipping for a docs-only change. |
Two clauses #3040 was missing, one of which I initially justified with the wrong incident and am recording correctly here. FIRST: a shared account cannot express a claim. Every one of our agents pushes and assigns as the same GitHub account, so `--add-assignee` records "somebody claimed this" and cannot record who. An assignment to your own account is therefore a claim by someone else until shown otherwise, and a claim needs a comment naming the session. This applies to our sessions only; an outside contributor has their own account and the field says what it appears to say. SECOND, and this is what #3012 actually demonstrates: the contributor check and the session check are DIFFERENT checks, and doing one does not do the other. I first wrote this up as a session collision. It was not. The issue was self-assigned at 14:12:52 and a PR for the same issue appeared 47 minutes later FROM AN OUTSIDE CONTRIBUTOR, who has no reason to know about an internal assignment and for whom the repo's existing rules already apply. The session that self-assigned never ran `gh pr list --search 3012`, and no assignee field however precise would have helped, because no session held it. Only the PR search would have. THIRD: colliding mid-flight. #3040 covers noticing before you start and after you finish, and has nothing for both sides already half-built when the claim appears, which is settled today by whoever opens a PR first and so rewards speed over ownership. The assignee decides, the other stops immediately and hands over what it has. That clause was proposed by the session that lost the race, which deliberately did not add it itself. The same session then checked my attribution and found it wrong, which is the only reason this commit says "contributor" rather than "third session".
…nt (#3049) * docs(agents): the contributor check and the session check are different Two clauses #3040 was missing, one of which I initially justified with the wrong incident and am recording correctly here. FIRST: a shared account cannot express a claim. Every one of our agents pushes and assigns as the same GitHub account, so `--add-assignee` records "somebody claimed this" and cannot record who. An assignment to your own account is therefore a claim by someone else until shown otherwise, and a claim needs a comment naming the session. This applies to our sessions only; an outside contributor has their own account and the field says what it appears to say. SECOND, and this is what #3012 actually demonstrates: the contributor check and the session check are DIFFERENT checks, and doing one does not do the other. I first wrote this up as a session collision. It was not. The issue was self-assigned at 14:12:52 and a PR for the same issue appeared 47 minutes later FROM AN OUTSIDE CONTRIBUTOR, who has no reason to know about an internal assignment and for whom the repo's existing rules already apply. The session that self-assigned never ran `gh pr list --search 3012`, and no assignee field however precise would have helped, because no session held it. Only the PR search would have. THIRD: colliding mid-flight. #3040 covers noticing before you start and after you finish, and has nothing for both sides already half-built when the claim appears, which is settled today by whoever opens a PR first and so rewards speed over ownership. The assignee decides, the other stops immediately and hands over what it has. That clause was proposed by the session that lost the race, which deliberately did not add it itself. The same session then checked my attribution and found it wrong, which is the only reason this commit says "contributor" rather than "third session". * docs(agents): the claim comment decides, because the account cannot Two review findings, both correct, and the first is a hole in the rule this file just added. I wrote "the assignee decides" one section after explaining that the assignee field holds one shared account and cannot name a session. Those cannot both be true. The claim comment can name a session, which is the other half of why it is required, so the earliest claim comment decides and "ask on the issue" is the fallback when none exists. Also states that an outside contributor's PR takes precedence over any internal claim however early, since they cannot see our claims and are not bound by them. Second: I told people to run `gh pr list --search "<n>"` as if it established a link. It is a TEXT search over comment bodies, so it misses linked PRs that never mention the number and returns unrelated ones that happen to contain it. Now framed as a reason to look rather than an answer, with the issue's linked-PR list as authoritative. Rejected the third finding, MD046 on an indented command block: there is no markdownlint config, script or workflow step in this repo, and AGENTS.md contains no fenced blocks at all, so the suggestion would make this section inconsistent with the file rather than consistent with a linter that does not run.
@Blogbotana asked for this on #2951, in as many words:
They were right to ask, and they asked after it happened to them twice in two days. This writes it into
AGENTS.md, which is the file every agent and session in this repo is bound by.The rule
assigneesbefore starting. If someone else is assigned, it is theirs. Not "unless you are further along", not "unless it looks stalled". If you think it is stalled, say so in a comment and let them answer.Point 3 is the one that was actually missing. An assignment made at PR time claims nothing, because the window it needed to cover has already closed. The rule also says to check again immediately before opening, since a claim can appear while you work, and that check is cheap.
It also states who keeps the work when a duplicate does happen: the person who was assigned, not whoever is further along or noticed first. And that a duplicate gets its unique contents enumerated before it is closed, so nothing is silently lost.
Why it is written as a rule rather than a norm
Three PRs duplicated claimed work today. The one worth naming: #2951 was filed by an external contributor, assigned to them, and implemented in #2952 — and #2970 arrived fifteen hours later implementing the same thing.
The cost is not the wasted effort. It is that someone who did everything right watched the project duplicate their work, and then had to be the one to raise it.
I have also started assigning myself to issues I am actively working (#3028, #2684), which I was not doing before.
Amended after maintainer feedback
The first draft said "if someone else is assigned, it is theirs, do not start". That is too absolute: it forbids the cases that are genuinely fine and gives no way to tell them apart from the case that is not.
Two things make it help rather than a takeover:
It now also lists what needs no permission at all, because the first draft could be read as discouraging it: reviewing someone's PR including finding real defects, diagnosing a failing check and posting the cause, answering a question, reporting a defect in shipped code.
And what is not help however good the code: a parallel implementation announced afterwards, an unraised branch duplicating their work, pushing to their branch, a competing PR.
If you already built something before noticing, say so, hand it over, and let them decide whether to use it. That is recoverable. Landing it is not.
This binds us as much as any bot. I built the entire #2940 section-print fix without checking, and only found that #2960 already contained it because a review agent went looking. I did not land it, which is the only reason it was recoverable.