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
31 changes: 31 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
#
# CodeRabbit configuration — WP-03 CodeRabbit クォータ設計 (ADR-019 amendment)
#
# 目的: 無料枠レートリミット (3〜4 レビュー/時) の解除待ちを構造的に削減する。
# 方針 (balanced): 初回 PR は自動レビューを維持し、fix push での自動増分レビューだけを
# 抑止する。修正を 1 push に束ねた後、監視 (cli-pr-monitor) が `@coderabbitai review` を
# 1 回だけ明示投稿して再レビューを発火する
# (pr-monitor-config.toml [fix] trigger_review_after_push = true と結合)。
#
# 注意: .coderabbit.yaml はダッシュボード設定を上書きし、未指定キーは CodeRabbit の
# 既定値になる。language を明示しないと既定 en-US に戻るため ja-JP を固定する。

language: "ja-JP"

reviews:
auto_review:
# 初回 PR (open) は自動レビュー。false にすると初回も手動トリガーが必要になる。
enabled: true
# draft PR は自動レビュー対象外 (既定 false だが意図を明示)。
drafts: false
# fix push ごとの自動再レビューを抑止 (レート消費の主因)。
# 再レビューは修正束ね後の明示 `@coderabbitai review` で 1 回だけ発火する。
auto_incremental_review: false
# レビュー済みコミットが N を超えたら自動レビューを一時停止する暴走ガード。
auto_pause_after_reviewed_commits: 5
# WIP タイトルの PR は自動レビュー対象外 (手動 WIP push でのレート消費を防ぐ)。
ignore_title_keywords:
- "WIP"
- "wip"
- "[skip review]"
38 changes: 38 additions & 0 deletions docs/adr/adr-019-coderabbit-review-hybrid-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,44 @@ ADR-019 の 3 レイヤー構成は外部 AI の種類に依存しない形で
- レビュー空振りを検出したら「そもそも push しない」「手動で claude -p review に切り替える」 (interactive 判断)
- ロックインが問題化した時点で plugin 可換設計の具体実装に着手 (本 ADR の方針に従う)

### WP-03 (2026-07-04 追記): CodeRabbit クォータ設計 — レビュー消費削減による rate-limit 緩和

#### 運用実態の変化 (M5 不採用の前提が崩れた)

2026-04-19 の「M5 (rate limit 耐性作り込み) を不採用」判断は「1h 3 回制限は日常運用でまず引っかからない」を前提としていた。しかしその後、監視 (cli-pr-monitor) の auto-push + takt fix loop 自動化が進み、**fix push ごとの自動増分レビューでレビュー消費が増加**、解除待ち (3〜4 回/時上限に対し体感で毎日頻発、1 回あたり 20〜40 分) が運用上の最大ボトルネックになった (2026-07-04 ユーザー確認)。本リポジトリは public だが、CodeRabbit の public 特典 (無償レビュー) は本アカウントの rate-limit を撤廃しておらず、無料枠の時間あたり上限が実際に効いている。

#### M5 不採用との整合 (耐性ではなく消費削減)

WP-03 は 2026-04-19 で却下した「rate-limit 耐性 (超過後の auto-retry / 失敗時 fallback)」= CodeRabbit 固有挙動への依存を深めるロックインの温床、とは**別のアプローチ**を採る:

- **却下したもの (耐性)**: 上限に当たった後に自動リトライ・迂回する機構。CodeRabbit 固有挙動依存を深める。
- **WP-03 (消費削減)**: そもそも消費するレビュー回数を減らす。標準の `.coderabbit.yaml` 設定 + 運用調整であり、可換性を損なわない (別ツール移行時は当該 config を捨てるだけ)。

#### 決定 (balanced 構成)

