Refactoring Skill
リファクタリングの定義・制約・禁止事項は references/definition.md を参照。 候補記録のテンプレートは references/discovery-template.md を参照。
ワークフロー
1. スコープレベルの確認
2. リファクタリング候補の並列探索
2a. 探索の分割戦略
2b. Agent tool による並列探索
2c. 結果の集約と提案
3. 振る舞い保持の検証(Gate)
3.5 テスト追加後の再開フロー
4. リファクタリングの実施
5. 完了の確認
6. 変更内容のサマリ出力
1. スコープレベルの確認
明示指示がない場合は Level 1(デフォルト)で進める。
| Level | 範囲 | 必要な明示指示 |
|---|---|---|
| 1 | 関数内 / 1ファイル内 | 不要(デフォルト) |
| 2 | 複数ファイル / 依存関係の整理 | 必要 |
| 3 | アーキテクチャ変更 | 必要 |
2. リファクタリング候補の並列探索
対象が明示されていない場合に実施。「直す価値が高く」「範囲が限定でき」「テストで守れる」箇所を候補化する。
探索結果は refactoring-discoveries/ ディレクトリに MD ファイルとして永続化する(テンプレートは references/discovery-template.md に準拠)。
既存の発見結果がある場合
refactoring-discoveries/ ディレクトリが既に存在し、ステータスが 未着手 の候補ファイルがある場合は、新規探索をスキップして Step 2c の集約・提案に直接進む。これにより、別セッションで発見した候補を引き継いで作業できる。
2a. 探索の分割戦略
探索を2軸で分割し、並列実行する。
| 軸 | 分割方法 | 並列単位 |
|---|---|---|
| ディレクトリ軸 | トップレベルのソースディレクトリ/パッケージ単位で分割 | ディレクトリごとに1エージェント |
| 分析観点軸 | 複雑性分析・重複分析・依存分析の3観点 | 観点ごとに1エージェント |
規模に応じた判断:
- プロジェクトの構造を確認する(
lsでトップレベルディレクトリを列挙、.gitignoreや設定ファイルからソースディレクトリを特定) - ソースディレクトリが 10未満 の場合: 観点軸のみで並列化(3エージェント)。ディレクトリ軸の分割はオーバーヘッドが大きいためスキップする
- ソースディレクトリが 10以上 の場合: ディレクトリ軸 × 観点軸 で並列化。ただし同時エージェント数は最大9に制限し、ディレクトリをグループ化して調整する
2b. Agent tool による並列探索
各探索単位で Agent tool (subagent_type: Explore) を run_in_background: true で起動する。
サブエージェントへの指示テンプレート:
以下の条件でリファクタリング候補を探索し、発見した候補を MD ファイルとして出力してください。
## 探索条件
- 対象ディレクトリ: {directory_path}
- 分析観点: {complexity|duplication|dependency}
- スコープレベル上限: Level {1|2|3}
## 分析観点ごとの手順
### 複雑性分析(complexity)
1. 対象ディレクトリ内のソースファイルを Glob で列挙
2. 各ファイルを Read し、以下を推定:
- 関数/メソッドごとの行数
- ネスト深度(条件分岐・ループの入れ子)
- 分岐数(if/switch/三項演算子の数 → 循環複雑度の近似)
3. 閾値超過(行数50以上、推定循環複雑度10以上、ネスト4以上)の関数を候補とする
### 重複分析(duplication)
1. 対象ディレクトリ内のソースファイルを Glob で列挙
2. Grep で類似パターン(同一のコードブロック、類似の処理フロー)を検出
3. 3箇所以上で重複、または10行以上の重複ブロックを候補とする
### 依存分析(dependency)
1. 対象ディレクトリ内のソースファイルを Glob で列挙
2. import/require/use 文を Grep で抽出し、依存グラフを構築
3. 高結合度(依存先10以上)、循環依存、不安定な依存方向を候補とする
## 動的指標の収集(全観点共通)
候補ごとに以下を Bash で取得:
- `git log --oneline --follow {file_path}` → 変更回数(churn)
- `git log --oneline --grep="fix\|bug" {file_path}` → バグ修正頻度
## 出力
発見した候補ごとに、以下のパスに MD ファイルを作成:
- パス: refactoring-discoveries/{NNN}-{function_name}.md
- フォーマット: references/discovery-template.md に準拠
- ステータス: 未着手
- 分析観点: {この探索の観点}
- 発見日時: {今日の日付}
候補が見つからなかった場合はファイルを作成せず、その旨を報告してください。
起動方法:
# 観点軸のみ(小規模)の場合: 3エージェントを並列起動
Agent(subagent_type=Explore, run_in_background=true) × 3(複雑性/重複/依存)
# ディレクトリ軸 × 観点軸(大規模)の場合: グループ × 3観点
Agent(subagent_type=Explore, run_in_background=true) × N
全エージェントの完了を待ってから次の Step 2c に進む。
2c. 結果の集約と提案
全エージェント完了後、以下を実施する:
- 読み取り:
refactoring-discoveries/内の全 MD ファイルを読み取る - 重複排除: 同一関数が複数の分析観点から検出された場合、1つの候補にマージする。マージ時は各観点の根拠を統合し、分析観点フィールドをカンマ区切りで結合する
- 統合スコアリング: 以下の重み付けでランキングする
| 指標 | 重み | 説明 |
|---|---|---|
| 循環複雑度 | 高 | 複雑なほど優先 |
| churn(変更頻度) | 高 | 頻繁に変更されるほど優先 |
| バグ修正頻度 | 中 | バグが多いほど優先 |
| 重複箇所数 | 中 | 重複が多いほど優先 |
| 行数 | 低 | 長いほど優先 |
| 結合度 | 低 | 結合が高いほど優先 |
- 提案: 上位N件(デフォルト5件、ユーザー指定があればその数)を以下のテーブル形式で提示する
提案フォーマット:
| # | 対象(ファイル:行 / 関数名) | 根拠(指標値) | 期待効果 | 影響範囲 | Gate B 材料 |
|---|---|---|---|---|---|
| 001 | foo.ts:42 / parseUser | 循環複雑度 12, churn 28回/月 | 可読性向上 | 呼び出し元3箇所 | 正常系のみカバー |
- 選択依頼: ユーザーに実行対象の候補番号を選択してもらう。複数選択可。
3. 振る舞い保持の検証(実行前 Gate チェック)
リファクタリングを実行する前に、選択された各候補ごとに以下の2つの Gate を確認する。
Gate A(必須条件): 既存の自動テストがすべて成功すること。
Gate B(十分性チェック): 変更対象の重要パスがテストされていること:
- 正常系(代表入力)
- 境界値(空/0/最大長/上限付近)
- 異常系(例外・エラー条件)
- 副作用(DB更新・外部I/O・キャッシュなど)
Gate A と Gate B を両方満たす候補のみ、リファクタリングを実行する。
いずれかが未達の場合はその候補のリファクタリングを中止し、以下を実施する:
出力(ユーザーへ):
- 未達の条件(A/B のどれか)
- 根拠(カバレッジ値、未テストの重要パスの具体)
- 実行しない理由(仕様保持を客観的に担保できないため)
- 推奨対応(追加すべきテストの概要)
記録(ファイルへ):
refactoring-discoveries/内の該当候補 MD ファイルのステータスを中止に更新し、中止理由を追記する- プロジェクトルートの
refactoring-aborted.mdに追記する。ファイルが存在しない場合は新規作成し、先頭に# リファクタリング中止ログヘッダーを付ける
## YYYY-MM-DD | `<対象ファイル:行>` / `<関数名>`
- **未達Gate**: A / B(該当するもの)
- **根拠**: <カバレッジ値・未テストパスの具体>
- **推奨対応**: <追加すべきテストの概要>
3.5 テスト追加後の再開フロー
ユーザーがテストを追加してリファクタリングの再実行を依頼した場合:
- Gate A・B を再チェックする
- 両方通過した場合: 該当候補 MD のステータスを
実行中に更新し、Step 4 へ進む(リファクタリング完了後に Step 5 でrefactoring-aborted.mdのエントリーを削除する) - まだ未達の場合: 残る未達条件と追加対応を案内し、
refactoring-aborted.mdの該当エントリーの「推奨対応」を更新する
4. リファクタリングの実施
Gate を通過した候補に対して、以下の2つの実行モードから選択する。
モード A: 同一セッション並列実行
複数の候補を同時にリファクタリングする場合に使用する。
- 選択された各候補について、Agent tool (
isolation: worktree) でサブエージェントを起動する - 各サブエージェントへの指示:
refactoring-discoveries/{NNN}-{function_name}.mdを読み取り、対象・推奨アプローチを把握する- Gate A を実行(テストが通ることを確認)
- 推奨アプローチに従いリファクタリングを実施する
- 変更は最小限・段階的に行う
- 禁止事項(references/definition.md 参照)を守る
- 完了後、テストを再実行して Gate A を通過することを確認する
- 全サブエージェント完了後、メインエージェントが:
- 各 worktree の変更内容を確認する
- コンフリクトがないことを確認し、マージする
- コンフリクトがある場合はユーザーに報告し、解決方針を相談する
モード B: 逐次実行(デフォルト)
候補が1件の場合、または別セッションで逐次的に作業する場合に使用する。
- 該当候補の MD ファイルのステータスを
実行中に更新する - 以下を守りながらリファクタリングを実施する:
- 変更は最小限・段階的に行う
- 禁止事項(references/definition.md 参照)を守る
モード選択の基準:
- 候補が1件 → モード B
- 候補が複数件かつ互いに依存関係がない → モード A を提案(ユーザー確認後に実行)
- 候補が複数件かつ依存関係がある → モード B で依存順に逐次実行
5. 完了の確認
以下の成功条件をすべて満たすことを確認する:
- 振る舞いが変更されていない(テストが通る)
- コードの理解しやすさが向上している
- 変更の影響範囲が限定されている
- 不要な複雑性が減少している
確認後、以下のクリーンアップを行う:
refactoring-discoveries/内の該当候補 MD ファイルを削除する。完了した候補の情報は Step 6 のサマリで報告するため、ファイルとして残す必要はない。refactoring-discoveries/ディレクトリが空になった場合はディレクトリごと削除してよいrefactoring-aborted.mdに対象のエントリーが存在する場合はそのエントリーを削除する。ファイルがヘッダー行のみになった場合はファイルごと削除してよい
6. 変更内容のサマリ出力
完了後、以下を簡潔に報告する:
- 実施したリファクタリングの種類と箇所
- 改善した点(可読性・重複排除など)
- テスト結果(Gate A/B の確認結果)
refactoring-discoveries/内の残り候補数(ステータス別の件数)