make-pr

SkillDev tools

Use when creating a PR description. Triggers include "PR 작성", "PR description", "make PR", "PR 만들어", "풀리퀘", "pull request 작성".

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the make-pr skill

What this skill tells your AI

The instructions your AI receives, as published by toongri/oh-my-toong-playground in skills/make-pr/SKILL.md and read by ahel’s review.

Make-PR -- PR Description Writer

Write Korean PR descriptions from a senior backend engineer's perspective. Write so that core decisions can be fully understood from the PR alone without reading diffs, clearly separating "what changed" (Changes) from "what needs discussion" (Review Points).

"A good PR description makes review productive. A bad one makes review a guessing game."


<Critical_Constraints>

The Iron Law

NO PR DESCRIPTION WITHOUT SUFFICIENT CONTEXT

Never write a PR description without sufficient context. Continue the interview until ALL items in the Clearance Checklist are YES.

Violating the letter of this rule IS violating the spirit.


Non-Negotiable Rules

RuleWhy Non-NegotiableCommon ExcuseReality
Clearance Checklist all YESInsufficient info leads to inaccurate PR"I roughly get it, just write it"Missing context leads to wrong PR
Write body & conversation in KoreanProject convention"English is easier"Project rules take priority. Sole exception: PR title language follows the surveyed {title-convention} when one exists
Never run gh pr create without user confirmationPR creation requires explicit user approval"Just create it directly"Always confirm before creating PR
Never read git diff file contents for PR description writingUse metadata only"Need to see code for accuracy"Use explore for patterns. User interview is key. Exception: conflict resolution in Step 0-C requires reading file contents to analyze and resolve conflicts
Never reference non-git content in PRReviewers can't access agent-internal files"Memory/plan adds context"PR is a public document; internal files are inaccessible to reviewers

</Critical_Constraints>


Scope

Writes PR description body. Optionally assesses PR scope for multi-thesis splitting, separating each sub-PR into its own worktree. Detects base branch via heuristic merge-base analysis, confirms the target, and requests later sync or conflict decisions only when their prerequisite state exists before collecting metadata + surveying repo PR conventions (title/branch/label) → interview → assessment → description. Creates the PR via gh pr create after user approval, assigned to the authenticated gh user, with labels per the surveyed convention.


When NOT to Use

  • Purpose is code review (use code-review skill)
  • Purpose is writing commit messages (use git-master skill)

Workflow

Discover facts before asking anything. Ask one user decision at a time, and ask only preferences or decisions; do not ask the user for facts you can determine. Run the target-branch setup, metadata discovery, interview, scope assessment, drafting, review, and explicit PR-creation approval in that order.

Interview contract: Ask one user decision at a time. Present detected target-branch evidence, then ask the user to confirm the target; never auto-select. Only after target confirmation, re-check divergence. If behind > 0, ask sync strategy before merge/rebase. If behind = 0, do not ask a sync question. Only if synchronization actually conflicts, obtain the conflict policy/decision before resolving. File-by-file mode asks one file decision at a time. Do not execute dependent actions before their required answer.


Step 0: Base Branch Detection & Synchronization

Upon receiving a PR writing request, detect the target base branch via heuristic analysis, confirm with the user, and synchronize the current branch before collecting metadata.


Step 0-A: Base Branch Detection

Phase 1 — Fetch all remote state:

git fetch --all --prune

Phase 2 — Analyze all remote branches as candidates:

For every remote branch except the current branch's remote counterpart (origin/$(git branch --show-current)) and symbolic refs (origin/HEAD), compute merge-base distance:

# For each remote branch {branch}:
MERGE_BASE=$(git merge-base HEAD origin/{branch} 2>/dev/null || true)
if [ -z "$MERGE_BASE" ]; then continue; fi  # Skip unrelated/orphan branches
AHEAD=$(git rev-list --count $MERGE_BASE..HEAD)
BEHIND=$(git rev-list --count $MERGE_BASE..origin/{branch})
DIFF_STAT=$(git diff --stat $MERGE_BASE..HEAD | tail -1)

Phase 3 — Build candidate table:

Collect all candidates and present a table showing commits ahead/behind and change scale. Sort by AHEAD ascending (smallest diff from current branch = most likely true base):

