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
27 changes: 27 additions & 0 deletions .claude/hooks-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,33 @@ cmd = "pnpm test:e2e"
name = "build"
cmd = "pnpm build"

# 順位 147 / PR-W5 (file-length-enforcement-plan.md): file-length Stop gate。
# PR 範囲 (base branch..@) の .rs file が 800 行超なら Stop を block する強制層。
# cmd は cmd.exe (`cmd /c`) 経由で実行されるため forward-slash (`./`) 始まりは不可。
# backslash 相対パスを TOML literal string (single quote、escape 不要) で指定する。
# gate の有効化は下記 [file_length_gate] enabled で制御 (この step があっても
# enabled = false なら exe は即 exit 0 で no-op)。
[[stop_quality.steps]]
name = "file-length"
cmd = '.\.claude\hooks-post-tool-comment-lint-rust.exe --check-modified-files'

# ─── PR-W5: file-length Stop gate 設定 (ADR-039 experimental feature 標準パターン) ───
#
# hooks-post-tool-comment-lint-rust.exe --check-modified-files が参照する opt-in gate。
# 上の [[stop_quality.steps]] "file-length" step から起動される。
#
# ADR-039 3 点セット:
# - Config opt-in (default OFF): code default は enabled = false (unwrap_or(false))。
# 本 repo は Phase 1 (PR-W1〜W4) の clean state を dogfood するため enabled = true。
# - Kill-switch: 恒久停止は enabled = false。緊急バイパスは env
# FILE_LENGTH_CHECK_OVERRIDE=1 (truthy 値、順位 151 pr_size_check と同 pattern)。
# - Bounded lifetime: 採否判定は file-length-enforcement-plan.md 削除条件 3
# (override 未使用で 1-2 セッション通過) を trigger とする。
#
# base: PR 範囲算出の base branch (省略時 "master"、ADR-021 § Revset Composability で引数化)。
[file_length_gate]
enabled = true

# ─── Push Pipeline: push-runner-config.toml に移行済み (ADR-015) ───
#
# pnpm push は cli-push-runner.exe (takt ベース) を使用。
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 41 additions & 3 deletions docs/file-length-enforcement-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,10 @@ Agent 委譲。ADR-018 (cli-pr-monitor の takt 移行) を参照させる必要

### PR-W5: Stop hook gate (C) 追加