1. **`.coderabbit.yaml` 新設** (リポジトリルート)。初回 PR は自動レビューを維持しつつ、fix push ごとの自動増分レビューを抑止する:
- `reviews.auto_review.enabled = true` (初回 PR open は自動レビュー)
- `reviews.auto_review.drafts = false` (draft は対象外、既定だが明示)
- `reviews.auto_review.auto_incremental_review = false` (**消費の主因である push 毎の自動再レビューを停止**)
- `reviews.auto_review.auto_pause_after_reviewed_commits = 5` (暴走ガード)
- `language = "ja-JP"` (`.coderabbit.yaml` はダッシュボード設定を上書きし未指定キーは既定 en-US に戻るため、日本語レビューを固定)
2. **明示再レビュートリガー (決定論層、監視側)**: `auto_incremental_review = false` は fix push 後の自動再レビューを止めるため、監視の auto-push 成功後に `@coderabbitai review` を 1 回だけ明示投稿して再レビューを発火する。`pr-monitor-config.toml [fix] trigger_review_after_push = true` で opt-in し、`src/cli-pr-monitor/src/stages/review_trigger.rs` が担う。この経路は**助言層 = fail-open** (state 不在 / PR 番号未確定 / gh 投稿失敗は log を残して続行。ADR-043 の fail-closed はゲート層にのみ適用)。
3. **運用 (1 push 束ね)**: fix step は全 finding を 1 iteration で修正 → 検証 → auto-push 1 回、が既存の挙動 (fix.md facet は変更不要)。トリガーが監視側に入ったことで「fix 束ね 1 回 = 明示レビュー 1 回」に確定する。

#### 消費モデルの変化

- **従来**: 初回レビュー 1 + fix push ごとの自動増分レビュー N = `1 + N` 回。
- **WP-03**: 初回レビュー 1 + fix 束ねごとの明示レビュー 1 = `1 + (iteration 数)` 回。push 毎ではなく「レビューしてほしい確定タイミング」のみ消費し、中間 push (rebase / cleanup 等) が誤ってレビューを消費しない。

#### 既知の制約

- **手動 fix push は手動トリガーが必要**: 明示トリガーは監視の auto-push 経路 (`auto_push_severity` = critical/major) のみ。ユーザー手動 push (severity=none / minor) 後は `@coderabbitai review` を手動投稿する (fail-open のログが誘導する)。
- **設定の二重管理**: `.coderabbit.yaml` の `auto_incremental_review` と `pr-monitor-config.toml` の `trigger_review_after_push` は必ず揃える (前者 false ⇔ 後者 true)。揃わないと再レビュー欠落 (両 off) or 二重レビュー (両誤設定) になる。派生プロジェクトの template では default false + コメント例で明示。

#### 受け入れ基準 (dogfood)

rate 解除待ちの発生が 1 回/日未満になること。導入後の実績で確認する。未達なら `auto_pause` 値 / トリガー条件を調整、または `enabled = false` (フル手動トリガー) への切替を再検討する。

## 影響

