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
148 changes: 73 additions & 75 deletions .takt/workflows/post-merge-feedback.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ description: >
マージ済み PR のフィードバックレポートを生成する決定論的 workflow (ADR-030)。
入力: cli-merge-pipeline が事前に書き出すコンテキストファイル群
- .takt/post-merge-feedback-context.json (PR メタデータ + 時刻 range)
- .takt/post-merge-feedback-transcript.jsonl (filter 済みセッション履歴)
facets を順次 chain し、aggregate-feedback で最終レポートを生成する。
- .takt/post-merge-feedback-transcript.jsonl (filter 済セッション履歴)
3 つの analyze facet は独立した情報源 (PR data / transcript / pre-push reports)
を扱うため parallel block で並列実行する。総実行時間は max(analyze) + aggregate
に抑えられる (PR #78 dogfood で sequential 12m13s → 並列化想定 7m30s を確認済)。
fix loop なし: コードではなくレポートを生成するため reviewers/fix の構造は不要。
出力: feedback-report.md (Report Directory に保存)
cli-merge-pipeline が takt 完了後に .claude/feedback-reports/<pr>.md にコピーする。
Expand All @@ -17,89 +19,85 @@ workflow_config:
network_access: true

max_steps: 10
initial_step: analyze-pr
initial_step: analyze

steps:
# ---------------------------------------------------------------------------
# Step 1: analyze-pr
# PR diff + reviews を分析し、再発防止に役立つ知見を抽出する。
# 旧 /analyze-pr skill から port (E:\work\claude-code-skills\analyze-pr\SKILL.md)。
# Step 1: analyze (parallel)
# 3 つの分析 facet を並列実行する。各 facet は独立した情報源から知見を抽出し、
# いずれも `analysis complete` で終了する。Report Directory には
# pr-analysis.md / session-analysis.md / prepush-analysis.md が並ぶ。
# ---------------------------------------------------------------------------
- name: analyze-pr
edit: false
persona: code-reviewer
model: sonnet
policy: review
knowledge: architecture
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
- Bash
instruction: analyze-pr
output_contracts:
report:
- name: pr-analysis.md
format: pr-analysis
rules:
- condition: analysis complete
next: analyze-session
- name: analyze
parallel:
# PR diff + reviews を分析 (旧 /analyze-pr skill から port)
- name: analyze-pr
edit: false
persona: code-reviewer
model: sonnet
policy: review
knowledge: architecture
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
- Bash
instruction: analyze-pr
output_contracts:
report:
- name: pr-analysis.md
format: pr-analysis
rules:
- condition: analysis complete

# ---------------------------------------------------------------------------
# Step 2: analyze-session
# filter 済みセッション transcript から実装時の学び・トラブル・ユーザー指示を抽出。
# ADR-030 §transcript 抽出戦略に従い、Rust 側で時刻 range filter 済の入力を読む。
# ---------------------------------------------------------------------------
- name: analyze-session
edit: false
persona: code-reviewer
model: sonnet
policy: review
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
instruction: analyze-session
pass_previous_response: false
output_contracts:
report:
- name: session-analysis.md
format: session-analysis
rules:
- condition: analysis complete
next: analyze-prepush-reports
# filter 済 transcript からセッション知見を抽出
- name: analyze-session
edit: false
persona: code-reviewer
model: sonnet
policy: review
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
instruction: analyze-session
output_contracts:
report:
- name: session-analysis.md
format: session-analysis
rules:
- condition: analysis complete

# pre-push-review の reports を集約
- name: analyze-prepush-reports
edit: false
persona: code-reviewer
model: sonnet
policy: review
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
instruction: analyze-prepush-reports
output_contracts:
report:
- name: prepush-analysis.md
format: prepush-analysis
rules:
- condition: analysis complete

# ---------------------------------------------------------------------------
# Step 3: analyze-prepush-reports
# pre-push-review の reports (.takt/runs/<latest>-pre-push-review/reports/) を集約。
# ---------------------------------------------------------------------------
- name: analyze-prepush-reports
edit: false
persona: code-reviewer
model: sonnet
policy: review
provider_options:
claude:
allowed_tools:
- Read
- Glob
- Grep
instruction: analyze-prepush-reports
pass_previous_response: false
output_contracts:
report:
- name: prepush-analysis.md
format: prepush-analysis
rules:
- condition: analysis complete
- condition: all("analysis complete")
next: aggregate-feedback

# ---------------------------------------------------------------------------
# Step 4: aggregate-feedback
# Step 2: aggregate-feedback
# 3 つの分析レポートを Plankton 優先度で統合し、最終レポートを生成する。
# 旧 post-merge-feedback skill の Phase 4 ロジックから port。
# pass_previous_response: false で、Report Directory の各 *-analysis.md を直接読む。
Expand Down
47 changes: 46 additions & 1 deletion docs/adr/adr-030-deterministic-post-merge-feedback.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,54 @@ skill ベースで運用していた analyze-pr / post-merge-feedback Phase 4

**採用根拠**: hard fail (merge を失敗扱いにする) は既にマージ済みの PR を取り消せないため不可能。retry 機構を Floor の外側に持つことで、Floor 自体は exactly-once を保証しつつ failure 時の人手介入経路を確保する。

#### Reconciliation (Phase B post-fix で追加)

PR #78 dogfood で発覚した **Windows の `child.kill()` が takt の descendants を殺せない** 問題への対策として、`run_takt_workflow` の戻り値に関わらず最後に必ず `copy_feedback_report` を試す reconciliation を `feedback::run` に組み込む:

```text
1. run_takt_workflow → 成功 / timeout / 失敗 のいずれか
2. copy_feedback_report を必ず試行
├─ report が存在 → success 扱い (既存の .failed marker は cleanup)
└─ report が不在 → 失敗扱い (.failed marker 書込み)
```

これにより以下のケースが救済される:
- takt が timeout で kill されたが、orphan が後から report を書き終えた
- takt が exit=non-zero を返したが、aggregate-feedback は完了していた

#### 並行起動 guard (Phase B post-fix で追加)

cross-invocation context overwrite race の予防として、`feedback::run` の冒頭で `.takt/post-merge-feedback-context.json` の経過時間を確認:

- `CONCURRENT_RUN_GUARD_SECS = 1500` (timeout 1200s より少し長い値) 以内に書かれた context.json が存在する場合、新規実行を refuse する
- 1500s 経過していれば「前回 takt は確実に終わっている」と判断して上書き許可

これは orphan takt がまだ走っている可能性が高い時間帯における新規 cli-merge-pipeline 起動を発生源で止め、context.json / transcript.jsonl の race を回避する。本格的な per-invocation isolation は将来 takt の context dir 連携で実現する余地を残す (Phase B のスコープ外)。

### レイテンシ

`pnpm merge-pr` の所要時間が takt workflow 実行分 (数分) 増加する。ユーザー判断 (作業計画策定時に合意) として **数分の追加レイテンシは許容**。`pnpm merge-pr` は同期実行で待つ前提とする ([ADR-016](adr-016-long-running-command-strategy.md) の長時間コマンド戦略に該当)。
`pnpm merge-pr` の所要時間が takt workflow 実行分増加する。ユーザー判断 (作業計画策定時に合意) として **数分の追加レイテンシは許容**。`pnpm merge-pr` は同期実行で待つ前提とする ([ADR-016](adr-016-long-running-command-strategy.md) の長時間コマンド戦略に該当)。

#### Phase B dogfood で確立した時間モデル

3 つの analyze facet (`analyze-pr` / `analyze-session` / `analyze-prepush-reports`) は独立した情報源を扱うため [`post-merge-feedback.yaml`](../../.takt/workflows/post-merge-feedback.yaml) では `parallel:` block で並列実行する。総時間モデル:

```text
total = max(analyze-pr, analyze-session, analyze-prepush-reports) + aggregate-feedback
```

PR #78 dogfood 計測 (sequential 構成時):

| step | 所要時間 |
|---|---|
| analyze-pr | 3m 22s |
| analyze-session | 5m 24s ← 最長 (transcript 量に依存) |
| analyze-prepush-reports | 1m 21s |
| aggregate-feedback | 2m 06s |
| **sequential 合計** | **12m 13s** |
| **parallel 想定** | **~7m 30s** |

`TAKT_TIMEOUT_SECS` は parallel 構成での観測実績に対し 2x 程度の安全係数を取り **1200s (20 分)** に設定している。analyze-session の所要時間は transcript の量 (commit 数 × セッション長) でスケールするため、長期 PR では再評価が必要。

### task labeling convention (Phase B dogfood で確立)

Expand Down
Loading