白いカードにテラコッタ色のClaudeの星形ロゴと黒のロゴタイプ

mattpocock-skillsで三つのテストを軸に刈り込む — FowlerのスメルとOusterhoutのモジュール概念は別々に保つ

Matt Pocockのmattpocock-skillsプラグインが教える、エージェント向けの文章術。刈り込み、密な用語、そしてFowlerのスメルとOusterhoutのモジュールがなぜ別々に保たれるか。

目次

はじめに

Matt Pocockのmattpocock-skillsプラグインを扱った動画を見ました。このプラグインはgrill-meというスキルを中心に据えており、動画はそれをコードを書く前にエージェントにプランを問い詰めさせる5行の指示だと説明していました。このリポジトリには以前のセッションからすでにこのプラグインが導入されていたので、動画の要約を繰り返すのではなく、その簡潔さの裏にある実際の規律を理解したいと考え、率直な監査を依頼しました。mattpocock-skillsを本当に使っていたのか、それとも設定しただけで放置していたのか。プラグイン自身のソースを読んだことで、動画の具体的な主張のうち2つが、どこかで繰り返される前に訂正されました。grill-meは28行のプリミティブを包む7行のラッパーであること、そしてFowlerのRefactoringのコード・スメルは、多くの人が推測するのとは違うスキルにあること。さらに、この規律を読むだけでなく実際に適用したことで、追加したのと同じセッション内で自分たちのレビュー・パイプラインにある本物のバグを見つけました。この記事では、プラグイン自身のメタスキルであるwriting-for-agentsが刈り込みと密な語彙について実際に何を語っているか、そして同梱される2つの独立したコード・スメル体系がなぜ分けられているかを、要約ではなくファイル単位でソースに照らして確認します。

動画の主張、その裏付けが必要だった理由

動画の枠組みは直接検証できるほど具体的でした。grill-meは5行でユーザーにプランを問い詰め、Fowlerのコード・スメル語彙(Shotgun Surgery、Feature Envy、Data Clumps)はプラグインのcodebase-designスキル、つまり深いモジュールの設計を扱うスキルにある、という主張です。どちらも表面上はもっともらしいものです。5行というのは攻撃的なシステムプロンプトがどれだけ短くなり得るかに合致していますし、codebase-designはまさに悪いコードの姿を定義するスキルのように聞こえます。

どちらもプラグイン自身のリポジトリを読むと通用しませんでした。 スキルは1つではなく5つのディレクトリに分かれています。engineeringproductivityin-progressmiscdeprecatedです。grill-meは確かに7行で存在しますが、それはproductivity/配下にあり、実際の中身は1つの指示だけです。grillingという、実際に問い詰める28行のスキルに対してSkillツールを呼び出す、というものです。codebase-designも実在し語彙を定義していますが、Fowlerのものとはまったく別の語彙です。

簡潔な文章を支える規律

プラグインにはwriting-for-agentsというメタスキルが同梱されており、その主題は残り24個のスキルをどう書くかという一点に尽きます。3つの独立したレバーを挙げており、そのどれも「短ければ短いほど良い」ではありません。

no-opテスト

一文がそこに存在する価値を持つのは、モデルのデフォルトの振る舞いを変える場合だけです。 スキル自身の言葉で言えば、それはモデルの動作を変えるのか、それともモデルがどのみちやることを言い直しているだけなのか、という問いです。この問いに落ちた文は、削って短くするのではなく、丸ごと削除されます。デフォルトの言い直しを短くしても、それはやはり言い直しでしかないからです。

leading wordという考え方

用語も装飾ではありません。スキルは、モデルが自身の学習からすでに分散的な定義を持っているコンパクトで事前学習済みの概念を「leading word」と呼びます。段落ひとつ分の説明の代わりに、そのトークンを使い回します。grilling自体の本文がメカニズムにほとんど言葉を割かないのは、まさにこの3つのleading wordだけで組み立てられているからです。「design tree」「frontier」「rounds」はそれぞれ一文分の説明の代わりを務め、読者がその用語を一度覚えれば、以後の使用は10語ではなく1語で済みます。

情報階層

長さそのものも敵ではありません。ここが「grill-meは5行」という話が見落としている部分です。スキルは階層を定義しています。in-file stepはエージェントが順番通りに行うことであり、in-file referenceは必要に応じて参照されるもの、disclosed referenceは別ファイルに追い出され、そのポインタが発火したときだけ読み込まれるものです。