### 採用される構成要素
Expand Down
4 changes: 3 additions & 1 deletion docs/harness-improvement-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基
|---|---|---|---|---|---|
| WP-01 | 1-A | ローカル LLM レビュアー選定スパイク | S-M | なし | 未着手 |
| WP-02 | 1-A | `local_review` stage 実装 | M | WP-01 | 未着手 |
| WP-03 | 1-A | CodeRabbit クォータ設計(`.coderabbit.yaml` 新設) | S | なし | 未着手 |
| 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 | なし | 未着手 |
| WP-06 | 1-B | 反証(refute)facet 追加 | S-M | なし | 未着手 |
Expand Down Expand Up @@ -114,6 +114,8 @@ Anthropic 公式のハーネスエンジニアリング指針(決定論的基

### WP-03: CodeRabbit クォータ設計

> **実装済 (2026-07-04、[ADR-019](adr/adr-019-coderabbit-review-hybrid-policy.md) amendment)**: 要確認 (step 1) の結果、public 特典は本アカウントの rate-limit を撤廃しておらず 3〜4 回/時上限が実際に効いている (ユーザー確認)。balanced 構成を採用: `.coderabbit.yaml` 新設 (`enabled=true` / `drafts=false` / `auto_incremental_review=false` / `auto_pause_after_reviewed_commits=5` / `language=ja-JP`) + 監視の auto-push 成功後に `@coderabbitai review` を明示投稿 (`pr-monitor-config.toml [fix] trigger_review_after_push`、`review_trigger.rs`、fail-open)。設計根拠・消費モデル・既知制約・dogfood 受け入れ基準は ADR-019 amendment に移管。dogfood で「rate 解除待ち < 1 回/日」を確認したら `完了`。以下は当初ステップ (記録用)。

- **目的**: レートリミット解除待ち(約 3 回/日 × 20〜40 分)を構造的に削減する。
- **ステップ**:
1. **要確認(着手時に必ず最新の公式 docs を参照)**: CodeRabbit は public/OSS リポジトリ向けに Pro 機能の無償提供を行っている場合がある。適用されればレートリミット自体が緩和される可能性があるため、設定変更の前にまず確認する。
Expand Down
7 changes: 7 additions & 0 deletions pr-monitor-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ extra_args = ["--pipeline", "--skip-git"]
auto_push_severity = "critical"
push_command = "jj git push"

# auto-push 成功後に `@coderabbitai review` を明示投稿して再レビューを 1 回発火する
# (WP-03 / ADR-019 amendment)。.coderabbit.yaml の
# reviews.auto_review.auto_incremental_review = false と結合する。増分レビューを抑止
# すると fix push だけでは CodeRabbit が再レビューしないため、監視側から明示トリガーする。
# auto_incremental_review が有効な環境で true にすると二重レビューになる (両者を揃える)。
trigger_review_after_push = true

# auto-push 前の品質 gate (PR #224 gate-bypass 対策 B1、fail-closed = ADR-043)。
# push-runner-config.toml の [[quality_gate.groups]] name=group を push 前に実行し、
# FAIL なら push せず action_required に倒す。fix diff が docs-only
Expand Down
19 changes: 19 additions & 0 deletions src/cli-pr-monitor/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ pub(crate) struct FixConfig {
pub(crate) sweep: SweepConfig,
#[serde(default)]
pub(crate) gate: crate::stages::gate::GateConfig,
/// auto-push 成功後に `@coderabbitai review` を投稿して再レビューを明示発火するか。
///
/// `.coderabbit.yaml` の `reviews.auto_review.auto_incremental_review = false`
/// と結合する (WP-03 / ADR-019 amendment)。増分レビュー抑止時は push だけでは
/// CodeRabbit が再レビューしないため、監視側から明示トリガーする必要がある。
/// デフォルト false (opt-in): auto_incremental_review が有効な環境で有効化すると
/// 二重レビューになるため、`.coderabbit.yaml` 側と揃えて明示的に true にする。
#[serde(default)]
pub(crate) trigger_review_after_push: bool,
}

fn default_auto_push_severity() -> String {
Expand All @@ -93,6 +102,7 @@ impl Default for FixConfig {
push_command: default_push_command(),
sweep: SweepConfig::default(),
gate: crate::stages::gate::GateConfig::default(),
trigger_review_after_push: false,
}
}
}
Expand Down Expand Up @@ -436,6 +446,10 @@ task = "t"
"gate はデフォルト有効 (fail-closed、ADR-043)"
);
assert_eq!(config.fix.gate.group, "rust-lint-test");
assert!(
!config.fix.trigger_review_after_push,
"trigger_review_after_push はデフォルト無効 (opt-in、.coderabbit.yaml と結合)"
);
}

#[test]
Expand All @@ -460,10 +474,15 @@ group = "custom-group"
[fix]
auto_push_severity = "major"
push_command = "git push"
trigger_review_after_push = true
"#;
let config: Config = toml::from_str(toml_str).unwrap();
assert_eq!(config.fix.auto_push_severity, "major");
assert_eq!(config.fix.push_command, "git push");
assert!(
config.fix.trigger_review_after_push,
"trigger_review_after_push = true が parse されること"
);
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions src/cli-pr-monitor/src/stages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) mod poll;
pub(crate) mod push;
pub(crate) mod push_jj_bookmark;
pub(crate) mod repush;
pub(crate) mod review_trigger;
pub(crate) mod takt;

pub(crate) use create_pr::run_create_pr;
Expand Down
10 changes: 9 additions & 1 deletion src/cli-pr-monitor/src/stages/repush.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,19 @@ fn run_auto_push(config: &crate::config::FixConfig, pr_label: &str, pre_cid: Opt
"[action] auto_push: {} の takt 修正を自動 re-push",
pr_label
));
if run_push(config) {
let push_ok = run_push(config);
if push_ok {
log_info("[action] auto_push: 成功");
} else {
log_info("[action] auto_push: 失敗 (手動対応が必要)");
}

if crate::stages::review_trigger::should_trigger_review_after_push(
push_ok,
config.trigger_review_after_push,
) {
crate::stages::review_trigger::trigger_coderabbit_review();
}
}