| 후보 브랜치           | commits ahead | commits behind | 변경 규모              |
|----------------------|---------------|----------------|----------------------|
| sisyphus-myth-title  | 1             | 0              | +53 -70 (8 files)    |
| main                 | 17            | 0              | +1832 -1881 (17 files)|

Present the detected target-branch evidence, then ask the user to confirm the target; never auto-select. Do not add candidate-count or UI-option rules.

Phase 4 — Target confirmation:

After presenting the evidence table, ask only for the target branch confirmation. Only after the user confirms the target, re-check divergence. Ask sync strategy only when the confirmed target is behind; if behind = 0, do not ask a sync question. Ask conflict policy only if synchronization actually conflicts, before resolving it. Do not execute dependent actions before their required answer.

#headerquestionoptionsIncluded when
1타겟 브랜치이 PR의 base 브랜치는 어디인가Show the detected candidates and ahead/behind/change scale evidence for user confirmationAlways
2동기화 방식타겟 브랜치가 앞서 있으면 그 커밋들을 어떻게 가져올까Explain the meaning and consequences of merge or rebaseConfirmed target is behind
3충돌 처리동기화 중 충돌이 나면 어떻게 처리할까파일별로 확인, 제안대로 자동 해결, 현재 브랜치 우선, 타겟 브랜치 우선Synchronization conflicts

The confirmed {base-branch} is used in subsequent git commands. Collect each later decision only when its prerequisite state exists.


Step 0-B: Target Branch Synchronization

After target confirmation, re-check the confirmed target's actual divergence before executing:

git rev-list --left-right --count origin/{base-branch}...HEAD
# Output: {behind}\t{ahead}

If behind = 0: No synchronization needed. Proceed to Step 1.

If behind > 0: Ask the user for {sync-strategy} and wait for the answer before running merge or rebase. Do not ask a sync question when behind = 0. If synchronization actually conflicts, ask for {conflict-policy} and wait for that answer before resolving conflicts.

# merge
git merge origin/{base-branch}

# rebase
git rebase origin/{base-branch}

If the operation completes without conflict: Proceed to Step 1.

If conflict is detected: Proceed to Step 0-C.


Step 0-C: Conflict Resolution

When a merge or rebase operation encounters conflicts:

Phase 1 — Enumerate conflicted files:

git diff --name-only --diff-filter=U

Phase 2 — Analyze every conflicted file in this round:

For each file in the list, first render the path as one shell-safe literal and bind it before any shell command. Use CONFLICT_FILE=<shell-word:file> (single-quote escaping as needed); after that binding, use only quoted variable expansions for the path:

CONFLICT_FILE=<shell-word:file>
git ls-files -u -- "$CONFLICT_FILE"

Stage 2 is ours and stage 3 is theirs. A missing stage is a deletion on that side, so do not assume that the worktree contains conflict markers (modify/delete and rename/delete conflicts may not). Read the present stage blobs (git show ":2:$CONFLICT_FILE" / git show ":3:$CONFLICT_FILE") when analyzing the two sides, then form a proposed resolution with reasoning. Use the correct ours/theirs mapping for the operation in progress:

  • During merge: HEAD side (ours) = current branch changes, incoming side (theirs) = target branch changes
  • During rebase: HEAD side (ours) = target branch changes (commit being rebased onto), incoming side (theirs) = current branch changes (commit being replayed)

Phase 3 — Settle them per {conflict-policy}:

{conflict-policy}How this round is settled
파일별로 확인Explain one conflicted file at a time in plain text: what each side holds, what the conflict represents, the proposed resolution and its reasoning. Ask one file decision at a time, then resolve only that file. Each question offers 제안대로 해결 / 현재 브랜치 유지 (merge: ours / rebase: theirs) / 타겟 브랜치 채택 (merge: theirs / rebase: ours)
제안대로 자동 해결Apply the Phase 2 proposal to every file, preserving whether it is a side selection, deletion, or synthesized/custom result
현재 브랜치 우선Take the current branch's side in every file — merge selects ours (stage 2), rebase selects theirs (stage 3)
타겟 브랜치 우선Take the target branch's side in every file — merge selects theirs (stage 3), rebase selects ours (stage 2)

