Skip to content

Conversation

@jordanpartridge
Copy link
Owner

@jordanpartridge jordanpartridge commented Jan 1, 2026

Summary

  • Adds .claude/agents/github-repo-maintainer.md with 6 documented skills for autonomous repository maintenance
  • Each skill includes workflow documentation, PHP code examples, and CLI commands

Skills Included:

  1. Issue Triage - Categorize, label, and prioritize incoming issues
  2. Pull Request Review - Automated code review checks
  3. Merge Conflict Resolution - Detect and help resolve merge conflicts
  4. Release Management - Automate changelog generation and version tagging
  5. Stale Issue Management - Identify and clean up inactive issues/PRs
  6. Dependency Security Monitoring - Track and respond to vulnerabilities

Test plan

  • Verify .claude/agents/github-repo-maintainer.md exists and is properly formatted
  • Confirm all 6 skills have examples (PHP code + CLI commands)
  • Check markdown renders correctly in GitHub

Closes #113

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added comprehensive GitHub Repository Maintainer Agent documentation and implementation blueprint covering six key maintenance skills: Issue Triage, Pull Request Review, Merge Conflict Resolution, Release Management, Stale Issue Management, and Dependency Security Monitoring.
    • Provides detailed workflows, configuration guidance, CI/CD integration examples, and practical implementation patterns to automate repository maintenance tasks and improve repository health.

✏️ Tip: You can customize this high-level summary in your review settings.

…ment

Adds a new Claude agent with 6 documented skills:
1. Issue Triage - Categorize and label incoming issues
2. Pull Request Review - Automated code review checks
3. Merge Conflict Resolution - Detect and help resolve conflicts
4. Release Management - Automate changelog and version tagging
5. Stale Issue Management - Clean up inactive issues/PRs
6. Dependency Security Monitoring - Track and respond to vulnerabilities

Each skill includes workflow documentation, PHP code examples using the
github-client package, and CLI commands using the gh CLI.

Closes #113

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 1, 2026

📝 Walkthrough

Walkthrough

A new comprehensive documentation file introducing a GitHub Repository Maintainer Agent blueprint with six core skills: Issue Triage, Pull Request Review, Merge Conflict Resolution, Release Management, Stale Issue Management, and Dependency Security Monitoring. Includes workflow descriptions, PHP code examples, CLI commands, error handling patterns, and CI/CD integration guidance.

Changes

Cohort / File(s) Summary
GitHub Repository Maintainer Agent Documentation
\.claude/agents/github-repo-maintainer.md
New comprehensive agent blueprint defining six maintenance skills with detailed workflows, PHP implementation examples, error handling conventions, environment variable configuration, GitHub Actions CI/CD integration, and end-to-end usage patterns for autonomous repository management

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Poem

🐰 A maintenance agent hops into view,
Six skills sharp—triage, reviews, and more!
Labels, releases, conflicts it'll chew,
Stale issues swept from the repo's door.
Autonomous guardianship, tried and true! ✨

Pre-merge checks

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a github-repo-maintainer agent documentation for autonomous PR/issue management.
Linked Issues check ✅ Passed The PR fully addresses issue #113 by providing comprehensive documentation for six repository maintenance skills with PHP examples and CLI commands.
Out of Scope Changes check ✅ Passed All changes are scoped to issue #113; the PR only adds the github-repo-maintainer agent documentation without unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
.claude/agents/github-repo-maintainer.md (2)

43-58: Issue Triage categorization logic may misclassify ambiguous issues.

The keyword-matching approach uses exclusive if/elseif branches, so issues containing both "bug" and "feature" keywords will only receive the first matching category. Consider whether ambiguous issues should receive multiple labels or explicit handling.

🔎 Optional refinement for multi-category detection
$labels = [];

if (str_contains($title, 'bug') || str_contains($body, 'error') || str_contains($body, 'crash')) {
    $labels[] = 'bug';
}
if (str_contains($title, 'feature') || str_contains($body, 'would be nice')) {
    $labels[] = 'enhancement';
}
if (str_contains($title, '?') || str_contains($body, 'how do i')) {
    $labels[] = 'question';
}