- **status**: not started
- **status**: 実装完了 (dogfood pass、PR 未作成) @5cfcfb5a
- **owner**: -
- **effort**: S
- **依存**: PR-W1 + W2 + W3 + W4 が **全て land 済** (clean state 必須、未 land 状態で C を入れると Stop が常に block)
- **依存**: PR-W1 + W2 + W3 + W4 が **全て land 済** (clean state 必須、未 land 状態で C を入れると Stop が常に block) — 4 件とも land 済 (#220/#224/#230/#231)

#### スコープ

Expand Down Expand Up @@ -406,6 +406,44 @@ Stop hook quality_gate に file_length check を追加。Phase 1 完了後の cl
- ADR-039 § 4 self-review checklist (config schema / default OFF / docs / kill-switch test の 4 点) を満たす
- dogfood: 意図的に 800 行超 file を作って block されることを確認 + override で通過することを確認

#### 実績 (実装完了、PR 未作成)

実装構成:

| 対象 | 内容 |
|---|---|
| `src/hooks-post-tool-comment-lint-rust/src/modified_files_check.rs` (新規、~345 行) | `--check-modified-files` batch mode 本体 + 17 tests |
| `src/hooks-post-tool-comment-lint-rust/src/main.rs` | dispatch 追加 (`--metrics` の隣) + `mod modified_files_check` |
| `src/hooks-post-tool-comment-lint-rust/Cargo.toml` | `toml = "0.8"` 依存追加 (config parse 用) |
| `.claude/hooks-config.toml` | `[[stop_quality.steps]]` "file-length" step + `[file_length_gate] enabled = true` section |

設計上の判断:

- **jj 変更検出**: `jj diff -r '<base>..@' --name-only` で PR 範囲 (working copy 含む) の `.rs` を取得。`base` は config 引数化 (default `master`、ADR-021 § Revset Composability — custom lint `NO_HARDCODED_JJ_REVSET_RANGE` の指摘に対応)
- **cmd path**: `[[stop_quality.steps]]` は `cmd /c` 経由で実行されるため forward-slash (`./`) 始まりは cmd.exe で `'.' is not recognized` エラー。backslash 相対パス (`.\.claude\...exe`) を TOML literal string で指定 (実測で判明)
- **fail-closed (ADR-043)**: jj 失敗時は判定不能として exit 1 (block 側)。`stop_hook_active` retry-skip (ADR-004) が永続 lock を防ぐ
- **templates**: `templates/hooks-config-{typescript,python}.toml` は Rust 非対象 (comment-lint-rust は Rust 限定) のため本 gate を追加せず

ADR-039 § 4 self-review checklist (4 点) 充足:

1. **config schema**: `FileLengthGateConfig { enabled: Option<bool>, base: Option<String> }`
2. **default OFF**: `gate_enabled()` が `unwrap_or(false)` (code default)。本 repo のみ dogfood で `enabled = true`
3. **docs / config example**: `.claude/hooks-config.toml` の `[file_length_gate]` section に 3 点セット + kill-switch を comment 明記 (plan doc 削除後も永続、ADR-039 § "明示的 decision trigger の必須化")
4. **kill-switch test**: unit test `gate_disabled_when_enabled_false` + dogfood で `enabled = false` 実機 no-op を確認

dogfood 結果 (deploy 済 exe で実機確認):

| シナリオ | 結果 |
|---|---|
| clean state (enabled=true、超過なし) | exit 0 ✅ |
| 850 行 file を作成 | exit 1 + 該当 file 列挙で block ✅ |
| `FILE_LENGTH_CHECK_OVERRIDE=1` | exit 0 + 実受理値表示で bypass ✅ |
| `FILE_LENGTH_CHECK_OVERRIDE=true` (truthy variant) | exit 0 + `=true` 表示で bypass ✅ (ADR-039 § 2) |
| `enabled = false` (超過 file 残存) | exit 0 + 無出力の no-op ✅ |
| 本 PR 自身の変更に対する self-host | exit 0 (self-consistent) ✅ |

削除条件 3 (`FILE_LENGTH_CHECK_OVERRIDE=1` 未使用で 1-2 セッション通過) の観測は **land 後** に開始する。

#### 進め方

batch mode 実装 (~50 行) + tests (~30 行) + config schema 更新。Agent 委譲不要、直接実装可能な規模。
Expand Down Expand Up @@ -445,7 +483,7 @@ PR-W1 [x] #220 (merged at 2026-06-24T18:04:56Z)
PR-W2 [x] #224 (merged at 2026-06-28T13:15:36Z)
PR-W3 [x] #230 (merged at 2026-07-01T05:27:34Z)
PR-W4 [x] #231 (merged at 2026-07-01T08:42:27Z)
PR-W5 [ ] not started
PR-W5 [~] 実装完了 (dogfood pass、PR 未作成) @5cfcfb5a
```

land 後は `[x]` + PR 番号を記入し、最終的に 6 件全て `[x]` で本 file を削除。
Expand Down
1 change: 1 addition & 0 deletions docs/todo-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
| 243 | 💎 Tier 3 | **`pub(crate)` vs `pub` 可視性チェックリストを module split 手順に追加 (PR #231 post-merge-feedback T3-1 採用)** | todo13.md | XS | なし (W-series module split で visibility scoping の判断が都度必要 = crate 内共有は `pub(crate)`、`pub` は同一 crate 内では有効だが library target 公開時のみ外部 API 化 (binary crate では pub(crate) と実質同等ゆえ pub(crate) 推奨) の違いを具体例付きで明示。Frequency Medium (file-length 強制継続で split 継続) + Effort XS + Adoption Risk None。順位 241 (pub(crate) 方針) と相補、追記先の file-length-enforcement-plan.md は W5 land 後削除予定のため coding-style.md / CLAUDE.md への恒久配置を着手時判断) |
| 244 | 💎 Tier 3 | **per-module test helper 複製方針を coding-style.md に明文化 (PR #231 post-merge-feedback T3-2 採用)** | todo13.md | XS | なし (`unique_temp_root` / `write_meta` / `parked_state` 等の test helper を各 module に複製し shared util module を作らない方針が前提知識化しておらず split の度に混乱。coupling vs isolation トレードオフの根拠 + split レビュー確認項目を coding-style.md に追記。Frequency Medium + Effort XS + Adoption Risk None、memory `feedback_test_dry_antipattern` の恒久 codify) |
| 245 | 💎 Tier 3 | **`PR_SIZE_CHECK_OVERRIDE=1` 適用ポリシーを push-runner-config.toml に明文化 (PR #231 post-merge-feedback T3-3 採用)** | todo13.md | XS | なし (override の使い方が「知っている人だけが知る」暗黙知化、機械的 refactor (削除≒追加) の定義と override 判断基準を push-runner-config.toml の `[pr_size_check]` コメントまたは docs に追記。file-length 強制継続で機械 refactor の override 判断は今後も発生 (Frequency Medium) + Effort XS + Adoption Risk None) |
| 246 | 🔧 Tier 2 | **monitor の CI 完了判定を短絡 — CodeRabbit review-complete + mergeability CLEAN で CI 待機を skip し merge-ready 判定 (PR #232 post-merge-feedback T2-1 採用)** | todo13.md | S | なし (CodeRabbit のみが check の構成 (GitHub Actions 等の実 CI 不在) で monitor が「CI: pending」を無限に誤報し、GitHub API 直接確認 (mergeStateStatus=CLEAN / mergeable=MERGEABLE) で merge 可能を確認する手動対応が PR #231/#232 で 2 回発生 = 幻の CI pending。docs-only PR の共通 pattern で再現見込み。poll ループに「review 完了 + mergeability CLEAN なら CI 待機を短絡」条件分岐を追加 (parse logic 改修不要)。Severity Medium + Frequency Medium + Effort S + Adoption Risk None) |

**戦略**: Tier 1 を 2〜3 セッションで片付け → Tier 2 で ADR-032 の前提 + rate-limit + convergence cost 削減を進める → Tier 3 で ADR-032 を land + ドキュメント整備。Tier 4-5 は cleanup / 外部展開で daily efficiency への直接効果は小さい。

Expand Down
28 changes: 28 additions & 0 deletions docs/todo13.md
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,34 @@

---

### monitor の CI 完了判定を短絡 — CodeRabbit review-complete + mergeability CLEAN で CI 待機を skip (PR #232 post-merge-feedback T2-1 採用)

> **動機**: 本リポジトリは check が CodeRabbit のみで GitHub Actions 等の実 CI が存在しない構成。この構成で cli-pr-monitor の poll が「CI: pending」を完了と判定できず recheck を上限まで繰り返す。PR #231 / #232 の両方で、GitHub API を直接確認 (`gh pr view --json mergeStateStatus,mergeable` → `CLEAN` / `MERGEABLE`) して merge 可能を人手で確認する必要が生じた (= 幻の CI pending)。
>
> **本タスクの位置づけ**: PR #232 post-merge-feedback Tier 2 #1 採用 (Severity Medium / Frequency Medium / Effort S / Adoption Risk None)。docs-only PR で共通に再現する pattern。
>
> **参照**: `.claude/feedback-reports/232.md` Tier 2 #1、`src/cli-pr-monitor/src/stages/poll/` (CI 完了判定 + poll ループ)、PR #231 / #232 (幻の CI pending を手動 GitHub API 確認で回避した実例)、ADR-018 (park モデル)。
>
> **実行優先度**: 🔧 **Tier 2** — Effort S。既存 poll ループへの条件分岐追加のみ (parse logic 改修不要)。

#### 設計決定 (案)

- CI 状態が「実 check 不在 or CodeRabbit のみ」かつ CodeRabbit review が完了 (unresolved 0 / actionable 0) かつ mergeability が `CLEAN` / `MERGEABLE` の場合、CI 待機 (pending) を短絡して merge-ready 判定に倒す。
- 誤短絡防止: 実 CI check が 1 件でも存在し pending なら従来通り待機 (CodeRabbit-only 構成に限定)。

#### 作業計画

- [ ] poll の CI 完了判定に「review-complete + mergeability CLEAN」短絡条件を追加
- [ ] CodeRabbit-only 構成の判定 (実 CI check の有無) を実装
- [ ] `cargo test -p cli-pr-monitor` pass + regression test (短絡が誤発火しないこと)
- [ ] 本 entry 削除 + todo-summary.md 行削除

#### 完了基準

- CodeRabbit-only 構成の PR で review 完了 + CLEAN なら monitor が recheck を無駄に繰り返さず merge-ready と判定する。実 CI がある場合は従来の pending 待機を維持。

---

## 既知課題 (記録のみ、本セッションで未対応)

(現時点で本ファイルへの既知課題は無し。docs/todo10.md / todo9.md 末尾を参照。)
1 change: 1 addition & 0 deletions src/hooks-post-tool-comment-lint-rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
tree-sitter = "0.22"
tree-sitter-rust = "0.21"

Expand Down
4 changes: 4 additions & 0 deletions src/hooks-post-tool-comment-lint-rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod file_length;
mod function_length;
mod line_filter;
mod metrics;
mod modified_files_check;
mod violations;

use line_filter::{
Expand Down Expand Up @@ -105,6 +106,9 @@ fn main() {
if args.len() >= 3 && args[1] == "--metrics" {
std::process::exit(run_metrics_mode(&args[2]));
}
if args.len() >= 2 && args[1] == "--check-modified-files" {
std::process::exit(modified_files_check::run_check_modified_files());
}

let mut input = String::new();
if io::stdin().read_to_string(&mut input).is_err() {
Expand Down
Loading