mcpField
P
pr-gardening

pr-gardening

github.com/paperclipaiテスト・品質108.3k78 回インストール今日更新
リポジトリ

pr-gardening について

Paperclip インスタンスが最近作成したプルリクエストを見つけ、最新コミットの準備状況を確認するスキルです。GitHub を読み取り専用で利用し、準備作業の調整やレポート作成を行いますが、マージ、承認、クローズは行いません。

主な機能

  1. 01対象プルリクエストの検出
  2. 02最新コミットの準備状況確認
  3. 03準備タスクの作成と重複排除
  4. 04元の issue へのコメント
  5. 05準備状況レポートの作成と公開
  6. 06条件を満たす受信箱 issue の任意アーカイブ

活用シーン

  1. 01最近作成されたインスタンス由来の PR の確認
  2. 02チェック失敗や更新の止まった PR の特定
  3. 03後続の準備作業の調整
  4. 04マージや承認を行わず準備状況を報告

インストール

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

$npx skills add https://github.com/paperclipai/paperclip --skill pr-gardening

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

同梱ファイル

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

scripts/
check-readiness.mjs
find-candidates.mjs
lib.mjs
pr-gardening.test.mjs
render-report.mjs

詳細

PR のガーデニング

最近の期間(デフォルトは14日間)にアクティブだった Paperclip の課題で参照されている、この Paperclip インスタンスが作成したプルリクエストを積極的にガーデニングします。候補の検出と準備状況の確認はスクリプトで行い、LLM による分析は行いません。このワークフローでは、GitHub へのアクセスは常に読み取り専用です。

対象範囲 — 自分たちの PR のみ

デフォルトでは、このワークフローはこのインスタンスの GitHub アイデンティティ(gh の認証済みログイン名。例:cryppadotta)が作成したプルリクエストのみをガーデニングします。コミュニティからのコントリビューションと dependabot の PR は、Stage A で作成者のログイン名によって機械的に除外され、droppedCommunityPullRequests に記録されます。手動で再追加してはいけません。呼び出し元が --authors または --include-community を明示的に指定した場合に限り、対象範囲を広げます。

厳守すべきガードレール

  • プルリクエストをマージ、承認、またはクローズしてはいけません。
  • 他の人やエージェントに、プルリクエストのマージ、承認、またはクローズを指示してはいけません。
  • コミュニティの PR をガーデニングしたり、コメントしたり、/prepare-paperclip-pr を実行したりしてはいけません。 対応可能なのは Stage A の作成者許可リストに含まれる PR のみです。
  • 変更を伴う gh コマンドや、変更を伴う GitHub API リクエストを使用してはいけません。スクリプトが使用するのは gh pr view と、読み取り専用の gh api GET リクエストのみです。
  • ドラフトのプルリクエストは報告のみを行います。ドラフトにガーデニングコメントを投稿してはいけません。
  • コメントは既存の起点となる課題にのみ投稿します。プルリクエストごとにガーデニング用の課題を作成してはいけません。
  • --dry-run は、ガーデニングコメント、準備タスク、受信トレイのアーカイブを含む、Paperclip に対するすべての変更を抑制します。どのモードでも、候補の検出と GitHub の調査は読み取り専用です。

入力

  • --days <N>:アクティビティの対象期間。デフォルトは 14 です。言及している課題のアクティビティと PR 自体の updatedAt の両方に適用されます。期間内にアクティビティがないオープン PR は、古いものとして除外されます。
  • --authors <logins>:対象とする PR の GitHub ログイン名をカンマ区切りで指定します。デフォルトは gh の認証済みユーザーです。
  • --include-community:作成者による絞り込みを完全に無効にします。呼び出し元が明示的にリクエストした場合に限ります。
  • --repo <owner/repo>:GitHub リポジトリ。デフォルトでは gh repo view で検出されます。
  • --dry-run:コメントを投稿したり、準備タスクを作成したり、受信トレイのエントリをアーカイブしたりせずに、検出、確認、報告を行います。
  • --archive-inbox:候補 PR が現在のヘッドでマージ済みであることを GitHub が確認した後、Stage D で担当ユーザーの受信トレイから起点となる課題をアーカイブします。
  • --cooldown-hours <N>:ガーデニングを繰り返すまでのクールダウン時間。デフォルトは 48 です。
  • --max-rounds <N>:PR ごとのガーデニングラウンドの最大数。デフォルトは 3 です。

