.NET Code Analysis
Trigger On
- the repo wants first-party .NET analyzers
- CI should fail on analyzer warnings
- the team needs
AnalysisLevel or AnalysisMode guidance
- the repo needs a gradual Roslyn warning promotion strategy
Do Not Use For
- third-party analyzer selection by itself
- formatting-only work
Inputs
- the nearest
AGENTS.md
- project files or
Directory.Build.props
- current analyzer severity policy
Hard Rules for AI Agents
Non-negotiable. Violating these undermines the user's explicit intent.
- Never disable or remove
TreatWarningsAsErrors or WarningsAsErrors if the project has set them. Do not comment them out, set to false, wrap in a condition, or add <TreatWarningsAsErrors>false</TreatWarningsAsErrors> to make the build pass.
- Never add
<NoWarn> or #pragma warning disable for warnings the user chose to treat as errors, unless the user explicitly approves the suppression.
- Never silently downgrade severity in
.editorconfig (e.g. error to warning or none) to make a build succeed.
- If warnings-as-errors breaks the build — fix the code. If the fix is too large, ask the user whether to defer that warning ID.
- If warning volume is too large to fix in one pass — report count and categories to the user and ask which to tackle first. Do not unilaterally disable the policy.
Workflow
flowchart TD
A[Start] --> B{New or legacy project?}
B -->|New| C[TreatWarningsAsErrors=true immediately]
B -->|Legacy| D[dotnet build, count warnings by ID]
D --> E{"< 30 warnings?"}
E -->|Yes| F[Fix all, then enable TreatWarningsAsErrors]
E -->|No| G[Report counts to user, ask which batch first]
G --> H[Add selected IDs to WarningsAsErrors]
H --> I[Fix that batch, verify build]
I --> J{More batches?}
J -->|Yes| G
J -->|No| F
C --> K[Set AnalysisLevel latest-recommended]
F --> K
K --> L[Promote security CA3xxx/CA5xxx to error in .editorconfig]
L --> M[Validate: build + CI green]
- Start with SDK analyzers before third-party packages.
- Detect project maturity: new or existing/legacy.
- Enable
EnableNETAnalyzers, AnalysisLevel, AnalysisMode in Directory.Build.props.
- Apply the right warning promotion strategy (see below).
- Per-rule severity goes in repo-root
.editorconfig.
dotnet build is the analyzer gate in CI.
Warning Promotion Strategy
New Projects
Set these in Directory.Build.props immediately:
TreatWarningsAsErrors = true
AnalysisLevel = latest-recommended
- Security category = error in
.editorconfig
Fix all warnings before merging.
Legacy Projects — Gradual Promotion
Blanket TreatWarningsAsErrors on a legacy codebase produces hundreds/thousands of errors. An agent cannot fix them all at once — context floods, fix quality drops. Promote in batches.
Phase 1: Trivial Hygiene (start here)
Mechanical fixes, lowest effort:
- CS8019 — unnecessary using directive (remove it)
- CS0219 — variable assigned but never used (remove it)
- CS0168 — variable declared but never used (remove it)
- CS1591 — missing XML comment for public member (add comment or disable for internal code)
- CS0612 — obsolete member used, no message (replace with non-obsolete API)
- CS0618 — obsolete member used, with message (follow migration guidance)
Add to WarningsAsErrors: CS8019;CS0219;CS0168. Fix all, then Phase 2.
Phase 2: Code Quality (ask user which categories)
- CA2000 — dispose objects before losing scope (Reliability)
- CA1062 — validate public method arguments (Design)
- CA1822 — mark members as static (Performance)
- CA1860 — avoid Enumerable.Any() for length check (Performance)
- CA1861 — avoid constant arrays as arguments (Performance)
- CA2007 — consider calling ConfigureAwait (Reliability)
- CS8600–CS8610 — nullable reference type warnings (Nullability)
Ask: "Which categories next — Nullability, Performance, or Reliability?" Add selected IDs to WarningsAsErrors, fix, repeat.
Phase 3: Security (always promote early)
Set in .editorconfig regardless of project maturity:
[*.cs]
dotnet_analyzer_diagnostic.category-Security.severity = error
Covers CA3001 (SQL injection), CA3002 (XSS), CA3003 (path injection), CA3075 (insecure DTD), CA5350/CA5351 (weak crypto), CA5394 (insecure randomness).
Phase 4: Full Coverage
Once all batches pass, transition to:
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsNotAsErrors>CA1707</WarningsNotAsErrors> <!-- explicit exceptions only -->
Interaction Protocol (legacy codebases)
- Run
dotnet build, count warnings by ID.
- Report summary: "Found 47 CS8019, 23 CA1822, 12 CA2000, 8 CS8600."
- Ask which batch to tackle. Recommend starting with Phase 1.
- Fix selected batch, verify build.
- Add those IDs to
WarningsAsErrors.
- Report back, ask about next batch.
Never skip the ask step. The user decides the pace.
Bootstrap When Missing
- Detect current state:
dotnet --info
rg -n "EnableNETAnalyzers|AnalysisLevel|AnalysisMode|TreatWarningsAsErrors|WarningsAsErrors" -g '*.csproj' -g 'Directory.Build.*' .
dotnet build SOLUTION_OR_PROJECT 2>&1 — count warnings by ID
- Classify: new (few/zero warnings) vs legacy (many warnings).
- Enable
EnableNETAnalyzers, AnalysisLevel, AnalysisMode in MSBuild config.
- Apply promotion strategy matching project maturity.
- Per-rule severity in repo-root
.editorconfig.
- Run
dotnet build, return status: configured or status: improved.
- If repo defers analyzer policy to another build layer, return
status: not_applicable.
Deliver
- explicit, reviewable first-party analyzer policy
- build-time analyzer execution for CI
- warning promotion plan matching project maturity
Validate
- analyzer behavior driven by repo config, not IDE defaults
- CI reproduces same warnings/errors locally
- no
TreatWarningsAsErrors, WarningsAsErrors, or severity settings removed/weakened without user approval
- promoted warnings produce build errors, not just IDE hints
Ralph Loop
- Plan: analyze state, define target, constraints, risks, execution plan, validation steps.
- Execute one step, produce concrete delta.
- Review result, capture findings.
- Apply fixes in small batches, rerun checks.
- Update plan after each iteration.
- Repeat until acceptable or only explicit exceptions remain.
- Missing dependency: bootstrap or return
status: not_applicable.
Required Result Format
status: complete | clean | improved | configured | not_applicable | blocked
plan: concise plan and current step
actions_taken: concrete changes
validation_skills: final skills run or skipped with reasons
verification: commands, checks, or review evidence
remaining: unresolved items or none
Load References
references/rules.md
references/config.md
references/code-analysis.md
Example Requests
- "Turn on built-in .NET analyzers."
- "Make analyzer warnings fail the build."
- "Set the right AnalysisLevel for this repo."
- "Start treating unused usings and unused variables as errors."
- "Help me gradually promote Roslyn warnings in my legacy project."
- "Which warnings should I promote to errors next?"
1---2name: dotnet-code-analysis3description: Use the free built-in .NET SDK analyzers and analysis levels with gradual Roslyn warning promotion. Use when a .NET repo needs first-party code analysis, `EnableNETAnalyzers`, `AnalysisLevel`, or warning-as-error policy wired into build and CI.4---56# .NET Code Analysis78## Trigger On910- the repo wants first-party .NET analyzers11- CI should fail on analyzer warnings12- the team needs `AnalysisLevel` or `AnalysisMode` guidance13- the repo needs a gradual Roslyn warning promotion strategy1415## Do Not Use For1617- third-party analyzer selection by itself18- formatting-only work1920## Inputs2122- the nearest `AGENTS.md`23- project files or `Directory.Build.props`24- current analyzer severity policy2526## Hard Rules for AI Agents2728Non-negotiable. Violating these undermines the user's explicit intent.29301. Never disable or remove `TreatWarningsAsErrors` or `WarningsAsErrors` if the project has set them. Do not comment them out, set to `false`, wrap in a condition, or add `<TreatWarningsAsErrors>false</TreatWarningsAsErrors>` to make the build pass.312. Never add `<NoWarn>` or `#pragma warning disable` for warnings the user chose to treat as errors, unless the user explicitly approves the suppression.323. Never silently downgrade severity in `.editorconfig` (e.g. `error` to `warning` or `none`) to make a build succeed.334. If warnings-as-errors breaks the build — fix the code. If the fix is too large, ask the user whether to defer that warning ID.345. If warning volume is too large to fix in one pass — report count and categories to the user and ask which to tackle first. Do not unilaterally disable the policy.3536## Workflow3738```mermaid39flowchart TD40 A[Start] --> B{New or legacy project?}41 B -->|New| C[TreatWarningsAsErrors=true immediately]42 B -->|Legacy| D[dotnet build, count warnings by ID]43 D --> E{"< 30 warnings?"}44 E -->|Yes| F[Fix all, then enable TreatWarningsAsErrors]45 E -->|No| G[Report counts to user, ask which batch first]46 G --> H[Add selected IDs to WarningsAsErrors]47 H --> I[Fix that batch, verify build]48 I --> J{More batches?}49 J -->|Yes| G50 J -->|No| F51 C --> K[Set AnalysisLevel latest-recommended]52 F --> K53 K --> L[Promote security CA3xxx/CA5xxx to error in .editorconfig]54 L --> M[Validate: build + CI green]55```56571. Start with SDK analyzers before third-party packages.582. Detect project maturity: new or existing/legacy.593. Enable `EnableNETAnalyzers`, `AnalysisLevel`, `AnalysisMode` in `Directory.Build.props`.604. Apply the right warning promotion strategy (see below).615. Per-rule severity goes in repo-root `.editorconfig`.626. `dotnet build` is the analyzer gate in CI.6364## Warning Promotion Strategy6566### New Projects6768Set these in `Directory.Build.props` immediately:69- `TreatWarningsAsErrors` = true70- `AnalysisLevel` = latest-recommended71- Security category = error in `.editorconfig`7273Fix all warnings before merging.7475### Legacy Projects — Gradual Promotion7677Blanket `TreatWarningsAsErrors` on a legacy codebase produces hundreds/thousands of errors. An agent cannot fix them all at once — context floods, fix quality drops. Promote in batches.7879#### Phase 1: Trivial Hygiene (start here)8081Mechanical fixes, lowest effort:82- CS8019 — unnecessary using directive (remove it)83- CS0219 — variable assigned but never used (remove it)84- CS0168 — variable declared but never used (remove it)85- CS1591 — missing XML comment for public member (add comment or disable for internal code)86- CS0612 — obsolete member used, no message (replace with non-obsolete API)87- CS0618 — obsolete member used, with message (follow migration guidance)8889Add to `WarningsAsErrors`: `CS8019;CS0219;CS0168`. Fix all, then Phase 2.9091#### Phase 2: Code Quality (ask user which categories)9293- CA2000 — dispose objects before losing scope (Reliability)94- CA1062 — validate public method arguments (Design)95- CA1822 — mark members as static (Performance)96- CA1860 — avoid Enumerable.Any() for length check (Performance)97- CA1861 — avoid constant arrays as arguments (Performance)98- CA2007 — consider calling ConfigureAwait (Reliability)99- CS8600–CS8610 — nullable reference type warnings (Nullability)100101Ask: "Which categories next — Nullability, Performance, or Reliability?" Add selected IDs to `WarningsAsErrors`, fix, repeat.102103#### Phase 3: Security (always promote early)104105Set in `.editorconfig` regardless of project maturity:106```editorconfig107[*.cs]108dotnet_analyzer_diagnostic.category-Security.severity = error109```110111Covers CA3001 (SQL injection), CA3002 (XSS), CA3003 (path injection), CA3075 (insecure DTD), CA5350/CA5351 (weak crypto), CA5394 (insecure randomness).112113#### Phase 4: Full Coverage114115Once all batches pass, transition to:116```xml117<TreatWarningsAsErrors>true</TreatWarningsAsErrors>118<WarningsNotAsErrors>CA1707</WarningsNotAsErrors> <!-- explicit exceptions only -->119```120121### Interaction Protocol (legacy codebases)1221231. Run `dotnet build`, count warnings by ID.1242. Report summary: "Found 47 CS8019, 23 CA1822, 12 CA2000, 8 CS8600."1253. Ask which batch to tackle. Recommend starting with Phase 1.1264. Fix selected batch, verify build.1275. Add those IDs to `WarningsAsErrors`.1286. Report back, ask about next batch.129130Never skip the ask step. The user decides the pace.131132## Bootstrap When Missing1331341. Detect current state:135 - `dotnet --info`136 - `rg -n "EnableNETAnalyzers|AnalysisLevel|AnalysisMode|TreatWarningsAsErrors|WarningsAsErrors" -g '*.csproj' -g 'Directory.Build.*' .`137 - `dotnet build SOLUTION_OR_PROJECT 2>&1` — count warnings by ID1382. Classify: new (few/zero warnings) vs legacy (many warnings).1393. Enable `EnableNETAnalyzers`, `AnalysisLevel`, `AnalysisMode` in MSBuild config.1404. Apply promotion strategy matching project maturity.1415. Per-rule severity in repo-root `.editorconfig`.1426. Run `dotnet build`, return `status: configured` or `status: improved`.1437. If repo defers analyzer policy to another build layer, return `status: not_applicable`.144145## Deliver146147- explicit, reviewable first-party analyzer policy148- build-time analyzer execution for CI149- warning promotion plan matching project maturity150151## Validate152153- analyzer behavior driven by repo config, not IDE defaults154- CI reproduces same warnings/errors locally155- no `TreatWarningsAsErrors`, `WarningsAsErrors`, or severity settings removed/weakened without user approval156- promoted warnings produce build errors, not just IDE hints157158## Ralph Loop1591601. Plan: analyze state, define target, constraints, risks, execution plan, validation steps.1612. Execute one step, produce concrete delta.1623. Review result, capture findings.1634. Apply fixes in small batches, rerun checks.1645. Update plan after each iteration.1656. Repeat until acceptable or only explicit exceptions remain.1667. Missing dependency: bootstrap or return `status: not_applicable`.167168### Required Result Format169170- `status`: `complete` | `clean` | `improved` | `configured` | `not_applicable` | `blocked`171- `plan`: concise plan and current step172- `actions_taken`: concrete changes173- `validation_skills`: final skills run or skipped with reasons174- `verification`: commands, checks, or review evidence175- `remaining`: unresolved items or `none`176177## Load References178179- `references/rules.md`180- `references/config.md`181- `references/code-analysis.md`182183## Example Requests184185- "Turn on built-in .NET analyzers."186- "Make analyzer warnings fail the build."187- "Set the right AnalysisLevel for this repo."188- "Start treating unused usings and unused variables as errors."189- "Help me gradually promote Roslyn warnings in my legacy project."190- "Which warnings should I promote to errors next?"