Spaces:
Running
Running
Jeremiah Lowin commited on
Update dedupe logic (#1460)
Browse files
.claude/commands/dedupe.md
CHANGED
|
@@ -11,27 +11,29 @@ To do this, follow these steps precisely:
|
|
| 11 |
|
| 12 |
2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue
|
| 13 |
|
| 14 |
-
3. Then, launch
|
| 15 |
|
| 16 |
4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed.
|
| 17 |
|
| 18 |
5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates)
|
| 19 |
|
| 20 |
Notes (be sure to tell this to your agents, too):
|
|
|
|
| 21 |
- Use `gh` to interact with Github, rather than web fetch
|
| 22 |
- Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.)
|
| 23 |
- Make a todo list first
|
| 24 |
- For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates):
|
| 25 |
|
| 26 |
---
|
| 27 |
-
|
| 28 |
Found 3 possible duplicate issues:
|
|
|
|
| 29 |
1. #123: Issue title here
|
| 30 |
2. #456: Another issue title
|
| 31 |
3. #789: Third issue title
|
| 32 |
|
| 33 |
This issue will be automatically closed as a duplicate in 3 days.
|
|
|
|
| 34 |
- If your issue is a duplicate, please close it and ๐ the existing issue instead
|
| 35 |
- To prevent auto-closure, add a comment or ๐ this comment
|
| 36 |
|
| 37 |
-
---
|
|
|
|
| 11 |
|
| 12 |
2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue
|
| 13 |
|
| 14 |
+
3. Then, launch 3 parallel agents to search Github for duplicates of this issue, using diverse keywords and search approaches, using the summary from #1
|
| 15 |
|
| 16 |
4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed.
|
| 17 |
|
| 18 |
5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates)
|
| 19 |
|
| 20 |
Notes (be sure to tell this to your agents, too):
|
| 21 |
+
|
| 22 |
- Use `gh` to interact with Github, rather than web fetch
|
| 23 |
- Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.)
|
| 24 |
- Make a todo list first
|
| 25 |
- For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates):
|
| 26 |
|
| 27 |
---
|
|
|
|
| 28 |
Found 3 possible duplicate issues:
|
| 29 |
+
|
| 30 |
1. #123: Issue title here
|
| 31 |
2. #456: Another issue title
|
| 32 |
3. #789: Third issue title
|
| 33 |
|
| 34 |
This issue will be automatically closed as a duplicate in 3 days.
|
| 35 |
+
|
| 36 |
- If your issue is a duplicate, please close it and ๐ the existing issue instead
|
| 37 |
- To prevent auto-closure, add a comment or ๐ this comment
|
| 38 |
|
| 39 |
+
---
|
.github/workflows/claude-dedupe-issues.yml
CHANGED
|
@@ -11,9 +11,9 @@ on:
|
|
| 11 |
type: string
|
| 12 |
|
| 13 |
jobs:
|
| 14 |
-
|
| 15 |
runs-on: ubuntu-latest
|
| 16 |
-
timeout-minutes:
|
| 17 |
permissions:
|
| 18 |
contents: read
|
| 19 |
issues: write
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
| 29 |
app-id: ${{ secrets.MARVIN_APP_ID }}
|
| 30 |
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
|
| 31 |
|
| 32 |
-
- name: Run Marvin
|
| 33 |
uses: anthropics/claude-code-base-action@beta
|
| 34 |
with:
|
| 35 |
prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
|
|
|
|
| 11 |
type: string
|
| 12 |
|
| 13 |
jobs:
|
| 14 |
+
marvin-dedupe-issues:
|
| 15 |
runs-on: ubuntu-latest
|
| 16 |
+
timeout-minutes: 10
|
| 17 |
permissions:
|
| 18 |
contents: read
|
| 19 |
issues: write
|
|
|
|
| 29 |
app-id: ${{ secrets.MARVIN_APP_ID }}
|
| 30 |
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
|
| 31 |
|
| 32 |
+
- name: Run Marvin dedupe command
|
| 33 |
uses: anthropics/claude-code-base-action@beta
|
| 34 |
with:
|
| 35 |
prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
|
.github/workflows/marvin.yml
CHANGED
|
@@ -39,7 +39,7 @@ jobs:
|
|
| 39 |
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
|
| 40 |
|
| 41 |
# Marvin Assistant
|
| 42 |
-
- name: Marvin
|
| 43 |
uses: anthropics/claude-code-action@beta
|
| 44 |
with:
|
| 45 |
github_token: ${{ steps.marvin-token.outputs.token }}
|
|
|
|
| 39 |
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
|
| 40 |
|
| 41 |
# Marvin Assistant
|
| 42 |
+
- name: Run Marvin
|
| 43 |
uses: anthropics/claude-code-action@beta
|
| 44 |
with:
|
| 45 |
github_token: ${{ steps.marvin-token.outputs.token }}
|
scripts/auto_close_duplicates.py
CHANGED
|
@@ -169,7 +169,7 @@ class GitHubClient:
|
|
| 169 |
return reactions
|
| 170 |
|
| 171 |
def close_issue(self, issue_number: int, comment: str) -> bool:
|
| 172 |
-
"""Close an issue with a comment."""
|
| 173 |
# First add the comment
|
| 174 |
comment_url = f"{self.base_url}/issues/{issue_number}/comments"
|
| 175 |
with httpx.Client() as client:
|
|
@@ -181,6 +181,16 @@ class GitHubClient:
|
|
| 181 |
print(f"Failed to add comment to issue #{issue_number}")
|
| 182 |
return False
|
| 183 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
# Then close the issue
|
| 185 |
issue_url = f"{self.base_url}/issues/{issue_number}"
|
| 186 |
with httpx.Client() as client:
|
|
@@ -194,11 +204,10 @@ class GitHubClient:
|
|
| 194 |
def find_duplicate_comment(comments: list[Comment]) -> Comment | None:
|
| 195 |
"""Find a bot comment marking the issue as duplicate."""
|
| 196 |
for comment in comments:
|
| 197 |
-
# Check for the specific duplicate message format
|
| 198 |
-
body_lower = comment.body.lower()
|
| 199 |
if (
|
| 200 |
-
|
| 201 |
-
and "
|
| 202 |
):
|
| 203 |
return comment
|
| 204 |
return None
|
|
|
|
| 169 |
return reactions
|
| 170 |
|
| 171 |
def close_issue(self, issue_number: int, comment: str) -> bool:
|
| 172 |
+
"""Close an issue with a comment and add duplicate label."""
|
| 173 |
# First add the comment
|
| 174 |
comment_url = f"{self.base_url}/issues/{issue_number}/comments"
|
| 175 |
with httpx.Client() as client:
|
|
|
|
| 181 |
print(f"Failed to add comment to issue #{issue_number}")
|
| 182 |
return False
|
| 183 |
|
| 184 |
+
# Add the duplicate label
|
| 185 |
+
labels_url = f"{self.base_url}/issues/{issue_number}/labels"
|
| 186 |
+
with httpx.Client() as client:
|
| 187 |
+
response = client.post(
|
| 188 |
+
labels_url, headers=self.headers, json={"labels": ["duplicate"]}
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
if response.status_code not in [200, 201]:
|
| 192 |
+
print(f"Failed to add duplicate label to issue #{issue_number}")
|
| 193 |
+
|
| 194 |
# Then close the issue
|
| 195 |
issue_url = f"{self.base_url}/issues/{issue_number}"
|
| 196 |
with httpx.Client() as client:
|
|
|
|
| 204 |
def find_duplicate_comment(comments: list[Comment]) -> Comment | None:
|
| 205 |
"""Find a bot comment marking the issue as duplicate."""
|
| 206 |
for comment in comments:
|
| 207 |
+
# Check for the specific duplicate message format from a bot
|
|
|
|
| 208 |
if (
|
| 209 |
+
comment.user_type == "Bot"
|
| 210 |
+
and "possible duplicate issues" in comment.body.lower()
|
| 211 |
):
|
| 212 |
return comment
|
| 213 |
return None
|