diff --git a/CLAUDE.md b/CLAUDE.md index 59b0eb3..fe25798 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,6 +32,7 @@ - [ADR-028: 外部可視成果物の生成コマンド (PR 作成/マージ) の実行ゲート](docs/adr/adr-028-pnpm-create-pr-gate.md) - [ADR-029: Post-Merge Feedback の自動起動 — pending file + 現セッション起動](docs/adr/adr-029-post-merge-feedback-auto-trigger.md) *(試験運用)* - [ADR-030: 決定論的 Post-Merge Feedback — takt 経由の同期実行 + 失敗マーカーによる recovery](docs/adr/adr-030-deterministic-post-merge-feedback.md) *(試験運用 / Supersedes ADR-014 full, ADR-029 partial)* +- [ADR-031: 週次プロジェクト全体レビューパイプライン — whole-tree review の自己改善ループ](docs/adr/adr-031-weekly-review-pipeline.md) *(試験運用)* ## Build diff --git a/docs/adr/adr-031-weekly-review-pipeline.md b/docs/adr/adr-031-weekly-review-pipeline.md new file mode 100644 index 0000000..3b958e5 --- /dev/null +++ b/docs/adr/adr-031-weekly-review-pipeline.md @@ -0,0 +1,343 @@ +# ADR-031: 週次プロジェクト全体レビューパイプライン — whole-tree review の自己改善ループ + +## ステータス + +試験運用 (2026-04-27) + +## コンテキスト + +### 問題: 既存 3 パイプラインの review scope の空白 + +本プロジェクトには 3 つのレビューパイプラインが稼働しているが、いずれも **変更差分** を起点としており、**プロジェクト全体を俯瞰する視点** が欠けている。 + +| 既存パイプライン | レビュー対象 | 主な観点 | 拾えないもの | +|---|---|---|---| +| pre-push-review ([ADR-015](adr-015-push-runner-takt-migration.md), [ADR-027](adr-027-push-review-simplicity-focus.md)) | push 前の diff | simplicity (diff 局所) | architectural drift / cross-PR の冗長 | +| post-pr-review ([ADR-018](adr-018-pr-monitor-takt-migration.md), [ADR-019](adr-019-coderabbit-review-hybrid-policy.md)) | PR 単位の diff | CodeRabbit 由来の品質 | PR 跨ぎの ADR 違反 / 累積複雑度 | +| post-merge-feedback ([ADR-030](adr-030-deterministic-post-merge-feedback.md)) | マージ済み PR + transcript | 再発防止 (差分起点) | 全体俯瞰 | + +ADR-027 は「push-time = simplicity 限定 / architectural review = post-PR」と決めたが、post-PR の CodeRabbit も **PR diff のみを見る** ため、PR 跨ぎの観点は依然空白のままである。 + +### 拾えていない具体的な瑕疵 + +- **cross-PR ドリフト**: 個別 PR では妥当でも、累積で見ると同じ責務の関数が複数モジュールに散らばる +- **ADR 違反の蓄積**: ADR で禁止したパターンが新規 PR では検出されるが、既に commit 済みの違反は誰も指摘しない +- **命名規約のドリフト**: ADR-012 で定めた命名が古いコードでは破られている +- **無駄の累積**: dead code / 未使用の抽象化 / overspec'd module が PR 単位では「今回の変更ではない」として見送られる +- **循環依存・レイヤ侵犯**: モジュール間関係は diff 単独では判断不可 + +### 設計上の知見: review scope 軸での既存パイプラインの分布 + +レビューを「scope (diff 局所 / PR diff / whole tree)」と「観点 (simplicity / security / architecture)」の 2 軸でマッピングすると、whole-tree × architecture と whole-tree × simplicity が空白である。 + +```text + | diff 局所 | PR diff | whole tree +--------------|-----------------|-----------------|----------------- +simplicity | pre-push (027) | CodeRabbit | ❌ 空白 +security | pre-push | CodeRabbit | ❌ 空白 +architecture | (ADR-027 で除外)| post-pr-review | ❌ 空白 +``` + +### 既存の決定論パターン (ADR-030) との比較 + +ADR-030 は「機械的 = Rust / AI parallel = takt / ask-based = ユーザー対話」の 3 層分離を確立した。本 ADR はこのパターンを **4 例目** として継承するが、**must-run 要件を持たない** 点で性質が異なる: + +| 観点 | ADR-030 (post-merge-feedback) | 本 ADR (weekly-review) | +|---|---|---| +| 起動タイミング | merge 直後 (機械的に必須) | 週次 (人間判断、忘れても致命的でない) | +| 失敗時の影響 | silent loss = 学習機会喪失 → must-run | 単に「今週はスキップ」で済む → best-effort で十分 | +| トリガー | cli-merge-pipeline (決定論的) | 手動 `/weekly-review` + reminder hook | +| 決定論ゲート | 必要 (`.failed` marker + L2 recovery) | 不要 (reminder で十分) | + +must-run でないことが「skill を主動線に置ける」設計上の余地を生む。ADR-030 が skill を否定したのは must-run 要件下での話であり、本 ADR はその結論を一般化した規範ではない。 + +## 検討した選択肢 + +### 選択肢 A: 既存 post-pr-review に whole-tree モードを追加 + +`post-pr-review.yaml` に `--whole-tree` フラグを追加し、PR ごとに全体レビューも走らせる案。**却下**: + +- PR ごとに whole-tree レビューを走らせると重複が大量に発生し、CodeRabbit 指摘との優先順位付けも難しい +- 「週次」のリズムで俯瞰したいという本要件のセマンティクスを満たさない +- post-pr-review は ADR-019 のハイブリッド構成で機能分担が確立しており、責務を増やすと崩れる + +### 選択肢 B: skill 単独 (手動 + AskUserQuestion で対話的レビュー) + +`/weekly-review` skill が単一の Claude セッション内で全観点を順次レビューする案。**却下**: + +- 3 観点 (simplicity / security / architecture) を逐次実行すると context window が肥大化し、後半の facet ほど判断が劣化する +- 並列性がないため wall-clock が長くなる +- ADR-015 / 018 / 030 で確立した「AI 並列処理は takt」原則と乖離する + +### 選択肢 C: takt 単独 (parallel facets, no skill) + +`weekly-review.yaml` workflow を直接呼び、レポートだけ出力する案。**却下**: + +- ユーザー採否対話 (採用 / 却下 / 保留) の UX が takt の loop / supervise 機構では表現しにくい +- todo.md への追記は「ユーザー意図表現を含む既存 artifact への書き込み」で、ADR-022 原則 1 の「未承認での確定」を避けるためにユーザー確認ゲートが必須 → ask-based な経路が必要 +- skill (AskUserQuestion) を介さないと、採否単位の細かい意思決定ができない + +### 選択肢 D: hybrid (takt workflow + skill, manual + reminder hook) + +並列レビューは takt、ユーザー対話と todo.md 反映は skill、リマインドは Rust hook。各層が得意な役割に専念する。**採用**。 + +## 決定 + +**選択肢 D を採用する。** + +### アーキテクチャ: 3 層構成 + +| 層 | 機構 | 責務 | 失敗時の挙動 | +|---|------|-----|------------| +| **L1 Reminder** | `hooks-session-start` (Rust) 拡張 | `.claude/weekly-review-last-run.json` の mtime を見て、7 日以上経過していれば `additionalContext` で `/weekly-review` を促す | reminder 不在 (致命的でない、ユーザーが気付けば実行) | +| **L2 Review** (AI parallel) | takt workflow `weekly-review` | 3 facets (simplicity / security / architecture) を **whole-tree** で並列レビュー、aggregate facet で findings JSON + markdown 統合 | `.claude/weekly-reviews/.md.failed` marker 残存 → 次セッションの L1 hook が recovery context を出力 | +| **L3 Approval & Apply** | skill `/weekly-review` | takt 起動 → pending JSON 読み込み → AskUserQuestion で採否一括選択 → 採用分のみ docs/todo.md に追記 | best-effort (ユーザーが skill を再起動すれば pending JSON から再開可能) | + +### 全体フロー + +```text +SessionStart hook (hooks-session-start.exe) + └─ .claude/weekly-review-last-run.json の mtime チェック + ├─ 7日未経過: silent exit + ├─ 7日経過: additionalContext で /weekly-review を促す (reminder) + └─ *.md.failed marker 検出: additionalContext で /weekly-review --resume を促す (recovery) + + ▼ (ユーザーが /weekly-review を実行) + +skill /weekly-review (Phase 1-4) + ├─ Phase 1: 起動条件チェック (--dry-run / --resume の判定) + ├─ Phase 2: takt run weekly-review.yaml を同期実行 + │ ├─ parallel: + │ │ ├─ review-simplicity-whole (whole-tree, ADR-027 制約解除) + │ │ ├─ review-security-whole (whole-tree, security knowledge) + │ │ └─ review-architecture-whole (新 persona, ADR 整合性) + │ └─ aggregate-weekly (3 reports → findings JSON + markdown) + │ 成功: .claude/weekly-reviews/.md + .claude/weekly-review-pending.json + │ 失敗: .claude/weekly-reviews/.md.failed marker + ├─ Phase 3: pending JSON を読み込み AskUserQuestion で採否一括選択 + │ (採用 / 却下 / 保留 を finding ごとに記録) + └─ Phase 4: 採用 finding を docs/todo.md の「週次レビュー採用 (date)」セクションに追記 + + .claude/weekly-review-last-run.json を更新 + + .claude/weekly-review-pending.json をクリア +``` + +### takt workflow 構成 (3 review facets + 1 aggregate) + +[ADR-020](adr-020-takt-facets-sharing.md) の facets 共通化原則に倣う。本 workflow は 4 facet を 2 step で chain する: + +| facet | 役割 | 派生元 | +|---|---|---| +| `review-simplicity-whole` | whole-tree の simplicity 観点 (重複 / 累積複雑度 / dead code / overspec'd 抽象化) | `review-simplicity.md` から派生 (※後述「アンチパターン」で共通化不可) | +| `review-security-whole` | whole-tree の security 観点 (機密漏出パターン / 入力検証の偏在 / 暗号アルゴリズム) | `review-security.md` から派生 | +| `review-architecture-whole` | ADR 整合性 / モジュール境界 / [ADR-012](adr-012-src-naming-convention.md) 命名規約 / 循環依存 / レイヤ侵犯 | 新規 | +| `aggregate-weekly` | 3 reports → findings JSON + markdown (採否単位の構造化) | `aggregate-feedback.md` を参考 | + +**並列構成**: 3 review facets を `parallel:` block で並列実行し、`aggregate-weekly` で統合する。これは [post-merge-feedback.yaml](../../.takt/workflows/post-merge-feedback.yaml) の構造を流用する (analyze 3 並列 → aggregate)。fix loop は不要 (修正対象がコードではなく findings レポート生成)。 + +### 入力源 + +- **ソースツリー全体**: 主要 dir (`src/`, `scripts/`, `.claude/`, `.takt/`, `docs/`) を各 facet が Glob で順読 +- **ADR コーパス**: `docs/adr/*.md` を architecture facet が参照 (ADR 違反検出のため) +- **CLAUDE.md**: プロジェクト規約の根本 (architecture facet が参照) + +サブツリー分割は MVP では行わない。context 圧迫が観測されてから 2nd PR で facet 内分割を切り出す ([YAGNI](../../CLAUDE.md))。 + +### 出力 + +| ファイル | 用途 | gitignore | +|---|---|---| +| `.claude/weekly-reviews/.md` | レポート本文 (履歴) | ✅ | +| `.claude/weekly-reviews/.md.failed` | 失敗マーカー (内容は失敗理由 + 復旧手順) | ✅ | +| `.claude/weekly-review-pending.json` | finding 配列 + decision フィールド (skill が読み書き) | ✅ | +| `.claude/weekly-review-last-run.json` | SessionStart hook 用タイムスタンプ | ✅ | + +### Findings スキーマ + +```json +{ + "run_date": "2026-04-27", + "report_path": ".claude/weekly-reviews/2026-04-27.md", + "findings": [ + { + "id": "WR-2026-04-27-A03", + "facet": "simplicity | security | architecture", + "severity": "critical | high | medium | low", + "category": "nesting | naming | adr-violation | cyclic-dep | dead-code | ...", + "location": { "path": "src/foo.rs", "line_range": "120-145" }, + "description": "...", + "proposal": "...", + "decision": "pending | adopted | rejected | deferred" + } + ] +} +``` + +`id` は `WR--` 形式。aggregate-weekly facet が一意に採番する。 + +### 採否フロー (pending JSON 経由) + +skill Phase 3 では AskUserQuestion で finding ごとに採否を聞く。`multiSelect: true` で「採用したい finding を選択 → 残りは却下扱い」のフローを基本とする。各 finding は `severity` でグループ化して提示し、critical/high を優先表示する。 + +ユーザー判断: + +- **採用 (adopted)**: docs/todo.md の「週次レビュー採用 (date)」セクションに展開して追記 +- **却下 (rejected)**: pending JSON 内に履歴として残るが、次回以降は出てこない (重複検出キーは `category + location.path` の組合せ) +- **保留 (deferred)**: 次週の `weekly-review` で再提示する (skill が pending JSON を読み込む際に保留分を注入) + +### todo.md 反映ルール + +採用 finding は docs/todo.md の `## 現在進行中` の **新セクション「週次レビュー採用 (YYYY-MM-DD)」** にまとめて追記する。各 finding を以下のテンプレートで展開: + +```markdown +### [finding.description の要約タイトル] + +> **動機**: [finding.description] +> **本タスクの位置づけ**: 週次レビュー [finding.id] で採用 (severity={severity}, facet={facet}) + +#### 背景: [finding.location でのコンテキスト] +#### 設計決定: [finding.proposal] +- [ ] サブタスク (ユーザーが後で詳細化) +#### 完了基準: [proposal の達成条件] +``` + +**重複検出は MVP では実装しない**。skill 側で「todo.md の既存セクション一覧を Read → タイトル一致っぽい場合は警告のみ」程度に留める。 + +却下 / 保留 finding は `.claude/weekly-reviews/.md` 内にのみ履歴として残し、todo.md には書かない (運用ルール「完了タスクを残さない」と整合 — todo.md は作業予定のみ)。 + +### 失敗ポリシー: best-effort + +takt 失敗時の挙動: + +- skill Phase 2 で `.claude/weekly-reviews/.md.failed` marker が残る +- 次セッションの SessionStart hook (L1) が `*.md.failed` を検出 → `additionalContext` で `/weekly-review --resume` を促す +- ユーザーが応答しなければ marker は残り続けるが、**ユーザー学習機会を逸するだけで実害なし** (must-run ではない) + +ADR-030 の `.failed` marker パターンを流用するが、L2 recovery (UserPromptSubmit hook) は実装しない。理由: + +- L1 (SessionStart) で十分 (週次レビューは「次のセッション開始時に思い出せば良い」レベルの粒度) +- UserPromptSubmit hook を増やすと session 起動時のオーバーヘッドが増える + +### トリガー方式と reminder + +- **手動トリガー**: `/weekly-review` skill を明示呼出 +- **reminder**: SessionStart hook が `.claude/weekly-review-last-run.json` の mtime を見て、7 日以上経過していれば `additionalContext` で促す (強制起動はしない) +- **将来の自動化**: 機能安定後に schedule スキル (CronCreate-based) や `/loop 7d /weekly-review` を検討するが、MVP では実装しない (YAGNI、機能の安定性を観測してから判断) + +### ADR-027 (push-time = simplicity 限定) との関係 + +ADR-027 は「architectural review は post-PR に委ねる」と決めたが、ここで言う「post-PR」は CodeRabbit による **PR diff レビュー** を指していた。**cross-PR な architectural review は明示的に空白** だったため、本 ADR がその空白を埋める。 + +ADR-027 の本質的判断 (push 時に重い arch review を走らせない) は維持し、本 ADR は **週次という別リズム** で whole-tree な architectural review を入れる。両者は競合しない。 + +### ADR-022 (責務分離原則) との整合性 + +L2 (takt) と L3 (skill) の副作用範囲は ADR-022 原則 1 の枠内に収まる: + +- **takt facets**: 全て `edit: false`、Read/Glob/Grep のみ → 副作用なし +- **aggregate-weekly facet**: `.claude/weekly-reviews/.md` と pending JSON への書き込み → **新規 artifact への自己記述** +- **skill Phase 4**: docs/todo.md への追記 → **既存 artifact だが意図表現ではない作業ファイルへの追記**、かつユーザー採否承認を経た後の確定 + +docs/todo.md は ADR-022 で言う「意図表現を含む既存 artifact」(commit description / PR title / bookmark 名) には該当せず、作業計画ファイルなのでユーザー承認後の追記は許可される。ただし skill 側で「採用 finding 一覧をユーザーに見せて確認 → 確定後に書き込む」フローを必須とすることで、未承認確定を避ける。 + +### ADR-028 (外部可視成果物ゲート) との関係 + +本 ADR は **内部 artifact のみ生成・更新**: + +- `.claude/weekly-reviews/*` — local 専用、`.gitignore` で除外 +- `.claude/weekly-review-pending.json` — local 専用、`.gitignore` で除外 +- `.claude/weekly-review-last-run.json` — local 専用、`.gitignore` で除外 +- `docs/todo.md` — repo に含まれるが PR でレビュー可能、外部公開 (GitHub PR / tag / commit description) ではない + +GitHub 上に観測可能な成果物 (PR / tag) を直接生成・改変することはないため、ADR-028 の `permissions.ask` ゲートの **対象外**。 + +### ADR-030 パターン継承 + +ADR-030 で確立した「機械的 = Rust / AI 並列 = takt / ask-based = skill or hook」3 層分離パターンの **4 例目** として位置付ける: + +| 例 | L1 (機械的) | L2 (AI 並列) | L3 (ask-based / 補助) | +|---|---|---|---| +| 1 (ADR-015 push) | quality gates (Rust) | pre-push-review (takt) | (なし) | +| 2 (ADR-018 PR monitor) | cli-pr-monitor poll (Rust) | post-pr-review (takt) | (なし) | +| 3 (ADR-030 post-merge) | cli-merge-pipeline (Rust) | post-merge-feedback (takt) | UserPromptSubmit hook (recovery, Rust) | +| **4 (本 ADR)** | **SessionStart hook (reminder, Rust)** | **weekly-review (takt)** | **`/weekly-review` skill (approval & apply)** | + +差分は L3 が実装の中心であること。これは **must-run でない** ことに起因する自然な分布。 + +## 実装タスク + +詳細な実装手順は [`docs/todo.md`](../todo.md) の「週次プロジェクト全体レビューパイプラインの導入」セクション Phase A-F を参照。本 ADR は仕様のみを規定する。 + +- **Phase A**: 本 ADR 起案 (PR 1) — 設計のみ +- **Phase B**: takt workflow + 4 facets + architecture-reviewer persona (PR 2) +- **Phase C**: skill + SessionStart hook 拡張 (PR 3) +- **Phase D**: e2e 検証 (PR 3 マージ後 / PR 4 起案前) +- **Phase E**: 試験運用 dogfood (PR 4 — 1〜2 週運用 + ADR-031 ステータス更新) +- **Phase F**: 自動化検討 (本採用後の任意 — schedule スキル経由の cron 化) + +## アンチパターン + +### `review-simplicity.md` を whole-tree 用と共有してはならない + +ADR-027 が `review-simplicity.md` を **diff 局所** に責務を絞ったのは、コンテキストサイズと判断空間の両面で本質的最適化だった。whole-tree 用 facet (`review-simplicity-whole.md`) はこの制約を解除する別物として **派生コピー** で実装する。共通化すると: + +- diff 用が累積複雑度の判断空間に引きずられて遅くなる (ADR-027 の改善が回帰) +- whole-tree 用が diff 局所制約に縛られて拾えるべき finding を見逃す + +両方とも目的が異なるため separation が正しい。これは [ADR-020](adr-020-takt-facets-sharing.md) の「責務が同じものだけを共通化する」原則の帰結。 + +### whole-tree レビューを must-run にしてはならない + +本 ADR は best-effort で十分という判断をした。これを「PR ごとに必ず走らせる」「マージブロック条件にする」等の must-run 化に拡張すると: + +- レビュー結果の重複処理 (同じ finding が複数 PR で繰り返し提示される) +- 開発速度の低下 (週次のリズムを失う) +- ADR-030 が解決した silent loss 問題が再発する余地が生まれる + +「週次という低頻度・俯瞰的な視点」自体に価値があり、頻度を上げると価値が逆に失われる設計上の知見。 + +### 採否対話を Phase 4 で省略してはならない + +「全部 todo.md に書いてユーザーが後で取捨選択」案は実装が簡単だが、todo.md が **採用していない作業案で膨らむ** ため、運用ルール「完了タスクを残さない」「作業予定のみ記録」と背反する。skill Phase 3 の AskUserQuestion を経由する設計は、todo.md の純度を保つために必須。 + +### Reminder を強制起動 (auto-trigger) にしてはならない + +SessionStart hook が `additionalContext` で促すのみで、skill を勝手に起動してはいけない。理由: + +- ADR-029 / 030 で得た「skill 強制起動は構造的に成立しない」教訓 +- 週次レビューはユーザーが自分のタイミングで実行すべき (must-run でない以上、強制は害) + +## 影響 + +### Positive + +- **レビュー scope の空白が埋まる**: cross-PR ドリフト / ADR 違反蓄積 / 累積複雑度を週次で拾える +- **ADR-030 パターンの一般化**: 「機械的 / takt / ask-based」3 層分離の 4 例目として確立し、今後のパイプライン設計の参照例になる +- **既存 ADR との非競合**: ADR-027 / 030 が空けた空白を埋めるだけで、既存パイプラインの責務には介入しない +- **dogfood しやすい**: 内部 artifact のみで完結し、失敗しても致命的でないため、試験運用がしやすい + +### Negative + +- **新規 takt workflow + 3 facets + 1 persona の保守コスト**: pre-push-review / post-pr-review / post-merge-feedback に続く 4 つ目の workflow となる +- **`review-simplicity.md` と `review-simplicity-whole.md` の派生関係を保守する負担**: ADR-027 改訂時に whole 版も追従する必要 (ただし共通化は不可、上述アンチパターン参照) +- **whole-tree レビューの context window 圧迫リスク**: 初回 dogfood で観測してから対処判断 (Phase E) +- **派生プロジェクトへのバックポート工数**: takt-test-vc 等への展開時は workflow + facets + persona + skill + hook 拡張のセット移植が必要 + +### 将来の展望 + +- **Phase E dogfood 安定後の本採用化**: ステータスを `承認済み` に更新 +- **schedule スキル経由の自動化** (Phase F): 機能安定後に weekly cron 化 +- **派生プロジェクトへのバックポート**: takt-test-vc / techbook-ledger 等 +- **finding 重複検出の自動化**: MVP では未実装、運用で必要性が観測されてから検討 +- **review scope 軸の他の空白埋め**: 例えば「whole-tree × performance」「whole-tree × accessibility」など、軸自体の拡張余地 + +## References + +- [ADR-012: src/ ディレクトリの命名規約](adr-012-src-naming-convention.md) — architecture facet の検証ルールに組み込む +- [ADR-015: Push Pipeline takt 移行](adr-015-push-runner-takt-migration.md) — 「機械的 = Rust、AI = takt」原則の先行事例 (1 例目) +- [ADR-018: cli-pr-monitor takt 移行](adr-018-pr-monitor-takt-migration.md) — 同原則の 2 例目 +- [ADR-019: CodeRabbit レビュー運用のハイブリッド構成](adr-019-coderabbit-review-hybrid-policy.md) — post-pr-review の現行責務範囲を確認する根拠 +- [ADR-020: takt facets 共通化戦略](adr-020-takt-facets-sharing.md) — facets の共通化判断基準 +- [ADR-022: 自動化コンポーネントの責務分離原則](adr-022-automation-responsibility-separation.md) — `edit: false` 方針 / 副作用範囲の根拠 +- [ADR-027: Push-time review を simplicity に限定](adr-027-push-review-simplicity-focus.md) — 本 ADR が補完する空白の特定根拠 +- [ADR-028: 外部可視成果物ゲート](adr-028-pnpm-create-pr-gate.md) — 外部可視成果物との軸別境界 (本 ADR は対象外) +- [ADR-030: 決定論的 Post-Merge Feedback](adr-030-deterministic-post-merge-feedback.md) — 3 例目、本 ADR は 4 例目として 3 層分離パターンを継承 diff --git a/docs/todo.md b/docs/todo.md index 7156ce2..204de48 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -196,6 +196,188 @@ dogfood では PR #74 マージ後、pending file が `dispatched` で stuck し - **現在地**: 上位タスクの Phase F 完了待ち - **詰まっている箇所**: ADR-030 実装 + dogfood 完了に依存 +### 週次プロジェクト全体レビューパイプラインの導入 (ADR-031 起案 + 実装) + +> **動機**: 既存の3つのレビューパイプライン (pre-push-review / post-pr-review / post-merge-feedback) はすべて「**変更差分** に対する」レビューで、プロジェクト全体を俯瞰する視点が欠けている。「PR 単位では見えない cross-PR ドリフト」「ADR 違反の蓄積」「全体俯瞰のアーキテクチャ瑕疵」「無駄の累積」は今のパイプラインでは拾えない。週に1回プロジェクト全体を **simplicity / security / architecture** の3観点でレビューし、改善提案を出す自己改善ループを導入する。コードは編集せず、ユーザー採用分のみ docs/todo.md に追記する。 +> +> **本タスクの位置づけ**: ADR-027 (push-time = simplicity 限定 / architectural review = post-PR) を補完する新 ADR-031 を起案し、週次レビュー基盤 (takt workflow + skill + SessionStart hook reminder) を実装する。試験運用フラグで導入し、1〜2 週の dogfood 観測後に本採用判断。 +> +> **計画ファイル参照**: `~/.claude/plans/1-docs-todo-md-askuserquestion-validated-orbit.md` (本タスク策定時の plan、新セッションでも同じ判断を再現可能) + +#### 背景: 既存レビューの空白 + +| 既存パイプライン | レビュー対象 | 主観点 | 拾えないもの | +|---|---|---|---| +| pre-push-review (ADR-015, ADR-027) | push 前の diff | simplicity (局所) | architectural drift, cross-PR の冗長 | +| post-pr-review (ADR-018, ADR-019) | PR 単位の diff | CodeRabbit 由来の品質 | PR 跨ぎの ADR 違反 | +| post-merge-feedback (ADR-030) | マージ済み PR + transcript | 再発防止 (差分起点) | 全体俯瞰 | + +**空白**: cross-PR な俯瞰観点 (累積複雑度 / ADR 違反蓄積 / 命名一貫性ドリフト / 循環依存)。これを週次の whole-tree レビューで埋める。 + +#### 設計決定: hybrid アーキテクチャ (新 ADR-031) + +ADR-030 で確立した「機械的=Rust / AI parallel=takt / ask-based=skill」3層分離パターンの 4 例目への適用。**must-run 要件ではない** ため決定論ゲートは省略、`.failed` marker による best-effort recovery で十分という判断。 + +``` +/weekly-review (skill, manual トリガー) + │ Phase 1: 7 日チェック + dry-run? 判定 + ├─► takt run weekly-review.yaml # parallel facets + │ ├─ review-simplicity-whole # whole-tree, ADR-027 制約解除 + │ ├─ review-security-whole # whole-tree + │ └─ review-architecture-whole # 新 persona, ADR 整合性 + │ ↓ all complete + │ └─ aggregate-weekly # findings JSON + markdown + │ Phase 2: pending JSON 生成 (.claude/weekly-review-pending.json) + │ Phase 3: AskUserQuestion で採否一括選択 + │ Phase 4: 採用分を docs/todo.md に追記、last-run 更新 + ▼ +.claude/weekly-reviews/.md (履歴、gitignore) +docs/todo.md (採用分のみ追記) + +SessionStart hook (hooks-session-start.exe 拡張) + └─► .claude/weekly-review-last-run.json の mtime 確認 + 7 日経過 → additionalContext で「/weekly-review 推奨」と reminder のみ (強制起動なし) +``` + +- **失敗ポリシー**: best-effort (ADR-030 の `.failed` marker パターンを流用、SessionStart hook が次セッションで再実行を促す) +- **入力源**: ソースツリー全体 (主要 dir: src/, scripts/, .claude/, .takt/, docs/) を各 facet が Glob で順読 +- **出力**: `.claude/weekly-reviews/.md` (履歴) + 採用分のみ docs/todo.md 追記 +- **採否単位**: finding ごと (採用 / 却下 / 保留) の一括選択。pending JSON 経由で UI を skill 側で提供 + +#### ユーザー判断記録 (本タスク策定時に合意済 — 2026-04-27) + +| 質問 | 回答 | +|---|---| +| トリガー方式 | **手動 `/weekly-review` + SessionStart hook reminder** (前回実行から7日経過で promote のみ。強制起動なし)。機能安定後に schedule スキル経由の自動化を将来検討 | +| レビュー対象スコープ | **毎回ソースツリー全体**。サブツリー分割は MVP 不要 (各 facet が Glob で主要 dir 順読)。context 圧迫が観測されたら 2nd PR で facet 内分割 | +| 承認フロー | **レポート提示 → 採否を一括選択**。pending JSON 経由 | +| Architecture facet 実装 | **新 `architecture-reviewer` persona 作成** (既存 simplicity/security と並列、ADR 整合性 + モジュール境界 + ADR-012 命名 + 循環依存) | +| アーキテクチャ形態 | **hybrid (takt workflow + skill)**。ADR-030 の 3 層分離パターン継承 | +| PR 分割 | **PR 1 (ADR) → PR 2 (takt) → PR 3 (skill + hook) → PR 4 (dogfood + 本採用判断)** の 4 段階を推奨 (post-merge-feedback の分割パターンに倣う) | +| 失敗ポリシー | **best-effort** (`.failed` marker + SessionStart hook reminder で再実行誘導。must-run ではないので決定論ゲート不要) | +| アンチパターン | **whole-tree 用 facet を diff 用 facet と共通化しない** (ADR-027 で diff 局所が本質要件のため separation 必須) | + +#### 作業計画 + +##### Phase B: takt workflow + facets + persona (PR 2) + +- [ ] `architecture-reviewer` persona 定義 (allowed_tools: Read/Glob/Grep のみ、knowledge: architecture) + - 既存 persona 定義の場所を調査して同様に追加 (`.takt/personas/` または config 内) +- [ ] [.takt/facets/instructions/review-simplicity-whole.md](.takt/facets/instructions/review-simplicity-whole.md): 既存 `review-simplicity.md` から派生コピー、diff 局所制約を whole-tree 向けに改変 (主要 dir Glob 順読、累積複雑度視点) +- [ ] [.takt/facets/instructions/review-security-whole.md](.takt/facets/instructions/review-security-whole.md): 既存 `review-security.md` から派生、whole-tree 版 +- [ ] [.takt/facets/instructions/review-architecture-whole.md](.takt/facets/instructions/review-architecture-whole.md): 新規。観点は ADR 整合性 / モジュール境界 / ADR-012 命名規約 / 循環依存 / レイヤ侵犯 +- [ ] [.takt/facets/instructions/aggregate-weekly.md](.takt/facets/instructions/aggregate-weekly.md): 既存 `aggregate-feedback.md` を参考に、3 レポートを統合し finding JSON + markdown を出力 +- [ ] [.takt/workflows/weekly-review.yaml](.takt/workflows/weekly-review.yaml): `parallel: [simplicity-whole, security-whole, architecture-whole]` → `aggregate-weekly` の 2 step。`post-merge-feedback.yaml` の構造をテンプレート流用 +- [ ] takt 単体 dry-run 検証: `takt run weekly-review.yaml` で 4 レポートが `.takt/runs/-weekly-review/reports/` に生成されることを確認 +- [ ] PR 作成・マージ + +##### Phase C: skill + SessionStart hook (PR 3) + +- [ ] [.claude/skills/weekly-review/SKILL.md](.claude/skills/weekly-review/SKILL.md) 定義 + - トリガー条件: `/weekly-review` 明示呼出のみ (一般的なレビュー依頼では発動しない) + - 4 Phase: 起動条件チェック → takt 起動 → AskUserQuestion 採否対話 → todo.md 反映 + - フラグ: `--dry-run` (todo.md 触らない) / `--resume` (`.failed` marker 検出時の再開) +- [ ] pending JSON schema 確定: `.claude/weekly-review-pending.json` に finding 配列 + decision フィールド +- [ ] todo.md 反映ロジック実装 (skill 内): 採用 finding を `## 現在進行中` の新セクション「週次レビュー採用 (YYYY-MM-DD)」にまとめて追記。各 finding を「動機 / 位置づけ / 背景 / 設計決定 / サブタスク / 完了基準」フォーマットへマッピング。重複検出は MVP 不要 (skill 側で警告のみ) +- [ ] [src/hooks-session-start/](src/hooks-session-start/) 拡張: `.claude/weekly-review-last-run.json` の mtime チェック + 7 日経過時の reminder 出力 + `*.md.failed` 検出時の recovery context 出力 (ADR-001 = Rust 一択) +- [ ] `.gitignore` 更新: `.claude/weekly-reviews/`, `.claude/weekly-review-pending.json`, `.claude/weekly-review-last-run.json` を除外 +- [ ] `pnpm build:all` + `pnpm deploy:hooks` で hook を派生プロジェクトに配布 +- [ ] PR 作成・マージ + +##### Phase D: e2e 検証 (PR 3 マージ後 / PR 4 起案前) + +- [ ] **dry-run smoke test**: `/weekly-review --dry-run` 実行 → reports 4 本生成確認 → `.claude/weekly-reviews/.dry-run.md` 書出 → todo.md は触られないこと +- [ ] **通常実行 + 採否選択**: `/weekly-review` → pending JSON 生成 → AskUserQuestion で finding 採否 → 採用分が docs/todo.md に追記 → last-run 更新 +- [ ] **SessionStart reminder 検証**: last-run.json mtime を 8 日前に偽装 → 新セッション起動 → additionalContext に reminder 含まれること +- [ ] **失敗時リカバリ**: facet instruction を一時的に壊して takt fail を inject → `.md.failed` marker 残存 → 次セッション SessionStart で recovery context → `/weekly-review --resume` で再開成功 + +##### Phase E: 試験運用 dogfood (PR 4 — Phase D 完了後) + +- [ ] 1〜2 週の試験運用で実際に週次レビューを実行 +- [ ] **観測項目**: + - 3 facets parallel の wall-clock 実行時間 (post-merge-feedback の analyze 並列 7m30s と比較) + - context window 圧迫 (whole-tree が 1 リクエストに収まるか) + - 5 分超 or context 圧迫が観測されたら facet 内サブツリー分割を 2nd PR で切り出す + - finding 品質: 採用率 / 既存 ADR との整合性 / false positive 率 + - SessionStart reminder の発火頻度と無視率 +- [ ] dogfood 結果を ADR-031 に追記 (試験運用 → 本採用 / 改善 / 廃止 の判断材料) +- [ ] 本採用判断: ADR-031 ステータスを「承認済み」に変更 or 廃止判断 + +##### Phase F: 自動化検討 (本採用後の任意) + +- [ ] schedule スキル (CronCreate-based) で weekly cron 登録の検討 + - 注意: ADR-018 で CronCreate は cli-pr-monitor では廃止済み。schedule スキル自体は別機構なので適用可 + - 代替: `/loop 7d /weekly-review` (シンプルだがセッション跨ぎ不可) + - 自動化の前に「reminder で十分か / 強制実行が必要か」を Phase E の観測結果から判断 + +#### 作業可能になるための前提情報 (新セッションで必読) + +##### 既存コンポーネントとの参照関係 + +- **既存 takt workflow テンプレート元**: + - `.takt/workflows/post-merge-feedback.yaml`: parallel + aggregate の 2-step 構造の流用元 ([参照](.takt/workflows/post-merge-feedback.yaml)) +- **既存 facet 派生元**: + - `.takt/facets/instructions/review-simplicity.md`: whole-tree 版を派生 ([参照](.takt/facets/instructions/review-simplicity.md)) + - `.takt/facets/instructions/review-security.md`: 同上 ([参照](.takt/facets/instructions/review-security.md)) + - `.takt/facets/instructions/aggregate-feedback.md`: aggregate-weekly の参考 ([参照](.takt/facets/instructions/aggregate-feedback.md)) +- **既存 hook 拡張先**: + - `src/hooks-session-start/`: SessionStart hook crate (Rust)。reminder ロジックを追加 ([参照](src/hooks-session-start/)) +- **既存 skill 規約**: + - 他 skill (`post-merge-feedback`, `pre-push-review` 等) の SKILL.md フォーマット (frontmatter / トリガー条件 / Phase 構成 / 例外的動作) を踏襲 + +##### 重要な既存 ADR (実装時に必ず参照) + +| ADR | 関係 | +|---|---| +| **ADR-001** | hooks 実装言語 = Rust。SessionStart hook 拡張は Rust 一択 | +| **ADR-012** | src/ 命名規約。architecture-reviewer の観点に組み込む | +| **ADR-022** | 自動化コンポーネントの責務分離。全 facet `edit: false` で整合 | +| **ADR-027** | push-time = simplicity 限定 / architectural review = post-PR。**本タスクの空白特定の根拠** | +| **ADR-030** | deterministic post-merge-feedback。**本タスクの 3 層分離パターン継承元**。must-run でないので決定論ゲートは流用しないが、`.failed` marker パターンは流用 | +| **ADR-020** | takt facets 共通化戦略。本タスクでは「whole-tree 用は別 facet」と判断する根拠 | + +##### memory 参照 + +- `feedback_todo_no_history.md`: todo.md は作業予定のみ。**採用 finding が「現在進行中」に入るのみで完了履歴セクションは作らない原則の根拠** +- `feedback_test_dry_antipattern.md`: テストの DRY 不適用。production code の review-simplicity-whole / -security-whole 派生は OK だが、test では原則的に共通化しない +- `feedback_side_effect_integration.md`: 副作用は新 phase ではなく既存 phase 末尾に統合。skill 内の todo.md 追記処理は新 Phase 作らず Phase 4 末尾に統合 +- `feedback_verify_edit_results.md`: 大きな Edit 後は grep で見出し検証。Phase B の facet ファイル作成時に有用 +- `project_takt_push_runner_learnings.md`: takt 導入の知見 + +##### 設計上の重要な制約 (実装時に必ず守る) + +| 制約 | 根拠 | 影響 | +|---|---|---| +| **コードを直接書き換えない** | 本タスクのコア要件 | 全 facet `edit: false`、skill も Read + Edit on docs/todo.md のみ | +| **採用 finding のみ todo.md へ** | ユーザー採用フロー | 却下/保留は report 内にのみ履歴 | +| **完了履歴セクションを作らない** | feedback_todo_no_history.md | 採用 task 完了時は ADR/仕組みに反映後、todo.md から削除 | +| **whole-tree facet を diff 用と共通化しない** | ADR-027 で diff 局所が本質要件 | review-simplicity-whole.md は派生コピー、共通化しない | +| **must-run 扱いしない** | best-effort 設計 | SessionStart hook は reminder のみ、強制起動しない | +| **schedule 自動化は dogfood 後** | YAGNI | Phase F で観測結果を見てから判断 | + +##### 新セッションで最初に確認すべきこと + +1. `git log --oneline -10` で master の最新状態を確認 +2. `docs/todo.md` の本セクション (本記録) を読む +3. `~/.claude/plans/1-docs-todo-md-askuserquestion-validated-orbit.md` を読む (本タスク策定時の plan) +4. `docs/adr/adr-027-push-review-simplicity-focus.md` を読む (空白特定の根拠) +5. `docs/adr/adr-030-deterministic-post-merge-feedback.md` を読む (3 層分離パターン参照元) +6. `docs/adr/adr-022-automation-responsibility-separation.md` を読む (`edit: false` 方針) +7. `.takt/workflows/post-merge-feedback.yaml` を読む (workflow テンプレート) +8. `.takt/facets/instructions/review-simplicity.md` + `review-security.md` を読む (派生元) +9. **どの Phase を実施するか確認**: Phase A 未完了なら ADR 起案から、Phase A 済なら Phase B (takt) から着手 + +#### 完了基準 + +- Phase A〜E すべて完了 (Phase F は任意、観測後判断) +- ADR-031 の試験運用結果が docs/adr/ に追記され、本採用 / 改善 / 廃止 のいずれかが決定 +- dogfood で 1〜2 週の運用を経て finding が実際に採用 → todo.md → 改善実装 のループが少なくとも 1 周回ること +- 本 todo.md エントリを削除 (運用ルール: 完了タスクは ADR/仕組みに反映後に削除) + +#### 詰まっている箇所 + +なし (全方向確定済、Phase A から着手可能) + --- ## スコープ外だが将来検討