---
name: platformplatform/create-pull-request
source: https://app.decimal.ai/s/platformplatform-create-pull-request@1/SKILL.md
source_sha256: 653c54619227
---

# Create Pull Request Workflow

## STEP 1: Gather Context

Run in parallel (quick reads, not background):

- `git status` - working tree state
- `git branch --show-current` - local branch
- `git --no-pager log --format=%s --reverse $(git merge-base HEAD main)..HEAD` - commits on the branch
- `git --no-pager diff main` - full diff
- `git rev-parse @{u} 2>/dev/null` - upstream presence (already pushed?)
- `gh pr view --json number,url,state 2>/dev/null` (only if upstream exists) - check if the branch already has an open pull request

## STEP 2: Kick Off Background Work

Everything in this step starts in the background (`run_in_background: true`) so the workflow proceeds without waiting. Results are reconciled in STEP 10.

### Validation

Skip anything already green this session. Only run what's genuinely uncertain.

When validation IS needed:

Run `build` first:
- **Backend change:** `build` (no flags - covers backend AND frontend; backend changes can break the frontend build via API contracts)
- **Frontend-only:** `build --frontend`
- **CLI-only:** `build --cli`

After build, in parallel (with `--no-build` where applicable):

- `aspire-restart` - service / Aspire wiring changed
- `format --<target>`, `lint --<target>` - for each target whose code changed
- `test --no-build` - backend change
- `e2e` - frontend or shared E2E-covered code changed; use `--smoke` for low-impact changes (judgment)