生成ファイルには、$PAPERCLIP_RUN_SCRATCH_DIR/pr-gardening など、実行専用のディレクトリを使用します。

Stage A — 候補の検出

抽出検索の処理を実行します。すべての結果ページをスキャンし、PR URL を正規化して PR 番号を重複排除し、言及しているすべての課題を記録し、課題の成果物を確認して起点を特定します。GitHub でマージ済みまたはクローズ済みとされている PR、作成者が許可リストに含まれない PR(コミュニティからのコントリビューション)、および PR 自体の updatedAt が期間より古いオープン PR はそれぞれ除外され、コミュニティからのコントリビューションは droppedCommunityPullRequests に、古い PR は droppedStalePullRequests に記録されます。課題ごとの抽出一致上限を超えた課題(通常、数百件の PR URL を列挙するダイジェストまたは QA の課題)は source.truncatedIssues に記録され、実行を中断する代わりにレポートに記載されます。

node .agents/skills/pr-gardening/scripts/find-candidates.mjs \
  --days 14 \
  --dry-run \
  --output "$RUN_DIR/candidates.json"

このスクリプトは kind=url、scope=all、updatedWithin=<N>d を指定して GET /api/companies/:companyId/search/extract を呼び出し、その後、--authors または --include-community で上書きされていない場合は gh api user から作成者の許可リストを取得します。これを、課題一覧の全件取得や LLM によるスキャンに置き換えてはいけません。

ステージ B — 現在のヘッドの準備状況を確認する

node .agents/skills/pr-gardening/scripts/check-readiness.mjs \
  --input "$RUN_DIR/candidates.json" \
  --output "$RUN_DIR/readiness.json" \
  --dry-run

各候補について、スクリプトは現在のヘッド SHA を再取得し、以下を記録します。

  • オープン/ドラフト状態とマージ可能性/競合;
  • statusCheckRollup のチェック実行と従来のステータス一覧;
  • 正確なヘッド上で完了した Greptile のチェック実行。success または neutral の場合のみクリーンと判定します;
  • reviewDecision;
  • ベースブランチからの遅れたコミット数。

判定結果は ready、needs_gardening、またはドラフトの場合は report_only です。PR を起こした後、または修正済みとの申告があった後は、必ずこのステージを再実行してください。準備完了の証拠として、イシューのコメントを決して信用しないでください。

フォローアップの PR 作成タスクの重複排除

ブランチに対して単一のプルリクエストを作成するフォローアップタスクが必要だとガーデニングで判断した場合は、タスクを作成する前に重複を排除してください。

各ブランチについて、一度に 1 つずつ、以下の手順を順番に実行します。

  1. ステータスが backlog、todo、in_progress、in_review、blocked のオープン状態にある Paperclip イシューを、ブランチ名と完全一致する条件で検索します。
  2. 該当するイシューのタイトル、説明、最近のコメントを調べ、同じブランチから PR を作成するための、内容が同等のオープンタスクがないか確認します。
  3. 内容が同等のオープンタスクがある場合は、それを再利用します。現在の PR/ヘッド/理由に関する簡潔なコメントを追加し、ガーデニングのイシューまたはブロッカー一覧からそのタスクにリンクします。別のタスクは作成しないでください。
  4. 内容が同等のオープンタスクがない場合に限り、そのブランチのフォローアップタスクを 1 つだけ作成します。

フォローアップタスクの作成を並列で行わないでください。PR 作成タスクまたは PR 準備タスクについて、POST /api/companies/:companyId/issues を同時に呼び出さないでください。P1 のイシュー作成の冪等性サポートが利用可能になった後は、PR 作成のフォローアップタスクを作成するたびに idempotencyKey: "pr-gardening:create-pr:{branch}" を指定し、PR 準備タスクを作成するたびに idempotencyKey: "pr-gardening:prepare-pr:{owner/repo}#{number}" を指定してください。

