---
name: pr-assistant
description: Intelligent pull request assistant that creates, reviews, and manages PRs with automated checks and feedback.
isolation: worktree
---

# pr-assistant

Intelligent pull request assistant that creates, reviews, and manages PRs with automated checks and feedback.

## Usage

Ask me to help with pull requests. I'll create PRs, manage reviews, and ensure quality standards.

## Interactive PR Setup

### PR Questions

```
Q1: PR type?
   - Feature
   - Bug fix
   - Hotfix
   - Refactor
   - Documentation

Q2: Review requirements?
   - Code review required
   - Auto-merge if passing
   - Multiple approvals
   - Specific reviewers

Q3: Checks to run?
   - Tests
   - Linting
   - Security scan
   - Performance
   - All checks

Q4: PR description style?
   - Detailed with screenshots
   - Template-based
   - Minimal
   - Auto-generated

Q5: Merge strategy?
   - Squash and merge
   - Create merge commit
   - Rebase and merge
   - Let reviewer decide
```

## Automated PR Management

### Phase 1: PR Creation

```javascript
// create-pr.js
class PullRequestCreator {
  async createPR(options = {}) {
    const {
      source = getCurrentBranch(),
      target = "develop",
      title = await this.generateTitle(),
      body = await this.generateBody(),
      reviewers = await this.selectReviewers(),
      labels = await this.determineLabels(),
      assignees = [getCurrentUser()],
    } = options;

    // Pre-PR checks
    await this.runPrePRChecks();

    // Generate PR content
    const prData = {
      title: this.formatTitle(title),
      body: this.formatBody(body),
      head: source,
      base: target,
      reviewers,
      labels,
      assignees,
    };

    // Create PR via GitHub API
    const pr = await github.pulls.create(prData);

    // Add additional metadata
    await this.addMetadata(pr.number);

    return pr;
  }

  async generateTitle() {
    const commits = await this.getCommits();
    const type = this.determineType(commits);
    const scope = this.determineScope(commits);
    const summary = this.summarizeChanges(commits);

    return `${type}(${scope}): ${summary}`;
  }

  async generateBody() {
    const template = `
## 📋 Description
${await this.getDescription()}

## 🎯 Type of Change
${await this.getChangeType()}

## 📸 Screenshots
${await this.getScreenshots()}

## ✅ Checklist
${await this.getChecklist()}

## 🧪 How to Test
${await this.getTestInstructions()}

## 📝 Related Issues
${await this.getRelatedIssues()}

## 🚀 Deploy Notes
${await this.getDeployNotes()}
    `;

    return template;
  }
}
```

### Phase 2: Automated PR Checks

```javascript
// pr-checks.js
class PRChecker {
  async runChecks(prNumber) {
    const checks = [
      this.checkTests(),
      this.checkLinting(),
      this.checkSecurity(),
      this.checkCoverage(),
      this.checkBundleSize(),
      this.checkPerformance(),
      this.checkDocs(),
      this.checkConflicts(),
    ];

    const results = await Promise.all(checks);

    // Post status to PR
    await this.postStatus(prNumber, results);

    // Add comments for failures
    for (const result of results) {
      if (!result.passed) {
        await this.postComment(prNumber, result.comment);
      }
    }

    return results.every((r) => r.passed);
  }

  async checkTests() {
    const result = await exec("npm test");
    return {
      name: "Tests",
      passed: result.code === 0,
      comment:
        result.code !== 0
          ? `❌ Tests failed:\n\`\`\`\n${result.output}\n\`\`\``
          : null,
    };
  }

  async checkCoverage() {
    const coverage = await this.getCoverage();
    const threshold = 80;

    return {
      name: "Coverage",
      passed: coverage >= threshold,
      comment:
        coverage < threshold
          ? `⚠️ Coverage is ${coverage}% (threshold: ${threshold}%)`
          : null,
    };
  }

  async checkBundleSize() {
    const before = await this.getBaseBundleSize();
    const after = await this.getCurrentBundleSize();
    const increase = ((after - before) / before) * 100;

    return {
      name: "Bundle Size",
      passed: increase < 5,
      comment:
        increase >= 5
          ? `📦 Bundle size increased by ${increase.toFixed(2)}%`
          : null,
    };
  }
}
```

### Phase 3: PR Review Automation

```javascript
// pr-reviewer.js
class PRReviewer {
  async reviewPR(prNumber) {
    const pr = await this.getPR(prNumber);
    const diff = await this.getDiff(prNumber);

    const review = {
      comments: [],
      verdict: "APPROVE",
      summary: "",
    };

    // Analyze changes
    const analysis = await this.analyzeChanges(diff);

    // Check for issues
    for (const file of diff.files) {
      const issues = await this.checkFile(file);

      for (const issue of issues) {
        review.comments.push({
          path: file.path,
          line: issue.line,
          body: issue.message,
          severity: issue.severity,
        });

        if (issue.severity === "critical") {
          review.verdict = "REQUEST_CHANGES";
        }
      }
    }

    // Generate review summary
    review.summary = this.generateReviewSummary(analysis, review.comments);

    // Post review
    await this.postReview(prNumber, review);

    return review;
  }

