mcpField
F
finish-pr

finish-pr

github.com/pinguapps開発0552 回インストール今日更新
リポジトリ

finish-pr について

Finish PR は、現在のブランチに紐づくプルリクエストを定義済みの完了状態に近づけるスキルです。競合、CI、レビュー指摘、PR Agent の確認に対処しつつ、スレッドの解決状態はレビュー担当者に委ねます。

主な機能

  1. 01リポジトリの指示とプルリクエスト状態を確認
  2. 02他の作業に先立ってマージ競合を解消
  3. 03レビュー指摘を個別のコミットで対応
  4. 04公開前に CI と PR Agent の状態を確認

活用シーン

  1. 01ブランチ上のプルリクエストをレビュー完了の条件に整える
  2. 02未解決のインラインレビュー指摘に対応
  3. 03プッシュや返信の前に自動レビューを待つ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pinguapps/skills --skill finish-pr

インストール後、Claude Code で/finish-prを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
scripts/
get-unresolved-pr-threads.ps1
reply-to-review-thread.ps1
wait-for-pr-review.ps1
tests/
reply-to-review-thread.tests.ps1
wait-for-pr-review.tests.ps1

詳細

PR を仕上げる

現在のブランチに紐づくプルリクエストを、実際にマージ可能な状態まで仕上げます。

Git 2.38 以降、リポジトリに対して認証済みの GitHub CLI(gh)、同梱ヘルパー用の PowerShell 7(pwsh)が必要です。

完了の定義

現在の PR の HEAD について、次のすべてを満たした時点でのみ完了です。

  • GitHub とローカルでのマージ検証の両方で、マージコンフリクトがないこと。
  • CI チェックに失敗がないこと。保留中のチェックは実行中のままでもかまいませんが、必須チェックが保留中の間は、PR が完全に準備できていると決して説明しないでください。
  • 未解決のレビューコメントスレッドがすべて、次のいずれかの状態であること。
    • 最新の未対応フィードバックに対応し、エージェントがその結果を返信している。または
    • 最新の関連コメントがエージェントの返信で、その後にレビュアーが返信していないため、スレッドはレビュー待ちであり、重複した作業は不要である。
  • 今回の実行で作成された返信が、保留中の GitHub レビューに残っていないこと。
  • 今回の実行によって、レビューコメントスレッドの解決状態が変更されていないこと。
  • このリポジトリで PR Agent が実行されている場合、正確に現在の HEAD に対して、成功して完了した PR Agent チェック実行、または状態が success の PR Agent コミットステータスがあり、アクティブな PR Agent レビューシグナルがないこと。検出方法と状態の意味については、以下の PR Agent のセクションを参照してください。

未解決のスレッドが、必ずしも未完了とは限りません。解決状態を決めるのはレビュアーであり、会話の順序によって、エージェントが現在対応する必要があるかどうかが決まります。

PR Agent

PR Agent は、実行されている場合とされていない場合があるセルフホスト型のレビュアーです。レビュー対象となるすべての PR の HEAD に投稿される、PR Agent という名前のチェック実行、またはコンテキストが PR Agent の従来のコミットステータス(CHECK_NAME で設定可能)を検出してください。

  • 検出:プルリクエストの現在の HEAD、またはそれ以前のコミットのいずれかに PR Agent のチェック実行かコミットステータスが存在する場合、この PR では PR Agent が実行されていると見なします。PR 内のどこにも存在しない場合は実行されていません。決して待機せず、起動させるための投稿もせず、以下の PR Agent に関するルールはすべてスキップしてください。
  • ステータスの意味:キュー待ち/実行中のチェック実行と従来の pending は、実行中を意味します。完了した failure は指摘事項ありを意味し、完了した success または従来の success は、その HEAD を承認したことを意味します。neutral、キャンセル済み、タイムアウト、スキップ、その他の成功でも指摘事項ありでもない結論、および従来の error は未完了を意味し、承認とは見なしません。インフラストラクチャの障害に合わせてコードを変更するのではなく、サービスエラーと再試行状態を確認してください。以前にアクティビティがあったにもかかわらず現在の HEAD のシグナルがない場合は、自動レビューを待ってください。シグナルが共存する場合、最新のシグナルが 1 つでもアクティブなら公開を控えてください。承認には、最新のシグナルがすべて成功している必要があります。
  • フィードバックの識別:現在の PR Agent のコメントは、その GitHub App から投稿されます。以前のバージョンではオーナーのログイン名が使われていました。レビュアーのメッセージは、隠し `` マーカーまたは PR Agent バッジで識別し、投稿者のログイン名だけで判断しないでください。同梱のウォッチャーは、ログイン名があなたと一致する場合でも、マーカー付きのレビュアーフィードバックを含めます。
  • スレッドへの対応:ほかのすべてのレビュアーとまったく同じロジックを適用してください。指摘に同意して修正する場合は、焦点を絞ったコミットを 1 つ作成し、その後、コミット SHA と検証結果を添えてスレッドに返信してください。異議を唱える場合は、具体的な根拠を示してください。PR Agent のスレッドは決して解決しないでください。解決は PR Agent が担当し、プッシュされた HEAD に対する修正を検証した場合、または正当な却下を受け入れた場合に、スレッドを自動的に解決します。
  • 解決内容の記憶:検証済みの修正、誤検知、意図した動作、受け入れたトレードオフを区別してください。修正済みの不具合が再発することもあり、指摘の却下が有効なのは、その根拠となった前提が引き続き成り立つ間だけです。PR Agent が再度異議を唱えた場合は、新しい根拠がある場合に限って議論を続けてください。それ以外の場合は、返信を待つ状態でスレッドを残してください。
  • 後続レビューによる置き換え:最初のレビューでは PR 全体を確認します。以降の自動レビューでは、最後に完了した祖先レビュー以降の変更と、指摘事項を検証するために必要なコンテキストを確認します。履歴を書き換えた場合や、保存済みの作業と互換性がない場合は、全体レビューが必要になることがあります。プッシュすると実行中のレビューは置き換えられます。以下の自動レビューゲートを使って実行中のレビューを保持し、デフォルトでは PR 全体のレビューを追加で要求しないでください。

