計画編で方針を、自動化基盤編でフレームワークを紹介しました。最終回では、実際に 15 Issue を自律実行した結果と、得られた教訓を共有します。


実行結果サマリー

タイムライン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
12:06 ── Phase 0: 初期セットアップ ────── 12分 (リトライ1回)
12:18 ── Phase 1-1: マスタモデル ──────── 14分 (リトライ1回)
12:33 ── Phase 1-2: 契約モデル ──────── 12分
12:45 ── Phase 1-3: 入金・会計モデル ──── 9分
12:57 ── Phase 2: 認証 & API ────────── 12分 (リトライ1回)
13:09 ── Phase 3-1: テンプレート ──────── 16分 (リトライ2回)
13:25 ── Phase 3-2: マスタ CRUD ────── 21分
13:46 ── Phase 4-1: 契約検索 ──────── 12分
13:58 ── Phase 4-2: 契約 CRUD ──────── 16分
14:14 ── Phase 4-3: 支払・入金 ──────── 21分 (リトライ1回)
14:35 ── Phase 5-1: CSV インポート ──── 24分 (リトライ1回)
14:59 ── Phase 5-2: Excel エクスポート ── 24分 (リトライ1回)
15:00 ── Phase 6: 月次締処理 ──────── 10分
15:34 ── Phase 7: テスト ──────────── 20分 (リトライ2回)
15:54 ── Phase 8: デプロイ準備 ──────── 8分
                            合計: 約 5.5 時間

数値で見る結果

項目数値
完了 Issue15 / 15
総コミット84
うち修正コミット (fix:)16 (19%)
リトライ発生 Issue8 / 15 (53%)
最大リトライ回数2 回
Python コード行数約 15,000 行
テンプレート50+ ファイル
テスト数199
テスト通過率100%
1 Issue あたり平均時間15〜25 分

うまくいったこと

1. inspectdb による正確なモデル定義

既存 DB ダンプから inspectdb でモデル雛形を生成し、それを整理する方式は非常に効果的でした。カラム名・型・制約が実 DB と完全一致するため、「モデル定義を書いたが DB と合わない」問題が発生しませんでした。

2. 外部 API の差異を事前に発見・記録

準備段階で API エンドポイントを実際に叩き、Laravel コードとの差異を CLAUDE.md に記録しました。GraphQL のクエリ名やフィールド名の違いを事前に把握していたことで、Phase 2(API 連携)がスムーズに進みました。

教訓: コードに書いてあることと実際の動作が違う情報は特に価値が高い。

3. code-reviewer サブエージェントの効果

Claude Code 内で別の Claude インスタンスをレビュアーとして起動し、以下のセキュリティ問題を検出・修正できました:

  • GraphQL インジェクション(ユーザー入力をクエリ文字列に直接埋め込み)
  • XSS(テンプレートでのエスケープ漏れ)
  • URL エンコード漏れ
  • 型不一致(Django フォームのバリデーション漏れ)

自分自身(Claude)がレビューする限界はありますが、ないよりは確実に品質が上がりました。

4. こまめなコミットによる中断耐性

「大きな作業の途中でもこまめにコミットする」という指示が功を奏しました。Phase 3-1 でセッションが中断した際、直前のコミットまでの作業が保存されており、リトライ時にスムーズに復旧できました。

5. 品質ツールチェーンの連携

Pre-commit Hook → PostToolUse Hook → CI の 3 層で品質を担保した結果、最終的なコードベースは ruff lint / Django check / pytest 全パスの状態で納品できました。


最大の問題: ブランチ分岐

何が起きたか

Phase 4-2(契約 CRUD)の完了後、2 つのブランチが独立して進行しました。

1
2
3
main ─── Phase 0〜4-2 ──┬── feature/phase-4-3 ── Phase 4-3 → 5-1 → 5-2
                         └── feature/phase-7 ──── Phase 6 → 7 → 8