Use judgment to decide which target a file belongs to (e.g. project / manifest / lock files affect their owning build, even when the extension isn't obvious). Each item runs only if needed and not already green.

## STEP 3: Verify Branch Name

Three checks - all read-only at this stage; renames happen in STEP 8.

1. **Strip `worktree-` prefix.** Local-only convention; never push it.
2. **Naming convention.** Lowercase kebab-case.
3. **Drift check.** If the slug no longer describes the work (e.g. `fix-login-bug` whose commits do a refactor), draft a new name.

If either check 1 or check 3 fires, stash the proposed new name; STEP 4 will ask the user to confirm.

## STEP 4: Ask the User

Ask everything upfront so the user doesn't wait through slow research/drafting just to be prompted at the end. Single AskUserQuestion call, up to four questions:

1. **Labels** (multi-select, can pick zero or more): `Enhancement`, `Bug`, `Deploy to Staging`.
2. **Pull request checklist** (single-select): the recommended option spells out every `[ ]` item from `.github/PULL_REQUEST_TEMPLATE.md` in present-tense (e.g. for the current template: "Confirm you have added tests, done manual regression tests, and updated the documentation"). The alternative is "Leave checklist items unchecked".
3. **Review before pushing** (single-select): "Show me the rendered title and description before pushing" / "Push immediately".
4. **Branch rename confirmation** (single-select), only if STEP 3 flagged a rename: "Rename `<current>` to `<proposed>`?" with options Yes / No / Use a different name (free-text).

Stash the answers; consumed in STEP 6, 7, 8, 11.

## STEP 5: Correlate to [Task]

Look up `.claude/reference/product-management/[PRODUCT_MANAGEMENT_TOOL].md` for [Task] ID format and MCP tools.

1. **Parse [Task] ID from branch name.** The exact pattern depends on the configured [PRODUCT_MANAGEMENT_TOOL] — check `.claude/reference/product-management/[PRODUCT_MANAGEMENT_TOOL].md`. Strip `worktree-` first if present.

2. **If [Task] detected**, fetch via MCP. Use its title, description, and parent [Feature] to validate the draft in STEP 6 and spot drift.

3. **Detect unrelated commits (rare).** If some commits clearly belong to a different scope, offer to create a **new [Task]** as future follow-up - written as a fresh problem statement (future tense, what needs to happen). [Feature] choice: parent [Feature] of current branch's [Task] -> [Feature] with [Active] status -> ask.

4. **If no [Task] in the branch name**, ask: "No [Task] detected. Create one for this pull request?". If yes, draft a [Task] from the diff (problem statement, not what was done) and create it via MCP. Suggest a [Feature] using the same rules as above.

## STEP 6: Draft Title and Description

### Title

Write a fresh title based on the actual diff, commits, and [Task] context - not the branch name (branch names are often abbreviated and won't make a good title).

- Imperative form ("Fix", "Add", "Upgrade", "Refactor")
- Sentence case (not Title Case)
- No trailing period
- No "Pull Request" / "PR" / abbreviations
- No personal pronouns ("we", "our", "he", "she")
- No [Task] IDs in the title

### Description

Use the official template at `.github/PULL_REQUEST_TEMPLATE.md`:

- **Summary & Motivation**: lead with the most important change, explain what and why (not how), use bullets for multiple items, mention minor fixes last. **Do not end with a closing benefit summary** - that is the most common rejection reason.
- **No "pull request" or "pull-request" in the body** - CI rejects either phrase. Use "this change", "the change", etc.
- **Checklist**: copy items from the template. Render every `[ ]` as `[x]` if the user picked "Mark all checklist items..." in STEP 4; otherwise leave them as `[ ]`.

Save the rendered title (as a level-1 heading) + body to `.workspace/<branch-name>/pull-request.md`. Use the un-prefixed branch name if STEP 3 stripped `worktree-`.

## STEP 7: Optional Review Gate

If the user picked "Show me before pushing" in STEP 4:

- Print the rendered title and the body inline.
- Ask "Open pull request with this content? (yes / edit)".
- On "edit", let the user dictate changes. Re-save the markdown. Re-confirm.

Otherwise skip this step.

## STEP 8: Branch Hygiene

If STEP 4 confirmed a rename, rename the branch and verify. Safe in a worktree (directory path is independent of branch name). The push step sets the new upstream.

## STEP 9: Push

1. Re-check upstream tracking with `git rev-parse @{u} 2>/dev/null`.
2. **If unset** (branch never pushed, or just renamed): ask "Branch is local-only. Push to origin?". On confirm, push and ensure the pushed branch has upstream tracking (`git push --set-upstream origin "$(git branch --show-current)"`).
3. **If upstream exists**, check divergence:
   - `git log --oneline @{u}..HEAD` (local-ahead)
   - `git log --oneline HEAD..@{u}` (remote-ahead)
   - If remote-ahead: surface the divergence and stop. Don't force-push without an explicit user request.
   - If only local-ahead: `git push`.

## STEP 10: Wait for Background Validation

Check the status of the background tasks started in STEP 2.

- **Done and passed**: continue silently.
- **Done and failed**: print the failure and pause. Do not push or open the pull request until the user decides (fix / push anyway / abort).
- **Still running**: surface the status. Ask "Wait for completion, or proceed?". If proceeding, mention that CI will re-run these.
- **Killed earlier (user opt-out)**: skip.

## STEP 11: Create or Update the Pull Request via gh

Pre-flight: `gh auth status`. If not authenticated, surface and stop.

Use the existing pull request check result from STEP 1.

**If an open pull request already exists for this branch:**

```sh
gh pr edit <number> \
  --title "<title>" \
  --body-file ".workspace/<branch>/pull-request.md" \
  --add-label "<each-selected-label>"
```

(Strip the level-1 heading from the body file before passing.) Tell the user the pull request was updated, not newly created. Don't change draft/ready state without an explicit ask.

**If no pull request exists:**

```sh
gh pr create \
  --title "<title>" \
  --body-file ".workspace/<branch>/pull-request.md" \
  --base main \
  --assignee @me
```

Append `--label "<name>"` per label from STEP 4. `@me` resolves to the authenticated user. Don't pass `--draft`; this workflow opens ready-for-review.

Capture the pull request URL from gh's output for STEP 12.

## STEP 12: Report

Print:

- The pull request URL (clickable)
- Title
- Labels applied
- [Task] linked via branch name (auto by [PRODUCT_MANAGEMENT_TOOL])
- Pull-request markdown saved at the absolute path

End with a clickable link to the saved file.

## Examples

### Example 1 - Title

```
# DO: imperative, sentence case, no period
Add user profile image upload functionality
Fix data protection key sharing between self-contained systems
Upgrade dependency versions to latest stable releases

# DON'T: past tense, period, title case, prefixes
Added User Profile Image Upload Functionality.
PR: Implement new feature
Updating dependencies
```

### Example 2 - Description

```markdown
### Summary & Motivation

Add data protection key sharing between self-contained systems to fix antiforgery token validation failures. Previously, each self-contained system had isolated encryption keys, causing tokens generated in one system to be invalid in another.

- Configure a common application name for all self-contained systems
- Store keys in a user-accessible directory on disk

# DO: stop here - no closing benefit summary

### Checklist

- [x] I have added tests, or done manual regression tests
- [ ] I have updated the documentation, if necessary
```

```markdown
### Summary

# DON'T: personal pronouns, past tense, "pull request" term, vague descriptions
In this pull request we fixed a bug causing issues in our scs's.

- We added some configuration.
- Fixed a bug.

These changes make the system more robust and maintainable. # DON'T: closing summary
```

### Example 3 - Branch with `worktree-` prefix

Local: `worktree-fix-login-redirect` -> propose `fix-login-redirect` (rename in STEP 8, push in STEP 9).

### Example 4 - Branch drift

Local: `fix-login-redirect`. Actual work: refactored the login command and added auto-redirect.

Propose `refactor-login-command-with-auto-redirect`. Confirm in STEP 4; rename in STEP 8.

### Example 5 - Unrelated commits

Branch: `fix-login-redirect`. Commits: the redirect fix + an unrelated typo fix in README.

Surface the typo commit. Offer to create a new [Task]: "Fix typo in README troubleshooting section" (problem statement, future tense). The pull request continues with both commits.

### Example 6 - End-of-output report

```
Pull request opened: https://github.com/<owner>/<repo>/pull/123

Title:        Fix login redirect after OTP verification
Labels:       Bug, Deploy to Staging
[Task]:       linked via branch name (auto-detected by [PRODUCT_MANAGEMENT_TOOL])
Description:  /absolute/path/to/repo/.workspace/fix-login-redirect/pull-request.md
```