運用ルール

  • 会話履歴を最優先のタスクコンテキストとして使用します。このスキルは実装後に呼び出されることが多いため、PR のフィードバックを評価する前に、ユーザーの意図、これまでの決定、トレードオフ、検証内容、既知の制限、現在の設計に至った理由を把握してください。
  • 該当するすべての AGENTS.md と、PR に関連するリポジトリ固有の要件および設計ドキュメントを読みます。これらはリポジトリと PR から特定してください。特定のタスクディレクトリ、ブランチの命名規則、言語、ビルドシステム、ホスティングプロバイダーを想定してはいけません。
  • 未解決のレビューコメントスレッドを、インラインフィードバックの信頼できる一覧として扱います。また、PR レベルのレビューと Issue のコメントも調べ、単独で対応が必要なフィードバックがないか確認してください。
  • 作業ツリーの無関係な変更は保持してください。この実行中に行った変更だけをコミットします。
  • 失敗したチェックより先に競合を解決し、レビューのフィードバックより先に失敗したチェックを解決します。後から得られた情報によって、前の段階を再検討する必要が生じる場合もあります。
  • 正しい変更のうち、最小のものを優先します。動作に関わる修正やリグレッションが起きやすい修正には、対象を絞ったテストを追加します。
  • 不具合を確認したら、変更した実装と関連する PR コードを調べ、同じ原因による別の箇所がないか確認します。フィードバック項目の原因と確認できた箇所は、同じコミット内で修正し、必要に応じて共通の不具合をテストします。PR に含めるべきでない既存の不具合はそのままにします。これは原因に絞った調査であり、リポジトリ全体の整理ではありません。
  • 対応が必要な PR フィードバックのうち、対応によって変更が生じる項目ごとに、対象を絞ったコミットを 1 つだけ作成します。コミットはスカッシュせず、フィードバック項目を 1 つのコミットにまとめてはいけません。関連性があっても同様です。異議を唱える正当な理由がある場合は返信しますが、コミットは作成しません。
  • ユーザーが別途明示的に依頼しない限り、リベース、強制プッシュ、GitHub 上でのプルリクエストのマージ、クローズ、承認、レビュー準備完了への変更は行いません。競合解決の手順では、PR ブランチに最新のベースコミットをマージできます。
  • レビュースレッドを解決済みにしたり、未解決に戻したりしてはいけません。resolveReviewThread、unresolveReviewThread、またはそれらに相当する操作を呼び出してはいけません。
  • レビュースレッドには、1 件ずつ直接返信します。返信を並行して作成してはいけません。
  • スレッドへの返信、異議、確認、リマインダー、プッシュ後の保留中の返信などを含め、プッシュや PR コメントを行う前に、必ず以下の自動レビューゲートを適用してください。
  • プッシュ後に PR Agent やその他のすべての情報源から新たなフィードバックが届いた場合も、以下の収束上限の範囲内で、自律的に対応を続けます。
  • PR 自動化によるレビュー開始を待ちます。原則として、レビューや返答を依頼するために、レビュー担当者(自動または人間)へ催促してはいけません。PR Agent と Copilot 以外のレビュー担当者については、返信が PR の完了に不可欠であり、アクティブなレビューがなく、自動レビュー担当者が 25 分以上、または人間のレビュー担当者が 1 営業日以上応答していない場合に限り、簡潔なリマインダーを 1 回だけ送信します。人間のレビュー担当者の待機時間は、このスキルを再開した実行をまたいで、PR の作成時またはエージェントの最新の返信時から計測します。それ以外の場合は、待機をブロッカーとして報告してください。GitHub の操作、レビュー担当者の割り当てや再割り当て、コメント、CLI コマンド、API 呼び出し、または同等の手段を使って、Copilot に催促したり、レビューまたは再レビューを手動で依頼・開始したりしてはいけません。pinguapps-pr-agent は作成時にすべての Copilot スレッドを引き継ぎます。そのフィードバックに対応し、修正または根拠のある辞退について 1 回返信した後の検証と追加のフォローアップは、そのボットに委ねてください。
  • PR Agent 用のトリガーコメントや代替手段を投稿してはいけません。PR Agent は実行時に PR とプッシュを自動検出します。完了のシグナルとして、チェック実行結果、従来のコミットステータス、インラインスレッドを使用してください。
自動レビューゲート

このゲートの対象は PR Agent のみです。他のレビュアーや無関係な CI チェックは、このゲートを通じたプッシュやコメントをブロックしません。既存の CI およびフィードバック要件は引き続き適用されます。

