Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Service health monitoring, endpoint validation, and CVE source auditing.
.claude/skills/notque-service-health-check/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 138% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 185% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 267% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 154% | 0% |
This skill provides deterministic service health monitoring using the Discover-Check-Report pattern. It finds services, gathers health signals from multiple sources (process table, health files, port binding), and produces actionable reports identifying degraded or failed services.
Core principle: Health assessment is evidence-based. Never report a service healthy without verifying process status independently of health file content. Never assume a running process is functional — always cross-check against health files and port binding.
| Signal | Load These Files | Why | |---|---|---| | Endpoint validation request | references/endpoint-validator.md | Full endpoint validation methodology | | Security header WARNs, HSTS/CSP/X-Frame issues | references/security-headers.md | Deep security header reference | | Config errors, hardcoded IPs, timeout problems | references/endpoint-config-preferred-patterns.md | Endpoint config patterns | | 401/403 failures, Bearer/API-key/cookie auth | references/auth-endpoint-patterns.md | Auth endpoint patterns | | CVE source audit request | references/cve-source-check.md | Full CVE source check methodology | | CVE registry schema questions | references/registry-schema.md | Registry shape and entry format | | CVE source URL verification | references/source-verification.md | HEAD-check semantics | | CVE report format questions | references/output-formats.md | JSON schema and Markdown sections |
Goal: Identify all services to check before running any health probes.
Step 1: Locate service definitions
Search for service configuration in this order:
services.json in project rootStep 2: Build service manifest
For each service, establish:
markdown## Service Manifest | Service | Process Pattern | Health File | Port | Stale Threshold | |---------|----------------|-------------|------|-----------------| | api-server | gunicorn.*app:app | /tmp/api_health.json | 8000 | 300s | | worker | celery.*worker | /tmp/worker_health.json | - | 300s | | cache | redis-server | - | 6379 | - |
Validation constraints:
Step 3: Validate manifest
Confirm each entry passes the constraints above. If a pattern is too broad, use ps aux | grep to identify distinguishing arguments, then update the pattern.
Gate: Service manifest complete with at least one service. Proceed only when gate passes.
Goal: Gather health signals for every service in the manifest. Always check process status independently of health file content—a running process and a healthy health file are separate signals.
Step 1: Check process status
For each service, run process check:
bashpgrep -f "<process_pattern>"
Record: running (true/false), PIDs, process count.
Rationale: Process existence is the primary signal. A missing process always means the service is DOWN. A running process alone is insufficient—the service may have crashed or failed to bind to its port.
Step 2: Parse health files (if configured)
Read and parse JSON health files. Evaluate:
Critical constraint: Never trust health file content alone. The file could be stale from before a process crash. Always verify:
Step 3: Probe ports (if configured)
Check if expected ports are listening:
bashss -tlnp "sport = :<port>"
Rationale: Verify ports are actually bound. A process can start but fail to bind to its configured port—that is effectively a DOWN state, not HEALTHY.
Step 4: Evaluate health per service
Apply this decision tree (constraints embedded in logic):
Gate: All services evaluated with evidence-based status. No status is determined without concrete signal (process check, health file, or port probe). Proceed only when gate passes.
Goal: Produce structured, actionable health report with specific remediation commands.
Step 1: Generate summary
SERVICE HEALTH REPORT
=====================
Checked: N services
Healthy: X/N
RESULTS:
service-name [OK ] HEALTHY PID 12345, uptime 2d 4h
background-worker [WARN] WARNING Health file stale (15 min)
cache-service [DOWN] DOWN Process not found
RECOMMENDATIONS:
background-worker: Restart recommended - health file not updated in 900s
cache-service: Start service - process not running
SUGGESTED ACTIONS:
systemctl restart background-worker
systemctl start cache-serviceStep 2: Set exit status
Step 3: Present to user
Gate: Report delivered with actionable recommendations for all non-healthy services.
User says: "Are all services up?" Actions:
Result: Clean report, no action needed
User says: "The background worker seems stuck" Actions:
Result: Specific diagnosis with actionable command
Cause: No services.json, docker-compose, or systemd units discovered Solution:
Cause: Pattern too broad (e.g., "python" matches all Python processes) Solution:
ps aux | grep to identify distinguishing argumentsCause: Malformed JSON, permissions issue, or file being written during read Solution:
ls -laServices should write health files as:
json{ "timestamp": "ISO8601, updated every 30-60s", "status": "healthy|degraded|error", "connection": "connected|disconnected|reconnecting", "last_activity": "ISO8601 of last meaningful action", "running": true, "uptime_seconds": 12345, "metrics": {} }
| Constraint | Rationale | Application | |-----------|-----------|-------------| | Process status verified independently of health file | Running process ≠ functional service | Always check process before trusting health file | | Health file staleness detected by timestamp freshness | File could be stale from before crash | Check timestamp against 300s (configurable) threshold | | Port binding verified when configured | Process running doesn't mean port is bound | Always verify expected port listening when port specified | | No auto-restart without explicit flag | Restart masks root cause | Report findings first; only execute restart if user flags it | | Narrow process patterns required | "python" matches all processes, giving false matches | Use full paths or specific args; validate with ps aux \| grep | | Evidence-based status only | Status must have supporting signal | No status without concrete evidence (process, health file, or port) |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 16,785 | 2,526 | -85% | 1 | 1 | 0% | 2,984 | 2,577 | -14% | 0 | 0 | — |
case-08 | pass→pass | 12,322 | 6,501 | -47% | 1 | 1 | 0% | 1,839 | 3,390 | +84% | 0 | 0 | — |
case-02 | fail→fail | 8,008 | 5,244 | -35% | 1 | 1 | 0% | 392 | 2,598 | +563% | 0 | 0 | — |
case-03 | fail→fail | 11,147 | 7,036 | -37% | 1 | 1 | 0% | 2,302 | 2,663 | +16% | 0 | 0 | — |
case-04 | pass→pass | 7,300 | 5,598 | -23% | 1 | 1 | 0% | 1,213 | 3,252 | +168% | 0 | 0 | — |
case-05 | fail→pass | 8,288 | 5,580 | -33% | 1 | 1 | 0% | 1,369 | 3,264 | +138% | 0 | 0 | — |
case-06 | fail→pass | 12,011 | 5,159 | -57% | 1 | 1 | 0% | 1,938 | 3,233 | +67% | 0 | 0 | — |
case-07 | fail→pass | 7,531 | 5,565 | -26% | 1 | 1 | 0% | 1,158 | 3,296 | +185% | 0 | 0 | — |
case-09 | pass→pass | 10,381 | 2,241 | -78% | 1 | 1 | 0% | 1,567 | 2,659 | +70% | 0 | 0 | — |
case-10 | fail→pass | 5,426 | 4,129 | -24% | 1 | 1 | 0% | 832 | 3,056 | +267% | 0 | 0 | — |
case-11 | fail→pass | 7,763 | 3,439 | -56% | 1 | 1 | 0% | 1,145 | 2,909 | +154% | 0 | 0 | — |
case-12 | fail→pass | 7,763 | 3,520 | -55% | 1 | 1 | 0% | 1,218 | 2,959 | +143% | 0 | 0 | — |
case-13 | fail→pass | 13,941 | 5,102 | -63% | 1 | 1 | 0% | 2,179 | 3,104 | +42% | 0 | 0 | — |
case-14 | fail→pass | 8,582 | 3,026 | -65% | 1 | 1 | 0% | 1,348 | 2,808 | +108% | 0 | 0 | — |
case-15 | pass→pass | 4,690 | 2,782 | -41% | 1 | 1 | 0% | 779 | 2,719 | +249% | 0 | 0 | — |
case-16 | fail→pass | 13,374 | 7,519 | -44% | 1 | 1 | 0% | 2,225 | 3,601 | +62% | 0 | 0 | — |
case-17 | pass→pass | 6,529 | 2,428 | -63% | 1 | 1 | 0% | 1,071 | 2,695 | +152% | 0 | 0 | — |
case-18 | fail→pass | 7,628 | 4,918 | -36% | 1 | 1 | 0% | 1,338 | 3,114 | +133% | 0 | 0 | — |
case-19 | fail→pass | 13,403 | 5,483 | -59% | 1 | 1 | 0% | 2,274 | 3,316 | +46% | 0 | 0 | — |
case-20 | pass→pass | 11,742 | 9,112 | -22% | 1 | 1 | 0% | 2,065 | 4,022 | +95% | 0 | 0 | — |
case-21 | pass→pass | 8,019 | 6,818 | -15% | 1 | 1 | 0% | 1,533 | 3,626 | +137% | 0 | 0 | — |
case-22 | pass→pass | 4,945 | 9,329 | +89% | 1 | 1 | 0% | 1,078 | 4,076 | +278% | 0 | 0 | — |
case-23 | fail→pass | 4,527 | 3,756 | -17% | 1 | 1 | 0% | 919 | 2,945 | +220% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 21 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +52 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.