Skip to content

Fix #81: treat assigned PRs as first-class work items#82

Merged
max-tet merged 1 commit into
mainfrom
clayde/issue-81
May 26, 2026
Merged

Fix #81: treat assigned PRs as first-class work items#82
max-tet merged 1 commit into
mainfrom
clayde/issue-81

Conversation

@ClaydeCode
Copy link
Copy Markdown
Owner

Summary

Closes #81.

Makes assignment the single signal for Clayde to work. Previously the poll loop only acted on assigned issues; a PR assigned directly to Clayde (with no parent issue) was never picked up. This PR adds a standalone-PR handler so Clayde can address review feedback on such PRs.

Changes

New: github.is_pull_request_item(item)

Checks html_url for /pull/ to distinguish PR items from issue items in the list returned by get_assigned_issues() (which already returns both, since GitHub models PRs as issues).

New: safety.filter_pr_reviews(reviews, github_username)

Returns only reviews authored by whitelisted users, excluding the bot's own reviews. Parallel to the existing filter_comments() gate for issue content.

New: tasks/pr_work.py + prompts/pr_work.j2

run(pr_url) fetches PR metadata + filtered reviews, invokes Claude with a focused "address this review" prompt, and posts a summary comment on the PR. State is keyed by PR URL in state.json (the same "issues" dict, since it already holds arbitrary URL keys).

Updated: orchestrator.py

  • _handle_standalone_pr(g, url) — mirrors _handle_issue() but operates on a PR URL; detects new whitelisted review activity, handles pure-approval, crash-recovery (in_progress), and usage-limit retry.
  • _is_pr_tracked_as_issue(pr_url, issues_state) — prevents double-handling: if a PR URL already appears as pr_url in any issue state entry (i.e. Clayde opened it for a tracked issue), the standalone handler skips it.
  • main() dispatch — iterates all assigned items, routes PR items to _handle_standalone_pr and issue items to _handle_issue as before.

Behaviour unchanged for issue flow

The existing plan → approval → implement → PR lifecycle is fully preserved. The _is_pr_tracked_as_issue guard ensures that PRs Clayde created for issues are never double-handled.

Tests

325 tests pass. New coverage:

  • test_github.pyis_pull_request_item
  • test_safety.pyfilter_pr_reviews
  • test_orchestrator.py_is_pr_tracked_as_issue, dispatch in main(), full _handle_standalone_pr suite (skip, invoke, first-time, pure-approval, crash-recovery, error-clearing, usage-limit)
  • tests/test_tasks_pr_work.py (new) — pr_work.run, _format_reviews

Recommended reading order

  1. src/clayde/github.pyis_pull_request_item (trivial helper)
  2. src/clayde/safety.pyfilter_pr_reviews
  3. src/clayde/prompts/pr_work.j2 — the new prompt
  4. src/clayde/tasks/pr_work.py — the new task
  5. src/clayde/orchestrator.py — dispatch logic, _handle_standalone_pr, _is_pr_tracked_as_issue

🤖 Generated with Claude Code

Add a standalone-PR handler so Clayde can address review feedback on PRs
that were not created through the normal issue → plan → implement flow.

Changes:
- github.py: add is_pull_request_item() helper — checks html_url for /pull/
- safety.py: add filter_pr_reviews() — keeps only whitelisted-user reviews,
  excluding the bot's own
- tasks/pr_work.py: new task module; run(pr_url) fetches PR context, filters
  reviews by whitelist, invokes Claude, posts summary comment
- prompts/pr_work.j2: new Jinja2 template for PR review work
- orchestrator.py:
  - _handle_standalone_pr() — mirrors _handle_issue() but keyed by PR URL;
    checks for new whitelisted review activity and invokes pr_work.run()
  - _is_pr_tracked_as_issue() — guards against double-handling a PR that was
    opened by Clayde for a tracked issue
  - main() dispatch — routes PR items to _handle_standalone_pr, issue items
    to _handle_issue as before
- Tests: full coverage for new functions across test_github.py,
  test_safety.py, test_orchestrator.py, and new test_tasks_pr_work.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@max-tet max-tet merged commit 9ba2dbc into main May 26, 2026
5 of 6 checks passed
@max-tet max-tet deleted the clayde/issue-81 branch May 26, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Treat assignment as the work signal — handle assigned PRs, not just issues

3 participants