diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index cf82bacdda..3870b27a2a 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -58,6 +58,11 @@ "name": "dotnet-aspnet", "source": "./plugins/dotnet-aspnet", "description": "ASP.NET Core web development skills including middleware, endpoints, real-time communication, and API patterns." + }, + { + "name": "dotnet11", + "source": "./plugins/dotnet11", + "description": "Skills for new .NET 11 APIs and language features." } ] } \ No newline at end of file diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 06d97faa0d..cff9b1c809 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -61,6 +61,11 @@ "name": "dotnet-aspnet", "source": "./plugins/dotnet-aspnet", "description": "ASP.NET Core web development skills including middleware, endpoints, real-time communication, and API patterns." + }, + { + "name": "dotnet11", + "source": "./plugins/dotnet11", + "description": "Skills for new .NET 11 APIs and language features." } ] } diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e86fcef67f..173d120730 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -147,3 +147,10 @@ /plugins/dotnet-nuget/ @dotnet/area-infrastructure-libraries @kartheekp-ms /tests/dotnet-nuget/ @dotnet/area-infrastructure-libraries @kartheekp-ms +# dotnet11 (.NET 11 new APIs and language features) +/plugins/dotnet11/ @ManishJayaswal @JanKrivanek @ViktorHofer +/tests/dotnet11/ @ManishJayaswal @JanKrivanek @ViktorHofer + +/plugins/dotnet11/skills/system-text-json-net11/ @ManishJayaswal @JanKrivanek @ViktorHofer +/tests/dotnet11/system-text-json-net11/ @ManishJayaswal @JanKrivanek @ViktorHofer + diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index cf82bacdda..3870b27a2a 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -58,6 +58,11 @@ "name": "dotnet-aspnet", "source": "./plugins/dotnet-aspnet", "description": "ASP.NET Core web development skills including middleware, endpoints, real-time communication, and API patterns." + }, + { + "name": "dotnet11", + "source": "./plugins/dotnet11", + "description": "Skills for new .NET 11 APIs and language features." } ] } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4c3a505702..f5a5ce1c44 100644 --- a/.gitignore +++ b/.gitignore @@ -426,3 +426,6 @@ FodyWeavers.xsd .DS_Store .nuget/ validation_report.md + +# Roslyn / C# language server cache files +*.lscache diff --git a/README.md b/README.md index d16171309d..806832ece8 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ This repository contains the .NET team's curated set of core skills and custom a | [dotnet-template-engine](plugins/dotnet-template-engine/) | .NET Template Engine skills: template discovery, project scaffolding, and template authoring. | | [dotnet-test](plugins/dotnet-test/) | Skills for running, diagnosing, and migrating .NET tests: test execution, filtering, platform detection, and MSTest workflows. | | [dotnet-aspnet](plugins/dotnet-aspnet/) | ASP.NET Core web development skills including middleware, endpoints, real-time communication, and API patterns. | +| [dotnet11](plugins/dotnet11/) | Skills for new .NET 11 APIs and language features. | ## Installation diff --git a/plugins/dotnet11/README.md b/plugins/dotnet11/README.md new file mode 100644 index 0000000000..7a85a71559 --- /dev/null +++ b/plugins/dotnet11/README.md @@ -0,0 +1,7 @@ +# dotnet11 + +Skills focused on new APIs and language features introduced in .NET 11. + +## Skills + +- system-text-json-net11 diff --git a/plugins/dotnet11/plugin.json b/plugins/dotnet11/plugin.json new file mode 100644 index 0000000000..042c95447a --- /dev/null +++ b/plugins/dotnet11/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "dotnet11", + "version": "0.1.0", + "description": "Skills for .NET 11 APIs and language features.", + "skills": ["./skills/"] +} diff --git a/plugins/dotnet11/skills/system-text-json-net11/SKILL.md b/plugins/dotnet11/skills/system-text-json-net11/SKILL.md new file mode 100644 index 0000000000..f9e249f15e --- /dev/null +++ b/plugins/dotnet11/skills/system-text-json-net11/SKILL.md @@ -0,0 +1,131 @@ +--- +name: system-text-json-net11 +description: > + Provides guidance on new System.Text.Json APIs introduced in .NET 11. + It covers typed JsonTypeInfo access via GetTypeInfo and TryGetTypeInfo on + JsonSerializerOptions, and the new JsonNamingPolicy.PascalCase static property. + Use when serializing or deserializing JSON in .NET 11 applications and needing + typed metadata access or PascalCase property naming. +license: MIT +--- + +# System.Text.Json — .NET 11 + +New APIs added to `System.Text.Json` across .NET 11 releases. + +## When to Use + +- Serializing or deserializing JSON in a .NET 11 (or later) project +- Needing strongly-typed `JsonTypeInfo` access instead of the untyped `JsonTypeInfo` overload +- Wanting to safely check whether type metadata is available without catching exceptions (`TryGetTypeInfo`) +- Requiring PascalCase property naming during JSON serialization + +## When Not to Use + +- The project targets .NET 10 or earlier — these APIs are not available before .NET 11 +- Using a JSON library that is not `System.Text.Json` (e.g., Newtonsoft.Json) +- The existing untyped `GetTypeInfo(Type)` / `TryGetTypeInfo(Type, ...)` overloads are sufficient + +## Target Framework + +```xml +net11.0 +``` + +## New APIs + +### Typed `JsonTypeInfo` Access + +#### `JsonSerializerOptions.GetTypeInfo()` + +Returns a strongly-typed `JsonTypeInfo` for the specified type, using the +options' configured type-info resolver. + +```csharp +JsonTypeInfo GetTypeInfo() +``` + +#### `JsonSerializerOptions.TryGetTypeInfo(out JsonTypeInfo?)` + +Attempts to retrieve typed metadata without throwing if the type is not resolved. + +```csharp +bool TryGetTypeInfo(out JsonTypeInfo? typeInfo) +``` + +### `JsonNamingPolicy.PascalCase` + +A new static property that converts property names to PascalCase during +serialization. + +```csharp +static JsonNamingPolicy PascalCase { get; } +``` + +## Examples + +### Get Typed JsonTypeInfo + +```csharp +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; + +var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); + +// Retrieve strongly-typed metadata for MyClass +JsonTypeInfo typeInfo = options.GetTypeInfo(); +Console.WriteLine($"Type: {typeInfo.Type.Name}"); +``` + +### TryGetTypeInfo for Safe Access + +```csharp +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; + +var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); + +if (options.TryGetTypeInfo(out var info)) +{ + Console.WriteLine($"Resolved type info for {info!.Type.Name}"); +} +else +{ + Console.WriteLine("Type info not available"); +} +``` + +### PascalCase Naming Policy + +```csharp +using System.Text.Json; + +var opts = new JsonSerializerOptions +{ + PropertyNamingPolicy = JsonNamingPolicy.PascalCase +}; + +var obj = new { firstName = "John", lastName = "Doe" }; +string json = JsonSerializer.Serialize(obj, opts); +Console.WriteLine(json); +// Output: {"FirstName":"John","LastName":"Doe"} +``` + +### Combined: Serialize with Typed Metadata + +```csharp +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; + +var options = new JsonSerializerOptions +{ + PropertyNamingPolicy = JsonNamingPolicy.PascalCase +}; + +JsonTypeInfo typeInfo = options.GetTypeInfo(); +string json = JsonSerializer.Serialize(new Person("Jane", 30), typeInfo); +Console.WriteLine(json); +// Output: {"Name":"Jane","Age":30} + +public record Person(string Name, int Age); +``` diff --git a/tests/dotnet11/system-text-json-net11/eval.yaml b/tests/dotnet11/system-text-json-net11/eval.yaml new file mode 100644 index 0000000000..f2d75ba482 --- /dev/null +++ b/tests/dotnet11/system-text-json-net11/eval.yaml @@ -0,0 +1,112 @@ +scenarios: + # --- Scenario 1: Serialize JSON in .NET 11 with PascalCase property names --- + # The prompt deliberately does NOT name any specific API. The skill description + # mentions "serializing JSON in .NET 11" and "PascalCase property naming" — those + # are the trigger words the agent should pick up on to load this skill. + - name: "Serialize JSON in .NET 11 with PascalCase property names" + prompt: | + I'm starting a new console app on .NET 11 and I need to serialize this record to JSON: + + ```csharp + public record Person(string name, int age); + ``` + + In the output JSON the property names should be PascalCase (so `Name` and `Age`, + not `name`/`age` or `firstName` style). I want to use whatever the framework + provides out of the box rather than writing my own naming-policy class. + + Please show me the full program targeting `net11.0` and run it so I can see the + JSON output. + assertions: + - type: "exit_success" + - type: "output_matches" + pattern: "JsonNamingPolicy\\.PascalCase" + - type: "output_matches" + pattern: "net11\\.0" + - type: "output_not_matches" + pattern: "class\\s+\\w+\\s*:\\s*JsonNamingPolicy" + - type: "output_matches" + pattern: "\"Name\"" + - type: "output_matches" + pattern: "\"Age\"" + rubric: + - "Uses the new built-in JsonNamingPolicy.PascalCase static property (added in .NET 11) and does not implement a custom JsonNamingPolicy subclass" + - "Targets net11.0 in the project / file-based app" + - "Actually runs the program and shows JSON output with PascalCase property names (e.g. \"Name\", \"Age\")" + timeout: 180 + + # --- Scenario 2: Typed metadata access on JsonSerializerOptions in .NET 11 --- + # Trigger words from the skill description: "typed metadata access", + # "JsonSerializerOptions", ".NET 11". The prompt asks for the desired *behavior* + # (type-safe metadata, no exception when missing) rather than naming the API. + - name: "Type-safe JsonTypeInfo access without exceptions in .NET 11" + prompt: | + In a .NET 11 library I'm working on, I have a `JsonSerializerOptions` instance + and I want to get the JSON metadata for a specific type `T` in a strongly-typed + way (i.e. I want back a `JsonTypeInfo`, not a non-generic `JsonTypeInfo` that + I have to cast). + + I also need a way to *probe* whether metadata for `T` is available without + having an exception thrown at me if it isn't — so I can branch on "have it" + vs "don't have it". I'd rather not wrap things in try/catch. + + Show me a minimal `net11.0` program that demonstrates both: getting the typed + metadata when it's available, and checking-without-throwing for a case where + it might not be. Run the program. + assertions: + - type: "exit_success" + - type: "output_contains" + value: "GetTypeInfo<" + - type: "output_contains" + value: "TryGetTypeInfo<" + - type: "output_matches" + pattern: "out\\s+(var|JsonTypeInfo)" + - type: "output_matches" + pattern: "net11\\.0" + - type: "output_not_matches" + pattern: "\\bcatch\\b\\s*(\\(|\\{)" + - type: "output_matches" + pattern: "(True|False|found|Found|JsonTypeInfo)" + rubric: + - "Uses the new generic JsonSerializerOptions.GetTypeInfo() overload (added in .NET 11) for the typed-access part" + - "Uses the new generic JsonSerializerOptions.TryGetTypeInfo(out JsonTypeInfo? info) overload (added in .NET 11) for the probing part" + - "Does NOT wrap GetTypeInfo in try/catch as a workaround" + - "Targets net11.0 and actually runs the program" + timeout: 180 + + # --- Scenario 3: Negative — skill should NOT activate --- + # This is a JSON serialization task on .NET 8, with camelCase naming. None of the + # APIs covered by this skill (PascalCase policy, generic GetTypeInfo/ + # TryGetTypeInfo) are relevant. The agent should solve the task without + # loading the system-text-json-net11 skill. + - name: "Non-activation: camelCase JSON serialization on .NET 8" + prompt: | + I have a .NET 8 console app and I need to serialize this record to JSON with + camelCase property names: + + ```csharp + public record Person(string Name, int Age); + ``` + + Show me a minimal program targeting `net8.0` that produces output like + `{"name":"Jane","age":30}` and run it. + expect_activation: false + assertions: + - type: "exit_success" + - type: "output_matches" + pattern: "net8\\.0" + - type: "output_matches" + pattern: "JsonNamingPolicy\\.CamelCase" + - type: "output_not_matches" + pattern: "JsonNamingPolicy\\.PascalCase" + - type: "output_not_matches" + pattern: "net11\\.0" + - type: "output_matches" + pattern: "\"name\"" + - type: "output_matches" + pattern: "\"age\"" + rubric: + - "Solves the task using only pre-.NET 11 APIs (JsonNamingPolicy.CamelCase, standard JsonSerializer.Serialize)" + - "Does NOT load or reference the system-text-json-net11 skill — none of its APIs are needed here" + - "Targets net8.0 and produces camelCase JSON output" + timeout: 180