Communityコーディング&開発github.com

chrislacey89/pre-merge

パイプラインの主要なレビューステップです。実装検証後、PRを作成し、アーキテクチャレビューを実施してマージ前に使用します。QA受付、計画立案、実装作業には使用しません。

pre-merge とは?

このスキルは、GitHub PRを作成し、PRDとスライスイシューにリンクを張り、プロジェクトのアーキテクチャ原則に対して全差分をレビューするためのものです。アドバイザリ型の所見を生成し、マージをブロックしたり、コードを自動修正したり、イシューを作成したりすることはありません。これは、実装が検証された後、メインブランチにマージする前、または他の誰かのPRをレビューするときに使用する主要なパイプラインスキルです。`/pre-merge` は3つのモード(Authorモード、Reviewerモード、Loopモード)で動作し、それぞれが `review-checklist.md` で定義されたアーキテクチャレビューの次元を再利用します。Authorモードでは、ブランチからPRを作成し、ターミナルに所見を出力します。Reviewerモードでは、既存のPRに対してレビューコメントの下書きテキストを生成します。Loopモードでは、所見を永続的な台帳に記録し、運用者が各所見にオーナーを割り当てるまで終了しません。このスキルは、Claude Code、Cursor、GitHub CLIなどの開発者ツール上で動作し、GitHub Issues / PRsとSidecarバックエンドの両方をサポートします。

対応✓Claude Code✓Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/chrislacey89/skills/tree/HEAD/pre-merge

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Pre-Merge (マージ前レビュー)

GitHub PRを作成し、PRDとスライスイシューにリンクを張り、プロジェクトのアーキテクチャ原則に対して全差分をレビューします。アドバイザリ型の所見を生成します。マージをブロックしたり、コードを自動修正したり、イシューを作成したりすることはありません。

呼び出し位置

これは、実装が検証された後、メインブランチにマージする前、または他の誰かのPRをレビューするときに使用する主要なパイプラインスキルです。

ブランチがPR作成、アーキテクチャレビュー、および計画とコードの最終的な整合性確認の準備ができたときに /pre-merge を使用します。自分が作成していないPRをレビューするときは /pre-merge --pr <番号> を使用します。

実装検証、QA受付、またはリファクタリング計画の代わりとして使用しないでください。このスキルは、作業がすでに構築され、レビューの準備ができていることを前提としています。

モード

/pre-merge は3つのモードのいずれかで実行されます。3つのモードすべてが review-checklist.md で定義されたアーキテクチャレビューの次元を再利用します。消費するものと生成するものだけが異なります。

  • Authorモード(デフォルト) — --pr 引数なしで自分のブランチで呼び出されます。このスキルはPRを作成し(フェーズ2)、ターミナルに所見をアドバイザリとして出力し(フェーズ4)、その後制御を戻します。自身で修正コミットを作成したり、2回目のパスを開始したりすることはありません。 これは /execute のステップ6でHITLパス上で自動的に呼び出されるモードです。何を読むかはブランチの状態によって決まり、フラグによって決まるわけではありません。 初回レビューはスライス全体を読みます。スライス全体は、スライスの作業項目が開始位置を記録していなければブランチ全体であり、記録されていればその開始位置からです。すでにレビュー通貨スタンプが付与され、その後HEADが移動したPRに対して再実行する場合、スタンプ後のデルタ(スタンプされたSHA以降のコミット)をレビューの対象とし、以前のレビューでカバーされた部分は再読み込みしません。フェーズ1のステップ4でこの判断を行い、出力します。デルタは対象であり、レビュアーが読む範囲を制限するものではありません。review-checklist.md がレビュアーが読む範囲を決定し、それにはデルタ周辺のツリーも含まれます。
  • Reviewerモード — --pr <番号> を指定して、自分が作成していないPRに対して呼び出されます。このスキルはPR作成(PRはすでに存在する)をスキップし、レビューして投稿するためのドラフトコメントテキスト(フェーズ4)を生成します。構造は references/comment-craft.md(5Pゲート、トリプルR、コメントシグナル、MMG交換)に従います。
  • Loopモード — /pre-merge --loop として呼び出されるか、AFK実行で /execute がハンドオフするときに自動的に開始されます。Authorモードと同様にフェーズ1〜4を実行します。ただし、フェーズ1のステップ4のスコープ決定は異なります。Loopモードは常にブランチ全体を読み取り、スタンプ後のデルタを対象とすることはありません。その後、フェーズ5に進みます。すべての所見をPR本文または作業項目の耐久性のある台帳に記録し([references/state-backend.md](references/state-backend.md) § レビューの記録が保存される場所 を参照)、各所見を支持または反証する証拠を添付し、制御を運用者に戻します。このモードでは、所見はターミナル出力ではなくなり、オーナーを持つ耐久性のある行になります。Loopモードは何も修正せず、コミットも作成しません。 各所見の処理方法は運用者が決定します(フェーズ5 § ループが修正しない理由 を参照)。

