work-with-pr について
コーディングエージェント向けのスキルで、独立した worktree の準備から実装、レビュー、マージまでの PR ライフサイクルを扱います。小さく独立してレビューできる PR と、証拠を残す手動 QA を重視します。
主な機能
- 01PR を小さな単位に分割
- 02分離したブランチ worktree の作成
- 03証拠を伴う手動 QA
- 04CI と Cubic の反復確認
- 05PR の作成とマージ
活用シーン
- 01大きなタスクを独立した変更として納品
- 02並行する PR 作業の分離
- 03CI やレビュー指摘に応じた修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ code-yeongyu/ oh-my-openagent --skill work-with-prインストール後、Claude Code で/work-with-prを入力して読み込まれたか確認します。
詳細
PR 作業 — PR の完全なライフサイクル
新しいタスク専用ワークツリーのセットアップから、ulw-loop による実装とエビデンスに基づく手動 QA、PR の作成、そして PR がマージされるまで終わりのない検証ループまで、PR のライフサイクル全体を実行します。このループには CI と Cubic という 2 つのゲートがあり、いずれかのゲートが失敗した場合は、その PR のワークツリーに戻って修正し、再度 QA を行います。有効なすべてのゲートが同時に通過するまで、これを繰り返します。
成果物の単位は、コンパイルでき、テストに合格し、それ単体で成立する最小の PR です。「1 タスクにつき 1 PR」ではありません。 1 つのタスクから複数のアトミックな PR に分割するのはよくあることです。以下のライフサイクルはそのうちの 1 つを説明しているため、それぞれに適用し、独立した PR は並行して作成してください(Phase 0)。
Phase 0: Setup → Split into atomic PRs, then branch + worktree per PR (parallel when independent)
Phase 1: Implement → Drive the work through the ulw-loop skill:
evidence-bound manual QA per success criterion, atomic commits
Phase 2: PR Creation → Push, create a reviewer-readable English PR targeting dev
Phase 3: Verify Loop → Unbounded iteration; a failing gate routes back to Phase 1:
├─ Gate A: CI → gh pr checks (bun test, typecheck, build)
└─ Gate B: Cubic → cubic-dev-ai[bot] "No issues found"
(SKIPPED, not failed, when Cubic's quota is exhausted)
Phase 4: Merge → Auto-merge by default; wait until actually merged, then worktree cleanup
Phase 0:セットアップ
実装を始める前に、PR ごとに新しく隔離されたワークツリーを作成します。ユーザーのメイン作業ディレクトリは読み取り専用のコンテキストとして扱います。未コミットの作業が含まれている可能性があり、ブランチをチェックアウトすると失われるためです。隔離することで並行作業も容易になります。PR ごとにワークツリーを 1 つ用意すれば、互いに競合することなく複数の PR を同時に進められます。
1. PR の分割を決める
何かを作成する前に、タスクを、それぞれがコンパイルでき、テストに合格し、レビュー可能な 1 つのまとまりを提供する、最小限のアトミックな PR に分解します。大きな PR 1 つより、小さな PR を複数作成することを優先してください。200 行の PR なら実質的なレビューが行われますが、2000 行の PR は形式的に承認されるだけです。依存関係に沿って順序を決めます。独立したまとまりはベースブランチから分岐して並行して進め、依存するまとまりは前のまとまりから分岐して積み重ねます。
複数の独立した PR を同時に作成することは、特殊な選択肢ではなく、推奨されるデフォルトです。
- サブエージェント — PR ごとにバックグラウンドのサブエージェントを 1 つ割り当て、それぞれが専用のワークツリーとブランチを使い、Phase 0→4 の全工程を担当します。
- チーム — 並行作業が多い場合は、チーム(
team_mode)を編成し、メンバー 1 人につき PR を 1 つ割り当てます。
作業量が多く、計画(ulw-plan)が必要な場合、この分解は任意の仕上げではありません。計画には、アトミックな PR、それらの依存順序、並行して実行する項目を、第一級の構造として必ず記述してください。
2. リポジトリのコンテキストを確認する
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
REPO_NAME=$(basename "$PWD")
BASE_BRANCH="dev" # CI blocks PRs to master
3. ブランチを作成する
ユーザーがブランチ名を指定した場合は、それを使用します。指定がない場合は、タスクに基づいて決めます。
# Auto-generate: feature/short-description or fix/short-description
BRANCH_NAME="feature/$(echo "$TASK_SUMMARY" | tr '[:upper:] ' '[:lower:]-' | head -c 50)"
git fetch origin "$BASE_BRANCH"
git branch "$BRANCH_NAME" "origin/$BASE_BRANCH"
4. ワークツリーを作成する
ワークツリーはリポジトリの内側ではなく、リポジトリと同じ階層に配置します。これにより、Git の入れ子になったリポジトリに関する問題を避け、作業ツリーをクリーンに保てます。
WORKTREE_PATH="../${REPO_NAME}-wt/${BRANCH_NAME}"
mkdir -p "$(dirname "$WORKTREE_PATH")"
git worktree add "$WORKTREE_PATH" "$BRANCH_NAME"
5. 作業コンテキストを設定する
以降の作業はすべてワークツリー内で行います。必要に応じて依存関係をインストールします。
cd "$WORKTREE_PATH"
# If bun project:
[ -f "bun.lock" ] && bun install
Phase 1:実装
ワークツリー内から ulw-loop スキル(ハーネス標準の ultrawork ループ)を使って、実装をすべて進めます。場当たり的に作業してはいけません。ulw-loop は、概要を二値で判定できる成功基準を持つ目標に分解し、コード編集と QA を適切な規模のサブエージェントに委任します。そして、ここで必須とする理由でもありますが、すべての成功基準について、テストスイートが成功するだけでなく、実際の環境でエビデンスに基づく手動 QAを行って証明するよう徹底します。
ゲートとなるのはテストではなく、手動 QA です。 このリポジトリのルールは絶対です。OpenCode または Codex に反映される変更は、実際のハーネス(tmux/HTTP/ブラウザー/GUI — ulw-loop スキルの手動 QA チャネル表を使用)を操作し、エビデンスをディスクに記録するまで完了ではありません。エビデンスファイルがなければ QA は行われておらず、コミットもプッシュもしてはいけません。「型チェックが通る」ことや「bun test が成功する」ことは QA ではありません。
スコープを守る
各 PR の内容は最小限にとどめます。担当する 1 つのまとまりを実装し、テストを追加して検証したら、そこで止めてください。周辺コードのリファクタリング、設定オプションの追加、壊れていない箇所の「改善」はしないでください。それらの作業は独立した PR で行うべきであり、スコープが広がると失敗の切り分けが難しくなります。
コミット戦略
ulw-loop は git-master を通じてコミットします。コミットはアトミックに保ち、1 つの変更で CI が失敗したときに、すべてを巻き戻さずに原因を切り分けて修正できるようにします。
3+ files changed → 2+ commits minimum
5+ files changed → 3+ commits minimum
10+ files changed → 5+ commits minimum
各コミットには実装とそのテストを含めます。また、基準に対応する QA エビデンスがディスクに保存された後にのみ、その基準の変更をコミットします。
### プッシュ前のローカル検証プッシュする前に、CI で実行されるものと同じチェックを実行してください。これは約 3~5 分かかる CI の往復を省くための簡易な事前チェックであり、上記の手動 QA の代わりにはなりません。
bun run typecheck
bun test
bun run build
プッシュする前に、失敗をすべて修正してください。修正はそれぞれ独立したアトミックコミットにします。
フェーズ 2:PR の作成
<pr_creation>
プッシュして PR を作成する
git push -u origin "$BRANCH_NAME"
PR の本文は、実装の経緯を追っていない人間のレビュアー向けに英語で記述してください。作業内容を平易な言葉で説明し、ファイルを羅列するのではなく、レビュアーに関係する領域ごとに変更をまとめ、各ログが何を証明するのかをレビュアーが推測しなくても QA の証拠を監査できるようにしてください。サニタイズ済みの成果物を示してください。シークレットを含む生ログ、環境変数のダンプ、トークン、認証ヘッダー、非公開の認証情報を PR に貼り付けないでください。
PR の本文にスクリーンショットやターミナルの PNG が必要な場合は、docs/reference/github-attachment-upload.md に従ってください。認証済みのウェブセッションから GitHub ユーザー添付ファイルとしてアップロードし、最終的な https://github.com/user-attachments/assets/<uuid> URL のみを含めてください。一時画像をコミットしたり、リリースアセットや外部ホストを使用したり、Cookie やトークンを記録したりしないでください。
gh pr create \
--base "$BASE_BRANCH" \
--head "$BRANCH_NAME" \
--title "$PR_TITLE" \
--body "$(cat <<'EOF'
## Summary
[2-4 sentences in plain language: what changed, why it changed, and how observable behavior is different after this PR.]
## Changes
[Group bullets by reviewer-relevant area, not by file. Each bullet should say what changed and how a reviewer can map it to the diff.]
## QA & Evidence
For each automated command or manual QA action:
- **What was tested:** [command or surface driven, with the behavior it was meant to prove]
- **Observed result:** [actual result, including before/after when relevant]
- **Artifact:** [`path/to/sanitized-log-or-report`]
- **Why sufficient:** [which risk or success criterion this evidence covers]
## Risks & Residuals
[Map each meaningful risk to the evidence above and state the conclusion: mitigated, accepted, or blocked. Include unavailable gates here with the concrete reason.]
## Related Issues
[Link to issue if applicable]
EOF
)"
PR 番号を取得します。
PR_NUMBER=$(gh pr view --json number -q .number)
</pr_creation>
フェーズ 3:検証ループ
これがこのスキルの中核です。PR の準備が整うには、有効なゲートがすべて合格している必要があります。反復回数に上限はありません。完了するまで続けてください。ゲートの順序には意図があります。CI が最も安価で高速であり、Cubic は外部かつ非同期です。Gate B(Cubic)は、満たすのではなくスキップできる唯一のゲートです。ただし、スキップできるのはクォータを使い切った場合に限られ、問題が見つかったという理由では決してスキップできません。ゲートの失敗は、その場でパッチしてプッシュするという意味ではありません。フェーズ 1 に戻り、修正にも同じスコープ規律を適用してください。また、動作が変わった場合は、新たな手動 QA の証拠を用意してからループに戻ってください。
<verify_loop>
while true:
1. Wait for CI → Gate A
2. If CI fails → back to Phase 1: read logs, fix + re-QA, commit, push, continue
3. Check Cubic → Gate B
4. If Cubic has issues → back to Phase 1: fix + re-QA, commit, push, continue
5. If Cubic quota out → record Gate B SKIPPED, stop waiting on it
6. All active gates pass → break
Gate A:CI チェック
CI は最も速いフィードバックループです。monitor を使って完了を待ち受けてください。gh pr checks --watch でモデルの往復をブロックしてはいけません。
# Subscribe to CI completion — the monitor event wakes the session when checks finish.
# Do NOT use `gh pr checks --watch` as a blocking tool call; it burns a full model
# round-trip (~29s) on every poll. Instead, register a monitor and end the turn:
monitor({
description: "CI completion for PR $PR_NUMBER",
command: "gh pr checks $PR_NUMBER --watch --fail-fast",
filter: "completed|fail|cancel"
})
# → end turn; the monitor's matching line arrives as an injected event.
# For a single midpoint status peek (at most once), use:
# gh pr checks "$PR_NUMBER" # one-shot, no --watch
失敗した場合:何が壊れたのかを把握するため、失敗した実行のログを取得します。
# Find the failed run
RUN_ID=$(gh run list --branch "$BRANCH_NAME" --status failure --json databaseId --jq '.[0].databaseId')
# Get failed job logs
gh run view "$RUN_ID" --log-failed
ログを読み、以下の反復規律に従って修正してください。
Gate B:Cubic の承認
Cubic(cubic-dev-ai[bot])は PR にコメントする自動レビュー用ボットです。GitHub の APPROVED レビュー状態は使用しません。その代わりに、問題の件数と確信度を含むコメントを投稿します。
承認のシグナル:最新の Cubic のコメントに **No issues found** と確信度 **5/5** が含まれていること。
問題のシグナル:コメントにファイル単位の詳細を含む問題が列挙されていること。
クォータ枯渇のシグナル:Cubic がレビューの代わりに使用量、クォータ、または上限に関するメッセージを投稿する、あるいは以下で定める待機時間内に Cubic のレビューが表示されないこと。Gate B をスキップして先に進めるのは、この場合に限られます。最終レポートには SKIPPED として記録し、決して黙ってスキップしないでください。問題があることは、スキップする理由にはなりません。
# Get the latest Cubic review
CUBIC_REVIEW=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
--jq '[.[] | select(.user.login == "cubic-dev-ai[bot]")] | last | .body')
if echo "$CUBIC_REVIEW" | grep -q "No issues found"; then
echo "Cubic: APPROVED"
elif echo "$CUBIC_REVIEW" | grep -qiE "quota|usage limit|rate limit|out of (credits|reviews)|upgrade your plan"; then
echo "Cubic: SKIPPED (quota exhausted)" # Gate B satisfied-by-skip; do not loop on it
else
echo "Cubic: ISSUES FOUND"
echo "$CUBIC_REVIEW"
fi
問題がある場合:Cubic のレビュー本文には、構造化された問題の説明が含まれています。それらを解析して有効かどうかを判断し(誤検知の可能性もあります)、有効なものを以下の反復規律に従って修正してください。
Cubic のレビューは PR の更新時に自動的に開始されます。修正をプッシュした後は、新しいレビューが届くのを待ち受けてください。モデルの往復を消費する for _ in $(seq 1 30) のポーリングループを回し続けてはいけません。
# Subscribe to a NEW Cubic review after push. The monitor exits when a review
# newer than PUSH_TIME appears, or times out (quota exhausted → Gate B SKIPPED).
PUSH_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
monitor({
description: "Cubic review for PR $PR_NUMBER",
command: "LATEST=$(gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews --jq '[.[] | select(.user.login == "cubic-dev-ai[bot]")] | last | .submitted_at // empty'); [ -n \"$LATEST\" ] && [ \"$LATEST\" > \"$PUSH_TIME\" ] && echo NEW_REVIEW || echo WAITING",
filter: "NEW_REVIEW",
timeout_ms: 600000 # 10 min bound — if no review arrives, Gate B is SKIPPED (quota exhausted)
})
# → end turn; if the monitor times out without NEW_REVIEW, treat Gate B as SKIPPED.
# For a single midpoint peek (at most once), use:
# gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" --jq '[.[] | select(.user.login == "cubic-dev-ai[bot]")] | last | .submitted_at'
反復規律
ループの各反復で、次の手順を実行します。
- 失敗したゲートで特定された問題のみを修正する
- 修正によって実行時の動作が変わる場合は、新たな手動 QA の証拠を取得する(フェーズ 1)
- アトミックにコミットする(1 つの論理的な修正につき 1 コミット)
- プッシュする
- Gate A から再開する(コードが変更されたため、検証を最初からすべてやり直す)
修正の反復中に、無関係なコードまで「改善」したくなる誘惑は避けてください。修正ループでスコープが広がるとデバッグが難しくなり、新たな失敗を招く可能性があります。
</verify_loop>
フェーズ 4:マージとクリーンアップ
有効なゲートがすべて合格したら(クォータを使い切った場合、Cubic は SKIPPED でも可):
<merge_cleanup>
PR をマージする(デフォルトでは自動マージ)
自動マージはデフォルトで有効にしてください。ユーザーから明示的にマージしないよう指示された場合を除き、有効にします。自動マージを設定すると、マージは GitHub に委ねられ、必須のゲートがすべてグリーンになった時点で PR がマージされるため、チェックの完了を待ち続ける必要はありません。ゲートをバイパスするわけではありません。ゲートに失敗すると GitHub はマージせず、ほかのゲートに失敗した場合と同様、修正して再度 QA を行うためにフェーズ 1 に戻ります。
# This repository requires merge commits. Never use --squash or --rebase.
# --auto arms auto-merge: GitHub merges as soon as all required checks pass.
gh pr merge "$PR_NUMBER" --merge --auto --delete-branch
# If the repo has not enabled the auto-merge feature, --auto errors; once the gates
# are green, fall back to a direct merge: gh pr merge "$PR_NUMBER" --merge --delete-branch
続いて、マージの完了を通知登録します。until [ ... MERGED ] のポーリングループでモデルのラウンドトリップをブロックしないでください。
# Subscribe to merge completion. The monitor exits when gh pr view returns MERGED.
monitor({
description: "Merge completion for PR $PR_NUMBER",
command: "[ \"$(gh pr view $PR_NUMBER --json state -q .state)\" = \"MERGED\" ] && echo MERGED || echo WAITING",
filter: "MERGED",
timeout_ms: 1800000 # 30 min bound for auto-merge to land after all gates pass
})
# → end turn; the MERGED event wakes the session for the cleanup step.
# If the monitor times out, check merge state once: gh pr view "$PR_NUMBER" --json state -q .state
ユーザーがマージをオプトアウトした場合はマージをスキップしますが、以下のクリーンアップは必ず実行してください。どちらの場合もワークツリーは削除されます。
.omo の状態をメインリポジトリに同期する
ワークツリーを削除する前に、.omo/ の状態をコピーして戻します。.omo/ が gitignore されている場合、ワークツリーでの作業中にそこへ書き込まれたファイルはコミットもマージもされず、ワークツリーの削除時に失われます。
# Sync .omo state from worktree to main repo (preserves task state, plans, notepads)
if [ -d "$WORKTREE_PATH/.omo" ]; then
mkdir -p "$ORIGINAL_DIR/.omo"
cp -r "$WORKTREE_PATH/.omo/"* "$ORIGINAL_DIR/.omo/" 2>/dev/null || true
fi
ワークツリーをクリーンアップする
ワークツリーの役目は終わりました。ディスク使用量が膨らまないように削除します。
cd "$ORIGINAL_DIR" # Return to original working directory
git worktree remove "$WORKTREE_PATH"
# Prune any stale worktree references
git worktree prune
完了を報告する
実施内容を要約します。
## PR Complete
- **PR**: #{PR_NUMBER} — {PR_TITLE}
- **Branch**: {BRANCH_NAME} → {BASE_BRANCH}
- **Iterations**: {N} verification loops
- **Gates**: CI pass | Cubic {pass | SKIPPED (quota exhausted)}
- **Merged**: {yes | no — left for you to merge, as requested}
- **Worktree**: cleaned up
</merge_cleanup>
障害からの復旧
<failure_recovery>
回復不能なエラー(例:ベースブランチとのマージコンフリクト、インフラストラクチャ障害)が発生した場合:
- ワークツリーを削除しないでください。ユーザーが内容を確認したり、手動で作業を続けたりする場合があります。
- 発生したこと、試みたこと、現在の状況を報告します。
- ユーザーが作業を再開できるよう、ワークツリーのパスを記載します。
マージコンフリクトの場合:
cd "$WORKTREE_PATH"
git fetch origin "$BASE_BRANCH"
git rebase "origin/$BASE_BRANCH"
# Resolve conflicts, then continue the loop
</failure_recovery>
アンチパターン
| 違反 | 問題となる理由 | 重大度 |
|---|---|---|
| 隔離されたワークツリーではなく、メインのワークツリーで作業する | ユーザーの作業ディレクトリを汚染し、未コミットの作業を破壊する可能性があります | CRITICAL |
| 手動 QA の証拠をディスク上に残さずにコミットまたはプッシュする | 「テストに合格」は機能が動作する証明にはなりません。また、OpenCode/Codex に関わる変更ではリポジトリの規則に違反します | CRITICAL |
| dev/master に直接プッシュする | レビューを完全に回避します | CRITICAL |
| コード変更後に CI ゲートをスキップする | Cubic が古いコードで合格する可能性があります | CRITICAL |
| Cubic が問題を見つけたためにスキップする | スキップが正当化されるのはクォータを使い切った場合のみです。実際の問題は修正して再プッシュする必要があります | HIGH |
| 検証ループ中に無関係なコードを修正する | スコープの逸脱により、新たな失敗が発生します | HIGH |
| 失敗時にワークツリーを削除する | ユーザーが内容を確認したり、作業を再開したりできなくなります | HIGH |
| Cubic の誤検知を根拠なく無視する | Cubic の指摘は、無条件に退けず、評価する必要があります | MEDIUM |
| 独立したスライスを 1 つの大きな PR にまとめる | 原子的なレビューが損なわれます。2000 行の PR が形式的に承認され、リグレッションが見えにくくなり、1 つの問題のあるスライスがほかすべてを妨げます | HIGH |
| 巨大なコミットを 1 つ作成する | 失敗箇所の特定が難しくなり、git-master の原則にも違反します | MEDIUM |
| プッシュ前にローカルチェックを実行しない | 明らかな失敗に CI の時間を浪費します | MEDIUM |