Summary
Make assignment the single signal for clayde to work. Today the loop only acts on assigned issues; a pull request assigned directly to clayde (with no parent issue) is never picked up, so review feedback on it is never addressed.
Reproduction
PR #80 ("feat: post-merge wrap-up") was opened by clayde on branch worktree-feat+post-merge-wrapup — outside the issue → plan → implement → PR flow. It has a CHANGES_REQUESTED review from max-tet (whitelisted) with two inline comments. Clayde never touches it: the poll loop runs fine every 5 min but only iterates the 4 assigned FreeshardBase issues. No state entry, no assigned issue → no code path to the PR.
Root cause
The loop is anchored entirely on assigned issues:
src/clayde/github.py — get_assigned_issues() drives everything; orchestrator.main() iterates only its result.
- A PR is reachable only as a child of a tracked issue:
_handle_issue() checks for review activity via issue_state["pr_url"] (src/clayde/orchestrator.py:114). State (src/clayde/state.py) is keyed by issue html_url; there is no concept of a standalone PR work item.
- Result: a PR assigned to clayde with no originating issue has no state, no parent, and is invisible to review handling.
Desired behavior
Assignment is the trigger, regardless of type:
- The loop fetches everything assigned to the bot — issues and PRs. (Note: GitHub models PRs as issues;
get_user().get_issues(filter="assigned") already returns PRs, each exposing a .pull_request attribute. Verify and branch on it rather than assuming.)
- For an assigned PR with no linked issue: clayde addresses new review activity (reviews + inline comments) on it directly — same behavior as the existing review path, just without requiring a parent issue. State is keyed by the PR url; track
last_seen_at / review ids the same way.
- Existing assigned-issue flow (plan → approval → implement → PR → review) is unchanged.
- Whitelist filtering still applies — only act on review content from whitelisted users, consistent with current
safety.py gating.
Acceptance criteria
- A PR assigned to clayde, not linked to any tracked issue, gets its
CHANGES_REQUESTED review addressed: clayde pushes commits to the PR branch and posts a summary comment.
- The assigned-issue lifecycle continues to work as before (no regression).
- PR work items persist in
state.json (keyed by PR url) so review activity is detected incrementally across ticks, not re-processed each cycle.
- Reviews authored by the bot itself are ignored (as today).
- Tests cover: assigned-PR-with-no-issue review handling, and the issue-vs-PR dispatch branch.
uv run pytest green.
Out of scope
Driving net-new implementation from a bare PR description (no review). This issue is about routing review feedback on assigned PRs. PR #80 is the concrete first target once this lands.
Summary
Make assignment the single signal for clayde to work. Today the loop only acts on assigned issues; a pull request assigned directly to clayde (with no parent issue) is never picked up, so review feedback on it is never addressed.
Reproduction
PR #80 ("feat: post-merge wrap-up") was opened by clayde on branch
worktree-feat+post-merge-wrapup— outside the issue → plan → implement → PR flow. It has aCHANGES_REQUESTEDreview frommax-tet(whitelisted) with two inline comments. Clayde never touches it: the poll loop runs fine every 5 min but only iterates the 4 assigned FreeshardBase issues. No state entry, no assigned issue → no code path to the PR.Root cause
The loop is anchored entirely on assigned issues:
src/clayde/github.py—get_assigned_issues()drives everything;orchestrator.main()iterates only its result._handle_issue()checks for review activity viaissue_state["pr_url"](src/clayde/orchestrator.py:114). State (src/clayde/state.py) is keyed by issue html_url; there is no concept of a standalone PR work item.Desired behavior
Assignment is the trigger, regardless of type:
get_user().get_issues(filter="assigned")already returns PRs, each exposing a.pull_requestattribute. Verify and branch on it rather than assuming.)last_seen_at/ review ids the same way.safety.pygating.Acceptance criteria
CHANGES_REQUESTEDreview addressed: clayde pushes commits to the PR branch and posts a summary comment.state.json(keyed by PR url) so review activity is detected incrementally across ticks, not re-processed each cycle.uv run pytestgreen.Out of scope
Driving net-new implementation from a bare PR description (no review). This issue is about routing review feedback on assigned PRs. PR #80 is the concrete first target once this lands.