各プッシュまたは PR コメントの直前に、公開されている PR のヘッドと、その PR Agent のチェック実行、およびレガシーの PR Agent コミットステータスを最新の状態に更新してください。gh pr checks を使用して、任意のものを含むすべてのチェックを確認してください。正確なヘッド、プロバイダー、または最新のステータスを特定する必要がある場合は、チェック実行とコミットステータスの API 結果をページネーションで取得してください。この PR で PR Agent が実行されていない場合に限り、ゲートをスキップします。PR Agent が検出された場合、現在のヘッドに関するシグナルがないことは完了の証明にはなりません。自動レビューを待ってください。

同梱の scripts/wait-for-pr-review.ps1 -Inspect -PrNumber <number> -Repository <host/owner/repo> は、ヘッドを検証した最新のスナップショットと、チェック実行およびレガシーステータスに対する prAgentStatus 分類(pending、success、failure、incomplete、absent)を出力します。両方の API をページネーションで取得し、App ごとに同名の実行のうち最新のものを選択します。読み取りまたは認証に失敗した場合は、存在しないものとして扱わず、不明かつブロック中として扱ってください。現在のシグナルがない場合も、過去の検出結果は引き続き適用されます。互換性のないステータス判定を独自に再構築するのではなく、この分類をゲートとフォールバックの監視処理に使用してください。

  • PR Agent の最新の現在のヘッドに対するレビュー用チェック実行のうち、completed でないもの(キュー待ちまたは実行中のものを含む)がある場合、または最新の現在のヘッドに対するレガシーステータスが pending の場合、PR Agent はアクティブです。
  • PR Agent がアクティブな間は、すべての修正、コミット、返信の下書きをローカルに保持してください。宛先やコミットへの言及の有無を問わず、PR コメントをプッシュまたは投稿してはいけません。レビューが完了した他のレビュアーからのフィードバックには対応してください。PR Agent のフィードバックはレビューが完了するまで保留にしてください。
  • PR Agent が完了したら、フィードバックを再取得し、新たに完了したフィードバックに対応してから、公開する一連の変更を再度フィードバック監査してください。完了には指摘や失敗が含まれる場合があります。このゲートで求められるのはレビューの完了であり、承認ではありません。完了の定義では、引き続きすべての結果が正常終了している必要があります。
  • プッシュの前、および各コメントを順番に投稿する前に、ゲートを再確認してください。以前の待機中でないことを示すスナップショット、取得済みのベースライン、監視結果、または成功したプッシュは、次の変更を許可するものではありません。プッシュによってすぐに新たなレビューが始まる場合があります。保留中の返信は PR Agent の完了まで保持し、その後、重複や不要になった返信を避けるため、スレッドを再取得してください。
  • 既定の 25 分の待機時間または全体の収束期限内に完了を確認できない場合は、ローカルのコミットと保留中の返信をそのまま残して停止し、ブロッカーを報告してください。タイムアウトしてもゲートを回避することはできません。

1. 状態と意図を確認する

  1. リポジトリのルートを特定し、適用される指示を読みます。

  2. 次を調べます。

    git status --short
    git rev-parse --abbrev-ref HEAD
    git rev-parse HEAD
    gh --version
    gh auth status
    gh pr view --json number,title,url,body,author,headRefName,headRefOid,headRepository,headRepositoryOwner,isCrossRepository,baseRefName,baseRefOid,mergeable,mergeStateStatus,reviews,comments
    
  3. 開始時の SHA と、既存の変更パスをすべて記録し、ステージ済み、未ステージ、未追跡に分けます。この実行で行うコミットに、既存の変更を含めてはいけません。フィードバックまたは CI の修正では、ステージ済み、未ステージ、未追跡のいずれかの変更がすでに存在するパスに触れてはいけません。そのパスを編集する前に停止してユーザーに確認してください。部分的なステージングと git commit --only を使っても、同一ファイル内のハンクを分離した状態は維持できません。

  4. 現在のブランチに PR がない場合は、gh pr status を調べます。対応関係が明確でローカルの変更が安全な場合に限り、PR に切り替えるかチェックアウトします。それ以外の場合はユーザーに確認します。

  5. 変更の意図を、次の優先順位に従って再構成します。

    • ユーザーの明示的な指示とこの会話
    • 適用されるリポジトリの指示
    • PR のタイトル、本文、コミット、差分
    • 関連する Issue、仕様、設計ドキュメント
    • 周辺のコード、テスト、規約
  6. 競合、CI、フィードバックを評価する前に、PR の差分全体を確認します。

  7. 上記のルールに従い、現在および以前の PR コミットから PR Agent を特定します。PR Agent の正確な HEAD を対象とするチェック実行または従来のステータスを、処理/完了の境界として扱い、レビューのスレッドから指摘を読み取ります。

  8. 認証済みの GitHub 閲覧者のログイン名を特定します。そのログイン名、または会話/PR の履歴からエージェントのログイン名だと明確に確認できる別のログイン名によるコメントは、エージェントからの応答として扱います。

  9. PR のメタデータから、ベースリポジトリとヘッドリポジトリを個別に特定します。

    • PR の URL からベースリポジトリを特定します。
    • ヘッドリポジトリには headRepository.nameWithOwner を使用します。
    • それらのリポジトリと正確に一致する、既存の設定済みリモートを優先します。
    • 一致するリモートがない場合は、GitHub から提供されたクローン URL を使用し、認証済みの gh クレデンシャルヘルパーを使うよう Git を設定します。
    • 正確な headRefName を保持します。
    $pr = gh pr view --json number,url,headRefName,headRefOid,headRepository,headRepositoryOwner |
      ConvertFrom-Json
    $prNumber = [int]$pr.number
    $prUri = [uri]$pr.url
    $pathSegments = $prUri.AbsolutePath.Trim("/").Split("/")
    $githubHostname = $prUri.Authority
    $baseRepositoryName = "$($pathSegments[0])/$($pathSegments[1])"
    $baseRepository = "$githubHostname/$baseRepositoryName"
    $baseMetadata = gh api --hostname $githubHostname "repos/$baseRepositoryName" |
      ConvertFrom-Json
    $headMetadata = gh api --hostname $githubHostname "repos/$($pr.headRepository.nameWithOwner)" |
      ConvertFrom-Json
    gh auth setup-git --hostname $githubHostname
    $baseFetchUrl = [string]$baseMetadata.clone_url
    $headPushUrl = [string]$headMetadata.clone_url
    

    GitHub の clone_url は、デフォルト以外のポートを含むサーバーの権限部分を維持します。また、gh auth setup-git を使うと、HTTPS による Git 操作で認証済みの CLI ID が使用されます。一致が確認された SSH/設定済みリモートを使用してもかまいません。認証、リポジトリの同一性、またはヘッドリポジトリが利用できないか、特定が曖昧な場合は停止します。フォークベースの PR で、origin がいずれかの側を指していると決めつけてはいけません。

  10. 変更を加える前に、チェックアウトを PR の正確なヘッドに合わせます。

