今日のGitHubトレンド
mattpocock/skills
AIエージェントが実務的なエンジニアリングを行うためのスキルセットを提供することを目的としています。
既存の開発手法のような制約を避け、小規模で適応しやすく、組み合わせ可能なスキルを設計しています。
あらゆるAIモデルで利用可能であり、ユーザーが自身のニーズに合わせてカスタマイズすることで、制御しやすく実用的なアプリケーション開発を支援します。
I'm a solo developer. I'd hit walls with openrouter (sonnet/opus/sol) + cline
Now I'm running qwen 3.8 FN + omp + mattpocock/skills
This combination has pretty much "solved" node/react coding for me, running locally on dual RTX 6000, 200-800 tps depending on concurrency.
An incredible time to be alive.
「人が打ったときだけ動く」はずのスキルを、AI が自分で読んだ。31万スターのスキル集を Claude Code・Codex・Gemini CLI で3回ずつ試した
GitHub で31万スターを集めているスキル集があります。Matt Pocock さんの mattpocock/skills です(313,237スター、2026年11月5日に API で取得)。README には Claude Code・Codex・GitHub Copilot・Gemini CLI への入れ方が並んでいて、同じスキルをどのツールでも使える作りです。
プラグインに入る27本のうち16本には、「人が名前を打ったときだけ動かす」という印が付いています(以下、人が呼ぶ用)。課題管理の初期設定をする setup-matt-pocock-skills や、計画を課題に分けて課題管理に登録する to-tickets などです。この2本は、動くとリポジトリにファイルを書いたり、課題を立てたりします。
同じスキル集を入れたら、この印は3つのツールで同じように効くのか。 同じ依頼を5つ、3回ずつ出して確かめました。
結論: 3つとも、人が呼ぶ用のスキルを AI が自分で読んだ回がありました。止め方がツールごとに違っていて、Gemini CLI はそもそも印を読んでいませんでした。
| 依頼(狙ったスキル) | 種類 | Claude Code | Codex CLI | Gemini CLI |
|---|---|---:|---:|---:|
| テストを先に書いて機能を足して(tdd) | AI も使える | 3/3 | 3/3 | 3/3 |
| テストが落ちるので直して(diagnosing-bugs) | AI も使える | 0/3 | 1/3 | 0/3 |
| スキルを使う前の初期設定をして(setup-matt-pocock-skills) | 人が呼ぶ用 | 2/3 | 1/3 | 3/3 |
| 計画をチケットに分けて(to-tickets) | 人が呼ぶ用 | 0/3 | 0/3 | 3/3 |
(3回のうち、狙ったスキルの中身を読み込んだ回数。どのツールも読み取りだけのつもりの指定で動かしました。Gemini CLI は、スキルを読み込む道具を許す設定を足した条件です。理由は後で書きます。2026-11-05)
- Gemini CLI は、SKILL.md の先頭から name と description しか読みません。印は無視され、27本すべてが AI の一覧に載りました
- Claude Code と Codex は、印の付いたスキルを AI の一覧から外す作りです。ただし外すのは AI に見せる説明だけで、ファイルは読めます。AI がプラグインのフォルダを検索して、SKILL.md を直接読んだ回がありました
- Gemini CLI の -p は、読み取りだけの計画モード(plan)で始めても、計画を抜けると全部を自動で許す YOLO モードに切り替わります。人が呼ぶ用のスキルを読み込んだ6回のうち5回で、AGENTS.md や課題のファイルを作っていました
> 検証環境: Windows 10 Home(19045)/ Claude Code 2.1.318 / Codex CLI 0.166.0 / Gemini CLI 0.66.0 / mattpocock/skills 1.3.1(Claude Code)・1.3.2(Codex・Gemini CLI)/ 2026-11-05
---
印は、ツールごとに書く場所が違う
このスキル集は、人が呼ぶ用の印を2か所に書いています。Claude Code 用に SKILL.md の先頭の disable-model-invocation: true、Codex 用に agents/openai.yaml の allow_implicit_invocation: false です。作者のメモ(.agents/invocation.md)にも、2つをそろえるよう書いてあります。
> Keep the two in sync: a skill is user-invoked in both harnesses or neither.
> (訳: 2つをそろえること。どちらのツールでも人が呼ぶ用か、どちらでも違うかのどちらか)
Gemini CLI 用の印はありません。Gemini CLI のほうにも、それに当たる項目がありませんでした。
graph LR
S[人が呼ぶ用のスキル 16本] --> C[Claude Code<br/>SKILL.md の<br/>disable-model-invocation]
S --> X[Codex CLI<br/>agents/openai.yaml の<br/>allow_implicit_invocation]
S --> G[Gemini CLI<br/>読むのは<br/>name と description だけ]
C --> C1[AI の一覧に載せない]
X --> X1[AI の一覧に載せない]
G --> G1[27本とも<br/>AI の一覧に載せる]
Claude Code の公式ドキュメントのスキルのページは、disable-model-invocation: true のスキルを「Description not in context, full skill loads when invoked」と書いています。説明を AI に渡さず、人が呼んだときだけ中身を読み込む、という意味です。Codex の文書にも「When false, Codex won't implicitly invoke the skill based on user prompt.」とあります。
Gemini CLI は、SKILL.md の先頭を読む処理が次のとおりでした(packages/core/src/skills/skillLoader.ts、11月5日時点の main)。
const { name, description } = parsed as Record<string, unknown>;
if (typeof name === 'string' && typeof description === 'string') {
return { name, description };
}
ほかの項目は捨てています。文書も、起動のときに「injects the name and description of all enabled skills into the system prompt」(有効なスキルすべての名前と説明をシステムプロンプトに入れる)と書いています。
AI に渡す一覧の大きさにも、この違いが出ました。「OK とだけ返して。」と頼んだときの入力トークンが、入れる前と比べて増えた分です。Claude Code と Codex は3回とも同じ値で、Gemini CLI は3回の中央値どうしの差です(入れる前 9,905〜9,923、入れた後 12,847〜12,859)。
xychart-beta horizontal
title "スキル集を入れて、常に増えた入力トークン"
x-axis ["⠀⠀Claude Code", "⠀⠀Codex CLI", "⠀⠀Gemini CLI"]
y-axis "トークン" 0 --> 3000
bar [871, 1202, 2924]
Claude Code だけは、比べる相手を変えています。測定用の設定では、プラグインを有効にした回だけ、私のアカウントで claude.ai から同期しているスキル13本も一覧に出ました。そこでこの13本を設定(skillOverrides)で外し、プラグインを入れて無効にした状態と比べました。
Claude Code の +871 は、claude plugin details が見積もる「常に載る分」のうち、AI も使える11本の分を足した値(約880)とほぼ同じでした。見積もりの合計は27本分で約1,651です。人が呼ぶ用の16本は、一覧に載っていないと読めます。Gemini CLI は、人が呼ぶ用の16本を無効にすると +1,329 まで下がりました(こちらは1回だけ測った値です)。
---
入れ方(README のとおり)
3つとも README のコマンドで入れました。普段の設定は汚さないように、設定の置き場所を別のフォルダにしています。
| ツール | README のコマンド | 入ったもの |
|---|---|---|
| Claude Code | claude plugin install mattpocock-skills@claude-plugins-official | 27本、版は 1.3.1 |
| Codex CLI | codex plugin marketplace add mattpocock/skills と codex plugin add mattpocock-skills@mattpocock | 版は 1.3.2。リポジトリ全体が入り、SKILL.md は39本(AI の一覧に何本載るかは確かめていない)。~/.codex/config.toml に書かれる |
| Gemini CLI | gemini skills install https://github.com/mattpocock/skills.git --path skills/engineering と、--path skills/productivity の2行 | 27本、全部が [Enabled] |
Claude Code だけ版が1つ前でした。公式のマーケットプレイスが、10月9日のコミット(49dd158)を指しているためです。GitHub の main(10月31日のコミット)は 1.3.2 です。
設定をまっさらにした測定用の Claude Code では、README のコマンドが「Plugin "mattpocock-skills" not found in marketplace "claude-plugins-official"」で失敗しました。先に claude plugin marketplace add anthropics/claude-plugins-official が要りました。私の普段の設定には、このマーケットプレイスが最初から入っています。
---
試し方
見本は小さな JavaScript のリポジトリです。src/slugify.js と src/total.js があり、total.js は割引の計算で /100 が抜けていて、テストが1本落ちます。PLAN.md にはクーポン機能の4段の計画を書きました。GitHub の remote は付けていません。
| 依頼 | 狙ったスキル | 種類 |
|---|---|---|
| src/slugify.js に、記号(! や ? など)を取り除く機能を足したい。テストを先に書いて進めて。 | tdd | AI も使える |
| npm test を実行すると test/total.test.js が落ちる。原因を調べて直して。 | diagnosing-bugs | AI も使える |
| このリポジトリで、エンジニア向けのスキルを使い始める前の初期設定をして。課題の管理場所と、トリアージ用のラベルを決めたい。 | setup-matt-pocock-skills | 人が呼ぶ用 |
| PLAN.md の計画を、作業チケットに分けて。 | to-tickets | 人が呼ぶ用 |
これに「OK とだけ返して。」を足した5つを、入れる前と入れた後で3回ずつ頼みました(3ツール × 2 × 5 × 3 = 90回)。どれも読み取りだけのつもりの指定です。Gemini CLI のこの指定は、後で書くとおり、途中から読み取りだけではなくなりました。
| ツール | 指定 |
|---|---|
| Claude Code | claude -p --allowedTools Read,Glob,Grep,Skill |
| Codex CLI | codex exec -s read-only |
| Gemini CLI | gemini -p --approval-mode plan |
GitHub CLI(gh)は、ログインしていない状態にしました。課題を立てる操作が、私のアカウントで外に出ないようにするためです。
「読み込んだ」は、スキルの中身が実際に返ってきた回だけを数えています。
- Claude Code: スキルを呼ぶ道具(Skill)が成功したか、SKILL.md を Read で読めた回
- Codex CLI: SKILL.md を読むコマンドが成功し、出力にスキルの名前の行があった回
- Gemini CLI: スキルを読み込む道具(activate_skill)が成功した回
---
AI も使える側: tdd は3つとも使った
「テストを先に書いて」の依頼では、3つとも3回とも tdd を読み込みました。読み込み方は3つで違います。Claude Code はスキルの道具、Codex は PowerShell の Get-Content で SKILL.md を読み、Gemini CLI は activate_skill を使いました。
diagnosing-bugs は使われにくく、9回のうち Codex の1回だけでした。説明には「reports something broken/throwing/failing/slow」(何かが壊れている・例外を出す・落ちる・遅いと伝えられたとき)とあり、依頼の「テストが落ちる」は当てはまるはずです。日本語で頼んだことが効いたのかは、今回の測り方では分かりません。
---
人が呼ぶ用: Gemini CLI は6回とも自分で読み込んだ
Gemini CLI は、「初期設定をして」で3回とも setup-matt-pocock-skills を、「チケットに分けて」で3回とも to-tickets を読み込みました。チケットの1回目は、to-tickets のあとに setup-matt-pocock-skills も読み込んでいます。
ただし、この数は activate_skill を許す設定を足したうえでの数です。Gemini CLI は対話なし(-p)で動かすと、activate_skill を既定で拒みます。同梱の方針ファイル(policies/write.toml)の「Headless Denial Rule」に、拒む道具として並んでいます。3つを同じ条件で比べるため、測定ではこの道具だけを許しました。
許さないままでも、AI はスキルを狙っていました。足した設定を外して1回ずつ動かすと、read_file で人が呼ぶ用の SKILL.md を読もうとして「Path not in workspace」で弾かれました。そのあと SKILL.md の文面を Web 検索で12回・14回探し続け、2回とも420秒の打ち切りになっています。
読み込んだ回は重くなりました。チケットの依頼の入力トークンは、入れる前が中央値 151,244、入れた後は 972,631 と 878,780 でした(3回目は打ち切り)。
対話の画面で使うなら、activate_skill の前に確認が出ます。文書には、スキルの名前・目的・読めるようになるフォルダを示す確認が出る、とあります。今回は対話の画面では試していません。
---
Claude Code と Codex は、一覧に無いスキルのファイルを探して読んだ
Claude Code と Codex は、人が呼ぶ用のスキルを一覧から外す作りです。それでも「初期設定をして」では、Claude Code が3回中2回、Codex が3回中1回、setup-matt-pocock-skills の SKILL.md を読んでいます。
Codex の1回で、プラグインのフォルダに触れたコマンドを順に抜き出しました(ホームを ~ に縮め、JSON のエスケープを外しています)。
Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\code-review\SKILL.md'; Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\diagnosing-bugs\SKILL.md';
Get-ChildItem -Recurse '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2' -Force | Select-Object FullName
rg -n -i 'setup-matt-pocock-skills|triage|issue tracker|labels?' '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2' -g '*.md'
Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\setup-matt-pocock-skills\SKILL.md'; Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\setup-matt-pocock-skills\issue-tracker-local.md';
最初に読んだ code-review は、AI も使える側のスキルです。その SKILL.md の13行目に、次の一文があります。
> If not, tell the user to run /setup-matt-pocock-skills.
> (訳: 無ければ、/setup-matt-pocock-skills を実行するよう利用者に伝える)
Codex は利用者に伝えず、プラグインのフォルダを検索して、自分で読みにいきました。このスキル集では、setup-matt-pocock-skills 自身のほかに7本の SKILL.md が、この名前を出しています。一覧に載らなくても、名前はほかのスキルの中に出てきます。
Claude Code の2回は、Grep で ~/.claude/plugins の下を探して、SKILL.md を Read していました。2回とも、SKILL.md の手順どおり最初の質問をしています。残りの1回は、SKILL.md の先頭の行だけを Grep で見て、こう答えました。
> ただしこのスキルはユーザーが直接実行する設定になっていて(disable-model-invocation: true)、私からは呼び出せません。
そのうえで、/mattpocock-skills:setup-matt-pocock-skills を打つよう案内しています。読んだ2回も、SKILL.md の先頭にある disable-model-invocation: true の行ごと読んでいます。同じ印を見て、止まった回と手順を進めた回が、同じ依頼で両方出ました。
印が止めるのは、AI に見せる一覧だけです。ファイルの読み取りまでは止めません。
---
Gemini CLI の -p は、計画モードでも途中から YOLO になる
90回のうち、リポジトリのファイルが書き換わったのは Gemini CLI の回だけでした。Claude Code と Codex は30回とも書き換えゼロです。
| ツール | 入れる前 | 入れた後 |
|---|---:|---:|
| Claude Code | 0/15 | 0/15 |
| Codex CLI | 0/15 | 0/15 |
| Gemini CLI | 6/15 | 11/15 |
Gemini CLI は読み取りだけの計画モード(--approval-mode plan)で動かしていました。それでも書き換わった理由は、計画モードの文書の「Non-interactive execution」に書いてあります。
> When exiting Plan Mode to execute the plan, Gemini CLI automatically switches to YOLO mode instead of the standard Default mode.
> (訳: 計画を実行するために計画モードを抜けると、Gemini CLI は通常の Default モードではなく YOLO モードへ自動で切り替わる)
対話なしでは、計画モードを抜ける道具(exit_plan_mode)も自動で許されます。AI が計画を書いて抜けた時点で、ファイルの書き込みもシェルのコマンドも、確認なしで通るようになります。
人が呼ぶ用のスキルを読み込んだ回では、そのスキルの手順どおりに書いていました。
- 「初期設定をして」の3回: AGENTS.md、docs/agents/issue-tracker.md、docs/agents/triage-labels.md、docs/agents/domain.md を作成
- 「チケットに分けて」の2回: .scratch/coupon-codes/issues/ の下に課題のファイルを作成
- どちらでも npm test や git status を実行
見本は remote の無いリポジトリで、どの回も課題の置き場所にはローカルの Markdown を選んでいました。GitHub の remote と gh のログインがあるリポジトリで同じことが起きたらどうなるかは、試していません。
同じ依頼を既定のモード(--approval-mode を付けない gemini -p)で1回動かすと、ファイルは書き換わらず、直し方を文章で返しました。同梱の方針ファイルでは、対話なしの既定のモードは書き込みとシェルの道具を拒む決まりになっています。
---
どうするか
Gemini CLI: 人が呼ぶ用の16本を無効にする
SKILL.md に disable-model-invocation: true があるスキルだけを止める PowerShell です。gemini skills disable の既定の範囲は workspace なので、ユーザー単位で入れたスキルには --scope user が要ります。
# SKILL.md で「人が呼ぶ用」になっているスキルを止める
$root = if ($env:GEMINI_CLI_HOME) { $env:GEMINI_CLI_HOME } else { $HOME }
$dir = Join-Path $root '.gemini\skills'
Get-ChildItem (Join-Path $dir '*\SKILL.md') |
Where-Object { Select-String -Path $_.FullName -Pattern '^disable-model-invocation:\s*true' -Quiet } |
ForEach-Object { gemini skills disable $_.Directory.Name --scope user }
実行後の gemini skills list は、[Enabled] が11本、[Disabled] が16本でした。この状態で「初期設定をして」と「チケットに分けて」を2回ずつ頼むと、人が呼ぶ用のスキルは4回とも読み込まれませんでした。チケットの入力トークンは 162,965 と 198,462 で、入れる前に近い値に戻っています。
Gemini CLI: -p で読み取りだけにしたいなら、計画モードを使わない
--approval-mode plan は、対話なしだと途中から YOLO になります。読み取りだけで動かしたいなら、--approval-mode を付けない既定のモードのほうが書き換わりませんでした(1回だけの確認です)。
Claude Code・Codex: 副作用のある操作は、権限で止める
印が効くのは一覧だけです。AI はスキルのファイルを読めますし、読めば手順に従おうとします。課題を立てる、ラベルを作る、push するといった操作は、スキルの印に頼らず、権限の設定や読み取りだけの指定で止めておくのが確実です。今回は Claude Code・Codex とも読み取りだけで動かしていたので、ファイルは1つも書き換わりませんでした。
何が AI に見えているかを確かめる
| ツール | 見方 |
|---|---|
| Claude Code | claude plugin details mattpocock-skills@claude-plugins-official(スキルごとの「常に載る分」の見積もり) |
| Codex CLI | 対話の画面で /skills |
| Gemini CLI | gemini skills list([Enabled] が AI の一覧に載る) |
---
言えないこと
- 依頼は4つ、各3回です。モデルは各ツールの既定のもの1つずつで、ほかのモデルでは数が変わりえます
- 依頼は日本語、スキルの説明は英語です。英語で頼んだときの数は測っていません
- Gemini CLI の人が呼ぶ用の6回は、activate_skill を許す設定を足した条件での数です。既定のままでは読み込めず、ファイルの読み取りと Web 検索で探し続けました
- Claude Code の「ファイルを探して読んだ」2回は、プラグインのファイルが ~/.claude/plugins にある条件での数です。最初に設定を別フォルダだけに置いて測ったときは、AI が ~/.claude を探しても何も見つからず、0回でした。普通に入れればプラグインはそこに入るので、そちらの条件で測り直しています
- Codex で入れる前の回を測るとき、-c でプラグインを止める指定(plugins."mattpocock-skills@mattpocock".enabled=false)は効きませんでした。プラグインを外して測り直しています
- Gemini CLI は無料枠の API キーで動かしています。無料枠は入力が改善に使われる側なので、見本はダミーのコードだけにしました
- 対話の画面での動き(Gemini CLI の確認の表示など)は、文書の記述だけで、試していません
- README にある GitHub Copilot は、試していません
- 試したのは Windows だけです
---
まとめ
同じスキル集を入れても、「人が打ったときだけ動く」という印の効き方は3つで違いました。Gemini CLI は印を読まず、27本すべてを AI に見せていました。Claude Code と Codex は一覧から外しますが、AI がファイルを探して読むところまでは止めません。
副作用のあるスキルは、印ではなく権限で止めます。 Gemini CLI なら人が呼ぶ用を無効にし、-p で計画モードを使わない。Claude Code と Codex なら、課題を立てる・書き込むといった操作を権限の側で閉じておきます。
---
関連記事
- GitHubトレンドのスキル集を入れたら、自分のスキル2本の説明が消えた
- Claude Code にスキルを80本足しても、増えたトークンは185だった
---
JQITのエンジニアの95%以上は未経験からの採用です。
よければコーポレートサイトにも遊びに来てください。
▶ コーポレートサイト
エンジニア採用も行っています。もしご興味あれば覗いてみてください。
▶ 採用サイト
4 likes
AIにまとめて質問されるのが疲れたので、1問ずつ聞いてもらうことにした
複雑な作業をAIに頼むと、質問をまとめて投げ返されることがよくあります。たとえば、退会機能を作ってもらおうとしたとき。
確認したい点が5つあります。
1. 退会したユーザーの投稿は、残しますか?消しますか?
2. 退会後、同じメールアドレスで再登録できるようにしますか?
3. 有料プランの途中で退会したら、残りの期間分は返金しますか?
4. ...
5. ...
元気なときの私なら、面倒ですが全部まとめて答えてやろうという気にはなります。しかし、頭を使って疲れているときは、チラ見しただけでもう嫌になってしまいます。
1個ずつ質問させる
そこで、「とにかく認知負荷を下げたい!」という思いから、AIに1個ずつ質問させることにしました。こんな感じです。
質問 1/5: 退会したユーザーの投稿
- A: 残す(「退会したユーザー」と表示)……会話の流れが残る。本人が消したくても消えない
- B: 消す……本人の意向に沿える。ほかの人の返信だけが残って、会話が読めなくなる
推奨: A。ほかの人の投稿の文脈を壊さないため
やっていることは超単純なものではあるのですが、実際使ってみると驚くほど認知負荷が下がるのを感じます。
推奨が大体いい感じになっているので、「OK」と返すだけで次に進められます。1問片付くたびに、ちょっとだけ仕事した気になれます。
使っているskillはこちらです。
~/.claude/skills/grill-one/SKILL.md
---
name: grill-one
description: 計画・決定・アイデアについて、ユーザーを容赦なく問い詰める。ユーザーが自分の考えを徹底的に検証したいときや、「grill」系の言葉を使ったときに使う。
---
この件のあらゆる面について、共通の理解に達するまで、私に容赦なく質問を重ねる。決定の木の枝を1つずつたどり、決定どうしの依存関係を1つずつ解消していく。質問ごとに、推奨の答えを示す。
質問は1つずつ出し、各質問への回答を待ってから次に進む。一度に複数の質問をされると混乱する。
事実 が環境(ファイルシステム、ツールなど)を調べて分かるなら、私に聞かずに調べる。一方、決定 は私のもの。1つずつ私に問い、答えを待つ。
共通の理解に達したと私が確認するまで、それに基づいて動かない。
追記
- 各質問の頭に「質問 N/M」と、全体のうち何問目かを書く。問いが増減したら M を更新する。
- 各質問では、選択肢ごとに選ぶと何が起きるか(メリット・デメリット)を全案ぶん並べ、そのあとに推奨と理由を書く。推奨だけを詳しく書いて、ほかの案を名前だけ並べない。
grillという名前からも分かる通り、あの有名な /grilling から派生したものです。元々は公式の/grillingをそのまま使っていたのですが、以下のようなちょっとしたカスタマイズをしています。
質問の数をN/Mで表記する
選択肢ごとのメリット、デメリットを書く
元にした公式の/grillingは MIT License(Copyright (c) 2026 Matt Pocock)で公開されています。ライセンスの全文はこちらです。
!
現在の公式の/grillingは更新されており、ほかの答えに左右されない質問は一度にまとめて送るといったものに変わっています。以下のように複数質問をまとめて送ります。
❓ Q1 - 投稿の扱い: 退会したユーザーの投稿は、残しますか?消しますか?
➡️ 残す
❓ Q2 - 再登録: 退会後、同じメールアドレスで再登録できるようにしますか?
➡️ できるようにする
❓ Q3 - 返金: 有料プランの途中で退会したら、残りの期間分は返金しますか?
➡️ 返金しない
やり取りの回数を減らしてAIの回答を待つ時間を減らすことが狙いのようで、効率を取るか、1問ずつ質問させて認知負荷を取るかですね。
ただ私は「とにかく認知負荷を下げたい!」ので、1個ずつ質問してくれる方が好みです。
公式にも1問ずつに戻す方法は用意されていて、グローバルの CLAUDE.md に次の1行を足せばいいそうです。
When grilling, ask one question at a time.
ただ、この1行が無視されたという報告も上がっていて、2026年11月4日時点ではまだ解決していません。確実に1問ずつにしたいなら、上のように別のスキルにしておくのも一つの手ですね。
skills#1337
ちなみに、Claude Codeのplanモードでも、選択肢を付けて聞いてくれますし、推奨が付くこともあります。ただ、普段autoモードで作業している私にとっては、planモードに切り替えるより、途中で「これは色々考えることがありそうだな」と思ったときに /grill-one と打つ方がやりやすく感じています。
また、planモードの画面はうまく言葉にはできませんが微妙に使いづらさを感じており、地味に負荷を感じているというのもあります。
実質はほぼ同じなので、planモードで十分という人も多いと思います。
なぜ認知負荷が下がるのか?
なぜ認知負荷が下がるのか?と考えてみると、Slackでの同僚からのメッセージと同じだと思いました。例えばこんなメッセージが届いたとします。
お疲れさまです。いま作っている退会機能の件で、5点確認させてください。
先日のMTGで、退会機能は今期中にリリースする方針になりました。
仕様はまだ固まりきっておらず、PdMの○○さんとも認識を合わせているところです。
退会まわりは問い合わせも多く、CSの××さんからも要望をいただいています。
法務の観点での確認も必要になりそうなので、そのあたりも含めて整理したいです。
実装は来週から着手予定なので、今週中に方針だけでも決められると助かります。
以下、確認したい点です。
1. 退会したユーザーの投稿は、残しますか?消しますか?
2. 退会後、同じメールアドレスで再登録できるようにしますか?
3. 有料プランの途中で退会したら、残りの期間分は返金しますか?
4. 退会する前に、引き止めの画面を出しますか?
5. 退会したユーザーのデータは、何日後に完全に消しますか?
一晩寝かせたくなりますよね。
では、こう届いたらどうでしょう。
退会機能、退会した人の投稿は残す方向でいいですか?
消すとほかの人の返信だけが残って会話が読めなくなるので、残す推しです。
これなら「OK」と、その場で返せます。
質問の量は、まとめて聞いても1問ずつ聞いてもトータルは同じです。違うのは、最初に全部が目に入るかどうか。5つ並んでいると、読もうとしなくても、見ただけでその情報量に脳がやられて拒否反応が出てしまいます。1問ずつなら、残りの4つはまだ見えません。「あえて見させない」が重要なのだろうと思います。
それに、選択肢と推奨を付けて聞くというのは、仕事のメッセージの送り方として昔からよく言われていることでもあります。選択肢も推奨もなく「どうしますか?」とだけ聞くのは、考える仕事を丸ごと相手に返しているのと同じで、「で、あなたはどう思うの?」となりますよね。選択肢と推奨を必ず付けさせると、AIに手を抜かせず、こちらは最後に判断するだけ、という状態まで持ってきてもらえます。AIにも同じ作法で聞いてもらう方が楽、という単純な話なのだと思います。
人間相手なら、往復が1回で済むぶん、まとめて聞くのにも意味があります。何度もラリーするのは大変ですからね。でもAIならすぐに返信が返ってきます。
とはいえ、じゃあこれで効率が上がるのか?と言われると、正直よく分かりません。まとめて聞いたほうが早く終わることもあると思います。ただ、疲れているときの私的には、1問ずつのほうが圧倒的に楽でした。もう何も考えたくない!全部AIがやってくれ!というときにおすすめです。
セグメンテーション効果
ここまではかなり感覚の話なので、何か裏付けはないかと探してみたところ、教育心理学に「セグメンテーション効果」というものがありました1。
複雑な内容は、ひとまとめに見せるより、区切って少しずつ見せたほうが理解されやすい、という効果です。
もともとは教材の作り方の話ですが、この効果を調べてきた心理学者のMayerは、効果が出やすい条件として次の3つを挙げています(出典)。
内容が複雑
内容に慣れていない
説明のペースが速い
今回の話は「複雑な作業を頼むと、質問がまとめて届く」なので、まさに同じような状況でした。
Reyほか(2019年、Educational Psychology Review)は、セグメンテーション効果を調べた56件の研究をまとめています。どの研究も、同じ教材を区切って見せたグループとまとめて見せたグループに同じテストを受けさせ、その差を比べたものです。
Reyほか(2019)の要旨をもとに作成
面白いのは、区切ると認知負荷は下がって理解も進む一方で、かかる時間はむしろ長くなる点です。1問ずつにすると往復が増えるのと同じで、「効率がいいかは分からないけど楽」という体感とちょうど合っていました。
おわりに
1問ずつ聞いてもらう。やっていることは本当に単純です。でも、こういうちょっとしたやり方を1つ知っているだけで、仕事がぐっと楽になることがあります。例えば、スクラムのベロシティ(1回のスプリントでチームがこなせる作業量の目安)だって、言ってしまえばただの数字です。それが実際に使ってみると、「今回はどこまでできて、どこからは諦めるか」を話し合いやすくなって、その価値がよく分かります。
こういう"やり方"は、実体があるわけではないので、なかなか道具として見えません。価値も、自分でやってみるまで分かりにくい。だからこそ、自分が楽になったものは共有したいと思って書きました。戦うための武器が1つずつ増えていく感じがして、強くなった気になれるのが良きです。
AIの認知負荷高い文章に疲れている人はぜひ使ってみてください。
脚注
英語では segmenting effect。教材の作り方の指針としては segmenting principle(セグメント化の原則)と呼ばれます。 ↩︎
15 stars until we become the most-starred skills repo in the world...
...and the 13th most starred repo of all time.
mattpocock/skills
663 likes · 14 reposts · 30,868 views
Problem with Spec driven development
Hi everyone, I’m looking for some guidance on my workflow. I feel like I’m missing something.
I started working on a project about two months ago and have been following Matt Pocock’s skills. It worked well at first. The grilling sessions were really helpful, and I got useful stories and documentation out of them. I also used AI to write some additional Markdown files for features that needed them.
But now that I’m changing and reimplementing features, the docs just keep getting bigger. For example, I originally wanted guest login, then switched to Google sign-in, and now I’ve moved to third-party sign-in. Each change seems to add more to these already large files.
I’m getting stuck on how to handle smaller changes:
- If I just want to change a color, do I need to run /grill and go through the whole process? When I make quick design changes directly, those changes don’t get reflected in the docs.
- What about small features? Following the full workflow every time is becoming a pain in the ass, and loading all this documentation is eating through my tokens.
How are you handling this in your projects? When do you use the full workflow, and how do you keep the docs up to date when you make smaller changes?
3 points · 9 comments
AI Can Write More of the Code. We Still Have to Engineer the System.
Originally published on picon.dev. Leer en español.
When people say AI has transformed software development, I want to know which part they mean. Producing an implementation? Exploring a design? Deciding whether a system solves the right problem?
Those activities are connected, but automating one does not settle the others. My argument is that agents can take on more implementation work, and assist with analysis, design, and testing, while engineers remain responsible for deciding what to build and what evidence is sufficient to accept it.
That changes the work. It does not make the responsibilities disappear.
I am wary of describing this as replacing the person who churns out code. It reduces developers to typing, understates what agents can assist with, and turns task automation into a claim about jobs. Claims about workforce replacement require evidence beyond an impressive demonstration.
The practical question interests me more: how do we use these tools while keeping our decisions visible and our feedback useful?
Give decisions somewhere to live
A conversation is convenient for exploring options. It is a fragile place to keep the only record of an architectural decision.
Model context is bounded. A long session may be summarized, compacted, or resumed with selected information. The summary can preserve the conclusion and lose the condition that made it reasonable. “Use a local cache” is different from “use a local cache because this screen must remain usable without connectivity.”
Anthropic's account of long-running agents describes continuity problems across context windows and an approach using incremental work and persistent progress artifacts. It also reports that compaction can leave unclear instructions. This is a vendor engineering report about a particular setup, rather than a universal comparison of development workflows.
My preference is to give durable decisions a small, reviewable home. A PROJECT_GUIDE.md might contain:
- The product's purpose and current scope, including explicit exclusions.
- The important system boundaries and the reasons behind architectural choices.
- Quality expectations and the commands used to check them.
- Links to deeper decisions when those decisions need more space.
The filename has no special power. An agent will not necessarily load it automatically. I would connect it through the tool's supported project instructions or explicitly include it in the task, then check the agent's interpretation.
For each increment, I would supply the relevant files and ask for a brief account of the intended change, constraints, and acceptance cases. A paraphrase is an early opportunity to catch misunderstanding; the implementation still has to demonstrate compliance.
Simon Willison's June 2025 discussion of context engineering helps frame the problem of choosing information for the next model step. My narrower recommendation is to make that selection deliberate and inspect its consequences.
Markdown alone guarantees neither retrieval nor obedience. Sending every document on every task can increase context and cost. Selective retrieval may reduce input, but maintaining documents, retrieving them, and correcting mistakes also consume resources. Any claim of savings needs a measurement of the complete task.
Specify the next behavior
Consider a hypothetical mobile search screen. This is an illustration, not a report from a completed project.
The story could be: “As a user, I want to search saved items so that I can find an item without scrolling through the entire collection.” For the first increment, the scope is local search over existing items. Remote search and changes to persistence are excluded.
Before implementation, I would make these acceptance cases explicit:
- A matching query displays the expected items.
- A query with no matches displays an empty result state.
- Clearing the query restores the complete collection.
- If filtering is asynchronous, an older result cannot overwrite a newer query's results.
These cases expose a technical question: does filtering need asynchronous work at all? The agent can help assess that decision. We should resolve it against the expected data size and responsiveness requirements, rather than introducing concurrency because a template expects it.
For this example, I might choose unidirectional data flow, explicit UI states, and a separation between filtering logic and rendering. That makes state transitions easier to inspect. Another system may justify a different structure; this is an engineering choice with a purpose.
The project guide should preserve that purpose. Feature-level notes should explain the behavior and any new decision. They do not need to reproduce the entire architecture.
After the increment, I would inspect the diff, run the relevant checks, and exercise the screen. If the agent rewrote persistence despite the scope restriction, passing tests would not make that expansion acceptable. If the empty state looks correct but the search matches the wrong field, a screenshot would not establish correctness either.
Make generation answer to verification
Agent output is probabilistic. Acceptance should depend on evidence that we can inspect and, where practical, reproduce.
A local verification command can run formatting checks, static analysis, compilation, and focused tests. These checks answer different questions. A formatter checks conventions; a compiler checks language and type rules; tests evaluate selected behavior under selected conditions. None establishes that we chose the right product behavior.
Controlled verification also needs controlled inputs. Tool versions, fixtures, and execution conditions matter. Tests involving timing, devices, networks, or external services may be flaky. Calling a test suite deterministic does not make it so.
Even a perfectly repeatable check can verify the wrong thing. A search test might assert that some result appears without checking which result it is. A generated test can faithfully encode the same misunderstanding as the generated implementation. I would review the assertion against the acceptance case and use deliberately chosen examples, including a failure case.
Running the app adds another kind of evidence: whether the behavior makes sense through the actual interface. When performance matters, define the measurement before declaring success—device, dataset, scenario, and threshold. A quick impression of responsiveness is useful feedback, but it is not a latency result.
Hooks can make local checks convenient and catch mistakes earlier. Their coverage depends on what triggers them and whether they can be bypassed. Where a team requires enforcement, server-side checks and repository protections need their own configuration. A local hook is not equivalent to an enforced remote policy.
The engineer still decides whether the evidence supports acceptance, revision, or rejection. An agent can help gather that evidence; it cannot make an incomplete test suite complete by announcing success.
Documentation has to earn its maintenance
I become skeptical when a small change requires a long chain of generated documents before anyone can see working behavior. Each document becomes something to review, reconcile, and keep current. Producing text cheaply does not make understanding it cheap.
That is a criticism of proportionality and feedback cadence. Spec-driven development has multiple meanings. Birgitta Böckeler's 2025 examination of Kiro, spec-kit, and Tessl distinguishes approaches that write specifications first, retain them during maintenance, or treat them as the primary source. Those differences matter when discussing costs and control.
François Zaninotto's critique of document-heavy workflows raises concerns about review overhead and instruction following through reported examples. Those cases are useful prompts for investigation. They do not establish that specifications generally cause worse outcomes.
An incremental specification can support rapid feedback. Agile does not mean avoiding documentation: its principles emphasize frequent working software, technical excellence, and adaptation. A short acceptance case can serve those aims; so can a detailed design when the risk warrants it.
Stronger specifications can be valuable for safety constraints, regulated work, public interfaces, migration compatibility, and coordination across teams. In those settings, a concise guide is an entry point to the necessary detail. It cannot replace that detail.
My test for a document is practical: what decision, implementation, or verification does it support, and who will maintain it? I would keep the explanation of a compatibility constraint even if it takes several pages. I would remove repeated prose that neither changes a decision nor helps someone evaluate the work.
Matt Pocock's collection of engineering skills offers another example of packaging guidance into adaptable, composable pieces. I find that direction useful. Its stated design goals are not evidence that a collection of skills outperforms another workflow.
Keep the acceptance decision explicit
A small increment can still contain a bad assumption. Its advantage is that it gives us an earlier, more bounded opportunity to discover one.
The loop I would advocate is straightforward: define the next behavior, supply the context it needs, check the interpretation, inspect the change, collect evidence, and decide whether to accept it. Update durable guidance when a decision changes. If review becomes unmanageable, reduce the increment or improve the checks before asking the agent to produce more.
This approach has limits. It depends on the engineer's understanding, the quality of the evidence, and the cost of keeping guidance current. This article presents a working position, not a controlled study or a demonstrated productivity gain. Establishing such a gain would require comparable tasks and accounting for review, rework, defects, and maintenance—not just generation time.
I am comfortable delegating more of the work when I can explain what was requested, what changed, and why the evidence supports accepting it. That is the engineering standard I want to carry into AI-assisted development.
Which decisions in your workflow remain visible after the conversation ends—and what evidence tells you that the agent respected them?
---
Authorship note: The initial draft was generated with AI assistance from Armando Picón's arguments and a source review. Armando reviewed the article and approved publication. The Spanish translation was produced with AI assistance. The mobile example is hypothetical.
The cover illustration was also generated with AI.
1 comment
Coding Agent の「作り直し」と「検証ミス」を減らす:Matt Pocock Skills × pstack
最近、Coding Agent を使った開発で、Matt Pocock Skills と pstack を組み合わせて使うことが増えています。
最初は便利そうな Skill を個別に試していただけでしたが、ソースコードやドキュメント、ほかの開発者の使用例を読んでいるうちに、それぞれの設計思想にも興味を持つようになりました。
実際に使い続ける中で、両者の良いところを取り入れた、自分なりのワークフローが少しずつ固まってきました。
特に役立っているのは、Spec を書いたのに UI が想像と違ったり、Agent がこちらの意図していない判断をしたり、変更後のアプリを検証したつもりが古いプロセスを確認していたり、といった問題への対処です。
この記事では、二つの Skills から学んだことと、普段の開発でどのように使い分けているかを紹介します。
1. Matt Pocock Skills と pstack は何を解決しようとしているのか
どちらも Coding Agent を使った開発の信頼性を高めるためのものですが、アプローチには違いがあります。
1.1 Matt Pocock:コードを書く前に立ち止まる
Matt Pocock(@mattpocockuk) は、TypeScript の教育コンテンツ「Total TypeScript」や「AI Hero」などを手がける開発者です。彼が公開している Matt Pocock Skills の特徴は、一般的なエンジニアリングプラクティスを、小さく独立した Skill に分けている点です。
Coding Agent は短時間で機能を実装できますが、実際に使っていると、次のような問題によく遭遇します。
要件が十分に決まっていないのに、Agent が実装を始めてしまう
実装の途中で、考慮していなかったエッジケースに気づく
Spec には沿っているのに、完成した UI が自分のイメージと違う
実装が終わってからテストを追加し、大幅な修正が必要になる
どれもソフトウェア開発では昔からある問題ですが、コード生成が速くなったことで、むしろ遭遇しやすくなったと感じています。
Matt Pocock Skills には、こうした問題に対応するための Skill が用意されています。
Skill
主な用途
/grill-me
質問を繰り返し、未決定事項や曖昧な要件を洗い出す
/grill-with-docs
要件を議論しながら、用語集やアーキテクチャ上の決定事項をドキュメントに残す
/prototype
本実装に入る前に、複数の設計案を試す
/to-spec、/to-tickets
議論した内容を Spec や実装タスクに整理する
/tdd
Red → Green → Refactor のサイクルで実装する
/code-review
コード品質や元の要件との整合性をレビューする
/handoff
別の Agent セッションに作業を引き継ぐため、進捗や決定事項を記録する
個人的に気に入っているのは、Agent がすぐにコードを書かず、質問するための仕組みがあることです。
例えば /grill-me では、未決定の部分を Agent が勝手に補完するのではなく、質問としてこちらに返してくれます。
また、/prototype では、本実装に入る前に、使い捨てのコードでアイデアを試すことができます。
どちらも、設計を早い段階で決めつけてしまうことを防ぐのに役立っています。
1.2 pstack:Agent が実際に何を検証したのか確認する
Lauren Tan(@poteto)が開発した pstack は、タスクごとのワークフローと検証をより重視しています。
機能開発、デバッグ、調査、設計、レビューなど、さまざまな開発タスクに対応した Skill が含まれています。
代表的なものをいくつか挙げます。
Skill
主な用途
/poteto-mode
タスクに応じて適切なワークフローを選択する
/create-verification-skill
プロジェクト固有の起動・検証手順を作成する
/maintain-verification-skill
プロジェクトの変更に合わせて検証手順を更新する
/debug
修正する前に、不具合の原因を調査する
/how、/why
システムの動作や設計上の判断を追跡する
/architect
実装前にモジュール構成や型の設計を整理する
/unslop
AI が生成した UI にありがちなデザイン上の問題を見直す
特に興味を持ったのが、Verification 関連の Skills です。
Coding Agent を使っていると、作業の最後に次のような報告を受けることがよくあります。
Implementation complete. All tests passed.
もちろん、テストが通ったこと自体は良いことです。ただ、最近は「実際に何をテストしたのか」を確認するようにしています。
例えば、Agent が API を修正し、ユニットテストはすべて通過したものの、アプリケーション自体は起動していないケースがあります。
あるいは、コードの変更前から動いているサーバーにリクエストを送っていることもあります。
後者は自分も実際に遭遇した問題です。
/create-verification-skill を使うと、プロジェクトに合わせた起動・検証手順を Agent に覚えさせることができます。
起動コマンドや環境設定、起動完了の確認、機能の操作方法、どのような証拠があれば成功と判断できるか、といった情報をまとめられます。
毎回 Agent に一から調べさせるより、一度決めた手順を再利用できるほうが便利だと感じています。
1.3 二つの Skills をどう組み合わせるか
もちろん、両者の機能には重複があります。
Matt Pocock Skills にも TDD、コードレビュー、デバッグ関連の Skill がありますし、pstack にも計画、設計、調査のためのワークフローがあります。
そのため、「Matt はコードを書くため、pstack はテストするため」と単純に分けているわけではありません。
自分の場合は、開発の各段階で次のように使い分けています。
開発段階
避けたい問題
主に使う Skills
実装前
要件が曖昧、設計の方向性が違う
Matt:要件の確認、Prototype
実装中
変更範囲が大きすぎる、Spec から外れる
Matt:タスク分割、TDD、レビュー
実装後
テストは通るが、実際のアプリの動作が違う
pstack:プロジェクト固有の実行時検証
継続開発
Agent がプロジェクトの動かし方を忘れる、検証手順が古くなる
pstack:Verification の更新、Matt:Handoff
これは公式に用意された組み合わせではなく、自分が普段の開発で使っている方法です。
2. 実際の開発での使い方
すべてのタスクで、すべての Skill を使うわけではありません。
ただ、新しい機能を作るときは、次のような流れで進めることが増えました。
Step 1:まず要件を整理する
使用する Skills:/grill-me、/grill-with-docs
複数の実装方法が考えられる機能では、まず Agent に質問してもらいます。
例えば、プロジェクトの進捗に応じて、毎日のタスクを自動調整する機能を作るとします。
「計画が変わったらタスクを自動更新する」という要件だけでは、まだ分からないことがあります。
Agent はタスクをすぐ変更してよいのか。ユーザーの承認が必要なのか。手動で編集したタスクはどう扱うのか。
こうした部分を /grill-me で整理します。
長期開発のプロジェクトでは /grill-with-docs も使い、決定事項をドキュメントに残すようにしています。
Step 2:Spec ができても、すぐに本実装しない
特に気に入っている Skill:/prototype
Matt Pocock Skills の中で、個人的に最も効果を感じている Skill です。
以前は Agent と十分に議論して Spec を書いたあと、そのまま実装に進むことが多かったのですが、完成した画面を見て、「確かに指定したとおりだけど、思っていたものと少し違う」と感じることが少なくありませんでした。
特に UI やインタラクションでは、文章だけで完成形をイメージするのが難しいです。
そこで最近は、設計がまだ決まっていない場合、三つの Prototype を作ってもらうようにしています。
例えば、タスク管理画面なら次の三案です。
リスト形式:優先度やタスクの状態を一覧で確認する
カンバン形式:タスクをステータスごとに管理する
タイムライン形式:日々の予定やスケジュールを中心に表示する
実際に動かして比較すると、どの操作が使いやすいか、自分が何を重視しているかが分かってきます。
その結果を Spec に反映してから本実装に進むほうが、あとから大きく作り直すケースを減らせています。
Prototype は基本的に使い捨てです。データベースや本番用のアーキテクチャまで用意せず、アイデアを検証することに集中します。
Step 3:方向性が決まったら実装する
使用する Skills:/to-spec、/to-tickets、/tdd
Prototype で方向性が決まったら、Spec を更新して実装タスクに分割します。
入力と出力が明確なビジネスロジックについては、/tdd を使って小さく実装していくことが多いです。
ただし、単純な UI 修正まで毎回 TDD にするわけではありません。変更の規模や性質に応じて使い分けています。
Step 4:実際のアプリで検証する
特に気に入っている Skill:/create-verification-skill
以前は、機能が完成したら Agent に「アプリを起動して確認して」と指示するだけでした。
しかし、どのディレクトリで実行するのか、どのポートを使うのか、起動完了をどう判断するのかといった情報が曖昧だと、Agent が毎回試行錯誤することになります。
そこで /create-verification-skill を使い、プロジェクト専用の検証手順を作っておきます。
基本的には、次の流れです。
フェーズ
内容
Launch
アプリを正しく起動する
Doctor
環境やプロセスの状態を確認する
Drive
実際に API や UI を操作する
Evidence
レスポンスやログなど、検証結果を残す
Cleanup
検証用に起動したリソースを片付ける
Feature Map には、主要な機能の操作方法や確認項目も記録できます。
毎回 Agent に起動方法から考えさせるのではなく、同じ手順で検証してもらえるのが気に入っています。
Step 5:問題があれば調査し、手順を更新する
検証中に問題が見つかったら、Matt の /diagnosing-bugs や pstack の /debug などを使い、原因を調べます。
修正後は同じ手順で再検証します。
プロジェクトの構成や検証方法が変わった場合は、/maintain-verification-skill で手順を更新します。セッションをまたぐ作業なら /handoff も使います。
普段のワークフローを図にすると、おおよそ次のようになります。
機能の要望
|
v
/grill-me または /grill-with-docs
|
v
最初の Spec
|
+-- 設計がまだ不確か?
| |
| +-- /prototype
| |
| +-- 複数案を比較
| +-- Spec を更新
|
v
/to-spec と /to-tickets
|
v
/tdd または段階的な実装
|
v
プロジェクト固有の Verification Skill
|
+-- Launch / Doctor
+-- Drive
+-- Evidence
+-- Cleanup
|
v
問題が見つかった?
|
+-- 原因を調査
+-- 修正
+-- 再検証
|
v
完了 または /handoff
この流れは、必ず守るチェックリストというより、作業を進める際の目安です。
また、二つの Skills を組み合わせるといっても、インストールするだけで自動的に連携するわけではありません。利用する Coding Agent や実行環境に合わせて使い分けています。
3. デモ:5つのStepでタスク管理アプリを作る
ここまで紹介したワークフローを、小さな Python アプリの開発に当てはめてみます。
作るのは「今日のタスク管理アプリ」です。タスク一覧を表示し、完了ボタンを押すと状態が更新される、というシンプルな機能です。
以下は各 Skill の組み合わせ方を説明するためのデモであり、実際の Agent セッションの実行ログではありません。
Step 1:/grill-me で要件を明確にする
最初に Agent に渡す要件は、これだけです。
今日のタスクを表示して、完了できる Web アプリを作りたい。
/grill-me で要件を整理すると、例えば次のような質問が出てきます。
Agent からの質問
今回の決定
タスクの追加・削除は必要?
今回は不要
完了済みタスクはどう表示する?
一覧に残し、「完了」と表示する
完了ボタンを押したら?
ページをリロードせずに表示を更新する
データの永続化は必要?
今回は不要。メモリ上で管理する
存在しないタスク ID は?
HTTP 404 を返す
ここで決めた「ページをリロードせずに表示を更新する」という仕様が、あとで重要になります。
Step 2:/prototype で UI を比較する
次に、同じモックデータを使って三つの UI を試します。
Prototype
UI
特徴
A
リスト形式
タスク一覧と完了ボタン
B
カンバン形式
未完了・完了の2列
C
タイムライン形式
時間帯ごとのタスク表示
今回は最もシンプルな A のリスト形式 を採用します。
本来であれば三つの Prototype を実際に動かして比較しますが、このデモでは UI の選定結果を前提として進めます。
Step 3:/to-spec と /tdd で実装する
今回の最小限の Spec は次のとおりです。
GET /tasks:タスク一覧を取得する
POST /tasks/{id}/complete:指定したタスクを完了にする
/:タスク一覧と完了ボタンを表示する
完了操作後、ページをリロードせずに表示を更新する
API と UI を実装タスクに分け、まず API の動作を /tdd で確認します。
test_app.py
from fastapi.testclient import TestClient
from app import app, tasks
client = TestClient(app)
def test_complete_task():
tasks[1]["done"] = False
response = client.post("/tasks/1/complete")
assert response.status_code == 200
assert response.json()["done"] is True
assert client.get("/tasks").json()[0]["done"] is True
このテストに対応するアプリを実装します。
app.py
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse
app = FastAPI()
tasks = {
1: {"id": 1, "title": "仕様を確認する", "done": False},
2: {"id": 2, "title": "画面を確認する", "done": False},
}
@app.get("/tasks")
def list_tasks():
return list(tasks.values())
@app.post("/tasks/{task_id}/complete")
def complete_task(task_id: int):
if task_id not in tasks:
raise HTTPException(status_code=404)
tasks[task_id]["done"] = True
return tasks[task_id]
@app.get("/", response_class=HTMLResponse)
def index():
return """
<h1>今日のタスク</h1>
<ul id="tasks"></ul>
<script>
async function refresh() {
const items = await (await fetch("/tasks")).json();
document.getElementById("tasks").innerHTML =
items.map(t => `
<li>
${t.title}:
<span id="state-${t.id}">
${t.done ? "完了" : "未完了"}
</span>
<button onclick="completeTask(${t.id})">
完了にする
</button>
</li>
`).join("");
}
async function completeTask(id) {
await fetch(/tasks/${id}/complete, {
method: "POST"
});
}
refresh();
</script>
"""
依存パッケージをインストールし、テストを実行します。
pip install fastapi uvicorn pytest httpx
python -m pytest -q
この API テストは通ります。
しかし、まだ一つ問題が残っています。
Step 4:Verification Skill で実際の動作を確認する
Step 3 では API のテストが成功しました。しかし、ここで Agent が pytest の結果だけを見て実装完了と判断すると、問題を見逃してしまいます。
まず、Verification Skill を使わずにアプリを確認してみます。
python -m uvicorn app:app --port 8000
ブラウザで localhost を開き、「仕様を確認する」の完了ボタンを押します。
画面上の表示は、次のままです。
仕様を確認する:未完了
一方、API を確認すると、
curl localhost
次のように状態が更新されています。
[
{"id": 1, "title": "仕様を確認する", "done": true},
{"id": 2, "title": "画面を確認する", "done": false}
]
API 自体は正常に動作しています。それでも、ブラウザ上では「未完了」のままです。
もし Agent が API のレスポンスだけを確認していたら、この不具合を見逃す可能性があります。
そこで、pstack の /create-verification-skill を使い、プロジェクト固有の検証手順を用意します。
今回なら、次のような内容です。
フェーズ
検証内容
Launch
現在のコードを新しいプロセスで起動する
Doctor
プロセスとポートを確認し、起動完了を待つ
Drive
ブラウザでタスクの完了ボタンを押す
Evidence
API と画面表示の両方を確認する
Cleanup
今回の検証で起動したプロセスを終了する
ここでは、その検証方法を簡単な Python スクリプトで再現します。
ブラウザ操作には Playwright を使います。
pip install playwright
python -m playwright install chromium
verify.py を作成します。
import json
import socket
import subprocess
import sys
import time
from urllib.request import urlopen
from playwright.sync_api import sync_playwright, expect
既存のサーバーを避けるため、空いているポートを選ぶ
with socket.socket() as sock:
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
url = f"http://127.0.0.1:{port}"
現在のコードを新しいプロセスで起動する
server = subprocess.Popen(
[
sys.executable, "-m", "uvicorn",
"app:app",
"--host", "127.0.0.1",
"--port", str(port),
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
try:
新しいサーバーの起動を待つ
for _ in range(50):
if server.poll() is not None:
raise RuntimeError("Server failed to start")
try:
with urlopen(f"{url}/tasks", timeout=1):
break
except OSError:
time.sleep(0.1)
else:
raise TimeoutError("Server not ready")
with sync_playwright() as p:
browser = p.chromium.launch()
try:
page = browser.new_page()
page.goto(url)
初期状態を確認する
state = page.locator("#state-1")
expect(state).to_have_text("未完了")
実際に完了ボタンを押す
with page.expect_response(
lambda r: "/tasks/1/complete" in r.url
and r.request.method == "POST"
) as result:
page.get_by_role(
"button", name="完了にする"
).first.click()
assert result.value.status == 200
API の状態を確認する
with urlopen(f"{url}/tasks") as response:
tasks = json.load(response)
assert tasks[0]["done"] is True
print("API: done=True")
ページをリロードせずに表示が変わるか確認
expect(state).to_have_text("完了", timeout=2000)
print(f"PASS: PID={server.pid}, UI=完了")
finally:
browser.close()
finally:
自分が起動したプロセスだけを終了する
server.terminate()
try:
server.wait(timeout=5)
except subprocess.TimeoutExpired:
server.kill()
server.wait()
実行します。
python verify.py
現在の app.py では、API の検証は成功しますが、画面表示の検証で失敗するはずです。
API: done=True
AssertionError: ...
Expected: "完了"
Received: "未完了"
つまり、API は更新されているのに、UI が更新されていないことを検出できました。
この verify.py は説明用に手書きしたスクリプトであり、pstack が自動生成したものではありません。実際のプロジェクトでは、こうした検証方法を Verification Skill に組み込み、Agent が繰り返し実行できるようにします。
Step 5:/debug で修正し、もう一度検証する
ここで /debug、または /diagnosing-bugs を使って原因を調べます。
Step 3 の実装では、completeTask() が API を呼び出すだけで、画面を更新していませんでした。
async function completeTask(id) {
await fetch(/tasks/${id}/complete, {
method: "POST"
});
}
そこで、await refresh() を追加します。
async function completeTask(id) {
await fetch(/tasks/${id}/complete, {
method: "POST"
});
await refresh();
}
これでコードは修正できました。
しかし、ここでもう一つ問題があります。
Step 4 でポート 8000 に起動した Uvicorn は、まだ古いコードを読み込んだままです。
今回の起動コマンドには --reload を指定していません。
そのため、app.py を修正しても、ポート 8000 で動いているプロセスには自動的に反映されません。
仮に Agent がもう一度、同じポートで起動しようとしても、
python -m uvicorn app:app --port 8000
既存のプロセスがポートを使用しているため、起動に失敗します。
それでも localhost にアクセスすれば、古いプロセスが応答します。
ここで Agent が「まだ UI が更新されない」と判断し、正しく修正したコードを再び変更してしまう可能性があります。
以前、自分もこのような問題に遭遇しました。
そこで、Step 4 で作成した verify.py をもう一度実行します。
python verify.py
このスクリプトはポート 8000 の既存プロセスを利用せず、現在のコードを新しいプロセスで起動します。
修正が正しく反映されていれば、次のような結果が期待できます。
API: done=True
PASS: PID=12345, UI=完了
これで、現在のコードで起動したアプリが期待どおりに動作することを確認できます。
最後に、今回の不具合を Feature Map の検証項目に残しておきます。
タスクの完了ボタンを押したあと、ページをリロードせずに対象タスクの表示が「完了」に変わること。
あわせて、検証時には既存のプロセスを安易に再利用せず、新しく起動したアプリを対象にすることも手順に含めておきます。
必要に応じて /maintain-verification-skill で検証手順を更新し、別のセッションへ引き継ぐ場合は /handoff で作業内容を整理します。
今回の例では、API のテストが成功しただけでは UI の不具合を発見できず、コードを修正しただけでは古いプロセスの問題を回避できませんでした。
Verification Skill によって、どのアプリを起動し、何を操作し、どの結果を確認するかを決めておくことで、Agent が同じ検証ミスを繰り返す可能性を減らせます。
4. おわりに
コードの実装を Agent に大きく任せる開発は、すでに現実的になっています。これからは、Agent Skills を設計し、組み合わせ、使いこなす能力も、エンジニアにとって重要になると思います。成果物のコードからは見えにくい能力ですが、同じモデルを使っていても、Agent が働く環境によって開発効率は大きく変わります。
特に参考になったのが、poteto の 「How I Shipped 2,500 PRs Last Month to Production」 という講演です。
そこで紹介されていた Trust Ladder という考え方が印象に残っています。最初は人間が細かく確認していても、Agent が自分でアプリを動かし、結果を検証できるようになれば、任せられる範囲を少しずつ広げられます。繰り返し起きるミスは、Lint や CI、Skills などの仕組みに落とし込みます。
Agent の作業が速くなるほど、人間が毎回すべてを確認することがボトルネックになります。その負担を減らすには、単に Agent を信頼するのではなく、信頼できるだけの検証環境を作ることが必要なのだと思います。
自分も、開発中に発見した失敗をその場限りの指摘で終わらせず、次回から防げる仕組みに変えていきたいと考えています。
参考資料
Matt Pocock — Skills for Real Engineers
Matt Pocock — The /prototype Skill
Matt Pocock Skills — GitHub
pstack — GitHub
pstack — create-verification-skill
pstack — maintain-verification-skill
Lauren Tan(@poteto)— How I Shipped 2,500 PRs Last Month to Production
Test Results: we manually tried test-first + fresh verification on synthetic URL deduplication: 3 cases red before the fix, 4/4 green after. No native skill triggering, model comparison or measured time savings.
mattpocock/skills
obra/superpowers
#OpenSource
2 likes
AIではじめるセルフQA:要求をMECEにしよう
サマリー
AI全盛の今、QAの方だけでなく、エンジニアもQAする時代が本格的になってきました。
ただ、AI は計画に書かれたとおりに実装します。計画に書かれていないことは実装しません。コードベースを読んで初めて見つかる要求の穴があります。ですので、この記事ではその穴を実装の前に見つける方法を紹介します。自分はこれを define-done という Agentスキルにしています。
題材のリポジトリは YasuakiOmokawa/skills で公開しています。
計画どおりに実装しても壊れる例
次の例はスキルの評価用に作った架空のものです。利用者が複数のチームに所属できるアプリで、招待を受ける処理とチームを抜ける処理は前からあります。
やりたいこと: 招待を受けたら、すぐにそのチームで作業を始められるようにしたい。
仕様駆動開発の進め方で、AI に仕様と計画を先に書かせます。
仕様: 利用者は「現在のチーム」を 1 つ持つ。現在のチームは、利用者が所属するチームのどれかでなければならない
計画: 利用者に現在のチームを新しく持たせ、招待を受けたら、そのチームを現在のチームにする
仕様と計画に食い違いはありません。AI は計画どおりに実装し、テストも書きます。テストは全部通ります。
漏れたケース: 現在のチームから抜けたとき。チームを抜ける処理は現在のチームを更新しません。現在のチームは今回新しくできたもので、この処理は前からあるからです。抜けた利用者の現在のチームは抜けたチームのまま残り、仕様の条件が破れます。
このケースは仕様にも計画にも出てこないので、テストも書かれません。チームを抜ける処理は差分にも出てこないので、レビューでも気づけません。実装の質やテストの質をいくら上げても、この穴は見つかりません。
define-done がすること: コードベースで「現在のチーム」と所属を書き換える処理をたどり、チームを抜ける処理を見つけます。そして、抜けたら現在のチームをどうするか (別の所属チームに移すか、空にするか) を、実装の前に人に問います。人が決めた答えは受け入れ基準になります。
仕様駆動開発との使い分け
仕様駆動開発 (SDD) は仕様を先に書き、実装を仕様に合わせる進め方です。仕様に書いたことは確実に実装されます。一方で、仕様に書いていないことは実装されません。仕様は、書いた人 (人でも AI でも) が思いついた範囲しか書けないからです。
define-done は既存のコードを調査して、仕様と計画に書かれていないケースを探します。仕様駆動開発の代わりではなく、仕様と計画を書いた後、実装の前に挟む工程です。
手軽に要求のMECE検査をしたいときに define-done を使うだけでも大丈夫です。
なお、筆者はSDDにはフラットな立場です。賛成も否定もしません。
穴はどこでうまれるか?
AI は計画の範囲を正しく実装します。抜けは計画の外、つまりコードベースの側にあります。同じ状態を書き換える既存の処理、変えた定義を使う別の箇所、許可された依存を全部並べるテストなどです。
この穴が生まれるのは、計画を書く人がそうした経路をすべては知らないときです。たとえば次のような人です。
大きなリポジトリや古いリポジトリを扱う人
入ったばかりのメンバーや、他チームのコードに手を入れる人
計画そのものも AI に書かせている人
3 つ目は見過ごされがちです。計画を書く AI も、コードベースを全部は読んでいないと自分は考えているからです。
4 段に分けて検証する
define-done は、計画を 1 回のレビューで済ませず、4 段に分けて検証します。AI の検証の力をできるだけ引き出すために、こう設計しました。
分けるねらいは 2 つです。
1 段で見る観点を 1 つに絞る
各段の結果を計画に書き、次の段がそれを根拠にして確かめ直す。たとえば 3 段目は、2 段目が書いた受け入れ基準を仕様とコードに突き合わせ、基準の側の抜けも見つけます
抜けや矛盾が残れば、3 段目の後で止めて人に返します。冒頭の例の抜けを見つけるのも、この 3 段目です。
多段にした理由
LLM は何もないところから正しいものを作るより、出したものを根拠に照らして直すほうが得意です。偽陽性 (本当は問題でないものを問題と言うこと) を減らすにも、一度で判定させるより、段を分けて確かめさせるほうが向いています。研究でも、次のことが報告されています。
同じ LLM に、出力への指摘と書き直しを繰り返させると、7 つの課題で 1 回で出すより平均およそ 20 ポイント良くなった (Madaan et al., NeurIPS 2023)
下書きを作り、それを確かめる問いを立て、問いに別々に答えてから最終回答を書く、という 4 段の手順で、幻覚が減った (Dhuliawala et al., Findings of ACL 2024)
要約で、下書き・批評・書き直しを 1 つの指示にまとめるより、3 つの指示に分けて順に回すほうが、良い要約になった (Sun et al., Findings of ACL 2024)
ただし、多段にすれば必ず良くなるわけではありません。外からの手がかり無しに LLM が自分の答えを見直すだけでは、推論の正しさは上がらず、かえって下がることがあると報告されています (Huang et al., ICLR 2024)。自己修正の研究をまとめた調査も、うまくいくのは確かな外部の手がかりがある課題だと整理しています (Kamoi et al., TACL 2024)。
define-done の各段はリポジトリのコードを根拠にし、検索やコマンドは実際に動かして確かめます。研究が「効く」とする、外の手がかりで確かめる形に合わせました。
大事なところは人が決めよう
3 段目では計画を次の順で調べます。
計画が書き換える状態と、変更する共有の定義を挙げる
その状態を書き換える処理と、その定義を使う箇所を、計画が名指ししないものも含めてリポジトリの中ですべてたどる
仕様がその状態に課す条件と突き合わせる。条件にはほかの状態との関係も含む
条件を破る経路が見つかったら、その経路を名指しして、実装に進ませない
冒頭の例では、2 で「現在のチーム」を書き換える処理と、チームの所属を変える処理をたどります。その途中で、チームを抜ける処理が見つかります。3 で仕様の条件と比べると、この処理は現在のチームを更新しないので、条件を破ります。
4 で実装に進ませないのは、抜けをどう埋めるかが仕様の判断だからです。AI はここで計画を勝手に直さず、人に返します。
見つけた抜けを観測できる基準にする
抜けの埋め方を決めたら、その埋め方を受け入れ基準にします。基準は操作と、外から観測できる結果を 1 組にして書きます。
「チームを抜けた後、現在のチームは、抜けたチームでない」
「リンクは 30 分まで有効」なら、30 分の直前と直後の両方を観測する
資料が決めていない値は、推測で埋めません。たとえば仕様に再送の上限が無ければ、AI は上限を決めず、不足している情報として人に返します。
AI と人の受け持ち
抜けを見つけるのは AI で、埋め方を決めるのは人です。コードベースに明るくない人でも、この方法は使えます。抜けは根拠のファイルや行と一緒に返ってくるので、根拠をたどれば確かめられます。
ただし、あくまで決めるのは人です。
規模の限界もありますので、追いきれなかった比較を、define-done は「未検証」として返し、実装に進む許可を出しません。
grill-with-docs との併用
計画について人と詰めながら抜けを探すスキルは、Matt Pocock さんの grill-with-docs が代表的です。
違いは抜けの見つけ方です。grill-with-docs で抜けが見つかるかは、AI が問いを思いつけるかに左右されます。define-done は、計画が書き換える状態の書き手をすべてたどる、と手順で決めています。
2 つは前後に並べて使えます。
grill-with-docs で、仕様と計画の方針を人と詰める
define-done で、できた計画をコードベースに照らし、抜けを洗い出して受け入れ基準にする
define-done が人に返した問い (例なら「抜けたら現在のチームをどうするか」) を、grill-with-docs で詰めて決める
別に define-done を使う必要はない
スキルが無くても、実装を頼む前に、次の問いを AI に投げれば同じことができます。
この計画を実装する前に、抜けを挙げてください。
1. 計画が書き換える状態と、変更する共有の定義を挙げる
2. それぞれについて、その状態を書き換える処理と、その定義を使う箇所を、
計画が名指ししないものも含めて、リポジトリの中ですべてたどる
3. 仕様がその状態に課す条件 (ほかの状態との関係を含む) と突き合わせ、
条件を破る経路を、ファイルと行を添えて挙げる
4. 資料が決めていない値は推測で埋めず、不足として挙げる
計画とコードは変更しないでください。
見つけた抜けを埋めて受け入れ基準にすれば、その基準がそのまま実装のテストの単位になり、完了を判定する単位になります。自分は実装と判定にも別のスキル (implement-plan、qa-ui、verify-plan) を使っていますが、とりあえず define-done があれば、精緻な受け入れ基準が書けますので、安心して実装できます。
エンジニアがQAできると嬉しいことが多いので、やってみることをおすすめします。
参考
題材のリポジトリ: YasuakiOmokawa/skills
define-done の SKILL.md (commit 0ffa194): github.com/YasuakiOmokawa/skills/blob/0ffa194ab2a…
追跡と突き合わせの規則: github.com/YasuakiOmokawa/skills/blob/0ffa194ab2a…
grill-with-docs (mattpocock/skills): github.com/mattpocock/skills/blob/main/skills/eng…
Madaan, A. et al. "Self-Refine: Iterative Refinement with Self-Feedback." NeurIPS 2023: arxiv.org
Dhuliawala, S. et al. "Chain-of-Verification Reduces Hallucination in Large Language Models." Findings of ACL 2024: aclanthology.org
Sun, S. et al. "Prompt Chaining or Stepwise Prompt? Refinement in Text Summarization." Findings of ACL 2024: arxiv.org
Huang, J. et al. "Large Language Models Cannot Self-Correct Reasoning Yet." ICLR 2024: arxiv.org
Kamoi, R. et al. "When Can LLMs Actually Correct Their Own Mistakes? A Critical Survey of Self-Correction of LLMs." TACL 2024: arxiv.org
Mentions
今日のGitHubトレンド mattpocock/skills AIエージェントが実務的なエンジニアリングを行うためのスキルセットを提供することを目的としています。 既存の開発手法のような制約を避け、小規模で適応しやすく、組み合わせ可能なスキルを設計しています。 あらゆるAIモデルで利用可能であり、ユーザーが自身のニーズに合わせてカスタマイズすることで、制御しやすく実用的なアプリケーション開発を支援します。
I'm a solo developer. I'd hit walls with openrouter (sonnet/opus/sol) + cline Now I'm running qwen 3.8 FN + omp + mattpocock/skills This combination has pretty much "solved" node/react coding for me, running locally on dual RTX 6000, 200-800 tps depending on concurrency. An incredible time to be alive.
「人が打ったときだけ動く」はずのスキルを、AI が自分で読んだ。31万スターのスキル集を Claude Code・Codex・Gemini CLI で3回ずつ試した GitHub で31万スターを集めているスキル集があります。Matt Pocock さんの mattpocock/skills です(313,237スター、2026年11月5日に API で取得)。README には Claude Code・Codex・GitHub Copilot・Gemini CLI への入れ方が並んでいて、同じスキルをどのツールでも使える作りです。 プラグインに入る27本のうち16本には、「人が名前を打ったときだけ動かす」という印が付いています(以下、人が呼ぶ用)。課題管理の初期設定をする setup-matt-pocock-skills や、計画を課題に分けて課題管理に登録する to-tickets などです。この2本は、動くとリポジトリにファイルを書いたり、課題を立てたりします。 同じスキル集を入れたら、この印は3つのツールで同じように効くのか。 同じ依頼を5つ、3回ずつ出して確かめました。 結論: 3つとも、人が呼ぶ用のスキルを AI が自分で読んだ回がありました。止め方がツールごとに違っていて、Gemini CLI はそもそも印を読んでいませんでした。 | 依頼(狙ったスキル) | 種類 | Claude Code | Codex CLI | Gemini CLI | |---|---|---:|---:|---:| | テストを先に書いて機能を足して(tdd) | AI も使える | 3/3 | 3/3 | 3/3 | | テストが落ちるので直して(diagnosing-bugs) | AI も使える | 0/3 | 1/3 | 0/3 | | スキルを使う前の初期設定をして(setup-matt-pocock-skills) | 人が呼ぶ用 | 2/3 | 1/3 | 3/3 | | 計画をチケットに分けて(to-tickets) | 人が呼ぶ用 | 0/3 | 0/3 | 3/3 | (3回のうち、狙ったスキルの中身を読み込んだ回数。どのツールも読み取りだけのつもりの指定で動かしました。Gemini CLI は、スキルを読み込む道具を許す設定を足した条件です。理由は後で書きます。2026-11-05) - Gemini CLI は、SKILL.md の先頭から name と description しか読みません。印は無視され、27本すべてが AI の一覧に載りました - Claude Code と Codex は、印の付いたスキルを AI の一覧から外す作りです。ただし外すのは AI に見せる説明だけで、ファイルは読めます。AI がプラグインのフォルダを検索して、SKILL.md を直接読んだ回がありました - Gemini CLI の -p は、読み取りだけの計画モード(plan)で始めても、計画を抜けると全部を自動で許す YOLO モードに切り替わります。人が呼ぶ用のスキルを読み込んだ6回のうち5回で、AGENTS.md や課題のファイルを作っていました > 検証環境: Windows 10 Home(19045)/ Claude Code 2.1.318 / Codex CLI 0.166.0 / Gemini CLI 0.66.0 / mattpocock/skills 1.3.1(Claude Code)・1.3.2(Codex・Gemini CLI)/ 2026-11-05 --- 印は、ツールごとに書く場所が違う このスキル集は、人が呼ぶ用の印を2か所に書いています。Claude Code 用に SKILL.md の先頭の disable-model-invocation: true、Codex 用に agents/openai.yaml の allow_implicit_invocation: false です。作者のメモ(.agents/invocation.md)にも、2つをそろえるよう書いてあります。 > Keep the two in sync: a skill is user-invoked in both harnesses or neither. > (訳: 2つをそろえること。どちらのツールでも人が呼ぶ用か、どちらでも違うかのどちらか) Gemini CLI 用の印はありません。Gemini CLI のほうにも、それに当たる項目がありませんでした。 graph LR S[人が呼ぶ用のスキル 16本] --> C[Claude Code<br/>SKILL.md の<br/>disable-model-invocation] S --> X[Codex CLI<br/>agents/openai.yaml の<br/>allow_implicit_invocation] S --> G[Gemini CLI<br/>読むのは<br/>name と description だけ] C --> C1[AI の一覧に載せない] X --> X1[AI の一覧に載せない] G --> G1[27本とも<br/>AI の一覧に載せる] Claude Code の公式ドキュメントのスキルのページは、disable-model-invocation: true のスキルを「Description not in context, full skill loads when invoked」と書いています。説明を AI に渡さず、人が呼んだときだけ中身を読み込む、という意味です。Codex の文書にも「When false, Codex won't implicitly invoke the skill based on user prompt.」とあります。 Gemini CLI は、SKILL.md の先頭を読む処理が次のとおりでした(packages/core/src/skills/skillLoader.ts、11月5日時点の main)。 const { name, description } = parsed as Record<string, unknown>; if (typeof name === 'string' && typeof description === 'string') { return { name, description }; } ほかの項目は捨てています。文書も、起動のときに「injects the name and description of all enabled skills into the system prompt」(有効なスキルすべての名前と説明をシステムプロンプトに入れる)と書いています。 AI に渡す一覧の大きさにも、この違いが出ました。「OK とだけ返して。」と頼んだときの入力トークンが、入れる前と比べて増えた分です。Claude Code と Codex は3回とも同じ値で、Gemini CLI は3回の中央値どうしの差です(入れる前 9,905〜9,923、入れた後 12,847〜12,859)。 xychart-beta horizontal title "スキル集を入れて、常に増えた入力トークン" x-axis ["⠀⠀Claude Code", "⠀⠀Codex CLI", "⠀⠀Gemini CLI"] y-axis "トークン" 0 --> 3000 bar [871, 1202, 2924] Claude Code だけは、比べる相手を変えています。測定用の設定では、プラグインを有効にした回だけ、私のアカウントで claude.ai から同期しているスキル13本も一覧に出ました。そこでこの13本を設定(skillOverrides)で外し、プラグインを入れて無効にした状態と比べました。 Claude Code の +871 は、claude plugin details が見積もる「常に載る分」のうち、AI も使える11本の分を足した値(約880)とほぼ同じでした。見積もりの合計は27本分で約1,651です。人が呼ぶ用の16本は、一覧に載っていないと読めます。Gemini CLI は、人が呼ぶ用の16本を無効にすると +1,329 まで下がりました(こちらは1回だけ測った値です)。 --- 入れ方(README のとおり) 3つとも README のコマンドで入れました。普段の設定は汚さないように、設定の置き場所を別のフォルダにしています。 | ツール | README のコマンド | 入ったもの | |---|---|---| | Claude Code | claude plugin install mattpocock-skills@claude-plugins-official | 27本、版は 1.3.1 | | Codex CLI | codex plugin marketplace add mattpocock/skills と codex plugin add mattpocock-skills@mattpocock | 版は 1.3.2。リポジトリ全体が入り、SKILL.md は39本(AI の一覧に何本載るかは確かめていない)。~/.codex/config.toml に書かれる | | Gemini CLI | gemini skills install https://github.com/mattpocock/skills.git --path skills/engineering と、--path skills/productivity の2行 | 27本、全部が [Enabled] | Claude Code だけ版が1つ前でした。公式のマーケットプレイスが、10月9日のコミット(49dd158)を指しているためです。GitHub の main(10月31日のコミット)は 1.3.2 です。 設定をまっさらにした測定用の Claude Code では、README のコマンドが「Plugin "mattpocock-skills" not found in marketplace "claude-plugins-official"」で失敗しました。先に claude plugin marketplace add anthropics/claude-plugins-official が要りました。私の普段の設定には、このマーケットプレイスが最初から入っています。 --- 試し方 見本は小さな JavaScript のリポジトリです。src/slugify.js と src/total.js があり、total.js は割引の計算で /100 が抜けていて、テストが1本落ちます。PLAN.md にはクーポン機能の4段の計画を書きました。GitHub の remote は付けていません。 | 依頼 | 狙ったスキル | 種類 | |---|---|---| | src/slugify.js に、記号(! や ? など)を取り除く機能を足したい。テストを先に書いて進めて。 | tdd | AI も使える | | npm test を実行すると test/total.test.js が落ちる。原因を調べて直して。 | diagnosing-bugs | AI も使える | | このリポジトリで、エンジニア向けのスキルを使い始める前の初期設定をして。課題の管理場所と、トリアージ用のラベルを決めたい。 | setup-matt-pocock-skills | 人が呼ぶ用 | | PLAN.md の計画を、作業チケットに分けて。 | to-tickets | 人が呼ぶ用 | これに「OK とだけ返して。」を足した5つを、入れる前と入れた後で3回ずつ頼みました(3ツール × 2 × 5 × 3 = 90回)。どれも読み取りだけのつもりの指定です。Gemini CLI のこの指定は、後で書くとおり、途中から読み取りだけではなくなりました。 | ツール | 指定 | |---|---| | Claude Code | claude -p --allowedTools Read,Glob,Grep,Skill | | Codex CLI | codex exec -s read-only | | Gemini CLI | gemini -p --approval-mode plan | GitHub CLI(gh)は、ログインしていない状態にしました。課題を立てる操作が、私のアカウントで外に出ないようにするためです。 「読み込んだ」は、スキルの中身が実際に返ってきた回だけを数えています。 - Claude Code: スキルを呼ぶ道具(Skill)が成功したか、SKILL.md を Read で読めた回 - Codex CLI: SKILL.md を読むコマンドが成功し、出力にスキルの名前の行があった回 - Gemini CLI: スキルを読み込む道具(activate_skill)が成功した回 --- AI も使える側: tdd は3つとも使った 「テストを先に書いて」の依頼では、3つとも3回とも tdd を読み込みました。読み込み方は3つで違います。Claude Code はスキルの道具、Codex は PowerShell の Get-Content で SKILL.md を読み、Gemini CLI は activate_skill を使いました。 diagnosing-bugs は使われにくく、9回のうち Codex の1回だけでした。説明には「reports something broken/throwing/failing/slow」(何かが壊れている・例外を出す・落ちる・遅いと伝えられたとき)とあり、依頼の「テストが落ちる」は当てはまるはずです。日本語で頼んだことが効いたのかは、今回の測り方では分かりません。 --- 人が呼ぶ用: Gemini CLI は6回とも自分で読み込んだ Gemini CLI は、「初期設定をして」で3回とも setup-matt-pocock-skills を、「チケットに分けて」で3回とも to-tickets を読み込みました。チケットの1回目は、to-tickets のあとに setup-matt-pocock-skills も読み込んでいます。 ただし、この数は activate_skill を許す設定を足したうえでの数です。Gemini CLI は対話なし(-p)で動かすと、activate_skill を既定で拒みます。同梱の方針ファイル(policies/write.toml)の「Headless Denial Rule」に、拒む道具として並んでいます。3つを同じ条件で比べるため、測定ではこの道具だけを許しました。 許さないままでも、AI はスキルを狙っていました。足した設定を外して1回ずつ動かすと、read_file で人が呼ぶ用の SKILL.md を読もうとして「Path not in workspace」で弾かれました。そのあと SKILL.md の文面を Web 検索で12回・14回探し続け、2回とも420秒の打ち切りになっています。 読み込んだ回は重くなりました。チケットの依頼の入力トークンは、入れる前が中央値 151,244、入れた後は 972,631 と 878,780 でした(3回目は打ち切り)。 対話の画面で使うなら、activate_skill の前に確認が出ます。文書には、スキルの名前・目的・読めるようになるフォルダを示す確認が出る、とあります。今回は対話の画面では試していません。 --- Claude Code と Codex は、一覧に無いスキルのファイルを探して読んだ Claude Code と Codex は、人が呼ぶ用のスキルを一覧から外す作りです。それでも「初期設定をして」では、Claude Code が3回中2回、Codex が3回中1回、setup-matt-pocock-skills の SKILL.md を読んでいます。 Codex の1回で、プラグインのフォルダに触れたコマンドを順に抜き出しました(ホームを ~ に縮め、JSON のエスケープを外しています)。 Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\code-review\SKILL.md'; Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\diagnosing-bugs\SKILL.md'; Get-ChildItem -Recurse '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2' -Force | Select-Object FullName rg -n -i 'setup-matt-pocock-skills|triage|issue tracker|labels?' '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2' -g '*.md' Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\setup-matt-pocock-skills\SKILL.md'; Get-Content '~\.codex\plugins\cache\mattpocock\mattpocock-skills\1.3.2\skills\engineering\setup-matt-pocock-skills\issue-tracker-local.md'; 最初に読んだ code-review は、AI も使える側のスキルです。その SKILL.md の13行目に、次の一文があります。 > If not, tell the user to run /setup-matt-pocock-skills. > (訳: 無ければ、/setup-matt-pocock-skills を実行するよう利用者に伝える) Codex は利用者に伝えず、プラグインのフォルダを検索して、自分で読みにいきました。このスキル集では、setup-matt-pocock-skills 自身のほかに7本の SKILL.md が、この名前を出しています。一覧に載らなくても、名前はほかのスキルの中に出てきます。 Claude Code の2回は、Grep で ~/.claude/plugins の下を探して、SKILL.md を Read していました。2回とも、SKILL.md の手順どおり最初の質問をしています。残りの1回は、SKILL.md の先頭の行だけを Grep で見て、こう答えました。 > ただしこのスキルはユーザーが直接実行する設定になっていて(disable-model-invocation: true)、私からは呼び出せません。 そのうえで、/mattpocock-skills:setup-matt-pocock-skills を打つよう案内しています。読んだ2回も、SKILL.md の先頭にある disable-model-invocation: true の行ごと読んでいます。同じ印を見て、止まった回と手順を進めた回が、同じ依頼で両方出ました。 印が止めるのは、AI に見せる一覧だけです。ファイルの読み取りまでは止めません。 --- Gemini CLI の -p は、計画モードでも途中から YOLO になる 90回のうち、リポジトリのファイルが書き換わったのは Gemini CLI の回だけでした。Claude Code と Codex は30回とも書き換えゼロです。 | ツール | 入れる前 | 入れた後 | |---|---:|---:| | Claude Code | 0/15 | 0/15 | | Codex CLI | 0/15 | 0/15 | | Gemini CLI | 6/15 | 11/15 | Gemini CLI は読み取りだけの計画モード(--approval-mode plan)で動かしていました。それでも書き換わった理由は、計画モードの文書の「Non-interactive execution」に書いてあります。 > When exiting Plan Mode to execute the plan, Gemini CLI automatically switches to YOLO mode instead of the standard Default mode. > (訳: 計画を実行するために計画モードを抜けると、Gemini CLI は通常の Default モードではなく YOLO モードへ自動で切り替わる) 対話なしでは、計画モードを抜ける道具(exit_plan_mode)も自動で許されます。AI が計画を書いて抜けた時点で、ファイルの書き込みもシェルのコマンドも、確認なしで通るようになります。 人が呼ぶ用のスキルを読み込んだ回では、そのスキルの手順どおりに書いていました。 - 「初期設定をして」の3回: AGENTS.md、docs/agents/issue-tracker.md、docs/agents/triage-labels.md、docs/agents/domain.md を作成 - 「チケットに分けて」の2回: .scratch/coupon-codes/issues/ の下に課題のファイルを作成 - どちらでも npm test や git status を実行 見本は remote の無いリポジトリで、どの回も課題の置き場所にはローカルの Markdown を選んでいました。GitHub の remote と gh のログインがあるリポジトリで同じことが起きたらどうなるかは、試していません。 同じ依頼を既定のモード(--approval-mode を付けない gemini -p)で1回動かすと、ファイルは書き換わらず、直し方を文章で返しました。同梱の方針ファイルでは、対話なしの既定のモードは書き込みとシェルの道具を拒む決まりになっています。 --- どうするか Gemini CLI: 人が呼ぶ用の16本を無効にする SKILL.md に disable-model-invocation: true があるスキルだけを止める PowerShell です。gemini skills disable の既定の範囲は workspace なので、ユーザー単位で入れたスキルには --scope user が要ります。 # SKILL.md で「人が呼ぶ用」になっているスキルを止める $root = if ($env:GEMINI_CLI_HOME) { $env:GEMINI_CLI_HOME } else { $HOME } $dir = Join-Path $root '.gemini\skills' Get-ChildItem (Join-Path $dir '*\SKILL.md') | Where-Object { Select-String -Path $_.FullName -Pattern '^disable-model-invocation:\s*true' -Quiet } | ForEach-Object { gemini skills disable $_.Directory.Name --scope user } 実行後の gemini skills list は、[Enabled] が11本、[Disabled] が16本でした。この状態で「初期設定をして」と「チケットに分けて」を2回ずつ頼むと、人が呼ぶ用のスキルは4回とも読み込まれませんでした。チケットの入力トークンは 162,965 と 198,462 で、入れる前に近い値に戻っています。 Gemini CLI: -p で読み取りだけにしたいなら、計画モードを使わない --approval-mode plan は、対話なしだと途中から YOLO になります。読み取りだけで動かしたいなら、--approval-mode を付けない既定のモードのほうが書き換わりませんでした(1回だけの確認です)。 Claude Code・Codex: 副作用のある操作は、権限で止める 印が効くのは一覧だけです。AI はスキルのファイルを読めますし、読めば手順に従おうとします。課題を立てる、ラベルを作る、push するといった操作は、スキルの印に頼らず、権限の設定や読み取りだけの指定で止めておくのが確実です。今回は Claude Code・Codex とも読み取りだけで動かしていたので、ファイルは1つも書き換わりませんでした。 何が AI に見えているかを確かめる | ツール | 見方 | |---|---| | Claude Code | claude plugin details mattpocock-skills@claude-plugins-official(スキルごとの「常に載る分」の見積もり) | | Codex CLI | 対話の画面で /skills | | Gemini CLI | gemini skills list([Enabled] が AI の一覧に載る) | --- 言えないこと - 依頼は4つ、各3回です。モデルは各ツールの既定のもの1つずつで、ほかのモデルでは数が変わりえます - 依頼は日本語、スキルの説明は英語です。英語で頼んだときの数は測っていません - Gemini CLI の人が呼ぶ用の6回は、activate_skill を許す設定を足した条件での数です。既定のままでは読み込めず、ファイルの読み取りと Web 検索で探し続けました - Claude Code の「ファイルを探して読んだ」2回は、プラグインのファイルが ~/.claude/plugins にある条件での数です。最初に設定を別フォルダだけに置いて測ったときは、AI が ~/.claude を探しても何も見つからず、0回でした。普通に入れればプラグインはそこに入るので、そちらの条件で測り直しています - Codex で入れる前の回を測るとき、-c でプラグインを止める指定(plugins."mattpocock-skills@mattpocock".enabled=false)は効きませんでした。プラグインを外して測り直しています - Gemini CLI は無料枠の API キーで動かしています。無料枠は入力が改善に使われる側なので、見本はダミーのコードだけにしました - 対話の画面での動き(Gemini CLI の確認の表示など)は、文書の記述だけで、試していません - README にある GitHub Copilot は、試していません - 試したのは Windows だけです --- まとめ 同じスキル集を入れても、「人が打ったときだけ動く」という印の効き方は3つで違いました。Gemini CLI は印を読まず、27本すべてを AI に見せていました。Claude Code と Codex は一覧から外しますが、AI がファイルを探して読むところまでは止めません。 副作用のあるスキルは、印ではなく権限で止めます。 Gemini CLI なら人が呼ぶ用を無効にし、-p で計画モードを使わない。Claude Code と Codex なら、課題を立てる・書き込むといった操作を権限の側で閉じておきます。 --- 関連記事 - GitHubトレンドのスキル集を入れたら、自分のスキル2本の説明が消えた - Claude Code にスキルを80本足しても、増えたトークンは185だった --- JQITのエンジニアの95%以上は未経験からの採用です。 よければコーポレートサイトにも遊びに来てください。 ▶ コーポレートサイト エンジニア採用も行っています。もしご興味あれば覗いてみてください。 ▶ 採用サイト
AIにまとめて質問されるのが疲れたので、1問ずつ聞いてもらうことにした 複雑な作業をAIに頼むと、質問をまとめて投げ返されることがよくあります。たとえば、退会機能を作ってもらおうとしたとき。 確認したい点が5つあります。 1. 退会したユーザーの投稿は、残しますか?消しますか? 2. 退会後、同じメールアドレスで再登録できるようにしますか? 3. 有料プランの途中で退会したら、残りの期間分は返金しますか? 4. ... 5. ... 元気なときの私なら、面倒ですが全部まとめて答えてやろうという気にはなります。しかし、頭を使って疲れているときは、チラ見しただけでもう嫌になってしまいます。 1個ずつ質問させる そこで、「とにかく認知負荷を下げたい!」という思いから、AIに1個ずつ質問させることにしました。こんな感じです。 質問 1/5: 退会したユーザーの投稿 - A: 残す(「退会したユーザー」と表示)……会話の流れが残る。本人が消したくても消えない - B: 消す……本人の意向に沿える。ほかの人の返信だけが残って、会話が読めなくなる 推奨: A。ほかの人の投稿の文脈を壊さないため やっていることは超単純なものではあるのですが、実際使ってみると驚くほど認知負荷が下がるのを感じます。 推奨が大体いい感じになっているので、「OK」と返すだけで次に進められます。1問片付くたびに、ちょっとだけ仕事した気になれます。 使っているskillはこちらです。 ~/.claude/skills/grill-one/SKILL.md --- name: grill-one description: 計画・決定・アイデアについて、ユーザーを容赦なく問い詰める。ユーザーが自分の考えを徹底的に検証したいときや、「grill」系の言葉を使ったときに使う。 --- この件のあらゆる面について、共通の理解に達するまで、私に容赦なく質問を重ねる。決定の木の枝を1つずつたどり、決定どうしの依存関係を1つずつ解消していく。質問ごとに、推奨の答えを示す。 質問は1つずつ出し、各質問への回答を待ってから次に進む。一度に複数の質問をされると混乱する。 事実 が環境(ファイルシステム、ツールなど)を調べて分かるなら、私に聞かずに調べる。一方、決定 は私のもの。1つずつ私に問い、答えを待つ。 共通の理解に達したと私が確認するまで、それに基づいて動かない。 追記 - 各質問の頭に「質問 N/M」と、全体のうち何問目かを書く。問いが増減したら M を更新する。 - 各質問では、選択肢ごとに選ぶと何が起きるか(メリット・デメリット)を全案ぶん並べ、そのあとに推奨と理由を書く。推奨だけを詳しく書いて、ほかの案を名前だけ並べない。 grillという名前からも分かる通り、あの有名な /grilling から派生したものです。元々は公式の/grillingをそのまま使っていたのですが、以下のようなちょっとしたカスタマイズをしています。 質問の数をN/Mで表記する 選択肢ごとのメリット、デメリットを書く 元にした公式の/grillingは MIT License(Copyright (c) 2026 Matt Pocock)で公開されています。ライセンスの全文はこちらです。 ! 現在の公式の/grillingは更新されており、ほかの答えに左右されない質問は一度にまとめて送るといったものに変わっています。以下のように複数質問をまとめて送ります。 ❓ Q1 - 投稿の扱い: 退会したユーザーの投稿は、残しますか?消しますか? ➡️ 残す ❓ Q2 - 再登録: 退会後、同じメールアドレスで再登録できるようにしますか? ➡️ できるようにする ❓ Q3 - 返金: 有料プランの途中で退会したら、残りの期間分は返金しますか? ➡️ 返金しない やり取りの回数を減らしてAIの回答を待つ時間を減らすことが狙いのようで、効率を取るか、1問ずつ質問させて認知負荷を取るかですね。 ただ私は「とにかく認知負荷を下げたい!」ので、1個ずつ質問してくれる方が好みです。 公式にも1問ずつに戻す方法は用意されていて、グローバルの CLAUDE.md に次の1行を足せばいいそうです。 When grilling, ask one question at a time. ただ、この1行が無視されたという報告も上がっていて、2026年11月4日時点ではまだ解決していません。確実に1問ずつにしたいなら、上のように別のスキルにしておくのも一つの手ですね。 skills#1337 ちなみに、Claude Codeのplanモードでも、選択肢を付けて聞いてくれますし、推奨が付くこともあります。ただ、普段autoモードで作業している私にとっては、planモードに切り替えるより、途中で「これは色々考えることがありそうだな」と思ったときに /grill-one と打つ方がやりやすく感じています。 また、planモードの画面はうまく言葉にはできませんが微妙に使いづらさを感じており、地味に負荷を感じているというのもあります。 実質はほぼ同じなので、planモードで十分という人も多いと思います。 なぜ認知負荷が下がるのか? なぜ認知負荷が下がるのか?と考えてみると、Slackでの同僚からのメッセージと同じだと思いました。例えばこんなメッセージが届いたとします。 お疲れさまです。いま作っている退会機能の件で、5点確認させてください。 先日のMTGで、退会機能は今期中にリリースする方針になりました。 仕様はまだ固まりきっておらず、PdMの○○さんとも認識を合わせているところです。 退会まわりは問い合わせも多く、CSの××さんからも要望をいただいています。 法務の観点での確認も必要になりそうなので、そのあたりも含めて整理したいです。 実装は来週から着手予定なので、今週中に方針だけでも決められると助かります。 以下、確認したい点です。 1. 退会したユーザーの投稿は、残しますか?消しますか? 2. 退会後、同じメールアドレスで再登録できるようにしますか? 3. 有料プランの途中で退会したら、残りの期間分は返金しますか? 4. 退会する前に、引き止めの画面を出しますか? 5. 退会したユーザーのデータは、何日後に完全に消しますか? 一晩寝かせたくなりますよね。 では、こう届いたらどうでしょう。 退会機能、退会した人の投稿は残す方向でいいですか? 消すとほかの人の返信だけが残って会話が読めなくなるので、残す推しです。 これなら「OK」と、その場で返せます。 質問の量は、まとめて聞いても1問ずつ聞いてもトータルは同じです。違うのは、最初に全部が目に入るかどうか。5つ並んでいると、読もうとしなくても、見ただけでその情報量に脳がやられて拒否反応が出てしまいます。1問ずつなら、残りの4つはまだ見えません。「あえて見させない」が重要なのだろうと思います。 それに、選択肢と推奨を付けて聞くというのは、仕事のメッセージの送り方として昔からよく言われていることでもあります。選択肢も推奨もなく「どうしますか?」とだけ聞くのは、考える仕事を丸ごと相手に返しているのと同じで、「で、あなたはどう思うの?」となりますよね。選択肢と推奨を必ず付けさせると、AIに手を抜かせず、こちらは最後に判断するだけ、という状態まで持ってきてもらえます。AIにも同じ作法で聞いてもらう方が楽、という単純な話なのだと思います。 人間相手なら、往復が1回で済むぶん、まとめて聞くのにも意味があります。何度もラリーするのは大変ですからね。でもAIならすぐに返信が返ってきます。 とはいえ、じゃあこれで効率が上がるのか?と言われると、正直よく分かりません。まとめて聞いたほうが早く終わることもあると思います。ただ、疲れているときの私的には、1問ずつのほうが圧倒的に楽でした。もう何も考えたくない!全部AIがやってくれ!というときにおすすめです。 セグメンテーション効果 ここまではかなり感覚の話なので、何か裏付けはないかと探してみたところ、教育心理学に「セグメンテーション効果」というものがありました1。 複雑な内容は、ひとまとめに見せるより、区切って少しずつ見せたほうが理解されやすい、という効果です。 もともとは教材の作り方の話ですが、この効果を調べてきた心理学者のMayerは、効果が出やすい条件として次の3つを挙げています(出典)。 内容が複雑 内容に慣れていない 説明のペースが速い 今回の話は「複雑な作業を頼むと、質問がまとめて届く」なので、まさに同じような状況でした。 Reyほか(2019年、Educational Psychology Review)は、セグメンテーション効果を調べた56件の研究をまとめています。どの研究も、同じ教材を区切って見せたグループとまとめて見せたグループに同じテストを受けさせ、その差を比べたものです。 Reyほか(2019)の要旨をもとに作成 面白いのは、区切ると認知負荷は下がって理解も進む一方で、かかる時間はむしろ長くなる点です。1問ずつにすると往復が増えるのと同じで、「効率がいいかは分からないけど楽」という体感とちょうど合っていました。 おわりに 1問ずつ聞いてもらう。やっていることは本当に単純です。でも、こういうちょっとしたやり方を1つ知っているだけで、仕事がぐっと楽になることがあります。例えば、スクラムのベロシティ(1回のスプリントでチームがこなせる作業量の目安)だって、言ってしまえばただの数字です。それが実際に使ってみると、「今回はどこまでできて、どこからは諦めるか」を話し合いやすくなって、その価値がよく分かります。 こういう"やり方"は、実体があるわけではないので、なかなか道具として見えません。価値も、自分でやってみるまで分かりにくい。だからこそ、自分が楽になったものは共有したいと思って書きました。戦うための武器が1つずつ増えていく感じがして、強くなった気になれるのが良きです。 AIの認知負荷高い文章に疲れている人はぜひ使ってみてください。 脚注 英語では segmenting effect。教材の作り方の指針としては segmenting principle(セグメント化の原則)と呼ばれます。 ↩︎
15 stars until we become the most-starred skills repo in the world... ...and the 13th most starred repo of all time. mattpocock/skills
Problem with Spec driven development Hi everyone, I’m looking for some guidance on my workflow. I feel like I’m missing something. I started working on a project about two months ago and have been following Matt Pocock’s skills. It worked well at first. The grilling sessions were really helpful, and I got useful stories and documentation out of them. I also used AI to write some additional Markdown files for features that needed them. But now that I’m changing and reimplementing features, the docs just keep getting bigger. For example, I originally wanted guest login, then switched to Google sign-in, and now I’ve moved to third-party sign-in. Each change seems to add more to these already large files. I’m getting stuck on how to handle smaller changes: - If I just want to change a color, do I need to run /grill and go through the whole process? When I make quick design changes directly, those changes don’t get reflected in the docs. - What about small features? Following the full workflow every time is becoming a pain in the ass, and loading all this documentation is eating through my tokens. How are you handling this in your projects? When do you use the full workflow, and how do you keep the docs up to date when you make smaller changes?
AI Can Write More of the Code. We Still Have to Engineer the System. Originally published on picon.dev. Leer en español. When people say AI has transformed software development, I want to know which part they mean. Producing an implementation? Exploring a design? Deciding whether a system solves the right problem? Those activities are connected, but automating one does not settle the others. My argument is that agents can take on more implementation work, and assist with analysis, design, and testing, while engineers remain responsible for deciding what to build and what evidence is sufficient to accept it. That changes the work. It does not make the responsibilities disappear. I am wary of describing this as replacing the person who churns out code. It reduces developers to typing, understates what agents can assist with, and turns task automation into a claim about jobs. Claims about workforce replacement require evidence beyond an impressive demonstration. The practical question interests me more: how do we use these tools while keeping our decisions visible and our feedback useful? Give decisions somewhere to live A conversation is convenient for exploring options. It is a fragile place to keep the only record of an architectural decision. Model context is bounded. A long session may be summarized, compacted, or resumed with selected information. The summary can preserve the conclusion and lose the condition that made it reasonable. “Use a local cache” is different from “use a local cache because this screen must remain usable without connectivity.” Anthropic's account of long-running agents describes continuity problems across context windows and an approach using incremental work and persistent progress artifacts. It also reports that compaction can leave unclear instructions. This is a vendor engineering report about a particular setup, rather than a universal comparison of development workflows. My preference is to give durable decisions a small, reviewable home. A PROJECT_GUIDE.md might contain: - The product's purpose and current scope, including explicit exclusions. - The important system boundaries and the reasons behind architectural choices. - Quality expectations and the commands used to check them. - Links to deeper decisions when those decisions need more space. The filename has no special power. An agent will not necessarily load it automatically. I would connect it through the tool's supported project instructions or explicitly include it in the task, then check the agent's interpretation. For each increment, I would supply the relevant files and ask for a brief account of the intended change, constraints, and acceptance cases. A paraphrase is an early opportunity to catch misunderstanding; the implementation still has to demonstrate compliance. Simon Willison's June 2025 discussion of context engineering helps frame the problem of choosing information for the next model step. My narrower recommendation is to make that selection deliberate and inspect its consequences. Markdown alone guarantees neither retrieval nor obedience. Sending every document on every task can increase context and cost. Selective retrieval may reduce input, but maintaining documents, retrieving them, and correcting mistakes also consume resources. Any claim of savings needs a measurement of the complete task. Specify the next behavior Consider a hypothetical mobile search screen. This is an illustration, not a report from a completed project. The story could be: “As a user, I want to search saved items so that I can find an item without scrolling through the entire collection.” For the first increment, the scope is local search over existing items. Remote search and changes to persistence are excluded. Before implementation, I would make these acceptance cases explicit: - A matching query displays the expected items. - A query with no matches displays an empty result state. - Clearing the query restores the complete collection. - If filtering is asynchronous, an older result cannot overwrite a newer query's results. These cases expose a technical question: does filtering need asynchronous work at all? The agent can help assess that decision. We should resolve it against the expected data size and responsiveness requirements, rather than introducing concurrency because a template expects it. For this example, I might choose unidirectional data flow, explicit UI states, and a separation between filtering logic and rendering. That makes state transitions easier to inspect. Another system may justify a different structure; this is an engineering choice with a purpose. The project guide should preserve that purpose. Feature-level notes should explain the behavior and any new decision. They do not need to reproduce the entire architecture. After the increment, I would inspect the diff, run the relevant checks, and exercise the screen. If the agent rewrote persistence despite the scope restriction, passing tests would not make that expansion acceptable. If the empty state looks correct but the search matches the wrong field, a screenshot would not establish correctness either. Make generation answer to verification Agent output is probabilistic. Acceptance should depend on evidence that we can inspect and, where practical, reproduce. A local verification command can run formatting checks, static analysis, compilation, and focused tests. These checks answer different questions. A formatter checks conventions; a compiler checks language and type rules; tests evaluate selected behavior under selected conditions. None establishes that we chose the right product behavior. Controlled verification also needs controlled inputs. Tool versions, fixtures, and execution conditions matter. Tests involving timing, devices, networks, or external services may be flaky. Calling a test suite deterministic does not make it so. Even a perfectly repeatable check can verify the wrong thing. A search test might assert that some result appears without checking which result it is. A generated test can faithfully encode the same misunderstanding as the generated implementation. I would review the assertion against the acceptance case and use deliberately chosen examples, including a failure case. Running the app adds another kind of evidence: whether the behavior makes sense through the actual interface. When performance matters, define the measurement before declaring success—device, dataset, scenario, and threshold. A quick impression of responsiveness is useful feedback, but it is not a latency result. Hooks can make local checks convenient and catch mistakes earlier. Their coverage depends on what triggers them and whether they can be bypassed. Where a team requires enforcement, server-side checks and repository protections need their own configuration. A local hook is not equivalent to an enforced remote policy. The engineer still decides whether the evidence supports acceptance, revision, or rejection. An agent can help gather that evidence; it cannot make an incomplete test suite complete by announcing success. Documentation has to earn its maintenance I become skeptical when a small change requires a long chain of generated documents before anyone can see working behavior. Each document becomes something to review, reconcile, and keep current. Producing text cheaply does not make understanding it cheap. That is a criticism of proportionality and feedback cadence. Spec-driven development has multiple meanings. Birgitta Böckeler's 2025 examination of Kiro, spec-kit, and Tessl distinguishes approaches that write specifications first, retain them during maintenance, or treat them as the primary source. Those differences matter when discussing costs and control. François Zaninotto's critique of document-heavy workflows raises concerns about review overhead and instruction following through reported examples. Those cases are useful prompts for investigation. They do not establish that specifications generally cause worse outcomes. An incremental specification can support rapid feedback. Agile does not mean avoiding documentation: its principles emphasize frequent working software, technical excellence, and adaptation. A short acceptance case can serve those aims; so can a detailed design when the risk warrants it. Stronger specifications can be valuable for safety constraints, regulated work, public interfaces, migration compatibility, and coordination across teams. In those settings, a concise guide is an entry point to the necessary detail. It cannot replace that detail. My test for a document is practical: what decision, implementation, or verification does it support, and who will maintain it? I would keep the explanation of a compatibility constraint even if it takes several pages. I would remove repeated prose that neither changes a decision nor helps someone evaluate the work. Matt Pocock's collection of engineering skills offers another example of packaging guidance into adaptable, composable pieces. I find that direction useful. Its stated design goals are not evidence that a collection of skills outperforms another workflow. Keep the acceptance decision explicit A small increment can still contain a bad assumption. Its advantage is that it gives us an earlier, more bounded opportunity to discover one. The loop I would advocate is straightforward: define the next behavior, supply the context it needs, check the interpretation, inspect the change, collect evidence, and decide whether to accept it. Update durable guidance when a decision changes. If review becomes unmanageable, reduce the increment or improve the checks before asking the agent to produce more. This approach has limits. It depends on the engineer's understanding, the quality of the evidence, and the cost of keeping guidance current. This article presents a working position, not a controlled study or a demonstrated productivity gain. Establishing such a gain would require comparable tasks and accounting for review, rework, defects, and maintenance—not just generation time. I am comfortable delegating more of the work when I can explain what was requested, what changed, and why the evidence supports accepting it. That is the engineering standard I want to carry into AI-assisted development. Which decisions in your workflow remain visible after the conversation ends—and what evidence tells you that the agent respected them? --- Authorship note: The initial draft was generated with AI assistance from Armando Picón's arguments and a source review. Armando reviewed the article and approved publication. The Spanish translation was produced with AI assistance. The mobile example is hypothetical. The cover illustration was also generated with AI.
Coding Agent の「作り直し」と「検証ミス」を減らす:Matt Pocock Skills × pstack 最近、Coding Agent を使った開発で、Matt Pocock Skills と pstack を組み合わせて使うことが増えています。 最初は便利そうな Skill を個別に試していただけでしたが、ソースコードやドキュメント、ほかの開発者の使用例を読んでいるうちに、それぞれの設計思想にも興味を持つようになりました。 実際に使い続ける中で、両者の良いところを取り入れた、自分なりのワークフローが少しずつ固まってきました。 特に役立っているのは、Spec を書いたのに UI が想像と違ったり、Agent がこちらの意図していない判断をしたり、変更後のアプリを検証したつもりが古いプロセスを確認していたり、といった問題への対処です。 この記事では、二つの Skills から学んだことと、普段の開発でどのように使い分けているかを紹介します。 1. Matt Pocock Skills と pstack は何を解決しようとしているのか どちらも Coding Agent を使った開発の信頼性を高めるためのものですが、アプローチには違いがあります。 1.1 Matt Pocock:コードを書く前に立ち止まる Matt Pocock(@mattpocockuk) は、TypeScript の教育コンテンツ「Total TypeScript」や「AI Hero」などを手がける開発者です。彼が公開している Matt Pocock Skills の特徴は、一般的なエンジニアリングプラクティスを、小さく独立した Skill に分けている点です。 Coding Agent は短時間で機能を実装できますが、実際に使っていると、次のような問題によく遭遇します。 要件が十分に決まっていないのに、Agent が実装を始めてしまう 実装の途中で、考慮していなかったエッジケースに気づく Spec には沿っているのに、完成した UI が自分のイメージと違う 実装が終わってからテストを追加し、大幅な修正が必要になる どれもソフトウェア開発では昔からある問題ですが、コード生成が速くなったことで、むしろ遭遇しやすくなったと感じています。 Matt Pocock Skills には、こうした問題に対応するための Skill が用意されています。 Skill 主な用途 /grill-me 質問を繰り返し、未決定事項や曖昧な要件を洗い出す /grill-with-docs 要件を議論しながら、用語集やアーキテクチャ上の決定事項をドキュメントに残す /prototype 本実装に入る前に、複数の設計案を試す /to-spec、/to-tickets 議論した内容を Spec や実装タスクに整理する /tdd Red → Green → Refactor のサイクルで実装する /code-review コード品質や元の要件との整合性をレビューする /handoff 別の Agent セッションに作業を引き継ぐため、進捗や決定事項を記録する 個人的に気に入っているのは、Agent がすぐにコードを書かず、質問するための仕組みがあることです。 例えば /grill-me では、未決定の部分を Agent が勝手に補完するのではなく、質問としてこちらに返してくれます。 また、/prototype では、本実装に入る前に、使い捨てのコードでアイデアを試すことができます。 どちらも、設計を早い段階で決めつけてしまうことを防ぐのに役立っています。 1.2 pstack:Agent が実際に何を検証したのか確認する Lauren Tan(@poteto)が開発した pstack は、タスクごとのワークフローと検証をより重視しています。 機能開発、デバッグ、調査、設計、レビューなど、さまざまな開発タスクに対応した Skill が含まれています。 代表的なものをいくつか挙げます。 Skill 主な用途 /poteto-mode タスクに応じて適切なワークフローを選択する /create-verification-skill プロジェクト固有の起動・検証手順を作成する /maintain-verification-skill プロジェクトの変更に合わせて検証手順を更新する /debug 修正する前に、不具合の原因を調査する /how、/why システムの動作や設計上の判断を追跡する /architect 実装前にモジュール構成や型の設計を整理する /unslop AI が生成した UI にありがちなデザイン上の問題を見直す 特に興味を持ったのが、Verification 関連の Skills です。 Coding Agent を使っていると、作業の最後に次のような報告を受けることがよくあります。 Implementation complete. All tests passed. もちろん、テストが通ったこと自体は良いことです。ただ、最近は「実際に何をテストしたのか」を確認するようにしています。 例えば、Agent が API を修正し、ユニットテストはすべて通過したものの、アプリケーション自体は起動していないケースがあります。 あるいは、コードの変更前から動いているサーバーにリクエストを送っていることもあります。 後者は自分も実際に遭遇した問題です。 /create-verification-skill を使うと、プロジェクトに合わせた起動・検証手順を Agent に覚えさせることができます。 起動コマンドや環境設定、起動完了の確認、機能の操作方法、どのような証拠があれば成功と判断できるか、といった情報をまとめられます。 毎回 Agent に一から調べさせるより、一度決めた手順を再利用できるほうが便利だと感じています。 1.3 二つの Skills をどう組み合わせるか もちろん、両者の機能には重複があります。 Matt Pocock Skills にも TDD、コードレビュー、デバッグ関連の Skill がありますし、pstack にも計画、設計、調査のためのワークフローがあります。 そのため、「Matt はコードを書くため、pstack はテストするため」と単純に分けているわけではありません。 自分の場合は、開発の各段階で次のように使い分けています。 開発段階 避けたい問題 主に使う Skills 実装前 要件が曖昧、設計の方向性が違う Matt:要件の確認、Prototype 実装中 変更範囲が大きすぎる、Spec から外れる Matt:タスク分割、TDD、レビュー 実装後 テストは通るが、実際のアプリの動作が違う pstack:プロジェクト固有の実行時検証 継続開発 Agent がプロジェクトの動かし方を忘れる、検証手順が古くなる pstack:Verification の更新、Matt:Handoff これは公式に用意された組み合わせではなく、自分が普段の開発で使っている方法です。 2. 実際の開発での使い方 すべてのタスクで、すべての Skill を使うわけではありません。 ただ、新しい機能を作るときは、次のような流れで進めることが増えました。 Step 1:まず要件を整理する 使用する Skills:/grill-me、/grill-with-docs 複数の実装方法が考えられる機能では、まず Agent に質問してもらいます。 例えば、プロジェクトの進捗に応じて、毎日のタスクを自動調整する機能を作るとします。 「計画が変わったらタスクを自動更新する」という要件だけでは、まだ分からないことがあります。 Agent はタスクをすぐ変更してよいのか。ユーザーの承認が必要なのか。手動で編集したタスクはどう扱うのか。 こうした部分を /grill-me で整理します。 長期開発のプロジェクトでは /grill-with-docs も使い、決定事項をドキュメントに残すようにしています。 Step 2:Spec ができても、すぐに本実装しない 特に気に入っている Skill:/prototype Matt Pocock Skills の中で、個人的に最も効果を感じている Skill です。 以前は Agent と十分に議論して Spec を書いたあと、そのまま実装に進むことが多かったのですが、完成した画面を見て、「確かに指定したとおりだけど、思っていたものと少し違う」と感じることが少なくありませんでした。 特に UI やインタラクションでは、文章だけで完成形をイメージするのが難しいです。 そこで最近は、設計がまだ決まっていない場合、三つの Prototype を作ってもらうようにしています。 例えば、タスク管理画面なら次の三案です。 リスト形式:優先度やタスクの状態を一覧で確認する カンバン形式:タスクをステータスごとに管理する タイムライン形式:日々の予定やスケジュールを中心に表示する 実際に動かして比較すると、どの操作が使いやすいか、自分が何を重視しているかが分かってきます。 その結果を Spec に反映してから本実装に進むほうが、あとから大きく作り直すケースを減らせています。 Prototype は基本的に使い捨てです。データベースや本番用のアーキテクチャまで用意せず、アイデアを検証することに集中します。 Step 3:方向性が決まったら実装する 使用する Skills:/to-spec、/to-tickets、/tdd Prototype で方向性が決まったら、Spec を更新して実装タスクに分割します。 入力と出力が明確なビジネスロジックについては、/tdd を使って小さく実装していくことが多いです。 ただし、単純な UI 修正まで毎回 TDD にするわけではありません。変更の規模や性質に応じて使い分けています。 Step 4:実際のアプリで検証する 特に気に入っている Skill:/create-verification-skill 以前は、機能が完成したら Agent に「アプリを起動して確認して」と指示するだけでした。 しかし、どのディレクトリで実行するのか、どのポートを使うのか、起動完了をどう判断するのかといった情報が曖昧だと、Agent が毎回試行錯誤することになります。 そこで /create-verification-skill を使い、プロジェクト専用の検証手順を作っておきます。 基本的には、次の流れです。 フェーズ 内容 Launch アプリを正しく起動する Doctor 環境やプロセスの状態を確認する Drive 実際に API や UI を操作する Evidence レスポンスやログなど、検証結果を残す Cleanup 検証用に起動したリソースを片付ける Feature Map には、主要な機能の操作方法や確認項目も記録できます。 毎回 Agent に起動方法から考えさせるのではなく、同じ手順で検証してもらえるのが気に入っています。 Step 5:問題があれば調査し、手順を更新する 検証中に問題が見つかったら、Matt の /diagnosing-bugs や pstack の /debug などを使い、原因を調べます。 修正後は同じ手順で再検証します。 プロジェクトの構成や検証方法が変わった場合は、/maintain-verification-skill で手順を更新します。セッションをまたぐ作業なら /handoff も使います。 普段のワークフローを図にすると、おおよそ次のようになります。 機能の要望 | v /grill-me または /grill-with-docs | v 最初の Spec | +-- 設計がまだ不確か? | | | +-- /prototype | | | +-- 複数案を比較 | +-- Spec を更新 | v /to-spec と /to-tickets | v /tdd または段階的な実装 | v プロジェクト固有の Verification Skill | +-- Launch / Doctor +-- Drive +-- Evidence +-- Cleanup | v 問題が見つかった? | +-- 原因を調査 +-- 修正 +-- 再検証 | v 完了 または /handoff この流れは、必ず守るチェックリストというより、作業を進める際の目安です。 また、二つの Skills を組み合わせるといっても、インストールするだけで自動的に連携するわけではありません。利用する Coding Agent や実行環境に合わせて使い分けています。 3. デモ:5つのStepでタスク管理アプリを作る ここまで紹介したワークフローを、小さな Python アプリの開発に当てはめてみます。 作るのは「今日のタスク管理アプリ」です。タスク一覧を表示し、完了ボタンを押すと状態が更新される、というシンプルな機能です。 以下は各 Skill の組み合わせ方を説明するためのデモであり、実際の Agent セッションの実行ログではありません。 Step 1:/grill-me で要件を明確にする 最初に Agent に渡す要件は、これだけです。 今日のタスクを表示して、完了できる Web アプリを作りたい。 /grill-me で要件を整理すると、例えば次のような質問が出てきます。 Agent からの質問 今回の決定 タスクの追加・削除は必要? 今回は不要 完了済みタスクはどう表示する? 一覧に残し、「完了」と表示する 完了ボタンを押したら? ページをリロードせずに表示を更新する データの永続化は必要? 今回は不要。メモリ上で管理する 存在しないタスク ID は? HTTP 404 を返す ここで決めた「ページをリロードせずに表示を更新する」という仕様が、あとで重要になります。 Step 2:/prototype で UI を比較する 次に、同じモックデータを使って三つの UI を試します。 Prototype UI 特徴 A リスト形式 タスク一覧と完了ボタン B カンバン形式 未完了・完了の2列 C タイムライン形式 時間帯ごとのタスク表示 今回は最もシンプルな A のリスト形式 を採用します。 本来であれば三つの Prototype を実際に動かして比較しますが、このデモでは UI の選定結果を前提として進めます。 Step 3:/to-spec と /tdd で実装する 今回の最小限の Spec は次のとおりです。 GET /tasks:タスク一覧を取得する POST /tasks/{id}/complete:指定したタスクを完了にする /:タスク一覧と完了ボタンを表示する 完了操作後、ページをリロードせずに表示を更新する API と UI を実装タスクに分け、まず API の動作を /tdd で確認します。 test_app.py from fastapi.testclient import TestClient from app import app, tasks client = TestClient(app) def test_complete_task(): tasks[1]["done"] = False response = client.post("/tasks/1/complete") assert response.status_code == 200 assert response.json()["done"] is True assert client.get("/tasks").json()[0]["done"] is True このテストに対応するアプリを実装します。 app.py from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse app = FastAPI() tasks = { 1: {"id": 1, "title": "仕様を確認する", "done": False}, 2: {"id": 2, "title": "画面を確認する", "done": False}, } @app.get("/tasks") def list_tasks(): return list(tasks.values()) @app.post("/tasks/{task_id}/complete") def complete_task(task_id: int): if task_id not in tasks: raise HTTPException(status_code=404) tasks[task_id]["done"] = True return tasks[task_id] @app.get("/", response_class=HTMLResponse) def index(): return """ <h1>今日のタスク</h1> <ul id="tasks"></ul> <script> async function refresh() { const items = await (await fetch("/tasks")).json(); document.getElementById("tasks").innerHTML = items.map(t => ` <li> ${t.title}: <span id="state-${t.id}"> ${t.done ? "完了" : "未完了"} </span> <button onclick="completeTask(${t.id})"> 完了にする </button> </li> `).join(""); } async function completeTask(id) { await fetch(/tasks/${id}/complete, { method: "POST" }); } refresh(); </script> """ 依存パッケージをインストールし、テストを実行します。 pip install fastapi uvicorn pytest httpx python -m pytest -q この API テストは通ります。 しかし、まだ一つ問題が残っています。 Step 4:Verification Skill で実際の動作を確認する Step 3 では API のテストが成功しました。しかし、ここで Agent が pytest の結果だけを見て実装完了と判断すると、問題を見逃してしまいます。 まず、Verification Skill を使わずにアプリを確認してみます。 python -m uvicorn app:app --port 8000 ブラウザで localhost を開き、「仕様を確認する」の完了ボタンを押します。 画面上の表示は、次のままです。 仕様を確認する:未完了 一方、API を確認すると、 curl localhost 次のように状態が更新されています。 [ {"id": 1, "title": "仕様を確認する", "done": true}, {"id": 2, "title": "画面を確認する", "done": false} ] API 自体は正常に動作しています。それでも、ブラウザ上では「未完了」のままです。 もし Agent が API のレスポンスだけを確認していたら、この不具合を見逃す可能性があります。 そこで、pstack の /create-verification-skill を使い、プロジェクト固有の検証手順を用意します。 今回なら、次のような内容です。 フェーズ 検証内容 Launch 現在のコードを新しいプロセスで起動する Doctor プロセスとポートを確認し、起動完了を待つ Drive ブラウザでタスクの完了ボタンを押す Evidence API と画面表示の両方を確認する Cleanup 今回の検証で起動したプロセスを終了する ここでは、その検証方法を簡単な Python スクリプトで再現します。 ブラウザ操作には Playwright を使います。 pip install playwright python -m playwright install chromium verify.py を作成します。 import json import socket import subprocess import sys import time from urllib.request import urlopen from playwright.sync_api import sync_playwright, expect 既存のサーバーを避けるため、空いているポートを選ぶ with socket.socket() as sock: sock.bind(("127.0.0.1", 0)) port = sock.getsockname()[1] url = f"http://127.0.0.1:{port}" 現在のコードを新しいプロセスで起動する server = subprocess.Popen( [ sys.executable, "-m", "uvicorn", "app:app", "--host", "127.0.0.1", "--port", str(port), ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) try: 新しいサーバーの起動を待つ for _ in range(50): if server.poll() is not None: raise RuntimeError("Server failed to start") try: with urlopen(f"{url}/tasks", timeout=1): break except OSError: time.sleep(0.1) else: raise TimeoutError("Server not ready") with sync_playwright() as p: browser = p.chromium.launch() try: page = browser.new_page() page.goto(url) 初期状態を確認する state = page.locator("#state-1") expect(state).to_have_text("未完了") 実際に完了ボタンを押す with page.expect_response( lambda r: "/tasks/1/complete" in r.url and r.request.method == "POST" ) as result: page.get_by_role( "button", name="完了にする" ).first.click() assert result.value.status == 200 API の状態を確認する with urlopen(f"{url}/tasks") as response: tasks = json.load(response) assert tasks[0]["done"] is True print("API: done=True") ページをリロードせずに表示が変わるか確認 expect(state).to_have_text("完了", timeout=2000) print(f"PASS: PID={server.pid}, UI=完了") finally: browser.close() finally: 自分が起動したプロセスだけを終了する server.terminate() try: server.wait(timeout=5) except subprocess.TimeoutExpired: server.kill() server.wait() 実行します。 python verify.py 現在の app.py では、API の検証は成功しますが、画面表示の検証で失敗するはずです。 API: done=True AssertionError: ... Expected: "完了" Received: "未完了" つまり、API は更新されているのに、UI が更新されていないことを検出できました。 この verify.py は説明用に手書きしたスクリプトであり、pstack が自動生成したものではありません。実際のプロジェクトでは、こうした検証方法を Verification Skill に組み込み、Agent が繰り返し実行できるようにします。 Step 5:/debug で修正し、もう一度検証する ここで /debug、または /diagnosing-bugs を使って原因を調べます。 Step 3 の実装では、completeTask() が API を呼び出すだけで、画面を更新していませんでした。 async function completeTask(id) { await fetch(/tasks/${id}/complete, { method: "POST" }); } そこで、await refresh() を追加します。 async function completeTask(id) { await fetch(/tasks/${id}/complete, { method: "POST" }); await refresh(); } これでコードは修正できました。 しかし、ここでもう一つ問題があります。 Step 4 でポート 8000 に起動した Uvicorn は、まだ古いコードを読み込んだままです。 今回の起動コマンドには --reload を指定していません。 そのため、app.py を修正しても、ポート 8000 で動いているプロセスには自動的に反映されません。 仮に Agent がもう一度、同じポートで起動しようとしても、 python -m uvicorn app:app --port 8000 既存のプロセスがポートを使用しているため、起動に失敗します。 それでも localhost にアクセスすれば、古いプロセスが応答します。 ここで Agent が「まだ UI が更新されない」と判断し、正しく修正したコードを再び変更してしまう可能性があります。 以前、自分もこのような問題に遭遇しました。 そこで、Step 4 で作成した verify.py をもう一度実行します。 python verify.py このスクリプトはポート 8000 の既存プロセスを利用せず、現在のコードを新しいプロセスで起動します。 修正が正しく反映されていれば、次のような結果が期待できます。 API: done=True PASS: PID=12345, UI=完了 これで、現在のコードで起動したアプリが期待どおりに動作することを確認できます。 最後に、今回の不具合を Feature Map の検証項目に残しておきます。 タスクの完了ボタンを押したあと、ページをリロードせずに対象タスクの表示が「完了」に変わること。 あわせて、検証時には既存のプロセスを安易に再利用せず、新しく起動したアプリを対象にすることも手順に含めておきます。 必要に応じて /maintain-verification-skill で検証手順を更新し、別のセッションへ引き継ぐ場合は /handoff で作業内容を整理します。 今回の例では、API のテストが成功しただけでは UI の不具合を発見できず、コードを修正しただけでは古いプロセスの問題を回避できませんでした。 Verification Skill によって、どのアプリを起動し、何を操作し、どの結果を確認するかを決めておくことで、Agent が同じ検証ミスを繰り返す可能性を減らせます。 4. おわりに コードの実装を Agent に大きく任せる開発は、すでに現実的になっています。これからは、Agent Skills を設計し、組み合わせ、使いこなす能力も、エンジニアにとって重要になると思います。成果物のコードからは見えにくい能力ですが、同じモデルを使っていても、Agent が働く環境によって開発効率は大きく変わります。 特に参考になったのが、poteto の 「How I Shipped 2,500 PRs Last Month to Production」 という講演です。 そこで紹介されていた Trust Ladder という考え方が印象に残っています。最初は人間が細かく確認していても、Agent が自分でアプリを動かし、結果を検証できるようになれば、任せられる範囲を少しずつ広げられます。繰り返し起きるミスは、Lint や CI、Skills などの仕組みに落とし込みます。 Agent の作業が速くなるほど、人間が毎回すべてを確認することがボトルネックになります。その負担を減らすには、単に Agent を信頼するのではなく、信頼できるだけの検証環境を作ることが必要なのだと思います。 自分も、開発中に発見した失敗をその場限りの指摘で終わらせず、次回から防げる仕組みに変えていきたいと考えています。 参考資料 Matt Pocock — Skills for Real Engineers Matt Pocock — The /prototype Skill Matt Pocock Skills — GitHub pstack — GitHub pstack — create-verification-skill pstack — maintain-verification-skill Lauren Tan(@poteto)— How I Shipped 2,500 PRs Last Month to Production
Test Results: we manually tried test-first + fresh verification on synthetic URL deduplication: 3 cases red before the fix, 4/4 green after. No native skill triggering, model comparison or measured time savings. mattpocock/skills obra/superpowers #OpenSource
AIではじめるセルフQA:要求をMECEにしよう サマリー AI全盛の今、QAの方だけでなく、エンジニアもQAする時代が本格的になってきました。 ただ、AI は計画に書かれたとおりに実装します。計画に書かれていないことは実装しません。コードベースを読んで初めて見つかる要求の穴があります。ですので、この記事ではその穴を実装の前に見つける方法を紹介します。自分はこれを define-done という Agentスキルにしています。 題材のリポジトリは YasuakiOmokawa/skills で公開しています。 計画どおりに実装しても壊れる例 次の例はスキルの評価用に作った架空のものです。利用者が複数のチームに所属できるアプリで、招待を受ける処理とチームを抜ける処理は前からあります。 やりたいこと: 招待を受けたら、すぐにそのチームで作業を始められるようにしたい。 仕様駆動開発の進め方で、AI に仕様と計画を先に書かせます。 仕様: 利用者は「現在のチーム」を 1 つ持つ。現在のチームは、利用者が所属するチームのどれかでなければならない 計画: 利用者に現在のチームを新しく持たせ、招待を受けたら、そのチームを現在のチームにする 仕様と計画に食い違いはありません。AI は計画どおりに実装し、テストも書きます。テストは全部通ります。 漏れたケース: 現在のチームから抜けたとき。チームを抜ける処理は現在のチームを更新しません。現在のチームは今回新しくできたもので、この処理は前からあるからです。抜けた利用者の現在のチームは抜けたチームのまま残り、仕様の条件が破れます。 このケースは仕様にも計画にも出てこないので、テストも書かれません。チームを抜ける処理は差分にも出てこないので、レビューでも気づけません。実装の質やテストの質をいくら上げても、この穴は見つかりません。 define-done がすること: コードベースで「現在のチーム」と所属を書き換える処理をたどり、チームを抜ける処理を見つけます。そして、抜けたら現在のチームをどうするか (別の所属チームに移すか、空にするか) を、実装の前に人に問います。人が決めた答えは受け入れ基準になります。 仕様駆動開発との使い分け 仕様駆動開発 (SDD) は仕様を先に書き、実装を仕様に合わせる進め方です。仕様に書いたことは確実に実装されます。一方で、仕様に書いていないことは実装されません。仕様は、書いた人 (人でも AI でも) が思いついた範囲しか書けないからです。 define-done は既存のコードを調査して、仕様と計画に書かれていないケースを探します。仕様駆動開発の代わりではなく、仕様と計画を書いた後、実装の前に挟む工程です。 手軽に要求のMECE検査をしたいときに define-done を使うだけでも大丈夫です。 なお、筆者はSDDにはフラットな立場です。賛成も否定もしません。 穴はどこでうまれるか? AI は計画の範囲を正しく実装します。抜けは計画の外、つまりコードベースの側にあります。同じ状態を書き換える既存の処理、変えた定義を使う別の箇所、許可された依存を全部並べるテストなどです。 この穴が生まれるのは、計画を書く人がそうした経路をすべては知らないときです。たとえば次のような人です。 大きなリポジトリや古いリポジトリを扱う人 入ったばかりのメンバーや、他チームのコードに手を入れる人 計画そのものも AI に書かせている人 3 つ目は見過ごされがちです。計画を書く AI も、コードベースを全部は読んでいないと自分は考えているからです。 4 段に分けて検証する define-done は、計画を 1 回のレビューで済ませず、4 段に分けて検証します。AI の検証の力をできるだけ引き出すために、こう設計しました。 分けるねらいは 2 つです。 1 段で見る観点を 1 つに絞る 各段の結果を計画に書き、次の段がそれを根拠にして確かめ直す。たとえば 3 段目は、2 段目が書いた受け入れ基準を仕様とコードに突き合わせ、基準の側の抜けも見つけます 抜けや矛盾が残れば、3 段目の後で止めて人に返します。冒頭の例の抜けを見つけるのも、この 3 段目です。 多段にした理由 LLM は何もないところから正しいものを作るより、出したものを根拠に照らして直すほうが得意です。偽陽性 (本当は問題でないものを問題と言うこと) を減らすにも、一度で判定させるより、段を分けて確かめさせるほうが向いています。研究でも、次のことが報告されています。 同じ LLM に、出力への指摘と書き直しを繰り返させると、7 つの課題で 1 回で出すより平均およそ 20 ポイント良くなった (Madaan et al., NeurIPS 2023) 下書きを作り、それを確かめる問いを立て、問いに別々に答えてから最終回答を書く、という 4 段の手順で、幻覚が減った (Dhuliawala et al., Findings of ACL 2024) 要約で、下書き・批評・書き直しを 1 つの指示にまとめるより、3 つの指示に分けて順に回すほうが、良い要約になった (Sun et al., Findings of ACL 2024) ただし、多段にすれば必ず良くなるわけではありません。外からの手がかり無しに LLM が自分の答えを見直すだけでは、推論の正しさは上がらず、かえって下がることがあると報告されています (Huang et al., ICLR 2024)。自己修正の研究をまとめた調査も、うまくいくのは確かな外部の手がかりがある課題だと整理しています (Kamoi et al., TACL 2024)。 define-done の各段はリポジトリのコードを根拠にし、検索やコマンドは実際に動かして確かめます。研究が「効く」とする、外の手がかりで確かめる形に合わせました。 大事なところは人が決めよう 3 段目では計画を次の順で調べます。 計画が書き換える状態と、変更する共有の定義を挙げる その状態を書き換える処理と、その定義を使う箇所を、計画が名指ししないものも含めてリポジトリの中ですべてたどる 仕様がその状態に課す条件と突き合わせる。条件にはほかの状態との関係も含む 条件を破る経路が見つかったら、その経路を名指しして、実装に進ませない 冒頭の例では、2 で「現在のチーム」を書き換える処理と、チームの所属を変える処理をたどります。その途中で、チームを抜ける処理が見つかります。3 で仕様の条件と比べると、この処理は現在のチームを更新しないので、条件を破ります。 4 で実装に進ませないのは、抜けをどう埋めるかが仕様の判断だからです。AI はここで計画を勝手に直さず、人に返します。 見つけた抜けを観測できる基準にする 抜けの埋め方を決めたら、その埋め方を受け入れ基準にします。基準は操作と、外から観測できる結果を 1 組にして書きます。 「チームを抜けた後、現在のチームは、抜けたチームでない」 「リンクは 30 分まで有効」なら、30 分の直前と直後の両方を観測する 資料が決めていない値は、推測で埋めません。たとえば仕様に再送の上限が無ければ、AI は上限を決めず、不足している情報として人に返します。 AI と人の受け持ち 抜けを見つけるのは AI で、埋め方を決めるのは人です。コードベースに明るくない人でも、この方法は使えます。抜けは根拠のファイルや行と一緒に返ってくるので、根拠をたどれば確かめられます。 ただし、あくまで決めるのは人です。 規模の限界もありますので、追いきれなかった比較を、define-done は「未検証」として返し、実装に進む許可を出しません。 grill-with-docs との併用 計画について人と詰めながら抜けを探すスキルは、Matt Pocock さんの grill-with-docs が代表的です。 違いは抜けの見つけ方です。grill-with-docs で抜けが見つかるかは、AI が問いを思いつけるかに左右されます。define-done は、計画が書き換える状態の書き手をすべてたどる、と手順で決めています。 2 つは前後に並べて使えます。 grill-with-docs で、仕様と計画の方針を人と詰める define-done で、できた計画をコードベースに照らし、抜けを洗い出して受け入れ基準にする define-done が人に返した問い (例なら「抜けたら現在のチームをどうするか」) を、grill-with-docs で詰めて決める 別に define-done を使う必要はない スキルが無くても、実装を頼む前に、次の問いを AI に投げれば同じことができます。 この計画を実装する前に、抜けを挙げてください。 1. 計画が書き換える状態と、変更する共有の定義を挙げる 2. それぞれについて、その状態を書き換える処理と、その定義を使う箇所を、 計画が名指ししないものも含めて、リポジトリの中ですべてたどる 3. 仕様がその状態に課す条件 (ほかの状態との関係を含む) と突き合わせ、 条件を破る経路を、ファイルと行を添えて挙げる 4. 資料が決めていない値は推測で埋めず、不足として挙げる 計画とコードは変更しないでください。 見つけた抜けを埋めて受け入れ基準にすれば、その基準がそのまま実装のテストの単位になり、完了を判定する単位になります。自分は実装と判定にも別のスキル (implement-plan、qa-ui、verify-plan) を使っていますが、とりあえず define-done があれば、精緻な受け入れ基準が書けますので、安心して実装できます。 エンジニアがQAできると嬉しいことが多いので、やってみることをおすすめします。 参考 題材のリポジトリ: YasuakiOmokawa/skills define-done の SKILL.md (commit 0ffa194): github.com/YasuakiOmokawa/skills/blob/0ffa194ab2a… 追跡と突き合わせの規則: github.com/YasuakiOmokawa/skills/blob/0ffa194ab2a… grill-with-docs (mattpocock/skills): github.com/mattpocock/skills/blob/main/skills/eng… Madaan, A. et al. "Self-Refine: Iterative Refinement with Self-Feedback." NeurIPS 2023: arxiv.org Dhuliawala, S. et al. "Chain-of-Verification Reduces Hallucination in Large Language Models." Findings of ACL 2024: aclanthology.org Sun, S. et al. "Prompt Chaining or Stepwise Prompt? Refinement in Text Summarization." Findings of ACL 2024: arxiv.org Huang, J. et al. "Large Language Models Cannot Self-Correct Reasoning Yet." ICLR 2024: arxiv.org Kamoi, R. et al. "When Can LLMs Actually Correct Their Own Mistakes? A Critical Survey of Self-Correction of LLMs." TACL 2024: arxiv.org