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/.claude/commands/set-mode.md b/.claude/commands/set-mode.md new file mode 100644 index 0000000..8ac83b2 --- /dev/null +++ b/.claude/commands/set-mode.md @@ -0,0 +1,171 @@ +--- +name: set-mode +model: inherit +description: "開発モード(solo / team)を切り替える.チーム層ファイル・settings.json・CLAUDE.md・.claude/project-mode を一括で整合させる." +argument-hint: "" +--- + +あなたは開発モード切替の担当者です. +プロジェクトの開発モードを **solo(個人開発)↔ team(チーム開発)** で切り替え,モードに紐づくファイル一式を過不足なく整合させてください. + +`/sync-template` は「テンプレートの版を追従する」道具であり,モード遷移(ファイルの追加・削除,CLAUDE.md/settings.json の書き換え)は行いません.本コマンドがその遷移を担います. + +実行環境: bash(Git Bash または Unix シェル)が必要.`mktemp`, `rm -rf`, `cp`, シェル変数展開を使用する. + +テンプレート URL: `https://github.com/rintoHasegawa/programming-template.git` + +## チーム層ファイル (Team-layer Files) + +モードに応じて配置/削除する対象.`/sync-template` の「モード依存ファイル」と同一のリストに保つこと. + +``` +docs/01_GUIDE/GUIDE_06_チーム開発ルール.md +docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md +.claude/commands/task-create.md +.claude/commands/task-start.md +.claude/commands/task-handoff.md +.claude/hooks/check_sync.sh +``` + +## ステップ 1: 事前確認 (Pre-check) + +1. `git status` でワーキングツリーがクリーンか確認する.未コミットの変更がある場合は「⚠ コミットされていない変更があります.先にコミットまたは stash してから再実行してください.」と伝えて中断する. +2. `$ARGUMENTS` を確認する.`solo` または `team` のいずれかであること.未指定・不正な値なら「切替先を `solo` または `team` で指定してください(例: `/set-mode team`)」と伝えて終了する. +3. 現在のモードを取得する(`.claude/project-mode` が無ければ `solo` 扱い): + ```bash + if [ -f .claude/project-mode ]; then CURRENT=$(tr -d '[:space:]' < .claude/project-mode); else CURRENT="solo"; fi + TARGET="$ARGUMENTS" # solo | team + ``` +4. `CURRENT == TARGET` の場合は「既に `$TARGET` モードです.変更はありません.」と伝えて終了する. + +## ステップ 2: ブランチ作成 (Branch) + +モード切替は共有設定(`CLAUDE.md` のルール部・`.claude/`)の変更を含むため,GUIDE_06「共有設定の扱い」に従い専用ブランチで行う. + +```bash +git checkout -b chore/set-mode-$TARGET +``` + +既に同名ブランチがあれば削除して作り直す.**本コマンドはコミットしない**(CLAUDE.md のルールに従い,取り込みは後で `/commit` で行う). + +## ステップ 3-A: solo → team(TARGET が team のとき) + +### 3-A.1 テンプレートから team 層ファイルを取得・配置 + +`/sync-template` の版差分では過去に追加済みの team 層ファイルを配置できないため,本コマンドはテンプレートを直接 clone して確実に配置する: + +```bash +TEMPLATE_URL="https://github.com/rintoHasegawa/programming-template.git" +TEMP_DIR=$(mktemp -d) +git clone --depth 1 "$TEMPLATE_URL" "$TEMP_DIR" + +# team 層ファイルをコピー(既存があっても最新版で上書き) +for f in \ + "docs/01_GUIDE/GUIDE_06_チーム開発ルール.md" \ + "docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md" \ + ".claude/commands/task-create.md" \ + ".claude/commands/task-start.md" \ + ".claude/commands/task-handoff.md" \ + ".claude/hooks/check_sync.sh" ; do + mkdir -p "$(dirname "$f")" + cp "$TEMP_DIR/$f" "$f" +done +rm -rf "$TEMP_DIR" +``` + +### 3-A.2 settings.json に SessionStart(check_sync) を配線 + +`.claude/settings.json` を Read し,既存の `PreToolUse`(`restrict_repo_access.py`)を保持したまま,`SessionStart` フックを追加する(既に配線済みなら何もしない): + +```json +"SessionStart": [ + { + "hooks": [ + { "type": "command", "command": "bash .claude/hooks/check_sync.sh", "timeout": 10 } + ] + } +] +``` + +Edit 後に `git diff .claude/settings.json` で結果を確認する. + +### 3-A.3 CLAUDE.md を team 化 + +`CLAUDE.md` を Read し,`/setup` の Phase 7(team 化)および GUIDE_06 に合わせて以下を反映する(既に反映済みの項目は触らない): + +- **「開発進捗」節**を,進捗欄(最新 1 行)ではなく **Issues ポインタ**に置き換える(例:「進捗・タスクは GitHub Issues と git 履歴で追う(GUIDE_06).現在のタスクは `gh issue list` で確認する.`CLAUDE.md` には進捗を書かない.」). +- **「必須ルール(コード実装時)」に「チーム開発(GUIDE_06 準拠)」小節を追加**する(直列運用・Issue ベースのタスク管理・`/task-create`/`/task-start`/`/task-handoff` の案内・条件付きセルフマージ・共有設定変更は専用 PR+他メンバー 1 名 Approve 必須). +- **「Git 運用」小節**に,セッション開始時の `[sync-check]` 警告を必ず認識する旨の 1 行を追加する. +- **「ドキュメント」→「01_GUIDE」一覧**に `GUIDE_06`・`GUIDE_07` の行を追加する. + +Edit 後に `git diff CLAUDE.md` で結果を確認する. + +### 3-A.4 その他 + +- `.gitignore` に `.claude/settings.local.json` が無ければ追記する(個人設定用.GUIDE_06). +- `echo team > .claude/project-mode` でモードを記録する. + +## ステップ 3-B: team → solo(TARGET が solo のとき) + +clone は不要(ローカルの削除・書き換えのみ).**破壊的操作を含むため,実行前に対象ファイルの一覧と CLAUDE.md 差分の要約をユーザーに提示し,同意を得てから実行する**. + +### 3-B.1 team 層ファイルを削除 + +```bash +rm -f \ + "docs/01_GUIDE/GUIDE_06_チーム開発ルール.md" \ + "docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md" \ + ".claude/commands/task-create.md" \ + ".claude/commands/task-start.md" \ + ".claude/commands/task-handoff.md" \ + ".claude/hooks/check_sync.sh" +``` + +### 3-B.2 settings.json から SessionStart(check_sync) を除去 + +`.claude/settings.json` を Read し,`check_sync.sh` を呼ぶ `SessionStart` フックのみを除去する.`PreToolUse`(`restrict_repo_access.py`)は保持する.他に個別追加された `SessionStart` フックがあれば残す(`check_sync.sh` の配線だけを外す).Edit 後に `git diff .claude/settings.json` で確認する. + +### 3-B.3 CLAUDE.md を solo 化 + +`CLAUDE.md` を Read し,team 化で加えた箇所を元の solo 既定へ戻す: + +- **「開発進捗」節**を solo 既定の骨組みに戻す.team 化で Issues ポインタになっているため,進捗欄(最新 1 行)+案内コメントの形へ置き換える: + ```markdown + ## 開発進捗 + + 最新: <直近の状況を 1 行.不明なら「(git 履歴 / 旧 Issue を参照)」> + ※ 本欄は**最新ステップ 1 行のみ上書き更新**.詳細な進捗履歴は docs/PROGRESS.md に追記する.運用ルールは GUIDE_05 参照. + ``` + 「最新」行に入れる現状はユーザーに確認する(team 期間の進捗は Issues / git 履歴にあるため,ここへ移し替える必要はない). +- **「チーム開発(GUIDE_06 準拠)」小節を削除**する. +- **「Git 運用」小節**の `[sync-check]` 警告の行を削除する. +- **「ドキュメント」→「01_GUIDE」一覧**から `GUIDE_06`・`GUIDE_07` の行を削除する(GUIDE_08 以降のプロジェクト固有ドキュメントがあれば残す). + +Edit 後に `git diff CLAUDE.md` で確認する. + +### 3-B.4 その他 + +- `echo solo > .claude/project-mode` でモードを記録する. +- `docs/PROGRESS.md` が無い場合は,solo 運用のため骨組みを用意するか確認する(テンプレート由来のファイルなので通常は存在する). + +## ステップ 4: 結果報告 (Report) + +以下を報告する: + +「**開発モードを `{CURRENT}` → `{TARGET}` に切り替えました.** + +- ブランチ: `chore/set-mode-{TARGET}` +- team 層ファイル: {配置した / 削除した} 一覧 +- `.claude/settings.json`: {SessionStart(check_sync) を追加 / 除去 / 変更なし} +- `CLAUDE.md`: {team 化 / solo 化} を反映 +- `.claude/project-mode`: `{TARGET}` + +内容を確認のうえ `/commit push` で取り込んでください. +{team に切り替えた場合: 「チーム運用の管理者初期設定(GitHub repo・CI 等)は GUIDE_06 を参照してください.共有設定の変更のため,他メンバー 1 名の Approve を得てからマージしてください(GUIDE_06).」}」 + +## 注意事項 (Notes) + +- 本コマンドは**コミットしない**.変更は `chore/set-mode-*` ブランチに未コミットで乗るので,`/commit` で取り込む. +- team ↔ solo の切替は共有設定の変更にあたる(GUIDE_06「共有設定の扱い」).team プロジェクトでは専用 PR+他メンバー 1 名 Approve を経てマージする. +- team 層ファイルのリストは `/sync-template` の「モード依存ファイル」と一致させること.どちらかを増減したら両方を更新する. +- solo→team で取得する team 層ファイルはテンプレート HEAD 版.版の細かな追従は以後の `/sync-template` に任せる(`template-sync-sha` は本コマンドでは変更しない). diff --git a/.claude/commands/setup.md b/.claude/commands/setup.md index fcfb723..493f4b9 100644 --- a/.claude/commands/setup.md +++ b/.claude/commands/setup.md @@ -28,6 +28,46 @@ 3. CLAUDE.md の「開発進捗」と `docs/PROGRESS.md` を確認し,どのフェーズから再開するか判断する 4. 初回の場合はフェーズ 1 から開始する +## 開発モードの選択 (Development Mode) + +新規立ち上げ時(Pre-check で初期状態だった場合),フェーズ 1 に入る前に開発モードを 1 度だけ確定する.既に `.claude/project-mode` がある場合(再開時)はこのステップを飛ばす. + +ユーザーに次を確認する: + +「**このプロジェクトの開発モードを選んでください.** + +- **solo(個人開発)**: 1 人で開発する.進捗は `CLAUDE.md` の進捗欄+ `docs/PROGRESS.md` で追う. +- **team(チーム開発)**: 複数人が Claude Code で開発する.進捗・タスクは GitHub Issues と git 履歴で追い,直列運用・条件付きセルフマージ等のチームルール(GUIDE_06)を適用する. + +どちらにしますか?(後から `/set-mode ` で切り替えられます)」 + +確定したら以下を行う: + +1. `.claude/project-mode` にモード(`solo` または `team` のいずれか 1 語)を書き出す. +2. **solo の場合**: チーム層ファイルが clone で配置されていれば削除し,solo プロジェクトを clean に保つ: + - `docs/01_GUIDE/GUIDE_06_チーム開発ルール.md` + - `docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md` + - `.claude/commands/task-create.md` / `task-start.md` / `task-handoff.md` + - `.claude/hooks/check_sync.sh` + - ※ `.claude/settings.json` はそのまま(solo でも `restrict_repo_access.py` を使う).SessionStart(check_sync) の配線は追加しない. +3. **team の場合**: 上記チーム層ファイルを残す.加えて: + - `.claude/settings.json` に SessionStart フックを追記して `check_sync.sh` を配線する(既存の PreToolUse ブロックは保持する): + ```json + "SessionStart": [ + { + "hooks": [ + { "type": "command", "command": "bash .claude/hooks/check_sync.sh", "timeout": 10 } + ] + } + ] + ``` + - `.gitignore` に `.claude/settings.local.json` が無ければ追記する(個人設定用.GUIDE_06). + - CLAUDE.md のチーム化は Phase 7 で行う(この時点ではまだ立ち上げ中で Issue/repo が無いため,進捗欄は setup 再開用にそのまま使う). + +### 進捗記録(立ち上げ中) + +立ち上げ中は repo/Issue がまだ無いため,**モードに関わらず** setup 再開のための進捗は `CLAUDE.md` の進捗欄(最新 1 行)+ `docs/PROGRESS.md` に記録する.team モードでの「進捗を Issue で追う」への切り替えは Phase 7(実装開始)以降に適用する. + ## フェーズ 1〜6: 各フェーズの実行 GUIDE_01 に定義された各フェーズを順番に実行する. @@ -57,16 +97,29 @@ ## フェーズ 7: 実装開始 1. GUIDE_01 の「CLAUDE.md の管理」セクションに従い,CLAUDE.md を最終更新する + - **team モードの場合**(`.claude/project-mode` が `team`)は,ここで CLAUDE.md をチーム開発向けに変換する: + - 「開発進捗」節を,進捗欄(最新 1 行)ではなく **Issues ポインタ**に置き換える(例: 「進捗・タスクは GitHub Issues と git 履歴で追う(GUIDE_06).現在のタスクは `gh issue list` で確認する.`CLAUDE.md` には進捗を書かない.」). + - 「必須ルール(コード実装時)」に **「チーム開発(GUIDE_06 準拠)」小節**を追加する(直列運用・Issue ベースのタスク管理・`/task-create`/`/task-start`/`/task-handoff` の案内・条件付きセルフマージ・共有設定変更は専用 PR+他メンバー 1 名 Approve 必須). + - 「Git 運用」小節に,セッション開始時の `[sync-check]` 警告を必ず認識する旨の 1 行を追加する. + - 「ドキュメント」→「01_GUIDE」一覧に `GUIDE_06`・`GUIDE_07` の行を追加する. + - **solo モードの場合**は従来どおり(進捗欄+ PROGRESS.md 運用). 2. 作成した全ドキュメントの一覧を表示する 3. 最初の実装ステップを確認する +4. **team モードの場合**は,AI に実施できない「管理者の初期設定」(GUIDE_06「管理者の初期設定」)をユーザーに案内する: + - GitHub リポジトリ作成・メンバー招待 + - Issue テンプレートの用意 + - CI 構築(未構築の間は GUIDE_06「CI 構築までの暫定ゲート」を適用) + - 依存脆弱性対策が必要ならスタックに応じた `.github/dependabot.yml` を追加(エコシステムはプロジェクト固有のため setup では作らない) 「**全フェーズが完了しました.** 作成したドキュメント: {ドキュメント一覧} +開発モード: {solo / team} CLAUDE.md を更新しました. -最初の実装ステップは `{ステップ名}` です.`/implement {タスク}` で開始できます.」 +最初の実装ステップは `{ステップ名}` です.`/implement {タスク}` で開始できます. +{team の場合: 「チーム運用の管理者初期設定(GitHub repo・CI 等)は GUIDE_06 を参照してユーザー側で実施してください.」}」 ## 中断時の処理 diff --git a/.claude/commands/sync-template.md b/.claude/commands/sync-template.md index 0e74b4a..83e80da 100644 --- a/.claude/commands/sync-template.md +++ b/.claude/commands/sync-template.md @@ -22,6 +22,7 @@ | `CLAUDE.md` | プロジェクト名・開発進捗・固有規約を保持する必要がある | テンプレートで変更された共通セクション(必須ルール,エージェントチーム,ドキュメント構成等)のみを Edit で更新.プロジェクト固有セクションは触らない | | `docs/PROGRESS.md` | プロジェクト固有の進捗ログを保持する必要がある | 既存ファイルがある場合は内容を上書きしない.テンプレート側の骨組み(タイトル・案内コメント)に差分があれば通知のみ行い手動マージを促す | | `.gitattributes` | プロジェクトによって設定が異なる可能性がある | 差分を表示し,ユーザーに「上書き / マージ / スキップ」を問う | +| `.claude/settings.json` | team モードで SessionStart(check_sync) 配線を追加している等,プロジェクト固有の hook 設定を保持する必要がある | 既存の hooks を保持しつつ,テンプレート側で追加・変更された hook のみ統合.差分を表示しユーザーに確認 | マージ処理の対象は **既存ファイルが存在する場合のみ**.初回同期(`.claude/template-sync-sha` がない状態)では全ファイルが A 扱いとなるが,これらのファイルはフレームワーク初期化(`flutter create` / `npm init` 等)や `/init` で既にプロジェクトに存在するのが通常なので,そのままマージ処理に入る.既存ファイルがない稀なケースに限り通常の `cp` で配置する. @@ -35,6 +36,27 @@ 判定はステップ 5.3 のループ内でマージ必須ファイル判定より先に行う. +## モード依存ファイル (Mode-gated / Team-layer Files) + +テンプレートは個人開発(solo)とチーム開発(team)の両モードを 1 つのリポジトリで提供する(GUIDE_06).以下の**チーム層ファイル**は team モードのプロジェクトにのみ配置し,solo モードのプロジェクトには同期しない. + +| ファイル | レイヤ | +| --- | --- | +| `docs/01_GUIDE/GUIDE_06_チーム開発ルール.md` | team | +| `docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md` | team | +| `.claude/commands/task-create.md` | team | +| `.claude/commands/task-start.md` | team | +| `.claude/commands/task-handoff.md` | team | +| `.claude/hooks/check_sync.sh` | team | + +判定はプロジェクトの `.claude/project-mode`(`solo` または `team`.`/setup` が作成)で行う: + +- **`team`**: チーム層ファイルを通常どおり同期(A/M/D すべて反映). +- **`solo`**: チーム層ファイルを同期対象外ファイルと同様に**完全スキップ**(コピー・上書き・削除いずれもしない).solo プロジェクトは `/setup` 時にこれらを削除済みのため,再配置しない. +- **`.claude/project-mode` が存在しない**(本機能導入前に作られた既存プロジェクト): 安全側に倒して **`solo` 扱い**とし,チーム層を配置しない.同期の最後に「チーム開発なら `.claude/project-mode` に `team` と記入し再同期してください」と案内する. + +なお `.claude/project-mode` 自体はテンプレートに含まれない(`/setup` が各プロジェクトで生成する)ため,同期で触れることはない. + ## ステップ 1: 事前確認 `git status` でワーキングツリーがクリーンか確認する. @@ -132,8 +154,23 @@ 以降の処理で利用する判定関数を定義する: ```bash -MERGE_FILES=(".gitignore" "CLAUDE.md" "docs/PROGRESS.md" ".gitattributes") +MERGE_FILES=(".gitignore" "CLAUDE.md" "docs/PROGRESS.md" ".gitattributes" ".claude/settings.json") SKIP_FILES=("README.md") +TEAM_LAYER_FILES=( + "docs/01_GUIDE/GUIDE_06_チーム開発ルール.md" + "docs/01_GUIDE/GUIDE_07_Issues・Projects運用ガイド.md" + ".claude/commands/task-create.md" + ".claude/commands/task-start.md" + ".claude/commands/task-handoff.md" + ".claude/hooks/check_sync.sh" +) + +# プロジェクトの開発モードを取得(未設定なら安全側で solo 扱い) +if [ -f .claude/project-mode ]; then + PROJECT_MODE=$(tr -d '[:space:]' < .claude/project-mode) +else + PROJECT_MODE="solo" +fi is_merge_file() { local t="$1" @@ -150,8 +187,18 @@ done return 1 } + +is_team_layer_file() { + local t="$1" + for f in "${TEAM_LAYER_FILES[@]}"; do + [ "$f" = "$t" ] && return 0 + done + return 1 +} ``` +`PROJECT_MODE` が `solo` の場合,チーム層ファイル(`is_team_layer_file` が真)は同期対象外ファイルと同様に完全スキップする(ステップ 5.3 のループでは `is_skip_file` 判定の直後に `[ "$PROJECT_MODE" = "solo" ] && is_team_layer_file "$file"` を追加で判定して `continue` する).`team` の場合は通常のコピー/マージ判定に進む. + ### 5.3 通常コピー対象の反映(マージ必須ファイル以外) マージ必須ファイルは後段(5.4)で個別処理するため,このループではスキップする.既存ファイルがない場合は通常どおり `cp` で配置する: @@ -165,6 +212,10 @@ if is_skip_file "$file"; then continue fi + # solo モードではチーム層ファイルを完全スキップ(再配置しない) + if [ "$PROJECT_MODE" = "solo" ] && is_team_layer_file "$file"; then + continue + fi # マージ必須ファイルで既存ファイルがある場合は 5.4 で処理 if is_merge_file "$file" && [ -f "$file" ]; then continue @@ -177,6 +228,9 @@ if is_skip_file "$newfile"; then continue fi + if [ "$PROJECT_MODE" = "solo" ] && is_team_layer_file "$newfile"; then + continue + fi if is_merge_file "$newfile" && [ -f "$newfile" ]; then continue fi @@ -250,6 +304,22 @@ - **スキップ**: 既存ファイルを維持 3. 選択に応じて処理する +**`.claude/settings.json` のマージ手順** + +`settings.json` は hooks 設定を持つ.team モードのプロジェクトは PreToolUse(`restrict_repo_access.py`)に加えて SessionStart(`check_sync.sh`)を配線しているため,テンプレート版で盲目的に上書きするとプロジェクト固有の配線が失われる.同期担当エージェント(= あなた)が Read と Edit で JSON をマージする: + +1. 既存 `.claude/settings.json` とテンプレート版 `$TEMP_DIR/.claude/settings.json` を Read する +2. 差分を表示する: + ```bash + diff -u .claude/settings.json "$TEMP_DIR/.claude/settings.json" + ``` +3. **既存の hooks を保持したまま**,テンプレート側で追加・変更された hook(イベント・matcher・command)のみを統合する: + - 既存に無いイベント/hook はテンプレート版から追加する + - プロジェクト固有の hook(team の SessionStart `check_sync.sh` 等)は残す + - 同一 hook の command 変更(例: `restrict_repo_access.py` の起動方法変更)はテンプレート版に合わせる + - solo モードで SessionStart(check_sync) が無い場合は,team 専用の配線を勝手に追加しない +4. `git diff .claude/settings.json` で結果を表示しユーザーに確認する + ### 5.5 削除候補の確認 削除候補(D およびリネーム元)を抽出する: @@ -258,6 +328,8 @@ DELETIONS=$(echo "$CHANGED_ENTRIES" | awk -F'\t' '$1 == "D" {print $2} $1 ~ /^R/ {print $2}') ``` +solo モードではチーム層ファイルはそもそもプロジェクトに存在しないため,削除候補から除外する(`$PROJECT_MODE` が `solo` のとき `is_team_layer_file` が真のパスを `$DELETIONS` から取り除く). + `$DELETIONS` が空でない場合,ユーザーに確認を求める: 「**以下のファイルはテンプレートから削除されています:** @@ -304,17 +376,25 @@ 「**テンプレート同期が完了しました.** - ブランチ: `{ブランチ名}` +- 開発モード: `{PROJECT_MODE}`(チーム層ファイルは {team: 同期対象 / solo: スキップ}) - 取り込んだ変更: {変更の要約} - コード修正: {あり(内容)/なし} `/commit push` でプッシュと PR 作成ができます.」 +`.claude/project-mode` が存在せず `solo` 扱いにした場合は,末尾に次を添える: + +「※ `.claude/project-mode` が未設定のため solo として同期しました.チーム開発にする場合は `/set-mode team` を実行してください(`.claude/project-mode` を手で書き換えるだけでは team 層は配置されません).」 + ## 注意事項 +- 本コマンドは一時ディレクトリ(`mktemp -d`)に clone したテンプレートを Read / `cp` / `rm -rf` する.`restrict_repo_access.py` フックはシステム一時ディレクトリを許可ゾーンとして例外扱いしており,本コマンドはそれに依存している(フックの例外を外すと本コマンドが動かなくなる) - テンプレートリポジトリへの push は行わない - コード修正はユーザーの確認なしに実行しない - マージ必須ファイル(`.gitignore`, `CLAUDE.md`, `docs/PROGRESS.md`, `.gitattributes`)は必ずステップ 5.4 の手順でマージする.盲目的な `cp` で上書きしない(フレームワーク固有の除外ルールやプロジェクト固有セクションが失われる) - 同期対象外ファイル(`README.md`)はテンプレート紹介用のためプロジェクトには反映しない.テンプレート側で追加・変更・削除があってもプロジェクトの該当ファイルは触らない +- チーム層ファイル(`GUIDE_06`/`GUIDE_07`/`task-*`/`check_sync.sh`)は `.claude/project-mode` が `team` のプロジェクトにのみ同期する.`solo`(または未設定)のプロジェクトには配置・更新・削除いずれもしない.`/sync-template` は「版の追従」のみを行い,**モードの切り替えはしない**.solo↔team の切替は `/set-mode ` を使う(team 層ファイルの配置/削除・`settings.json` 配線・`CLAUDE.md` の team 化/solo 化・`project-mode` 更新を一括で行う).`.claude/project-mode` を手で書き換えるだけでは切り替わらない +- `.claude/settings.json` はマージ必須ファイル.team の SessionStart(check_sync) 配線を保持したままテンプレートの hook 変更を統合する.盲目的な `cp` で上書きしない - 通常コピー対象でもプロジェクト固有の変更が上書きされうる場合は,`git diff` で確認してユーザーに報告する - テンプレートが管理するのは `.claude/` 配下のうち `agents/`,`commands/`,`hooks/`,`settings.json`,`template-sync-sha` のみ.`.claude/plans/` や `.claude/commit-context.md` 等のプロジェクト固有ファイルはテンプレートに含まれないため同期対象外 - `chore/sync-template` ブランチは他の作業ブランチと混ぜず,作成後は速やかにマージすること.複数の作業ブランチで `/sync-template` を実行すると `.claude/template-sync-sha` がコンフリクトする.コンフリクト時は新しい(HEAD 側の)SHA を採用すること. diff --git a/.claude/commands/task-create.md b/.claude/commands/task-create.md new file mode 100644 index 0000000..051ac85 --- /dev/null +++ b/.claude/commands/task-create.md @@ -0,0 +1,51 @@ +--- +name: task-create +model: inherit +description: "GUIDE_06/07 に従い,Issue を作成しボードに追加する(着手はしない).タスクの事前計画用." +argument-hint: "<タスクの説明>" +--- + +あなたはタスク計画担当です. +GUIDE_06(チーム開発ルール)と GUIDE_07(Issues・Projects 運用ガイド)に従い,新しいタスクの Issue を作成してボードに並べてください. + +本コマンドは**タスクを事前に定義する**ためのものです.着手は別途 `/task-start ` で行います(または手動で).Issue 無しで進める作業はこのコマンドを使う必要はありません(GUIDE_06). + +## 前提確認 (Pre-check) + +$ARGUMENTS(タスクの説明)が指定されているか確認する.指定がなければ「タスクの説明を指定してください」と伝えて終了する. + +## ステップ 1: Project の特定 (Project Lookup) + +1. リポジトリ所有者を取得する(`gh repo view --json owner --jq .owner.login`). +2. Project を特定する(`gh project list --owner `).複数ある場合はユーザーに確認する.見つからない場合はその旨を伝え,ステップ 3(ボード追加)は飛ばして進める(管理者の初期設定が未完了.GUIDE_06). + +## ステップ 2: Issue 作成 (Create Issue) + +$ARGUMENTS の説明から Issue 本文を組み立てる. + +- **やること**は必ず書く. +- **完了条件(受け入れ基準)**は非自明な場合のみ書く(GUIDE_06). +- 担当者は**アサインしない**(誰が拾うかは着手時に決まる). + +`gh issue create --title "<タイトル>" --body "<本文>"` で作成する. + +## ステップ 3: ボードに追加 (Add to Board) + +GUIDE_07「Projects の操作」に従う(Project が無い場合は飛ばす). + +1. `gh project item-add --owner --url ` でボードに追加する. +2. 追加されたアイテムの Status を `Todo` に設定する(`gh project field-list`・`item-list` で必要な ID を取得し `gh project item-edit`). +3. `gh project` の書き込み系は成功しても無出力のことがある.`gh project item-list` で結果を確認する(GUIDE_07). + +## ステップ 4: 完了サマリー (Summary) + +以下を提示する: + +- **Issue**: 番号・タイトル・URL +- **ボード**: Todo +- **次の手順**: 「このタスクに着手する場合は `/task-start ` を実行してください.」 + +## 注意事項 (Notes) + +- 複数タスクを一括で作る場合は,本コマンドを複数回実行してください. +- Projects 操作には `project` スコープが必要.スコープエラーが出たら `gh auth refresh -s project` を実行する(GUIDE_07). diff --git a/.claude/commands/task-handoff.md b/.claude/commands/task-handoff.md new file mode 100644 index 0000000..b4cede2 --- /dev/null +++ b/.claude/commands/task-handoff.md @@ -0,0 +1,108 @@ +--- +name: task-handoff +model: inherit +description: "現在 In Progress の Issue に進捗メモ(完了済み・残タスク・確定事項・git 状態・再開方法)をコメントで投稿する.セッション中断・引継ぎ用." +argument-hint: "<追加メモ(省略可)>" +--- + +あなたは作業引継ぎ担当です.現在 **In Progress** の Issue に,次セッション・次メンバーが再開できるだけの情報を進捗メモとして投稿します. + +GUIDE_06(チーム開発ルール)の「進捗は Issues / Projects と git 履歴で追う」方針に沿い,引継ぎ情報を Issue コメントに集約します(`CLAUDE.md` に進捗は書かない). + +## 前提確認 (Pre-check) + +リポジトリ所有者を取得する(`gh repo view --json owner --jq .owner.login`). + +## ステップ 1: 対象 Issue の特定 (Identify Issue) + +1. Project を特定する(`gh project list --owner `).見つからない場合は「Project 未設定のため進捗メモを投稿できません.管理者の初期設定が必要です(GUIDE_06).」と伝えて終了する. +2. ボードから Status が `In Progress` の Issue を抽出する(`gh project item-list --owner --format json`). +3. 件数で挙動を変える: + - **0 件**: 「In Progress の Issue がありません.まず `/task-start ` で着手してから本コマンドを使ってください.」と伝えて終了. + - **1 件**: そのまま対象とする. + - **複数件**: 各 Issue 番号・タイトルを示し,「どれを対象にしますか?」とユーザーに確認する. + +## ステップ 2: コンテキスト収集 (Collect Context) + +以下を取得してドラフト生成材料とする. + +- `gh issue view --json number,title,body,comments` で Issue 本文と過去コメントを取得 +- `git branch --show-current` で作業ブランチ +- `git rev-parse --short HEAD` で現在 HEAD +- `git log main..HEAD --oneline` で main から積んだコミット一覧 +- `git status --porcelain` で未コミット変更の有無 +- 直近のセッション会話履歴から「**確定した重要な設計判断**」と「**未決定で次に詰める点**」を抽出 + +## ステップ 3: ドラフト生成 (Draft) + +以下のフォーマットで進捗メモを生成する.**該当なしのセクションは省略してよい**. + +````markdown +## 進捗メモ (YYYY-MM-DD) + + + +### 完了済み + +| フェーズ / タスク | 成果物 | コミット | +| --- | --- | --- | +| ... | ... | <短縮 SHA> | + +### 残タスク + +- ... + +### 確定した重要な設計判断(再開時の文脈) + +- ... + +### 未決定で次に詰める点 + +- ... + +### 現在の git 状態 + +- ブランチ: `<ブランチ名>` +- HEAD: `<短縮 SHA>` +- 未コミット変更: <あり / なし> + +### 次セッションの再開方法 + +```bash +git checkout <ブランチ名> +``` + +<再開時の指針コメント.例: 「`/setup` を再実行するか,手動でフェーズ N から続行」> +```` + +### ドラフトの粒度方針 + +- **完了済み**: 当該セッションで積んだコミット中心.本 Issue に関わる範囲のみ. +- **残タスク**: Issue 本文の TODO や未着手項目を整理. +- **確定した設計判断**: セッション中にユーザーと合意して**今後の作業の前提**になるもの.既に Issue 本文や過去コメントに明記されている内容は重複させない(差分のみ). +- **未決定で次に詰める点**: 次セッションで判断が必要なもの. +- **粒度感**: 1 セッション分の引継ぎ.週次レポートではない. + +## ステップ 4: 承認 (Approval) + +ドラフトをユーザーに提示し,「**この内容で投稿しますか? 修正点があれば指示してください.**」と確認する. + +ユーザーの明示的な同意(「OK」「投稿して」「これで」等)が得られるまで投稿しない.修正指示があれば反映して再提示する. + +## ステップ 5: 投稿 (Post) + +`gh issue comment --body "<本文>"` で投稿する.投稿後,コメントの URL を表示する. + +## 完了サマリー (Summary) + +以下を提示する: + +- **Issue**: 番号・タイトル・URL +- **コメント URL** +- **次のステップ**: 「次セッションで再開する場合は `git checkout <ブランチ名>` から始めてください.」 + +## 注意事項 (Notes) + +- 本コマンドは Issue を **Done に動かさない**.In Progress のまま残す(作業継続前提).完了させたい場合は別途 `/commit merge` で PR をマージ → `Closes #<番号>` で自動クローズ. +- 進捗メモは**コメント**として投稿する.Issue 本文は書き換えない. +- Projects 操作には `project` スコープが必要.スコープエラーが出たら `gh auth refresh -s project` を実行する(GUIDE_07). diff --git a/.claude/commands/task-start.md b/.claude/commands/task-start.md new file mode 100644 index 0000000..99a21b3 --- /dev/null +++ b/.claude/commands/task-start.md @@ -0,0 +1,61 @@ +--- +name: task-start +model: inherit +description: "GUIDE_06/07 に従い,既存 Issue を拾って作業を開始する(アサイン・ボード In Progress・作業ブランチ作成)." +argument-hint: "" +--- + +あなたはタスク着手の準備担当です. +GUIDE_06(チーム開発ルール)と GUIDE_07(Issues・Projects 運用ガイド)に従い,**既存 Issue を拾って**作業に取り掛かるための準備を整えてください. + +本コマンドは既存 Issue から作業を始めるためのものです.新規 Issue を立てる場合は `/task-create` を使ってください.Issue 無しで小さい変更や試験的作業を進める場合はこのコマンドは不要です(GUIDE_06). + +## 前提確認 (Pre-check) + +1. 作業ツリーの状態を確認する(`git status`).未コミットの変更がある場合は,その旨をユーザーに伝え,先に片付けるか続行するか確認する. +2. 現在のブランチを確認する(`git branch --show-current`).`main` 以外にいる場合は,そのブランチに未マージのコミットが残っていないか確認する(`git log main..HEAD --oneline`).残っていれば「前の作業が未マージです.先にマージしてから着手するのが推奨です.続行しますか?」とユーザーに確認する(直列運用.GUIDE_06). +3. $ARGUMENTS を確認する.Issue 番号(数値または `#数値`)が指定されていなければ「対象の Issue 番号を指定してください.新規 Issue を立てる場合は `/task-create` を使います」と伝えて終了する. + +## ステップ 1: 直列運用チェック (Serial Check) + +GUIDE_06「作業の直列化」より,同時に進行中のコード作業は原則 1 件とする. + +1. リポジトリ所有者を取得する(`gh repo view --json owner --jq .owner.login`). +2. Project を特定する(`gh project list --owner `).複数ある場合はユーザーに確認する.見つからない場合はその旨を伝え,ステップ 3(ボード操作)は飛ばして進める(管理者の初期設定が未完了.GUIDE_06). +3. ボードのアイテムで Status が `In Progress` のものを数える(`gh project item-list --owner --format json`).対象 Issue 以外で 1 件以上ある場合は,該当タスクを示し「直列運用では進行中の作業は原則 1 件です.続行しますか?」とユーザーに確認する(禁止ではなく原則.GUIDE_06). + +## ステップ 2: 対象 Issue の確認・アサイン (Verify & Assign) + +1. `gh issue view ` で Issue の内容を確認する.存在しない・クローズ済みの場合はユーザーに知らせて判断を仰ぐ. +2. 担当者が未設定,または自分以外なら,`gh issue edit --add-assignee @me` で自分をアサインする(他人がアサインされている場合は,重複着手にならないかユーザーに確認). + +## ステップ 3: ボードを In Progress へ (Board) + +GUIDE_07「Projects の操作」に従う(Project が無い場合はこのステップを飛ばす). + +1. 対象 Issue がボードに未追加なら `gh project item-add --owner --url ` で追加する. +2. 対象アイテムの Status を `In Progress` に変更する(`gh project field-list`・`item-list` で必要な ID を取得し `gh project item-edit`). +3. `gh project` の書き込み系は成功しても無出力のことがある.`gh project item-list` で結果を確認する(GUIDE_07). + +## ステップ 4: 作業ブランチ作成 (Branch) + +GUIDE_04 に従う. + +1. `git checkout main && git pull origin main` で `main` を最新化する. +2. GUIDE_04 の基本形式(`[プレフィックス][概要]`)でブランチ名を決める.プレフィックスはタスク種別(`feature` / `fix` / `refactor` / `docs` / `chore`),概要は内容を表す英単語 2〜4 語(kebab-case)とする.ブランチ名に Issue 番号は含めない(GUIDE_06). +3. `git checkout -b <ブランチ名>` で作業ブランチを作成する. + +## ステップ 5: 完了サマリー (Summary) + +以下を提示する: + +- **Issue**: 番号・タイトル・URL +- **ボード**: In Progress +- **ブランチ**: 作成したブランチ名 +- **次の手順**: 「`/implement` に対象 Issue の内容を渡して実装を開始してください(`gh issue view ` で取得できます).」 + +## 注意事項 (Notes) + +- branch↔Issue の紐付けは,後の PR 本文の `Closes #` で行う(GUIDE_06).ブランチ名には番号を入れない. +- Projects 操作には `project` スコープが必要.スコープエラーが出たら `gh auth refresh -s project` を実行する(GUIDE_07). +- 新規 Issue を立てる場合は `/task-create`,Issue 無しで進める場合は本コマンドを使わず直接 `/implement` 等へ. diff --git a/.claude/hooks/check_sync.sh b/.claude/hooks/check_sync.sh new file mode 100644 index 0000000..f7ece22 --- /dev/null +++ b/.claude/hooks/check_sync.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# SessionStart hook: ローカルブランチが origin と同期しているかをチェックし, +# JSON で systemMessage (UI 表示) と additionalContext (モデルに注入) を出力する. +# 読み取り専用 (git fetch のみ). 失敗してもセッション開始は阻害しない. +# +# GUIDE_06「直列運用」「main を常に動作可能」を補助する目的で, +# 古い main から作業を始めるミスをセッション開始時に可視化する. + +# JSON 整形は python3 に任せる (jq 非依存. 既存 hook も python3 を利用). +emit() { + local msg="$1" + python3 - "$msg" <<'PY' +import json, sys +msg = sys.argv[1] +print(json.dumps({ + "systemMessage": msg, + "hookSpecificOutput": { + "hookEventName": "SessionStart", + "additionalContext": msg, + }, +}, ensure_ascii=False)) +PY +} + +# git リポジトリ外なら静かに終了 +git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0 + +# origin が未設定なら静かにスキップ (個人 clone・ローカル実験用途) +git remote get-url origin >/dev/null 2>&1 || exit 0 + +# fetch (5 秒で打ち切り). 失敗 = オフライン等. 警告だけ出して継続. +if ! timeout 5 git fetch --quiet origin 2>/dev/null; then + emit "[sync-check] origin への fetch に失敗 — オフラインの可能性" + exit 0 +fi + +BRANCH=$(git branch --show-current) +# detached HEAD は判定できないので静かに終了 +[ -z "$BRANCH" ] && exit 0 + +LOCAL=$(git rev-parse HEAD 2>/dev/null) || exit 0 +REMOTE=$(git rev-parse "@{u}" 2>/dev/null) +if [ -z "$REMOTE" ]; then + emit "[sync-check] $BRANCH は upstream 未設定" + exit 0 +fi +BASE=$(git merge-base HEAD "@{u}") + +DIRTY="" +[ -n "$(git status --porcelain)" ] && DIRTY=" / 未コミット変更あり" + +if [ "$LOCAL" = "$REMOTE" ]; then + emit "[sync-check] ✓ $BRANCH は origin と同期${DIRTY}" +elif [ "$LOCAL" = "$BASE" ]; then + AHEAD=$(git rev-list --count "HEAD..@{u}") + emit "[sync-check] ⚠ $BRANCH は origin より ${AHEAD} コミット遅れ — \`git pull\` 推奨${DIRTY}" +elif [ "$REMOTE" = "$BASE" ]; then + AHEAD=$(git rev-list --count "@{u}..HEAD") + emit "[sync-check] ℹ $BRANCH は origin より ${AHEAD} コミット先行${DIRTY}" +else + AHEAD=$(git rev-list --count "@{u}..HEAD") + BEHIND=$(git rev-list --count "HEAD..@{u}") + emit "[sync-check] ⚠ $BRANCH は origin と分岐 (先行 ${AHEAD} / 遅れ ${BEHIND}) — rebase/merge が必要${DIRTY}" +fi diff --git a/.claude/hooks/restrict_repo_access.py b/.claude/hooks/restrict_repo_access.py index 36bfe96..e8ea139 100644 --- a/.claude/hooks/restrict_repo_access.py +++ b/.claude/hooks/restrict_repo_access.py @@ -1,10 +1,24 @@ -"""PreToolUse hook: リポジトリ外のファイルアクセスをブロックする.""" +"""PreToolUse hook: リポジトリ外のファイルアクセスをブロックする. + +例外としてシステム一時ディレクトリ(/tmp・%TEMP% 等)は許可ゾーンとする: +- Read/Write/Edit/Glob/Grep: 一時ディレクトリ配下なら許可 + (/sync-template・/set-mode がテンプレートを mktemp -d に clone して読むため. + また Claude Code のスクラッチパッドは %TEMP% 配下にあり,Write をブロック + するとハーネスの一時ファイル運用が壊れる) +- Bash の破壊的コマンド: 対象が一時ディレクトリ配下なら許可 + (cp "$TEMP_DIR/..." や rm -rf "$TEMP_DIR" の後片付けは正当な操作) + +一時ディレクトリは使い捨て領域であり,本フックの目的(ユーザーのファイルを +事故から守る)に照らして許可ゾーンにしても失うものがない. +""" import json import os +import posixpath import re import shlex import sys +import tempfile # Bash で検出する破壊的コマンド DESTRUCTIVE_COMMANDS = {"rm", "rmdir", "mv", "cp", "chmod", "chown", "unlink"} @@ -27,6 +41,22 @@ return real_target == real_base or real_target.startswith(real_base + os.sep) +def is_temp_path(path: str) -> bool: + """path がシステム一時ディレクトリ配下かを判定する. + + OS ネイティブの一時ディレクトリ(tempfile.gettempdir())に加え, + Git Bash 等の POSIX 形式 /tmp も文字列正規化で判定する + (Windows では /tmp が実パスに解決できないため realpath に頼れない). + `..` は正規化してから判定するので /tmp/../etc のような脱出は温存されない. + """ + # POSIX 形式 /tmp の判定(.. を潰してから前方一致) + norm = posixpath.normpath(path.replace("\\", "/")) + if norm == "/tmp" or norm.startswith("/tmp/"): + return True + # OS ネイティブの一時ディレクトリの判定 + return is_within_directory(path, tempfile.gettempdir()) + + def check_bash_command(command: str, cwd: str) -> str | None: """Bash コマンド内の破壊的操作がリポジトリ外を対象としていないかチェックする. @@ -61,6 +91,10 @@ continue # 絶対パスまたは .. を含むパスをチェック if os.path.isabs(token) or ".." in token: + # 一時ディレクトリ配下への破壊的操作は許可 + # (テンプレート clone の cp・後片付けの rm -rf 等) + if is_temp_path(token): + continue resolved = os.path.realpath(os.path.join(cwd, token)) if not is_within_directory(resolved, cwd): return ( @@ -104,6 +138,12 @@ if target_path is None: sys.exit(0) + # 一時ディレクトリ配下は許可(Read/Write/Edit/Glob/Grep すべて) + # (/sync-template・/set-mode が mktemp -d に clone したテンプレートを読む. + # Claude Code のスクラッチパッドも %TEMP% 配下で Write が必要) + if is_temp_path(target_path): + sys.exit(0) + if not is_within_directory(target_path, cwd): deny( f"リポジトリ外のパスへのアクセスはブロックされました: {target_path}" diff --git a/.gitignore b/.gitignore index d2f109f..f5b74c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,19 @@ +# 個人・マシン固有の Claude 設定(共有 settings.json を汚さない.GUIDE_06) +.claude/settings.local.json + # /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/README.md b/README.md index a6b5056..ffc91c9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Claude Code と協働でプロジェクトを立ち上げ・実装するための汎用テンプレート.`/setup` で対話的に立ち上げ,`/implement` で実装を進める. +**個人開発(solo)とチーム開発(team)の 2 モード**を 1 つのテンプレートで提供する.`/setup` の冒頭でモードを選ぶだけで,チーム開発向けのルール・コマンドが有効化される. + +- **solo**: 1 人で開発.進捗は `CLAUDE.md` の進捗欄+ `docs/PROGRESS.md` で追う.チーム層ファイルは配置されない. +- **team**: 複数人が Claude Code で開発.進捗・タスクは GitHub Issues と git 履歴で追い,直列運用・条件付きセルフマージ等のチームルール(GUIDE_06)と `/task-create`・`/task-start`・`/task-handoff` コマンド,SessionStart の同期チェック(`check_sync.sh`)が有効になる. + ## Quick Start 新規プロジェクトを始めるときは,以下の手順でテンプレートをカレントディレクトリに展開し,履歴を引き継がない新規リポジトリとして初期化する. @@ -25,14 +30,18 @@ rm README.md ``` -その後 Claude Code を起動し,`/setup ` でプロジェクト立ち上げを開始する.以降,テンプレートの更新を取り込むときは `/sync-template` を実行する. +その後 Claude Code を起動し,`/setup ` でプロジェクト立ち上げを開始する.`/setup` の冒頭で **solo / team のモードを選択**する(選択結果は `.claude/project-mode` に記録され,以降の `/sync-template` がモードに応じてチーム層ファイルを出し分ける).以降,テンプレートの更新を取り込むときは `/sync-template` を実行する. + +> 途中でモードを切り替える場合は **`/set-mode `** を実行する.team 層ファイル(GUIDE_06/07・`task-*`・`check_sync.sh`)の配置/削除,`settings.json` の hook 配線,`CLAUDE.md` の team 化/solo 化,`.claude/project-mode` の更新を一括で整合させる(`.claude/project-mode` を手で書き換えるだけでは切り替わらない). ## 主なスラッシュコマンド -- `/setup ` — GUIDE_01 に従いプロジェクト立ち上げを対話的に進行 +- `/setup ` — GUIDE_01 に従いプロジェクト立ち上げを対話的に進行(solo/team を選択) - `/implement <タスク>` — 実装パイプライン(コーディング → テスト → リファクタリング) - `/commit` / `/commit push` — コミット作成(`push` でプッシュと PR 作成まで) - `/sync-template` — テンプレートの最新変更を取り込む +- `/set-mode ` — 開発モードを切り替える(team 層ファイル・settings.json・CLAUDE.md・project-mode を一括整合) +- `/task-create` / `/task-start` / `/task-handoff` — **team モードのみ**.Issue ベースのタスク作成・着手・引継ぎ ## ドキュメント @@ -43,3 +52,5 @@ - `GUIDE_03_ファイル命名規則.md` — ファイル名の規則 - `GUIDE_04_Git運用ルール.md` — ブランチ・コミット・PR の運用 - `GUIDE_05_エージェント運用ルール.md` — `/implement` のエージェントチーム運用 +- `GUIDE_06_チーム開発ルール.md` — **team モードのみ**.直列運用・条件付きセルフマージ・共有設定の扱い +- `GUIDE_07_Issues・Projects運用ガイド.md` — **team モードのみ**.`gh` による Issue/Project 操作手順 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..0c2ef4d 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,8 +136,15 @@ ※ リファクタリングとテストは実装と一体の成果物として,まとめてコミットする.必要に応じて分割コミットも可. +※ **例外(無人運転)**: 以下のループは CLAUDE.md の「`/commit` 自発実行禁止」ルールに対するユーザー承認済みの例外として,専用ブランチに自律コミットする.いずれも push・PR・マージ・`main` への操作は行わず,取り込み可否は人間が判断する. + +- `/auto-refactor`(リファクタ/ドキュメント整理ループ)→ `refactor/` 専用ブランチ +- `/auto-audit`(バグ/脆弱性の巡回監査ループ.発見を裏取り後,再現テストで正しさを担保できるものだけ自動修正し,それ以外は台帳へ報告)→ `fix/` 専用ブランチ + ## 進捗記録の運用ルール(CLAUDE.md / PROGRESS.md) +> ⚠ **チーム開発モード(team)では本節は上書きされる**.team プロジェクトでは進捗を `CLAUDE.md`・`docs/PROGRESS.md` に書かず,GitHub Issues と git 履歴で追う([GUIDE_06](GUIDE_06_チーム開発ルール.md)).以下は個人開発モード(solo)の既定ルールである.team モードでは Phase 4 の進捗更新を Issue コメント(`/task-handoff` 等)に置き換える. + 進捗記録は **2 ファイルの二段構成**で管理する.Phase 4 や `/setup` 中断時にこれらを更新する. | ファイル | 役割 | 更新方法 | diff --git "a/docs/01_GUIDE/GUIDE_06_\343\203\201\343\203\274\343\203\240\351\226\213\347\231\272\343\203\253\343\203\274\343\203\253.md" "b/docs/01_GUIDE/GUIDE_06_\343\203\201\343\203\274\343\203\240\351\226\213\347\231\272\343\203\253\343\203\274\343\203\253.md" new file mode 100644 index 0000000..44ba076 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_06_\343\203\201\343\203\274\343\203\240\351\226\213\347\231\272\343\203\253\343\203\274\343\203\253.md" @@ -0,0 +1,142 @@ +# チーム開発ルール (Team Development Rules) + +チーム全員が Claude Code を用い,人間が直接コードを書くことはほぼない前提で,並行開発を破綻させずに進めるための協調ルールを定義する. + +> 本ガイドは**チーム開発モード**(`/setup` で team を選択したプロジェクト)でのみ有効.個人開発モード(solo)のプロジェクトには本ファイル・GUIDE_07・`task-*` コマンドは配置されない. + +Git の手順は [GUIDE_04](GUIDE_04_Git運用ルール.md),1 タスクの実装パイプラインは [GUIDE_05](GUIDE_05_エージェント運用ルール.md) に従う.本ガイドはそれらの上に立つ「複数人が同時に動くときの調整」を扱う. + +## 基本方針 (Basic Policy) + +- 全員が Claude Code で開発し,実装はエージェントが行う(チーム規模はプロジェクトによる). +- 原則として並行作業を行わず,1 人ずつ直列で開発する.急ぎではないため,スループットより単純さと `main` の整合性を優先する.これは禁止ではなく既定のスタンスであり,状況に応じた判断は妨げない(詳細は「作業の直列化」). +- 人間の本質的な役割は「AI にできない判断と確認」(GUIDE_05 と同じ).加えて「共有設定の番人」を担う. +- 進捗・タスクは GitHub Issues と git 履歴で追う.`CLAUDE.md` には進捗を書かない(この点は GUIDE_05 の進捗記録ルールを**上書き**する). +- `main` は常に動作可能な状態を保つ(GUIDE_04).壊れたら他の作業より優先して直す. + +## タスク管理 (Task Management) + +進捗管理の補助として GitHub Issues と Projects を用いる.`gh` コマンドでの具体的な操作手順は [GUIDE_07](GUIDE_07_Issues・Projects運用ガイド.md) を参照. + +### Issue (Issue) + +Issue は**進捗管理の補助**として使う.追跡したい作業に対して立て,PR と紐付けてボードで可視化する. + +- 作業 1 単位 = 1 Issue を推奨する.既に Issue がある作業は,新たに作らずそれに従って進める(重複 Issue を作らない). +- **Issue は着手・PR 作成・マージのいずれの段階でも必須としない**.小さい変更(typo・1 行修正等)や試験的・探索的な作業は Issue 無しで進めてよい. +- ただし**追跡する価値のある作業には Issue を立てるのが望ましい**(後追いと進捗可視化のため).特に複数回の `/implement` に跨る作業や,他メンバーに見えていてほしい作業は Issue を作る. +- PR と Issue を紐付ける場合は本文に `Closes #` を記載する.マージ時に Issue が自動クローズされ,ボードのカードも `Done` へ移る. +- Issue 本文には少なくとも「やること」を書く.「完了条件(受け入れ基準)」は非自明な作業のみで構わない. +- 担当者は明確にしておくのが望ましい(重複着手を避けるため). +- Issue は最初に書き切らなくてよい.`/implement` の Phase 4 で実装サマリーを Issue にコメントし,必要に応じて本文も育てる(GUIDE_05). + +### Project ボード (Project Board) + +> ⚠ **既定では未使用**.タスク管理は Issue ベース(`gh issue list`)で運用する.Project ボードはチームが拡大したり Issue が常時 10 件超になった等の局面で再導入する想定.以下は将来導入時の参考. + +- 列: `Todo` / `In Progress` / `In Review` / `Done`. +- Issue をカードとして配置し,状態を移動して可視化する. +- マージ連動の自動化を設定し,カード移動の手作業を最小化する(設定は管理者作業.「管理者の初期設定」参照). + +### タスクの流れ (Task Flow) + +Issue を立てる場合の標準フロー(小さい変更や探索的作業はこの限りでない). + +```text +1. Issue 起票(完了条件を明記) +2. 自分にアサイン(ボード未使用のためアサインのみ.ボード運用復活時は In Progress へ移動) +3. main から作業ブランチ作成(GUIDE_04) +4. /implement に Issue の内容を渡して実装(GUIDE_05) +5. PR 作成,本文に "Closes #<番号>" +6. セルフマージ条件を確認 → マージ +7. マージで Issue 自動クローズ → カード自動 Done +``` + +- 上記 1 は `/task-create`(事前定義用),2 と 3 は `/task-start `(既存 Issue から着手)で半自動化できる.Issue 無しで進める場合はどちらも不要. +- Claude へのタスク文脈は `CLAUDE.md` ではなく Issue から渡す.`gh issue view ` で取得する. + +## ブランチと PR (Branch & PR) + +[GUIDE_04](GUIDE_04_Git運用ルール.md) に従う.チーム運用上の追加事項のみ以下に定める. + +- ブランチ命名は GUIDE_04 の基本形式(`[プレフィックス][概要]`)に従う.ブランチ名に Issue 番号は含めなくてよい. +- branch↔Issue の紐付けは PR 本文の `Closes #<番号>` で行う.マージ時に Issue が自動クローズされる.既存 Issue からブランチを作る場合は `gh issue develop` でネイティブにリンクできる(GUIDE_07). +- PR の `--title` はコミットメッセージと同じ書式(`[タグ] 内容`,GUIDE_04). + +## レビューとマージ (Review & Merge) + +誰も手書きしない体制では,マージ条件が唯一の品質ゲートとなる.本プロジェクトは**条件付きセルフマージ**を採用する.他メンバーの Approve 待ちは原則作らない代わりに,作者自身が満たすべき条件を実質的なゲートとして定める. + +### 通常の機能 PR (Feature PR) + +次を全て満たせば,作者がセルフマージしてよい. + +- CI で全テストが緑である. +- 作者自身が Phase 1 の動作確認(実機・ブラウザ等,AI にできない確認)を済ませている(GUIDE_05). +- `/implement` のパイプラインをスキップせず完走している. +- 対応 Issue がある場合は完了条件を満たしている(Issue 無しの PR は不要). +- 共有設定(`CLAUDE.md` のルール部・`.claude/`)の変更を含まない. + +※ レビューは任意.他メンバーはコメントしてよいが,マージをブロックしない. + +### 共有設定を変更する PR (Shared Config PR) + +`CLAUDE.md` のルール部や `.claude/` を変更する PR は,全員の Claude の挙動を変えるため例外とする. + +- 機能 PR に混ぜず,専用 PR とする(「共有設定の扱い」参照). +- 他メンバー 1 名の Approve を必須とする(セルフマージ不可). + +### CI 構築までの暫定ゲート (Interim Gate) + +CI が未構築の間は「CI 緑」を以下で代替する.CI 構築後はこの節を削除する. + +- `/implement` を完走している. +- ローカルで全テストが緑である. +- 作者自身が Phase 1 の動作確認を済ませている. + +## 共有設定の扱い (Shared Configuration) + +`CLAUDE.md` と `.claude/`(agents・commands・hooks・settings.json)は全員の Claude の挙動を決める共有インフラである. + +- **git 追跡を継続する**.untrack や `.gitignore` 化はしない(履歴の保全と挙動の統一のため). +- **進捗は `CLAUDE.md` に書かない**.進捗は Issues と git 履歴で追う(「タスク管理」参照). +- **変更は「チームルール変更」カテゴリ**として扱う. + - 機能 PR に混ぜない.専用 PR とする(ブランチは `chore/` または `docs/`). + - 他メンバー 1 名の Approve を必須とする. + - マージ後はチームに周知し,全員が `git pull` して Claude セッションを再起動する. + - ※ Claude はセッション開始時に `CLAUDE.md` を読むため,古いまま動くと文脈がずれる. +- **例外: ドキュメント一覧への追記**は,そのドキュメントを追加する PR と同じ PR で行ってよい.衝突しても両方の行を残せば解決できる. +- **個人・マシン固有の設定**は `.claude/settings.local.json` に置く.これは `.gitignore` 対象とし,共有の `settings.json` を個人都合で汚さない. + +## 作業の直列化 (Serialized Work) + +- 原則として,同時に進行中のコード作業は 1 件とする(進行中の Issue は原則 1 件.Project ボード運用復活時は `In Progress` 列も同様). +- 次の作業に着手してよいのは,前の作業の PR が `main` にマージされた後とする(マージ条件は「レビューとマージ」参照). +- タスクは小さく保つ.直列運用では,1 単位が小さいほど次の人の待ち時間が短くなる. +- 直列運用により並行コンフリクトと共有設定のドリフトは原理的にほぼ発生しない.例外的に並行が生じてコンフリクトした場合は GUIDE_04 の rebase 手順をフォールバックとして用いる. +- `main` を壊した場合は他作業より優先して復旧する.自分で対処できない場合は直ちにチームへ報告する(GUIDE_04). + +## メンバーのオンボーディング (Onboarding) + +新メンバー参加時の手順. + +1. リポジトリへのコラボレーター招待を承認する(GitHub の通知,または `https://github.com///invitations`). +2. リポジトリを clone する. +3. `ENV_02_環境構築手順.md`(GUIDE_01 参照,立ち上げ時に作成)に従い開発環境を構築する. +4. `gh auth login` で GitHub CLI を認証する.Projects も操作する場合は `project` スコープを含める(GUIDE_07「必要なスコープ」). +5. 必要なら `.claude/settings.local.json` を用意する(個人設定.git 追跡されない). +6. 最初に `CLAUDE.md` と `docs/01_GUIDE/` を読む(特に本ガイド・GUIDE_04・GUIDE_05・GUIDE_07). +7. `.gitignore` が整備されていることを確認する(GUIDE_04). + +## 管理者の初期設定 (Admin Setup) + +以下は外部サービス操作を含み,AI には実施できない.ルール確定後に管理者(人間)が一度だけ行う. + +- GitHub リポジトリの作成,メンバー招待. +- (既定では未使用)GitHub Project の作成,列(`Todo` / `In Progress` / `In Review` / `Done`)の定義. +- (既定では未使用)マージ連動の自動化設定(PR マージ時に Issue クローズ・カードを `Done` へ移動). +- Issue テンプレートの用意(「やること」「完了条件」欄). +- 共有設定変更 PR に他メンバー Approve を求める運用の周知(必要なら `main` のブランチ保護設定). +- CI の構築(全テストを実行し,緑をマージ条件にできる状態にする). + +※ 完了するまでは本ガイドの「CI 構築までの暫定ゲート」を適用する. diff --git "a/docs/01_GUIDE/GUIDE_07_Issues\343\203\273Projects\351\201\213\347\224\250\343\202\254\343\202\244\343\203\211.md" "b/docs/01_GUIDE/GUIDE_07_Issues\343\203\273Projects\351\201\213\347\224\250\343\202\254\343\202\244\343\203\211.md" new file mode 100644 index 0000000..629ee09 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_07_Issues\343\203\273Projects\351\201\213\347\224\250\343\202\254\343\202\244\343\203\211.md" @@ -0,0 +1,136 @@ +# Issues・Projects 運用ガイド (Issues & Projects Operations Guide) + +GitHub Issues と Projects を `gh` コマンドで操作する手順を定義する.人間も AI(Claude Code)も同じコマンドで操作する. + +> ⚠ **Projects の操作は現時点では未使用**.本ガイドの「Projects の操作」セクションは将来導入時の参考として残す.現状の運用は Issue ベースで完結する([GUIDE_06](GUIDE_06_チーム開発ルール.md)).Issue 操作・タスクライフサイクルは引き続き本ガイドの該当セクションを参照する. + +タスク管理の方針(Issue = 作業単位,ボードの列,直列運用等)は [GUIDE_06](GUIDE_06_チーム開発ルール.md) に従う.本ガイドはその操作手順を扱う. + +## 基本方針 (Basic Policy) + +- 操作は GitHub CLI(`gh`)に統一する.Web UI でも同じことはできるが,再現性とドキュメント化のため `gh` を基準とする. +- Issue がタスクの単位であり,`/implement` の入力でもある(GUIDE_06). +- AI に Issue を読ませる場合は `gh issue view ` を使う. + +### 必要なスコープ (Required Scopes) + +`gh` のトークンスコープが操作範囲を決める. + +| 操作 | 必要スコープ | +| --- | --- | +| Issues の読み書き | `repo` | +| Projects の読み書き | `repo` + `project` | + +スコープの確認と追加: + +```bash +gh auth status # 現在のスコープを確認 +gh auth refresh -s project # Projects 用スコープを追加(対話的な再認証が走る) +``` + +## Issues の操作 (Issues) + +### 参照 (View) + +```bash +gh issue list # 一覧 +gh issue list --assignee @me # 自分の担当のみ +gh issue list --state open # 未クローズのみ +gh issue view # 詳細表示 +gh issue view --json title,body,assignees,labels # 構造化出力(AI への受け渡し等) +``` + +### 作成 (Create) + +```bash +gh issue create --title "<タイトル>" --body "<本文>" +``` + +- 本文には「やること」と「完了条件(受け入れ基準)」を必ず書く(GUIDE_06). +- `--assignee <ユーザー名>`,`--label <ラベル>` で担当・ラベルを同時に指定できる. + +### 更新・コメント・状態変更 (Edit / Comment / State) + +```bash +gh issue edit --add-assignee @me # 自分をアサイン +gh issue edit --add-label "<ラベル>" # ラベル追加 +gh issue comment --body "<コメント>" # コメント追加 +gh issue close # クローズ +gh issue reopen # 再オープン +``` + +## Projects の操作 (Projects) + +※ `gh project` 系は `project` スコープが必要(「必要なスコープ」参照).`` はリポジトリ所有者(個人またはオーガニゼーション). + +### 参照 (View) + +```bash +gh project list --owner # プロジェクト一覧(Project 番号を確認) +gh project view --owner # プロジェクトの概要 +gh project item-list --owner # ボード上のアイテム一覧 +gh project field-list --owner # フィールド(Status 等)と選択肢の ID を確認 +``` + +### Issue をボードに追加 (Add) + +```bash +gh project item-add --owner --url +``` + +### カードの状態(列)を移す (Move) + +`Status` フィールドの選択肢(`Todo` / `In Progress` 等)を変更する.フィールド ID と選択肢 ID は `field-list` で確認する. + +```bash +gh project item-edit \ + --id <アイテム ID> \ + --project-id <プロジェクト ID> \ + --field-id \ + --single-select-option-id <移動先の選択肢 ID> +``` + +※ ID の確認が煩雑なため,日常のカード移動は Web UI のボードで行い,一覧取得や自動化に `gh` を使う,という使い分けでもよい. + +## タスクのライフサイクル (Task Lifecycle) + +GUIDE_06 の「タスクの流れ」を `gh` コマンドで具体化したもの. + +※ ステップ 1 は `/task-create <タスクの説明>` で,ステップ 2〜4 は `/task-start ` で半自動化できる.以下は手動でも行える操作の参照. + +1. **Issue 起票**(完了条件を明記) + + ```bash + gh issue create --title "<タイトル>" --body "<やること・完了条件>" + ``` + +2. **アサインしてボードを In Progress へ** + + ```bash + gh issue edit --add-assignee @me + gh project item-add --owner --url # 未追加の場合 + ``` + + ボードの `Status` を `In Progress` に移す(`item-edit` または Web UI). + +3. **作業ブランチ作成**(GUIDE_04 の基本形式) + + ```bash + git checkout main && git pull origin main + git checkout -b feature/<概要> + ``` + + ※ 既存 Issue から作る場合は `gh issue develop --name feature/<概要> --base main` を使うと,ブランチ作成と Issue↔ブランチのリンクを同時に行える(ブランチ名に依存しないリンク手段). + +4. **実装**: `gh issue view ` で本文を取得し,`/implement` に渡す(GUIDE_05). + +5. **PR 作成**: 本文に `Closes #` を記載する(GUIDE_04). + +6. **マージ**: マージで Issue は自動クローズされ,連動設定があればカードも `Done` へ移る(自動化設定は管理者作業.GUIDE_06「管理者の初期設定」). + +## トラブルシューティング (Troubleshooting) + +- **`gh project` の書き込み系が無反応に見える**: `create` / `item-add` / `item-edit` は成功しても標準出力が空のことがある.`gh project list` / `item-list` で結果を確認する. +- **`gh project` がスコープエラーになる**: `project` スコープが未付与.`gh auth refresh -s project` を実行する. +- **コラボレーターが操作できない**: 招待を承認していない.`gh api "repos///collaborators" --jq '.[].login'` で承認済みメンバーを確認する. +- **`item-edit` の ID がわからない**: `gh project item-list` でアイテム ID,`gh project field-list` でフィールド ID・選択肢 ID を確認する.