git fetch $headPushUrl $pr.headRefName
$remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
$lastObservedPrHeadSha = $remoteHeadSha
$localHeadSha = (git rev-parse HEAD).Trim()
git merge-base --is-ancestor $remoteHeadSha $localHeadSha
$localContainsRemoteHead = $LASTEXITCODE -eq 0

if ($localContainsRemoteHead -and $localHeadSha -ne $remoteHeadSha) {
  $initialLocalAheadCommits = git log --oneline "$remoteHeadSha..$localHeadSha"
  # Validate and record every commit against the recovered user intent and full PR diff.
  # Stop for confirmation if any commit is unrelated, unfinished, or ambiguous.
}

if (-not $localContainsRemoteHead) {
  git merge-base --is-ancestor $localHeadSha $remoteHeadSha
  $canFastForward = $LASTEXITCODE -eq 0 -and -not (git status --porcelain)
  if (-not $canFastForward) {
    throw "Local HEAD is stale or diverged from the PR head; stop before mutation."
  }

  git merge --ff-only $remoteHeadSha
}

ローカルの HEAD が取得した PR ヘッドと一致する場合、それへ安全に早送りできる場合、または最初からローカルにのみ存在したすべてのコミットが、会話とリポジトリの証拠に基づいて意図された PR 作業だと明示的に検証されている場合に限り、続行します。それらのコミットは既存のプッシュ対象として記録します。不確かな点があれば確認のために停止します。ローカルにのみ存在するコミットを、決して黙って公開してはいけません。 11. リポジトリ外に一意の状態ディレクトリを作成し、実行全体を通して保持します。

$runStateDirectory = Join-Path ([IO.Path]::GetTempPath()) (
  "finish-pr-{0}-{1}" -f $prNumber, [guid]::NewGuid().ToString("N")
)
New-Item -ItemType Directory -Path $runStateDirectory | Out-Null

並行実行によって互いのファイルが上書きされないよう、この実行のベースライン、スナップショット、ウォッチャー状態ファイルはすべてこのディレクトリ内に保存します。

2. マージコンフリクトを解決する

CI やフィードバックの前に、以下を実行します。

  1. PR/ベースブランチのメタデータを更新し、変更を加えないローカルプローブを実行します。

    $pr = gh pr view $prNumber --repo $baseRepository --json number,url,baseRefName,baseRefOid,headRefName,headRefOid,headRepository,headRepositoryOwner,mergeable,mergeStateStatus |
      ConvertFrom-Json
    git fetch $baseFetchUrl $pr.baseRefName
    $baseCommit = (git rev-parse FETCH_HEAD).Trim()
    git merge-tree --write-tree --messages HEAD $baseCommit
    
  2. GitHub が CONFLICTING、DIRTY、UNKNOWN と報告した場合、またはプローブでコンフリクトが報告された場合は、ローカルで調査します。

  3. コンフリクトがある場合は、マージする前に初期状態のワークツリーを確認します。通常のマージにはクリーンなインデックスが必要です。既存のステージ済み変更が残っている場合は、変更を加える前に停止し、コミットまたはスタッシュするようユーザーに伝えるか、インデックスを分離して復元する明示的な許可を求めます。許可なく、ユーザーの作業に --autostash を使用しないでください。

    インデックスがクリーンで、無関係なローカル変更に問題がなければ、最新のベースブランチを PR ブランチにマージします。

    git merge --no-ff $baseCommit
    
  4. 復元したタスクの意図、リポジトリの要件、周辺のコード、テストに基づいて各コンフリクトを解決します。どちらか一方を機械的に優先しないでください。

  5. 対象を絞って検証し、解決内容だけをステージしてコミットします。コンフリクトの概要、コミット SHA、実行したチェックを記録します。

  6. マージに問題がない場合は、Git が作成したマージコミットをそのまま残し、追加の空コミットは作成しないでください。

