Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
adf2c7b
Add issue duplicate automation workflow
enyst Apr 21, 2026
f140353
chore: verify PR review synchronize trigger
enyst Apr 21, 2026
9ecb6ff
chore: address PR review feedback (#2909)
enyst Apr 21, 2026
c604d38
chore: stop auto-review on every PR push
enyst Apr 21, 2026
ef21d98
chore: address second round of PR feedback (#2909)
enyst Apr 21, 2026
c6f9660
chore: use agent final response endpoint for duplicate checks (#2909)
enyst Apr 21, 2026
f7b3065
chore: harden duplicate auto-close comment handling (#2909)
enyst Apr 21, 2026
b48b7ce
chore: address remaining duplicate automation review feedback (#2909)
enyst Apr 21, 2026
7954a8c
chore: address follow-up duplicate automation review comments (#2909)
enyst Apr 21, 2026
68cf508
test: fix malformed issue data cross-test isolation (#2909)
enyst Apr 21, 2026
3a40ec3
fix: harden duplicate automation edge cases (#2909)
enyst Apr 21, 2026
53ba891
test: cover duplicate automation failure paths (#2909)
enyst Apr 21, 2026
60665d0
fix: harden duplicate workflow operations (#2909)
enyst Apr 21, 2026
5d8a1cf
fix: close duplicate automation review gaps (#2909)
enyst Apr 21, 2026
5cbe558
fix: harden duplicate check response handling (#2909)
openhands-agent Apr 22, 2026
096422d
chore: narrow duplicate checker smoke clone (#2909)
openhands-agent Apr 23, 2026
d029322
fix: keep duplicate workflow repo-local (#2909)
openhands-agent Apr 23, 2026
bd4cdf3
fix: redact duplicate-check debug payloads (#2909)
enyst Apr 24, 2026
47d216c
Fix duplicate automation review follow-ups
enyst Apr 24, 2026
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
468 changes: 468 additions & 0 deletions .github/workflows/issue-duplicate-checker.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/pr-review-by-openhands.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ jobs:
# picks up the sub-agent code (extensions#164 not yet on main)
extensions-version: feat/pr-review-sub-agent-delegation
llm-api-key: ${{ secrets.LLM_API_KEY }}
github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }}
github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC || github.token }}
lmnr-api-key: ${{ secrets.LMNR_SKILLS_API_KEY }}
64 changes: 64 additions & 0 deletions .github/workflows/remove-duplicate-candidate-label.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: Remove duplicate candidate label on activity

on:
issue_comment:
types: [created]

permissions:
issues: write

Comment thread
enyst marked this conversation as resolved.
concurrency:
group: remove-duplicate-${{ github.repository }}-${{ github.event.issue.number }}
cancel-in-progress: false

jobs:
remove-duplicate-candidate:
if: |
github.event.issue.state == 'open' &&
github.event.issue.pull_request == null &&
contains(github.event.issue.labels.*.name, 'duplicate-candidate') &&
Comment thread
enyst marked this conversation as resolved.
github.event.comment.user.type != 'Bot' &&
Comment thread
enyst marked this conversation as resolved.
Comment thread
enyst marked this conversation as resolved.
!startsWith(github.event.comment.body || '', '<!-- openhands-duplicate-check') &&
!startsWith(github.event.comment.body || '', '<!-- openhands-duplicate-veto')
runs-on: ubuntu-latest
steps:
- name: Remove duplicate-candidate label
uses: actions/github-script@v7
with:
github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC || github.token }}
script: |
const issueNumber = context.issue.number;
const commenter = context.payload.comment.user.login || '';
const normalizedCommenter = commenter.toLowerCase();

if (
normalizedCommenter.endsWith('[bot]') ||
normalizedCommenter === 'all-hands-bot'
) {
core.info(
`Skipping duplicate-candidate label removal for bot comment from ${commenter || 'unknown'}`
);
return;
}

core.info(
`Removing duplicate-candidate label from issue #${issueNumber} after comment from ${commenter}`
);

try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: 'duplicate-candidate',
});
} catch (error) {
if (error.status === 404) {
core.info(
`duplicate-candidate label was already removed from issue #${issueNumber}`
);
return;
}
throw error;
}
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ When reviewing code, provide constructive feedback:
- AgentSkills progressive disclosure goes through `AgentContext.get_system_message_suffix()` into `<available_skills>`, and `openhands.sdk.context.skills.to_prompt()` truncates each prompt description to 1024 characters because the AgentSkills specification caps `description` at 1-1024 characters.
- Workspace-wide uv resolver guardrails belong in the repository root `[tool.uv]` table. When `exclude-newer` is configured there, `uv lock` persists it into the root `uv.lock` `[options]` section as both an absolute cutoff and `exclude-newer-span`, and `uv sync --frozen` continues to use that locked workspace state.
- `pr-review-by-openhands` delegates to `OpenHands/extensions/plugins/pr-review@main`. Repo-specific reviewer instructions live in `.agents/skills/custom-codereview-guide.md`, and because task-trigger matching is substring-based, that `/codereview` skill is also auto-injected for the workflow's `/codereview-roasted` prompt.
- The duplicate-issue automation scripts should validate `owner/repo` arguments before interpolating GitHub API paths, handle per-issue auto-close failures without aborting the whole batch, and keep `app_conversation_id` paths unquoted because OpenHands conversation IDs are already canonicalized for those endpoints.
- Auto-title generation should not re-read `ConversationState.events` from a background task triggered by a freshly received `MessageEvent`; extract message text synchronously from the incoming event and then reuse shared title helpers (`extract_message_text`, `generate_title_from_message`) to avoid persistence-order races.


Expand Down
Loading
Loading