feat(hooks): 設定駆動型アーキテクチャに移行し配布自動化を実装 - #1
Conversation
b89658a to
4b283b2
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (18)
💤 Files with no reviewable changes (3)
✅ Files skipped from review due to trivial changes (10)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughこのPRはフック群を設定駆動化し、 Changes
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: フック判定(許可/ブロック/診断)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
scripts/deploy-targets.template.json (1)
1-6: テンプレートパターンは適切です。
deploy-hooks.jsがdeploy-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: カスタムパターンのブロックメッセージにパターン情報を含めることを検討してください。現在、カスタムパターンによるブロック時のメッセージは汎用的です。ユーザーがどのパターンに一致したかを知るために、パターン文字列をメッセージに含めると診断が容易になります。
♻️ 改善案
カスタムパターン用のメッセージを動的に生成するには、
BlockedPatternのmessageをStringにするか、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
⛔ Files ignored due to path filters (6)
.claude/hooks-post-tool-linter/Cargo.lockis excluded by!**/*.lock.claude/hooks-pre-tool-validate/Cargo.lockis excluded by!**/*.lock.claude/hooks-stop-quality-py/Cargo.lockis excluded by!**/*.lock.claude/hooks-stop-quality/Cargo.lockis excluded by!**/*.locksrc/__pycache__/sample.cpython-310.pycis excluded by!**/*.pyctests/__pycache__/test_sample.cpython-310-pytest-9.0.2.pycis 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.gitignoreCLAUDE.mddocs/adr/adr-006-config-driven-hooks.mdpackage.jsonscripts/deploy-hooks.jsscripts/deploy-targets.template.jsontemplates/hooks-config-python.tomltemplates/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
| // 設定からステップとタイムアウトを取得 | ||
| 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; | ||
| } |
There was a problem hiding this comment.
設定ファイルがない場合、品質ゲートが無効になります。
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.
4b283b2 to
867c07e
Compare
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>
867c07e to
5154ee4
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 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
⛔ Files ignored due to path filters (6)
.claude/hooks-post-tool-linter/Cargo.lockis excluded by!**/*.lock.claude/hooks-pre-tool-validate/Cargo.lockis excluded by!**/*.lock.claude/hooks-stop-quality-py/Cargo.lockis excluded by!**/*.lock.claude/hooks-stop-quality/Cargo.lockis excluded by!**/*.locksrc/__pycache__/sample.cpython-310.pycis excluded by!**/*.pyctests/__pycache__/test_sample.cpython-310-pytest-9.0.2.pycis 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.gitignoreCLAUDE.mddocs/adr/adr-006-config-driven-hooks.mdpackage.jsonscripts/deploy-hooks.jsscripts/deploy-targets.template.jsontemplates/hooks-config-python.tomltemplates/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
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)
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 に実装方針を記録
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 に実装方針を記録
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 に実装方針を記録
* 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 見出しリンクのアンカーが壊れる可能性があります
* 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)
Summary
hooks-config.toml) 駆動に移行し、1セットの共通バイナリで複数プロジェクトに対応可能にしたhooks-stop-qualityとhooks-stop-quality-pyを統合し、exe を 4本→3本に削減pnpm deploy:hooksで派生プロジェクトへの一括配布を自動化deploy-targets.jsonをテンプレート化し、ローカルパスの漏洩を防止(public リポジトリ化に備えて)変更の詳細
設定駆動化 (全3 hook)
pre-tool-validatedefault,git,jj-*,electron) + 追加保護ファイルpost-tool-linterstop-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で派生プロジェクトへの配布確認🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
Summary by CodeRabbit
新機能
改善
ドキュメント
削除