/spec-intake:grill-issue — issue を詰めて spec に落とせる状態にする
昇格プロトコルの ① issue で議論するを支援する。曖昧な issue を質問攻めで鋭くするのが仕事。
曖昧な issue ──/spec-intake:grill-issue──▶ 鋭い issue ──/spec-intake:spec-draft──▶ spec ──/loop-engine:loop-engine──▶ 実装PR
/spec-intake:spec-draft は「二値で機械判定できる完了基準が書けない issue」を拒否する門番だが、
拒否されたものを詰め直す手段がこれ。門番だけあって詰める手段が無いと片手落ちになる。
方法論は grilling に従う(写経しない=DRY)
対話の進め方(設計ツリー / ラウンド / フロンティア / 推奨解を添えた番号付き質問)は
grilling skill を invoke して、そのとおりに実行する。
grillingが導入されていない場合はその旨を告げ、ラウンド形式の詰めは省いて 通常の質問で進める(導入は https://github.com/mattpocock/skills を参照)。 本 skill はその上に「issue 固有の材料集め・終了条件・書き戻し」を足すだけ。
grilling の大原則で、本 skill でも特に効くもの:
- 事実を見つけるのは AI の仕事、決定を下すのは人間の仕事。 「この機能って今どう動いてる?」を人間に聞かない。調べれば分かることは調べてから聞く。
- フロンティア(前提が揃った問い)を1ラウンドでまとめて出す。 小出しにしない。
- 各質問に自分の推奨解を添える。 丸投げしない。
手順
1. 入口の分岐
| 引数 | 動き |
|---|---|
/spec-intake:grill-issue <番号> |
既存 issue を詰める。本文+全コメントを読む(議論が覆っていることがある) |
/spec-intake:grill-issue(引数なし) |
issue がまだ無い状態から詰める。最後に gh issue create で新規作成 |
既存 issue の場合は gh issue view <N> --json title,body,comments,labels,state で現状を把握する。
すでに loop-ready label が付いている issue は詰め直す前に警告する(spec が既にある=
詰め直すと spec と食い違う。spec 側の更新が要るかを人間に確認する)。
2. 事実収集(質問する前にやる)
grilling が禁じているのは「人間に事実を聞くこと」。ラウンド1を出す前に現物を調べる:
- 現状の挙動 — 関連する実装を読む。「今どうなっているか」を人間に確認させない。
- 製品仕様(anchor) —
docs/specs/に関係する仕様があれば読む(あるプロジェクトなら)。 - 既存テスト — 何がすでに検証されているか。その issue が既に解決済みでないかもここで分かる。
- 関連 issue / PR — 同じ話が別issueで既出でないか(
gh issue list --search)。
広く浅い探索は Task で Explore を haiku で起動してよい(コストを抑える)。
調べた結果はラウンド1の前に「現状こうなっています」として提示する。これが議論の土台になる。
3. grilling を回す
grilling skill の手順どおりにラウンドを回す。
issue を詰める文脈では、次が典型的な設計ツリーの枝になる(毎回全部聞くのではなく、
その issue で未決着の枝だけを選ぶ):
- 意図 — 何が問題か。誰が困るか。放置するとどうなるか。
- 期待する挙動 — 「こうなってほしい」の具体。境界値・エッジケース。
- スコープ — やること / やらないこと(Out が曖昧だと後で膨らむ)。
- 完了の判定 — 何をもって「直った」とするか。どう検証すれば二値で分かるか。
- 触る面 — フロント / API / データ・DB / CLI / infra / docs。security・perf に触れるか。
- 制約 — 後方互換・依存追加の可否・触ってはいけない領域。
4. 終了条件(spec に落とせる要素が揃ったら止める)
grilling の既定は「フロンティアが空になるまで」だが、本 skill はゴールが
/spec-intake:spec-draft に渡せる issue なので、次が揃った時点で止める(無限に詰めない):
- 意図(なぜ要るか)が書ける
- 完了基準の候補が、二値で機械判定できる形で言える(「使いやすくする」で止まっていない)
- スコープ In / Out が言える
- **触る面(検証サーフェス)**が言える
- 制約・ガードレールが言える(無ければ「無し」と言い切れる)
- 無人化禁止対象(security・課金・破壊的変更・認証認可)に触れるかが判定できる
揃わないまま詰め続けてもいい issue にはならないケースがある(=探索が要る・判断が重い)。 その場合は正直に「これは loop 向きではない。
/conductor:dev/人間駆動へ」と結論を出して終わる。 全部を spec 駆動にしない(loop-intake-triage.mdの3トリアージ)。
5. 書き戻し(必ず人間の確認を取ってから)
issue の更新は外向きの破壊的操作。書き換える前に新しい本文の全文を提示して合意を取る。
必ずファイル経由(--body-file)で受け渡す。issue 本文にはバッククォート・$・%・改行・
HTML タグが普通に含まれるため、シェル変数やヒアドキュメントに直接埋めるとクォートが壊れる。
元の本文をコメントに退避する(消さない)。次の3行は必ず1回の Bash 呼び出しで実行する (シェル変数は Bash ツールの呼び出しをまたいで残らないため、分割すると空文字で退避され、 エラーにならず静かに失敗する):
N=<issue番号> gh issue view "$N" --json body -q .body > "/tmp/grill-issue-$N-original.md" { printf '<!-- /spec-intake:grill-issue で整理する前の本文(履歴) -->\n\n'; cat "/tmp/grill-issue-$N-original.md"; } | gh issue comment "$N" --body-file -- 元本文が空・空白のみなら退避コメントは投稿しない(残すものが無いのにノイズを増やさない)。 実際に「本文が空の issue」は珍しくない(タイトルだけで起票されたもの)。
- 退避した場合は、コメントが投稿され中身が空でないことを確認してから次へ進む。
<details>で包まない(元本文が</details>を含むと入れ子が壊れるため。HTML コメントで十分)。ghはリポジトリ内で実行する(cwd がリポジトリ外だとnot a git repositoryで落ちる)。
新しい本文をファイルに書いてから置き換える(
Writeで書き、--body-fileで渡す):gh issue edit "$N" --body-file "/tmp/grill-issue-$N-new.md"issue 本文は現在の合意を示す anchor であるべきで、雑な初稿が残っていると実装時に どれが正か迷う。だから追記ではなく置き換える(元は 1 で退避済み)。
引数なしで始めた場合は、ここで
gh issue create --body-file "/tmp/grill-issue-new.md"する (label は付けない=loop-readyは spec がマージされた後)。
書き戻す本文の形(SPEC.template.md に素直に写せる並びにしておく):
## 意図(なぜ)
<解こうとしている問題。「何を作るか」でなく「なぜ要るか」>
## 期待する挙動
<こうなってほしい、の具体。境界値・エッジケース>
## 触る面(検証サーフェス)
- フロント / API / データ・DB / CLI・lib / infra・config / docs
- 横断: security / perf に触れるか
## 完了の判定(案)
- <二値で判定できる基準>(検証: <実行コマンド / テスト名 の見当>)
## スコープ
- In: <やること>
- Out: <やらないこと>
## 制約・ガードレール
<後方互換・依存追加の可否・触ってはいけない領域。無ければ「無し」>
## 調べて分かっている現状
<手順2で収集した事実。実装の現在地・関連テスト・製品仕様へのリンク>
---
<!-- /spec-intake:grill-issue で整理。元の本文はコメントに退避してあります -->
6. 次の一手を案内して終了
# spec を起草する(issue+コードベース+製品仕様を読んで検証コマンド付きで書き、PR にする)
/spec-intake:spec-draft <N>
loop 向きでないと結論した場合は /conductor:dev を案内する。
アンチパターン
- 調べれば分かることを人間に聞く(grilling の第一原則違反。現状把握は AI の仕事)。
- 質問を小出しにする(フロンティアは1ラウンドでまとめて出す)。
- 推奨解を添えずに丸投げする(「どうしますか?」だけの質問は人間の負荷を上げるだけ)。
- 確認なしに issue 本文を書き換える(外向きの破壊的操作。元本文の退避と合意が先)。
loop-readylabel を付ける(ここではまだ付けない。spec がマージされた後=昇格プロトコル④)。- spec をここで書く(本 skill のゴールは鋭い issue。spec 化は
/spec-intake:spec-draft)。 - 詰まらないものを無理に詰め続ける(
/conductor:dev/人間駆動へ回すのが正しい結論のこともある)。