--- name: infer-intent description: Git履歴から設計意図・歴史的文脈を推論し、変更の背景を理解 user-invocable: true argument-hint: [ファイルパスまたはドメイン名] allowed-tools: Read, Grep, Glob, Bash context: fork --- # civicship-api 設計意図推論 Git履歴・コミットメッセージから**設計の意図**や**歴史的文脈**を推論します。なぜこのコードがこう書かれているのか、過去の変更理由を理解することで、安全な変更を支援します。 ## 使用方法 ```bash # 特定ファイルの設計意図を推論 /infer-intent src/application/domain/account/wallet/service.ts # ドメイン全体の歴史を分析 /infer-intent wallet # 特定の実装パターンの理由を調査 /infer-intent "なぜWalletServiceはトランザクションを必須にしているのか" ``` **引数:** - `$ARGUMENTS`: ファイルパス、ドメイン名、または質問 --- ## 意図推論プロセス ### ステップ1: Git履歴の取得 対象ファイル・ドメインのコミット履歴を取得: ```bash # ファイルの全履歴 git log --follow --oneline src/application/domain/account/wallet/service.ts # 詳細な変更履歴 git log -p --follow src/application/domain/account/wallet/service.ts # 特定期間のコミット git log --since="1 year ago" --oneline -- src/application/domain/account/wallet # コミット統計 git log --stat --oneline -- src/application/domain/account/wallet ``` **履歴レポート:** ```markdown ## Git履歴の概要 ### 変更統計 | 項目 | 値 | |------|-----| | 総コミット数 | 45件 | | 最初のコミット | 2023-06-20 | | 最新のコミット | 2026-01-10 | | 期間 | 2年7ヶ月 | | 主要コントリビューター | 3名 | --- ### コミット頻度 | 期間 | コミット数 | |------|-----------| | 2023年 | 12件 | | 2024年 | 20件 | | 2025年 | 10件 | | 2026年 | 3件 | **トレンド:** 2024年にピーク(機能追加が活発) --- ### 主要なコミット #### 1. 初期実装(2023-06-20) ``` commit a1b2c3d feat: Add wallet domain with basic CRUD operations ``` **変更内容:** - WalletService, WalletRepository の初期実装 - 基本的なCRUD操作のみ --- #### 2. トランザクション対応(2023-08-15) ``` commit e4f5g6h fix: Add transaction support to wallet operations ``` **変更内容:** - すべてのメソッドに `tx` パラメータ追加 - トランザクション内での操作を保証 **理由(コミットメッセージから推論):** - ポイント送受信で不整合が発生したバグ修正 - トランザクションなしでは残高計算にレースコンディション --- #### 3. バリデーション強化(2024-02-10) ``` commit i7j8k9l feat: Add strict validation for negative balance ``` **変更内容:** - 残高がマイナスにならないチェック追加 **理由:** - 本番環境でマイナス残高が発生 - ビジネスルール違反を防ぐため --- #### 4. パフォーマンス最適化(2024-06-20) ``` commit m1n2o3p perf: Optimize wallet balance calculation with cache ``` **変更内容:** - 残高計算にキャッシュ導入 - クエリ回数を削減 **理由:** - ユーザー増加によりレスポンスタイム劣化 - 100ms → 30ms に改善 --- #### 5. セキュリティ修正(2025-03-15) ``` commit q4r5s6t security: Add RLS to all wallet queries ``` **変更内容:** - すべてのクエリに `ctx.issuer` を適用 **理由:** - 他ユーザーのウォレット情報が見えるバグ - セキュリティ監査で指摘 ``` --- ### ステップ2: コミットメッセージの分析 コミットメッセージから設計判断を推論: ```markdown ## コミットメッセージ分析 ### カテゴリ別の分類 | カテゴリ | 件数 | 割合 | |---------|------|------| | feat (機能追加) | 18件 | 40% | | fix (バグ修正) | 12件 | 27% | | perf (パフォーマンス) | 5件 | 11% | | security (セキュリティ) | 3件 | 7% | | refactor (リファクタリング) | 4件 | 9% | | test (テスト) | 3件 | 7% | **傾向:** 機能追加が多いが、バグ修正も頻繁 --- ### 頻出キーワード分析 | キーワード | 出現回数 | 文脈 | |-----------|---------|------| | transaction | 8回 | トランザクション対応 | | validation | 6回 | バリデーション強化 | | balance | 10回 | 残高計算ロジック | | security | 5回 | セキュリティ修正 | | performance | 4回 | パフォーマンス改善 | **解釈:** - トランザクションが重要な関心事 - 残高計算は複雑で頻繁に修正 - セキュリティ問題が過去に複数回発生 --- ### 重要な設計決定 #### 決定1: トランザクション必須化 **コミット:** e4f5g6h (2023-08-15) **メッセージ:** ``` fix: Add transaction support to wallet operations ポイント送受信でレースコンディションが発生し、 残高の不整合が発生した。 今後すべてのウォレット操作はトランザクション内で 実行することを必須とする。 ``` **推論される意図:** - データ整合性が最優先 - 並行アクセスでのレースコンディションを防ぐ - パフォーマンスよりも正確性を重視 --- #### 決定2: マイナス残高の禁止 **コミット:** i7j8k9l (2024-02-10) **メッセージ:** ``` feat: Add strict validation for negative balance 本番環境でマイナス残高が発生したため、 厳密なバリデーションを追加。 ポイント使用時に残高不足の場合はエラーを返す。 ``` **推論される意図:** - ビジネスルール: ポイントは借金できない - 既存のバリデーションが不十分だった - 信頼性向上のための防御的プログラミング --- #### 決定3: キャッシュ導入 **コミット:** m1n2o3p (2024-06-20) **メッセージ:** ``` perf: Optimize wallet balance calculation with cache ユーザー増加によりウォレットクエリが ボトルネックになっていた。 残高計算に10秒のキャッシュを導入し、 レスポンスタイムを100ms→30msに改善。 ``` **推論される意図:** - スケーラビリティへの対応 - リアルタイム性よりパフォーマンスを優先(10秒は許容) - 将来的なユーザー増加を見越した設計 --- #### 決定4: RLS(Row-Level Security)の徹底 **コミット:** q4r5s6t (2025-03-15) **メッセージ:** ``` security: Add RLS to all wallet queries セキュリティ監査で、一部のクエリでRLSが 適用されていないことが判明。 全てのクエリで ctx.issuer を使用するよう修正。 ``` **推論される意図:** - セキュリティが最重要課題 - 一度でも情報漏洩があった(またはリスクがあった) - 再発防止のための徹底的な対策 ``` --- ### ステップ3: コード変更パターンの分析 コード変更の傾向から設計思想を推論: ```bash # ファイルパスを引数から取得 FILE_PATH="${ARGUMENTS}" # 追加された行数と削除された行数 git log --stat --oneline -- "${FILE_PATH}" | \ grep "$(basename "${FILE_PATH}")" | awk '{sum+=$4} END {print sum}' # 特定関数の変更履歴(例: createWallet関数) git log -L :createWallet:"${FILE_PATH}" ``` **変更パターンレポート:** ```markdown ## コード変更パターン ### メソッド別の変更頻度 | メソッド | 変更回数 | 最終変更日 | |---------|---------|-----------| | createWallet | 8回 | 2025-01-10 | | findByUserId | 12回 | 2024-11-20 | | transferPoints | 15回 | 2025-12-05 | | calculateBalance | 10回 | 2024-06-20 | **解釈:** - `transferPoints` が最も変更が多い(複雑なロジック) - `findByUserId` も頻繁に変更(セキュリティ、パフォーマンス改善) --- ### createWallet メソッドの進化 #### Version 1(2023-06-20) ```typescript async createWallet(userId: string) { return this.repo.create({ userId, balance: 0 }); } ``` **特徴:** シンプル、トランザクションなし --- #### Version 2(2023-08-15) ```typescript async createWallet(userId: string, tx: Prisma.TransactionClient) { return this.repo.create({ userId, balance: 0 }, tx); } ``` **変更:** トランザクション対応 --- #### Version 3(2024-02-10) ```typescript async createWallet(ctx: IContext, userId: string, tx: Prisma.TransactionClient) { // バリデーション追加 const existing = await this.repo.findByUserId(ctx, userId, tx); if (existing) { throw new Error("WALLET_ALREADY_EXISTS"); } return this.repo.create({ userId, balance: 0 }, tx); } ``` **変更:** 重複チェック追加 --- #### Version 4(現在) ```typescript async createWallet( ctx: IContext, input: GqlWalletCreateInput, communityId: string, tx: Prisma.TransactionClient ): Promise { // バリデーション const existing = await this.repo.findByUserId(ctx, input.userId, tx); if (existing) { throw new Error("WALLET_ALREADY_EXISTS"); } // 入力変換 const data = this.converter.toCreateData(input, communityId); // 作成 return await this.repo.create(ctx, data, tx); } ``` **変更:** Clean Architecture パターンに準拠、Converter導入 **推論:** - 段階的にアーキテクチャを改善 - 最初はシンプルだったが、バグを経験して厳格化 - 最終的にDDDパターンに完全準拠 ``` --- ### ステップ4: 関連IssueとPRの調査 GitHubのIssue/PRから背景を調査: ```bash # 関連PRを検索 gh pr list --search "wallet" --state all --limit 20 # 特定PRの詳細(PR番号を引数から取得) PR_NUMBER="${ARGUMENTS}" gh pr view "$PR_NUMBER" # PRのコメントを確認 gh api repos/Hopin-inc/civicship-api/pulls/"$PR_NUMBER"/comments ``` **Issue/PR分析:** ```markdown ## 関連Issue/PRの分析 ### 重要なPR #### PR #45: トランザクション対応 **タイトル:** Add transaction support to wallet operations **作成日:** 2023-08-15 **状態:** Merged **説明:** ``` ## 問題 ポイント送受信で以下のバグが発生: 1. ユーザーAが100ptをユーザーBに送信 2. 同時にユーザーBが100ptをユーザーAに送信 3. 両者のポイントが増加(残高の不整合) ## 原因 トランザクション管理がなく、レースコンディション ## 対策 すべてのウォレット操作をトランザクション内で実行 ``` **レビューコメント:** - "トランザクションを必須にするのは良い判断" - "パフォーマンスへの影響は?" → "問題なし、10ms以下" **推論:** - 実際に本番でバグが発生していた - データ整合性を最優先する文化 - パフォーマンスよりも正確性 --- #### PR #78: セキュリティ修正 **タイトル:** Add RLS to all wallet queries **作成日:** 2025-03-15 **状態:** Merged **説明:** ``` ## 問題 セキュリティ監査で指摘: ユーザーAが他ユーザーのウォレット情報を取得可能 ## 原因 一部のクエリで ctx.issuer を使用していない ## 対策 全てのRepositoryメソッドでRLSを適用 ``` **レビューコメント:** - "Critical なセキュリティバグ、即座にマージすべき" - "テストカバレッジを100%にして" **推論:** - セキュリティインシデントが発生した可能性 - 監査プロセスが機能している - セキュリティを非常に重視 ``` --- ### ステップ5: コードレビューコメントの分析 過去のコードレビューから設計思想を推論: ```bash # PRのレビューコメントを取得 gh api repos/Hopin-inc/civicship-api/pulls/45/reviews ``` **レビューコメント分析:** ```markdown ## コードレビューから見える設計思想 ### 頻出するレビュー指摘 #### 1. トランザクション管理 **コメント例:** ``` このメソッドはトランザクション内で呼ばれる可能性があるので、 tx パラメータを追加してください。 ``` **頻度:** 10回以上 **推論される原則:** - トランザクション管理は必須 - 全てのメソッドで tx を伝播すべき - データ整合性への強いこだわり --- #### 2. エラーハンドリング **コメント例:** ``` バリデーションエラーは Error ではなく、 ビジネス例外クラスを使ってください。 ``` **頻度:** 5回以上 **推論される原則:** - エラーを適切に分類 - クライアントに意味のあるエラーメッセージ - デバッグしやすいコード --- #### 3. テストカバレッジ **コメント例:** ``` このメソッドのテストが不足しています。 エッジケースもカバーしてください。 ``` **頻度:** 8回以上 **推論される原則:** - テストを重視 - カバレッジ目標: 90%以上 - エッジケースを見逃さない --- #### 4. パフォーマンス **コメント例:** ``` このクエリはN+1問題を引き起こします。 DataLoaderを使用してください。 ``` **頻度:** 3回以上 **推論される原則:** - パフォーマンスを意識 - N+1問題は許容しない - スケーラビリティを考慮 ``` --- ### ステップ6: チーム文化の推論 コミットメッセージ、PR、レビューから組織文化を推論: ```markdown ## チーム文化の推論 ### 開発プロセス #### コードレビュー文化 - **全PRにレビュー必須** - 平均レビュー数: 2-3名 - レビュー期間: 1-2日 - マージ条件: 全レビュアーの承認 + CI通過 **推論:** - 品質を重視する文化 - チーム間のナレッジ共有 - 属人化を防ぐ仕組み --- #### テスト文化 - **テストなしのPRはマージされない** - カバレッジ目標: 90% - E2Eテストも重視 **推論:** - テスト駆動開発(TDD)に近い文化 - 品質保証を最優先 --- #### セキュリティ意識 - **セキュリティ監査を定期実施** - RLSを徹底 - センシティブデータの取り扱いに厳格 **推論:** - 金融系・個人情報を扱うプロダクト - セキュリティインシデントを経験している可能性 - コンプライアンスを重視 --- ### 技術的な価値観 #### 優先順位 1. **正確性 > パフォーマンス** - トランザクション必須化 - 厳格なバリデーション 2. **セキュリティ > 利便性** - 全クエリにRLS - 認証・認可の徹底 3. **保守性 > 開発速度** - Clean Architecture準拠 - リファクタリングを厭わない 4. **テスト > 機能追加** - 高いカバレッジ要求 - エッジケースの網羅 **推論:** - 長期的な運用を見据えた設計 - 技術的負債を許容しない文化 ``` --- ### ステップ7: 設計パターンの推論 コードの進化から設計パターンを推論: ```markdown ## 設計パターンの進化 ### パターン1: トランザクション管理 **進化:** ``` V1: トランザクションなし ↓ V2: 一部のメソッドにトランザクション ↓ V3: 全メソッドでトランザクション必須 ↓ V4: UseCaseでトランザクション管理、Serviceは伝播のみ ``` **推論される設計思想:** - レイヤー責任の明確化 - UseCaseがトランザクション境界 - Serviceはビジネスロジックのみ --- ### パターン2: エラーハンドリング **進化:** ``` V1: 例外をそのままthrow ↓ V2: カスタムエラークラス導入 ↓ V3: エラーコードの統一 ↓ V4: GraphQLエラーとの統合 ``` **推論される設計思想:** - ユーザーフレンドリーなエラーメッセージ - デバッグしやすいエラー情報 - クライアント側での適切なハンドリング --- ### パターン3: データアクセス **進化:** ``` V1: Serviceが直接Prismaを呼ぶ ↓ V2: Repository層を導入 ↓ V3: Converter層を導入(入力変換) ↓ V4: Presenter層を導入(出力変換) ``` **推論される設計思想:** - Clean Architectureへの段階的移行 - 各レイヤーの責任を明確化 - テストしやすい構造 ``` --- ### ステップ8: 技術的決定の背景推論 なぜこの技術選択をしたのかを推論: ```markdown ## 技術的決定の背景 ### 決定1: Prisma ORM 採用 **推論される理由:** 1. **型安全性:** TypeScriptとの親和性 2. **マイグレーション:** スキーマ管理が容易 3. **開発効率:** 生SQLを書く必要がない 4. **コミュニティ:** 活発なエコシステム **裏付け:** - 初期コミットからPrisma使用 - マイグレーションファイルが整然と管理されている - Prisma独自の機能(RLS、トランザクション)を活用 --- ### 決定2: GraphQL 採用 **推論される理由:** 1. **柔軟性:** クライアントが必要なデータのみ取得 2. **型安全性:** スキーマ駆動開発 3. **フロントエンドとの親和性:** React/Apollo との統合 4. **N+1防止:** DataLoaderでパフォーマンス最適化 **裏付け:** - DataLoaderの積極的な活用 - GraphQL Code Generatorでの型生成 - スキーマファーストな開発プロセス --- ### 決定3: tsyringe(DI) 採用 **推論される理由:** 1. **テスタビリティ:** モック化が容易 2. **疎結合:** 依存関係の明確化 3. **保守性:** インターフェースベースの設計 4. **スケーラビリティ:** 依存関係の管理が容易 **裏付け:** - 全てのクラスで `@injectable()` を使用 - テストでのモック差し替えが一貫している - インターフェース(IXxxRepository)の徹底 ``` --- ### ステップ9: 暗黙的な制約の発見 コードから暗黙的なビジネスルール・制約を推論: ```markdown ## 暗黙的な制約 ### 制約1: 1ユーザー = 1ウォレット **コード:** ```typescript const wallet = await this.repo.findByUserId(ctx, userId, tx); // 配列ではなく単一オブジェクトを返す ``` **推論:** - ビジネスルール: ユーザーは1つのウォレットのみ - 将来的に複数ウォレット対応は想定外 - データモデル: `userId UNIQUE` 制約 --- ### 制約2: ポイントは整数のみ **コード:** ```typescript balance: Int // Prismaスキーマ ``` **推論:** - ビジネスルール: 小数点以下のポイントは存在しない - 1pt = 最小単位 - 将来的に小数対応は大きな変更 --- ### 制約3: マイナス残高は許容しない **コード:** ```typescript if (balance < requiredPoints) { throw new Error("INSUFFICIENT_BALANCE"); } ``` **推論:** - ビジネスルール: 借金(マイナス残高)は不可 - 前払いシステム - 与信機能は存在しない --- ### 制約4: ポイント送受信は同一コミュニティ内のみ **コード:** ```typescript const fromWallet = await this.repo.findByCommunity(ctx, fromUserId, communityId, tx); const toWallet = await this.repo.findByCommunity(ctx, toUserId, communityId, tx); ``` **推論:** - ビジネスルール: コミュニティをまたいだポイント移動は不可 - コミュニティごとに独立した経済圏 - 将来的にクロスコミュニティ機能は大きな変更 ``` --- ### ステップ10: 意図推論レポートの生成 ```markdown # 設計意図推論レポート **対象:** WalletService **分析日:** 2026-01-15 --- ## エグゼクティブサマリー ### 設計の核心 **このコードは何のために存在するか:** - ポイント経済システムの中核 - データ整合性とセキュリティを最優先 - スケーラブルで保守しやすい設計 **主要な設計判断:** 1. トランザクション必須化(データ整合性) 2. RLS徹底(セキュリティ) 3. Clean Architecture準拠(保守性) 4. 厳格なバリデーション(信頼性) --- ## 歴史的文脈 ### タイムライン **2023年6月:** 初期実装 - シンプルなCRUD操作 - トランザクション未対応 **2023年8月:** レースコンディション発生 - 本番でバグ → トランザクション必須化 - データ整合性への意識向上 **2024年2月:** マイナス残高バグ - バリデーション不足 → 厳格化 - 防御的プログラミングへ **2024年6月:** スケーラビリティ問題 - ユーザー増加 → パフォーマンス最適化 - キャッシュ導入 **2025年3月:** セキュリティ監査 - RLS漏れ → 全面適用 - セキュリティ最優先へ --- ## 変更時の注意事項 ### してはいけないこと 1. **トランザクションを削除しない** - 理由: 過去にレースコンディションで不整合発生 - 正確性 > パフォーマンス 2. **RLSをスキップしない** - 理由: セキュリティ監査で指摘された過去あり - 全クエリで `ctx.issuer` 必須 3. **バリデーションを緩和しない** - 理由: マイナス残高バグの再発防止 - ビジネスルールの厳格な適用 4. **1ユーザー1ウォレットの前提を崩さない** - 理由: システム全体がこの前提で設計 - 変更は全体への影響大 --- ### 推奨される変更方法 **新機能追加時:** 1. 既存のトランザクションパターンに従う 2. テストカバレッジ 90%以上 3. セキュリティレビュー必須 **パフォーマンス改善時:** 1. 正確性を損なわない 2. キャッシュ導入は慎重に 3. ベンチマークで検証 **リファクタリング時:** 1. Clean Architecture パターンを維持 2. レイヤー責任を明確に 3. 段階的に実施 --- ## 将来の方向性 ### 予想される課題 1. **複数ウォレット対応** - 現状: 1ユーザー1ウォレット - 変更影響: システム全体 2. **クロスコミュニティ送金** - 現状: 同一コミュニティ内のみ - 変更影響: トランザクション境界の再設計 3. **小数点ポイント対応** - 現状: 整数のみ - 変更影響: 型定義、計算ロジック全体 --- ## 参考資料 - PR #45: トランザクション対応 - PR #78: セキュリティ修正 - Issue #23: マイナス残高バグ - Issue #67: パフォーマンス劣化 ``` --- ## 活用例 ### 例1: なぜこのコードがこう書かれているか ```bash /infer-intent "WalletServiceのtxパラメータが必須な理由" ``` **出力:** - Git履歴からレースコンディションのバグを発見 - トランザクション必須化の背景を説明 --- ### 例2: 変更してはいけない箇所の特定 ```bash /infer-intent src/application/domain/account/wallet/service.ts ``` **出力:** - 過去のバグ修正履歴 - 変更時の注意事項 --- ## 注意事項 ### 推論の限界 - ❌ コミットメッセージが不明確な場合、推論不可 - ❌ 口頭での決定事項は把握できない - ❌ ビジネス要件の詳細は不明 ### 推奨される使い方 - ✅ 変更前に設計意図を理解 - ✅ 新メンバーのオンボーディング - ✅ リファクタリング前の調査 --- ## 参考資料 以下については `@CLAUDE.md` を参照してください: - アーキテクチャパターン - トランザクション管理 - RLSの使い方