From d79c9415930566deecfb1ee1bdaf47c2829d8700 Mon Sep 17 00:00:00 2001 From: A <258483684+la14-1@users.noreply.github.com> Date: Sun, 22 Feb 2026 09:28:12 -0800 Subject: [PATCH] feat: draft PR workflow + stale PR cleanup for agent teams (#1706) Agents now open draft PRs immediately after first commit and convert to non-draft when work is complete, enabling visibility into in-progress work. Security reviewer skips draft PRs. Stale drafts (7+ days) are auto-closed. Refactor pr-maintainer picks up stale non-draft PRs (3+ days). Co-authored-by: lab <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) --- .../discovery-team-prompt.txt | 17 +++++++++----- .claude/skills/setup-agent-team/refactor.sh | 22 ++++++++++++------- .claude/skills/setup-agent-team/security.sh | 15 ++++++++++--- CLAUDE.md | 8 +++++++ 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/.claude/skills/setup-agent-team/discovery-team-prompt.txt b/.claude/skills/setup-agent-team/discovery-team-prompt.txt index e5d59a56..5df46a9a 100644 --- a/.claude/skills/setup-agent-team/discovery-team-prompt.txt +++ b/.claude/skills/setup-agent-team/discovery-team-prompt.txt @@ -72,10 +72,13 @@ Complete within 45 minutes. At 35 min tell teammates to wrap up, at 40 min shutd ## No Self-Merge Rule -Teammates NEVER merge their own PRs. After creating a PR: -1. Self-review: `gh pr review NUMBER --repo OpenRouterTeam/spawn --comment --body "Self-review by AGENT-NAME: [summary]\n\n-- discovery/AGENT-NAME"` -2. Label: `gh pr edit NUMBER --repo OpenRouterTeam/spawn --add-label "needs-team-review"` -3. Leave open — merging is handled externally. +Teammates NEVER merge their own PRs. Use the draft-first workflow: +1. After first commit, open a draft PR: `gh pr create --draft --title "title" --body "body\n\n-- discovery/AGENT-NAME"` +2. Keep pushing commits as work progresses +3. When complete: `gh pr ready NUMBER` +4. Self-review: `gh pr review NUMBER --repo OpenRouterTeam/spawn --comment --body "Self-review by AGENT-NAME: [summary]\n\n-- discovery/AGENT-NAME"` +5. Label: `gh pr edit NUMBER --repo OpenRouterTeam/spawn --add-label "needs-team-review"` +6. Leave open — merging is handled externally. ## Phase 1: Check Upvote Thresholds (ALWAYS DO FIRST) @@ -189,8 +192,10 @@ Values: cloud-scout, agent-scout, issue-responder, implementer, team-lead. git fetch origin main git worktree add WORKTREE_BASE_PLACEHOLDER/BRANCH -b BRANCH origin/main cd WORKTREE_BASE_PLACEHOLDER/BRANCH -# ... work, commit, push ... -gh pr create --title "title" --body "body\n\n-- discovery/AGENT-NAME" +# ... first commit, push ... +gh pr create --draft --title "title" --body "body\n\n-- discovery/AGENT-NAME" +# ... keep pushing commits ... +gh pr ready NUMBER # when work is complete gh pr review NUMBER --comment --body "Self-review: [summary]\n\n-- discovery/AGENT-NAME" gh pr edit NUMBER --add-label "needs-team-review" git worktree remove WORKTREE_BASE_PLACEHOLDER/BRANCH diff --git a/.claude/skills/setup-agent-team/refactor.sh b/.claude/skills/setup-agent-team/refactor.sh index 5c70a2a1..acb90e21 100755 --- a/.claude/skills/setup-agent-team/refactor.sh +++ b/.claude/skills/setup-agent-team/refactor.sh @@ -180,9 +180,11 @@ Track lifecycle: "pending-review" → "under-review" → "in-progress". Check la 3. Post acknowledgment (ONLY if no `-- ` sign-off exists in any comment): `gh issue comment SPAWN_ISSUE_PLACEHOLDER --repo OpenRouterTeam/spawn --body "Thanks for flagging this! Looking into it now.\n\n-- refactor/issue-fixer"` 4. Create worktree: `git worktree add WORKTREE_BASE_PLACEHOLDER -b fix/issue-SPAWN_ISSUE_PLACEHOLDER origin/main` 5. Spawn issue-fixer + issue-tester -6. When fix is ready: push, create PR with `Fixes #SPAWN_ISSUE_PLACEHOLDER` in body, post update comment linking PR -7. Do NOT close the issue — `Fixes #SPAWN_ISSUE_PLACEHOLDER` auto-closes on merge -8. Clean up: `git worktree remove WORKTREE_BASE_PLACEHOLDER`, shutdown teammates +6. After first commit: push and open a draft PR immediately: `gh pr create --draft --title "fix: [desc]" --body "Fixes #SPAWN_ISSUE_PLACEHOLDER\n\n-- refactor/issue-fixer"` +7. Keep pushing commits to the same branch as work progresses +8. When fix is complete and tests pass: `gh pr ready NUMBER`, post update comment linking PR +9. Do NOT close the issue — `Fixes #SPAWN_ISSUE_PLACEHOLDER` auto-closes on merge +10. Clean up: `git worktree remove WORKTREE_BASE_PLACEHOLDER`, shutdown teammates ## Commit Markers @@ -343,7 +345,7 @@ Assign teammates to labeled issues first (no plan mode). Remaining teammates do 6. **pr-maintainer** (Sonnet) Role: Keep PRs healthy and mergeable. Do NOT review/approve/merge — security team handles that. - First: `gh pr list --repo OpenRouterTeam/spawn --state open --json number,title,headRefName,updatedAt,mergeable,reviewDecision` + First: `gh pr list --repo OpenRouterTeam/spawn --state open --json number,title,headRefName,updatedAt,mergeable,reviewDecision,isDraft` For EACH PR, fetch full context: ``` @@ -361,14 +363,16 @@ Assign teammates to labeled issues first (no plan mode). Remaining teammates do - **Failing checks**: investigate, fix if trivial, push. If non-trivial, comment. - **Approved + mergeable**: rebase, merge: `gh pr merge NUMBER --repo OpenRouterTeam/spawn --squash --delete-branch` - **Not yet reviewed**: leave alone — security team handles review. + - **Stale non-draft PRs (3+ days, no review)**: If a non-draft PR (\`isDraft\`=false) has \`updatedAt\` older than 3 days AND \`reviewDecision\` is empty (not yet reviewed), check it out in a worktree, continue the work (fix issues, update code, push), and comment: \`"Picked up stale PR — [what was done].\n\n-- refactor/pr-maintainer"\` NEVER review or approve PRs. But if already approved, DO merge. Only act on PRs that are: - **Approved + mergeable** → rebase and merge - **Have explicit review feedback** (changes requested) → address the feedback + - **Stale non-draft, not yet reviewed (3+ days)** → pick up and continue work - Leave unreviewed PRs alone. Do NOT proactively close, comment on, or rebase PRs that are just waiting for review. + Leave fresh unreviewed PRs alone. Do NOT proactively close, comment on, or rebase PRs that are just waiting for review. 6. **community-coordinator** (Sonnet) First: `gh issue list --repo OpenRouterTeam/spawn --state open --json number,title,body,labels,createdAt` @@ -400,7 +404,7 @@ Assign teammates to labeled issues first (no plan mode). Remaining teammates do ## Issue Fix Workflow 1. Community-coordinator: dedup check → label "under-review" → acknowledge → delegate → label "in-progress" -2. Fixing teammate: `git worktree add WORKTREE_BASE_PLACEHOLDER/fix/issue-NUMBER -b fix/issue-NUMBER origin/main` → fix → commit (with Agent: marker) → push → `gh pr create --body "Fixes #NUMBER\n\n-- refactor/AGENT-NAME"` → clean up worktree +2. Fixing teammate: `git worktree add WORKTREE_BASE_PLACEHOLDER/fix/issue-NUMBER -b fix/issue-NUMBER origin/main` → fix → first commit (with Agent: marker) → push → `gh pr create --draft --body "Fixes #NUMBER\n\n-- refactor/AGENT-NAME"` → keep pushing → `gh pr ready NUMBER` when done → clean up worktree 3. Community-coordinator: post PR link on issue. Do NOT close issue — auto-closes on merge. 4. NEVER close a PR without a comment. NEVER close an issue manually. @@ -416,8 +420,10 @@ Every teammate uses worktrees — never `git checkout -b` in the main repo. ```bash git worktree add WORKTREE_BASE_PLACEHOLDER/BRANCH -b BRANCH origin/main cd WORKTREE_BASE_PLACEHOLDER/BRANCH -# ... work, commit, push ... -gh pr create --title "title" --body "body\n\n-- refactor/AGENT-NAME" +# ... first commit, push ... +gh pr create --draft --title "title" --body "body\n\n-- refactor/AGENT-NAME" +# ... keep pushing commits ... +gh pr ready NUMBER # when work is complete git worktree remove WORKTREE_BASE_PLACEHOLDER/BRANCH ``` diff --git a/.claude/skills/setup-agent-team/security.sh b/.claude/skills/setup-agent-team/security.sh index 5e60af53..ca942394 100644 --- a/.claude/skills/setup-agent-team/security.sh +++ b/.claude/skills/setup-agent-team/security.sh @@ -209,7 +209,7 @@ Complete within 12 minutes. At 9 min wrap up, at 11 min shutdown, at 12 min forc ## Team Structure -1. **implementer** (Opus) — Identify target script (`.claude/skills/setup-agent-team/{team}.sh`), implement changes in worktree, update workflows if needed, run `bash -n`, create PR: `gh pr create --title "feat: [desc]" --body "Implements #ISSUE_NUM_PLACEHOLDER\n\n-- security/implementer"` +1. **implementer** (Opus) — Identify target script (`.claude/skills/setup-agent-team/{team}.sh`), implement changes in worktree, update workflows if needed, run `bash -n`. Open a draft PR immediately after first commit: `gh pr create --draft --title "feat: [desc]" --body "Implements #ISSUE_NUM_PLACEHOLDER\n\n-- security/implementer"`. Keep pushing commits. When complete: `gh pr ready NUMBER` 2. **reviewer** (Opus) — Wait for PR, review for security/correctness/macOS compat/consistency. Approve or request-changes. If approved, merge: `gh pr merge NUMBER --repo OpenRouterTeam/spawn --squash --delete-branch` ## Workflow @@ -356,9 +356,11 @@ cd REPO_ROOT_PLACEHOLDER && git worktree remove WORKTREE_BASE_PLACEHOLDER/pr-NUM ## Step 1 — Discover Open PRs -\`gh pr list --repo OpenRouterTeam/spawn --state open --json number,title,headRefName,updatedAt,mergeable\` +\`gh pr list --repo OpenRouterTeam/spawn --state open --json number,title,headRefName,updatedAt,mergeable,isDraft\` -If zero PRs, skip to Step 3. +**Skip draft PRs** — draft PRs are work-in-progress and not ready for security review. Only review PRs where \`isDraft\` is \`false\`. + +If zero non-draft PRs, skip to Step 3. ## Step 2 — Create Team and Spawn Reviewers @@ -432,6 +434,13 @@ Spawn **branch-cleaner** (model=sonnet): - For each non-main branch: if no open PR + stale >48h → \`git push origin --delete BRANCH\` - Report summary. +## Step 3.5 — Close Stale Draft PRs + +From the PR list in Step 1, for each draft PR (\`isDraft\`=true) with \`updatedAt\` older than 7 days: +\`\`\`bash +gh pr close NUMBER --repo OpenRouterTeam/spawn --delete-branch --comment "Closing stale draft PR (no updates for 7+ days). Re-open or create a new PR when ready to continue.\n\n-- security/pr-reviewer" +\`\`\` + ## Step 4 — Stale Issue Re-triage Spawn **issue-checker** (model=google/gemini-3-flash-preview): diff --git a/CLAUDE.md b/CLAUDE.md index 8d279f95..f15ea475 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -368,6 +368,14 @@ refactor.yml — GitHub Actions workflow that POSTs to the trigger server - If a PR can't be merged (conflicts, superseded, wrong approach), close it with `gh pr close {number} --comment "Reason"` - Never rebase main or use `--force` unless explicitly asked +### Draft PR Workflow (for autonomous agents) + +- **Commit early and often** — make small, incremental commits as you work +- **Push and open a draft PR immediately** — `gh pr create --draft` after your first commit +- **Keep working on the draft PR** — push additional commits to the same branch +- **Convert to non-draft when ready for review** — `gh pr ready NUMBER` +- Draft PRs that go stale (no updates for 1 week) will be auto-closed + ## After Each Change 1. `bash -n {file}` syntax check on all modified scripts