mcpField
P
pr-recap

pr-recap

github.com/mdsmithaustinその他844 回インストール今日更新
リポジトリ

pr-recap について

pr-recapは、レビュー担当者向けのプルリクエスト要約をGitHubコメントとして作成するスキルです。差分の分析から、任意の図の作成、コメントの更新までを案内します。

主な機能

  1. 01差分に基づく主張の検証
  2. 02レビュー担当者向けの構成
  3. 03任意のPNG機構図
  4. 04GitHubコメントの更新手順
  5. 05コミットSHAとリンクの確認

活用シーン

  1. 01動作変更を含むプルリクエストの要約
  2. 02新しいコミット後の要約更新
  3. 03投稿前の要約内容の検証

インストール

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

$npx skills add https://github.com/mdsmithaustin/pstack --skill pr-recap

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

同梱ファイル

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

CREDITS.md
references/
block.md
reader.md
sketch.md
references/examples/
bars.json
check.json
flow.json
rewire.json
to-scale.json
scripts/
attachment.mjs
scripts/sketch/
bun.lock
draw.mjs
package.json
sketch.mjs
scripts/sketch/vendor/
OFL-Excalifont.txt

詳細

PR の要約

レビュー担当者向けに、プルリクエストの要約を1つ作成します。レビュー担当者が最初の画面を見ただけで、変更の理由、変更内容、変更方法を理解できるようにします。要約では差分を参照します。差分を読むことに代わるものではありません。

このワークフローはローカルで実行します。要約は、GitHub Markdown と PR 自体のホストにアップロードした PNG 画像1枚を含む、1つの PR コメントです。gh が必要です。スケッチには Bun と同梱のスケッチツールが必要です。他のホストには何も投稿しません。

PR に要約を付けるか判断する

レビュー担当者が追跡する必要のある動作が差分に含まれていない場合は、要約を省略します。たとえば、バージョンの固定とそのハッシュ、誤字や文言の修正、書式のみの変更、ロックファイルのみの変更、1つのコミットのリバートなどです。バージョンの固定は、メジャーバージョンをまたぐ場合でも省略します。固定にはスケッチにできる仕組みがないためです。

要約を省略する PR には、GitHub に何も投稿しません。返信には次の1行を記載します。

Recap skipped for PR <n>: <what the diff is>, <why it needs no recap>.

それ以外の場合は、要約を作成します。差分が変わるプッシュのたびに、新しいヘッドが公開され、その上で実行されたゲートの結果が出た後、要約を再作成します。

事実を集める

  1. origin の fetch URL から <host>/<owner>/<repo> を特定します。すべての gh pr 呼び出しに -R <host>/<owner>/<repo> を指定します。すべての gh api 呼び出しに --hostname <host> を指定します。
  2. gh pr view <n> -R <host>/<owner>/<repo> --json number,title,body,baseRefName,baseRefOid,headRefOid,files,commits,reviews,comments,closingIssuesReferences で PR の記録を読みます。baseRefOid と headRefOid を記録します。要約に記載するすべての事実は、これら2つの SHA の間の差分を説明するものにします。
  3. gh pr diff <n> -R <host>/<owner>/<repo> で差分全体を読みます。説明する各ハンクの周辺コード、その呼び出し元、リンクされた各イシューを読みます。読んでいないファイルについては主張しません。
  4. 投稿済みのレビュー、投稿済みの判定コメント、ヘッド上の CI 実行結果を読みます。PR に投稿されていない判定は、証拠として扱いません。
  5. すべての主張は、これらの記録に基づいて作成します。セッションの記憶は記録を見つける手がかりにはなりますが、主張の証明にはなりません。

書き始める前にストーリーを見つける

メモの中で、記録に基づいて次の3つの質問に答えます。

  • 理由。 この PR の前に何がうまくいかなかったのか、または何が必要だったのか。経路の消失、誤った判定、監視役がいないままのマージなど、利用者が目にした具体的な症状を挙げます。「X を改善する」は理由になりません。
  • 内容。 PR が変更する仕組みを1つ挙げます。複数ある場合は、理由に直接関係するものを選びます。
  • 方法。 並べ替え、新しい役割、新しいチェック、呼び出しのつなぎ替えなど、問題を解決する変更を挙げます。

根拠のない理由を作りません。差分、PR 本文、リンクされたイシュー、コミットメッセージ、または投稿済みのレビューに理由が示されている場合にのみ、その理由を記載します。それ以外の理由には (推測) と記載します。

コメントを書く

ブロック内のテンプレートをコピーします。最初の画面は、次の3つの要素だけで構成します。

  1. ストーリー。 2文以内、60語以内にします。1文目では、具体的な症状を挙げて理由を説明します。2文目では、レビュー担当者が差分内で見つけられる表現を使い、変更内容と方法を説明します。セミコロン、ファイル一覧、スケッチですでに示されている件数は使いません。
  2. スケッチ。 変更された仕組みを示す画像を1枚載せます。スケッチを参照してください。
  3. 未確認事項。 PR が証明していない内容を1行で挙げます。たとえば、実測していない実行時の動作、テストしていない経路、投稿済みの判定に記載された注意事項などです。

