The test-anti-patterns skill was not reliably activated in plugin mode
because sibling descriptions overlapped:
- test-quality-auditor agent: narrowed to multi-skill audit pipelines
only, explicitly excluding single-file reviews
- writing-mstest-tests skill: removed 'review' and 'anti-patterns' from
description, added explicit exclusion for test quality auditing
- test-anti-patterns skill: expanded trigger phrases to better match
review prompts (flaky tests, duplication, tests that pass without
verifying)
- Add 'Use when:' trigger phrases to all 7 sub-agent descriptions
so parent agents can reliably discover and delegate to them
- Add .testagent/ cleanup rule to generator agent to prevent
ephemeral pipeline state from being committed
* Add test-quality-auditor hub agent for .NET test suite analysis
Introduces a new test-quality-auditor agent that triages test quality
concerns to specialized analysis skills: assertion quality, test smells,
anti-patterns, mock usage, test gaps, maintainability, coverage risk,
and test tagging. Includes a comprehensive audit pipeline that chains
multiple skills for broad health checks.
* Address Copilot review: clarify diagnostic role and coverage routing
- Reword intro to acknowledge file-modifying workflows (test tagging)
are only used with explicit user confirmation
- Clarify coverage-analysis vs crap-score: prefer coverage-analysis for
project-wide analysis, reserve crap-score for targeted method/class scope
* Add test-migration hub agent for .NET test framework and platform migrations
Introduces a new test-migration agent that auto-detects the current test
framework, version, and platform, then routes to the appropriate migration
skill (MSTest v1/v2→v3, v3→v4, xUnit v2→v3, VSTest→MTP). Handles
multi-step migrations with commit boundaries between steps.
* Align framework detection with platform-detection skill
Address Copilot review: MSTest requires metapackage, Sdk, or both
TestFramework+TestAdapter (not either alone). Add missing xUnit MTP
package variants.
* Add 'dotnet sln add' step to code-testing-implementer
When a new test project is created, register it with the solution
file using 'dotnet sln add' so that 'dotnet test <solution>'
discovers the tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: improve dotnet sln add guidance
- Use solution identified in research/plan rather than searching
- Account for .slnf solution filter scenarios
- Prefer 'dotnet test --solution' over 'dotnet test <solution>'
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Move dotnet sln add guidance to dotnet.md extension
The implementer is polyglot, so 'dotnet sln add' doesn't belong
there. Replace with a generic 'register with build system' step
that defers to extensions/, and add the .NET-specific detail
(sln/slnx/slnf handling) to extensions/dotnet.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: fix solution registration guidance in dotnet.md
- Include .slnf in 'don't substitute' warning alongside .sln/.slnx
- Qualify '--solution' flag as SDK 10+/MTP-only; fall back to
positional form for older SDKs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add testability migration skills and agent for dotnet-test
Introduces three skills and one orchestrator agent to help developers
incrementally replace hard-to-test static dependencies with injectable
abstractions:
- detect-static-dependencies: scans C# code for DateTime.Now, File.*,
Environment.*, HttpClient, Console.*, Process.* and ranks by frequency
- generate-testability-wrappers: generates wrapper interfaces or guides
adoption of built-in abstractions (TimeProvider, IHttpClientFactory,
System.IO.Abstractions)
- migrate-static-to-wrapper: mechanical codemod-style bulk replacement of
static call sites with wrapper calls, scoped per project/namespace
- testability-migration agent: orchestrates the Detect-Generate-Migrate
pipeline end-to-end
Includes eval.yaml tests and fixture projects for all three skills and
the agent.
* Fix activation, token overhead, and eval timeouts
- Expand skill descriptions with more trigger phrases for
migrate-static-to-wrapper and generate-testability-wrappers
to fix NOT ACTIVATED issues
- Collapse verbose replacement mapping tables and constructor
examples to reduce token overhead (~30% fewer tokens)
- Increase generate-testability-wrappers eval timeouts from
120s to 240s to prevent timeout-impacted scoring
- Soften detect-static-dependencies scenario 2 rubric to
reduce run-to-run variance in plugin mode
- Increase migrate-static-to-wrapper non-activation timeout
* Deduplicate test skill references and clarify skill boundaries
- Move platform-detection.md and filter-syntax.md to plugins/dotnet-test/shared/,
removing 3 identical copies of each from run-tests, mtp-hot-reload, and
migrate-vstest-to-mtp reference directories.
- Move dotnet.md from exp-test-smell-detection/extensions/ to shared/ as
dotnet-test-frameworks.md in both dotnet-test and dotnet-experimental plugins.
Update exp-assertion-quality, exp-test-boilerplate-detection, exp-test-tagging,
and test-anti-patterns to reference the shared file instead of inlining
framework detection tables.
- Differentiate test-anti-patterns (quick pragmatic review) from
exp-test-smell-detection (deep formal audit with academic taxonomy) by updating
descriptions and cross-referencing each other in When Not to Use sections.
- Update skill-validator to allow ../../shared/ file references while still
blocking other parent-directory traversals. Add tests for the new rule.
* Switch from shared/ directories to hidden reference skills
Replace the plugin-level shared/ directories with non-invocable reference
skills (user-invocable: false) that other skills reference by name.
- Create platform-detection, filter-syntax, and dotnet-test-frameworks as
hidden skills under plugins/dotnet-test/skills/. These contain the
detection tables and syntax references previously duplicated across
run-tests, mtp-hot-reload, and migrate-vstest-to-mtp.
- Create exp-dotnet-test-frameworks as a hidden skill under
plugins/dotnet-experimental/skills/ for the experimental test analysis
skills (exp-test-smell-detection, exp-assertion-quality, etc.).
- Update all consuming skills to reference these by skill name in backtick
notation instead of file links.
- Revert the skill-validator ../../shared/ exception — no longer needed
since all references now use the standard skill name mechanism.
* Merge exp-test-boilerplate-detection into exp-test-maintainability
exp-test-maintainability was only 6 calibration rules with no workflow.
exp-test-boilerplate-detection had the full 5-category detection workflow,
examples, calibration, and validation. Merge the boilerplate content into
exp-test-maintainability (the broader, more user-facing name) and add the
two unique maintainability rules (DisplayName guidance, DataRow vs
DynamicData preference) to Category 3.
- Replace exp-test-maintainability SKILL.md with the merged content
- Move test fixtures from exp-test-boilerplate-detection to exp-test-maintainability
- Merge eval.yaml scenarios (4 total: 2 from each original skill)
- Delete exp-test-boilerplate-detection skill and tests
- Update all cross-references in exp-test-smell-detection, dotnet-test-frameworks,
exp-dotnet-test-frameworks, and CODEOWNERS
* Add cross-references to test-anti-patterns for deep mock and duplication analysis
Point users to exp-mock-usage-analysis from the Over-mocking entry and
to exp-test-maintainability from the Duplicate tests entry.
* Add exp-dotnet-test-frameworks to CODEOWNERS
* Improve run-tests SDK 10 MTP detection for blame-hang scenario
Inline the critical SDK 10 detection signal (global.json test.runner)
directly in Step 1 instead of deferring entirely to the platform-detection
skill. This makes the distinction between SDK 10 (no -- separator) and
SDK 8/9 (requires -- separator) more prominent.
Add a quick detection summary table, strengthen the Common Pitfalls entry
for SDK 10 with a blame-hang-timeout example, and keep the
platform-detection skill reference for the full detection logic.
* Improve skill activation keywords in descriptions
- exp-test-maintainability: Add 'suggest a better test structure',
'consolidate similar test methods', 'convert copy-paste tests to
data-driven parameterized tests' to match prompts like 'each new case
needs a whole new method, suggest a better structure'.
- test-anti-patterns: Add 'review tests', 'find test problems', 'check
test quality', 'audit tests for common mistakes' to match review-style
prompts that don't use the word 'anti-pattern'.
- run-tests: Add 'hang timeout', 'blame-hang', 'blame-crash', 'TUnit'
to match SDK 10 blame scenarios and TUnit filter scenarios that were
intermittently not activating.
* Add coverage-analysis skill to dotnet-test plugin
Adds an automated, project-wide code coverage and CRAP score analysis skill
for .NET projects. Complements the existing crap-score skill (which is
manual/targeted for single methods) with an end-to-end pipeline:
- Auto-detects solution structure and test projects
- Detects coverage provider (Microsoft.Testing.Extensions.CodeCoverage or
Coverlet) per test project and selects the correct dotnet test arguments
- Runs coverage collection, generates reports via ReportGenerator
- Calculates CRAP scores per method via bundled PowerShell scripts
- Surfaces risk hotspots ranked by danger (complex + uncovered code)
- Produces actionable recommendations with projected score improvements
Boundary with crap-score: coverage-analysis is project-wide and automated;
crap-score is targeted and LLM-directed. The frontmatter descriptions
cross-reference each other so the skill router disambiguates correctly.
Includes eval.yaml with 3 scenarios (existing data analysis, from-scratch
coverage collection, coverage plateau diagnosis) and shared buildable
fixtures.
Fixes#457
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update plugins/dotnet-test/skills/coverage-analysis/SKILL.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Address PR review: coverage output path and scoped tool install
- Add --coverage-output $rawDir to all MS CodeCoverage dotnet test
commands (unified, .NET 9, .NET 10+, and mixed-project modes) so
Cobertura XML lands in the expected directory for downstream search
- Replace dotnet tool install --global with --tool-path scoped to
the coverage output directory to avoid mutating the user environment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Cobertura XML fixture line numbers to match StudentService.cs
FindById starts at line 101 (was 88), Search starts at line 109 (was 96).
Updated both partial-coverage and plateau fixtures.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Wrap Get-ChildItem pipelines in @() for single-result array safety
PowerShell returns a scalar FileInfo (not array) when a pipeline yields
exactly one result, making .Count return null. Wrapping in @() ensures
the result is always an array so .Count works reliably for the common
single-test-project case.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove CODEOWNERS change - not needed for this PR
The existing /plugins/dotnet-test/ and /tests/dotnet-test/ wildcards
already route reviews to @dotnet/dotnet-testing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: .csproj fallback, cross-platform paths, .sln header
- Add .csproj fallback discovery in Step 1 when no .sln found (emit
ENTRY_TYPE:Project) to match documented behavior
- Fix ProjectReference backslash to forward slash in test fixture .csproj
- Remove leading blank line from ContosoUniversity.sln fixture
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add plateau/stuck trigger language to frontmatter description
The skill was NOT ACTIVATED for the 'Coverage plateau diagnosis' eval
scenario because the frontmatter description (used by the skill router)
lacked plateau-related keywords. The prompt 'coverage is stuck' and
'what's blocking me' didn't match the existing description text.
Add 'stuck', 'plateaued', and 'blocking improvement' to the frontmatter
Use-when sentence so the skill router activates for plateau diagnosis
prompts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make CRAP scores mandatory, add existing-data shortcut path
The plateau eval scenario scored 1/5 on CRAP scores across all modes
because the LLM shortcut the workflow when existing Cobertura XML was
provided — it read the XML directly and gave a quick diagnostic answer
without computing CRAP scores or following the output template.
- Add existing-data guidance at top of Workflow section: skip test
execution but still run CRAP score computation (Steps 5-6)
- Add mandatory CRAP rule to guidelines.md: Risk Hotspots table is
required in every output regardless of analysis mode
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update plugins/dotnet-test/skills/coverage-analysis/SKILL.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>
* Extract shared references and add cross-refs for dotnet-test skills
- Extract platform detection logic into run-tests/references/platform-detection.md
(shared by run-tests, mtp-hot-reload, migrate-vstest-to-mtp)
- Extract filter syntax reference into run-tests/references/filter-syntax.md
(shared by run-tests, mtp-hot-reload, migrate-vstest-to-mtp)
- Add cross-references between skills in When Not to Use / Related Skills sections
- run-tests SKILL.md reduced from 364 to 191 lines
* Fixes
* 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>
* Add writing-mstest-tests skill with eval scenarios
Add a new skill for writing modern MSTest 3.x/4.x unit tests covering:
- Test class structure (sealed, AAA pattern, naming conventions)
- Modern assertion APIs (Assert.Throws, IsInstanceOfType, collection asserts)
- Data-driven tests (DataRow, DynamicData with ValueTuples)
- Async tests with cancellation and timeout patterns
- Test lifecycle (constructor init, TestContext injection)
- Anti-pattern detection and modernization
Includes 10 eval scenarios across 4 goal categories with fixture files
for both modern MSTest and legacy anti-pattern test projects.
MSTest.Sdk version is recommended via global.json msbuild-sdks instead of
inline in the project file, ensuring all test projects get bumped together.
* Fixes
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Apply suggestion from @Evangelink
* Apply suggestion from @Evangelink
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>