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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ src/*/Cargo.lock
.claude/pr-monitor-state.json.tmp
.claude/scheduled_tasks.lock
# ADR-029: post-merge-feedback の pending file (cli-merge-pipeline 生成、skill が consume する一時 artifact)
# 旧経路。Phase E で機構ごと廃止予定 (ADR-030 supersede)
.claude/post-merge-feedback-pending.json

# ADR-030: post-merge-feedback の出力レポート + 失敗マーカー (内部 artifact)
.claude/feedback-reports/

# ADR-030: takt workflow への入力 (cli-merge-pipeline が生成、workflow が読む)
.takt/post-merge-feedback-context.json
.takt/post-merge-feedback-transcript.jsonl

# Temp PR body file (generated by `pnpm prepare-pr-body`, removed by `pnpm prepare-pr-body:cleanup`)
.tmp-pr-body.md
112 changes: 112 additions & 0 deletions .takt/facets/instructions/aggregate-feedback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Aggregate Feedback

3 つの分析レポート (PR 知見・セッション知見・pre-push レポート知見) を Plankton 優先度で統合し、最終的な再発防止策レポートを生成する。

旧 `/post-merge-feedback` skill (`E:\work\claude-code-skills\post-merge-feedback\SKILL.md`) の Phase 4 ロジックから port。

**重要な原則:**
- 読み取り専用。コードの修正は一切行わない (実装は L2 recovery / ユーザー判断で行う)
- 知見がない場合は「提案なし」で正常終了する。無理に提案を捻出しない
- 重複する提案はマージし、根拠 (rationale) を統合する
- Tier 1 を最優先で提案する。Tier 3 のみの提案は価値が低い

---

## Input

### Report Directory (takt が提供)

本 step (`pass_previous_response: false`) は前 step の response を受け取らない代わりに、**Report Directory** に保存された 3 つの先行レポートを Read で読み取る:

- `pr-analysis.md` — analyze-pr facet の出力
- `session-analysis.md` — analyze-session facet の出力
- `prepush-analysis.md` — analyze-prepush-reports facet の出力

### Context file

`.takt/post-merge-feedback-context.json` も Read で読み、PR 番号・タイトル等のメタデータを取得する:

```json
{
"pr_number": 123,
"owner_repo": "aloekun/claude-code-hook-test",
"merged_at": "2026-04-25T10:00:00Z"
}
```

PR タイトルが context に含まれていない場合は、レポート内の `### PR: ...` ヘッダから抽出する。

## Phase 1: 3 レポートの統合

各レポートの提案リスト (Tier 1 / 2 / 3 の表) を抽出し、以下のルールで統合する:

1. **重複検出**: 同じ `Target` + 似た `Description` の提案はマージする
2. **根拠統合**: マージした提案の `Rationale` カラムには複数ソース (PR diff / session / prepush) を併記する
3. **Tier 並び**: 最終リストは Tier 1 → Tier 2 → Tier 3 の順
4. **品質フィルタ**: 以下の提案は除外する
- 一般的なベストプラクティスの押し付け (具体的根拠がない)
- すでに hooks-config.toml / custom-lint-rules.toml に存在するルール (Read で確認可能)
- 対象ファイルが read-only zone (`.takt/`, `docs/adr/`, `templates/`) のみで具体的な編集箇所が示せないもの

## Phase 2: 最終レポート生成

以下の Required output 形式で `feedback-report.md` を出力する。

### Source 表記の凡例

`Rationale` に書く `Source` の表記:
- `PR diff` — PR の差分から抽出
- `Review comment` — PR レビューコメントから抽出
- `Session` — セッション transcript から抽出
- `Prepush:simplicity` / `Prepush:security` — pre-push-review の各レポートから抽出
- 複数ソースは `;` 区切り (例: `PR diff; Session`)

---

## Required output

```markdown
## Post-Merge Feedback Report

### PR: <owner/repo>#<number> <title>
- マージ日時: <merged_at>
- 分析ソース: PR data, Session transcript, Pre-push reports

### 統合された再発防止策

#### Tier 1: Hooks/Linter 改善 (決定論的防止)

| # | Type | Description | Target | Effort | Rationale (Source) |
|---|------|-------------|--------|--------|--------------------|
| 1 | custom_lint_rule | ... | .claude/custom-lint-rules.toml | Low | PR diff; Session |

#### Tier 2: テスト/自動化

| # | Type | Description | Target | Effort | Rationale (Source) |
|---|------|-------------|--------|--------|--------------------|

#### Tier 3: ドキュメント/ルール

| # | Type | Description | Target | Effort | Rationale (Source) |
|---|------|-------------|--------|--------|--------------------|

### 次のアクション

- ユーザーがレポートを確認後、UserPromptSubmit hook (L2 recovery) または直接的な指示で実装へ進む
- このレポートは `.claude/feedback-reports/<pr_number>.md` に保存される (`.gitignore` 除外、内部 artifact)
```

提案がない Tier はセクションごと省略する。

提案がゼロの場合は以下:

```markdown
## Post-Merge Feedback Report

### PR: <owner/repo>#<number> <title>

この PR から特筆すべき再発防止策は見つかりませんでした。
3 レポート (PR / Session / Pre-push) のいずれにも、決定論的な防止策に値する事象が記録されていませんでした。
```

最後に `aggregation complete` で終了する。
143 changes: 143 additions & 0 deletions .takt/facets/instructions/analyze-pr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Analyze PR (post-merge-feedback workflow)

マージ済み PR のコード差分・レビューコメントを分析し、再発防止に役立つ知見を構造化レポートで出力する。

旧 `/analyze-pr` skill (`E:\work\claude-code-skills\analyze-pr\SKILL.md`) から port。

**重要な原則:**
- 読み取り専用。コードの修正は一切行わない
- 知見がない場合は「提案なし」で正常終了する。無理に提案を捻出しない
- セッション知見は扱わない (`analyze-session` facet が別途処理)

---

## Input

`.takt/post-merge-feedback-context.json` を Read で読み、PR メタデータを取得する。

```json
{
"pr_number": 123,
"owner_repo": "aloekun/claude-code-hook-test",
"merged_at": "2026-04-25T10:00:00Z",
"first_commit_time": "2026-04-25T08:00:00Z",
"transcript_path": ".takt/post-merge-feedback-transcript.jsonl",
"prepush_reports_dir": ".takt/runs/<latest>-pre-push-review/reports"
}
```

context file が存在しない / parse 失敗の場合は `## PR Analysis Report` セクションに「context unavailable」と書き、analysis complete で次へ進める。

## Phase 1: PR データ取得

`pr_number` と `owner_repo` を使い、Bash で並列にデータを取得する:

```bash
# コード差分
gh pr diff <pr_number> --repo <owner_repo>

# レビューコメント (インライン)
gh api repos/<owner_repo>/pulls/<pr_number>/comments \
--jq '.[] | {user: .user.login, body: .body, path: .path, line: .line}'

# レビュー判定
gh api repos/<owner_repo>/pulls/<pr_number>/reviews \
--jq '.[] | {user: .user.login, state: .state, body: .body}'

# PR メタデータ
gh pr view <pr_number> --repo <owner_repo> \
--json title,body,labels,mergedAt,state
```

### エラーハンドリング

| エラー | 対応 |
|--------|------|
| PR が存在しない | エラーセクションを書き、analysis complete で次へ |
| diff 取得失敗 | エラーを記録し、レビューコメントのみで続行 |
| コメント / レビュー取得失敗 | 警告を出して diff のみで続行 |

## Phase 2: 分析 & 知見抽出

PR diff + レビューコメントを分析し、再発防止に役立つ知見を抽出する。

### 着眼点

- **繰り返しパターン**: diff 内で同じ種類の修正が複数箇所にあるか → リンタールールで防止可能か
- **レビュー指摘の傾向**: 同じカテゴリの指摘が複数あるか → hooks で自動検出可能か
- **危険な操作**: セキュリティリスク、破壊的操作が含まれていたか → block_pattern で防止可能か
- **設計上の課題**: アーキテクチャ的な問題が指摘されていたか → ドキュメントやテストで防止可能か

### Plankton 優先度 (Tier 分類)

各提案を以下の Tier に分類する。**Tier 1 を最優先で検討**。

#### Tier 1: Hooks/Linter 改善 (決定論的防止 — 最も強力)

| Type | 対象ファイル | 説明 |
|------|------------|------|
| `block_pattern` | `.claude/hooks-config.toml` | PreToolUse のコマンド実行ブロック正規表現 |
| `custom_lint_rule` | `.claude/custom-lint-rules.toml` | PostToolUse のリテラル検出ルール |
| `linter_pipeline` | `.claude/hooks-config.toml` | リンターパイプラインへのステップ追加 |

#### Tier 2: テスト/自動化 (半決定論的)

| Type | 説明 |
|------|------|
| `test_addition` | 再発検出のためのテストケース追加 |
| `ci_step` | CI パイプラインへのステップ追加 |

#### Tier 3: ドキュメント/ルール (非決定論的 — 最も弱い)

| Type | 対象ファイル | 説明 |
|------|------------|------|
| `claude_md_rule` | `CLAUDE.md` | プロジェクトルールの追加 |
| `adr` | `docs/adr/` | 設計判断の記録 |

### 提案の品質基準

- **具体的であること**: 「セキュリティに注意」ではなく「危険な API 使用を `custom_lint_rule` で検出」のように具体的なルール提案
- **実装可能であること**: 対象ファイルと具体的な変更内容を含む
- **根拠があること**: PR diff またはレビューコメントの具体的な事例に基づく
- **過剰提案しないこと**: 本当に再発リスクがある問題のみ。一般的なベストプラクティスの押し付けはしない

---

## Required output

```markdown
## PR Analysis Report

### PR: <owner/repo>#<number> <title>
- 状態: Merged (<mergedAt>)
- 分析ソース: PR diff, レビューコメント

#### Tier 1: Hooks/Linter 改善

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|

#### Tier 2: テスト/自動化

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|

#### Tier 3: ドキュメント/ルール

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|
```

提案がない Tier はセクションごと省略する。

提案がゼロなら以下:

```markdown
## PR Analysis Report

### PR: <owner/repo>#<number> <title>

この PR から特筆すべき再発防止策は見つかりませんでした。
```

最後に `analysis complete` で終了する。
110 changes: 110 additions & 0 deletions .takt/facets/instructions/analyze-prepush-reports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Analyze Pre-Push Reports

PR がマージされる前の最終 push 時に生成された pre-push-review レポート (simplicity / security) を集約し、再発防止に値する指摘をまとめる。

**重要な原則:**
- 読み取り専用。コードの修正は一切行わない
- pre-push-review レポートが見つからない / 空の場合は「対象データなし」で正常終了する
- 既に push 時に APPROVED されている指摘でも、「再発防止策に転用できそうな知見」がある場合は抽出する

---

## Input

`.takt/post-merge-feedback-context.json` を Read で読み、`prepush_reports_dir` を確認する:

```json
{
"pr_number": 123,
"prepush_reports_dir": ".takt/runs/20260425-094925-pre-push-review/reports"
}
```

`prepush_reports_dir` が空 / dir が存在しない場合は:

```markdown
## Pre-Push Reports Analysis

### Status

pre-push-review の reports が見つかりませんでした。
```

を出力し `analysis complete` で次へ進める。

## Phase 1: レポートの収集

Glob で `<prepush_reports_dir>/*.md` を列挙し、それぞれ Read で内容を取得する。

典型的なレポート:
- `simplicity-review.md` — 簡潔性レビューの指摘
- `security-review.md` — セキュリティレビューの指摘
- `supervisor-validation.md` — supervisor 判定 (任意)
- `summary.md` — 統合サマリ (任意)

各レポートは markdown 形式で、findings / verdict / recommendations が含まれる想定。

## Phase 2: 集約・整理

以下の観点で要約する:

1. **明示された finding**: 各レビューで `REJECT` / `needs_fix` 判定だった指摘
2. **修正完了済の事象**: takt の fix loop で APPROVE に至った修正の系統
3. **supervise 判定の警告**: supervisor の警告 / コメント

各 finding に対して、**Plankton 優先度 (Tier 1〜3)** で再発防止策を提案する。

注意点:
- supervisor が `ready to push` で APPROVE した場合、**コードレベルの修正は不要** だが、それでも「同じパターンを次回検出するための仕組み」を Tier 1 候補として検討する
- 個別の review コメントは要約のみ (原文引用は最小限)

---

## Required output

```markdown
## Pre-Push Reports Analysis

### 集約サマリ

- 対象 reports: {ファイル名のリスト}
- simplicity verdict: {APPROVE / REJECT / N/A}
- security verdict: {APPROVE / REJECT / N/A}
- supervisor verdict: {APPROVE / REJECT / N/A}

### 主要 findings (要約)

1. {要約} (出典: {report ファイル名})
- 防止策: Tier {N} - {具体的な提案}

### 再発防止候補 (Plankton 分類)

#### Tier 1: Hooks/Linter 改善

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|

#### Tier 2: テスト/自動化

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|

#### Tier 3: ドキュメント/ルール

| # | Type | Description | Target | Effort | Rationale |
|---|------|-------------|--------|--------|-----------|
```

提案がない Tier はセクションごと省略する。

該当なしの場合は以下:

```markdown
## Pre-Push Reports Analysis

### Status

pre-push reports は読み込めましたが、再発防止に値する findings は見つかりませんでした。
```

最後に `analysis complete` で終了する。
Loading