それ以外はすべて、これらの後に1つの折りたたみ可能な <details> ブロックに記載します。リスクの行、SHA、読む順序、変更箇所の短い一覧、根拠へのリンクを含めます。表は使いません。

差分に含まれる秘密情報、トークン、認証情報らしき値は絶対にコピーしません。代わりに <redacted> と記載します。

要約の文には technical-writing スキルを使います。その後、unslop スキルを使います。

スケッチを描く

scene.json、sketch.png、story.txt、recap.md 用に、スキルの外に書き込み可能な作業フォルダーを1つ用意します。レンダー、読み取り、投稿のコマンドは、そのフォルダーから実行します。<skill> は、このスキルのディレクトリーの絶対パスに置き換えてください。

スケッチに従ってください。概要としては、カタログから描画を1つ選び、作業フォルダーに scene.json を書き、bun "<skill>/scripts/sketch/sketch.mjs" scene.json sketch.png でレンダリングします。報告された問題はすべて修正してから、使用前に自分で PNG を確認してください。

実行環境に Bun がない場合、または古いバージョンしかない場合は、スケッチにある npx --allow-scripts=bun [email protected] の方法でレンダリングします。その方法も失敗した場合、または実行環境で画像を表示できない場合は、スケッチを省略してください。ストーリー、「Not covered」の行、詳細ブロックを投稿し、返信ではスケッチを省略したこととその理由を伝えてください。Mermaid 図や表で代用しないでください。

投稿前にすべての主張を確認する

  1. レキャップの事実を述べる各文と、スケッチ内の各ラベルを列挙します。
  2. それぞれを、diff の hunk または SHA を固定した行と照合します。検証済み、修正済み、根拠なし、検証不能のいずれかを記録します。
  3. 修正済みの主張はそれぞれ修正します。根拠のない主張や検証不能な主張は削除するか、推測として書き換えます。ラベルを変更した場合は、スケッチを再レンダリングします。
  4. 各リンクを確認します。ソースへのリンクには記録した head SHA を指定してください。レビューと CI のリンクは PR 上の記録を指し、CI 実行はその head 上のものでなければなりません。ボットレビューの URL は、コードスパン内も含め、コメントのどこにも記載しないでください。レキャップでレビューの指摘をトリアージしてはいけません。また、watch-pr と merge-gate は、レキャップをレビューへの対応として扱いません。
  5. headRefOid を再度読み取ります。値が変わっていた場合は、新しい diff からレキャップを作り直します。

判定結果はコメントではなく、メモに残してください。件数は返信で報告します。

コメントを投稿または更新する

スケッチを省略する場合も含め、同じ作業フォルダーの recap.md にレキャップを書きます。スケッチがある場合、画像行は ![<alt text>](./sketch.png) です。すべてのコマンドはそのフォルダーから実行します。attachment.mjs は <skill>/scripts/attachment.mjs にあります。bun または node で実行してください。--host には PR のホストを渡します。

コメントでは、開始マーカーの次の行にスケッチを記録します。``。次回の更新時にはその記録を読み取り、スケッチに変更がなければアップロードを再利用します。コメント ID は記録しません。コメントに自身の ID を記録できないためです。開始マーカーと投稿者を使って、自分のレキャップコメントを見つけてください。

スケッチがない場合は、手順1を実行し、手順2と3を飛ばして、gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat recap.md)" で recap.md を current に上書きします。該当するコメントがない場合は、gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md を実行します。コメントから <keep> を取得し、手順4に進みます。

  1. 自分のレキャップコメントを古い順に列挙します。最後のものが current です。該当するコメントがなければ、手順3に進みます。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\"))) | .id"
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<current>" --jq .body > old.md
  1. アップロードを再利用します。old.md にこの sketch.png のハッシュが記録されている場合に限り、reuse は記録された URL を出力します。次に stamp がその URL と新しい記録を新しい本文に追加し、API がそれを current に書き込みます。attach は実行しません。
url=$(bun "<skill>/scripts/attachment.mjs" reuse --host <host> sketch.png old.md) &&
bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.md &&
gh api --hostname <host> -X PATCH "repos/<owner>/<repo>/issues/comments/<current>" -f body="$(cat body.md)"

<current> を <keep> として保持し、手順4に進みます。reuse が終了コード1を返した場合は、スケッチが変更されたか、コメントに記録がないため、アップロードしてください。

  1. スケッチをアップロードします。まず CLI を1回だけ試します。
gh pr comment <n> -R <host>/<owner>/<repo> --body-file recap.md --attach sketch.png

新しいコメントの URL が出力されます。その #issuecomment-<id> が <keep> です。gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > new.md でそのコメントの本文を new.md に読み込み、stamp --host <host> sketch.png new.md > body.md を実行し、body.md を使って <keep> を PATCH します。手順4に進みます。

