HEAD とユーザーが指定した固定点との間の差分を2軸でレビューします。
- 規約 (Standards):コードはこのリポジトリの文書化されたコーディング規約に準拠していますか?
- 仕様 (Spec):コードは元のIssue/仕様を忠実に実装していますか?
両方の軸は並列サブエージェントとして実行されるため、互いのコンテキストを汚染しません。その後、本スキルがそれらの結果を集約します。
イシュートラッカーが提供されているはずです。提供されていない場合は、ユーザーに /setup-matt-pocock-skills を実行するよう伝えてください。
プロセス
1. 固定点を確定する
ユーザーが指定した固定点(コミットSHA、ブランチ名、タグ、main、HEAD~5 など)をそのまま使用します。ユーザーが指定しなかった場合は、それを尋ねてください。
差分コマンドを一度だけ取得します:git diff <固定点>...HEAD(三点ドット。これによりマージベースとの比較になります)。また、git log <固定点>..HEAD --oneline でコミットのリストも記録します。
先に進む前に、固定点が解決可能であること(git rev-parse <固定点>)と、差分が空でないことを確認してください。不正な参照や空の差分は、ここで失敗させるべきであり、2つの並列サブエージェントの中で失敗させてはいけません。
2. 仕様のソースを特定する
発行元の仕様を以下の順序で探します:
- コミットメッセージ内のIssue参照(
#123、Closes #45、GitLab!67など)。トラッカードキュメントのワークフローを使用して取得します。 - ユーザーが引数として渡したパス。
docs/、specs/、または.scratch/にある、ブランチ名または機能名に一致する仕様ファイル。- 何も見つからない場合は、ユーザーに仕様の場所を尋ねます。ユーザーが「仕様はない」と言った場合、仕様サブエージェントはスキップして「利用可能な仕様なし」と報告します。
3. 規約のソースを特定する
リポジトリ全体から、コードの書き方を文書化したすべてのファイルを検索します。CODING_STANDARDS.md または CONTRIBUTING.md が存在する場合は、必ずリストに含めます。
リポジトリが文書化している内容に加えて、「規約」軸は常に以下のスメルベースラインを保持します。これは、リポジトリが何も文書化していなくても適用される、固定のFowlerコードスメル集(Refactoring 第3章)です。2つのルールがこれを束縛します:
- リポジトリが上書きする。 文書化されたリポジトリの規約が常に優先されます。リポジトリの規約がスメルベースラインでフラグされる内容を推奨している場合は、そのスメルを抑制します。
- 常に判断である。 各スメルはラベル付けされたヒューリスティック(「おそらくFeature Envy」)であり、厳格な違反ではありません。他の規約と同様に、ツールがすでに強制しているものはスキップします。
各スメルは それが何か → 修正方法 の形式で読まれ、差分と照合します:
- 理解しがたい名前 (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. 両方のサブエージェントを並列に起動する
両方のサブエージェント呼び出しをフォアグラウンドで一緒に発行し、返されたレポートを集約します。
規約サブエージェントのプロンプトには以下を含める必要があります:
- 完全な差分コマンドとコミットリスト。
- ステップ3で見つけた規約ソースファイルのリスト。さらに、ステップ3のスメルベースラインを全文貼り付け(サブエージェントはそれにアクセスできません)。
- 指示:「ファイル/ハンクごとに関連する場合、(a) 差分が文書化された規約に違反しているすべての箇所を報告:規約を引用(ファイル + ルール);(b) 気づいたベースラインスメルがあれば、その名前を挙げてハンクを引用。厳格な違反と判断を区別:文書化された規約違反は厳格であり得るが、ベースラインスメルは常に判断であり、文書化されたリポジトリ規約がベースラインを上書きします。ツールが強制するものはスキップ。400ワード以内。」
仕様サブエージェントのプロンプトには以下を含める必要があります:
- 差分コマンドとコミットリスト。
- 仕様のパスまたは取得した内容。
- 指示:「報告:(a) 仕様が要求したが欠落または不完全な要件;(b) 差分に含まれるが要求されていない動作(スコープクリープ);(c) 実装されているように見えるが、実装が間違っているように見える要件。各発見に対して仕様の行を引用。400ワード以内。」
仕様がない場合は、仕様サブエージェントをスキップし、最終レポートにその旨を記載します。
5. 集約する
2つのレポートを ## 規約 (Standards) および ## 仕様 (Spec) の見出しの下に、逐語的または軽くクリーニングして提示します。発見事項をマージしたり再ランク付けしたりしないでください。2つの軸は意図的に分離されています(なぜ2軸なのか を参照)。
最後に、1行の要約を追加します:各軸ごとの発見の総数、および各軸内で最悪の問題(あれば)。軸をまたいで単一の勝者を選ばないでください:その再ランク付けを防ぐために分離が存在します。
なぜ2軸なのか
変更は一方の軸を通過し、もう一方で不合格になることがあります:
- すべての規約に従っているが、間違ったものを実装しているコード → 規約合格、仕様不合格。
- Issueが要求したことを正確に行っているが、プロジェクトの慣習を破っているコード → 仕様合格、規約不合格。
それらを別々に報告することで、一方の軸がもう一方の軸を隠してしまうのを防ぎます。