情報階層:埋め込むところと、ポインタの先へ送るところ3段が縦に積まれている。常に読み込まれ順番に実行される in-file step、同じファイル内で必要に応じて参照される in-file reference、別ファイルに追い出されポインタが発火したときだけ読み込まれる disclosed reference。左側のゲージは、上から下に向かって常時読み込みの比重が減っていくことを示す。常時読み込みの比重1in-file stepエージェントの手順そのもの。毎ターン必ず読み込まれる。2in-file reference定義やルール。必要なときだけ参照。3disclosed reference別ファイルへ追い出す。ポインタが発火したときだけ読む。
writing-for-agentsの情報階層:インラインに留まるもの、ポインタの先に移されるもの。

codebase-designは完全な用語集とASCII図を含めて114行ありますが、このテストに照らせば水増しは一つもありません。 どの行も、デフォルトの言い直しではなく、読者が必要なときに本当に求める参照資料だからです。15行のスキルも114行のスキルも、どちらも正しく刈り込まれ得ます。この規律が実際に測っているのは行数ではなく階層構造です。

二つのコード・スメル語彙、意図的に分けられている

code-reviewのスメル一覧は、FowlerのRefactoringにあるものの12項目版です。Mysterious Name、Duplicated Code、Feature Envy、Data Clumps、Primitive Obsession、Repeated Switches、Shotgun Surgery、Divergent Change、Speculative Generality、Message Chains、Middle Man、Refused Bequest。それぞれ同じ形式で書かれています。それが何であり、どう直すかです。そして両方とも、一覧の上に一度だけ書かれた2つの規則に縛られます。 文書化されたリポジトリ標準はこの基準より優先されること、そしてすべてのスメルはラベル付きの判断材料であって、強制違反ではないことです。

codebase-designはその語彙をまったく使いません。その用語集はModule、Interface、Implementation、Depth、Seam(Michael Feathersに帰属)、Adapter、Leverage、Localityを定義しており、それぞれについて、代わりに多くの人が使いがちな語への明示的な警告が付いています。Moduleに対して「unit」や「service」を避けること、Interfaceに対して「API」や「signature」を避けること、Seamに対して「boundary」を避けること。深いモジュールは小さなInterfaceに多くのImplementationを組み合わせたものであり、浅いモジュールはその逆で、スキルはこれを避けるよう述べています。さらに自身の出典を名指ししたうえで、それを部分的に否定してもいます。 Ousterhoutの元々の指標はDepthをImplementationの行数とInterfaceの行数の比率で測りますが、スキルはこの枠組みを名指しで批判します。Implementationを水増しすることに報酬を与えてしまうからで、代わりに「depth as leverage」を使います。

2つの分けられたコード・スメル語彙左右2枚のカードが「≠」の仕切りで並ぶ。左は code-review の Fowler スメル一覧: Mysterious Name、Duplicated Code、Feature Envy、Data Clumps、Shotgun Surgery ほか7項目。2つの規則が支配する。リポジトリの明文化された基準が優先し、どのスメルも判断材料であって強制違反ではない。右は codebase-design の Ousterhout系語彙: Module、Interface、Implementation、Depth、Seam、Adapter、Leverage、Locality。実装行と interface 行の比率という Ousterhout 自身の指標ではなく、「深さ=レバレッジ」で測る。右カードの下の注記は、この語彙が improve-codebase-architecture にも再利用されることを示す。左側は他のどこにも再利用されない。code-reviewFowler スメル基準• Mysterious Name• Duplicated Code• Feature Envy• Data Clumps• Shotgun Surgery• 他7項目リポジトリの基準が優先どのスメルも判断材料codebase-designOusterhout系語彙• Module• Interface• Implementation• Depth• Seam• Adapter• Leverage• Locality深さ = レバレッジOusterhout自身の比率ではない語彙は共有されないimprove-codebase-architecture も利用
Fowlerのスメルと、Ousterhout系のモジュール:決して統合されない2つの語彙。

