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) <noreply@anthropic.com>
This commit is contained in:
A 2026-02-22 09:28:12 -08:00 committed by GitHub
parent 21f7e7683f
commit d79c941593
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 45 additions and 17 deletions

View file

@ -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

View file

@ -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
```

View file

@ -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):

View file

@ -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