Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 まで」等と言われたら、コミットメッセージ承認だけ挟んで一気通貫で進めてよい。段階を飛ばす指定も尊重する。

Expand Down Expand Up @@ -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 <touched_file>"` で個別検証してから進める(既存違反を巻き込まない)。
- **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`

## 命名規約

Expand Down
1 change: 1 addition & 0 deletions .claude/rules/backend/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
1 change: 1 addition & 0 deletions .claude/rules/backend/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 な関数で握りつぶさないこと

## マイグレーション運用

Expand Down
4 changes: 2 additions & 2 deletions .claude/rules/backend/layers.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ paths:
# Backend 層の境界ルール

`backend/architecture.md` が「何があるか」を示すのに対し、このファイルは「各層で何を書いてはいけないか」の禁止事項を補完する。
新しい負債を発見したら本ファイルの Bad/Good 例と `CLAUDE.md`「失敗から学んだ知見」の両方を更新すること
層責務に関する再発防止ルールはこのファイルが正本。新しい負債を発見したら本ファイルの Bad/Good 例を更新すること(`CLAUDE.md`「失敗から学んだ知見」の索引表からはここを指している)

## 層ごとの責務と禁止事項

Expand Down Expand Up @@ -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
```

Expand Down
1 change: 1 addition & 0 deletions .claude/rules/backend/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <path>"` を使う。生シェルで `.venv/bin/python` を直接叩くのは禁止(WeasyPrint の動的ライブラリが解決できず import に失敗するため)
- **lint 失敗時は当該ファイルだけ確認する**: `make lint-backend` が他ファイルの I001 等で落ちる場合、自分の変更分は上記の個別 `ruff check <touched_file>` で検証してから進める(既存違反を巻き込まない)
- 未使用の import を残さないこと(F401)
- 重複検知 / DRY ポリシーは `.claude/rules/common/duplication.md` を参照(抽出先は `backend/app/services/shared/` または同一サブパッケージの `_utils.py`)

Expand Down