Commit Graph

354 Commits

Author SHA1 Message Date
Amaury Levé 8854249222 migrate-xunit-to-mstest: forbid CancellationToken.None replacement explicitly (#758)
* migrate-xunit-to-mstest: forbid CancellationToken.None replacement explicitly

The TestContext.Current.CancellationToken guidance already forbids replacing
it with a fresh CancellationTokenSource, but real-world agent migrations have
been observed substituting CancellationToken.None instead, which silently
drops the test host's cancellation linkage. Call CancellationToken.None out
explicitly so both common shortcuts are covered.

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

* Address review: mention property injection for MSTest < 3.6

Per Copilot review on PR #758: the section above notes that projects pinned to MSTest < 3.6 must use property injection. Reword the CancellationToken callout to cover both constructor and property injection so the guidance stays correct in that supported scenario.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 16:08:53 +02:00
YuliiaKovalova 74c58505e5 Improve dotnet-template-engine plugin: accuracy, dedup, and two new skills (#745)
* Improve dotnet-template-engine plugin: accuracy, dedup, and two new skills

Fix inaccurate reserved-shortName guidance, consolidate validation rules into
a single skill, expand discovery mappings, add explicit CPM/version steps, and
introduce template-comparison and template-smart-defaults skills.

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

* Fix .codex-plugin manifest indentation; add evals for new skills

Make .codex-plugin/plugin.json byte-consistent with plugin.json (2-space
indent on the agents line). Add eval.yaml + eval.vally.yaml capability
evals for the new template-comparison and template-smart-defaults skills.

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

* Address PR review: source reserved list from dotnet new --help, note workload/package availability, tighten version-refresh

- Clarify the reserved shortName set is the current dotnet new subcommands
  (authoritative source: dotnet new --help); create is verified as a real
  subcommand (alias behind dotnet new <template>).
- template-discovery: note that some mapped short names (maui, winui3, aspire,
  func, orleans) need workloads/template packages, with fallback to
  dotnet new list/search.
- template-instantiation: keep template versions by default; if refreshing,
  use dotnet list package --outdated + user confirmation and constrain to
  same major/minor rather than always latest stable.

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

* Address 2nd review round: enforce eval negatives, split combined assertion, reframe reserved list

- smart-defaults evals: enforce --no-https absence (auth scenario), absence of
  minimal-API flag (controllers scenario), and no newer --framework TFM when
  net8.0 is explicitly required, using output_not_contains/output_not_matches.
- comparison eval: split the combined (auth|aot|docker|controllers) check into
  four separate output_matches assertions so partial comparisons fail.
- template-validation/authoring: reframe the reserved shortName list as
  non-exhaustive examples and source the authoritative set from dotnet new --help;
  drop the specific create-alias assertion in favor of parsing-ambiguity wording.

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

* Make template-comparison evals robust to CI SDK currency

Switch the Blazor comparison scenario from blazorserver (absent in the CI
SDK) to blazor (Blazor Web App) vs blazorwasm, both reliably present in
.NET 8+, and instruct the agent to inspect each via --help. Update the
SKILL.md example reference for currency.

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

* Add CLI-failure resilience guidance to discovery/comparison skills

The isolated eval runs failed because the agent ran 'dotnet new <t> --help',
hit the template engine's global-mutex/persistence error (common when the
command runs concurrently in a sandbox), and then returned no answer at all.

Instruct both skills to run 'dotnet new' calls sequentially, retry once on a
transient mutex/persistence error, and fall back to the intent/parameter
mapping so a concrete answer is always produced instead of empty output.

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

* Address PR review: accurate flags + robust negative-assertion prompts

- template-smart-defaults SKILL.md: drop the non-existent --publish-aot
  flag. Clarify --aot is a dotnet new flag only on templates that expose it
  (console/worker/grpc, not webapi) and that publish-time AOT is the MSBuild
  PublishAot=true property, not a dotnet new flag.
- template-discovery SKILL.md: replace the hardcoded --enable-docker mapping
  (not a real flag on common templates) with generic 'confirm with --help'.
- smart-defaults evals: tighten the negative-assertion prompts to output only
  the command line and not mention unused flags, so a negated explanation
  can't trip output_not_contains/output_not_matches. Switch the AOT scenario
  from webapi to worker (which actually supports --aot).

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

* Address PR review round 3: scope negative checks, de-emphasize stale lists

- smart-defaults evals: anchor the negative assertions to the 'dotnet new'
  command line (same-line regex) instead of whole-output substring/regex, so a
  flag mentioned only in prose can't fail the test.
- template-validation / template-authoring: mark the dotnet new subcommand
  examples as illustrative/version-dependent and tell readers not to hardcode
  them; the live 'dotnet new --help' output is canonical.
- template-comparison: fix the example table's AOT row — webapi/webapp do not
  expose a --aot template flag; native AOT is publish-time via PublishAot.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 15:15:56 +02:00
Amaury Levé 0a387fcdfe code-testing-implementer: add mandatory harness-discovery check (#757)
* code-testing-implementer: add mandatory harness-discovery check

Generic CI/benchmark verifiers run the framework's default discovery from the repo root. Tests that pass via a scoped command (e.g. 'dotnet test MyProject.Tests.csproj', 'bundle exec rspec subgem/spec', 'Invoke-Pester -Path ./tools') but are invisible to the harness count as 0 generated tests.

Repeatedly observed in msbench cta-nightly runs:

- new C# test project never 'dotnet sln add'ed (ocelot)

- Pester tests placed under custom directories invisible to default Invoke-Pester (homebrew, ruby/ruby)

- RSpec specs placed in a sub-gem's spec/ dir invisible from repo root (fastlane)

Changes:

- code-testing-implementer: capture baseline test count in Step 2, new Step 7 'Verify Harness Discovery (MANDATORY)' with concrete failure examples, HARNESS_DISCOVERY line in report template, reminder after Step 3 to revisit registration if Step 4 creates a new project.

- code-testing-researcher: instruct to record BOTH scoped test command and harness-equivalent discovery command in .testagent/research.md.

- dotnet.md: strengthen 'Registering a new test project' heading to MANDATORY when dotnet new was used; add 'Harness Discovery Check' section with 'dotnet test <solution> --list-tests' from repo root.

- powershell.md: add 'Harness Discovery Check' section with default-config Invoke-Pester from repo root.

- ruby.md: add gem-monorepo trap guidance (fastlane, ruby/ruby) in Test Placement Contract; add 'Harness Discovery Check' section with 'bundle exec rspec --dry-run' from repo root.

* Address review feedback on harness-discovery check

- dotnet.md: replace stale `Step 8 cleanup` reference with the actual Step 3 (`Register Test Project with Build System`).
- dotnet.md: demote `Harness Discovery Check` to `###` so it nests under the parent `## .csproj / .sln Handling` section alongside `### Registering...`.
- dotnet.md: replace `\s\{4\}` (non-POSIX) in the grep regex with 4 literal spaces so the count works under BRE.
- ruby.md: group the rake/rails fallback with `{ ...; } | wc -l` so the pipe applies to both branches of `||`.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 12:39:29 +00:00
Amaury Levé 9be44ad6e5 migrate-xunit-to-mstest: add learnings from dotnet/sdk migration (#756)
* migrate-xunit-to-mstest: add learnings from dotnet/sdk migration

Refines the skill based on a real migration of 5 test projects in dotnet/sdk:

- MSTest.Sdk implicit global using: do not add `<Using Include='Microsoft.VisualStudio.TestTools.UnitTesting' />` or per-file `using` in MSTest.Sdk projects (it's already in scope). Note Option A (`MSTest` metapackage) still needs the per-file using.
- `Assert.IsExactInstanceOfType<T>` (MSTest 4.1+) is the proper single-call equivalent of xUnit's exact-type `Assert.IsType<T>`; previous guidance silently degraded it to assignable semantics (closes #755).
- `Assert.AreSequenceEqual` (MSTest 4.3+) is the modern element-wise equivalent of xUnit's `Assert.Equal` on `IEnumerable<T>`, avoiding the `CollectionAssert` + `.ToList()` dance and the MSTEST0065 trap on plain `AreEqual`.
- Clarify `AwesomeAssertions` ships in the `FluentAssertions` namespace, so it's a no-source-change swap.

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

* SKILL.md: split IsType/IsAssignableFrom row to avoid implying drop-in equivalence

Address dotnet/sdk#54727 review comment: the Step 6 summary table conflated xUnit's exact-type Assert.IsType<T> and assignable Assert.IsAssignableFrom<T> into a single row, which implies both map interchangeably even though their semantics differ. Split into three rows -- IsType<T> -> IsExactInstanceOfType<T>, IsNotType<T> -> IsNotExactInstanceOfType<T>, IsAssignableFrom<T> -> IsInstanceOfType<T> -- and explicitly call out the silent-weakening trap.

The cheatsheet already maps these correctly; this aligns the SKILL.md summary with the cheatsheet so the at-a-glance table doesn't suggest a wrong mapping.

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

* SKILL.md: resolve Step 3/Step 4 conflict on the MSTest using for Option B

Address review feedback on dotnet/skills#756: Step 3 said to skip the
per-file 'using Microsoft.VisualStudio.TestTools.UnitTesting;' on
Option B (MSTest.Sdk provides it as an implicit global using), but
Step 4 unconditionally instructed replacing xUnit usings with that
MSTest using -- so an agent following Step 4 literally would re-add
the redundant using on Option B projects.

Also drop the dangling 'Step 4 rewriter' phrasing in Step 3 (there is
no rewriter in Step 4, just a list of mechanical rewrites the agent
applies).

Step 4 now explicitly says to skip the MSTest using on Option B and
only remove the 'using Xunit;' lines, matching Step 2's note and
Step 3's branch instructions.

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

---------

Co-authored-by: Evangelink <amaury@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 07:44:23 +02:00
Abhitej John c85a2d8d9f Fix dotnet-msbuild Codex plugin install by externalizing mcpServers (#740)
* Fix dotnet-msbuild Codex plugin install by externalizing mcpServers

Move the inline mcpServers configuration to a separate .mcp.json file
inside .codex-plugin/, and update .codex-plugin/plugin.json to reference
it via a relative path string. This matches the Codex plugin spec which
requires mcpServers to be a path reference to a .mcp.json file rather
than an embedded object.

The root plugin.json retains the inline mcpServers format for the
skill-validator. Both validator methods (FindPluginMcpServers and
ExternalDependencyChecker.CheckPlugin) are updated to also handle the
Codex string path format for forward compatibility.

Fixes #738

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

* Address review: validate mcpServers path and log parse errors

- Reject rooted paths and paths with '..' segments to prevent directory
  traversal when resolving mcpServers string references.
- Log parse errors in ResolveMcpFile to stderr (consistent with
  plugin.json parse error handling) instead of silently swallowing.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 17:07:14 -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
Copilot 2d163bb600 Rename ASP.NET Core plugin from dotnet-aspnet to dotnet-aspnetcore (#711)
* Initial plan

* Rename dotnet-aspnet plugin to dotnet-aspnetcore

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-08 09:20:31 -07:00
Joey Robichaud 998ae28063 Update lsp.config to invoke dnx from the plugin directory (#607)
Due to the behavior of dotnet SDK resolution when running in repos which use a global.json, we are not gaurenteed that the choosen SDK will be new enough to support the dotnet dnx command which we were using to install and run the roslyn-language-server. Instead, we will ship our own global.json and configure the current working directory to be the plugin directory.
2026-06-05 14:25:46 -07:00
Amaury Levé 803b91f167 Add grade-tests skill for per-test PR-comment quality grading (#727)
* Add grade-tests skill for per-test quality grading

Adds a new polyglot skill that grades a provided list of test methods on a
letter scale (A-F) with a score band and 1-line notes, suitable for posting
in a PR comment table. Complements existing audit skills (assertion-quality,
test-anti-patterns, test-smell-detection) which produce suite-wide reports.

The skill:
- Takes an explicit list of tests (refuses to grade a whole workspace silently)
- Uses a 3-dimension rubric (Assertion strength, Structure & focus, Anti-pattern hygiene)
- Combines via 0.45/0.30/0.25 weighting with safety caps
- Starts at A and only deducts for observable issues
- Does not flag idiomatic patterns (table-driven sub-tests, bare assert, etc.)

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

* Address review feedback

- OrderProcessorTests.cs: fix 4 invocations that mixed named arg
  customerId: with subsequent positional args -- invalid C# syntax
  (Copilot review on PR #727)
- README.md: update 'five test-analysis skills' to 'six' in three
  places now that grade-tests is added to the polyglot list, and
  clarify that only the original 5 load from test-analysis-extensions
  while grade-tests has an inline rubric

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

* eval: drop 'grade-tests skill' wording from scenario prompts

The skill-validator's evaluate pre-flight check ValidateEvalPrompts
rejects any prompt that names the target skill, because mentioning the
skill biases baseline (skill-not-loaded) runs and inflates measured
lift. The two scenarios that asked the agent to 'use the grade-tests
skill' now just ask it to grade test methods individually -- the agent
is still expected to pick the right skill organically.

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

* Fix rubric consistency per review feedback

- README: drop incorrect 'inline rubric instead' claim (grade-tests also
  loads test-analysis-extensions for language-specific guidance)
- Assertion sub-grade: literal always-true assertions are now F (was D),
  matching the eval expectation that 'assert True' produces overall F
- Anti-pattern catalog: split always-true literals (now -> F) from
  self-referential assertions (still -> D) — they were conflated
- Combination rule: overall grade is now capped at the worst sub-grade
  (was capped at D), so an F in any one dimension yields overall F

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-05 15:42:36 +00:00
Amaury Levé 812565f8d1 Add polyglot evals for code-testing-agent (Python Flask + TypeScript Vitest) (#709)
* Add polyglot evals for code-testing-agent (Python Flask + TypeScript Vitest)

Adds two non-.NET evaluation scenarios to the dotnet-test/code-testing-agent
eval to measure how well the agent generates idiomatic tests in Python and
TypeScript — the languages exercised by the msbench top5-* benchmarks.

New fixtures (no pre-existing tests, so passing pytest/vitest proves the agent
actually generated them):
- fixtures/python-flask-tasks/ — small Flask app with TaskService (injected
  clock), TaskRepository Protocol + InMemoryTaskRepository, and a /tasks
  blueprint with HTTP 201/200/400/404/409 surfaces. Validated locally with
  `python -m pip install -e ".[test]" && python -m pytest`.
- fixtures/typescript-vitest-cart/ — small shopping-cart library with an
  injectable DiscountPolicy seam (No/Percentage policies) and a Cart class
  with non-trivial merge / clamping semantics. Validated locally with
  `npm ci && npx vitest run`. package-lock.json committed so `npm ci` is
  reproducible in CI.

New scenarios (added to both eval.yaml and eval.vally.yaml):
- "Generate pytest tests for the Flask tasks API (Python polyglot)" — asserts
  that `python3 -m pip install -e '.[test]' && python3 -m pytest` exits 0
  and that at least one `tests/**/test_*.py` file was produced. Rubric
  rewards using Flask's `test_client()`, mocking `TaskRepository` for
  service-level tests, asserting HTTP status + JSON body, and covering the
  empty-title / >200-char / not-found / already-done error paths.
- "Generate Vitest tests for the shopping-cart library (TypeScript polyglot)"
  — asserts that `npm ci && npx vitest run` exits 0 and that at least one
  `tests/**/*.test.ts` file was produced. Rubric rewards mocking
  `DiscountPolicy` via `vi.fn()`, covering Cart merge semantics,
  `updateQuantity` zero-removes, `totals()` discount-clamping, and the
  `PercentageDiscountPolicy` constructor boundary.

Companion to #708 (polyglot examples + sub-agent generification); these
scenarios exercise the per-language guidance that PR adds.

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

* Address review feedback for #709

- routes.py: guard `create_task` against non-dict JSON payloads (e.g. list)
  by returning 400 instead of letting `payload.get(...)` raise AttributeError
  and surface as a 500. This keeps the API behavior stable and makes it easier
  for generated tests to assert 400 on invalid input shapes.
- tsconfig.json: drop `vitest/globals` from `compilerOptions.types`. The
  fixture's vitest.config.ts sets `globals: false`, so allowing TypeScript
  to assume globals (describe/it/expect) only enables tests that compile but
  fail at runtime. Removing it keeps the fixture aligned with the non-global
  Vitest API the eval is exercising.

Both fixtures re-smoke-tested locally: vitest 1/1, pytest 2/2 (including a
new test confirming the non-dict body returns 400).

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

* Fix skill activation for polyglot scenarios in PR #709

Both polyglot scenarios (pytest + Flask, Vitest + TS) scored 5.0/5
quality but reported `⚠️ NOT ACTIVATED` because the SDK's skill router
did not load `code-testing-agent` into the agent's context:
`activated: false, detectedSkills: []` in skillActivationIsolated /
skillActivationPlugin. The .NET ContosoUniversity scenario activates
fine because its prompt has stronger `project-wide, multi-file ... high
coverage` framing and SKILL.md already covers .NET keywords.

Fixes per `eng/skill-validator/src/docs/InvestigatingResults.md` section
"Skill not activated":

- SKILL.md description: add framework-specific keywords (pytest,
  Flask/Django, Vitest, Jest, Mocha, JUnit, Node libraries, API,
  package, project-wide, multi-file) so the router has explicit hooks
  for polyglot prompts. Trimmed verbose `DO NOT USE FOR` clauses to
  stay under the 1,024-char skill spec limit (now 1,019 chars).
- eval.yaml + eval.vally.yaml: rewrite the two polyglot prompts to
  mirror the .NET scenario's framing — add `project-wide, multi-file
  test generation task across the ... layers` and `achieve high
  coverage`, soften the library-prescriptive bullets (Mock(spec=...),
  vi.fn()) into capability-level requirements (`mocked or stubbed`,
  `mock or hand-written stub`). Rubric items unchanged — they remain
  flexible enough to grade either mock style.

Validated locally: `dotnet run --project eng/skill-validator/src --
check --plugin ./plugins/dotnet-test` => ✅ All checks passed
(23 skill(s), 11 agent(s), 1 plugin(s)).

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

* Address PR #709 review + sharpen polyglot skill activation

**Activation fix for polyglot scenarios (Python + TypeScript)**

The previous attempt (e8e6feeb2) added pytest/Vitest framework names
to a long capability list, but both polyglot scenarios still reported
activated: false in skillActivationIsolated/skillActivationPlugin
across two consecutive /evaluate runs.

Rewrote the SKILL.md frontmatter description so trigger vocabulary
moves into the "Use when asked to ..." intent phrase and mirrors
the EXACT phrasing the polyglot prompts use (the .NET scenario
already activates because it says "scaffold a new test project",
which is in the description):

- Action triggers: "generate pytest tests", "generate Vitest tests"
  alongside "generate tests" / "write unit tests".
- Scaffolding triggers: "scaffold a new test project / test suite"
  (matches "scaffold a comprehensive pytest suite" and "scaffold
  a comprehensive Vitest suite").
- Surface nouns matching the polyglot fixtures: "web app",
  "REST API", "blueprint", "services, repositories, routes,
  and modules".
- Up front: list what the skill scaffolds across all languages
  (".NET test projects, pytest test suites, Vitest/Jest test
  suites, Go test files, JUnit test suites").

Trimmed the "DO NOT USE FOR" clause to keep the folded description
at 992 chars (under the 1,024 agentskills.io spec limit).

**Review comment fixes**

- fixtures/typescript-vitest-cart/tsconfig.json: drop
  types: ["node"] — fixture has no @types/node so tsc
  would fail with "Cannot find type definition file for 'node'".
- fixtures/typescript-vitest-cart/src/pricing.ts: rewrite the
  DiscountPolicy.computeDiscountCents @returns docstring.
  Was "Must not exceed the subtotal" (contradicted by
  Cart.totals() which clamps both negative and over-subtotal
  values). Now clearly states policies should target
  [0, subtotalCents] but Cart.totals() clamps out-of-range
  values back into the range, so contract and implementation match.
- fixtures/python-flask-tasks/src/tasks_api/models.py: the
  Task.created_at default now uses datetime.now(timezone.utc)
  via default_factory, matching TaskService's timezone-aware
  _now callable. Avoids mixing naive datetime.utcnow() with
  aware datetimes when Task is instantiated directly (e.g., in
  generated tests).
- fixtures/python-flask-tasks/src/tasks_api/routes.py: add an
  explicit isinstance(title, str) guard in create_task
  before delegating to TaskService.create. Previously a JSON
  title value that was a number/null/object would fall through
  to title.strip() and crash with AttributeError -> 500.
- fixtures/python-flask-tasks/src/tasks_api/service.py:
  defense-in-depth — TaskService.create now raises ValueError
  on non-string titles (instead of crashing) so non-Flask callers
  (and unit tests that exercise the service directly with bad
  inputs) get a clean validation error.

Validated locally:

- dotnet run --project eng/skill-validator/src -- check --plugin
  ./plugins/dotnet-test -> All checks passed (23 skill(s),
  11 agent(s), 1 plugin(s)).
- Python fixture: python -m compileall -q src clean.
- TS fixture: npm ci && npx tsc --noEmit clean.

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

* Simplify polyglot prompts to encourage skill activation

The Python pytest and TypeScript Vitest scenarios were marked NOT
ACTIVATED in evaluation runs even after rewriting the SKILL.md
description with polyglot trigger vocabulary. Investigation of
results.json showed the agent went straight to view/create without
ever invoking the `skill` tool.

Root cause: the polyglot prompts contained long bullet lists
pre-specifying exact test cases (Cart.add merge semantics, updateQuantity
zero-removes, PercentageDiscountPolicy boundary tests, TaskService
validation errors, etc.). This gave the model a complete plan and removed
any incentive to load a planning skill.

Compare with the .NET ContosoUniversity scenario (which does activate
the skill): a short open-ended prompt — "write comprehensive unit tests
across the controllers, services, and the data layer. Achieve high code
coverage." plus a real tool-config requirement (coverlet.collector for
Cobertura XML).

Mirror that style in both polyglot prompts:
- Drop the prescriptive bullet lists; keep a short framing intro and a
  single open-ended ask.
- Add a coverage tooling requirement (pytest-cov XML for Python,
  @vitest/coverage-v8 lcov for TypeScript) to give the skill real
  scaffolding value.
- Rubric and assertions unchanged — they still grade the actual quality
  of the generated suite.

Mirrors guidance in eng/skill-validator/src/docs/InvestigatingResults.md
section 5 ("Check the scenario itself has sufficient information that
the agent can reason that it needs the skill") and avoids the
"illegitimate fixes" called out there.

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

* Elaborate polyglot prompts and enforce coverage in assertions

The previous prompt rewrite got the TypeScript Vitest scenario
activating in isolated mode (2/3 runs) but the Python scenario still
NEVER activated. Inspecting the session events showed the agent went
straight to view+create on all 3 Python runs without invoking the
`skill` tool.

Theory: the Python prompt is too abstract (just "service layer, the
repository, and the Flask routes") compared to the .NET prompt which
enumerates Students/Courses/Departments/Instructors controllers. Make
the polyglot prompts feel as substantial as the .NET one by:

- Naming concrete symbols (TaskService with injected clock,
  InMemoryTaskRepository, /tasks, /tasks/<id>, /tasks/<id>/complete
  for Python; Cart.add/remove/updateQuantity/totals plus the two
  policy classes for TS) — mirrors the .NET prompt's named
  controllers list.
- Pointing at the exact mocking + injection strategy ("with the
  repository mocked and the clock injected", "with DiscountPolicy
  mocked").
- Pinning the coverage report to an explicit path (coverage.xml for
  Python, coverage/lcov.info for TS).

Also enforce the coverage tooling requirement at assertion time so
the prompt's "and the project should be configured so... coverage"
is a real deliverable — mirrors the .NET scenario's
`coverage.cobertura.xml` file_exists check:

- Python: added file_exists for fixtures/python-flask-tasks/coverage.xml
  (pytest with --cov=tasks_api --cov-report=xml in addopts writes
  coverage.xml from the directory pytest runs in).
- TS: added a `npx vitest run --coverage` run step plus file_exists
  for fixtures/typescript-vitest-cart/coverage/lcov.info.

Both changes are legitimate per
eng/skill-validator/src/docs/InvestigatingResults.md "improving the
skill vs gaming the eval" — they make the deliverable richer rather
than steering toward the skill or relaxing the rubric.

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

* Clarify SKILL.md routing and mirror coverage assertions in eval.vally.yaml

Per rubber-duck review of the activation strategy:

1. SKILL.md description was ambiguous about coverage — the previous
   wording said "DO NOT USE FOR coverage/CRAP analysis" but the
   polyglot prompts heavily mention coverage tooling. In plugin mode
   that could confuse the router into deferring to coverage-analysis
   or crap-score even when the user wants new tests written. Clarify:
   - In-scope: "configures coverage tooling (coverlet, pytest-cov,
     @vitest/coverage-v8) as part of test generation"
   - Out-of-scope: "analyzing existing coverage reports" (not just
     "coverage")
   Description re-tightened to 1003 chars (under the 1024 limit).

2. eval.vally.yaml previously asserted only that test files exist; the
   eval.yaml mirror added coverage XML / lcov.info file_exists
   assertions in the prior commit. Mirror those into the vally graders
   so both eval schemas enforce the same coverage deliverable:
   - Python: assert fixtures/python-flask-tasks/coverage.xml exists
   - TS: run npx vitest run --coverage --reporter=basic then assert
     fixtures/typescript-vitest-cart/coverage/lcov.info exists

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

* Harden polyglot fixtures so baseline cannot perfectly ace them

Both polyglot scenarios (Python Flask, TypeScript Vitest) activated the
code-testing-agent skill in isolated mode but not in plugin mode. Root
cause: the baseline (no skill loaded) was scoring 5/5, leaving the skill
no headroom to demonstrate value, so plugin-mode runs went straight to
view+write without invoking any skill.

Per InvestigatingResults.md section 8, the correct fix is to add genuine
complexity that benefits from a planning workflow rather than relaxing
rubrics or gaming activation. This commit grows both fixtures into
realistic, multi-seam libraries that genuinely reward layered test
planning.

Python (fixtures/python-flask-tasks/) additions:

- models.py: TaskPriority enum, Tag value-object with normalization /
  validation, due_at on Task, is_overdue(now) helper.
- queries.py (new): TaskQuery / TaskPage / apply_query separating
  filter / sort / pagination from the service. Sort by created_at,
  due_at, priority, or title with ascending / descending order; filter
  by status, tag, search substring, and overdue.
- repository.py: TaskRepository protocol gains delete(); added
  normalize_tags() helper that the service uses for tag dedup.
- repository_sqlite.py (new): SqliteTaskRepository — a second backend
  implementing the same Protocol using stdlib sqlite3 (no extra deps),
  with persisted tags via a task_tags table and ON DELETE CASCADE.
- service.py: configurable max_title_length, timezone-aware due_at
  validation, priority / due_at / tag mutations, reopen() and delete()
  state transitions, add_tags / remove_tag with normalization.
- routes.py: new endpoints — DELETE /tasks/<id>, POST /tasks/<id>/reopen,
  POST /tasks/<id>/tags, DELETE /tasks/<id>/tags/<name>. GET /tasks now
  parses status / tag / q / overdue / sort / order / limit / offset and
  returns a paged response with total / has_more.
- app.py: env / config-driven backend selection (TASKS_BACKEND =
  memory | sqlite, TASKS_DATABASE_URL, TASKS_MAX_TITLE_LENGTH).
- README.md: documents the new layout and the expected layered test
  approach.

TypeScript (fixtures/typescript-vitest-cart/) additions:

- pricing.ts: FixedAmountDiscountPolicy and CompositeDiscountPolicy
  with "sum" vs "chain" stacking modes (the latter compounds discounts
  on the remaining subtotal).
- tax.ts (new): TaxCalculator interface; NoTaxCalculator,
  RegionalTaxCalculator (per-region rate table with default fallback),
  AsyncTaxRateProvider async seam, AsyncTaxCalculator adapter.
- shipping.ts (new): ShippingCalculator interface;
  FreeShippingCalculator, FlatShippingCalculator (with optional
  free-over-threshold), WeightBasedShippingCalculator (bracket-based
  with overflow cost).
- inventory.ts (new): PriceFetcher and InventoryChecker async seams,
  InventoryError with productId / requested / available, refreshPrices()
  helper.
- cart.ts: fixed pricing pipeline subtotal → discount (clamped) → tax
  (on the discounted subtotal) → shipping; async checkout() that
  refreshes prices, checks inventory (first denial wins,
  InventoryError thrown), and supports an AsyncTaxRateProvider for
  this call.
- product.ts: optional weightGrams (used by shipping) and currency.
- index.ts: barrel re-exports for all new symbols.
- README.md: documents the new layout and the expected layered test
  approach.

eval.yaml + eval.vally.yaml:

- Updated both polyglot prompts to name the new modules and seams
  (queries.apply_query, SqliteTaskRepository, tag endpoints,
  CompositeDiscountPolicy stacking, AsyncTaxRateProvider,
  WeightBasedShippingCalculator, PriceFetcher / InventoryChecker,
  InventoryError). Style remains open-ended (.NET-style) — no bullet
  list of test cases.
- Replaced the small rubric with outcome-based rubric items that grade
  the new behaviors: pipeline composition (tax on discounted
  subtotal), CompositeDiscountPolicy stacking-mode differences, weight
  bracket boundary semantics, async checkout() with mocked
  collaborators including InventoryError shape, queries.apply_query
  pagination boundaries, SqliteTaskRepository integration tests
  against an in-memory connection, multi-status assertions across
  200/201/204/400/404/409, and constructor validation on the boundary
  classes.
- Bumped per-command timeouts from 5m to 10m to absorb the larger
  test suite.

No skill description / SKILL.md changes — the skill description is
already accurate for these scenarios (1003 / 1024 chars).

* Enforce hard 80% coverage floor on polyglot fixtures

After the previous harden commit (c78532bf7), the polyglot scenarios still
scored a 5.0/5 baseline with no plugin-mode activation. Root cause: even on
the larger fixtures the judge ticked every rubric item because the baseline
agent wrote tests that *touched* each named module — the rubric grades
"covered this concept", not "covered this code path", so a strong baseline
naturally clears it.

The previous commit hardened the SURFACE of the fixtures. This commit
hardens the SUCCESS BAR by baking coverage thresholds into the test
runners themselves, so a baseline that skips an entire module fails the
existing pytest / vitest run-command assertion outright (assertion exit
code != 0 → run fails → judge cannot give 5/5).

Python (fixtures/python-flask-tasks/pyproject.toml):

- Added `pytest-cov>=5.0,<7.0` to the [test] extra so coverage is
  pre-installed (the agent no longer has to add it manually).
- Set `addopts = "-q --cov=tasks_api --cov-branch --cov-report=xml
  --cov-report=term-missing --cov-fail-under=80"`. pytest now exits
  non-zero when total line + branch coverage on tasks_api is below 80%,
  which makes the existing `python -m pytest` assertion fail.

TypeScript (fixtures/typescript-vitest-cart/vitest.config.ts):

- Added a `coverage` block that pre-configures provider: 'v8',
  reporter: ['lcov', 'text'], include: ['src/**/*.ts'], and thresholds
  of lines / statements / functions ≥ 80, branches ≥ 70. The agent no
  longer has to wire up the coverage provider. `npx vitest run
  --coverage` exits non-zero when any threshold is unmet.

Prompts (eval.yaml + eval.vally.yaml):

- Trimmed the prompts to drop the "configure coverage if not already
  there" guidance — coverage tooling is now pre-installed and the floor
  is fixed. The prompt now explicitly tells the agent the threshold is
  enforced and that incidental coverage will not clear the bar, so the
  agent's planning workflow has a concrete cross-module target to plan
  against.

READMEs: documented the new behavior so the agent reading the README
sees the coverage floor up front.

Verified locally: with an empty tests/ directory, pytest exits 1 with
"FAIL Required test coverage of 80% not reached" and `vitest run
--coverage` exits 1 with "Coverage for lines (0%) does not meet global
threshold (80%)". The existing run-command assertions therefore fail for
incomplete suites without needing any new assertion / grader.

* Address PR #709 review: snapshot deep-copy, due_at sort, tests/ wording

- cart.ts: snapshot() now deep-copies the Product on each line in addition

  to the CartLine, so callers mutating the returned snapshot can no longer

  reach back into the cart's internal state via line.product. (Copilot 3344261946)

- queries.py: _sort_key for 'due_at' returns a (is_none, isoformat) tuple

  so we never compare across the None / not-None boundary, and never

  trigger 'cannot compare naive and aware datetimes' TypeErrors when

  a stray naive datetime sneaks through. (Copilot 3347273389)

- README + eval.yaml + eval.vally.yaml: reword the 'tests/ directory is

  intentionally empty' phrasing to 'no test files yet — only a .gitkeep

  marker' so the docs are strictly accurate about what's on disk.

  (Copilot 3344580026 / 3344580055 / 3344580067 / 3344580085 / 3344580104

  / 3344580136 / 3344580156)

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-05 12:38:35 +00:00
Amaury Levé 7fc6d472c3 Add migrate-xunit-to-mstest skill (#718)
* Add migrate-xunit-to-mstest skill

Adds a skill to migrate .NET test projects from xUnit.net (v2 or v3) to

MSTest v4. Covers package replacement, attribute/assertion/fixture/lifecycle

translation, ITestOutputHelper -> TestContext, [Trait] -> [TestCategory]/

[TestProperty], and xUnit v3 TestContext.Current.CancellationToken.

Front-loads parallelization handling because xUnit parallelizes test classes

by default while MSTest serializes — the single largest source of post-

migration regressions. Step 11 enumerates three explicit choices and how to

translate CollectionBehavior/MaxParallelThreads/[Collection] settings.

Preserves the existing test platform (VSTest stays VSTest; MTP stays MTP)

by default — bundling a platform migration would violate the

test-migration agent's 'never mix migration steps' rule.

- plugins/dotnet-test/skills/migrate-xunit-to-mstest/SKILL.md (workflow)

- plugins/dotnet-test/skills/migrate-xunit-to-mstest/references/mapping-cheatsheet.md

- tests/dotnet-test/migrate-xunit-to-mstest/eval.yaml (12 scenarios)

- tests/dotnet-test/migrate-xunit-to-mstest/eval.vally.yaml (parity with sibling skill)

- plugins/dotnet-test/README.md (table entry)

- plugins/dotnet-test/agents/test-migration.agent.md (triage routing)

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

* Fix step cross-references flagged in PR review

- Step 1.5 'Custom DataAttribute' bullet pointed to Step 6 (assertions);

  custom DataAttribute mapping lives in Step 5 (data-driven tests).

- Step 7 lifecycle table 'Constructor' row pointed to Step 8 for

  ITestOutputHelper; ITestOutputHelper conversion is in Step 9 (output).

- Commit-strategy callout said 'after Step 5 (asserts fixed)' and 'after

  Step 9 (fixtures/lifecycle rewritten)'; asserts are in Step 6 and

  fixtures/lifecycle complete after Step 8.

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

* Map [assembly: Xunit.Trait] to [assembly: TestCategory]/[TestProperty]

Both TestCategoryAttribute and TestPropertyAttribute target Assembly,

Class, and Method, so an xUnit [assembly: Trait] does not need to be

demoted to per-class/per-method MSTest attributes — assembly scope is

preserved 1:1.

- references/mapping-cheatsheet.md §8 now maps [assembly: Trait] to

  [assembly: TestCategory] / [assembly: TestProperty] instead of 'Remove'.

- SKILL.md Step 12 promoted to 'Convert' (was 'Remove'); the same mapping

  is documented inline.

- Notes after the Step 4 and §1 trait tables now disclose the assembly

  target so users do not assume class/method-only scope.

Addresses PR feedback from @Evangelink.

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

* Address second round of PR review feedback

From @Evangelink:

- [Ignore]/[Timeout] do NOT discover a test on their own — they are

  modifiers. SKILL.md Step 4 + cheatsheet §1 now show [Fact(Skip)] ->

  [TestMethod] + [Ignore(...)] (and same for [Timeout]). Eval scenario 9

  rubric updated to require both attributes.

- TestProperty IS filterable (was incorrectly described as 'metadata that

  does not need filter integration'). Notes after the trait tables in

  both SKILL.md and cheatsheet §1 now show both filter syntaxes.

- For environmental gates (OS-/CI-/arch-conditional), point at MSTest

  3.10+'s condition attributes ([OSCondition], [CICondition],

  [ArchitectureCondition], [NonParallelizableCondition]) as the preferred

  alternative to overloading [TestCategory] or scattering Assert.Inconclusive

  through test bodies. Strengthened in cheatsheet §3.9, SKILL.md Step 6,

  Step 10 SkippableFact row, and the Common Pitfalls table.

- TestDataRow<T> is also a supported MSTest data source (strongly typed

  with per-row DisplayName/Ignore metadata). Added to both SKILL.md Step 5

  and cheatsheet §2 with link to the docs.

- MSTest.Sdk + <UseVSTest>true</UseVSTest> pulls in Microsoft.NET.Test.Sdk

  automatically — the manual PackageReference was incorrect. Removed it

  from both files (Step 2, Step 3 'common mistakes', and Common Pitfalls).

- Added the 'pin MSTest.Sdk in global.json msbuild-sdks' alternative as

  the recommended pattern for multi-project solutions.

- Xunit.Combinatorial -> Combinatorial.MSTest (Youssef1313 community port).

  Updated both SKILL.md Step 10 and cheatsheet §10.

From Copilot reviewer:

- MSTest.Sdk example in SKILL.md Step 2 Option B hardcoded

  <TargetFramework>net9.0</TargetFramework>, contradicting the

  preserve-TFM rule. Replaced with a placeholder + explicit comment.

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

* Improve xUnit-to-MSTest skill effectiveness based on eval feedback

Eval results on PR #718 showed regressions on three rubric items where the

agent did the migration correctly but did not COMMUNICATE the judgement-call

decisions, so the judge could not verify the choice was deliberate:

- ICollectionFixture scope decision (rubric: 'Explicitly explains the scope

  decision instead of silently widening' scored 1/5 because the agent said

  'Let me convert everything' with zero scope discussion). Step 8 now requires

  a templated explanation of (source scope, target scope, what is shared, what

  is serialized, why the rejected alternative was rejected) before applying.

- Parallelization 'MSTest default is serial' messaging (rubric scored 1.7/5

  because the agent only implicitly conveyed it). Step 11 Choice A now demands

  a templated sentence explaining that the [assembly: Parallelize] is REQUIRED

  to match xUnit, otherwise the suite silently regresses to serial.

- Response Guidelines now lists the three judgement-call decisions that MUST

  be communicated up-front: fixture scope, parallelization model, and the

  Throws/ThrowsExactly semantic flip.

Additional fixes from this round:

- Step 2: explicit guidance to default to Option A (MSTest metapackage) when

  the user says 'preserve VSTest', so the safer PackageReference path is

  picked over MSTest.Sdk + UseVSTest.

- Step 4: pulled the '[Ignore]/[Timeout] are modifiers, need [TestMethod]'

  callout out of a table footer into a visible note above the table.

- known-domains.txt: allowlist github.com/Youssef1313/Combinatorial.MSTest

  (referenced from SKILL.md Step 10 and cheatsheet §10 after the recent

  Xunit.Combinatorial -> Combinatorial.MSTest switch).

Validator: green (24 skills, 11 agents).

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

* Add concrete TestContext.Current.CancellationToken migration example

The CancellationToken scenario was failing/low-scoring because the skill only
contained a one-line mapping with no concrete example. The agent often missed
the requirement to:

  - Add constructor TestContext injection (even when ITestOutputHelper is absent)
  - Map Assert.False -> Assert.IsFalse alongside the rename
  - NOT fabricate a CancellationTokenSource as a replacement

Add a full xUnit v3 -> MSTest worked example next to the TestContext.Current
mapping (Step 9), and reinforce the CancellationTokenSource warning in the
cheatsheet. The example covers all 3 rubric points for the scenario.

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

* Address third round of PR review feedback

- Remove fictional MSTest condition attributes [ArchitectureCondition] and
  [NonParallelizableCondition] from SKILL.md and cheatsheet (only [OSCondition]
  and [CICondition] exist in MSTest 3.10+; for non-parallel intent use
  [DoNotParallelize], for architecture gating fall back to runtime
  Assert.Inconclusive). (Copilot)
- TestPropertyAttribute targets only [Class|Method] (no AttributeTargets.Assembly),
  so [assembly: TestProperty(...)] does not compile. Update the trait notes in
  SKILL.md Step 4, cheatsheet section 1, Step 12, and cheatsheet section 8 to
  collapse a non-category xUnit [assembly: Trait] to [assembly: TestCategory] or
  push it down to per-class [TestProperty]. (@Evangelink)
- Step 1 platform detection: stop inlining a buggy VSTest-vs-MTP matrix;
  delegate to the platform-detection skill. Note explicitly that
  <UseMicrosoftTestingPlatformRunner> only affects 'dotnet run' and is not a
  reliable runner signal. (@Youssef1313)
- Step 2 Option A: add MTP code-coverage caveat -- Microsoft.NET.Test.Sdk
  pulls VSTest's Microsoft.CodeCoverage transitively, which can interfere with
  MTP's collector. Prefer Option B (MSTest.Sdk without UseVSTest) for MTP
  projects. (@Youssef1313)
- Step 3: remove fictional MSBuild properties (<CaptureConsoleOutput>,
  <UseRoslynCompilers>); restate the bullet about xunit.runner.json -> Step 11
  port instead. Restate the <UseMicrosoftTestingPlatformRunner> bullet to make
  clear it is not a runner switch. (@Youssef1313)

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

* Address Copilot review round 4

- mapping-cheatsheet.md (Assert.Contains predicate): the suggested fallback
  Assert.Contains(collection.First(x => predicate), collection) is buggy --
  First() throws InvalidOperationException on no-match (changing the failure
  mode), and feeding the result back into Assert.Contains is circular. Keep
  only the correct translation: Assert.IsTrue(collection.Any(x => predicate)).
- SKILL.md Step 4 / cheatsheet table: stop instructing 'mark every class
  sealed'. xUnit projects commonly use base/derived test classes (shared
  setup, generic base fixtures); mechanically sealing them would break
  compilation. Sealing is now framed as an optional follow-up handled by
  writing-mstest-tests, not part of the mechanical migration.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-05 11:40:40 +02:00
Roman Głogowski ebd901dd83 Update plugins/dotnet/.lsp.json
Co-authored-by: Joey Robichaud <joseph.robichaud@microsoft.com>
2026-06-05 07:31:00 +02:00
Amaury Levé ecbecbc6f7 writing-mstest-tests: tighten description triggers (#712)
Refine the SKILL.md frontmatter description so the skill router has
sharper hooks for common MSTest test-writing prompts:

- Add concrete intent triggers (better MSTest assertion than
  Assert.IsTrue, replace hard cast with MSTest type assertion).
- Expand the assertion API surface listed in USE FOR with the modern
  MSTest 3.x/4.x set (IsInstanceOfType, Contains, ContainsSingle,
  IsEmpty/IsNotEmpty, DoesNotContain).
- Group related triggers (data-driven, lifecycle, parallelization)
  for readability.
- Tighten DO NOT USE FOR (drop redundant clauses) and explicitly
  exclude xUnit/NUnit/TUnit so the router doesn't grab non-MSTest
  prompts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-04 08:06:15 +02:00
Amaury Levé 49a77a90bf code-testing-agent: add polyglot pipeline examples for Python/TypeScript/Go/Java (#708)
* code-testing-agent: add polyglot pipeline examples for Python/TypeScript/Go/Java

The code-testing-agent skill family is polyglot in description but in
practice biased toward .NET because dotnet-examples.md was the only
filled-in pipeline walkthrough. The four sub-agents that participate in
the Research-Plan-Implement pipeline (researcher, planner, implementer,
generator) all pointed to dotnet-examples.md whenever they suggested a
concrete example, which made it harder for the agent to produce
idiomatic non-.NET tests (e.g. in msbench top5-* benchmarks for
Python/Flask, TypeScript/Express).

This change

* adds four new example files mirroring dotnet-examples.md format
  (source → research → plan → generated test → fix cycle → final report):
  - python-examples.md (pytest, unittest.mock, Mock(spec=...), parametrize)
  - typescript-examples.md (Vitest with notes for Jest; it.each,
    async tests, fake timers, ESM/CJS fix cycle)
  - go-examples.md (standard testing package, table-driven subtests,
    hand-written fake repository, injected clock)
  - java-examples.md (JUnit 5 + Mockito on Maven, @ParameterizedTest +
    @CsvSource, Clock.fixed, Surefire fix cycles)
* updates code-testing-extensions/SKILL.md TOC to list the new files
  and clarifies usage instructions to read the matching <language>-
  examples.md alongside the base extension
* makes the "Concrete example" pointers in code-testing-generator,
  code-testing-implementer, code-testing-planner and
  code-testing-researcher agents language-agnostic (list all available
  example files instead of hard-coding dotnet-examples.md)
* expands code-testing-researcher project-structure detection list to
  cover more Python (tox.ini, noxfile.py, requirements*.txt, uv.lock,
  poetry.lock, pdm.lock), JS/TS (.mts/.cts/.jsx, vitest.config.*,
  jest.config.*), C++ (CMakeLists.txt, BUILD.bazel, meson.build),
  Java/Kotlin (pom.xml, build.gradle[.kts], wrappers), and other
  ecosystem files; expands the Identify-Language section accordingly
* extends the "Language-Specific Examples" section in
  code-testing-agent/SKILL.md to summarise each example file

Validated with: skill-validator check --plugin ./plugins/dotnet-test
(23 skills, 11 agents — all checks passed) and markdownlint-cli2.

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

* Address review feedback for #708

- go-examples.md: replace the hand-rolled `contains`/`stringIndex`
  helpers with `strings.Contains` from the standard library. The hand-rolled
  `contains` had subtly wrong semantics — `contains(""abc"", """")` returned
  `false` while `strings.Contains` returns `true` — and the helpers are
  unnecessary complexity for a code-generation example.
- go-examples.md: in the `go test -run` "wrong selection regex" sample fix
  cycle, quote the test name and use `single_item` (matching the underscore
  that the surrounding diagnosis text refers to) instead of the unquoted
  `single item` which the shell would parse as two separate CLI arguments.
- java-examples.md: the source-tree file list described `Invoice.java` as a
  `record` but the `InvoiceService.markAsPaid` example mutates the invoice
  via `setStatus(...)` and `setPaidDate(...)` — records are immutable, so
  the description was internally inconsistent. Re-describe it as a mutable
  POJO with explicit mutators to match the service code.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 13:42:46 +00:00
Amaury Levé 680292e04c Make dotnet-test analysis skills and auditor agent polyglot (#707)
* Make dotnet-test analysis skills and auditor agent polyglot

Five test analysis skills and the test-quality-auditor agent in
plugins/dotnet-test previously activated only on .NET MSTest/xUnit/NUnit/
TUnit cues, even though the underlying techniques (assertion diversity,
anti-pattern detection, pseudo-mutation gap analysis, academic smell
catalog, trait tagging) apply equally to other test frameworks.

This change makes them polyglot across .NET, Python (pytest/unittest),
TypeScript/JavaScript (Jest/Vitest/Mocha/node:test), Java (JUnit/TestNG),
Go, Ruby (RSpec/Minitest), Rust, Swift (XCTest/Swift Testing), Kotlin
(JUnit/Kotest), PowerShell (Pester), and C++ (GoogleTest/Catch2/doctest).

Changes
-------

* New reference skill `test-analysis-extensions` with per-language
  extension files (dotnet, python, typescript, java, go, ruby, rust,
  swift, kotlin, powershell, cpp). Each documents test markers,
  assertion APIs, sleep / time / random APIs, skip annotations,
  setup/teardown, mystery-guest indicators, integration markers, and
  tag-support capability for the corresponding framework.
* `assertion-quality`, `test-anti-patterns`, `test-gap-analysis`,
  `test-smell-detection`, `test-tagging` SKILL.md updated: frontmatter
  now lists all polyglot frameworks (keeping .NET trigger words for
  backward compat); bodies reference `test-analysis-extensions` and
  add per-language calibration (e.g., Go/Rust table-driven loops are
  idiomatic and not Conditional Test Logic; pytest bare `assert` is
  canonical; missing-await on async assertions is a new Critical smell).
* `test-quality-auditor` agent now runs language detection, gates
  .NET-only pipeline steps (coverage-analysis, CRAP, detect-static-
  dependencies, testability migration, experimental dotnet skills), and
  recommends native tooling for non-.NET projects via an explicit
  Capability Matrix.
* README updated to split sections by polyglot vs .NET-only.
* New polyglot eval scenarios added (Python/pytest, TS/Jest,
  Java/JUnit) alongside existing C# scenarios in
  `test-anti-patterns`, `assertion-quality`,
  `test-smell-detection`.

The .NET-only skills (writing-mstest-tests, migrate-*, coverage-analysis,
crap-score, detect-static-dependencies, run-tests, filter-syntax,
platform-detection, dotnet-test-frameworks, mtp-hot-reload, exp-*) are
unchanged and continue to activate only for .NET work.

Validated with skill-validator `check --plugin ./plugins/dotnet-test`.

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

* Address PR #707 review feedback

* typescript.md: replace xpect.fail() recommendation (Jest has no
  such API) with 	hrow new Error(...) / explicit failing assertion.
* test-tagging SKILL.md description: clarify that unittest has no
  canonical tag syntax (pytest markers are the auto-edit mechanism;
  unittest is report-only). Switch doctest reference to "decorators"
  rather than implying a Catch2-style [tags] mechanism exists.
* test-tagging SKILL.md auto-edit list and table: use
  `* doctest::test_suite("tag")` decorator chain syntax for doctest
  in both the bullet list and the per-framework table, matching the
  example already shown.
* cpp.md extension: spell out the Catch2 vs doctest tagging
  distinction in the capability matrix (Catch2 [tag], doctest
  * doctest::test_suite("tag") decorator).

Validated with `dotnet run --project eng/skill-validator/src -- check
--plugin ./plugins/dotnet-test` (23 skills + 11 agents).

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-01 16:46:26 +02:00
Amaury Levé 2b7fcdd7ab dotnet-test: add Rule #0 (Confirm the Test Target) to ruby/powershell extensions (#702)
* dotnet-test: add Rule #0 (Confirm the Test Target) to ruby/powershell extensions

When the prompt does not name a specific file ("test the repository", "one
core module", "comprehensive suite"), agents frequently target the wrong
code — typically the largest upstream module that already has rich existing
tests — instead of the newly-added module the user actually wants tested.
Recent benchmark runs (top5-{ruby,powershell}-*-{simple,complex}) showed
this is a dominant failure mode for Ruby/PowerShell: the agent burns 50+
turns writing tests for files the verifier never measures, while the real
target (a small untracked `lib/string_utils.rb` or `tools/StringUtils.psm1`)
sits one `git status` away.

Adds a Rule #0 to both ruby.md and powershell.md, ahead of the existing
"Rule #1: Investigate the Repo First". The rule:

- Tells the agent to use git history (`git status -s`,
  `git ls-files --others --exclude-standard`,
  `git log --diff-filter=A --name-only -5`) to find the actual target
  rather than guessing from repo size.
- Documents a Test Placement Contract — RSpec scopes to `spec/`,
  Pester scopes to whatever directory the harness passes to
  `Invoke-Pester -Path`; tests placed elsewhere are invisible.
- Adds a First-Test Sanity Loop: write one test, run --dry-run /
  -PassThru to confirm discovery > 0, fix LoadError / Import-Module
  issues before expanding. Catches placement mistakes on turn 1.

Both files validate cleanly under skill-validator. The existing Rule #1
and all subsequent sections are unchanged — this is a pure prepend.

Co-authored-by: Copilot <223556219+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>

* Address PR review: clarify Rule #0 precedence and broaden require regex

- Rephrase Rule #0's discovery preamble in ruby.md and powershell.md to
  call out the commands as the read-only exception to Rule #1, removing
  the apparent contradiction between 'before planning' and Rule #1's
  'before writing any test or running any command'.
- Broaden the spec_helper require grep to match leading whitespace and
  `require_relative`, avoiding false negatives that send the agent to
  the wrong target.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 10:22:38 +02:00
Amaury Levé 3123e607a1 dotnet-test: add explicit non-.NET guards to 5 skill descriptions (#705)
* dotnet-test: add explicit non-.NET guards to 5 skill descriptions

Five skills in plugins/dotnet-test have language-neutral trigger phrases
in their USE FOR sections that could plausibly mis-route on non-.NET
prompts in mixed-language workflows:

- writing-mstest-tests ("write unit tests for a class", "create test class")
- test-anti-patterns ("audit my tests", "test smell audit")
- assertion-quality ("identify assertion-free tests")
- test-gap-analysis ("find weak tests", "discover untested edge cases")
- test-tagging ("categorize, audit, or label tests with traits")

Each skill now has an explicit non-.NET exclusion clause in its
DO NOT USE FOR section, naming the most common languages it must NOT
match (Python, JS/TS, Go, Java, Rust, Ruby, PHP, Swift, Kotlin) and
restating that the skill only handles C#/F#/VB.NET test code.

This was surfaced by an MSBench investigation comparing a baseline
Copilot CLI run vs the same run with this pruned dotnet-test plugin
installed against the sweatlas-tw-unit benchmark (24 Python / 15 Go /
5 TS, 0 .NET). Both runs scored identically (15/44 resolved). Skills
correctly never fired (0 invocations across all 43 instances), so this
is a hardening change, not a bug fix — it makes the router's job easier
in heterogeneous repos and future benchmarks.

Validated with: dotnet run --project eng/skill-validator/src/SkillValidator.csproj -- check --plugin plugins/dotnet-test

Co-authored-by: Copilot <223556219+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>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 10:21:13 +02:00
Amaury Levé 4f78daf583 run-tests: add platform-detection keywords for activation (#700)
* run-tests: add platform-detection keywords for activation

The 'Detect test platform from Directory.Build.props' eval scenario
regressed from 2.7/5 to 2.0/5 with run-tests not activated (skill
loaded column shows NOT ACTIVATED). The scenario prompt asks 'figure
out which test platform it uses' but the previous description framed
detection only as 'chooses the correct platform/SDK/framework syntax'
and 'selecting VSTest vs Microsoft.Testing.Platform command syntax' --
both focused on syntax selection, not on platform detection from
project files.

Per InvestigatingResults.md guidance for 'skill not activated'
failures, surface the detection use case explicitly with the file
names the scenario hinges on:

  detecting test platform/framework from \global.json\, \.csproj\,
  \Directory.Build.props\

Trim the syntax clause ('command syntax' -> 'syntax', 'including' ->
'incl.') and shorten the multi-TFM example (drop redundant
\dotnet test\ prefix) to stay under the 1,024-char description cap.

Folded description: 948 -> 1,010 chars.

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

* run-tests: rephrase platform detection with prompt-shaped language

The previous fix (021b0a343) activated the Detect test platform from
Directory.Build.props scenario in isolated mode but plugin-mode activation
still failed (1.3/5 → 1.7/5, isolated ✅ / plugin ⚠️ NOT ACTIVATED).

The scenario prompt asks the agent to `figure out which test platform`
a project uses, but the description used `detecting test
platform/framework` — the router did not bridge these phrasings when
competing sibling skills were loaded in plugin mode.

Changes:

- Replace `detecting test platform/framework from \global.json\...\` with
  `figuring out which test platform (VSTest vs Microsoft.Testing.Platform)
  a project uses from \global.json\, \.csproj\, \Directory.Build.props\
  and selecting the matching syntax\\. This mirrors the prompt verb
  `figure out\\ and merges the two adjacent clauses (detection +
  selection) into one stronger USE FOR entry.

- Trim verbose tokens elsewhere to stay within the 1024-char folded
  description cap (\SkillProfiler.cs\ MaxDescriptionLength): `TRX and
  other reporting` -> `TRX/reporting`, `writing or generating` ->
  `writing/generating`, `CI/CD pipeline configuration` -> `CI/CD
  config`, drop `e.g., ` from the VSTest/MTP mixups list.

Folded description length: 1010 -> 1007 / 1024.

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

* run-tests: lead description with platform detection as primary value

Plugin-mode activation still failed after the second iteration (2.0/5 →
2.3/5, isolated activates / plugin does NOT). Eval artifact analysis
(run 26581320083) shows the plugin agent actually correctly read
`Directory.Build.props` and identified MTP (rubric: 5/5 + 5/5 on
detection), but did NOT load the skill — so it missed the SDK 9 MTP
`--` separator rule and integration-test filtering (rubric: 1/5 + 1/5
on syntax), capping the score at 2/5.

The router declined to load the skill because the prior opening
sentence `Runs .NET tests with \dotnet test\ and chooses the correct
platform/SDK/framework syntax\\ sounded like base knowledge — the model
felt it could answer `run dotnet test` directly. The detection clause
was buried as the 2nd item in USE FOR, where the router did not weight
it strongly enough.

This rewrite leads the description with platform detection as the
primary value proposition:

  `For \dotnet test\: figures out which test platform (VSTest vs
  Microsoft.Testing.Platform) a project uses from \Directory.Build.props\,
  \global.json\, and \.csproj\, then picks the matching command
  syntax.\\

Other changes:

- Add a parallel USE FOR entry `identifying the test runner/platform
  from project files\\ to widen verb/noun coverage (`figures out` /
  `identifying`, `platform\\ / `runner`) for prompt phrasings the
  router may otherwise miss.

- Promote `\--\ separator rules on .NET SDK 8/9 vs 10+\\ from a
  parenthetical aside to a standalone USE FOR entry so it shows up as
  distinct specialized knowledge.

- Drop redundant `and selecting the matching syntax\\ since it is now
  in the opening sentence.

Folded description length: 1007 -> 994 / 1024. `skill-validator check`
green.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-28 21:28:08 +02:00
Tom Longhurst 36209c3b52 TUnit Fixes & Improvements (#677)
* Update target framework to net10.0 and upgrade TUnit package to version 1.45.8

* Fix and expand TUnit coverage in dotnet-test-frameworks reference

Cross-referenced against tunit.dev/llms.txt and the official attributes
comparison page. Corrects the test class marker (TUnit is convention-based,
not [ClassDataSource]), and fills in the previously-missing TUnit rows for
the assertion APIs, setup/teardown methods, exception-handling examples,
and integration test category marker.

* Refine TUnit assertion table accuracy

The Type row's TUnit cell now uses IsAssignableTo<T>() to match the
assignable-type semantics of the MSTest/xUnit/NUnit equivalents, with a
note pointing at IsTypeOf<T>() for exact-type checks. The Skip row now
documents that [Skip] also applies at class and assembly scope and that
Skip.Test("reason") handles dynamic in-test skipping.

Verified against the TUnit migration guides and the type-assertions docs.

* Spell out TUnit assertion alternatives as complete awaited expressions

The Boolean, Null, Exception, and Type rows in the assertions table
previously used a `await Assert.That(x).IsTrue()` / `.IsFalse()` shorthand
for the alternative form. A reader copy-pasting just the second fragment
would end up with an un-awaited assertion that silently passes — which
contradicts the note immediately below the table about always awaiting.
Each alternative is now a complete, independently copy-pasteable expression.

Addresses the inline review on dotnet/skills#677.

---------

Co-authored-by: Amaury Levé <amauryleve@microsoft.com>
2026-05-28 15:30:29 +02:00
Amaury Levé ac653c62e4 dotnet-test: add cross-language edit-boundary rules to code-testing-implementer (#689)
The code-testing-* agent family generates tests for 12 languages (not just
.NET). Until now, no instruction told the implementer to keep its changes
additive: it would routinely modify existing test files non-additively
(deleting/reformatting lines) or edit non-test production code to make
something easier to test. Both behaviors cause the change to be rejected
by:

- the msbench 'simple' test verifier (any 'dels > 0' on a test file, or
  any change to a non-test file, sets reward=0)
- most real-world test-quality gates, code-review policies, and CI

Add explicit cross-language rules in the implementer agent prompt:

1. Existing test files are append-only (no reformat/reorder/remove).
2. Do not modify non-test source files; surface untestable seams as
   follow-ups for the testability-migration agent.
3. Prefer new test files over edits to existing ones when equivalent.
4. Build-system manifests may be edited only for project/dependency
   registration.

Rule 6 in the Rules section now points at the Step 4 detail so the
implementer reads it on every phase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-27 09:42:22 +02:00
Javier Calvarro Nelson 198e58c983 Add blazor skills to dotnet-blazor plugin (#357)
* Add dotnet-blazor plugin and convert-blazor-server-to-webapp skill

Add the dotnet-blazor plugin with 9 skills covering Blazor Web App development:
- plan-ui-change: Plan and scaffold UI features in Blazor Web Apps
- create-blazor-project: Create new Blazor projects with proper render mode setup
- author-component: Author Razor components with parameters, events, lifecycle
- coordinate-components: Share state across components using CascadingValueSource/scoped services
- use-js-interop: Call JavaScript from Blazor and vice versa
- fetch-and-send-data: HTTP data access with proper service patterns
- configure-auth: Set up ASP.NET Core Identity and authorization in Blazor
- collect-user-input: Build forms with EditForm, validation, and file uploads
- support-prerendering: Handle prerendering lifecycle and state persistence

Add convert-blazor-server-to-webapp skill to the dotnet-aspnet plugin for
migrating .NET 7 Blazor Server apps to .NET 8+ Blazor Web App architecture.

All 10 skills pass evaluation with quality improvements ranging from 12-50%
and overfitting scores within acceptable thresholds.

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

* Update eng/allowed-external-deps.txt

* Update .gitignore

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 16:25:27 +00:00
YuliiaKovalova da5e63e878 [dotnet-msbuild] Fix AP-13/AP-14 false positives and add source-vs-packed layout guidance (#687)
* [dotnet-msbuild] Fix AP-13/AP-14 false positives and add source-vs-packed layout guidance

The msbuild-quality-review run on microsoft/testfx surfaced two confidently-stated
false positives that the maintainer rightly pushed back on:

1. The reviewer claimed unguarded `<Import>` forwarders in MSTest's NuGet
   `build/<tfm>/` folders point at non-existent paths under `buildTransitive/<tfm>/`.
   In reality those folders are produced at pack time by the `.nuspec` `<file
   target="...">` mappings, so the forwarders resolve correctly in every restored
   package.

2. The reviewer flagged backslashes in `<Import Project="...\...\...">` as a
   cross-platform 🔴 error. MSBuild's evaluator normalizes `\` to `/` on
   Unix-like systems via `FileUtilities.MaybeAdjustFilePath` /
   `ConvertToUnixSlashes` before resolving the path, so existing backslash-style
   imports work everywhere — confirmed by years of shipping MSTest to Linux/macOS
   users.

This change updates the rubric so the same false positives don't recur across
every consumer of the dotnet-msbuild plugin:

* `msbuild-antipatterns/SKILL.md` AP-13 — adds an explicit "NuGet package
  forwarders" exception and tells reviewers to consult `.nuspec` /
  `<PackagePath>` before flagging.
* `msbuild-antipatterns/SKILL.md` AP-14 — rewritten to distinguish where
  backslashes are a real bug (raw `<Exec>` shell strings, CDATA, non-MSBuild
  consumers — keep 🔴) from where they're only style (`<Import>` and other
  evaluator-routed paths — 🔵 with a cite to the MSBuild source).
* `extension-points/SKILL.md` — adds a "Source Tree vs Packed Layout" section
  documenting the three packaging mechanisms (.nuspec `<file>` mappings, csproj
  `<PackagePath>` metadata, SDK pack conventions) that legitimately reshape the
  layout, with the cross-check procedure reviewers must run before flagging
  "missing-file" imports.
* `agents/msbuild-code-review.agent.md` — Discovery now records the projected
  packed layout; Category 4 references the new AP-13/AP-14 nuances; new
  "Veracity gate" step downgrades or drops 🔴 findings that would imply
  currently-shipping CI is broken.

No fixtures change: the `tests/dotnet-msbuild/msbuild-antipatterns/eval.yaml`
rubric does not enumerate AP-13/AP-14 by id, and the F#-specific scenarios are
unaffected. Markdownlint passes on all edited files.

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

* Address PR review feedback

- extension-points: rewrite .nuspec example so the source file is genuinely shared (single buildTransitive/common/MyAdapter.props fan-out instead of three already-per-TFM sources); clarify <file target=> folder-vs-rename semantics.
- extension-points: replace semicolon-list PackagePath example with the unambiguous multi-<None> form, and note in prose that semicolon syntax is also supported. Avoids reader confusion noted in review.
- msbuild-antipatterns AP-13 cross-check: align search scope with extension-points (project directory AND any parent directory) so reviewers don't miss shared mono-repo nuspecs.

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

* AP-13: drop ../ link to extension-points to satisfy skill-validator

Skill-validator rejects file references that traverse out of the skill directory (parent-directory traversal). Replace the markdown link with a plain-text reference to the dotnet-msbuild/extension-points skill — the prose is still discoverable to humans and to the agent that loads the plugin, but no longer trips the validator.

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

* Address second round of PR review feedback

- AP-13: replace <tfm> placeholders inside XML attribute strings with concrete TFM examples (net8.0) so the snippets are valid copy-pasteable XML.
- AP-13 & extension-points: bound the .nuspec search to project directory + IMMEDIATE parent only (no unbounded walking); wording now identical in both docs.
- AP-14: add explicit text severity next to severity emoji (🔴 Error / 🔵 Style) for accessibility — screen readers and plain-text copies now convey severity without relying on color/emoji rendering.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 16:08:01 +00:00
Amaury Levé ca21fd61c1 run-tests: prompt-shaped multi-TFM keywords for plugin activation (#688)
* run-tests: use prompt-shaped multi-TFM keywords for plugin activation

The 'Run tests in a multi-TFM project targeting a specific framework' eval

scenario kept failing plugin-mode activation after #667. The skill description

had 'multi-TFM projects (--framework)' as a brief parenthetical, but the

scenario prompt uses different language: 'This test project targets both

net8.0 and net9.0. I only want to run the tests on net9.0 using dotnet test.'

Per the InvestigatingResults.md guidance for 'skill not activated' failures,

expand that clause to include keywords from the prompt — 'running tests

against a single target framework when a project targets multiple TFMs'

plus a concrete '<TargetFrameworks>net8.0;net9.0</TargetFrameworks>' example

and the '--framework <TFM>' invocation. Per-skill description is 947 chars,

well under the 1024 spec cap.

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

* Replace simple multi-TFM scenario with a harder MTP+SDK 9 variant that requires skill knowledge

The previous 'Run tests in a multi-TFM project targeting a specific
framework' scenario tested a trivial prompt (single --framework flag)
that the model already answers perfectly from training (baseline 4.7/5).
This matches pattern #8 (baseline already good, no headroom) in
InvestigatingResults.md, and explains why two prior attempts to fix
plugin-mode activation via description tweaks (PR #667, #688) failed:
the router rationally skips loading the skill for a trivial question.

This change replaces the scenario with a meaningfully harder one that
combines several signals the model often confuses:

  - Multi-TFM project (TargetFrameworks plural)
  - MTP runner (TestingPlatformDotnetTestSupport)
  - .NET SDK 9 (-- separator required for MTP extension args)
  - TRX report (MTP extension flag)

The correct answer requires knowing that --framework is a dotnet
test/MSBuild flag that always goes BEFORE --, while --report-trx is an
MTP extension flag that goes AFTER -- on SDK 9:

  dotnet test --framework net9.0 -- --report-trx

The ordering assertion in eval.yaml enforces this on a single line, so
swapping --framework after the separator no longer satisfies the
scenario.

Also fix a documentation bug in SKILL.md surfaced by this work: the
'Common MTP flags > Built-in flags' table previously listed --framework
and --no-build under 'On SDK 8/9, pass after --', which is wrong. Those
are dotnet test/MSBuild flags consumed by dotnet test itself; they
always go before --. The table now lists only flags genuinely consumed
by MTP, and an Important note clarifies the rule.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 17:57:21 +02:00
Amaury Levé 5810d492c9 test-anti-patterns / test-smell-detection: narrow-specialist re-pitch (Variant B) (#671)
Both skills suffer plugin-mode activation failures: in plugin runs the model

bypasses the skill tool entirely for ~5/6 of test-anti-patterns audit prompts

and ~2/3 of test-smell-detection prompts, answering directly from training.

Variant B repositions the two skills as umbrella + narrow specialist:

* test-anti-patterns becomes THE umbrella audit skill for all pragmatic

  test-quality reviews (anti-patterns and smell-style prompts alike). Its

  description explicitly absorbs smell-audit triggers.

* test-smell-detection is repositioned as a narrow niche that only fires

  when the user explicitly asks for the testsmells.org / academic 19-smell

  catalog with citable smell names from the research literature.

Eval prompts for test-smell-detection are rewritten to match the narrow

niche (explicit testsmells.org / 19-smell catalog requests) so we test

specialist activation rather than the umbrella scenarios.

Variant B of a 3-PR experiment to fix activation. Companion PRs:

* Variant A = activation-only rewrite, both skills keep overlap;

* Variant C = full merge into test-anti-patterns.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-25 13:18:17 +00:00
Amaury Levé 362b3f25ec Fix plugin-mode skill activation for 8 dotnet-test scenarios (#667)
* migrate-vstest-to-mtp: fix plugin activation for OutputType=Exe scenario

The `Set OutputType=Exe only for test projects in Directory.Build.props`
scenario was failing plugin-mode skill activation (skillActivationPlugin.
activated=false, detectedSkills=[]) in the latest scheduled eval. The
model answered from its own knowledge and proposed the wrong solution
(`Condition="'$(IsTestProject)' == 'true'"` in Directory.Build.props,
which the skill explicitly warns against).

Two fixes:

1. SKILL.md description: add an explicit `conditioning OutputType=Exe to
   test projects when centralizing MTP properties in Directory.Build.props`
   USE FOR clause so the description surfaces this specific MTP migration
   pitfall to the skill router. Per-skill description stays at <= 1024
   chars (trimmed `configuration` -> `config` and `MSTest version
   upgrades (use migrate-mstest-* skills)` -> `MSTest version upgrades`
   to keep within the spec limit).

2. eval.vally.yaml: add the missing scenario (the eval.yaml scenario was
   added in PR #556 but vally was never synced — vally had 10 stimuli vs
   eval.yaml's 11). Brings vally and skill-validator coverage to parity.

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

* test-anti-patterns: strengthen description for severity-ranked audits

The `Detect mixed severity anti-patterns in repository service tests`
scenario was failing plugin-mode skill activation
(skillActivationPlugin.activated=false, detectedSkills=[]) in the latest
scheduled eval, even though the prompt explicitly says `Audit the test
class ... for .NET test anti-patterns ... Give me a severity-ranked
list (Critical / Warning / Info)`.

The previous description only mentioned `USE FOR: audit test quality,
review test code, find test anti-patterns, ...`, so the model could not
distinguish this skill from sibling test-quality skills based on the
`severity-ranked` and `Critical/Warning/Info` framing in the prompt.
Surface the catalog shape (severity-ranked output, concrete code-level
fixes) and add explicit `severity-ranked test audit`, `self-comparing
assertions` and `broad exception types` triggers — these are the
exact phrases used by failing scenarios.

Description stays at 822 chars (<= 1024 limit). Aggregate dotnet-test
description stays at 15,099 chars (<= 20,000 limit).

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

* run-tests: restructure description for higher-signal plugin activation

Six run-tests scenarios were failing plugin-mode skill activation in the
latest scheduled eval (skillActivationPlugin.activated=false,
detectedSkills=[]) even though isolated activation worked for every
scenario:

- Run tests with trx reporting on MTP project (SDK 9)
- Run tests in a multi-TFM project targeting a specific framework
- Filter MSTest tests by category on VSTest
- Filter NUnit tests by class name on VSTest
- Filter TUnit tests by class using treenode-filter
- Negative test: do not use MTP syntax for a VSTest project

The previous description piled ~30 quoted trigger phrases (`run tests`,
`run my tests`, `run these tests`, `execute tests`, `dotnet test`,
`test filter`, `filter by category`, `filter by class`,
`combine filters`, `run only specific tests`, `integration tests`,
`unit tests`, `tests not running`, `hang timeout`, `blame-hang`,
`blame-crash`, `crash dump`, `TRX report`, `TRX`, `test report`,
`generate TRX`, `TUnit`, `treenode-filter`, `target framework`,
`multi-TFM`, ...). In plugin mode this signal-poor keyword wall made
the skill look generic enough that the router preferred to answer
directly from model knowledge.

Replace the keyword pile with five higher-signal scope clauses grouped
by user-visible concern:

1. running, filtering, or troubleshooting `dotnet test`
2. VSTest vs Microsoft.Testing.Platform syntax (incl. `--` separator
   rules on SDK 8/9 vs 10+)
3. framework-specific filter syntax for MSTest / xUnit / NUnit / TUnit
   (--filter, --filter-class, --filter-trait, --filter-query,
   --treenode-filter)
4. TRX/reporting (--report-trx vs --logger trx), blame/hang/crash
   diagnostics, multi-TFM (--framework)
5. avoiding MTP/VSTest argument mixups

These are the same concerns the previous description tried to cover,
but framed as decisions the skill helps make (and that distinguish it
from sibling test skills) rather than as a list of bare keywords.
Per-skill description shrinks from 1,000 to 819 chars (still <= 1,024
limit). Aggregate dotnet-test description stays well under the
20,000-char cap.

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

* test-anti-patterns: drop specific severity labels from description

PR review (copilot-pull-request-reviewer on #667) caught that
`Produces a severity-ranked (Critical / Warning / Info) catalog ...`
in the new description contradicts the SKILL.md body, which actually
teaches a 4-level Critical / High / Medium / Low taxonomy. The
`Critical / Warning / Info` wording came from one eval scenario's
prompt, but other prompts ask for different bucket schemes, and the
skill itself does not enforce a fixed three-level mapping.

Drop the specific labels from the description and keep just
`severity-ranked` as the activation signal. The body remains
unchanged (it teaches Critical / High / Medium / Low and the agent
maps to the prompt's requested buckets at output time).

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 13:44:40 +02:00
Amaury Levé b24599aa36 test-smell-detection: trim to detailed tier and add prompt-shaped triggers (#653)
Multi-model skill-validator eval (claude-haiku-4.5, claude-opus-4.6,

gpt-5.3-codex, gpt-5.4-mini) showed two issues with this skill:

1. Quality regression on stronger models (+0.15 haiku, -0.14 opus,

   -0.17 codex, -0.29 gpt-5.4-mini): the skill added tokens and tool

   calls without lifting rubric quality on larger models.

2. Plugin-mode activation loss: the skill activated reliably in

   isolated mode but was almost never picked in plugin mode where it

   competed with siblings (code-testing-agent, etc.).

Changes:

- Trim BPE tokens 2,487 -> 1,472 (still detailed tier, well within

  the 800-2,500 sweet spot per SkillsBench guidance). Collapsed long

  smell-by-smell prose, `Why Test Smells Matter`, and pitfalls into a

  compact taxonomy table plus a short decision procedure / output

  checklist. Removed bulky examples. Kept taxonomy, calibration,

  negative guidance, and references intact.

- Add prompt-shaped USE FOR triggers drawn from the eval prompts

  (`review test smells`, `review these tests and tell me if there are`

  `any problematic patterns`, `check my tests for test design`

  `problems or anti-patterns`, `give us an objective assessment of`

  `our integration tests`, plus explicit smell names).

- Strengthen DO NOT USE FOR clause: `write new tests / scaffold tests`

  `from scratch / generate a complete MSTest test suite` now defers

  cleanly to code-testing-generator (covers the negative eval scenario).

Validation: skill-validator check --plugin clean for this skill;

build + 545/545 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 13:42:13 +02:00
Jan Krivanek 0724ccf8ac Update binlog mcp name (#684) 2026-05-22 13:48:09 +00:00
Jan Krivanek 1a6e78c9c6 Add binlog MCP usage to other msbuild skills/agents (#683)
* Add binlog MCP usage to other msbuild skills/agents

* Apply suggestions from code review

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-22 15:32:31 +02:00
YuliiaKovalova 5f1170152b Add MSBuild target authoring skills (target-authoring, property-patterns, item-management, extension-points) (#669)
* Add 4 MSBuild target authoring skills for dotnet-msbuild plugin

New skills:
- target-authoring: three-level target chain, DependsOn extension, naming conventions
- property-patterns: conditional defaults, composition, path normalization, TFM helpers
- item-management: Include/Remove/Update, batching, transforms, FileWrites registration
- extension-points: CustomBefore/After hooks, import gating, NuGet build extensions

Each skill includes eval.yaml tests with anti-pattern fixtures.

Closes #668

* Address Copilot review feedback

- target-authoring: Reword DO NOT USE clause to exclude only deep
  incremental-build diagnostics, not basic Inputs/Outputs usage
- property-patterns: Close unclosed XML elements in String Functions
  snippet (PropertyGroup, TargetFrameworkMoniker)
- extension-points: Add missing CustomAfterMySDK property definition
  to match the import at bottom of example

* Remove accidental pr-body.md file

* Fix wildcard import placeholder path and quote NormalizePath args

- extension-points: Use full MSBuildExtensionsPath expression and
  consistent Exists() casing in wildcard import example
- property-patterns: Quote property arguments in NormalizePath call

* Tune eval prompts to reduce overfitting

Rewrite all 4 eval prompts as natural developer problem descriptions
instead of skill-aligned checklists. Softens technique-prescriptive
rubric items. Result: overfitting scores drop from 0.15-0.31 to
0.06-0.08 (all green). property-patterns now passes eval.

* Fix Copilot review round 3: quote property function args, fix fixture

- property-patterns: Quote  in IsPathRooted call
- extension-points: Quote  in GetDirectoryNameOfFileAbove
- item-management fixture: Use literal semicolon instead of %3B in WriteLinesToFile

* Add harder multi-file eval scenarios for all 4 skills

Each skill now has a second scenario with multi-file setups containing
interacting bugs that require cross-file analysis:

- target-authoring: SDK .targets + Directory.Build.targets with 3 bugs
  (target redefinition, fragile BeforeTargets, duplicate DependsOn chain)
- property-patterns: nested Directory.Build.props with 5 bugs
  (import order, unconditional overwrite, unquoted condition, missing
  trailing slash, NoWarn overwrite)
- item-management: csproj with 5 interacting bugs (Include vs Update,
  cross-product batching, eval-time FileWrites, too-broad Remove glob)
- extension-points: Directory.Build.props/targets + NuGet package with
  6 bugs (inverted guard, late ImportByWildcard, CustomBefore overwrite,
  missing Exists guard, target name collision, internal target hook)

Timeouts increased to 180s for all scenarios.

* Fix review round 4: revert unintended README change, quote intrinsic call in condition

* Improve eval quality for 4 new MSBuild authoring skills

Eval improvements across target-authoring, property-patterns,
item-management, and extension-points skills:

- Rewrite prompts to describe observable symptoms without naming
  MSBuild concepts, inspired by real dotnet/msbuild and dotnet/sdk
  issues (msbuild#2470, #12894, #13056, #4109, sdk#43908)
- Broaden assertion regex patterns to test for diagnostic outcomes
  rather than skill-specific vocabulary
- Improve rubric items to test understanding and diagnosis flow
  (diagnosis -> root cause -> fix) instead of skill terminology
- Add task-completion 'fix it' scenario to each skill with
  file_contains assertions that verify the agent applied correct
  patterns (CompileDependsOn append, FileWrites, Exists guard, etc.)
- Remove leading 'Anti-pattern:', 'BUG N:' comments from fixture
  files that were giving away answers to the baseline agent, making
  scenarios more realistic and better at measuring skill value

Each skill now has 3 scenarios: basic review, hard multi-file review,
and a task-completion fix scenario. Total: 12 scenarios across 4 skills.

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

* Fix review comments: quote TFM intrinsic, fix PrivateAssets example

- property-patterns SKILL.md: Quote the GetTargetFrameworkIdentifier
  intrinsic call result in the Condition to match the 'always quote
  both sides' guidance and avoid brittle parse when empty
- item-management SKILL.md: Replace PackageReference Update on
  Microsoft.NETCore.App (not a real user-added item) with Include
  on Microsoft.CodeAnalysis.NetAnalyzers (a concrete analyzer package)

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

* Fix eval activation and timeouts based on eval run results

- Add MSBuild domain terms to prompts (e.g., 'MSBuild targets',
  'MSBuild property patterns', 'MSBuild item groups', 'MSBuild
  extension points') to improve skill activation rates — skills
  were NOT ACTIVATED in plugin mode due to prompts being too
  symptom-focused without domain keywords
- Increase timeouts: review scenarios 180s -> 240s, fix-it
  scenarios 180s -> 300s to avoid timeout-related scoring penalties
- Keep prompts symptom-driven but include enough domain context
  for the skill router to activate the correct skill

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

* Fix PR review comments and improve eval quality

Review comment fixes:
- TargetAuthoring.csproj: Replace %22/%3B URL encoding with XML
  escaping (&quot;/;) so generated C# code is valid
- target-authoring eval: Fix prompt referencing 'schema files' when
  fixture has endpoint definitions — now says 'endpoint list'
- property-patterns eval: Reword LangVersion rubric — unconditional
  assignment in .props IS overridable by csproj but prevents override
  from earlier imports and command-line properties
- extension-points eval: Add stronger activation terms to Fix scenario
  prompt (explicit mention of CustomBeforeMicrosoftCommonTargets)

Eval quality improvements based on CI results:
- Shorten target-authoring rubric items to reduce overfitting (was 0.30)
- Remove 'Focus on target authoring patterns' instruction from hard
  scenario prompt (was directing agent too specifically)

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

* Improve eval: increase timeout, add activation keywords, explicit fix instructions

- property-patterns 'Diagnose multi-level': timeout 240s -> 360s (was hitting limit at 249s)
- target-authoring 'Diagnose custom target': add CompileDependsOn/incremental build keywords for better skill activation
- property-patterns 'Fix': add 'edit ... directly' to prompt to encourage file edits
- target-authoring 'Fix': add 'edit ... directly' to prompt
- item-management 'Fix': add 'edit ... directly' to prompt

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

* Fix target-authoring skill description and eval prompts for plugin activation

The skill description said 'DO NOT USE FOR: deep incremental-build diagnostics'
which caused the plugin agent to skip it for scenarios about build regressions.
Clarified that the skill IS for diagnosing target authoring mistakes (missing
Inputs/Outputs, broken dependency chains) that cause full rebuilds.

Also updated eval prompts to use 'target authoring mistakes' framing and
increased Fix scenario timeout to 360s.

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

* Increase eval timeouts: extension-points NuGet (240->360s), item-management cascading (240->360s)

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

* Fix 3 fresh PR review comments + update eval prompts for target-authoring

- property-patterns/SKILL.md: add warning that TargetFramework-conditioned
  PropertyGroups must be in .targets not .props (empty in single-target .props)
- extension-points/SKILL.md: add Exists() guard to GetPathOfFileAbove Import
  to prevent build failure when no parent file is found
- target-authoring/SKILL.md: fix comment mismatch — validation target runs
  via dependency chain, not BeforeTargets; update comment accordingly
- target-authoring/eval.yaml: reframe 'Diagnose' and 'Fix' prompts to use
  'dependency chain' / 'authoring patterns' language (avoids routing to
  incremental-build skill which also claims Inputs/Outputs diagnostics)

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

* Improve skill descriptions for reliable plugin-mode activation

Add 'Only activate in MSBuild/.NET build context.' prefix to all 4 skills
for consistency with existing skills in the plugin.

Add explicit 'diagnosing and fixing' and 'reviewing' keywords to USE FOR
sections so the SDK selects these skills over the broader
msbuild-antipatterns skill when prompts ask to fix or review specific
item/extension/property/target patterns.

Add 'general MSBuild anti-pattern catalog (use msbuild-antipatterns)' to
DO NOT USE FOR sections to help the SDK disambiguate.

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

* Fix skill descriptions: shorten to under 1024-char SDK limit

All 4 new skills had descriptions exceeding the 1024-character maximum
enforced by the skill-validator check command. The Copilot SDK silently
ignores skills with over-length descriptions, causing 0% activation in
both isolated and plugin evaluation modes.

Shortened all 4 descriptions while preserving key activation keywords
(USE FOR / DO NOT USE FOR / 'Only activate in MSBuild/.NET build context').

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

* Address PR review comments

- target-authoring eval.yaml: fix prompt to say 'Outputs attribute' (not
  'Returns') since the fixture uses Outputs on a query target, which is
  the actual bug that causes MSBuild to skip re-execution
- property-patterns eval.yaml: reword prompt and rubric — the real issue
  is unconditional assignment breaking parent-child Directory.Build.props
  inheritance, not project files being unable to override properties
- extension-points SKILL.md: fix GetPathOfFileAbove example to factor
  the path into a property so Project= and Condition= use the same value
  consistently (avoiding the ..\\ vs ..\ discrepancy)
- CustomSdk.targets: add WriteLinesToFile to CoreCodeGen so it actually
  creates the .g.cs output files (prevents compilation failure in fixture)

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

* Fix property-patterns fixtures to match rubric claims

Scenario 1 (path merge bug):
- PropertyPatterns.csproj: add OutputPath using CustomOutputDir without a
  trailing separator, making the merge bug observable
  (artifacts\binPropertyPatterns\ instead of artifacts\bin\PropertyPatterns\)

Scenario 2 (multi-level hierarchy bugs):
- hard/Directory.Build.props: make LangVersion unconditional so it
  overwrites the child src/Directory.Build.props LangVersion=preview,
  matching the rubric claim about parent unconditional assignments
- hard/Directory.Build.props: add NoWarn=NU1702 (conditional default)
  so parent suppressions are visible but lost when the child's
  unconditional <NoWarn>CS1591;IDE0005</NoWarn> overwrites them after import

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 09:39:23 +00:00
Sayed Ibrahim Hashimi 3b0ece94ad Add web api skill and tests (#613)
* adding web api skill and tests

* fixing link

* Potential fix for pull request finding

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-21 09:51:05 -07:00
Jan Krivanek e951d69ab9 dotnet-msbuild: move AITools.BinlogMcp source to dotnet-tools feed (#680)
The MCP package was relocated from the dotnet-eng public feed to the dotnet-tools public feed on dnceng. Update plugin.json --add-source URL and the SKILL.md fallback note accordingly.
2026-05-21 13:14:51 +02:00
Jason Malinowski e2dc44c377 Bump our warmup timeout to something higher (#666)
30 seconds is the default, but a bit higher has a chance of completing
for more users successfully.
2026-05-19 16:58:04 -07:00
David Wengier c1f9e820a1 Add LSP support for .razor and .cshtml file extensions (#644)
The roslyn-language-server package includes the Razor LSP bits now
2026-05-19 17:48:52 -04:00
Jan Krivanek dfc8aa786d dotnet-msbuild: register AITools.BinlogMcp and use it from binlog-failure-analysis (#673)
* dotnet-msbuild: register AITools.BinlogMcp and use it from binlog-failure-analysis

Adds the AITools.BinlogMcp MCP server (pulled via dnx from the dotnet-eng public NuGet feed, prerelease, no version pin) to the dotnet-msbuild plugin and rewrites the binlog-failure-analysis SKILL.md to lead with the MCP tools (binlog_overview, binlog_errors, binlog_search, binlog_items, binlog_properties, binlog_imports, binlog_nuget). The text-log replay workflow is kept as a fallback for environments without the MCP.

* Improve skills

* Reflect PR comments
2026-05-19 19:45:34 +02:00
Jan Krivanek 2fcfc099b9 Improve direct scenario (#675) 2026-05-19 19:34:29 +02:00
Amaury Levé dde9f99cf0 dotnet-test: drop tools field from agents that declared it (#665)
The four agents (code-testing-generator, test-migration, testability-migration,
test-quality-auditor) were the only dotnet-test agents declaring a 'tools:'
list. Per Jan's suggestion on #660, drop the field so they inherit the runtime's
default tool surface (matching the convention used by every other agent in the
repo).

Follow-up to #660.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 14:47:00 +02:00
Amaury Levé 2a193300ca Replace 'terminal' with 'bash' and 'powershell' in agent tools (#660)
The skill-validator only recognizes 'bash' and 'powershell' as built-in shell tools, not 'terminal'. Update the four affected agents in the dotnet-test plugin to use both for cross-platform support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 13:39:33 +02:00
Amaury Levé b0c2336d49 Tighten crap-score boundary to fix coverage-analysis plateau activation (#652)
Dashboard data showed coverage-analysis failing to activate in 8/10
recent scheduled plugin-mode runs for the 'Coverage plateau diagnosis'
scenario, while activating reliably in isolated mode. PR #647 added
positive triggers to coverage-analysis but did not address sibling
attention competition.

The crap-score description matched the plateau prompt almost as well as
coverage-analysis (it advertised 'evaluate whether complex methods have
sufficient test coverage' + 'Requires code coverage data (Cobertura
XML)') without redirecting project-wide / stuck-coverage diagnosis to
coverage-analysis. With 22 sibling skills competing for attention this
overlap is enough to suppress activation altogether.

Tighten the crap-score frontmatter to:
- Scope positive triggers to a named method, class, or single source
  file (the actual eval surface — see tests/dotnet-test/crap-score/
  eval.yaml, all 3 scenarios target OrderService.cs).
- Add explicit DO NOT USE FOR redirects covering project-wide coverage
  analysis, coverage plateau / stuck coverage, what's blocking
  coverage, and where to add tests across a project — all of which
  point at coverage-analysis.

skill-validator check passes (22 skills, 11 agents, 1 plugin).
Aggregate dotnet-test description size: 14,932 chars (limit 15,000).
markdownlint passes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 16:24:10 +02:00
Amaury Levé 3d59e44c7e Fix coverage-analysis activation for plateau diagnosis prompts (#647)
* Fix coverage-analysis activation for plateau diagnosis prompts

coverage-analysis SKILL.md:
- Trim verbose implementation details (provider detection,
  ReportGenerator) that consumed description budget without
  aiding skill activation
- Add explicit USE FOR keywords: coverage stuck, coverage plateau,
  can't increase coverage, what's blocking coverage

code-testing-agent SKILL.md:
- Add 'diagnosing coverage plateaus or CRAP score computation
  (use coverage-analysis)' to DO NOT USE FOR boundary to prevent
  test-generation skill from intercepting diagnostic prompts

* Potential fix for pull request finding

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

* Strengthen code-testing-agent activation; harden coverage-analysis isolated mode

Address eval regressions reported on PR #647 (run 25813728646):

1. code-testing-agent: `Generate tests for ContosoUniversity ASP.NET Core MVC app`
   was NOT ACTIVATED in plugin mode (detectedSkills=[], skillEventCount=0,
   invokedAgents=[]). The model bypassed the skill system entirely.

   - SKILL.md description: restructure to use the proven `Use when user says ...`
     pattern with quoted trigger phrases (matching the run-tests skill that
     consistently activates), make the link to the code-testing-generator
     sub-agent explicit, and tighten DO NOT USE FOR clauses.
   - eval prompt (eval.yaml + eval.vally.yaml): make the request
     pipeline-shaped (`project-wide, multi-file test generation task`,
     `scaffold a new test project`) so the model recognizes it as multi-step
     work that benefits from the orchestrated pipeline. Explicitly request
     coverlet.collector + a Cobertura XML run so rubric criterion 1
     (`high line coverage as reported by the Cobertura XML in TestResults/`)
     becomes achievable without overfitting.

2. code-testing-tester agent + code-testing-extensions/dotnet.md: open a
   scoped exception to the `skip coverage tools` rule. Default behavior
   stays the same, but when the user/harness explicitly asks for a
   Cobertura/XML coverage artifact, the agent may add coverlet.collector
   to the generated test csproj so the harness's coverage command produces
   output. The agent still does not run the coverage command itself.

3. coverage-analysis SKILL.md: add a `User-visible output is mandatory`
   guard at the top of the Workflow section. The latest eval showed isolated
   mode producing literally `(no output)` in 2 of 3 scenarios — the agent
   ran Compute-CrapScores.ps1 / Extract-MethodCoverage.ps1 / ReportGenerator
   in parallel, then the session ended without ever surfacing findings.
   The guard tells the agent to always return a partial summary instead of
   ending silent, and to deprioritize ReportGenerator HTML when budget is
   tight. (Plugin-mode quality is already strong: 4.3 / 4.3 / 5.0 — no
   regression risk there.)

Aggregate dotnet-test plugin description size: 14,925 chars (limit 15,000).
skill-validator check passes (22 skills, 11 agents, 1 plugin); markdownlint
passes for all 4 modified files.

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

* Restore MSTest modernization exclusion in code-testing-agent description

* Fix isolated-mode coverage-analysis: emit summary before optional ReportGenerator

The previous workflow encouraged the agent to run `dotnet tool install` for
ReportGenerator in parallel with the CRAP scoring scripts (Phase 2 "Steps
3 and 4 in parallel" + Phase 3 "Steps 5 and 6 in parallel"). In isolated
mode that pattern reliably crashed the session with "Failed to persist
session events: timeout while waiting for mutex to become available"
right after the scripts returned valid data, so the agent never produced
the user-facing summary.

Restructure the workflow into 5 phases:

- Phase 1 (Setup) - unchanged
- Phase 2 (Test execution) - skip when Cobertura XML already exists
- Phase 3 (Analysis) - run only the two PowerShell scripts, no RG
- Phase 4 (User-facing summary) - MANDATORY, must be the next assistant
  response after Phase 3, before any RG work; also save
  coverage-analysis.md as a secondary follow-up
- Phase 5 (ReportGenerator HTML/CSV) - strictly optional, post-summary,
  skipped by default for existing-Cobertura and plateau-diagnosis paths

Also update references/output-format.md so the Reports section marks RG
artifacts as "Not generated (optional - request HTML reports to enable)"
when Phase 5 has not run, and update references/guidelines.md so the
"show and open the markdown report" rule explicitly defers to the
user-facing assistant response.

Targets the isolated-mode regressions in PR #647 eval:
- Project-wide coverage with existing Cobertura: 1.0/5 -> expected 3+
- Coverage plateau diagnosis: 1.0/5 -> expected 3+
- Run coverage from scratch: 2.3/5 -> expected steady or up

Verified: skill-validator check --plugin ./plugins/dotnet-test passes;
markdownlint-cli2 clean on all 3 modified files.

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

* Address PR #647 review comments

1. Prerequisites: distinguish the from-scratch path (needs NuGet for the
   coverage-provider package install + optional internet for ReportGenerator)
   from the existing-Cobertura path (needs neither).

2. Add Step 2c "Discover or accept existing Cobertura XML" so the
   existing-data path actually has $coberturaFiles populated before
   Phase 3, instead of relying on Phase 2's discovery (which it
   skips). Also clarify Step 2's destructive Remove-Item only manages
   the skill-owned coverage-analysis/ subdirectory.

3. references/output-format.md: replace the unconditional
   "Reports saved to: <coverageDir>/reports/" line with one that
   always points at <coverageDir>/ (markdown summary + raw Cobertura)
   and only mentions reports/ if Phase 5 ran.

4. Have Compute-CrapScores.ps1 emit OVERALL_LINE_COVERAGE and
   OVERALL_BRANCH_COVERAGE from the Cobertura root attributes, and
   update Phase 4 to read those values directly from the script's
   output. The Phase 4 mandatory-summary rule no longer requires a
   separate XML parse before composing the response.

Verified: skill-validator check --plugin ./plugins/dotnet-test passes;
markdownlint-cli2 clean on all modified files; Compute-CrapScores.ps1
smoke-tested on a synthetic Cobertura XML (emits OVERALL_LINE_COVERAGE:75,
OVERALL_BRANCH_COVERAGE:50 alongside HOTSPOTS).

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

* Apply suggestion from @Evangelink

* Address unresolved coverage-analysis and eval review comments

* Refine follow-up review feedback from validation

* Tighten coverage aggregation fallback notes and counters

* Clarify pre-response save instruction wording

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-14 17:41:31 +00:00
Amaury Levé 42afc2688d Add Go, Java, Rust, Ruby, Swift, and Kotlin extensions to code-testing-extensions (#650)
* Add Go, Java, Rust, Ruby, Swift, and Kotlin extensions to code-testing-extensions

Adds six new language-specific guidance files to the code-testing-extensions skill, modeled on the existing python.md and typescript.md structure.

Each new extension covers: investigate-first rule, toolchain detection, build commands, test commands (with framework variants), lint command, project layout/imports, common errors with fixes, mocking rules, dependency installation as last resort, and a Skip Coverage Tools footer.

SKILL.md is updated to advertise the new files in the discovery table.

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

* Address review feedback and fix markdownlint issues

- rust.md: replace #  code span (MD038) with quoted text

- java.md: clarify wildcard-import guidance to avoid contradicting the explicit-imports template

- java.md: scope 'class must be public' to JUnit 4 only (JUnit 5 allows package-private)

- java.md: correct Mockito final-class fix to inline mock maker (default in 5+, mockito-inline for 3.x/4.x); remove incorrect mockito-subclass suggestion

- kotlin.md: same Mockito final-class correction

- kotlin.md: replace nonexistent testScheduler.testDispatcher() with StandardTestDispatcher(testScheduler)

- kotlin.md: rephrase coroutines-test dependency guidance to avoid contradiction

- kotlin.md: correct cross-module 'internal' fix; @VisibleForTesting does not widen Kotlin visibility

- ruby.md: replace numbered block parameter '_1' with '|f| require f' (works on Ruby < 2.7)

- swift.md: Swift Testing requires Swift 6/Xcode 16, not 5.10

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 17:51:27 +02:00
Amaury Levé f532cf1d94 Add coverage-touching and self-referential assertion heuristics (#635)
* Add coverage-touching and self-referential assertion heuristics

- test-anti-patterns: add 'Coverage touching' and 'Self-referential assertion'
  as named Critical-severity anti-patterns in the detection catalog
- assertion-quality: add 'Tests with self-referential assertions' metric and
  a calibration rule distinguishing tautological from valid round-trip assertions
- Add eval scenarios for both new heuristics in test-anti-patterns (coverage-
  touching ProductCatalog facade, self-referential SerializerTests)
- Add eval scenario and fixture for self-referential assertions in
  assertion-quality (ConfigTests with identity/round-trip patterns)

* Fix test-anti-patterns activation: rewrite description with USE FOR keyword list

The skill was not activating in any eval scenario because the description
used narrative prose instead of the explicit 'USE FOR:' / 'DO NOT USE FOR:'
keyword list pattern that well-activating sibling skills use (run-tests,
writing-mstest-tests). Restructured the description with trigger phrases
matching common user prompts.

* Fix eval activation, timeouts, and add missing vally scenarios

- test-anti-patterns/eval.vally.yaml: increase timeout 2m→5m, add
  coverage-touching and self-referential scenarios with constraints
- assertion-quality/eval.vally.yaml: add self-referential scenario
  with environment files, broaden assertion pattern
- test-anti-patterns/eval.yaml: add setup.files to all 6 scenarios
  to create workspace files that trigger skill discovery/activation
- assertion-quality/eval.yaml: increase timeouts 120→300 for
  self-referential and decline-request scenarios, broaden
  self-referential assertion pattern
- Create fixture files for mixed-severity, well-written,
  coverage-touching, and self-referential test-anti-patterns scenarios

* Address review comments: fix test names and use source references

- Rename ThrowsArgumentException to ThrowsArgumentOutOfRangeException in
  PaymentProcessorTests.cs fixture and inlined code in eval.yaml and
  eval.vally.yaml to match the actual exception type being asserted.
- Replace inline csproj content blocks with source references to existing
  fixture files for UserRepo, Payments, and CatalogService scenarios in
  eval.yaml to avoid drift between fixtures and eval setup.

* Address review comments: pin MSTest versions, use source refs, fix naming

- Pin MSTest to 3.8.2 in all fixture .csproj files, add standard
  properties (ImplicitUsings, Nullable, IsPackable)
- Replace inline csproj content blocks with source references to
  fixture files to avoid content drift
- Create missing .csproj fixtures for flaky-coupled, duplicate-magic,
  and assertion-quality self-referential scenarios
- Fix test method names: ThrowsArgumentException ->
  ThrowsArgumentOutOfRangeException to match the actual assertion

* Fix activation, eval timeouts, and per-skill description limits

Address remaining issues from PR #635 eval scoreboard
(run 25677669933) and skill-validator failures:

1. test-anti-patterns activation (was NOT ACTIVATED in BOTH plugin and
   isolated mode for ALL 6 scenarios — model answered everything from
   inline code without ever needing the skill):

   - eval.yaml + eval.vally.yaml: drop the giant inline `csharp` blocks
     from every prompt. Each prompt now names the workspace files
     explicitly (`Audit `Foo.Tests/FooTests.cs` for .NET test
     anti-patterns ...`) and asks for the skill's signature deliverable
     (severity-ranked list with concrete code-level fixes). The model
     must read the workspace, which gives it a chance to consult the
     skill — and the skill's structured-findings format is the actual
     value-add over inline analysis.
   - All 6 scenarios consistently get reject_tools (read-only review)
     and timeout 180s.
   - eval.vally.yaml: also added missing environment.files for each
     scenario (was prompt-only before, no fixture on disk).

2. assertion-quality `Flag assertion-free tests` plugin-mode activation
   (was bouncing to other skills because the prompt was generic `check
   whether these tests verify anything useful`):

   - eval.yaml + eval.vally.yaml: rewrite the prompt to name the file
     (`SmokeTests/ApiEndpointSmokeTests.cs`) and explicitly request
     `assertion quality and depth`, `assertion-free tests`, and
     `trivial assertions like Assert.IsNotNull` — direct trigger
     phrases for assertion-quality.
   - assertion-quality SKILL.md: extend description with explicit USE
     FOR keywords for `assertion-free tests`, `self-referential`, and
     `tautological` so plugin-mode activation isn't won by sibling
     skills like test-anti-patterns.

3. test-anti-patterns description size — was 1,301 chars (over the
   1,024 per-skill limit) AND pushed dotnet-test plugin aggregate to
   15,312 (over the 15,000 limit), failing skill-check on PR #635.
   Trimmed to 779 chars; aggregate now at 14,983.

4. Vally job-level timeout (60m → 180m) was already raised on main
   in commit 0f31228b5 (#641); inheriting that via merge of upstream/main.

Verified: skill-validator check --plugin passes (22 skills, 11 agents,
1 plugin); markdownlint clean; all 4 eval YAMLs parse OK.

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

* Address round-2 review comments: add missing production stubs, reject_tools

Address the 3 new Copilot review comments on PR #635
(IDs 3240547649, 3240547701, 3240547725):

1. coverage-touching fixture: `ProductCatalogTests.cs` references
   `new InMemoryStore()` but the fixture only declared the
   `IProductStore` interface. Audit agents could surface `this won't
   compile` as the top finding instead of the intended coverage-touching
   pattern. Added a minimal `InMemoryStore : IProductStore`
   implementation in the same file as `ProductCatalog.cs`.

2. self-referential fixture: `SerializerTests.cs` referenced 8 production
   types (Serializer, UserDto, Money, Config, NameNormalizer, Mapper,
   UserEntity, Validator) with no production code on disk. Added a new
   `Serialization/Serialization.cs` file with minimal stubs for all 8
   types so the audit can stay focused on assertion semantics. Updated
   the `Detect self-referential...` scenario in eval.yaml +
   eval.vally.yaml to copy the new file into the workspace.

3. assertion-quality `Identify self-referential assertions...` scenario:
   added `reject_tools: [bash, edit, create]` and explicit `Do not
   edit the files` wording to match the read-only audit pattern used by
   other scenarios in the file. Applied to both eval.yaml and
   eval.vally.yaml (where it lives under `constraints.reject_tools`).

Verified: skill-validator check passes, markdownlint clean, all 4
eval YAMLs parse OK.

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

* Strengthen activation: name anti-patterns explicitly, dedupe self-referential boundary

PR #635 eval scoreboard run [25859929883](https://github.com/dotnet/skills/actions/runs/25859929883):
- 3 test-anti-patterns scenarios still NOT ACTIVATED in plugin mode (mixed
  severity, flakiness, well-written) — variance was high (CV 0.90-1.59),
  but only 1-3 of 9 plugin runs actually loaded the skill, vs 3/3 for
  scenarios that named specific patterns (coverage-touching, self-referential).
- assertion-quality 'Identify self-referential' NOT ACTIVATED in plugin —
  detectedSkills was empty (model picked neither AQ nor TAP despite both
  matching the prompt's 'self-referential or tautological' phrasing).

Two-pronged fix:

1. Reduce overlap between assertion-quality and test-anti-patterns —
   remove 'self-referential or tautological assertions' from
   test-anti-patterns USE FOR. Both skills could plausibly own this, but
   assertion-quality is the more focused owner; in plugin mode neither
   was winning, so giving assertion-quality the unambiguous trigger
   improves activation. test-anti-patterns still owns the broader 'tests
   pass but don't verify anything', and the test-anti-patterns 'Detect
   self-referential' eval scenario activates fine on the explicit
   'audit ... for .NET test anti-patterns' phrasing.

2. Strengthen the 5 problem prompts with skill-specific terminology —
   the working pattern from coverage-touching/self-referential prompts
   (3/3 and 2/3 plugin activation) was naming the specific anti-pattern
   category. Apply the same pattern to the failing scenarios:
   - test-anti-patterns/Detect mixed severity: enumerate the catalog
     (missing/no assertions, swallowed exceptions, always-true /
     self-comparing, weak negative, broad exception types, unused
     fields) and ask for findings tied to named anti-patterns.
   - test-anti-patterns/Detect flakiness: name the pattern categories
     explicitly (Thread.Sleep / DateTime.Now flakiness, ordering
     dependency, shared static state, reflection coupling, god tests).
   - test-anti-patterns/Recognize well-written: enumerate the catalog
     and ask for severity-ranked output 'Critical / Warning / Info /
     no issues found' tied to named anti-patterns.
   - assertion-quality/Identify self-referential: ask for an
     'assertion-quality analysis' / 'assertion-quality metrics' /
     'assertion-quality review' (3 mentions of the skill name) and
     name the metric (how many tests are self-referential).

Same prompt updates applied to both eval.yaml and eval.vally.yaml.
skill-validator check passes (22 skills, 11 agents, 1 plugin),
aggregate description 14,938 / 15,000.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 17:43:35 +02:00
YuliiaKovalova e1e8568375 Revert "dotnet-test: add unit-under-test + behaviors quality cue to code-test…" (#651)
This reverts commit f1b09eba79.
2026-05-14 17:00:07 +02:00
Amaury Levé de0a97c551 Fix migrate-vstest-to-mtp activation for Handle exit code 8 scenario (#648)
The `Handle exit code 8 when migrating from VSTest to MTP` scenario was
not activating the migrate-vstest-to-mtp skill in plugin mode in the
latest scheduled eval (skillActivationPlugin.activated=false,
detectedSkills=[], skillEventCount=0, vally row showed `--`), even
though all 10 other scenarios in this eval activated cleanly.

Three layered fixes:

1. Prompt (eval.yaml + eval.vally.yaml): switch from past-tense
   `We migrated`/`How do I fix this behavioral difference` to
   present-tense migration framing — `We're migrating ... After
   enabling MTP ... How do I handle this MTP behavioral difference?`.
   The previous past-tense framing read as a generic post-migration CI
   troubleshooting question, which the model felt confident answering
   without consulting any skill.

2. SKILL.md description: add an explicit `USE FOR:` clause for MTP
   behavioral differences (exit code 8, zero tests discovered,
   --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE), matching the
   pattern that fixed coverage-analysis activation in 9fc75e2cd.
   Aggregate dotnet-test description size stays at 15,000 chars (limit).

3. SKILL.md `When Not to Use`: tighten `project already runs on MTP
   -- migration is done` so it no longer disqualifies post-enable
   behavioral-difference cases like exit code 8.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 11:29:59 +02:00
Amaury Levé 0f31228b58 Fix eval timeouts and skill activation for dotnet-test evals (#641)
* Fix evaluation timeouts and improve prompts for dotnet-test skills

- writing-mstest-tests: increase global vally timeout from 3m to 5m to match
  the 300s eval.yaml timeout for the complex 'Modernize legacy test patterns' stimulus
- code-testing-agent: increase timeout from 40m/2400s to 60m/3600s
- mtp-hot-reload: increase timeout from 6m to 10m and remove overly strict
  expect_tools constraint on launchSettings stimulus
- migrate-mstest-v1v2-to-v3: rephrase prompt for assertion overload errors to
  mention CS1501 and cover AreNotEqual/AreSame alongside AreEqual

* Increase eval timeouts for mtp-hot-reload and migrate-mstest-v1v2-to-v3 scenarios

* Strengthen activation prompts and add missing vally scenarios

- migrate-mstest-v1v2-to-v3: Add explicit 'MSTest v2 to v3' migration
  language in .testsettings and DataRow prompts (both eval.yaml and
  eval.vally.yaml)
- writing-mstest-tests: Add 'MSTest' keyword and skill-specific
  terminology to all prompts that lacked activation signal
- writing-mstest-tests: Add 5 missing vally scenarios (string
  assertions, comparison assertions, collection/null/reference
  assertions, conditional execution, parallelization)
- Add service-registry fixture files for the collection assertions
  scenario

* Improve skill activation via SKILL.md descriptions and prompt alignment

Three-pronged fix for systematic NOT ACTIVATED failures:

1. SKILL.md descriptions: Restructure writing-mstest-tests, migrate-
   mstest-v1v2-to-v3, and code-testing-agent descriptions to use the
   proven 'Use when user says' pattern with quoted trigger phrases
   (matching the working run-tests pattern)

2. Vally prompts: Each prompt now contains at least one exact quoted
   trigger phrase from its SKILL.md description to ensure strong
   description-to-prompt matching

3. Specific fixes:
   - writing-mstest-tests: All 15 prompts now include MSTest-specific
     trigger phrases (Assert.ThrowsExactly, sealed test class, DataRow,
     DynamicData, Assert.HasCount, Assert.IsInstanceOfType, etc.)
   - migrate-mstest-v1v2-to-v3: Add '.NET 5 dropped' and 'framework
     compatibility issues' to trigger phrases; strengthen dropped-TFM
     prompt
   - code-testing-agent: Add 'generate comprehensive unit tests' and
     'achieve high code coverage' to trigger phrases

* Revert SKILL.md description changes that caused activation regression

The description restructuring in 67056d8ec broke skill activation:
- migrate-mstest-v1v2-to-v3: went from 6/9 activating to 0/9
- writing-mstest-tests: lost isolated activation
- code-testing-agent: unnecessary change to working description

Restore all three SKILL.md files to their pre-regression state.
Keep the vally prompt improvements from 259727e.

* Fix writing-mstest-tests plugin-mode activation

- Add MSTest carve-out to code-testing-agent DO NOT USE FOR to prevent
  it from intercepting MSTest-specific prompts
- Add test parallelization/MSTest.Sdk keywords to writing-mstest-tests
  description (scenario 15 failed even in isolated mode)
- Strengthen prompts to be more MSTest-specific:
  - Scenario 1: emphasize MSTest patterns over generic 'write tests'
  - Scenario 4: remove vague 'something seems off', directly ask to
    fix swapped Assert.AreEqual arguments
  - Scenario 5: reframe as modernization request with specific APIs
  - Scenario 13: name specific MSTest assertion APIs in the prompt

* Fix writing-mstest-tests description over 1024 char limit

Shorten the USE FOR section by removing redundant 'help me write
comprehensive tests' and condensing the assertion API list.
Description is now 944 chars (limit: 1024).

* Increase vally job timeout from 60m to 180m

The code-testing-agent eval has a 60m per-stimulus timeout, and vally
runs multiple configurations (baseline, isolated, plugin). The 60m
job-level timeout was causing the job to be cancelled mid-evaluation.

Match the 180m timeout from the evaluate job in evaluation.yml.

* Address PR review comments

- Add IsPackable=false to writing-mstest-tests fixture csproj for
  consistency with other dotnet-test fixture projects
- Fix grammar in migrate-mstest-v1v2-to-v3 eval prompts: add comma
  after 'upgrade' and add 'file' for clarity (both eval.yaml and
  eval.vally.yaml)

* Trim dotnet-test aggregate description size under 15,000 limit

Consolidate duplicate filter keyword mentions in migrate-vstest-to-mtp
and shorten the cross-reference in migrate-xunit-to-xunit-v3 while
keeping the --filter-class/--filter-trait/--filter-query trigger
keywords for skill activation.

* Fix vally skill activation for 9 failing eval scenarios

Improve eval.vally.yaml prompts that were too specific, causing the model
to answer from general knowledge without activating the skill:

- migrate-mstest-v1v2-to-v3: Remove leading question that gives away the
  answer ('Is .NET 5 dropped?'); use multi-target fixture matching eval.yaml
- writing-mstest-tests (7 scenarios): Add 'following MSTest best practices'
  to trigger skill reading; make prompts more open-ended (don't name exact
  APIs like OSCondition, Assert.AreSame); match eval.yaml prompt style
- code-testing-agent: Clarify app complexity to encourage skill pipeline

The pattern: vally prompts that give away exact API names or answers let
the model skip reading the skill. More open-ended prompts referencing
'best practices' trigger skill activation.

* Improve skills and eval prompts for regression scenarios

migrate-xunit-to-xunit-v3 SKILL.md:
- Restructure from 16 steps to 13, merging redundant steps
- Move test platform selection from step 12 to step 4
- Mark steps 6-12 as conditional with prioritization note
- Remove external URL references that caused web_fetch detours

writing-mstest-tests SKILL.md:
- Add Response Guidelines for proportional responses
- Remove redundant Validation checklist and Common Pitfalls table
  (all items already covered in workflow steps)
- Reduces token count from 3,305 to 2,944

migrate-mstest-v1v2-to-v3 eval.vally.yaml:
- Relax DataRow rubric to account for MSTest 3.8.0 fixing the
  16-parameter constructor limit

writing-mstest-tests eval.vally.yaml:
- Make 3 prompts more open-ended by removing API name hints
  (Assert.HasCount, Assert.StartsWith, DynamicData to ValueTuples)
  so baseline model cannot answer confidently without the skill
2026-05-13 17:49:55 +02:00
YuliiaKovalova f1b09eba79 dotnet-test: add unit-under-test + behaviors quality cue to code-testing-generator (#646)
* CTA: invocation-only baseline (dispatch mechanics, no content rules)

Experiment branch to isolate the impact of "invoke prompted subagents
more often" from the impact of "make those subagents do richer work."
Same baseline as dev/ykovalova/cta-prompt-tuning (main = 66628b6), but
strips out every content/quality rule and keeps only the dispatch
plumbing.

Comparison branch: dev/ykovalova/cta-prompt-tuning (HEAD: bd530be)
which contains both the dispatch mechanics AND content/quality rules.

Files modified (3 vs 5 in cta-prompt-tuning):
- code-testing-generator.agent.md  +110 lines
- code-testing-implementer.agent.md +11 lines
- code-testing-fixer.agent.md      +1  line
- code-testing-researcher.agent.md  UNTOUCHED (baseline)
- code-testing-planner.agent.md     UNTOUCHED (baseline)

KEPT (invocation / dispatch mechanics):

Generator:
- Rule 1: every task() call MUST use agent_type "dotnet-test:code-testing-..."
  (without this, calls dispatch generic built-ins and never reach the
  named CTA agents)
- Rule 2: routing table -- which named agent for which job
- Rule 3: prefer one named-agent dispatch over many tool calls
- Rule 4: orchestrator MUST NOT edit/create test files itself
  (forces implementer dispatch)
- Rule 5: orchestrator MUST NOT run builds/tests via terminal
  (forces builder/tester dispatch)
- Rule 6: every run MUST dispatch the planner (no exceptions for "small"
  scope; Direct still goes through planner)
- Rule 7: every build/test failure MUST dispatch the fixer
- Step 1b: mandatory initial researcher dispatch (every strategy)
- Direct strategy rewritten: dispatches planner -> implementer -> builder
  -> tester -> fixer -> linter (was "Skip Steps 3-5, write tests inline")
- All Step 3/4/5/6/7/8/9 dispatches converted from runSubagent({agent:...})
  to task({ agent_type: "dotnet-test:code-testing-...", name:..., prompt:...})
- Step 9 validator dispatch (forces builder dispatch for cleanup)
- Steps 6/7 mandatory builder/tester dispatch wrapper

Implementer:
- Section 5: "you MUST dispatch fixer for build errors" + no-inline-edit
  block (forces fixer dispatch on build failures)
- Section 6: "you MUST dispatch fixer for test failures" + no-inline-edit
  block (forces fixer dispatch on test failures)
- Section 7: "Format Code (mandatory if a lint command exists)"
  (was "Optional"; mandatory firing of linter)
- Rule 6: never declare SUCCESS while build/tests fail (gates SUCCESS on
  fixer dispatch)
- Rule 7: no inline test-file edits between failed dispatch and fixer

Fixer:
- Frontmatter description widened to advertise handling of failing tests
  (without this, the orchestrator's routing logic does not select the
  fixer for test failures, so even Rule 7's mandate produces no firing
  -- this is the change that took fixer firing from 0.00/inst to 0.39/inst
  in earlier iterations)

DROPPED (content / quality rules -- in cta-prompt-tuning, NOT here):

Generator:
- Test-strength rules embedded in implementer dispatch prompt
- Test-design rules embedded in implementer dispatch prompt (OFAT,
  mutation self-check, never mock subject under test)
- File-location rules embedded in implementer dispatch prompt
- TARGET ENTITIES / PHASE CHECKLIST / TEST TRACEABILITY blocks in
  implementer dispatch prompt
- CHECKLIST format spec in planner dispatch prompt
- Step 9 validator's detailed cleanup classification

Implementer:
- Section 4b "Verify CHECKLIST coverage" pre-completion check
- Section 8 "CHECKLIST COVERAGE" report block
- "Honor the CHECKLIST" rule

Fixer:
- "Process -- Failing Tests" section (5-step diagnosis flow)
- All anti-weakening / anti-skipping rules
- "Re-derive expected from production source" guidance

Planner:
- CHECKLIST format ("one item per TARGET BEHAVIOR, Source/Variants/
  Expected mandatory")
- "Test name from research.md conventions" rule
- "At least 2 phases" rule

Researcher:
- Section 8 "Extract Local Test Naming & Style Conventions"
- TARGET ENTITIES / TARGET BEHAVIORS / TEST INFRASTRUCTURE structure
  in research.md
- Test naming pattern extraction

WHAT THE SUBAGENTS WILL ACTUALLY DO:

The researcher / planner / implementer / fixer all operate at baseline
behavior -- they receive the same prompts they receive in the upstream
"vanilla" runs. The only difference vs vanilla is that the orchestrator
ACTUALLY DISPATCHES THEM (where vanilla often inlines the work or skips
sub-agent dispatch entirely).

EXPECTED COMPARISON:

If quality on this branch is similar to or higher than dev/ykovalova/
cta-prompt-tuning (bd530be), then "more dispatches" is the dominant
quality lever and the content/quality rules in cta-prompt-tuning are
adding marginal or noise-level value.

If quality on this branch is materially lower than cta-prompt-tuning,
then the content/quality rules are doing the heavy lifting and the
dispatch mechanics alone are insufficient.

If quality on this branch matches or exceeds vanilla but trails
cta-prompt-tuning, then the dispatch mechanics provide a baseline lift
and the content rules add an incremental quality layer on top.

Rubber-duck check passed (validated dispatch-vs-content classification;
fixer frontmatter is routing metadata not a runtime gate; surviving
dispatch prompts contain no dangling references to removed CHECKLIST /
TARGET ENTITIES / TEST STRENGTH / naming-convention concepts).

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

* CTA: extract unit-under-test + behaviors quality cue (no caps)

* Address PR #646 review feedback

- Step 1b prompt: explicitly request unit-under-test (file:line) and behaviors
  so the verification gate rarely needs re-dispatch.
- Step 3: rename to 'Deep Research Phase', mark skipped for Direct strategy,
  and switch from overwriting research.md to extending it (no double-research).
- Step references: update '6-9' -> '6-10' and 'Step 9' -> 'Steps 9-10' in the
  strategy table and the All-strategies-MUST line, since reporting is Step 10.
- Step 6 builder prompt: drop '*.sln' glob (could expand to multiple args);
  use 'dotnet build --no-incremental' (auto-discovers .sln) per dotnet.md.
- Step 9: stop overloading the builder agent; perform diff/cleanup directly
  in the orchestrator (Rule 5 forbids inline build/test, not git/fs hygiene).
- Fixer agent: update mission text to cover failing tests and assertion
  correction (front-matter description already mentioned this; body now
  matches), with explicit no-Ignore/no-Skip/no-production-rewrite guardrails.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Yuliia Kovalova <ykovalova@example.com>
2026-05-13 14:03:31 +02:00
Amaury Levé 4c40b873f2 Add detect-static-dependencies evals for report structure, obj exclusion, and lambda statics (#640)
Cover previously uncovered skill aspects:
- [Validation] All .cs files in scope were scanned (check count)
- [Validation] Report includes category totals, top patterns, and affected files
- [Validation] obj/ and bin/ directories were excluded
- [Pitfall] Scanning obj/ or generated code
- [Pitfall] Missing statics inside lambdas/LINQ
- [WorkflowStep] Step 4: Present the report

Three new scenarios with supporting fixtures:
- Structured report with file count, categories, and top patterns
- Exclude obj/bin directories (with Generated.cs decoy in obj/)
- Detect statics inside lambdas and LINQ expressions
2026-05-13 11:49:18 +00:00
Jakub Jareš 6e7adc5e32 Add extension files for Python, TypeScript, and PowerShell (#617)
* Add Python and TypeScript extension files for code-testing pipeline

First-draft language extension files following the dotnet.md pattern.
These guide the polyglot test agent on build/test/lint/fix for each language.

Python: pytest-focused, environment/runner detection (Poetry/PDM/uv/Hatch),
public-API testing philosophy, common errors, mocking guidelines.

TypeScript: package-manager detection (npm/pnpm/yarn/bun), Jest+Vitest+Mocha
support, ESM/CJS guidance, TS-specific considerations, framework detection.

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

* Revise python.md and typescript.md based on 10-agent review

Key changes:
- Add 'Rule #1: Investigate the repo first' as top section
- Remove generic templates (anchor to wrong conventions)
- Remove testing philosophy (unactionable for agent)
- Fix command inconsistency (parameterize with <prefix>/<exec>)
- Move dependency install to 'last resort' section
- Add error-driven fixer playbook with concrete fixes
- Fix Mocha --grep (test name, not file filter)
- Fix ESM guidance (don't change package.json type field)
- Add monorepo/workspace guidance (Nx, Turborepo)
- Add framework notes (React, Express, NestJS)
- Add Jest mock hoisting warning
- Cut from 224+289 lines to 117+136 lines (~57% reduction)

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

* Add powershell.md extension for Pester v5 test generation

Key sections:
- Repo investigation first (shell target detection)
- Pester v5 discovery vs run phase rules
- Import patterns for modules, library scripts, and executable scripts
- Cross-platform guidance (pwsh vs powershell.exe, Join-Path, casing)
- Non-terminating error handling with Should -Throw
- Mock scoping, -ModuleName, PesterBoundParameters
- TestDrive: for file-based tests
- Non-obvious assertion gotchas (Contain vs Be, Throw needs scriptblock)

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

* Reword test infra guidance; add framework detection to dotnet.md

- Reword 'do not add' to 'use existing, only introduce if none exist'
- Add test framework detection table to dotnet.md (MSTest/xUnit/NUnit)
- Tailor wording per language (Python defaults to pytest, TS follows
  scripts.test, PS defaults to Pester)

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

* Make Python extension framework-adaptive instead of pytest-centric

Rule #1 now searches for ALL test file formats (not just test_*.py),
explicitly calls out custom frameworks like UTscapy, and emphasizes
adopting repo conventions fully rather than layering pytest on top.

Test Commands section now has a custom framework block before the
pytest block, and Test File Naming defers to repo conventions.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 11:16:45 +02: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
Amaury Levé 5856011d8f Add README.md for dotnet-test plugin (#636) 2026-05-11 15:54:27 +00:00
Amaury Levé d575b1faa8 Add eval scenarios for writing-mstest-tests skill coverage (#593)
* Add eval scenarios for writing-mstest-tests skill coverage

* Fix invalid YAML and remove build-validation claim from rubric

* Fix timeouts and low quality

* Improve further

* Increase timeout for string assertions scenario from 120s to 180s

Agent-Logs-Url: https://github.com/dotnet/skills/sessions/9943a60f-070b-4bea-9912-c994d1bed428

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-11 13:23:21 +00:00