Skip to content

feat(hooks): 設定駆動型アーキテクチャに移行し配布自動化を実装 - #1

Merged
aloekun merged 1 commit into
masterfrom
feat/config-driven-hooks
Mar 19, 2026
Merged

feat(hooks): 設定駆動型アーキテクチャに移行し配布自動化を実装#1
aloekun merged 1 commit into
masterfrom
feat/config-driven-hooks

Conversation

@aloekun

@aloekun aloekun commented Mar 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • hooks を TOML 設定ファイル (hooks-config.toml) 駆動に移行し、1セットの共通バイナリで複数プロジェクトに対応可能にした
  • hooks-stop-qualityhooks-stop-quality-py を統合し、exe を 4本→3本に削減
  • pnpm deploy:hooks で派生プロジェクトへの一括配布を自動化
  • deploy-targets.json をテンプレート化し、ローカルパスの漏洩を防止(public リポジトリ化に備えて)

変更の詳細

設定駆動化 (全3 hook)

Hook カスタマイズポイント
pre-tool-validate ブロックパターンのプリセット選択 (default, git, jj-*, electron) + 追加保護ファイル
post-tool-linter 拡張子ごとのリンターパイプライン定義 (コマンド・引数・fix/check)
stop-quality 品質チェックステップ名・コマンド・タイムアウト

新規ファイル

  • .claude/hooks-config.toml — 本家用設定
  • scripts/deploy-hooks.js — 配布スクリプト
  • scripts/deploy-targets.template.json — 配布先テンプレート
  • templates/hooks-config-{python,typescript}.toml — 派生プロジェクト用テンプレート
  • docs/adr/adr-006-config-driven-hooks.md — ADR

削除

  • .claude/hooks-stop-quality-py/hooks-stop-quality に統合

Test plan

  • cargo test — 全3 hook で 123 tests passed (89 + 25 + 9)
  • pnpm build:hooks で exe ビルド確認
  • pnpm deploy:hooks で派生プロジェクトへの配布確認
  • 派生プロジェクトで hooks-config.toml の設定に基づく動作確認

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

Summary by CodeRabbit

  • 新機能

    • プロジェクト毎のフック設定(検証パターン、リンターパイプライン、品質チェック手順)を追加。
    • フックの一括配布スクリプトを追加し、複数プロジェクトへ自動デプロイ可能に。
  • 改善

    • フックを設定駆動化し、リンタ/品質ゲートの柔軟性とタイムアウト設定を導入。
    • ビルド/デプロイ関連スクリプトを整理・追加。
  • ドキュメント

    • 設定駆動フックのADRと言語別テンプレートを追加。
  • 削除

    • 旧Python版品質ゲートバイナリを廃止。

@aloekun
aloekun force-pushed the feat/config-driven-hooks branch from b89658a to 4b283b2 Compare March 19, 2026 08:03
@aloekun

aloekun commented Mar 19, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 19, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Mar 19, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 344b140d-4bc2-45ed-918d-9ef3ed8262d2

📥 Commits

Reviewing files that changed from the base of the PR and between 867c07e and 5154ee4.

