Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions .claude/skills/prepare-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
name: prepare-pr
description: >
`pnpm push` 完了後の PR 作成フローを標準化する試験運用スキル。
jj commit description と diff から PR title / body の初稿を生成し、
ユーザーの明示承認を経て `pnpm prepare-pr-body` → `pnpm create-pr` を実行する。
トリガー条件: `/prepare-pr`、「PR を作成して」「PR 作成して」と明示された場合。
単なる「PR レビュー」「git 操作」では発動しない。
---

# Prepare PR

`pnpm push` 完了後の PR 作成フローを標準化するインタビュー型スキル (試験運用)。

ADR-028 (外部可視成果物の生成コマンドの実行ゲート) の運用フローを具体化し、
Claude が draft を提示 → ユーザー承認 → harness 再確認の三段階で安全に PR を作成する。

## ステータス

**試験運用** (2026-04-19〜)。

評価軸:
- 発火頻度 (月何件)
- 3-4 ステップ (status 確認 → draft → 承認 → 実行) を通せているか
- Claude が勝手に AskUserQuestion をスキップしないか
- body が切り詰めなく保存できているか

半年後に正式採用 / 改良 / 廃止を判断する。

## 前提条件

本 skill を走らせる前に以下が成立していること:

1. `.claude/settings.json` の `permissions.ask` に `pnpm create-pr*` 登録済 (PR-B / ADR-028)
2. `pnpm prepare-pr-body` / `pnpm prepare-pr-body:cleanup` スクリプト利用可 (PR-B / [scripts/prepare-pr-body.ps1](../../../scripts/prepare-pr-body.ps1))
3. jj working copy は `pnpm push` 完了済 (bookmark が remote に反映されている)
4. master との差分が存在する

前提が不成立の場合は skill を開始せず、ユーザーに不足工程を促す。

## 実行手順

### Step 1: 現状確認

以下のコマンドで状態を確認する:

```bash
jj status
jj log -r 'master..@' --no-graph -T 'change_id.short() ++ " | " ++ description ++ "\n\n"'
jj log -r @ --no-graph -T 'local_bookmarks.map(|b| b.name()).join(",") ++ " -> " ++ remote_bookmarks.map(|r| r.name()).join(",")'
```

チェック項目:
- `master..@` 差分が空 → skill 終了 (commit がない)
- `@` に local bookmark なし → skill 終了 (`jj bookmark create` を促す)
- remote bookmark が空 → skill 終了 (`pnpm push` を促す)

### Step 2: PR title 初稿生成

最新 commit の `description.first_line()` を取得:

```bash
jj log -r @ --no-graph -T 'description.first_line()'
```

調整:
- 70 文字超: 短縮候補を提示 (要点を保ったまま短く)
- conventional commits prefix (`feat:` / `fix:` / `refactor:` / `docs:` / `chore:` / `perf:` / `ci:` / `test:`) を維持
- プロジェクト固有の suffix (例: `(PR-D)`) は commit に既にあれば保持

### Step 3: PR body 初稿生成

`jj diff -r 'master..@' --stat` と `jj log -r master..@` を読み取り、以下のセクション構成で初稿を生成:

```markdown
## Summary
- <変更点の bullet 3-6 個、技術的要点を簡潔に>

## Context
<なぜこの変更か。参照 ADR / PR / issue / セッション>

## Validation
- [ ] <lint / test / build の pass 状況>
- [ ] <手動 smoke test 内容>
- [ ] <pre-push-review の verdict>

## References
- <関連 ADR>
- <参照 PR>
- <関連 memory>
```

生成時の注意:
- 実装の意図を復元する (diff だけでなく commit message も読む)
- プロジェクトの ADR 命名 (`ADR-XXX`) と PR 番号 (`PR #XX`) のリンクを明記
- Validation は実測値を使う (ビルド結果・テスト件数・review 所要時間など)

### Step 4: 明示承認 (AskUserQuestion 必須)

Claude は title / body 初稿を user に提示し、**AskUserQuestion ツールで明示承認を取る**。

選択肢例:
- **OK / 実行**: そのまま `pnpm create-pr` を実行
- **修正**: ユーザーが title / body の修正指示を入れる → Step 3 に戻る
- **中止**: PR 作成を行わない

このステップは auto mode でも必ず停止する。AskUserQuestion を使わない (別の方法で確認したつもりになる) のは ADR-028 違反。

### Step 5: body を一時ファイルに書き込み

承認された body を `pnpm prepare-pr-body` 経由で `.tmp-pr-body.md` に UTF-8 (BOM なし) で書き出す:

```bash
cat <<'EOF' | pnpm prepare-pr-body
<approved PR body content>
EOF
```
Comment on lines +113 to +117

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify 1) PowerShell tool is enabled 2) skill doc still contains Bash heredoc example
rg -n "CLAUDE_CODE_USE_POWERSHELL_TOOL|permissions" .claude/settings.json -C2
rg -n "cat <<'EOF' \\| pnpm prepare-pr-body" .claude/skills/prepare-pr/SKILL.md -C2

Repository: aloekun/claude-code-hook-test

