| name | pr-creator |
| description | SmartHR UIリポジトリでPRを作成する際に、プロジェクトのPRテンプレートに沿った形式でPR本文を生成するスキル。PRの作成、`gh pr create`、`gh pr edit` でのタイトル変更、プルリクエスト、マージリクエストなどのキーワードで発動する。ユーザーがPRを作りたいと言った場合や、作業完了後にPRを出すよう求められた場合にも使用すること。破壊的変更(Conventional Commits の `!`)を付けるかどうかの判定もこのスキルが担うため、リリースバージョンに影響する変更を扱う場合は必ず参照すること。 |
SmartHR UI PR作成スキル
このリポジトリでPRを作成する際は、以下のルールとテンプレートに従う。
破壊的変更(!)の判定 — 最初に必ず行う
タイトルを書く前にここを読む。! の有無だけがリリースバージョンを決めるため、他のどの項目よりも間違えたときのコストが大きい。
なぜ最優先なのか
release-please は squash merge されたコミットメッセージを読み、! が付いていれば major を上げる。そして 一度上がったバージョンは revert しても戻らない(release-please の仕様)。
2026-09-05 の #6971 で実際に起きたこと:
- ファイル移動とリファクタだけで公開APIは何も変わっていないPRに
refactor(Button)!: と付いた
- 気づかずマージ → v99.6.0 から v100 の release branch が生成された
- revert してもバージョンは戻らず、コミットに
Release As: 99.6.1 を書いて強制指定する必要があった
- squash merge ではそのコメントが消えるため、クライアントからオプション付きでマージし直す羽目に
- さらに同一リポジトリの
packages/charts まで 99.6.1 に巻き添えで上がり、設定でバージョンを固定して回避
- 復旧に5本のPRを要した
一方、! の付け忘れは次のリリースまでに追いPRで直せる。コストは非対称なので、迷ったら付けずに人に聞く。
参考までに、直近マージ済み200PRのうち ! が付いていたのは上記の誤りの1件だけ。このリポジトリで ! が正当に必要になることは滅多にない、というのが正しい事前確率。
何が破壊的変更か
判定の基準は「このリポジトリの公開APIに依存している利用プロダクトのコードが、バージョンを上げただけで壊れるか」。公開APIとは packages/smarthr-ui/src/index.ts(charts は packages/charts/src/index.ts)から export されているものを指す。
破壊的変更にあたる:
src/index.ts からの export の削除・リネーム
- 公開コンポーネントの props の削除・リネーム・optional から required への変更
- props の型を狭める変更(受け付ける値が減る)
- props のデフォルト値の変更や、既定の挙動・見た目が変わる変更
- 利用者が依存し得る DOM 構造・class・ARIA 属性の変更
peerDependencies の要求バージョン引き上げ
破壊的変更にあたらない(このリポジトリで誤判定されやすいもの):
- ファイル・ディレクトリの移動や分割(
client/ への切り出しなど)。利用者は公開バレル経由で import するため、内部のファイル配置は影響しない
src/index.ts から export されていないコンポーネント・型・関数のリネーム・削除
- 内部実装の変更で、公開 props と DOM 出力が変わらないもの
- optional props の追加、型を広げる変更(受け付ける値が増える)
'use client' の付け外し
- テスト・Storybook・ドキュメントのみの変更
判定手順
差分に対して順に確認する。
- 公開バレル(
packages/smarthr-ui/src/index.ts / packages/charts/src/index.ts)から export の削除・リネームがあるか
- export されているものの型の契約が狭まっているか — 公開コンポーネントの props、公開フック・関数のシグネチャと戻り値、公開型の定義に、削除・リネーム・必須化・受け付ける値の削減があるか
- 既定の挙動・見た目・DOM 出力が変わるか
package.json の peerDependencies の要求バージョンを引き上げているか
いずれも No なら破壊的変更ではない。一つでも Yes なら、差分が小さくても破壊的変更として扱う。
手順2 でコンポーネントだけを見ないこと。src/index.ts は useTheme / useEnvironment とその Provider も export しており、これらのシグネチャや戻り値の型も公開契約に含まれる。
手順4 は見落としやすいわりに影響が大きい。現在 styled-components の peer は ^5.0.1 で、RSC対応のために v6 系へ上げる検討が進んでいるが、これは利用プロダクト側の対応を要する破壊的変更にあたる。
手順3 を「変わらない」と判断したなら、その根拠(DOM出力の比較、既存テストが無変更で通る等)を「確認方法」に書く。
! を付ける場合は必ず承認を得る
上記の判定で「破壊的変更にあたる」と結論した場合、PRを作成せずに一旦止まり、以下を提示してユーザーの承認を得る。
- 壊れる公開API(該当ファイルと、Before/After のシグネチャ)
- 利用者側で必要になる書き換えの内容
判断に迷う場合も同じく止まって聞く。ユーザーは差分の背景を知っているので、数秒で判断できる。承認が得られるまで ! は付けない。
! を付けない場合も判定結果を1行報告する
! なしでPRを作るときは、作成後(または作成前の確認時)に一行で判定結果を伝える。
破壊的変更: なし(src/index.ts の export・公開propsに変更なし)
付け忘れの側の誤りに、ユーザーが気づけるようにするため。
タイトルと本文の整合を必ず確認する
「プロダクト側で対応が必要な事項」が「なし」なのに、タイトルに ! が付いているのは矛盾している。 どちらかが必ず間違っている。
#6971 はまさにこの形だった。本文には自分で「なし。公開コンポーネント(Button/AnchorButton)のprops・DOM構造に変更はない」と書きながら、タイトルは refactor(Button)!: になっていた。本文を書き終えた時点でタイトルと突き合わせていれば、そこで気づけた。
- 本文が「なし」→ タイトルに
! を付けない
- タイトルに
! を付ける → 本文に、利用者が何をどう書き換えるべきかを具体的に書く
バージョンを決めるのはコミットメッセージで、通常はタイトルの1行だけ
release-please が読むのは squash merge されたコミットメッセージであり、PR本文ではない。このリポジトリの設定はコミットタイトル = PRタイトル、コミット本文 = 空(squash_merge_commit_message: BLANK)で、実際 git log で見えるコミット本文は Co-authored-by: のみになっている。
つまり通常のマージでは release-please に届くのはPRタイトルの1行だけで、PR本文にどれだけ丁寧に「破壊的変更ではない」と書いてもバージョン計算には影響しない。タイトルの ! が単独でバージョンを決める。
例外はマージ画面でコミット本文を手入力した場合。 ここに英語表記の BREAKING CHANGE: を書くと Conventional Commits の footer として解釈され、タイトルに ! が無くても major が上がる。#6971 の復旧で Release As: を入れるためにこの欄を実際に使っているとおり、触る場面はある。意図した破壊的変更でない限りこの文字列を書かない。
いずれにせよタイトルは1行しかないぶん、本文のレビューに比べて見落とされやすい。だから本文を書き終えたら、前項の突き合わせを必ず行う。
PRタイトル
Conventional Commits 形式で記述する。日本語で書く。
<type>(<scope>): <subject>
- type:
feat, fix, refactor, chore, docs, test など
- scope: コンポーネント名(任意)
! は破壊的変更を示す。付ける場合は前述の承認が必須
- subject: 変更内容が利用者に伝わるように書く(スカッシュマージのコミットメッセージがリリースノートに反映されるため)
例:
fix(DropZone): inputとButtonの両方にフォーカスが当たってしまうのを解消
refactor(Button): Button/AnchorButtonのclient境界を最小化する(ファイル移動と内部リファクタのみ。! は付けない)
refactor!: コンポーネントサイズ指定を大文字に統一(size="default" が使えなくなるため破壊的変更。承認済みの場合のみ)
feat(StepFormDialog)!: onSubmitの内部の自由度を向上(onSubmit のシグネチャが変わるため破壊的変更。承認済みの場合のみ)
PR本文テンプレート
以下の構造で記述する。HTMLコメントは含めない。各セクションは必ず記載し、該当なしの場合は「なし」と書く。
## 関連URL
(関連するJIRAチケット、Slack URL、GitHub Issuesなどを記載)
## 概要
(PRを作成した目的や解決したい課題を簡潔に記載)
## 変更内容
(どのような変更を加えたのか、マージ後にどう変わるかを具体的に記載)
## プロダクト側で対応が必要な事項
(このPRの変更によりプロダクト側で対応が必要なことを記載。特に破壊的変更の場合は必須)
## 確認方法
(変更内容を確認する方法。Storybookでの確認で十分な場合はその旨を記載)
セクション別の書き方ガイド
関連URL
- JIRAチケット、Slack、GitHub Issuesなど関連リンクを箇条書きで記載
- 関連URLがない場合は「なし」
概要
- PRの目的と背景を簡潔に書く
- 「なぜこの変更が必要か」が伝わるようにする
変更内容
- 具体的に何を変更したかを書く
- コンポーネントの新規追加やスタイル変更がある場合はキャプチャを添付する
- インタフェースの変更(特に破壊的変更)がある場合、Before/After のコード例を記載する
Before/Afterの例:
### 変更例
```tsx
// Before
<Button size="default" />
// After
<Button size="M" />
### プロダクト側で対応が必要な事項
- プロダクト側での書き換えが必要な場合は具体的な対応方法を書く
- ここに書いた内容がリリースノートに転記されるため、利用者に伝わる内容にする
- 破壊的変更でない場合は「なし」
- **ここが「なし」なら、タイトルに `!` は付かない**
### 確認方法
- Storybookやテストでの確認方法を記載
- Chromatic での確認URLがあれば記載
- 「公開APIは変わっていない」と判断した根拠があればここに書く(DOM出力の比較、既存テストが無変更で通る等)
## gh pr create の実行
PR本文は `gh pr create` の `--body` にHEREDOCで渡す:
```bash
gh pr create --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF'
## 関連URL
なし
## 概要
...
## 変更内容
...
## プロダクト側で対応が必要な事項
なし
## 確認方法
...
EOF
)"
実行前に、タイトルの ! の有無と「プロダクト側で対応が必要な事項」の内容が整合しているかを最後にもう一度確認する。
既存PRのタイトルを変更する場合
gh pr edit --title で ! を足す場合も、新規作成時と同じ承認ゲートを通す。マージ前であれば修正は容易だが、マージ後は前述の復旧作業が必要になる。