プロジェクトマイグレーション(テックスタック)

チームがメンテナンスできないコードベースを引き継ぐことは、アウトソーシングでよくあるシナリオです。クライアントのメンテナンスチームが変わり、突然DjangoモノリスをLaravelアプリケーションに変換する必要が生じます — 同じ動作、異なるスタック。リスクは書き直し自体にあるのではなく、誰かの頭の中にドキュメントなしで存在し、移行中に消えてしまうビジネスロジックにあります。Sun Agent Kitはスカウトファーストの原則でこれを解決します:何かを移動する前にすべてをマッピングし、各チェックポイントで同一性テストが動作を検証しながら、モジュールごとに移行します。

概要

目標: ビジネスロジックを一切失うことなくプロジェクトを別のテックスタックに移行する
所要時間: 中規模プロジェクトで1〜3日(手動では2〜4週間)
使用エージェント: scoutplannerimplementertesterreviewer
コマンド: /sk:scout/sk:brainstorm/sk:research/sk:plan/sk:cook/sk:test/sk:code-review/sk:security-scan/sk:git

前提条件

  • Sun Agent Kitがインストール済みであること(インストールガイド
  • ソースコードベースがチェックアウトされ、ローカルでアクセス可能であること
  • ターゲットスタックのランタイムが利用可能であること(例:LaravelにはPHP 8.2 + Composer)
  • ソースとターゲットの両ディレクトリでGitが初期化済みであること
  • ソースプロジェクトで使用されているサードパーティサービスの認証情報へのアクセス(Stripeキー、APIトークンなど)
  • ソースプロジェクトの既存テストスイートまたはAPIコントラクトドキュメント(部分的なカバレッジでも有益)

ステップバイステップのワークフロー

ステップ1:ソースコードベースをスカウトする

/sk:scout "map everything in this Django project: models with fields and relationships, views and API endpoints with request/response shapes, middleware, Celery tasks, Stripe integration, custom authentication logic — generate a complete source inventory"

実行内容: エージェントが以下を実行します:

  1. ソースコードベース全体を走査し、すべてのモデル、ビュー、シリアライザー、タスクファイルを読み取ります
  2. フィールド型、制約、外部キー関係を含むモデルスキーマを抽出します
  3. 各エンドポイントをマッピングします:URL、HTTPメソッド、リクエストボディの形状、レスポンスの形状、ステータスコード
  4. すべてのバックグラウンドジョブ、スケジュールタスク、非同期処理ロジックを特定します
  5. 完全なソースインベントリを plans/reports/scout-report.md に保存します

ステップ2:移行戦略を決定する

/sk:brainstorm "given the scout inventory of 15 models and 40+ endpoints with Celery tasks and Stripe: what is the optimal migration strategy? Compare big-bang rewrite vs module-by-module migration. Which modules carry the most risk? What is the optimal migration order?"

実行内容: エージェントが以下を実行します:

  1. スカウトインベントリを読み取り、モデルとエンドポイントを論理的なモジュールにグループ化します
  2. モジュール間の依存関係を分析し、安全な移行順序を決定します
  3. 各モジュールのリスクを評価します — 複雑さ、外部統合、テストカバレッジのギャップ
  4. 明示的なトレードオフの根拠とともに、ビッグバンまたはインクリメンタルなアプローチを推奨します
  5. リスクランク付きのモジュールリストと提案された移行シーケンスを出力します

ステップ3:フレームワークマッピングを調査する

/sk:research "Django ORM to Eloquent migration patterns, Celery to Laravel Queues equivalents, Django REST Framework to Laravel API Resources, Stripe SDK differences between Python and PHP, Django middleware to Laravel middleware mapping"

実行内容: エージェントが以下を実行します:

  1. ソースとターゲット両フレームワークの最新ドキュメントを取得します
  2. 直接的な対応関係を特定します(例:Djangoシグナル → Laravelイベント)
  3. クリーンなマッピングがなくカスタム実装が必要な領域にフラグを立てます
  4. PythonとPHPクライアント間のStripe SDKの動作の違いをドキュメント化します
  5. 実装時に参照できるフレームワークマッピングリファレンスを plans/research/ に保存します

ステップ4:モジュールごとに移行を計画する

/sk:plan "module-by-module migration: Module 1 user management (4 models, 8 endpoints). Module 2 product catalog (5 models, 12 endpoints). Module 3 order processing (4 models, 14 endpoints). Module 4 Stripe integration and background jobs"

実行内容: エージェントが以下を実行します:

  1. plans/{timestamp}-django-to-laravel/ 配下に各モジュールのフェーズファイルを作成します
  2. 各モジュールについてソースファイルからターゲットファイルへの明示的なオーナーシップでマッピングします
  3. スカウトインベントリから導き出した、保持しなければならないすべてのビジネスルールをリストアップします
  4. 実装前に各モジュールの同一性テストの受け入れ基準を定義します
  5. モジュール間の依存関係を特定し、移行順序が守られるようにします

ステップ5:モジュールを1つずつ実装する

/sk:cook plans/{timestamp}-django-to-laravel/phase-01-user-management.md

各モジュールについて繰り返します。現在のモジュールが同一性テストに合格するまで次のモジュールを開始しないでください。

実行内容: エージェントが以下を実行します:

  1. フェーズ計画と現在のモジュールのスカウトインベントリセクションを読み取ります
  2. 同一のフィールド定義と関係を持つEloquentモデルを生成します
  3. DjangoシリアライザーとまったくのレスポンスShapeを生成するAPIリソースクラスを実装します
  4. すべてのビジネスルール、バリデーションロジック、エラーレスポンスフォーマットをそのまま保持します
  5. Laravelに直接相当するものがないDjangoパターンにフラグを立て、代替案を提案します

ステップ6:同一性テストを作成して実行する

/sk:test "write parity tests for the user management module — verify identical behavior: same endpoints, same response shapes, same status codes, same error messages as the Django version"

実行内容: エージェントが以下を実行します:

  1. スカウトインベントリと新しく実装されたLaravelモジュールの両方を読み取ります
  2. 代表的なペイロードですべてのエンドポイントを呼び出す統合テストを生成します
  3. レスポンスの形状、HTTPステータスコード、エラーメッセージのフォーマットがDjangoバージョンと一致することをアサートします
  4. スカウトインベントリに捕捉されたエッジケースをテストします(例:バリデーション失敗時のレスポンス)
  5. 期待値と実際値の差分とともに、動作の乖離を失敗テストとして報告します

ステップ7:移行された各モジュールをレビューする

/sk:code-review --pending

実行内容: エージェントが以下を実行します:

  1. フェーズ計画のビジネスルールチェックリストを実装されたコードと照合します
  2. 欠落しているバリデーション、不正確なエラーハンドリング、変換されなかったDjangoパターンにフラグを立てます
  3. 実装中にエンドポイントのレスポンスの形状がサイレントに変更されていないことを確認します
  4. 元のDjangoモデルグラフに対してEloquentリレーションシップの正確さをレビューします
  5. 次のモジュールを開始する前に、ブロッキングな調査結果を含むレビューレポートを作成します

ステップ8:完全なコードベースのセキュリティスキャンを行う

/sk:security-scan

モジュールごとではなく、すべてのモジュールが完了した後に1回実行します。

実行内容: エージェントが以下を実行します:

  1. 移行されたLaravelコードベース全体に対してOWASPアラインのスキャンを実行します
  2. すべての保護されたエンドポイントの認証ミドルウェアのカバレッジを確認します
  3. インジェクションの脆弱性、マスアサインメントの露出、安全でないクエリ構築をスキャンします
  4. PHPでStripeウェブフックの署名検証が正しく実装されていることを検証します
  5. フレームワークのデフォルトと実際の脆弱性を区別したセキュリティレポートを出力します

ステップ9:移行全体を通じてコミットする

/sk:git cm

実行内容: エージェントが以下を実行します:

  1. 現在のモジュールに属するファイルのみをステージングします
  2. モジュールと移行フェーズを識別するコンベンショナルコミットメッセージを作成します
  3. 各モジュールの移行をアトミックでレビュー可能なコミットとして保持します
  4. クライアントが移行の完全性を検証できるクリーンな履歴を維持します

完全な例:PHPチームのためのDjangoモノリスからLaravelへ

クライアントのメンテナンスチームはPHPベースですが、3年前のDjangoモノリスを引き継ぎました。このモノリスは15のモデル、40以上のAPIエンドポイント、注文処理とメール用のCeleryバックグラウンドタスク、サブスクリプション用のStripe統合、部分的なテストカバレッジを持っています。契約には6週間の移行タイムラインが含まれており、既存のモバイルアプリが変更を必要としないよう、同一のAPI動作が求められています。

移行は以下のように進みます:

# 月曜日 — 何かに触れる前にソース全体をマッピングする
/sk:scout "map everything in this Django project: models with fields and relationships, views and API endpoints with request/response shapes, middleware, Celery tasks, Stripe integration, custom authentication logic — generate a complete source inventory"

# 火曜日の朝 — 移行アプローチを決定する
/sk:brainstorm "given the scout inventory of 15 models and 40+ endpoints with Celery tasks and Stripe: what is the optimal migration strategy? Compare big-bang rewrite vs module-by-module migration. Which modules carry the most risk? What is the optimal migration order?"

# 火曜日の午後 — フレームワークのギャップを調査する
/sk:research "Django ORM to Eloquent migration patterns, Celery to Laravel Queues equivalents, Django REST Framework to Laravel API Resources, Stripe SDK differences between Python and PHP, Django middleware to Laravel middleware mapping"

# 水曜日 — モジュールごとの計画を作成する
/sk:plan "module-by-module migration: Module 1 user management (4 models, 8 endpoints). Module 2 product catalog (5 models, 12 endpoints). Module 3 order processing (4 models, 14 endpoints). Module 4 Stripe integration and background jobs"

# 第1〜2週:モジュール1 — 実装、テスト、レビュー、コミット
/sk:cook plans/{timestamp}-django-to-laravel/phase-01-user-management.md
/sk:test "parity tests for user management: same endpoints, same response shapes, same status codes, same error messages as Django"
/sk:code-review --pending
/sk:git cm

# 第2〜3週:モジュール2 — 商品カタログ
/sk:cook plans/{timestamp}-django-to-laravel/phase-02-product-catalog.md
/sk:test "parity tests for product catalog module"
/sk:code-review --pending
/sk:git cm

# 第3〜4週:モジュール3 — 注文処理
/sk:cook plans/{timestamp}-django-to-laravel/phase-03-order-processing.md
/sk:test "parity tests for order processing module"
/sk:code-review --pending
/sk:git cm

# 第4〜5週:モジュール4 — Stripe + バックグラウンドジョブ
/sk:cook plans/{timestamp}-django-to-laravel/phase-04-stripe-and-jobs.md
/sk:test "parity tests for Stripe integration and queue jobs"
/sk:code-review --pending
/sk:git cm

# 最終週 — 完全なコードベースのセキュリティスキャン
/sk:security-scan

結果: クライアントは同一のAPI動作を持つLaravelコードベース、モジュールごとに動作の同一性を証明する同一性テスト、クリーンなセキュリティレポートを、6週間の契約期間内に受け取ります。APIを使用するモバイルアプリには変更が一切不要です。

時間比較

タスク手動Sun Agent Kit使用
ソースコードベースのインベントリ1〜2日数分
移行戦略 + 計画1〜2日数分
フレームワーク調査 + マッピング2〜3日数分
実装(4モジュール)1〜2週間1〜2日
モジュールごとの同一性テスト2〜3日数時間
コードレビュー + セキュリティスキャン1〜2日数分
合計2〜4週間1〜3日

ベストプラクティス

1. ターゲットに触れる前にソースを完全にスカウトする ✅

知らないことは計画できません。スカウトインベントリは移行を生き延びなければならないすべてのビジネスルールの唯一の正しい情報源です。/sk:scout の前に /sk:cook を実行することは、ロジックを見逃す確実な方法です。

2. ファイルごとではなくモジュールごとに移行する ✅

モジュールには明確な境界と独立してテスト可能な出力があります。ファイルごとの移行は検証不可能な部分的な動作状態を生み出します。モジュールの境界は各移行チャンクを範囲限定かつレビュー可能に保ちます。

3. ユニットテストだけでなく同一性テストを書く ✅

移行の成功指標は動作の同一性です — LaravelエンドポイントはDjangoエンドポイントと同一のレスポンスを返しますか?ユニットテストは内部を検証し、同一性テストはクライアントのモバイルアプリが実際に受け取るものを検証します。

4. 移行中はAPIレスポンスの形状を同一に保つ ✅

移行途中でレスポンスの形状を「改善」する誘惑に抗ってください。レスポンス構造への変更はAPIコントラクトを破り、調整されたクライアントのアップデートが必要になります。移行が検証された後の別のパスでクリーンアップしてください。

5. 1回の /sk:cook 実行ですべてを移行しようとする ❌

40以上のエンドポイントを持つ4つのモジュールを1回のパスで確実に実装することはできません。モジュールの境界は失敗の影響範囲を減らすために存在します。コードベース全体に対する失敗したcook実行は、失敗したモジュールよりもはるかに診断が難しいです。

6. モジュール間で /sk:test をスキップする ❌

ロジックのギャップは複合します。モジュール1で欠落しているバリデーションがモジュール3で積み上げられると、300行のコードにわたるデバッグセッションになります。モジュール1でそれを検出すれば数分で済みます。モジュール4が完了した後に検出すると数時間かかります。

トラブルシューティング

問題:スカウトインベントリが不完全 — バックグラウンドタスクが見逃された

解決方法: フォーカスしたフォローアップスカウトを実行してください: /sk:scout "list all Celery task files, scheduled jobs in settings.py, and any management commands used in production"。初回スカウトはメインアプリケーションツリーをカバーし、ターゲットを絞ったスカウトは周辺の処理ロジックを捕捉します。

問題:CookがDjangoバージョンのビジネスルールを見逃す

解決方法: スカウトインベントリを実装されたコードと照合してください。ルールがスカウトレポートに記載されているが実装に存在しない場合は、そのルールを明示的に説明してcookを再実行してください: /sk:cook "implement rate limiting on the login endpoint: 5 attempts per 15 minutes, returns 429 with Retry-After header — matches Django behavior in scout report"

問題:同一性テストがエッジケースで失敗する

解決方法: これらは本物の移行バグであり、テストの問題ではありません。同一性テストは正しく機能しています — DjangoとLaravelの動作の乖離を発見しました。次のモジュールに移る前に、DjangoのわたしのLaravelコードを一致するよう修正してください。乖離を回避するために同一性テストを調整しないでください。

問題:セキュリティスキャンがフレームワークのデフォルトパターンにフラグを立てる(例:LaravelのCSRF処理)

解決方法: スキャンレポートをレビューし、フレームワークのデフォルトと本物の脆弱性を区別してください。LaravelのビルトインCSRFミドルウェア、Eloquentのパラメータ化クエリ、デフォルトのセッション処理はセキュリティ問題ではありません — これらは正しい実装です。フレームワークのデフォルト以外の調査結果に修正パスを集中させてください。

次のステップ


要点: ソースインベントリなしの移行は不確実性を伴う書き直しです — /sk:scout は1行も移動する前にすべてのモデル、エンドポイント、バックグラウンドタスクをマッピングし、モジュールごとの /sk:plan + /sk:cook + /sk:test サイクルが次に進む前に各チャンクを検証可能にします。