global/skills/pr-work/SKILL.md
Analyze and fix failed CI/CD workflows for a pull request. Use when CI checks fail, GitHub Actions show red, build/test/lint errors block a PR, or the user says 'fix CI', 'fix the build', 'PR is failing', or 'check failed'. Supports solo, team, and batch modes with automated retry and escalation.
npx skillsauth add kcenon/claude-config pr-workInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Analyze and fix failed CI/CD workflows for a pull request.
/pr-work # Batch: all repos, all failing PRs
/pr-work <project-name> # Batch: all failing PRs in project
/pr-work <pr-number> # Single: fix PR in current project
/pr-work <project-name> <pr-number> # Single: fix specific PR
/pr-work <organization>/<project-name> <pr-number>
Examples:
/pr-work # Batch: all repos, all PRs with failed CI
/pr-work hospital_erp_system # Batch: all failing PRs in project
/pr-work 42 # Single: fix PR #42 (auto-detect repo)
/pr-work hospital_erp_system 42 # Single: fix PR #42 in project
/pr-work hospital_erp_system 42 --org mycompany # Explicit org
/pr-work mycompany/hospital_erp_system 42 # Full path format
/pr-work 42 --solo # Force solo mode (sequential)
/pr-work 42 --team # Force team mode (diagnoser + fixer)
/pr-work --org mycompany # Batch: all repos in org
/pr-work hospital_erp_system --limit 5 # Batch: top 5 failing PRs
/pr-work hospital_erp_system --dry-run # Preview batch plan only
/pr-work hospital_erp_system --inline # Batch: process items in the parent context (legacy)
[project-name]: Project name or full repository path (optional)
[pr-number]: Pull request number (optional)
[--solo|--team]: Execution mode override (optional)
--solo — Force solo mode for all items--team — Force team mode for all items[--limit N]: Maximum number of items to process in batch mode (default: 5, max: 10)
--force-large to acknowledge rule drift risk. Empirically, drift becomes visible around items 15-25 in long batches; the conservative default keeps batches inside the safe zone.[--force-large]: Allow --limit > 10. Required to bypass the safe-batch cap.
[--no-confirm]: Skip the chunked confirmation gate fired every 5 items in batch mode. Intended for CI-driven or fully unattended batches; interactive sessions should leave it off so the gate can serve as both a user-control checkpoint and an attention refresh for accumulated context.
[--auto-restart]: Force a session restart every CONFIRM_INTERVAL items instead of showing the interactive chunked gate. The batch writes .claude/resume.md using the Batch Workflow Resume Format and exits cleanly; a fresh claude session picks up the next PR from the resume file. Use for long unattended PR-fixing batches where a full process-level attention reset per chunk matters more than human confirmation. Ignored in single-item mode.
[--no-restart]: Suppress the forced restart. When combined with --auto-restart, the batch falls back to the interactive chunked gate. Meaningful primarily as a defensive flag in scripts that want to guarantee no session exit even if --auto-restart is set elsewhere (aliases, wrappers, or a future default change).
[--dry-run]: Show batch plan only, do not execute
[--inline]: Process each batch item in the parent conversation context instead of delegating to a fresh subagent.
general-purpose Agent. The parent keeps only the queue state and a short per-item summary; CI log fetches, diff reads, and build outputs live inside the subagent and are discarded on completion. This is the preferred mode for batches >3 items because rule compliance at item 30 looks like item 1.--inline: The parent executes Solo/Team workflow directly for every item. Lower token overhead (~10-15% savings) but accumulated CI log noise drives rule drift around items 15-25. Use for tiny batches (≤3 items) or when several PRs share a root cause and you want cross-item context.[--org <organization>]: Scope to a specific GitHub organization
Auto-checkout: In single-item mode, the command automatically detects and checks out the PR's branch.
Parse $ARGUMENTS and determine organization, PR number, and batch mode:
ARGS="$ARGUMENTS"
PR_NUMBER=""
PROJECT=""
ORG=""
EXEC_MODE=""
BATCH_MODE="single" # single | single-repo | cross-repo
BATCH_LIMIT=5
MAX_LIMIT=10
CONFIRM_INTERVAL=5
DRY_RUN=false
FORCE_LARGE=false
NO_CONFIRM=false
INLINE_MODE=false
AUTO_RESTART=false
NO_RESTART=false
# Extract flags
ORIGINAL_ARGS="$ARGS"
if [[ "$ARGS" == *"--solo"* ]]; then EXEC_MODE="solo"; ARGS=$(echo "$ARGS" | sed 's/--solo//g'); fi
if [[ "$ARGS" == *"--team"* ]]; then EXEC_MODE="team"; ARGS=$(echo "$ARGS" | sed 's/--team//g'); fi
if [[ "$ARGS" == *"--dry-run"* ]]; then DRY_RUN=true; ARGS=$(echo "$ARGS" | sed 's/--dry-run//g'); fi
if [[ "$ARGS" == *"--force-large"* ]]; then FORCE_LARGE=true; ARGS=$(echo "$ARGS" | sed 's/--force-large//g'); fi
if [[ "$ARGS" == *"--no-confirm"* ]]; then NO_CONFIRM=true; ARGS=$(echo "$ARGS" | sed 's/--no-confirm//g'); fi
if [[ "$ARGS" == *"--no-restart"* ]]; then NO_RESTART=true; ARGS=$(echo "$ARGS" | sed 's/--no-restart//g'); fi
if [[ "$ARGS" == *"--auto-restart"* ]]; then AUTO_RESTART=true; ARGS=$(echo "$ARGS" | sed 's/--auto-restart//g'); fi
if [[ "$ARGS" == *"--inline"* ]]; then INLINE_MODE=true; ARGS=$(echo "$ARGS" | sed 's/--inline//g'); fi
if [[ "$ARGS" =~ --limit[[:space:]]+([0-9]+) ]]; then BATCH_LIMIT="${BASH_REMATCH[1]}"; ARGS=$(echo "$ARGS" | sed -E 's/--limit[[:space:]]+[0-9]+//g'); fi
if [[ "$ARGS" =~ --org[[:space:]]+([^[:space:]]+) ]]; then ORG="${BASH_REMATCH[1]}"; ARGS=$(echo "$ARGS" | sed -E 's/--org[[:space:]]+[^[:space:]]+//g'); fi
# Hard cap on batch size to mitigate rule drift in long batches.
# Drift becomes empirically visible around items 15-25; default 5 keeps the
# operator inside the safe zone, and bypassing requires explicit acknowledgment.
if (( BATCH_LIMIT > MAX_LIMIT )) && [[ "$FORCE_LARGE" != "true" ]]; then
echo "Error: --limit ${BATCH_LIMIT} exceeds safe cap of ${MAX_LIMIT}." >&2
echo "Long batches risk rule drift around items 15-25." >&2
echo "Either split the batch into smaller runs or pass --force-large to override." >&2
exit 1
fi
# Trim remaining args
ARGS=$(echo "$ARGS" | xargs)
# Determine mode based on remaining args
if [[ -z "$ARGS" && -z "$ORG" ]]; then
# No args at all → cross-repo batch
BATCH_MODE="cross-repo"
elif [[ -z "$ARGS" && -n "$ORG" ]]; then
# Only --org provided → cross-repo batch scoped to org
BATCH_MODE="cross-repo"
elif [[ "$ARGS" =~ ^[0-9]+$ ]]; then
# Single numeric arg → PR number in current project (unchanged behavior)
BATCH_MODE="single"
PR_NUMBER="$ARGS"
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
ORG=$(echo "$REMOTE_URL" | sed -E 's|.*[:/]([^/]+)/[^/]+\.git$|\1|' | sed -E 's|.*[:/]([^/]+)/[^/]+$|\1|')
PROJECT=$(echo "$REMOTE_URL" | sed -E 's|.*[:/][^/]+/([^/]+)\.git$|\1|' | sed -E 's|.*[:/][^/]+/([^/]+)$|\1|')
elif [[ "$ARGS" =~ ^[a-zA-Z] ]] && ! [[ "$ARGS" =~ [[:space:]][0-9]+([[:space:]]|$) ]]; then
# Project name only, no PR number → single-repo batch
BATCH_MODE="single-repo"
if [[ "$ARGS" == *"/"* ]]; then
ORG=$(echo "$ARGS" | cut -d'/' -f1 | xargs)
PROJECT=$(echo "$ARGS" | cut -d'/' -f2 | xargs)
else
PROJECT="$ARGS"
if [[ -z "$ORG" ]]; then
cd "$PROJECT" 2>/dev/null || { echo "Error: Project directory not found: $PROJECT"; exit 1; }
ORG=$(git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+)/[^/]+\.git$|\1|' | sed -E 's|.*[:/]([^/]+)/[^/]+$|\1|')
fi
fi
else
# Project + PR number → single-item mode (unchanged)
BATCH_MODE="single"
if [[ "$ARGS" == *"/"* ]]; then
REPO_PATH=$(echo "$ARGS" | awk '{print $1}')
ORG=$(echo "$REPO_PATH" | cut -d'/' -f1)
PROJECT=$(echo "$REPO_PATH" | cut -d'/' -f2)
PR_NUMBER=$(echo "$ARGS" | awk '{print $2}')
else
PROJECT=$(echo "$ARGS" | awk '{print $1}')
PR_NUMBER=$(echo "$ARGS" | awk '{print $2}')
if [[ -z "$ORG" ]]; then
cd "$PROJECT" 2>/dev/null || { echo "Error: Project directory not found: $PROJECT"; exit 1; }
ORG=$(git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+)/[^/]+\.git$|\1|' | sed -E 's|.*[:/]([^/]+)/[^/]+$|\1|')
fi
fi
fi
$BATCH_MODE == "single-repo" or $BATCH_MODE == "cross-repo" → Execute Batch Mode Instructions below$BATCH_MODE == "single" → Execute Phase 0: Execution Mode Selection (skip Batch Mode)See reference/batch-mode.md for the complete batch mode workflow including discovery, priority sorting, plan approval, and sequential execution.
Batch-only behaviors (do not apply in single-item mode):
general-purpose Agent so CI log fetches and file reads live inside the subagent and never reach the parent. The parent retains only {pr_number, repo, status, ci_conclusion} per item. Pass --inline to fall back to the legacy single-context loop.--inline mode it is emitted directly in the parent context.@load: reference/... inside the per-item loop: keep the inline reminder as the most recent context anchor.--no-confirm. When --auto-restart is set (and --no-restart is not), the gate is replaced by a forced session restart that writes .claude/resume.md and exits; a fresh claude session resumes from the next PR.Determine whether to run in Solo mode (single agent, sequential) or Team mode (diagnoser + fixer agents in parallel).
FAILED_RUNS=$(gh run list --repo $ORG/$PROJECT --branch "$HEAD_BRANCH" --status failure --limit 10 --json databaseId,name -q 'length')
--solo or --team flag was providedSkip mode selection — use $EXEC_MODE directly.
Auto-recommend based on failure complexity:
| Signal | Solo (Recommended) | Team (Recommended) | |--------|-------------------|-------------------| | Failed workflows | 1 | 2+ | | Error categories | Single (build OR test OR lint) | Multiple (build AND test) | | Previous fix attempts | 0 | 1+ (already tried, recurring) |
Use AskUserQuestion to present the choice:
Store the result in $EXEC_MODE (solo | team).
$EXEC_MODE == "solo" → Execute Solo Mode Instructions (Steps 1-11 below)$EXEC_MODE == "team" → Execute Team Mode Instructions (after Solo Mode section)# Get PR information including branch name
PR_INFO=$(gh pr view $PR_NUMBER --repo $ORG/$PROJECT --json title,state,headRefName,checks)
# Extract branch name from PR
HEAD_BRANCH=$(echo "$PR_INFO" | jq -r '.headRefName')
if [[ -z "$HEAD_BRANCH" ]]; then
echo "Error: Cannot determine branch name for PR #$PR_NUMBER"
exit 1
fi
echo "PR #$PR_NUMBER branch: $HEAD_BRANCH"
Identify:
Branch auto-detection: The PR's branch name is automatically extracted from headRefName.
# List failed workflow runs for the PR
gh run list --repo $ORG/$PROJECT --branch "$HEAD_BRANCH" --status failure --limit 5
# Get detailed log for failed run
gh run view <RUN_ID> --repo $ORG/$PROJECT --log-failed
For each failed workflow:
MANDATORY: Post a failure analysis comment to the PR after analysis, before attempting a fix. All comments must be in English only. Sanitize secrets, IPs, PII, and connection strings before posting.
See
reference/comment-templates.mdfor the full comment template, guidelines, and sensitive data handling rules.
Auto-checkout: The command automatically checks out the PR's branch.
# Navigate to project directory (if not already there)
if [[ ! -z "$PROJECT" && -d "$PROJECT" ]]; then
cd "$PROJECT"
fi
# Fetch latest changes
git fetch origin
# Check if branch exists locally
if git show-ref --verify --quiet refs/heads/"$HEAD_BRANCH"; then
# Branch exists locally, switch to it
git checkout "$HEAD_BRANCH"
git pull origin "$HEAD_BRANCH"
else
# Branch doesn't exist locally, create and track
git checkout -b "$HEAD_BRANCH" "origin/$HEAD_BRANCH"
fi
echo "Switched to PR branch: $HEAD_BRANCH"
Branch handling:
Based on workflow analysis, fix the identified issues:
| Failure Type | Common Fixes | |--------------|--------------| | Build error | Fix compilation errors, missing dependencies | | Test failure | Fix failing tests or update test expectations | | Lint error | Apply code formatting, fix style violations | | Type error | Fix type mismatches, add missing types | | Missing header | Add required #include statements | | Link error | Fix undefined references, library linking |
Select inline (< 30s) or background + log polling (30s+) strategy based on build duration. Diagnose before retrying — do NOT re-run the same build without changes.
See
reference/build-verification.mdfor strategy selection table, inline/background execution patterns, and outcome detection.
git add <fixed-files>
git commit -m "fix(<scope>): <description>
Fixes CI failure: <brief explanation>"
Commit rules:
fix, build, test, or cicommit-settings.md)git push origin "$HEAD_BRANCH"
If gh commands fail with TLS certificate errors in sandbox mode:
x509: certificate signed by unknown authority
tls: failed to verify certificate
Use dangerouslyDisableSandbox for the gh command, or suggest the user
run outside sandbox. Never assume authentication has failed without verifying —
ask the user to confirm if unclear.
After push, monitor CI with non-blocking polling (30s intervals, 10min max). Do NOT use gh run watch. Do NOT merge while any check is queued or in_progress.
See
reference/build-verification.mdfor the full CI monitoring protocol, status interpretation table, and polling limits.
If workflows still fail, repeat steps 2-8. Max 3 retry attempts with 30s CI polling intervals. Each fix is a separate commit. Post a follow-up failure analysis comment at the start of each iteration.
See
reference/build-verification.mdfor iteration limits, CI polling loop, and iteration rules. Seereference/comment-templates.mdfor the per-attempt follow-up comment template.
ABSOLUTE CI GATE — MANDATORY PRE-MERGE VERIFICATION:
Before executing gh pr merge, you MUST run gh pr checks and verify every single check:
gh pr checks $PR_NUMBER --repo $ORG/$PROJECT
Do NOT merge if ANY check shows:
fail or failure conclusion (regardless of perceived cause)pending, queued, or in_progress statuscancelled, timed_out, or startup_failure conclusionALL checks must show pass or neutral to proceed. No exceptions. No rationalization.
Never judge a failure as "unrelated", "pre-existing", or "infrastructure-only" — all failures block merge.
If any check is not passing, STOP. Do NOT proceed to merge. Instead:
gh pr checks output to the userOnly when ALL checks pass:
gh pr merge $PR_NUMBER --repo $ORG/$PROJECT --squash --delete-branch
If merge fails (e.g., review required, branch protection), report the status and skip merge. Do not force-merge.
When max retry attempts (3) are exceeded: post summary comment to PR (English only), add needs-manual-review label, and report final status to user.
See
reference/comment-templates.mdfor the escalation comment template and decision matrix.
See reference/team-mode.md for the complete team mode workflow including architecture, teammate spawning, feedback loops, and cleanup.
See _policy.md for common rules.
| Item | Rule | |------|------| | Language | All PR comments and commit messages MUST be written in English only | | Max retry attempts | 3 before escalation | | CI poll interval | >= 30 seconds (respect API rate limits) | | CI max poll duration | 10 minutes per run (20 polls x 30s) |
CRITICAL: Do NOT produce a "Success" summary if CI has any failing, pending, or incomplete checks. A task is only successful when gh pr checks confirms ALL checks pass.
After successful merge, provide summary:
## PR Fix Summary
| Item | Value |
|------|-------|
| Repository | $ORG/$PROJECT |
| PR | #$PR_NUMBER |
| Branch | $HEAD_BRANCH |
| Execution mode | Solo / Team |
| Attempts | X/3 |
| CI Status | All checks passed (`gh pr checks` verified) |
| Final Status | Success — Merged |
### Workflows Fixed
| Workflow | Status | Fix Applied |
|----------|--------|-------------|
| Build | Fixed | description |
| Test | Fixed | description |
### Commits Made
1. `fix(scope): description` - hash
2. `fix(scope): description` - hash
If CI failed or max retries exceeded, use this format instead:
## PR Fix Summary (INCOMPLETE)
| Item | Value |
|------|-------|
| Repository | $ORG/$PROJECT |
| PR | #$PR_NUMBER |
| Branch | $HEAD_BRANCH |
| Attempts | X/3 |
| CI Status | FAILING — [list failed checks] |
| Final Status | Escalated — NOT merged |
### Escalation
- Escalation reason: [reason]
- PR comment added: Yes/No
- Label applied: needs-manual-review
### Action Required
- User must resolve CI failures before merge
See reference/error-handling.md for prerequisite checks, runtime errors, batch mode errors, and common CI failure patterns.
testing
Comprehensive security audit covering OWASP Top 10, input validation, authentication, authorization, secret management, dependency vulnerabilities, and injection attack prevention. Use when reviewing security posture, implementing auth flows, handling user input, auditing dependencies, conducting penetration test prep, or before production deployment.
development
Provides workflow guidelines for problem-solving, git commits, GitHub issues, PRs, build management, and testing. Use when planning tasks, creating issues, submitting PRs, managing builds, or writing tests.
development
Review pull requests with comprehensive analysis covering code quality, security vulnerabilities, performance implications, test coverage, documentation completeness, and architectural impact. Use when reviewing PRs, conducting code reviews, evaluating merge readiness, or assessing change impact across the codebase.
development
Performance optimization analysis: CPU/memory profiling, caching strategies, database query optimization, connection pooling, concurrency patterns, memory leak detection, and throughput improvement. Use when code is slow, memory usage is high, latency needs reduction, or conducting performance reviews before release.