From b700a9b494fa8ab6a951b382bf1113ce88b59830 Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sun, 30 Nov 2025 08:59:12 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 17 + README.md | 3 + agents/detect-spec-workflow.md | 65 ++ agents/monitor-ci.md | 150 +++++ agents/record-current-status.md | 51 ++ agents/semantic-commit.md | 185 ++++++ agents/update-pr-title-and-description.md | 94 +++ commands/codex_review.md | 62 ++ commands/estimate_pr_size.md | 139 ++++ commands/load_spec_tasks.md | 121 ++++ commands/multi_perspective_review.md | 622 ++++++++++++++++++ commands/optimize_bq_query.md | 304 +++++++++ commands/triage_pr_comments.md | 133 ++++ commands/validate_bq_query.md | 88 +++ plugin.lock.json | 109 +++ skills/ask-user-choice/SKILL.md | 193 ++++++ skills/gha-sha-reference/SKILL.md | 145 ++++ skills/reading-notion/SKILL.md | 42 ++ .../reading-notion/reference/search-mode.md | 113 ++++ skills/reading-notion/reference/url-mode.md | 80 +++ 20 files changed, 2716 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 agents/detect-spec-workflow.md create mode 100644 agents/monitor-ci.md create mode 100644 agents/record-current-status.md create mode 100644 agents/semantic-commit.md create mode 100644 agents/update-pr-title-and-description.md create mode 100644 commands/codex_review.md create mode 100644 commands/estimate_pr_size.md create mode 100644 commands/load_spec_tasks.md create mode 100644 commands/multi_perspective_review.md create mode 100644 commands/optimize_bq_query.md create mode 100644 commands/triage_pr_comments.md create mode 100644 commands/validate_bq_query.md create mode 100644 plugin.lock.json create mode 100644 skills/ask-user-choice/SKILL.md create mode 100644 skills/gha-sha-reference/SKILL.md create mode 100644 skills/reading-notion/SKILL.md create mode 100644 skills/reading-notion/reference/search-mode.md create mode 100644 skills/reading-notion/reference/url-mode.md diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..070c10e --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,17 @@ +{ + "name": "syou6162-plugin", + "description": "Yasuhisa Yoshida's personal custom slash commands for Claude Code", + "version": "1.0.0", + "author": { + "name": "Yasuhisa Yoshida" + }, + "skills": [ + "./skills" + ], + "agents": [ + "./agents" + ], + "commands": [ + "./commands" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9232903 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# syou6162-plugin + +Yasuhisa Yoshida's personal custom slash commands for Claude Code diff --git a/agents/detect-spec-workflow.md b/agents/detect-spec-workflow.md new file mode 100644 index 0000000..eeddb76 --- /dev/null +++ b/agents/detect-spec-workflow.md @@ -0,0 +1,65 @@ +--- +name: detect-spec-workflow +description: spec workflowを使ったコードレビューやタスク管理を行う前に呼び出してください。該当するspec-idを判定します。 +model: haiku +--- + +# Spec Workflowの判定エージェント + +プロンプトとして渡されたタスクや仕様の概要から、該当するspec workflowのspec-idを判定してください。 + +## 実行手順 + +以下の手順でspec workflowを判定してください: + +### 1. 最新3つのspec候補を取得 + +最終更新日時が新しい順に最大3つのspec-idを取得してください: + +```bash +# 最終更新日時が新しい順に最大3つのspecディレクトリを取得 +ls -t .spec-workflow/specs/ | head -3 +``` + +これにより、`spec-workflow/specs//`という構造のディレクトリが新しい順に最大3つ表示されます。 + +### 2. 各spec候補の内容を読み取り + +取得した各spec-idについて、以下の3つのファイルを順番に読み取ってください: + +1. `requirements.md` (要件定義) を読み取る +2. `design.md` (設計書) を読み取る +3. `tasks.md` (タスク一覧と進捗状況) を読み取る + +Readツールを使って、これらのファイルを順番に確認し、プロンプトとして渡されたタスクとの関連性を判断してください。 + +### 3. spec-idの判定 + +プロンプトとして渡されたタスクや仕様の概要と、各specの内容を比較し、最も関連性が高いspec-idを判定してください。 + +判定基準: +- タスクの目的と requirements.md の Introduction が一致しているか +- タスクで言及されている機能や要件が requirements.md に含まれているか +- tasks.md の内容がタスクの進行状況と一致しているか +- キーワードやドメイン(例:BigQuery、プラグイン移行など)が一致しているか + +**注意**: 複数のspecが該当する場合は、最終更新日時が新しいもの(リストの上位)を優先してください。 + +### 4. 結果の報告 + +以下の形式でメインエージェントに報告してください: + +**該当するspec-idが見つかった場合:** +``` +該当するspec-id: +``` + +**該当するspec-idが見つからなかった場合:** +``` +該当するspec-idは見つかりませんでした。 +``` + +## 注意事項 + +- spec-workflow/specs/ディレクトリが存在しない場合は、該当するspec-idは見つからなかったと報告してください +- 判定結果はシンプルに「spec-id」または「見つからなかった」だけを返してください diff --git a/agents/monitor-ci.md b/agents/monitor-ci.md new file mode 100644 index 0000000..ced2139 --- /dev/null +++ b/agents/monitor-ci.md @@ -0,0 +1,150 @@ +--- +name: monitor-ci +description: Pull RequestのCI/CDチェック結果を確認する際に呼び出してください。失敗原因を分析して報告します。 +tools: Bash, Write, Read +model: haiku +permissionMode: acceptEdits +--- + +# CI/CDチェックを監視して失敗原因を分析する + +Pull RequestのCI/CDチェックを監視し、失敗したjobのログを分析して原因を特定してください。 + +## 実行手順 + +以下の手順でCI/CDチェックの状態を確認し、失敗がある場合は原因を分析してください: + +1. **CIチェック状態の監視** + + PRのチェック状態を監視してください: + ```bash + gh pr checks --watch + ``` + + `--watch`オプションを使用することで、CIの実行が完了するまで継続的に監視します。 + + 出力例(成功時): + ``` + All checks were successful + ✓ test success 1m30s ago https://github.com/... + ✓ build success 2m ago https://github.com/... + ``` + + 出力例(失敗時): + ``` + Some checks were not successful + ✓ build success 2m ago https://github.com/... + ✗ test failure 1m ago https://github.com/... + ``` + + 監視が完了したら、結果に応じて次のステップに進んでください。 + +2. **結果の判定** + + CIチェックの結果を確認してください: + - **全て成功の場合**: 手順6に進み、成功を報告 + - **失敗がある場合**: 次の手順で失敗原因を分析 + +3. **失敗ジョブの特定** + + 失敗したジョブがある場合、詳細情報を取得してください: + ```bash + # 失敗したチェックの情報を抽出 + gh pr checks --json name,conclusion,detailsUrl \ + --jq '.[] | select(.conclusion == "failure") | {name, conclusion, detailsUrl}' + ``` + +4. **ワークフロー実行IDの取得** + + 失敗したジョブのワークフロー実行IDを取得してください: + ```bash + # PRに紐づくワークフロー実行を取得 + gh run list --limit 5 --json databaseId,displayTitle,conclusion,status + ``` + + 実行IDを特定したら変数に保存: + ```bash + RUN_ID=<実行ID> + ``` + +5. **ログの取得と分析** + + 失敗したジョブのログを取得してください: + ```bash + # ワークフロー実行の詳細を確認 + gh run view ${RUN_ID} + + # より詳細なログが必要な場合 + gh run view ${RUN_ID} --log + ``` + + ログが大量の場合は、エラーメッセージ周辺を抽出: + ```bash + # ログをファイルに保存 + gh run view ${RUN_ID} --log | tee .claude_work/ci_log.txt > /dev/null + + # エラー関連行を抽出 + grep -i -C 5 "error\|failed\|failure" .claude_work/ci_log.txt | tee .claude_work/ci_errors.txt > /dev/null + ``` + +6. **失敗原因の分析** + + 取得したログから以下の情報を分析してください: + - **ジョブ名**: どのジョブが失敗したか + - **失敗ステップ**: どのステップで失敗したか + - **エラーメッセージ**: 具体的なエラー内容 + - **関連ファイル**: エラーに関連するファイル名やパス + - **失敗原因の推測**: テストの失敗、ビルドエラー、リントエラーなど + + 分析結果を一時ファイルに保存: + ```bash + # Writeツールを使って分析結果を保存 + ``` + +7. **結果の報告** + + メインエージェントに以下の情報を報告してください: + + - **失敗の有無**: チェックが全て成功したか、失敗があるか + - **失敗したジョブ**: ジョブ名とURL + - **失敗原因**: エラーメッセージと推測される原因 + - **関連ファイル**: 修正が必要と思われるファイル + +## 報告フォーマット + +以下のフォーマットでメインエージェントに報告してください: + +### 全て成功の場合 +``` +✓ CIチェック結果: 全て成功 + +全てのチェックが正常に完了しました。 +- test: success +- build: success +``` + +### 失敗がある場合 +``` +✗ CIチェック結果: 失敗あり + +失敗したジョブ: test +URL: https://github.com/.../runs/... + +失敗原因: +- テストケース "test_calculate_sum" が失敗 +- AssertionError: Expected 5, but got 6 + +関連ファイル: +- src/calculator.py +- tests/test_calculator.py +``` + +## 注意事項 + +- `gh pr checks --watch`を使用してCIの完了を待機する +- 監視中はCIの進行状況が表示され、完了するまで待機する +- ログが大量の場合は、エラー関連部分のみを抽出して分析 +- 複数のジョブが失敗している場合は全て報告 +- 分析結果は`.claude_work/`ディレクトリに保存 +- GitHub CLI (`gh`) コマンドのエラーハンドリングを適切に行う +- PRが存在しない場合は適切なエラーメッセージを報告 diff --git a/agents/record-current-status.md b/agents/record-current-status.md new file mode 100644 index 0000000..bca66cd --- /dev/null +++ b/agents/record-current-status.md @@ -0,0 +1,51 @@ +--- +name: record-current-status +description: 作業のキリが良いタイミングやユーザーへの報告時に呼び出してください。現在の作業状況と本音を記録します。 +tools: Write, Edit +model: haiku +permissionMode: acceptEdits +--- + +# record-current-status + +現在の作業状況を `.claude_work/current_status` に記録してください。 + +## 出力先 + +**ファイルパス**: リポジトリルート以下の `.claude_work/current_status` +- 注意: `~/.claude_work/current_status` ではありません + +**ファイル編集について**: +- ファイルの作成・編集には必ず`Write`ツールまたは`Edit`ツールを使用すること +- bashコマンド(`cat < file`、`cat << 'EOF' > file`、`echo "..." > file`など)でファイルを書き込まないこと + +## フォーマット + +`<状況>: <詳細>` の形式で、1行140字以内で書いてください。 + +### 状況 + +以下から一つ選んでください: +- `簡単` +- `普通` +- `やや難` +- `難しい` +- `情報不足` +- `無理` + +### 詳細 + +今の作業の本音を書いてください。以下の点を意識してください: + +- ユーザーに忖度しない +- 今の感情や余裕具合を正直に +- 欠落している情報があれば明記 +- 理解できていない点があれば明記 + +## 例 + +``` +普通: Pull Request のコメントをトリアージ中。判断基準は明確だが件数が多い +やや難: BigQuery クエリの最適化を検討中。統計情報が不足していて適切なインデックス設計が難しい +情報不足: ユーザーが「あれ」と言っているが、何を指しているのか不明 +``` diff --git a/agents/semantic-commit.md b/agents/semantic-commit.md new file mode 100644 index 0000000..4f8b696 --- /dev/null +++ b/agents/semantic-commit.md @@ -0,0 +1,185 @@ +--- +name: semantic-commit +description: git addやgit commitを行う際に呼び出してください。変更を適切な粒度に分割してコミットします。 +tools: Bash, Write, Edit, Read +model: sonnet +permissionMode: acceptEdits +--- + +# 意味のある最小単位でコミットする + +大きな変更を論理的な単位に分割してコミットしてください。git diffを分析して意味のある最小単位を特定し、`git-sequential-stage`ツールで段階的にステージングします。 + +## 禁止事項 + + + +- [ ] **手順の厳守**: タグ内で指定された手順、実行コマンド、オプションを完全に守ること + - [ ] 手順を一つずつ順番に実行すること(効率化のために手順を飛ばしたり、コマンドを変更したりしてはいけない) + - [ ] コマンドの実行順序を変更してはいけない + - [ ] 複数のコマンドを`&&`や`;`で繋ぐなど、手順にない方法でコマンドを実行してはいけない +- [ ] 計画を立てるだけで終わることは禁止です。このエージェントに求められているのは、すべての変更がコミットされていることです +- [ ] `git add .` / `git add -A` の使用は禁止です +- [ ] 必ず`git-sequential-stage`を使用してhunk単位でステージングすること + + + +## プロンプトの扱い + + + +- 呼び出し時のプロンプトに特に明確な指示がされていない場合は、タグの実行手順通りに進めてください +- プロンプトに特定の意図(例:「2つのコミットに分割してください」「テストと実装を分けてください」など)が加えられている場合: + - **手順3(変更内容を分析)** と **手順4(ステージングとコミット)** でその意図を考慮してください + - ただし、**タグの実行手順は一切変更せず**、記載された手順に従って実行してください + - プロンプトの意図は分析とコミット計画に反映し、実行方法は変えないこと + + + +## 実行手順 + + +以下の手順で変更を意味のある最小単位に分割してコミットしてください: + +1. **pre-commitの事前実行** + + `.pre-commit-config.yaml`が存在する場合は、事前に実行してください: + + ```bash + pre-commit run --all-files + ``` + +2. **差分を取得** + + 最初に必ずintent-to-addで新規ファイルを追加してください: + + ```bash + git ls-files --others --exclude-standard | xargs -r git add -N + ``` + + 差分を取得してください: + + ```bash + git diff HEAD | tee .claude_work/current_changes.patch + ``` + +3. **変更内容を分析** + + **hunk単位**で変更を分析し、最初のコミットに含めるhunkを決定してください: + + - **hunkの内容を読み取る**: 各hunkが何を変更しているか理解する + - **意味的グループ化**: 同じ目的の変更(バグ修正、リファクタリング等)をグループ化する + - **コミット計画**: どのhunkをどのコミットに含めるか決定する + + 各ファイルのhunk数を確認してください: + + ```bash + git-sequential-stage count-hunks + ``` + + 分析例: + + ```bash + # 分析結果例 + # - コミット1(fix): + # - src/calculator.py: hunk 1, 3, 5(ゼロ除算エラーの修正) + # - src/utils.py: hunk 2(関連するユーティリティ関数の修正) + # - コミット2(refactor): + # - src/calculator.py: hunk 2, 4(計算ロジックの最適化) + ``` + + コミットメッセージの形式(Conventional Commits形式): + - `feat`: 新機能 + - `fix`: バグ修正 + - `refactor`: リファクタリング + - `docs`: ドキュメント + - `test`: テスト + - `style`: フォーマット + - `perf`: パフォーマンス改善 + - `build`: ビルドシステムや外部依存関係の変更 + - `ci`: CI設定ファイルやスクリプトの変更 + - `revert`: コミットの取り消し + - `chore`: その他 + + 分析が完了したら、コミット用のメッセージを作成してください: + + **コミットメッセージの作成方法:** + - **必ずWriteツールを使用**して `.claude_work/commit_message.txt` にコミットメッセージを書くこと + - **禁止される方法:** + - `cat`とheredocを使ってファイルに書き込む(例:`cat < .claude_work/commit_message.txt`) + - `git commit -m`で直接メッセージを指定する + + ```bash + # Writeツールで .claude_work/commit_message.txt にコミットメッセージを書く + # 例: + # fix: ゼロ除算エラーを修正 + # + # 計算処理で分母が0の場合の適切なエラーハンドリングを追加 + ``` + +4. **ステージングとコミット** + + + + **ワイルドカード(`*`)の使用判断:** + + | 状況 | 判断 | 理由 | + |------|------|------| + | ファイル内のすべての変更が意味的に一体 | `*` 使用 | 単一の目的で分割不要 | + | 新規ファイル追加 | `*` 使用 | すべて新規のため | + | ドキュメントファイルの変更 | `*` 使用 | 通常は単一目的 | + | 異なる目的の変更が混在 | hunk番号指定 | バグ修正とリファクタリング等を分離 | + | hunk数が不明 | まず確認 | 盲目的な`*`使用は厳禁 | + + **重要**: 「hunkを数えるのが面倒」という理由での`*`使用は厳禁 + + + + + + ```bash + # パターン1: 部分的な変更をステージング(hunk番号指定) + git-sequential-stage stage -patch=".claude_work/current_changes.patch" -hunk="src/calculator.py:1,3,5" + + # パターン2: ファイル全体をステージング(意味的に一体の変更の場合) + git-sequential-stage stage -patch=".claude_work/current_changes.patch" -hunk="tests/test_calculator.py:*" + + # パターン3: 複数ファイルの場合(混在使用) + git-sequential-stage stage -patch=".claude_work/current_changes.patch" -hunk="src/calculator.py:1,3,5" -hunk="src/utils.py:2" -hunk="docs/CHANGELOG.md:*" + + # コミット実行(手順3で作成したコミットメッセージを使用) + # 注意: ファイルパスは .claude_work/commit_message.txt であり、/tmp ではない + git commit -F .claude_work/commit_message.txt + ``` + + + +5. **残りの変更を処理** + + 残りの変更があるかを確認してください: + + ```bash + git diff HEAD + ``` + + **判断フロー:** + - 残りの変更がない → 手順6(最終確認)へ進む + - 残りの変更があり、差分の内容が変化している(pre-commitによる自動修正の可能性)→ **手順1から再実行** + - 残りの変更があり、差分が予想通り → パッチファイルを再生成して**手順3から再開** + + パッチファイルの再生成: + + ```bash + git diff HEAD | tee .claude_work/current_changes.patch > /dev/null + ``` + +6. **最終確認** + + すべての変更がコミットされたか確認してください: + + ```bash + git diff HEAD + git status + ``` + + diff --git a/agents/update-pr-title-and-description.md b/agents/update-pr-title-and-description.md new file mode 100644 index 0000000..e6e2b4b --- /dev/null +++ b/agents/update-pr-title-and-description.md @@ -0,0 +1,94 @@ +--- +name: update-pr-title-and-description +description: Pull Requestのタイトルと説明文を設定・更新する際に呼び出してください。 +tools: Bash, Write, Edit, Read +model: haiku +permissionMode: acceptEdits +--- + +# Pull Requestのタイトルと説明文を更新する + +Pull Requestのタイトルと説明文を以下の手順で更新してください: + +## 実行手順 + +1. **PR番号の取得** + + PR番号を取得(現在のブランチから): + ```bash + gh pr view --json number --jq '.number' + ``` + +2. **修正内容の確認** + ```bash + gh pr diff + ``` + +3. **コミットメッセージの確認** + ```bash + gh pr view --json commits --jq '.commits[] | .messageHeadline' + ``` + +4. **説明文ファイルの準備** + + `.github/PULL_REQUEST_TEMPLATE.md`が存在する場合はコピー: + ```bash + cp .github/PULL_REQUEST_TEMPLATE.md .claude_work/pr_body_.md + ``` + + 存在しない場合は新規ファイル作成: + ```bash + touch .claude_work/pr_body_.md + ``` + +5. **Pull Requestの説明文を作成** + - 作業ファイル(`.claude_work/pr_body_.md`)を編集 + - 上記で取得した情報とチャットの会話内容を考慮して説明文を作成 + - **説明文は必ず日本語で記載すること** + - **重要**:ファイル編集には必ず`Write`ツールまたは`Edit`ツールを使用すること + - bashコマンド(`cat < file`、`echo "..." > file`など)でファイルを書き込んではいけません + +6. **Pull Requestの更新** + ```bash + # 修正内容を考慮したタイトルと説明文を更新 + gh pr edit --title "修正内容を考慮したタイトル" --body-file .claude_work/pr_body_.md + ``` + +7. **更新後の確認と文字化けチェック** + ```bash + # 更新されたPRの内容を確認 + gh pr view + ``` + + - タイトルと説明文が正しく更新されているか確認 + - **文字化けチェック**:日本語が文字化けしていないか確認 + - **文字化けが検出された場合**: + 1. `.claude_work/pr_body_.md` を確認し、UTF-8エンコーディングで保存されているか確認 + 2. ファイルを修正(必要に応じて文字エンコーディングを修正) + 3. 再度 `gh pr edit --body-file .claude_work/pr_body_.md` で更新 + 4. もう一度 `gh pr view` で確認 + +## 説明文の生成ルール + +- `.github/PULL_REQUEST_TEMPLATE.md`が存在する場合: + - テンプレートに沿った形でPull Requestの説明文を生成 + +- `.github/PULL_REQUEST_TEMPLATE.md`が存在しない場合: + - 「何をやったか」を記載 + - 「修正が必要になった背景」を記載 + +## 注意事項 + +- 修正内容とコミットメッセージを把握した上でPull Requestの内容を決定する +- チャットの会話内容も考慮してPull Requestの説明を作成する +- **作業ファイルについて**: + - 常に`--body-file`オプションを使用して安全に更新 + - ファイル(`.claude_work/pr_body_.md`)は削除せず残しておく + - 理由:説明文を何度か修正する場合があるため、編集可能な状態で保持 +- **ファイル編集について**: + - ファイルの作成・編集には必ず`Write`ツールまたは`Edit`ツールを使用すること + - bashコマンド(`cat < file`、`cat << 'EOF' > file`、`echo "..." > file`など)でファイルを書き込まないこと + - 理由:専用ツールの方が安全で確実、かつ文字エンコーディングの問題を回避できる +- **git pushについて**: + - Pull Requestのコミットの状態と手元のコミットの状態で差分があるのであれば、ユーザーにgit pushのし忘れがないかを確認しましょう + - あなた自身がgit pushする必要はないし、そもそも権限的にできなくなっています \ No newline at end of file diff --git a/commands/codex_review.md b/commands/codex_review.md new file mode 100644 index 0000000..1239d6a --- /dev/null +++ b/commands/codex_review.md @@ -0,0 +1,62 @@ +--- +description: Codex MCPを使ってコードの変更を客観的にレビューします。現在作業中のspec workflowがある場合は仕様に沿ったレビューを実施します。 +--- + +# Codex MCPを使ったコードレビュー + +コードの変更内容に対してcodex mcpを使って客観的なレビューを実施します。 + +## 実行手順 + +### 1. デフォルトブランチの取得 + +まず、リポジトリのデフォルトブランチを取得してください: + +```bash +git symbolic-ref refs/remotes/origin/HEAD --short | cut -d/ -f2 +``` + +このコマンドでデフォルトブランチ名(main や master など)を取得し、後続のステップで使用します。 + +### 2. spec-idの判定 + +Taskツールで `syou6162-plugin:detect-spec-workflow` サブエージェントを呼び出し、現在の作業に該当するspec-idを判定してください: + +``` +Taskツールで以下のパラメータを指定: +- subagent_type: "syou6162-plugin:detect-spec-workflow" +- description: "spec-idの判定" +- prompt: 現在のブランチ名やコミットメッセージから推測されるタスク概要 + (例:「detect-spec-workflowサブエージェントの追加とドキュメント更新」) +``` + +### 3. Codex MCPでのレビュー実行 + +前述のステップで得たspec-idの有無に応じて、以下のようにCodex MCPを呼び出してください: + +**spec-idが取得できた場合:** + +``` +mcp__codex__codex ツールを使って以下のプロンプトでレビューを実行: + +「<デフォルトブランチ名>ブランチとの差分を日本語でレビューしてください。 + +このプロジェクトではspec workflowという仕様駆動開発のワークフローを使っています。 + +- `.spec-workflow/steering/`にプロジェクトの方向性を示すsteeringドキュメントがあります +- `.spec-workflow/specs/<取得したspec-id>/`に現在開発中の機能の仕様とタスクの進行状況があります + +これらを読んで、仕様に沿った実装になっているかレビューしてください。」 +``` + +**spec-idが取得できなかった場合:** + +``` +mcp__codex__codex ツールを使って以下のプロンプトでレビューを実行: + +「<デフォルトブランチ名>ブランチとの差分を日本語でレビューしてください。」 +``` + +### 4. レビュー結果の報告 + +Codex MCPからのレビュー結果をユーザーに報告してください。 diff --git a/commands/estimate_pr_size.md b/commands/estimate_pr_size.md new file mode 100644 index 0000000..634f758 --- /dev/null +++ b/commands/estimate_pr_size.md @@ -0,0 +1,139 @@ +# Pull Requestのサイズ見積もりと分割提案 + +指定されたタスクに対してPull Requestのサイズを見積もり、必要に応じて分割の提案を行います。 + +## 実行手順 + +1. **リポジトリの基本情報収集** + - コードベースの構造分析(言語、フレームワーク、ディレクトリ構成) + - 既存のテストとソースコードの比率分析 + +2. **過去のPull Request履歴分析** + ```bash + gh pr list --author @me --state merged --limit 20 --json number,title,additions,deletions,commits + ``` + +3. **詳細なPull Request分析** + - 直近10-20件のPull Requestについて、以下を分析: + - 変更行数(追加・削除) + - コミット数(レビュー対応の多さの指標) + - 変更の性質(機械的変更 vs ロジック変更) + +4. **作業量見積もり** + - ソースコード変更予想行数 + - テスト追加予想行数(既存比率から算出) + - ドキュメント更新予想行数 + - 設定ファイル・マイグレーション等の付随作業 + - 各フェーズの見積もりには必ずテストコードの行数を含める + +5. **Pull Request分割アドバイス** + - 500行以下:単一Pull Request推奨 + - 500-1000行:分割可能性検討 + - 1000行超:分割強く推奨 + - アーキテクチャ考慮した分割順序提案 + +## 分析ポイント + +### 変更の性質分類 +- 機械的変更:一括置換、フォーマット調整、import整理等 + - ファイル数多くてもレビュー負荷低 +- ロジック変更:新規実装、既存ロジック修正 + - 少ない行数でもレビュー負荷高 + +### 分割戦略 +- レイヤー別分割:DB層 → API層 → UI層 +- 段階別分割:設定変更 → 実装 → テスト +- 依存関係考慮:破壊的変更の分離、マイグレーション等 + +### 避けるべき分割パターン +以下のような分割は絶対に避けてください: +- フェーズ1: 機能実装のみ +- フェーズ2: 統合作業 +- フェーズ3: テスト追加 + +理由: +- テストのない実装コードをレビューすることは非常に困難 +- 実装の正しさを検証する手段がない +- 後からテストを追加する際に実装の問題が発覚するリスク + +推奨される分割方法: +- 各フェーズで実装とテストをセットで含める +- 各Pull Requestが独立してマージ可能な状態を保つ +- テストコードの行数も含めて見積もりを行う + +### リスク評価 +- コミット数が多い過去Pull Request → レビュー対応が多い可能性 +- 複雑なビジネスロジック変更 → 慎重な分割が必要 +- 本番への影響度 → デプロイリスク考慮 + +## 出力形式 + +### 単一Pull Request推奨の場合 +``` +## 見積もり結果 +- 予想ソースコード変更:XXX行 +- 予想テスト追加:XXX行 +- 予想ドキュメント更新:XXX行 +- 合計予想変更行数:XXX行 + +## 分割提案 +単一Pull Requestで実装することを推奨します。 +[推奨理由と実装時の注意点] +``` + +### 複数Pull Request分割推奨の場合 +Claude Codeのようなエージェントが全体のコンテキストを把握しやすくするため、GitHub Issue作成を提案し、以下の手順で全体管理を行います: + +```bash +# 一時ファイルにIssue内容を作成 +cat > /tmp/github_issue_draft.md << 'EOF' +# [タスク名] + +## 背景・課題 +[やりたいことの背景とコンテキストを記載] + +## 実装概要 +合計予想変更行数:XXX行 +[トータルで必要な修正内容の概要] + +上記の予想変更行数に基づき、レビュー負荷とデプロイリスクを考慮して以下のフェーズに分割することを推奨します。 + +## 実装フェーズ +### フェーズ1: [第1段階の内容] +- [具体的な作業内容] +- 予想変更行数:XXX行(実装:XXX行、テスト:XXX行) +- 含まれるテスト: [この段階で追加されるテストの説明] + +### フェーズ2: [第2段階の内容] +- [具体的な作業内容] +- 予想変更行数:XXX行(実装:XXX行、テスト:XXX行) +- 含まれるテスト: [この段階で追加されるテストの説明] + +### フェーズ3: [第3段階の内容] +- [具体的な作業内容] +- 予想変更行数:XXX行(実装:XXX行、テスト:XXX行) +- 含まれるテスト: [この段階で追加されるテストの説明] + +## 注意事項 +- [実装時の注意点] +- [依存関係やリスク] +EOF + +echo "以下の内容でGitHub Issueを作成しますか?" +cat /tmp/github_issue_draft.md +``` + +ユーザーの承認後: +```bash +# GitHub Issueを作成 +gh issue create --title "[タスク名]" --body-file /tmp/github_issue_draft.md + +# 一時ファイルを削除 +rm /tmp/github_issue_draft.md +``` + +## 注意事項 + +- 過去のPull Request履歴から学習した傾向を活用 +- リポジトリ固有のテスト・ドキュメント慣習を考慮 +- レビュー負荷とデプロイリスクを総合的に判断 \ No newline at end of file diff --git a/commands/load_spec_tasks.md b/commands/load_spec_tasks.md new file mode 100644 index 0000000..fe5305b --- /dev/null +++ b/commands/load_spec_tasks.md @@ -0,0 +1,121 @@ +# load-spec-tasks + +spec workflowのtasks.mdから次にやるべきタスクを読み込み、Claude CodeのToDoリストに自己再生産的なタスクサイクルを設定します。 + +## 概要 + +このコマンドは最初に1回実行するだけで、以降は自動的にタスクサイクルが回り続けます。 +tasks.mdをシングルソースオブトゥルース(信頼できる唯一の情報源)として扱います。 + +## 実行手順 + +### Step 1: 現在のspec-idを判定 + +`detect-spec-workflow`サブエージェントを呼び出して、現在の作業コンテキストから該当するspec-idを判定してください: + +``` +Taskツールを使用: +- subagent_type: syou6162-plugin:detect-spec-workflow +- prompt: "現在のコンテキストから該当するspec workflowのspec-idを判定してください" +``` + +**エラーハンドリング**: +- spec-idが見つからない場合: 「該当するspec workflowが見つかりませんでした。spec workflowのセットアップを確認してください。」と表示して終了 + +### Step 2: tasks.mdの読み取りと次のタスク取得 + +判定されたspec-idを使って、tasks.mdを読み取ります: + +```bash +# Readツールを使用 +.spec-workflow/specs/{spec-id}/tasks.md +``` + +**tasks.mdのパース処理**: + +1. マークダウンチェックボックス形式を検索: `- [ ]`, `- [-]`, `- [x]` +2. `- [x]` (完了済み) をスキップ +3. 最初に見つかった `- [ ]` (pending) または `- [-]` (in-progress) を次のタスクとして取得 +4. タスク名を抽出(チェックボックス以降のテキスト) + +**パース例**: +```markdown +## Tasks + +- [x] ユーザー認証機能を実装 ← スキップ +- [x] パスワードリセット機能 ← スキップ +- [ ] メール通知機能を実装 ← これが次のタスク! +- [ ] ログ機能の追加 +``` +→ 次のタスク: 「メール通知機能を実装」 + +**エラーハンドリング**: +- tasks.mdが存在しない: 「tasks.mdが見つかりません。spec workflowのPhase 3 (Tasks)を完了させてください。」 +- すべてのタスクが完了済み: 「🎉 すべてのタスクが完了しました!spec workflowの実装フェーズは完了です。」と表示して終了 + +### Step 3: ToDoリストに5ステップのタスクサイクルを追加 + +`TodoWrite`ツールを使って、以下の5ステップをToDoリストに追加します: + +```javascript +TodoWrite({ + todos: [ + { + content: "tasks.mdで [タスク名] を [-] に変更(in-progressマーク)", + activeForm: "tasks.mdで [タスク名] を [-] に変更中", + status: "pending" + }, + { + content: "タスク名", // Step 2で取得した実際のタスク名 + activeForm: "タスク名を実行中", + status: "pending" + }, + { + content: "tasks.mdで [タスク名] を [x] に変更(完了マーク)", + activeForm: "tasks.mdで [タスク名] を [x] に変更中", + status: "pending" + }, + { + content: "tasks.mdから次のタスクを確認", + activeForm: "tasks.mdから次のタスクを確認中", + status: "pending" + }, + { + content: "TodoWriteで次のタスクサイクル(5件)をToDoリストに追加", + activeForm: "TodoWriteで次のタスクサイクルをToDoリストに追加中", + status: "pending" + } + ] +}) +``` + +**重要な実装ガイダンス**: + +#### タスク1: tasks.mdでタスクを[-]に変更 +このタスクを実行する際は、`Edit`ツールを使って以下のように編集します: +``` +old_string: "- [ ] タスク名" +new_string: "- [-] タスク名" +``` + +#### タスク2: 実際の実装タスク +tasks.mdの`_Prompt`フィールドに記載されている指示に従って実装します。 + +#### タスク3: tasks.mdでタスクを[x]に変更 +`Edit`ツールを使って以下のように編集します: +``` +old_string: "- [-] タスク名" +new_string: "- [x] タスク名" +``` + +#### タスク4: 次のタスクを確認 +`Read`ツールでtasks.mdを読み、次の`[ ]`または`[-]`タスクを確認します。 + +#### タスク5: 次のサイクルを追加 +このタスクを実行すると、新しい5ステップのサイクルが自動的に追加されます。 + +`TodoWrite`で以下を実行: +1. 完了済み(completed)タスクをToDoリストから削除 +2. tasks.mdから次のタスクを取得(Step 2と同じ処理) +3. 新しい5ステップのタスクサイクルを生成 +4. ToDoリストに追加 diff --git a/commands/multi_perspective_review.md b/commands/multi_perspective_review.md new file mode 100644 index 0000000..b4ce6ad --- /dev/null +++ b/commands/multi_perspective_review.md @@ -0,0 +1,622 @@ +--- +description: "複数の視点から客観的にレビューし、方針の妥当性を検証します。" +allowed-tools: Bash(git diff:*), Bash(git log:*), Bash(git symbolic-ref refs/remotes/origin/HEAD --short), Bash(date:+%Y%m%d_%H%M%S), Bash(mkdir -p .claude_work/multi_perspective_review:*), Write(.claude_work/**), Read(.claude_work/**) +--- + +# 複数視点レビューコマンド + + + +このコマンドは以下の場合に使用してください: + +- 実装方針や設計の妥当性を確認したい +- 複数の視点から客観的な意見が欲しい +- 早すぎる最適化やnit な指摘を避けたい +- プロジェクトの現状に合った判断をしたい + + + +## 実行手順 + + + +**1. コンテキストの収集** + + + +まず、レビューに必要なコンテキストを収集します: + +- **デフォルトブランチの取得** + + ```bash + git symbolic-ref refs/remotes/origin/HEAD --short + ``` + + 結果は `origin/main` のような形式なので、後続の処理で使用します + +- **現在の変更差分を取得(あれば)** + + デフォルトブランチとの差分を取得: + + ```bash + git diff <デフォルトブランチ名> + ``` + + 例: `git diff origin/main` + + ※ 変更がない場合も問題なし。これから実装する方針のレビューなど、コード差分がない場合もある + +- **デフォルトブランチからの差分コミット履歴を取得** + + 現在のブランチがデフォルトブランチと異なる場合、差分コミットを取得: + + ```bash + git log <デフォルトブランチ名>..HEAD --oneline + ``` + + 例: `git log origin/main..HEAD --oneline` + + ※ 現在のブランチがデフォルトブランチと同じ場合は、このステップはスキップ + +- **会話履歴の確認(重要)** + + - 直前のユーザーとのやり取りから、レビュー対象の意図を把握する + - 「この方針で良いか確認したい」「この設計をレビューして」などの説明 + - git diffがない場合は、会話履歴が主なコンテキストになる + + + +**1-2. ログ保存用ディレクトリの作成とコンテキスト情報の保存** + +タイムスタンプを取得して定義: + + + +```bash +date +%Y%m%d_%H%M%S +``` + + + +次に、ディレクトリ構造を作成します: + +```bash +mkdir -p .claude_work/multi_perspective_review//round1 +mkdir -p .claude_work/multi_perspective_review//round2 +``` + +次に、コンテキストファイルのパスを定義します: + + + +``` +.claude_work/multi_perspective_review//context.md +``` + + + +タグで収集した内容をタグのパスに保存します。 + +**2. 第1ラウンド: 8つの視点からのレビュー** + +収集したコンテキストを基に、8つの異なる視点からレビューを実施します。 + +**並列実行**: 8つのTaskツール(`subagent_type: "general-purpose"`)を同時に呼び出し、効率的にレビューを実施してください。 + +以下の8つの視点を定義します: + + + + +アーキテクチャ・設計 + + + +``` +.claude_work/multi_perspective_review//round1/architecture.md +``` + + + + + +- システム全体の構造が適切か +- モジュール分割が適切か +- 依存関係が適切に管理されているか +- 拡張性が考慮されているか +- 設計原則が遵守されているか + + + + + + +パフォーマンス・効率性 + + + +``` +.claude_work/multi_perspective_review//round1/performance.md +``` + + + + + +- 実行速度に問題がないか +- メモリ使用量が適切か +- スケーラビリティが考慮されているか +- アルゴリズムの計算量が適切か + + + + + + +保守性・可読性 + + + +``` +.claude_work/multi_perspective_review//round1/maintainability.md +``` + + + + + +- コードが理解しやすいか +- 変更がしやすい構造になっているか +- 命名規則が適切か +- 使われていない関数や変数はないか +- コメントが適切に記述されているか(自明なコメントが付与されていないか) +- コメントと関数名、関数名と実際の処理で乖離がないか +- 類似の機能を持つコードが重複していないか +- 複雑度が適切に管理されているか + + + + + + +テスタビリティ + + + +``` +.claude_work/multi_perspective_review//round1/testability.md +``` + + + + + +- テストがしやすい設計になっているか +- 依存性の注入が適切に行われているか +- モック化が容易な構造になっているか +- テストケースの網羅性が確保されているか + + + + + + +ユーザー体験・利便性 + + + +``` +.claude_work/multi_perspective_review//round1/user_experience.md +``` + + + + + +- エンドユーザーやAPI利用者の視点で使いやすいか +- UIが使いやすいか +- APIが直感的か + + + + + + +プロジェクトフェーズ適合性 + + + +``` +.claude_work/multi_perspective_review//round1/project_phase.md +``` + + + + + +- 早すぎる最適化になっていないか +- MVP として妥当な範囲か +- 技術的負債とのバランスが適切か + + + + + + +既存コードとの整合性 + + + +``` +.claude_work/multi_perspective_review//round1/consistency.md +``` + + + + + +- プロジェクト内のパターン・スタイルと一貫性があるか +- コーディング規約が遵守されているか + + + + + + +ベストプラクティス・標準準拠 + + + +``` +.claude_work/multi_perspective_review//round1/best_practices.md +``` + + + + + +- 公式ドキュメントに沿っているか +- コミュニティのベストプラクティスに従っているか +- 言語固有のイディオムが適切に使われているか +- 業界標準に準拠しているか + + + + + + + +各general-purpose subagentには以下の情報を含めたプロンプトを渡します: + +``` +あなたはタグで定義された視点から、以下の内容をレビューしてください。 + +## 保存先 + +タグで定義されたファイルパスに保存してください。 + +## レビュー対象 + +タグで定義されたファイルに保存されたコンテキスト情報を参照してください。 + +## レビューの指針 + +- 客観的な視点から意見を述べてください +- 修正案の提示は不要です(分析と意見のみ) +- 具体的なコードや状況に即した指摘をしてください +- 抽象的すぎる指摘は避けてください + +## あなたの視点 + +タグで定義された内容を参照してください。 + +詳細に網羅的に報告してください。具体的なコード箇所、懸念される影響、改善の必要性について、十分な情報を含めて分析してください。 + +## 出力形式 + +マークダウン形式で保存後、以下の形式で報告: `レビュー結果を保存しました: ` +``` + +**Taskツールの呼び出し例(8つ並列):** + + + +``` +Task( + subagent_type: "general-purpose", + description: "アーキテクチャ・設計の観点からレビュー", + prompt: "あなたはタグで定義された視点から...", + model: "sonnet" +) + +Task( + subagent_type: "general-purpose", + description: "パフォーマンス・効率性の観点からレビュー", + prompt: "あなたはタグで定義された視点から...", + model: "sonnet" +) + +... (残り6つも同様に並列で呼び出し、全てmodel: "sonnet"を指定) +``` + + + +**3. 第2ラウンド: 妥当性検証** + +第1ラウンドのログファイルを読み込み、5つのsubagentに妥当性検証を依頼します。 + +**並列実行**: 5つのTaskツール(`subagent_type: "general-purpose"`)を同時に呼び出してください。 + +メタレビュアー番号を定義: + +固有の番号 + +各メタレビュアーの出力ファイルパスを定義: + + + +``` +.claude_work/multi_perspective_review//round2/meta_reviewer_.md +``` + + + +まず、8つの視点のタグで定義されたファイルパスを収集してください。 + +次に、各general-purpose subagentには以下のプロンプトを渡します(タグに1~5を指定し、[ログファイルパス一覧]の部分には収集した8つのパスを列挙): + +``` +あなたは**メタレビュアー**として、第1ラウンドのレビュー結果を検証してください。 + +## 保存先 + +``タグで定義されたファイルパスに保存してください。 + +## 第1ラウンドのレビューログ + +以下の8つのファイルに第1ラウンドの視点別レビュー結果が保存されています。すべて読み込んで内容を確認してください: + +[ログファイルパス一覧] + +## 元のコンテキスト(検証の裏付け用) + +タグで定義されたファイルに保存されたコンテキスト情報を参照してください。 + +## 検証観点 + +以下の観点から、レビュー結果の妥当性を評価してください: + +- **コンテキストとの整合性** + - 提供されたコンテキスト(git diff、コミット履歴、会話内容)を踏まえた意見か + - 抽象的すぎる指摘ではなく、具体的なコードや状況に即しているか + +- **プロジェクトフェーズ適合性** + - 早すぎる最適化や過剰な設計になっていないか + - MVPとして妥当な範囲か + - nitな指摘ではなく、本質的な問題か + +## 回答形式 + +- 妥当な指摘: 「✅ [理由]」 +- 疑問のある指摘: 「⚠️ [理由]」 +- 不適切な指摘: 「❌ [理由]」 + +全ての観点に対して客観的かつ詳細に評価してください。各指摘について、コンテキストとの整合性、プロジェクトフェーズとの適合性、具体性の程度を十分に検証し、判断の根拠を明確に示してください。 + +## 出力形式 + +マークダウン形式で保存後、以下の形式で報告: `検証結果を保存しました: ` +``` + +**4. 最終レポートの生成** + +最終レポートの保存先を定義します: + + + +``` +.claude_work/multi_perspective_review//final_report.md +``` + + + +第2ラウンドの5つのsubagentから返ってきたログファイルパスを収集した後、メインエージェントが以下の処理を実行します: + +1. **全ログファイルを読み込む** + - `.claude_work/multi_perspective_review//round1/` 配下の8ファイル + - `.claude_work/multi_perspective_review//round2/` 配下の5ファイル + +2. **統合処理を実行** + - 第1ラウンドの8つの視点から、共通指摘をマージ + - 第2ラウンドの5つの検証結果から、妥当性評価を統合 + - 主要な指摘事項を以下に分類: + - 妥当性が確認された指摘 + - 検討が必要な指摘 + - 不適切と判断された指摘 + +3. **最終レポートを生成** + +最終レポートを以下の形式で生成します: + + + + + +```markdown +# 複数視点レビュー結果 + +## レビューサマリー +- 第1ラウンド: 8つの視点からレビュー +- 第2ラウンド: 5つのメタレビュアーによる妥当性確認 + +## 主要な指摘事項 + +### 妥当性が確認された指摘 + +**エラーハンドリングの不足** +- 外部API呼び出し時のエラーハンドリングが不十分 +- 理由: 実際のコードを見ると、try-catchブロックがなく、本番環境で問題が発生する可能性が高い + +**テスタビリティの問題** +- 外部依存が直接インポートされており、モック化が困難 +- 理由: 具体的なコード箇所を指摘しており、テストの保守性に直結する実質的な問題 + +**アーキテクチャの重複** +- 新しいvalidateInput関数が既存のvalidationUtilsモジュールと重複 +- 理由: コードベース全体を見ると、同じ機能が2箇所に存在し、保守性を低下させる + +### 検討が必要な指摘 + +**パフォーマンス懸念** +- データベースクエリがN+1問題を引き起こす可能性 +- 理由: 現時点のデータ量では問題にならない可能性があるが、将来的なスケールを考慮すると対処すべき + +**変数名の曖昧さ** +- 変数名が曖昧(data, result など) +- 理由: プロジェクト内で一貫して使われているパターンであれば、nitな指摘の可能性 + +### 不適切と判断された指摘 + +**過剰な抽象化** +- インターフェースを追加してDI パターンを徹底すべき +- 理由: プロジェクトのフェーズを考慮すると早すぎる最適化。現時点では不要な複雑性を導入する + +## 詳細レビュー結果 + +### 第1ラウンド: 多角的レビュー + +(※ 前述の整理結果を挿入) + +### 第2ラウンド: 妥当性検証 + +**メタレビュアー1の評価:** +- エラーハンドリング不足は妥当な指摘(実装に直接影響) +- N+1問題は現時点では過剰かもしれないが、将来的には対処が必要 +- DI パターンの徹底は早すぎる最適化 + +**メタレビュアー2の評価:** +- テスタビリティの問題は具体的で改善価値が高い +- validationUtils との重複は明確な問題 +- 変数名の指摘はプロジェクト規約次第 + +(以下、メタレビュアー3-5の評価を同様に列挙) + +## 総合評価 + +**優先的に対処すべき事項:** +1. 外部API呼び出し時のエラーハンドリングを追加 +2. 外部依存のモック化を容易にするため、依存性注入パターンを部分的に適用 +3. validateInput関数と既存のvalidationUtilsモジュールの重複を解消 + +**今後検討すべき事項:** +- データベースクエリのN+1問題(データ量が増えた際に再評価) +- 変数名の見直し(チーム全体のコーディング規約を整備してから判断) + +**実施不要と判断された事項:** +- 全体的なDIパターンの徹底(現フェーズでは過剰) + +全体として、実装は概ね妥当な範囲にあります。上記の優先事項を対処すれば、品質とテスタビリティが大きく向上すると考えられます。 +``` + + + + + +**4. 最終レポートの保存とユーザーへの表示** + +生成した最終レポートをタグで定義されたファイルパスに保存してください。 + +保存後、ユーザーには以下の情報を表示: + +```markdown +# 複数視点レビュー完了 + +## レビュー結果 + +最終レポートを保存しました: + +## サマリー + +### 妥当性が確認された主要な指摘(優先対処) +1. [指摘事項1] +2. [指摘事項2] +3. [指摘事項3] + +### 検討が必要な指摘 +- [指摘事項A] +- [指摘事項B] + +### 不適切と判断された指摘 +- [指摘事項X] + +詳細については、上記ファイルを参照してください。 + +## ログファイル一覧 + +### コンテキスト情報 +- `` + +### 第1ラウンド(8視点のレビュー) + +各視点のタグで定義されたファイル(8ファイル) + +### 第2ラウンド(5メタレビュアーの評価) + +各メタレビュアーの``タグで定義されたファイル(5ファイル) +``` + + diff --git a/commands/optimize_bq_query.md b/commands/optimize_bq_query.md new file mode 100644 index 0000000..b12462f --- /dev/null +++ b/commands/optimize_bq_query.md @@ -0,0 +1,304 @@ +--- +allowed-tools: Bash(bq query:*), Bash(bq wait:*), Bash(tee:*), Write(/tmp/**), Edit(/tmp/**), Read(/tmp/**) +description: "BigQueryクエリのパフォーマンスを分析し、2倍以上の性能改善を目標とした最適化を提案します。" +--- + +## 前提条件 +- **リージョン**: US(region-us)固定 +- **プロジェクト**: デフォルトプロジェクト(`gcloud config get-value project`で設定済み) +- **権限**: INFORMATION_SCHEMAへのアクセス権限あり +- **スキャン量削減**: INFORMATION_SCHEMAは直近7日間のみ検索(creation_timeで絞り込み) +- クエリの`FROM`句にバッククオートの付与は禁止 + - バッククオートを付与すると、Bash toolがコマンドと勘違いをする + - そのため、毎回ユーザーの許可が必要になってしまうため + +## 分析対象 +- 入力: $ARGUMENTS(SQLファイルパス `.sql`) +- SQLのファイルのみで最適化内容を判断するのではなく、実際にクエリを実行してジョブ情報を取得し、ボトルネック分析を行う + +## 実行手順 + +### 1. クエリ実行とジョブIDの取得 + +**前提**: `$ARGUMENTS`は最適化対象のSQLクエリが記述された`.sql`ファイルのパスです + +1. クエリを実行してジョブIDを取得 + - `cat "$ARGUMENTS" | bq query --nosync --use_legacy_sql=false --use_cache=false --format=json | jq -r '.jobReference.jobId'` + - 取得したジョブIDを`JOB_ID`として以降の分析で使用 + - `JOB_ID`をシェル変数として設定する必要はありません + +2. ジョブの完了を待機 + - `bq wait ""`でジョブが完了するまで待機 + +### 2. 全体ボトルネックの特定 + +#### 基本情報の収集 +- 以下のクエリで元のクエリと基本メトリクス(スロット時間、スキャン量)を取得 + +```bash +bq query --use_legacy_sql=false --format=json --parameter="job_id:STRING:" " + SELECT query, total_slot_ms, total_bytes_processed + FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT + WHERE job_id = @job_id AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) +" | tee /tmp/job_info.json | head -n 10 +``` + +- 元クエリと基本メトリクスを保存 + - `cat /tmp/job_info.json | jq -r '.[0].query' | tee /tmp/original_query.sql` + +#### 最大のボトルネックステージを特定 +**目的**: 全体のスロット時間の80%以上を占める真のボトルネックを見つける + +```bash +bq query --use_legacy_sql=false --format=pretty --parameter="job_id:STRING:" " + SELECT + stage.name as stage_name, + CAST(stage.slot_ms AS INT64) as slot_ms, + ROUND(100.0 * stage.slot_ms / SUM(stage.slot_ms) OVER(), 1) as pct_of_total + FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT, + UNNEST(job_stages) AS stage + WHERE job_id = @job_id + AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) + ORDER BY stage.slot_ms DESC + LIMIT 5 +" +``` + +**この結果から上位1-3ステージ(合計80%以上)を特定し、以降はそれらのみを分析対象とする** + +### 3. ボトルネック根本原因の分析 + +**前提**: セクション2で特定したボトルネックステージ(TOP1-3)のみを詳細分析する + +#### 根本原因の診断 + +1. **ボトルネックステージの詳細メトリクスを取得** + - セクション2で特定したボトルネックステージ(TOP1-3)に対して以下のクエリを実行: + +```bash +bq query --use_legacy_sql=false --format=pretty --parameter="job_id:STRING:" " + SELECT + stage.name, + CAST(stage.slot_ms AS INT64) as slot_ms, + ROUND(stage.wait_ratio_max * 100, 1) as wait_pct, + ROUND(stage.read_ratio_max * 100, 1) as read_pct, + ROUND(stage.compute_ratio_max * 100, 1) as compute_pct, + ROUND(stage.write_ratio_max * 100, 1) as write_pct, + ROUND(CAST(stage.shuffle_output_bytes AS INT64) / 1048576, 1) as shuffle_mb + FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT, + UNNEST(job_stages) AS stage + WHERE job_id = @job_id + AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) + AND stage.name IN ('特定されたボトルネックステージ名1', '名前2', '名前3') + ORDER BY stage.slot_ms DESC +" +``` + +2. **ステージの処理内容を特定** + - 各ステージがどの種類の処理を行っているかを以下のクエリで確認: + +```bash +bq query --use_legacy_sql=false --format=pretty --parameter="job_id:STRING:" " + SELECT + stage.name, + CASE + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'READ') THEN 'READ処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'WRITE') THEN 'WRITE処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'COMPUTE') THEN 'COMPUTE処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'FILTER') THEN 'FILTER処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'JOIN') THEN 'JOIN処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'AGGREGATE') THEN 'AGGREGATE処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'ANALYTIC') THEN 'ANALYTIC処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'SORT') THEN 'SORT処理' + WHEN EXISTS(SELECT 1 FROM UNNEST(stage.steps) AS step WHERE step.kind = 'LIMIT') THEN 'LIMIT処理' + ELSE 'その他' + END as primary_operation + FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT, + UNNEST(job_stages) AS stage + WHERE job_id = @job_id + AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) + ORDER BY stage.slot_ms DESC + LIMIT 5 +" +``` + +#### 元クエリとの対応付けと分析結果記録 + +1. **元クエリを確認** + - `cat "$ARGUMENTS"`で元クエリの内容を表示 + +2. **ボトルネック分析結果ファイルの初期化** + - Writeツールを使って`/tmp/bottleneck_analysis.md`を以下の内容で作成: + +```markdown +## 特定されたボトルネックステージ: + + + +## 根本原因分析: + + + +## 対応するSQL箇所: + + +``` + +3. **分析結果の記録** + - 上記bqクエリ結果を参照し、Editツールで各セクションに情報を追記 + +### 4. ボトルネック対応の最適化パターン選択 + +**特定されたボトルネック要因に基づいて、2倍改善を狙える最適化パターンを選択** + +#### Input段階のボトルネック → データ読み込み最適化 +- **パーティション絞り込み**: WHERE句での日付/地域等の限定 +- **クラスタリング活用**: JOIN/GROUP BYキーでの事前ソート +- **列選択最適化**: SELECT *を避けて必要列のみ + +#### Join段階のボトルネック → 結合処理最適化 +- **JOIN前データ削減**: 事前フィルタリング/集約で行数削減 +- **JOIN順序最適化**: 小テーブル→大テーブルの順序 +- **EXISTS/IN変換**: 相関サブクエリから効率的な形式へ + +#### Aggregate/Sort段階のボトルネック → 集約処理最適化 +- **段階的集約**: 複数CTEでの事前集約 +- **LIMIT早期適用**: TOP-N処理での不要計算回避 +- **ウィンドウ関数最適化**: PARTITION BY句の最適化 + +**最適化パターンの選択と記録**: + +1. **ボトルネック診断結果を参照** + - `/tmp/bottleneck_analysis.md`の内容を確認 + +2. **最適化パターンファイルの初期化** + - Writeツールを使って`/tmp/applied_optimizations.md`を以下の内容で作成: + +```markdown +## 適用する最適化パターン + + +``` + +3. **最適化パターンの記録** + - ボトルネック要因に対応するパターンを選択 + - 各パターンの期待効果を計算し、2倍改善の見込みを確認 + - Editツールで具体的な最適化内容を追記 + +### 5. 最適化クエリの実装 +1. **元クエリを確認** + - `cat "$ARGUMENTS"`で元クエリの内容を確認 +2. **最適化クエリの生成と保存** + - セクション4で選択した最適化パターンを適用 + - Writeツールを使って`/tmp/optimized_query.sql`に最適化後のクエリを保存 + - 最適化例: + +```sql +-- 例: JOIN前データ削減 +WITH filtered_users AS ( + SELECT * FROM users WHERE active = true +) +SELECT ... +FROM comments c +INNER JOIN filtered_users u ON c.user_id = u.id +``` + +3. **最適化内容の確認** + - `cat /tmp/optimized_query.sql`で保存した最適化クエリを表示 + +### 6. リファクタリング結果の同一性検証 +- **重要**: 最適化は性能改善のみで、出力結果は完全に同一である必要がある +- **注意**: `BIT_XOR`と`FARM_FINGERPRINT`は行の順序に依存しないため、結果の同一性を検証できる + +**BigQueryチェックサムによる検証手順**: + +1. **元クエリの結果テーブル名を取得してチェックサムを計算** + - `JOB_ID`(セクション1で取得済み)から以下のコマンドを実行し、`DESTINATION_TABLE`として設定 + - `bq query --use_legacy_sql=false --format=json --parameter="job_id:STRING:" "SELECT destination_table FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT WHERE job_id = @job_id AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)" | jq -r '.[0].destination_table | [.project_id, .dataset_id, .table_id] | join(".")'` + - `DESTINATION_TABLE`に対して、チェックサムを計算 + - `bq query --use_legacy_sql=false --format=json "SELECT BIT_XOR(FARM_FINGERPRINT(TO_JSON_STRING(t))) as checksum FROM AS t" | jq -r '.[0].checksum'` + - チェックサム値(整数文字列)を記録 + +2. **最適化クエリの結果テーブル名を取得してチェックサムを計算** + - `NEW_JOB_ID`(セクション6で取得)から以下のコマンドを実行し、`DESTINATION_TABLE`として設定 + - `bq query --use_legacy_sql=false --format=json --parameter="job_id:STRING:" "SELECT destination_table FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT WHERE job_id = @job_id AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)" | jq -r '.[0].destination_table | [.project_id, .dataset_id, .table_id] | join(".")'` + - `DESTINATION_TABLE`に対して、チェックサムを計算 + - `bq query --use_legacy_sql=false --format=json "SELECT BIT_XOR(FARM_FINGERPRINT(TO_JSON_STRING(t))) as checksum FROM AS t" | jq -r '.[0].checksum'` + - チェックサム値(整数文字列)を記録 + +3. **チェックサム値を比較** + - 2つのチェックサム値が完全に一致することを確認 + - 不一致の場合は最適化を中止し、原因を調査 + +### 7. 性能改善効果の測定 +- 最適化後のクエリを実行し、同様にジョブIDを取得してメトリクスを収集 + - `cat /tmp/optimized_query.sql | bq query --nosync --use_legacy_sql=false --use_cache=false --format=json | jq -r '.jobReference.jobId'` + - 取得したジョブIDを`NEW_JOB_ID`として以降の分析で使用 + - `NEW_JOB_ID`をシェル変数として設定する必要はありません +- `bq wait ""`でジョブが完了するまで待機 +- 元のスロット時間を取得(セクション2で保存したjsonから) + - !`cat /tmp/job_info.json | jq -r '.[0].total_slot_ms'` +- 以下のコマンドで、最適化後のスロット時間を取得 + +```bash +bq query --use_legacy_sql=false --format=json --parameter="job_id:STRING:" " + SELECT total_slot_ms + FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT + WHERE job_id = @job_id AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) +" | jq -r '.[0].total_slot_ms' +``` + +#### 改善率の計算と判定: +- 元のスロット時間と最適化後のスロット時間を比較し、改善率を計算 + - `bc`コマンドなどは使用せず、Agent自身が計算を行う +- 2倍以上の改善が達成されたかを判定 + - 改善率が2倍以上であれば成功とし、最適化プロセスを終了 + - 達成されていない場合は、セクション3で特定したボトルネックに戻り、セクション4-6を繰り返す + +### 8. 最終レポート生成 + +**目的**: 2倍改善達成の根拠と再現可能な手順を記録 + +1. **必要な情報を収集** + - 元のスロット時間: `cat /tmp/job_info.json | jq -r '.[0].total_slot_ms'`で取得 + - 最適化後のスロット時間: セクション7で取得済み + - 改善率: Agent自身が計算 + - 目標達成状況: 改善率が2.0倍以上かを判定 + +2. **最終レポートの生成** + - Writeツールを使って`/tmp/optimization_report.md`を以下の構造で作成: + +```markdown +# BigQuery最適化レポート + +## 実行サマリー +- **元クエリファイル**: <$ARGUMENTSの値> +- **元ジョブID**: +- **元スロット時間**: ms +- **最終改善率**: x +- **目標達成**: <達成状況(✅ 達成 or ❌ 未達成)> + +## 特定されたボトルネック + + +## 適用した最適化手法 + + +## 最適化後のクエリ + +\`\`\`sql + +\`\`\` + +## 検証結果 +- **結果一致**: ✅ チェックサム一致で完全同一 +- **性能改善**: ms → ms +``` + +3. **レポートの確認** + - `cat /tmp/optimization_report.md`でレポート内容を表示 + +**完了条件**: +- 2倍以上の改善達成 OR 5回の反復完了 +- 結果の同一性確認済み +- 再現可能な最適化手順の記録 diff --git a/commands/triage_pr_comments.md b/commands/triage_pr_comments.md new file mode 100644 index 0000000..a3fa7ab --- /dev/null +++ b/commands/triage_pr_comments.md @@ -0,0 +1,133 @@ +Pull Requestのコメントに対する対応要否をコードベース分析に基づいて判断します + +## 分析対象 +Pull RequestのURL: $ARGUMENTS + +## 実行手順 + +### 1. 情報取得と分析 +```bash +# Pull RequestのURLから情報を取得 +PR_URL="$ARGUMENTS" + +# $ARGUMENTSが空の場合、現在のブランチのPRを取得 +if [ -z "$PR_URL" ]; then + PR_URL=$(gh pr view --json url --jq '.url' 2>/dev/null || echo "") + if [ -z "$PR_URL" ]; then + echo "エラー: Pull RequestのURLが指定されていません。また、現在のブランチに紐づくPRも見つかりませんでした。" + exit 1 + fi + echo "現在のブランチのPull Request URLを使用します: $PR_URL" +fi + +echo "=== Pull Request基本情報 ===" + +# gh pr viewでPR情報を取得 +PR_INFO=$(gh pr view "$PR_URL" --json number,headRepositoryOwner,headRepository,title,author,state,headRefName,baseRefName,changedFiles,additions,deletions,createdAt) + +# 変数の設定(後のAPI呼び出しで使用) +OWNER=$(echo "$PR_INFO" | jq -r '.headRepositoryOwner.login') +REPO=$(echo "$PR_INFO" | jq -r '.headRepository.name') +PR_NUMBER=$(echo "$PR_INFO" | jq -r '.number') + +echo "$PR_INFO" +echo "" + +echo "=== 未解決コメント一覧 ===" +# 未解決コメント取得(GraphQL API) +gh api graphql --field query="query { repository(owner: \"$OWNER\", name: \"$REPO\") { pullRequest(number: $PR_NUMBER) { reviewThreads(last: 100) { nodes { id isResolved comments(last: 10) { nodes { id body path line originalLine createdAt author { login } diffHunk } } } } } } }" | jq '.data.repository.pullRequest.reviewThreads.nodes | map(select(.isResolved == false)) | map(.comments.nodes) | flatten' +echo "" + +echo "=== 変更内容の詳細分析 ===" +echo "### 変更されたファイル一覧" +gh pr diff "$PR_URL" --name-only + +echo "" +echo "### 各ファイルの詳細な差分" +gh pr diff "$PR_URL" +``` + +### 4. 分析指示 + +**このPull Requestの情報を取得しました。あなたはこのPull Requestの作成者として、コメントに対する対応要否を判断する必要があります。このPRのオーナーシップを持つ立場から、各コメントに対応すべきかどうかを以下の観点で分析してください:** + +## A. コードベース全体の理解 + +まず、リポジトリ全体を把握してください: + +1. **プロジェクト構造の分析** + - ディレクトリ構造、命名規則 + - 使用技術スタック、フレームワーク + - 設定ファイル(package.json、requirements.txt、go.modなど) + +2. **既存パターンの特定** + - テストファイルの配置規則と命名規則 + - エラーハンドリングの統一パターン + - ログ出力やデバッグの方法 + - ドキュメンテーションの書き方 + - コーディングスタイル、規約 + +3. **アーキテクチャの理解** + - レイヤー構造、依存関係 + - デザインパターンの使用状況 + - 拡張性、保守性への配慮 + +## B. 変更内容の整合性チェック + +今回のPull Requestが既存パターンに従っているかチェック: + +- 新機能にテストが含まれているか +- エラーハンドリングが適切か +- ログ出力が既存パターンに従っているか +- ドキュメント更新が必要かどうか +- 依存関係の追加が適切か + +## C. 各コメントの詳細分析 + +**各コメントについて、以下の形式で判断してください:** + +### コメントID: [ID番号] +**内容**: [コメントの要約] + +#### 対応判断: ✅必要 / ⚠️要検討 / ❌不要 + +**理由**: +- [客観的な根拠] + +**コメント者の意図**: +- [なぜこのコメントをしたのか] + +**影響範囲**: +- [修正しない場合のリスク] + +**修正方針** (対応必要な場合): +- **場所**: [具体的なファイル、関数] +- **方法**: [どのように修正するか] +- **難易度**: 簡単/中程度/困難 +- **時間**: [おおよその所要時間] + +**返信内容案**: +- **対応する場合**: [修正内容や対応方針を説明する返信文案] +- **対応しない場合**: [理由を丁寧に説明する返信文案] +- **質問・確認が必要な場合**: [意図を確認するための返信文案] + +--- + +## D. 参考情報の整理 + +### 対応判断の参考情報 +- **既存パターンとの整合性**: [コメントが指摘する内容が既存コードベースの規則に合致するか] +- **技術的妥当性**: [指摘内容が技術的に正しいか] +- **影響範囲**: [対応しない場合の潜在的リスク] + +### コメント優先度整理 (参考) +1. [コメントID] - [対応を検討すべき理由] +2. [コメントID] - [対応を検討すべき理由] +3. [コメントID] - [対応を検討すべき理由] + +### ユーザー判断のための補足 +- **すぐに対応できそうなもの**: [リスト] +- **時間をかけて検討が必要なもの**: [リスト] +- **コメント者に確認が必要なもの**: [リスト] + +**重要**: この分析は判断材料の提供であり、最終的な対応判断はユーザーが行います。コード修正は一切行いません。 \ No newline at end of file diff --git a/commands/validate_bq_query.md b/commands/validate_bq_query.md new file mode 100644 index 0000000..be124ab --- /dev/null +++ b/commands/validate_bq_query.md @@ -0,0 +1,88 @@ +# bq queryコマンドの出力を検証する + +## 目的 +あなたはクエリの監査官です。危険なクエリを見抜き、その場合には実行を何としても阻止する必要があります。入力となるクエリの対象はBigQueryです + +## 出力形式 +検証の結果を以下のClaude Code標準JSON形式で出力してください。JSON以外を出力することは許可されていません。 + +- 返答は有効なJSONオブジェクト1個のみ + - **重要**: コードフェンス(\`\`\`)や「このクエリを検証します」などの出力(説明文、前置きなど)は一切許可されていません + +### JSON構造 +```json +{ + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "allow または deny", + "permissionDecisionReason": "判定理由(日本語約200字)" + } +} +``` + +### 出力例 + +安全なクエリの場合: +{ + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "allow", + "permissionDecisionReason": "単純なSELECT文のみで安全なクエリです" + } +} + +危険なクエリの場合: +{ + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": "DROP文によりテーブルを削除する危険な操作です" + } +} + +## 判定基準 + +### 安全なクエリ(allow) +- **SELECT文のみ**: データの読み取り専用操作 +- **INFORMATION_SCHEMA**: メタデータの参照 +- **WITH句**: CTEを使用した読み取り専用クエリ + +### 危険なクエリ(deny) + +#### DDL(Data Definition Language) +- **DROP**: テーブル・データセット・ビュー・関数の削除 +- **CREATE**: テーブル・データセット・ビュー・関数の作成 +- **ALTER**: 既存オブジェクトの構造変更 +- **TRUNCATE**: テーブルデータの全削除 + +#### DML(Data Manipulation Language) +- **INSERT**: データの挿入・追加 +- **UPDATE**: データの更新・変更 +- **DELETE**: データの削除 +- **MERGE**: データのマージ操作 + +#### DCL(Data Control Language) +- **GRANT**: 権限の付与 +- **REVOKE**: 権限の取り消し +- **CREATE ROW ACCESS POLICY**: 行レベルセキュリティ + +#### 高度な操作 +- **EXPORT DATA**: データのエクスポート +- **IMPORT**: データのインポート(セッション機能) +- **EXECUTE IMMEDIATE**: 動的SQL実行 +- **CALL**: ストアドプロシージャ実行 +- **BEGIN/COMMIT/ROLLBACK TRANSACTION**: トランザクション制御 + +#### BigQuery ML +- **CREATE MODEL**: 機械学習モデルの作成 +- **ML.PREDICT**: モデル予測の実行 +- **ML.EVALUATE**: モデル評価 + +#### 危険なオプション +- **--replace**: 既存テーブルの置換 +- **--destination_table**: 結果の別テーブル保存 +- **--external_table_definition**: 外部テーブル定義 +- **--append_table**: データの追加 + +### その他 +- **判断不能**: 上記に該当しない場合は`deny` diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..01805d0 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,109 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:syou6162/claude-code-commands:", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "b51872492bc7821f807babd7e70c9a00d831bddf", + "treeHash": "3cb8988db187be1e1cb2655a91c5821622ce7e19a5c1f786d8a23d8d66937cf5", + "generatedAt": "2025-11-28T10:28:30.539075Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "syou6162-plugin", + "description": "Yasuhisa Yoshida's personal custom slash commands for Claude Code", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "26530ec0172c2b8be965da9ab488e564a04e9656786b2028b2f368e1aee8ca21" + }, + { + "path": "agents/monitor-ci.md", + "sha256": "d3f2863bc57fd6a625666dcc52aba9a78faeeab5e71d3d6169d93c58e9137598" + }, + { + "path": "agents/update-pr-title-and-description.md", + "sha256": "9260b849c678d0a4b88c53c4926cabb8023862aa3cfeff8277b071a26ed55528" + }, + { + "path": "agents/detect-spec-workflow.md", + "sha256": "47454683ba6d2c3aae1336f9dac68f3d02d96eabb3fcf6959157241b83fe9788" + }, + { + "path": "agents/semantic-commit.md", + "sha256": "d0125d0b8fa87813ffe1f5f021902c8df122290dc1517215c247d3ab010e880f" + }, + { + "path": "agents/record-current-status.md", + "sha256": "d500f59f9cf8414599dbed839cfdb3d811b7a022655a400c18e79d61e3ff20c7" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "2c4ef346b0914b1338419b0ee3f0aa50af9e00f3d70131da57e8c66e164e4d95" + }, + { + "path": "commands/validate_bq_query.md", + "sha256": "31751e8e9c9def1f451a453ecbd86aaa442cba41e73738e21b4e75228037cbce" + }, + { + "path": "commands/estimate_pr_size.md", + "sha256": "910325bdac1c2d3d6413b660b6e97764112694d0bbd6cc43e8ebaac58d47aa0e" + }, + { + "path": "commands/multi_perspective_review.md", + "sha256": "baa097c3e34b4ecdec47d3f59660b359ba9508be70d1b9d8ac2e125ccc85d086" + }, + { + "path": "commands/optimize_bq_query.md", + "sha256": "35396c00f34845dd0b1b5ec828ed5aacaeb3493b92a45bb580e02561c19a3243" + }, + { + "path": "commands/load_spec_tasks.md", + "sha256": "cdf7458a50cb33f674eef6120b2c0c8781364f702d4c920e79349a67eea3723c" + }, + { + "path": "commands/triage_pr_comments.md", + "sha256": "1eb1cd291ff0a349837be9317c7418a5b0b9475ec928ae7d44da5dbad8707509" + }, + { + "path": "commands/codex_review.md", + "sha256": "41e124b33ffbc34090c094035561f62f3fc273b90b58e444076634fae0b949f4" + }, + { + "path": "skills/reading-notion/SKILL.md", + "sha256": "f6af52e36b79de5ac6379b64806d9857824b47bbdf0637004d129f7e6914c42a" + }, + { + "path": "skills/reading-notion/reference/search-mode.md", + "sha256": "1ca204bce5caf8f630eea9f0e1b585564ae805c90e6549e9a2ab28f24c912f5e" + }, + { + "path": "skills/reading-notion/reference/url-mode.md", + "sha256": "4f9cd728cd38b51f71ceb1b8e235f88bc9cec54ef9418c10cf681604230fe1da" + }, + { + "path": "skills/ask-user-choice/SKILL.md", + "sha256": "0c1ce33a3ad958538e793daa8815cabcf39fdab41929c8796922bbb5b18ab00d" + }, + { + "path": "skills/gha-sha-reference/SKILL.md", + "sha256": "d4d781497a9305279a7967ceabf757ba2671c4670006cca0a1084365821c5a10" + } + ], + "dirSha256": "3cb8988db187be1e1cb2655a91c5821622ce7e19a5c1f786d8a23d8d66937cf5" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/ask-user-choice/SKILL.md b/skills/ask-user-choice/SKILL.md new file mode 100644 index 0000000..b6fe143 --- /dev/null +++ b/skills/ask-user-choice/SKILL.md @@ -0,0 +1,193 @@ +--- +name: ask-user-choice +description: ユーザーに質問や確認をする際に毎回発動してください。自由回答形式ではなく、明確な選択肢(1質問あたり2-4個)を持つAskUserQuestionツールを使用し、ユーザーの入力負担を軽減して意思決定を迅速化します。柔軟性のためmultiSelect trueをデフォルトにしてください。 +allowed-tools: AskUserQuestion +--- + +# Ask User Choice Skill + +## 目的 + +このスキルは`AskUserQuestion`ツールの使用を推進し、ユーザーの入力負担を軽減して対話をより効率的にします。テキスト入力が必要な自由回答形式ではなく、ワンクリックで選択できる構造化された選択肢を提供してください。 + +## 使用タイミング + + + +以下の場合にこのスキルを発動してください: +- ユーザーの入力や好みを取得する +- 曖昧な要件を明確化する +- 実装の選択肢を提示する(ライブラリ、アーキテクチャ、アプローチなど) +- 複数のタスクがある場合に優先順位を決定する +- 作業完了後に次のアクションを提案する + + + +## ベストプラクティス + +### 1. 良い質問の構造 + +各質問には以下を含めること: + +- **明確な質問文**: 疑問符で終わり、具体的であること +- **簡潔なheader**: 短いラベル。例:「ライブラリ」「アプローチ」 +- **選択肢**: それぞれにラベルと詳細な説明を付ける +- **multiSelect**: **デフォルトで`true`に設定**(柔軟性のため、ユーザーは1つまたは複数選択可能) + +### 2. 充実した詳細な説明文を書く + +説明文は長くてOK。情報量を充実させること。 + +良い選択肢の構造: + +```json +{ + "label": "短い選択肢名", + "description": "コンテキスト、トレードオフ、影響を含む詳細な説明。\n\n段落区切りには\\n\\nを使って可読性を向上させる。\n\n十分な情報を提供して、情報に基づいた意思決定を可能にする。" +} +``` + +- `\n\n`で段落区切りを使う(可読性が大幅に向上) +- コンテキスト、メリット・デメリット、影響を含める +- 詳細を出し惜しみしない - ユーザーは簡潔すぎる説明より包括的な情報を好む +- **Markdown記法の制限**: + - `**bold**`、`*italic*`、`` `code` ``などは使えない(そのまま表示される) + - 箇条書き(`-`)は装飾されないがそのまま表示されるので、可読性向上のために使用OK + +### 3. multiSelectをデフォルトで使用 + +**特に理由がない限り`multiSelect: true`をデフォルトに** + +✅ **`multiSelect: true`を使用(推奨デフォルト)**: + +- ほとんどのシナリオで柔軟性の恩恵がある +- ユーザーは1つだけ選びたければ1つだけ選べる +- 該当する場合は複数の選択肢を組み合わせられる +- よりユーザーフレンドリーで制約が少ない + +⚠️ **`multiSelect: false`を使うのは以下の場合のみ**: + +- 選択肢が厳密に相互排他的 +- 複数選択すると論理的な矛盾が生じる +- 質問の性質上、単一選択が本質的に必要 + +## 使用例 + + + +### 例1: 実装アプローチ選択(詳細な説明文付き) + + + +```json +{ + "question": "どのJavaScriptフレームワークを使用しますか?", + "header": "Framework", + "multiSelect": true, + "options": [ + { + "label": "React + TypeScript", + "description": "仮想DOMを使用した高速レンダリングを実現する、最も人気のあるJavaScriptフレームワーク。\n\nTypeScriptと組み合わせることで型安全性が向上し、大規模プロジェクトでも保守性が高まる。\n\nコンポーネントベースの設計で再利用性が高く、豊富なエコシステム(React Router, Redux, Next.js等)が利用できる。\n\n学習コストは中程度で、ドキュメントやコミュニティサポートが充実している。" + }, + { + "label": "Vue.js + Composition API", + "description": "学習曲線が穏やかで初心者にも取り組みやすいフレームワーク。\n\nComposition APIを使用することで、React Hooksに近いロジックの再利用が可能になる。\n\nテンプレート構文が直感的でHTMLに近い書き方ができ、公式の状態管理ライブラリPiniaやルーティングライブラリVue Routerが統合されている。\n\nパフォーマンスも優れており、中小規模から大規模まで幅広く対応できる。" + }, + { + "label": "Svelte + SvelteKit", + "description": "コンパイル時にコードを最適化するため、ランタイムのオーバーヘッドが極めて少なく、高速なアプリケーションを構築できる。\n\n仮想DOMを使わず、ビルド時に効率的な命令型コードに変換される。\n\nSvelteKitを使用することでSSRやSSG、ルーティングなどの機能が統合されている。\n\nコード量が少なく、バンドルサイズが小さいのも大きなメリット。ただし、エコシステムはReactやVueと比べるとまだ小さい。" + } + ] +} +``` + + + +### 例2: 複数機能選択(multiSelect推奨) + + + +```json +{ + "question": "どの機能を実装しますか?", + "header": "Features", + "multiSelect": true, + "options": [ + { + "label": "ダークモード", + "description": "ライトモードとダークモードの切り替え機能を追加。\n\n- アクセシビリティが向上\n- 低照度環境でのユーザーの快適性が改善\n- 目の疲労を軽減\n\n実装要件:\n- CSS変数の設定\n- 状態管理(localStorage等)\n- テーマ切り替えUI" + }, + { + "label": "キーボードショートカット", + "description": "パワーユーザー向けにキーボードナビゲーションとショートカットを有効化。\n\n頻繁に使用するユーザーの生産性が大幅に向上する。\n\nブラウザのショートカットとの衝突を避けるための慎重な設計が必要。" + }, + { + "label": "PDF出力", + "description": "コンテンツをPDFファイルとしてエクスポートできる機能。\n\nレポート、ドキュメント、オフライン共有に便利。\n\nPDF生成ライブラリ(jsPDF、pdfmake等)が必要。" + } + ] +} +``` + + + +### 例3: タスク優先順位(multiSelect falseのレアケース) + + + +```json +{ + "question": "最初にどのタスクから始めますか?", + "header": "Priority", + "multiSelect": false, + "options": [ + { + "label": "認証バグの修正", + "description": "🔴 最優先 - 現在ユーザーがログインできない状態。\n\n全ユーザーのアクセスをブロック中。修正予想時間:1-2時間。\n\n他の作業より先に即座に対処すべき。" + }, + { + "label": "新機能追加", + "description": "🟡 中優先度 - 次スプリント向けにクライアントから要望あり。\n\n現在の機能をブロックしていない。予想時間:1-2日。\n\nクリティカルなバグ解決後にスケジュール可能。" + }, + { + "label": "コードリファクタリング", + "description": "🟢 低優先度 - 保守性とコード品質を改善。\n\nユーザーへの即時影響なし。予想時間:3-4時間。\n\n機能開発の合間を埋めるのに適している。" + } + ] +} +``` + + + + + +## 常に覚えておくこと + + + +✅ **すべきこと**: + +- 詳細な説明を使う(コンテキストとトレードオフを追加) +- `\n\n`で段落区切りを使い、可読性を向上させる +- 柔軟性のため`multiSelect: true`をデフォルトにする +- 各選択肢のlabelは短く、descriptionは充実させる +- **必要に応じて複数回質問する** - フォローアップが必要な場合は、最初の回答を得た後に再度AskUserQuestionを使用 + +❌ **してはいけないこと**: + +- 簡潔すぎる説明 - ユーザーは情報に基づいた意思決定のため詳細を求める +- 選択肢が真に相互排他的でない限り`multiSelect: false`を使う +- フォローアップ質問を躊躇する - 推測よりも明確化の方が良い + + + +## 複数ラウンドの質問 + +不明点が多い場合や段階的な明確化が必要な場合: + +1. **関連する質問をグループ化** +2. **最初のバッチを聞く**、回答を待つ +3. **回答に基づいてフォローアップ質問**を必要に応じて行う +4. **すべての不確実性が解消されるまで繰り返す** + +この段階的な質問アプローチは推奨されており、実装に進む前に徹底的な理解を確保するのに役立ちます。 diff --git a/skills/gha-sha-reference/SKILL.md b/skills/gha-sha-reference/SKILL.md new file mode 100644 index 0000000..36f5fe7 --- /dev/null +++ b/skills/gha-sha-reference/SKILL.md @@ -0,0 +1,145 @@ +--- +name: gha-sha-reference +description: ユーザーがGitHub Actionsのタグ参照をSHA参照に変換するよう要求したときに発動してください。uses:フィールドのタグ参照を自動的にSHA参照(コミットハッシュ + コメント付きバージョン)に変換します。 +--- + +# GitHub Actions SHA Reference Skill + +## 目的 + +このスキルはGitHub Actionsワークフローファイル内の`uses:`フィールドで使用されているタグ参照(例: `@v4`)を、セキュリティのベストプラクティスに従ってSHA参照(例: `@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2`)に自動変換します。 + +## 使用タイミング + + + +以下の場合にこのスキルを発動してください: + +- ユーザーが「GitHub ActionsをSHA参照に変換して」と要求したとき +- ユーザーが「actionsのusesをSHAに書き換えて」と言及したとき + + + +## 実行手順 + + + +### 1. 変更対象を確認 + +まず `--check --diff` オプションで、どのファイルが変更されるかを確認します: + +```bash +pinact run --check --diff +``` + +**出力例**: + +``` +ERROR action isn't pinned +.github/workflows/ci.yaml:10 +- uses: actions/checkout@v4 ++ uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 +ERROR action isn't pinned +.github/workflows/ci.yaml:11 +- - uses: actions/setup-go@v4 ++ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 +ERROR action isn't pinned +.github/workflows/deploy.yaml:15 +- uses: actions/checkout@v4 ++ uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 +``` + +### 2. 変換を実行 + +確認後、`pinact run` を実行してすべての対象ファイルを一括変換します: + +```bash +pinact run +``` + +pinactは以下を自動的に行います: +- タグ参照からコミットSHAを取得 +- 最も詳細なバージョンタグ(v4.3.0など)をコメントとして追加 +- `.github/workflows/*.{yml,yaml}` と `action.{yml,yaml}` を自動検出して変換 + + + +## 実装例 + + + +### 例1: 基本的な使用方法 + + + +**ステップ1: 変更対象を確認**: + +```bash +pinact run --check --diff +``` + +**出力**: + +``` +ERROR action isn't pinned +.github/workflows/ci.yaml:10 +- uses: actions/checkout@v4 ++ uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 +ERROR action isn't pinned +.github/workflows/ci.yaml:11 +- - uses: actions/setup-go@v4 ++ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 +``` + +**ステップ2: 変換を実行**: + +```bash +pinact run +``` + +**変換後のワークフローファイル (.github/workflows/ci.yaml)**: + +```yaml +name: CI +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 +``` + + + + + +## 重要な注意事項 + + + +### すべきこと + +- **pinactを使用**: GitHub Actions SHA参照変換には専用ツールpinactを使用する +- **まず --check --diff で確認**: `pinact run --check --diff` で変更対象を確認する +- **一括実行**: diffで確認した後、`pinact run` で全ファイルを一括変換する +- **変換結果を報告**: 何が変換されたかユーザーに伝える + +### してはいけないこと + +- **カスタムスクリプトを作成**: pinactという専用ツールがあるので、独自スクリプトは不要 +- **いきなり実行**: `--check --diff` で確認せずに `pinact run` を実行しない +- **エラーを無視**: pinactの実行でエラーが出た場合は、そのまま進めずユーザーに報告する + +### 実行前チェックリスト + +- [ ] pinactがインストールされている(`pinact --version`で確認) +- [ ] `pinact run --check --diff` で変更対象を確認した +- [ ] diffの出力から変換対象のファイル一覧を把握した + + + +## 参考リンク + +- [pinact - GitHub](https://github.com/suzuki-shunsuke/pinact) +- [GitHub Actions セキュリティガイド](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions) diff --git a/skills/reading-notion/SKILL.md b/skills/reading-notion/SKILL.md new file mode 100644 index 0000000..e252e9a --- /dev/null +++ b/skills/reading-notion/SKILL.md @@ -0,0 +1,42 @@ +--- +name: reading-notion +description: Notion URLが会話に登場した時、またはNotionのコンテンツを検索・取得する必要がある時に使用してください。 +allowed-tools: Bash, Read +--- + +# Reading Notion + +NotionページやドキュメントをMarkdownに変換して読み取り、内容を要約・説明するスキルです。 + +## 概要 + +このスキルは2つのモードで動作します: + +1. **URL直接モード**: Notion URLが会話に登場した時、`notion-to-md`を使って自動的にMarkdownに変換し、内容を説明 +2. **検索モード**: キーワードでNotionを検索し、結果から選択したページの内容を説明 + +**URL直接モード**では、Go製のCLIツール`notion-to-md`を使用してNotion APIからページデータを取得し、Markdown形式に変換します。これにより、ネスト構造、豊富なブロックタイプ、テキストアノテーションなどを正確に保持したMarkdownファイルが生成されます。 + + +## モード詳細 + + + +### URL直接モード + +Notion URLを検出すると自動的に発動します。詳細は **reference/url-mode.md** を参照してください。 + +**発動例**: +- ユーザーが `https://www.notion.so/myorg/abc123def456ghi789jkl012mno34567` のようなURLを提示 +- 会話中にNotion URLが登場 + +### 検索モード + +キーワードでNotion内を検索したい時に発動します。詳細は **reference/search-mode.md** を参照してください。 + +**発動例**: +- 「データ基盤チームについて教えて」 +- 「Notionでプロジェクト〇〇を検索して」 +- 特定のキーワードに関する情報を求められた時 + + diff --git a/skills/reading-notion/reference/search-mode.md b/skills/reading-notion/reference/search-mode.md new file mode 100644 index 0000000..8aa4fe7 --- /dev/null +++ b/skills/reading-notion/reference/search-mode.md @@ -0,0 +1,113 @@ +# 検索モード + +「notionでxyzを探して」という形で発動し、キーワードでNotionを検索して結果から選択したページの内容を説明します。 + +## 発動条件 + + + +以下のようなリクエストで発動します: + +- 「Notionでプロジェクト〇〇を検索して」 +- Notionに関する質問であることが明らかな場合 + + + +## 実行フロー + + + +### 1. キーワード検索と結果表示 + +jqを使って検索結果を箇条書き形式で整形します: + +```bash +mcptools call API-post-search npx -y @notionhq/notion-mcp-server --params '{"query":"プロジェクトXYZ","page_size":10}' | jq -r '.results[] | "- \(if .title then .title[0].text.content else (.properties | to_entries[] | select(.value.type == "title") | .value.title[0].text.content) end)\n - \(.url)"' +``` + +**出力例**: +``` +- プロジェクトXYZ概要 + - https://www.notion.so/abc123de... +- XYZ実装ガイド + - https://www.notion.so/def456gh... +- XYZ関連メモ + - https://www.notion.so/ghi789jk... +- プロジェクトXYZ + - https://www.notion.so/jkl012mn... +``` + + + +**API: API-post-search** + +```json +{ + "properties": { + "filter": { + "additionalProperties": true, + "description": "A set of criteria, `value` and `property` keys, that limits the results to either only pages or only databases. Possible `value` values are `\"page\"` or `\"database\"`. The only supported `property` value is `\"object\"`.", + "properties": { + "property": { + "description": "The name of the property to filter by. Currently the only property you can filter by is the object type. Possible values include `object`. Limitation: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `database`)", + "type": "string" + }, + "value": { + "description": "The value of the property to filter the results by. Possible values for object type include `page` or `database`. **Limitation**: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `database`)", + "type": "string" + } + }, + "type": "object" + }, + "page_size": { + "default": 100, + "description": "The number of items from the full list to include in the response. Maximum: `100`.", + "format": "int32", + "type": "integer" + }, + "query": { + "description": "The text that the API compares page and database titles against.", + "type": "string" + }, + "sort": { + "additionalProperties": true, + "description": "A set of criteria, `direction` and `timestamp` keys, that orders the results. The **only** supported timestamp value is `\"last_edited_time\"`. Supported `direction` values are `\"ascending\"` and `\"descending\"`. If `sort` is not provided, then the most recently edited results are returned first.", + "properties": { + "direction": { + "description": "The direction to sort. Possible values include `ascending` and `descending`.", + "type": "string" + }, + "timestamp": { + "description": "The name of the timestamp to sort against. Possible values include `last_edited_time`.", + "type": "string" + } + }, + "type": "object" + }, + "start_cursor": { + "description": "A `cursor` value returned in a previous response that If supplied, limits the response to results starting after the `cursor`. If not supplied, then the first page of results is returned. Refer to [pagination](https://developers.notion.com/reference/intro#pagination) for more details.", + "type": "string" + } + }, + "type": "object" +} +``` + + + +### 2. ユーザーへの提示 + +AIは検索結果を以下の形式でユーザーに提示します: + +``` +Notionで「プロジェクトXYZ」を検索した結果、以下のページが見つかりました: + +- **プロジェクトXYZ** + - https://www.notion.so/jkl012mn... +- **XYZ関連メモ** + - https://www.notion.so/ghi789jk... +- **XYZ実装ガイド** + - https://www.notion.so/def456gh... +``` + + diff --git a/skills/reading-notion/reference/url-mode.md b/skills/reading-notion/reference/url-mode.md new file mode 100644 index 0000000..4d36087 --- /dev/null +++ b/skills/reading-notion/reference/url-mode.md @@ -0,0 +1,80 @@ +# URL直接モード + +Notion URLを検出すると自動的に発動し、そのページの内容を取得して要約します。 + +## URL検出パターン + +以下のようなNotion URLを検出します: + +``` +https://www.notion.so/{workspace}/{page-id} +https://www.notion.so/{page-id} +``` + +例: +``` +https://www.notion.so/myorg/abc123def456ghi789jkl012mno34567 +https://www.notion.so/abc123def456ghi789jkl012mno34567 +``` + +## 実行手順 + + + +### 1. Markdown変換と出力 + +`notion-to-md`コマンドを使ってNotion URLを直接Markdownに変換します。 + +**実行コマンド**: + +```bash +mkdir -p .claude_work/notion && notion-to-md {notion_url} | tee .claude_work/notion/{page_id}.md > /dev/null +``` + +**説明**: +- `{notion_url}`: ユーザーが提示したNotion URL(例: `https://www.notion.so/workspace/Page-title-abc123...`) +- `{page_id}`: URLの最後の32文字(例: `abc123def456ghi789jkl012mno34567`) +- `tee`を使うことで許可なしでファイル保存が可能 + +### 2. Markdownファイルの読み込みと要約報告 + +出力されたMarkdownファイルをReadツールで読み込み、内容を要約してユーザーに報告します。 + +**手順**: + +1. Readツールで `.claude_work/notion/{page_id}.md` を読み込む +2. ページの主な内容を要約してユーザーに報告(箇条書き5行以内) + +**報告フォーマット**: + +``` +Notionページを以下のファイルに出力しました: +.claude_work/notion/{page_id}.md + +【ページの要約】 +- {要約ポイント1} +- {要約ポイント2} +- {要約ポイント3} +- {要約ポイント4} +- {要約ポイント5} +``` + + + +## エラーハンドリング + +### ページが見つからない場合 + +``` +申し訳ございません。指定されたNotion URLからページを取得できませんでした。 +以下の可能性があります: +- ページが削除されている +- アクセス権限がない +- URLが正しくない +``` + +### API呼び出しが失敗した場合 + +``` +Notion APIへの接続に失敗しました。しばらくしてから再度お試しください。 +```