Add migrate-dotnet8-to-dotnet9 skill#182
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new migrate-dotnet8-to-dotnet9 skill to the plugins/dotnet plugin, enabling AI agents to systematically guide .NET 8 projects through migration to .NET 9. It is modeled after the existing migrate-dotnet9-to-dotnet10 skill structure, providing a 6-step migration workflow backed by 10 technology-area reference documents and 12 eval scenarios.
Changes:
- Adds the
SKILL.mdworkflow with frontmatter, 6-step migration process, and reference loading table for the new skill - Adds 10 reference documents (
csharp-compiler.md,core-libraries.md,sdk-msbuild.md,aspnet-core.md,efcore.md,cryptography.md,serialization-networking.md,winforms-wpf.md,containers-interop.md,deployment-runtime.md) covering all .NET 9 breaking change categories - Adds
eval.yamlwith 12 eval scenarios and a CODEOWNERS entry assigning ownership to@danmoseley
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/SKILL.md |
Core skill workflow with 6 migration steps and reference loading table |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/aspnet-core.md |
ASP.NET Core 9 breaking changes reference |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/containers-interop.md |
Container and CET interop breaking changes reference |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/core-libraries.md |
Core libraries breaking changes including params span overloads and SYSLIB codes |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/cryptography.md |
Cryptography breaking changes (SYSLIB0057 / X509CertificateLoader migration) |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/csharp-compiler.md |
C# 13 compiler breaking changes reference |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/deployment-runtime.md |
Deployment and runtime configuration breaking changes |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/efcore.md |
EF Core 9 breaking changes including Cosmos DB discriminator rename |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/sdk-msbuild.md |
SDK and MSBuild behavioral changes including Terminal Logger |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/serialization-networking.md |
BinaryFormatter removal, JSON and HttpClientFactory changes |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/winforms-wpf.md |
WinForms WFO1000 analyzers, PictureBox, StatusStrip, and WPF changes |
tests/dotnet/migrate-dotnet8-to-dotnet9/eval.yaml |
12 evaluation scenarios covering all major breaking change categories |
.github/CODEOWNERS |
Adds ownership entries for the new skill and test directory |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...s/dotnet/skills/migrate-dotnet8-to-dotnet9/references/serialization-networking-dotnet8to9.md
Show resolved
Hide resolved
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/cryptography.md
Outdated
Show resolved
Hide resolved
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/aspnet-core.md
Outdated
Show resolved
Hide resolved
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/winforms-wpf.md
Outdated
Show resolved
Hide resolved
|
/eval |
|
/evaluate |
Mirrors the structure and approach of the existing migrate-dotnet9-to-dotnet10 skill. Covers all .NET 8→9 breaking changes organized by technology area: - C# 13 compiler (InlineArray records, iterator safe context, collection expressions) - Core libraries (params span overloads, BinaryFormatter removal, BigInteger, TimeSpan) - SDK/MSBuild (Terminal Logger, version requirements, .NET 7/Standard warnings) - ASP.NET Core (HostBuilder validation, forwarded headers, middleware constructors) - EF Core (pending migrations, explicit transactions, Cosmos DB changes) - Cryptography (X509Certificate2 SYSLIB0057, SafeEvpPKeyHandle) - Serialization/Networking (BinaryFormatter, JsonDocument null, HttpClientFactory) - WinForms/WPF (security analyzers, StatusStrip, PictureBox, XmlNamespaceMaps) - Containers/Interop (zlib removal, CET support) - Deployment/Runtime (env var precedence, FP-to-int saturation, MonoVM deprecated) 12 eval scenarios covering all technology areas with assertions and rubrics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
BinaryFormatter migration is a major architectural decision affecting data format, backward compatibility, and stored data migration. The skill should present options and let the user decide rather than picking a serializer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep SKILL.md as concise index; full guidance lives in serialization-networking.md reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tter duplicate - Remove BinaryFormatter duplicate from Step 4 (already covered in Step 3) - Delegate inline fix details for EF Core, FP saturation, HttpClientFactory to references - Collapse niche SYSLIB0055/0056 into one-liner pointing to reference - Shorten params span and String.Trim entries Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tivation
- Add setup files (csproj, .cs, Dockerfile, etc.) to 10/12 scenarios so agent
works with real code instead of pure knowledge questions
- Make prompts task-oriented ('Migrate this app to .NET 9') instead of
knowledge-oriented ('What breaks?')
- Set expect_activation: false on all scenarios — this is a pure knowledge/
reference skill with no MCP tools, so activation via SkillInvokedEvent is
unreliable
- Increase timeouts to 420s to avoid penalizing skilled runs that do more work
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace easy scenarios (BinaryFormatter/X509) where Opus always ties with harder ones targeting areas where the skill adds measurable value: - Empty env var behavior on Unix (null vs empty string) - ZipArchiveEntry UTF-8 bit flag mechanism - FromKeyedServices no-fallback behavior - Cosmos DB id format change (discriminator no longer embedded) - Env var precedence reversal with concrete GC/ThreadPool impact Keep scenarios where skill consistently helps: Cosmos DB id format, container zlib removal, CI pipeline net7.0 warnings, WinForms PictureBox. Increase timeouts to 420s to avoid penalizing skilled runs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tell the agent about the migrate-dotnet9-to-dotnet10 skill so it knows to continue the chain after completing the 8-to-9 migration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The eval scenarios claim to test a .NET 8 to .NET 9 migration but the starting csproj files already reference EF Core 9.0.0 packages. This reduces test signal since the package upgrade step is already done. Change all EF Core package versions to 8.0.0 in scenarios 4, 5, and 10. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The rubric expects the model to warn about the InlineArray 1 MiB runtime size limit, but the example was only 8 KiB (InlineArray(1024) with byte element). Increase to 1,048,577 bytes so the breaking change is concretely applicable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The eval used a non-existent overload of ConfigurePrimaryHttpMessageHandler
with a (handler, _) => {} lambda that doesn't return a handler. Replace
with ConfigureHttpMessageHandlerBuilder which correctly casts
PrimaryHandler to HttpClientHandler -- the pattern that actually breaks
when the default switches to SocketsHttpHandler in .NET 9.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The breaking change example used a non-existent overload of ConfigurePrimaryHttpMessageHandler. Replace with ConfigureHttpMessageHandlerBuilder which is the actual API that casts PrimaryHandler and would break when the default changes to SocketsHttpHandler. Also fix Option 2 to use the same correct API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clearing KnownProxies and KnownNetworks accepts forwarded headers from any source, enabling attackers to spoof X-Forwarded-For/Proto/Host headers. Replace with a warning against this pattern and steer toward registering only trusted proxy addresses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Disabling header redaction globally with RedactLoggedHeaders(_ => false) logs Authorization tokens, cookies, and other credentials in cleartext. Replace with guidance to whitelist only specific non-sensitive headers and add an explicit warning against disabling redaction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the unsupported NuGet package option with a clear security warning that BinaryFormatter deserialization enables remote code execution and should not be re-enabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WFO1000 guards against insecure deserialization of WinForms control properties. Replace the suppression option with a warning explaining the security risk and recommend the attribute-based fix instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Warn that disabling CET removes hardware-enforced control-flow integrity (protection against ROP/JOP exploits) and should only be done when a specific native library is confirmed incompatible. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add context that suppressing PendingModelChangesWarning risks silent schema drift and that MigrationsUserTransactionWarning suppression has transaction safety implications. Both are temporary workarounds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mark behavioral changes that can cause runtime exceptions with a warning indicator and move them to the top of the list so agents address them first. Add rollForward policy guidance to the global.json update step to prevent SDK resolution issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e blocks The combined snippet used obj before declaration, which was misleading. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously listed only SYSLIB0054 and SYSLIB0057, omitting 0055 and 0056. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Setup code uses synchronous Migrate(), not MigrateAsync(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Duplicate 'var cert' declarations would cause compilation errors if pasted as-is. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The claim is confusing in an 8-to-9 migration guide context. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previous wording was logically inconsistent about the direction of the type change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
13bdf96 to
bb6208e
Compare
|
/evaluate |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/core-libraries.md
Outdated
Show resolved
Hide resolved
Skill Validation Results
Model: claude-opus-4.6 | Judge: claude-opus-4.6 |
plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/efcore.md
Outdated
Show resolved
Hide resolved
AndriySvyryd
left a comment
There was a problem hiding this comment.
Reviewed EF Core content
|
thanks @AndriySvyryd |
…core.md Co-authored-by: Andriy Svyryd <AndriySvyryd@users.noreply.github.com>
The code example incorrectly used ReadOnlySpan<char> as a static field, which is impossible (ref struct). The eval scenario used a local ReadOnlySpan<char> variable which actually compiles fine on .NET 9 GA, so it didn't demonstrate the breaking change. Updated both to correctly show the RC2-to-GA overload removal issue. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…llisions Other version migration skills (e.g., 9-to-10) have similarly named reference files. Adding the suffix disambiguates them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/evaluate |
| @@ -0,0 +1,240 @@ | |||
| --- | |||
| name: migrate-dotnet8-to-dotnet9 | |||
| description: > | |||
There was a problem hiding this comment.
A skills description is loaded into the context every single time, for any user of the plugin. It is the trigger which decides if rest of the skills .md should be loaded or not.
I would suggest to:
- Have the description as vanilla "Migrate from net8 to net9"
- Have the remarks and all the "DO NOT USE FOR" in the skills body. That means the context cost will be only paid if someone is doing a migration.
- Choose between providing a link to published document about breaking changes vs. restating what the document says. If we do both, a web search enabled agent will read the web page as well as the .md here
There was a problem hiding this comment.
Thanks @T-Gro . I did experiment with variations, including what you said (short description and do not use in the body). I ended up with it in the description because in evaluation the skill was not getting loaded in obviously relevant scenarios.
For your 2, that's a good point, but also the skill would be loaded in unecessary situations when the user IS doing a migration. That may be the right trade off of course.
For your 3, also a good point. I think we're learning here. Most skills have chosen to not refer to docs for "core functionality" but maybe they should?
I'm inclined to leave things as is, as we're learning here and it's easy to change later. We presumably don't have many users yet, and hopefully they'll give us feedback in this repo and we can adjust. By the way these things are distributed, we ship almost continuously
BTW perhaps grouping into a migration agent might help the LLM find and load the right skill, without so much tuning of description?
Recreated from #154 (original PR was orphaned when the fork relationship with dotnet/skills was re-established).
Add .NET 8 → .NET 9 Migration Skill
Adds a new skill to guide agents through migrating .NET 8 projects to .NET 9, systematically resolving all breaking changes. Modeled after the migrate-dotnet9-to-dotnet10 skill structure.
Structure
csharp-compiler.md— C# 13 compiler changes (InlineArray on records, iterator safe context, collection expressions)core-libraries.md— params span overloads, SYSLIB0054–0057, BigInteger limits, String.Trim removalsdk-msbuild.md— Terminal Logger, VS version requirements, out-of-support TFM warningsaspnet-core.md— ValidateOnBuild/ValidateScopes, ForwardedHeaders, middleware changesefcore.md— Pending migrations exception, explicit transactions, Cosmos DB discriminator/ rename, sync I/Ocryptography.md— X509CertificateLoader migration (SYSLIB0057)serialization-networking.md— BinaryFormatter removal, JsonDocument null, HttpClientFactory SocketsHttpHandlerwinforms-wpf.md— WFO1000 security analyzers, PictureBox HttpRequestException, StatusStripcontainers-interop.md— zlib removal from images, CET support, Monitor tag changesdeployment-runtime.md— Env var precedence reversal, floating-point saturation, empty env varsKey design decisions
expect_activation: false: This is a pure knowledge/reference skill with no MCP tools. Activation viaSkillInvokedEventis unreliable for this skill type — the skill content influences agent output throughSkillDirectoriesinjection but doesn't always trigger explicit invocation events.Eval Results (claude-opus-4.6, 3 runs, judged by claude-opus-4.6)
Observations: