/test-gap-analysis
Find caller-visible production changes existing tests would miss through pseudo-mutation analysis; verify candidates or close gaps only when requested. Includes read-only per-test composition for grading. Polyglot. USE FOR: would tests catch a bug, behavioral blind spots,
Claude Code
$ npx -y skills add dotnet/skills --skill test-gap-analysis --agent claude-code
Codex
$ npx skills add dotnet/skills --skill test-gap-analysis -a codex -y
Cursor
$ npx skills add dotnet/skills --skill test-gap-analysis -a cursor -y
Gemini CLI
$ npx skills add dotnet/skills --skill test-gap-analysis -a gemini-cli -y
GitHub Copilot
$ npx skills add dotnet/skills --skill test-gap-analysis -a github-copilot -y
OpenCode
$ npx skills add dotnet/skills --skill test-gap-analysis -a opencode -y
Windsurf
$ npx skills add dotnet/skills --skill test-gap-analysis -a windsurf -y
SKILL.md
test-gap-analysis.SKILL.mdname: test-gap-analysis
description: >-
Find caller-visible production changes existing tests would miss through
pseudo-mutation analysis; verify candidates or close gaps only when requested.
Includes read-only per-test composition for grading. Polyglot.
USE FOR: would tests catch a bug, behavioral blind spots, surviving mutations.
DO NOT USE FOR: concrete fix/feature revision proof (test-value-evidence);
suite taxonomy (test-tagging); .NET coverage, Cobertura, plateaus or
coverage-backed priorities (coverage-analysis); named CRAP (crap-score);
new suites (code-testing); assertion/smell audits; mutation tools.
license: MIT
Test Gap Analysis
Answer one question: **which caller-visible production behaviors could change without an existing test failing?** Mutation reasoning is a probe, not the goal. Inventory public outcomes first, then verify only credible gaps.
Composition dispatch
Before entering the decision flow, check the caller's mode. An explicit `per-test-read-only` request (including composition from `grade-tests`) uses only [references/per-test-read-only.md](references/per-test-read-only.md). This mode is assessment context conveyed through the host's supported caller instructions, not a new skill-loader parameter or a mode-specific skill name. Read that reference and return its per-test assessment inline; **do not enter the standalone workflow below**. Loading this mode does not authorize a baseline run, mutation execution, file edits, suite discovery, or delegation. If the bundled reference is unavailable, allow at most one listing of the known `references/` directory, then return **N/A / unverified** with the reason.
Requests without this mode retain the standalone analysis, verification, and test-addition paths below.
Decision flow
1. Set scope
Discover production and test files from manifests and file types. After a narrow search misses, inspect the current directory broadly before asking for paths.
| Request | Action | |---|---| | One component or named risk | Inventory every high-risk public outcome in scope; do not edit production code unless verification was requested | | General small-component review | Inventory distinct outcomes and report caller-visible gaps from source/assertion mapping | | Explicit survivor verification | Inventory all requested outcomes; execute one representative observable candidate for each distinct high-risk outcome under verification, then classify it as **Survived** or **Killed** | | Explicit exhaustive audit | Read [references/mutation-catalog.md](references/mutation-catalog.md) and classify all meaningful candidates | | Add tests to an existing suite | Analyze first; add tests only for verified survivors or demonstrated no-coverage outcomes | | Create a new suite | Stop and use `code-testing` |
When the request names a risk, turn it into a one-line public-outcome allowlist before reading code. An outcome is not in scope merely because the same method writes it. For `money math`, allow computed or returned amounts, rates, tier/boundary choice, percentage base/order, floors/caps, and rounding; exclude non-monetary state predicates (including derived booleans), identity, and formatting. Private code is in scope only to trace an allowed outcome.
Do not expand a focused request into a repository audit, plan artifact, or dashboard. Use source and tests directly for familiar frameworks. When discovery or assertion semantics are unclear, read the matching language file relative to the caller-provided or runtime-listed `test-analysis-extensions` catalog; do not invoke the reference-only helper or search installation directories. If absent, state the limitation and use the pinned APIs and rules here.
2. Establish one baseline
For a source-only advisory review, skip execution and label empirical survival unverified. A baseline is required when the user requests execution or survivor verification, or when closing gaps with tests. Run the narrowest existing test command once. Choose it from the project manifest; Microsoft.Testing.Platform executables may require `dotnet run`. Confirm tests executed: exit 0 with build-only output is not green. If that one attempt cannot run the suite, do not troubleshoot the runner or try alternate commands for an advisory review; continue statically and label all candidates **unverified**. Do not infer a project-configuration cause from missing output; name a cause only when the command reports it.
Missing runner output limits only claims of empirical mutation survival. It does not make source-proven facts tentative: a public outcome with no reaching test is still **No coverage**, and an exact expected value derived from the unmodified implementation is still actionable. State the baseline limitation once, then give the static source/assertion conclusion directly instead of hedging every row.
For an advisory review such as "would tests catch this?", stop execution after that baseline. Source-to-assertion mapping is sufficient evidence for **No coverage** and **Candidate survivor (unverified)**. Trace or run the unmodified code once only when an original value is unclear. Apply mutations only for explicit verification, an exhaustive audit, or closing gaps with tests.
Any focused mutation budget limits execution, not discovery. Keep every distinct unasserted public outcome in the inventory.
3. Inventory public outcomes
For each public entry point, map:
- input partitions: classifier arms, compound conditions, invalid and
nearest-valid guard boundaries, and default cases;
- each independent observation: returned field/variant, exception type,
invalid-input acceptance, public state transition, or external side effect;
- private-helper composition, constants/rates, rounding, retries, cancellation,
and error propagation as observed through the public caller.
Use `public input/sequence -> expected outcome -> existing assertion -> gap`. One asserted return f
Read more
name: test-gap-analysis description: >- Find caller-visible production changes existing tests would miss through pseudo-mutation analysis; verify candidates or close gaps only when requested. Includes read-only per-test composition for grading. Polyglot. USE FOR: would tests catch a bug, behavioral blind spots, surviving mutations. DO NOT USE FOR: concrete fix/feature revision proof (test-value-evidence); suite taxonomy (test-tagging); .NET coverage, Cobertura, plateaus or coverage-backed priorities (coverage-analysis); named CRAP (crap-score); new suites (code-testing); assertion/smell audits; mutation tools. license: MIT
Test Gap Analysis
Answer one question: **which caller-visible production behaviors could change without an existing test failing?** Mutation reasoning is a probe, not the goal. Inventory public outcomes first, then verify only credible gaps.
Composition dispatch
Before entering the decision flow, check the caller's mode. An explicit `per-test-read-only` request (including composition from `grade-tests`) uses only [references/per-test-read-only.md](references/per-test-read-only.md). This mode is assessment context conveyed through the host's supported caller instructions, not a new skill-loader parameter or a mode-specific skill name. Read that reference and return its per-test assessment inline; **do not enter the standalone workflow below**. Loading this mode does not authorize a baseline run, mutation execution, file edits, suite discovery, or delegation. If the bundled reference is unavailable, allow at most one listing of the known `references/` directory, then return **N/A / unverified** with the reason.
Requests without this mode retain the standalone analysis, verification, and test-addition paths below.
Decision flow
1. Set scope
Discover production and test files from manifests and file types. After a narrow search misses, inspect the current directory broadly before asking for paths.
| Request | Action | |---|---| | One component or named risk | Inventory every high-risk public outcome in scope; do not edit production code unless verification was requested | | General small-component review | Inventory distinct outcomes and report caller-visible gaps from source/assertion mapping | | Explicit survivor verification | Inventory all requested outcomes; execute one representative observable candidate for each distinct high-risk outcome under verification, then classify it as **Survived** or **Killed** | | Explicit exhaustive audit | Read [references/mutation-catalog.md](references/mutation-catalog.md) and classify all meaningful candidates | | Add tests to an existing suite | Analyze first; add tests only for verified survivors or demonstrated no-coverage outcomes | | Create a new suite | Stop and use `code-testing` |
When the request names a risk, turn it into a one-line public-outcome allowlist before reading code. An outcome is not in scope merely because the same method writes it. For `money math`, allow computed or returned amounts, rates, tier/boundary choice, percentage base/order, floors/caps, and rounding; exclude non-monetary state predicates (including derived booleans), identity, and formatting. Private code is in scope only to trace an allowed outcome.
Do not expand a focused request into a repository audit, plan artifact, or dashboard. Use source and tests directly for familiar frameworks. When discovery or assertion semantics are unclear, read the matching language file relative to the caller-provided or runtime-listed `test-analysis-extensions` catalog; do not invoke the reference-only helper or search installation directories. If absent, state the limitation and use the pinned APIs and rules here.
2. Establish one baseline
For a source-only advisory review, skip execution and label empirical survival unverified. A baseline is required when the user requests execution or survivor verification, or when closing gaps with tests. Run the narrowest existing test command once. Choose it from the project manifest; Microsoft.Testing.Platform executables may require `dotnet run`. Confirm tests executed: exit 0 with build-only output is not green. If that one attempt cannot run the suite, do not troubleshoot the runner or try alternate commands for an advisory review; continue statically and label all candidates **unverified**. Do not infer a project-configuration cause from missing output; name a cause only when the command reports it.
Missing runner output limits only claims of empirical mutation survival. It does not make source-proven facts tentative: a public outcome with no reaching test is still **No coverage**, and an exact expected value derived from the unmodified implementation is still actionable. State the baseline limitation once, then give the static source/assertion conclusion directly instead of hedging every row.
For an advisory review such as "would tests catch this?", stop execution after that baseline. Source-to-assertion mapping is sufficient evidence for **No coverage** and **Candidate survivor (unverified)**. Trace or run the unmodified code once only when an original value is unclear. Apply mutations only for explicit verification, an exhaustive audit, or closing gaps with tests.
Any focused mutation budget limits execution, not discovery. Keep every distinct unasserted public outcome in the inventory.
3. Inventory public outcomes
For each public entry point, map:
- input partitions: classifier arms, compound conditions, invalid and
nearest-valid guard boundaries, and default cases;
- each independent observation: returned field/variant, exception type,
invalid-input acceptance, public state transition, or external side effect;
- private-helper composition, constants/rates, rounding, retries, cancellation,
and error propagation as observed through the public caller.
Use `public input/sequence -> expected outcome -> existing assertion -> gap`. One asserted return f
This repository contains the .NET team's curated set of portable skills and host-specific custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about test-gap-analysis.
- Which coding agents can use test-gap-analysis?
- test-gap-analysis installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

