diff --git a/.claude/hooks-config.toml b/.claude/hooks-config.toml index f2e7d50d..99ec287c 100644 --- a/.claude/hooks-config.toml +++ b/.claude/hooks-config.toml @@ -9,7 +9,7 @@ # 1. $CLAUDE_ENV_FILE → Bash ツールの環境変数 (CLAUDE_CODE_SESSION_ID) # 2. .claude/.session-id → 子プロセス exe から読み取り可能 # 同一 ID ならスキップ、異なる ID なら上書きする方式。 -# ※ hooks-post-pr-monitor は daemon + state file 方式に移行済みのため +# ※ cli-pr-monitor は daemon + state file 方式に移行済みのため # .session-id の直接参照は不要になったが、将来の拡張用に維持。 # [session_start] diff --git a/.claude/settings.local.json.template b/.claude/settings.local.json.template index 23c58ce7..d82c08eb 100644 --- a/.claude/settings.local.json.template +++ b/.claude/settings.local.json.template @@ -1,7 +1,7 @@ { "permissions": { "allow": [ - "Bash(pnpm build:hooks)", + "Bash(pnpm build:all)", "Bash(pnpm check-ci *)", "Bash(pnpm pr-create *)", "Bash(cargo test:*)" diff --git a/.gitignore b/.gitignore index 40c67848..0d1e9109 100644 --- a/.gitignore +++ b/.gitignore @@ -2,17 +2,11 @@ .claude/hook-debug.log .claude/post-pr-monitor-debug.log -# Generated from .claude/settings.local.json.template by build:hooks +# Generated from .claude/settings.local.json.template by build:all .claude/settings.local.json -# Built executables (can be rebuilt with pnpm build:hooks) -.claude/hooks-pre-tool-validate.exe -.claude/hooks-post-tool-linter.exe -.claude/hooks-stop-quality.exe -.claude/hooks-push-pipeline.exe -.claude/hooks-post-pr-monitor.exe -.claude/check-ci-coderabbit.exe -.claude/hooks-session-start.exe +# Built executables (can be rebuilt with pnpm build:all) +.claude/*.exe # Deploy targets (contains local paths; create from deploy-targets.template.json) scripts/deploy-targets.json @@ -25,14 +19,7 @@ __pycache__/ *.pyc # Rust build artifacts -src/hooks-pre-tool-validate/target/ -src/hooks-post-tool-linter/target/ -src/hooks-stop-quality/target/ -src/hooks-push-pipeline/target/ -src/hooks-post-pr-monitor/target/ -src/check-ci-coderabbit/target/ -src/hooks-session-start/target/ -src/hooks-report-formatter/target/ +src/*/target/ # Runtime generated files .claude/.session-id diff --git a/CLAUDE.md b/CLAUDE.md index 73cafcf4..74401f99 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,10 +13,11 @@ - [ADR-008: Push Pipeline ハーネスの実装](docs/adr/adr-008-push-pipeline-harness.md) - [ADR-009: Post-PR Monitor — push/PR作成後の CI・CodeRabbit 自動監視](docs/adr/adr-009-post-pr-monitor.md) - [ADR-011: jj の新規ブックマーク push 戦略](docs/adr/adr-011-jj-push-new-bookmark-strategy.md) +- [ADR-012: src/ ディレクトリの命名規約](docs/adr/adr-012-src-naming-convention.md) ## Build ```sh -pnpm build:hooks # 全 hooks exe を一括ビルド +pnpm build:all # 全 hooks/CLI exe を一括ビルド pnpm deploy:hooks # 派生プロジェクトに exe を配布 ``` diff --git a/docs/adr/adr-001-hooks-implementation-language.md b/docs/adr/adr-001-hooks-implementation-language.md index 433c972e..60234553 100644 --- a/docs/adr/adr-001-hooks-implementation-language.md +++ b/docs/adr/adr-001-hooks-implementation-language.md @@ -42,7 +42,7 @@ Windows 環境では以下の問題が発生した。 - Windows 環境で hooks が確実に動作する - PreToolUse / PostToolUse で実装パターンが統一される - ビルド済み exe を `.gitignore` で除外し、ソースコードだけをバージョン管理できる -- `pnpm build:hooks` 一発で全 hooks を再ビルドできる +- `pnpm build:all` 一発で全 hooks を再ビルドできる ### Negative diff --git a/docs/adr/adr-003-hooks-layout-and-build-strategy.md b/docs/adr/adr-003-hooks-layout-and-build-strategy.md index a97298a9..29574b17 100644 --- a/docs/adr/adr-003-hooks-layout-and-build-strategy.md +++ b/docs/adr/adr-003-hooks-layout-and-build-strategy.md @@ -59,13 +59,13 @@ Claude Code の hooks を複数管理する上で、ファイル配置・ビル - `pnpm build:hooks-pre-tool-validate` — PreToolUse フック単体ビルド - `pnpm build:hooks-post-tool-linter` — PostToolUse フック単体ビルド - `pnpm build:hooks-stop-quality` — Stop フック単体ビルド - - `pnpm build:hooks` — 全フック一括ビルド + - `pnpm build:all` — 全フック一括ビルド - 各コマンドは `cd .claude/ && cargo build --release && cp target/release/.exe ../.exe` の形式 ### バージョン管理 - `.gitignore` で除外するもの: - - ビルド済み exe(`pnpm build:hooks` で再生成可能) + - ビルド済み exe(`pnpm build:all` で再生成可能) - `target/` ディレクトリ(Rust ビルド成果物) - バージョン管理するもの: - `Cargo.toml` と `src/` 以下のソースコード @@ -76,22 +76,22 @@ Claude Code の hooks を複数管理する上で、ファイル配置・ビル ### Positive - フックの追加時に命名規則・配置が明確で迷わない -- `pnpm build:hooks` 一発で全フックを再ビルドできる +- `pnpm build:all` 一発で全フックを再ビルドできる - exe はバージョン管理外なのでリポジトリサイズが肥大化しない - 各フックが独立した Cargo プロジェクトなので、依存関係の競合が起きない ### Negative - フック追加時に `package.json` の scripts と `.gitignore` の両方を更新する必要がある -- クローン直後は `pnpm build:hooks` を実行しないと hooks が動作しない +- クローン直後は `pnpm build:all` を実行しないと hooks が動作しない ### 新しいフックを追加する手順 1. `.claude/<機能名>/` に Cargo プロジェクトを作成 -2. `package.json` に `build:hooks-<機能名>` スクリプトを追加し、`build:hooks` にチェーン +2. `package.json` に `build:hooks-<機能名>` スクリプトを追加し、`build:all` にチェーン 3. `.gitignore` に `.claude/<機能名>.exe` と `.claude/<機能名>/target/` を追加 4. `settings.local.json` の該当フックイベントに exe のパスを登録 -5. `pnpm build:hooks` でビルド確認 +5. `pnpm build:all` でビルド確認 ## References diff --git a/docs/adr/adr-005-hooks-path-resolution-with-template.md b/docs/adr/adr-005-hooks-path-resolution-with-template.md index afe8610a..f2c6d73c 100644 --- a/docs/adr/adr-005-hooks-path-resolution-with-template.md +++ b/docs/adr/adr-005-hooks-path-resolution-with-template.md @@ -37,7 +37,7 @@ ADR-003 では `settings.local.json` の `command` フィールドで `%CLAUDE_P ## Decision -**`settings.local.json.template` をテンプレートとして git 管理し、`pnpm build:hooks` 実行時にプロジェクトの絶対パスを埋め込んで `settings.local.json` を自動生成する。** +**`settings.local.json.template` をテンプレートとして git 管理し、`pnpm build:all` 実行時にプロジェクトの絶対パスを埋め込んで `settings.local.json` を自動生成する。** ### テンプレート @@ -55,7 +55,7 @@ ADR-003 では `settings.local.json` の `command` フィールドで `%CLAUDE_P node -e "...process.cwd() で {{PROJECT_DIR}} を置換..." ``` -`build:hooks` の末尾で自動実行されるため、exe ビルドとパス設定が 1 コマンドで完了する。 +`build:all` の末尾で自動実行されるため、exe ビルドとパス設定が 1 コマンドで完了する。 ### バージョン管理 @@ -68,14 +68,14 @@ node -e "...process.cwd() で {{PROJECT_DIR}} を置換..." ### Positive -- `pnpm build:hooks` を 1 回実行するだけで exe ビルド + パス設定が完了する +- `pnpm build:all` を 1 回実行するだけで exe ビルド + パス設定が完了する - `%CLAUDE_PROJECT_DIR%` の不安定性に依存しない - テンプレートを git 管理するため、hooks 設定の変更履歴が追跡できる -- プロジェクトをコピーしても `pnpm build:hooks` で正しいパスに自動更新される +- プロジェクトをコピーしても `pnpm build:all` で正しいパスに自動更新される ### Negative -- クローン直後に `pnpm build:hooks` を実行しないと hooks が動作しない(ADR-003 と同様) +- クローン直後に `pnpm build:all` を実行しないと hooks が動作しない(ADR-003 と同様) - テンプレートと生成物の二重管理になる(ただし生成は自動なので実質的な負担は小さい) ### ADR-003 への影響 diff --git a/docs/adr/adr-006-config-driven-hooks.md b/docs/adr/adr-006-config-driven-hooks.md index ca26c649..caa8f2c6 100644 --- a/docs/adr/adr-006-config-driven-hooks.md +++ b/docs/adr/adr-006-config-driven-hooks.md @@ -31,7 +31,7 @@ hooks (Rust 製 exe 4 本) を複数の派生プロジェクト (auto-review-fix ### 配布 -- `pnpm build:hooks` で本家でビルド +- `pnpm build:all` で本家でビルド - `pnpm deploy:hooks` で `scripts/deploy-targets.json` に登録された派生プロジェクトに exe を一括コピー - 派生プロジェクトは `hooks-config.toml` のみを管理 diff --git a/docs/adr/adr-008-push-pipeline-harness.md b/docs/adr/adr-008-push-pipeline-harness.md index 55318094..f9106477 100644 --- a/docs/adr/adr-008-push-pipeline-harness.md +++ b/docs/adr/adr-008-push-pipeline-harness.md @@ -18,7 +18,7 @@ Git には `pre-push` フックがあり、Lefthook のような OSS でパイ 2. **PreToolUse でブロック + スタンドアロン exe で パイプラインを実行** - PreToolUse で `jj git push` をブロックし、「`pnpm push` を使え」と誘導 - - `pnpm push` がスタンドアロン exe (hooks-push-pipeline) を呼び出し、テスト → レビュー → push を順次実行 + - `pnpm push` がスタンドアロン exe (cli-push-pipeline) を呼び出し、テスト → レビュー → push を順次実行 - → Claude Code hooks の制約内で push パイプラインを実現可能 3. **Skill (`/push`) として実装** @@ -28,7 +28,7 @@ Git には `pre-push` フックがあり、Lefthook のような OSS でパイ ## 決定 -**選択肢 2 を採用する。** PreToolUse の `jj-push-guard` プリセットで直接の push をブロックし、`hooks-push-pipeline` (スタンドアロン Rust exe) で push 前パイプラインを実行する。 +**選択肢 2 を採用する。** PreToolUse の `jj-push-guard` プリセットで直接の push をブロックし、`cli-push-pipeline` (スタンドアロン Rust exe) で push 前パイプラインを実行する。 ### アーキテクチャ @@ -44,7 +44,7 @@ PreToolUse (hooks-pre-tool-validate) Claude が "pnpm push" を実行する │ ▼ -hooks-push-pipeline.exe (スタンドアロン) +cli-push-pipeline.exe (スタンドアロン) ├─ hooks-config.toml [push_pipeline] を読み込み ├─ command 型ステップを順次実行 ├─ ai 型ステップは現在スキップ (将来実装) @@ -54,7 +54,7 @@ hooks-push-pipeline.exe (スタンドアロン) ### Claude Code hooks プロトコルとの違い -| | Claude Code hooks (Pre/Post/Stop) | hooks-push-pipeline | +| | Claude Code hooks (Pre/Post/Stop) | cli-push-pipeline | |---|---|---| | 起動方法 | Claude Code が自動的に呼び出す | `pnpm push` から手動/Claude 経由で呼び出す | | 入力 | stdin に JSON | なし (hooks-config.toml から設定読み込み) | @@ -76,14 +76,14 @@ hooks-push-pipeline.exe (スタンドアロン) ### Positive - Claude Code hooks に push イベントがない制約下で、事実上の push hook を実現できる -- 既存のビルド・配布フロー (`pnpm build:hooks`, `pnpm deploy:hooks`) にそのまま乗る +- 既存のビルド・配布フロー (`pnpm build:all`, `pnpm deploy:hooks`) にそのまま乗る - `hooks-config.toml` の `[push_pipeline]` セクションで、プロジェクトごとにステップをカスタマイズできる - `type = "ai"` ステップの導入により、将来の AI レビュー・コミット整理統合への拡張ポイントが確保されている ### Negative - PreToolUse ブロックは Claude 経由の push にのみ有効。ユーザーが直接ターミナルから `jj git push` を叩いた場合はバイパスされる(前提条件により許容) -- `hooks-push-pipeline` は Claude Code hooks プロトコルに準拠しないスタンドアロン exe であり、hooks 群の中で唯一の例外的な存在になる +- `cli-push-pipeline` は Claude Code hooks プロトコルに準拠しないスタンドアロン exe であり、hooks 群の中で唯一の例外的な存在になる - `run_step()` / `drain_pipe()` ロジックが `hooks-stop-quality` と重複する(ADR-003 の独立 Cargo プロジェクト方針に従い、共通クレート化は見送り) ### 将来の検討事項 diff --git a/docs/adr/adr-009-post-pr-monitor.md b/docs/adr/adr-009-post-pr-monitor.md index 6908067d..7f7efe7e 100644 --- a/docs/adr/adr-009-post-pr-monitor.md +++ b/docs/adr/adr-009-post-pr-monitor.md @@ -52,7 +52,7 @@ PreToolUse guard (gh-pr-create-guard) がブロック Claude が "pnpm pr-create -- --title ..." を実行 │ ▼ -hooks-post-pr-monitor.exe (スタンドアロン) +cli-pr-monitor.exe (スタンドアロン) ├─ gh pr create を実行(引数を転送) ├─ PR番号・リポジトリ情報を gh CLI で取得 ├─ .claude/pr-monitor-state.json に初期 state 書き出し @@ -64,16 +64,16 @@ Claude が stdout を読み、CronCreate で定期ジョブ作成 (任意) └─ command: cat .claude/pr-monitor-state.json 【既存 PR への push 時】 -pnpm push → hooks-push-pipeline.exe (テスト + レビュー + push) +pnpm push → cli-push-pipeline.exe (テスト + レビュー + push) │ ▼ (push 成功後に && でチェイン) -hooks-post-pr-monitor.exe --monitor-only +cli-pr-monitor.exe --monitor-only ├─ gh pr view で PR 存在確認 ├─ PR なし → exit 0 (何もしない) └─ PR あり → state file 初期化 + daemon スポーン + stdout 指示 【daemon (バックグラウンド)】 -hooks-post-pr-monitor.exe --daemon --state-file +cli-pr-monitor.exe --daemon --state-file ├─ check-ci-coderabbit.exe を poll_interval_secs 間隔で実行 ├─ 結果を pr-monitor-state.json に毎回書き出し ├─ 意味的終了: action != "continue_monitoring" @@ -89,7 +89,7 @@ cat .claude/pr-monitor-state.json | コンポーネント | 種別 | 役割 | |---|---|---| -| `hooks-post-pr-monitor.exe` | スタンドアロン CLI (Rust) | PR 作成 + daemon 起動 + state file 管理 | +| `cli-pr-monitor.exe` | スタンドアロン CLI (Rust) | PR 作成 + daemon 起動 + state file 管理 | | `hooks-pre-tool-validate.exe` | PreToolUse hook (Rust) | `gh-pr-create-guard` で直接の `gh pr create` をブロック | | `check-ci-coderabbit.exe` | スタンドアロン CLI (Rust) | CI・CodeRabbit 状態チェック → JSON 出力 | | `post-pr-create-review-check` SKILL.md | Claude Skill | 監視結果の解釈・報告手順 | @@ -130,7 +130,7 @@ check_coderabbit = true - push/PR 作成後の CI・CodeRabbit 確認を自動化し、開発フローの摩擦を削減 - 判定ロジックが Rust の純粋関数に分離されており、unit test で網羅可能 -- 既存のビルド・配布フロー (`pnpm build:hooks`, `pnpm deploy:hooks`) にそのまま乗る +- 既存のビルド・配布フロー (`pnpm build:all`, `pnpm deploy:hooks`) にそのまま乗る - `hooks-config.toml` でプロジェクトごとにポーリング間隔・監視対象をカスタマイズ可能 ### Negative diff --git a/docs/adr/adr-010-hooks-layout-and-build-strategy-v2.md b/docs/adr/adr-010-hooks-layout-and-build-strategy-v2.md index 4c0b55fd..ff942cf5 100644 --- a/docs/adr/adr-010-hooks-layout-and-build-strategy-v2.md +++ b/docs/adr/adr-010-hooks-layout-and-build-strategy-v2.md @@ -40,10 +40,10 @@ project-root/ │ ├── hooks-stop-quality/ # Stop フックのソース │ │ ├── Cargo.toml │ │ └── src/main.rs -│ ├── hooks-push-pipeline/ # Push Pipeline のソース +│ ├── cli-push-pipeline/ # Push Pipeline CLI のソース │ │ ├── Cargo.toml │ │ └── src/main.rs -│ ├── hooks-post-pr-monitor/ # Post-PR Monitor のソース +│ ├── cli-pr-monitor/ # PR Monitor CLI のソース │ │ ├── Cargo.toml │ │ └── src/main.rs │ ├── hooks-session-start/ # SessionStart フックのソース @@ -60,8 +60,8 @@ project-root/ │ ├── hooks-pre-tool-validate.exe # ビルド済み exe(.gitignore) │ ├── hooks-post-tool-linter.exe │ ├── hooks-stop-quality.exe -│ ├── hooks-push-pipeline.exe -│ ├── hooks-post-pr-monitor.exe +│ ├── cli-push-pipeline.exe # CLI ツール exe +│ ├── cli-pr-monitor.exe │ ├── hooks-session-start.exe │ └── check-ci-coderabbit.exe └── package.json # ビルドスクリプト @@ -76,15 +76,15 @@ project-root/ ### ビルド戦略 - `package.json` に個別ビルドコマンドと一括ビルドコマンドを定義: - - `pnpm build:hooks-<機能名>` — 各フック単体ビルド - - `pnpm build:hooks` — 全フック一括ビルド + - `pnpm build:<フォルダ名>` — 各フック/CLI 単体ビルド + - `pnpm build:all` — 全フック一括ビルド - 各コマンドは `cd src/ && cargo build --release && cp target/release/.exe ../../.claude/.exe` の形式 - `pnpm deploy:hooks` で派生プロジェクトへの exe 配布(変更なし) ### バージョン管理 - `.gitignore` で除外するもの: - - ビルド済み exe(`pnpm build:hooks` で再生成可能) + - ビルド済み exe(`pnpm build:all` で再生成可能) - `src/*/target/` ディレクトリ(Rust ビルド成果物) - バージョン管理するもの: - `src/*/Cargo.toml` と `src/*/src/` 以下のソースコード @@ -103,16 +103,16 @@ project-root/ ### Negative - ADR-003 と同様: フック追加時に `package.json` と `.gitignore` の両方を更新する必要がある -- ADR-003 と同様: クローン直後は `pnpm build:hooks` を実行しないと hooks が動作しない +- ADR-003 と同様: クローン直後は `pnpm build:all` を実行しないと hooks が動作しない - ビルド出力先が2階層上(`../../.claude/`)になるため、ビルドスクリプトがやや複雑 ### 新しいフックを追加する手順 1. `src/<機能名>/` に Cargo プロジェクトを作成 -2. `package.json` に `build:hooks-<機能名>` スクリプトを追加し、`build:hooks` にチェーン +2. `package.json` に `build:<フォルダ名>` スクリプトを追加し、`build:all` にチェーン 3. `.gitignore` に `.claude/<機能名>.exe` と `src/<機能名>/target/` を追加 4. `.claude/settings.local.json.template` の該当フックイベントに exe のパスを登録 -5. `pnpm build:hooks` でビルド確認 +5. `pnpm build:all` でビルド確認 ## References diff --git a/docs/adr/adr-012-src-naming-convention.md b/docs/adr/adr-012-src-naming-convention.md new file mode 100644 index 00000000..6b9d635a --- /dev/null +++ b/docs/adr/adr-012-src-naming-convention.md @@ -0,0 +1,83 @@ +# ADR-012: src/ ディレクトリの命名規約 — プレフィックスによる役割分類 + +## ステータス + +承認済み (2026-04-06) + +## コンテキスト + +プロジェクト発足時、`src/` 配下のクレートはすべて `hooks-` プレフィックスで命名していた。当初は Claude Code hooks(PreToolUse / PostToolUse / Stop / SessionStart)の実装のみだったため問題なかったが、以下の経緯で hooks 以外の機能が増加した。 + +### 問題点 + +1. **CLI ツールの混在**: `hooks-push-pipeline` や `hooks-post-pr-monitor` は Claude Code hooks プロトコルに準拠しない独立した CLI exe であり、`hooks-` プレフィックスが実態と合わない +2. **共有ライブラリの混在**: `hooks-report-formatter` は exe ではなくライブラリクレートだが、同じ `hooks-` プレフィックスのために判別しづらい +3. **コーディング AI の混乱**: フォルダ名だけでは「Claude Code が自動呼び出しする hook」と「ユーザー/スクリプトが明示的に呼ぶ CLI」と「依存ライブラリ」の区別がつかず、修正や拡張時に誤った前提で作業するリスクがある + +### 原則 + +- **コーディング AI が `src/` を一覧しただけで、各クレートの役割を推定できること** +- 今後 hooks や CLI が増えても、命名規約に従えば自然に分類できること + +## 決定 + +**`src/` 配下のディレクトリ名にプレフィックスを付与し、クレートの役割を3分類する。** + +| プレフィックス | 役割 | 呼び出し元 | 例 | +|---|---|---|---| +| `hooks-` | Claude Code hooks | Claude Code が自動呼び出し(stdin JSON) | `hooks-pre-tool-validate`, `hooks-session-start` | +| `cli-` | スタンドアロン CLI | `pnpm push` 等のスクリプトから明示的に呼び出し | `cli-push-pipeline`, `cli-pr-monitor` | +| `lib-` | 共有ライブラリ | 他クレートから `[dependencies]` で参照 | `lib-report-formatter` | +| (なし) | 補助 CLI / その他 | 状況による | `check-ci-coderabbit` | + +### Cargo パッケージ名 + +- フォルダ名 = Cargo パッケージ名(`Cargo.toml` の `[package] name`)とする +- ライブラリクレートの `[lib] name` はハイフンをアンダースコアに変換(Rust の慣例: `lib-report-formatter` → `lib_report_formatter`) + +### ビルドスクリプト名 + +- `package.json` の個別ビルドスクリプトは `build:<フォルダ名>` とする(例: `build:cli-push-pipeline`) +- 一括ビルドスクリプトは `build:all`(旧 `build:hooks` から変更。hooks 以外も含むため) + +### リネーム一覧 + +| 旧名 | 新名 | 理由 | +|---|---|---| +| `hooks-push-pipeline` | `cli-push-pipeline` | hooks プロトコル非準拠の独立 CLI | +| `hooks-post-pr-monitor` | `cli-pr-monitor` | 同上。`post-` は呼び出しタイミングであり名前に含めない | +| `hooks-report-formatter` | `lib-report-formatter` | exe ではなくライブラリクレート | +| `build:hooks` | `build:all` | hooks 以外の CLI / lib も含む一括ビルド | + +### 変更しないもの + +| 名前 | 理由 | +|---|---| +| `hooks-pre-tool-validate` | Claude Code PreToolUse hooks そのもの — `hooks-` が正確 | +| `hooks-post-tool-linter` | Claude Code PostToolUse hooks そのもの | +| `hooks-stop-quality` | Claude Code Stop hooks そのもの | +| `hooks-session-start` | Claude Code SessionStart hooks そのもの | +| `check-ci-coderabbit` | 補助 CLI。`cli-` を付けてもよいが、既に役割が明確なため据え置き | + +## 影響 + +### Positive + +- `src/` を `ls` するだけで hooks / CLI / lib の区別がつき、コーディング AI が適切な前提で作業できる +- 新しいクレート追加時に「どのプレフィックスを付けるか」で設計判断が明示される +- `build:all` への統一により、「hooks しかビルドされない」という誤解が解消される + +### Negative + +- 既存の ADR・ドキュメント内の旧名を一括置換する必要がある(本 ADR と同一コミットで対応済み) +- 派生プロジェクト(`deploy:hooks` の配布先)で exe ファイル名が変わるため、`hooks-config.toml` や `pnpm push` スクリプトの更新が必要 + +### ADR-010 への影響 + +ADR-010 のディレクトリ構成図・ビルド戦略の記述を本 ADR の命名規約に合わせて更新済み。`build:hooks` → `build:all` の変更、`.gitignore` の glob 化(`.claude/*.exe`, `src/*/target/`)も反映。 + +## References + +- [ADR-008: Push Pipeline ハーネスの実装](adr-008-push-pipeline-harness.md) — `cli-push-pipeline` の設計背景 +- [ADR-009: Post-PR Monitor](adr-009-post-pr-monitor.md) — `cli-pr-monitor` の設計背景 +- [ADR-010: hooks の配置規則とビルド戦略 v2](adr-010-hooks-layout-and-build-strategy-v2.md) — ディレクトリ構成の親 ADR diff --git a/docs/todo.md b/docs/todo.md index 3d6a7899..081a877b 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,6 +1,6 @@ # TODO -## hooks-post-pr-monitor Known Issues (PR #13) +## cli-pr-monitor Known Issues (PR #13) - [x] **改行を含む `--body` が切り詰められる**: `--body` に改行 (`\n` リテラルまたは実改行) を検出した場合、一時ファイルに書き出して `--body-file` に自動変換する方式に変更 - [x] **PR 番号パースが失敗する (pr=None)**: `gh pr create` の stdout 出力 (PR URL) から `parse_pr_number_from_url()` で番号を直接抽出するよう修正。フォールバックとして `get_pr_info()` の多段検索 (gh pr view → jj bookmark + gh pr list --head) も追加 @@ -9,4 +9,4 @@ ## CronCreate セッション問題 (PR #16 調査で発見) -- [ ] **CronCreate がサブセッションに閉じ込められる**: `pnpm push` 実行時、`review:ai` (`claude -p "/pre-push-review"`) のサブセッションが「最新セッション」となり、後続の `hooks-post-pr-monitor --monitor-only` の `--continue` がサブセッションに接続してしまう。SessionStart hook でメインセッション ID を `.session-id` ファイルに記録し、`--resume ` で明示指定する方式に修正 +- [ ] **CronCreate がサブセッションに閉じ込められる**: `pnpm push` 実行時、`review:ai` (`claude -p "/pre-push-review"`) のサブセッションが「最新セッション」となり、後続の `cli-pr-monitor --monitor-only` の `--continue` がサブセッションに接続してしまう。SessionStart hook でメインセッション ID を `.session-id` ファイルに記録し、`--resume ` で明示指定する方式に修正 diff --git a/package.json b/package.json index 25af4ade..0e78cb91 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,17 @@ "build:hooks-pre-tool-validate": "cd src/hooks-pre-tool-validate && cargo build --release && cp target/release/hooks-pre-tool-validate.exe ../../.claude/hooks-pre-tool-validate.exe", "build:hooks-post-tool-linter": "cd src/hooks-post-tool-linter && cargo build --release && cp target/release/hooks-post-tool-linter.exe ../../.claude/hooks-post-tool-linter.exe", "build:hooks-stop-quality": "cd src/hooks-stop-quality && cargo build --release && cp target/release/hooks-stop-quality.exe ../../.claude/hooks-stop-quality.exe", - "build:hooks-push-pipeline": "cd src/hooks-push-pipeline && cargo build --release && cp target/release/hooks-push-pipeline.exe ../../.claude/hooks-push-pipeline.exe", - "build:hooks-post-pr-monitor": "cd src/hooks-post-pr-monitor && cargo build --release && cp target/release/hooks-post-pr-monitor.exe ../../.claude/hooks-post-pr-monitor.exe", + "build:cli-push-pipeline": "cd src/cli-push-pipeline && cargo build --release && cp target/release/cli-push-pipeline.exe ../../.claude/cli-push-pipeline.exe", + "build:cli-pr-monitor": "cd src/cli-pr-monitor && cargo build --release && cp target/release/cli-pr-monitor.exe ../../.claude/cli-pr-monitor.exe", "build:check-ci-coderabbit": "cd src/check-ci-coderabbit && cargo build --release && cp target/release/check-ci-coderabbit.exe ../../.claude/check-ci-coderabbit.exe", "build:hooks-session-start": "cd src/hooks-session-start && cargo build --release && cp target/release/hooks-session-start.exe ../../.claude/hooks-session-start.exe", "build:hooks-settings": "node -e \"const fs=require('fs');const t=fs.readFileSync('.claude/settings.local.json.template','utf8');const p=process.cwd().replace(/\\\\/g,'\\\\\\\\');fs.writeFileSync('.claude/settings.local.json',t.replace(/\\{\\{PROJECT_DIR\\}\\}/g,p))\" && echo settings.local.json generated", - "build:hooks": "pnpm build:hooks-session-start && pnpm build:hooks-pre-tool-validate && pnpm build:hooks-post-tool-linter && pnpm build:hooks-stop-quality && pnpm build:hooks-push-pipeline && pnpm build:hooks-post-pr-monitor && pnpm build:check-ci-coderabbit && pnpm build:hooks-settings", + "build:all": "pnpm build:hooks-session-start && pnpm build:hooks-pre-tool-validate && pnpm build:hooks-post-tool-linter && pnpm build:hooks-stop-quality && pnpm build:cli-push-pipeline && pnpm build:cli-pr-monitor && pnpm build:check-ci-coderabbit && pnpm build:hooks-settings", "review:ai": "claude -p \"/pre-push-review\"", - "push": ".\\.claude\\hooks-push-pipeline.exe && .\\.claude\\hooks-post-pr-monitor.exe --monitor-only", - "pr-create": ".\\.claude\\hooks-post-pr-monitor.exe", + "push": ".\\.claude\\cli-push-pipeline.exe && .\\.claude\\cli-pr-monitor.exe --monitor-only", + "pr-create": ".\\.claude\\cli-pr-monitor.exe", "check-ci": ".\\.claude\\check-ci-coderabbit.exe", - "mark-notified": ".\\.claude\\hooks-post-pr-monitor.exe --mark-notified", + "mark-notified": ".\\.claude\\cli-pr-monitor.exe --mark-notified", "check-monitor": "type .\\.claude\\pr-monitor-state.json 2>NUL || echo No active monitor", "deploy:hooks": "npx tsx scripts/deploy-hooks.ts", "py-lint": "ruff check src/", diff --git a/scripts/deploy-hooks.ts b/scripts/deploy-hooks.ts index fbd1f442..ecbcfc0d 100644 --- a/scripts/deploy-hooks.ts +++ b/scripts/deploy-hooks.ts @@ -23,8 +23,8 @@ const EXE_FILES = [ "hooks-pre-tool-validate.exe", "hooks-post-tool-linter.exe", "hooks-stop-quality.exe", - "hooks-push-pipeline.exe", - "hooks-post-pr-monitor.exe", + "cli-push-pipeline.exe", + "cli-pr-monitor.exe", "check-ci-coderabbit.exe", ]; @@ -82,7 +82,7 @@ function deployTo(targetDir: string): boolean { for (const exe of EXE_FILES) { const src = join(CLAUDE_DIR, exe); if (!existsSync(src)) { - logger.warn(` ${exe} not found (run pnpm build:hooks first)`); + logger.warn(` ${exe} not found (run pnpm build:all first)`); continue; } copyFile(src, join(targetClaude, exe)); diff --git a/src/check-ci-coderabbit/Cargo.lock b/src/check-ci-coderabbit/Cargo.lock index 857828c2..a0f29fe1 100644 --- a/src/check-ci-coderabbit/Cargo.lock +++ b/src/check-ci-coderabbit/Cargo.lock @@ -15,26 +15,26 @@ dependencies = [ name = "check-ci-coderabbit" version = "0.1.0" dependencies = [ - "hooks-report-formatter", + "lib-report-formatter", "regex", "serde", "serde_json", ] [[package]] -name = "hooks-report-formatter" +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lib-report-formatter" version = "0.1.0" dependencies = [ "serde", "serde_json", ] -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - [[package]] name = "memchr" version = "2.8.0" diff --git a/src/check-ci-coderabbit/Cargo.toml b/src/check-ci-coderabbit/Cargo.toml index 4f966b9b..6c10a184 100644 --- a/src/check-ci-coderabbit/Cargo.toml +++ b/src/check-ci-coderabbit/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" regex = "1" -hooks-report-formatter = { path = "../hooks-report-formatter" } +lib-report-formatter = { path = "../lib-report-formatter" } [profile.release] opt-level = 3 diff --git a/src/check-ci-coderabbit/src/main.rs b/src/check-ci-coderabbit/src/main.rs index 127d7311..c6a63283 100644 --- a/src/check-ci-coderabbit/src/main.rs +++ b/src/check-ci-coderabbit/src/main.rs @@ -11,7 +11,7 @@ //! 0 - チェック完了 (結果は stdout JSON の action フィールドを参照) //! 1 - 引数エラーまたは致命的エラー -use hooks_report_formatter::Finding; +use lib_report_formatter::Finding; use serde::{Deserialize, Serialize}; use std::process::Command; use std::time::Duration; diff --git a/src/hooks-post-pr-monitor/Cargo.lock b/src/cli-pr-monitor/Cargo.lock similarity index 98% rename from src/hooks-post-pr-monitor/Cargo.lock rename to src/cli-pr-monitor/Cargo.lock index 2a0a3343..f621bd31 100644 --- a/src/hooks-post-pr-monitor/Cargo.lock +++ b/src/cli-pr-monitor/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "cli-pr-monitor" +version = "0.1.0" +dependencies = [ + "lib-report-formatter", + "serde", + "serde_json", + "toml", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -14,24 +24,6 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -[[package]] -name = "hooks-post-pr-monitor" -version = "0.1.0" -dependencies = [ - "hooks-report-formatter", - "serde", - "serde_json", - "toml", -] - -[[package]] -name = "hooks-report-formatter" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "indexmap" version = "2.13.0" @@ -48,6 +40,14 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "lib-report-formatter" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "memchr" version = "2.8.0" diff --git a/src/hooks-post-pr-monitor/Cargo.toml b/src/cli-pr-monitor/Cargo.toml similarity index 67% rename from src/hooks-post-pr-monitor/Cargo.toml rename to src/cli-pr-monitor/Cargo.toml index 7ade77aa..46a68e84 100644 --- a/src/hooks-post-pr-monitor/Cargo.toml +++ b/src/cli-pr-monitor/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hooks-post-pr-monitor" +name = "cli-pr-monitor" version = "0.1.0" edition = "2021" @@ -7,7 +7,7 @@ edition = "2021" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" toml = "0.8" -hooks-report-formatter = { path = "../hooks-report-formatter" } +lib-report-formatter = { path = "../lib-report-formatter" } [profile.release] opt-level = 3 diff --git a/src/hooks-post-pr-monitor/src/main.rs b/src/cli-pr-monitor/src/main.rs similarity index 97% rename from src/hooks-post-pr-monitor/src/main.rs rename to src/cli-pr-monitor/src/main.rs index b41c4439..567058bd 100644 --- a/src/hooks-post-pr-monitor/src/main.rs +++ b/src/cli-pr-monitor/src/main.rs @@ -20,7 +20,7 @@ //! 0 - 正常終了 //! 1 - gh pr create 失敗 (PR 作成モードのみ) -use hooks_report_formatter::Finding; +use lib_report_formatter::Finding; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -165,34 +165,17 @@ fn truncate_safe(s: &str, max_chars: usize) -> &str { } } -// ─── パイプ排出 (push-pipeline から移植) ─── - -const MAX_LINES: usize = 40; +// ─── パイプ排出 ─── +// NOTE: push-pipeline 版は MAX_LINES=40 でログ表示用に切り詰めるが、 +// こちらは check-ci-coderabbit の JSON 出力全体をパースするため制限なし。 fn drain_pipe(pipe: impl std::io::Read + Send + 'static) -> std::thread::JoinHandle { std::thread::spawn(move || { - use std::io::BufRead; + use std::io::Read; + let mut output = String::new(); let mut reader = std::io::BufReader::new(pipe); - let mut collected = Vec::with_capacity(MAX_LINES); - let mut buf = Vec::new(); - - loop { - buf.clear(); - match reader.read_until(b'\n', &mut buf) { - Ok(0) => break, - Ok(_) => { - if collected.len() < MAX_LINES { - collected.push( - String::from_utf8_lossy(&buf) - .trim_end_matches(&['\r', '\n'][..]) - .to_string(), - ); - } - } - Err(_) => break, - } - } - collected.join("\n") + let _ = reader.read_to_string(&mut output); + output.trim_end().to_string() }) } diff --git a/src/hooks-push-pipeline/Cargo.lock b/src/cli-push-pipeline/Cargo.lock similarity index 99% rename from src/hooks-push-pipeline/Cargo.lock rename to src/cli-push-pipeline/Cargo.lock index ff36f9d9..26e3b178 100644 --- a/src/hooks-push-pipeline/Cargo.lock +++ b/src/cli-push-pipeline/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "cli-push-pipeline" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "toml", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -14,15 +23,6 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -[[package]] -name = "hooks-push-pipeline" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", - "toml", -] - [[package]] name = "indexmap" version = "2.13.0" diff --git a/src/hooks-push-pipeline/Cargo.toml b/src/cli-push-pipeline/Cargo.toml similarity index 87% rename from src/hooks-push-pipeline/Cargo.toml rename to src/cli-push-pipeline/Cargo.toml index 9dc5830a..b03c1866 100644 --- a/src/hooks-push-pipeline/Cargo.toml +++ b/src/cli-push-pipeline/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hooks-push-pipeline" +name = "cli-push-pipeline" version = "0.1.0" edition = "2021" diff --git a/src/hooks-push-pipeline/src/main.rs b/src/cli-push-pipeline/src/main.rs similarity index 100% rename from src/hooks-push-pipeline/src/main.rs rename to src/cli-push-pipeline/src/main.rs diff --git a/src/hooks-session-start/src/main.rs b/src/hooks-session-start/src/main.rs index 1d17fd2e..0141eb76 100644 --- a/src/hooks-session-start/src/main.rs +++ b/src/hooks-session-start/src/main.rs @@ -10,7 +10,7 @@ //! - 既に同じ session_id が書かれていれば何もしない (冪等) //! - 異なる ID (新セッション or サブセッション) の場合は上書きする //! -//! 現在 hooks-post-pr-monitor は daemon + state file 方式に移行済みのため +//! 現在 cli-pr-monitor は daemon + state file 方式に移行済みのため //! .session-id を直接参照しないが、将来の拡張用にこの仕組みは維持する。 use serde::Deserialize; diff --git a/src/hooks-report-formatter/Cargo.lock b/src/lib-report-formatter/Cargo.lock similarity index 98% rename from src/hooks-report-formatter/Cargo.lock rename to src/lib-report-formatter/Cargo.lock index b413ae23..90d16171 100644 --- a/src/hooks-report-formatter/Cargo.lock +++ b/src/lib-report-formatter/Cargo.lock @@ -3,7 +3,7 @@ version = 4 [[package]] -name = "hooks-report-formatter" +name = "lib-report-formatter" version = "0.1.0" dependencies = [ "serde", diff --git a/src/hooks-report-formatter/Cargo.toml b/src/lib-report-formatter/Cargo.toml similarity index 71% rename from src/hooks-report-formatter/Cargo.toml rename to src/lib-report-formatter/Cargo.toml index 15227fd2..69549785 100644 --- a/src/hooks-report-formatter/Cargo.toml +++ b/src/lib-report-formatter/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "hooks-report-formatter" +name = "lib-report-formatter" version = "0.1.0" edition = "2021" [lib] -name = "hooks_report_formatter" +name = "lib_report_formatter" path = "src/lib.rs" [dependencies] diff --git a/src/hooks-report-formatter/src/lib.rs b/src/lib-report-formatter/src/lib.rs similarity index 100% rename from src/hooks-report-formatter/src/lib.rs rename to src/lib-report-formatter/src/lib.rs