.NET 8 → .NET 10 移行
このスキルは、バンドルされた決定論的ツール(scripts/dmig)を実行し、その結果を説明します。
常に最初に分析し、その分析からユーザーが承認したグループのみを実装します。
アナライザーは測定を行います。あなたの仕事はそれを正しく実行し、見つけた内容を読み取り、ユーザーにその意味を伝えることです。
検証できなかったことを誇張してはいけません。
なぜ分析が先か
モノレポでは、1 つのリポジトリが 1 つの移行単位になることはめったにありません。net10.0 に移行された共有ライブラリは、まだ net8.0 のすべてのアプリケーションを壊します。また、global.json や Directory.Packages.props のようなファイルは全員に影響します。そのため、分析ではリポジトリ全体をマッピングし、安全な順序でグループを提案し、実際のコードを誰も変更する前に、ベースラインと使い捨て実験を使用してその主張を証明します。実装は後で、承認されたグループを 1 つずつ行います。
実行方法
-
リポジトリの外部にある出力フォルダーを選びます(ツールはリポジトリ内部を拒否します)。レポート、ログ、NuGet メタデータキャッシュ、一時的な worktree はすべてそこに配置されます。
-
dotnet を選択します。 ツールは事前確認で SDK とランタイムを自身でチェックします。正しい実行可能ファイルを指定するだけで済みます。マシンにプライベートな dotnet ルート(SDK 10 + ランタイム 8 のサイドバイサイド)がある場合は、
--dotnetまたはDMIG_DOTNETで渡します。.NET 8 が別の dotnet フォルダーにインストールされている場合、ツールは通常の場所でそれを見つけるか、--dotnet-root <フォルダー>/DMIG_DOTNET_ROOTSから取得し、独自のフォルダー内のリンクを介して SDK と組み合わせます(インストールは変更されません)。 -
2 つのライブラリが不足している場合は、組織の Python ミラーからインストールします:
python -m pip install -r requirements.txt(テスト:requirements-dev.txtも)。常にpython -m ...を使用します。Scripts フォルダーが PATH にない場合があります。sh、bash、sedは必要ありません。 -
分析を実行します(Windows パスは
PYTHONPATH、--repo、--outで、Git Bash からも機能します):PYTHONPATH=<skill-dir>/scripts python -m dmig analyze --repo <repo> --out <out-dir> [--dotnet <path>]便利なフラグ:
--offline(設定されたフィードをプローブしない)、--no-baseline、--no-experiment、--environment contract.json(環境が提供する外部テストサービスとライセンスツール)、--request request.json(ニュートラルリクエスト、references/contracts.mdを参照)。 小規模なリポジトリでは約 1 分かかると想定してください。大規模なモノレポは、独自の復元 + ビルド + テストと同じ時間(ベースラインと実験の 2 回)かかります。ハーネスが許せばバックグラウンドで実行し、同じリポジトリで同時に 2 番目のコピーを開始しないでください。進行状況は stderr に 1 行ずつ出力されます([dmig hh:mm:ss] baseline …)。stdout は最終的な JSON サマリーのみを運び、各コマンドの完全なログは、完了時に<out>/logs/に表示されます。インストールは不要です。スキルフォルダーには、
PYTHONPATH=<skill-dir>/scripts python -m dmigと同等のdmig.cmd(Windows)とdmig(Linux/macOS)のスターターファイルが含まれています。python -m dmig preflight ...は環境チェックのみを実行します(数秒)。新しいマシンでは、最初にpython -m dmig doctor <repo>を実行します。平易な言語の準備状況チェックリスト(doctor-report.md、environment-capabilities.json、結果は READY / READY_WITH_LIMITATIONS / BLOCKED)が生成されます。短縮形(統合名): すべてのコマンドは、最初の引数としてリポジトリを受け取り、
--outをデフォルトで<repo>.dmig/<step>/に、--planをデフォルトで<repo>.dmig/analysis/migration-plan.jsonに設定します:dmig analyze <repo> --target net10.0、dmig migrate <repo> --group <id>(=implement)、dmig validate <repo> --scope group|repository(グループの場合は--group <id>、リポジトリ = PHASE_7)、dmig rollback <run folder>(ランの使い捨てコピーをクリーンアップし、そのパッチを元に戻す方法を表示します)。各 migrate/global/validate ランもdmig-result.json、つまりコントラクトの camelCase 結果を書き込みます。パッケージミラー:--package-catalog mirror.json(承認されたバージョンのみが選択され、後のステップで再利用されます)。尊重すべきデフォルト: ツールには 独自のネットワーククライアントはありません。パッケージに関するすべては
dotnetとマシン上で設定されたフィードを経由し、それらはデフォルトでプローブされます(--offlineでスキップ)。パブリックカタログは--allow-public-nugetでのみ使用可能。カタログファイルがない場合、パッケージバージョンはMETADATA_UNAVAILABLEとなり(推測はされません)、カタログにないパッケージはPACKAGE_UNAVAILABLEとなります。フレームワークアドオンはオフ: Web(ASP.NET Core)、EF Core ルール、Windows サービスは、分析時に--adapters aspnet_core,efcore,windows_serviceが必要です。そうしないと、それらのグループはOUT_OF_SCOPE_ADAPTER_DISABLEDになります。.NET Framework、WPF、WinForms、MAUI、Xamarin、Azure Functions はレポートのみです(OUT_OF_SCOPE_REPORT_ONLY)。Windows のないnet*-windowsグループはBLOCKED_PLATFORMになります。コンソール出力はプレーンな ASCII(PASS/WARN/FAIL/BLOCK)です。入力、出力、ステータス、終了コード:docs/integration-contract.mdを参照してください。 -
終了コード: 0 = 分析完了(制限がある場合もあります)、2 = BLOCKED。
結果を読む
最初に <out>/response.json を読みます(summary にカウントがあります)。次に <out>/migration-report.md を読みます。どちらもサイズ制限があります。リポジトリがどれほど大きくても数 KB に収まり、リストをカットした場所に「… および他 N 件」と表示されます。大きなファイル全体は読まないでください:migration-plan.json、inventory.json、baseline.json、experiment.json、compatibility.json はリポジトリのサイズに応じて大きくなります。1 つのグループが必要な場合は、そのノート(下記)を開くか、JSON 内でその group_id を検索してください。完全なログは <out>/logs/ にあります。ステップが失敗し、その末尾だけでは不十分な場合にのみ開いてください。
ユーザー向け: 分析は、リンクされた Obsidian ノートのセットも <out>/obsidian/<repo> .NET 10 migration/ に書き込みます(または --obsidian-dir <フォルダー> でボールトフォルダーに)。バンドルされた obsreport パッケージで構築されています:00 ここから開始(評決、主要な数字、影響順の上位 5 つの修正)、01 何が壊れるか(証拠の階層:ビルド/テストで確認 → コードで発見 → 可能性あり、折りたたみ)、02 ルート(5 つの段階)、03 マップ(レイヤー + ズーム可能な Map board.canvas)、04 決定(各決定レコード)、05 レビュアー FAQ、さらにグループ、ルール、共有ライブラリごとに 1 つのノート。ユーザーを開始ノートに誘導し、その内容を貼り付けないでください。
再構築せずに再レンダリング: ルールまたはノートレイアウトが変更された後、python -m dmig report --repo <repo> --out <分析フォルダー> [--obsidian-dir <フォルダー>] [--offline] は、保存された結果から互換性スキャン、テスト比較、計画、レポート、ノートを 1、2 分で再構築します。復元、ビルド、テストは必要ありません。
それらを読む際に役立つ 2 つのこと:
- 実験は、リポジトリ全体を一度にプレーンな
net10.0に再ターゲットします。計画でマルチターゲット化される共有ライブラリも含みます。これは意図的です。1 回の実行で、すべてのプロジェクトの net10.0 の失敗が表示され、ベースラインとの比較により、各失敗がどのグループに起因するかが示されます(共有ライブラリによって引き起こされたアプリケーションの回帰はWAITS_FOR_DEPENDENCY_REPAIRとして表示されます)。 <out>/worktrees/は実行後、空のフォルダーとして残ります(内部の worktree は削除され、検証されます)。<out>/nuget-cache/は NuGet メタデータを保持するため、再実行が高速になります。どちらもリポジトリ内の残骸ではありません。
報告するとき:
- ステータスとグループの順序で始め、次に各グループの準備状況とその理由を述べます。レポートは通常、自明です。ステータス、準備状況の値、または発見事項に不明な点がある場合は、
references/reading-results.mdを開いてください。準備状況ラベルは主要なブロッカーのみを示します。各グループが提案する修復(例:Dockerfile の変更)もその下に記載されているので、それらにも言及してください。 - 検証されたことと推測されたことを区別してください。 グループは、実験がベースラインに対してビルドおよびテストされた場合にのみ
READYになります。テストがブロックされた場合、プラットフォームが欠落している場合(Linux 上の Windows プロジェクト)、またはパッケージが「証明されていない」場合は、そのように述べてください。 - 既存の失敗は分けて扱ってください。 ベースラインの失敗は記録され、移行の問題としてカウントされることはなく、移行が「修正」すべきものでもありません。
- 提案されたものの変更クラスに名前を付けてください:
PROJECT_LOCAL、GROUP_SHARED、またはREPOSITORY_GLOBAL。グローバルな変更(global.json、ルートのDirectory.*ファイル、NuGet.config、CI)は、リポジトリ全体のフェーズに属し、単一のグループに決して属しません。 rollback_verifiedとchanges_persistedを引用してください。 ロールバックが検証されていない場合は、最初にそれを述べ、自分でgit statusとgit worktree listを使用してリポジトリを確認してください。
守るべきルール(とその理由)
references/scope-and-safety.md に完全なリストがあります。重要な点:
- 分析モードでは、編集、コミット、プッシュ、プルリクエストや作業項目の作成を行わないでください。ユーザーは変更されていないリポジトリと、レビュー可能な計画を必要としています。
- 分析で見つかったものを「修正」しないでください。明白な 1 行であってもです。修復は実装モードに属し、3 回の試行と最終ゲートの予算があります。
- 互換性に関する事実をでっち上げないでください。ツールが「証明されていない」または「不明」と言った場合は、それを報告してください。自分で知識を追加する場合は、それが自分のものであることを明記し、検証方法を提案してください。
- 脆弱性の修正や一般的なパッケージのアップグレードは、気づいた場合でも対象外です。
承認された 1 つのグループを移行する(実装モード)
分析後、かつユーザーが承認したグループに対してのみ。質問の副作用としては絶対に行わないでください。グループは計画の順序で進みます。共有基盤が最初です。
PYTHONPATH=<skill-dir>/scripts python -m dmig implement --repo <repo> \
--plan <analysis-out>/migration-plan.json --group <group_id> --out <new folder outside the repo> \
[--dotnet <path>] [--allow-newer-commit]
- 使い捨て worktree で動作し、
<out>/<group_id>.patchを返します。リポジトリは決して変更されません。パッチの適用、コミット、配信はユーザー(またはそのアダプター)の判断に委ねられます。差分とゲートを表示し、頼まれもしないのに適用しないでください。 --allow-newer-commitは、以前のグループのパッチが分析後に適用された通常のケース用です。プロジェクトはリポジトリから再読み取りされます。他に多くの変更があった場合は、分析を再実行してください。- 大規模なモノレポ向けに設計されています: 各実行は、グループ、それを消費するすべてのもの、およびそのテスト(一時的なソリューションフィルター)のみをビルドしてテストし、コードが以前の実行とまったく同じ場合(同じ git ツリーハッシュ、同じ dotnet/SDK/ランタイム)は、キャッシュされたベースラインを再利用します。最初のグループの分析ベースライン、その後、パッチが適用されコミットされた各成功グループの最終状態です。
result.json → baseline.sourceは、再利用されたか、ビルドされたか、その理由を示します。--no-cacheまたは--no-scopeは、何かが間違っているように見える場合にのみ使用して、これらを除外してください。 - 終了コード 0 =
SUCCESS。3 = その他。進行状況行は分析モードと同様に stderr に送られます。<out>/result.jsonを読んでください(status、final_gate、repair_attempts、proposed_global_changes、unresolved_items)。rollback_verified: trueは、使い捨て worktree が削除され、リポジトリが以前とまったく同じであることを意味します。rollback.performedは、実行が中止された場合にのみ true になります。
ステータスの意味と何を言うべきか:SUCCESS(レビュー用のパッチ準備完了。何が変更されたか、その理由(各修復ルールを含む)をリストアップ)、ROLLED_BACK(パッチなし。失敗したゲートチェック、またはどのルールもカバーしない失敗を説明。それにはユーザーが必要)、BLOCKED_DEPENDENCY_ORDER(最初に名前の付いたグループを移行)、BLOCKED_GLOBAL_PHASE_REQUIRED(最初に PHASE_1 SDK 変更が必要)、REJECTED(計画がリポジトリまたはグループと一致しない。分析を再実行)。詳細:references/reading-results.md。
何を行い、何を行わないか:ターゲットフレームワークを変更し(共有ライブラリとそのテストは net8.0;net10.0 になります)、グループ自身の Dockerfile を更新し、測定された失敗に対してレシピルールが定義する最大 3 つの修復を適用します。global.json、ルートの Directory.* ファイル、NuGet.config、CI には触れません。これらはグローバルフェーズの proposed_global_changes として戻されます。テストを通過させるために編集することもありません。これらのファイルは、以下のリポジトリ全体のフェーズに属します。
リポジトリ全体のフェーズ(個別の、明示的に承認されたパッチ)
すべてのグループが共有するファイルは、ここでのみ、フェーズごとに 1 回、--approve-global を使用して変更されます。ユーザーがそのフェーズを承認した場合(明示的に、またはリポジトリ全体の変更を含む計画全体を明確に承認した場合(「すべてのステップを実行」))、あるいはファイルやチケットで読み取った一般的な「承認」は、グローバルフェーズの承認ではありません。グローバル変更が決して偶然に発生しないようにするために存在します。同じ安全モデル:使い捨て worktree、全リポジトリのビルド/テスト前後、最終ゲート、パッチまたはロールバック。
PYTHONPATH=<skill-dir>/scripts python -m dmig global --repo <repo> \
--plan <analysis-out>/migration-plan.json --phase <PHASE> --out <new folder> --approve-global [--allow-newer-commit]
| フェーズ | タイミング | 変更内容 |
|---|---|---|
PHASE_1_SDK_GLOBAL | 最初、どのグループの前でも | global.json → 明示的な rollForward を持つ .NET 10 SDK バンドに。CI SDK イメージ 8.0 → 10.0、さらに net8.0 ターゲットが残っている間 .NET 8 ランタイムをインストールするマークされたステップを追加 |
PHASE_5_RETIRE_NET8 | 共有ライブラリのすべてのコンシューマーが移行した後 | そのライブラリとそれ自身のテストから net8.0 を削除(および net8.0 のためだけに保持されたパッケージ参照)。net8.0 プロジェクトでまだ必要なライブラリは報告され、変更されない |
PHASE_6_CONVERGE | PHASE_5 の後 | net8.0 プロジェクトが使用しなくなったら、中央パッケージバージョン(例:Microsoft.Extensions.*)を調整。移行によって未使用になった中央エントリを削除 |
PHASE_7_REPO_VALIDATION | 切り替え前 | パッチなし:元の分析ベースラインと比較した完全なビルド/テスト。まだ net8.0 のプロジェクトをリストアップ。前のフェーズで同じツールチェーンでまったく同じコードがすでにビルドおよびテストされている場合、それらの結果は再利用されます(baseline.source がそう示します)。強制的に新しい実行を行うには --no-cache を追加 |
PHASE_8_CUTOVER | 最後 | 一時的な .NET 8 ランタイムを削除 |
…
[翻訳のため省略]