pr
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.
- PR: Gather context — reconcile spec and implementation
- PR: Write body — fill template with conditional sections
- 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:
-
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
tracesTouser 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 highestverifiedViafidelity 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 bycategory. 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
plannedstatus (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.gapTypefor non-null values and group by gap type. Render only when at least one scenario has a non-nullenrichment.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. - Clean pass (notes empty) →
-
Existing
## Verificationor## Manual QAsection 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. -
Neither exists: Write "No manual QA performed." Do not generate speculative test scenarios. If you believe QA should be run, note: "Consider running
/qato 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 (
$ARGUMENTSincludes--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/prafter pushing the branch and creating a PR./shipproduces code, tests, docs, and local review — the developer handles PR creation. Checktmp/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.
More from inkeep/team-skills
qa
Manual QA testing — verify features end-to-end as a user would, by all means necessary. Exhausts every local tool: browser (Playwright), Docker, ad-hoc scripts, REPL, dev servers. Mock-aware — mocked test coverage does not count. Proves real userOutcome at highest achievable fidelity. Blocked scenarios flow to /pr as pending human verification. Standalone or composable with /ship. Triggers: qa, qa test, manual test, test the feature, verify it works, exploratory testing, smoke test, end-to-end verification.
61cold-email
Generate cold emails for B2B personas. Use when asked to write cold outreach, sales emails, or prospect messaging. Supports 19 persona archetypes (Founder-CEO, CTO, VP Engineering, CIO, CPO, Product Directors, VP CX, Head of Support, Support Ops, DevRel, Head of Docs, Technical Writer, Head of Community, VP Growth, Head of AI, etc.). Can generate first-touch and follow-up emails. When a LinkedIn profile URL is provided, uses Crustdata MCP to enrich prospect data (name, title, company, career history, recent posts) for deep personalization.
54spec
Drive an evidence-driven, iterative product+engineering spec process that produces a full PRD + technical spec (often as SPEC.md). Use when scoping a feature or product surface area end-to-end; defining requirements; researching external/internal prior art; mapping current system behavior; comparing design options; making 1-way-door decisions; negotiating scope; and maintaining a live Decision Log + Open Questions backlog. Triggers: spec, PRD, proposal, technical spec, RFC, scope this, design doc, end-to-end requirements, scope plan, tradeoffs, open questions.
54ship
Orchestrate any code change from requirements to review-ready branch — scope-calibrated from small fixes to full features. Composes /spec, /implement, and /research with depth that scales to the task: lightweight spec and direct implementation for bug fixes and config changes, full rigor for features. Produces tested, locally reviewed, documented code on a feature branch. The developer pushes the branch and creates the PR. Use for ALL implementation work regardless of perceived scope — the workflow adapts depth, never skips phases. Triggers: ship, ship it, feature development, implement end to end, spec to PR, implement this, fix this, let's implement, let's go with that, build this, make the change, full stack implementation, autonomous development.
52docs
Write or update documentation for engineering changes — both product-facing (user docs, API reference, guides) and internal (architecture docs, runbooks, inline code docs). Builds a world model of what changed and traces transitive documentation consequences across all affected surfaces. Discovers and uses repo-specific documentation skills, style guides, and conventions. Standalone or composable with /ship. Triggers: docs, documentation, write docs, update docs, document the changes, product docs, internal docs, changelog, migration guide.
52implement
Convert SPEC.md to spec.json, craft the implementation prompt, and execute the iteration loop via subprocess. Use when converting specs to spec.json, preparing implementation artifacts, running the iteration loop, or implementing features autonomously. Triggers: implement, spec.json, convert spec, implementation prompt, execute implementation, run implementation.
52