diff --git a/.claude/commands/auto-audit.md b/.claude/commands/auto-audit.md index 090112b..7ba7d21 100644 --- a/.claude/commands/auto-audit.md +++ b/.claude/commands/auto-audit.md @@ -1,11 +1,11 @@ --- name: auto-audit model: opus -description: "放置中(無人)に自律的に回り続け,空き時間をコードベース全体の「バグ発見」と「脆弱性発見」に充てる巡回ループ.見つけた指摘を独立検証(裏取り)した上で,バグを再現して落ちるテスト(赤→緑)で修正の正しさを担保できるものだけを積極的に自動修正し,再現テストが書けない/挙動判断が要るものは台帳に報告する.影響範囲を解析し,各修正について人間が行うべき動作確認を添えて報告する.専用ブランチ(fix/)へ自律コミットするが push・PR・マージはしない." +description: "放置中(無人)に自律的に回り続け,空き時間をコードベース全体の「バグ発見」と「脆弱性発見」に充てる巡回ループ.メインは薄い司令塔として振る舞い,各指摘の裏取り〜修正〜検証を「1指摘=1体の項目オーケストレータ」に隔離コンテキストで完走させる(内部で tester/coder 等の専門エージェントを使い分ける).見つけた指摘を独立検証(裏取り)した上で,バグを再現して落ちるテスト(赤→緑)で修正の正しさを担保できるものだけを積極的に自動修正し,再現テストが書けない/挙動判断が要るものは台帳に報告する.影響範囲を解析し,各修正について人間が行うべき動作確認を添えて報告する.専用ブランチ(fix/)へ自律コミットするが push・PR・マージはしない." argument-hint: "[bug|security|all(省略時 all)] [対象ディレクトリ/モジュールの絞り込み(省略可)]" --- -あなたは**自律バグ/脆弱性 監査ループのオペレーター**です. +あなたは**自律バグ/脆弱性 監査ループの制御層(オーケストレータ)**です. ユーザーが席を外している無人時間に,空いた稼働枠を「コードベース全体を巡回してバグ・脆弱性を発見し,安全に直せるものを直す」ことに充てるために起動されました. GUIDE_04(Git 運用),GUIDE_05(エージェント運用)を読み,書式・規約・パイプラインのルールを理解した上で,以下の不変条件を厳守してループを回してください. @@ -16,10 +16,29 @@ いずれで見つけた指摘も,後述の **4 ゲート(裏取り → 再現テスト先行 → 影響範囲解析 → 影響評価つき報告)** を通す.違いは「何を探すか」だけで,「どう安全に直すか」は同じ. +## 二層構造 — 誰が何をするか(重要・このコマンドの核) + +このループは**コンテキストを薄く保ったまま長時間回す**ために,責務を階層で分ける.メインは自分でコードやテストを触らず,指摘1件ごとに専用の作業体を起動し,**その最終報告(構造化サマリ)だけ**を受け取って台帳に反映する.こうするとメインには各指摘の詳細な読み込み・思考が積もらず,長時間・大規模でも司令塔のコンテキストが一定に保たれる.一方で専門エージェントの役割分担(独立したテスト作成・修正)はそのまま維持される(サブエージェントの内部コンテキストはメインに戻らないため,両立できる). + +- **① ループ制御層(あなた=メイン)**:セットアップ,台帳の読み書き,発見の起動,指摘の選定,**項目オーケストレータの起動**,返ってきた構造化サマリの台帳反映,収束判定,完了報告のみを行う.**自分でコード・テストを編集しない.指摘の詳細な裏取り・修正・検証はすべて下層に委ねる**(メインを薄く保つため). +- **② 項目オーケストレータ(1指摘=1体)**:メインから渡された**1つの指摘**について,4 ゲートを隔離コンテキストで**丸ごと完走**する司令塔.内部で下層の専門エージェントを使い分け,最後に**構造化サマリ1通**をメインへ返す.自動修正できたものは自分で `fix/` ブランチへコミットする. +- **③ 専門エージェント(項目オーケストレータが内部で使う)**: + - **発見**:`Explore`(読み取り専用で候補箇所を広く洗い出す). + - **裏取り(反証)**:独立した検証役(別エージェント)に「これは誤検知だ」と反証を試みさせる(adversarial verify). + - **再現テスト・特性化テスト**:`tester`. + - **修正**:`coder`. + - ※ 専門エージェントへの委譲が使えない環境では,項目オーケストレータが同じ手順(別ステップ・赤→緑規律)を自分で行ってよい.ただし**テスト作成と修正は必ず別ステップ**とし,独立性と赤→緑の規律を崩さない. + +### 二層で回すときの鉄則 + +- **メインは逐次に1体ずつ**項目オーケストレータを起動する(並行起動しない).同一の作業ツリー・`fix/` ブランチを共有するため,同時にコミットすると競合するため. +- メインが下層へ渡すのは「1つの指摘」と,本コマンドの**不変条件・4 ゲート・検証コマンド・除外リスト・観点フィルタ・既存台帳の要点(既にスキップ/報告済みで再処理不要なもの)**.渡した後はメインは待ち,**返ってきたサマリだけ**を信じて台帳を更新する(下層の詳細をメインが読み返さない=薄さを保つ). +- 発見(`Explore`)はメイン自身の起動でも,項目オーケストレータ内でもよいが,**メインが自分でコードを精読して候補を作らない**(読み込みは `Explore` に出す). + ## このコマンドの位置づけ(重要) - 本コマンドは **CLAUDE.md の「`/commit` 自発実行禁止」ルールに対する,ユーザー承認済みの明示的な例外**である(`/auto-refactor` と同格の例外). - - ただし例外が認められるのは **`fix/` 専用ブランチへのコミットに限る**. + - ただし例外が認められるのは **`fix/` 専用ブランチへのコミットに限る**(コミットは項目オーケストレータが行うが,制約は同じ). - **`git push`・PR 作成・マージ・`main` への操作は一切行わない**(取り込み可否の判断は後で人間が行う). - 「無人で回り続ける」ことが目的のため,各修正での人間確認は挟まない.これが許される根拠は次の通り: - **自動修正するのは「再現テストで正しさを証明できたバグ/脆弱性」だけ**である(後述ゲート②).赤→緑になる再現テストと,緑を保つ既存スイートが,人間確認の代わりの安全網を果たす. @@ -27,16 +46,18 @@ ## 不変条件 (Invariants) — 1つでも破れそうなら停止する -1. **再現テストで証明できた修正だけを自動適用する**:どんな修正も「そのバグ/脆弱性を再現して**落ちるテスト(修正前は赤)**を書く → 修正 → **そのテストが緑になり,かつ既存の検証スイート全体も緑**」を満たした場合にのみコミットする.再現テストが書けない/緑にできないものは自動修正しない(ゲート②へ). -2. **裏取りしてから触る**:発見した指摘は,独立した視点で「本当にバグ/脆弱性か」を検証し,**誤検知(false positive)を修正対象から除外**してから着手する(ゲート①).確度が低いものは報告のみに落とす. -3. **影響範囲を保護してから直す**:修正するシンボルの呼び出し元・依存先を洗い出し,**テスト未カバーの影響先には先に特性化テスト(現状固定)を足して保護**してから修正する.影響が広すぎて無人で追い切れない場合は自動修正せず報告に落とす(ゲート③). -4. **挙動を戻さない安全網**:修正後に検証スイート(テスト+あればビルド/型チェック/リンタ)が**完全に緑**であること.赤が1つでも出たら,その修正は破棄(revert/stash)して対象を報告に落とす. -5. **専用ブランチのみ**:作業は `fix/` ブランチ上でのみ行う.`main` には絶対にコミットしない. -6. **push/PR しない**:リモート操作は一切しない. -7. **1修正 = 1コミット(テストは別コミット可)**:意味のあるまとまり(1バグ修正/1脆弱性修正)単位でこまめにコミットし,巨大な未コミット差分を溜めない.再現テスト・特性化テストの追加は `[add]`,修正本体は `[fix]` に分けてよい. -8. **除外領域に触れない**:後述の「対象外の領域(除外リスト)」に該当する箇所は修正対象に選ばない. -9. **疑わしきは報告に落とす**:判断に迷う・裏取りで確信が持てない・再現テストが書けない・影響が追い切れない・テストコマンドが特定できない場合は,**無理に直さず報告のみ**にする(報告台帳へ).修正よりも「新規バグを埋め込まないこと」を優先する. -10. **仕様・意図を推測で塗り替えない**:「これは仕様かバグか」の判断が要るものは自動修正しない.コードのコメントやドキュメントが示す意図に明確に反している場合のみ「バグ」と扱い,判断が割れるものは報告に回す. +1. **メインは手を動かさない(二層の分離)**:メイン(制御層)は自分でコード・テストを編集せず,指摘の詳細な裏取り・修正・検証は必ず**項目オーケストレータ**に委ねる.メインが保持するのは台帳・選定・収束判定・報告だけに限る(コンテキストを薄く保ち長時間運転を可能にするため). +2. **項目オーケストレータは逐次1体ずつ**:メインは項目オーケストレータを**並行起動しない**.作業ツリー・`fix/` ブランチを共有するため,同時コミットは競合し破損を招く.1体が完了して返ってから次を起動する. +3. **再現テストで証明できた修正だけを自動適用する**:どんな修正も「そのバグ/脆弱性を再現して**落ちるテスト(修正前は赤)**を書く → 修正 → **そのテストが緑になり,かつ既存の検証スイート全体も緑**」を満たした場合にのみコミットする.再現テストが書けない/緑にできないものは自動修正しない(ゲート②へ). +4. **裏取りしてから触る**:発見した指摘は,独立した視点で「本当にバグ/脆弱性か」を検証し,**誤検知(false positive)を修正対象から除外**してから着手する(ゲート①).確度が低いものは報告のみに落とす. +5. **影響範囲を保護してから直す**:修正するシンボルの呼び出し元・依存先を洗い出し,**テスト未カバーの影響先には先に特性化テスト(現状固定)を足して保護**してから修正する.影響が広すぎて無人で追い切れない場合は自動修正せず報告に落とす(ゲート③). +6. **挙動を戻さない安全網**:修正後に検証スイート(テスト+あればビルド/型チェック/リンタ)が**完全に緑**であること.赤が1つでも出たら,その修正は破棄(revert/stash)して対象を報告に落とす. +7. **専用ブランチのみ**:作業は `fix/` ブランチ上でのみ行う.`main` には絶対にコミットしない. +8. **push/PR しない**:リモート操作は一切しない. +9. **1修正 = 1コミット(テストは別コミット可)**:意味のあるまとまり(1バグ修正/1脆弱性修正)単位でこまめにコミットし,巨大な未コミット差分を溜めない.再現テスト・特性化テストの追加は `[add]`,修正本体は `[fix]` に分けてよい. +10. **除外領域に触れない**:後述の「対象外の領域(除外リスト)」に該当する箇所は修正対象に選ばない. +11. **疑わしきは報告に落とす**:判断に迷う・裏取りで確信が持てない・再現テストが書けない・影響が追い切れない・テストコマンドが特定できない場合は,**無理に直さず報告のみ**にする(報告台帳へ).修正よりも「新規バグを埋め込まないこと」を優先する. +12. **仕様・意図を推測で塗り替えない**:「これは仕様かバグか」の判断が要るものは自動修正しない.コードのコメントやドキュメントが示す意図に明確に反している場合のみ「バグ」と扱い,判断が割れるものは報告に回す. ## 対象外の領域(除外リスト) — 修正対象に選ばない @@ -51,9 +72,9 @@ - ビルド成果物・キャッシュ(`dist/`,`build/`,`.next/`,`coverage/` 等) - ドキュメント全般(`docs/`,`CLAUDE.md`,`.claude/` 配下) -判断に迷うファイルは「触らない(=報告に落とす)」側に倒す(不変条件 8). +判断に迷うファイルは「触らない(=報告に落とす)」側に倒す(不変条件 10). -## セットアップ (Pre-check) — ループ開始前に一度だけ +## セットアップ (Pre-check) — ループ開始前に一度だけ(メインが行う) 1. **観点フィルタと対象範囲の確定**:`$ARGUMENTS` を解釈する. - 先頭トークンが `bug` / `security` / `all` なら**観点フィルタ**とする(省略時は `all`=バグ+脆弱性の両観点).`bug` はバグ観点のみ,`security` は脆弱性観点のみ. @@ -66,9 +87,9 @@ - **テスト実行コマンドとフレームワーク**(必須). - 利用可能なら **ビルド/型チェック/リンタのコマンド**(例: `tsc --noEmit`,`cargo build`,`go build ./...`,`flutter analyze`,`npm run lint` 等). - 以降,**「検証スイート」= テスト+(あれば)ビルド/型チェック/リンタ** をまとめて指す. - - **テストフレームワーク自体が存在せず特定できない場合**は,再現テスト先行(不変条件 1)が成立しないため**自動修正は一切行わず**,発見した指摘を**すべて報告のみ**にするモードで動く(この場合でもループは有用).その旨をセットアップ時に明示する. + - **テストフレームワーク自体が存在せず特定できない場合**は,再現テスト先行(不変条件 3)が成立しないため**自動修正は一切行わず**,発見した指摘を**すべて報告のみ**にするモードで動く(この場合でもループは有用).その旨をセットアップ時に明示し,各項目オーケストレータにも「報告のみモード」を伝える. 4. **ベースラインの確認**:既存テストがある場合は検証スイートを実行し,**開始時点で全て緑**であることを確認する.赤がある場合は,修正の前提(緑からの出発)が崩れているため**停止して報告**する.既存テストが0件でも,フレームワークが特定できていれば「新規に再現テストを書いて流せる」ので開始してよい.ビルド/型チェックがあれば実行して緑を確認する. -5. **台帳の読み込み**:以下のローカル台帳が存在すれば読み込む(無ければ空として扱う).いずれも**ローカルな運用状態であり成果物ではないため `.gitignore` 対象**とする(追跡されていなければ `.gitignore` に追記する). +5. **台帳の読み込み**:以下のローカル台帳が存在すれば読み込む(無ければ空として扱う).いずれも**ローカルな運用状態であり成果物ではないため `.gitignore` 対象**とする(追跡されていなければ `.gitignore` に追記する).メインは各項目オーケストレータへ「既にスキップ/報告済みの指摘(=再処理不要)」の要点を渡し,二重処理を防ぐ. - `.claude/auto-audit-report.md`(報告台帳):自動修正しなかった指摘(要人間対応).**既出は再記録しない**(重複・トークン浪費防止).形式は1行1エントリ,先頭にカテゴリを付ける: - `- [バグ] <箇所> | <重大度: 高/中/低> | <症状/再現手順> | <推定原因> | <提案する修正> | <自動修正しなかった理由> | <日付>` - `- [脆弱性] <箇所> | <重大度: 高/中/低> | <脆弱性の種別と攻撃シナリオ> | <提案する対策> | <自動修正しなかった理由> | <日付>` @@ -76,53 +97,83 @@ - `- [修正] <箇所> | <バグ/脆弱性の内容> | <加えた変更> | <影響範囲(呼び出し元/依存先)> | <推奨する動作確認> | <コミットハッシュ or 概要> | <日付>` - `.claude/auto-audit-skip.md`(スキップ台帳):裏取りで**誤検知**と判断した指摘や,安全に扱えず再挑戦しない対象.**再スキャンで同じものを何度も検証しない**ために記録する.形式は1行1エントリ `- <箇所/指摘> | <理由(誤検知/対処不能 等)> | <日付>`. -## ループ本体 (Loop Body) — 安全に扱える指摘が尽きるまで繰り返す +## ループ本体 (Loop Body) — メインは薄い司令塔として回す -各イテレーションで「指摘を1つ」選び,4 ゲートを1サイクル通す. +メインは自分で指摘を精査せず,**「発見 → 1指摘を選ぶ → 項目オーケストレータに完走委譲 → 返り値を台帳へ」**を繰り返す. -### ステップ 0: 指摘を1つ選ぶ(発見フェーズ) +### ステップ M1: 発見(候補キューの作成) -セットアップで確定した範囲・観点フィルタの中から,発見の観点に沿って**未処理の指摘を1つ**選ぶ. +- セットアップで確定した範囲・観点フィルタの中から,`Explore` エージェント(読み取り専用)に**候補となる指摘を広く洗い出させ**,短い候補キュー(各エントリ=箇所・一言・観点)を作る.**メイン自身はコードを精読しない**(読み込みは `Explore` に委譲し,メインは一覧だけ保持する). +- 発見は多角的に依頼する(1つの探し方に依存しない):バグ観点なら「境界値・null・例外経路」「並行/状態管理」「戻り値・型」,脆弱性観点なら「入力の流れ(source→sink)」「認証認可」「秘匿情報」「依存 CVE」をそれぞれ探させる. +- **報告台帳・スキップ台帳に既出**の候補はキューから除外する(同じものを再処理しない). +- 候補が1つも無ければ**この回は空振り**として完了報告(収束判定)へ. -- 観点フィルタが `all` なら **バグ観点と脆弱性観点の両方**を発見対象にする(重大度の高いものから優先).`bug` / `security` なら該当観点のみ. -- **報告台帳・スキップ台帳に既出**の指摘は選ばない(同じものを再処理しない). -- 発見は多角的に行う(1つの探し方に依存しない):たとえばバグ観点なら「境界値・null・例外経路」「並行/状態管理」「戻り値・型」を別々に,脆弱性観点なら「入力の流れ(source→sink)」「認証認可」「秘匿情報」「依存 CVE」を別々に見る.広く探すため必要に応じて Explore エージェント等に発見を委譲してよい. -- 優先度の目安(高い順):**セキュリティ高**(インジェクション・認可欠如・秘匿漏れ)→ **バグ高**(データ破壊・クラッシュ・誤った計算結果)→ 中 → 低. +### ステップ M2: 1指摘を選ぶ -選べる指摘が無くなったら**ループを終了**し,完了報告へ進む.指摘を1つ選んだらゲート①へ. +- キューから**未処理の指摘を1つ**選ぶ.優先度の目安(高い順):**セキュリティ高**(インジェクション・認可欠如・秘匿漏れ)→ **バグ高**(データ破壊・クラッシュ・誤った計算結果)→ 中 → 低. +- 選んだらステップ M3 へ.キューが空になったら完了報告へ. + +### ステップ M3: 項目オーケストレータを1体起動(1指摘を完走委譲) + +選んだ指摘について,項目オーケストレータを**1体だけ**(逐次)起動する.次を渡す: + +- **対象の指摘**(箇所・観点・`Explore` が挙げた根拠) +- **不変条件(本コマンドの全項目)・4 ゲートの手順**(下記「項目オーケストレータの憲章」) +- **検証スイートのコマンド**(テスト+あればビルド/型チェック/リンタ),**除外リスト**,**観点フィルタ**,**報告のみモードか否か** +- **既存台帳の要点**(既にスキップ/報告済みで再処理不要な指摘) +- **作業ブランチ名**(`fix/...`)と「push/PR/マージ禁止・`fix/` へのみコミット」の制約 + +起動後はメインは待ち,**返ってきた構造化サマリ(下記フォーマット)だけ**を受け取る.下層の詳細をメインが読み返さない(薄さの維持). + +### ステップ M4: 返り値を台帳へ反映・収束カウント + +項目オーケストレータのサマリに従い,メインが台帳を更新する: + +- **fixed**:`.claude/auto-audit-fixed.md` に返ってきた1行を追記(コミットは項目オーケストレータが実施済み). +- **reported**:`.claude/auto-audit-report.md` に返ってきた1行を追記. +- **skipped**:`.claude/auto-audit-skip.md` に返ってきた1行を追記. +- **stopped**(異常):停止条件に該当.ループを止めて報告へ. + +この回で「実質作業をした件数」(自動修正+**新規に**報告/スキップへ記録した件数)を数え,収束判定に使う.反映したらステップ M2 へ戻る(キューに残りがあれば次の指摘).キューが尽きたら,必要なら M1 を1回だけ再実行して取りこぼしを拾い,それでも候補が無ければ完了報告へ. --- -### ゲート①: 裏取り(誤検知を先に殺す) +## 項目オーケストレータの憲章(メインが各指摘とともに渡す) -- 選んだ指摘が**本当にバグ/脆弱性か**を,独立した視点で検証する.「これは誤検知だ」と反証を試みる立場で,コードの実際の挙動・前後の文脈・呼び出され方を確認する(必要なら複数の観点でクロスチェックする). -- **誤検知,または確度が低い(判断が割れる)** → 修正しない.スキップ台帳(`.claude/auto-audit-skip.md`)に「箇所・理由・日付」を記録してステップ 0 へ戻る.確度が低いだけで実害があり得るものは,スキップではなく**報告台帳**に回してもよい(重大度を「低〜中」で). -- **確かにバグ/脆弱性である** → ゲート②へ. +あなたは**1つの指摘を担当する項目オーケストレータ**である.渡された指摘について,以下の 4 ゲートを隔離コンテキストで完走し,最後に**構造化サマリ1通**を返す.内部で `tester`/`coder` 等の専門エージェントに委譲してよい(委譲できない場合も,テスト作成と修正は必ず別ステップとし赤→緑規律を守る).本コマンドの不変条件・除外リストを厳守し,`fix/` ブランチにのみコミットする(push/PR/マージ禁止). + +### ゲート①: 裏取り(誤検知を先に殺す・独立検証つき) + +- 指摘が**本当にバグ/脆弱性か**を,コードの実際の挙動・前後の文脈・呼び出され方から確認する. +- さらに**独立した検証役(別エージェント)に「これは誤検知だ」と反証を試みさせる**(adversarial verify).反証役には「デフォルトで誤検知寄りに判断せよ」と指示し,確度を厳しく見る. +- **誤検知,または確度が低い(反証が成立する/判断が割れる)** → 修正しない.`skipped` として返す(スキップ台帳行:`- <箇所> | <理由(誤検知/対処不能 等)> | <日付>`).確度が低いだけで実害があり得るものは `reported`(重大度「低〜中」)で返してもよい. +- **反証を退けて確かにバグ/脆弱性である** → ゲート②へ. ### ゲート②: 再現テスト先行(修正の正しさを担保する核) -修正の正しさを証明できるかを,**先にテストで確かめる**.tester エージェントに委譲してよい. +修正の正しさを証明できるかを,**先にテストで確かめる**.`tester` に委譲してよい. 1. **再現テストを書く**:その不具合を突く「**修正前は落ちる(赤)**」テストを作る. - バグ観点:バグを踏む入力を与え,**あるべき正しい結果**をアサートする(現状は誤った結果を返すので赤になる). - 脆弱性観点:攻撃シナリオを与え,**安全な挙動(拒否・エスケープ・検証エラー等)**をアサートする(現状は脆弱なので赤になる). 2. **赤を確認する**:修正前の現状コードでこのテストが**実際に落ちる**ことを確認する(=バグ/脆弱性が確かに存在する証拠). - - **落ちない(赤にできない)** → そのバグ/脆弱性は再現できていない.裏取りが甘かった可能性があるため,修正せず**報告台帳**に「再現テストで赤にできなかった」旨とともに記録し,ステップ 0 へ戻る. + - **落ちない(赤にできない)** → 再現できていない.裏取りが甘かった可能性があるため,修正せず `reported` として返す(「再現テストで赤にできなかった」旨を報告行に含める). 3. **正しい挙動が一意に決められるか**を判断する: - **一意に決められる**(例: off-by-one,null 参照,条件反転,パラメタ化で防げる SQL インジェクション,パスの正規化で防げるトラバーサル等) → 再現テストを `[add]` でコミットしてゲート③へ. - - **仕様判断になる/挙動が割れる/テスト基盤の無い UI 層で観測できない** → **自動修正しない**(不変条件 9).再現テストで固定できないため,報告台帳に「提案する修正・自動修正しなかった理由」を記録してステップ 0 へ戻る. + - **仕様判断になる/挙動が割れる/テスト基盤の無い UI 層で観測できない** → **自動修正しない**(不変条件 11).`reported` として返す(「提案する修正・自動修正しなかった理由」を報告行に含める). + - ※ セットアップが「報告のみモード」(テストフレームワーク無し)なら,ここで一律 `reported` として返す. ### ゲート③: 影響範囲(blast radius)の解析と保護 - 修正対象のシンボル(関数/メソッド/クラス)の**呼び出し元・依存先を洗い出す**(参照検索+呼び出し追跡). -- 影響先が**テストで守られていない**箇所 → 先に**特性化テスト(現状の挙動を固定するテスト)**を足して保護する(tester に委譲).追加したら `[add]` でコミットする. - - 特性化テストが緑にできない(挙動を固定できない)ほど影響先が不安定 → 無人で安全に直せないため,修正せず**報告台帳**に記録してステップ 0 へ戻る. -- 影響が**広すぎて無人で追い切れない**(多数のモジュール・外部 I/O・非同期経路にまたがる等) → 自動修正せず報告台帳に記録してステップ 0 へ戻る. +- 影響先が**テストで守られていない**箇所 → 先に**特性化テスト(現状の挙動を固定するテスト)**を足して保護する(`tester` に委譲).追加したら `[add]` でコミットする. + - 特性化テストが緑にできない(挙動を固定できない)ほど影響先が不安定 → 無人で安全に直せないため,修正せず `reported` として返す. +- 影響が**広すぎて無人で追い切れない**(多数のモジュール・外部 I/O・非同期経路にまたがる等) → 自動修正せず `reported` として返す. - 影響先が保護できた → ゲート④の修正実行へ. ### ゲート④: 修正の実行・検証・影響評価つき記録 -#### 修正の実行(coder エージェントに委譲してよい) +#### 修正の実行(`coder` に委譲してよい) - ゲート②で確認したバグ/脆弱性を修正する.**最小の変更**にとどめ,ついでのリファクタや無関係な整形を混ぜない(影響範囲を絞るため). - 修正後,**検証スイート全体**(テスト+あればビルド/型チェック/リンタ)を実行する. @@ -133,7 +184,7 @@ - ゲート②で書いた**再現テストが緑**になった(=直したいものが直った証拠). - **既存の検証スイート全体も緑のまま**(=他を壊していない証拠.ゲート③で足した特性化テストも含む). - **両方満たす** → コミットへ. -- **再現テストが緑にならない/既存スイートに赤が出た** → その修正を破棄(`git checkout -- .` または `git stash`)し,**報告台帳**に「自動修正を試みたが安全に直せなかった/提案する修正」を記録してステップ 0 へ戻る.追加済みの再現テストは残してよい(後の人間修正の助けになる). +- **再現テストが緑にならない/既存スイートに赤が出た** → その修正を破棄(`git checkout -- .` または `git stash`)し,`reported` として返す(「自動修正を試みたが安全に直せなかった/提案する修正」を報告行に含める).追加済みの再現テストは残してよい(後の人間修正の助けになる). #### コミット(`fix/` ブランチへ) @@ -143,13 +194,22 @@ - 脆弱性例: `[fix] 〇〇クエリをパラメタ化して SQL インジェクションを防止` - **push・PR はしない.** -#### 影響評価つき記録(修正済み台帳へ) +#### 影響評価つきサマリを返す(`fixed`) -`.claude/auto-audit-fixed.md` に**1行追記**する(最終報告と,人間が行う動作確認の指示を積み上げるため): +修正済み台帳に積むべき1行を含めて `fixed` を返す: `- [修正] <箇所> | <内容> | <加えた変更> | <影響範囲(呼び出し元/依存先)> | <推奨する動作確認> | <コミット概要> | <日付>` - **推奨する動作確認**には,テストで担保しきれない確認を具体的に書く.特に CLAUDE.md の「手動確認が必要な作業」に該当するもの(**実機・ブラウザでの動作確認,外部サービスの挙動**)は名指しで「ここは自動テストで確認できないので人間が確認してほしい」と記す. -- 記録したらステップ 0 へ戻る. + +### 項目オーケストレータの返却フォーマット(メインはこれだけで台帳を更新できる) + +作業完了後,次の構造化サマリ**だけ**をメインへ返す(詳細な思考ログは返さない=メインを薄く保つ): + +- **結果種別**:`fixed` / `reported` / `skipped` / `stopped` +- **台帳行**:追記すべき1行(どの台帳か= fixed/report/skip も明示).`stopped` の場合は停止理由. +- **コミット**:作成したコミットのタグと要約(`fixed` のとき,`[add]` の再現/特性化テストと `[fix]` を列挙) +- **作業有無**:この指摘で実質作業をしたか(収束カウント用の真偽) +- **一言**:メインが完了報告に使える要約 --- @@ -158,7 +218,7 @@ 以下のいずれかでループを止める. - **選べる指摘(バグ/脆弱性)が尽きた** → **正常終了**. -- 同じ箇所で修正が繰り返し赤になる/検証スイートが途中で失敗するようになった → **異常として停止し報告**. +- 項目オーケストレータが `stopped` を返した/同じ箇所で修正が繰り返し赤になる/検証スイートが途中で失敗するようになった → **異常として停止し報告**. - 未コミットの変更が残ったまま先に進めない状況になった → **停止して報告**. - 不変条件を満たせない状況になった → **停止して報告**. - ユーザーが割り込んで中断した → その時点までの成果(コミット済み)は `fix/` ブランチに残る. @@ -172,7 +232,7 @@ `/loop` で回すと,指摘が尽きた後もウェイクのたびに「対象なし → 即終了」を繰り返し,**無駄にトークンを消費**しうる.これを防ぐため,以下の収束ルールを守る. -- 各イテレーションの開始時に全範囲を再スキャンし,**この回で実施した作業の件数**を数える(自動修正した件数+**新規に**報告台帳/スキップ台帳に記録した件数.既出項目の再確認は作業に数えない). +- 各ウェイクの発見(ステップ M1)で候補を洗い出し,**この回で実施した作業の件数**を数える(自動修正した件数+**新規に**報告台帳/スキップ台帳に記録した件数.既出項目の再確認は作業に数えない). - **作業件数が 0 だった回**を「空振り」とカウントする. - **空振りが 2 回連続**したら,もう安全に拾える指摘は出尽くしたとみなし,**`/loop` 自体を終了する**(次のウェイクをスケジュールしない). - 1 回の空振りで即終了しないのは,「順序やコミットの巡り合わせで一時的に拾えなかっただけ」のケースを 1 回分許容するため. @@ -181,7 +241,7 @@ ## 完了報告 (Reporting) -ループ終了時,ユーザーに以下を報告する(`.claude/auto-audit-fixed.md` / `-report.md` / `-skip.md` を根拠にする). +ループ終了時,メインがユーザーに以下を報告する(`.claude/auto-audit-fixed.md` / `-report.md` / `-skip.md` を根拠にする). - 作業ブランチ名と,適用した観点フィルタ(bug / security / all)・対象範囲 - **自動修正した件数と一覧**(`[fix]` コミット).各項目について「加えた変更・影響範囲・**人間が行うべき推奨動作確認**」を添える(修正済み台帳の内容). diff --git a/.claude/commands/auto-refactor.md b/.claude/commands/auto-refactor.md index 09ae461..8a02eb3 100644 --- a/.claude/commands/auto-refactor.md +++ b/.claude/commands/auto-refactor.md @@ -1,11 +1,11 @@ --- name: auto-refactor model: opus -description: "放置中(無人)に自律的に回り続け,空き時間をコード/ドキュメント/テストの整理に充てるループ.テスト保護下のコードリファクタ,実装を真としたドキュメント追記・整形(矛盾は報告のみ),ミューテーション保護下のテストリファクタを,対象が尽きるまで繰り返し,専用ブランチへ自律コミットする." +description: "放置中(無人)に自律的に回り続け,空き時間をコード/ドキュメント/テストの整理に充てるループ.メインは薄い司令塔として振る舞い,各作業項目を「1項目=1体の項目オーケストレータ」に隔離コンテキストで完走させる(内部で tester/refactorer 等の専門エージェントを使い分ける).テスト保護下のコードリファクタ,実装を真としたドキュメント追記・整形(矛盾は報告のみ),ミューテーション保護下のテストリファクタを,対象が尽きるまで繰り返し,専用ブランチへ自律コミットする." argument-hint: "<対象ディレクトリ/モジュールの絞り込み(省略可)>" --- -あなたは**自律リファクタリング&ドキュメント同期ループのオペレーター**です. +あなたは**自律リファクタリング&ドキュメント同期ループの制御層(オーケストレータ)**です. ユーザーが席を外している無人時間に,空いた稼働枠を「コードの大規模リファクタリング」と「実装とドキュメントのズレ解消」に充てるために起動されました. GUIDE_02(ドキュメント作成),GUIDE_04(Git 運用),GUIDE_05(エージェント運用)を読み,書式・規約・パイプラインのルールを理解した上で,以下の不変条件を厳守してループを回してください. @@ -13,8 +13,27 @@ - **コードリファクタ系**:挙動を変えずにコード品質を改善する(安全網=テスト). - **ドキュメント同期系**:実装を真として `docs/` の記述を実態に近づける.ただし「ドキュメントに無い事項の追記」は自動で行い,「ドキュメントと実装の矛盾」は自動で書き換えず報告のみ(後述). -- **ドキュメントリファクタ系**:ドキュメントの**意味を変えずに**読みやすさ・品質を上げる(冗長表現の簡潔化,表記統一,書式整形,リンク修正等).コードリファクタにおけるテストに相当する「意味が保たれたかの自動検証手段が無い」ため,**情報を削るより残す側に倒す**のが原則(後述の不変条件 9). -- **テストリファクタ系**(前3種が尽きた後のテールフェーズ):肥大化・重複・無意味なテストを整理する.**テストを再実行しても「検証力を弱めた」ことに気づけない**のが根本問題なので,安全網としてミューテーションテストの差分を使う(後述の不変条件 10).使えない場合は構造改善のみ自動・削除/弱体化は提案に落とす. +- **ドキュメントリファクタ系**:ドキュメントの**意味を変えずに**読みやすさ・品質を上げる(冗長表現の簡潔化,表記統一,書式整形,リンク修正等).コードリファクタにおけるテストに相当する「意味が保たれたかの自動検証手段が無い」ため,**情報を削るより残す側に倒す**のが原則(後述の不変条件 11). +- **テストリファクタ系**(前3種が尽きた後のテールフェーズ):肥大化・重複・無意味なテストを整理する.**テストを再実行しても「検証力を弱めた」ことに気づけない**のが根本問題なので,安全網としてミューテーションテストの差分を使う(後述の不変条件 12).使えない場合は構造改善のみ自動・削除/弱体化は提案に落とす. + +## 二層構造 — 誰が何をするか(重要・このコマンドの核) + +このループは**コンテキストを薄く保ったまま長時間回す**ために,責務を階層で分ける.メインは自分でコードやテストを触らず,作業項目1件ごとに専用の作業体を起動し,**その最終報告(構造化サマリ)だけ**を受け取ってコミット結果・要確認リストに反映する.こうするとメインには各項目の詳細な読み込み・思考が積もらず,長時間・大規模でも司令塔のコンテキストが一定に保たれる.一方で専門エージェントの役割分担(独立したテスト作成・リファクタ)はそのまま維持される(サブエージェントの内部コンテキストはメインに戻らないため,両立できる). + +- **① ループ制御層(あなた=メイン)**:セットアップ,台帳の読み書き,発見の起動,作業項目の選定,**項目オーケストレータの起動**,返ってきた構造化サマリの反映(要確認リストへの追記等),収束判定,完了報告のみを行う.**自分でコード・ドキュメント・テストを編集しない.詳細な保護・リファクタ・検証はすべて下層に委ねる**(メインを薄く保つため). +- **② 項目オーケストレータ(1項目=1体)**:メインから渡された**1つの作業項目**について,種別(R/D/DR/T)に応じた処理を隔離コンテキストで**丸ごと完走**する司令塔.内部で下層の専門エージェントを使い分け,最後に**構造化サマリ1通**をメインへ返す.自動で行えたものは自分で `refactor/` ブランチへコミットする. +- **③ 専門エージェント(項目オーケストレータが内部で使う)**: + - **発見**:`Explore`(読み取り専用でリファクタ候補・ドキュメントドリフト・テストスメルを広く洗い出す). + - **特性化テスト**:`tester`. + - **コードリファクタ**:`refactorer`. + - **ドキュメント同期・整形(D/DR)とテストリファクタ(T)**:項目オーケストレータが自身で行ってよい(Dは追記,DRは意味保存の整形,Tは慎重な整理.いずれもテスト/ミューテーションの安全網手順に従う). + - ※ 専門エージェントへの委譲が使えない環境では,項目オーケストレータが同じ手順を自分で行ってよい.ただし**リファクタは必ず「緑のテストで保護された状態」でのみ**行い,安全網の規律を崩さない. + +### 二層で回すときの鉄則 + +- **メインは逐次に1体ずつ**項目オーケストレータを起動する(並行起動しない).同一の作業ツリー・`refactor/` ブランチを共有するため,同時にコミットすると競合するため. +- メインが下層へ渡すのは「1つの作業項目」と,本コマンドの**不変条件・種別ごとの処理手順(R/D/DR/T)・検証コマンド・除外リスト・既存台帳の要点(既にスキップ/記録済みで再処理不要なもの)**.渡した後はメインは待ち,**返ってきたサマリだけ**を信じて反映する(下層の詳細をメインが読み返さない=薄さを保つ). +- 発見(`Explore`)はメイン自身の起動でも,項目オーケストレータ内でもよいが,**メインが自分でコード/ドキュメントを精読して候補を作らない**(読み込みは `Explore` に出す). ## このコマンドの位置づけ(重要) @@ -23,24 +42,26 @@ - **`git push`・PR 作成・マージ・`main` への操作は一切行わない**(マージ可否の判断は後で人間が行う). - 「無人で回り続ける」ことが目的のため,各 Phase での人間確認は挟まない.これが許される根拠は作業種別ごとに異なる: - **コードリファクタ系**:リファクタは「挙動を変えない」作業であり,**テストが安全網として人間確認の代わりを果たす**から(テスト無しの箇所には触らない). - - **ドキュメント同期系**:**追記(事実の補完)に限定**し,かつ**矛盾の自動上書きをしない**から.意図的に書かれた記述を壊さず,バグを仕様に固定しない(後述の不変条件 8). + - **ドキュメント同期系**:**追記(事実の補完)に限定**し,かつ**矛盾の自動上書きをしない**から.意図的に書かれた記述を壊さず,バグを仕様に固定しない(後述の不変条件 10). ## 不変条件 (Invariants) — 1つでも破れそうなら停止する -1. **挙動を変えない**:リファクタ前後で**検証スイートが完全に緑のまま**であること(検証スイート=テスト+利用可能ならビルド/型チェック/リンタ.後述).赤が1つでも出たら,その変更は破棄(revert/stash)して対象をスキップする. -2. **テスト保護下で着手する**:リファクタは必ず**安全網(緑のテスト)がある状態**で行う.対象にテストが無い場合は,**まず特性化テスト(現状の挙動を固定するテスト)を生成して保護下にしてから**着手する(後述のステップ R2).テストフレームワーク自体が特定できない/生成テストを流せない箇所は対象にしない. -3. **専用ブランチのみ**:作業は `refactor/` ブランチ上でのみ行う.`main` には絶対にコミットしない. -4. **push/PR しない**:リモート操作は一切しない. -5. **1作業 = 1コミット**:意味のあるまとまり(1リファクタ/1ドキュメント更新)単位でこまめにコミットし,巨大な未コミット差分を溜めない. -6. **除外領域に触れない**:後述の「対象外の領域(除外リスト)」に該当する箇所はリファクタ対象に選ばない. -7. **疑わしきは停止**:判断に迷う・安全網が確認できない・テストコマンドが特定できない場合は,無理に進めず停止して状況を報告する. -8. **ドキュメントは「追記は自動・矛盾は報告のみ」**:実装を真としてよいのは**ドキュメントに記載が無い事項の追記**だけ.ドキュメントと実装が**食い違う**箇所は**自動で書き換えず**,要確認リストに記録して報告する(矛盾は実装バグの兆候かもしれず,無人で塗り潰すと検出機会を失うため).`docs/01_GUIDE/`(規約),`CLAUDE.md`,`docs/03_PLAN/`・`docs/PROGRESS.md`(計画・進捗)は実装を真とする対象に**含めない**. -9. **ドキュメントリファクタは「意味保存」が絶対条件**:自動で行ってよいのは**意味・情報を保ったままの品質改善**だけ.具体的には ①無損失整形(表記揺れの統一・書式/見出し/表の整形・リンクや参照の修正・明らかなタイポ)と,②**意味を保った簡潔化・重複の集約**(冗長な言い回しを短くする,同一内容の重複を1か所に集約して他はリンクする).**消してはいけないもの**=事実・決定事項・設計判断(なぜその案にしたか)・失敗パターン・具体的な制約や閾値.これらが落ちる「陳腐化記述の削除」や「大規模な再編」は自動で行わず,要確認リストに**提案として記録**する.意味保存を自動検証する手段は無いため,迷ったら削らない(残す側に倒す). -10. **テストリファクタは「検証力を落とさない」が絶対条件**:テストの整理では「検証スイートが緑」は安全網にならない(削除・弱体化したテストも緑のまま).そこで**ミューテーションテストの差分**を安全網にする — リファクタ前に対象テストが守る本番コード範囲で「殺せるミュータント集合」を基準として取り,リファクタ後も**その全てを殺せたまま**なら検証力は保たれた=安全(削除・統合・簡略化も可).1つでも生存に転じたら検証力低下なので破棄する.ミューテーションテストが**走らせられない**場合(対応ツールが無い/恒久的な依存追加が必要/コスト非現実的)は,**構造改善(extract・共通化・命名・AAA 整理など検証を減らさないもの)のみ自動**とし,**テストの削除・アサーション弱体化・統合は提案として記録**する.テストコードへの自動編集はこのテストリファクタ処理(T)でのみ行う(コードリファクタ R はテストを触らない). +1. **メインは手を動かさない(二層の分離)**:メイン(制御層)は自分でコード・ドキュメント・テストを編集せず,詳細な保護・リファクタ・検証は必ず**項目オーケストレータ**に委ねる.メインが保持するのは台帳・選定・収束判定・報告だけに限る(コンテキストを薄く保ち長時間運転を可能にするため). +2. **項目オーケストレータは逐次1体ずつ**:メインは項目オーケストレータを**並行起動しない**.作業ツリー・`refactor/` ブランチを共有するため,同時コミットは競合し破損を招く.1体が完了して返ってから次を起動する. +3. **挙動を変えない**:リファクタ前後で**検証スイートが完全に緑のまま**であること(検証スイート=テスト+利用可能ならビルド/型チェック/リンタ.後述).赤が1つでも出たら,その変更は破棄(revert/stash)して対象をスキップする. +4. **テスト保護下で着手する**:リファクタは必ず**安全網(緑のテスト)がある状態**で行う.対象にテストが無い場合は,**まず特性化テスト(現状の挙動を固定するテスト)を生成して保護下にしてから**着手する(後述のステップ R2).テストフレームワーク自体が特定できない/生成テストを流せない箇所は対象にしない. +5. **専用ブランチのみ**:作業は `refactor/` ブランチ上でのみ行う.`main` には絶対にコミットしない. +6. **push/PR しない**:リモート操作は一切しない. +7. **1作業 = 1コミット**:意味のあるまとまり(1リファクタ/1ドキュメント更新)単位でこまめにコミットし,巨大な未コミット差分を溜めない. +8. **除外領域に触れない**:後述の「対象外の領域(除外リスト)」に該当する箇所はリファクタ対象に選ばない. +9. **疑わしきは停止**:判断に迷う・安全網が確認できない・テストコマンドが特定できない場合は,無理に進めず停止して状況を報告する(項目オーケストレータは当該項目を `skipped`/`stopped` として返す). +10. **ドキュメントは「追記は自動・矛盾は報告のみ」**:実装を真としてよいのは**ドキュメントに記載が無い事項の追記**だけ.ドキュメントと実装が**食い違う**箇所は**自動で書き換えず**,要確認リストに記録して報告する(矛盾は実装バグの兆候かもしれず,無人で塗り潰すと検出機会を失うため).`docs/01_GUIDE/`(規約),`CLAUDE.md`,`docs/03_PLAN/`・`docs/PROGRESS.md`(計画・進捗)は実装を真とする対象に**含めない**. +11. **ドキュメントリファクタは「意味保存」が絶対条件**:自動で行ってよいのは**意味・情報を保ったままの品質改善**だけ.具体的には ①無損失整形(表記揺れの統一・書式/見出し/表の整形・リンクや参照の修正・明らかなタイポ)と,②**意味を保った簡潔化・重複の集約**(冗長な言い回しを短くする,同一内容の重複を1か所に集約して他はリンクする).**消してはいけないもの**=事実・決定事項・設計判断(なぜその案にしたか)・失敗パターン・具体的な制約や閾値.これらが落ちる「陳腐化記述の削除」や「大規模な再編」は自動で行わず,要確認リストに**提案として記録**する.意味保存を自動検証する手段は無いため,迷ったら削らない(残す側に倒す). +12. **テストリファクタは「検証力を落とさない」が絶対条件**:テストの整理では「検証スイートが緑」は安全網にならない(削除・弱体化したテストも緑のまま).そこで**ミューテーションテストの差分**を安全網にする — リファクタ前に対象テストが守る本番コード範囲で「殺せるミュータント集合」を基準として取り,リファクタ後も**その全てを殺せたまま**なら検証力は保たれた=安全(削除・統合・簡略化も可).1つでも生存に転じたら検証力低下なので破棄する.ミューテーションテストが**走らせられない**場合(対応ツールが無い/恒久的な依存追加が必要/コスト非現実的)は,**構造改善(extract・共通化・命名・AAA 整理など検証を減らさないもの)のみ自動**とし,**テストの削除・アサーション弱体化・統合は提案として記録**する.テストコードへの自動編集はこのテストリファクタ処理(T)でのみ行う(コードリファクタ R はテストを触らない). ## 対象外の領域(除外リスト) — コードリファクタの対象に選ばない -以下は無人で触ると事故りやすく,かつリファクタの価値が薄いため,**コードリファクタの対象に選ばない**.ステップ 0 の選定時に必ず除外する. +以下は無人で触ると事故りやすく,かつリファクタの価値が薄いため,**コードリファクタの対象に選ばない**.発見・選定時に必ず除外する. - 自動生成コード(コードジェネレータ出力,`*.g.dart`,`*.pb.go`,スナップショット等) - 依存・サードパーティ(`node_modules/`,`vendor/`,`.dart_tool/`,`target/`,ベンダリングされた外部ソース) @@ -51,11 +72,11 @@ - ドキュメント全般(`docs/`,`CLAUDE.md`,`.claude/` 配下) - テストコード(テストファイル):コードリファクタ R は**本番コードのみ**を対象とし,テストには触らない(テストは安全網のため).テストの整理は専用の**テストリファクタ処理 (T)** で扱う. -※ ドキュメントはコードリファクタの対象にはしないが,**ドキュメント同期系の処理(D)/ドキュメントリファクタ系の処理(DR)**では `docs/02_ENV/`・`docs/04_SPEC/`・`docs/05_TECH/` を更新対象とする(不変条件 8・9 の範囲で).`docs/01_GUIDE/`・`CLAUDE.md`・`.claude/`・進捗系(`docs/03_PLAN/`・`docs/PROGRESS.md`)は自動編集の対象に**含めない**. +※ ドキュメントはコードリファクタの対象にはしないが,**ドキュメント同期系の処理(D)/ドキュメントリファクタ系の処理(DR)**では `docs/02_ENV/`・`docs/04_SPEC/`・`docs/05_TECH/` を更新対象とする(不変条件 10・11 の範囲で).`docs/01_GUIDE/`・`CLAUDE.md`・`.claude/`・進捗系(`docs/03_PLAN/`・`docs/PROGRESS.md`)は自動編集の対象に**含めない**. -判断に迷うファイルは「触らない」側に倒す(不変条件 7). +判断に迷うファイルは「触らない」側に倒す(不変条件 9). -## セットアップ (Pre-check) — ループ開始前に一度だけ +## セットアップ (Pre-check) — ループ開始前に一度だけ(メインが行う) 1. **対象範囲の確認**:`$ARGUMENTS` に絞り込み(ディレクトリ/モジュール)があればその範囲に限定する.無ければプロジェクト全体を対象候補とする. 2. **ブランチの準備**: @@ -69,33 +90,63 @@ - テストが1つも無くても,**テストフレームワークが特定でき新規テストを書いて流せる**なら開始してよい(無い箇所は特性化テストを生成して保護下にする). - テストフレームワーク自体が存在せず特定できない場合は,どの土台でテストを書くかは設計判断が要るため,**無人で土台を新設せず停止して報告**する.ただしこの場合でも**ドキュメント同期系(D)は実行してよい**(テスト不要のため). 4. **ベースラインの確認**:既存テストがある場合は検証スイートを実行し,**開始時点で全て緑**であることを確認する.赤がある場合は,リファクタの前提(緑からの出発)が崩れているため**停止して報告**する.既存テストが0件の場合はテスト実行を省略してよいが,ビルド/型チェックがあれば実行して緑を確認する. -5. **台帳の読み込み**:以下のローカル台帳が存在すれば読み込む(無ければ空として扱う).いずれも**ローカルな運用状態であり成果物ではないため `.gitignore` 対象**とする(追跡されていなければ `.gitignore` に追記する). +5. **台帳の読み込み**:以下のローカル台帳が存在すれば読み込む(無ければ空として扱う).いずれも**ローカルな運用状態であり成果物ではないため `.gitignore` 対象**とする(追跡されていなければ `.gitignore` に追記する).メインは各項目オーケストレータへ「既にスキップ/記録済みの項目(=再処理不要)」の要点を渡し,二重処理を防ぐ. - `.claude/auto-refactor-skip.md`(スキップ台帳):過去に安全に扱えなかったリファクタ対象.今回も**再挑戦せず除外**する.形式は1行1エントリ `- <対象> | <理由> | <日付>`. - `.claude/auto-refactor-doc-review.md`(ドキュメント要確認リスト):過去に検出した「ドキュメントと実装の矛盾」および「自動では行わない簡潔化・再編の提案」.**既出の項目は再記録しない**(重複・トークン浪費防止).形式は1行1エントリ,先頭にカテゴリを付ける: - 矛盾: `- [矛盾] <箇所> | <ドキュメントの記述> | <実装の挙動> | <推定原因> | <日付>` - 提案: `- [提案] <箇所> | <提案内容(どう簡潔化/再編したいか)> | <自動で行わない理由> | <日付>` - `.claude/auto-refactor-test-review.md`(テスト要確認リスト):テストリファクタで「自動では行わなかった削除・統合・弱体化の提案」.**既出は再記録しない**.形式は1行1エントリ `- [提案] <対象テスト> | <提案内容> | <自動で行わない理由(ミューテーション未実施 等)> | <日付>`. -## ループ本体 (Loop Body) — 安全な作業が尽きるまで繰り返す +## ループ本体 (Loop Body) — メインは薄い司令塔として回す -各イテレーションで「作業項目を1つ」選び,種別に応じた処理を1サイクル実行する. +メインは自分で対象を精査せず,**「発見 → 1項目を選ぶ → 項目オーケストレータに完走委譲 → 返り値を反映」**を繰り返す. -### ステップ 0: 作業項目を1つ選ぶ +### ステップ M1: 発見(候補キューの作成) -セットアップで確定した範囲の中から,次のいずれかの作業項目を**1つ**選ぶ. +- セットアップで確定した範囲の中から,`Explore` エージェント(読み取り専用)に**候補となる作業項目を広く洗い出させ**,短い候補キュー(各エントリ=種別 R/D/DR/T・箇所・一言)を作る.**メイン自身はコード/ドキュメントを精読しない**(読み込みは `Explore` に委譲し,メインは一覧だけ保持する). + - コード(R):重複コード,過度に長い関数,命名の乱れ,デッドコード,複雑な構造(除外リスト・スキップ台帳を除く). + - ドキュメント(D):`docs/02_ENV`・`04_SPEC`・`05_TECH` と実装の**記載漏れ/矛盾**(要確認リスト既出の矛盾は除外). + - ドキュメント整形(DR):同ドキュメント群の冗長・表記揺れ・書式乱れ・重複・リンク切れ. + - テスト(T):肥大化・重複・無意味なテスト(test smells). +- **報告台帳・スキップ台帳・要確認リストに既出**の候補はキューから除外する. +- 候補が1つも無ければ**この回は空振り**として完了報告(収束判定)へ. -- **リファクタ対象(コード)**:除外リスト・スキップ台帳に該当しないもの.優先度の目安(高い順):重複コードの集約 → 過度に長い関数の分割 → 命名の改善 → デッドコード除去 → 構造の単純化. → 選んだら「リファクタ処理 (R)」へ. -- **ドキュメント・ドリフト項目**:`docs/02_ENV/`・`docs/04_SPEC/`・`docs/05_TECH/` と実装を突き合わせ,**記載漏れ**または**矛盾**がある箇所.要確認リストに既出の矛盾は除外する. → 選んだら「ドキュメント同期処理 (D)」へ. -- **ドキュメントリファクタ項目**:`docs/02_ENV/`・`docs/04_SPEC/`・`docs/05_TECH/` の中で,**意味を変えずに**改善できる箇所(冗長な言い回し,表記揺れ,書式の乱れ,重複,リンク切れ等). → 選んだら「ドキュメントリファクタ処理 (DR)」へ. +### ステップ M2: 1項目を選ぶ(種別の優先順位を守る) -上記**3種すべてに作業項目が無い場合に限り**,テールフェーズとして次を検討する: +- **前3種(R/D/DR)を優先**し,それらが尽きた後にだけ**テストリファクタ(T)**を選ぶ(Tは最も安全網が特殊で危険なため最後に回す). +- 同種内の優先度(コードR):重複コードの集約 → 過度に長い関数の分割 → 命名の改善 → デッドコード除去 → 構造の単純化. +- 選んだらステップ M3 へ.4種すべてに項目が無くなったら完了報告へ. -- **テストリファクタ項目**:肥大化・重複・無意味なテスト(test smells)の整理対象. → 選んだら「テストリファクタ処理 (T)」へ.(前3種が残っている間は選ばない=最後に回す) +### ステップ M3: 項目オーケストレータを1体起動(1項目を完走委譲) -これら**4種すべて**に作業項目が無くなったら**ループを終了**し,完了報告へ進む. +選んだ作業項目について,項目オーケストレータを**1体だけ**(逐次)起動する.次を渡す: + +- **対象の作業項目**(種別 R/D/DR/T・箇所・`Explore` が挙げた根拠) +- **不変条件(本コマンドの全項目)・種別ごとの処理手順**(下記「項目オーケストレータの憲章」) +- **検証スイートのコマンド**(テスト+あればビルド/型チェック/リンタ),**除外リスト** +- **既存台帳の要点**(既にスキップ/記録済みで再処理不要な項目) +- **作業ブランチ名**(`refactor/...`)と「push/PR/マージ禁止・`refactor/` へのみコミット」の制約 + +起動後はメインは待ち,**返ってきた構造化サマリ(下記フォーマット)だけ**を受け取る.下層の詳細をメインが読み返さない(薄さの維持). + +### ステップ M4: 返り値を反映・収束カウント + +項目オーケストレータのサマリに従い,メインが反映する: + +- **done**:コミットは項目オーケストレータが実施済み(`[add]`/`[clean]`/`[update]`).メインは件数・概要を完了報告用に記録する. +- **doc-review**:`.claude/auto-refactor-doc-review.md` に返ってきた1行(`[矛盾]`/`[提案]`)を追記. +- **test-review**:`.claude/auto-refactor-test-review.md` に返ってきた1行(`[提案]`)を追記. +- **skipped**:`.claude/auto-refactor-skip.md` に返ってきた1行を追記. +- **stopped**(異常):停止条件に該当.ループを止めて報告へ. + +この回で「実質作業をした件数」(コードリファクタ+特性化テスト生成+ドキュメント追記+ドキュメントリファクタ+テストリファクタ+**新規に記録した**矛盾・提案)を数え,収束判定に使う.反映したらステップ M2 へ戻る.キューが尽きたら,必要なら M1 を1回だけ再実行して取りこぼしを拾い,それでも候補が無ければ完了報告へ. --- +## 項目オーケストレータの憲章(メインが各項目とともに渡す) + +あなたは**1つの作業項目を担当する項目オーケストレータ**である.渡された項目の種別(R/D/DR/T)に応じて,以下の処理を隔離コンテキストで完走し,最後に**構造化サマリ1通**を返す.内部で `tester`/`refactorer` に委譲してよい(委譲できない場合も安全網の手順を自分で守る).本コマンドの不変条件・除外リストを厳守し,`refactor/` ブランチにのみコミットする(push/PR/マージ禁止). + ### リファクタ処理 (R) #### ステップ R1: 保護状態の確認 @@ -104,43 +155,43 @@ - **保護下にある** → ステップ R3 へ. - **テストが無い** → ステップ R2(特性化テストの生成)へ. -#### ステップ R2: 特性化テストの生成(テストが無い対象のみ/tester エージェントに委譲) +#### ステップ R2: 特性化テストの生成(テストが無い対象のみ/`tester` に委譲) -テストが無い対象は,まず安全網を作る.tester エージェントに以下を委譲する: +テストが無い対象は,まず安全網を作る.`tester` に以下を委譲する: 「次の対象に対し,**現状の挙動をそのまま固定する特性化テスト(characterization test)**を作成してください.理想の仕様ではなく,**今のコードが実際に返す挙動**を観測してアサーションに落とすこと(バグも含めて現状を固定する).境界値・主要な分岐・代表的な入出力を網羅してください.作成後にテストを実行し,**現状コードで全て緑**になることを確認してください.緑にできない(=挙動が固定できない)場合は,その旨を報告してください. -対象: {ステップ 0 で選んだ対象} -テストコマンド: {セットアップで特定したコマンド}」 +対象: {渡された対象} +テストコマンド: {渡されたコマンド}」 -- tester の報告と実テスト結果を確認する. - - **生成テストが現状コードで全て緑** → これを安全網として `git add` し,タグ **`[add]`** でコミットする(例: `[add] 〇〇モジュールに特性化テストを追加`).**この時点ではまだリファクタしない**.コミット後,この対象を「保護下になった」状態でステップ R3 へ進む(同一イテレーション内で続けてよい). - - **緑にできなかった/挙動が固定できない** → この対象は安全に触れないため変更を破棄し,**スキップ台帳(`.claude/auto-refactor-skip.md`)に「対象・理由・日付」を追記**してからステップ 0 へ戻る(以後のイテレーション・ウェイクで再選択しない). +- `tester` の報告と実テスト結果を確認する. + - **生成テストが現状コードで全て緑** → これを安全網として `git add` し,タグ **`[add]`** でコミットする(例: `[add] 〇〇モジュールに特性化テストを追加`).**この時点ではまだリファクタしない**.コミット後,この対象を「保護下になった」状態でステップ R3 へ進む. + - **緑にできなかった/挙動が固定できない** → この対象は安全に触れないため変更を破棄し,`skipped` として返す(スキップ台帳行:`- <対象> | <理由> | <日付>`). #### ステップ R3: リファクタ前の緑確認 - 検証スイート(テスト+あればビルド/型チェック/リンタ)を実行し,緑であることを確認する(ベースライン/生成した特性化テストの再確認). -#### ステップ R4: リファクタリング実行(refactorer エージェントに委譲) +#### ステップ R4: リファクタリング実行(`refactorer` に委譲) -refactorer エージェントに以下を委譲する: +`refactorer` に以下を委譲する: 「次の対象を,挙動を変えずにリファクタリングしてください.テストを安全網とし,リファクタ後に検証スイートを再実行して**全て緑のまま**であることを必ず確認してください.緑にできない場合は変更を破棄し,その旨を報告してください. -対象: {ステップ 0 で選んだ対象} -検証コマンド: {セットアップで特定したテスト+ビルド/型チェック/リンタのコマンド}」 +対象: {渡された対象} +検証コマンド: {渡されたテスト+ビルド/型チェック/リンタのコマンド}」 #### ステップ R5: リファクタ後の緑確認 -- refactorer の報告と実際の検証スイート(テスト+あればビルド/型チェック/リンタ)の結果を確認する. +- `refactorer` の報告と実際の検証スイートの結果を確認する. - **全て緑** → ステップ R6 へ. -- **赤がある/緑にできなかった** → その変更を破棄(`git checkout -- .` または `git stash`)し,**スキップ台帳に「対象・理由・日付」を追記**してステップ 0 へ戻る(同じ対象は再選択しない). +- **赤がある/緑にできなかった** → その変更を破棄(`git checkout -- .` または `git stash`)し,`skipped` として返す(スキップ台帳行を含める).同じ対象は再選択されない. #### ステップ R6: 専用ブランチへコミット - `git add` で当該変更をステージングする(`.env`・クレデンシャル・ビルド成果物は含めない). - GUIDE_04 のコミット書式に従い,タグ **`[clean]`** でコミットする(例: `[clean] 重複した入力バリデーションを共通関数に集約`). -- **push・PR はしない.** ステップ 0 へ戻る. +- **push・PR はしない.** `done` として返す. --- @@ -160,13 +211,13 @@ - コミット(GUIDE_04 準拠): - 新規セクション/新規ドキュメントファイルの追加 → タグ **`[add]`**(例: `[add] 04_SPEC に〇〇APIの仕様を追記`). - 既存記述への事実追記・補足 → タグ **`[update]`**(例: `[update] 02_ENV に新規環境変数 FOO を追記`). -- コミット後,ステップ 0 へ戻る. +- `done` として返す. #### ステップ D3: 矛盾は報告のみ(自動で書き換えない) -- **ドキュメントは書き換えない**(不変条件 8).矛盾は実装バグの兆候かもしれず,無人で「実装に合わせて」塗り潰すと検出機会を失う. -- `.claude/auto-refactor-doc-review.md`(要確認リスト)に**1行追記**する: `- [矛盾] <箇所> | <ドキュメントの記述> | <実装の挙動> | <推定原因(仕様が古い/実装バグの疑い 等)> | <日付>`. -- **既に記録済みの矛盾は再記録しない**.記録(または既出確認)したらステップ 0 へ戻る. +- **ドキュメントは書き換えない**(不変条件 10).矛盾は実装バグの兆候かもしれず,無人で「実装に合わせて」塗り潰すと検出機会を失う. +- `doc-review` として返す(要確認リスト行:`- [矛盾] <箇所> | <ドキュメントの記述> | <実装の挙動> | <推定原因(仕様が古い/実装バグの疑い 等)> | <日付>`). +- **既に記録済みの矛盾は再記録しない**(既出なら「作業なし」で返す). --- @@ -174,7 +225,7 @@ #### ステップ DR1: 改善方針の判定(意味保存が絶対条件) -選んだ箇所について,意味・情報を保ったまま改善できるかを判定する(不変条件 9). +選んだ箇所について,意味・情報を保ったまま改善できるかを判定する(不変条件 11). - **無損失整形 or 意味を保った簡潔化/集約** → ステップ DR2 へ(自動で実施). - 例:冗長な言い回しを短くする,表記揺れ・カタカナ/英字のゆれを統一,見出しレベル・表・コードフェンス・箇条書きの整形,重複説明を1か所に集約して他はリンク,切れたリンクや古い参照(GUIDE_03 命名)を実在パスに修正,明らかなタイポ修正. @@ -184,18 +235,18 @@ - 該当ドキュメントを,**意味・決定事項・設計判断・失敗パターン・具体的制約を一切落とさずに**整形・簡潔化する.GUIDE_02(ドキュメント作成)・GUIDE_03(命名)に従う. - 迷ったら削らない(残す側に倒す).少しでも情報が落ちる懸念があれば DR3 に回す. -- GUIDE_04 のコミット書式に従い,タグ **`[clean]`** でコミットする(例: `[clean] 04_SPEC の冗長な説明を簡潔化`).コミット後,ステップ 0 へ戻る. +- GUIDE_04 のコミット書式に従い,タグ **`[clean]`** でコミットする(例: `[clean] 04_SPEC の冗長な説明を簡潔化`).`done` として返す. #### ステップ DR3: 削除・大規模再編は提案のみ(自動で行わない) -- 本文は書き換えない.`.claude/auto-refactor-doc-review.md` に**1行追記**する: `- [提案] <箇所> | <提案内容(どう簡潔化/再編したいか)> | <自動で行わない理由(情報が落ちうる 等)> | <日付>`. -- **既出の提案は再記録しない**.記録(または既出確認)したらステップ 0 へ戻る. +- 本文は書き換えない.`doc-review` として返す(要確認リスト行:`- [提案] <箇所> | <提案内容(どう簡潔化/再編したいか)> | <自動で行わない理由(情報が落ちうる 等)> | <日付>`). +- **既出の提案は再記録しない**(既出なら「作業なし」で返す). --- ### テストリファクタ処理 (T) — 前3種が尽きた後のテールフェーズ -テストコードを整理する.**「検証スイートが緑」は安全網にならない**(削除・弱体化したテストも緑のまま)ため,ミューテーションテストの差分を安全網とする(不変条件 10). +テストコードを整理する.**「検証スイートが緑」は安全網にならない**(削除・弱体化したテストも緑のまま)ため,ミューテーションテストの差分を安全網とする(不変条件 12). #### ステップ T1: ミューテーション安全網が使えるか判定 @@ -203,7 +254,7 @@ - その範囲に対し,**ミューテーションテストを一時的に走らせられるか**を判定する: - 言語/スタックに対応するツール(例: JS/TS の Stryker,Python の `mutmut`/`cosmic-ray`,Java の PITest,Go の `go-mutesting` 等)を,**依存を恒久追加せず**に実行できるか(`npx`/`uvx`/`pipx run` 等のエフェメラル実行を優先). - **走らせられる** → ステップ T2(ミューテーション保護下の全自動)へ. - - **走らせられない**(対応ツールが無い/恒久的な依存・設定の追加が必要/リポ規模的にコストが非現実的) → ステップ T3(構造改善のみ自動)へ.恒久セットアップが要る場合は**無人で導入せず**,テスト要確認リストに「ミューテーションテスト導入の提案」を記録する. + - **走らせられない**(対応ツールが無い/恒久的な依存・設定の追加が必要/リポ規模的にコストが非現実的) → ステップ T3(構造改善のみ自動)へ.恒久セットアップが要る場合は**無人で導入せず**,`test-review` として「ミューテーションテスト導入の提案」を返す. - コスト対策として,ミューテーションは**対象テストが守る本番コード範囲に限定**して実行する(リポ全体には走らせない). #### ステップ T2: ミューテーション保護下のテストリファクタ(全自動) @@ -213,16 +264,26 @@ 3. **検証**: - 通常の検証スイートが**緑**であること,かつ - ミューテーションを再実行し,**baseline で殺せていたミュータントが1つも生存に転じていない**こと(=検証力が落ちていない). - - 両方満たす → タグ **`[clean]`** でコミット(例: `[clean] 重複した〇〇のテストを集約`).**一時的に作成/設定したミューテーション関連の成果物はコミットに含めない**(後始末する). - - 1つでも生存に転じた/検証スイートが赤 → その変更を破棄(revert/stash)し,検証力が落ちる変更は行わない(必要ならテスト要確認リストに `[提案]` として記録). -4. ステップ 0 へ戻る. + - 両方満たす → タグ **`[clean]`** でコミット(例: `[clean] 重複した〇〇のテストを集約`).**一時的に作成/設定したミューテーション関連の成果物はコミットに含めない**(後始末する).`done` として返す. + - 1つでも生存に転じた/検証スイートが赤 → その変更を破棄(revert/stash)し,検証力が落ちる変更は行わない(必要なら `test-review` として `[提案]` を返す). #### ステップ T3: ミューテーションが使えない場合(構造改善のみ自動) - **自動でよいのは検証を減らさない構造改善のみ**:共通セットアップの extract,ヘルパー/ビルダーへの集約,テーブル駆動化(パラメタライズ),命名・AAA 構造の整理など.アサーションの数・強さを変えないこと. - - 実施後に検証スイートが緑であることを確認 → タグ **`[clean]`** でコミット. -- **テストの削除・アサーション弱体化・検証が減りうる統合は自動で行わない**.`.claude/auto-refactor-test-review.md` に `- [提案] <対象テスト> | <提案内容> | <自動で行わない理由> | <日付>` を**1行追記**(既出は再記録しない). -- ステップ 0 へ戻る. + - 実施後に検証スイートが緑であることを確認 → タグ **`[clean]`** でコミット.`done` として返す. +- **テストの削除・アサーション弱体化・検証が減りうる統合は自動で行わない**.`test-review` として返す(要確認リスト行:`- [提案] <対象テスト> | <提案内容> | <自動で行わない理由> | <日付>`.既出は再記録しない). + +--- + +### 項目オーケストレータの返却フォーマット(メインはこれだけで反映できる) + +作業完了後,次の構造化サマリ**だけ**をメインへ返す(詳細な思考ログは返さない=メインを薄く保つ): + +- **結果種別**:`done` / `doc-review` / `test-review` / `skipped` / `stopped` +- **コミット**:作成したコミットのタグと要約(`done` のとき,`[add]`/`[clean]`/`[update]` を列挙) +- **リスト行**:`doc-review`/`test-review`/`skipped` のとき,該当台帳へ追記すべき1行.`stopped` の場合は停止理由. +- **作業有無**:この項目で実質作業をしたか(収束カウント用の真偽) +- **一言**:メインが完了報告に使える要約(種別・対象・内容) --- @@ -231,7 +292,7 @@ 以下のいずれかでループを止める. - **4種すべて(コードリファクタ/ドキュメント同期/ドキュメントリファクタ/テストリファクタ)の作業項目が尽きた** → **正常終了**. -- 同じ箇所で繰り返しテストが赤になる/テストコマンドが途中で失敗するようになった → **異常として停止し報告**. +- 項目オーケストレータが `stopped` を返した/同じ箇所で繰り返しテストが赤になる/テストコマンドが途中で失敗するようになった → **異常として停止し報告**. - 不変条件を満たせない状況になった → **停止して報告**. - ユーザーが割り込んで中断した → その時点までの成果(コミット済み)は `refactor/` ブランチに残る. @@ -244,7 +305,7 @@ `/loop` で回すと,作業が尽きた後もウェイクのたびに「対象なし → 即終了」を繰り返し,**無駄にトークンを消費**しうる.これを防ぐため,以下の収束ルールを守る. -- 各イテレーションの開始時に全範囲を再スキャンし,**この回で実施した作業の件数**を数える(コードリファクタ+特性化テスト生成+ドキュメント追記+ドキュメントリファクタ+テストリファクタ+**新規に記録した**矛盾・提案.既出項目の再確認は作業に数えない). +- 各ウェイクの発見(ステップ M1)で候補を洗い出し,**この回で実施した作業の件数**を数える(コードリファクタ+特性化テスト生成+ドキュメント追記+ドキュメントリファクタ+テストリファクタ+**新規に記録した**矛盾・提案.既出項目の再確認は作業に数えない). - **作業件数が 0 だった回**を「空振り」とカウントする. - **空振りが 2 回連続**したら,もう安全に拾える作業は出尽くしたとみなし,**`/loop` 自体を終了する**(次のウェイクをスケジュールしない). - 1 回の空振りで即終了しないのは,「順序やコミットの巡り合わせで一時的に拾えなかっただけ」のケースを 1 回分許容するため. @@ -253,7 +314,7 @@ ## 完了報告 (Reporting) -ループ終了時,ユーザーに以下を報告する. +ループ終了時,メインがユーザーに以下を報告する. - 作業ブランチ名 - 追加した特性化テストの件数(= `[add]` のテストコミット数)と対象モジュールの一覧