Commit Graph

14 Commits

Author SHA1 Message Date
Amaury Levé 47dd914532 Add Claude plugin manifests (#1071)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-27 12:16:20 +00:00
github-actions[bot] 62ff166f2b Weekly plugin version sync 2026-08-03 10:19:29 +00:00
Abhitej John ca1b47371f Add automated per-plugin versioning (NBGV) with /version-bump + weekly backstop (#813)
* Add automated per-plugin versioning (NBGV) with /version-bump + weekly backstop

WHY
Tools that surface skills (Copilot CLI, Claude Code, Codex, Cursor) read a
plugin's version directly from its checked-in manifest. With no versioning
discipline, a plugin's behavior can change while its advertised version stays
flat, so clients never learn to re-pull, and there is no human-readable signal
of what changed. We want correct, current versions in the repo with minimal
manual work and without bloating the marketplace clone.

WHAT
- Per-plugin semantic versioning via Nerdbank.GitVersioning (NBGV). Each plugin
  owns a version.json whose pathFilters exclude the generated manifests and the
  version.json itself, so version height tracks real content changes only.
- The computed version is materialized into the checked-in manifests
  (plugin.json and .codex-plugin/plugin.json) so every consumer reads a current
  value with no build step on their side.
- eng/version/Sync-PluginVersions.ps1 is the single workhorse. It resolves the
  set of changed plugins from a git diff, computes each version with nbgv
  (predicting the squash-merge height for PRs), and either reports or stamps.

AUTOMATIONS (two, low-touch by design)
- /version-bump: an admin/maintainer comments the command on a PR and the
  affected plugins are stamped on the PR branch. Gated on collaborator
  permission (admin/write/maintain); forks are rejected before any privileged
  step. No other PRs are auto-modified.
- weekly-version-sync: a Monday backstop (and workflow_dispatch) that stamps any
  drift on main, opens/updates a single bot PR, and explains the per-plugin
  reason. This self-heals anything that merged without a bump.

We deliberately did NOT auto-edit contributor PRs or add a noisy advisory
comment bot; maintainers stay in control and the signal stays clean.

SECURITY (multi-model adversarial review: GPT-5.5 + Gemini 3.1 Pro)
- Supply chain (High, both models): dotnet tool restore would have honored a
  nuget.config authored in the PR tree, letting an attacker remap the nbgv
  package source to a malicious feed and run code in the privileged
  contents:write context. Mitigated with a trusted eng/version/nuget.config
  (clear + nuget.org-only + packageSourceMapping), overlaid from main and used
  via --configfile so PR-supplied configs are ignored. No nuget.config is
  tracked in the repo today, so this path was genuinely exploitable.
- TOCTOU (Medium): /version-bump now checks out the authorized head SHA rather
  than the mutable branch name; a racing push fails non-fast-forward, which is
  the safe outcome.
- Injection: Set-ManifestVersion uses a MatchEvaluator (not a replacement
  string) so a "$"-bearing version cannot re-expand, plus a strict
  major.minor.patch guard that throws on a malformed base, leaving manifests
  untouched.
- A base-only version.json bump (0.1 -> 0.2) is correctly detected and stamped.

VERIFIED
End-to-end against a real NBGV git harness: content-scoped predict, base-only
bump -> x.y.0, docs-only -> [], weekly drift stamping, malformed-base guard,
and --configfile restore (exit 0). actionlint passes on both workflows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address Copilot review feedback

- Add missing plugins/dotnet-test-migration/version.json so it participates
  in versioning (it was the only plugin without one; manifests are at 0.1.0).
- CONTRIBUTING: the two manifests are not byte-identical; say the version is
  duplicated across two manifest files instead.
- weekly-version-sync: include version.json in commit attribution so a
  base-only bump is explained rather than showing 'no attributable commits'.
- Get-NbgvInfo: capture nbgv stderr and include it in the thrown error so CI
  failures are diagnosable, while keeping stdout clean for JSON parsing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-13 10:07:45 -07:00
Abhitej John 2ab3501158 Add .codex-plugin/plugin.json manifests for Codex CLI plugin install (#726)
The Codex CLI requires .codex-plugin/plugin.json as the plugin manifest
entry point. Without it, 'codex plugin add' fails with 'missing plugin.json'
even though the marketplace listing works.

This adds .codex-plugin/plugin.json to all 14 plugin directories, with paths
relative to the plugin root per the Codex docs. Also updates the agents
marketplace to use dotnet-aspnetcore (per #711 rename) and adds missing
dotnet-blazor and dotnet11 entries.

Fixes #578
Fixes #724

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 09:29:42 -07:00
Dan Moseley fe11dec69d Update .NET 10→11 migration skill for Preview 2 and 3 (#628)
* Update .NET 10→11 migration skill for Preview 2 and 3

Add breaking changes from .NET 11 Preview 2 and Preview 3 to the
migrate-dotnet10-to-dotnet11 skill. The skill previously covered only
Preview 1.

Changes:
- Add 15 new breaking changes across all reference files
- Create new aspnetcore-dotnet10to11.md reference (OpenAPI v3, Blazor)
- Update SKILL.md workflow steps, assessment checklist, and patterns
- Add 4 new eval scenarios covering high-impact P2/P3 changes
- Add github.com/dotnet/aspnetcore to known-domains.txt

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback

- Replace prompt-echoable 'corrupt' in ZipArchive eval regex with 'checksum'
- Update EF Core reference note to say 'Preview 1 through Preview 3'
- Add missing Source link for Zstandard entry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback: tighten eval regex, fix raw HTML

- Tighten OverscanCount grader regex to require 'OverscanCount' with
  a number, instead of matching bare '3' anywhere
- Wrap Blazor component snippet in backticks so it renders as code

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 19:29:36 +00:00
Dan Moseley e7ec5a77a0 Fix markdownlint CI workflow (startup_failure since inception) (#629) 2026-05-08 08:33:08 +01:00
Jan Krivanek 05aeb657e6 Add license to agent files (#568) 2026-04-21 12:57:18 +00:00
Copilot 6face98ff6 Change agents and skills fields in plugin.json to array format for Claude Code CLI compatibility (#407)
* Initial plan

* Remove agents string field from plugin.json and handle array format in parser

Claude Code CLI validates `agents` as array-of-strings per its plugin manifest
schema. Our plugin.json files had `"agents": "./agents/"` (a string), which
caused "agents: Invalid input" validation errors on install.

Remove the field from the 3 affected plugin.json files — agents are still
discovered by convention from the `agents/` directory. Also make ParsePluginJson
resilient to both string and array formats for forward-compatibility.

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Remove `agents` string field from plugin.json for Claude Code CLI compatibility

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Change agents field to array format in plugin.json, update validator to read array-first with string fallback

Plugin.json files now declare agents as an array of file paths:
  "agents": ["./agents/foo.agent.md", "./agents/bar.agent.md"]

ParsePluginJson reads the array first (preferred, Claude Code schema),
falls back to a string path (legacy). PluginInfo gains an AgentPaths
field. Validator and discovery use the array when present, else fall
back to directory-based convention.

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Simplify agents to directory-path array form ["./agents/"], handle directories in array entries

Per Copilot CLI spec, agents field values are "Path(s) to agent directories"
— no need to list individual files. Use ["./agents/"] to mirror how
skills uses "./skills/". Updated validator and discovery to handle both
directory and file entries in the array.

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Delete .nuget/nuget.exe

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Convert skills field to array format in plugin.json, update validator to handle both forms

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Align AgentPaths null checks to use { Count: > 0 } pattern for consistency

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Change `agents` and `skills` fields in plugin.json to array format for Claude Code CLI compatibility

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

* Delete .nuget/nuget.exe

* Consolidate SkillsPath/SkillPaths and AgentsPath/AgentPaths into single array fields

Remove dual string/array fields from PluginInfo. The parser now
normalizes legacy string values into single-element arrays, so all
downstream code uses only SkillPaths and AgentPaths (IReadOnlyList<string>).
This eliminates all array-vs-string fallback branching.

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-20 10:27:28 +01:00
Dan Moseley 3f510a8c55 Fix minor review feedback on migrate-dotnet9-to-dotnet10 (#180) (#335)
* Fix post-merge review feedback on #180

- sdk-msbuild: Fix incorrect 'use single quotes' guidance for #r/#load
  directives — the correct fix is to remove the quotes entirely
- serialization: Split dual Animal class declaration into separate
  before/after code blocks so each is valid C#

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update plugins/dotnet-upgrade/skills/migrate-dotnet9-to-dotnet10/references/serialization-networking-dotnet9to10.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-12 19:32:32 -06:00
Dan Moseley 3923c078b9 Add migrate-dotnet9-to-dotnet10 skill (#180)
* Add migrate-dotnet9-to-dotnet10 skill

Adds a new migration skill that guides upgrading .NET 9 projects to .NET 10,
covering TFM updates, NuGet package upgrades, and source-breaking changes
across the full .NET 10 surface area.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback: fix eval/reference consistency and CODEOWNERS

- Fix ExecuteUpdateAsync rubric: use 'regular lambda/delegate instead of
  expression tree' instead of incorrect 'Func instead of Expression'
- Fix config null binding eval prompt: .NET 9 bound null as empty string,
  not preserving constructor default
- Clarify .NET 10 null binding overwrites constructor default in reference
- Add @ViktorHofer as CODEOWNER for migrate-dotnet9-to-dotnet10

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Suffix reference filenames with -dotnet9to10 to avoid collisions

Rename all reference files under migrate-dotnet9-to-dotnet10/references/
from e.g. efcore.md to efcore-dotnet9to10.md so they don't collide with
reference files from other version migration skills. Update all
references in SKILL.md to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address BrennanConroy review: ForwardedHeaders KnownIpNetworks example and IApiEndpointMetadata guidance

- Show KnownIpNetworks property with UseForwardedHeaders context in example
- Add IApiEndpointMetadata explanation for cookie login redirect behavior
- Link to aspnetcore#62883 for details on influencing the behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Shorten skill description to fit 1024-char limit

Reduce description from 1,370 to 1,017 characters by trimming
redundant phrasing while preserving all key search terms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update CODEOWNERS

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-11 14:06:00 -06:00
Dan Moseley db33912b98 Add migrate-dotnet10-to-dotnet11 skill (#181)
* Add migrate-dotnet10-to-dotnet11 skill (Preview 1 coverage)

Adds a new migration skill that guides upgrading .NET 10 projects to .NET 11,
covering TFM updates, NuGet package upgrades, and breaking changes across
the .NET 11 Preview 1 surface area.

Sources:
- https://learn.microsoft.com/en-us/dotnet/core/compatibility/11
- https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-11.0/breaking-changes
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%2011
- https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-11/overview

Skill coverage:
- C# 15 compiler: Span safe-context, ref readonly InAttribute, nameof(this.),
  with() parsing, dynamic &&/|| with interfaces
- Core libraries: DeflateStream/GZipStream empty payloads, MemoryStream capacity,
  TAR checksum validation, ZipArchive.CreateAsync eager loading,
  Environment.TickCount consistency
- EF Core 11: Cosmos DB sync I/O fully removed
- Cryptography: DSA removed from macOS
- Runtime/JIT: x86-64-v2 minimum, Arm64 LSE requirement on Windows
- SDK: Mono launch target removed for .NET Framework apps

6 reference files loaded based on project type + 7 eval scenarios.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SYSLIB0063 NamedPipeClientStream breaking change to 10→11 skill

Add documentation for the NamedPipeClientStream constructor obsoletion
(SYSLIB0063) which was merged in dotnet/runtime#120328 for .NET 11 but
not yet documented on learn.microsoft.com. The isConnected parameter
overload is obsoleted, and projects with TreatWarningsAsErrors will
fail to build.

Changes:
- core-libraries.md: Add Obsoleted APIs section with SYSLIB0063
- SKILL.md: Add to description, Step 1 assessment, Step 3 patterns

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Tune skill description and eval prompts for activation

- Add explicit migration framing to skill description to differentiate
  from csharp-scripts skill (SDK was routing to wrong skill)
- Add 'Use the migrate-dotnet10-to-dotnet11 skill' to eval prompts,
  matching real-world usage where users explicitly invoke migration skills

Eval results (3 runs each, explicit skill invocation):

  Haiku:  6/7 activated, best +1.3 (compression/TAR scenario)
  Sonnet: 7/7 activated, best +0.3 (EF Core, TFM update scenarios)

Skill activates reliably now. Quality gains are modest because the
skill covers only Preview 1 breaking changes (training data already
includes MS Learn docs). Expect larger gains as content grows with
later previews.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update plugins/dotnet/skills/migrate-dotnet10-to-dotnet11/references/csharp-compiler.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Split nameof(this.) example into before/after code blocks

Separate the breaking and fixed code into distinct blocks to avoid
ambiguity about which line to use vs remove.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback: fix code examples and global.json guidance

- SKILL.md: Show global.json as a diff edit preserving existing keys
  (rollForward, other settings) instead of replacing the entire file
- csharp-compiler.md: Fix ref readonly lambda example to use a static
  field instead of a captured local (which won't compile in a lambda)
- csharp-compiler.md: Declare missing local variable x in ref readonly
  local function example
- eval.yaml: Fix ref readonly lambda snippet to use a class with a
  static field, matching the reference file fix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR feedback: add second CODEOWNER, add preview version to EF Core

- Add @ViktorHofer as second owner for migrate-dotnet10-to-dotnet11 and
  migrate-nullable-references paths per CONTRIBUTING.md requirements
- Add Preview 1 annotation to EF Core reference file per reviewer feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Suffix reference filenames with -dotnet10to11 to avoid collisions

Rename e.g. efcore.md to efcore-dotnet10to11.md so names won't collide
with reference files from other version migration skills. Update all
paths in SKILL.md to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove explicit skill name from eval prompts to reduce overfitting

The eval prompts were explicitly saying 'Use the migrate-dotnet10-to-dotnet11
skill' which biases baseline runs — the agent wastes time searching for a
nonexistent skill, guaranteeing worse performance. Rephrased all 7 prompts
to describe the migration task naturally without naming the skill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback: fix with/when label, add exit_success assertions

- Rename 'with()' to 'when' in switch-expression-arm parsing label
  (SKILL.md and csharp-compiler reference) to match the actual breaking change
- Add exit_success assertion to all 7 eval scenarios to match repo convention

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move Japanese Calendar breaking change to core-libraries reference

The globalization change was in the runtime-jit reference, which is only
conditionally loaded for older-hardware deployments. Since this affects
all projects regardless of hardware, move it to core-libraries (always
loaded) so it is not missed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify workflow note: allow local repo inspection, forbid only external sources

The previous wording ("Do not search the filesystem") was too broad —
the agent needs to read .csproj, solution, and source files to determine
which breaking changes apply. Reword to explicitly allow local repository
inspection while forbidding web/external sources for breaking change info.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Shorten skill description to fit 1,024-char limit (762 chars)

Remove granular breaking change names (covered in body/references),
drop LOADS REFERENCES (implementation detail), remove unsupported
ASP.NET Core 11 claim (no reference docs shipped), and tighten
DO NOT USE FOR section.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update CODEOWNERS to use @dotnet/compat team instead of individual

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move 'when' parsing change from Step 4 to Step 3

The when switch-expression-arm parsing change is a source/compilation
breaking change, not a runtime behavioral change. It belongs in Step 3
(source-breaking changes) alongside other C# 15 compiler changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-11 14:05:03 -06:00
Dan Moseley e9370fe663 Add migrate-dotnet8-to-dotnet9 skill (#182)
* Add migrate-dotnet8-to-dotnet9 skill with references and eval scenarios

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: stop and ask user for replacement strategy

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>

* Trim SKILL.md to delegate BinaryFormatter detail to reference

Keep SKILL.md as concise index; full guidance lives in
serialization-networking.md reference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Trim SKILL.md: delegate fix details to references, remove BinaryFormatter 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>

* Improve eval scenarios: setup files, task-oriented prompts, expect_activation

- 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>

* Refocus eval scenarios on Opus blind spots

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>

* Add forward-chaining guidance to migrate-dotnet8-to-dotnet9 skill

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>

* Fix EF Core eval scenarios to start with 8.0.0 package versions

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>

* Fix InlineArray eval to actually exceed 1 MiB size limit

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>

* Fix non-compiling ConfigurePrimaryHttpMessageHandler in eval

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>

* Fix non-compiling HttpClientFactory example in reference doc

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>

* Remove unsafe KnownProxies.Clear() guidance from aspnet-core reference

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>

* Remove unsafe RedactLoggedHeaders guidance from reference doc

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>

* Remove insecure BinaryFormatter re-enablement option from guidance

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>

* Add security warning against suppressing WFO1000 analyzer

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>

* Add security warning to CET opt-out guidance

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>

* Label EF Core warning suppressions as temporary workarounds

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>

* Prioritize behavioral changes and add global.json rollForward guidance

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>

* Split BinaryFormatter code snippet into separate serialize/deserialize blocks

The combined snippet used obj before declaration, which was misleading.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix SYSLIB heading to include full range SYSLIB0054-SYSLIB0057

Previously listed only SYSLIB0054 and SYSLIB0057, omitting 0055 and 0056.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix eval rubric to match setup code: Migrate/MigrateAsync

Setup code uses synchronous Migrate(), not MigrateAsync().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use distinct variable names in X509CertificateLoader examples

Duplicate 'var cert' declarations would cause compilation errors if pasted as-is.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove misleading 'backported from .NET 8' from ForwardedHeaders section

The claim is confusing in an 8-to-9 migration guide context.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify GetXmlNamespaceMaps InvalidCastException explanation

Previous wording was logically inconsistent about the direction of the type change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update plugins/dotnet/skills/migrate-dotnet8-to-dotnet9/references/efcore.md

Co-authored-by: Andriy Svyryd <AndriySvyryd@users.noreply.github.com>

* Fix ReadOnlySpan<char> String.Trim example and eval scenario

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>

* Add -dotnet8to9 suffix to reference filenames to avoid cross-skill collisions

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>

* Shorten skill description to fit 1024-char limit

Remove LOADS REFERENCES section (implementation detail already covered by
the reference loading table in the body) and tighten wording. All USE FOR
activation keywords and DO NOT USE FOR rejection keywords preserved.
Description is now 1006 characters.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback

- CODEOWNERS: Replace @ViktorHofer with @jeffschwMSFT for migrate-dotnet8-to-dotnet9
- SKILL.md: Shorten description from 1,400 to 671 chars (max 1,024)
- sdk-msbuild-dotnet8to9.md: Clarify VS 17.11 SDK targeting phrasing
- core-libraries-dotnet8to9.md: Fix cross-reference to serialization-networking-dotnet8to9.md
- serialization-networking-dotnet8to9.md: Replace 'whitelist' with 'allowlist'
- winforms-wpf-dotnet8to9.md: Rename heading to cover both Get/SetXmlNamespaceMaps
- eval.yaml: Use ReadOnlySpan<char> to properly demonstrate String.Trim RC2 breakage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* CODEOWNERS: Use solo @danmoseley (consistent with migrate-nullable-references)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update CODEOWNERS to use @dotnet/compat team instead of individual

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback: fix factual errors in references and eval

- Fix URL with %20 spaces to use hyphens (csharp-compiler ref)
- Fix DOTNET_GCConcurrent -> DOTNET_gcConcurrent casing (eval.yaml)
- Remove invalid [StructLayout] combined with [InlineArray] (eval.yaml)
- Move JSON comment outside code fence (deployment-runtime ref)
- Remove confusing preview-era sentence (winforms-wpf ref)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revert URL change: %20 encoding is correct for this MS Learn page

The original URL with percent-encoded spaces is the actual working URL;
the hyphenated version returns 404.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Improve EF Core reference doc to help failing eval scenarios

- Promote HasIndex from Low to Medium Impact with crash detail and
  removal guidance (Scenario 5 missed this causing quality regression)
- Expand id format change section with data migration implications
  and HasRootDiscriminatorInJsonId mitigation (Scenario 5 rubric)
- Add concrete DateTime.UtcNow in HasData before/after example
  (Scenario 4 missed connecting HasData to pending changes exception)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add explicit HasData search action for pending model changes

The agent reads the reference doc but doesn't connect DateTime.UtcNow
in HasData to the pending changes exception. Make the SKILL.md workflow
step prescriptive: search for non-deterministic values and replace them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Andriy Svyryd <AndriySvyryd@users.noreply.github.com>
2026-03-11 14:03:42 -06:00
Dan Moseley 8e50fc8558 Add agent and plugin spec conformance validation (#279)
* Add agent and plugin spec conformance validation

Extend the validation pipeline to check .agent.md files and plugin.json
files alongside skills. Previously only SKILL.md files were validated.

Agent validation (AgentProfiler):
- Frontmatter required (error)
- Name and description required (error)
- Name format: same rules as skills (lowercase alphanum + hyphens, 64 max)
- Name must match filename minus .agent.md suffix
- Description max 1024 chars
- Body max 500 lines

Plugin validation (PluginValidator):
- Name required, must match directory name
- Version and description required
- Description max 1024 chars
- Skills path required and must exist
- Agents path warned if specified but missing

Discovery (SkillDiscovery):
- DiscoverAgents() walks up from skill paths to plugin roots,
  scans agents/ directories for .agent.md files
- DiscoverPlugins() finds plugin.json from skill paths

Integration (ValidateCommand):
- Runs after skill discovery, before evaluation
- Errors block with exit code 1 (same as spec_conformance_failure)

All 4 existing agents and 2 plugins pass cleanly.
25 new tests (13 agent, 12 plugin).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Code review fixes: spec comments, ValidateNameFormat, kind-specific messages

- Refactor ValidateName into ValidateNameFormat (format-only) + ValidateName
  (format + directory match) so agent/plugin validation doesn't abuse the
  skill directory-match check by passing name twice.
- Warning messages now say 'Agent name' or 'Plugin name' instead of
  'Skill name' when called from AgentProfiler/PluginValidator.
- Add spec URL comments to AgentProfiler and PluginValidator referencing
  agentskills.io/specification, VS Code agent-plugins docs, and Claude Code
  plugins-reference.
- Add missing agent name edge-case tests: leading/trailing hyphen,
  consecutive hyphens, and message-prefix assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove unused agents path from plugins that have no agents

The dotnet, dotnet-data, and dotnet-upgrade plugins declared an agents
path but had no agents/ directory, producing validation warnings. Remove
the field; it can be added back when agents are actually created.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Promote agent/plugin name validation from warnings to errors

The agentskills.io spec uses 'Must' for all name constraints (length,
character set, no leading/trailing hyphens, no consecutive hyphens).
For a publishing validator these should block, not just warn. Agent
filename mismatch is also promoted since the IDE won't discover the
agent if the name doesn't match.

Skill name validation stays as warnings (lenient loading, not part
of this PR).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback

- Fix FrontmatterRegex: remove RegexOptions.Multiline so a horizontal
  rule (---) in the body is not mistaken for frontmatter. Detection and
  stripping now both anchor to start of string.
- Use filename as fallback identifier in AgentProfile when agent.Name
  is empty, so error output shows [agent:foo.agent.md] not [agent:].
- Add TryGetSafeSubdirectory to PluginValidator: rejects absolute paths
  and parent-directory traversal in skills/agents path fields. Used by
  both PluginValidator and SkillDiscovery.DiscoverAgents.
- Use DirectoryName as fallback for plugin result name when Name is
  empty, so error output shows [plugin:my-dir] not [plugin:].
- Add tests for path traversal rejection and name fallback behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Detect orphaned test directories with no matching plugin/skill

Add FindOrphanedTestDirectories to SkillDiscovery: checks that every
directory under tests/{plugin}/{skill}/ has a corresponding directory
under plugins/{plugin}/skills/{skill}/. Plugin-level orphans (tests/
directory with no matching plugins/ directory) are also flagged.

Integrated into ValidateCommand after plugin/agent validation so it
runs on every validation pass. Errors are blocking (exit 1).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR #279 review feedback

- Use case-sensitive (Ordinal) comparison for agent filename matching
  since agent names are required to be lowercase by spec.
- Replace OrdinalIgnoreCase path-under-root check in TryGetSafeSubdirectory
  with Path.GetRelativePath + '..' prefix check for correct behavior on
  case-sensitive filesystems.
- Let ParsePluginJson throw JsonException on malformed JSON instead of
  silently returning null. ValidateCommand catches it as a blocking error.
- Add test for malformed plugin.json.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Increase eval timeouts for dump-collect and dotnet-trace-collect to 120s

The with-skill runs for these skills were hitting the 60s scenario timeout
in CI, causing the agent to be killed before producing output. Other skills
in the same plugin already use 120s. The 30s decline/negative-test scenario
is left unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix fixture paths in clr-activation-debugging and analyzing-dotnet-performance evals

The source paths referenced tests/dotnet/ but the fixtures live under
tests/dotnet-diag/. This caused file-not-found exceptions at runtime,
which set hasRejections and caused unconditional exit 1 (bypassing
--verdict-warn-only).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Surface execution errors in validation summary

Previously, skills that threw exceptions (e.g. missing fixture files)
were silently excluded from the verdict count. The summary showed
'2/4 skills passed' with no indication that 2 other skills crashed
entirely. Now the summary shows '2/6 skills passed (2 rejected due
to execution errors)' and lists the specific error messages near
the summary rather than buried in the middle of the log.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Reduce parallelism for infra-change evaluation runs

When infrastructure changes trigger evaluation of all plugins
simultaneously, the high default parallelism (5x5x5) causes API
rate limits (429s) and scenario timeouts from contention. Reduce
to 2x3x3 for infra-change runs only; regular single-plugin PR
evaluations keep the default 5x5x5.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-08 15:40:06 +01:00
Dan Moseley 042a9d2b2c Reorganize plugins into domain-specific groupings (#274)
* Reorganize plugins per agreed structure (#271)

Split the dotnet plugin into domain-specific plugins per discussion
in #271:

- dotnet: narrowed to common everyday C#/.NET coding tasks
- dotnet-diag: perf investigations, debugging, incident analysis
- dotnet-data: data access and Entity Framework
- dotnet-aspnet, dotnet-wpf, dotnet-winforms, dotnet-maui: scaffolded
  empty to convey intent for future framework-specific skills

Moved skills, tests, and CODEOWNERS entries accordingly.
No file content was changed; all skill/test moves are pure renames.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Improve dotnet-diag and dotnet-winforms descriptions

- dotnet-diag: add '.NET' qualifier to clarify scope
- dotnet-winforms: use official 'Windows Forms (WinForms)' name

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add .NET qualifier to dotnet-data description

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove empty plugins; list them in CONTRIBUTING.md as future options

Remove the four empty placeholder plugins (dotnet-aspnet, dotnet-wpf,
dotnet-winforms, dotnet-maui) that had only plugin.json and no skills.

Add a 'Plugin organization' section to CONTRIBUTING.md that describes the
domain-specific plugin groupings introduced in this PR and lists the four
removed plugin names as reserved candidates for future contributions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Create dotnet-upgrade plugin with migration/upgrade skills

Move migrate-nullable-references, thread-abort-migration, and
dotnet-aot-compat from dotnet to the new dotnet-upgrade plugin.

Update CODEOWNERS paths (same owners), CONTRIBUTING.md plugin table,
and fix the thread-abort-migration SKILL.md link in CONTRIBUTING.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 21:01:52 -08:00