PR 規律
概要
PR はチームの時間を消費します。ここでの規律は、無駄(驚きのスコープによる再レビュー、誤ったブランチへのマージ、誤った帰属)を発生させる前に防ぐことにあります。
原則: アーキテクチャに関わる変更は事前合意、フォーマットは常に一貫、マージ先は二重確認。
開始時に宣言: 「この PR には pr-discipline を適用しています。」
ステップ 1: コードを書く前にメンテナーと事前調整する(該当する場合)
以下の変更に該当する場合、PR を開く 前に モジュールのメンテナーに提案のパラグラフを送信すること:
- 既存エンドポイントのレスポンス形式。
- DTO やバリデータの構造。
- クロスリポジトリのパターン(バリデータ、サービス、エラーハンドリング)。
- アーキテクチャの抽象化(新しいデコレーター、サービス層、モジュールレベルのパターン)。
テンプレート:
「[メンテナー]、feature Y のために X を実行しようとしています。スコープ:a、b、c。その他の X は Z の理由で現状のままにします。よろしいですか?」
承認を待ちます。反対があれば、テキスト上で反復します(コストが低い)。承認された場合、PR は後から議論されることなく通過します。
適用対象外: コントラクトを変更しないバグ修正、既存パターンに従った機能、モジュール内部のリファクタリング、ドキュメントやテストのみ。
ステップ 2: PR の正しいベースブランチを確認する
PR のベースブランチは常に main とは限りません。use-worktrees スキルを呼び出して解決します(ステップ 1 — 完全なウォーターフォール)。解決されると自動メモリに保持され、以降の呼び出しでは質問なしで適用されます。
このスキルが尊重する一般的なフロー:
| フロー | フィーチャーブランチの基点 | PR のターゲット |
|---|---|---|
| ステージングバッファありのバックエンド | staging | staging(その後 staging → main は別途) |
| モバイル / シンプルな Web | main または main-web | main または main-web |
| 伝統的な Gitflow | dev | dev(その後 dev → master) |
| Trunk-based | main または trunk | main または trunk |
推測せず、常に解決します。
ステップ 3: 作る前に再利用する
新しいファイル、バリデータ、ガード、サービス、コンポーネント、ヘルパー、定数、型を追加する前に:reuse-existing-patterns スキルを呼び出します。このスキルは、カテゴリ別の検索方法、既存のものを使用するタイミング、並列作成が正当となる場合(PR 本文に理由を記載)をカバーします。
この習慣を経ずにコードを書き始めないでください — これは「これは既に存在します。現在のパターンを使用してください」というレビューコメントの最大の原因です。
ステップ 4: PR を作成する — タイトル、本文、帰属
タイトル
- 70 文字未満。長いものは本文へ。
- リポジトリのフォーマットに従う(Conventional Commits があればそれ、なければ短いフレーズ)。
- チームの言語で記述(チームがスペイン語で書くならタイトルもスペイン語)。
本文
最小テンプレート:
## 概要
<何が変更され、なぜ変更されたか、1〜3 つの箇条書き>
## テスト計画
- [ ] <確認するコマンドまたはフロー>
- [ ] <その他>
## リスク
<エッジケース、ロールバック計画、依存関係>
リポジトリにテンプレート (.github/PULL_REQUEST_TEMPLATE.md) があれば、それをベースに使用します。
帰属(コミット ID)
git commit に -c user.email=... や -c user.name=... を決して渡さないでください。 仕事のリポジトリには正しいローカル設定があり、グローバル設定は通常個人用です。誤ってオーバーライドすると、仕事のコミットが個人の GitHub アカウントに帰属してしまいます。
プッシュする前に確認:
git log -1 --format='%an <%ae>'
メールが仕事用でない場合、プッシュせず、事前に修正:
git commit --amend --reset-author # 現在のローカル設定を使用
帰属性だけのために main/staging(保護されたブランチ)の履歴を書き換えないでください — フォースプッシュのコストが利益を上回ります。
ステップ 5: バッククォートが正しいマークダウンをアップロードする
gh pr edit --body-file と gh pr comment --body はバッククォートを \ にエスケープし、フォーマットを壊します。解決策:gh api -X PATCH を JSON ペイロードで使用します。
python3 <<'PY'
import json, subprocess
with open('/tmp/body.md') as f:
body = f.read()
subprocess.run(
['gh', 'api', '-X', 'PATCH', 'repos/<org>/<repo>/pulls/<num>', '--input', '-'],
input=json.dumps({'body': body}), text=True, check=True
)
PY
確認:
gh pr view <num> --json body --jq .body | head -10
バッククォートがリテラル(エスケープされていない)で出力されれば、成功です。
ステップ 6: レビューコメントのスタイル
- 重大度でグループ化:ブロッキング / 軽微な改善 / ニット。
- 発見ごとに 1 つの箇条書き、1 行で:内容 + 理由 + 提案修正。
- 行を参照するには
ファイル.ts:42の形式(GitHub でクリック可能)。 - 観察よりも理由を先に。ピアレビューの余白メモのように、外部監査のようにではなく。
- 作成者が PR 本文で自分の推論を文書化している場合、その推論に関与する — 第一原理から再発明しない。
- 「B1」「M2」のような人工的なタグは不要。役に立たない場合はコードブロック例も不要。
経験豊富な人間のレビュアーが「AI ダンプ」と気付くもの:対称すぎる構造、同じトランジションフレーズ、作成者の文脈がない箇条書き。
ステップ 7: マージする — チームのフローに応じて squash か merge を選択
リポジトリの慣習を確認。一般的なパターン:
| リポジトリタイプ | feature → integration | integration → main |
|---|---|---|
| ステージングありのバックエンド | squash | merge commit |
| ステージングなしのモバイル/Web | squash または merge | N/A |
| 伝統的な Gitflow | merge を dev へ | merge を master へ |
ステージングがあるリポジトリでの非対称性の理由: staging → main を squash すると、PR が巨大に見えます(既に squash された N 個の feature を繰り返します)。merge commit は staging に投入された feature のリストをそのまま保持します。
# feature → staging
gh pr merge --squash <num>
# staging → main(分離しているリポジトリの場合)
git pr merge --merge <num>
リポジトリに staging がある場合、決して直接 main にマージしないでください:
git revertはコードを元に戻しますが、コミットは履歴に永久に残り — チーム全員に見えます。gh pr createの--baseと GitHub UI のマージターゲットを実行前に三重確認。gh pr mergeを実行する前に、ユーザーに「staging にマージしますか?」と質問します。疑わしい場合。
クイックリファレンス
| 状況 | アクション |
|---|---|
| 変更がコントラクトやアーキテクチャに影響する場合 | ステップ 1: メンテナーと事前調整 |
| ブランチを作成する場合 | ステップ 2: ウォーターフォールでベースを解決 |
| 実装を開始する場合 | ステップ 3: パターンがリポジトリに既に存在するか検索 |
| PR を開く準備ができた場合 | ステップ 4: タイトル <70 文字、テンプレート付き本文、帰属確認 |
| コードを含む本文またはコメント | ステップ 5: gh api PATCH を JSON で |
| レビューを残す場合 | ステップ 6: 重大度別の箇条書き、理由から先に |
| マージする場合 | ステップ 7: 慣習に応じて squash か merge |
| ステージングがあるリポジトリ | 決して直接 main にマージしない |
よくある間違い
- 事前調整なしでアーキテクチャ PR を開く。 2〜3 ラウンドの再レビューと後からの議論を引き起こします。コードを書く前に提案のパラグラフを送信すること。
- 既存の同等物があるのに新しいファイルや抽象化を作成する。 まず検索(ステップ 3)。レビュアーは指摘します。
- 完全な説明を含む 70 文字超えのタイトル。 タイトルは短く、詳細は本文に。
- スクリプト化されたコミットに
-c user.emailを渡す。 仕事のローカル設定を個人のグローバル設定で上書きします。 - バッククォートを含む
gh pr edit --body-file file.md。 エスケープされます。gh api PATCHを JSON で使用すること。 - 散文形式のレビュー。 ユーザーは重大度別の箇条書きを望んでいます — スキャン可能、散文ではなく。
- staging → main の squash。 各 feature で既に squash された履歴を繰り返します。merge commit を使用すること。
- 「小さいから」と直接 main にマージ。 コミットは履歴に永久に残り、全員に見えます。
レッドフラグ
絶対にしないこと:
- 事前調整なしでコントラクト/アーキテクチャに影響する PR を開く。
- 既存の同等物があるのに並列ファイルや抽象化を作成する。
git commitに-c user.email/-c user.nameを渡す。git log -1 --format='%ae'を確認せずにプッシュする。- バッククォートを含むマークダウンに
gh pr edit --body-fileを使用する。 - ステージングがあるリポジトリで直接 main にマージする。
- staging → main を squash する。
- 重大度でグループ化せずにレビューを残す。
常にすること:
- アーキテクチャ変更はメンテナーと事前調整。
- PR のベースをウォーターフォールで解決し、
mainと推測しない。 - 新しいパターンを作成する前に、リポジトリに既存のパターンがないか検索。
- タイトル <70 文字 + 本文に 概要 + テスト計画 + リスク。
- プッシュ前にコミットの帰属を確認。
- コードを含むマークダウンには
gh api PATCHを JSON で使用。 - レビューでは重大度別の箇条書き、理由から先に。
- feature → integration は squash、integration → main は merge commit。