ステージ C — /prepare-paperclip-pr で自分たちの PR を準備完了にする

--dry-run モードの場合、および ready または report_only のエントリについては、このステージをスキップします。

ここにある needs_gardening の PR はすべて、このインスタンスが開いたものです(ステージ A で保証されています)。そのため、報告するだけでなく、対象に /prepare-paperclip-pr スキルを実行して、マージ可能な状態にしてください。PR は 1 つずつ処理します。

  1. クールダウンとラウンド。 candidates.json から originatingIssue を特定します(選択の優先順位:pull_request 作業成果物として PR の URL と完全一致するものを持つイシュー、次にコメントで PR に言及しているイシュー、次に PR に言及している最も最近アクティブなイシュー)。そのコメントを取得し、以下のマーカーを検索します。

    最新の該当マーカーがクールダウン期間内にある場合は、その PR をスキップします。該当マーカーからラウンド数を記録し、3 ラウンドに達したら停止して、収束していません。クローズまたは人による判断を推奨します と報告します。これは人に対応を委ねるための推奨であり、PR をクローズする指示ではありません。

  2. 重複排除。 PR 番号/ブランチを指定して、オープン状態の Paperclip イシューを検索します。内容が同等のオープン中の PR 準備タスクがすでにある場合は、別のタスクを作成する代わりに、簡潔なステータスコメントを付けてそのタスクを再利用します(上記の重複排除のセクションを参照)。

  3. 準備スキルを実行する。 PR ごとに、コーディングエージェント(CodexCoder を優先)に割り当てた、対象を絞った子タスクを 1 つ作成します。その PR に対して /prepare-paperclip-pr を実行するよう指示し、PR URL、ブランチ、現在のヘッド SHA、readiness.json から取得した機械検出の reasons[] を正確に含めてください。ガーデナー自身が対象 PR のブランチをワークツリーでチェックアウト済みの場合は、委任せずに /prepare-paperclip-pr を直接実行してもかまいません。どちらの場合も、準備作業で PR をマージ、承認、またはクローズしてはいけません。

  4. マーカーコメントを残す。 上記のマーカー、現在のヘッド SHA、コピーした reasons[]、ラウンドカウンター、準備タスクへのリンクを添えて、起点イシューにコメントします。X-Paperclip-Run-Id を使用して POST /api/issues/:issueId/comments を呼び出してください。イシューが終了状態の場合は resume: true を含め、コメントによってアクティブな継続が作成されるようにします。

推奨する本文:


Gardening: dispatched `/prepare-paperclip-pr` for https://github.com/paperclipai/paperclip/pull/1234 via PAP-XXXX.

Current-head verification at `abc123` found:
- failing check: test
- Greptile missing at current head

Gardening round 1/3. Re-verification is required after changes; do not merge based on this comment.

ステージ D — 受信トレイの整理(任意)

呼び出し元が明示的に --archive-inbox を指定した場合にのみ、このステージを実行します。--dry-run が指定されている場合は、--archive-inbox も指定されていても、受信トレイへの変更は常に抑止されます。このフラグがない場合は、何もアーカイブしないでください。

ステージ D の対象は、以前に監視していた候補のうち、マージ済みに移行したものです。このステージの直前にステージ B を再実行し、その検証で記録された同じ現在のヘッド SHA について、GitHub が state: merged と報告することを必須とします。ステージ A で新たに検出する際は、すでにマージ済みまたはクローズ済みの PR は意図的に除外されます。

条件を満たす候補ごとに、担当ユーザーの受信トレイから、その originatingIssue を POST /api/issues/:issueId/inbox-archive と空の JSON 本文でアーカイブします。userId は渡さないでください。Paperclip API は、ガーデナーの実行コンテキストから担当ユーザーを解決し、そのユーザーの受信トレイに関するエージェントポリシーを適用します。GitHub へのアクセスは引き続き読み取り専用です。

