(ywc) Use when the user wants to open a pull request and says "create a PR", "open a PR", "submit code for review", "push and create PR", "PR 만들어줘", "풀리퀘 작성", "プルリク作成", or is wrapping up a feature branch. Do not use for committing only without PR creation, for the full delivery lifecycle of merging an already-completed branch (use ywc-finish-branch), or for handling existing PR review comments (use ywc-handle-pr-reviews).
Scanned 9/2/2026
Install to Claude Code
npx -y skills add yongwoon/ywc-agent-toolkit --skill ywc-create-pr --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ywc Create Pr?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/yongwoon-ywc-create-pr)More formats (shields.io, HTML) on the badges page.
---
name: ywc-create-pr
version: 1.0.0
description: (ywc) Use when the user wants to open a pull request and says "create a PR", "open a PR", "submit code for review", "push and create PR", "PR 만들어줘", "풀리퀘 작성", "プルリク作成", or is wrapping up a feature branch. Do not use for committing only without PR creation, for the full delivery lifecycle of merging an already-completed branch (use ywc-finish-branch), or for handling existing PR review comments (use ywc-handle-pr-reviews).
category: release
phase: release
requires: []
advisor_budget: 0
allowed tools: Bash, Read, Glob, Grep
---
# Create PR
**Announce at start:** "I'm using the ywc-create-pr skill to commit and open a pull request."
Commit changes and create a draft PR following the PR template.
## Rationalization Defense
When tempted to skip a step, check this table first:
| Excuse | Reality |
|---|---|
| "User said 'create PR' — they obviously want it merged too" | Default is **draft** PR. Mark ready/merge only when explicitly asked. |
| "CI check is slow, just push and let CI run remotely" | Local CI catches failures before review delay. Skip only with `--skip-ci-check`. |
| "Force push will resolve the rejection faster" | Non-fast-forward = teammate work or rebase needed. Force only with explicit user approval. |
| "The PR template is generic, my custom body is better" | If `.github/pull_request_template.md` exists, follow it. Templates encode team norms. |
| "Secret scan flagged a value but it's just a test fixture" | Stop and confirm with the user before bypassing the scan. Better to over-confirm than leak. |
| "Base branch is obvious from history" | Auto-detect order is develop → main → master. Show the chosen base before proceeding. |
| "The hook is just being pedantic, `CLAUDE_MD_CHECK=skip git push` will fix it" | Inline `VAR=value git push` does NOT reach the hook subprocess — the hook runs before the command executes. Use `export VAR=value && git push` in a single Bash call instead, or instruct the user to run `! VAR=value git push` in their terminal. |
| "CI passed locally, so remote CI will pass too" | Remote CI may use different OS runners, Node versions, or environment secrets unavailable locally. Always verify remote CI after pushing — local and remote diverge more often than expected. |
| "CI is slow — let the reviewer catch failures" | CI failures signal a broken branch to every reviewer. Fix them immediately after PR creation so the PR stays reviewable and avoids a second round-trip after the reviewer waits for another push. |
| "CI is green, so the PR is ready to merge" | CI status and merge-readiness are independent gates. A green PR can still be `CONFLICTING` against the base if the base advanced. Check `gh pr view --json mergeable,mergeStateStatus` before declaring the PR done — a `CONFLICTING`/`BEHIND`/`BLOCKED` PR blocks every reviewer just like a CI failure. |
| "The PR conflicts with base — I'll rebase the feature branch to fix it" | Rebasing rewrites commit SHAs and orphans existing PR review threads. Merge the base *into* the feature branch instead (`git merge --no-ff origin/<base>`); it preserves SHAs and review history. See `references/pr-conflict-resolution.md`. |
| "The UL update adds noise before every PR" | The update is a diff-driven incremental review, not a full re-extraction. If no new domain terms appeared in the branch, the skill produces no changes. Skipping it lets the glossary drift from the codebase with every PR that introduces new vocabulary. |
| "I generated this code, I know it is fine — just file the PR" | Filing code whose diff you have not read yourself inflicts unreviewed code on every reviewer. Read each changed line first (Step 6.5); it catches scope creep, leftover debug output, and secrets the generation step introduced — the cheapest review pass there is. |
| "Checking the task README too is extra work, just fuzzy-match the plan folder" | The task README's `## Spec Reference` → `Primary Sources` is already recorded precisely by `ywc-task-generator` — it is the authoritative source. Path A (task lookup) always runs before Path B (fuzzy match), never the reverse. |
| "Completed plans always live in `OLD/`, so I only need to search that folder" | The subdirectory name for completed plans is project-specific (`OLD`, `archive`, `done`, etc.). Search `docs/ywc-plans/**/*.md` recursively instead of hardcoding one folder name. |
| "`docs/ywc-plans/` is missing, treat it as an error" | Other projects reusing this skill may never have created the directory, or it may be `.gitignore`d. Absence is a normal state — skip Step 6.6's Path B silently, never surface it as a failure. |
**Violating the letter of these rules is violating the spirit.** If you find yourself rephrasing a rule to make an exception, stop and ask the user.
## Context
- Changed files: !`git status --short`
- Current branch: !`git branch --show-current`
## Task
Follow the steps below to commit and create a PR.
### 0. Language and Title Initialization
1. **Title**: Check `$ARGUMENTS` for `--title "<value>"`. If present, store it as the PR title — it will be used verbatim in Step 7 (skip self-generated title).
2. **Language**: Check `$ARGUMENTS` for a language hint (e.g., `--lang ja`, `--language korean`). If a `--lang` flag is present, use it. Otherwise resolve the output language via the shared resolution reference **before** prompting.
> Run `bash claude-code/skills/scripts/resolve-language.sh [--lang <code>]`.
> Resolved code → write the PR title and body in that language and skip the language prompt entirely (AC6). `UNRESOLVED` → continue to the prompt below.
Only when resolution yields nothing (no `--lang`, no policy) **and** no `--title` was provided, use the `AskUserQuestion` tool to ask: "What language should the PR title and description be written in?" with the full option set English / Japanese / Korean / Spanish / Chinese (`en | ja | ko | es | zh`) — then **immediately continue to Step 0.5 in the same turn**; do not end the turn or wait for further input after receiving the answer. If `--title` was provided, it is used verbatim in Step 7 and a resolved policy governs only the **body** language (EC4); with no policy, infer the body language from the title or default to English — do not prompt. The title's `[task-id]` / conventional prefix always stays English.
3. Apply the chosen language consistently when writing the PR description in Step 7.
4. **Post-CI check**: Check `$ARGUMENTS` for `--skip-post-ci-check`. If present, skip Step 8 (Remote CI & Bot Review). This flag is passed by `ywc-finish-branch`, which handles CI verification independently in its own Step 4.
5. **Ubiquitous Language update**: Check `$ARGUMENTS` for `--skip-ubiquitous-update`. Store the flag — it controls Step 0.5.
6. **Plan-doc override**: Check `$ARGUMENTS` for `--plan-doc <path>`. If present, store the path — Step 6.6 treats it as the single confident candidate and skips its own Task/Plan discovery (Path A/B).
7. **Plan-doc opt-out**: Check `$ARGUMENTS` for `--no-plan-ref`. Store the flag — it disables Step 6.6 entirely. Mutually exclusive with `--plan-doc`; if both are present, `--plan-doc` wins and `--no-plan-ref` is ignored.
### 0.5. Ubiquitous Language Update (optional)
**Skip this step if `--skip-ubiquitous-update` is present in `$ARGUMENTS`.** This flag is passed by `ywc-finish-branch`, which runs the update in its own Step 1.5 before delegating PR creation to this skill.
Check whether `docs/ubiquitous-language.md` exists in the project root:
```bash
test -f docs/ubiquitous-language.md
```
- **Exists**: Invoke `ywc-ubiquitous-language --mode update`. Any changes to `docs/ubiquitous-language.md` will be picked up and committed by Step 4.
- **Not exists**: Skip silently — the project has not yet established a ubiquitous language document.
### 1. Determine Base Branch
- If a base branch is specified in `$ARGUMENTS`, use it
- Otherwise, auto-detect the default base branch in the following priority order:
1. `develop` — if it exists locally or in remote (`git rev-parse --verify develop 2>/dev/null || git rev-parse --verify origin/develop 2>/dev/null`)
2. `main` — if it exists locally or in remote
3. `master` — fallback
- Store the determined base branch and use it consistently throughout all subsequent steps
- Show the determined base branch to the user: "Base branch: `<branch>`"
### 2. Pre-flight Checks
Before proceeding, verify the environment is ready:
- Confirm `gh` CLI is installed and authenticated (`gh auth status`). If not, stop and tell the user how to set it up
- Check if a PR already exists for this branch (`gh pr list --head <current-branch> --state open`). If one exists, show the URL and ask the user whether to update it or create a new one
- **If update**: Skip PR creation (Step 7), but do **not** skip Step 8. Commit and push changes, optionally update the PR description with `gh pr edit <number> --body-file -`, then proceed to Step 8 (Remote CI & Bot Review Check). Updating a PR can break CI exactly like creating one — the verification must run on the update path too, not only on the new-PR path (unless `--skip-post-ci-check` was passed by an upstream caller).
- **If new**: Continue with the full workflow
- Verify the current branch is not the base branch itself — refuse to create a PR from main/develop/master to itself
### 3. Security Check
Run the bundled secret scan script:
```bash
# Phase 1+2: dangerous file names + staged/unstaged diff content
bash claude-code/skills/ywc-create-pr/scripts/scan-secrets.sh --staged
# Phase 3: all commits on this branch vs base (secrets already committed)
bash claude-code/skills/ywc-create-pr/scripts/scan-secrets.sh --committed <base-branch>
```
Exit 0 = clean — proceed. Exit 1 = secrets or dangerous files found — the script prints matches to stdout.
If either scan returns exit 1, warn the user and show the script output. Do not include flagged files in the commit unless the user explicitly confirms. For committed secrets (second scan), require explicit confirmation before proceeding to PR creation.
### 4. Commit Uncommitted Changes
- Check uncommitted changes with `git status` and `git diff`
- If there are uncommitted changes, delegate to `ywc-commit` with `--skip-ubiquitous-update`:
- **Why the flag**: Step 0.5 of this skill already invoked `ywc-ubiquitous-language --mode update` (unless this skill itself was called with `--skip-ubiquitous-update` by an upstream caller like `ywc-finish-branch`). Without the flag, `ywc-commit`'s own Step 0.5 would run the update a second time. The flag must always be passed in this delegation — even when this skill's Step 0.5 was skipped, because the upstream caller is the one responsible for the UL update in that scenario.
- `ywc-commit` classifies every changed file as IN / UNKNOWN / OUT relative to the current session, splits logically distinct changes into separate commits, and learns the project's commit message style from `git log`
- It will confirm with the user before staging any UNKNOWN or OUT files — do not skip that confirmation
- Follow the repository's observed co-author trailer convention; do not force-add a trailer if the repository does not already use one
- If there are no uncommitted changes: skip this step
### 5. CI Check (Pre-push Validation)
Run the same lint, format, typecheck, and test checks locally that CI will execute. The goal is to catch failures before pushing, since CI failures delay PR review.
**Skip this step if `--skip-ci-check` is present in `$ARGUMENTS`.**
#### 5-1. Detect CI Check Commands
Run the bundled detector first — it emits candidate commands from each source plus the package manager, so you do not re-derive the same greps each run:
```bash
bash claude-code/skills/ywc-create-pr/scripts/detect-ci-commands.sh [repo-dir]
```
It is best-effort; reconcile its output against the priority order below (workflows are authoritative, then CLAUDE.md, then package.json, then Makefile):
1. **`.github/workflows/*.yml`** — Read CI workflow files and extract active check commands
- Look for `run:` fields containing `lint`, `format`, `typecheck`, `type-check`, `test`, `check`
- Exclude deployment-related jobs/steps (deploy, release, publish, docker build)
- Prioritize workflows with `on: pull_request` or `on: push` triggers
2. **`CLAUDE.md`** — Search the project root CLAUDE.md (or parent directory) for lint, format, typecheck, and test commands
3. **`package.json` scripts** — Use scripts whose keys match `lint`, `format`, `typecheck`, `type-check`, or `test`
4. **`Makefile`** — Use targets named `lint`, `format`, `check`, or `test`
If no commands are detected, skip this step and inform the user of the reason.
#### 5-2. Detect Execution Environment
- If CLAUDE.md specifies a `docker exec <container>` prefix, apply it to all commands
- Determine the package manager (`pnpm`, `npm`, `yarn`, etc.) from the lock file
#### 5-3. Run Checks
- Execute all detected check commands in sequence (recommended order: lint → format → typecheck → test)
- Record the pass/fail result of each command
- Continue running remaining commands even if one fails — report all results together at the end
#### 5-4. Report Results and Next Steps
- If all checks pass, proceed to the next step (Push)
- If any check fails:
- Summarize which checks failed and what the errors were
- Present the user with two options:
1. **Fix and retry** — Resolve the issues, then re-commit and re-run checks
2. **Skip and proceed** — Ignore the check failures and continue to Push & PR creation
### 6. Push to Remote
- Check if the current branch is already up-to-date with the remote (`git status -sb` — look for `ahead` count). If the branch is already pushed and there are no new local commits, skip the push
- Push to remote with `git push -u origin HEAD`
- If push fails due to a **PreToolUse hook error** (error message contains "hook error" or "Blocked:"):
1. Read the full hook error message — it usually states exactly what is required or how to bypass
2. Look for a bypass env var hint (e.g., `CLAUDE_MD_CHECK=skip`, `SKIP_CHECK=true`). If found:
- Retry with `export <BYPASS_VAR>=<value> && git push -u origin HEAD` in a single Bash call
- **Why**: `VAR=value git push` sets the variable only for the git process, not for the hook subprocess that runs before it. Exporting in the same shell command makes the variable available to the hook
3. If the hook requires a content action (e.g., "update CLAUDE.md before pushing"):
- Evaluate whether the requirement genuinely applies to the changed files
- If yes: fulfill the requirement (e.g., update CLAUDE.md), then retry the push normally
- If no (e.g., changes are test fixtures or QA docs with no documentation impact): use the bypass approach in step 2
4. If the bypass attempt also fails or no bypass is indicated, instruct the user to run this in their terminal:
```
! export <BYPASS_VAR>=<value> && git push origin HEAD
```
Explain: the `!` prefix runs the command directly in the user's shell session, where the exported variable reaches the hook subprocess. Continue to Step 7 once the user confirms the push succeeded
- If push fails due to **remote changes** (non-fast-forward):
- Suggest `git pull --rebase origin <current-branch>` to the user (rebase against the same feature branch, not the base branch)
- Do not force-push without explicit user approval
### 6.5. Author Self-Review Gate (mandatory)
Before filing the PR, read your own diff end to end. **Do not file code you have not reviewed yourself** — unreviewed code shifts the cost of your mistakes onto every reviewer. This gate has no skip flag.
```bash
git diff <base-branch>...HEAD
```
Read the full output and confirm each row. If any fails, fix it before Step 7:
| Check | Reject if |
|---|---|
| Intent traceability | A changed line does not trace to this session's request (scope creep) |
| No debug residue | Leftover `console.log` / `print` / `dbg!`, commented-out blocks, or `FIXME`/`TODO` introduced by generation |
| No drive-by edits | Unrelated reformatting, renames, or "improvements" outside the task |
| No secrets | Hardcoded keys, tokens, or credentials (Step 3 scans patterns; this is the human-readable cross-check) |
| Convention fit | Naming and structure match the surrounding code |
This is the **author's own pass**, not an approval — it does not replace independent review. For a thorough multi-aspect review before filing, run `ywc-impl-review` (architecture / design / devex / security / QA); that pass stays opt-in, this self-review does not.
### 6.6. Discover Related Task/Plan/Design-Intent Document (best-effort, non-blocking)
**Skip this step entirely if `--no-plan-ref` is present in `$ARGUMENTS` and `--plan-doc` is absent.** Per Step 0 item 7, `--plan-doc` takes precedence when both flags are present — in that case proceed to sub-step 1 below instead of skipping.
PR bodies generated purely from diff/commit history lose the *why* behind a design decision already captured by `ywc-brainstorm`/`ywc-plan` (in `docs/ywc-plans/`) or by `ywc-task-generator` (in each task's `README.md` `## Spec Reference`). This step looks for that document and, when found with confidence, holds it for Step 7 to cite in a "Design Background" section. It never blocks PR creation — no match is a normal, silent outcome.
1. **Explicit override.** If `--plan-doc <path>` is present in `$ARGUMENTS`, validate it first: the path must be repository-relative (reject a leading `/` or any `..` segment) and must end in `.md` — this also excludes non-Markdown sensitive files (`.env`, credentials, keys) by construction, since only `.md` paths are ever read. String checks alone do not stop a symlink from pointing outside the repository, so also resolve the candidate to its canonical path (`realpath <path>`) and reject it unless the result is still inside the repository root (`git rev-parse --show-toplevel`). Read that **canonical** path from here on, never the original argument — re-resolving the original leaves a window in which the symlink is repointed between the check and the read. If validation fails, or the file does not exist / cannot be Read, print one line to the conversation explaining why and continue directly to Step 7 with no design-background result — an explicit `--plan-doc` is not a hint to fall back to Path A/Path B search. If valid and readable, that path is the single confident candidate — skip Path A and Path B below and go directly to sub-step 6 (Excerpt Extraction, `source: "plan"`).
2. **Path A — Task-based lookup (authoritative, tried first).**
- If the current branch (`git branch --show-current`) does not start with `feature/`, Path A has no candidate — go to Path B.
- Otherwise let `<task-name>` be the branch name with the `feature/` prefix stripped. Glob `tasks/<task-name>/README.md`; if not found, Glob `tasks/completed/<task-name>/README.md`.
- If neither exists, Path A has no candidate — go to Path B.
- If found, Read the file and extract its `## Spec Reference` section: the `### Primary Sources` list and the `### Summary` text. If `Primary Sources` reads `N/A — no external spec (housekeeping / refactor / config only)` (or equivalent), there is nothing to cite — Path A has no candidate, go to Path B.
- Otherwise this is the confident result: hold `{source: "task", task_readme_path, primary_sources, summary}` and **skip Path B entirely** — go to sub-step 7.
3. **Path B — Plan-directory fuzzy match (fallback, runs only when Path A found no candidate).**
- Glob `docs/ywc-plans/**/*.md` recursively — this covers `docs/ywc-plans/OLD/` and any other subdirectory a project moves completed plans into; do not hardcode a specific subdirectory name. Exclude `*.spec-ready-log.md` and `*/architecture-verdict.md` sidecar files.
- If `docs/ywc-plans/` does not exist, or the Glob returns zero files, stop here silently — this is expected in projects that reuse this skill without adopting `ywc-plan`, or where the directory is `.gitignore`d and was never created locally. Do not treat this as an error. Base this check on the local filesystem only (Glob/Read) — never on `git log`/`git ls-files`, since the directory may be untracked.
4. **Branch-to-filename token match (Path B only).**
- Strip a single leading `<type>/` segment (`feature/`, `fix/`, `chore/`, etc.) from the current branch name, then tokenize the remainder on `-`/`_`/`.` into lowercase tokens, dropping tokens shorter than 4 characters. The 4-character floor (not 3) specifically drops the `ywc` prefix that recurs across nearly every plan filename in a `ywc-*`-adopting project — at 3 characters it survives tokenization and produces false-positive matches purely from that shared prefix (verified: `feature/ywc-brainstorm-premise-gate` cross-matched an unrelated `ywc-brainstorm-design-self-review` plan until the floor was raised).
- For each candidate file, strip its `YYYYMMDD-` date prefix, optional `small_` prefix, and `.md` suffix from the **basename** (ignore which subdirectory it lives in), then tokenize the same way.
- A candidate is a **confident match** when it shares ≥2 tokens with the branch token set, or shares exactly 1 token that is ≥6 characters long (guards against generic short tokens like `api` or `add` producing false positives).
5. **Resolve Path B to zero, one, or many confident matches.**
- **Zero** → stop here silently; no design-background section is added.
- **One** → hold `{source: "plan", plan_path}` and continue to sub-step 6.
- **Two or more** → do not guess. Print one line to the conversation (not the PR body): `Found N candidate plan documents for this branch, none confidently distinct: <path1>, <path2>, ... Re-run with --plan-doc <path> to cite one explicitly.` Then proceed to Step 7 with no design-background result.
6. **Excerpt extraction (`source: "plan"` or `--plan-doc` override only).** Bound the read before it happens — a large plan file would otherwise burn the context this PR still needs. Bound it on **bytes**, not lines — a 120-line cap still admits a single multi-megabyte line. Take the excerpt source from `head -c 8192 <plan_path>` (first 8 KB, truncated mid-line if needed), never a full-file Read. Within that window, take the content under its `## Goal` heading (Small-path template) or `## Purpose` heading (Medium/Large spec template) — whichever is present — up to the next `##` heading, capped at 5 lines / ~500 characters. If neither heading exists (custom or older plan format), take the first paragraph after the title instead, same cap. Never forward the full file. Also look, within that same bounded window, for a `## Alternatives Considered` or `## Trade-offs` heading (whichever appears first), take the content under that heading up to the next `##` heading, and apply the same 5-line / ~500-character cap — this is opportunistic: no current plan template guarantees the section exists, so its absence is the normal case and produces no finding, not a gap to fill by inventing content. Hold `{source: "plan", plan_path, excerpt, alternatives_excerpt?, alternatives_heading_kind?}` — `alternatives_excerpt` and `alternatives_heading_kind` (`"alternatives"` or `"trade-offs"`, recording which of the two source headings was actually found) are present only when that heading was found. Step 7 uses `alternatives_heading_kind` to pick the matching localized sub-heading — never hardcode "Alternatives Considered" regardless of which heading the source file used.
(Skip this sub-step for `source: "task"` — the `summary` already extracted in Path A sub-step 2 is used as-is, with no redundant re-fetch.)
7. **Untracked-source confirmation gate.** Whatever the source, if the document git does not track it (`git ls-files --error-unmatch <path>` exits non-zero — the normal case for a `.gitignore`d `docs/ywc-plans/`), its text has never passed review and may hold local secrets or PII that this step would publish verbatim to a remote PR. Show the user the path and the exact excerpt, and ask for explicit confirmation before citing it. On decline, continue to Step 7 with no design-background result. Tracked documents skip this gate.
8. **Hold the final result** — `{source: "task", ...}`, `{source: "plan", ...}`, or nothing — for Step 7 to consume. This step performs no writes.
### 7. Create PR
- Check if `.github/pull_request_template.md` exists
- **If exists**: Read the template and create the PR description following its structure
- **If not exists**: Create a PR description with the following default structure:
```markdown
## Summary
[1-3 bullet points summarizing the changes]
## Changes
[List of specific changes made]
## Test Plan
[How to verify the changes]
```
- Write each section based on all commits from the base branch (`git log <base-branch>..HEAD`)
- Review the full diff (`git diff <base-branch>...HEAD`) to ensure the description accurately reflects the changes
- **Design Background (optional, appended)**: if Step 6.6 held a result, **append** a Design Background section after the template/default body above — this augments the body, it never replaces or reorders the project's own template structure (same rule as the `.github/pull_request_template.md` precedence above). Localize the heading and intro line to the language chosen in Step 0 — do not hardcode a single language:
| Language | Heading | Intro (`source: "task"`) | Intro (`source: "plan"`) |
|---|---|---|---|
| en | `## Design Background` | `> Derived from task \`<task_readme_path>\`'s Spec Reference.` | `> Excerpted from \`<plan_path>\` — see the file for full context.` |
| ko | `## 설계 배경 (Design Background)` | `> task \`<task_readme_path>\`의 Spec Reference에서 도출됨.` | `> \`<plan_path>\`에서 발췌 — 전체 맥락은 원문 참조.` |
| ja | `## 設計背景 (Design Background)` | `> タスク \`<task_readme_path>\` の Spec Reference から抽出。` | `> \`<plan_path>\` から抜粋 — 全文は原文参照。` |
| zh | `## 设计背景 (Design Background)` | `> 源自任务 \`<task_readme_path>\` 的 Spec Reference。` | `> 摘自 \`<plan_path>\` — 完整内容请参见原文件。` |
| es | `## Antecedentes de diseño (Design Background)` | `> Derivado de la Spec Reference de la tarea \`<task_readme_path>\`.` | `> Extraído de \`<plan_path>\` — consulte el archivo para el contexto completo.` |
For `source: "task"`:
```markdown
<localized heading>
<localized intro (task)>
**Primary Sources**: <primary_sources, comma- or bullet-listed>
<summary text, verbatim>
```
For `source: "plan"` (including the `--plan-doc` override):
```markdown
<localized heading>
<localized intro (plan)>
<excerpt text, verbatim>
```
**Alternatives Considered / Trade-offs (optional, `source: "plan"` only)**: if Step 6.6 held an `alternatives_excerpt`, append one further sub-block after the excerpt above, using the localized sub-heading that matches `alternatives_heading_kind` — pick the `"alternatives"` column when the source file's heading was `## Alternatives Considered`, or the `"trade-offs"` column when it was `## Trade-offs`. Never default to the `"alternatives"` column when `alternatives_heading_kind` is `"trade-offs"` — the label must match what the source document actually said. Omit the whole sub-block entirely when `alternatives_excerpt` is absent — most plan documents will not have one, and that is the normal case, not a gap:
| Language | Sub-heading (`alternatives_heading_kind: "alternatives"`) | Sub-heading (`alternatives_heading_kind: "trade-offs"`) |
|---|---|---|
| en | `### Alternatives Considered` | `### Trade-offs` |
| ko | `### 검토했던 대안 (Alternatives Considered)` | `### 트레이드오프 (Trade-offs)` |
| ja | `### 検討した代替案 (Alternatives Considered)` | `### トレードオフ (Trade-offs)` |
| zh | `### 已考虑的替代方案 (Alternatives Considered)` | `### 权衡取舍 (Trade-offs)` |
| es | `### Alternativas consideradas (Alternatives Considered)` | `### Compensaciones (Trade-offs)` |
```markdown
<localized sub-heading matching alternatives_heading_kind>
<alternatives_excerpt text, verbatim>
```
The quoted `summary`/`excerpt`/`alternatives_excerpt` text itself stays verbatim (it is a quotation, not translated). If Step 6.6 held no result, omit this section entirely — do not add an empty or placeholder Design Background block.
- **PR title**: if `--title` was provided in Step 0, use it verbatim. Otherwise, generate a title from the commit history in the language chosen in Step 0.
- Write all description content in the language chosen in Step 0
- If there are no UI changes, write "N/A" in the screenshot section (if the template has one)
- Write the finished body to a temp file and create a **draft** PR with `gh pr create --draft --base <base-branch> --title "<title>" --body-file "$body_file"`. Do **not** pipe the body through a `<<'EOF'` heredoc: the Design Background block carries verbatim third-party document text, and a line reading exactly `EOF` inside it would close the heredoc early and hand the remainder to the shell as commands.
- Always specify `--title` and `--body-file` explicitly to avoid interactive prompts
### 8. Remote CI & Bot Review Check
**Skip this step entirely if `--skip-post-ci-check` is present in `$ARGUMENTS`.** This step runs only when `ywc-create-pr` is invoked directly by the user — `ywc-finish-branch` passes `--skip-post-ci-check` and handles CI + bot review in its own Step 4.
After the PR is created **or updated** (the Step 2 update path also lands here), retrieve the PR number and verify that remote CI passes and no automated reviewers have flagged issues.
```bash
PR_NUMBER=$(gh pr view --json number --jq .number)
```
#### 8-1. Wait for CI to Complete
```bash
gh pr checks $PR_NUMBER --watch
# exit 0 = all checks passed; exit 1 = one or more checks failed
```
If no CI checks are configured for this repository (command returns immediately with no output), skip to Step 8-3. If `--skip-ci-check` is present in `$ARGUMENTS`, skip to Step 8-3.
#### 8-2. CI Failure Fix Loop (up to 2 attempts)
If `gh pr checks` exits 1, at least one check failed. Apply fixes in the loop below — at most **2 attempts**:
1. **Get failure details:**
```bash
# List failed run IDs for the current branch
gh run list --branch $(git branch --show-current) \
--json databaseId,name,conclusion \
--jq '.[] | select(.conclusion == "failure")'
# View logs for the most recent failed run
gh run view <run-id> --log-failed
```
2. **Categorize and fix by failure type:**
| Failure type | Fix action |
|---|---|
| Lint / format | Run the project's auto-fix command (`eslint --fix`, `prettier --write`, `ruff --fix`, `biome check --apply`), commit the changes |
| Type errors | Read compiler output, fix type mismatches in affected files, commit |
| Test failures | Analyze failing test output, fix the implementation (never disable or weaken tests), commit |
| Build errors | Read compiler/bundler output, fix compilation or import errors, commit |
3. **Push the fixes** and re-run `gh pr checks $PR_NUMBER --watch` to re-verify.
4. After **2 failed fix attempts**, report the failing check name(s) with the last 30 log lines, leave the PR as draft for manual intervention, and note the CI failure in the Completion Report.
#### 8-3. Bot Review Polling
> **Action required**: Read [`claude-code/skills/references/pr-bot-polling.md`](../references/pr-bot-polling.md) before proceeding. The canonical polling procedure and parameters are defined there.
```bash
bash claude-code/skills/scripts/poll-pr-reviews.sh $PR_NUMBER
# stdout (last line): BOT_COUNT=<n> WINDOW=complete|degraded
# exit 0 → BOT_COUNT > 0 (bots posted)
# exit 1 → BOT_COUNT == 0 after the FULL window (no bots) → merge allowed
# exit 3 → WINDOW=degraded: a gh query failed → NOT evidence of zero bots
```
**Completion gate — the merge condition is not a number, it is the marker.** Only `BOT_COUNT=0 WINDOW=complete` (exit 1) permits proceeding to Step 8-4:
- **`BOT_COUNT=<n>` with n > 0, `WINDOW=complete`, exit 0**: Invoke `ywc-handle-pr-reviews` to address all comments, then re-run the polling script to catch any follow-up comments. If code fixes were pushed, re-run `gh pr checks $PR_NUMBER --watch` (one additional fix attempt allowed).
- **`BOT_COUNT=0 WINDOW=complete`, exit 1**: No bot reviews — proceed to Step 8-4.
- **`WINDOW=degraded`, exit 3, or no `WINDOW=` line at all (Bash timeout/kill/hang)**: The poll never completed a full window — this is **not** evidence of zero bots. Re-run the poll (with an explicit `timeout: 600000` if the prior call was killed by the Bash tool's default timeout). Do **not** proceed to Step 8-4 on a degraded or unfinished result.
#### 8-4. Merge-Readiness (Conflict) Check
> **Action required**: Read [`claude-code/skills/references/pr-conflict-resolution.md`](../references/pr-conflict-resolution.md) before proceeding. The `mergeable` / `mergeStateStatus` semantics, the merge-not-rebase rule, and the surface-vs-auto-resolve boundary are defined there.
CI passing does not mean the PR is mergeable — the base branch may have advanced and now conflict. After CI and bot review settle, check the merge state:
```bash
gh pr view $PR_NUMBER --json mergeable,mergeStateStatus --jq '{mergeable, mergeStateStatus}'
```
- `MERGEABLE` / `CLEAN` → the PR is review-ready; proceed to Completion Report.
- `BEHIND` → the branch is merely out of date (no textual conflict). Follow **Update Branch From Base** for the fast catch-up, push, and re-verify CI.
- `CONFLICTING` / `DIRTY` → follow **Update Branch From Base** in the reference. If the merge auto-resolves (branch was merely behind), push and re-verify CI. If it reports real textual conflicts, surface the conflicting files and PR URL to the user and note the conflict in the Completion Report — do not auto-resolve or force-push.
- `BLOCKED` → a required check or review gate is missing — **not** a conflict. Do not run the base-merge procedure; report which required check or review is outstanding so it can be resolved.
- `UNKNOWN` → poll briefly per the reference, then re-read.
Because this skill creates a **draft** PR by default and does not merge, a conflicting result is reported (not a hard stop) unless the user asked to take the PR further — but the branch should still be brought up to date so reviewers see a mergeable PR.
### 9. Completion Report
Display:
- The created PR URL (clickable)
- Summary: number of commits, files changed, insertions/deletions
- Base branch used
## Notes
- Follow any additional instructions in `$ARGUMENTS`
- Never force-push or amend published commits without explicit user approval
- If any step fails, explain what went wrong and suggest the fix rather than silently retrying
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!