プラグインのどこを見ても、どちらの語彙も互いから借用していません。コードベースの健全性スキャンを行うimprove-codebase-architectureは、codebase-designの語を使い、「component」「service」「API」「boundary」に流れないよう明示的に指示されています。この2つの体系は異なる問題を解いています。一方はdiffにすでに何が問題かを名指しし、もう一方は何かが問題になる前にInterfaceをどう形作るかを名指しします。 短い要約がしがちなように1つの一覧にまとめてしまうと、それぞれが存在する理由が失われます。

規律を説明するのではなく、実際に適用する

規律を読むことと、それを使うことは別です。そしてこのリポジトリには、すでにそれを使う場所がありました。自身のリリース・パイプラインはマージのたびにコードレビューを走らせており、一般的なコード・スメルの観点を一度も持ったことのないリポジトリ固有のチェックリストに照らしてチェックしています。エージェントの提案は、プラグインのcode-reviewスキルを第2の独立したパスとして走らせるのではなく、code-reviewの12項目の基準を出典を明記したうえで既存のチェックリストに8番目の観点として組み込むことでした。 1つのdiffに対して2つのレビュー結果を出せば、リリースのたびにその食い違いを調整することになります。1つのチェックリストに新しい観点を1つ追加するなら、その必要はありません。

同じ訪問で、このリポジトリになかったドメイン用語集も作られました。後回しにせず、すぐに種を蒔くよう依頼しました。用語は考案したものではなく実際のコード(ArticleLocaleFigureThumbnail、ほか8個)から拾い、書き留める前に、それを実際に定義しているファイルと照らし合わせて確認しました。

刈り込みテストは、全面的な書き直しよりも狭い範囲で、このリポジトリ自身の文章にも使われました。リポジトリ内で最も長い2つのスキルファイルに対して、no-opテストとleading wordテストのみを走らせ、すべてのインシデントの記述とガードレールの表はそのまま残すことを選びました。writing-for-agents自身が、そうした素材は正当なキャッシュであり、刈り込むべき水増しではないと述べています。「明文化されていない慣習、選択の背後にある理由、どの設定も白状しない落とし穴」です。

変化したこと、検証したこと

このリポジトリ自身のスキルに対する刈り込みパスは、水増しを見つけたというより、規律そのものを裏付ける結果になりました。 no-opテストとleading wordテストを988行のリリーススキルと609行のスタイルガイドに適用したところ、それぞれ正当な削減が3件見つかっただけで、何十件ではありませんでした。これは見落としではなく、設計上こうなるべき低い数字です。両ファイルの長さの大半は実際のリリースから学んだインシデントの記憶、正確なコマンド、正確な失敗モードであり、writing-for-agents自身の規則はそれをフラグするのではなく守る側に回ります。

新しいレビューの観点は、ドキュメントだけでなく実際のコードに触れたdiffで最初の実地テストを受け、実際に何かを見つけました。重複していたフェンス解析ルーチンを1つの共有関数に統合する過程で、クロージング規則が静かに緩んでいました。行全体がフェンス文字だけであることを要求する、隣接する関数がすでに使っていたより厳格な規則の代わりに、フェンスマーカーの先頭部分にマッチするようになっており、しかも新しい関数自身のコメントはその規則を共有していると主張していましたが、実際にはそうなっていませんでした。追加されたばかりの8番目の観点が、プルリクエストがマージされる前にそれを捕まえました。 バグは本物で、その時点ではコーパス中で実際に発現してはいなかったものの潜在していました。導入されたのと同じセッションで修正されました。スメルの基準はチェックリストの飾りではありませんでした。それはレビューされる内容そのものを変えました。

まとめ

Matt Pocockのmattpocock-skillsプラグインが簡潔なのは、その中のメタスキルが何を削り何を残すかを正確に定義しているからです。 言い直された既定文は削られ、密な事前学習済みの用語が説明の代わりを務め、参照資料はインラインではなくポインタの先に移されます。同梱されるコード・スメル語彙は1つではなく2つあります。 すでに間違っているdiffのためのFowlerのものと、まだ何も間違っていない段階でInterfaceを形作るための、修正されたOusterhoutのものです。動画は語彙とその行数、両方の区別を一緒くたにしてしまっていました。要約ではなくソースを読んだことが、それを捕まえました。この規律を実際に使い、1つの語彙を第2のツールとして走らせるのではなく既存のレビューに組み込んだことで、その違いは目に見える形になりました。それが変えたチェックリストは、そのリリースが出る前に、自分自身の中のバグを捕まえました。

この記事をシェア