結果:

  • feature/phase-7 に Phase 4-3〜5-2 の機能が含まれていない
  • TES 支払更新、CSV インポート、Excel エクスポートが欠落
  • 3 件の PR が Open のまま main にマージされていない

なぜ起きたか

表面的には「PR がマージされないまま次の Phase が別ブランチで始まった」ですが、根本原因を調査した結果、スクリプトにブランチ管理のロジックが存在しなかったことが判明しました。

具体的な問題:

  1. ブランチ作成がスクリプトにない: Claude Code の自律判断に委ねていた
  2. PR マージがスクリプトにない: 完了処理は gh issue close のみ
  3. push 先が固定: origin main に直接 push しようとしていた
  4. ブランチの連続性が未保証: 前の Issue のブランチの上にいる保証がない

どう修復したか

  1. feature/phase-4-3(4-3〜5-2 の成果)を feature/phase-7(6〜8 の成果)にマージ
  2. コンフリクト解消(2 ファイル: URL 設定と実行ログ)
  3. 検証: ruff / Django check / pytest 199 テスト全パス
  4. main にマージ & push

コンフリクトは 2 ファイルだけで、統合自体はスムーズでした。


教訓: 次回やるべきこと

1. ワークフロー制御は Claude に任せない

最重要の教訓。ブランチ作成・push・PR・マージなどの「ワークフロー制御」は、スクリプト側で確定的に実行すべきです。Claude Code には「実装とテスト」に集中させます。

1
2
3
4
5
6
7
❌ Claude にブランチ切替を任せる
   → セッションごとに異なる判断をする
   → ブランチ分岐・コード欠落のリスク

✅ スクリプトがブランチを作成・管理
   → 確定的な動作
   → Issue 間の状態遷移を保証

2. 禁止事項を明示する

CLAUDE.md には「やること」だけでなく「やってはいけないこと」を書くべきです。

1
2
3
4
5
## 禁止事項
- git branch / checkout / switch を実行しない
- git push を実行しない
- gh pr create / merge を実行しない
- 他の Issue のファイルを変更しない

Claude Code は「指示がない = 自律判断してよい」と解釈します。禁止されていない操作は実行される可能性があります。

3. テストは各フェーズで書く

テストを最後(Phase 7)にまとめて書いた結果、ブランチ分岐で欠落した機能のテストが不十分だった可能性があります。

1
2
❌ Phase 1〜6: 実装のみ → Phase 7: テスト一括作成
✅ 各 Phase: 実装 + テスト をセットで作成

4. 依存関係をスクリプトで強制する

Issue の依存関係は計画ドキュメントに表として書いただけで、スクリプトが検証していませんでした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 次の Issue に進む前に
check_dependencies() {
  # 依存 Issue が main にマージ済みであることを確認
  for dep in $(get_dependencies $ISSUE); do
    if ! is_merged_to_main $dep; then
      echo "依存 Issue #$dep が未マージです"
      exit 1
    fi
  done
}

5. ドライランを実施する

15 Issue の全自動実行を開始する前に、最初の 1〜2 Issue でドライランすべきでした。品質ツール(ruff、CI、verify-phase.sh)の検証には時間をかけましたが、ワークフロー自体の検証は行いませんでした。

品質ツールは「実装の品質」を保証しますが、「ワークフローの正しさ」は保証しません。

6. プロンプトと CLAUDE.md の重複を排除する

CLAUDE.md の「作業フロー」とプロンプトの「作業手順」が重複し、内容が微妙に異なっていました。Claude Code は両方を読むため、どちらに従うか不安定になります。

1
2
CLAUDE.md: プロジェクト固有の技術情報(DB 方針、設計方針、API 差異)
プロンプト: 作業手順・ステップ

を明確に分離すべきです。

7. 実行中のセルフチェック

--max-turns 80 で長い作業を許容していましたが、方向を間違えたまま走り続けるリスクがあります。

1
2
3
「20ターンごとに git status を確認し、
 正しいブランチにいること・
 未コミットの変更が溜まりすぎていないことを検証する」