$priority = match(true) {
    in_array('bug', $labels) => 'high',
    in_array('enhancement', $labels) => 'medium',
    in_array('question', $labels) => 'low',
    default => 'low'
};

641-661: CI/CD workflow structure is sound.

The GitHub Actions setup correctly triggers on schedule/dispatch, configures PHP environment, and runs the maintenance commands. The workflow provides a practical foundation for autonomous maintenance execution.

Consider adding explicit error handling (e.g., continue-on-error: false for critical steps, notifications on failure) for production deployments to ensure visibility into maintenance task failures.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d9740a and ace5a46.

📒 Files selected for processing (1)
  • .claude/agents/github-repo-maintainer.md
🔇 Additional comments (6)
.claude/agents/github-repo-maintainer.md (6)

180-221: Merge Conflict Resolution approach is sound.

The detection logic using mergeable property and helpful git commands are well-implemented. The use of createComment() on issues for PR comments is correct since PRs inherit from issues in the GitHub API.


373-416: Stale Issue Management implementation is well-structured.

The two-phase approach (close if past grace period, then mark as stale) with label skipping for pinned/help-wanted issues is a sound pattern. Date calculations and state transitions are correct.


602-624: Error handling patterns are comprehensive.

The exception handling covers the main failure modes (rate limiting, authentication, API errors) with appropriate logging and recovery hints (getResetTime for rate limits). This provides a solid foundation for production use.


1-20: Comprehensive agent documentation with all required skills.

The documentation successfully covers all six skills (Issue Triage, PR Review, Merge Conflicts, Release Management, Stale Issues, Dependency Security) with clear workflows, PHP examples using the github-client package, and CLI command alternatives. The documentation structure is professional and well-organized.

However, several code examples depend on accurate github-client package API signatures. Please verify:

  1. The commit object structure returned from Github::commits()->all() (line 278 accessing ->message)
  2. The exact JSON structure of composer audit --format=json output (line 496 referencing reportedAt)

These verification steps will ensure examples work correctly when implemented.


98-143: Update method calls to use pullRequests() and fix createReview() signature.

The code uses non-existent method Github::pulls() which should be Github::pullRequests(). Additionally, createReview() accepts separate parameters, not an array. The correct approach:

use JordanPartridge\GithubClient\Facades\Github;

$pulls = Github::pullRequests()->all('owner', 'repo', ['state' => 'open']);

foreach ($pulls as $pr) {
    $files = Github::pullRequests()->files('owner', 'repo', $pr->number);
    
    $issues = [];
    
    foreach ($files as $file) {
        if (str_ends_with($file->filename, '.php')) {
            if (str_contains($file->patch ?? '', 'dd(') || str_contains($file->patch ?? '', 'dump(')) {
                $issues[] = "Found debugging statement in `{$file->filename}`";
            }
            if (str_contains($file->patch ?? '', 'var_dump')) {
                $issues[] = "Found `var_dump` in `{$file->filename}` - use proper logging instead";
            }
        }
        
        if ($file->changes > 500) {
            $issues[] = "Large change ({$file->changes} lines) in `{$file->filename}` - consider splitting";
        }
    }
    
    if (empty($issues)) {
        Github::pullRequests()->createReview('owner', 'repo', $pr->number, 'Automated checks passed. LGTM!', 'APPROVE');
    } else {
        Github::pullRequests()->createReview('owner', 'repo', $pr->number, "Found issues:\n- " . implode("\n- ", $issues), 'REQUEST_CHANGES');
    }
}

The facade provides pullRequests() not pulls(). The createReview() method signature is createReview(string $owner, string $repo, int $number, string $body, string $event = 'COMMENT', array $comments = []).

Likely an incorrect or invalid review comment.


481-504: Use correct field for fixed version in composer audit advisory.

Line 496 uses {$advisory['reportedAt']}, but composer audit JSON output does not include a 'reportedAt' field as a version number. Use fixedIn or first_patched_version['name'] (depending on the advisory source) instead. The current code will produce a malformed message with a missing version number.

Comment on lines +268 to +289
// Get commits since last release
$commits = Github::commits()->all('owner/repo', since: $latestRelease?->created_at);

// Categorize commits by conventional commit prefixes
$features = [];
$fixes = [];
$breaking = [];
$other = [];