3. 失敗した CI を修正する

  1. すべてのチェックを調べます。

    gh pr checks $prNumber --repo $baseRepository --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    gh pr checks $prNumber --repo $baseRepository --required --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    

    2 つ目のクエリを使って、必須チェックと任意チェックを区別します。「必須チェックが報告されていない」場合は、失敗ではなく必須チェックが空の状態として扱います。

  2. 各失敗について、編集する前に実際のログを取得します。

    gh run list --repo $baseRepository --branch $pr.headRefName --commit $pr.headRefOid --json databaseId,name,workflowName,status,conclusion,url,headSha,event,createdAt -L 50
    gh run view <run-id> --repo $baseRepository --json name,status,conclusion,jobs,url
    gh run view <run-id> --repo $baseRepository --log-failed
    
  3. Actions 以外のチェックについては、プロバイダーのリンクまたは利用可能なチェックの詳細を調べます。

  4. 症状だけでなく根本原因を修正します。ある失敗が他の失敗に波及している場合があるため、最も明確な上流の失敗から順に対応します。

  5. 最も近いローカルの同等チェックを実行し、初期状態のワークツリーを確認してから、その修正だけをステージします。既存のステージ済み変更が CI のコミットに含まれないよう、正確なパス指定を使ってコミットします。

    git commit --only -m "fix(ci): address <failed check>" -- <exact-ci-fix-paths>
    

    CI 修正対象のパスにステージ済み、未ステージ、または未追跡の変更がすでにある場合は、編集する前に停止します。チェック、原因、SHA、検証結果を記録します。

  6. 失敗が外部要因、不安定な動作、権限の問題、またはリポジトリで修正できない問題の場合は、証拠を記録します。安全であり、サポートされている場合に限って再試行します。無関係な失敗に合わせるためにコードを変更しないでください。

4. フィードバックの取得と分類

読み込まれたスキルのディレクトリを特定し、同梱されているヘルパーは絶対パスで使用してください。スキルが対象リポジトリ内にあると想定しないでください。

各スレッドの読み取り専用の解決ベースラインをすべて取得し、リポジトリの外部に保存してください。

$threadBaseline = Join-Path $runStateDirectory "thread-resolution.json"
$threadSnapshot = Join-Path $runStateDirectory "unresolved-threads.json"
pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname -All |
  Set-Content -Encoding utf8 $threadBaseline

pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname |
  Set-Content -Encoding utf8 $threadSnapshot

未解決のスレッドごとに、ページ分割されたコメントをすべて時系列順に読み、分類してください。隠し `` マーカーまたは PR Agent バッジが付いたコメントは、投稿者のログイン名にかかわらず、すべてレビュアーのフィードバックとして分類してください。そのうえで、スレッドを次のように分類してください。

  • Copilot への引き継ぎ: Copilot がスレッドを作成した場合は、そのフィードバックに対応し、修正または根拠に基づく却下の返信を一度だけ投稿してください。pinguapps-pr-agent が返信を検証し、その後のフォローアップを処理します。Copilot にレビューを依頼したり、リマインダーを送ったりしないでください。
  • レビュアーの応答待ち: 最新の関連コメントが、送信済みレビュー内のエージェントの応答(pullRequestReview.state != PENDING かつ submittedAt が null ではない)であり、その後に誰も返信していない場合です。何もしないでください。リマインダーを投稿したり、修正を繰り返したり、応答を重複させたりしないでください。このルールでは PR Agent のメッセージもレビュアーのメッセージとして扱います。PR Agent が返信(検証結果、異議、解決の通知)した場合、スレッドはあなたの対応待ちか、すでに対応によって解決済みです。
  • 対応が必要: エージェントの最新の送信済み応答より後にレビュアーのフィードバックがある場合、エージェントがまだ応答していない場合、または最新の応答が保留中のレビューにのみ存在する場合です。PR Agent にもこの会話順序のルールを適用してください。すでに応答待ちの未解決スレッドについては、修正や返信を重複させる必要はありません。新たに対応が必要なフィードバックには、同意して対象を絞ったコミットで修正するか、根拠を示して異議を述べ、PR Agent に再評価させてください。
  • 解消済み/対応不要: それ以降の会話で、その指摘が明示的に撤回、回答、または置き換えられている場合です。エージェントによる確認がまだ必要な場合に限って返信し、すでにあるエージェントの応答を重複させないでください。PR Agent がスレッドを解決した直後に「verified ... resolving this thread」と解決の通知を投稿している場合、返信は不要です。

対応が必要なスレッドでは、個別のフィードバック項目をそれぞれ特定してください。ユーザーの意図、会話履歴、リポジトリのルール、関連する要件、PR の範囲、現在のコード、慣例、テストに照らして判断してください。スレッドをコミットの境界とします。1 つのスレッドに必要な作業は、そのスレッドの単一のコミットにまとめます。ただし、別のスレッドの作業は決して含めないでください。

PR レベルのレビュー本文と Issue コメントのうち、対応可能なものも同じルールで分類してください。単独のフィードバック項目ごとに独立したコミット境界とし、レビューのスレッドや別の単独項目とまとめないでください。レビューのスレッド ID がないため、フィードバック ID とパーマリンクで追跡してください。

  • 実際のバグ、見落とされた要件、破られた不変条件、欠けているテスト、誤解を招く動作、または対象範囲内の保守性の問題を指摘している場合は、同意してください。
  • 要件、確立された意図、リポジトリの不変条件と矛盾する場合、またはより悪い設計や対象範囲外の設計につながる場合は、異議を述べてください。
  • 判断に迷う場合は、根拠があれば小規模で対象を絞った正確性の修正を行ってください。そうでない場合は、変更しない理由と不確実な点を説明してください。