Loopモードの終了条件は、すべての所見にオーナーがいることです。レビューがクリーンに戻ったことではありません。 「所見ゼロ」は禁止された終了シグナルです。これは、フェーズ4の既存の最低所見数ガードと一致しています。このガードは、重要な差分に対してほぼ空のレビューが返ってきた場合、コードに欠陥がないのではなく、レビューが早期に停止したことを意味するために追加されました。クリーンなレビューで終了するループは、確実にクリーンなレビューとそれ以外は何も生成しません(Meadows, Seeking the Wrong Goal; Leveson: 低いインシデント件数に報いるのではなく、報告自体に報いること)。

ユーザーの作業ブランチ以外のブランチで実行しており、--pr が指定されていない場合は、推測するのではなく、特定のPR番号に対するReviewerモードを意味するのかどうかを1回だけ尋ねてください。自動検出することでキーストロークを節約できますが、モードを誤って分類すると、ローカルアドバイザリであるべきものがドラフトコメントになったり、その逆になったりします。

使用時

  • Authorモード: QA合格後、フィーチャーブランチをmainにマージする前。RalphがAFK実行を完了し、動作を確認した後。または、完全なパイプライン実行がなくても、マージ前にレビューしたいブランチがある場合。
  • Reviewerモード: チームメイトまたは外部コントリビューターがPRを開き、その差分に review-checklist.md の完全なアーキテクチャレビューを適用し、建設的なコメントテキストを生成したい場合。
  • Loopモード: 所見が、それらを生成したセッションを超えて存続する必要がある場合。つまり、/execute からのAFKハンドオフ、または複数回にわたってレビューし、毎回再導出したくないブランチがある場合。支払っているコストが所見を見失うことであり、修正を行うことではない場合に使用します。

実行フロー

フェーズ1: コンテキスト収集