のようなセルフチェックポイントを設けるべきでした。

8. ファイルサイズのガイドライン

contracts/views.py が 1,546 行、exports/views.py が 1,023 行に膨張しました。Claude Code は「動くコード」を書くのは得意ですが、適切なファイル分割の判断は弱い傾向があります。

1
2
3
# CLAUDE.md に追加すべきルール
- 1 ファイル 500 行を超える場合は分割を検討
- views.py → views/ パッケージ化(機能ごとにファイル分割)

自己レビューの限界

84 コミット中 16 件が修正系(fix:)で、ほとんどが code-reviewer サブエージェントの指摘対応でした。レビュー自体は機能していましたが、根本的な限界があります:

  • 同じモデルの盲点は検出できない: 書く Claude もレビューする Claude も同じ傾向を持つ
  • ワークフローの問題はコードレビューで検出されない: ブランチ分岐問題はコードの品質とは無関係
  • 「動いているが設計が悪い」を指摘しにくい: 1,500 行の views.py は動くが保守性が低い

対策: コードレビューとは別に、ワークフローの正しさを検証する仕組み(ブランチ状態チェック、依存 Issue のマージ確認)が必要。


成功パターンのまとめ

次回の同様なプロジェクトで再利用すべきパターン:

パターン効果
既存 DB ダンプ + inspectdbモデル定義の正確性が大幅向上
外部 API の事前動作確認実装中の手戻りを防止
CLAUDE.md への差異記録全 Phase で同じ間違いを防止
code-reviewer サブエージェントセキュリティ問題を複数検出
こまめなコミット指示中断からの復旧が可能
Pre-commit + PostToolUse Hookコード品質の自動担保
verify-phase.shPhase 完了の客観的確認

改善すべき点のまとめ

問題改善方針
ブランチ管理が Claude 任せスクリプトで確定的に制御
禁止事項が未定義CLAUDE.md に明示
テストが最後に一括作成各 Phase でセットで作成
依存関係の検証なしスクリプトでゲートチェック
ワークフローのドライランなし最初の 1-2 Issue で検証
プロンプトと CLAUDE.md の重複責務を分離
実行中のセルフチェックなしチェックポイントを設定
ファイルサイズの制限なし500 行上限のガイドライン
実行の可観測性が不足通知・タイムアウト検知

総括

Claude Code による全自動移行は「実用的」か?

Yes、ただし条件付き

5.5 時間で 15,000 行の Django コード + 199 テスト + 50 テンプレートを生成し、ruff / Django check / pytest 全パスの状態で納品できたのは、人間が手作業で行う場合と比較して圧倒的に高速です。

ただし:

  • ワークフロー制御は人間(またはスクリプト)が握るべき — Claude に任せるとブランチ分岐のような非決定的な問題が発生する
  • 事前の設計・計画は人間が行うべき — フェーズ分割、依存関係、技術方針は Claude に決めさせるより人間が決めた方が確実
  • 品質保証は多層的に設計すべき — Claude の自己レビューだけでは不十分、自動テスト + CI + Hook の組み合わせが必要

Claude Code の適性

得意不得意
コード実装(量産力が高い)ワークフロー制御(非決定的)
テスト作成ファイル分割の判断
セキュリティレビューアーキテクチャの長期的判断
ドキュメント生成実行中の自己モニタリング
エラー修正・リトライセッション間の状態引き継ぎ

最後に

本プロジェクトの最大の学びは、「Claude Code に何を任せ、何を任せないか」の境界設計が成否を分けるということです。

実装力は十分。品質も(多層的な仕組みがあれば)担保できる。しかし、ワークフローの制御 — ブランチ管理、依存関係の検証、状態の引き継ぎ — は確定的なスクリプトに任せるべきです。

Claude Code は優秀な「実装者」ですが、「プロジェクトマネージャー」ではありません。この区別を意識すれば、フレームワーク移行のような大規模タスクも自律実行で回せる — それが本プロジェクトの結論です。