/// gate FAIL を state に反映する (`action_required`)。
Expand Down
67 changes: 67 additions & 0 deletions src/cli-pr-monitor/src/stages/review_trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! auto-push 後の CodeRabbit 再レビュー明示トリガー (WP-03 / ADR-019 amendment)。
//!
//! `.coderabbit.yaml` の `reviews.auto_review.auto_incremental_review = false` と結合する。
//! 増分レビューを抑止すると fix push だけでは CodeRabbit が再レビューしないため、
//! 監視側 (`repush.rs` の auto-push 成功後) から `@coderabbitai review` を明示投稿して
//! 再レビューを 1 回だけ発火する。レート消費を「fix 1 束ねあたり 1 レビュー」に抑える。

use crate::log::log_info;

/// auto-push 後に `@coderabbitai review` を明示投稿すべきかの純粋判定。
///
/// push が成功し、かつ `trigger_review_after_push` が有効なときのみ true。
/// push 失敗時はレビュー対象の変更が remote に反映されていないため投稿しない。
/// flag が false のときは `.coderabbit.yaml` の auto_incremental_review が有効な前提で、
/// 明示投稿すると二重レビューになるため投稿しない。
pub(crate) fn should_trigger_review_after_push(push_ok: bool, flag: bool) -> bool {
push_ok && flag
}

/// `@coderabbitai review` を投稿して CodeRabbit の再レビューを明示発火する。
///
/// PR 番号は state から解決する。state 不在 / PR 番号未確定 / gh 投稿失敗は
/// いずれも log を残して続行する (再レビュー起動は助言層 = fail-open。
/// ADR-043 の fail-closed はゲート層にのみ適用され、本経路は該当しない)。
pub(crate) fn trigger_coderabbit_review() {
use crate::state::{read_state_from, state_file_path};

let Some(pr) = read_state_from(&state_file_path()).and_then(|s| s.pr) else {
log_info(
"[review_trigger] PR 番号が state から解決できず @coderabbitai review をスキップ (必要なら手動投稿してください)",
);
return;
};
let pr_str = pr.to_string();
if crate::runner::run_gh_quiet(&["pr", "comment", &pr_str, "--body", "@coderabbitai review"])
.is_none()
{
log_info(&format!(
"[review_trigger] @coderabbitai review 投稿失敗 (PR #{})。必要なら手動投稿してください",
pr
));
return;
}
log_info(&format!(
"[review_trigger] @coderabbitai review を投稿 (PR #{}, auto_incremental_review=false 経路)",
pr
));
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn should_trigger_review_only_when_push_ok_and_flag_enabled() {
assert!(should_trigger_review_after_push(true, true));
assert!(
!should_trigger_review_after_push(false, true),
"push 失敗時は変更が remote に無いので再レビューを発火しない"
);
assert!(
!should_trigger_review_after_push(true, false),
"flag off なら auto_incremental_review 有効 (二重レビュー防止)"
);
assert!(!should_trigger_review_after_push(false, false));
}
}
8 changes: 8 additions & 0 deletions templates/pr-monitor-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ check_coderabbit = true
# task = "post-pr-review"
# extra_args = ["--pipeline", "--skip-git"]

# auto-push 成功後に `@coderabbitai review` を明示投稿して再レビューを 1 回発火する
# (WP-03 / ADR-019 amendment)。default は false。有効化するのは、この派生プロジェクトにも
# .coderabbit.yaml (reviews.auto_review.auto_incremental_review = false) を置いて
# 増分レビューを抑止する場合のみ。auto_incremental_review が有効なまま true にすると
# 二重レビューになるため、必ず .coderabbit.yaml 側と揃えること。
# [fix]
# trigger_review_after_push = true

# auto-push 前の品質 gate (fail-closed = ADR-043)。default は enabled = true で、
# push-runner-config.toml の [[quality_gate.groups]] name="rust-lint-test" を push 前に実行する。
# Rust workspace を持たない派生プロジェクトでは group が見つからず fail-closed で
Expand Down