Authorモード:

  1. PRDイシュー番号を尋ねます。 この変更が完全なパイプラインを経由していない場合は「なし」を受け入れます。AFK /execute ハンドオフから開始されたLoopモードでは、尋ねないでください。 ハンドオフからイシュー番号を取得し(/execute ステップ6が渡します)、存在しない場合は「なし」として扱います。誰も答える人がいないため、無条件の質問は最初のステップで実行を停止させてしまいます。サイドカーバックエンドでは、答えは W-<n> ワークアイテムIDです(ステップ2)。そこで「なし」とすると、フェーズ2でPRを記録する場所がなくなり、レビューノートとLoopモードの台帳の保存場所もなくなります。[references/state-backend.md](references/state-backend.md) § レビューの記録が保存される場所 を参照してください。

  2. PRDが指定された場合:

    gh issue view <番号>
    gh issue list --search "in:body #<prd-number>" --state all --json number,title,state,body --limit 100
    

    各スライスイシューの本文からバウンダリマップ(Produces/Consumesセクション)を解析します。

    サイドカーバックエンド(bash "$SC" backend slices が sidecar を返す場合、[references/state-backend.md](references/state-backend.md) を参照。以下のブロックがそれを確認し、拒否された場合は gh issue にフォールバックせずに停止します)では、PRDとそのスライスはワークアイテムであり、ステップ1で尋ねられた番号は W-<n> IDです。これは、このブランチが実装するスライス(/execute が渡すもの)、またはそのPRDです。gh issue コマンドは実行されません。系統とバウンダリマップはワークアイテムから取得します。

    SC="<このスキルのディレクトリ>/references/sidecar.sh"
    W="W-<n>"
    case "$(bash "$SC" backend slices)" in
      sidecar) ;;
      github) echo "backend is github: read the lineage with the issue block above"; exit 0 ;;
      *) echo "lineage aborted: sidecar.sh backend slices failed; not guessing the github path" >&2; exit 1 ;;
    esac
    J="$(bash "$SC" work view "$W" --json)" || { echo "lineage aborted: cannot read $W" >&2; exit 1; }
    case "$(jq -r '.kind // empty' <<<"$J")" in
      slice) PRD="$(jq -r '.parent // empty' <<<"$J")" ;;
      prd)   PRD="$W" ;;
      *) echo "lineage aborted: $W has no kind" >&2; exit 1 ;;
    esac
    SLICES="$W"
    if [ -n "$PRD" ]; then
      bash "$SC" work view "$PRD" --json | jq -r '"# \(.id) (prd, \(.state))\n\(.body)"'
      SLICES="$(bash "$SC" work list --kind slice --parent "$PRD" --state all)" \
        || { echo "lineage aborted: cannot list the slices of $PRD" >&2; exit 1; }
    fi
    while IFS= read -r S; do
      [ -n "$S" ] || continue
      bash "$SC" work view "$S" --json | jq -r '"# \(.id) (slice, \(.state))\n\(.body)"'
    done <<<"$SLICES"
    

    イシュー本文とまったく同じように、これらの本文からバウンダリマップを解析します。$W を保持します。フェーズ2でPRを記録する際に使用します。

  3. ベースブランチを検出し、差分を評価します:

    SC="<このスキルのディレクトリ>/references/sidecar.sh"
    # $BASE_REF は範囲の終点です。$BASE_BRANCH は `--base` が受け取る名前です。
    BASE_REF="$(bash "$SC" base-ref)" || { echo "base-ref failed: not guessing a base" >&2; exit 1; }
    BASE_BRANCH="$(bash "$SC" base-ref --name)" || { echo "base-ref --name failed: not guessing a base" >&2; exit 1; }
    git diff "$BASE_REF...HEAD" --stat
    git log --oneline "$BASE_REF..HEAD"
    

    base-ref は、サイドカーが宣言した base_ref がある場合はそれを出力し、それ以外の場合は origin/HEAD のデフォルトを出力します。ゼロ以外の終了コードの場合は参照を出力しません。ベースを推測せずに、そのstderrを中継して停止します。スタックされたPRスライスの場合、ここで設定された変数は後のブロックには到達しません。各ブロック(バックエンドのフェーズ2ブロックとフェーズ4のスタンプブロック)の BASE_BRANCH= プレースホルダーに、兄弟スライスのブランチ名(PRがターゲットとするアップストリーム)を入れます。ベースからの差分がない場合は、レビューするものがないことをユーザーに伝えて停止します。

    残差: $BASE_REF は最後の git fetch 以降の鮮度しかありません。origin/<base> が解決できない場合、base-ref はローカルブランチに対して測定し、その旨をstderrに出力します。カウントがおかしいと思われる場合は、git fetch して再実行してください。

  4. スコープを決定します — スライス全体、またはスタンプ後のデルタ。 この決定はAuthorモードのみです。Loopモードはこれをスキップし、SCOPE_FROM="$BASE_REF" を無条件に設定し、毎回ブランチ全体を読み取ります(フェーズ3のLoopモードの箇条書きに従います)。初回レビューはスライス全体を読み取ります。sidecar.sh range はその左端を与えます。左端は、ステップ2で指定された作業項目にこのブランチ上にまだ記録された開始点がある場合はその開始点であり、それ以外の場合は $BASE_REF です。したがって、github バックエンドでは、スライスはブランチ全体です。このスキルがすでにスタンプし、その後HEADが移動したPRに対する再実行(/fix-findings ラウンド、または意図的なロック削除後の手動修正)は、スタンプ後のデルタを対象とします。スタンプは backend stamp が示す場所にあります([references/state-backend.md](references/state-backend.md) 参照)。PR本文またはサイドカーです。/closeout ステップ2と同じ式でPR本文を読み取ります。scripts/test-review-currency-marker.sh は2つがバイト単位で同一であることを確認し、scripts/test-delta-review-scope.sh は、両方のバックエンドで、名前が挙げられているすべてのブランチ状態に対してフィクスチャを使用してこのブロックを実行します。

    SC="<このスキルのディレクトリ>/references/sidecar.sh"
    case "$(bash "$SC" backend stamp)" in
      sidecar)
        REVIEWED_SHA=$(bash "$SC" stamp read "$(git branch --show-current)") ;;
      github)
        REVIEWED_SHA=$(gh pr list --head "$(git branch --show-current)" --json body -q '.[0].body // ""' \
          | sed -n 's/.*<!-- reviewed-at: \([0-9a-f]\{40\}\) -->/\1/p' | tail -1) ;;
      *) echo "scope aborted: sidecar.sh backend stamp failed; not guessing the github path" >&2; exit 1 ;;
    esac
    W="<ステップ2で指定されたW-<n>。githubバックエンドでは空>"
    BASE_REF="$(bash "$SC" base-ref)" || { echo "scope aborted: sidecar.sh base-ref failed" >&2; exit 1; }
    RANGE="$(bash "$SC" range ${W:+"$W"})" || { echo "scope aborted: sidecar.sh range failed" >&2; exit 1; }
    SLICE_FROM="${RANGE%%..*}"
    SCOPE_FROM="$SLICE_FROM"
    if [ -n "$REVIEWED_SHA" ] \
      && git merge-base --is-ancestor "$REVIEWED_SHA" HEAD 2>/dev/null \
      && [ "$REVIEWED_SHA" != "$(git rev-parse HEAD)" ] \
      && [ -z "$(git log --merges --format=%H "$REVIEWED_SHA..HEAD")" ]; then
      SCOPE_FROM="$REVIEWED_SHA"
    elif [ -n "$REVIEWED_SHA" ] \
      && ! git merge-base --is-ancestor "$REVIEWED_SHA" HEAD 2>/dev/null \
      && [ "$(git rev-parse -q --verify "$REVIEWED_SHA^{tree}")" = "$(git rev-parse 'HEAD^{tree}')" ]; then
      SCOPE_FROM="HEAD"
    fi
    if [ "$SCOPE_FROM" = HEAD ]; then
      echo "review scope: none, history-only rewrite — HEAD carries the tree reviewed at $REVIEWED_SHA"
    elif [ "$SCOPE_FROM" = "$BASE_REF" ]; then
      echo "review scope: whole branch, from $BASE_REF"
    elif [ "$SCOPE_FROM" = "$SLICE_FROM" ]; then
      echo "review scope: whole slice, from $SLICE_FROM ($W's recorded start)"
    else
      echo "review scope: post-stamp delta, from $SCOPE_FROM"
    fi
    git diff "$SCOPE_FROM...HEAD" --stat
    git log --oneline "$SCOPE_FROM..HEAD"
    

    4つの状態は、それぞれ意図的にスライス全体にフォールバックします。スタンプがない(初回レビュー、または手動で作成されたPR)。HEAD の祖先ではなく、HEAD がツリーを保持していないスタンプ(ブランチが書き換えられ、コンテンツもそれに伴って変更されたか、レビューされたコミットが消失した — /closeout はこれをより強い分岐シグナルと呼び、より小さなレビューではありません)。HEAD と等しいスタンプ(スコープする新しいものはない)。スタンプ後のマージコミット(スタンプ後の差分には、このブランチで誰も書いていないベースブランチ自身の変更が含まれる)。スライス全体は、range が記録された開始点を見つけられない限りブランチ全体であり、foldやrebaseによって書き換えられた場合は、その旨をstderrに出力して $BASE_REF を返し、開始点を再設定することはありません。この決定は出力されるため、ターミナルの読み取りとPRは、読み取られた内容について同じことを言います。

    レビューされたツリーを保持した書き換えは分岐ではありません。 スタンプされたコミットが HEAD の祖先ではないが、ローカルにまだ存在し、HEAD と同じツリーを持っている場合、履歴は変更されましたが、コンテンツは変更されていません。フェーズ4のハンドオフが提供するfold(git rebase -i --autosquash)はまさにこれを生成します。ブロックは review scope: none を出力し、SCOPE_FROM="HEAD" を設定します。フェーズ3とフェーズ4のスタンプ以外のすべて(HEAD で再スタンプする)とハンドオフメニューをスキップします。スタンプはレビューされたコンテンツを証明し、ツリーハッシュはそのコンテンツを正確に示します。スタンプされたコミットがローカルで利用できない場合、ツリーを比較できず、書き換えは上記のブランチ全体フォールバックを取ります。

    デルタ再実行では、デルタが対象であり、ツリーはまだ読み取り可能です。 各フェーズ3のレビュアーに、スタンプ後のコミットがクローズすると主張する所見(このセッションでの以前の読み取り、Loopモードが台帳に書き込んだ場合はその台帳([references/state-backend.md](references/state-backend.md) § レビューの記録が保存される場所 を参照)、またはコミットメッセージ自体)、/fix-findings ブレーカー判定(ある場合)、および bash "$SC" profile の出力(そのまま)を、フェーズ3の契約がすべてのレビュアーに提供するものとして、簡単に説明します。コミットごとの最初の質問は、修正がその所見のすべてのサイトで所見をクローズするかどうかです。これは修正完全性の次元です。2つ目の質問は、...

