feat: add 'fix-pr' skill for agentic iterative PR fixing

This commit is contained in:
mkorwel
2026-03-13 19:25:03 -07:00
parent 7d85e84d17
commit 3649059a28
3 changed files with 119 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
# Fix PR Skill
This skill enables the agent to autonomously and iteratively fix a Pull Request until it is mergeable and passes all quality checks. It is designed to be run in a dedicated, non-blocking environment (like an offloaded remote session).
## Objective
The goal is to move a PR from its current state (failing tests, merge conflicts, or unaddressed comments) to a "Ready to Merge" state.
## Iterative Fix Loop
The agent must follow this loop until the PR is green and mergeable:
### 1. Synchronization & Merge Conflicts
- Fetch latest main: `git fetch origin main`.
- Attempt to merge: `git merge origin/main`.
- **If conflicts occur**:
- Use `git status` to identify conflicted files.
- Resolve the conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) based on the project's architectural direction.
- `git add` and `git commit` the resolution.
### 2. CI Failure Analysis
- Check current status: `gh pr checks`.
- **If CI is failing**:
- Download failing logs: `gh run view --log-failed`.
- Analyze the specific error (lint, typecheck, or test failure).
- Reproduce the failure locally (e.g., `npm run lint`, `npm test -- <path>`).
- Apply a targeted fix.
### 3. Comment Resolution
- Fetch all comments: Use `scripts/fetch-pr-info.js` or `gh pr view --json reviews,comments`.
- Analyze:
- **Line-level comments**: Fix the specific logic requested.
- **Review rejections**: Address the high-level architectural concerns.
- **General comments**: Respond or implement requested changes.
- For each fixed item, summarize the change in a commit message.
### 4. Verification & Push
- Verify the fix locally: `npm run build` and relevant tests.
- **If local verification fails**: Re-analyze and apply a new fix.
- **If local verification passes**:
- `git add .`
- `git commit -m "fix: address <issue/comment>"`
- `git push origin HEAD`
### 5. Wait for CI
- Run the blocker tool: `npx tsx .gemini/skills/fix-pr/scripts/wait-for-ci.ts`.
- **If CI passes**: Move to final check.
- **If CI fails**: Repeat the loop from step 2.
## Final Check
The PR is considered "Fix Complete" when:
1. `gh pr checks` returns success for all required jobs.
2. There are no outstanding merge conflicts with `main`.
3. All critical review comments have been addressed via code changes.
## Best Practices
- **Reason about failures**: Don't just guess. Read the stack traces and log files.
- **Incremental commits**: Make small, focused commits for different fixes.
- **Verify before pushing**: Always run the build/test locally before pushing to CI to save time.
- **Be Autonomous**: In an offloaded session, you have full permission to iterate until successful.

View File

@@ -0,0 +1,41 @@
/**
* CI Waiter Utility for Fix PR Skill
* Blocks until GitHub checks for the current branch are complete.
*/
import { spawnSync } from 'child_process';
async function wait(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log('🔍 Waiting for GitHub Checks to complete...');
let attempts = 0;
const maxAttempts = 30; // 15 minutes total
while (attempts < maxAttempts) {
const checkStatus = spawnSync('gh', ['pr', 'checks'], { shell: true });
const output = checkStatus.stdout.toString();
if (output.includes('fail')) {
console.log('❌ CI Failed.');
process.exit(1);
} else if (output.includes('pending')) {
console.log(`⏳ CI still pending... (check ${attempts + 1}/${maxAttempts})`);
await wait(30000); // 30 seconds
} else if (output.trim() === '') {
console.log('⚠️ No checks found yet, waiting...');
await wait(10000);
} else {
console.log('✅ CI Passed!');
process.exit(0);
}
attempts++;
}
console.error('⏰ Timeout waiting for CI.');
process.exit(1);
}
main().catch(console.error);

View File

@@ -0,0 +1,18 @@
import { spawnSync } from 'child_process';
import path from 'path';
export async function runFixPlaybook(prNumber: string, targetDir: string, policyPath: string, geminiBin: string) {
console.log(`🚀 Offload | FIX | PR #${prNumber}`);
console.log('Switching to agentic fix loop inside Gemini CLI...');
// Use the nightly gemini binary to activate the fix-pr skill and iterate
const result = spawnSync(geminiBin, [
'--policy', policyPath,
'--cwd', targetDir,
'-p', `Please activate the 'fix-pr' skill and use it to iteratively fix PR #${prNumber}.
Ensure you handle CI failures, merge conflicts, and unaddressed review comments
until the PR is fully passing and mergeable.`
], { stdio: 'inherit' });
return result.status || 0;
}