auto-issue-fixer
Automate the complete GitHub issue lifecycle. Fetches all issues, prioritizes by importance and execution speed, implements fixes using TDD, creates PRs, monitors for reviews, handles feedback autonomously, and notifies when complete. Uses extensive subagent parallelization for context efficiency.
When & Why to Use This Skill
The Auto Issue Fixer is an advanced autonomous Claude skill that automates the entire GitHub issue resolution lifecycle. It utilizes Test-Driven Development (TDD) and parallel subagent orchestration to prioritize tasks, implement code fixes, and manage the pull request process. By autonomously monitoring CI pipelines and addressing reviewer feedback—including comments from AI bots like Copilot—it significantly reduces manual engineering overhead and accelerates software delivery.
Use Cases
- Autonomous Bug Resolution: Automatically fetch and fix high-priority repository issues using a rigorous Red-Green-Refactor TDD workflow.
- End-to-End PR Management: Streamline the creation of pull requests and autonomously handle the feedback loop, including CI failure diagnosis and resolution.
- Backlog Prioritization: Analyze large volumes of GitHub issues to identify and execute 'quick wins' based on implementation speed and business importance.
- AI-Driven Code Maintenance: Reduce developer fatigue by delegating the handling of routine bot reviews and minor code change requests to an autonomous agent.
- Continuous Quality Enforcement: Ensure every code fix is verified against existing test suites and linting rules before it ever reaches a human reviewer.
| name | auto-issue-fixer |
|---|---|
| description | Automatically merge PR when complete (true/false, default false). If true, merges after all reviews addressed. If false, notifies user for manual merge. |
| - name | AUTO_MERGE |
| required | false |
Auto Issue Fixer
Fully autonomous GitHub issue lifecycle automation with TDD implementation.
Overview
Codex note: This skill references Claude Code subagents (Task(...)). In Codex, run the equivalent steps with tool calls (for example functions.shell_command and multi_tool_use.parallel) or run them sequentially. See ../../COMPATIBILITY.md.
This skill runs completely autonomously:
- Fetches and prioritizes all open issues
- Selects the highest-priority issue
- Implements the fix using TDD (Red-Green-Refactor)
- Creates a PR and requests review
- Monitors and addresses CI failures and review feedback
- Notifies the user when ready for final review
Workflow: PRs are created immediately to trigger CI and review requests. The skill monitors feedback and addresses it autonomously. When complete, it tags the user for final review and merge.
Status Output
IMPORTANT: Output clear status messages at each stage so the user can follow progress. Use this format:
================================================================================
AUTO-ISSUE-FIXER: [PHASE] - [ACTION]
================================================================================
Required Status Messages
Output these messages at each stage:
| Phase | Message |
|---|---|
| Start | AUTO-ISSUE-FIXER: STARTING - Fetching issues from repository |
| Issues found | AUTO-ISSUE-FIXER: FOUND {N} ISSUES - Analysing priorities... |
| Issue selected | AUTO-ISSUE-FIXER: SELECTED ISSUE #{N} - {title} |
| Sync | AUTO-ISSUE-FIXER: SYNCING - Pulling latest from origin/main |
| Planning | AUTO-ISSUE-FIXER: PLANNING - Creating TDD implementation plan |
| RED phase | AUTO-ISSUE-FIXER: TDD RED - Writing failing tests |
| GREEN phase | AUTO-ISSUE-FIXER: TDD GREEN - Implementing to pass tests |
| REFACTOR phase | AUTO-ISSUE-FIXER: TDD REFACTOR - Cleaning up implementation |
| PR created | AUTO-ISSUE-FIXER: PR CREATED - #{N} {url} |
| Monitoring | AUTO-ISSUE-FIXER: MONITORING - Waiting for CI and reviews |
| Bot wait | AUTO-ISSUE-FIXER: WAITING - Waiting for bot reviews (Copilot, Claude) |
| Feedback | AUTO-ISSUE-FIXER: FEEDBACK - Processing {N} items |
| Quiet period | AUTO-ISSUE-FIXER: VERIFYING - Quiet period check ({N} min remaining) |
| Complete | AUTO-ISSUE-FIXER: COMPLETE - PR #{N} ready for review |
| Merging | AUTO-ISSUE-FIXER: MERGING - Auto-merge enabled, merging PR #{N} |
| Merged | AUTO-ISSUE-FIXER: MERGED - PR #{N} merged successfully |
| No issues | AUTO-ISSUE-FIXER: NO ISSUES - No actionable issues found |
| Error | AUTO-ISSUE-FIXER: ERROR - {description} |
Phase 1: Issue Discovery and Prioritization
1.1 Fetch All Issues
scripts/list-all-issues.sh [--labels LABELS] [--exclude LABELS]
This fetches all open issues with metadata needed for prioritization.
1.2 Parallel Complexity Analysis
Launch Explore subagents in parallel (batches of 5 issues) to analyze implementation complexity:
Launch parallel Explore agents (one per batch):
"Analyze these GitHub issues for implementation complexity:
Issues: {batch_of_5_issues}
For each issue, evaluate:
1. Number of files likely affected (search codebase for keywords)
2. Presence of reproduction steps (clear = easier)
3. Clarity of expected outcome
4. Existing test coverage for affected areas
5. Similar past issues/PRs as reference
Return JSON:
{
"issues": [
{"number": N, "complexity_score": 0-100, "estimated_files": N, "has_repro": bool, "notes": "..."}
]
}"
1.3 Auto-Exclude Issues
Before scoring, automatically exclude issues that should not be processed:
| Condition | Reason | Detection |
|---|---|---|
| Has open linked PR | Already being worked on | has_linked_pr == true from script |
| Assigned to human | Someone is handling it | assignees contains non-bot users |
Label: auto-fixing |
Currently being processed | Label check |
Label: auto-fixed |
Already completed | Label check |
Label: wontfix |
Intentionally not fixing | Label check |
Label: duplicate |
Duplicate of another | Label check |
Label: blocked |
Blocked by dependency | Label check |
Label: on-hold |
Intentionally paused | Label check |
The list-all-issues.sh script detects linked PRs via GitHub's timeline API:
- Finds
CROSS_REFERENCED_EVENT(PR mentions issue) - Finds
CONNECTED_EVENT(PR explicitly linked) - Only counts OPEN PRs (closed/merged PRs don't block)
# Example output showing issue with linked PR
{
"number": 874,
"title": "Enforce capacity limit",
"has_linked_pr": true,
"linked_pr_count": 1,
"linked_prs": [879]
}
This issue would be SKIPPED - PR #879 is already addressing it.
1.4 Calculate Priority Scores
Combined Score Formula: (Importance * 0.6) + (Speed * 0.4)
Importance Score (0-100):
| Factor | Weight | Scoring |
|---|---|---|
| Labels | 30% | security: 95, priority-critical: 90, priority-high: 80, bug: 70, enhancement: 40 |
| Age | 20% | >30 days: 80, >14 days: 60, >7 days: 40, <7 days: 20 |
| Author | 15% | Maintainer: 80, Contributor: 60, External: 40 |
| Assignees | 10% | Unassigned: 70, Assigned to bot: 80, Assigned to human: 20 |
| Comments | 15% | >5: 70, 3-5: 50, 1-2: 30, 0: 20 |
| Milestone | 10% | Current: 90, Next: 60, None: 30 |
Speed Score (0-100) - From subagent analysis:
| Factor | Weight | Scoring |
|---|---|---|
| Description length | 20% | <200 chars: 80, 200-500: 60, 500-1000: 40, >1000: 20 |
| Files affected | 30% | 1 file: 90, 2-3: 70, 4-5: 40, >5: 20 |
| Complexity keywords | 25% | "typo/fix/update": 80, "add/change": 60, "refactor": 30, "rewrite/architecture": 10 |
| Has reproduction | 15% | Yes: 80, Partial: 50, No: 30 |
| Has suggested fix | 10% | Yes: 90, Partial: 60, No: 40 |
See references/prioritization-criteria.md for full scoring details.
1.5 Select Top Issue
Automatically select the issue with highest combined score. Output prioritization report:
## Issue Prioritization
| Rank | Issue | Title | Importance | Speed | Combined |
|------|-------|-------|------------|-------|----------|
| 1 | #123 | Fix null pointer | 75 | 85 | 79 |
| 2 | #456 | Add validation | 70 | 70 | 70 |
**Selected**: #123 - High importance AND quick to implement
Phase 2: Setup and Planning
2.1 Sync with Remote
Pull the latest changes before starting any work:
git fetch origin
git pull --rebase origin main
This ensures we're working with the latest codebase and avoids merge conflicts later.
2.2 Create Worktree
Use the existing worktree setup script:
../fix-github-issue/scripts/setup-worktree.sh $ISSUE_NUMBER
This creates an isolated worktree at .worktrees/issue-$ISSUE_NUMBER.
2.3 Mark Issue In Progress
Add a label to indicate work has started:
gh issue edit $ISSUE_NUMBER --add-label "auto-fixing"
This prevents other runs from picking up the same issue and signals to humans that automated work is underway.
2.4 Load Issue Context
../fix-github-issue/scripts/load-issue.sh $ISSUE_NUMBER
2.5 Create TDD Plan
Launch Explore subagent to create a TDD-specific implementation plan:
Launch Explore agent:
"Create a TDD implementation plan for issue #{number}: {title}
Issue details:
{issue_body}
Explore the codebase and return a plan with:
## Phase 1: RED - Failing Tests
List specific test cases to write first:
- Test file path
- Test function name
- What behavior it verifies
- Expected failure reason
## Phase 2: GREEN - Minimal Implementation
List minimal code changes to make tests pass:
- File path
- Function/method to modify
- Specific change description
## Phase 3: REFACTOR - Cleanup
List refactoring opportunities:
- DRY violations to fix
- Naming improvements
- Performance optimizations
## Verification Commands
Detect and list:
- Test command (npm test, pytest, go test, etc.)
- Lint command
- Build command
Return structured markdown using templates/tdd-plan.md format"
Phase 3: TDD Implementation
3.1 RED Phase - Write Failing Tests
- Create or update test file based on the TDD plan
- Write test cases that define expected behavior
- Run tests to verify they fail:
{TEST_COMMAND}
# Expected: FAIL (tests should fail before implementation)
Critical: If tests pass before implementation, the tests may not be testing the right behavior. Review and adjust test cases.
3.2 GREEN Phase - Minimal Implementation
- Write the minimum code to make tests pass
- Focus on correctness, not elegance
- Run tests after each change:
{TEST_COMMAND}
# Expected: PASS
3.3 REFACTOR Phase
- Clean up implementation while keeping tests green
- Apply DRY principles
- Improve naming and structure
- Final verification:
{TEST_COMMAND} && {LINT_COMMAND} && {BUILD_COMMAND}
3.4 Background Test Monitoring
Launch background subagent for continuous feedback:
Launch background agent:
"Monitor test and lint status continuously.
Run every 30 seconds:
- {TEST_COMMAND}
- {LINT_COMMAND}
Report immediately when:
- All tests pass (GREEN achieved)
- New test failures (regression detected)
- Lint errors introduced
Return: Status updates as work progresses"
Phase 4: Submit PR
4.1 Final Verification
Run all checks before committing:
{TEST_COMMAND} && {LINT_COMMAND} && {TYPECHECK_COMMAND} && {BUILD_COMMAND}
4.2 Commit Changes
git add -A
git commit -m "$(cat <<'EOF'
fix: [Brief description from issue title]
- [Change 1]
- [Change 2]
TDD Approach:
- Added [N] test cases for [scenario]
- Verified [edge case] handling
Closes #ISSUE_NUMBER
Co-Authored-By: Claude Code <noreply@anthropic.com>
EOF
)"
4.3 Create PR
git push -u origin HEAD
gh pr create --title "fix: [Brief description]" --body-file templates/pr-body.md
The PR is created immediately to trigger CI checks and allow reviewers to be notified.
4.4 Record PR Number
PR_NUMBER=$(gh pr view --json number -q '.number')
echo "Created PR #$PR_NUMBER"
Phase 5: Feedback Loop
This phase handles ALL PR feedback including CI failures, code reviews, inline comments, and general discussion. The skill must track and address each piece of feedback before marking the PR ready.
5.1 Fetch All Current Feedback
Before monitoring for changes, get the current state of all feedback:
scripts/fetch-pr-comments.sh $PR_NUMBER --json > /tmp/pr-feedback-state.json
This returns structured data including:
- Review threads (inline code comments with resolution status)
- Reviews (approve/request changes/comment with body text)
- General comments (discussion on the PR)
- Actionable items (items requiring response or code changes)
5.2 Launch Parallel Monitors
Start background agents to monitor for new feedback:
# Monitor for any new PR activity (reviews, threads, comments)
scripts/monitor-pr.sh $PR_NUMBER --timeout $REVIEW_TIMEOUT_MINUTES &
MONITOR_PID=$!
# Separately monitor CI status
scripts/wait-for-ci.sh $PR_NUMBER --timeout 15 &
CI_PID=$!
The monitor-pr.sh script detects:
THREAD_RECEIVED- New inline code review commentREVIEW_RECEIVED- New review (approve/request changes)COMMENT_RECEIVED- New general PR commentTHREAD_UNRESOLVED- Thread was re-openedMERGED/CLOSED/TIMEOUT
5.3 Handle CI Failures
When CI fails, diagnose and fix:
Launch Explore agent:
"CI has failed for PR #{pr_number}.
Failure logs:
{ci_failure_logs}
Current changes (git diff):
{diff_summary}
Diagnose:
1. Root cause of each failure
2. Specific code changes needed
3. Whether new tests are required
Return: Actionable fix plan with file paths and code changes"
Apply fixes, commit, and push:
git add -A
git commit -m "fix: Address CI failures
- [Fix 1]
- [Fix 2]"
git push
5.4 Categorize Review Feedback
When feedback arrives, categorize each item:
# Get all unresolved actionable items
scripts/fetch-pr-comments.sh $PR_NUMBER --unresolved-only --json
For each feedback item, classify it:
| Category | Detection | Action Required |
|---|---|---|
| Code Change Request | Keywords: "fix", "change", "update", "remove", "add", "please", "should", "must" | Modify code, reply, resolve thread |
| Question | Ends with "?", starts with "why", "how", "what", "could you" | Answer question, resolve thread |
| Suggestion (in scope) | "Consider", "maybe", "alternatively", "what about" + related to current change | Evaluate, implement or explain, resolve thread |
| Suggestion (out of scope) | Suggestion about unrelated code, broad refactoring | Thank, offer to create issue, resolve thread |
| Nitpick | "nit:", "minor:", style preferences | Apply if trivial, explain if not, resolve thread |
| Approval/Praise | "LGTM", "looks good", "nice", "approved" | Thank briefly, no code change needed |
| Concern/Blocker | "Blocking", "must fix", "security", "breaking" | Prioritize fixing, escalate if unclear |
5.5 Process Feedback with Subagents
Launch parallel agents to handle different feedback types:
Launch parallel Explore agents:
1. Code Changes Agent:
"Process these review comments that require code changes:
{code_change_items_json}
For each comment:
1. Understand what change is being requested
2. Locate the relevant code in the codebase
3. Apply the change (read file first, then edit)
4. Prepare a confirmation reply: 'Done: [brief description]'
Return JSON:
{
'changes': [{'file': 'path', 'description': 'what changed'}],
'replies': [{'thread_id': 'id', 'reply': 'text'}]
}"
2. Response Agent:
"Process these review comments that need responses only:
{response_items_json}
For each comment, draft appropriate reply:
- If QUESTION: Answer directly with context from codebase
- If SUGGESTION (out of scope): Thank, explain scope, offer to create issue
- If CONCERN: Explain the reasoning or acknowledge and fix
- If APPROVAL: Brief thanks
Return JSON:
{
'replies': [{'thread_id': 'id', 'reply': 'text', 'should_resolve': bool}]
}"
5.6 Reply to Threads and Resolve
Use the reply-to-thread.sh script to reply and optionally resolve in one step:
If code change was applied:
scripts/reply-to-thread.sh "$THREAD_ID" "Done - [description of fix]" --resolve
If declining the suggestion (with reason):
scripts/reply-to-thread.sh "$THREAD_ID" "Thanks for the suggestion. I kept the current approach because:
1. [Technical reason]
2. [Scope reason]
Happy to discuss further." --resolve
If answering a question:
scripts/reply-to-thread.sh "$THREAD_ID" "[Answer to the question]" --resolve
If need to discuss further (don't resolve):
scripts/reply-to-thread.sh "$THREAD_ID" "Good point. [Response]. What do you think?"
# Don't use --resolve - leave open for continued discussion
Post general PR comment (not a thread reply):
gh pr comment $PR_NUMBER -b "$COMMENT_TEXT"
5.7 Resolution Rules
ALWAYS reply before resolving - Never resolve without an explanation.
When to resolve (use --resolve flag):
- Code change was applied as requested → Reply "Done - [what changed]"
- Question was answered → Reply with answer
- Suggestion declined → Reply with reason why
- Nitpick addressed → Reply "Fixed" or "Left as-is because [reason]"
When NOT to resolve:
- Waiting for reviewer to confirm fix is acceptable
- Disagreement needs further discussion
- Reviewer explicitly asks to leave open
- Unsure if change is correct
Every thread must end with one of:
- Reply + Resolve (action taken or declined with reason)
- Reply only (needs discussion)
- Escalation to human (can't determine action)
5.8 Reply Templates
For code changes applied:
Done - [brief description of what was changed].
For questions answered:
[Direct answer to the question]
[Optional: Link to relevant code or documentation]
For suggestions declined (in scope):
Thanks for the suggestion! I considered this but kept the current approach because:
- [Technical reason: e.g., "This aligns with the existing pattern in `utils/validation.ts`"]
- [Practical reason: e.g., "The suggested change would require updating 15 call sites"]
Happy to discuss further if you'd like to reconsider.
For suggestions declined (out of scope):
Good point! This change is outside the scope of this PR (which focuses on [issue focus]).
I've created issue #[N] to track this improvement separately. Would you like me to prioritize it next?
For concerns/blockers:
Thanks for flagging this. I've addressed it by:
- [Change 1]
- [Change 2]
Please let me know if this addresses your concern or if you'd like further changes.
5.9 Handle Conflicting Feedback
When reviewers disagree:
- Identify the conflict: Same code, different suggestions
- Check reviewer authority: Maintainer opinion typically takes precedence
- If equal authority:
- Summarize both perspectives in a comment
- Implement the more conservative/safe option
- Ask for consensus: "I went with [X] but happy to switch if you both prefer [Y]"
- If unclear: Escalate to human
5.10 Iteration Loop
ITERATION=0
MAX_ITERATIONS=$MAX_FEEDBACK_ITERATIONS
BOT_WAIT_MINUTES=5 # Time to wait for Copilot/Claude after CI
QUIET_PERIOD_MINUTES=3 # Time with no new reviews before marking ready
while [ $ITERATION -lt $MAX_ITERATIONS ]; do
ITERATION=$((ITERATION + 1))
# 1. Fetch current feedback state (ALL types - threads, reviews, comments)
FEEDBACK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
UNRESOLVED=$(echo "$FEEDBACK" | jq '.summary.unresolved_threads')
CHANGES_REQUESTED=$(echo "$FEEDBACK" | jq '.summary.changes_requested')
ACTIONABLE_COMMENTS=$(echo "$FEEDBACK" | jq '.summary.actionable_comments')
# 2. If nothing to address, DON'T break yet - must wait for bot reviews
if [ "$UNRESOLVED" -eq 0 ] && [ "$CHANGES_REQUESTED" -eq 0 ] && [ "$ACTIONABLE_COMMENTS" -eq 0 ]; then
info "No pending feedback - waiting for potential bot reviews..."
# Continue to step 5 to wait for bots
else
# 3. Process all actionable items
# (Use subagents as described above)
# 4. Commit any changes
git add -A
if ! git diff --cached --quiet; then
git commit -m "Address review feedback (iteration $ITERATION)"
git push
fi
fi
# 5. Wait for CI
scripts/wait-for-ci.sh $PR_NUMBER --timeout 10
# 6. CRITICAL: Wait for bot reviews AFTER CI completes
# Copilot often arrives 2-5 minutes after CI passes
info "Waiting $BOT_WAIT_MINUTES minutes for bot reviews (Copilot, Claude)..."
scripts/monitor-pr.sh $PR_NUMBER --timeout $BOT_WAIT_MINUTES --interval 30
# 7. Re-fetch feedback - bots may have added new items
FEEDBACK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
UNRESOLVED=$(echo "$FEEDBACK" | jq '.summary.unresolved_threads')
CHANGES_REQUESTED=$(echo "$FEEDBACK" | jq '.summary.changes_requested')
ACTIONABLE_COMMENTS=$(echo "$FEEDBACK" | jq '.summary.actionable_comments')
# 8. Check if truly ready (nothing pending after bot wait)
if [ "$UNRESOLVED" -eq 0 ] && [ "$CHANGES_REQUESTED" -eq 0 ] && [ "$ACTIONABLE_COMMENTS" -eq 0 ]; then
info "All feedback addressed - verifying quiet period..."
# 9. Quiet period check - ensure no new reviews for 3 minutes
QUIET_START=$(date +%s)
QUIET_OK=true
for i in $(seq 1 $QUIET_PERIOD_MINUTES); do
sleep 60
CURRENT_FEEDBACK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
NEW_UNRESOLVED=$(echo "$CURRENT_FEEDBACK" | jq '.summary.unresolved_threads')
NEW_CHANGES=$(echo "$CURRENT_FEEDBACK" | jq '.summary.changes_requested')
if [ "$NEW_UNRESOLVED" -gt 0 ] || [ "$NEW_CHANGES" -gt 0 ]; then
warn "New feedback arrived during quiet period - reprocessing..."
QUIET_OK=false
break
fi
done
if [ "$QUIET_OK" = true ]; then
info "Quiet period complete - proceeding to mark PR ready"
break
fi
# Otherwise continue loop to process new feedback
fi
done
if [ $ITERATION -ge $MAX_ITERATIONS ]; then
# Escalate to human
gh pr comment $PR_NUMBER -b "## Escalation
After $MAX_ITERATIONS feedback iterations, some items remain unresolved.
Human review requested.
Remaining:
- Unresolved threads: $UNRESOLVED
- Changes requested: $CHANGES_REQUESTED
- Actionable comments: $ACTIONABLE_COMMENTS"
fi
5.11 Wait for Bot Reviews (CRITICAL)
IMPORTANT: Bot reviewers like Copilot and Claude often submit reviews AFTER CI completes. These reviews contain valuable feedback that MUST be addressed before marking the PR ready.
Known bot reviewers to wait for:
| Bot | Username Pattern | Typical Delay |
|---|---|---|
| GitHub Copilot | copilot[bot], github-copilot |
2-5 min after CI |
| Claude | claude[bot], claude-code |
1-3 min after CI |
| CodeRabbit | coderabbitai[bot] |
3-7 min after CI |
| Dependabot | dependabot[bot] |
Immediate |
| Renovate | renovate[bot] |
Immediate |
Waiting strategy after each push:
# After pushing changes:
scripts/wait-for-ci.sh $PR_NUMBER --timeout 15
# CRITICAL: Wait for bot reviews AFTER CI completes
# Copilot especially often arrives 2-5 minutes after CI passes
info "Waiting for bot reviews (Copilot, Claude, etc.)..."
BOT_WAIT_MINUTES=5
scripts/monitor-pr.sh $PR_NUMBER --timeout $BOT_WAIT_MINUTES --interval 30
# Then re-check ALL feedback - bots may have added new items
FEEDBACK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
Never skip this wait - Copilot reviews in particular contain security and quality feedback that is critical to address.
5.12 Quiet Period Verification
Before marking the PR as ready, verify there's been a "quiet period" with no new reviews:
# After processing all feedback:
QUIET_PERIOD_MINUTES=3
LAST_CHECK_TIME=$(date +%s)
while true; do
# Wait for quiet period
sleep 60
# Fetch current state
CURRENT_FEEDBACK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
CURRENT_TIME=$(date +%s)
# Check for new items since last check
NEW_THREADS=$(echo "$CURRENT_FEEDBACK" | jq '.summary.unresolved_threads')
NEW_CHANGES=$(echo "$CURRENT_FEEDBACK" | jq '.summary.changes_requested')
NEW_ACTIONABLE=$(echo "$CURRENT_FEEDBACK" | jq '.summary.actionable_comments')
if [ "$NEW_THREADS" -gt 0 ] || [ "$NEW_CHANGES" -gt 0 ] || [ "$NEW_ACTIONABLE" -gt 0 ]; then
# New feedback arrived - process it and reset quiet period
info "New feedback detected - processing..."
# (Process feedback as per 5.4-5.6)
LAST_CHECK_TIME=$(date +%s)
continue
fi
# Check if quiet period has elapsed
ELAPSED=$((CURRENT_TIME - LAST_CHECK_TIME))
if [ $ELAPSED -ge $((QUIET_PERIOD_MINUTES * 60)) ]; then
info "Quiet period complete - no new reviews for $QUIET_PERIOD_MINUTES minutes"
break
fi
done
5.13 Iteration Limits and Escalation
- Max iterations: Default 3 (configurable via MAX_FEEDBACK_ITERATIONS)
- Per iteration: Fetch all feedback → process → push → wait for CI → wait for bot reviews → wait for response
- Bot review wait: Always wait at least 5 minutes after CI for Copilot/Claude reviews
- Quiet period: Verify 3 minutes of no new activity before marking ready
- Escalation triggers:
- MAX_FEEDBACK_ITERATIONS exceeded
- Reviewer explicitly requests human review
- Feedback requires architectural decisions
- Conflicting reviewer opinions without resolution
Phase 6: Completion
6.1 Verify Completion Criteria
CRITICAL: The PR must meet ALL criteria before marking ready. This is the final gate to ensure no reviews are missed.
All must be true before marking ready:
# 1. CI green
CI_STATUS=$(gh pr checks $PR_NUMBER --json bucket -q '[.[] | .bucket] | unique')
[ "$CI_STATUS" = '["pass"]' ] || exit 1
# 2. No unresolved review threads
REVIEW_DATA=$(gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes { isResolved }
}
reviews(first: 50) {
nodes {
id
state
author { login }
body
}
}
comments(first: 100) {
nodes {
id
author { login }
body
}
}
}
}
}' -f owner="$OWNER" -f repo="$REPO" -F pr="$PR_NUMBER")
UNRESOLVED=$(echo "$REVIEW_DATA" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length')
[ "$UNRESOLVED" = "0" ] || { echo "ERROR: $UNRESOLVED unresolved threads"; exit 1; }
# 3. No reviews requesting changes (includes Copilot, Claude, human reviews)
CHANGES_REQUESTED=$(echo "$REVIEW_DATA" | jq '[.data.repository.pullRequest.reviews.nodes[] | select(.state == "CHANGES_REQUESTED")] | length')
[ "$CHANGES_REQUESTED" = "0" ] || { echo "ERROR: $CHANGES_REQUESTED reviews requesting changes"; exit 1; }
# 4. No unaddressed bot reviews (Copilot, Claude, etc.)
BOT_PATTERNS="copilot|claude|coderabbit|github-actions"
UNADDRESSED_BOT_REVIEWS=$(echo "$REVIEW_DATA" | jq --arg bots "$BOT_PATTERNS" '
[.data.repository.pullRequest.reviews.nodes[] |
select(.author.login | test($bots; "i")) |
select(.state == "CHANGES_REQUESTED" or (.state == "COMMENTED" and .body != null and .body != "" and (.body | test("(?i)(fix|issue|error|should|must|recommend)"))))] | length')
[ "$UNADDRESSED_BOT_REVIEWS" = "0" ] || { echo "ERROR: $UNADDRESSED_BOT_REVIEWS unaddressed bot reviews"; exit 1; }
# 5. Quiet period verified (no new reviews in last 3 minutes)
# This should have been done in Phase 5, but verify again
echo "All completion criteria verified"
Why each check matters:
| Check | Purpose |
|---|---|
| GitHub merge state | CRITICAL: If GitHub says BLOCKED, do NOT mark ready |
| CI green | Code compiles, tests pass |
| No unresolved threads | All inline comments addressed |
| No changes requested | All formal review requests addressed (LATEST review per author) |
| No unaddressed bot reviews | Copilot/Claude feedback addressed |
| Quiet period | No late-arriving reviews pending |
CRITICAL: Latest Review Per Author
GitHub shows the LATEST review from each reviewer, not all historical reviews. The skill MUST match this behavior:
# WRONG: Checks all historical reviews (might miss current "changes requested")
CHANGES_REQUESTED=$(echo "$REVIEWS" | jq '[.[] | select(.state == "CHANGES_REQUESTED")]')
# RIGHT: Get latest review per author, then check status
LATEST_REVIEWS=$(echo "$REVIEWS" | jq '
group_by(.author.login) |
map(sort_by(.createdAt) | last) |
[.[] | select(. != null)]
')
CHANGES_REQUESTED=$(echo "$LATEST_REVIEWS" | jq '[.[] | select(.state == "CHANGES_REQUESTED")]')
CRITICAL: Respect GitHub's Merge State
Before marking ready, check GitHub's own merge state:
mergeStateStatus: BLOCKED→ Do NOT mark ready (unresolved conversations, missing approvals)reviewDecision: CHANGES_REQUESTED→ Reviewer has requested changesmergeable: CONFLICTING→ Merge conflicts exist
6.2 Mark PR Ready for Review
scripts/mark-pr-ready.sh $PR_NUMBER
This script:
- Verifies all CI checks pass
- Verifies all review threads are resolved
- If PR is a draft, marks it as ready (
gh pr ready) - Adds
readylabel to the PR - Tags the logged-in user for notification
- Posts a completion summary comment
The comment tags the user so they receive a GitHub notification:
## Ready for Manual Review
@username - This PR is ready for your review.
### Summary
All automated work has been completed:
- All CI checks passing
- All review feedback addressed
- All review threads resolved
### Next Steps
1. Review the changes
2. Approve if satisfied
3. Merge when ready
The user tag ensures the human gets notified when the skill completes its work.
6.3 Generate Completion Report
Output summary using templates/completion-report.md:
## Auto Issue Fixer - Complete
### Issue
- **Number**: #123
- **Title**: Fix null pointer in user service
### PR
- **Number**: #456
- **Status**: Ready for review
- **URL**: https://github.com/owner/repo/pull/456
### TDD Summary
| Phase | Result |
|-------|--------|
| RED | 3 test cases written |
| GREEN | 2 files modified |
| REFACTOR | 1 cleanup applied |
### Feedback Handled
- Code changes: 2
- Responses: 1
- Iterations: 2/3
**Next step**: Human review and merge
6.4 Update Issue Labels
Swap the in-progress label for a completed label:
gh issue edit $ISSUE_NUMBER --remove-label "auto-fixing" --add-label "auto-fixed"
This signals that automated work is complete and the PR is ready for human review.
6.5 Auto-Merge Decision
Based on the AUTO_MERGE argument, either merge automatically or leave for human:
if [ "$AUTO_MERGE" = "true" ]; then
info "AUTO-ISSUE-FIXER: MERGING - Auto-merge enabled, merging PR #$PR_NUMBER"
# Final safety checks before merge
# 1. Verify CI is still green (could have changed)
CI_STATUS=$(gh pr checks $PR_NUMBER --json bucket -q '[.[] | .bucket] | unique')
if [ "$CI_STATUS" != '["pass"]' ]; then
error "CI no longer passing - aborting auto-merge"
gh pr comment $PR_NUMBER -b "## Auto-Merge Aborted
CI checks are no longer passing. Manual intervention required.
Current CI status: $CI_STATUS"
exit 1
fi
# 2. Verify no new reviews arrived (final check)
FINAL_CHECK=$(scripts/fetch-pr-comments.sh $PR_NUMBER --json)
FINAL_UNRESOLVED=$(echo "$FINAL_CHECK" | jq '.summary.unresolved_threads')
FINAL_CHANGES=$(echo "$FINAL_CHECK" | jq '.summary.changes_requested')
if [ "$FINAL_UNRESOLVED" -gt 0 ] || [ "$FINAL_CHANGES" -gt 0 ]; then
error "New feedback arrived - aborting auto-merge"
gh pr comment $PR_NUMBER -b "## Auto-Merge Aborted
New review feedback arrived after completion. Processing required.
- Unresolved threads: $FINAL_UNRESOLVED
- Changes requested: $FINAL_CHANGES"
exit 1
fi
# 3. Merge the PR
if gh pr merge $PR_NUMBER --squash --delete-branch; then
info "AUTO-ISSUE-FIXER: MERGED - PR #$PR_NUMBER merged successfully"
# Post success comment (will be on the now-closed PR)
gh pr comment $PR_NUMBER -b "## Auto-Merged
PR was automatically merged after all criteria were met:
- All CI checks passing
- All review feedback addressed
- All review threads resolved
- Quiet period verified
Issue #$ISSUE_NUMBER has been closed." 2>/dev/null || true
else
error "Merge failed - may require manual intervention"
gh pr comment $PR_NUMBER -b "## Auto-Merge Failed
Attempted to merge but failed. Possible reasons:
- Branch protection rules require additional approvals
- Merge conflicts detected
- Required status checks changed
Please merge manually."
exit 1
fi
else
# AUTO_MERGE is false or not set - leave for human
info "AUTO-ISSUE-FIXER: COMPLETE - PR #$PR_NUMBER ready for review"
# The mark-pr-ready.sh script already posted a comment tagging the user
# Just ensure the user knows to merge manually
fi
Auto-merge safety checks:
| Check | Why |
|---|---|
| CI still green | Status could have changed since last check |
| No new reviews | Late-arriving feedback must be addressed |
| Squash merge | Clean commit history |
| Delete branch | Cleanup after merge |
When auto-merge is aborted:
- Posts a comment explaining why
- Leaves PR open for manual intervention
- Does NOT retry automatically (prevents loops)
Escalation Triggers
Stop and escalate to human when:
| Condition | Action |
|---|---|
| CI fails after 3 attempts | Report failures, request help |
| Reviewer requests architectural changes | Flag as out of scope |
| MAX_FEEDBACK_ITERATIONS exceeded | Post summary, request guidance |
| Reviewer explicitly requests human | Stop and notify |
| Merge conflicts | Attempt rebase; if fails, escalate |
| No test framework detected | Warn and proceed without TDD |
Escalation message:
## Escalation Required
**Issue**: #{issue_number}
**PR**: #{pr_number}
**Reason**: {escalation_reason}
### Context
{relevant_details}
### Attempted Solutions
{what_was_tried}
### Recommended Action
{suggestion}
Scripts Reference
| Script | Purpose |
|---|---|
scripts/list-all-issues.sh |
Fetch all open issues with metadata |
scripts/fetch-pr-comments.sh |
Fetch all PR feedback (threads, reviews, comments) with categorization |
scripts/monitor-pr.sh |
Poll for new reviews, threads, and comments |
scripts/wait-for-ci.sh |
Wait for CI completion |
scripts/reply-to-thread.sh |
Reply to a review thread and optionally resolve it |
scripts/mark-pr-ready.sh |
Convert draft to ready for review |
Reused from other skills:
| Script | Source |
|---|---|
setup-worktree.sh |
fix-github-issue |
load-issue.sh |
fix-github-issue |
create-pr.sh |
fix-github-issue |
load-pr-feedback.sh |
pr-feedback-workflow |
resolve-thread.sh |
pr-feedback-workflow |
Subagent Usage Summary
| Phase | Type | Purpose | Parallel |
|---|---|---|---|
| 1 | Explore (x N) | Complexity analysis (batches of 5) | YES |
| 2 | Explore | TDD plan creation | NO |
| 3 | Background | Continuous test monitoring | YES |
| 5 | Background (x 2) | CI + Review monitors | YES |
| 5 | Explore (x 2) | Code changes + Responses | YES |
Token efficiency: Main context handles orchestration; subagents handle all codebase exploration and monitoring.
Quick Start
# Fix the highest-priority issue (leaves PR for human to merge)
/auto-issue-fixer
# Fix and auto-merge when complete (fully autonomous)
/auto-issue-fixer --auto-merge
# Fix issues with specific label
/auto-issue-fixer --labels bug
# Dry run - analyze without implementing
/auto-issue-fixer --dry-run
# Process up to 3 issues with auto-merge
/auto-issue-fixer --max-issues 3 --auto-merge
# Fully autonomous with custom wait times
/auto-issue-fixer --auto-merge --bot-wait-minutes 7 --quiet-period-minutes 5
Auto-merge behavior:
--auto-merge(orAUTO_MERGE=true): Merges PR automatically after all reviews addressed- Without flag: Notifies user and leaves PR open for manual merge (default)
Related Skills
- fix-github-issue: Manual issue fixing with worktrees
- pr-feedback-workflow: Dedicated PR feedback handling
- cleanup-issue: Post-merge cleanup