Length of output: 303


🏁 Script executed:

# Check full context around the problematic section and look for other shell examples
sed -n '100,130p' .claude/skills/prepare-pr/SKILL.md

# Look for other bash/shell code blocks in the file
rg -n "^\`\`\`(bash|sh)" .claude/skills/prepare-pr/SKILL.md

Repository: aloekun/claude-code-hook-test

Length of output: 903


🏁 Script executed:

# Get the content of all bash code blocks in the file
sed -n '113,140p' .claude/skills/prepare-pr/SKILL.md

Repository: aloekun/claude-code-hook-test

Length of output: 619


PowerShell 環境での Bash heredoc は実行不可です。すべてのシェル例を PowerShell 互換に更新してください。

.claude/settings.jsonCLAUDE_CODE_USE_POWERSHELL_TOOL: "1" が有効なため、ドキュメント内の Bash コード例(lines 113–135)はそのままでは実行できません。以下の 3 つのコード ブロックをすべて PowerShell ここ文字列構文に変換する必要があります:

  • Line 113–116: cat <<'EOF' | pnpm prepare-pr-body → PowerShell @' '@ | pnpm prepare-pr-body
  • Line 123–125: pnpm create-pr --title ...
  • Line 133–135: pnpm prepare-pr-body:cleanup
PowerShell への変換例
-```bash
-cat <<'EOF' | pnpm prepare-pr-body
+```powershell
+@'
 <approved PR body content>
-EOF
-```
+'@ | pnpm prepare-pr-body
+```
-```bash
-pnpm create-pr --title '<approved title>' --body-file .tmp-pr-body.md
-```
+```powershell
+pnpm create-pr --title '<approved title>' --body-file .tmp-pr-body.md
+```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/prepare-pr/SKILL.md around lines 113 - 117, Replace the Bash
heredoc examples with PowerShell here-strings: change the block that starts with
"cat <<'EOF' | pnpm prepare-pr-body" to use PowerShell @' ... '@ piped to pnpm
prepare-pr-body, update the "pnpm create-pr --title '<approved title>'
--body-file .tmp-pr-body" example block to be labeled and formatted as
PowerShell, and convert the cleanup example that references "pnpm
prepare-pr-body:cleanup" to PowerShell formatting as well; ensure you replace
the three bash code fences (the cat <<'EOF' invocation, the pnpm create-pr
invocation, and the pnpm prepare-pr-body:cleanup fence) with PowerShell
here-string equivalents and matching fenced blocks so they run when
CLAUDE_CODE_USE_POWERSHELL_TOOL is enabled.


