| name | issue |
| description | GitHub issue を会話コンテキストから新規作成する。起票前に1問ずつのインタビューで内容を合意し、リポジトリを調査して検証可能な要件・影響範囲・品質ゲートを含む本文を作る。「issue にして」「issue 作って」「バグ報告して」「追跡用にチケットを切って」など、新規起票を依頼されたときに使う。閲覧・検索・クローズ・コメント追加には使わない。 |
issue
会話コンテキストとリポジトリの事実から、実装者が単独で着手できる GitHub issue を作成する。
実行スタイル
- 調査は自分で行う: リポジトリ調査を subagent に委任しない。数回のツール呼び出しで済む範囲であり、委任するとインタビュー開始が遅れる。委任してよいのは影響範囲がリポジトリ全域に及び並行探索が明確に速い場合だけで、そのときも1体に留める
- 実況しない: インタビュー中は質問だけを出し、調査の途中経過や検討過程を逐一書かない
- 完了報告は結論から: 作成した issue の URL とタイトルを先に述べる。本文の内容を会話に再掲しない
1. コンテキストを収集する
次を確認する。
gh repo view --json nameWithOwner
git branch --show-current
gh label list --json name,description,color
gh issue list --limit 30 --state all --json number,title,state,labels
あわせて AGENTS.md / CLAUDE.md、README、CI workflow、package manifest、Makefile などを読み、以下を実コードから特定する。
- 関連する既存実装とテスト
- 変更が波及する兄弟入口や設定経路
- lint / test / typecheck などの品質ゲート
.github/ISSUE_TEMPLATE/ の有無(テンプレートがあるリポジトリではその構成を優先し、本スキルのコア構造から不足分だけ補う)
存在しないファイルやコマンドを推測しない。起票時には品質ゲートを実行せず、実装完了時の受け入れ基準として記録する。
重複を先に確認する
インタビューを始める前に類似 issue を探す。重複だと判明するのが遅いほど、それまでの質問が無駄になる。
gh search issues --repo <owner/repo> "<起票内容のキーワード>" --limit 10
gh issue list --limit 30 は直近分しか見えないため、キーワード検索を必ず併用する。類似 issue が見つかったらユーザーに提示し、新規作成を続けるか判断を仰ぐ。既存 issue へのコメント追加は行わない。
2. 内容を合意する
本文生成前に、grilling スタイルでユーザーと合意する。
- 一度に1問だけ聞く
- 調査結果から推奨回答を提示し、Yes / No / 修正で答えられる形にする
- AskUserQuestion ツールが使える環境ではそれを使い、推奨案を先頭の選択肢にして「(Recommended)」を付ける。選択式にできない自由記述の質問だけテキストで聞く
- ファイルパスや既存挙動などの事実は自分で調べ、ユーザーには方針・境界・期待結果だけを聞く
- 会話ですでに合意済みの事項は聞き直さない
次の順で必要な項目だけ確認する。
- 目的と解決したい問題
- カテゴリ
- 再現手順または提案仕様
- 検証可能な受入条件
- スコープ外
- 影響範囲と兄弟入口
- 品質ゲート
- 設計判断がある場合のアプローチ
- 分割方針(振る舞いが2つ以上に見えるなら必ず確認する。分割する場合はスタックの積み順もあわせて合意する)
ユーザーが「そのまま作って」「対話なしで」「おまかせ」と明示した場合、またはタイトルと本文が完全指定されている場合だけインタビューを省略する。
3. カテゴリを決める
| カテゴリ | 用途 | 標準ラベル |
|---|
bug | 不具合報告 | bug |
feature | 新機能・機能改善 | enhancement |
refactor | 挙動を変えない内部改善 | refactor |
chore | 依存更新・設定・雑務 | chore |
docs | ドキュメント更新 | documentation |
複数該当する場合は主カテゴリを1つ選び、補助カテゴリは追加ラベルで表す。該当しない案件はユーザーと合意した汎用構成を使う。
4. 本文を生成する
次のコア構造を使い、不要な任意セクションは省略する。本文は実装者の判断に必要な実質だけを書き、該当のないセクション・要件の言い換え・締めの定型文で膨らませない。
## 概要
何を、なぜ行うかを1〜3文で記述する。
## 背景・目的
複雑な背景がある場合のみ記述する。
<!-- カテゴリ固有セクション -->
## 検討したアプローチ
| アプローチ | 採否 | 理由 |
|---|---|---|
## 参照資料
- path/to/file
## 影響ファイル
- **新規**: path/to/new
- **変更**: path/to/existing
- **削除**: path/to/old
### 兄弟入口・貫通先
- 同じ責務を扱う別入口と、変更要否・理由
## 要件
| # | 入力・操作 | 期待される観測結果 | 種別 | 備考 |
|---|---|---|---|---|
| 1 | ... | ... | 明示 | |
## スコープ外
| 項目 | 除外理由 |
|---|---|
## 受け入れ基準
- [ ] `<lint command>` が exit 0 になる
- [ ] `<test command>` が成功する
依存関係(Blocked by)は本文に書かない。GitHub ネイティブの blocking 関係として登録する(後述)。
カテゴリ固有セクションは次を使う。
bug: 再現手順、期待される動作、実際の動作、影響範囲
feature: 提案する仕様、ユースケース
refactor: 現状の問題、あるべき状態、制約
docs: 対象、想定読者、更新方針
chore: 固有セクションなし
要件は1行に1つの観測可能な結果を書く。A/B、global/project、allow/deny、read/write、作成・更新・削除などの並列条件は別行に分ける。「改善する」「対応する」だけの測定不能な要件を書かない。
1 issue = 1 振る舞い = 1 PR = スタック1段 を粒度の単位とする。
振る舞いとは、外から観測できる挙動の変化を1つ指す。上の要件テーブルの「期待される観測結果」1行に対応する。内部構造だけを変えて観測結果が変わらないものは振る舞いではない。
判定は次の一文で行う。
この issue を完了させたとき、利用者または呼び出し側から見て何が1つ変わるかを1文で言い切れるか。
「〜と〜ができるようになる」「〜を直しつつ〜も追加する」のように接続詞で繋がなければ言えないなら、繋いだ数だけ issue に割る。
次は量的な代理指標で、超えたら振る舞いが複数混ざっている疑いが濃い。単独では分割理由にならないため、該当したら上の一文を言い切れるか問い直す。
| 指標 | 閾値 | 強さ |
|---|
| 要件の件数 | 2件以上 | 強い(要件1行 = 1振る舞いのため) |
| 独立した機能領域・関心事 | 2つ以上混在 | 強い |
| 影響ファイル数 | 4件以上 | 弱い(1つの振る舞いが広く波及することはある) |
「実装が複数 PR に分かれそう」はスタック前提では分割の理由ではなく結果である。複数段に分かれること自体は正常なので、それを避けるために1 issue へ押し戻さない。
判断に迷う場合も分割案を提示する側に倒す。分割で合意した場合は親 issue を本スキルで作成し、子 issue の作成と GraphQL addSubIssue での親子接続は issue-organize スキルの手順に従う。
分割後の1件が満たすべき形
分割して得た各 issue は、次を満たすこと。
- 振る舞いが1つ閉じる: その issue だけを完了させた時点で、宣言した1つの振る舞いを実演または検証できる
- 全レイヤを貫く: schema / API / UI / テストを縦に貫通する狭い完全な経路にする。振る舞いを閉じるには通常これが必要になるため、1レイヤだけを横に切った issue にしない
- 1 context に収まる: 新規セッション1本で実装しきれる分量に収める
- prefactor を先に置く: 実装を楽にする下準備が必要なら、それを先行 issue として独立させる(振る舞いを持たない下準備は下の例外に従う)
例外: 振る舞いを持たない準備段
schema の追加、共通ユーティリティの新設、後述の expand フェーズのように、それ自体では観測できる挙動が変わらない変更がある。これらは「1 issue = 1 振る舞い」を満たさないが、次をすべて満たす場合に限り独立した issue にしてよい。
- スタックの下段に置く
- それを消費して振る舞いを閉じる上段 issue を同時に起票する
- 上段から下段へ
addBlockedBy で依存を張る
- 下段単体で CI green を保てる(旧い形を壊さず隣に足すだけにする)
上段を伴わない準備段は起票しない。上段が存在しないまま準備段だけが main に入ると、誰も呼ばないコードが残る。上段に何を載せるか決まっていない段階は、準備段の起票そのものが早い。
Blocked by(依存関係)を付ける
各 issue に、着手前に完了している必要がある issue を依存関係として登録する。sub-issue の親子は階層であって依存関係ではないため、両方を持たせる。
GitHub ネイティブの blocking 関係(addBlockedBy)を必ず使う。 本文には書かない — 2箇所に持つと必ず食い違うため、ネイティブ側を唯一の正とする。gh issue に依存関係のサブコマンドは無いので GraphQL を使う。
作成順は**依存順(blocker が先)**にする。addBlockedBy は issue の node ID を要求するため、blocker が既に存在していないと接続できない。
BLOCKED_ID=$(gh issue view <塞がれる側の番号> --json id --jq .id)
BLOCKER_ID=$(gh issue view <塞ぐ側の番号> --json id --jq .id)
gh api graphql -f query='
mutation($issueId:ID!,$blockingIssueId:ID!){
addBlockedBy(input:{issueId:$issueId, blockingIssueId:$blockingIssueId}){
issue{ number issueDependenciesSummary{ totalBlockedBy } }
}
}' -F issueId="$BLOCKED_ID" -F blockingIssueId="$BLOCKER_ID"
addBlockedBy の応答に含まれる totalBlockedBy が結果の確認そのものなので、成功応答が返ったら追加の照会はしない。応答が意図と違うとき、または複数 issue を張り終えて依存グラフ全体を見たいときだけ照会する。
gh api graphql -f query='
query($owner:String!,$repo:String!,$num:Int!){
repository(owner:$owner,name:$repo){
issue(number:$num){ blockedBy(first:50){ nodes{ number title state } } }
}
}' -F owner=<owner> -F repo=<repo> -F num=<番号>
着手は frontier — blockedBy が空、または全 blocker が CLOSED の issue — から選ぶ。直列に繋がっている場合は上から順になる。
誤って張った依存は removeBlockedBy を同じ引数で呼べば外せる。
依存チェーンはそのままスタックの積み順になる
分割で得た issue 群の blockedBy チェーンは、実装時に gh-stack のスタック構造そのものになる。起票の段階でスタックを設計していることを意識する。
main (trunk)
└── #12 (blockedBy: なし) → 1段目・PR base = main
└── #13 (blockedBy: #12) → 2段目・PR base = #12 のブランチ
└── #14 (blockedBy: #13) → 3段目
- 直列に置けるものは直列にする: 並列な blocker は積み順が一意に決まらず、スタックに落とす時点で順序を決め直すことになる。実装順に意味があるなら直列の依存を張る
- 1つのスタックは1つのストーリーに保つ: 同じ目的へ向かう issue 群だけを1本の依存チェーンにまとめる。無関係な作業を同じチェーンに混ぜない(別スタックになる)
- 段を積みすぎない: 下段がマージされるたび上段すべてが rebase される。チェーンが伸びるほど1回のマージで動く範囲が広がるため、独立して出せる塊があれば別チェーンに分ける
起票は依存順(blocker が先)に行う。実装側でスタックを積む手順は gh-stack スキルに従う。
例外: wide refactor は expand–contract で並べる
リネームや共有シンボルの再定義のように、1つの機械的変更が全コードベースに波及するもの(wide refactor)は、縦に切ろうとすると単体で green にできない。1つの振る舞いに押し込まず、次の順に並べる。
- expand: 新しい形を旧い形の隣に追加する。この時点では何も壊れない
- migrate: 呼び出し側を波及範囲ごと(パッケージ単位・ディレクトリ単位)のバッチで移す。各バッチを1 issue とし、expand を
Blocked by に置く。旧い形が残っているのでバッチごとに CI は green を保てる
- contract: 呼び出し側が無くなってから旧い形を削除する。全 migrate バッチを
Blocked by に置く
バッチ単体でも green を保てない場合は、この順序のまま1本のスタックに積み、最上段に置いた「統合して検証する」issue へ全バッチを Blocked by として集約する。green を約束するのはその1件だけとする。
5. タイトルとラベルを決める
- タイトルは日本語で簡潔かつ具体的にする
- 過去issueのラベル運用と既存ラベルの description を確認する
- カテゴリに対応する既存ラベルを優先する
- 適切な既存ラベルがない場合だけ、インタビュー中に新規ラベルを提案する
- ユーザーの承認なしに
gh label create を実行しない
takt:* などの workflow・自動化トリガー用ラベルは付与しない。過去 issue でその運用が見えても従わない(着手方式の判断は起票後に行う)
確定タイトルで既存 issue と再度照合する。インタビュー中にスコープが変わっている場合があるため、冒頭の重複確認とは別に最終ガードとして行う。類似 issue があれば新規作成前にユーザーへ確認する。
6. プレビューして作成する
合意したリポジトリ、カテゴリ、タイトル、品質ゲート、ラベルと本文をプレビューする。インタビューでの合意を作成承認とみなし、類似issueがない限り追加確認なしで作成する。
gh issue create --title "タイトル" --body "本文" --label "label1,label2"
作成後はURLを表示する。修正依頼があれば gh issue edit で追従する。
Rules
- APIキー、トークン、パスワード、接続文字列、個人情報を
***REDACTED*** に置換する
参照資料 と 影響ファイル は可能な限り実在する相対パスで書く
要件 と スコープ外 は空のまま作成しない
- 1 issue に振る舞いを2つ以上含めない。「何が1つ変わるか」を1文で言い切れない起票を作らない
- 依存関係は GitHub ネイティブの
addBlockedBy で登録し、本文に Blocked by を書いて代用しない(正が2箇所に分かれるため)
- 品質ゲートを特定できない場合はコマンドを捏造せず、その旨を記載する
- 本文は日本語で書き、コード・識別子・技術用語は原表記を保つ
- 新規 issue 作成以外の GitHub 操作へ範囲を広げない。既存 issue の編集・クローズ・ラベル整理には踏み込まない