古くなった未解決のスレッドも省略せず、そのフィードバックが現在のコードにまだ当てはまるか確認してください。

5. 修正して返信する

自動レビューゲートの対象となる、対応が必要なレビューのスレッドまたは単独のフィードバック項目ごとに、次の手順を行います。

  1. そのスレッド内の対応可能な項目すべてに対し、対象を絞ったテストを含め、必要十分な最小限の修正を行います。

  2. 意味のある範囲で最も限定的な検証を実行します。

  3. その項目に関するファイルだけを確認してステージングします。

    git status --short
    git diff
    git add <paths>
    git diff --cached
    

    他のパスにある無関係なステージ済み変更は、そのままステージ済みにしておきます。修正対象のパスに事前にステージ済み、未ステージ、または未追跡の変更がある場合は、そのファイルの編集を始める前に中止してください。同じファイルを分離するために、部分的なステージングの後で git commit --only に頼ることは決してしないでください。

  4. 対応によって変更が生じた場合は、次の項目に進む前に、フィードバック単位ごとに必ず1つのコミットを作成します。

    git commit --only -m "fix(pr): address <thread summary>" -- <exact-thread-fix-paths>
    

    フィードバックのコミットを修正、スカッシュ、または統合しないでください。先行する単位の変更で、後続の合意済み単位が完全に満たされ、個別のファイル変更が残らない場合は、そのコミット履歴を統合するのではなく、後続の単位に対して --allow-empty を指定した追跡可能性を明示するコミットを作成してください。正当な異議がある場合は、コミットを作成しないでください。

  5. レビュースレッドのフィードバックについては、自動レビューゲートおよび以下のコミット延期条件に従い、評価と関連するコミットの作成後に、スレッドへ直接返信します。どちらかの条件により投稿が妨げられる場合は、返信文をローカルで作成し、キューに入れてください。

    $body = @"
    Agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    pwsh <skill-directory>/scripts/reply-to-review-thread.ps1 -ThreadId "<thread-id>" -Hostname $githubHostname -Body $body
    

    単独のフィードバックについては、該当するフィードバックのパーマリンクを正確に示すPRレベルの返信を投稿します。

    $body = @"
    Regarding [this feedback](<feedback-permalink>): agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    gh pr comment $prNumber --repo $baseRepository --body $body
    

    単独の正当な異議についても同じPRレベルの方法を使い、フィードバックのパーマリンクと、以下の異議の文面を含めてください。

    正当な異議の場合:

    I don't think this change is correct for this PR.
    
    Reason: <specific reason grounded in requirements, conversation, or code>.
    
    No code change made.
    

    PR Agent のフィードバックへの対応によって、まだプッシュされていないコミットが作成された場合は、バッチをプッシュして自動レビューゲートが解除されるまで、そのスレッドまたはPRレベルの返信を延期してください。PR Agent はローカルにしかない SHA を検証できません。コミットを確認できる前に返信すると、誤解を招く追加レビューにつながる可能性があります。異議にはコミットの依存関係はありませんが、ゲートが解除される必要があります。すべての返信は順番に行ってください。

  6. 変更が生じた対応について、フィードバック単位 ID とコミット SHA の1対1の対応関係に加え、すべての対応、検証結果、および返されたコメント ID を記録します。レビュースレッドにはスレッド ID を、単独の項目にはフィードバック ID を使います。正当な異議については no commit — disagreement と記録します。

返信ヘルパーは、GitHub の単一コメント返信エンドポイントを使用するため、共有される保留中のレビューを送信したり変更したりすることはありません。その後、state != PENDING かつ submittedAt が null ではないことを検証します。ヘルパーの失敗はブロッキング要因です。コメント URL が返されたことだけでは、投稿の証明になりません。

返信がキューに残っている場合も含め、各フィードバックバッチの後に次の手順を行います。

  1. -All を指定してすべてのスレッドを再取得し、PR レベルのレビューとイシューコメントも再取得します。
  2. この実行で作成された返信がすべて、送信済みレビューに属していることを検証します。
  3. 認証済みユーザーが、この実行より前に作成されたレビューも含め、PR 上に保留中のレビューを持っていないことを検証します。
  4. ベースラインに存在するすべてのスレッド ID について、isResolved の値を現在の値と比較します。ベースラインの解決状態は変更されていない必要があります。外部による変更を報告し、元に戻す操作は決して行わないでください。レビューの収束中に新しいスレッド ID が生じることは想定内です。解決状態の変更として扱うのではなく、追加のフィードバックに分類してください。
  5. バッチ中に対応が必要な新しいレビュースレッドまたは単独のフィードバック項目が現れた場合は、対象となる各項目に個別のコミットで対応し、監査を繰り返します。自動レビューゲートが解除され、更新後のフィードバック一式に対応済み、またはレビュー担当者の応答待ちとなった場合に限り、プッシュは一度だけ行います。ローカルでの対応が完了し、返信がキューに入っている項目は、このプッシュ前の監査では対応済みとして扱います。ただし、コミットの延期条件とゲートが解除された後に返信する必要があります。返信が投稿されるまでは、レビュー担当者の応答待ちにはなりません。

