Skip to content

feat(bundle): hooks-pre-tool-validate PowerShell preset + check-ci-coderabbit 境界 test (順位 212-215) - #215

Merged
aloekun merged 4 commits into
masterfrom
bundle-212-214-implementation
Jun 22, 2026
Merged

feat(bundle): hooks-pre-tool-validate PowerShell preset + check-ci-coderabbit 境界 test (順位 212-215)#215
aloekun merged 4 commits into
masterfrom
bundle-212-214-implementation

Conversation

@aloekun

@aloekun aloekun commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

docs/todo-summary.md 順位 212/213/214 を bundle として実装。PR #213 post-merge-feedback 採用 3 件 (feedback-T1-1 + T2-1 + T2-2) を統合して 1 PR で land する。順位 215 (PR #214 post-merge-feedback T3-1 採用の todo entry) も含めた 4 commits 構成。

内訳

順位 215 (docs): PR #214 post-merge-feedback T3-1 採用 todo entry 追加

  • docs/todo-summary.md + docs/todo10.md に「Defensive State Reset in State Machines」section を ~/.claude/rules/common/coding-style.md に追記する todo entry を追加
  • 由来: PR refactor(cli-pr-monitor): poll.rs を 3 module に分割 (PR B、partial) #214 round 2 で finalize_initial_review_parkstate.pr / state.repo / state.started_atread_state() 後に無条件上書きする pattern (5 field 適用済) を future reviewer が「redundant」と削除しないよう global rule で防御

順位 213/214 (test): check-ci-coderabbit parser 境界テスト追加

  • parse_coderabbit_status.first() semantics を doc comment + assert message で explicit 化 (cr_status_reverse_chronological_picks_first)
  • parse_actionable_commentssubmitted_at >= push_time inclusive 比較を境界 test で固定 (actionable_includes_review_at_exact_push_time + actionable_excludes_review_before_push_time の sentinel-based negative test)
  • 由来: PR refactor(check-ci-coderabbit): main.rs を 7 module に分割 (PR A) #213 takt-fix iter 2 で .last().first() semantic fix + t > push_timet >= push_time 境界 fix の retest 防御
  • 既存 rule⑦ no-time-field-strict-greater を補完する second defense layer

順位 212 (feat): PowerShell dispatch + powershell-destructive-write-block preset 追加

  • 新 preset (5 BlockedPattern): [System.IO.File]::WriteAllText|WriteAllBytes|WriteAllLines + Out-File + Set-Content -Value
  • handle_powershell_tool 関数 + dispatch table に "PowerShell" arm 追加
  • default_preset_names 登録で Config::default() でも default-on
  • 由来: PR refactor(check-ci-coderabbit): main.rs を 7 module に分割 (PR A) #213 (refactor PR A) 作業中、PowerShell スクリプトの連鎖失敗 (IndexOf -1Substring 例外$null contentWriteAllText で 0 byte 化) で check-ci-coderabbit/src/main.rs (2369 行) が消失した事故。memory feedback_no_powershell_inplace_edit の codify と併用する mechanical defense layer

Pre-push-review (takt) Warning 4 件解消 (ADR-043 fail-closed 強化)