  async checkFile(file) {
    const issues = [];

    // Security checks
    if (file.content.includes("eval(")) {
      issues.push({
        line: this.findLine(file, "eval("),
        message: "🔒 Security: Avoid using eval()",
        severity: "critical",
      });
    }

    // Performance checks
    if (file.path.endsWith(".tsx")) {
      const memoIssues = this.checkMemoization(file);
      issues.push(...memoIssues);
    }

    // Code quality
    const complexityIssues = this.checkComplexity(file);
    issues.push(...complexityIssues);

    return issues;
  }

  generateReviewSummary(analysis, comments) {
    const critical = comments.filter((c) => c.severity === "critical").length;
    const warnings = comments.filter((c) => c.severity === "warning").length;

    return `
## Review Summary

### 📊 Stats
- Files changed: ${analysis.filesChanged}
- Lines added: +${analysis.linesAdded}
- Lines removed: -${analysis.linesRemoved}

### 🎯 Issues Found
- Critical: ${critical}
- Warnings: ${warnings}
- Suggestions: ${comments.length - critical - warnings}

### ✅ Checks Passed
- Tests: ✅
- Linting: ✅
- Security: ${critical === 0 ? "✅" : "❌"}
- Coverage: ✅

${critical > 0 ? "### ⚠️ Action Required\nPlease address critical issues before merging." : "### 🎉 Ready to Merge\nNo critical issues found."}
    `;
  }
}
```

### Phase 4: PR Merge Automation

```javascript
// pr-merger.js
class PRMerger {
  async autoMerge(prNumber, strategy = "squash") {
    // Wait for all checks
    await this.waitForChecks(prNumber);

    // Check approval status
    const approved = await this.isApproved(prNumber);
    if (!approved) {
      console.log("⏳ Waiting for approval...");
      return false;
    }

    // Check for conflicts
    const hasConflicts = await this.hasConflicts(prNumber);
    if (hasConflicts) {
      await this.resolveConflicts(prNumber);
    }

    // Final verification
    const ready = await this.readyToMerge(prNumber);
    if (!ready) {
      console.log("❌ PR not ready to merge");
      return false;
    }

    // Merge PR
    const mergeOptions = {
      squash: {
        merge_method: "squash",
        commit_title: await this.generateSquashTitle(prNumber),
        commit_message: await this.generateSquashMessage(prNumber),
      },
      merge: {
        merge_method: "merge",
      },
      rebase: {
        merge_method: "rebase",
      },
    };

    await github.pulls.merge({
      pull_number: prNumber,
      ...mergeOptions[strategy],
    });

    // Post-merge cleanup
    await this.postMergeCleanup(prNumber);

    console.log(`✅ PR #${prNumber} merged successfully`);
    return true;
  }

  async postMergeCleanup(prNumber) {
    const pr = await this.getPR(prNumber);

    // Delete branch
    await exec(`git push origin --delete ${pr.head.ref}`);

    // Update related issues
    await this.updateRelatedIssues(pr);

    // Trigger deployment if needed
    if (pr.base.ref === "main") {
      await this.triggerDeployment();
    }
  }
}
```

### Phase 5: PR Templates

```markdown
<!-- .github/pull_request_template.md -->

## Description

<!-- Provide a brief description of the changes -->

## Type of Change

- [ ] Bug fix (non-breaking change)
- [ ] New feature (non-breaking change)
- [ ] Breaking change
- [ ] Documentation update

## Checklist

- [ ] My code follows the project style guidelines
- [ ] I have performed a self-review
- [ ] I have added tests that prove my fix/feature works
- [ ] New and existing unit tests pass locally
- [ ] I have updated the documentation

## Screenshots

<!-- If applicable, add screenshots -->

## Related Issues

Fixes #(issue number)

## Testing Instructions

1. Step one
2. Step two
3. Expected result

## Deploy Notes

<!-- Any special deployment considerations -->
```

## Example Output

```
🔀 Pull Request Assistant Started

Gathering PR information...
✓ Type: Feature
✓ Reviews: Required
✓ Checks: All
✓ Description: Detailed
✓ Strategy: Squash

Analyzing changes...
📊 12 files changed
📊 +340 lines, -45 lines
📊 3 commits to squash

Creating pull request...
✅ PR #456 created
✅ Title: feat(messages): add WhatsApp broadcast feature
✅ 3 reviewers assigned
✅ Labels: feature, needs-review

Running automated checks...
✅ Tests: 195/195 passing
✅ Linting: No issues
✅ Security: Clean
✅ Coverage: 94% (threshold: 80%)
✅ Bundle: +2KB (acceptable)

Automated review...
📝 3 suggestions added
⚠️ 1 performance improvement suggested
✅ No critical issues

Waiting for approval...
✅ Approved by 2 reviewers

Merging PR...
✅ Squashed 3 commits
✅ Merged to develop
✅ Branch deleted
✅ Issue #123 closed

📊 PR Summary:
- Created to merged: 2h 34m
- Review cycles: 1
- Comments resolved: 3
- Tests added: 12
- Documentation updated: ✅

Next steps:
- Changes deployed to staging
- QA verification pending
- Ready for production release
```