stdin を使うのは `--body` 引数経由のシェル切り詰め問題を回避するため (PR #51 / memory `feedback_pnpm_create_pr_body.md`)。

### Step 6: `pnpm create-pr` を foreground 実行

```bash
pnpm create-pr --title '<approved title>' --body-file .tmp-pr-body.md
```

`permissions.ask` プロンプトで harness 側が再確認する (二次防衛層)。ユーザーは deny して取り消しも可能。

### Step 7: 一時ファイルのクリーンアップ

PR 作成が成功したら `.tmp-pr-body.md` を削除:

```bash
pnpm prepare-pr-body:cleanup
```

PR 作成が失敗した場合は body を手元に残して原因調査できるようにクリーンアップを遅らせてよい。

## 設計原則

### user-supplied text を尊重 (ADR-022)

Claude が生成した draft は「初稿」。ユーザーの修正指示 (「〜の記述を消して」「References に PR #XX を追加して」等) を優先し、skill 内で忠実に反映する。

承認後の title / body は automated actor (takt / cli-*) が書き換えない。

### ADR-028 の二層防衛を活かす

| 層 | メカニズム | 本 skill での役割 |
|---|---|---|
| 一次 (Claude 側) | memory `feedback_bookmark_auto_naming.md` + 本 skill の AskUserQuestion | ユーザーが明示的に「OK」を出すまで進まない |
| 二次 (harness 側) | `.claude/settings.json` の `permissions.ask` | Claude が一次を誤って飛ばしても、ここで再確認が発火する |

どちらか一方を無効化すると一層だけになる。両方必須。

### 自動化コンポーネントから独立

takt / claude -p / cli-* の自律ループはこの skill を呼ばない。interactive session で Claude が明示指示 (`/prepare-pr` 起動や「PR を作成して」依頼) を受けた時のみ発動する。

### body は必ず一時ファイル経由

`--body "..."` 引数形式は複数行 / シェル quote で切り詰めリスクがある (PR #51 で修正済だが、defense-in-depth として helper 経由を徹底)。

## 避けるべきアンチパターン

- **AskUserQuestion をスキップ**: auto mode でも必須。飛ばせば ADR-028 一次防衛が崩壊する
- **`--body "..."` を直接使う**: `.tmp-pr-body.md` 経由を徹底する
- **skill から `jj bookmark create` / `pnpm push` を実行**: 事前工程で完了済の前提。skill の責務外。必要なら Claude が別途実行する
- **Claude が承認済 draft を勝手に「改善」**: ユーザーが承認した後の二重書き換えは ADR-022 違反
- **PR 作成失敗時に無言で `cleanup`**: 失敗原因の body を失う。失敗時は body を手元に残す

## 関連

- **ADR-028** (外部可視成果物の生成コマンドの実行ゲート): 本 skill の設計根拠
- **ADR-022** (自動化コンポーネントの責務分離): user-supplied text の保護
- **PR #57** (PR-B): `permissions.ask` + `pnpm prepare-pr-body` helper
- **memory `feedback_bookmark_auto_naming.md`**: 一次防衛層の源
- **memory `feedback_pnpm_create_pr_body.md`**: `--body` の切り詰め対策
54 changes: 1 addition & 53 deletions docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,61 +159,9 @@

---

## セッション 247510ea 由来: 整備タスク群 (PR-D)

> **最優先ブロック**。PR #54 / #55 のマージ後に確定した ADR / 仕組みの整備作業。残 1 タスク。
>
> **背景コンテキスト**:
> - **発端セッション**: `247510ea-3f24-4b87-8f68-3c860e1b1b4e` (2026-04-18)
> - **先行成果**:
> - PR #54 (cli-merge-pipeline の revset 拡張 `@-..@--` + trunk filter)
> - PR #55 (cli-pr-monitor への同パターン水平展開)
> - PR-A (ADR 集約 / PR #56 merged): ADR-028 新設、ADR-021 原則 5 追加、ADR-024 本採用、ADR-019 可換性追記
> - PR-B (Ask ルール + body helper / PR #57 merged): `permissions.ask` 4 パターン追加、`scripts/prepare-pr-body.ps1` 新設
> - PR-C (jj-helpers 抽出 / 本 PR): `src/lib-jj-helpers/` 新設、3 クレート差し替え、重複テストを lib 側に集約
> - **ユーザーフィードバック 3 点** (memory `feedback_bookmark_auto_naming.md` に記録済):
> 1. auto mode は試験導入。基本は自律実行だが、**最終出力の責任をユーザーが握るため `pnpm create-pr` / `pnpm merge-pr` は事前許可必須**
> 2. bookmark 名は Claude が自動採番して OK
> 3. `pnpm push` は foreground 実行 OK (permission prompt がゲート)
> - **設計的な確認事項** (ADR-028 / ADR-019 追記で明文化済):
> - `hooks` での `block` は許可後も効くので UX 崩壊 → 採用せず
> - 代わりに **settings.json の Ask ルール** で「毎回確認プロンプト」を出す (PR-B で実装済)
> - CodeRabbit 無料枠の制約 (1h 3 回、public リポジトリ限定) を許容し、rate limit 耐性の作り込みは **しない** (レビュアーロックイン回避のため)
>
> **PR 依存関係**:
> ```
> PR-A (ADR 集約, merged) ──┬── PR-B (Ask ルール + body helper, merged) ── PR-D (prepare-pr skill)
> └── PR-C (jj-helpers 抽出, 本 PR)
> ```

### 7. [PR-D] `prepare-pr` skill (試験運用)

- **やろうとしたこと**: auto mode で安全に PR を作成するためのインタビュー型 skill を試験運用として整備。commit log と diff から PR title / body の初稿を生成し、ユーザー承認後に `pnpm create-pr` を foreground 実行するフローを標準化
- **現在地**: 未着手。PR-B merge 後に着手 (ADR-028 の運用フローと PR-B の body helper が前提)
- **実装内容**:
- [ ] **`.claude/skills/prepare-pr/SKILL.md` 新規** (試験運用ステータス)
- 起動条件: 「PR を作成して」等の明示依頼、または `/prepare-pr` 起動
- ステップ:
1. `jj status` + `jj log -r master..@` で差分サマリ取得
2. commit description から PR title 初稿生成
3. diff から PR body 初稿生成 (Summary / Changes / Test Plan / References セクション)
4. Claude が提示 → **明示承認** (AskUserQuestion 強制)
5. `pnpm prepare-pr-body` (PR-B 成果物) 経由で body 書き込み
6. `pnpm create-pr --title ... --body-file ...` foreground 実行 (Ask プロンプトで再確認)
7. `.tmp-pr-body.md` 削除
- [ ] **検証**: skill 起動テスト、PR 作成完遂確認
- **詰まっている箇所**:
- **skill の既存 frontend-design/pre-push-review との連携**: 既存スキルとの衝突可否を skill-sync-check で確認
- **想定サイズ**: 小〜中 (skill 定義 1 本、~100-200 行)
- **依存**: **PR-A** (ADR-028), **PR-B** (M1 body helper, Ask ルール)
- **見積**: 1-2 時間
- **参照**: ADR-028, PR-B 成果物

---

## その他の進行中タスク

### 8. 雑務: 過去の delete-pending bookmark cleanup
### 7. 雑務: 過去の delete-pending bookmark cleanup

- **やろうとしたこと**: `jj git push --tracked` で `Refusing to push deleted bookmark fix/push-allow-new` の警告が出るため、`jj bookmark forget fix/push-allow-new` で消す
- **現在地**: 未対応。push を block しないので緊急性なし
Expand Down