From 8d7e2d9367fee68dbe1e14d04f5002d4ea141375 Mon Sep 17 00:00:00 2001 From: Wada Yusuke Date: Mon, 22 Jun 2026 20:44:35 +0900 Subject: [PATCH] =?UTF-8?q?docs(claude):=20PR=20=E4=BD=9C=E6=88=90?= =?UTF-8?q?=E5=BE=8C=E3=81=AE=E8=BF=BD=E5=BE=93=E3=83=AB=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=A8=E5=A4=B1=E6=95=97=E7=9F=A5=E8=A6=8B?= =?UTF-8?q?=E3=81=AE=20scoped=20rule=20=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md「コミット / PR フロー」に PR 作成後の追従を追記 (CI・レビュー指摘の確認→修正→再 push、意思決定/範囲逸脱は承認) - 「失敗から学んだ知見」の領域固有項目を各 scoped rule へ移設し索引化 - lint 個別検証 → rules/backend/python.md - IntegrityError 後の再 SELECT → rules/backend/database.md - タスクハンドラの黙って return 禁止 → rules/backend/architecture.md - layers.md の旧 CLAUDE.md 参照を整合(正本は layers.md / database.md) Co-Authored-By: Claude Opus 4.8 --- .claude/CLAUDE.md | 15 +++++++-------- .claude/rules/backend/architecture.md | 1 + .claude/rules/backend/database.md | 1 + .claude/rules/backend/layers.md | 4 ++-- .claude/rules/backend/python.md | 1 + 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 1fa523f5..d76e2298 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -123,6 +123,7 @@ CI 定義: `.github/workflows/ci.yml` | **stage** | 実装 → `make ci` → `git add` まで。作業開始時にブランチを切り損ねて `main` にいた場合はここで feature ブランチを `origin/main` 起点で切る(本来は「作業開始時のブランチ運用」で切る)。会話に「サマリ+判断が必要な事案」を提示し、ユーザーのエディタ確認を待つ | | **commit** | コミットメッセージ案(**日本語**)を提示 → **ユーザー承認を待ってから** commit。承認は必須ゲート | | **pr** | `git fetch origin main` → `git log --oneline origin/main..HEAD` / `git diff --stat origin/main...HEAD` で**最新の main との差分を確認**(ローカルの古い `origin/main` 参照で誤認しないため)→ `git push` → `gh pr create`(**日本語**タイトル/本文、base = `main`)→ PR URL を返す | +| **pr 後の追従** | PR 作成後、`gh pr checks` / `gh pr view --comments` で **CI と指摘を確認**。こけ・指摘があれば修正 → `make ci` → 同ブランチへ push を green かつ解消まで繰り返す。CI 修正は実装フェーズなので元のモデルで(Haiku のままにしない)。**ただし意思決定を要する指摘(設計・API/型契約・挙動変更)と diff 範囲を逸脱する指摘は、勝手に直さず指摘内容・対応案・影響範囲を提示して承認を待つ**。範囲内の機械的修正(lint / typo 等)は承認不要 | 修正依頼時に「PR まで」等と言われたら、コミットメッセージ承認だけ挟んで一気通貫で進めてよい。段階を飛ばす指定も尊重する。 @@ -156,17 +157,15 @@ Claude Code は `/model` コマンドを自分では実行できないため、 ## 失敗から学んだ知見 -過去の手戻り・障害から導いた再発防止ルール。 +過去の手戻り・障害から導いた再発防止ルール。**領域固有の項目は各 scoped rule に集約済み**(対象パス編集時に自動ロードされる)。ここには領域横断(常に効かせたい)ものだけを残す。 - **テストで DB をモックしない**: 統合テストは実 DB(テスト用 SQLite セッション)に当てる。モック/本番乖離でマイグレーション失敗を見落とした実績がある。 - **新規ブランチは `origin/main` 起点で切る**: リリース前は全てを `main` にマージする運用。以前は `origin/dev` 起点だったが dev 環境作業の名残で、現在は廃止。 -- **契約変更時は既存テストの assert を必ず見直す**: 戻り値・例外仕様を変える時、旧契約を固定化したテスト(例: `test_no_cache_returns_early` のような silent-return アサーション)が残ると修正の意図が後退する。テスト名と本体の両方を更新する。 -- **`IntegrityError` 後の再 SELECT は `None` を判定する**: ユニーク制約衝突後の再取得で他セッションが先に commit したケースを想定し、`None` ならば明示的に `RuntimeError` を上げる。戻り値型が non-Optional な関数で握りつぶさないこと。 -- **タスクハンドラの「黙って return」は禁止**: 失敗パスでは `NonRetryableError` / `RetryableError` を `raise` し、worker に `dead_letter` / `retrying` 遷移と通知発行を任せる。早期 return は呼び出し側に completed として観測される。 -- **lint 失敗時は当該ファイルだけ確認**: `make lint-backend` が他ファイルの I001 等で落ちる場合、自分の変更分は `nix develop --command bash -c "cd backend && .venv/bin/python -m ruff check "` で個別検証してから進める(既存違反を巻き込まない)。 -- **Router には「エンドポイント定義・依存性解決・HTTP 変換」のみ**: 外部 API 呼び出し・DB クエリ(`db.query(...)` 直書き)・ビジネスロジックを router に書かない。外部 API の例外は service 層で処理し、router では `raise_app_error` への変換のみ行う。詳細・Bad/Good 例: `.claude/rules/backend/layers.md` -- **ORM model には「テーブル定義・リレーション」のみ**: ソート・フォーマット等の表示ロジックを `@property` として model に持たせない。`sort_utils` のような presentation 層ユーティリティを model に import しない。ソートは `relationship(order_by=...)` か service 層で行う。詳細: `.claude/rules/backend/layers.md` -- **300 行超のコンポーネント・500 行超のサービスモジュールは分割を検討する**: 行数は目安(強制閾値ではない)だが、超過したら責務が複数混在していないかを確認する。モーダル状態や更新ハンドラ群は専用フックに切り出す。詳細・Good パターン例: `.claude/rules/web/component-design.md` + +領域別の再発防止ルールは各 scoped rule に集約(対象パス編集時に自動ロード): + +- **Backend**: 契約変更時の assert 見直し → `rules/backend/test.md` / lint の当該ファイル個別検証 → `rules/backend/python.md` / `IntegrityError` 後の再 SELECT は `None` 判定で `RuntimeError` → `rules/backend/database.md` / タスクハンドラの黙って return 禁止 → `rules/backend/architecture.md` / Router・ORM model の責務境界 → `rules/backend/layers.md` +- **Web**: 300/500 行超コンポーネント・サービスモジュールの分割検討 → `rules/web/component-design.md` ## 命名規約 diff --git a/.claude/rules/backend/architecture.md b/.claude/rules/backend/architecture.md index be0ea527..5a9ecdfa 100644 --- a/.claude/rules/backend/architecture.md +++ b/.claude/rules/backend/architecture.md @@ -103,4 +103,5 @@ backend/app/ - **routers/auth/ と routers/blog/**: いずれもパッケージ化されている。auth は `endpoints` / `github_auth` / `oauth_flow` / `token_manager`、blog は `accounts` / `score` / `sync` に責務分割 - **services/tasks/**: Cloud Tasks(本番)と BackgroundTasks(ローカル)を共通の `execute_task` でディスパッチ。状態遷移(`processing` / `completed` / `dead_letter` / `retrying`)は worker が担う。現在登録されているタスクは `GITHUB_LINK` の 1 種類のみだが、`AsyncTaskCacheService` / `TaskHandler` は新規タスク追加の拡張ポイントとして汎用化してある(インライン化しない) + - **タスクハンドラの「黙って return」は禁止**: 失敗パスでは `NonRetryableError` / `RetryableError` を `raise` し、`dead_letter` / `retrying` 遷移と通知発行を worker に任せる。早期 return すると呼び出し側に completed として観測されてしまう - **services/intelligence/**: GitHub 連携 → スキル集計パイプライン。`github_link_service` → `pipeline` → `github_collector` → `skill_extractor` が live 経路。LLM は使わず決定論的(ルールベース)に処理する(intelligence モジュールは LLM を使わない。LLM は services/agent/ のみ / ADR-0010) diff --git a/.claude/rules/backend/database.md b/.claude/rules/backend/database.md index b840406f..82888846 100644 --- a/.claude/rules/backend/database.md +++ b/.claude/rules/backend/database.md @@ -10,6 +10,7 @@ paths: - 日付は可能な限り DB の `DATE` / `TIMESTAMP` を使うこと - `blog_articles` は `account_id` 起点で管理し、`user_id` や `platform` を冗長保持しないこと - マイグレーション: Alembic(`backend/alembic_migrations/versions/`)。詳細は下記「マイグレーション運用」を参照 +- **`IntegrityError` 後の再 SELECT は `None` を判定する**: ユニーク制約衝突後の再取得で、他セッションが先に commit していたケースを想定する。再 SELECT が `None` を返したら明示的に `RuntimeError` を上げ、戻り値型が non-Optional な関数で握りつぶさないこと ## マイグレーション運用 diff --git a/.claude/rules/backend/layers.md b/.claude/rules/backend/layers.md index 94e1b46a..cec85ce2 100644 --- a/.claude/rules/backend/layers.md +++ b/.claude/rules/backend/layers.md @@ -6,7 +6,7 @@ paths: # Backend 層の境界ルール `backend/architecture.md` が「何があるか」を示すのに対し、このファイルは「各層で何を書いてはいけないか」の禁止事項を補完する。 -新しい負債を発見したら本ファイルの Bad/Good 例と `CLAUDE.md`「失敗から学んだ知見」の両方を更新すること。 +層責務に関する再発防止ルールはこのファイルが正本。新しい負債を発見したら本ファイルの Bad/Good 例を更新すること(`CLAUDE.md`「失敗から学んだ知見」の索引表からはここを指している)。 ## 層ごとの責務と禁止事項 @@ -90,7 +90,7 @@ class GitHubLinkCacheRepository: self.db.add(cache) self.db.flush() # IntegrityError 後の再 SELECT が None を返す場合は RuntimeError を上げる - # (CLAUDE.md「失敗から学んだ知見」参照) + # (詳細: .claude/rules/backend/database.md) return cache ``` diff --git a/.claude/rules/backend/python.md b/.claude/rules/backend/python.md index b8565f80..f3472dcf 100644 --- a/.claude/rules/backend/python.md +++ b/.claude/rules/backend/python.md @@ -9,6 +9,7 @@ paths: - PEP8を守るな、PEP8を理解した上で抽象化しろ - コード変更後は `make lint-backend` を実行し、違反がないことを確認すること(Nix devshell 経由で ruff が解決される) - 特定ファイルだけ検証したい場合は `nix develop --command bash -c "cd backend && .venv/bin/python -m ruff check "` を使う。生シェルで `.venv/bin/python` を直接叩くのは禁止(WeasyPrint の動的ライブラリが解決できず import に失敗するため) +- **lint 失敗時は当該ファイルだけ確認する**: `make lint-backend` が他ファイルの I001 等で落ちる場合、自分の変更分は上記の個別 `ruff check ` で検証してから進める(既存違反を巻き込まない) - 未使用の import を残さないこと(F401) - 重複検知 / DRY ポリシーは `.claude/rules/common/duplication.md` を参照(抽出先は `backend/app/services/shared/` または同一サブパッケージの `_utils.py`)