2軸レビュー: ユーザーが指定した固定点と HEAD の間の差分をレビューします。
- 標準 (Standards): コードはこのリポジトリに文書化されたコーディング標準に従っていますか?
- 仕様 (Spec): コードは元のIssue/仕様を忠実に実装していますか?
両方の軸は並列サブエージェントとして実行されるため、互いのコンテキストを汚染しません。その後、このスキルがそれぞれの結果を集約します。
Issueトラッカーは事前に提供されている必要があります。提供されていない場合は、ユーザーに /setup-matt-pocock-skills を実行するよう伝えてください。
プロセス
1. 固定点を特定する
ユーザーが指定した固定点(コミットSHA、ブランチ名、タグ、main、HEAD~5など)を使用します。ユーザーが固定点を指定しなかった場合は、入力を求めます。
差分コマンドを一度だけ取得します: git diff <fixed-point>...HEAD(3つのドットを使用し、マージベースとの比較)。また、コミットのリストを git log <fixed-point>..HEAD --oneline で取得します。
先に進む前に、固定点が解決可能であること(git rev-parse <fixed-point>)と、差分が空でないことを確認します。不正な参照や空の差分は、並列サブエージェントを実行する前にここで失敗させるべきです。
2. 仕様ソースを特定する
元の仕様を以下の優先順位で探します。
- コミットメッセージ内のIssue参照(
#123、Closes #45、GitLabの!67など)。トラッカードキュメントのワークフローを使用して取得します。 - ユーザーが引数として渡したパス。
- ブランチ名や機能名に一致する
docs/、specs/、または.scratch/ディレクトリ内の仕様ファイル。 - 何も見つからない場合、ユーザーに仕様の場所を尋ねます。ユーザーが仕様はないと答えた場合、Specサブエージェントはスキップされ、「仕様なし」と報告します。
3. 標準ソースを特定する
コードの記述方法を文書化したすべてのファイルをリポジトリ内で検索します。CODING_STANDARDS.md または CONTRIBUTING.md が存在する場合は、必ずリストに含めます。
リポジトリが文書化している内容に加えて、Standards軸は常に以下のスメルベースラインを持ちます。これはMartin Fowlerのコードスメル(『リファクタリング』第3章)の固定セットで、リポジトリが何も文書化していない場合でも適用されます。2つのルールがこれを制約します。
- リポジトリが優先される。 文書化されたリポジトリ標準は常に優先されます。ベースラインがフラグを立てる内容をリポジトリ標準が認めている場合は、そのスメルは抑制されます。
- 常に判断を要する。 各スメルはラベル付けされたヒューリスティック(「可能性のある機能嫉妬」)であり、厳格な違反ではありません。ここでの他の標準と同様に、ツールが既に強制しているものはスキップします。
各スメルは、その内容 → 修正方法 として読みます。差分と照合します:
- ** Mysterious Name(不可解な名前)**: 関数、変数、型の名前が、その動作や保持する内容を明らかにしていない。→ 名前を変更する。正直な名前が思い浮かばなければ、設計が曖昧である。
- ** Duplicated Code(重複したコード)**: 同じロジックの形状が、変更内の複数のハンクまたはファイルに現れている。→ 共通の形状を抽出し、両方から呼び出す。
- ** Feature Envy(機能嫉妬)**: メソッドが、自身のデータよりも他のオブジェクトのデータに多くアクセスしている。→ メソッドを、それが羨んでいるデータを持つオブジェクトに移動する。
- ** Data Clumps(データの固まり)**: 同じいくつかのフィールドやパラメータが常に一緒に渡されている(生まれるべき型を暗示)。→ それらを1つの型にまとめ、その型を渡す。
- ** Primitive Obsession(プリミティブへの固執)**: プリミティブや文字列が、独自の型を持つべきドメイン概念の代わりに使われている。→ その概念に専用の小さな型を与える。
- ** Repeated Switches(繰り返されるスイッチ)**: 同じ型に対する同じ
switch/ifカスケードが変更全体にわたって繰り返されている。→ ポリモーフィズムに置き換えるか、両方の箇所で共有する1つのマップを使用する。 - ** Shotgun Surgery(ショットガン手術)**: 1つの論理的な変更が、多くのファイルに散在する編集を強制する。→ 変更すべきものを1つのモジュールにまとめる。
- ** Divergent Change(発散する変更)**: 1つのファイルやモジュールが、無関係な複数の理由で編集されている。→ 各モジュールが1つの理由でのみ変更されるように分割する。
- ** Speculative Generality(推測による汎用性)**: 仕様にないニーズのために追加された抽象化、パラメータ、フック。→ 削除する。本当のニーズが現れるまでインライン化して戻す。
- ** Message Chains(メッセージ連鎖)**: 呼び出し元が依存すべきでない長い
a.b().c().d()ナビゲーション。→ 最初のオブジェクトの1つのメソッドの背後にウォークを隠す。 - ** Middle Man(中間者)**: 主に転送を行うだけのクラスや関数。→ 削除し、実際のターゲットを直接呼び出す。
- ** Refused Bequest(拒否された遺産)**: 継承または実装したものの大部分を無視またはオーバーライドするサブクラスや実装者。→ 継承をやめて、コンポジションを使用する。
4. 両方のサブエージェントを並行して起動する
両方のサブエージェント呼び出しを一緒にフォアグラウンドで発行し、それらが返すレポートを集約します。
Standardsサブエージェントのプロンプトには以下を含めます:
- 完全な差分コマンドとコミットリスト。
- ステップ3で見つけた標準ソースファイルのリスト、およびステップ3のスメルベースラインを全文コピーしたもの(サブエージェントは他にアクセスできません)。
- 指示: 「ファイル/ハンクごとに、以下を報告せよ: (a) 差分が文書化された標準に違反している箇所すべて。標準を引用せよ(ファイル + ルール)。(b) 確認したベースラインスメルがあれば、名前を挙げてハンクを引用せよ。文書化された標準違反はハード違反となり得るが、ベースラインスメルは常に判断事項であり、文書化されたリポジトリ標準はベースラインに優先する。ツールが強制するものはスキップせよ。400語以内。」
Specサブエージェントのプロンプトには以下を含めます:
- 差分コマンドとコミットリスト。
- 仕様のパスまたは取得した内容。
- 指示: 「以下を報告せよ: (a) 仕様が要求しているが、欠落しているか部分的にしか実装されていない要件。(b) 差分内で要求されていない動作(スコープクリープ)。(c) 実装されているように見えるが、実装が間違っているように見える要件。各指摘について仕様の行を引用せよ。400語以内。」
仕様がない場合は、Specサブエージェントをスキップし、最終レポートにその旨を記載します。
5. 集約
2つのレポートを ## Standards および ## Spec の見出しの下に、そのまま、または軽くクレンジングして提示します。指摘事項をマージしたり再ランク付けしたりしないでください。2つの軸は意図的に分離されています(なぜ2軸なのか を参照)。
各軸の合計評定数と、各軸内で最も深刻な問題(ある場合)を含む1行の要約で締めくくります。軸をまたいで単一の勝者を選ばないでください。それは、この分離が防ごうとしている再ランク付けだからです。
なぜ2軸なのか
変更は、一方の軸をパスし、もう一方の軸で不合格になる可能性があります:
- すべての標準に従っているが、間違ったものを実装しているコード → Standards合格、Spec不合格。
- Issueが要求したことを正確に行っているが、プロジェクトの規約を破っているコード → Spec合格、Standards不合格。
それらを別々に報告することで、一方の軸がもう一方の軸を覆い隠すことを防ぎます。