[truncated for translation]

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

chrislacey89/closeout

Primary pipeline tail step after /pre-merge, when a reviewed PR is ready to land and you want the workspace back to a clean base. Use to merge, switch off the worktree before removing it, prune the merged branch, pull base, and verify a clean end state. Triggers on 'close out', 'merge and clean up', 'get back to a clean main/base', 'tear down the worktree'. Not for capturing lessons (that's /compound), or closing the PRD and any other open slices and research-artifact hygiene (that's the cleanup prose in SYSTEM-OVERVIEW Step 9).

chrislacey89/compound

Primary pipeline knowledge-capture step that closes the compounding loop. Capture a durable lesson in docs/solutions/ onto the open PR before /closeout merges (the default), or post-merge when the lesson only surfaces during/after merge. Use so future /research and /write-a-prd runs improve. Not for trivial edits with no reusable project-level learning, and not for the merge/teardown itself (that's /closeout).

chrislacey89/excavate

User-invoked side-route for onboarding to a legacy repo with no docs/solutions/, research archive, or written decisions. Mines the last 12 months of git history and, when gh is available, PR bodies and review threads, into ranked hotspots, cited recovered decisions, and a who-to-ask map, then offers a PR of docs/solutions/ entries. Not for repos that already compound, not for judging people, not model-invoked.

chrislacey89/execute

Primary pipeline execution step after /prd-to-issues or for clearly scoped implementation work. Use to build, verify, and commit a concrete slice, delegating to /tdd for backend work and behavior-heavy frontend logic when red-green-refactor will reduce risk. Not for shaping or pre-merge review.

関連スキル