一键导入
reliability-scorecard
Deterministic procedure to evaluate Azure workloads against a fixed reliability rule pack and emit a fixed-format markdown report.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Deterministic procedure to evaluate Azure workloads against a fixed reliability rule pack and emit a fixed-format markdown report.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Deterministic procedure to watch an ARM deployment, evaluate a health gate, and automatically cancel + redeploy the last-known-good template on breach.
Deterministic procedure to find tag-non-compliant Azure resources, emit a fixed-format report, and (on explicit authorisation) deploy ARM patches to apply missing tags.
Deterministic procedure to inspect an ARM template, cross-reference affected resources via ARG, categorize each change, flag policy violations and dependency fan-out, and emit a fixed-format risk report.
Deterministic procedure to surface top cost-driving resources by querying ARG for new/resized resources in a time window, joined with owner tags, and emit a fixed-format markdown report.
Deterministic procedure to provision, monitor, and cancel pre-approved ARM golden-path template deployments with naming guardrails, tag enforcement, and compliance checks.
Deterministic procedure to compare a checked-in ARM template with live Azure state and emit a property-level drift report in markdown + JSON patch (RFC 6902) format.
| name | reliability-scorecard |
| description | Deterministic procedure to evaluate Azure workloads against a fixed reliability rule pack and emit a fixed-format markdown report. |
Inputs:
scope: name of a runbook under runbooks/<scope>.yaml. Defaults to prod.mode: one of scorecard (default), drilldown <workload>, remediate.az account show for the CLI fallback. Do not synthesize a probe ARG
query — that would violate "never invent ARG queries".
On failure, abort with: ABORT: Azure auth missing — sign in with az login or initialize the ARM MCP session.exports/ and exports/_run/ exist; create if missing.validate_query/execute_query MCP tools are present in
the runtime, use the MCP transport. Otherwise fall back to az graph query per
agent Hard Rule 11. Record the chosen transport in the run manifest (Step 2.7).runbooks/<scope>.yaml as raw text. If a sibling runbooks/<scope>.values.yaml
exists, parse it and substitute every ${key} token in the runbook text with the
corresponding value (lists/maps are inlined as YAML). Then parse the substituted
text as YAML. If <scope>.values.yaml is missing, abort with the literal message:
ABORT: runbooks/<scope>.values.yaml missing — copy <scope>.values.yaml.example and fill in real values.subscriptions[], workload_key (default resourceGroup),
rg_include[], rg_exclude[].workload_key is pinned to resourceGroup in v1. If the runbook specifies any
other value, abort with: ABORT: workload_key '<value>' not supported in v1 — use 'resourceGroup' (tag-based grouping is deferred to v2).rg_include / rg_exclude semantics (formal): both lists hold case-insensitive
substring patterns matched against the row's resourceGroup column.
rg_include is empty OR at least one include pattern
is a substring of the row's resourceGroup (case-insensitive), AND
(b) no rg_exclude pattern is a substring of the row's resourceGroup.rg_exclude always wins.resourceGroup is empty are dropped (counted as dropped_rows per rule).skills/reliability-scorecard/rules/rules.yaml. Compute SHA-256 of the file
contents; keep first 8 hex chars as ruleset_hash8. If the file cannot be read,
abort with: ABORT: rules.yaml unreadable.run_id = "RPS-" + UTC date YYYYMMDD + "-" + scope + "-" + ruleset_hash8.runbook_value_hash = SHA-256 of the post-substitution runbook YAML
(used in the run manifest, not the run_id).For each rule in rules.yaml in file order:
rule.kql is missing → record status: SKIPPED and continue.kql_t (transported form). Pre-condition: the kql block contains no
multi-line string literals and no // or /* */ comments (the v1 rule pack
satisfies this). Both validate and execute MUST use kql_t (never validate one
form and execute another).expected_columns by parsing the final | project ... segment of
kql_t: split each comma-separated term on = and take the left side as the
column name (or the whole term if no =), trimming whitespace. Example:
project id, name, resourceGroup, sku=sku.name → {id, name, resourceGroup, sku}.kql_t to validate_query (or to the CLI validate equivalent).
On parse error → status: INVALID, reason: parse-error, continue.kql_t to execute_query with page size 1000.
While the response carries a non-null skip_token, repeat with that token. Union
all pages. On transport error or timeout → status: INVALID,
reason: transport-error, continue (no retries).expected_columns (no extras like tags, properties,
kind — those signal a transport-mangled query that silently returned the full
ARG resource shape). Mismatch → status: INVALID, reason: result-schema-mismatch,
continue. This is the strongest defense against the silent-wrong-data class of bug.id MUST be non-empty and start with /subscriptions/. Mismatch →
status: INVALID, reason: result-id-malformed, continue.exports/_run/{run_id}/{rule_id}.json. Append a manifest entry to
exports/_run/{run_id}/manifest.json recording: run_id, scope,
ruleset_hash8, runbook_value_hash, subscriptions (sorted),
workload_key, transport (mcp or cli), and per-rule {status, row_count, page_count, dropped_rows}. Cached rows are pre-filter so downstream rg_include
changes do not invalidate the cache.rg_include / rg_exclude per Step 1.4 against the resourceGroup column.resourceGroup. Record per workload: {rule_id, weight, severity, failing_resource_count} where failing_resource_count is the count of distinct
id values in the workload's bucket (not the row count — multi-row finds like
R009/R010/R012 must not double-count a single resource).For each workload that appears in any rule's results:
score = max(0, 100 - sum(rule.weight for each rule where failing_resource_count > 0))
Round to integer. Track failed_rules list and top_gap = highest-weight failed
rule_id (ties broken by ascending rule_id).
scorecardtemplates/output-report.md.{{run_id}}, {{scope}}, {{generated_utc}} (ISO 8601 to seconds, UTC, Z suffix),
{{rules_total}}, {{rules_evaluated}}, {{rules_skipped}}, {{rules_invalid}},
{{workloads_total}}, {{ruleset_hash8}}.{{bottom10_table}} — markdown rows sorted ascending by score, ties by workload ascending. Limit to 10 rows. If fewer than 10 workloads, list all.{{failing_checks_table}} — one row per rule with failing_resource_count > 0,
sorted descending by weight, ties by rule_id.{{top3_gaps_block}} — three subsections for the three rule_ids with highest
(weight × failing_resource_count). Ties broken by rule_id ascending. If fewer than three
gap rule_ids exist, list as many as exist.exports/scorecard-{scope}-latest.md with the rendered report.exports/{run_id}.md with the same content.exports/scorecard-trend.csv. Header (create if missing):
run_id,generated_utc,scope,ruleset_hash8,workloads_total,avg_score,min_score,rules_failing.
If a row with the current run_id exists, replace it in-place (do not append a
duplicate). Otherwise append. Output contract: exactly one row per run_id.drilldown <workload>Snapshot semantics: drilldown explains the most recent scorecard snapshot for the
current (scope, ruleset_hash8). It does not re-query live Azure unless the cache is
missing or stale.
exports/_run/{run_id}/manifest.json for the latest scorecard run
matching the current (scope, ruleset_hash8, runbook_value_hash post-filter) — note
that cache rows are pre-filter, so a rg_include/rg_exclude change since the
scorecard run is safe.(scope, ruleset_hash8), abort with:
ABORT: no scorecard snapshot available for this scope+ruleset — run @scorecard run for scope <scope> first.templates/output-drilldown.md.rule_id,
severity, weight, failing_resource_count (distinct id count for this
workload), the verbatim multi-line KQL from rules.yaml (NOT the transport-collapsed
form — drilldown shows what's in the rule pack), and the first 25 distinct id
values for this workload.exports/drilldown-{scope}-{workload}.md (overwrite). Print. No CSV write.remediatescorecard run (locate via exports/_run/<run_id>/manifest.json;
re-run a scorecard pass if no snapshot is found), pick the three rule_ids with the
highest (weight × failing_resource_count), ties by rule_id ascending.rule.remediation_template. If null, report
"no template available for {{rule_id}}" and continue.create_template_deployment with the template file at
remediation/<remediation_template> and parameters drawn from the failing
resource list. Use mode = Incremental.templates/output-remediation.md with the deployment names + statuses.
Persist to exports/remediation-{run_id}.md (overwrite). Print.INVALID reasons (rule is excluded from scoring, recorded in the manifest, and counted
in rules_invalid):
parse-error — validate_query failed.transport-error — execute_query HTTP/timeout/auth failure.result-schema-mismatch — returned columns ≠ expected_columns (Step 2.6).result-id-malformed — at least one row's id is empty or not /subscriptions/-prefixed.truncated — pagination cap reached without draining skip_token (only if a hard
cap is configured; default = no cap).Other rules:
rules.yaml cannot be read, abort: ABORT: rules.yaml unreadable.# Reliability Posture Scorecard.run_id (upsert semantics — re-runs replace
the prior row in place).exports/scorecard-{scope}-latest.md always reflects the most recent run for that scope.exports/{run_id}.md is the immutable name-stamped copy of the same content.exports/_run/{run_id}/ is the per-run cache: {rule_id}.json per rule (pre-filter
raw rows) plus manifest.json. Drilldown reuses this; remediate reads from it.failing_resource_count is a distinct id count in every context (per-rule,
per-workload, in the failing-checks table, and in the top-3 gaps math).