diff --git a/.gemini/skills/fix-pr/SKILL.md b/.gemini/skills/fix-pr/SKILL.md new file mode 100644 index 0000000000..216e8cff1c --- /dev/null +++ b/.gemini/skills/fix-pr/SKILL.md @@ -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 -- `). + - 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 "` + - `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. diff --git a/.gemini/skills/fix-pr/scripts/wait-for-ci.ts b/.gemini/skills/fix-pr/scripts/wait-for-ci.ts new file mode 100644 index 0000000000..b31418a3da --- /dev/null +++ b/.gemini/skills/fix-pr/scripts/wait-for-ci.ts @@ -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); diff --git a/.gemini/skills/offload/scripts/playbooks/fix.ts b/.gemini/skills/offload/scripts/playbooks/fix.ts new file mode 100644 index 0000000000..23adb2e2c7 --- /dev/null +++ b/.gemini/skills/offload/scripts/playbooks/fix.ts @@ -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; +}