初回 push で raised された 4 Warning を round 2 で全て解消:

  • W-002 SEC (Low): .NET method pattern に (?i) flag 追加 — PowerShell の .NET method 名は case-insensitive で [system.io.file]::writealltext() で bypass 可能だった
  • W-001 SEC (Medium): exception を path 位置に scope — 旧 exception (['"]__[^'"]*['"]) が command 全体を見るため ReadAllText("__a"); WriteAllText("prod", $null) で bypass、新 exception はそれぞれの cmdlet/method 直後の最初の引数のみ
  • W-001 SIMP (Warning): Set-Content main pattern を [^|]*-Value に変更 — -Path-Value の順序非依存に
  • W-002 SIMP (Warning): Out-File exception で ['"]? で quote optional 化 — unquoted scratch path (Out-File __output.txt) も allow

Test plan

  • cargo test -p hooks-pre-tool-validate: 221 passed (= 202 既存 + 19 new = 11 base PowerShell + 8 edge case)
  • cargo test -p check-ci-coderabbit: 96 passed (= 93 既存 + 3 new = 213/214 tests)
  • cargo clippy -p hooks-pre-tool-validate -- -D warnings: clean
  • cargo test --workspace: 全テスト pass (regression なし)
  • pre-push-review takt (round 1): simplicity / security 両方 APPROVE (4 Warning 付き)
  • pre-push-review takt (round 2): diff 空でスキップ (Warning 解消は workspace test + clippy で検証)
  • PR 作成後の CodeRabbit review で追加 finding 無し

設計判断 & Out of scope

  • file_length lint 超過: src/hooks-pre-tool-validate/src/main.rs は 2900 行 (800 行ガイドライン超過) になるが、本 PR は 順位 212 の mechanical defense 追加に scope 限定。ファイル分割 refactor は別 PR (PR refactor(check-ci-coderabbit): main.rs を 7 module に分割 (PR A) #213/refactor(cli-pr-monitor): poll.rs を 3 module に分割 (PR B、partial) #214 と同 pattern) で対応
  • todo entry 削除: 順位 212/213/214 の docs/todo10.md エントリは本 PR では削除せず、merge 後 follow-up commit で削除 (memory feedback_todo_no_history.md per、PR reject 時の orphan 削除リスク回避)
  • Bundle 戦略: memory feedback_minimize_pr_count_during_rate_limit.md per、3 タスクを 1 PR で bundle (Effort M + S + S の合計でも diff < 400 行に収まる)

Summary by CodeRabbit

リリースノート

  • Documentation

    • State Machineの防御的状態リセットパターンに関するドキュメントを追加
  • Tests

    • GitHubステータス解析のテストカバレッジを拡張
    • PowerShellファイル書込検証テストを追加
  • New Features

    • PowerShellの破壊的ファイル書込操作をブロック(スクラッチファイルは例外)

aloekun added 3 commits June 21, 2026 19:31
PR #214 (refactor PR B partial) post-merge-feedback report の T3-1 を採用:
`~/.claude/rules/common/coding-style.md` に "Defensive State Reset in
State Machines" section を追記する todo entry を docs/todo-summary.md +
docs/todo10.md に追加。

由来: PR #214 round 2 で CR Major #4 fix として
`finalize_initial_review_park` 内 `read_state()` 後の
`state.pr`/`state.repo`/`state.started_at` 無条件上書きが land。同型
`head_commit`/`review_recheck_count` reset と合わせて 5 field の確立
された defensive pattern を future reviewer が "redundant" と誤判定して
削除しないよう global rule で防御する。

Severity Medium / Frequency Medium / Effort S / Adoption Risk None で
ユーザー承認 (2026-06-20)。pre-push:simplicity + pre-push:security の
独立 2 ソース検出。実装時は `feedback_global_config_backup` 適用必須。
順位 213 (PR #213 post-merge-feedback T2-1 採用):
parse_coderabbit_status の `.first()` semantics を test 名 +
doc comment + assert message で explicit 化。GitHub statuses API の
reverse-chronological 返却 implicit assumption を test fixture で
固定し、refactor 時の意味喪失を機械的に検出する。

順位 214 (PR #213 post-merge-feedback T2-2 採用):
parse_actionable_comments の `submitted_at >= push_time` inclusive
比較を境界で固定する 2 test を追加:
- actionable_includes_review_at_exact_push_time: `==` 境界の inclusive 比較を保証
- actionable_excludes_review_before_push_time: 配列 latest 位置に
  sentinel (Actionable: 99, 11:00) を置き、rfind が time filter で
  正しく除外することを確認 (filter 壊れた場合 99 が返り test 落ちる)

既存 rule⑦ `no-time-field-strict-greater` は変数名抽出後を catch
不可なため、test による second defense layer として機能。
memory `feedback_test_dry_antipattern.md` 適用で独立 setup。

検証:
- cargo test -p check-ci-coderabbit: 96 passed (= 93 + 3 new)
- 既存 actionable_filters_by_time との相補的 boundary 検証
…uctive-write-block preset 追加 (順位 212)

PR #213 (refactor PR A) 作業中に発生した PowerShell スクリプトでの
`check-ci-coderabbit/src/main.rs` (2369 行) 0 byte 化事故の機械強制
対策。memory `feedback_no_powershell_inplace_edit` の codify と併用する
mechanical defense layer として preset と dispatch を追加した。

設計:

- 新 preset `powershell-destructive-write-block` (5 BlockedPattern)
  - `[System.IO.File]::WriteAllText|WriteAllBytes|WriteAllLines` (事故直接因)
  - `Out-File` (redirect 系 cmdlet)
  - `Set-Content -Value` (cmdlet 版書込、-Value flag 付きのみ false positive 回避)
- すべての pattern に `(?i)` flag を付与 (PowerShell の .NET method 名 +
  cmdlet 名は case-insensitive)
- Exception を path 位置に scope (= command 全体ではなく cmdlet/method 直後の
  最初の引数のみ):
  - WriteAllText/Bytes/Lines: `\(\s*['"]__` で open paren 直後限定
  - Out-File: `Out-File\s+(?:-FilePath\s+)?['"]?__` (unquoted も allow)
  - Set-Content: `Set-Content\s+(?:-(?:Literal)?Path\s+)?['"]?__`
- Set-Content main pattern は `[^|]*-Value` で param 順非依存
  (`-Value` が `-Path` より先に来る reversed order でも block)
- dispatch table に `PowerShell` arm 追加 + `handle_powershell_tool` 関数
  (handle_bash_tool と同形で `tool_input.command` を build_blocked_patterns
  全 preset で照合)
- `default_preset_names` に登録 = Config::default() で default-on

追加 test 19 件 (= 11 base + 8 edge case):

base 11 件:
- positive (5): WriteAllText / WriteAllBytes / WriteAllLines / Out-File /
  Set-Content -Value の destructive write block
- negative scratch (2): `__*` prefix path への write は allow
- negative legit (3): Get-ChildItem / Where-Object / Set-Content 単体 (false
  positive 回避)
- default-on (1)

edge case 8 件 (pre-push-review Warning 4 件に対応、ADR-043 fail-closed):
- W-002 SEC: lowercase `.NET` method 名 (`writealltext`) でも block
- W-001 SEC: `__` 文字列が value 位置にあるとき block (path 位置に scope)
- W-001 SEC: ReadAllText で `__` を読んでも WriteAllText 先が prod なら block
- W-001 SIMP: Set-Content の reversed parameter order (`-Value` 先) でも block
- W-001 SIMP: Set-Content の reversed order でも scratch path なら allow
- W-002 SIMP: unquoted scratch path (`Out-File __output.txt`) は allow
- value 位置の `__` を path と誤認しない (Set-Content 版)

検証:
- cargo test -p hooks-pre-tool-validate: 221 passed (= 202 既存 + 19 new)
- cargo clippy -p hooks-pre-tool-validate -- -D warnings: clean
- cargo test --workspace: 全テスト pass (regression なし)

Note: `src/hooks-pre-tool-validate/src/main.rs` は本 PR 後 2900 行になり
file_length lint (800 行ガイドライン) を超過するが、本 PR は順位 212 の
mechanical defense 追加に scope を限定し、ファイル分割 refactor は別 PR
(PR #213/#214 と同 pattern) で対応する。
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@aloekun, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 36 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4581da7a-a8df-442d-aa53-0324ffbce1d6

📥 Commits

Reviewing files that changed from the base of the PR and between 5bcd5a4 and f264ece.

📒 Files selected for processing (1)
  • src/hooks-pre-tool-validate/src/main.rs
📝 Walkthrough

Walkthrough

hooks-pre-tool-validateにPowerShell向け破壊的ファイル書込ブロックプリセット(WriteAllText/Bytes/Lines・Out-File・Set-Content)を新規追加し、デフォルト有効化・プリセット解決・mainハンドラ分岐・テストを実装した。またcheck-ci-coderabbitパーサーへ境界条件テストを追加し、タスク管理ドキュメントを更新した。

Changes

PowerShell破壊的書込ブロックプリセット

Layer / File(s) Summary
プリセット定義とメッセージ定数
src/hooks-pre-tool-validate/src/main.rs
preset_powershell_destructive_write を新設し、WriteAllText/Bytes/Lines・Out-File・Set-Content -Valueの5種をブロック対象にしつつ、__接頭辞scratchパスをexceptionで許可する条件とブロック時メッセージ定数を追加した。
デフォルト登録・プリセット解決・mainハンドラ
src/hooks-pre-tool-validate/src/main.rs
default_preset_names()"powershell-destructive-write-block"を追加、resolve_preset_or_custom()でプリセット名解決を追加、main()tool_name分岐に"PowerShell"を追加してhandle_powershell_toolからbuild_blocked_patterns/validate_commandで照合し終了コード2を返す経路を実装した。
PowerShellプリセットテスト群
src/hooks-pre-tool-validate/src/main.rs
WriteAllText/Bytes/Lines・Out-File・Set-Content・__scratch例外・大文字小文字無視・引数順序差異・false positive回避・default config有効性をis_blocked_withベースで検証するテストを追加した。

check-ci-coderabbitパーサーテスト追加

Layer / File(s) Summary
ステータスおよびアクション可能コメントテスト
src/check-ci-coderabbit/src/parsers.rs
parse_coderabbit_statusのreverse-chronological仕様を固定するテスト、parse_actionable_commentssubmitted_at == push_time inclusive判定テスト、submitted_at < push_timeのsentinel値除外テストを追加した。

タスクドキュメント追記

Layer / File(s) Summary
タスク定義と推奨実行順序エントリ
docs/todo10.md, docs/todo-summary.md
coding-style.mdへ「Defensive State Reset in State Machines」section追加タスクの作業計画・完了基準をtodo10.mdに追記し、todo-summary.mdの推奨実行順序テーブルに順位215(Tier 3)エントリを追加した。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • aloekun/claude-code-hook-test#13: build_blocked_patterns・デフォルト/プリセット解決・テスト構造など、同一のプリセット追加パイプラインをhooks-pre-tool-validateで拡張している。
  • aloekun/claude-code-hook-test#166: src/hooks-pre-tool-validate/src/main.rsの同一プリセット/パターン解決フロー(build_blocked_patterns/プリセット名処理)に新たなブロックプリセットを追加している点で共通している。
  • aloekun/claude-code-hook-test#201: default_preset_names・プリセット解決・マッチングフローという同一の共通プリセット基盤に異なる新プリセット(secret-detection)を追加している。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PRタイトルはPowerShellプリセット追加と境界テスト追加(位置212-215)という主な変更内容を適切に要約している。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/hooks-pre-tool-validate/src/main.rs`:
- Around line 532-536: The current regex pattern in the exception field does not
handle all parameter orderings for the Set-Content PowerShell command. The
pattern only matches when the -Path or -LiteralPath parameter immediately
follows Set-Content, but fails to detect cases where the -Value parameter
appears before -Path. Update the regex pattern in the Regex::new call to handle
both parameter orderings (whether -Path comes first or -Value comes first), and
add test cases to verify that the updated pattern correctly matches both
scenarios.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 63275ab7-87d9-46e2-be11-ca4770f99770

📥 Commits

Reviewing files that changed from the base of the PR and between 4e07a35 and 5bcd5a4.

📒 Files selected for processing (4)
  • docs/todo-summary.md
  • docs/todo10.md
  • src/check-ci-coderabbit/src/parsers.rs
  • src/hooks-pre-tool-validate/src/main.rs

Comment thread src/hooks-pre-tool-validate/src/main.rs
…CR Minor #1)

PR #215 CR review が指摘した Minor finding を対応:
`Set-Content` の exception regex が main pattern と order-independence
を共有していなかったため、`Set-Content -Value $x -Path "__file"` のような
reversed parameter order での scratch path 指定が false positive で block
されていた。

修正:

旧 exception:
  `(?i)\bSet-Content\b\s+(?:-(?:Literal)?Path\s+)?['"]?__`
  → `-Path` が Set-Content 直後にある順序のみカバー

新 exception:
  `(?i)\bSet-Content\b(?:\s+['"]?__|[^|]*\s-(?:Literal)?Path\s+['"]?__)`
  → 2-alternative:
    - alt 1: `Set-Content` 直後の positional `__` path
    - alt 2: `Set-Content` 以降のいずれかの位置の `-Path`/`-LiteralPath`
      後の `__` path

CR の修正案は `(?=...)` lookahead を使っていたが、Rust 標準 `regex` crate
は lookahead 非対応 (compile failure) のため、同 semantics を 2-alt 構成で
lookahead なしに実装。main pattern `[^|]*-Value` が既に `-Value` 存在を
保証しているため、exception 側に lookahead-based verification は不要。

test 追加:
- `Set-Content -Value $x -Path "__file.txt"` (reversed order) → allow
- `Set-Content -Value $x -LiteralPath "__file.txt"` (LiteralPath 変種) → allow
- 既存の positional case (`Set-Content "__file.txt" -Value $x`) は維持

検証:
- cargo test -p hooks-pre-tool-validate: 221 passed
- cargo clippy -p hooks-pre-tool-validate -- -D warnings: clean

由来: PR #215 CR Minor #1 (discussion_r3448719154)、ADR-043 fail-closed
原則による security gate と false-positive 抑制の両立。
@aloekun
aloekun merged commit bddf6f2 into master Jun 22, 2026
1 check passed
@aloekun
aloekun deleted the bundle-212-214-implementation branch June 22, 2026 09:59
aloekun added a commit that referenced this pull request Jun 22, 2026
…er enable (#216)

5 entries の stale cleanup と weekly review reminder の試験運用元 enable。

## Stale entry cleanup (5 件)

PR #202 / #215 で land 済だが docs/todo*.md に entry が残存していた
タスクを削除:
- 順位 147 (File length lint, todo9.md) — PR #202
- 順位 151 (PR diff lines check, todo9.md) — PR #202
- 順位 212 (PowerShell dispatch, todo10.md) — PR #215
- 順位 213 (parse_coderabbit_status test, todo10.md) — PR #215
- 順位 214 (parse_actionable_comments test, todo10.md) — PR #215

順位 215 (coding-style.md "Defensive State Reset" section 追加) は
PR #215 で todo entry を追加しただけで実装は未着手のため保持。
grep "Defensive State Reset" ~/.claude/rules/common/coding-style.md
で実体確認済。

## weekly_review_reminder の試験運用元 enable

.claude/hooks-config.toml [session_start.weekly_review_reminder] を
enabled = false → true に変更。

ADR-031 (週次レビュー pipeline) は 2026-06-01 に本採用化済みだが、
Phase E 観測で「reminder は実発火していない」状態が継続し最後の実行から
21 日経過 (2026-06-01 → 2026-06-23) していたため、試験運用元では明示的に
enable する運用に切替。派生プロジェクト deploy 時の default は
ADR-039 § 1 opt-in 契約に従い OFF 維持。

本変更は PR-3 (layered config: [features].enabled allow-list 移行) で
真の opt-in 切り替えになるまでの暫定。toml に rationale comment block を
明記済み。

## PR 計画における位置

PR-1 (本 PR) → PR-3 (layered config) → PR-2 (Stop hook todo cleanup check)
の 3 PR plan の 1 件目。PR-3 で本 PR の `enabled = true` は
`[features].enabled` allow-list 登録に置き換わる。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant