diff --git a/CLAUDE.md b/CLAUDE.md index 037f03e7..ab616404 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,6 +46,7 @@ - [ADR-043: Security/Quality Gate での Fail-Closed 原則](docs/adr/adr-043-security-gates-fail-closed.md) *(試験運用)* - [ADR-044: subprocess utility extraction の境界判定 — 共通化と分離の線引き](docs/adr/adr-044-subprocess-utility-extraction-boundary.md) *(試験運用)* - [ADR-045: jj workspace による並列セッション運用 — メイン作業と細粒度改善の分離](docs/adr/adr-045-jj-workspace-parallel-sessions.md) *(試験運用)* +- [ADR-046: ローカル LLM pre-push レビュアー — 選定スパイクと不採用判断](docs/adr/adr-046-local-llm-review-spike.md) *(却下)* ## Build diff --git a/docs/adr/adr-046-local-llm-review-spike.md b/docs/adr/adr-046-local-llm-review-spike.md new file mode 100644 index 00000000..836c59d8 --- /dev/null +++ b/docs/adr/adr-046-local-llm-review-spike.md @@ -0,0 +1,98 @@ +# ADR-046: ローカル LLM pre-push レビュアー — 選定スパイクと不採用判断 + +> 採番 046 は暫定 (land 時に空き番号で確定 — [ADR-039](adr-039-experimental-feature-standard-pattern.md) 配下 / 順位 135 placeholder policy)。 + +## ステータス + +却下 (2026-07-04、選定スパイクの negative result により local_review stage の実装を見送り) + +> 本 ADR は実装機構を持たず、[ADR-040](adr-040-local-llm-context-size.md) と同様に「実施したスパイクの empirical data + 判断根拠」を permanent record として固定する性格を持つ。CodeRabbit 往復削減を目的にローカル LLM の push 前レビューを挟む提案 (以下「local_review 案」) を、実測に基づき却下する。 + +## コンテキスト + +### スパイクの目的 + +CodeRabbit 無料枠のレートリミット (3 件/時) が運用上の最大ボトルネックであり、push 前にローカル LLM で「CodeRabbit が出す指摘を先取りするレビュー」を挟めば往復を削減できる、という仮説を検証する。判断基準は **CodeRabbit findings に対する再現率**: ローカルモデルが同じ問題を push 前に surface できれば、著者が事前修正でき CodeRabbit 到達時に指摘が減る。 + +受け入れ基準 (事前定義): **再現率 50% 未満なら local_review 案 (実装フェーズ) を中止**する。 + +### 実測環境 + +- GPU: **NVIDIA RTX PRO 5000 Blackwell 48GB VRAM** ([ADR-038](adr-038-local-llm-finding-classification.md) / [ADR-040](adr-040-local-llm-context-size.md) が前提とする RTX 3070 8GB から更新済み。全候補モデルが 100% GPU で稼働し VRAM は制約にならない)。 +- Ollama 0.30.10。 +- 候補モデル (`ollama show` 実測、全 Q4_K_M): + +| モデル | arch | params | context | 種別 | +|---|---|---|---|---| +| qwen3-coder:30b | qwen3moe | 30.5B | 262144 | MoE・コーディング特化 | +| gemma4:31b | gemma4 | 31.3B | 262144 | dense | +| gemma4:26b | gemma4 | 25.8B | 262144 | MoE (active 小) | +| mistral:7b | llama | 7.2B | 32768 | baseline (ADR-038 現行 classifier) | + +### 評価データ (ground truth) + +`check-ci-coderabbit --list-findings` を PR #90〜#242 に走査し、CodeRabbit の**未解決インライン findings** を **67 件 / 33 PR** 取得 (code=41, docs=24, config=2 / Major 35, Minor 30, Critical 2)。各 finding は file / line / severity / 要約を持つ。ツールは未解決スレッドルートのみ返す (`resolved:` 返信済みは除外) ため、これは歴史的 findings の下限。 + +パイロットは 5 PR / 23 findings (#233, #131, #113, #91, #97) を対象とし、diff は jj の squash commit から再構成 (全て num_ctx 32768 に収まるサイズを選定)。評価ハーネス (Node.js) は Ollama `/api/generate` をストリーミング呼び出し (`format:json`, temperature 0.1, num_ctx 32768, num_predict 4096)、「徹底的な senior reviewer」プロンプトで各モデルに diff をレビューさせ、findings を ground truth と照合した。 + +## 決定 + +**local_review 案を却下する** (push 前ローカル LLM レビュー stage を実装しない)。パイロットの再現率が受け入れ基準 50% を大きく下回り、かつ過剰検出が深刻なため。 + +### 実測結果 + +| モデル | 自動recall (行±25、上限甘) | 意味的recall (実力) | 過剰検出率 | latency 中央 | latency 最大 | VRAM | +|---|---|---|---|---|---|---| +| qwen3-coder:30b | 0.35 | 約 13% | 0.87 | 8.3s | 26.5s | 21.8GB | +| gemma4:31b | 0.26 | 約 9% | 0.77 | 23.4s | 26.5s | 20.9GB | +| gemma4:26b | 0.09 | 約 4% | 0.33 | 2.8s | 10.9s | 17.6GB | +| mistral:7b | 0.13 | 約 9% | 0.69 | 32.9s | 41.1s | 8.9GB | + +- **どのモデルも意味的再現率 50% に遠く及ばない** (23 findings に対し union で約 6 件 ≈ 26%、厳密一致では約 3-4 件 ≈ 15%、単一最良モデルで約 13%)。 +- 自動 recall 最良の qwen3-coder (0.35) は、大量に findings を出して GT 行の近くに偶然一致する **spray による水増し** (過剰検出率 0.87)。実力は約 13%。 +- CodeRabbit findings の**約 4 割は docs / 合成 fixture** で、コードレビュープロンプトでは原理的に検出不能。 +- コードファイル内でも、ローカルモデルは CodeRabbit とは**別の (多くは妥当だが異なる) 問題**を指摘する。意味的重複が低い。 +- **過剰検出が深刻** (0.69〜0.87): push 前に挟むと CodeRabbit 指摘を先取りするどころか大量のノイズを足す。目的 (往復削減) に逆行する。 + +### 較正の過程で得た知見 (それ自体が再利用価値のある成果) + +1. **再現率はプロンプトのフレーミングに強く依存する**。既存 lint-screen プロンプト由来の「flag しすぎるな・空が正解」抑制フレーミングでは qwen3-coder / gemma は findings 0 件になる。徹底フレーミングに変えて初めて出す。→ ローカル LLM レビューは prompt calibration に極めて敏感で、単一プロンプトの数字を過度に一般化できない。 +2. **モデル別の固有失敗モード** (本リポの diff 規模で観測): + - qwen3-coder:30b — 大 diff で退行的反復ループ (同一指摘を数十行にコピー) → num_predict 上限で JSON truncation。 + - gemma4:26b — 30KB 超の diff で沈黙 (diff は読むが `{"findings":[]}` を返す)。5 PR 中 4 PR で 0 件。 + - gemma4:31b — 中央 23s と遅い割に recall 低。 + - mistral:7b — 広範レビューで暴走生成 (非ストリーミングだと 300s タイムアウト)、最遅。 +3. **行番号ベースの自動マッチは spray で水増しされる**ため、意味的判定が必須。モデルとレビュアーは同じ問題を別の行にアンカーする。 + +### 妥当性の脅威 (限界) + +- N が小さい (5 PR / 23 findings)。ただし 4 モデル × 5 PR で一貫して 50% に届かず、シグナルは強い。 +- プロンプトは未最適化。ただし失敗モードは「保守的すぎ」ではなく「CodeRabbit と別の問題を指摘」= 能力/整合の gap で、prompt tuning で 50% まで届く見込みは薄い。 +- ground truth が未解決スレッドのみで母集団が偏る可能性。 + +## 帰結 + +### 却下による影響 + +- push 前 local_review stage は実装しない (`push-runner-config.toml` への `[local_review]` 追加、cli-push-runner への stage 追加は行わない)。 +- CodeRabbit 往復削減は別アプローチ (レビュー対象の絞り込み = `.coderabbit.yaml` 設定、fix の push 束ね等) で追求する。 + +### 保持する価値 + +- **ground truth harvest の手法は再利用可能**: `check-ci-coderabbit --list-findings` を PR レンジに走査 → file/line/severity/要約付き findings を集約する評価データ生成法は、[ADR-038](adr-038-local-llm-finding-classification.md) 系の classifier eval や将来の LLM 機能評価に転用できる。 +- **GPU 更新の事実**: [ADR-040](adr-040-local-llm-context-size.md) の実測値 (RTX 3070 8GB 前提) は陳腐化した。VRAM ではなく latency が実効制約になった。ADR-040 の再 calibration を follow-up とする (順位 255)。 +- **独立レビュアーとしての別価値**: ローカル LLM は CodeRabbit と重複しない別の妥当な問題も出す。ただし過剰検出 (0.69〜0.87) に埋もれるため、「CodeRabbit 先取り」とは異なる premise であり、本 ADR の scope 外。必要なら別途評価する。 + +### classifier (ADR-038) との違い + +本スパイクが却下したのは **review (open-ended な問題発見)** タスクであり、ADR-038 が採用している **classification (既知 findings の triage)** や lint-screen (狭い正規ルールの検出) は別タスク。分類は入力が構造化され判定空間が閉じているためローカル LLM が機能する。本結論は分類層の採用判断に影響しない。 + +## 関連 ADR + +- ADR-038: ローカル LLM による CodeRabbit findings classification — 分類層 (本 ADR が却下した review 層とは別タスク、採用継続) +- ADR-039: Experimental feature 標準パターン — 本 ADR の判断形式 (bounded lifetime = スパイクで採否決定) の基盤 +- ADR-040: Local LLM Context Size と Resource Trade-off — 本スパイクで GPU 更新により実測値が陳腐化、再 calibration の follow-up (順位 255) + +## 由来 + +- 2026-07-04 のハーネス改善計画で定義されたローカル LLM レビュアー選定スパイクを実施。CodeRabbit 往復削減の仮説を、過去 PR の CodeRabbit findings を ground truth とした実測で検証し、再現率が受け入れ基準を満たさないため local_review 案を却下した。 diff --git a/docs/harness-improvement-plan.md b/docs/harness-improvement-plan.md index bad72fba..4babdbf2 100644 --- a/docs/harness-improvement-plan.md +++ b/docs/harness-improvement-plan.md @@ -60,8 +60,8 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基 | WP | セクション | タスク | 工数 | 依存 | 状態 | |---|---|---|---|---|---| -| WP-01 | 1-A | ローカル LLM レビュアー選定スパイク | S-M | なし | 未着手 | -| WP-02 | 1-A | `local_review` stage 実装 | M | WP-01 | 未着手 | +| WP-01 | 1-A | ローカル LLM レビュアー選定スパイク | S-M | なし | 見送り (ADR-046: 意味的再現率 ~13% ≪ 50%、GPU 再calibration → 順位 255) | +| WP-02 | 1-A | `local_review` stage 実装 | M | WP-01 | 見送り (WP-01 前提不成立、ADR-046 で却下) | | WP-03 | 1-A | CodeRabbit クォータ設計(`.coderabbit.yaml` 新設) | S | なし | 実装済(ADR-019 amendment、dogfood 観測待ち: rate 解除待ち < 1 回/日) | | WP-04 | 1-A | classifier モデル格上げ(7b → 27b 級) | XS-S | WP-01 | 未着手 | | WP-05 | 1-A | Stop hook 高速化(nextest + 変更 crate 限定) | M | なし | 未着手 | @@ -93,6 +93,8 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基 ### WP-01: ローカル LLM レビュアー選定スパイク +> **見送り (2026-07-04、[ADR-046](adr/adr-046-local-llm-review-spike.md) で却下)**: 実施済み。PR #90〜242 から CodeRabbit findings 67 件/33 PR を harvest し、5 PR/23 findings のパイロットで 4 モデル (qwen3-coder:30b / gemma4:31b / gemma4:26b / mistral:7b) を実測。意味的再現率は最良でも約 13%(union で約 26%)で受け入れ基準 50% を大きく下回り、かつ過剰検出が深刻 (0.69〜0.87)。結論・比較表・較正知見・モデル別失敗モードは ADR-046 に移管。副次 follow-up (GPU 更新による ADR-040 再 calibration) は順位 255。以下の当初ステップは記録用。 + - **目的**: CodeRabbit 往復(最大ボトルネック)をローカル LLM の事前レビューで削減できるか、モデル選定と実測で判断する。 - **ステップ**: 1. **候補モデルは着手時に必ず ollama.com/library で最新状況を確認して差し替える**(以下は 2026-07-04 時点のスナップショット。LLM の世代交代は速く、本リストの鮮度は保証されない)。現時点の候補 3 つ: `qwen3-coder:30b`(MoE 30B-A3B、Q4 で 19GB。active 3B のため推論が数倍速い、コーディング特化)/ `gemma4:31b`(dense、20GB、256K context。品質枠)/ `gemma4:26b`(MoE active 4B、18GB。速度枠)。 @@ -105,6 +107,8 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基 ### WP-02: `local_review` stage 実装 +> **見送り (2026-07-04、[ADR-046](adr/adr-046-local-llm-review-spike.md) で却下)**: 前提 (WP-01 スパイクで再現率 50% 以上) が不成立のため実装しない。push 前 local_review stage の追加 (`push-runner-config.toml` の `[local_review]` / cli-push-runner stage) は行わない。CodeRabbit 往復削減は WP-03(`.coderabbit.yaml` によるレビュー対象絞り込み)等の別経路で追求する。 + - **目的**: push 前にローカル LLM レビューを挟み、CodeRabbit 到達時点で指摘が出尽くしている状態を作る。 - **ステップ**: 1. `push-runner-config.toml`(ルートと `templates/` の両方)に `[local_review]` セクション追加。`enabled = false` デフォルト(ADR-039 標準パターン: config opt-in + kill-switch + bounded lifetime)。 diff --git a/docs/todo-summary.md b/docs/todo-summary.md index 5cf40682..17541fac 100644 --- a/docs/todo-summary.md +++ b/docs/todo-summary.md @@ -120,6 +120,7 @@ | 252 | 💎 Tier 3 | **ADR-NNN (採番未確定、land 時に確定): 部分効果 env var anti-pattern の文書化 (PR #239 post-merge-feedback T3-1 採用)** | todo13.md | S | なし (`GH_REPO` が gh pr 系に効き引数なし `gh repo view` に効かない partial coverage が PR #238 で「マージ成功 / feedback silent 消失」を招いた実例を原則化。gh-repo-env-guard preset = 機械層 (PR #239 実装済) に対する文書層の 2 層防御、同型ショートカット提案 (`GH_HOST` 等) への review guard、順位 135 placeholder policy 適用、CLAUDE.md はリンクのみ = ADR-022 方針) | | 253 | 💎 Tier 3 | **ADR-030 に PR #239 の feedback silent skip 実装記録を追記 (PR #239 post-merge-feedback T3-2 採用)** | todo13.md | XS | なし (owner_repo 検出失敗 → marker 未書込 → L2 recovery 未発動の silent skip シナリオ (PR #238 実観測) と `AiStepContext::SkipWithMarker` による対処を ADR-030 に実装記録として残す。Severity Low = 既修正、次回 ADR-030 参照 PR への同乗で消化可) | | 254 | 🔧 Tier 2 | **pr_size_check の base を remote tracking ref に変更 — 並列 workspace のローカル master 遅延による誤計測解消 (順位242 push で実観測)** | todo13.md | XS-S | なし (`[pr_size_check] default_branch = "master"` がローカル bookmark 基準の revset `master..@` を使うため、ADR-045 並列 workspace でローカル master が遅延すると merge 済み PR 分を合算して誤計測。順位 242 push で実 diff ~160 行が 1604 行と誤 block された実害、PR #239/#240 でも warning を静かに誤超過。ADR-013 の「remote tracking ref を使う」原則 (sync_local で test 固定済) を pr_size_check にも適用、`[file_length_gate] base` も同点検、順位 250 と相補) | +| 255 | 💎 Tier 3 | **ADR-040 の実測値を新 GPU (RTX PRO 5000 48GB) で再 calibration (ADR-046 WP-01 スパイクで陳腐化を観測)** | todo13.md | S | なし (ADR-038/040 が前提とする RTX 3070 8GB は RTX PRO 5000 Blackwell 48GB に更新済み。27-31B Q4 モデルが 100% GPU で動き VRAM が制約でなくなったため、ADR-040 の VRAM/latency trade-off 表と「VRAM scarcity → model swap 制約」framing が陳腐化。ADR-046 で mistral:7b / gemma4 / qwen3-coder の VRAM・latency を実測済 → ADR-040 amendment に反映、num_ctx 選定 flow の memory 軸を latency 軸へ再重み付け) | **戦略**: Tier 1 を 2〜3 セッションで片付け → Tier 2 で ADR-032 の前提 + rate-limit + convergence cost 削減を進める → Tier 3 で ADR-032 を land + ドキュメント整備。Tier 4-5 は cleanup / 外部展開で daily efficiency への直接効果は小さい。 diff --git a/docs/todo13.md b/docs/todo13.md index 3df0848a..491a5566 100644 --- a/docs/todo13.md +++ b/docs/todo13.md @@ -696,6 +696,31 @@ --- +### ADR-040 の実測値を新 GPU (RTX PRO 5000 48GB) で再 calibration (ADR-046 WP-01 スパイクで陳腐化を観測) + +> **動機**: ADR-038 / ADR-040 は Local LLM の実行環境を **RTX 3070 8GB** として実測値を固定しているが、実機は **NVIDIA RTX PRO 5000 Blackwell 48GB** に更新済み (2026-07-04 に `nvidia-smi` で確認)。この結果、(1) ADR-040 の VRAM/latency trade-off 表 (例: mistral:7b ~2GB at 32K ctx) と (2)「VRAM scarcity → 同時起動不可 / model swap 制約 / KV cache budgeting」という framing が陳腐化した。27-31B Q4 モデルが 100% GPU で動き (qwen3-coder:30b ~21.8GB / gemma4:31b ~20.9GB / gemma4:26b ~17.6GB at num_ctx 32768)、VRAM ではなく latency が実効制約になった。 +> +> **参照**: ADR-040 (Local LLM Context Size、実測値元)、ADR-046 (WP-01 スパイク、4 モデルの VRAM・latency 実測を保持)、ADR-038 (現行 classifier、RTX 3070 前提の記述)、memory `gpu-upgrade-rtx-pro-5000`。 +> +> **実行優先度**: 💎 Tier 3 — Effort S。実装変更を伴わず ADR amendment 中心。分類層 (ADR-038) の運用に直接の不具合はないが、num_ctx 再選定や派生プロジェクト porting 時に誤った RTX 3070 前提を引き継ぐリスクを解消する。 + +#### 作業計画 + +- [ ] ADR-040 に amendment: RTX 3070 8GB の実測表は「旧環境 (historical)」と明示し、新 GPU での再測定値 (ADR-046 の VRAM 実測 + 代表 diff の latency) を追記 +- [ ] 「Context 選定の判断 flow」の memory 軸 (同時起動可否 / swap) を latency 軸へ再重み付け +- [ ] ADR-038 の RTX 3070 前提記述 (§コンテキスト / §帰結の VRAM 8GB 制約) に更新環境への参照を付す +- [ ] 本 entry 削除 + todo-summary.md 行削除 + +#### 完了基準 + +- ADR-040 を読んだ実装者が、現行 GPU では VRAM が制約でなく latency が実効制約であることを把握でき、RTX 3070 8GB の数値を現行前提と誤認しないこと。 + +#### 詰まっている箇所 + +- なし (GPU 更新の事実・ADR-046 の実測値あり)。 + +--- + ## 既知課題 (記録のみ、本セッションで未対応) (現時点で本ファイルへの既知課題は無し。docs/todo10.md / todo9.md 末尾を参照。)