6. プッシュしてレビューを収束させる

  1. この実行で作成された未コミットの変更がワークツリーにないことを確認します。スレッドごとのコミットを作成するたびに個別にプッシュしないでください。実行中の PR Agent レビューが完了し、更新後のフィードバック監査に問題がないことを確認してから、スカッシュされていないスレッドのコミットをすべてまとめてプッシュします。

  2. 開始時の SHA 以降のコミットと、実行開始時点ですでにローカルが先行していた検証済みのすべてのコミットを確認してから、プッシュ前に PR の正確なヘッドをフェッチします。

    git log --oneline <starting-sha>..HEAD
    git fetch $headPushUrl $pr.headRefName
    $remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
    $localHeadSha = (git rev-parse HEAD).Trim()
    $currentPrHeadSha = (gh pr view $prNumber --repo $baseRepository --json headRefOid --jq .headRefOid).Trim()
    $pushRequired = $localHeadSha -ne $remoteHeadSha
    git status --short --branch
    

    $remoteHeadSha と $currentPrHeadSha が異なる場合、またはいずれかが $lastObservedPrHeadSha と異なる場合は停止します。予期しないリモートの値で $lastObservedPrHeadSha を上書きしないでください。PR ヘッドをプッシュする必要があるかどうかは、開始時の SHA のコミット範囲ではなく、$pushRequired を使って判断します。この範囲は報告用のコンテキストにすぎません。

  3. $pushRequired が真の場合は、$reviewRound をインクリメントし、プッシュの直前にレビューのベースラインを記録します。

    $reviewRound++
    $reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -CaptureBaseline `
      -StatePath $reviewState `
      -PrNumber $prNumber `
      -Repository $baseRepository `
      -Hostname $githubHostname `
      -PrAgentContext "PR Agent"
    
  4. プッシュの直前に、公開済みのヘッドを対象に自動レビューのゲートを再確認します。ブロックされている場合は、バッチをローカルに保留し、完了を待ってから、ベースラインを再取得する前にフィードバック監査とヘッドの確認を繰り返します。問題がなければ、強制プッシュせずにプッシュし、正確な HEAD を記録します。

    $reviewRequestedAt = [DateTimeOffset]::UtcNow
    git push $headPushUrl "HEAD:refs/heads/$($pr.headRefName)"
    $expectedHeadSha = git rev-parse HEAD
    $lastObservedPrHeadSha = $expectedHeadSha
    

    プッシュ後も返信をキューに保持します。返信ごとに自動レビューのゲートを再確認し、プッシュによって PR Agent レビューが開始されている場合は、完了を待ちます。その後、フィードバックを再読み込みし、現在表示されているコミット SHA と検証結果を含めて、まだ必要な返信のみを順番に投稿します。スレッドへの返信が送信されたことを確認し、フィードバックを更新します。意見の相違や、ほかのレビュアーへの返信にも同じゲートを適用します。

  5. プッシュ後、PR Agent が実行中の場合は、正確な HEAD を対象とする結果を待ちます。

    • PR Agent のチェック実行またはレガシーのステータス: 利用可能であれば環境の PR ウォッチャーを使い、起動のたびに正確なヘッドの監査を再開します。それ以外の場合は、下記の同梱の -Wait コマンドを使います。このコマンドは -Inspect と同じ分類で、両方のシグナル種別に対応します。正確なヘッドの結果が成功し、新しいフィードバックがなければ、そのまま最終監査に進めます。
    • PR Agent が実行中でない場合: チェックとフィードバックを更新してから、最終監査に進みます。存在しないインテグレーションを待たないでください。
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -Wait `
      -StatePath $reviewState `
      -ExpectedHeadSha $expectedHeadSha `
      -ReviewRequestedAt $reviewRequestedAt `
      -TimeoutMinutes 25 `
      -PollSeconds 20
    

    長時間実行するツール呼び出しとして実行します。実行中は環境の待機機能のみを使用し、ユーザーに中断されない限り何も出力しないでください。ウォッチャーが繰り返しのポーリングをモデルのコンテキスト外で処理します。

  6. 選択した待機パスの結果を、以下の結果に従って処理します。バンドルされたウォッチャーは、他のレビュアーと同様に newFeedback を通じてインラインの指摘を配信します。別のレビューが進行中でもフィードバックが届くことがあります。自動レビューのゲートを使って、どのフィードバックが対象となるか、公開が許可されているかを判断してください:

    • feedback:コンテキストを把握するためフィードバックをすべて取得しますが、対応するのは新たに対応が必要なフィードバックのみです(バンドルされたウォッチャーを使用する場合は newFeedback ID)。これには、インラインスレッド(PR Agent、Copilot、その他のレビュアーによるもの)、あらゆるレビュアーからの PR レベルのフィードバック、コメントを取得できないまま PR Agent が failure を報告した場合の合成 pragent_status 項目が含まれることがあります。新しいコメントが古い未解決スレッドに追加された場合は、スレッド全体を読み、最後のエージェントの応答以降のフィードバックのみを処理します。PR Agent の指摘にも、同意して修正する/異議を伝えるという同じルールが適用され、プッシュされた修正を再検証してスレッドを自動的に解決します。Copilot のスレッドには、pinguapps-pr-agent がフォローアップできるよう、対応方針を一度だけ返信してください。Copilot に再レビューを依頼してはいけません。
    • approved:最新の完全一致する HEAD に対する PR Agent のシグナルがすべて成功しています。チェック、PR レベルのフィードバック、スレッドを一度再取得し、完了の定義全体が引き続き満たされている場合にのみ完了とします。
    • incomplete:レビューが承認も指摘ありの判定もないまま終了しました。チェック出力と再試行の状態を調べ、既にスケジュールされている再試行を既存の上限内で待つか、サービスのブロッカーを報告します。これをコードへのフィードバックや承認として扱ってはいけません。また、コメントでレビューを起動してはいけません。
    • timeout:必須の自動レビュアーが、レビューが進行中でない状態で丸 25 分間応答していないか確認します。人の場合は、PR の作成時、または最新のエージェントの返信から、営業日で 1 日が経過していることを確認します。これには再開後の実行も含まれます。PR を完了するために返信が不可欠な場合に限り、運用ルールの対象レビュアーに対する 1 回限りのリマインダー例外を検討できます。PR Agent と Copilot は対象外です。それ以外の場合は待機をブロッカーとして報告し、準備完了を主張してはいけません。
    • head_changed:新しい状態を取得して確認します。他のアクターによるプッシュで以降の変更が安全でなくなった場合は停止します。
    • pr_closed:停止して PR の状態を報告します。
  7. 新しいフィードバックがあった場合は、対象となる修正 → 検証 → コミット → キュー投入またはゲートで制御された逐次返信 → 完了済みレビューと更新された監査 → ベースライン → ゲートで制御されたプッシュ → 待機、を繰り返します。ゲートが解除され、コミットの延期条件も解消された場合にのみ、引き続き必要な返信をキューから送信します。返信監査に合格した後に限り完了とします。

