pr

Installation
SKILL.md

Pull Request

Write or update a PR body that gives reviewers everything they need to understand the change without reading the spec, commit history, or any other document.


Principles

  • Self-contained. The PR body stands on its own. A reviewer should understand what this PR does, why, and what key decisions were made — without reading a spec, commit history, or anything else.
  • Stateless. The PR body always reflects the current scope of the PR relative to origin/main. It is a snapshot, not a journal. When updating, rewrite affected sections to reflect current reality — do not append change notes or leave revision artifacts.

Create workflow tasks (first action)

Before starting any work, create a task for each step using TaskCreate with addBlockedBy to enforce ordering. Derive descriptions and completion criteria from each step's own workflow text.

  1. PR: Gather context — reconcile spec and implementation
  2. PR: Write body — fill template with conditional sections
  3. PR: Apply — create or update PR

Mark each task in_progress when starting and completed when its step's exit criteria are met. On re-entry, check TaskList first and resume from the first non-completed task.


Workflow

Step 1: Gather context

Determine what this PR does from whatever is available:

Input How to use it
PR number provided Run gh pr diff <number> and gh pr view <number>. Read changed files to understand what was built.
SPEC.md path provided Read the spec. Cross-reference with the actual implementation — the code is the source of truth, not the spec.
"new" (no PR yet) Run git diff main...HEAD --stat and read changed files. Understand what was built from the code.
No input Infer from current branch: gh pr view --json number -q '.number' or git diff main...HEAD --stat.

When a SPEC.md exists, use it as source material alongside the implementation. The PR body synthesizes both — spec intent and implementation reality — into a unified narrative. When no SPEC.md exists, derive everything from the code and commit history.

QA screenshot evidence: Check if tmp/ship/screenshots/ exists and has files. If yes, include them in the "Screenshots / recordings" section of the PR body — upload via ship-upload-pr-asset.js or inline as image links. If the directory doesn't exist or is empty, omit the screenshots section.

Step 2: Write the PR body

Fill in each section of the template below. Omit sections that don't apply (noted in each section's guidance). Write for the audience: a reviewer who has not seen the spec or the commit history.

Summary

What this PR does + what problem this solves, why now, who benefits. 1-3 sentences if brief, if multiple pronged, can use numbered list to describe key scenarios/problems being solved. Keep it to the point.

Key decisions

Technical decisions worth scrutinizing: what was chosen, why, and what alternatives were considered. Flag gray areas where reasonable engineers might disagree or where the decision could be revisited. If the implementation diverged from the spec, capture the divergence here with rationale. Omit if the change is straightforward with no meaningful decision points.

Recordings

Video recordings of QA test execution. Omit if no scenarios have evidence[] URLs.

When tmp/ship/qa-progress.json exists, check scenarios for evidence[] arrays containing video URLs. Embed each as a collapsible section:

<details>
<summary>QA-001: settings page renders at mobile viewport</summary>

