create-pr · v2.2.0 · 2026-09-09 · sha256 ce0cb07c15fe1ea5
create-pr v2.2.0A
Immutable. This exact content is served forever at /api/v1/blob/ce0cb07c15fe1ea5.
---
name: create-pr
description: Create a pull request from the current branch following project conventions. Uses the branch name to find the Jira ticket, generates a PR with the standard template, audits publication artifacts, pushes to origin, and closes the associated bead.
allowed-tools: "Read,Bash(git:*),Bash(~/.agents/skills/start-ticket/scripts/git-branch-preflight.sh:*),Bash(~/.agents/skills/artifact-hygiene/scripts/artifact_hygiene.py:*),Bash(~/.agents/skills/next/scripts/next-select:*),Bash(bd close:*),Bash(bd list:*),Bash(bd show:*),Bash(bd update:*),Bash(~/.agents/skills/create-pr/scripts/gh-pr-create.sh:*),Bash(gh pr create:*),Skill,AskUserQuestion"
model-tier: standard
model: sonnet
effort: medium
version: "2.2.0"
author: "flurdy"
---
# Create Pull Request
Create a pull request from the current branch using project conventions.
## Usage
```
/create-pr # Resolve recorded/default base
/create-pr {base-branch} # Explicit base, including a stacked parent
/create-pr --draft {base-branch} # Create a draft PR against that base
```
## Instructions
Parse optional `--draft` plus at most one `{base-branch}`. Reject unknown or duplicate arguments.
Expand `{draft-flag}` to `--draft` when requested and to nothing otherwise.
### 1. Gather context
Get the current branch and working-copy state:
```bash
git branch --show-current
git status -sb
```
If the branch is empty, stop: HEAD is detached. Preserve the commit on a branch before attempting
to push or create a PR.
### 2. Resolve the PR base
Use the first available source:
1. explicit `{base-branch}` argument;
2. `git config --get branch.{branch-name}.gh-merge-base` (recorded by `/stack-branch`);
3. the default branch from `origin/HEAD`, falling back to local `main`, then `master`.
If the result is empty, equals the head branch, or does not resolve to a commit, ask rather than
guessing. Fetch the selected base, then use it consistently for context and PR creation:
```bash
git fetch origin {base-branch}
git log origin/{base-branch}..HEAD --oneline
git diff origin/{base-branch}...HEAD --stat
```
### 3. Extract Jira Ticket from Branch Name
Parse the branch name to find the ticket number:
- Pattern: `{type}/{TICKET-NUMBER}-{description}`
- Example: `feat/AB-123-sanitize-input` → `AB-123`
- Ticket format: 2-4 uppercase letters, dash, numbers (e.g., `AB-123`, `SSP-456`)
If no ticket found, ask the user.
### 4. Look Up Jira Ticket
Use [jira-ticket](../jira-ticket/SKILL.md) for the key, summary and description. It owns tool
availability, deferred discovery and unavailable-context handoffs. If skill invocation is absent,
read that installed skill and follow it; do not reconstruct the lookup. Missing context remains
unavailable in the draft unless supplied by the user; never fabricate fetched requirements.
### 5. Generate PR Title
Use conventional commit format based on branch prefix:
| Branch Prefix | PR Title Format |
|---------------|-----------------|
| `feat/` | `feat(<scope>): <description>` |
| `fix/` | `fix(<scope>): <description>` |
| `refactor/` | `refactor(<scope>): <description>` |
| `chore/` | `chore(<scope>): <description>` |
| `docs/` | `docs(<scope>): <description>` |
| `perf/` | `perf(<scope>): <description>` |
Infer the scope from changed files (e.g., `offers-cms`, `web`, `api`).
### 6. Generate PR Body
Analyze the actual code changes (use `git diff origin/{base-branch}...HEAD`) to write a meaningful description.
House style: say what changed in general terms, easy to digest. Keep the why brief or absent
(Jira/Trello owns it) and details minimal (the commits and diff own them). No test narrative, no
future-task lists, no names, no bead IDs.
Check for a repo-specific PR template at `.github/pull-request-template.md` or `.github/pull_request_template.md`. If found, use that format. If not, ask user for confirmation on generating the body ourselves.
### 6a. Publication audit
From the same repository/worktree whose branch will be published, run the authoritative,
local-only, read-only helper (Python 3.10+, Git and Gitleaks required):
```bash
~/.agents/skills/artifact-hygiene/scripts/artifact_hygiene.py --pretty
```
Capture stdout and exit status, including nonzero exits. Render **coverage before findings**
using [artifact-hygiene's Report contract](../artifact-hygiene/SKILL.md#report): exact status/verdict,
each source's status and safe error codes, normalized redacted findings, and `suppressed` counts
with clone-local allowances disclosed. Use only the helper's normalized evidence; partial is never clean.
Never recover raw evidence from reported files, commits, scanner output, or configuration.
Remediation is a separate explicitly approved task; do not edit artifacts, rewrite history, change
allowances, install tooling, or copy detectors as part of this audit step.
Exit `0` alone is not clearance: it includes complete reports with findings. Continue only with
valid `artifact-hygiene/v1` JSON, exit `0`, `status: complete`, `verdict: clean`, no findings, and every
required coverage source present and complete. On findings, exit `2` (partial), exit `3` (failed), missing helper/scanner,
malformed output, or any other incomplete coverage, **stop before push or PR creation**. Render the
available redacted report or an unavailable diagnostic, never a fabricated clean result.
This audits the full publishable working tree and the helper's locally resolved unpublished history,
not the PR diff or drafted title/body. Do not pass a PR base or narrow its findings to the selected
change; the helper has no diff/base option. §6's draft review still applies. An already-published
branch still needs this audit before PR creation; a result cannot undo prior publication.
Use fresh evidence from this invocation. Any intervening edit, staging change, commit, ref or audit
policy change invalidates it; rerun before asking for publication approval. A clean audit is not consent:
§7 and §8 retain their separate immediately-before-action confirmations and standalone commands.
### 7. Confirm push
Run the shared preflight immediately before deciding whether publication is needed:
```bash
~/.agents/skills/start-ticket/scripts/git-branch-preflight.sh {branch-name}
```
Skip this phase only when `target_published=true`: HEAD matches the exact `origin/{branch-name}` destination.
Never infer publication from a parent upstream or stale remote-tracking ref. On `unknown` or a
preflight error, stop. Otherwise show the exact branch and remote. Use `AskUserQuestion`
**immediately before** the push. If approved, the push must be the next tool call, standalone and unchained:
```bash
git push -u origin {branch-name}
```
Approval applies only to this push. A retry requires fresh confirmation. If declined, stop before
PR creation.
### 8. Confirm PR creation
Even if the push phase was skipped, rerun §6a before the PR-creation confirmation. Stop on any
non-clean or unavailable audit result. Then show the user the target, title, and complete body draft. Use `AskUserQuestion`
**immediately before** creating the PR. Push approval does not authorize this second remote action.
If approved, invoke the wrapper as the next tool call, standalone and unchained:
```bash
~/.agents/skills/create-pr/scripts/gh-pr-create.sh {draft-flag} --base {base-branch} --title "{title}" --body "$(cat <<'EOF'
{body}
EOF
)"
```
If the script is unavailable, show and separately confirm the fallback before running it:
```bash
gh pr create {draft-flag} --base {base-branch} --title "{title}" --body "$(cat <<'EOF'
{body}
EOF
)"
```
### 9. Close the Associated Bead
Once the PR is created, close the bead for this work — this is the preferred close point in a PR workflow (the commit was done in `/complete-task`, which deliberately left the bead open for this step). Reopen later if review demands major changes.
Skip this whole step silently if `bd` is unavailable or the repo has no beads database.
1. Find the in-progress bead for this work:
```bash
bd list --status=in_progress
```
Match by the Jira key from §3 appearing in the bead title/description, or an obvious 1:1 correspondence to the branch.
2. If multiple beads plausibly match, ask the user which (if any) to close with `AskUserQuestion`. If none match, skip silently — don't invent one.
3. Resolve the chosen bead to its owning store before closing. Never infer the store from the ID or the cwd; at a workspace root the cwd store is the workspace store, not the repository the PR belongs to.
```bash
~/.agents/skills/next/scripts/next-select resolve <bead-id>
```
| status | action |
|---|---|
| `resolved` | take `directory`; close and reopen with `bd -C <directory>` |
| `ambiguous` | show `matches[].selector`, ask which `<repo>:<id>` is meant; close nothing |
| `unavailable` | report `failures`; the PR stands, the bead stays `in_progress`, say why |
| `not-found` | skip the close and say so; never guess another store |
4. Close it in that store, referencing the PR:
```bash
bd -C <directory> close <bead-id> --reason="PR #<number> created: <pr-title>"
```
5. Tell the user the bead was closed and how to reopen it if review requires major changes:
```bash
bd -C <directory> update <bead-id> --status=in_progress
```
Note: `/ready-to-merge` closes a bead only if it is `in_progress`. It therefore no-ops when this
close remains current, but closes it post-merge if `/review-comments` reopened it for substantial
review work.
### 10. Return Result
Output the PR URL so the user can view it, and note the bead that was closed (or left open, if none matched).