Pr Ship

Autonomously iterate on a PR — local CI, code review, remote CI, review comments, merge conflicts — until ready to merge

tstapler 7 updated 23d ago
Claude CodeGeneric
View source ↗
---
description: Autonomously iterate on a PR — local CI, code review, remote CI, review comments, merge conflicts — until ready to merge
prompt: |
  # PR Ship Loop — Make It Ready to Merge

  Drive PR `${1:-$(gh pr list --head $(git branch --show-current) --json number --jq '.[0].number')}` to a mergeable state by iterating through five ordered gates until all are green.

  ## State File

  All progress is tracked in `/tmp/pr-ship-${REPO_SLUG}-${BRANCH_SLUG}-${PR}.md`. Read it at the start of every iteration to understand what's already done. Update it after every action. This is your working memory across ScheduleWakeup wakeups.

  **State file format** (initialize if missing):
  ```markdown
  # PR Ship State — PR #N
  Iteration: 0
  Branch: <branch>
  Base: <base-branch>

  ## Changed Files
  (populated once from `gh pr diff "$PR" --name-only`)
  - path/to/file.go

  ## Gate Status
  - [ ] Gate 1a: Local compile
  - [ ] Gate 1b: Local tests (changed packages only)
  - [ ] Gate 2:  Code review clean
  - [ ] Gate 3:  PR review comments addressed
  - [ ] Gate 4:  Remote CI green
  - [ ] Gate 5:  No merge conflicts

  ## Push History
  (append after each push: `- COMMIT_SHA pushed at ITERATION N`)

  ## Code Review Issues
  ### Open
  (populated after Gate 2 runs; format: `- [ ] FILE:LINE — DESCRIPTION [severity]`)

  ### Resolved
  (moved here when fixed; format: `- [x] FILE:LINE — DESCRIPTION [fixed in COMMIT]`)

  ## Decision Log
  (one line per iteration: what gate advanced, what was done, commits made)

Entry Check

PR="${1:-$(gh pr list --head $(git branch --show-current) --json number --jq '.[0].number')}"
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' | tr '/' '-')
BRANCH=$(gh pr view "$PR" --json headRefName --jq '.headRefName' | tr '/' '-' | tr '_' '-' | cut -c1-40)
STATE="/tmp/pr-ship-${REPO}-${BRANCH}-${PR}.md"
gh pr view "$PR" --json number,title,state,mergeable,mergeStateStatus,headRefName,baseRefName

If the PR is already merged or closed, report that and stop.

Read the state file. If it doesn't exist, initialize it. Populate Changed Files once using:

gh pr diff "$PR" --name-only

Never re-derive the changed files list from scratch — use what's in the state file.


Context Discipline — Orchestrator Only

This skill is an orchestrator, not a worker. Delegate all file editing, compiling, and committing to fresh subagents. Never accumulate file contents or diffs in this context — only gate status and state file updates. This is the lean-agent-loop skill pattern: the state file is the coordinator's memory, each fresh subagent is a Ralph Wiggum agent, and the five gates are the loop condition.

Orchestrator (this context)
  └─ reads state file, checks gate, collects failure details
     └─ spawns Agent(prompt="Fix these specific failures: ...") → waits for result
        └─ fresh agent does all file reading, editing, testing, committing, pushing

After each agent returns: verify the fix locally (run the relevant check command), update the state file, append to Decision Log, then advance to the next gate.


The Loop (max 10 iterations; stop if no gate advances)

At the top of each iteration, increment Iteration: in the state file. Read Gate Status. Skip gates already marked [x]. Process gates in order — do not jump ahead.

Gate 1a — Local Compile

Only run if [ ]. Detect stack from repo contents, then compile:

Stack Compile check
Java/Maven ./mvnw compile -q
Kotlin/KMP ./gradlew compileTestKotlinJvm --no-daemon
Go go build ./...
TypeScript npx tsc --noEmit
JS npm run build

If it fails: delegate to a fresh agent with the exact error and the repo path. After agent returns, re-run the same compile command to verify — do not mark [x] until you confirm it passes. Update state file.

Gate 1b — Local Tests (changed packages only)

Only run if [ ] and Gate 1a is [x]. Scope tests to only the packages/modules containing changed files:

Stack Scoped test command
Go `go test $(git diff --name-only origin/...HEAD | grep '.go$' | xargs -I{} dirname {} | sort -u | sed 's
Java/Maven ./mvnw test -pl $(changed modules) -q
TypeScript npm test -- --testPathPattern="<changed files>"
Kotlin/KMP ./gradlew jvmTest --no-daemon

If a scoped command is too complex to derive, fall back to the full test suite. If it fails: delegate to a fresh agent with failing test output. After agent returns, re-run the failing tests to verify — not the full suite, just the specific failing ones. Mark [x] only after the re-run passes.

Gate 2 — Code Review (changed files only)

Only run if [ ] and Gates 1a+1b are [x].

Invoke the code review skill on the current diff (it naturally scopes to changed files):

/code:review --fix

Parse the findings. Write all BLOCKER and CRITICAL issues to ## Code Review Issues → Open in the state file. Write MAJOR issues too. Suggestions/NITs are optional — log them but don't block.

Delegate a fresh agent to fix all BLOCKER/CRITICAL/MAJOR issues. Include in the agent prompt:

  • The state file path
  • Each open issue with file, line, severity, description
  • Instruction to commit (but NOT push — Gate 3 handles the push decision)

After the agent returns:

  1. Re-run /code:review to verify no new BLOCKER/CRITICAL issues
  2. Move fixed issues to Resolved in the state file with the commit SHA
  3. Repeat until no BLOCKER/CRITICAL/MAJOR issues remain
  4. Mark [x] in state file

Gate 3 — PR Review Comments

Only run if [ ] and Gates 1a+1b+2 are [x]. Address all reviewer feedback before pushing so CI runs on code reviewers have already seen and haven't flagged.


Maintain Pr Ship?

Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.

[Pr Ship on getagentictools](https://getagentictools.com/loops/tstapler-pr-ship?ref=badge)