⛔ Files ignored due to path filters (6)
  • .claude/hooks-post-tool-linter/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-pre-tool-validate/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality-py/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality/Cargo.lock is excluded by !**/*.lock
  • src/__pycache__/sample.cpython-310.pyc is excluded by !**/*.pyc
  • tests/__pycache__/test_sample.cpython-310-pytest-9.0.2.pyc is excluded by !**/*.pyc
📒 Files selected for processing (18)
  • .claude/hooks-config.toml
  • .claude/hooks-post-tool-linter/Cargo.toml
  • .claude/hooks-post-tool-linter/src/main.rs
  • .claude/hooks-pre-tool-validate/Cargo.toml
  • .claude/hooks-pre-tool-validate/src/main.rs
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/hooks-stop-quality-py/src/main.rs
  • .claude/hooks-stop-quality/Cargo.toml
  • .claude/hooks-stop-quality/src/main.rs
  • .claude/settings.local.json.template
  • .gitignore
  • CLAUDE.md
  • docs/adr/adr-006-config-driven-hooks.md
  • package.json
  • scripts/deploy-hooks.js
  • scripts/deploy-targets.template.json
  • templates/hooks-config-python.toml
  • templates/hooks-config-typescript.toml
💤 Files with no reviewable changes (3)
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/settings.local.json.template
  • .claude/hooks-stop-quality-py/src/main.rs
✅ Files skipped from review due to trivial changes (10)
  • .claude/hooks-post-tool-linter/Cargo.toml
  • .claude/hooks-pre-tool-validate/Cargo.toml
  • scripts/deploy-targets.template.json
  • CLAUDE.md
  • templates/hooks-config-typescript.toml
  • templates/hooks-config-python.toml
  • .claude/hooks-post-tool-linter/src/main.rs
  • docs/adr/adr-006-config-driven-hooks.md
  • .claude/hooks-config.toml
  • .claude/hooks-stop-quality/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (3)
  • .gitignore
  • package.json
  • scripts/deploy-hooks.js

📝 Walkthrough

Walkthrough

このPRはフック群を設定駆動化し、.claude/hooks-config.toml と言語別テンプレートを追加し、Rustフック実装をTOML設定読み込みへ変更、Python版 stop-quality を削除して配布スクリプトを追加します。

Changes

Cohort / File(s) Summary
共通プロジェクト設定
.claude/hooks-config.toml
プロジェクト固有のフック設定を追加([pre_tool_validate]のblocked_patterns/extra_protected_files、[post_tool_linter]のパイプライン、[stop_quality]の手順とstep_timeout)。
テンプレート設定
templates/hooks-config-python.toml, templates/hooks-config-typescript.toml
言語別のhooks-configテンプレートを追加(pre_tool_validate / post_tool_linter / stop_quality を定義)。
フック実装(設定駆動化)
.claude/hooks-pre-tool-validate/src/main.rs, .claude/hooks-post-tool-linter/src/main.rs, .claude/hooks-stop-quality/src/main.rs
各フックをTOML設定対応へ書き換え:設定読み込み、プリセット選択とカスタム正規表現、拡張子→パイプラインマッチング、汎用ステップ実行、可変タイムアウト等を導入。テスト更新あり。
削除されたPython stop-quality
.claude/hooks-stop-quality-py/src/main.rs, .claude/hooks-stop-quality-py/Cargo.toml
Pythonベースの stop-quality 実装とマニフェストを削除。settings/ビルド参照も除去。
Cargo依存追加
.claude/*/Cargo.toml
複数フックCrateに toml = "0.8" 依存を追加(TOMLパース用)。
配布スクリプト
scripts/deploy-hooks.js, scripts/deploy-targets.template.json
複数ターゲットへのフック実行ファイル配布スクリプトを追加(targets JSON 読み込み、exeコピー、settings.local.jsonテンプレート置換)。
ビルド・設定更新
package.json, .claude/settings.local.json.template, .gitignore
build:hooks から Python stop-quality ビルドを除外、deploy:hooks スクリプト追加、Stop フック参照をテンプレートから削除、.gitignore 更新(pyキャッシュや deploy-targets など)。
ドキュメント/ADR
CLAUDE.md, docs/adr/adr-006-config-driven-hooks.md
設定駆動型フックアーキテクチャのADRと配布手順を追加。

Sequence Diagram(s)

sequenceDiagram
    participant App as アプリケーション
    participant Hook as フック実行バイナリ
    participant Config as hooks-config.toml
    participant Pipeline as パイプライン実行
    participant Cmd as 外部コマンド

    App->>Hook: フック起動 (対象ファイル/操作)
    Hook->>Config: 設定読み込み
    Config-->>Hook: TOML設定オブジェクト
    Hook->>Pipeline: 拡張子/操作でパイプライン選択
    Pipeline->>Pipeline: ステップ順・{file}置換
    loop 各ステップ
      Pipeline->>Cmd: コマンド実行 (args)
      Cmd-->>Pipeline: stdout/stderr, exit
      Pipeline->>Pipeline: fix=false の出力を先頭20行まで蓄積
    end
    Pipeline-->>Hook: 実行結果 / additionalContext
    Hook-->>App: フック判定(許可/ブロック/診断)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは設定駆動型アーキテクチャへの移行と配布自動化の実装という主要な変更を正確に反映しており、PR全体の主要な目的と一致している。
Docstring Coverage ✅ Passed Docstring coverage is 89.58% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
📝 Coding Plan
  • Generate coding plan for human review comments

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: 3

🧹 Nitpick comments (3)
scripts/deploy-targets.template.json (1)

1-6: テンプレートパターンは適切です。

deploy-hooks.jsdeploy-targets.jsonを読み込み、存在しない場合はエラーで終了する設計と合致しています。これによりプレースホルダーパスが誤って使用されることを防いでいます。

クロスプラットフォーム対応として、Unix形式のパス例もコメントに追加すると親切かもしれません。