gh がアップロードを拒否する場合、または --attach がない場合、このホストでは CLI からアップロードできません。CLI の制限として一度だけ分類してください。GHES がアップロードを拒否することがあります。これはリポジトリーで添付ファイルが禁止されていることを示すものではありません。この方法を再試行しないでください。

  • ユーザーが手動アップロードを許可しました。 sketch.png の絶対パスをユーザーに伝えてください。Web UI の PR のコメント欄にドラッグして、送信せずに、表示された URL、![...](...)、または <img> のマークアップを返信するよう依頼してください。返信内容を paste.txt に書き込み、このブロックを実行してください。

    url=$(bun "<skill>/scripts/attachment.mjs" url --host <host> paste.txt) &&
    bun "<skill>/scripts/attachment.mjs" stamp --host <host> sketch.png recap.md "$url" > body.md
    

    url はマークアップ形式を受け付け、URL のみを出力します。それ以外のホストまたはパスの場合は終了コード 1 で終了します。ブロックの終了コード 1 はどちらかのコマンドが原因である可能性があるため、エラーを確認してください。no https://<host>/user-attachments/assets/<uuid> URL found は url によるエラーで、返信内容がこのホスト上の添付ファイルではないことを意味します。アップロードできないものとして扱い、URL を推測せず、認証なしの手順に進んでください。no <host> attachment image in the body; pass the attachment URL to replace ./sketch.png または the body must start with は stamp によるエラーで、recap.md に作成上の誤りがあることを意味します。recap.md を修正し、ブロックを再実行してください。ブロックが終了コード 0 で終了したら、body.md を使って current に PATCH してください(<keep> は current です)。current がない場合は、gh api --hostname <host> -X POST "repos/<owner>/<repo>/issues/<n>/comments" -f body="$(cat body.md)" で POST し、返された id を <keep> としてください。

  • 認証なし。 recap.md から画像の行を削除してください。その本文を current に書き込むか、current がなければ投稿し、<keep> を取得してください。upload unavailable: <the gh error> と報告してください。

  1. 自分が投稿した他の recap をすべて削除し、PR に recap が 1 件だけ残るようにしてください。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\")) and .id != <keep>) | .id" |
	while read -r id; do gh api --hostname <host> -X DELETE "repos/<owner>/<repo>/issues/comments/$id"; done
  1. 保存されたコメントを確認し、自分の recap の数を数えてから、画像が表示されることを確認してください。アップロード、保存されたコメント、表示結果を 3 つの別々の結果として報告してください。
me=$(gh api --hostname <host> user --jq .login)
gh api --hostname <host> --paginate "repos/<owner>/<repo>/issues/<n>/comments" \
	--jq ".[] | select(.user.login == \"$me\" and (.body | startswith(\"\"))) | .id" | grep -c .
gh api --hostname <host> "repos/<owner>/<repo>/issues/comments/<keep>" --jq .body > saved.md
bun "<skill>/scripts/attachment.mjs" check --host <host> --head <head SHA, 8 characters> saved.md
curl -s -o /dev/null -w '%{http_code} %{content_type}' -L -H "Authorization: Bearer $(gh auth token --hostname <host>)" "<url that check printed>"

check は開始マーカー、終了マーカー、head SHA、このホスト上のいずれかの形式の画像を確認します。記録がある場合は、記録された URL が本文内の画像 URL であることを確認します。記録の存在は必須ではなく、ハッシュも検証しません。どの確認に失敗したか、エラーを読んで特定してください。件数は 1 と出力されなければなりません。それ以外の数値は手順 4 が失敗したことを意味するため、再実行してください。取得結果は 200 image/png でなければなりません。404 は、このリクエストではアセットを利用できないことを意味します。再利用した URL の取得に失敗した場合は、記録が無効なものとして扱い、手順 3 から再アップロードしてください。サインアウト状態での取得に失敗しても、正常にアップロードされている可能性があるため、何も証明しません。スケッチがない場合は --no-image を付けて check を実行し、マーカーと head SHA だけを確認して、取得を省略してください。

エディターの <img width=... alt=... src="..."> マークアップは url と check で使用できます。Markdown の画像形式と、ブロックにある代替テキストを使って recap を作成してください。stamp は読み込んだ本文内の画像形式を保持します。画像をリポジトリまたはリリースアセットとしてホストすることは、このスキルの対象外です。

PR の本文ではなく、PR のコメントとして投稿してください。no-mistakes によって保護されたリポジトリでは、PR 本文はゲートが管理します。

返信

  • recap が説明するコメント URL と head SHA、またはスキップ行。
  • 使用したカタログの図、またはスケッチを省略した理由。
  • クレーム確認の件数:検証済み、修正済み、推測として削除または書き換えた件数。

CREDITS.md には、このスキルが適用している情報源が記載されています。

コメント