issueトリアージのラベル操作をラッパースクリプトで安全化

anthropics/claude-code

Claude Codeのissueトリアージ自動化において、ラベル操作を専用の edit-issue-labels.sh スクリプトに集約し、AIが架空のラベルを適用するリスクを排除しました。あわせてトリアージプロンプトを /triage-issue コマンドとして独立したファイルに分離しています。

背景

これまでのトリアージワークフローでは、AIが gh issue edit --add-label を直接呼び出す設計でした。この設計では、AIが存在しないラベルを「発明」してしまう恐れがあり、プロンプト内に許可ラベルの一覧を静的に列挙することで対応していました。しかし、リポジトリのラベルが増減するたびにワークフローYAMLの更新が必要になるという課題がありました。

さらに、トリアージのロジック全体がワークフローYAMLのインラインプロンプトとして記述されており、69行にわたるプロンプト文字列がワークフロー定義に埋め込まれた状態でした。プロンプトの修正がYAMLの編集を意味するため、保守性の観点から分離が求められていました。

技術的な変更

今回の変更は、ラベル操作のバリデーションをランタイムに移行した点が核心です。新設の scripts/edit-issue-labels.sh は、ラベルを適用する前に gh label list でリポジトリの実在するラベルを取得し、指定されたラベルがその一覧に含まれるかを検証します。

スクリプトは --issue--add-label--remove-label の各引数をパースし、issue番号が数値であること、追加・削除のいずれかのラベルが指定されていることを確認してから操作を実行します。バリデーション失敗時は即座に exit 1 で終了するため、不正なラベルがGitHubに送信されることを防ぎます。

トリアージのプロンプトは .claude/commands/triage-issue.md として独立したコマンドファイルに抽出されました。ワークフロー側の変更は prompt: ブロックの削除と1行の差し替えのみで、インラインに展開されていた69行のプロンプトが外部ファイルへの委譲に置き換わっています。コマンドファイルの allowed-tools フロントマターには Bash(./scripts/edit-issue-labels.sh:*) が明示されており、ツールの使用許可をコマンド定義と同じファイルで管理できるようになっています。

また、変更後のコマンドでは gh label list をAIが自ら実行することも促しており、ラベル一覧の取得が「プロンプトへの静的な埋め込み」から「実行時のAPI呼び出し」に変わっています。

# Fetch valid labels from the repo
VALID_LABELS=$(gh label list --limit 500 --json name --jq '.[].name')

設計判断

ラベルバリデーションをAIのプロンプト制約ではなくスクリプト側の責務に移した点が、この変更の最も重要な設計判断です。

プロンプトで「このリストにあるラベルのみ使用せよ」と指示する方法はAIの従順性に依存しており、ラベル一覧の陳腐化リスクも抱えていました。ラッパースクリプトを介在させることで、バリデーションを確定的なコードで行えるようになり、AIの出力がどうであれ不正なラベルは適用されません。

allowed-tools でスクリプトの呼び出しを許可リストに限定する設計も、ツールの使用範囲をコマンド定義と一体で管理できるため、CI設定とは独立したセキュリティ境界を形成しています。

まとめ

プロンプト内の静的な制約をランタイムのバリデーションに置き換えたことで、ラベル操作の安全性がAIの挙動に依存しない確定的な保証に昇格しました。プロンプトの外部コマンド化と合わせて、トリアージ自動化の保守性と信頼性が同時に向上した変更です。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
732faa4c

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)、背景、技術的な変更、設計判断(各論)、まとめ(結論)という「総論→各論→結論」の構成が明確に適用されており、非常に分かりやすい構造です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(`bash:scripts/edit-issue-labels.sh`)とPR番号のリンク記法(`[PR #27911](URL)`)がガイドラインに準拠して正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

ワークフローYAML、シェルスクリプト、プロンプトといったトピックを扱っており、専門知識を持つエンジニアという対象読者に適した技術レベルと表現です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られています。これにより、記事の要点を素早く把握できます。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されている`scripts/edit-issue-labels.sh`のコードスニペットは、提供されたDiff情報と完全に一致しており、正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「ラッパースクリプト」「インラインプロンプト」「フロントマター」など、文脈に応じた技術用語が正確かつ適切に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

ラベルバリデーションをスクリプト側に移行した点や、プロンプトを外部ファイル化した点など、技術的な変更に関する説明はすべてPRのDiff内容と整合しており、論理的かつ正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべてPRのTitle, Description, Diffから裏付け可能です。「69行のプロンプト」という具体的な数値もDiffと一致しており、ハルシネーション(捏造)は見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#27911)、プロンプトの行数(69行)、ファイルパスなどがすべてPR情報と正確に一致しています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「issueトリアージのラベル操作をラッパースクリプトで安全化」は、PRの主題「Use wrapper script for label operations in issue triage」を的確に要約しており、内容と一致しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事には、PR情報に記載のないバージョンサポート状況やリリース日程などの外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「これまでのワークフローでは」「今回の変更は」といった時間表現が、PRの変更前後関係を正確に反映しています。