📝 クロスプラットフォーム例の追加案
 {
+  "_comment": "Windows: C:\\path\\to\\project, Unix: /home/user/project",
   "targets": [
     "C:\\path\\to\\project-a",
     "C:\\path\\to\\project-b"
   ]
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deploy-targets.template.json` around lines 1 - 6, The template
currently only shows Windows paths in the "targets" array; to help
cross-platform users, update deploy-targets.template.json to include Unix-style
example paths (e.g. "/path/to/project-a", "/path/to/project-b") alongside the
Windows examples in the "targets" array so deploy-hooks.js still validates
presence but users on POSIX systems see correct examples; alternatively add a
short note in the repo README referencing deploy-targets.template.json and the
"targets" array to show POSIX path examples if you prefer not to modify the JSON
file itself.
.claude/hooks-pre-tool-validate/src/main.rs (1)

260-270: カスタムパターンのブロックメッセージにパターン情報を含めることを検討してください。

現在、カスタムパターンによるブロック時のメッセージは汎用的です。ユーザーがどのパターンに一致したかを知るために、パターン文字列をメッセージに含めると診断が容易になります。

♻️ 改善案

カスタムパターン用のメッセージを動的に生成するには、BlockedPatternmessageString にするか、Cow<'static, str> を使用する必要があります。現在の &'static str では静的なメッセージしか保持できません。

将来の改善として検討してください。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks-pre-tool-validate/src/main.rs around lines 260 - 270, The
custom-pattern block currently constructs BlockedPattern with a &'static str
message, preventing inclusion of the actual regex; change BlockedPattern.message
to an owned String (or Cow<'static, str>) and update the construction in the
custom arm (where Regex::new(custom) succeeds) to build a dynamic message that
includes the pattern string (custom) so users see which pattern matched; ensure
all other BlockedPattern instantiations are updated to provide owned Strings or
Cow values and adjust any signatures/usages of BlockedPattern (types,
constructors, and serializations) accordingly.
.claude/hooks-post-tool-linter/src/main.rs (1)

159-190: {file} プレースホルダーのサニタイズを検討してください。

resolve_args{file} を単純に置換していますが、ファイルパスに {file} という文字列が含まれる場合(極めて稀ですが)、意図しない置換が発生する可能性があります。

現状のコードはシェルを経由せず直接コマンドを実行しているため、コマンドインジェクションのリスクは低いですが、将来の保守性のために留意してください。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks-post-tool-linter/src/main.rs around lines 159 - 190, The
replace logic in resolve_args can unintentionally substitute when the file path
itself contains the string "{file}"; update resolve_args to sanitize the file
value before substitution (or only substitute when the arg equals the
placeholder) so accidental in-file "{file}" fragments are not injected into
args. Concretely, inside resolve_args sanitize the incoming file (e.g., escape
or transform any "{file}" substrings in the file variable) or change the mapping
to only replace whole-argument tokens (if a == "{file}" then use
file.to_string(), else keep a.clone()) to ensure safe, predictable substitution
used by run_pipeline and any callers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/hooks-stop-quality/src/main.rs:
- Around line 161-169: The current use of
config.stop_quality.unwrap_or_default() loses the distinction between a missing
config and an explicit empty stop_quality, causing silent disablement of the
quality gate; change the logic that sets stop_config/steps to detect when
config.stop_quality is None and in that case populate a sensible default steps
list (or at minimum log a warning) instead of returning an empty steps vector;
locate the code around stop_quality / stop_config / steps (and
DEFAULT_STEP_TIMEOUT_SECS) and replace the unwrap_or_default flow with a match
or if-let that either assigns default steps or emits a warning so the quality
checks run by default when the config file is absent.

In `@scripts/deploy-hooks.js`:
- Around line 26-36: The loadTargets function currently calls
JSON.parse(fs.readFileSync(targetsPath, "utf8")) without handling syntax errors;
wrap the read/parse in a try/catch around JSON.parse (and fs.readFileSync) and
when parsing fails log a clear, user-friendly error that includes the
targetsPath and the parse error message (but avoid dumping a raw stack), then
call process.exit(1); update references in loadTargets to return [] only after
successful parse or exit on error so callers like loadTargets see either valid
targets or the process terminates.

In `@templates/hooks-config-python.toml`:
- Around line 37-39: The stop_quality step references a non-existent script
"py-test:e2e"; either update the TOML step to call the existing script by
changing cmd from "pnpm py-test:e2e" to "pnpm test:e2e" (and keep name
"py-test:e2e" or rename the step to "test:e2e" for clarity), or add a new npm
script "py-test:e2e" to package.json that delegates to the Python e2e runner
(e.g., map "py-test:e2e" -> the same command as "test:e2e" or the appropriate
python test command) so the step and package.json stay consistent.

---

Nitpick comments:
In @.claude/hooks-post-tool-linter/src/main.rs:
- Around line 159-190: The replace logic in resolve_args can unintentionally
substitute when the file path itself contains the string "{file}"; update
resolve_args to sanitize the file value before substitution (or only substitute
when the arg equals the placeholder) so accidental in-file "{file}" fragments
are not injected into args. Concretely, inside resolve_args sanitize the
incoming file (e.g., escape or transform any "{file}" substrings in the file
variable) or change the mapping to only replace whole-argument tokens (if a ==
"{file}" then use file.to_string(), else keep a.clone()) to ensure safe,
predictable substitution used by run_pipeline and any callers.

In @.claude/hooks-pre-tool-validate/src/main.rs:
- Around line 260-270: The custom-pattern block currently constructs
BlockedPattern with a &'static str message, preventing inclusion of the actual
regex; change BlockedPattern.message to an owned String (or Cow<'static, str>)
and update the construction in the custom arm (where Regex::new(custom)
succeeds) to build a dynamic message that includes the pattern string (custom)
so users see which pattern matched; ensure all other BlockedPattern
instantiations are updated to provide owned Strings or Cow values and adjust any
signatures/usages of BlockedPattern (types, constructors, and serializations)
accordingly.

In `@scripts/deploy-targets.template.json`:
- Around line 1-6: The template currently only shows Windows paths in the
"targets" array; to help cross-platform users, update
deploy-targets.template.json to include Unix-style example paths (e.g.
"/path/to/project-a", "/path/to/project-b") alongside the Windows examples in
the "targets" array so deploy-hooks.js still validates presence but users on
POSIX systems see correct examples; alternatively add a short note in the repo
README referencing deploy-targets.template.json and the "targets" array to show
POSIX path examples if you prefer not to modify the JSON file itself.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca5f9756-affd-48fc-ae50-565a0f1f8ecc

📥 Commits

Reviewing files that changed from the base of the PR and between c94e867 and 4b283b2.

⛔ Files ignored due to path filters (6)
  • .claude/hooks-post-tool-linter/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-pre-tool-validate/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality-py/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality/Cargo.lock is excluded by !**/*.lock
  • src/__pycache__/sample.cpython-310.pyc is excluded by !**/*.pyc
  • tests/__pycache__/test_sample.cpython-310-pytest-9.0.2.pyc is excluded by !**/*.pyc
📒 Files selected for processing (18)
  • .claude/hooks-config.toml
  • .claude/hooks-post-tool-linter/Cargo.toml
  • .claude/hooks-post-tool-linter/src/main.rs
  • .claude/hooks-pre-tool-validate/Cargo.toml
  • .claude/hooks-pre-tool-validate/src/main.rs
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/hooks-stop-quality-py/src/main.rs
  • .claude/hooks-stop-quality/Cargo.toml
  • .claude/hooks-stop-quality/src/main.rs
  • .claude/settings.local.json.template
  • .gitignore
  • CLAUDE.md
  • docs/adr/adr-006-config-driven-hooks.md
  • package.json
  • scripts/deploy-hooks.js
  • scripts/deploy-targets.template.json
  • templates/hooks-config-python.toml
  • templates/hooks-config-typescript.toml
💤 Files with no reviewable changes (3)
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/settings.local.json.template
  • .claude/hooks-stop-quality-py/src/main.rs

Comment on lines +161 to 169
// 設定からステップとタイムアウトを取得
let stop_config = config.stop_quality.unwrap_or_default();
let steps = stop_config.steps.unwrap_or_default();
let timeout = stop_config.step_timeout.unwrap_or(DEFAULT_STEP_TIMEOUT_SECS);

// ステップが無い場合は何もせず停止許可
if steps.is_empty() {
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

設定ファイルがない場合、品質ゲートが無効になります。

hooks-config.toml が存在しない(または [stop_quality] セクションがない)場合、steps は空になり、品質チェックが一切実行されずに Claude の停止が許可されます。

ADR-004 によると、無出力 + exit 0 は「停止許可」を意味するため、これは意図的な設計変更かもしれませんが、以前のハードコード版では常に品質チェックが実行されていたため、後方互換性が失われています

派生プロジェクトでデプロイ後に hooks-config.toml を作成し忘れると、品質ゲートが静かに無効化されます。

🛠️ 修正案: デフォルトステップを追加
+/// デフォルトのステップ (設定ファイルが無い場合のフォールバック)
+fn default_steps() -> Vec<QualityStepConfig> {
+    vec![
+        QualityStepConfig { name: "lint".into(), cmd: "pnpm lint".into() },
+        QualityStepConfig { name: "test".into(), cmd: "pnpm test".into() },
+    ]
+}
+
 fn main() {
     let config = load_config();
     // ...
     let stop_config = config.stop_quality.unwrap_or_default();
-    let steps = stop_config.steps.unwrap_or_default();
+    let steps = stop_config.steps.unwrap_or_else(default_steps);
     let timeout = stop_config.step_timeout.unwrap_or(DEFAULT_STEP_TIMEOUT_SECS);

または、設定ファイルが存在しない場合に警告を出力する方法もあります。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks-stop-quality/src/main.rs around lines 161 - 169, The current
use of config.stop_quality.unwrap_or_default() loses the distinction between a
missing config and an explicit empty stop_quality, causing silent disablement of
the quality gate; change the logic that sets stop_config/steps to detect when
config.stop_quality is None and in that case populate a sensible default steps
list (or at minimum log a warning) instead of returning an empty steps vector;
locate the code around stop_quality / stop_config / steps (and
DEFAULT_STEP_TIMEOUT_SECS) and replace the unwrap_or_default flow with a match
or if-let that either assigns default steps or emits a warning so the quality
checks run by default when the config file is absent.

Comment thread scripts/deploy-hooks.js
Comment thread templates/hooks-config-python.toml
@aloekun
aloekun force-pushed the feat/config-driven-hooks branch from 4b283b2 to 867c07e Compare March 19, 2026 11:20
hooks を TOML 設定ファイル駆動に移行し、1セットの共通バイナリで
複数プロジェクトに対応可能にした。これにより hooks 更新時の
転用コストが O(N) から O(1) に削減される。

主な変更:
- hooks-config.toml による設定駆動化 (全3 hook)
- pre-tool-validate: ブロックパターンのプリセット選択方式
- post-tool-linter: 拡張子→パイプラインの動的ディスパッチ
- stop-quality: TS版とPython版を統合、ステップをTOML定義
- pnpm deploy:hooks による一括配布スクリプト
- deploy-targets.json のテンプレート化 (セキュリティ対策)
- .pyc ファイルを追跡解除し .gitignore に追加
- ADR-006 追加

CodeRabbitレビュー反映:
- stop-quality: hooks-config.toml が無い場合に警告を stderr に出力
- deploy-hooks.js: JSON.parse のエラーハンドリングを追加
- package.json: py-test:e2e スクリプトを追加

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@aloekun
aloekun force-pushed the feat/config-driven-hooks branch from 867c07e to 5154ee4 Compare March 19, 2026 11:24
@aloekun

aloekun commented Mar 19, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 19, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

🧹 Nitpick comments (1)
.claude/hooks-pre-tool-validate/src/main.rs (1)

369-376: current_exe() のエラー処理について確認が必要

current_exe() が失敗した場合(サンドボックス環境や特殊なファイルシステムなど)、unwrap_or_default() により空の PathBuf が返され、その後の parent()None を返すため Path::new(".") にフォールバックします。これは意図した動作と思われますが、設定ファイルが見つからない場合のデバッグが困難になる可能性があります。

current_exe() の失敗時に警告ログを出力することを検討してください。

♻️ 提案: exe パス取得失敗時の警告追加
 fn config_path() -> PathBuf {
-    std::env::current_exe()
-        .unwrap_or_default()
+    std::env::current_exe()
+        .map_err(|e| {
+            eprintln!("[validate-command] Warning: Failed to get executable path: {}", e);
+            e
+        })
+        .unwrap_or_default()
         .parent()
         .unwrap_or(Path::new("."))
         .join("hooks-config.toml")
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks-pre-tool-validate/src/main.rs around lines 369 - 376, The
config_path() helper swallows failures from std::env::current_exe() via
unwrap_or_default(), making it hard to debug when exe path resolution fails;
update config_path to detect current_exe() errors, log a warning (using the
project's logger) when current_exe() returns Err before falling back to
Path::new("."), and preserve the existing fallback behavior so the function
still returns a PathBuf pointing to "hooks-config.toml"; reference config_path
and current_exe() to locate the change and add a single, clear warning log
message on failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.claude/hooks-pre-tool-validate/src/main.rs:
- Around line 369-376: The config_path() helper swallows failures from
std::env::current_exe() via unwrap_or_default(), making it hard to debug when
exe path resolution fails; update config_path to detect current_exe() errors,
log a warning (using the project's logger) when current_exe() returns Err before
falling back to Path::new("."), and preserve the existing fallback behavior so
the function still returns a PathBuf pointing to "hooks-config.toml"; reference
config_path and current_exe() to locate the change and add a single, clear
warning log message on failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fef72cd0-b74e-4916-9adf-00ae902b76a6

📥 Commits

Reviewing files that changed from the base of the PR and between 4b283b2 and 867c07e.

⛔ Files ignored due to path filters (6)
  • .claude/hooks-post-tool-linter/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-pre-tool-validate/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality-py/Cargo.lock is excluded by !**/*.lock
  • .claude/hooks-stop-quality/Cargo.lock is excluded by !**/*.lock
  • src/__pycache__/sample.cpython-310.pyc is excluded by !**/*.pyc
  • tests/__pycache__/test_sample.cpython-310-pytest-9.0.2.pyc is excluded by !**/*.pyc
📒 Files selected for processing (18)
  • .claude/hooks-config.toml
  • .claude/hooks-post-tool-linter/Cargo.toml
  • .claude/hooks-post-tool-linter/src/main.rs
  • .claude/hooks-pre-tool-validate/Cargo.toml
  • .claude/hooks-pre-tool-validate/src/main.rs
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/hooks-stop-quality-py/src/main.rs
  • .claude/hooks-stop-quality/Cargo.toml
  • .claude/hooks-stop-quality/src/main.rs
  • .claude/settings.local.json.template
  • .gitignore
  • CLAUDE.md
  • docs/adr/adr-006-config-driven-hooks.md
  • package.json
  • scripts/deploy-hooks.js
  • scripts/deploy-targets.template.json
  • templates/hooks-config-python.toml
  • templates/hooks-config-typescript.toml
💤 Files with no reviewable changes (3)
  • .claude/settings.local.json.template
  • .claude/hooks-stop-quality-py/Cargo.toml
  • .claude/hooks-stop-quality-py/src/main.rs
✅ Files skipped from review due to trivial changes (9)
  • .claude/hooks-pre-tool-validate/Cargo.toml
  • .claude/hooks-stop-quality/Cargo.toml
  • CLAUDE.md
  • .claude/hooks-post-tool-linter/Cargo.toml
  • .gitignore
  • templates/hooks-config-python.toml
  • .claude/hooks-config.toml
  • scripts/deploy-targets.template.json
  • docs/adr/adr-006-config-driven-hooks.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • scripts/deploy-hooks.js
  • package.json
  • templates/hooks-config-typescript.toml
  • .claude/hooks-post-tool-linter/src/main.rs
  • .claude/hooks-stop-quality/src/main.rs

@aloekun
aloekun merged commit 752609d into master Mar 19, 2026
1 check passed
@aloekun
aloekun deleted the feat/config-driven-hooks branch March 19, 2026 16:26
aloekun added a commit that referenced this pull request Mar 30, 2026
PreToolUse の jj-push-guard プリセットで直接の push をブロックし、
hooks-push-pipeline (スタンドアロン Rust exe) で push 前パイプラインを
実行する2段構成で、Claude Code hooks に存在しない push hook を補完する。

- PreToolUse: jj-push-guard プリセット追加
- hooks-push-pipeline: command 型/ai 型ステップの順次実行 + 最終 push
- hooks-config.toml: [push_pipeline] セクション追加
- ビルド・配布統合: package.json, .gitignore, deploy-hooks.ts 更新
- ADR-008: 設計判断を記録

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

fix: CodeRabbit レビュー指摘4件を修正

- push_cmd/cmd の空文字バリデーション追加 (#1 Major)
- jj-push-guard に環境変数プレフィックスバイパス対策 (#3 Nitpick)
- ADR-008 コードブロックに言語指定追加 (#4 Nitpick)
- hooks-push-pipeline 全関数に docstring 追加 (#5 Pre-merge)
aloekun added a commit that referenced this pull request Apr 16, 2026
PR #43 で観測された 2 つの連鎖バグを修正。

## バグ #1 (誤検出 / monitor.rs:91)
jj の working-copy-is-a-commit モデルで `@` が PR の content commit その
ものだと、`jj diff --stat` (= @ vs parent) が常に PR 全体の diff を返すため
「takt fix 後の変更」と誤認される問題。

修正: commit id の pre/post 比較と実 diff 確認の二段構え判定 (decide_repush
pure function) に置き換え。jj の metadata 更新で ID だけ変化するケースも吸収。

## バグ #2 (破壊的 describe / push.rs:15-24)
`jj describe -m "fix(cli-pr-monitor): ..."` が元 description を無条件上書き。
takt fix が @ を amend する設計と不整合。

修正: jj describe を完全廃止 (P1)。commit message 管理は人間/PR title の責務。
takt はコード修正のみ。

## 追加改善
- ログを [state] / [decision] / [action] プレフィックスで構造化
- auto_push を should_run_auto_push(setting, has_change) の二段構えに統一
- 退行防止の統合テスト 1 本 (#[ignore]) を追加、push pipeline でのみ実行
  (PostToolUse / Stop hook では実行せずイテレーション速度を保護)

## 変更ファイル
- src/cli-pr-monitor/src/stages/monitor.rs: decide_repush + execute_repush_flow
- src/cli-pr-monitor/src/stages/push.rs: jj describe 削除
- src/cli-pr-monitor/Cargo.toml: tempfile (dev-dep)
- push-runner-config.toml: rust-test group を push pipeline に追加
- docs/todo.md: task #4 に実装方針を記録
aloekun added a commit that referenced this pull request Apr 16, 2026
PR #43 で観測された 2 つの連鎖バグを修正。

## バグ #1 (誤検出 / monitor.rs:91)
jj の working-copy-is-a-commit モデルで `@` が PR の content commit その
ものだと、`jj diff --stat` (= @ vs parent) が常に PR 全体の diff を返すため
「takt fix 後の変更」と誤認される問題。

修正: commit id の pre/post 比較と実 diff 確認の二段構え判定 (decide_repush
pure function) に置き換え。jj の metadata 更新で ID だけ変化するケースも吸収。

## バグ #2 (破壊的 describe / push.rs:15-24)
`jj describe -m "fix(cli-pr-monitor): ..."` が元 description を無条件上書き。
takt fix が @ を amend する設計と不整合。

修正: jj describe を完全廃止 (P1)。commit message 管理は人間/PR title の責務。
takt はコード修正のみ。

## 追加改善
- ログを [state] / [decision] / [action] プレフィックスで構造化
- auto_push を should_run_auto_push(setting, has_change) の二段構えに統一
- 退行防止の統合テスト 1 本 (#[ignore]) を追加、push pipeline でのみ実行
  (PostToolUse / Stop hook では実行せずイテレーション速度を保護)

## 変更ファイル
- src/cli-pr-monitor/src/stages/monitor.rs: decide_repush + execute_repush_flow
- src/cli-pr-monitor/src/stages/push.rs: jj describe 削除
- src/cli-pr-monitor/Cargo.toml: tempfile (dev-dep)
- push-runner-config.toml: rust-test group を push pipeline に追加
- docs/todo.md: task #4 に実装方針を記録
aloekun added a commit that referenced this pull request Apr 16, 2026
PR #43 で観測された 2 つの連鎖バグを修正。

## バグ #1 (誤検出 / monitor.rs:91)
jj の working-copy-is-a-commit モデルで `@` が PR の content commit その
ものだと、`jj diff --stat` (= @ vs parent) が常に PR 全体の diff を返すため
「takt fix 後の変更」と誤認される問題。

修正: commit id の pre/post 比較と実 diff 確認の二段構え判定 (decide_repush
pure function) に置き換え。jj の metadata 更新で ID だけ変化するケースも吸収。

## バグ #2 (破壊的 describe / push.rs:15-24)
`jj describe -m "fix(cli-pr-monitor): ..."` が元 description を無条件上書き。
takt fix が @ を amend する設計と不整合。

修正: jj describe を完全廃止 (P1)。commit message 管理は人間/PR title の責務。
takt はコード修正のみ。

## 追加改善
- ログを [state] / [decision] / [action] プレフィックスで構造化
- auto_push を should_run_auto_push(setting, has_change) の二段構えに統一
- 退行防止の統合テスト 1 本 (#[ignore]) を追加、push pipeline でのみ実行
  (PostToolUse / Stop hook では実行せずイテレーション速度を保護)

## 変更ファイル
- src/cli-pr-monitor/src/stages/monitor.rs: decide_repush + execute_repush_flow
- src/cli-pr-monitor/src/stages/push.rs: jj describe 削除
- src/cli-pr-monitor/Cargo.toml: tempfile (dev-dep)
- push-runner-config.toml: rust-test group を push pipeline に追加
- docs/todo.md: task #4 に実装方針を記録
aloekun added a commit that referenced this pull request Apr 28, 2026
* docs(todo): PR #88 post-merge-feedback の Tier 1/2 finding を採用

PR #88 post-merge-feedback (.claude/feedback-reports/88.md) で生成された 7 件の
finding のうち、ユーザー判断により #1-5 を採用、#6-7 を見送り。

採用 finding (5 件):
- T1 #1 (順位 5): Stop hook の `pnpm lint:md` 統合 — XS、順位 1 完了済の gap closure
- T1 #2 (順位 6): AI 生成一時スクリプト pattern の pre-push 検出 — Small、順位 1 と関連
- T2 #3 (順位 13): `vitest` を devDependencies に固定 — Small
- T2 #4 (順位 12): `cli-pr-monitor` ポーリング延長 + 重複起動ロック — Medium、★ rate-limit critical
- T2 #5 (順位 14): `pnpm create-pr` 必須引数ヘルプ改善 — Small

見送り finding:
- T3 #6: hook 統合時の commit 分割基準 → グローバルルール (~/.claude/) 編集は permission denied、要別経路
- T3 #7: jj rebase conflict 解消手順 → 同上

変更:
- docs/todo3.md 新設 (todo2.md が 50KB に到達したため、PR #88 以降の新規エントリは todo3.md へ)
- docs/todo.md 推奨実行順序サマリーに 5 件を Tier 別に挿入し、20 → 24 タスクへ全 renumber
- 戦略テキストと cross-reference を全面更新
- todo2.md / todo3.md 内の 順位 N 参照を新採番へ追従
- 順位 1 (markdownlint hook 統合) は merged 済として削除参照を merged context に書き換え

* fix(review): apply CodeRabbit fixes for #89

Resolved findings:
- [Minor] docs/todo.md:49 順位参照の文言が現行テーブルと不整合です
- [Major] docs/todo3.md:7 見出しリンクのアンカーが壊れる可能性があります
aloekun added a commit that referenced this pull request Apr 28, 2026
Tier 2 #2 finding -> Tier 2 #1 finding に書き換え (case A)。
title "PR #89 T2-1" の Tier-local 番号と body の参照番号を統一。

参照: PR #90 CodeRabbit Minor finding (docs/todo3.md:298)
aloekun added a commit that referenced this pull request Apr 28, 2026
* docs(todo): PR #89 post-merge-feedback の Tier 1/2 finding を採用

PR #89 post-merge-feedback (.claude/feedback-reports/89.md) で生成された 4 件の
finding のうち、ユーザー判断により Tier 1/2 (#1, #2) を採用、Tier 3 (#3, #4) を
見送り (お願いベースのため Tier 1 対応で様子見)。

採用 finding (2 件):
- T1 #1 (順位 7): Markdown 非 ASCII GFM アンカー検出 lint rule — S、ADR-007 拡張
- T2 #2 (順位 14): post-pr-review に rate-limit 自動検出 + 再トリガーロジック — Medium、★ rate-limit critical

見送り finding:
- T3 #3: 可変テキスト見出しに明示アンカー必須ルール → Tier 1 #1 で決定論的に防止できる
- T3 #4: 表並び替え後の prose rank 参照 grep ルール → 順位 24 (採番管理 ADR) で構造的に解消予定

変更:
- docs/todo3.md に 2 タスク追記 (本ファイルでの新規追加は計 7 タスク)
- docs/todo.md 推奨実行順序サマリーを 24 → 26 タスクへ全 renumber
- 順位 7 (anchor lint) を Tier 1 末尾に挿入、順位 14 (rate-limit auto-trigger) を Tier 2 内 順位 13 (cli-pr-monitor polling) の隣に挿入
- 戦略テキストに rate-limit 改善の 3 層構造 (順位 4/13/14) を明記
- 順位 7 と順位 20 の二重防衛関係を sub-text に追記
- todo2.md cross-reference を全面更新 (sed bulk + 個別 fix)

PR #89 セッション知見:
- ADR-030 の soft-fail recovery (.failed marker + UserPromptSubmit hook) が Claude
  rate-limit interruption からの復旧で機能した実証
- takt 単独実行時の post-processing (report copy + marker 削除) は cli-merge-pipeline
  側責務で手動補完が必要 — 復旧手順 marker への追記が将来の改善ポイント

* fix(review): apply CodeRabbit fix for #90

Tier 2 #2 finding -> Tier 2 #1 finding に書き換え (case A)。
title "PR #89 T2-1" の Tier-local 番号と body の参照番号を統一。

参照: PR #90 CodeRabbit Minor finding (docs/todo3.md:298)
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