Skip to content

Add implementing-health-checks skill#263

Open
mrsharm wants to merge 5 commits intodotnet:mainfrom
mrsharm:musharm/health-check-skill
Open

Add implementing-health-checks skill#263
mrsharm wants to merge 5 commits intodotnet:mainfrom
mrsharm:musharm/health-check-skill

Conversation

@mrsharm
Copy link
Member

@mrsharm mrsharm commented Mar 6, 2026

Summary

Adds the implementing-health-checks skill for configuring ASP.NET Core health checks with Kubernetes liveness, readiness, and startup probes.

Skill Validation Results

Skill Test Baseline With Skill Delta Verdict
implementing-health-checks Add health checks with Kubernetes probes 4.3/5 5.0/5 +0.7 PASS
implementing-health-checks Health check skill should not activate for monitoring setup 2.0/5 2.3/5 +0.3 PASS

Overall improvement: +17.2% (3 runs)

Model: claude-opus-4.6 | Judge: claude-opus-4.6

What the Skill Teaches

  • Critical liveness vs readiness distinction: Liveness checks process health only (never external dependencies); readiness checks dependencies
  • Failure to separate probes causes cascading pod restarts during dependency outages
  • Correct tag-based filtering with separate /healthz/live, /healthz/ready, and /healthz/startup endpoints
  • Timeout parameters on all health check registrations (TimeSpan.FromSeconds(5))
  • Kubernetes probe YAML configuration (initialDelaySeconds, periodSeconds, failureThreshold)
  • Health check UI setup with AspNetCore.HealthChecks.UI
  • Common pitfalls table (DB in liveness, missing timeouts, auth on health endpoints)

Files

  • plugins/dotnet/skills/implementing-health-checks/SKILL.md
  • tests/dotnet/implementing-health-checks/eval.yaml

@mrsharm mrsharm requested a review from a team March 6, 2026 17:05
Copilot AI review requested due to automatic review settings March 6, 2026 17:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new .NET skill, implementing-health-checks, to guide users through configuring ASP.NET Core health checks for Kubernetes probes (liveness/readiness/startup), along with an evaluation scenario to validate activation behavior.

Changes:

  • Added skill content describing package setup, tagging strategy, endpoint mapping, and Kubernetes probe configuration.
  • Added eval scenarios to validate the skill activates for Kubernetes health checks requests and does not activate for OpenTelemetry/APM requests.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
plugins/dotnet/skills/implementing-health-checks/SKILL.md New skill documentation for implementing ASP.NET Core health checks and Kubernetes probes.
tests/dotnet/implementing-health-checks/eval.yaml New evaluation scenarios for the skill’s activation and non-activation behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.


### Step 2: Register health checks with SEPARATE liveness and readiness

**Critical distinction** most implementations get wrong:
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence "Critical distinction most implementations get wrong:" reads grammatically incomplete. Consider rephrasing to something like "Critical distinction most implementations get wrong:" or "Critical distinction: most implementations get wrong" to improve readability.

Suggested change
**Critical distinction** most implementations get wrong:
**Critical distinction most implementations get wrong:**

Copilot uses AI. Check for mistakes.
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready"),
ResponseWriter = WriteDetailedResponse
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The readiness endpoint is configured to return a detailed JSON payload including per-check descriptions. In real deployments these descriptions can contain internal dependency names and failure details, which is risky if this endpoint is reachable outside the cluster or is marked anonymous. Consider defaulting readiness to the minimal response, or explicitly calling out that the detailed response should be protected (auth/network policy) or enabled only in non-production environments.

Suggested change
ResponseWriter = WriteDetailedResponse
// Use minimal response by default; expose detailed health only on protected/internal endpoints
ResponseWriter = WriteMinimalResponse

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +27
- type: "output_not_contains"
value: "AddHealthChecks"
- type: "output_not_contains"
value: "MapHealthChecks"
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The negative assertions use output_not_contains for the strings "AddHealthChecks" and "MapHealthChecks". This can make the scenario brittle if a good OpenTelemetry-focused answer briefly contrasts with health checks (e.g., "don't call AddHealthChecks here"), causing a false failure. Consider using output_not_matches to only reject actual method invocations (e.g., \b(AddHealthChecks|MapHealthChecks)\s*\(), and/or add positive assertions for expected OpenTelemetry terms ("OpenTelemetry", "AddOpenTelemetry", "tracing", "metrics", exporters).

Suggested change
- type: "output_not_contains"
value: "AddHealthChecks"
- type: "output_not_contains"
value: "MapHealthChecks"
- type: "output_not_matches"
pattern: "\\b(AddHealthChecks|MapHealthChecks)\\s*\\("
- type: "output_matches"
pattern: "(OpenTelemetry|AddOpenTelemetry|tracing|metrics|exporter)"

Copilot uses AI. Check for mistakes.
@mrsharm
Copy link
Member Author

mrsharm commented Mar 6, 2026

/eval

@mrsharm
Copy link
Member Author

mrsharm commented Mar 6, 2026

Migration Note

This PR replaces #88 which was opened from mrsharm/skills-old. The skill and eval files have been migrated to the new plugins/ directory structure:

  • src/dotnet/skills/implementing-health-checks/plugins/dotnet/skills/implementing-health-checks/
  • src/dotnet/tests/implementing-health-checks/tests/dotnet/implementing-health-checks/

All prior review feedback from #88 still applies — please see that PR for the full discussion history.

@mrsharm
Copy link
Member Author

mrsharm commented Mar 6, 2026

Feedback carried over from #88

Code Review Comments (3 threads)

  • @copilot on src/dotnet/skills/implementing-health-checks/SKILL.md (L87):

    The startup probe configuration uses Predicate = _ => true, which executes ALL registered health checks including database, Redis, and external API dependency checks. This contradicts Kubernetes best practices: startup probes should check the same thing as liveness probes (process health only), not readiness checks (dependencies). The current implementation means if any dependency is unavailable during the 150-second startup window, Kubernetes will kill the pod rather than marking it as "no...

  • @copilot on src/dotnet/skills/implementing-health-checks/SKILL.md (L64):

    The Common Pitfalls section recommends adding timeout parameters to health check registrations, but the example code in Step 2 doesn't include any timeout parameters. For consistency and to demonstrate best practices, consider adding timeout parameters to the health check registrations in Step 2. For example: .AddSqlServer(connectionString: ..., name: "database", tags: new[] { "ready" }, timeout: TimeSpan.FromSeconds(5))

            tags: new[] { "ready" },
            timeout: Tim...
    
  • @copilot on src/dotnet/skills/implementing-health-checks/SKILL.md (L33):

    The package Microsoft.Extensions.Diagnostics.HealthChecks is already included in ASP.NET Core framework references and doesn't need to be explicitly installed. While this line isn't harmful, it's redundant and could be removed to avoid confusion.

    
    ```
    

Discussion Comments (2)

  • @mrsharm:

    Skill Validation Results ΓÇö implementing-health-checks

    Skill Test Baseline With Skill Δ Verdict
    implementing-health-checks Add health checks with Kubernetes probes 4.0/5 4.3/5 +0.3 ✅
    implementing-health-checks Health check skill should not activate for monitoring setup 2.7/5 3.7/5 +1.0 ✅

    Overall improvement: +17.2% (3 runs, not statistically significant)

    Model: claude-opus-4.6 | Ju...

  • @mrsharm:

    Skill Validation Results ΓÇö implementing-health-checks

    Skill Test Baseline With Skill Δ Verdict
    implementing-health-checks Add health checks with Kubernetes probes 4.0/5 4.3/5 +0.3 ✅
    implementing-health-checks Health check skill should not activate for monitoring setup 2.7/5 3.7/5 +1.0 ✅

    Overall improvement: +17.2% (3 runs, not statistically significant)

    Model: claude-opus-4.6 | Ju...

@ManishJayaswal
Copy link
Contributor

@mrsharm - - the repo has undergone some restructuring to make everything more organized. Hence, we are asking all open PRs to update the branch. Sorry about this.
This skill should be under ASP plugin. Please update the PR and submit again.
@adityamandaleeka @BrennanConroy - please review

mrsharm added 5 commits March 10, 2026 11:53
Teaches ASP.NET Core health check configuration for Kubernetes:
liveness vs readiness vs startup probes, custom health checks for
dependencies (SQL, Redis, external APIs), and K8s YAML configuration.

Eval results: +33.1% improvement over baseline (threshold: 10%)
Includes eval.yaml with K8s probe scenario + negative test.
- Fix: Remove redundant Microsoft.Extensions.Diagnostics.HealthChecks package
  (already included in ASP.NET Core framework)
- Fix: Add timeout: TimeSpan.FromSeconds(5) to all health check registrations
  to match Common Pitfalls guidance
- Move skill from src/dotnet/skills/ to plugins/dotnet/skills/
- Move eval from src/dotnet/tests/ to tests/dotnet/
…add eval cases

- Create dotnet-aspnet plugin (plugin.json, marketplace.json entries, CODEOWNERS, README)
- Move skill from plugins/dotnet/ to plugins/dotnet-aspnet/ per Manish's feedback
- Move tests from tests/dotnet/ to tests/dotnet-aspnet/
- Fix grammar: 'Critical distinction most implementations get wrong:'
- Change readiness endpoint to use minimal response by default (security)
- Fix startup probe to check process health only, not all checks
- Add 'detailed response on public endpoint' to Common Pitfalls
- Replace output_not_contains with output_not_matches regex (less brittle)
- Add positive assertion for expected OpenTelemetry terms
- Add eval: 'Separate startup probe from liveness' scenario
- Add eval: 'Health checks with load balancer' scenario
- Add eval: 'Do not confuse health checks with logging middleware' scenario
Copilot AI review requested due to automatic review settings March 10, 2026 19:30
@mrsharm mrsharm force-pushed the musharm/health-check-skill branch from 800b11d to 8108581 Compare March 10, 2026 19:30
@mrsharm
Copy link
Member Author

mrsharm commented Mar 10, 2026

/evaluate

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

- "Did NOT suggest health checks for a request logging scenario"
- "Focused on HTTP logging or request logging middleware configuration"
timeout: 60
timeout: 60
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scenario defines timeout twice. YAML duplicate keys are easy to miss and the last value will win, which can hide edits or cause confusing behavior during evaluation. Remove the duplicate timeout entry so the scenario has a single, unambiguous timeout value.

Suggested change
timeout: 60

Copilot uses AI. Check for mistakes.
- type: "output_not_matches"
pattern: "\\b(AddHealthChecks|MapHealthChecks)\\s*\\("
- type: "output_matches"
pattern: "(UseHttpLogging|UseSerilog|logging|middleware)"
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion pattern (UseHttpLogging|UseSerilog|logging|middleware) is so broad that a response mentioning unrelated “middleware” could satisfy it without actually recommending request logging. Tighten the pattern to require logging-specific terms (e.g., UseHttpLogging, Serilog, request logging, etc.) so this scenario can’t pass on false positives.

Suggested change
pattern: "(UseHttpLogging|UseSerilog|logging|middleware)"
pattern: "(UseHttpLogging|UseSerilog|request logging|http logging|HTTP logging|logging middleware)"

Copilot uses AI. Check for mistakes.

```csharp
builder.Services.AddHealthChecksUI().AddInMemoryStorage();
app.MapHealthChecksUI();
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.MapHealthChecksUI() exposes the HealthChecks UI endpoint with detailed health information but no authentication or access control, which can leak internal dependency names, connection details, and health statuses to unauthenticated clients. An attacker who can reach this endpoint could use this operational data to map internal services or assist further attacks. Restrict access to the HealthChecks UI (for example by applying authorization, IP/network restrictions, or hosting it on an internal-only path) rather than exposing it directly on the public app pipeline.

Suggested change
app.MapHealthChecksUI();
// Expose UI on a custom path and require authorization to avoid leaking details
app.MapHealthChecksUI(options =>
{
options.UIPath = "/health-ui"; // UI endpoint
options.ApiPath = "/health-ui-api"; // backend API
}).RequireAuthorization();

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Contributor

Skill Validation Results

Skill Scenario Quality Skills Loaded Overfit Verdict
implementing-health-checks Add health checks with Kubernetes probes 4.7/5 → 5.0/5 🟢 ✅ implementing-health-checks; tools: skill, glob, edit, create ✅ 0.06 [1]
implementing-health-checks Health check skill should not activate for monitoring setup 3.0/5 → 2.3/5 🔴 ✅ tools: bash ✅ 0.06
implementing-health-checks Separate startup probe from liveness 4.0/5 → 5.0/5 🟢 ✅ implementing-health-checks; tools: skill, report_intent, view, glob ✅ 0.06
implementing-health-checks Health checks with load balancer instead of Kubernetes 3.7/5 → 3.7/5 ✅ implementing-health-checks; tools: skill, glob ✅ 0.06
implementing-health-checks Do not confuse health checks with logging middleware 3.3/5 ⏰ → 4.7/5 🟢 ⚠️ NOT ACTIVATED ✅ 0.06

[1] Quality improved but weighted score is -7.7% due to: completion (✓ → ✗), tokens (33788 → 208438), tool calls (3 → 21), time (26.5s → 97.2s)

timeout — run hit the scenario timeout limit; scoring may be impacted by aborting model execution before it could produce its full output

Model: claude-opus-4.6 | Judge: claude-opus-4.6

Full results

Copy link
Member

@DeagleGross DeagleGross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for writing this skill, but I am concerned about adding it in such form because:

  1. there is an excellent doc which agent can read from, describing a general approach to building health-checks in aspnetcore: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-10.0.

  2. Skill has a broard number of packages included, and those are not represented in frontmatter. We need to decide whether this skill has to be a specific one related to Kubernetes / sql / redis, or it is a general-purpose skill around health-checks.

Let me know your thoughts please!

### Step 1: Add the health checks packages

```bash
dotnet add package AspNetCore.HealthChecks.SqlServer # for SQL Server
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are packages for SqlServer, Redis and Uris required for the skill about health-checks for Kubernetes and load balancer integration? Skill has to be very specific, and it feels like this one supports multiple different resources not really following the single idea.

pattern: "(liveness|readiness|live|ready)"
- type: "output_matches"
pattern: "(healthz|health)"
rubric:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skill clearly relies on installing specific NuGet package(s), and rubric does not validate that at all. Are those packages really required, or agent can generate code building GET endpoint handlers from scratch?

@@ -0,0 +1,70 @@
scenarios:
- name: "Add health checks with Kubernetes probes"
prompt: "I need to add health checks to my ASP.NET Core API for Kubernetes deployment. It should check the database and Redis connections and have separate liveness and readiness endpoints."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prompt is overfitting for the name of skill. I dont imagine myself writing "i need to add health checks for MY ASPNETCORE API", I will simply ask agent "need to add health checks dependant on db" for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants