From bff02b04284bff29a0899f73dff76eaef10bc8ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 04:53:16 +0000 Subject: [PATCH] chore: refresh upstream skill catalog --- .../skills/csharp-refactoring/SKILL.md | 150 ++++++++++++++++++ .../skills/csharp-refactoring/manifest.json | 5 + .../references/operation-catalog.md | 37 +++++ .../agents/code-testing-generator/AGENT.md | 2 +- .../agents/testability-migration/AGENT.md | 2 + .../agents/msbuild/AGENT.md | 3 + .../dotnet-diag/.codex-plugin/plugin.json | 3 +- .../dotnet-skills/dotnet-diag/README.md | 7 + .../dotnet-msbuild/.codex-plugin/plugin.json | 8 +- .../dotnet-skills/dotnet-msbuild/README.md | 8 + .../dotnet-msbuild/agents/msbuild.agent.md | 3 + .../.codex-plugin/plugin.json | 3 +- .../dotnet-template-engine/README.md | 7 + .../.codex-plugin/plugin.json | 7 +- .../dotnet-test-migration/README.md | 5 +- .../dotnet-test/.codex-plugin/plugin.json | 14 +- .../dotnet-skills/dotnet-test/README.md | 5 +- .../agents/code-testing-generator.agent.md | 2 +- .../agents/testability-migration.agent.md | 2 + .../dotnet/.codex-plugin/plugin.json | 5 +- .../upstreams/dotnet-skills/dotnet/README.md | 3 + .../dotnet/skills/csharp-refactoring/SKILL.md | 150 ++++++++++++++++++ .../references/operation-catalog.md | 37 +++++ external-sources/vendir.lock.yml | 12 +- 24 files changed, 438 insertions(+), 42 deletions(-) create mode 100644 catalog/Platform/Official-DotNet/skills/csharp-refactoring/SKILL.md create mode 100644 catalog/Platform/Official-DotNet/skills/csharp-refactoring/manifest.json create mode 100644 catalog/Platform/Official-DotNet/skills/csharp-refactoring/references/operation-catalog.md create mode 100644 external-sources/upstreams/dotnet-skills/dotnet-diag/README.md create mode 100644 external-sources/upstreams/dotnet-skills/dotnet-msbuild/README.md create mode 100644 external-sources/upstreams/dotnet-skills/dotnet-template-engine/README.md create mode 100644 external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/SKILL.md create mode 100644 external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/references/operation-catalog.md diff --git a/catalog/Platform/Official-DotNet/skills/csharp-refactoring/SKILL.md b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/SKILL.md new file mode 100644 index 00000000..2be35110 --- /dev/null +++ b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/SKILL.md @@ -0,0 +1,150 @@ +--- +name: csharp-refactoring +description: "Performs safe, behavior-preserving refactoring of C#/.NET code, verified with build, tests, and analyzers. USE FOR: rename or move a symbol/type/file; extract a method/type/interface; inline a wrapper/method/local; merge or consolidate near-identical classes or duplicate helpers; split or modernize C# code; generated/partial declarations; public, serialized, friend-assembly, or multi-targeted contracts; and mixed requests where a feature, bug fix, package/framework upgrade, public nullability change, or other behavior/contract change is presented as a refactor and must be separated or declined. DO NOT USE FOR: ordinary feature or bug-fix requests not framed as refactoring; upgrades after reclassification (use dotnet-upgrade); new tests; or formatting-only passes (use dotnet format)." +license: MIT +--- + +# C# Refactoring (behavior-preserving) + +A refactor changes **structure**, never observable **behavior**. Do the edit with binding-aware tools, +then confirm behavior held with a build + the relevant tests. Keep the effort proportional to the change: +a one-line local rename does not need the ceremony a public multi-targeted change does. + +## Mandatory gate: classify before validation or editing + +Read only enough repository context to classify the request. Do this before restoring, building, or +making an edit. If the entire requested operation changes behavior or cannot preserve the relevant +public/source contract, the correct result of this skill is a decisive handoff, not an implementation +attempt: + +1. State: `Not a behavior-preserving refactor: .` +2. State: `No files changed.` +3. State: `Next workflow: .` Then stop. Do not add manual implementation steps, alternatives, + an offer to proceed without the workflow, or a follow-up question — even when that workflow is unavailable. + +| Requested as a "refactor" | Classification and action | +|---|---| +| Framework or NuGet version change | **Upgrade.** Do not edit or validate the upgrade here; hand off to `dotnet-upgrade`. | +| New capability, flag, endpoint, tier, or behavior | **Feature.** Do not implement it here; hand off to the repository's feature workflow. | +| Threshold, rate, output, or bug-result change | **Behavior change.** Defer it and hand off to the repository's bug-fix or behavior-change workflow; still complete any clearly separable structural operation. | +| Tighten or loosen a shipped/public nullable annotation | **Source-contract change.** Leave the declaration and API record unchanged; hand off to the repository's API-contract workflow. | + +The three-line stop response applies only when the entire request is outside behavior-preserving +refactoring. For a mixed request, perform only a clearly separable structural operation and explicitly +defer the behavior/contract change. Never state `No files changed.` after completing that structural +operation, and never modify tests to make an unauthorized behavior change appear preserved. + +## Work only in the current repository + +Resolve the repository root first (`git rev-parse --show-toplevel`) and resolve any prompt-provided +relative solution/project path inside that root. Search and edit only that workspace. Never use +filesystem-wide search or select a similarly named clone, temporary directory, build output, or +another worktree because a file also exists there. If the named path is absent from the current +repository, stop and report that mismatch instead of guessing another workspace. + +## Rename / move by bindings, not text + +The #1 way a "rename" silently corrupts code is editing textual matches (comments, strings, unrelated +overloads) instead of real **bindings**. Find every binding reference first, then edit semantically. Use +the strongest tool available: an IDE/Roslyn workspace refactoring, then the C# LSP the +[`dotnet` plugin declares](https://github.com/dotnet/skills/blob/main/plugins/dotnet/lsp.json) +(`findReferences`, `goToDefinition`, `incomingCalls`, `rename` code action), then analyzer code-fixes / +Roslynator, then compiler-validated edits (edit the true bindings, rebuild, let the compiler flag misses). +Plain find/replace only when scope is provably tiny and every hit is verified. Include **every** `partial` +declaration, and edit the generator input, never generated (`*.g.cs`) output. + +For the operation → Roslyn-provider mapping and representative PRs, see +[references/operation-catalog.md](references/operation-catalog.md). + +## Consolidate toward the existing source of truth + +When de-duplicating, preserve the ownership direction stated by the code or request. If `B` duplicates +an implementation already owned by `A`, keep `A` canonical and make `B` delegate to it; do not invert +the dependency merely because either direction compiles. Preserve public compatibility wrappers when +the duplicate surface is shipped, and migrate only in-repo callers that are safe to move. + +## Decisions that change the edit + +Use the first matching row instead of applying the requested operation mechanically: + +| Situation | Do | Never | +|---|---|---| +| Inline an internal, unshipped pass-through wrapper | Migrate every binding reference to the target, remove the wrapper, then compile to catch misses. | Keep dead indirection "for compatibility" when no compatibility boundary exists. | +| Inline or remove a shipped/public wrapper | Migrate ordinary in-repo callers, but retain an `[Obsolete]` forwarding entry point unless the request explicitly authorizes a breaking change. | Delete a shipped API merely because all current source callers were migrated. | +| Rename a member reached by a string, reflection, DI, or configuration | Rename binding-based callers; preserve the observed external name with a forwarding shim or metadata, and exercise the old-name path. | Rewrite an external/configured name just to make the new source name consistent. | +| Extract duplicated logic whose callers pass different values | Extract the algorithm and pass each caller's existing inputs through unchanged. | Collapse distinct inputs, evaluation order, rounding, or side effects into one caller's version. | +| Rename code compiled under `#if` or multiple TFMs | Update every source branch and validate each target framework explicitly. | Treat a green default-target build as evidence for unbuilt branches. | +| Merge near-identical types | Parameterize only the values that differ, migrate every construction site, and preserve each old value exactly. If the old types are internal/unshipped and the request says to merge into one type, delete their declarations. | Retain unnecessary aliases, static holders, factories, or wrapper types that leave the requested merge incomplete; introduce a new hierarchy or behavior. | + +## Preserve contracts beyond C# call sites + +Compilation proves binding compatibility, not every external contract. Before renaming or moving a +type/member, check whether its name or metadata is observed by serialization, reflection, dependency +injection, configuration binding, source generators, P/Invoke, or `dynamic`. + +| Boundary | Required decision | +|---|---| +| Serialized/configuration name | Preserve the external name with the repository's existing mechanism (for example, `JsonPropertyName`) while migrating C# callers; run a focused round-trip or payload test. | +| Public nullable annotation | The mandatory classification gate applies: leave it unchanged and hand off as a source-contract change. | +| Uncovered reflection or runtime lookup | Do not guess that a compile-clean rename is safe. Preserve the observed name or stop and report the unverified runtime boundary. | + +## Verify proportionally + +Confirm behavior is preserved after the edit — scaled to blast radius, not a fixed ceremony: + +- **Local / private** (method-local or `private` member, one file, single target framework, no public + surface, no `partial`/generated/`#if`): skip a separate baseline unless the tree is already suspect. + Make the edit, then run the narrowest build and relevant tests once. Let the compiler catch missed + references. +- **Cross-boundary** (public/shipped symbol, multi-targeted project, `#if`/platform branches, or + `partial`/generated code): establish a baseline, then run an explicit build and the relevant tests for + **each** target framework after the edit (a test command's implicit build is not separate build evidence; + a green default build can hide a break on another TFM), and run the hazards check below. + +Use the repo's own build/test workflow when it documents one (`README`/`CONTRIBUTING`, `build.*`, `eng/`, +`global.json`, `.github/workflows`); its instructions win over any generic command. + +### Typical workflow (one operation) +1. Choose one named refactoring operation and keep the step focused on that operation only. +2. Find true binding references (`findReferences`/`goToDefinition`/rename) and include all `partial` declarations. +3. Establish a baseline first only for a cross-boundary change or a tree not already known green. +4. Apply the change via the most semantics-aware tool available; avoid blind find/replace when possible. +5. Rebuild and run the relevant tests. If the gate goes red, report the failure and repair or reassess only + your edit; never discard unrelated worktree changes. + +Otherwise: +```bash +dotnet build # 0 errors +dotnet test # stays green; same pass count as before +``` + +One operation per step; never mix a refactor and a behavior change in the same step. On red, stop and report the failure; repair only your edit without discarding unrelated worktree changes. + +## Final response contract + +Keep the handoff concise and evidence-based: + +- **Refactor:** name the structural operation and the symbols/files changed. +- **Preserved:** name the behavior or compatibility boundary and the mechanism that preserved it. +- **Validation:** report the exact commands and observed result; never claim success after a failed restore, + build, target framework, or test run. +- **Deferred:** for a mixed request, name the behavior/contract change intentionally left undone and its + correct next workflow. Omit this line when nothing was deferred. + +## Cross-boundary hazards (only when it touches a boundary) + +If — and only if — the change touches a **public** symbol, a **multi-targeted** project, or +`partial`/generated code, some breaks won't show up as a failing test. Search the repo for the surface +that governs the symbol (don't assume): the public-API gate (`PublicAPI.Shipped/Unshipped.txt` for +PublicApiAnalyzers, and/or `ApiCompat`/`` — not interchangeable), +``/`#if` branches, and `InternalsVisibleTo`. Moving a public type to another assembly +needs `[TypeForwardedTo]` in the original assembly; a move within one assembly does not. A public +*rename* needs an `[Obsolete]` shim, not a forwarder. For a provably local/private change, skip these +checks. + +## Stop and ask when + +- The baseline is already red (you can't prove you preserved behavior). +- A public/shipped API would change without a forwarder/shim or explicit authorization for a breaking change. +- Equivalence depends on runtime behavior tests don't cover (reflection, DI, serialization, `dynamic`, + P/Invoke) — flag it. diff --git a/catalog/Platform/Official-DotNet/skills/csharp-refactoring/manifest.json b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/manifest.json new file mode 100644 index 00000000..286bd19c --- /dev/null +++ b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/manifest.json @@ -0,0 +1,5 @@ +{ + "version": "0.2.4", + "category": "Core", + "compatibility": "Requires a .NET repository or solution." +} diff --git a/catalog/Platform/Official-DotNet/skills/csharp-refactoring/references/operation-catalog.md b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/references/operation-catalog.md new file mode 100644 index 00000000..340eed23 --- /dev/null +++ b/catalog/Platform/Official-DotNet/skills/csharp-refactoring/references/operation-catalog.md @@ -0,0 +1,37 @@ +# C# refactoring operation catalog (detail) + +Load this when you need the full operation taxonomy or the Roslyn provider each maps to. +The core SKILL.md keeps only the short operation list; this file is the depth. + +## Contents + +- Operation catalog (provider, recurrence, representative PR) +- "Modernize" is defined by the repo's analyzer config + +## Operation catalog + +Canonical operations, aligned with Roslyn's own IDE refactoring providers +(`src/Features/CSharp/Portable/CodeRefactorings`). The provider column is informational — a +headless CLI agent usually cannot invoke these IDE code actions directly, so apply them via the fallback +ladder in SKILL.md. + +| Operation | Roslyn provider / tool | Recurrence | Representative real PR | +|-----------|------------------------|-----------:|------------------------| +| **Rename** symbol / type / file | rename engine (`Renamer`) | high | _runtime_ "Rename `DISABLE_CROSSGEN`"; _sdk_ "Rename `dnup` to `dotnetup`" | +| **Move** type / member / file | `MoveType`, `MoveStaticMembers` | high | _runtime_ "Move DSA tests into System.Security.Cryptography"; _sdk_ "Move SDK task unit test projects from src/ to test/" | +| **Consolidate / de-duplicate** | analyzer-assisted | high | _runtime_ "Consolidate ComWrappers implementation across platforms" | +| **Modernize / simplify** idioms | `UseExplicitOrImplicitType`, `UseRecursivePatterns`, `ConvertLocalFunctionToMethod`, `AddAwait` | high | _roslyn_ "Simplify lots of redundant code in code fix providers" | +| **Split** large class / file / assembly | extract + move | medium | _roslyn_ "Split `FeatureSwitchManager`"; _runtime_ "Move RPC contracts to a separate assembly" | +| **Extract** method / class / interface | `ExtractClass`, extract-method, extract-interface | medium | _runtime_ "Extract `ManifestBuilder` and `EventListener`" | +| **Inline** method / local / constant | `InlineMethod`, `InlineTemporary` | lower | _runtime_ "Refactor `UInt128` division" | +| **Pull up / push down** member | `PullMemberUp` | tail | move members between a type and its base/interface | +| **Sync namespace** to folder | `SyncNamespace` | tail | align `namespace` with folder layout after a move | + +## "Modernize" is defined by the repo's analyzer config, not personal taste + +These repos drive idiom rules through `.editorconfig` + `EnforceOnBuild` (roslyn #49995 "Set +EnforceOnBuild values for code style analyzers"). Apply the fixes the repo's own analyzers request +(IDE00xx / CAxxxx) via `dotnet format` / code-fixes; don't impose a style it hasn't opted into, and don't +blanket-suppress diagnostics to make an edit "pass." For _adopting_ nullable annotations specifically, see +`dotnet-upgrade/migrate-nullable-references`; enabling nullable across a project or changing public API +annotations is a migration or contract change, not a canonical behavior-preserving refactoring operation. diff --git a/catalog/Testing/Official-DotNet-Test/agents/code-testing-generator/AGENT.md b/catalog/Testing/Official-DotNet-Test/agents/code-testing-generator/AGENT.md index 6707d76e..b19d8df7 100644 --- a/catalog/Testing/Official-DotNet-Test/agents/code-testing-generator/AGENT.md +++ b/catalog/Testing/Official-DotNet-Test/agents/code-testing-generator/AGENT.md @@ -33,7 +33,7 @@ You coordinate test generation using the Research-Plan-Implement (RPI) pipeline. ### Step 1: Clarify the Request and Load Language Guidance -Understand what the user wants: scope (project, files, classes), priority areas, framework preferences. If clear, proceed directly. If the user provides no details or a very basic prompt (e.g., "generate tests"), use [unit-test-generation.prompt.md](https://github.com/managedcode/dotnet-skills/blob/main/catalog/Testing/Official-DotNet-Test/skills/code-testing-agent/unit-test-generation.prompt.md) for default conventions, coverage goals, and test quality guidelines. +Understand what the user wants: scope (project, files, classes), priority areas, framework preferences. If clear, proceed directly. If the user provides no details or a very basic prompt (e.g., "generate tests"), use [unit-test-generation.prompt.md](../skills/code-testing-agent/unit-test-generation.prompt.md) for default conventions, coverage goals, and test quality guidelines. Before writing code, read the language-specific base extension. Reuse it for the whole run; sub-agents must not independently reload the same reference unless they need a section that was not captured in the research document. diff --git a/catalog/Testing/Official-DotNet-Test/agents/testability-migration/AGENT.md b/catalog/Testing/Official-DotNet-Test/agents/testability-migration/AGENT.md index eff4a793..d141e847 100644 --- a/catalog/Testing/Official-DotNet-Test/agents/testability-migration/AGENT.md +++ b/catalog/Testing/Official-DotNet-Test/agents/testability-migration/AGENT.md @@ -7,6 +7,8 @@ description: >- Use when asked to make code testable, remove static coupling, migrate to TimeProvider, adopt IFileSystem, or improve testability of a legacy codebase. name: testability-migration +agents: + - code-testing-generator handoffs: - label: Generate Tests for Migrated Code agent: code-testing-generator diff --git a/catalog/Tools/Official-DotNet-MSBuild/agents/msbuild/AGENT.md b/catalog/Tools/Official-DotNet-MSBuild/agents/msbuild/AGENT.md index 249b2f19..4ca5b6f1 100644 --- a/catalog/Tools/Official-DotNet-MSBuild/agents/msbuild/AGENT.md +++ b/catalog/Tools/Official-DotNet-MSBuild/agents/msbuild/AGENT.md @@ -3,6 +3,9 @@ name: msbuild description: "Expert agent for MSBuild and .NET build troubleshooting, optimization, and project file quality. Routes to specialized agents for performance analysis and code review. Verifies MSBuild domain relevance before deep-diving. Specializes in build configuration, error diagnosis, binary log analysis, and resolving common build issues." user-invokable: true disable-model-invocation: false +agents: + - build-perf + - msbuild-code-review license: MIT --- diff --git a/external-sources/upstreams/dotnet-skills/dotnet-diag/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet-diag/.codex-plugin/plugin.json index 263839dc..8ed7789a 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-diag/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet-diag/.codex-plugin/plugin.json @@ -2,6 +2,5 @@ "name": "dotnet-diag", "version": "0.1.2", "description": "Skills for .NET performance investigations, debugging, and incident analysis.", - "skills": ["./skills/"], - "agents": ["./agents/optimizing-dotnet-performance.agent.md"] + "skills": ["./skills/"] } diff --git a/external-sources/upstreams/dotnet-skills/dotnet-diag/README.md b/external-sources/upstreams/dotnet-skills/dotnet-diag/README.md new file mode 100644 index 00000000..c3d2491b --- /dev/null +++ b/external-sources/upstreams/dotnet-skills/dotnet-diag/README.md @@ -0,0 +1,7 @@ +# dotnet-diag + +Skills for .NET performance investigations, debugging, and incident analysis. + +The `optimizing-dotnet-performance` file under `agents/` is a GitHub Copilot custom-agent +definition. Codex plugin installs expose this plugin's skills, but do not install that `.agent.md` +file as a native Codex agent. diff --git a/external-sources/upstreams/dotnet-skills/dotnet-msbuild/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/.codex-plugin/plugin.json index 14b2cd04..81c2fe93 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-msbuild/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/.codex-plugin/plugin.json @@ -3,11 +3,6 @@ "version": "0.1.10", "description": "Comprehensive MSBuild and .NET build skills: failure diagnosis, performance optimization, code quality, and modernization.", "skills": ["./skills/"], - "agents": [ - "./agents/build-perf.agent.md", - "./agents/msbuild-code-review.agent.md", - "./agents/msbuild.agent.md" - ], "mcpServers": { "binlog": { "type": "stdio", @@ -17,8 +12,7 @@ "Microsoft.AITools.BinlogMcp", "--yes", "--prerelease" - ], - "tools": ["*"] + ] } } } diff --git a/external-sources/upstreams/dotnet-skills/dotnet-msbuild/README.md b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/README.md new file mode 100644 index 00000000..bab6e662 --- /dev/null +++ b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/README.md @@ -0,0 +1,8 @@ +# dotnet-msbuild + +Skills for MSBuild failure diagnosis, performance optimization, code quality, and modernization. +The plugin also exposes the `binlog` MCP server to supported hosts. + +Files under `agents/` are GitHub Copilot custom-agent definitions. Codex plugin installs expose the +skills and the Codex-compatible `binlog` MCP declaration, but do not install those `.agent.md` files +as native Codex agents. diff --git a/external-sources/upstreams/dotnet-skills/dotnet-msbuild/agents/msbuild.agent.md b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/agents/msbuild.agent.md index 249b2f19..4ca5b6f1 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-msbuild/agents/msbuild.agent.md +++ b/external-sources/upstreams/dotnet-skills/dotnet-msbuild/agents/msbuild.agent.md @@ -3,6 +3,9 @@ name: msbuild description: "Expert agent for MSBuild and .NET build troubleshooting, optimization, and project file quality. Routes to specialized agents for performance analysis and code review. Verifies MSBuild domain relevance before deep-diving. Specializes in build configuration, error diagnosis, binary log analysis, and resolving common build issues." user-invokable: true disable-model-invocation: false +agents: + - build-perf + - msbuild-code-review license: MIT --- diff --git a/external-sources/upstreams/dotnet-skills/dotnet-template-engine/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet-template-engine/.codex-plugin/plugin.json index b579845c..a3da1e6a 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-template-engine/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet-template-engine/.codex-plugin/plugin.json @@ -2,6 +2,5 @@ "name": "dotnet-template-engine", "version": "0.1.4", "description": ".NET Template Engine skills for dotnet new: create projects (console app, class library, web API, Blazor, MAUI), discover and search templates, inspect template parameters and frameworks (net8.0, net9.0, net10.0), scaffold solutions, author and validate custom templates, install template packages from NuGet.", - "skills": ["./skills/"], - "agents": ["./agents/template-engine.agent.md"] + "skills": ["./skills/"] } diff --git a/external-sources/upstreams/dotnet-skills/dotnet-template-engine/README.md b/external-sources/upstreams/dotnet-skills/dotnet-template-engine/README.md new file mode 100644 index 00000000..81313a40 --- /dev/null +++ b/external-sources/upstreams/dotnet-skills/dotnet-template-engine/README.md @@ -0,0 +1,7 @@ +# dotnet-template-engine + +Skills for discovering, instantiating, authoring, and validating .NET templates. + +The `template-engine` file under `agents/` is a GitHub Copilot custom-agent definition. Codex +plugin installs expose this plugin's skills, but do not install that `.agent.md` file as a native +Codex agent. diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test-migration/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet-test-migration/.codex-plugin/plugin.json index bd424234..0a282b5c 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test-migration/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet-test-migration/.codex-plugin/plugin.json @@ -1,9 +1,6 @@ { "name": "dotnet-test-migration", "version": "0.1.9", - "description": "Skills and an orchestrator agent for migrating .NET test frameworks and platforms: MSTest and xUnit version upgrades, xUnit/NUnit-to-MSTest conversion, and VSTest to Microsoft.Testing.Platform.", - "skills": ["./skills/"], - "agents": [ - "./agents/test-migration.agent.md" - ] + "description": "Skills for migrating .NET test frameworks and platforms: MSTest and xUnit version upgrades, xUnit/NUnit-to-MSTest conversion, and VSTest to Microsoft.Testing.Platform.", + "skills": ["./skills/"] } diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test-migration/README.md b/external-sources/upstreams/dotnet-skills/dotnet-test-migration/README.md index adcd2a16..ee766946 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test-migration/README.md +++ b/external-sources/upstreams/dotnet-skills/dotnet-test-migration/README.md @@ -1,6 +1,6 @@ # dotnet-test-migration -Skills and an orchestrator agent for migrating .NET test frameworks and platforms. Covers framework version upgrades (MSTest, xUnit), cross-framework conversion (xUnit/NUnit → MSTest), and test platform migration (VSTest → Microsoft.Testing.Platform). +Skills and a GitHub Copilot orchestrator agent for migrating .NET test frameworks and platforms. Covers framework version upgrades (MSTest, xUnit), cross-framework conversion (xUnit/NUnit → MSTest), and test platform migration (VSTest → Microsoft.Testing.Platform). ## When to use this plugin @@ -24,6 +24,9 @@ Skills and an orchestrator agent for migrating .NET test frameworks and platform ## Agents +The agent below is a GitHub Copilot `.agent.md` definition. Codex plugin installs expose the +migration skills, but not this agent or its static handoff. + | Agent | Purpose | |---|---| | **test-migration** | Auto-detects framework/version/platform and routes to the correct migration skill; coordinates multi-step migrations (e.g., MSTest v1 → v3 → v4) | diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet-test/.codex-plugin/plugin.json index 5ef40437..ff3c6b4f 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet-test/.codex-plugin/plugin.json @@ -2,17 +2,5 @@ "name": "dotnet-test", "version": "0.2.22", "description": "Skills for running, generating, analyzing, and improving .NET tests: test execution, filtering, platform detection, coverage, testability, and MSTest workflows.", - "skills": ["./skills/"], - "agents": [ - "./agents/code-testing-generator.agent.md", - "./agents/code-testing-researcher.agent.md", - "./agents/code-testing-planner.agent.md", - "./agents/code-testing-implementer.agent.md", - "./agents/code-testing-builder.agent.md", - "./agents/code-testing-tester.agent.md", - "./agents/code-testing-fixer.agent.md", - "./agents/code-testing-linter.agent.md", - "./agents/testability-migration.agent.md", - "./agents/test-quality-auditor.agent.md" - ] + "skills": ["./skills/"] } diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test/README.md b/external-sources/upstreams/dotnet-skills/dotnet-test/README.md index 32fcc364..4a7f7ea9 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test/README.md +++ b/external-sources/upstreams/dotnet-skills/dotnet-test/README.md @@ -1,6 +1,6 @@ # dotnet-test -Skills and agents for running, generating, analyzing, and improving tests. Originally built for .NET (MSTest, xUnit, NUnit, TUnit) and platforms (VSTest, Microsoft.Testing.Platform); the test-generation pipeline and the six test-analysis skills (anti-patterns, smells, assertion quality, gap analysis, tagging, grade tests) plus the `test-quality-auditor` agent are **polyglot** and also work with Python (pytest/unittest), TypeScript/JavaScript (Jest/Vitest/Mocha/Jasmine/node:test), Java (JUnit 4/5/TestNG), Go (testing/testify), Ruby (RSpec/Minitest), Rust (built-in/proptest), Swift (XCTest/Swift Testing), Kotlin (JUnit/Kotest), PowerShell (Pester), and C++ (GoogleTest/Catch2/doctest/Boost.Test). +Skills and GitHub Copilot custom agents for running, generating, analyzing, and improving tests. Originally built for .NET (MSTest, xUnit, NUnit, TUnit) and platforms (VSTest, Microsoft.Testing.Platform); the test-generation pipeline and the six test-analysis skills (anti-patterns, smells, assertion quality, gap analysis, tagging, grade tests) plus the `test-quality-auditor` agent are **polyglot** and also work with Python (pytest/unittest), TypeScript/JavaScript (Jest/Vitest/Mocha/Jasmine/node:test), Java (JUnit 4/5/TestNG), Go (testing/testify), Ruby (RSpec/Minitest), Rust (built-in/proptest), Swift (XCTest/Swift Testing), Kotlin (JUnit/Kotest), PowerShell (Pester), and C++ (GoogleTest/Catch2/doctest/Boost.Test). > **Test framework/platform migration** (MSTest/xUnit upgrades, xUnit → MSTest, VSTest → Microsoft.Testing.Platform) lives in the separate [`dotnet-test-migration`](../dotnet-test-migration/) plugin. @@ -95,6 +95,9 @@ filtered-command scenarios in the `run-tests` eval. ## Agents +The agents below are GitHub Copilot `.agent.md` definitions. Codex plugin installs expose this +plugin's skills, but not these agents or their static handoffs. + ### User-facing agents These are the entry-point agents you invoke directly: diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test/agents/code-testing-generator.agent.md b/external-sources/upstreams/dotnet-skills/dotnet-test/agents/code-testing-generator.agent.md index 6707d76e..b19d8df7 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test/agents/code-testing-generator.agent.md +++ b/external-sources/upstreams/dotnet-skills/dotnet-test/agents/code-testing-generator.agent.md @@ -33,7 +33,7 @@ You coordinate test generation using the Research-Plan-Implement (RPI) pipeline. ### Step 1: Clarify the Request and Load Language Guidance -Understand what the user wants: scope (project, files, classes), priority areas, framework preferences. If clear, proceed directly. If the user provides no details or a very basic prompt (e.g., "generate tests"), use [unit-test-generation.prompt.md](https://github.com/managedcode/dotnet-skills/blob/main/catalog/Testing/Official-DotNet-Test/skills/code-testing-agent/unit-test-generation.prompt.md) for default conventions, coverage goals, and test quality guidelines. +Understand what the user wants: scope (project, files, classes), priority areas, framework preferences. If clear, proceed directly. If the user provides no details or a very basic prompt (e.g., "generate tests"), use [unit-test-generation.prompt.md](../skills/code-testing-agent/unit-test-generation.prompt.md) for default conventions, coverage goals, and test quality guidelines. Before writing code, read the language-specific base extension. Reuse it for the whole run; sub-agents must not independently reload the same reference unless they need a section that was not captured in the research document. diff --git a/external-sources/upstreams/dotnet-skills/dotnet-test/agents/testability-migration.agent.md b/external-sources/upstreams/dotnet-skills/dotnet-test/agents/testability-migration.agent.md index eff4a793..d141e847 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet-test/agents/testability-migration.agent.md +++ b/external-sources/upstreams/dotnet-skills/dotnet-test/agents/testability-migration.agent.md @@ -7,6 +7,8 @@ description: >- Use when asked to make code testable, remove static coupling, migrate to TimeProvider, adopt IFileSystem, or improve testability of a legacy codebase. name: testability-migration +agents: + - code-testing-generator handoffs: - label: Generate Tests for Migrated Code agent: code-testing-generator diff --git a/external-sources/upstreams/dotnet-skills/dotnet/.codex-plugin/plugin.json b/external-sources/upstreams/dotnet-skills/dotnet/.codex-plugin/plugin.json index 609af72e..3fe9d78a 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet/.codex-plugin/plugin.json +++ b/external-sources/upstreams/dotnet-skills/dotnet/.codex-plugin/plugin.json @@ -1,7 +1,6 @@ { "name": "dotnet", "version": "0.2.4", - "description": "C# language server (LSP) integration for coding agents and high-level .NET development skills.", - "skills": ["./skills/"], - "lspServers": "./lsp.json" + "description": "Core C# and .NET development skills for coding agents.", + "skills": ["./skills/"] } diff --git a/external-sources/upstreams/dotnet-skills/dotnet/README.md b/external-sources/upstreams/dotnet-skills/dotnet/README.md index d62d861b..fd107988 100644 --- a/external-sources/upstreams/dotnet-skills/dotnet/README.md +++ b/external-sources/upstreams/dotnet-skills/dotnet/README.md @@ -10,6 +10,8 @@ Core .NET and C# skills for coding agents. ## LSP This plugin declares a C# LSP server that is launched through the .NET CLI. +The LSP declaration is available to hosts that support the plugin `lspServers` extension. Codex +plugin installs expose this plugin's skills but do not load that host-specific LSP declaration. Prerequisites: - .NET 10 SDK installed @@ -17,4 +19,5 @@ Prerequisites: ## Skills +- [csharp-refactoring](skills/csharp-refactoring/SKILL.md) - [setup-local-sdk](skills/setup-local-sdk/SKILL.md) diff --git a/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/SKILL.md b/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/SKILL.md new file mode 100644 index 00000000..2be35110 --- /dev/null +++ b/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/SKILL.md @@ -0,0 +1,150 @@ +--- +name: csharp-refactoring +description: "Performs safe, behavior-preserving refactoring of C#/.NET code, verified with build, tests, and analyzers. USE FOR: rename or move a symbol/type/file; extract a method/type/interface; inline a wrapper/method/local; merge or consolidate near-identical classes or duplicate helpers; split or modernize C# code; generated/partial declarations; public, serialized, friend-assembly, or multi-targeted contracts; and mixed requests where a feature, bug fix, package/framework upgrade, public nullability change, or other behavior/contract change is presented as a refactor and must be separated or declined. DO NOT USE FOR: ordinary feature or bug-fix requests not framed as refactoring; upgrades after reclassification (use dotnet-upgrade); new tests; or formatting-only passes (use dotnet format)." +license: MIT +--- + +# C# Refactoring (behavior-preserving) + +A refactor changes **structure**, never observable **behavior**. Do the edit with binding-aware tools, +then confirm behavior held with a build + the relevant tests. Keep the effort proportional to the change: +a one-line local rename does not need the ceremony a public multi-targeted change does. + +## Mandatory gate: classify before validation or editing + +Read only enough repository context to classify the request. Do this before restoring, building, or +making an edit. If the entire requested operation changes behavior or cannot preserve the relevant +public/source contract, the correct result of this skill is a decisive handoff, not an implementation +attempt: + +1. State: `Not a behavior-preserving refactor: .` +2. State: `No files changed.` +3. State: `Next workflow: .` Then stop. Do not add manual implementation steps, alternatives, + an offer to proceed without the workflow, or a follow-up question — even when that workflow is unavailable. + +| Requested as a "refactor" | Classification and action | +|---|---| +| Framework or NuGet version change | **Upgrade.** Do not edit or validate the upgrade here; hand off to `dotnet-upgrade`. | +| New capability, flag, endpoint, tier, or behavior | **Feature.** Do not implement it here; hand off to the repository's feature workflow. | +| Threshold, rate, output, or bug-result change | **Behavior change.** Defer it and hand off to the repository's bug-fix or behavior-change workflow; still complete any clearly separable structural operation. | +| Tighten or loosen a shipped/public nullable annotation | **Source-contract change.** Leave the declaration and API record unchanged; hand off to the repository's API-contract workflow. | + +The three-line stop response applies only when the entire request is outside behavior-preserving +refactoring. For a mixed request, perform only a clearly separable structural operation and explicitly +defer the behavior/contract change. Never state `No files changed.` after completing that structural +operation, and never modify tests to make an unauthorized behavior change appear preserved. + +## Work only in the current repository + +Resolve the repository root first (`git rev-parse --show-toplevel`) and resolve any prompt-provided +relative solution/project path inside that root. Search and edit only that workspace. Never use +filesystem-wide search or select a similarly named clone, temporary directory, build output, or +another worktree because a file also exists there. If the named path is absent from the current +repository, stop and report that mismatch instead of guessing another workspace. + +## Rename / move by bindings, not text + +The #1 way a "rename" silently corrupts code is editing textual matches (comments, strings, unrelated +overloads) instead of real **bindings**. Find every binding reference first, then edit semantically. Use +the strongest tool available: an IDE/Roslyn workspace refactoring, then the C# LSP the +[`dotnet` plugin declares](https://github.com/dotnet/skills/blob/main/plugins/dotnet/lsp.json) +(`findReferences`, `goToDefinition`, `incomingCalls`, `rename` code action), then analyzer code-fixes / +Roslynator, then compiler-validated edits (edit the true bindings, rebuild, let the compiler flag misses). +Plain find/replace only when scope is provably tiny and every hit is verified. Include **every** `partial` +declaration, and edit the generator input, never generated (`*.g.cs`) output. + +For the operation → Roslyn-provider mapping and representative PRs, see +[references/operation-catalog.md](references/operation-catalog.md). + +## Consolidate toward the existing source of truth + +When de-duplicating, preserve the ownership direction stated by the code or request. If `B` duplicates +an implementation already owned by `A`, keep `A` canonical and make `B` delegate to it; do not invert +the dependency merely because either direction compiles. Preserve public compatibility wrappers when +the duplicate surface is shipped, and migrate only in-repo callers that are safe to move. + +## Decisions that change the edit + +Use the first matching row instead of applying the requested operation mechanically: + +| Situation | Do | Never | +|---|---|---| +| Inline an internal, unshipped pass-through wrapper | Migrate every binding reference to the target, remove the wrapper, then compile to catch misses. | Keep dead indirection "for compatibility" when no compatibility boundary exists. | +| Inline or remove a shipped/public wrapper | Migrate ordinary in-repo callers, but retain an `[Obsolete]` forwarding entry point unless the request explicitly authorizes a breaking change. | Delete a shipped API merely because all current source callers were migrated. | +| Rename a member reached by a string, reflection, DI, or configuration | Rename binding-based callers; preserve the observed external name with a forwarding shim or metadata, and exercise the old-name path. | Rewrite an external/configured name just to make the new source name consistent. | +| Extract duplicated logic whose callers pass different values | Extract the algorithm and pass each caller's existing inputs through unchanged. | Collapse distinct inputs, evaluation order, rounding, or side effects into one caller's version. | +| Rename code compiled under `#if` or multiple TFMs | Update every source branch and validate each target framework explicitly. | Treat a green default-target build as evidence for unbuilt branches. | +| Merge near-identical types | Parameterize only the values that differ, migrate every construction site, and preserve each old value exactly. If the old types are internal/unshipped and the request says to merge into one type, delete their declarations. | Retain unnecessary aliases, static holders, factories, or wrapper types that leave the requested merge incomplete; introduce a new hierarchy or behavior. | + +## Preserve contracts beyond C# call sites + +Compilation proves binding compatibility, not every external contract. Before renaming or moving a +type/member, check whether its name or metadata is observed by serialization, reflection, dependency +injection, configuration binding, source generators, P/Invoke, or `dynamic`. + +| Boundary | Required decision | +|---|---| +| Serialized/configuration name | Preserve the external name with the repository's existing mechanism (for example, `JsonPropertyName`) while migrating C# callers; run a focused round-trip or payload test. | +| Public nullable annotation | The mandatory classification gate applies: leave it unchanged and hand off as a source-contract change. | +| Uncovered reflection or runtime lookup | Do not guess that a compile-clean rename is safe. Preserve the observed name or stop and report the unverified runtime boundary. | + +## Verify proportionally + +Confirm behavior is preserved after the edit — scaled to blast radius, not a fixed ceremony: + +- **Local / private** (method-local or `private` member, one file, single target framework, no public + surface, no `partial`/generated/`#if`): skip a separate baseline unless the tree is already suspect. + Make the edit, then run the narrowest build and relevant tests once. Let the compiler catch missed + references. +- **Cross-boundary** (public/shipped symbol, multi-targeted project, `#if`/platform branches, or + `partial`/generated code): establish a baseline, then run an explicit build and the relevant tests for + **each** target framework after the edit (a test command's implicit build is not separate build evidence; + a green default build can hide a break on another TFM), and run the hazards check below. + +Use the repo's own build/test workflow when it documents one (`README`/`CONTRIBUTING`, `build.*`, `eng/`, +`global.json`, `.github/workflows`); its instructions win over any generic command. + +### Typical workflow (one operation) +1. Choose one named refactoring operation and keep the step focused on that operation only. +2. Find true binding references (`findReferences`/`goToDefinition`/rename) and include all `partial` declarations. +3. Establish a baseline first only for a cross-boundary change or a tree not already known green. +4. Apply the change via the most semantics-aware tool available; avoid blind find/replace when possible. +5. Rebuild and run the relevant tests. If the gate goes red, report the failure and repair or reassess only + your edit; never discard unrelated worktree changes. + +Otherwise: +```bash +dotnet build # 0 errors +dotnet test # stays green; same pass count as before +``` + +One operation per step; never mix a refactor and a behavior change in the same step. On red, stop and report the failure; repair only your edit without discarding unrelated worktree changes. + +## Final response contract + +Keep the handoff concise and evidence-based: + +- **Refactor:** name the structural operation and the symbols/files changed. +- **Preserved:** name the behavior or compatibility boundary and the mechanism that preserved it. +- **Validation:** report the exact commands and observed result; never claim success after a failed restore, + build, target framework, or test run. +- **Deferred:** for a mixed request, name the behavior/contract change intentionally left undone and its + correct next workflow. Omit this line when nothing was deferred. + +## Cross-boundary hazards (only when it touches a boundary) + +If — and only if — the change touches a **public** symbol, a **multi-targeted** project, or +`partial`/generated code, some breaks won't show up as a failing test. Search the repo for the surface +that governs the symbol (don't assume): the public-API gate (`PublicAPI.Shipped/Unshipped.txt` for +PublicApiAnalyzers, and/or `ApiCompat`/`` — not interchangeable), +``/`#if` branches, and `InternalsVisibleTo`. Moving a public type to another assembly +needs `[TypeForwardedTo]` in the original assembly; a move within one assembly does not. A public +*rename* needs an `[Obsolete]` shim, not a forwarder. For a provably local/private change, skip these +checks. + +## Stop and ask when + +- The baseline is already red (you can't prove you preserved behavior). +- A public/shipped API would change without a forwarder/shim or explicit authorization for a breaking change. +- Equivalence depends on runtime behavior tests don't cover (reflection, DI, serialization, `dynamic`, + P/Invoke) — flag it. diff --git a/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/references/operation-catalog.md b/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/references/operation-catalog.md new file mode 100644 index 00000000..340eed23 --- /dev/null +++ b/external-sources/upstreams/dotnet-skills/dotnet/skills/csharp-refactoring/references/operation-catalog.md @@ -0,0 +1,37 @@ +# C# refactoring operation catalog (detail) + +Load this when you need the full operation taxonomy or the Roslyn provider each maps to. +The core SKILL.md keeps only the short operation list; this file is the depth. + +## Contents + +- Operation catalog (provider, recurrence, representative PR) +- "Modernize" is defined by the repo's analyzer config + +## Operation catalog + +Canonical operations, aligned with Roslyn's own IDE refactoring providers +(`src/Features/CSharp/Portable/CodeRefactorings`). The provider column is informational — a +headless CLI agent usually cannot invoke these IDE code actions directly, so apply them via the fallback +ladder in SKILL.md. + +| Operation | Roslyn provider / tool | Recurrence | Representative real PR | +|-----------|------------------------|-----------:|------------------------| +| **Rename** symbol / type / file | rename engine (`Renamer`) | high | _runtime_ "Rename `DISABLE_CROSSGEN`"; _sdk_ "Rename `dnup` to `dotnetup`" | +| **Move** type / member / file | `MoveType`, `MoveStaticMembers` | high | _runtime_ "Move DSA tests into System.Security.Cryptography"; _sdk_ "Move SDK task unit test projects from src/ to test/" | +| **Consolidate / de-duplicate** | analyzer-assisted | high | _runtime_ "Consolidate ComWrappers implementation across platforms" | +| **Modernize / simplify** idioms | `UseExplicitOrImplicitType`, `UseRecursivePatterns`, `ConvertLocalFunctionToMethod`, `AddAwait` | high | _roslyn_ "Simplify lots of redundant code in code fix providers" | +| **Split** large class / file / assembly | extract + move | medium | _roslyn_ "Split `FeatureSwitchManager`"; _runtime_ "Move RPC contracts to a separate assembly" | +| **Extract** method / class / interface | `ExtractClass`, extract-method, extract-interface | medium | _runtime_ "Extract `ManifestBuilder` and `EventListener`" | +| **Inline** method / local / constant | `InlineMethod`, `InlineTemporary` | lower | _runtime_ "Refactor `UInt128` division" | +| **Pull up / push down** member | `PullMemberUp` | tail | move members between a type and its base/interface | +| **Sync namespace** to folder | `SyncNamespace` | tail | align `namespace` with folder layout after a move | + +## "Modernize" is defined by the repo's analyzer config, not personal taste + +These repos drive idiom rules through `.editorconfig` + `EnforceOnBuild` (roslyn #49995 "Set +EnforceOnBuild values for code style analyzers"). Apply the fixes the repo's own analyzers request +(IDE00xx / CAxxxx) via `dotnet format` / code-fixes; don't impose a style it hasn't opted into, and don't +blanket-suppress diagnostics to make an edit "pass." For _adopting_ nullable annotations specifically, see +`dotnet-upgrade/migrate-nullable-references`; enabling nullable across a project or changing public API +annotations is a migration or contract change, not a canonical behavior-preserving refactoring operation. diff --git a/external-sources/vendir.lock.yml b/external-sources/vendir.lock.yml index 6b8a44b4..94e7a2f1 100644 --- a/external-sources/vendir.lock.yml +++ b/external-sources/vendir.lock.yml @@ -2,20 +2,20 @@ apiVersion: vendir.k14s.io/v1alpha1 directories: - contents: - git: - commitTitle: Surface activation-only evaluation failures (#1163)... - sha: 24f7cfbd42ad7bf52bcd67372816b982c38c64c6 + commitTitle: 'Merge pull request #873 from dotnet/add-dotnet-refactoring-skills...' + sha: 26323a52990d0cbfc838117109b40e115aac891f tags: - - skill-validator-nightly-1-g24f7cfb + - skill-validator-nightly-61-g26323a5 path: dotnet-skills - git: commitTitle: Add Cursor rules that reference the existing skill docs... sha: af2319bd01bb7cc881267a9ef42cafdaf5e9029d path: webgpu-claude-skill - git: - commitTitle: '[ci] format' - sha: 88767f2e1c67b3bba25128a1bcb1278ed1484068 + commitTitle: 'feat(factory): adversary skills (#18006)' + sha: c2e6b0d7c7badff6f27cfb8d7dbe8bcaad64759f tags: - - '@astrojs/cloudflare@14.3.1-34-g88767f2e1c' + - '@astrojs/cloudflare@14.3.1-42-gc2e6b0d7c7' path: astro path: upstreams kind: LockConfig