foreach ($commits as $commit) {
$message = $commit->message;

if (str_starts_with($message, 'feat:') || str_starts_with($message, 'feat(')) {
$features[] = $message;
} elseif (str_starts_with($message, 'fix:') || str_starts_with($message, 'fix(')) {
$fixes[] = $message;
} elseif (str_contains($message, 'BREAKING CHANGE')) {
$breaking[] = $message;
} else {
$other[] = $message;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and read the file in question
find . -name "github-repo-maintainer.md" -type f

Repository: jordanpartridge/github-client

Length of output: 115


🏁 Script executed:

# Search for github-client package or related commit handling code
fd -type f \( -name "*.php" -o -name "*.md" \) | xargs grep -l "github-client\|Github::" 2>/dev/null | head -10

Repository: jordanpartridge/github-client

Length of output: 243


🏁 Script executed:

# Look for how commits are accessed in the codebase
rg -B3 -A3 "commit.*message\|->message" --type php | head -30

Repository: jordanpartridge/github-client

Length of output: 55


🏁 Script executed:

# Read the file to see the actual code and context
cat -n ./.claude/agents/github-repo-maintainer.md | sed -n '260,295p'

Repository: jordanpartridge/github-client

Length of output: 1382


🏁 Script executed:

# Search for the github-client package or related code in the repository
find . -name "*.php" | head -20

Repository: jordanpartridge/github-client

Length of output: 763


🏁 Script executed:

# Look for commit handling or Github class definitions
rg "class.*Commit\|function.*commit\|->commit\|->message" --type-list

Repository: jordanpartridge/github-client

Length of output: 462


🏁 Script executed:

# Try a simpler search for commit-related code
rg "commit" --max-count=20

Repository: jordanpartridge/github-client

Length of output: 17478


🏁 Script executed:

# Read the CommitData class to understand the structure
cat -n ./src/Data/Commits/CommitData.php

Repository: jordanpartridge/github-client

Length of output: 2572


🏁 Script executed:

# Also check CommitDetailsData which likely contains the message
cat -n ./src/Data/Commits/CommitDetailsData.php

Repository: jordanpartridge/github-client

Length of output: 2210


🏁 Script executed:

# Look at the actual command usage to see how commits are accessed
cat -n ./src/Commands/GithubClientCommand.php | sed -n '80,100p'

Repository: jordanpartridge/github-client

Length of output: 715


🏁 Script executed:

# Continue reading the showCommits method to see actual usage
cat -n ./src/Commands/GithubClientCommand.php | sed -n '100,130p'

Repository: jordanpartridge/github-client

Length of output: 1311


🏁 Script executed:

# Check if CommitData has any magic methods like __get or __call
rg -A20 "class CommitData" ./src/Data/Commits/CommitData.php | grep -E "__get|__call|__isset"

Repository: jordanpartridge/github-client

Length of output: 55


🏁 Script executed:

# Also verify by looking at test files to see how commits are actually used
cat -n ./tests/CommitResourceTest.php

Repository: jordanpartridge/github-client

Length of output: 4628


Fix commit message access to use nested property.

Line 278 should access the message through the nested commit property: $commit->commit->message instead of $commit->message. The CommitData object contains a commit property (type CommitDetailsData) which holds the message field.

Corrected code snippet
foreach ($commits as $commit) {
    $message = $commit->commit->message;

    if (str_starts_with($message, 'feat:') || str_starts_with($message, 'feat(')) {
        $features[] = $message;
    } elseif (str_starts_with($message, 'fix:') || str_starts_with($message, 'fix(')) {
        $fixes[] = $message;
    } elseif (str_contains($message, 'BREAKING CHANGE')) {
        $breaking[] = $message;
    } else {
        $other[] = $message;
    }
}
🤖 Prompt for AI Agents
.claude/agents/github-repo-maintainer.md around lines 268 to 289: the loop reads
commit message from $commit->message but the GitHub CommitData nests the text
under $commit->commit->message; update the code to read $message =
$commit->commit->message (and optionally guard with null checks if
$commit->commit or ->message may be missing) so categorization uses the actual
commit message.

@jordanpartridge jordanpartridge merged commit d4b8e3c into master Jan 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add github-repo-maintainer agent for autonomous PR/issue management

2 participants