doc-and-modernize について
ローカルにチェックアウトしたリポジトリの設計を文書化し、またはモダナイゼーションを計画するスキルです。計画に設計の基準が必要な場合は先に文書化し、ローカルファイルの根拠と引用、テスト可能性や安全性に応じた段階的な変更を重視します。
主な機能
- 01ローカルコードから引用付き設計文書を作成
- 02リポジトリ構造とランタイム構成を整理
- 03依存関係と検証コマンドを調査
- 04段階的なモダナイゼーション計画を作成
- 05システムのテスト可能性に応じて安全策を選定
活用シーン
- 01未知のコードベースへの開発者のオンボーディング
- 02ローカルチェックアウトの設計を文書化
- 03レガシーシステムのアップグレードや移行を計画
- 04モダナイゼーションのリスクと検証手順を特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill doc-and-modernizeインストール後、Claude Code で/doc-and-modernizeを入力して読み込まれたか確認します。
同梱ファイルreferences/copilot-instructions.template.mdreferences/migration-hazards.md
詳細
ドキュメント化とモダナイゼーション
ユーザーがすでにローカルにチェックアウトしているリポジトリ向けの、相互に補完する2つのワークフローを1つのスキルにまとめています。
- ドキュメント化モード — ディスク上のコードを基に、根拠を引用した決定版のアーキテクチャドキュメントを作成します。オンボーディング、システム設計マップ、モダナイゼーションの取り組みに向けたエビデンスベースとして最適です。
- モダナイゼーションモード — そのアーキテクチャを、段階的で安全性を考慮した、レガシーシステムのアップグレード、移行、書き換えの計画に落とし込みます。
モードの選択
- ユーザーがコードベースの理解、文書化、マッピング、調査、オンボーディングを望んでいる場合は、ドキュメント化モードを実行します。
- ユーザーがシステムのモダナイゼーション、移行、アップグレード、書き換えを望んでいる場合は、モダナイゼーションモードを実行します。モダナイゼーションモードだけで完結します。アーキテクチャドキュメントがまだ存在しない場合は、まずドキュメント化モードのワークフローを同じ実行内で行い、そのまま計画の作成に進みます。
判断に迷う場合は、まずアーキテクチャドキュメントを作成してください。どちらのモードでも、この監査済みのエビデンスベースを基に進めます。
ドキュメント化モード
ユーザーがすでにローカルにチェックアウトしているリポジトリについて、根拠を引用した決定版のアーキテクチャドキュメントを1つ作成します。新しいエンジニアにオンボーディング用の参考資料として渡せる文書を目指します。システム全体をカバーできる広さと、難しい部分を役立つ形で説明できる深さを備え、すべての記述がディスク上のファイルを根拠としているため、信頼できるものにしてください。
ローカル優先の理由
ローカルのチェックアウトから読み取ることは(GitHub APIやウェブからではなく)、意図的なデフォルトです。高速で無料、レート制限を回避でき、何よりも、リモート上のmainがどうなっているかではなく、目の前にある正確なコードを説明できます。唯一のトレードオフは、リモートでしか確認できない情報(スター数、CIの全実行履歴、関連リポジトリなど)が見えないことです。問題ありません。そのような情報は対象外と明記するか、推測するのではなく[UNVERIFIED]と記してください。
ローカル優先とは、ローカルだけを使い、決してリモートを使わないという意味ではありません。ウェブ/APIでの検索は、ディスク上の情報からは本当に確認できず、かつドキュメントにとって重要な事実に限る、意図的な最後の手段です。検索した場合は、その結果を明確に示してください(例:[UNVERIFIED]/リモートから取得した情報)。読者がチェックアウトから得た情報ではないと分かるようにし、ディスク上のコードを読む代わりに手軽な方法として使わないでください。
ワークフロー
- まず対象を特定します。
git remote -v、git branch --show-current、git log -1を実行し、特定のリモート、ブランチ、コミットに基づいたドキュメントにします。読者が、どのスナップショットについて説明しているかを把握できる必要があります。リモートURLに認証情報が埋め込まれている場合があります(例:https://<token>@github.com/...)。ドキュメントに記録する前に、URLから認証情報/トークンを必ず伏せてください。 - 推測せず、実際の情報を確認します。 実際のマニフェスト(
go.mod、package.json、Cargo.toml、pyproject.toml、pom.xmlなど)、Makefile/タスクランナー、CI設定、リポジトリ固有のエージェント向けドキュメントやコントリビューター向けドキュメント(AGENTS.md、CONTRIBUTING、README、docs/)を確認します。これらが技術スタックやコマンドの信頼できる情報源です。フレームワークについての事前知識より、こちらを優先してください。 - 全体像を把握してから、詳細を掘り下げます。 まず、以下の3つの観点でリポジトリ全体のマップを作成し、その後、最も難しいサブシステムを2~3つ選んで詳しく調べます。
- 調査と並行して検証します。 引用するファイルは実際に開いてください。行番号を記載する場合は、その行を実際に読んでいる必要があります。ここでは、根拠のない記述は記載漏れよりも問題です。このドキュメントの価値は、信頼できることにあります。
出力構成
以下のセクションをこの順序で含む単一のMarkdownファイルを作成します。実際のプロジェクトに合わせて見出しを調整してください(CLIツールには「フロントエンド」の観点がありません。その枠はリポジトリにとって重要な内容に置き換えます)。ただし、3つの観点から成る構成と、検証の徹底は維持してください。
パート1 — リポジトリ全体の技術的な詳細分析
- リポジトリの概要(READMEを引用した1段落)。
- 技術スタック検出テーブル:レイヤー | 技術 | 根拠(ファイル名+行番号)。
- エントリーポイント(バックエンド、フロントエンド、CLIなど、該当するもの)。
- コマンドと検証の一覧 — プロジェクトの標準コマンドをまとめた表(
command | purpose | evidence)。推測ではなく、タスクランナー、マニフェスト、CI設定を確認してください。ビルド、実行/サーブ、テスト(単一のテストを実行する方法も含む)、リンター、フォーマッターを網羅してください。さらに、存在する場合は型チェック、エンドツーエンド/スモークテスト、コントラクトテスト、その他のゲートコマンドと、それらを実行するCIワークフローおよび実行トリガーも含めてください。CIが強制されているかどうかも記録してください。つまり、マージを実際にブロックする必須ステータスチェック/ブランチ保護ルールであるワークフローと、単に実行されるだけのワークフローを区別します。この違いは手動で人が設定するものであり、モダナイゼーションモードでは推測せずに明示する必要があります。通常、ローカルのチェックアウトだけでは強制の有無を判断できません。ユーザーに確認するか、権威ある情報源で確認できない場合は[UNVERIFIED]と記してください(リモート照会は、上記のローカル優先ルールに従い、最後の手段であることを明示してください)。この一覧は、後続の計画(モダナイゼーションモード)が実行可能な終了条件を提示するための信頼できる情報源です。希望的観測にとどめないでください。エコシステムごとに(npm/yarn/pnpm、make、just、cargo、go、poetry/tox/nox、gradle/mavenなど)検出し、技術スタックを決めつけないでください。確認できなかったコマンドには[UNVERIFIED]を付けてください。 - 主要な領域ごとのディレクトリ構成と、各ディレクトリの目的を1行で説明してください。
- デプロイとランタイムの適用範囲 — システムの実行時に使用する言語/ランタイムやバックエンドサービスのバージョンが固定されている箇所をすべて表にしてください(ビルド時だけの設定は除く)。コンテナのベースイメージ(
Dockerfile/Containerfile、docker-compose*のビルドコンテキスト)、CIランナーのイメージ/setup-*のバージョン、engines/.nvmrc/.tool-versions/runtime.txt、サーバーレス/Lambdaランタイム、状態を保持するデータストアのイメージタグ(DB/キャッシュ/ブローカー/検索)を対象にします。それぞれにファイル名+行番号を添えてください。この範囲は、後続のプラットフォーム/ランタイムのバージョン更新を一貫して反映すべき箇所です。ビルド時と実行時のランタイムにずれがあれば、モダナイゼーション計画の作成前に把握できるよう明記してください。 - EOL/不要な依存関係のスキャン — サポート終了、メンテナンス停止、または次のメジャーバージョンで名前空間の変更やコンポーネント群の削除が見込まれるフレームワークなど、対象バージョンで削除される可能性のあるフレームワーク、ランタイム、ベースイメージ、ライブラリを挙げてください。必要に応じて
[INFERRED]/[UNVERIFIED]を付けてください。これは、モダナイゼーションモードで実現可能性を調査し、リスクを厳しく洗い出すための基礎資料です。 - データ/ストレージ層、API、プラグイン/拡張機能、バックグラウンドジョブ、CI/CD、テスト。
パート2 — コンテキストとエコシステム
- ローカルチェックアウトの識別情報テーブル(リモート、ブランチ、HEADコミット、バージョン、ライセンス)。
- リポジトリ固有のエージェント/コントリビューター向けドキュメントの有無と、そこに記されたルール。
- 開発時の注意点(テストのウォッチモードのデフォルト、ビルドの遅さ、生成コードのコミット必須、事前コミットフックなど)。それぞれに根拠を添えてください。
- このプロジェクトと、より広いエコシステムまたは兄弟サービスとの関係を、ディスク上で確認できる範囲で説明してください(ビルドタグ、任意でリンクされたリポジトリ、個別にデプロイ可能なコンポーネントなど)。リモートのエコシステム情報を持ち込まないでください。
パート 3 — アーキテクチャ設計図
- 技術スタックの概要(パート 1 の表を参照してもかまいません)。
- Mermaid による C4 形式の図:レベル 1 のシステムコンテキスト、レベル 2 のコンテナ、 レベル 3 の代表的なリクエスト/コンポーネントのライフサイクル。
- レイヤー構成と依存関係のルール(何が何に依存してよいか、およびそれを何が強制しているか)。
- 横断的関心事の表:認証、設定、ロギング、メトリクス/トレーシング、シークレット、 エラー処理、機能フラグについて、それぞれの配置場所と根拠を示します。
- 推定されるアーキテクチャ決定記録(コードとドキュメントから再構成したもの)。
- ガバナンスと適用の仕組み(CI ゲート、コード生成の検証、CODEOWNERS、レビューゲート、互換性ルール)。
- 「機能の追加方法」ガイドとよくある落とし穴。
サブシステムの詳細解説
最も複雑、またはアーキテクチャ上重要なサブシステムを 2~3 個特定します。新しいエンジニアが最も理解に苦労する箇所、たとえば評価/スケジューリングエンジン、プラグインローダーパイプライン、状態機械、レンダリング/移行フレームワークなどが該当します。それぞれについて、内部構造、ライフサイクルまたは状態機械、主要な型、データフローを扱う専用の小節を追加し、該当箇所を示すローカルファイルと行番号の引用、およびフローを明確にする小さな Mermaid 図を含めます。これにより、単なるディレクトリ一覧ではなく、役に立つオンボーディング資料になります。ここには十分に労力をかけてください。
信頼度の評価
主要な主張の領域を High/Inferred/Unverified で評価した表を作成し、読者がどの部分をそのまま信頼でき、どの部分を再確認すべきかを正確に把握できるようにします。
脚注 — ローカルファイルの引用
このドキュメントの根拠となる主要なローカルファイルの一覧を作成し、それぞれが何を裏付けるかを一行で説明します。
ドキュメントの信頼性を高める慣習
これらは、このスキルによる出力を一般的な概要と区別する習慣です。ドキュメントの価値は、読者がすべてを自分で調べ直さなくても信頼できることにあります。
- 自明でない主張にはすべて、ローカルパスを引用します。 特定の内容を示す箇所には行番号も付けます(
pkg/server/server.go#L39-L41)。リポジトリルートからの相対パスにすると、リンクをクリックできます。 - 不確実な点は正直に示します。 推論したものの明記されていない内容には
[INFERRED]、繰り返し述べているものの確認していない内容(たとえば、再計測していないドキュメント記載のビルド時間に関する主張)には[UNVERIFIED]を使います。正直に不足を示すほうが、根拠のない確信より役に立ちます。 - 矛盾はそのまま繰り返さず、解決します。 2 つの情報源で食い違いがある場合(たとえば、コード内のバージョン表記とマニフェストの違い)、コードを確認して実際の答えを判断し、説明を添えて
[Resolved contradiction]と記載します。矛盾を読者に解明させるのは、失敗につながります。 - リポジトリが定める互換性とデプロイ頻度のルールを記載します。 FE/BE の PR 分割、双方向のストレージ互換性、protobuf の追加のみの変更など、新しいメンバーが最も破りやすいルールを明記します。
- 曖昧な数より正確な数を優先します。 「サービスパッケージ 73 個」「ワークフローファイル 89 個」(ディレクトリ一覧による)のように書けば、検証済みだと分かります。「多数のサービス」のような表現では推測に見えます。
対象範囲の管理
ドキュメントはチェックアウトの内容に基づいたものにしてください。プロジェクトのより広いエコシステム(関連製品、README のマーケティング情報、関連リポジトリ)へ話がそれやすいため、ディスク上で確認できるものではない限り避け、ローカルツリー外から得た情報は明確に示してください。読者が求めているのは このコードベース であり、それを忠実に記録することです。
モダナイゼーションモード
レガシーなコードベースのための、完全かつ実行可能なモダナイゼーション計画を作成します。このスキルでは、これから取り組む作業、つまり何を、なぜ、どの順序で、どのようにモダナイズするかに重点を置きます。ただし、それ自体で完結しており、まずアーキテクチャ文書の存在を確認し、必要な場合はドキュメントモードで作成します。
デフォルトでは、システムは動作不能だと想定します。 古いスタックのアップグレードが難しい、あるいは不可能だからこそ、人々はモダナイゼーションを検討します。ランタイムのサポート終了、コンパイルできないネイティブモジュール、廃止されたパッケージミラー、放棄されたフレームワークなどがその例です。そのため、このスキルでは、レガシーツールチェーンを復活させて完全に成功する CI ゲートを用意してから着手できるとは想定しません。こうした「凍結してから移行する」アプローチは、幸運なケースであり、デフォルトではありません。代わりに、スキルでは期間を限定した実現可能性調査を行い、その後、実際のシステムの稼働状況に応じて移行戦略と安全性戦略を選びます。本当に動作不能なアプリでは、成功するレガシーゲートを構築すること自体がモダナイゼーションプロジェクトとなり、堂々巡りに陥ります。このスキルはそれを避けるよう設計されています。
計画全体の軸となる考え方は3つあり、以下で紹介します。テスト可能性マイルストーン(コンポーネントごとに、システムが再びビルド、実行、テスト合格できるようになる時点)、安全性の段階(実際に到達可能な、回帰に対する安全性の最高レベル。レベルを下げることも失敗ではなく、承認された結果として扱います)、そしてCI マイルストーン(どのフェーズで初めて CI を導入するか、および CI を必須チェックとして適用するのは手動での人間の作業であり、エージェントにはできないという注意点)です。
前提条件
このスキルで計画を立てるには、システムのアーキテクチャを把握する必要があります。次の手順で対応してください。
- アーキテクチャ文書がすでにある場合(上記のドキュメントモードで作成されたもの、ユーザーが指定した README / ARCHITECTURE.md、または十分な過去の会話コンテキスト)は、それを使って以下のワークフローに進みます。
- アーキテクチャ文書がない場合は、まず上記のドキュメントモードのワークフローを実行して、出典を明記したアーキテクチャ文書を作成し、続けて同じ作業の中でそのまま以下のフェーズ1に進みます。ユーザーに別途実行してもらうために中断したり、2つの文書の間でレビューを待ったりしないでください。
成果物は2つです。監査済みの根拠資料となるアーキテクチャ文書と、これから実行する作業をまとめたモダナイゼーション計画です。
計画を立てる前に、「コマンドと検証の一覧」が存在することを確認してください。 完了条件は実行できなければ意味がないため、計画ではプロジェクトで正式に使われているビルド、実行、テスト、lint、型チェック、E2E、コントラクトの各コマンドと CI ゲートを参照できる必要があります。ドキュメントモードでは、パート1でこの一覧を作成します。README や過去のコンテキストをもとに作業していて一覧がない場合は、完了条件を記述する前に、各エコシステムの設定(npm/yarn/pnpm、make、just、cargo、go、poetry/tox/nox、gradle/mvn など)を確認し、自分でコマンドを検出して記録してください。タスクランナー、マニフェスト、CI 設定で確認していないコマンドを作り出してはいけません。
ワークフロー
フェーズ1:現状を評価する(既存文書から)
アーキテクチャ文書を読み、以下を抽出します。
- 技術スタック一覧 — 言語、フレームワーク、ランタイム、依存関係(確認できる場合はバージョンも含む)
- 機能/ドメインマップ — システムの主な機能領域
- すでに特定されている課題 — 技術的負債、懸念事項、非推奨の依存関係、既存文書で指摘されたアーキテクチャ違反
- デプロイとインフラストラクチャ — 現在のシステムの実行方法
すべてのソースファイルを読み直さないでください。アーキテクチャ文書を信頼してください。モダナイゼーションに関する疑問を解決するために詳細を確認する必要がある場合(例:「この依存関係は実際に使われているのか、宣言されているだけなのか」)に限り、該当するファイルを開いてください。
フェーズ 2:実現可能性のスパイク、戦略の分岐、安全性の段階
これは計画全体の方向を決める重要な局面です。目標アーキテクチャを推奨したり、フェーズを作成したりする前に実施してください。 目的は、次の問いに迅速かつ率直に答えることです。このシステムはどの程度稼働できるのか、どのような移行の形が適しているのか、実際にどの程度のリグレッション対策を実現できるのか。
2a. 時間を区切った実現可能性のスパイクを実施する
厳格な時間制限を設定してください(例:1 日)。スパイクで問うべきなのは、「CI をグリーンにできるか?」ではありません。 — **「動作を記録するために、少なくとも 1 回 実行できるか?」**です。コンポーネント/デプロイ可能な単位ごとに、次の点を確認します。
- 現在、依存関係をインストールできるか(理想的には、手作業でパッチを当てずに、コミット済みのロックファイルから)?
- ネイティブビルド/ビルドの手順は、現在サポートされているツールチェーンで成功するか?
- 起動/開始できるか?
- テストランナーを実行できるか、また、意味のあるテストが少なくとも 1 つ成功するか?
部分的な成功も含め、実際に確認した内容を記録してください(モノレポでは、1 つのサービスはインストールできてテストも成功する一方で、別のサービスはコンパイルできないことがよくあります)。蘇生できないと判明するまで、すでに機能しないものの復旧に 2 スプリントを費やしてはいけません。時間制限に達したら、手元にある証拠に基づいて判断してください。
2b. テスト可能になるマイルストーンを特定する(コンポーネントごと)
「テスト可能」であることは、機能停止したアプリに対して満たせる前提条件ではありません。機能停止したアプリでは、それはモダナイゼーションの入力ではなく、出力です。 したがって、すべての計画で、テスト可能になるマイルストーンをあらかじめ明示する必要があります。すなわち、システム(または特定のコンポーネント)が、次の 4 つの条件をすべて同時に初めて満たす具体的なフェーズです。
- サポートされている(EOL ではない)ランタイムで動作する。
- 手作業でパッチを当てずに、ロックファイルから依存関係をインストールできる。
- ネイティブビルド/ビルドの手順が、現在のツールチェーンで成功する。
- CI でテストランナーが実行され、意味のあるテストが少なくとも 1 つ成功する。
コンポーネントごとに評価してください。参考となる Nylas の事例が示すように、ほぼモダンなクラウドサービスはすぐにこの基準に到達する一方で、レガシーな Electron クライアントは数フェーズ後まで到達しないことがあります。このマイルストーンは、計画で最も重要な指標です。 各コンポーネントでどの段階に到達するのか、明確に述べてください。
2c. すべてのフェーズにテスト可能になる前か後かを明記する
テスト可能になるマイルストーンによって、取り組みは異なる安全規則を持つ 2 つの段階に分かれます。
- テスト可能になる前の「暗い」段階:コンポーネントを信頼できる状態で実行できません。安全性は、テスト以外の手段から確保します(以下の安全性の段階を参照)。ここで CI のテストゲートを必須とするのは、適用範囲の誤りです。まだ稼働していないものに対して、テストの成功を要求することになります。
- テスト可能になった後の「明るい」段階:サポート対象の稼働中スタック上でビルドと実行ができます。ここからは、実際の CI、特性評価、E2E が実現可能となり、投資する価値もあります。従来型のグリーンゲートを適用するのはこの段階です。
ルール:コンポーネントがそれぞれのテスト可能ラインを越える前に、自動テストゲートを必須にしてはいけません。
2d. 移行戦略を選択する — A/B の分岐点
スパイクによって、次のどちらの形が適しているかを判断します(モノレポではコンポーネントごとに判断します)。
- (A) 凍結してから引き上げる。 古いアプリを現状のままネットに乗せ、そのネットの上でアップグレードします。古いアプリを許容できるコストで復活させられることが必要です。つまり、ほぼ動作する状態である必要があります。従来の「何かを変更する前に特性テストを書く」方法です。デフォルトではなく、選択制です。
- (B) 足がかりを作ってから拡張する(ウォーキングスケルトン)。 役目を終えたアプリをネットに乗せるのではありません。可能な限り最小限のエンドツーエンドのスライスを最新のスタックに移し、ビルド、起動、テストができるようにしてから、残りを少しずつ置き換え、その過程で新しいスタック上でテストを書きます。動かなくなったアプリでは、こちらがデフォルトです。 戦略 B の第 1 フェーズは「最小限のスライスでテスト可能性のマイルストーンに到達する」ことであり、「レガシーのツールチェーン全体を凍結する」ことではありません。
コンポーネントをまったくビルドも実行もできない場合、定義上、古いスタック上で特性テストを行うことは不可能です。アプローチを逆転させ、役目を終えたアプリをネットに乗せようとするのをやめ、ターゲットスタック上で段階的にネットを構築します。その際、古いコードや出力を参照用のオラクルとして使います。
2e. 安全性ラダーで到達可能な最上位の段階を選ぶ
回帰安全性は二者択一ではなく、段階的なものです。コンポーネントごとに、実際に到達できる最上位の段階を選んでください。残存リスクを明示している限り、より低い段階への引き下げも、失敗ではなく、正式に認められた第一級の選択肢です。
- L4 — 完全な自動ゲート: CI で lint + unit + characterization + e2e がすべて成功します。
- L3 — 部分的なゲート: 一部のテストスイートが成功し、lockfile と、達成可能な範囲の CI が整っています。残りは、対象を明記したリストとともに隔離します。
- L2 — ふるまいの特性評価/ゴールデンマスターのみ: CI では実行できませんが、I/O スナップショット/ふるまいの差分を記録します(手動でもかまいません)。
- L1 — 可逆性に基づく対応: 実行可能なテストはありません。小さく可逆的な変更、ストラングラーパターン/並行実行、スモークチェックリスト、レビューによって安全性を確保します。
- L0 — ネットを張れない: 仕様駆動の書き換え(古いコードを仕様とする)として扱うか、アーカイブします。
安全性を確保する方法はテストだけではありません。 少なくとも5つの要素があり、停止したアプリでは2〜4が1を上回ることもよくあります。
- テスト(ふるまいの特性評価/unit/e2e) — 最も強力ですが、停止したアプリでは実施できないことがよくあります。
- 可逆性 — 小さなコミット、変更ごとのブランチ、簡単なロールバック。
- 分離 — フィーチャーフラグ、ストラングラーフィグ、旧システムと新システムを並行して実行し、出力を比較します。
- 稼働中の旧システムをオラクルとして使う — テストハーネスなしでふるまいを特性評価できるよう、実際の I/O を記録して再生します。
- 人によるレビュー + ドメイン知識。
単体ではなく、ふるまいの境界で安全性を確保してください。 あらゆるアプリに共通する、スタックに依存しない永続的な契約は、外部から観測可能なふるまいです。具体的には、HTTP エンドポイント、DB スキーマ/クエリ、ファイル/ワイヤーフォーマット、CLI 出力、プロトコルなどです。それらをゴールデンマスター/承認用スナップショットとして固定します。**書き換え後もそれらは残りますが、停止したレガシーコードの単体テストは、モジュールを置き換えた瞬間に削除されます。**利用可能なものから、オラクルを選んでください。
- 最善 — どこかで実行できる(本番、VM、古いコンテナ、読み取り専用の環境でも)うえ、使用が許可されている場合:実際の I/O を記録し、新しいコードに対して再生します。1回でも成功した記録があれば、レガシー CI を恒久的に成功させ続けるより有効です。(この段階が常に利用できるとは限らない点に注意してください。忠実なサードパーティ製の再実装や、復元したレガシーバイナリは、ポリシーやライセンス、あるいは「手元にあるものだけで」構築するという明示的な決定により、使用できない場合があります。その場合は、自己凍結の段階に進んでください。)
- 代替案 — まったく実行できない: 古いソースコードを仕様とします。本番ログ、DB ダンプ、ドキュメント、チケットで補い、正しさを確認した後、新しい実装に対してふるまいの特性評価テストを作成して固定することを受け入れます。
- 自己凍結ゴールデンマスター — 外部の参照先が存在しない、または使用を許可されていない: 信頼できるものが何も実行できず、外部のオラクルを借りることも許されない場合、モダナイズされたコンポーネントは、最初に実行した時点(テスト可能性マイルストーン)で独自のゴールデンマスターを記録し、以降の各フェーズで、その凍結されたスナップショットと差分を比較します。これは実用可能な段階です。ただし、残存リスクを明確に述べてください。保証されるのは以降のリファクタリングにおける自己整合性であり、最初の起動時の正しさではありません(スナップショットの正しさは、それを生成した実行の正しさにのみ依存します)。最初の実行を承認するため、人によるレビューや仕様との照合を組み合わせてください。
2f. 経済性とオラクルのトリアージを選択に反映する
段階を選ぶ際は、回帰コストを考慮してください。アプリは本番稼働中ですか? 実際のユーザーがいますか? 参照用として旧システムをまだ実行できますか? ユーザーがゼロの放棄されたアプリでは、回帰コストはほぼゼロです。そのようなアプリにコストのかかるゲートを設けるのは過剰なエンジニアリングです。ユーザーがいる本番システムでは、より高い段階と実際のオラクルが正当化されます。
2g. CI マイルストーンを特定する(CI を立ち上げるフェーズを明記する)
テスタビリティマイルストーンが「コンポーネントを初めて実行してテストできる時点」を示すのと同様に、CI マイルストーンは「継続的インテグレーションを初めて立ち上げる時点」を示します。これはロードマップに明記し、フェーズの説明文に埋もれさせてはいけません。 モダナイゼーション計画でよくある失敗は、どのフェーズで CI が導入されるのかを読者が判断できないことです。必ず明示してください。
ルール:CI を立ち上げるのは、最初の明るいフェーズ、つまりコンポーネントがテスタビリティマイルストーンに到達した直後またはその時点です。それより前に行ってはいけません。 まだビルド/実行できないコンポーネントで CI をグリーンにすることはできません。そのため、暗黒期に CI のゲートを組み込むのは、そこでテストゲートを要求するのと同種のカテゴリーエラーです。(lint のみ、またはビルドのみのワークフローのような単純な足場づくりは、もっと早い段階で導入してもかまいません。ただし、正式なテストゲートを導入するのは CI マイルストーンです。)
CI は明確に異なる 2 つの手順からなり、2 つ目は人間だけが実行できます。 両方を明記してください。
- ゲートを実行する CI ワークフローファイルを作成する(例:
.github/workflows/*.yml、.gitlab-ci.yml、Azure Pipelines)。エージェントが実行できます。 - そのワークフローを強制適用されるゲートにする(必須ステータスチェック/ブランチ保護ルール/マージリクエスト承認ルール)。これはプラットフォームの UI/管理者による手動の手順です(GitHub → Settings → Branches、GitLab の保護ブランチと MR 設定など)。エージェントには実行できません。 人間が設定するまでは、CI は PR で実行されますが、マージをブロックしません。
手順 2 はエージェントの手の届かない範囲にあるため、CI を立ち上げるすべての計画で、これを明示的なユーザーアクション項目として提示しなければなりません(そのフェーズの終了基準と §9「ステークホルダーからの確認が必要な未解決の質問/決定事項」の両方に記載します)。これにより、ゲートは有効化されるまで自動的に強制適用されないことを読者が理解できます。
フェーズ 2 の成果物: コンポーネントごとに、スパイクの結果、選択した戦略(A または B)、特定したテスタビリティマイルストーン、移行前後のラベル、残存リスクがあればそれを明記した目標の安全ラダー段階を提示します。これに加えて、計画全体の CI マイルストーン(どのフェーズで CI を立ち上げるか)と、それを強制適用するには人間による手動の手順が必要である旨も記載します。以降のすべての作業は、これらに依存します。
フェーズ 2.5:すべてのフェーズをハザードカタログに照らしてレッドチーム検証する(必須)
ここまでの戦略的な足場(テスタビリティ、安全ラダー、CI マイルストーン)は必要ですが、それだけでは十分ではありません。 モダナイゼーション計画は、戦術面で起こりやすく、エコシステムに特有のハザードによっても失敗します。不完全な隔離対象セット、見落とされた名前空間のコード改変、ベースイメージの更新漏れを招くランタイムのアップグレード、イメージのアップグレードと同じ扱いをされたステートフルなデータストアのメジャーアップグレード、匿名ルートのクラスを削除してしまうエッジ層の書き換えなどです。こうした事例はあまりにも頻繁に起こるため、独自のカタログがあります。references/migration-hazards.md(H1~H8)を参照してください。
ルール:どのフェーズも実装する前に、その計画を references/migration-hazards.md のすべてのハザードに照らしてレッドチーム検証してください。 各ハザードについて「このフェーズで発生するか」を確認し、実際のリポジトリに対してハザードの検出プローブを実行したうえで、コードを書く前に、その対応をフェーズのタスク/終了基準に反映します。計画時に検出できればタスクで済みますが、レビュー時なら手戻りになり、本番環境で見つかればインシデントになります。発生したものだけでなく、確認して問題なしと判断したハザードも記録してください。確認しないまま省略されると、見逃したのか意図的に対象外としたのか区別できません。
これは、独立した批判者による検証を制度化したものです。カタログを順に確認して自分で実施し、独立したセカンドオピニオンが得られる場合(例:ラバーダック役や批評エージェント)には、それも活用してください。参照用の PiggyMetrics の実行では、この検証によってすべてのフェーズで計画上の重大な欠落が見つかり、その欠落はそれぞれ H1~H8 のいずれかに該当していました。各フェーズの「決定事項」と終了基準に検証結果を反映し、実行エージェントがハザードを再発見するのではなく、確認済みのチェックリストを引き継げるようにしてください。
フェーズ 3:目標アーキテクチャを推奨する
意思決定の枠組み — 常に次の順序で評価してください: 各コンポーネント/依存関係について、影響の小さいものから大きいものへ、次のレベルを順に検討してください。問題を解決できる最初のレベルで止めてください。
-
そのままアップグレードする — メジャーバージョンを上げて、問題となる変更に対処できますか?(例:Node 14→22、Python 2→3、React 16→19、Rails 5→7)。これをデフォルトの選択肢としてください。アップグレードパスが公式にサポートされていない場合、破壊的変更が非常に広範で書き直しのコストを上回る場合、またはフレームワーク自体が放棄されている/EOL の場合に限り、これを退けてください。
-
依存関係を置き換える — 特定のライブラリは使われなくなっていても、そのパターン自体に問題がない場合、同じインターフェース形状を持つ、保守されている代替ライブラリに置き換えられますか?(例:Moment.js → date-fns、Request → got/fetch、CoffeeScript → decaffeinate を使用した TypeScript)。存在する場合は、ドロップイン置換や機械的な移行ツールを優先してください。
-
ラップ/アダプトする(Strangler Fig) — コンポーネントのインターフェースに問題はないものの、内部実装が保守困難な場合、クリーンなインターフェースを前面に設け、その背後で内部実装を段階的に置き換えられますか?結合度が管理可能で、旧システムと新システムを共存させて実行できる場合に有効です。
-
書き直す — 次の場合に限ります:フレームワークが放棄され、アップグレードパスがない。アーキテクチャ上の根本的な制約により、必要な新機能をサポートできない(例:同期処理専用の設計をリアルタイム対応にする必要がある)。または、率直な見積もりによってアップグレードのコストが書き直しのコストを上回ると判明した。書き直しを推奨する場合は、すべてに明確な根拠を求めてください。「古いから」だけでは不十分です。
-
削除する — 使われていないコード、使用実績がゼロの機能、ほかのシステムに置き換えられた非推奨機能が対象です。削除を推奨する前に、使用状況に関する主張を確認してください。
保守的な判断を優先してください。 最も安価な移行は、実行しない移行です。変更の影響が大きくなるほど、リスク、所要期間、コストが増します。新しいフレームワークで未完了の書き直しを行うより、古いフレームワーク上で動作しているシステムのほうが優れています。
機械的な移行に関する付随要件(アップグレード、置き換え、削除を推奨する場合に適用)。 これらは、ターゲットアーキテクチャの決定において初稿の計画でよく抜け落ちる項目です。それぞれ、references/migration-hazards.md のハザードクラスに対応しています。
- 依存関係の隔離漏れをなくす(H1)。 依存関係ファミリー全体を削除/切り替える場合は、すべてのマニフェストで使用されていない成果物を grep し、移行または隔離が必要な依存先をすべて列挙してください。最初に思い浮かんだ一部だけを挙げてはいけません。切り替え後のビルドターゲットを明示してください。
- フレームワークのメジャーアップグレードに伴うコードモッド(H2)。 メジャーバージョンの引き上げには、ロジックとは無関係な機械的な破壊的変更が伴います。名前空間の変更、非推奨 API の削除、テストエンジンの変更、設定キーの変更などが該当します。それぞれを個別のタスクとして列挙し、大規模なコードベースでは手作業による編集より、エコシステムの自動化されたレシピ/コードモッドツール(OpenRewrite、jscodeshift/react-codemod、
2to3/pyupgradeなど)を優先してください。最も忘れられやすい、テストフレームワークの移行も忘れないでください。 - ランタイムとデプロイの同期(H3)。 推奨によって言語/ランタイムのメジャーバージョンを上げる場合、アプリの実行時に使うランタイムのバージョンが固定されている箇所(ベースイメージ、
docker-composeのビルドコンテキスト、CI ランナーイメージ、engines/.nvmrc/.tool-versions、サーバーレスランタイムなど)はすべて、同じフェーズで更新する必要があります。フェーズの境界をまたいでビルド用ランタイムと実行用ランタイムが食い違ってはいけません。食い違うと、アプリのビルドは成功しても実行時に失敗します。
次の内容を含むターゲットアーキテクチャセクションを作成してください。
- 推奨技術スタック: 各選択の根拠を含む(フレームワーク、言語、ランタイム、データベース、インフラストラクチャ)
- アーキテクチャパターンの推奨(モノリス → モジュラーモノリス → サービス、イベント駆動、サーバーレスなど)と、その根拠
- 残すもの・置き換えるもの: 上記の判断フレームワークを用いて、主要なコンポーネントをそれぞれ明示的に分類します:
- ✅ そのまま維持(現在でも十分に新しい、または適切)
- ⬆️ その場でアップグレード(バージョンを上げ、破損箇所を修正)
- 🔀 依存関係を入れ替え(保守されなくなったライブラリを、保守されている同等品に置き換え)
- 🔄 ラップ/適合(インターフェース層を追加し、内部を段階的に置き換え)
- 🔁 書き直し(根本的に互換性がない。正当化が必要)
- 🗑️ 削除(デッドコード、非推奨の機能、置き換え済みのもの)
各推奨事項について、インライン ADR を記述します:
#### ADR: [Decision Title]
- **Context:** [Why this decision is needed]
- **Decision:** [What we chose and which decision framework level it falls under]
- **Alternatives considered:** [What else was evaluated and why it lost]
- **Consequences:** [Tradeoffs accepted]
フェーズ 4: 機能ごとの移行分析
アーキテクチャドキュメントで特定した主要な機能/ドメインごとに、以下を網羅したセクションを作成します:
- 現在の実装 — ファイル参照を含む一段落の要約
- 移行戦略 — このコンポーネントについてフェーズ 2 で選んだ A/B の選択肢(Freeze-then-lift か Beachhead/walking-skeleton か)と、その手法: Strangler Fig、Big Bang 書き直し、Lift & Shift、Incremental Refactor、Leave In Place のいずれか
- テスト可能性の状態 — このコンポーネントの Testability Milestone がどこに位置するか、および 安全性ラダー の段階(L0〜L4)と、残存リスクの明記
- 依存関係と結合 — 一緒に壊れる、または一緒に移動しなければならない他の要素
- 工数見積もり — T シャツサイズ(XS/S/M/L/XL)と根拠
- リスク評価 — 何が問題になりうるか、データ移行上の懸念、ユーザーへの影響
- 受け入れ基準 — 移行が成功したことをどう判断するか(未稼働のテストスイートに対してではなく、選択したオラクル/シーム(seam)の契約に対して表現する)
フェーズ 5: 段階的な実装計画
順序付けられた段階的な計画を作成します。各フェーズは独立してデプロイ可能であること(本番環境で動作しない、移行途中の中途半端な状態を作らない)。
フェーズのゲーティングは、リージョン(regime)を考慮します(すべてのフェーズに適用)。 このルールは段階的計画の冒頭で明示し、すべてのフェーズの終了基準で必ず守ってください。フェーズは、その検証・終了基準がパスするまで 完了とみなしません。基準は次の条件を満たす必要があります: (a) 客観的に検証可能であること。(b) 次のフェーズを開始する前に 実際に実行され、記録されていること。(c) ゲーティングされていること。すなわち、フェーズ N の基準が明確に満たされるまで、フェーズ N+1 に進んではいけません。ただし、どの基準が有効かは、そのコンポーネントのリージョン(フェーズ 2c)によって異なります:
- テスト可能化後(「lit」)のフェーズ: 終了基準は実行可能なコマンドやグリーンな CI です。そのフェーズのブランチ/PR におけるグリーンな CI が正式な判定シグナルです。
- テスト可能化前(「dark」)のフェーズ: コンポーネントがまだ稼働していないため、グリーンな CI によるテストゲートは カテゴリーエラーです。終了基準は、達成可能な安全性ラダーの段階から導き出します。たとえば、取得済みのシーム/オラクルのスナップショット、可逆性の足場が存在することの検証、合格したスモークチェックリスト、記録されたレビューなどです。まだ実行できないテストスイートを理由に、dark リージョンのフェーズをブロックしないでください。
フェーズの合否が不明な場合は、合格したと仮定せず、その旨をユーザーに報告してください。
最初のフェーズは、固定された「レガシーのグリーンゲート」ではなく、達成可能な最大限の安全性を確立するものです。 「すべてを復旧させ、CI をグリーンにする」とハードコードしないでください。フェーズ 2 の出力に基づき、コンポーネントごとに最初のフェーズを形作ってください。
- 戦略 A(凍結してから解除)、コンポーネントは蘇生可能: 最初のフェーズは、
従来型のセーフティネットとベースラインそのものです。純粋に追加のみで、動作変更はありません:
- 特性化/ゴールデン/コントラクトテスト を シーム に設置し、現在の観測可能な動作を固定します(プロトコルトレース、API スナップショット、出力ゴールデン)。
- CI・リンター・フォーマッター を設定し、グリーンにします(後続の lit 段階に対する権威あるゲートになります)。
- 依存関係の固定/コミット済みロックファイル と、記録された既知の正常なベースライン(バージョン、ツールチェーン、現在のビルドと実行の方法)。
- 「ネットが失敗することを証明する」。 意図的にコードを変更し(例: 1 つのプロトコルコードまたは戻り値を変える)、新しいテストが 赤 になることを確認してから元に戻します。決して失敗しないセーフティネットは何も証明しません。その歯が実際に機能することを証明してください。
- 戦略 B(橋頭堡/ウォーキングスケルトン)、コンポーネントは死んでいる: 最初のフェーズは 「最小のスライスで Testability Milestone に到達する」 ことです。最も薄いエンドツーエンドのパスを最新のスタックに通し、ビルドでき、起動でき、実行中の実テストが 1 つ以上グリーンになるまで進めます。その間、検証の基準として旧システムからシーム/オラクルのコントラクトを採取します。死骸をネットで囲もうとしないでください。 その終了基準は、残存リスクを明示したうえで達成可能なセーフティラダーの段階です。承認されたダウングレードは失敗ではありません。
最初のフェーズの基準が(どの段階であれ)満たされて初めて、後続のインフラおよび機能フェーズを開始します。
各フェーズは次の形式で構成してください:
### Phase N: [Name] (T-shirt size: M)
**Goal:** [One sentence]
**Regime:** [pre-testability ("dark") | post-testability ("lit")] — per component
**Safety rung:** [L0–L4, with residual risk named if below L4]
**Prerequisites:** [Which phases must complete first]
**Duration estimate:** [Relative, not calendar — e.g., "2-4 sprints"]
#### Tasks
| ID | Task | Component | Blocked by |
|----|------|-----------|------------|
| N.1 | ... | ... | — |
| N.2 | ... | ... | N.1 |
#### Risks & Mitigations
- **Risk:** ... → **Mitigation:** ...
#### Decisions made
- [Every sub-decision this phase depends on, resolved and documented here so the
phase can be implemented without further user input. State "dropped" vs
"deferred" explicitly for anything cut.]
#### Verification & Exit Criteria (Definition of Done)
- [ ] [Regime-appropriate criterion. For LIT phases: a runnable command / green
CI check, citing the actual command from the Commands & Verification
Inventory. For DARK phases: the achievable safety-ladder rung's evidence —
captured seam/oracle snapshots, reversibility proven, smoke checklist
passed — NOT a green test suite the component can't yet run.]
- [ ] [Include a parity/characterization check against the chosen oracle whenever
the change is meant to preserve behavior.]
- [ ] [If purely additive, assert it: "no behavior/dependency/logic changed."]
- [ ] [If exiting below L4, state the residual risk and which later phase closes
it (e.g., "client test gate deferred to the client-migration phase").]
順序付けの原則:
- まずコンポーネントごとに Testability Milestone を特定してください。 「テスト可能」を末尾に先送りしながら、冒頭でゲートを要求することのないよう、そこに早く到達する最小のスライスを計画します。
- コンポーネントは、自身の testability line を越えるまで、自動テストゲートを要求してはなりません。
- ロードマップで CI Milestone を明記してください。 どのフェーズで CI を構築するか(Testability Milestone 到達時点以降で最初の lit フェーズ)を明示し、読み手が CI の開始時期を推測しなくて済むようにします。また、それを 強制する(必須ステータスチェック/ブランチ保護)のは手動の人間による作業であり、エージェントのタスクではないことを明記してください。
- 動作変更の前に最初のフェーズで安全性を確保してください。 動作を変更する前に、達成可能な最高の段階を確立します(必ずしも完全なグリーンゲートである必要はありません)。
- 次にインフラと横断的関心事(認証、設定、ロギング、CI/CD)
- 次に最もリスクが高い、または最も価値の高い機能(パターンを早期に実証する)
- 最後に低リスク・低結合の機能(並列化しやすい容易な成果)
- データ移行には独立したフェーズを設け、ロールバック計画を用意してください
フェーズ 6: 実行ガバナンス
移行計画は紙の上ではなく、実行段階で失敗します。各フェーズを誠実かつ可逆に保つガバナンスを組み込んでください(あらゆるエコシステムに共通する内容です):
- フェーズごとにブランチを切る。 フェーズの作業を既定ブランチに直接コミットしないでください。フェーズごとに PR を 1 つ開き、lit レジームのフェーズでは、マージ前に PR 上の CI が成功することを正式な合格シグナルとしてください。dark レジームのフェーズでは、PR にもそのラングの証跡(取得済みのコントラクト、スモークテストの結果、可逆性のための足場)を含めてください。
- 次のフェーズの前にトランクへマージし、スタックしない(H7)。 各フェーズブランチはトランクから切り出し、その PR は次のフェーズを開始する前にトランクへマージしてください。フェーズブランチやその PR を兄弟のフェーズブランチを基点にしないでください。そうすると PR 同士が互いにマージされ、トランクが知らないうちに数フェーズ遅れ、後続のフェーズがスタック禁止ルールを破らざるを得ない状況に追い込まれます。フェーズを開始する前に、前のフェーズがトランクにマージ済みであること、およびブランチ作成時点で
git log origin/<trunk>..HEADが空であることを確認してください。制御されたスタッキングが真に避けられない場合に限り、スタック全体をトランクに取り込む必須の調整 PR と、明示的な残存リスクの注記を伴う場合にのみ許可されます。黙示的な既定としては決して行わないでください。 - トランク名を確認し、旧来の既定ブランチを廃止する。 リポジトリの実際のトランク(例:
main)を固定してください。また、既定に準ずるブランチ(master)が別に存在する場合は、「履歴のみ — 対象にしない」と明記し、フェーズの作業が誤ったブランチに入らないようにしてください。 - ゲートはレジームに合わせる。 lit フェーズは CI が成功した時点で次へ進みます。dark フェーズは、残存リスクを明示したうえで、達成可能な安全ラダーのラングに到達した時点で次へ進みます。「完了しているように見える」という判断や、まだ実行できないテストスイートに基づいて進めてはいけません。
- CI マイルストーンで CI を整備し、強制の作業は人間に引き継ぐ。 CI を導入するフェーズ(最初の lit フェーズ)を明示してください。2 つのステップを区別してください。ワークフローファイルの作成はエージェントが行えます。一方、それを強制される必須ステータスチェック/ブランチ保護(または MR 承認)ルールにする作業は、エージェントが実行できないプラットフォームの管理画面での手作業です。人間が設定するまでは、CI は実行されるものの、マージをブロックしません。したがって「ブランチ保護/必須チェックを有効にする」は、CI フェーズの完了基準と §9 のステークホルダー決定事項の両方に、明示的なユーザー対応項目として記録してください。エージェントが完了したタスクとして扱ってはいけません。
- インターフェースを保持し、独立してデプロイ可能にする。 各フェーズ後もシステムが実行可能な状態を保つため、ロールバックは前のバージョンを再デプロイすることで行えます。インターフェースを保つ書き換えを優先してください(内部実装を安定したインターフェースの背後にラップする)。そして、シーム/オラクルのコントラクト(存在する場合はゴールデンテスト/特性テスト)によって同等性を証明してください。
- 生きた計画として維持する。 各フェーズの完了基準を満たしたら、
MODERNIZATION_PLAN.mdのステータスマーカーを更新してください。✅ 完了、⏭️ 範囲縮小、🗑️ 中止のいずれかを使用します。実装中に行った決定を記録し、コンポーネントがテスト可能性の境界を越えた時点で、安全ラダーのラングと残存リスクの登録簿を更新してください。 - 実行可能なドキュメントも最新に保つ(H8)。 生きた計画の規律はプランファイルだけに適用されるものではありません。トポロジーを変更するフェーズ(モジュール/リアクターの構成、サービスの削除、ブランチ名の変更、コマンドの変更、エンドポイントの追加・削除)では、同じ PR で
.github/copilot-instructions.md、README、およびモジュール/トポロジーの一覧を必ず更新してください。これらのドキュメント更新はフォローアップ作業ではなく、フェーズの完了の定義(Definition of Done)の一部として扱ってください。「隔離されたモジュール」の古い一覧や、ハードコードされた古いブランチへのリンクは、次のエージェントや人間を積極的に誤らせます。 - 各フェーズを実装する前にレッドチーム検証を行う(フェーズ 2.5)。 フェーズ計画を
references/migration-hazards.md(H1〜H8)と照らし合わせて検証し、修正内容をタスクと完了基準に組み込んでから、コードを書き始めてください。確認済みのチェックリストをフェーズの「実施した決定」に記録してください。 - 編集可能な指示を生成する。 テンプレート
references/copilot-instructions.template.mdから.github/copilot-instructions.mdを生成してください(必要に応じて.github/ディレクトリを作成します)。このファイルには、コマンド表と、レジームを考慮したフェーズゲートおよびブランチ/PR のルールを含めてください。これにより、実行するエージェントや人間が、GitHub Copilot が自動で読み込む場所で正式なコマンドとゲートを参照できます。ユーザーは自分のゲートに合わせてこのファイルを編集します。既に.github/copilot-instructions.mdが存在する場合は上書きしないでください。コマンド、ゲート、ブランチの各セクションをマージするか、生成したファイルを.github/copilot-instructions.modernization.mdとして並べて作成し、ユーザーにマージするよう伝えてください。
フェーズ 7:移行のセーフティネット
必要な運用上のガードレールを文書化します。
- フィーチャーフラグ — 何をフラグで制御するか、旧バージョンと新バージョンをどのように共存させるか
- データ移行戦略 — スキーマ変更、バックフィル、デュアルライト期間。
永続ボリュームを使用するステートフルなデータストアのメジャーアップグレード(H5)では、
エンジンイメージ/タグの更新は移行ではありません。次のいずれかを選び、文書化します。
手順とロールバックを含む段階的な/機能互換バージョンによるアップグレード、または
データが一時的/デモ用の場合の明示的な破壊的リセット(ボリュームを削除して再シード)。
これは意図的な決定として明記し、ロールバック用に旧メジャーバージョンのイメージを保持します。
(例:既存の
/data/dbボリュームを使った Mongo 3→7 の場合、デモならdown -vと再シードを行うか、実データなら段階的な FCV アップグレードが必要です。) - ロールバック計画 — 問題が発生した場合に、各フェーズでどのように元に戻すか
- 一時的な非セキュア状態の登録簿(H6) — 移行中もシステムを実行可能に保つために意図的に導入する、弱い状態 (すべてを許可する暫定措置、CSRF の無効化、公開されたエンドポイント、プレースホルダーのシークレット)をすべて記載します。 それぞれについて、必要な理由、その状態を解消するフェーズ、残存リスク、レビュー担当者向けの 「フェーズ N までは設計上この状態とする」という注記を含めます。各弱体化の範囲は可能な限り限定します (例:すべてを許可するチェーンでも、フォームログイン/HTTP Basic は明示的に無効にします)。 事前に宣言することで、繰り返されるスキャナー/レビュー担当者からの指摘を、追跡可能な決定事項に置き換えられます。
- オラクルとシームの契約 — 実行中のインスタンス/記録された I/O/ゴールデンスナップショット (外部参照を利用できない、または許可されていない場合は自己凍結したゴールデンマスター)のうち、 どれを動作上の参照とするか、また新しい作業をどのように比較するか
- テスト戦略 — 新たに必要となるテストカバレッジ(コンポーネントがテスト可能性の境界を越えるたびに ターゲットスタック上に構築するもの)と、隔離したままにするもの
- 可観測性 — 新システムが旧システムと一致することを証明するメトリクス/アラート
出力構成
次の内容を含む主要な Markdown ファイル MODERNIZATION_PLAN.md を作成します。
- エグゼクティブサマリー(何を、なぜ行うのか、おおよその範囲を1段落で)
- 現状の評価(アーキテクチャ文書に基づく)
- 実現可能性スパイクの結果と戦略 — コンポーネントごとのスパイクの調査結果、A/B 移行戦略、特定したテスト可能性マイルストーン、目標とするセーフティラダーの段階、L4 未満の項目に対する残存リスク登録簿。さらに、計画全体のCI マイルストーン(どのフェーズで CI を立ち上げるか)と、これを強制するには人間による手動の作業が必要である旨を記載します。
- ADR を含むターゲットアーキテクチャ
- 機能ごとの移行分析(テスト可能性の状態とセーフティラダーの段階を含む)
- 段階的な実装計画 — 最初のフェーズで、固定されたグリーンのレガシーゲートではなく、達成可能な範囲で最も高いセーフティラダーの段階を確立します。各フェーズにはテスト可能性の前/後を明記し、適切なレジームに応じたゲート付き終了条件を設けます。CI マイルストーンのフェーズ名を明記し、「ブランチ保護/必須ステータスチェックを有効化する」という手動のユーザー作業を列挙します。
- 実行ガバナンス(フェーズごとのブランチ、レジームを考慮したゲート、最新状態を保つ計画)
- 移行のセーフティネット(オラクルとシームの契約、フラグ、ロールバック、可観測性)
- 未解決の質問/関係者による決定事項 — エージェントが実行できない手動のプラットフォーム設定の引き継ぎを含みます(例:CI を強制ゲートにするための必須ステータスチェック/ブランチ保護の有効化)
また、.github/copilot-instructions.template.md から、付属ファイル .github/copilot-instructions.md を作成します(GitHub
Copilot が自動読み込みするパスです。.github/ が存在しない場合は作成してください)。プロジェクトの標準コマンド、フェーズゲートのルール、ブランチのルールを記入し、計画を実行する担当者が編集して採用できる状態にします。既存の
.github/copilot-instructions.md は上書きしないでください。既存の内容と統合するか、同階層に
.github/copilot-instructions.modernization.md を作成し、その旨をユーザーに伝えてください。
規約
- 現状を参照する際は、すべてを言い直すのではなく、アーキテクチャ文書を引用してください。この文書では将来の方針を示してください。
- 明確な意見を示してください。「A でも B でもよい」ではなく、具体的な推奨案を示してください。何を選ぶか、その理由も明記してください。ユーザーは変更できます。
- 現実的な範囲に収めてください。 一度にすべてを変えようとするモダナイゼーション計画は現実的ではありません。フェーズ 1 の対象と「将来の検討事項」を明確に分けてください。
- 計画中に、フェーズ内のすべての判断を確定してください。 フェーズ計画には、その実装に必要なすべての下位判断を、すでに決定して文書化した状態で含めてください(「決定事項」ブロック)。これにより、ユーザーに再確認せずにフェーズを実行できます。対象から外すものはすべて、「対象外」か「延期」かを明確にしてください。この 2 つは同じではありません。
[DECISION NEEDED]は、フェーズを阻む真のステークホルダー/ビジネス上の選択(予算、チーム規模、製品の方向性、スケジュールの制約)に限って使用し、実行可能なフェーズに未決事項を残さず、計画中にユーザーと解決してください。 - 過剰な作り込みは避けてください。 古いスタックでも問題なく動作し、保守の負担もないコンポーネントには、「そのままにする」という推奨も有効です。
- デフォルトでは停止しているものとみなし、安全性は状況に応じて調整してください。 最初からレガシー CI ゲートをすべてグリーンにすることを求めないでください。実現可能性のスパイクを実施し、到達可能な安全性ラダーの最上位を選び、レベルの引き下げも妥当な結果として扱い、残るリスクを明示してください。決して失敗とはみなしません。
- テスト可能になる時期を明確にしてください。 各計画ではコンポーネントごとにテスト可能性マイルストーンを示し、そのコンポーネントがテスト可能性の境界を越える前に、自動テストゲートを必須にしてはいけません。
- CI マイルストーンを明示し、適用は人間に委ねてください。 CI を立ち上げるフェーズ(最初に実施するフェーズ)を明記し、CI を必須チェック/ブランチ保護ルールにするには、エージェントには実施できない手動のプラットフォーム操作が必要であることを明確にしてください。完了済みのタスクではなく、ユーザーのアクション項目として提示してください。
- 死骸ではなく、接続部分を検証してください。 外部から観測できる契約(プロトコル、スキーマ、ワイヤ形式/ファイル形式、エンドポイント)を安全性の基準とし、優先順位を付けたオラクルを使ってください(実行中のインスタンス → 記録済みの I/O → コードを仕様として扱う → 外部の参照元が存在しない、または使用を許可されていない場合は自前で固定したゴールデンマスター)。リライト時に削除するテストを実行するためだけに、スプリントを費やして停止したツールチェーンを復活させないでください。
- 汎用的な表現にしてください。 コマンドとゲートは、特定のスタックを前提とせず、プロジェクトのパッケージマネージャー/テストランナー/CI に沿って記述してください。
- 実装前に各フェーズをレッドチームで検証してください(H1~H8)。 各フェーズ計画を
references/migration-hazards.mdと照らし合わせて確認し、対策をタスク/終了条件に組み込んでから着手してください。計画中に発見したハザードはタスク、レビュー中なら手戻り、本番環境ならインシデントになります。不完全な隔離、フレームワークのコードモッド、ランタイムとベースイメージの同時更新、ルートクラスの網羅的な列挙、データストアのアップグレード経路、移行中の安全性低下に関するノイズ、積み重なった PR とトランクの乖離、生きたドキュメントの乖離といった戦術的なハザードは、戦略的な足場づくりだけでは見落とされ続けます。