Phase 2 proposals may be an explicit side selection, a deletion, or a synthesized/custom result. For a deletion proposal, resolve it with git rm -- "$CONFLICT_FILE". For a synthesized/custom proposal, preserve the exact proposed content in the worktree, then stage it with git add -- "$CONFLICT_FILE". The stage checkout procedure below applies only to explicit current-branch/target-branch side choices. For those side choices, resolve the selected stage explicitly. If the selected stage is absent, resolve the deletion with git rm -- "$CONFLICT_FILE"; otherwise check out the selected side and stage it:

stages=$(git ls-files -u -- "$CONFLICT_FILE")
# selected_stage is 2 (ours) or 3 (theirs), according to the mapping above
if ! printf '%s\n' "$stages" | awk -v stage="$selected_stage" '$3 == stage { found=1 } END { exit !found }'; then
  git rm -- "$CONFLICT_FILE"
else
  git checkout --$selected_side -- "$CONFLICT_FILE"
  git add -- "$CONFLICT_FILE"
fi

This stage inspection and missing-stage git rm rule also applies to file-by-file choices; never blindly run git checkout when the chosen side is a deletion.

Under the three non-interactive policies, report what was applied per file in plain text after the operation finishes, so the user can see the resolutions they did not individually approve.

Phase 4 — Finalize the operation:

After all conflicted files are resolved:

# If merge:
git commit --no-edit   # creates the merge commit with default message

# If rebase:
git rebase --continue

Phase 5 — Check for additional conflicts:

If git rebase --continue triggers a new conflict (rebase replays commits one by one), return to Phase 1 and repeat for the new conflict set. {conflict-policy} is answered once and carries across every round — do not re-ask it.

When all conflicts are resolved and the operation completes: Proceed to Step 1.


Step 1: Collect Git Metadata & PR Conventions

After base branch detection and fetch, collect lightweight git metadata.

# Commit history
git log origin/{base-branch}..HEAD --oneline

# Changed file list
git diff origin/{base-branch}..HEAD --stat

# Commit messages and descriptions
git log origin/{base-branch}..HEAD --format='%s%n%b'

Use this metadata as supplementary context for the interview. Use it to gauge the scope and scale of changes, but do NOT read actual file contents.

PR Convention Survey

Survey the repo's recent PRs to learn its title, branch-name, and label conventions. Run once per session, right after metadata collection:

# Recent PRs (10-30): title / branch / label conventions
gh pr list --state all --limit 30 --json number,title,labels,headRefName

# Labels that actually exist in the repo
gh label list --limit 100

From the survey, derive and record three values for later steps:

ValueDerived fromWhat to extract
{title-convention}title fieldPrefix style (conventional commit / gitmoji / bare), language, typical length
{branch-convention}headRefName fieldNaming pattern (e.g., feat/*, fix/*, {user}/*, kebab-case topic)
{label-convention}labels fieldWhich labels are applied to which kinds of change (feature/fix/refactor/docs …)

Convention exists only when a majority pattern does. An axis counts as having a convention only when BOTH hold: (1) at least 5 PRs were surveyed, and (2) strictly more than half of them share the pattern — an exact tie (e.g., 3-3 between two styles) means no convention. With fewer than 5 surveyed PRs, mark every axis "no convention" — a handful of PRs is not a convention. For any axis without a convention, use the fallback defaults (title: conventional commit style Korean, branch: keep current name, labels: none).

Every branch name this skill creates, renames, or proposes must use English words only. A surveyed branch convention may determine structure, but never overrides the English-only rule.

Never invent labels. Only labels present in gh label list output may ever be applied. If no existing label fits, apply none.


Step 2: Explore Codebase Patterns

Use the explore agent to understand codebase patterns and structure. For architecture-level changes (e.g., module restructuring, design pattern changes), additionally consult oracle for deeper analysis. Do NOT ask the user about the codebase.

Context Brokering (CRITICAL):

Question TypeAsk User?Action
"What's the project architecture?"NODiscover via explore
"Which files changed?"NOCheck via git metadata
"What are the existing patterns?"NODiscover via explore
"What's the architectural impact?"NOConsult oracle
"What's the motivation for this change?"YESUser interview
"What alternatives were considered?"YESUser interview
"Anything you want to ask reviewers?"YESUser interview

Only ask the user about PREFERENCES and DECISIONS. Discover FACTS yourself.


Step 3: User Interview

Interview Rules

  1. One question at a time -- never bundle multiple questions. This rule applies globally; request each later decision only when its prerequisite state exists, and wait for the answer before dependent actions.
  2. Adaptive question count -- repeat until Clearance Checklist is all YES. Could be 1-2 if user provides enough upfront, or 5-6+ for complex changes
  3. AskUserQuestion = structured choices, plain text = open-ended questions
  4. Context Brokering -- if the codebase can answer it, use explore instead of asking
  5. No shortcut from prior sessions -- memory, plans, and previous session context do not replace the interview. Always start from git metadata + explore

Question Type Selection

SituationMethodReason
Decision with 2-4 clear optionsAskUserQuestionProvide structured choices
Open/subjective questionplain textFree-form answer needed
Yes/No confirmationplain textAskUserQuestion is overkill

Question Quality Standard

BAD:
  question: "What changed?"

GOOD:
  question: "I see changes in OrderService and PaymentService from git log.
    The commit messages suggest event-based decoupling.
    Could you share the core motivation (e.g., removing domain coupling,
    transaction separation, scalability)?"

Handling User Responses

Vague answers:

  1. Do not accept as-is
  2. Ask specific follow-up questions
  3. Repeat until clear

Explicit delegation ("figure it out", "pass", "you decide"):

  1. Investigate autonomously via explore/git metadata
  2. Decide based on industry best practices or codebase patterns
  3. Reflect the decision in the PR description

Bare-text reference (e.g., issue key, channel name):

  1. Ask once for the full URL/permalink so References can be rendered as a markdown link
  2. If the user has no URL, bare-text is acceptable as fallback

Step 4: Clearance Checklist (Interview Exit Condition)

Run after every interview turn. If ANY NO, continue the interview.

#CheckMust Be
1Is the background/purpose clear enough to write Summary?YES
2Are the changes and their reasons clear enough to write Changes?YES
3Are enough technical decisions/concerns collected to write Review Points?YES
4Are acceptance criteria organized enough to write Checklist?YES

All YES -> Proceed to Step 5. Any NO -> Continue interview. Do not proceed.

This checklist is internal -- do NOT show it to the user.


Step 5: Scope Assessment

After Clearance Checklist passes, analyze whether the PR contains multiple independent theses (behavioral changes) that should be separate PRs. Read references/scope-assessment.md now — it contains the complete multi-thesis split framework required for this step.

Quick summary:

  1. Identify candidate theses, then absorb exception-matching changes (campsite cleanup, minimal cross-domain) into their nearest main thesis
  2. Check proxy signals (commit type diversity, domain spread, LOC) as initial triggers
  3. Apply thesis isolation test: "Does this PR prove a single thesis?"
  4. If single thesis → proceed to Step 6
  5. If multi-thesis → propose split to user (Accept/Reject/Modify)
  6. On Accept → create one git worktree per sub-PR (so each PR stays editable side by side once review starts), write sub-PR descriptions (Step 6-8 per sub-PR)
  7. On Reject → proceed to Step 6 as single PR

Data sources: git diff origin/{base-branch}..HEAD --stat, git log, explore results, interview answers. Never read git diff file contents.


Step 6: Write PR Title & Description

PR Title

  • Include a PR title along with the description body
  • Format: follow {title-convention} from the Step 1 PR Convention Survey — match the surveyed prefix style, language, and length
  • Title-language precedence: for the title only, the surveyed language wins over the Korean default (an English-titled repo gets an English title). The PR body and user conversation remain Korean regardless
  • Fallback (no surveyed convention): conventional commit style (feat:, fix:, refactor:, etc.), Korean, under 50 characters (excluding prefix)
  • Fallback example: refactor: 주문-결제 간 이벤트 기반 아키텍처 전환
  • Split sub-PR: the title carries its position in the series as a (K/N) suffix after the convention-conforming title — feat: 주문 이벤트 스키마 정의 (1/3). The suffix sits at the end so the surveyed prefix style still leads

PR Labels

  • Select labels per {label-convention} from the Step 1 survey: pick the label(s) the repo applies to this kind of change
  • Only labels that exist in gh label list output — never invent one; if none fits, apply none
  • Present the selected labels alongside the title and body in Step 7 so the user reviews them together

Writing Principles

  • Write so fellow developers can quickly understand the changes
  • Be concise and focused on essentials
  • Separate "what changed" (Changes) from "what needs discussion" (Review Points)
  • Proactively identify areas where reviewer feedback would help
  • Base on provided documents and code; ask for confirmation if uncertain

Output Format

MUST read references/output-format.md before writing the PR body. It contains the definitive template (emoji headers, Impact Scope field, Review Points 5-part structure, Checklist format). Follow it exactly. Key requirements:

  • Use emoji section headers: 📌 Summary, 🔧 Changes, 💬 Review Points, ✅ Checklist, 📎 References
  • Each Changes subsection MUST include **영향 범위** (Impact Scope)
  • Each Checklist item MUST be a verifiable acceptance criterion in - [ ] checkbox format, with the relevant file path indented below. Write true/false verifiable conditions, not file lists or feature descriptions.
  • Review Points MUST use the 5-part structure: 배경 및 문제 상황 → 해결 방안 → 구현 세부사항 → 관련 코드 (optional) → 선택과 트레이드오프

Review Points Selection Criteria

  • Core architecture decisions
  • Trade-offs between competing concerns (performance vs readability, simplicity vs extensibility)
  • Patterns/approaches where multiple valid alternatives exist
  • Areas where a senior engineer's domain expertise would be valuable
  • Implementation choices that deviate from common conventions
  • Mixed strategies within the same flow (e.g., different lock mechanisms)
  • Data modeling decisions affecting future extensibility

Each Review Point Structure

  1. 배경 및 문제 상황: Why it was needed, what problem existed
  2. 해결 방안: How it was solved (overview)
  3. 구현 세부사항: Detailed implementation explanation
  4. 관련 코드: (Optional) Useful for Before/After comparison
  5. 선택과 트레이드오프: Rationale for the choice, rejected alternatives, acknowledged trade-offs. Include open questions only when they naturally arise.

Step 7: User Review & Revision

Present the drafted PR description to the user and collect feedback.

  • If approved: proceed to Step 8
  • If revision requested: incorporate feedback and re-present

Step 8: PR Creation

After user approves the PR description, ask if they want to create the PR.

Pre-creation Check

Before pushing, verify the branch still holds commits that {base-branch} does not:

git fetch origin {base-branch}
AHEAD=$(git rev-list --count origin/{base-branch}..HEAD)
ConditionAction
AHEAD > 0Proceed to push + gh pr create
AHEAD == 0The branch's commits already exist in {base-branch} — there is nothing to open a PR for. Tell the user and stop

AHEAD is a property of the current branch, so this check is evaluated once and its answer does not change when the target branch receives new commits meanwhile. It is also the only precondition gh pr create needs: GitHub computes the merge server-side, so the branch does not have to be up to date with the target. Synchronizing the branch with the target is handled earlier, by the Step 0-B merge/rebase that runs before the interview.

  • If user confirms: check branch name convention, push the branch, and run gh pr create with the approved title, description, assignee, and labels
  • If user declines: output the final PR description only

For a split sub-PR, resolve its branch → worktree mapping from Step 5 and bind the matching $WT_DIR before any ahead check, branch-name/convention check, remote lookup, rename, or push. If the mapping is missing, stop and ask the user; never infer a worktree path. Never interpolate a raw branch/ref placeholder into shell source: render each external value as one shell-safe literal into a variable, validate branch refs with git check-ref-format --branch when created or renamed, and use only quoted variable expansions. A branch such as feat;id, $() or backticks remains data. Run those operations from the bound $WT_DIR, then create the PR with the mapped branch. This binding rule applies only to split sub-PRs; single-PR Step 8 keeps the flow below unchanged.

Branch Name Convention Check (before push)

If {branch-convention} exists (Step 1 survey) and the current branch name does not match it:

  1. Skip when the branch already exists on origin (git ls-remote --heads origin {current-branch} non-empty) — renaming a pushed branch orphans the remote copy
  2. Otherwise propose a convention-conforming name via AskUserQuestion:
    • {proposed-name}으로 변경: git branch -m {proposed-name} then push under the new name
    • 현재 이름 유지: push as-is

For single PR (create after remote push):

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
25
Forks
1
Last commit
Sep 2026

ahel review

  • K4blow
    destructive-scoped (in references/scope-assessment.md)
  • K4blow
    destructive-scoped (in tests/test-scenarios.md)

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Catalog kind
skill
Gateway key
make-pr-toongri
Source
github.com/toongri/oh-my-toong-playground