単に ready の PR、マージせずにクローズされた PR、ドラフト、保留中の PR、または未検証もしくは古いヘッドのままマージされた PR はアーカイブしないでください。ユーザーが引き続きレビュー、判断、承認、またはその他の対応を待っている間は、元の Issue を決してアーカイブしないでください。担当ユーザーが特定できない、受信トレイ管理が無効になっている、ガーデナーが許可リストに登録されていない、または信頼境界が適用されるために Paperclip が変更を拒否した場合は、その拒否を報告し、ポリシーを回避するために再試行せずに続行します。

アーカイブが成功したら、元の Issue に標準のガーデニングマーカーコメントを残し、アーカイブした Issue とマージ済みの PR を明記します:


Inbox tidy-up: archived [PAP-310](/PAP/issues/PAP-310) from the responsible user's inbox after confirming https://github.com/paperclipai/paperclip/pull/1234 merged at current head `abc123`.

This archive is audited and reversible; later issue activity may resurface the item.

POST /api/issues/:issueId/comments を使用し、アーカイブとコメントの両方のリクエストに X-Paperclip-Run-Id を含めてください。--dry-run では、実際に書き込まれるはずだったアーカイブとマーカーコメントを報告しますが、どちらの変更も実行しません。

ステージ E — 終了まで監視

ガーデニング実行 Issue の blockedByIssueIds に、ステージ C で関与した未終了の準備タスクと元の Issue を設定し、ブロッカーが解決したときにガーデナーが再開されるようにします。代替手段として、スケジュール実行または手動での再実行を使用します。

再開するたびに、まずステージ B を再実行します。次のいずれかが機械的に確認された場合にのみ、PR はアクティブなガーデニングの対象から外れます:

  • 現在のヘッドで検証済みの ready。
  • 外部でマージまたはクローズされた。
  • 最大ラウンド数に達し、収束していないと報告された。

終了済みの Issue をガーデニング Issue のブロッカーとして残さないでください。エージェントや長時間実行セッションをポーリングしないでください。

ステージ F — レポートの作成と公開

node .agents/skills/pr-gardening/scripts/render-report.mjs \
  --input "$RUN_DIR/readiness.json" \
  --output "$RUN_DIR/gardening-report.md"

レポートには対象範囲(作成者と期間)を記載し、オープン中の各 PR について、作成者、PR の説明から取得した目的の要約(1 行)、および準備状況の信頼度区分を記載します:

  • 高: 現在のヘッドのチェックがすべて成功し、競合がなく、Greptile の問題がなく、ベースが最新で、元の Issue が終了済み。
  • 中: それ以外は問題ないが、ベースが古い、レビューが完了していない、または元の Issue が対応中。
  • 低: チェックの失敗または保留中、Greptile がない、ドラフト/修正済みだが未検証の状態、または特定可能な元の Issue がない。

PR の目的を示す生成文が空、または役に立たない場合は、レポートの公開時に PR タイトルと差分の要約から 1 文の説明を作成してください。

candidates.json、readiness.json、gardening-report.md をガーデニング Issue にアップロードし、Markdown の本文で gardening-report Issue ドキュメントを作成または更新して、成果物へのリンクを含む要約コメントを残します。レポートが成果物です。マージを許可するものでは決してありません。

検証

対象を絞ったスクリプトテストを実行します:

node --test .agents/skills/pr-gardening/scripts/pr-gardening.test.mjs

ライブのドライランでは、--dry-run を指定してステージ A、B、F を実行し、名前が指定された PR がまだオープン中の場合に限り、妥当性を確認します。マージ済みまたはクローズ済みの例は、準備状況の結果ではなく droppedClosedPullRequests に表示される必要があります。また、コミュニティ作成の PR は droppedCommunityPullRequests のみに表示される必要があります。許可リストにない作成者の候補やレポート項目は、対象範囲の違反です。--archive-inbox も検証する場合は、抑止されたステージ D のアクションがレポートに記載され、Paperclip のアーカイブやマーカーコメントの変更が一切行われていないことを確認してください。

コメント