[Video recording](https://video.bunnycdn.com/play/...)

</details>

When no qa-progress.json exists, omit this section. Video capture is QA's responsibility during execution.

Review setup

Minimal steps to see the change running — env vars, seed data, feature flags, or commands needed to get into a reviewable state. Not a test plan; just how to get the reviewer to a point where they can see the change. Omit if standard dev workflow is sufficient.

Verification

What QA verified and what still needs human eyes. This section covers only scenarios that resist automation — visual correctness, UX flows, integration reality, edge cases, failure modes. Do not restate what the automated test suite covers — reviewers can read the test files.

Source of truth — read in this order:

  1. tmp/ship/qa-progress.json (when it exists): Read the file. Render the following sub-sections in order:

    Coverage by story — Prepend a story-level rollup table. Group scenarios by tracesTo user story ID:

    | Story | Tested | Gaps | Fidelity |
    |-------|--------|------|----------|
    | US-001: Create project | 4/5 ✅ | 1 blocked | browser |
    | US-002: Settings page | 2/3 ✅ | 1 coverage gap | shell _(browser unavailable)_ |
    | _(code-discovered)_ | 3/3 ✅ || browser |
    

    For each story: count validated vs total scenarios tracing to it. If any have status: "failed", "blocked", or "skipped", note the gap count. Show the highest verifiedVia fidelity for that story's scenarios.

    Show the fidelity summary line only when bootstrapResult.achievedFidelity < bootstrapResult.targetFidelity: _QA ran at **<achieved>** fidelity (<target> unavailable). N visual scenarios fell back to <fallback>._

    Verified by QA (N/M) — scenarios with status: "validated". Group by category. For each:

    • Clean pass (notes empty) → - [x] **<name>** — <verifies>
    • Pass with notes → - [x] **<name>** — <verifies> · <notes>

    Needs human verification (K/M) — scenarios with status: "failed", "blocked", or "skipped". No category grouping — list flat with the reason prominent:

    • failed- [ ] **<category>: <name>** — FAILED: <notes>
    • blocked- [ ] **<category>: <name>** — BLOCKED: <notes>
    • skipped- [ ] **<category>: <name>** — Skipped: <notes>

    Omit scenarios still in planned status (QA didn't get to them). If any exist, add a note: "N scenarios not yet executed."

    Gaps — developer action needed — Append after the "Needs human verification" list. Scan scenarios[].enrichment.gapType for non-null values and group by gap type. Render only when at least one scenario has a non-null enrichment.gapType. Map each gap type to an icon and developer action:

    • ⚠️ **Implementation gap** (fixable_gap): — "you may need to implement this"
    • 🔴 **Contradiction** (contradiction): — "the spec assumption was wrong — verify the current behavior is acceptable"
    • 📂 **Stale** (stale): — "this scenario references something that no longer exists — verify manually if user-facing"
    • ✅ **Formalized** (enrichment.formalizable: true): — "this became an automated test — no manual action needed" (informational)

    When no scenarios have a non-null enrichment.gapType (and none are formalizable), omit this sub-section entirely.

  2. Existing ## Verification or ## Manual QA section on the PR body (when no JSON file exists): Read the existing PR body before writing. Incorporate the QA checklist items (with their pass/fail/blocked status) into this section — do not discard them.

  3. Neither exists: Write "No manual QA performed." Do not generate speculative test scenarios. If you believe QA should be run, note: "Consider running /qa to generate and execute a test plan."

Related issues

Links to GitHub issues this PR closes or relates to. Use Closes #123 syntax where applicable. Omit if none.

Future considerations

Items out of scope for this PR but worth tracking. Omit if none.

When tmp/ship/ship-summary.md exists: Read the file and source the "Deferred Scope" and "Surfaced Opportunities" sections from it. Present them as two subsections:

  • Deferred scope — known obligations left behind (work identified as needed during the ship run but consciously not done). These are action items for the team — not blockers for this PR, but things that should be tracked.
  • Surfaced opportunities — informed observations that emerged during implementation, review, or QA. Not obligations — context that would otherwise be lost after merge.

Render each item concisely (one bullet per item). Include the source phase when it adds useful context (e.g., "Phase 5 reviewer flagged"). Do not restate what's already in the Verification section's gaps — Deferred Scope and QA Coverage Gaps are distinct categories.

When no ship-summary.md exists: Derive future considerations from the diff and review context — items surfaced during review that are out of scope but worth tracking. Updated during the review loop as reviewers raise pre-existing or tangential issues.

Step 3: Apply

First, verify gh CLI is available (gh auth status). If unavailable, output the PR body for the user (or the invoking skill) to apply manually — do not fail silently.

Draft vs full PR:

  • Headless mode ($ARGUMENTS includes --headless): Create a full (non-draft) PR. Do not ask.
  • Interactive mode (default): Ask the user whether they want a draft or a full PR before creating.

Dirty working tree check: Before pushing, run git status. If there are uncommitted changes:

  • Interactive mode: Show the user which files have uncommitted changes and ask whether they should be included in this PR. Stage and commit only what the user confirms.
  • Headless mode: Do not commit uncommitted files. Push only what is already committed on the branch. Note any uncommitted changes in the completion output — they may need manual attention.
  • Never stash, reset, or discard uncommitted changes. If the working tree state is too complex to resolve cleanly (e.g., merge conflicts, mixed staged/unstaged in the same file), stop and report the situation rather than attempting to fix it.

Creating a new PR:

git push -u origin <branch>
gh pr create [--draft] --title "<concise title>" --body "$(cat <<'EOF'
<filled-in PR body>
EOF
)"

Include --draft only if the user chose draft (interactive) or omit it entirely (headless).

Updating an existing PR:

gh pr edit <number> --body "$(cat <<'EOF'
<updated PR body>
EOF
)"

When updating, rewrite the full body to reflect current reality. Do not patch individual sections — the body is stateless.


When invoked by other skills

When /review-cloud or another skill delegates PR body work:

  • Accept any context they provide (SPEC.md path, PR number, QA results, review feedback).
  • Return the filled-in PR body for them to apply, or apply it directly if a PR number is available.
  • The invoking skill decides when to update the PR body; this skill handles how.
  • After /ship: The developer invokes /pr after pushing the branch and creating a PR. /ship produces code, tests, docs, and local review — the developer handles PR creation. Check tmp/ship/ for artifacts: qa-progress.json (QA results), review-output.md (local review summary), screenshots/ (QA evidence), ship-summary.md (deferred scope and surfaced opportunities from the ship run).

Calibrating depth

Match PR body depth to what changed:

What changed PR body depth Verification depth
New feature, all scenarios validated, no gaps All sections Story table + verified list (compact)
New feature, some blocked/failed/gaps All sections Story table + verified list + needs-verification list + gaps sub-section (full)
Enhancement, few scenarios Summary, verification. Key decisions if design choices were made. Flat verified/needs-verification lists (no story table)
Bug fix Summary, verification. Flat list only
Config / infra / refactor Summary only. "No manual QA performed."

After PR creation

Keeping the body current

When you push subsequent commits to this branch in the same session (fixes, reviewer feedback, QA improvements, polishing), re-invoke /pr to refresh the body before the conversation ends. The PR body is a stateless snapshot of current scope — a stale body forces reviewers to re-derive context from the diff, defeating the purpose. Not every trivial fix requires a refresh (typo fixes, lint cleanup), but any change that alters what the PR does, what was tested, or what decisions were made warrants an update.

Offer review-cloud

Ask the user: "Would you like me to monitor and auto-address cloud reviewer feedback using /review-cloud?"

Wait for the user's response. Do not invoke /review-cloud automatically.

Related skills

More from inkeep/team-skills

Installs
33
GitHub Stars
10
First Seen
Feb 25, 2026