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