Pull Request Workflow (Author)
Create and update pull requests as an author: prepare PRs, push for review, then address reviewer feedback.
Which Phase Are You In?
| Phase | Triggers | Details |
|---|---|---|
| CREATE | "create a PR", "make a pull request", "open a PR", "submit for review" | → See CREATE section below |
| ITERATE | "address PR review", "fix PR feedback", "address review comments" | → See ITERATE section below |
When your PR is ready to merge, reviewers use the review-pull-request skill to validate.
Prerequisites
Before starting any mode, ensure:
- You're in a git repository
- GitHub CLI is installed and authenticated (
gh auth login) - You have write access to the repository
CREATE Mode: New PR
Creates a new pull request with comprehensive safety checks.
PR Template and Structure
- If the repo has a pull request template in
.github/pull_request_template.mdor.github/PULL_REQUEST_TEMPLATE/, always use it. - Use the template's section headings and checklist in the PR body. Fill in each section; keep any links (e.g. Contributing guide) at the bottom.
- If there is no template, still apply the title and body preferences below.
- Do not add or change the template file itself unless explicitly requested.
Workflow
- Setup: Fetch latest, rebase feature branch
- Files: Select files to stage
- Validate & Fix: Check artifacts/secrets, run pre-commit hooks
- Test & Document: Run tests, update CHANGELOG/README/docstrings
- Commit & Push: Create commit message, push to origin
- Create PR: Push branch, create draft PR via gh-cli, clean up temp files
Title Preferences
- Short, scoped, action-oriented. Prefer:
Scope: what the PR does. - Examples:
CLI: add retry flag for transient errors,Pipelines: add step for X. - Human-readable summary, not a raw Conventional Commit line.
- No ticket prefixes in the title unless the team convention requires it.
Body Preferences
Outcome-focused, not implementation-focused. Describe what the change enables, replaces, or delivers — not how it works internally. Reviewers can read the diff; they need context on why this matters and what it unblocks.
- ❌ "Adds
FromFilename(filename, stackVersion string) (Package, error)that infers type/arch/OS from the filename" - ✅ "Classifies artifact filenames into typed manifest entries, covering all package formats the RM currently handles"
For feature/fix PRs: Short bullet list. One bullet per main change; outcome phrasing.
For refactoring/architectural PRs: High-level narrative format (Problem → Solution → Impact) explaining why the changes matter. Include impact metrics or scope.
Always include:
- When the change has measurable impact (performance, reduced lines, security fixes): add a short impact block with before/after or what is skipped.
- Issue ticket: Include the tracking issue link (cross-repo format if needed:
owner/repo#N). If no issue is obvious from context, ask the user before writing N/A — don't assume there isn't one. - Checklist: Use
- [ ]or- [x]per actual state; keep the template checklist and links at the bottom. - Test plan scope: checkboxes are for things verifiable during review, before merge, only. Anything that can only happen after merge (cutting a release, bumping a downstream pin, re-running an external integration test) goes in a separate plain-bullet "Follow-up" section — a checkbox implies verify-before-merge, and closed PRs don't get revisited to check boxes later.
Example PR body (feature/fix)
## Describe your changes
- Extract dependency installation into setup script
- Reuse existing virtualenv when requirements unchanged
**Pre-commit duration impact:**
- **Before this PR:** ~49s total
- **After this PR:** ~12s total (90% faster)
## Issue ticket
Closes #123
## Checklist before requesting a review
- [x] Tests pass locally
Example PR body (refactoring/architectural)
## Problem
[1-2 sentences: What's broken, confusing, or suboptimal]
## Solution
[How you're fixing it, organized by theme]
## Impact
[User/maintainer/operational benefits]
## Metrics
- [Before/after stats: lines, complexity, performance, security]
CREATE Instructions
Phase 1: Setup
Always branch from the repo's default branch (usually main) explicitly: git checkout -b <branch> main.
git fetch origin
CURRENT_BRANCH=$(git branch --show-current)
# Infer default branch from origin (e.g., main or master)
DEFAULT_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')
if [ -z "$DEFAULT_BRANCH" ]; then
DEFAULT_BRANCH="main"
fi
# If on main/master, ask for feature branch name and create it from the default branch
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
echo "Enter feature branch name:"
read -r FEATURE_BRANCH
git checkout -b "$FEATURE_BRANCH" "origin/$DEFAULT_BRANCH"
else
FEATURE_BRANCH=$CURRENT_BRANCH
fi
# Rebase on the default branch
if ! git merge-base --is-ancestor "origin/$DEFAULT_BRANCH" HEAD; then
GIT_EDITOR=true git rebase "origin/$DEFAULT_BRANCH" || {
echo "❌ Rebase conflict. Resolve manually, retry."
git rebase --abort
exit 1
}
fi
echo "✅ Up-to-date with $DEFAULT_BRANCH"
Phase 2: File Selection
git status --porcelain
# Ask user: which files to stage?
# Offer categories: Modified | Untracked | All
Auto-exclude: .gitignore patterns, temp files, virtual envs, build artifacts
Phase 3: Validate & Fix
Check files:
- ⚠️ No temporary agent artifacts (
.analysis,.report,.debug) - ⚠️ No temp files (
.tmp,.lock,.swp,~,.DS_Store) - ⚠️ No untracked files (should they be staged?)
- ⚠️ No secrets (password, api_key, token, credential fields)
Run pre-commit fixes:
git diff --cached | grep -iE '(password|secret|api[_-]?key|token|credential)["\s]*[:=]' && { exit 1; }
make pre-commit || make format # Auto-fix linting/formatting
Phase 4: Test & Document
Run tests (skip for docs-only changes):
STAGED=$(git diff --cached --name-only)
if echo "$STAGED" | grep -vqE '\.(md|txt)$'; then
make test || { echo "❌ Tests failed"; exit 1; }
fi
Update documentation (if code changed):
- CHANGELOG.md (if repo uses one)
- README (for user-facing changes)
- Function docstrings
Phase 5: Prepare Commit & PR
Commit message (summarizing changes):
Brief summary from changed files
- Key change 1
- Key change 2
PR description (from commit message + testing status):
## Summary
[From commit message]
## Changes
[From git diff summary]
## Testing
- Tests: ✅ Passing
Save both to COMMIT_MESSAGE.md and PR_DESCRIPTION.md.
Phase 6: Push & Create PR
Before proceeding: Confirm that you're ready to push to origin and create the PR. Review the commit message and PR body one more time if needed.
Confirmation: Ask the user: "Ready to push to origin and create PR? (yes/no)"
Only proceed if user explicitly confirms.
Options: Draft by default; use --repo <owner/repo> for non-current repo; use Closes #X in body for issue linkage.
If confirmed:
git commit -F COMMIT_MESSAGE.md
git push -u origin $FEATURE_BRANCH
gh pr create \
--base main \
--head $FEATURE_BRANCH \
--draft \
--title "<auto-generated-title>" \
--body-file PR_DESCRIPTION.md
# Cleanup temp files
rm -f COMMIT_MESSAGE.md PR_DESCRIPTION.md
echo "✅ PR created"
ITERATE Mode: Address Feedback
Address review feedback on an existing PR.
Workflow
- Auto-detect PR: Find PR from current branch
- Fetch comments: Get all review comments via GitHub API
- Categorize: Sort as must-fix/enhancement/NIT
- Fix & validate: Apply fixes, run tests, scan for similar patterns
- Commit & resolve: Commit fixes, mark comments resolved
- Summary: Show what was done
ITERATE Instructions
Phase 1: Auto-detect PR
PR=$(gh pr view --json number -q .number 2>/dev/null) || {
echo "❌ No open PR for current branch"
exit 1
}
echo "✅ Found PR #$PR"
Phase 2: Fetch Comments
OWNER=$(gh repo view --json owner -q .owner.login)
REPO=$(gh repo view --json name -q .name)
gh api repos/$OWNER/$REPO/pulls/$PR/comments \
--jq '.[] | {id, path, line, body}' > /tmp/pr_comments.json
Phase 3: Categorize Comments
Triage each comment as:
- Must-fix: Safety, correctness, required standards
- Enhancement: Improvements, consistency, best practices
- NIT: Formatting, cosmetic (can skip)
Summarize for user approval: "Fix X must-fixes and Y enhancements? (y/n)"
Phase 4: Apply Fixes
For each must-fix and enhancement:
- Read affected file (use Read tool)
- Apply fix based on comment
- Stage file:
git add <file>
After each fix:
- Re-read the changed block to confirm correctness
- Proactively scan the codebase for the same pattern — don't wait for next review cycle
- Fix all occurrences found in the codebase
Common grep patterns:
# Broad exception handlers
grep -rn "except Exception:" src/
# Missing validation
grep -rn "\.exists()" src/ | grep -v "is_dir"
# Hardcoded values
grep -rn "if.*> [0-9]\|== ['\"]" src/ | grep -v "test"
Safety checks during fixes:
- Agent instructions/settings: Flag if the PR modifies
AGENTS.md,CLAUDE.md,settings.json, or permission files — treat as critical - Cross-codebase patterns: If you flag a pattern, grep for same pattern elsewhere and fix all occurrences
Phase 5: Verify Staged Files
Before committing, check:
- No temporary agent artifacts or temp files
- Only intended files are staged
- If uncertain, unstage and verify
Phase 6: Security & Tests
Same checks as CREATE mode:
- Secrets check
- Pre-commit validation
- Tests (skip docs-only)
- Documentation validation
Phase 7: Commit & Push
git commit -m "fix: address review feedback
- Addressed X comments
- Applied Y improvements"
git push origin $(git branch --show-current)
Phase 8: Resolve Comments
After fixes are pushed, mark comments as resolved:
# For each fixed comment
THREAD_ID=<thread-id>
gh api graphql -f id="$THREAD_ID" -f query='
mutation($id: ID!) {
resolveReviewThread(input: {threadId: $id}) {
thread { id isResolved }
}
}
'
echo "✅ Comment resolved"
Batch resolve all threads using the github skill's batch resolve command.
Mark Ready for Review
Before undrafting or requesting review, run and post local test evidence as a PR comment.
What to run
Check repository agent instructions (such as AGENTS.md or CLAUDE.md) for a ## PR Review section — it lists repo-specific tests tied to the files changed. Run whichever apply:
- Shell scripts / CI scripts: run the changed logic in isolation with mocked inputs; cover the happy path, the rejection path, and edge cases (empty/null/missing values).
- Go pipeline generator: generate pipeline YAML and diff against
main(./LOCAL/check-pipelines.shif available). - Python code: run the relevant pytest suite (
venv/bin/pytest tests/ -v). - Other: run whatever
make test/ pre-commit hooks exercise for the changed files.
Posting results
Post a comment on the PR with a summary table before marking ready. Example format:
| Test | Scenario | Result |
|------|----------|--------|
| T1 | happy path | ✅ pass |
| T2 | rejection | ✅ pass |
| T3 | edge case | ✅ pass |
If a test can't be run locally (requires live infra, secrets, or a full pipeline run), note that explicitly so reviewers know what coverage is missing.
Next: Request Review
Once tests are posted and fixes are pushed, undraft and request review. Reviewers will use the review-pull-request skill to validate merge readiness.