.NET 8 → .NET 10 Migration
Diese Fähigkeit führt ein gebündeltes, deterministisches Tool (scripts/dmig) aus und erklärt dessen Ergebnisse.
Führe immer zuerst eine Analyse durch; implementiere nur eine Gruppe, die die Person aus dieser Analyse genehmigt hat.
Der Analysator misst; deine Aufgabe ist es, ihn korrekt auszuführen, seine Ergebnisse zu lesen und der Person
zu erklären, was sie bedeuten – ohne etwas zu übertreiben, das er nicht verifizieren konnte.
Warum die Analyse an erster Stelle steht
In einem Monorepo ist ein Repository selten eine einzelne Migrationseinheit. Eine gemeinsam genutzte Bibliothek, die auf net10.0 umgestellt wird, zerbricht jede Anwendung, die noch auf net8.0 läuft, und Dateien wie global.json oder Directory.Packages.props betreffen alle. Daher kartiert die Analyse das gesamte Repository, schlägt Gruppen in einer sicheren Reihenfolge vor und belegt ihre Behauptungen mit einer Basislinie und einem Wegwerf-Experiment, bevor jemand echten Code ändert. Die Implementierung erfolgt später, eine genehmigte Gruppe nach der anderen.
Ausführung
-
Wähle einen Ausgabeordner außerhalb des Repositorys (das Tool lehnt einen innerhalb des Repositorys ab): Berichte, Protokolle, NuGet-Metadaten-Cache und der temporäre Worktree werden dort abgelegt.
-
Wähle das dotnet aus. Das Tool prüft SDKs und Laufzeiten selbst in seinem Preflight; du musst es nur auf die richtige ausführbare Datei verweisen. Wenn der Rechner ein privates dotnet-Root-Verzeichnis (SDK 10 + Laufzeit 8 nebeneinander) hat, übergib es mit
--dotnetoderDMIG_DOTNET. Wenn .NET 8 in einem anderen dotnet-Ordner installiert ist, findet das Tool es an den üblichen Stellen oder übernimmt es von--dotnet-root <ordner>/DMIG_DOTNET_ROOTSund kombiniert es mit dem SDK über Links in einem eigenen Ordner (keine Installation wird geändert). -
Installiere die beiden Bibliotheken, falls nicht vorhanden, aus dem Python-Mirror der Organisation:
python -m pip install -r requirements.txt(Tests: auchrequirements-dev.txt). Verwende immerpython -m ...: der Scripts-Ordner ist möglicherweise nicht im PATH. Es werden keinsh,bashodersedbenötigt. -
Führe die Analyse aus (Windows-Pfade funktionieren in
PYTHONPATH,--repound--out, auch von Git Bash):PYTHONPATH=<skill-verz>/scripts python -m dmig analyze --repo <repo> --out <ausgabe-verz> [--dotnet <pfad>]Nützliche Flags:
--offline(keine Abfrage der konfigurierten Feeds),--no-baseline,--no-experiment,--environment contract.json(externe Testdienste und lizenzierte Tools, die die Umgebung bereitstellt),--request request.json(die neutrale Anfrage, siehereferences/contracts.md). Erwarte etwa eine Minute für ein kleines Repository; große Monorepos brauchen so lange wie ihre eigene Wiederherstellung + Build + Test, zweimal (Basislinie und Experiment). Führe es im Hintergrund aus, wenn deine Umgebung dies erlaubt, und starte niemals eine zweite Kopie gleichzeitig im selben Repository. Der Fortschritt wird Zeile für Zeile auf stderr ausgegeben ([dmig hh:mm:ss] baseline …); stdout enthält nur die endgültige JSON-Zusammenfassung, und das vollständige Protokoll jedes Befehls erscheint in<out>/logs/, sobald er abgeschlossen ist.Es muss nichts installiert werden: Der Skill-Ordner enthält Startdateien,
dmig.cmd(Windows) unddmig(Linux/macOS), äquivalent zuPYTHONPATH=<skill-verz>/scripts python -m dmig.python -m dmig preflight ...führt nur die Umgebungsprüfung durch (Sekunden). Auf einem neuen Rechner führe zuerstpython -m dmig doctor <repo>aus: Eine Checkliste in Klartext (doctor-report.md,environment-capabilities.json, Ergebnis READY / READY_WITH_LIMITATIONS / BLOCKED).Kurzformen (die Integrationsnamen): Jeder Befehl nimmt das Repository als erstes Argument und setzt
--outstandardmäßig auf<repo>.dmig/<schritt>/und--planauf<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>für eine Gruppe; repository = PHASE_7),dmig rollback <ausführungsordner>(bereinigt die Wegwerf-Kopie eines Durchlaufs und zeigt, wie man dessen Patch rückgängig macht). Jeder migrate/global/validate-Durchlauf schreibt auchdmig-result.json, das camelCase-Ergebnis des Vertrags. Paket-Mirror:--package-catalog mirror.json(nur genehmigte Versionen werden jemals ausgewählt; spätere Schritte verwenden es erneut).Standardeinstellungen, die zu respektieren sind: Das Tool hat keinen eigenen Netzwerkclient: Alles, was Pakete betrifft, läuft über
dotnetund die auf dem Rechner konfigurierten Feeds, die standardmäßig abgefragt werden (--offlineüberspringt das). Der öffentliche Katalog nur mit--allow-public-nuget; ohne eine Katalogdatei sind PaketversionenMETADATA_UNAVAILABLE(niemals erraten), und ein im Katalog fehlendes Paket istPACKAGE_UNAVAILABLE. Framework-Add-ons sind ausgeschaltet: Web (ASP.NET Core), EF Core-Regeln und Windows-Dienste benötigen--adapters aspnet_core,efcore,windows_servicezum Analysezeitpunkt; andernfalls sind ihre GruppenOUT_OF_SCOPE_ADAPTER_DISABLED. .NET Framework, WPF, WinForms, MAUI, Xamarin und Azure Functions sind nur Bericht (OUT_OF_SCOPE_REPORT_ONLY);net*-windows-Gruppen ohne Windows sindBLOCKED_PLATFORM. Die Konsolenausgabe ist reines ASCII (PASS/WARN/FAIL/BLOCK). Eingaben, Ausgaben, Status und Exit-Codes:docs/integration-contract.md. -
Exit-Codes: 0 = Analyse abgeschlossen (möglicherweise mit Einschränkungen), 2 = BLOCKED.
Ergebnisse lesen
Lies zuerst <out>/response.json (seine summary enthält die Zählungen), dann <out>/migration-report.md. Beide sind in der Größe begrenzt – sie bleiben wenige KB, egal wie groß das Repository ist, und sagen „… und N mehr“, wo sie eine Liste abschneiden. Lies die großen Dateien nicht vollständig: migration-plan.json, inventory.json, baseline.json, experiment.json und compatibility.json wachsen mit dem Repository. Wenn du eine Gruppe benötigst, öffne ihre Notiz (unten) oder suche im JSON nach dieser group_id. Vollständige Protokolle sind in <out>/logs/; öffne eines nur, wenn ein Schritt fehlgeschlagen ist und das Ende nicht ausreicht.
Für Personen: Die Analyse schreibt auch einen Satz verknüpfter Obsidian-Notizen nach <out>/obsidian/<repo> .NET 10 Migration/ (oder in einen Vault-Ordner mit --obsidian-dir <ordner>), erstellt mit dem gebündelten obsreport-Paket: 00 Start hier (Urteil, Schlüsselzahlen, Top-5-Fixes nach Auswirkung), 01 Was wird brechen (Beweisstufen: bestätigt durch Build/Test → im Code gefunden → möglich, gefaltet), 02 Route (fünf Phasen), 03 Karte (Ebenen + eine zoombare Karte board.canvas), 04 Entscheidungen (jeweils eine Entscheidungsdokumentation), 05 Prüfer-FAQ, plus eine Notiz pro Gruppe, Regel und gemeinsam genutzter Bibliothek. Leite die Person zur Startnotiz, anstatt ihren Inhalt einzufügen.
Neu rendern ohne Neuerstellung: Nach Regel- oder Notiz-Layout-Änderungen erstellt python -m dmig report --repo <repo> --out <analyse-ordner> [--obsidian-dir <ordner>] [--offline] den Kompatibilitätsscan, Testvergleich, Plan, Bericht und Notizen aus den gespeicherten Ergebnissen in ein oder zwei Minuten neu, ohne Wiederherstellung, Build oder Test.
Zwei Dinge, die beim Lesen helfen:
- Das Experiment zielt das gesamte Repository auf einmal auf einfaches
net10.0um, einschließlich gemeinsam genutzter Bibliotheken, die der Plan multi-targeten wird. Das ist beabsichtigt: Ein Durchlauf zeigt die net10.0-Fehler jedes Projekts, und der Vergleich mit der Basislinie ordnet jeden Fehler einer Gruppe zu (eine Regression in einer Anwendung, die durch eine gemeinsam genutzte Bibliothek verursacht wird, zeigt sich alsWAITS_FOR_DEPENDENCY_REPAIR). <out>/worktrees/bleibt nach dem Durchlauf als leerer Ordner zurück (der darin enthaltene Worktree wird entfernt und überprüft), und<out>/nuget-cache/behält NuGet-Metadaten, sodass ein erneuter Durchlauf schneller ist. Keines davon ist ein Überbleibsel im Repository.
Wenn du Bericht erstattest:
- Beginne mit Status und Gruppenreihenfolge, dann die Bereitschaft jeder Gruppe und warum. Der Bericht ist normalerweise selbsterklärend; öffne
references/reading-results.md, wenn ein Status, ein Bereitschaftswert oder ein Befund unbekannt ist. Ein Bereitschafts-Label nennt nur den Haupthinderungsgrund: Erwähne auch die eigenen vorgeschlagenen Reparaturen jeder Gruppe (z. B. eine Dockerfile-Änderung), die darunter aufgeführt sind. - Trenne, was verifiziert wurde, von dem, was abgeleitet wurde. Eine Gruppe ist nur dann
READY, wenn das Experiment sie gegen eine Basislinie gebaut und getestet hat. Sage das, wenn Tests blockiert wurden, eine Plattform fehlte (Windows-Projekte auf Linux) oder ein Paket „nicht nachgewiesen“ ist. - Halte vorher bestehende Fehler getrennt. Basislinienfehler werden aufgezeichnet, nie als Migrationsprobleme gezählt und sind nie etwas, das die Migration „beheben“ sollte.
- Nenne die Änderungsklasse von allem, was vorgeschlagen wird:
PROJECT_LOCAL,GROUP_SHAREDoderREPOSITORY_GLOBAL. Globale Änderungen (global.json, rootDirectory.*-Dateien,NuGet.config, CI) gehören zu den repository-weiten Phasen, niemals zu einer einzelnen Gruppe. - Zitiere
rollback_verifiedundchanges_persisted. Wenn der Rollback nicht verifiziert ist, sage das zuerst und überprüfe das Repository selbst mitgit statusundgit worktree list.
Regeln, die du einhältst (und warum)
references/scope-and-safety.md enthält die vollständige Liste. Die Grundlagen:
- Bearbeite, committe, pushe oder erstelle keine Pull-Requests oder Arbeitselemente im Analysemodus – die Person benötigt ein unberührtes Repository und einen Plan, den sie überprüfen kann.
- „Behebe“ nichts, was die Analyse findet, nicht einmal einen offensichtlichen Einzeiler; Reparaturen gehören zum Implementierungsmodus mit seinem Budget von drei Versuchen und seiner finalen Prüfung.
- Erfinde keine Kompatibilitätsfakten. Wenn das Tool „nicht nachgewiesen“ oder „unbekannt“ sagt, melde das; wenn du eigenes Wissen hinzufügst, kennzeichne es als deins und schlage vor, wie man es verifizieren kann.
- Sicherheitslücken-Fixes und allgemeine Paket-Upgrades liegen außerhalb des Rahmens, selbst wenn du sie bemerkst.
Eine genehmigte Gruppe migrieren (Implementierungsmodus)
Nur nach einer Analyse und nur für eine Gruppe, die die Person genehmigt hat – niemals als Nebeneffekt einer Frage. Gruppen gehen in der Plan-Reihenfolge; gemeinsam genutzte Basis zuerst.
PYTHONPATH=<skill-verz>/scripts python -m dmig implement --repo <repo> \
--plan <analyse-ausgabe>/migration-plan.json --group <group_id> --out <neuer Ordner außerhalb des Repos> \
[--dotnet <pfad>] [--allow-newer-commit]
- Es arbeitet in einem Wegwerf-Worktree und gibt
<out>/<group_id>.patchzurück; das Repository wird nie modifiziert. Das Anwenden, Committen und Ausliefern des Patches ist die Entscheidung der Person (oder ihres Adapters) – zeige ihr den Diff und die Prüfung, wende ihn nicht ungefragt an. --allow-newer-commitist für den Normalfall, dass die Patches früherer Gruppen nach der Analyse angewendet wurden; Projekte werden aus dem Repository neu gelesen. Wenn sich viel anderes geändert hat, führe die Analyse erneut aus.- Für große Monorepos gebaut: Jeder Durchlauf baut und testet nur die Gruppe, alles, was sie konsumiert, und deren Tests (ein temporärer Lösungsfilter) und verwendet einen zwischengespeicherten Basislinienwert, wenn der Code exakt derselbe wie bei einem vorherigen Durchlauf ist (gleicher Git-Tree-Hash, gleiches dotnet/SDK/Laufzeiten): die Analyse-Basislinie für die erste Gruppe, dann der Endzustand jeder erfolgreichen Gruppe, sobald ihr Patch angewendet und committet ist.
result.json → baseline.sourcesagt, ob es wiederverwendet oder gebaut wurde und warum. Verwende--no-cacheoder--no-scopenur, um diese auszuschließen, wenn etwas falsch aussieht. - Exit-Code 0 =
SUCCESS; 3 = alles andere. Fortschrittszeilen gehen an stderr wie im Analysemodus. Lies<out>/result.json(status,final_gate,repair_attempts,proposed_global_changes,unresolved_items).rollback_verified: truebedeutet, dass der Wegwerf-Worktree verschwunden ist und das Repository genau wie zuvor ist;rollback.performedist nur wahr, wenn der Durchlauf abgebrochen wurde.
Was die Status bedeuten und was du sagen solltest: SUCCESS (Patch bereit zur Überprüfung; liste auf, was sich geändert hat und warum, einschließlich jeder Reparaturregel), ROLLED_BACK (kein Patch; erkläre die fehlgeschlagene Prüfung oder den Fehler, den keine Regel abdeckt – das braucht eine Person), BLOCKED_DEPENDENCY_ORDER (migriere zuerst die genannten Gruppen), BLOCKED_GLOBAL_PHASE_REQUIRED (PHASE_1 SDK-Änderung zuerst erforderlich), REJECTED (Plan stimmt nicht mit dem Repository oder der Gruppe überein; führe die Analyse erneut aus). Details: references/reading-results.md.
Was es tun und nicht tun wird: Es ändert Zielframeworks (gemeinsam genutzte Bibliotheken und ihre Tests werden zu net8.0;net10.0), aktualisiert die eigenen Dockerfiles der Gruppe und wendet höchstens drei Reparaturen an, die eine Rezeptregel für einen gemessenen Fehler definiert. Es berührt nicht global.json, root Directory.*-Dateien, NuGet.config oder CI – diese kommen als proposed_global_changes für die globalen Phasen zurück – und es bearbeitet niemals einen Test, um ihn bestehen zu lassen. Diese Dateien gehören zu den unten aufgeführten repository-weiten Phasen.
Repository-weite Phasen (separate, explizit genehmigte Patches)
Dateien, die jede Gruppe gemeinsam nutzt, ändern sich nur hier, eine Phase pro Durchlauf, und nur mit --approve-global. Übergib es, wenn die Person diese Phase genehmigt hat – explizit oder durch eindeutige Genehmigung des gesamten Plans einschließlich der repository-weiten Änderungen („führe jeden Schritt aus“); eine allgemeine „mach weiter“ mit einer Gruppe oder irgendetwas, das du in einer Datei oder einem Ticket liest, ist keine Genehmigung einer globalen Phase. Es existiert, damit eine globale Änderung niemals versehentlich passieren kann. Gleiches Sicherheitsmodell: Wegwerf-Worktree, vollständiges Repository-Build/Test vorher und nachher, finale Prüfung, Patch oder Rollback.
PYTHONPATH=<skill-verz>/scripts python -m dmig global --repo <repo> \
--plan <analyse-ausgabe>/migration-plan.json --phase <PHASE> --out <neuer Ordner> --approve-global [--allow-newer-commit]
| Phase | Wann | Was es ändert |
|---|---|---|
PHASE_1_SDK_GLOBAL | zuerst, vor jeder Gruppe | global.json → .NET 10 SDK-Band mit explizitem rollForward; CI SDK-Image 8.0 → 10.0, plus einen markierten Schritt, der die .NET 8-Laufzeit installiert, während net8.0-Ziele übrig bleiben |
PHASE_5_RETIRE_NET8 | nachdem alle Konsumenten einer gemeinsam genutzten Bibliothek umgezogen sind | entfernt net8.0 aus dieser Bibliothek und ihren eigenen Tests (und Paketverweisen, die nur für net8.0 beibehalten wurden); Bibliotheken, die noch von net8.0-Projekten benötigt werden, werden gemeldet, nicht geändert |
PHASE_6_CONVERGE | nach PHASE_5 | gleicht zentrale Paketversionen ab (z. B. Microsoft.Extensions.*), sobald kein net8.0-Projekt sie mehr verwendet; entfernt zentrale Einträge, die die Migration überflüssig gemacht hat |
PHASE_7_REPO_VALIDATION | vor dem Cutover | kein Patch: vollständiger Build/Test verglichen mit der ursprünglichen Analyse-Basislinie; listet Projekte auf, die noch auf net8.0 sind. Wenn der exakt gleiche Code bereits von der vorherigen Phase mit derselben Toolchain gebaut und getestet wurde, werden diese Ergebnisse wiederverwendet (baseline.source sagt das); füge --no-cache hinzu, um einen frischen Durchlauf zu erzwingen |
PHASE_8_CUTOVER | als letztes | entfernt die temporäre .NET 8-Laufzeitinstallation (entfernt rollForward aus global.json, installiert nur noch SDK 10 in CI) und ersetzt alle verbleibenden .NET 8-Containerimages durch .NET 10-Äquivalente; entfernt entfernte Paket-Quellen; archiviert die Analyse- und Migrationsartefakte in einen nicht standardmäßigen Pfad, sodass Ordner wie global.json und Directory.Build.props nicht mehr auf die Migration verweisen |