プッシュが不要な場合は、ステップ 5 と同じ待機パスの選択を使用します。ゲートが解除され、残りの完了条件が満たされていれば、現在の完全一致する HEAD に対する PR Agent チェックまたはレガシーステータスの成功で十分です。PR Agent が存在しない場合は、最終監査に直接進みます。それ以外の場合は現在の状態を記録し、自動レビューを読み取り専用で待ってから、デフォルトのトリガーを投稿せずに同じタイムアウトルールを適用します。

$expectedHeadSha = (git rev-parse HEAD).Trim()
$reviewRound++
$reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -CaptureBaseline `
  -StatePath $reviewState `
  -PrNumber $prNumber `
  -Repository $baseRepository `
  -Hostname $githubHostname

環境に PR ウォッチャーがない場合は、どちらのシグナルタイプについても次の待機コマンドを実行します。

pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -Wait `
  -StatePath $reviewState `
  -ExpectedHeadSha $expectedHeadSha `
  -ReviewRequestedAt ([DateTimeOffset]::MinValue) `
  -TimeoutMinutes 25 `
  -PollSeconds 20

ウォッチャーは、想定される PR の HEAD を検証し、現在のチェック実行とレガシーステータスを分類してから、承認、指摘、または未完了を報告します。レビュー完了前に新しいフィードバックが届くとウォッチャーが起動することがありますが、すべての公開は引き続き自動レビューのゲートに従います。API エラーが発生した場合、統合が存在しないかのように振る舞うのではなく、ヘルパーを終了します。

3 回目のレビューラウンドのプッシュ後、残っているフィードバックを、新たなリグレッション、繰り返し発生している意見の相違、または以前に見落とした事例に分類します。アプローチや要件の解釈が手戻りの原因になっていないか確認します。残りの作業について、具体的で証拠に裏付けられた計画がある場合にのみ続行します。それ以外の場合は、承認を主張せずにブロッカーを報告します。このチェックポイントでは、レビュー全体をもう一度依頼したり、カウンターをリセットしたりしません。プッシュを伴うレビューは最大 5 ラウンド、全体の所要時間は最大 2 時間という厳格な上限を維持します。問題のない結果、タイムアウト、クローズ、予期しない HEAD の変更、または実際のブロッカーが発生した場合は、上限に達する前でも停止します。

最終監査と報告

レビュー修正によって動作、判断、検証、または復旧方法が変わった場合は、保存済みPRのレビューコンテキストを更新してください。テンプレートと、無関係な作成者の内容は維持してください。この更新を公開する前にも、同じ自動レビューのゲートに従ってください。現在のHEADでの検証結果と重大な不足点を記録し、手動テストの引き継ぎ内容を重複させないでください。ワークフローをときどき評価する場合は、実際に人が介入した内容とおおよその実作業時間(分)を、PR Agentのモデルコストとは別に記録してください。待ち時間は人の作業時間ではありません。

キャッシュされた状態に頼らず、再取得してください。

  • PRのHEAD、マージ可能性、ベースブランチ
  • 最新のベースコミットと、新しい git merge-tree --write-tree --messages HEAD <base-commit> による競合確認
  • すべてのチェック
  • gh pr checks --required を使って個別に取得した必須チェック
  • 現在のHEADと一致する PR Agent のチェック実行ステータス/結論、および従来のコミットステータス(このリポジトリでPR Agentが実行されている場合)
  • PRレベルのレビュー/コメント
  • すべてのレビュー スレッドと返信の送信状態
  • ローカル/リモートのブランチ状態とワークツリー

簡潔に報告してください。

  • PR番号とURL
  • 競合とCIの結果、およびコミット
  • スレッド数:対応済み、レビュアー待ち、意見不一致
  • 修正内容、重点的な検証、コミットSHA
  • プッシュ結果とレビューラウンド数
  • 現在のHEADに対する最終的な PR Agent の結果:成功したチェックの完了、または従来の success(プルリクエストにどちらのシグナルもない場合は not running)
  • 未返信のレビュー返信数:0
  • レビュースレッドの解決状態を変更した回数:0。ベースラインの監査結果も記載
  • ブロッカー、または保留中の必須チェック

コメント