From yci
Produce a typed blast-radius label (tenants, services, devices, dependencies, downstream consumers, RTO band, confidence, coverage gaps) for a proposed change against the active customer's inventory. Use when the user runs /yci:blast-radius, asks "what breaks if I change X", needs impact analysis before a CAB submission, or needs the structured JSON label consumed by yci:network-change-review, yci:mop, yci:evidence-bundle, and the change-window-gate hook. Reads the active customer profile's inventory.adapter (file minimum; netbox stub).
How this skill is triggered — by the user, by Claude, or both
Slash command
/yci:blast-radiusThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill produces a typed blast-radius label for a proposed change against the
references/change-input-schema.mdreferences/error-messages.mdreferences/file-adapter-layout.mdreferences/label-schema.jsonreferences/label-schema.mdscripts/adapter-file.shscripts/reason.shscripts/render-markdown.shtests/fixtures/change-cascade.yamltests/fixtures/change-simple.yamltests/fixtures/change-unknown-target.yamltests/fixtures/expected-inventory.jsontests/fixtures/expected-label-cascade.jsontests/fixtures/expected-label-simple.jsontests/fixtures/expected-label-unknown.jsontests/fixtures/inventory-other-customer/dependencies.yamltests/fixtures/inventory-other-customer/devices/other-edge-01.yamltests/fixtures/inventory-other-customer/services/other-service.yamltests/fixtures/inventory-other-customer/tenants/other-tenant.yamltests/fixtures/inventory-widgetcorp/dependencies.yamlThis skill produces a typed blast-radius label for a proposed change against the
active customer's inventory. Given a change-input file and the customer's normalized
inventory, it runs a structured reasoning pass to identify directly affected devices,
services, tenants, dependencies, and downstream consumers, assigns an RTO band and a
confidence score, and flags coverage gaps where inventory data is insufficient to
reason. It does NOT mutate any data (no writes to inventory or state outside the
artifacts directory), it does NOT call vendor MCPs or live device APIs, and it does
NOT approve or reject changes — those decisions belong to the downstream consumers
of the label (yci:cab-prep, yci:mop, the change-window-gate hook).
--change-file <path>)The primary input is a change-input file in YAML (default) or JSON format. The
file extension determines the parser: .json uses the JSON parser; any other
extension (including .yaml and .yml) uses the YAML parser.
The full schema for this file is documented in references/change-input-schema.md.
Required fields at minimum:
change_id — unique identifier for the change record (e.g., WIDGET-CR-2024-A)change_type — enum classifying the change categorysummary — human-readable description of the changetargets — list of inventory identifiers the change will touchIf --change-file is omitted entirely, the skill exits 1 with
br-missing-change-file. If the path is provided but does not exist or is
unreadable, the skill exits 1 with br-change-file-missing.
--adapter <name> — forces a specific inventory adapter, overriding the
inventory.adapter value in the active customer profile. Known values:
file, netbox, nautobot, servicenow-cmdb, infoblox. Only file is
fully implemented; netbox, nautobot, servicenow-cmdb, and infoblox
exit 2 with br-adapter-not-implemented and point to the stub in
_shared/inventory-adapters/<name>/ADAPTER.md. Any other value exits 2
with br-unknown-adapter.--data-root <path> — overrides the data-root resolution chain (see Data Root
section in yci:customer-profile). Passed directly to resolve-data-root.sh.--format json|markdown|both — controls output format (default json). See
Outputs section.--output <path> — explicit output path. When omitted with --format both,
the skill writes two artifact files under
<data-root>/artifacts/<customer>/blast-radius/. When provided, the path must
resolve under <data-root>/artifacts/<customer>/; paths outside that boundary
are rejected with br-output-path-refused (exit 1).json (default)The blast-radius label JSON is written to stdout, or to --output if provided.
The label schema is fully documented in references/label-schema.md and
references/label-schema.json. Key top-level fields (names and enum values
mirror references/label-schema.json verbatim):
schema_version — label schema version (integer, currently 1)change_id — echoed from the change-inputcustomer — active customer IDinventory_adapter — adapter that produced the inventory
(file | netbox | nautobot | servicenow-cmdb | infoblox | none)inventory_source_fingerprint — sha256:<64-hex> digest of the
inventory snapshot used for this reasoning passgenerated_at — RFC3339 / ISO-8601 UTC timestamptenants — list of tenant IDs affectedservices — list of service objects (id, criticality, rto_band,
optional owner_tenant) affecteddirect_devices — list of device objects (id, role, optional site)
directly targeted by the changedependencies — edges walked during reasoning (from, to, type)downstream_consumers — services and tenants consuming the targeted
resources (id, kind, distance)rto_band — aggregate recovery-time objective band
(lt-5m | 5m-1h | 1h-4h | gt-4h | unknown)confidence — reasoning confidence score (high | medium | low)coverage_gaps — list of gap objects where inventory data was insufficientmarkdownThe label JSON is piped through render-markdown.sh to produce a human-readable
impact summary. The renderer reads $YCI_ACTIVE_REGIME to apply regime-aware
formatting (HIPAA, PCI, SOX, etc.). When regime is none or commercial, the
environment variable is exported as empty. Output goes to stdout or --output.
bothTwo artifact files are written to disk:
<data-root>/artifacts/<customer>/blast-radius/<change_id>.json<data-root>/artifacts/<customer>/blast-radius/<change_id>.mdBoth paths are printed to stdout (one per line, prefixed blast-radius:).
When --output is provided alongside --format both, it is treated as an error
and the skill exits 1 with br-output-conflict — a single --output path
cannot receive both JSON and markdown outputs. Omit --output to use the
default artifacts location.
The skill orchestrates the three backing scripts in sequence. Each step propagates non-zero exit codes verbatim — the skill does not reformat errors from upstream scripts.
Step 1 — Parse flags.
Validate --format against {json, markdown, both}. Any other value exits 2
with br-format-invalid. Default to json if --format is absent.
Step 2 — Resolve data-root.
bash ${CLAUDE_PLUGIN_ROOT}/skills/_shared/scripts/resolve-data-root.sh [--data-root <path>]
Capture the canonicalized path on stdout. Propagate any non-zero exit verbatim.
Step 3 — Resolve active customer.
bash ${CLAUDE_PLUGIN_ROOT}/skills/customer-profile/scripts/resolve-customer.sh --data-root <data-root>
Capture the customer ID on stdout. Propagate any non-zero exit verbatim. The skill refuses to run without an active customer — there is no fallback.
Step 4 — Load profile.
bash ${CLAUDE_PLUGIN_ROOT}/skills/customer-profile/scripts/load-profile.sh <data-root> <customer>
Capture the normalized profile JSON on stdout. Propagate exit codes verbatim (exit 1 for missing profile, exit 2 for schema violations, exit 3 for runtime errors including missing pyyaml).
Step 5 — Pick adapter.
If --adapter was supplied, use that value. Otherwise read profile.inventory.adapter
from the loaded profile JSON.
file → proceed to Step 6.netbox, nautobot, servicenow-cmdb, or infoblox → exit 2
with br-adapter-not-implemented, pointing to the stub at
${CLAUDE_PLUGIN_ROOT}/skills/_shared/inventory-adapters/<adapter>/ADAPTER.md.br-unknown-adapter.Step 6 — Resolve inventory path.
Use profile.inventory.path if set and non-empty. Otherwise default to
<data-root>/inventories/<customer>/. Canonicalize to an absolute path. Pass the
canonical path as the sole positional argument to adapter-file.sh:
bash ${CLAUDE_PLUGIN_ROOT}/skills/blast-radius/scripts/adapter-file.sh <inventory-root>
Capture normalized inventory JSON on stdout. Propagate non-zero exits verbatim.
Step 7 — Load change file.
Read the --change-file <path> argument. If missing → exit 1 with
br-missing-change-file. If path is provided but unreadable → exit 1 with
br-change-file-missing. Detect format: if the extension is .json, parse as
JSON; otherwise parse as YAML using python3 -c "import yaml, json, sys; ...".
A parse failure exits 2 with br-change-file-malformed. Validate required fields
(change_id, change_type, summary, targets); a missing field or bad
change_type enum exits 2 with br-change-file-schema.
Step 8 — Build payload and run reasoner.
Construct the payload object {"inventory": <inventory-json>, "change": <change-json>, "customer": "<customer>"} and pipe it to reason.sh:
echo '<payload>' | bash ${CLAUDE_PLUGIN_ROOT}/skills/blast-radius/scripts/reason.sh
Capture the label JSON on stdout. Propagate non-zero exits verbatim.
Step 9 — Emit outputs per --format.
json → write label JSON to stdout, or to --output if provided.markdown → export YCI_ACTIVE_REGIME=<profile.compliance.regime> (export as
empty string if regime is none or commercial); pipe label JSON into
render-markdown.sh; write rendered output to stdout or --output.both → create <data-root>/artifacts/<customer>/blast-radius/ if it does not
exist; write <change_id>.json and <change_id>.md there; print both paths to
stdout prefixed blast-radius:.Exit-code convention (mirrors references/error-messages.md):
| Exit | Meaning |
|---|---|
| 0 | success |
| 1 | user-input error or missing resource (file not found, no customer) |
| 2 | schema violation (bad format flag, bad change file, unknown adapter) |
| 3 | runtime / environment error (pyyaml missing, permission denied) |
The full error catalogue with literal message text is in references/error-messages.md.
Errors from adapter-file.sh, reason.sh, render-markdown.sh,
resolve-customer.sh, load-profile.sh, and resolve-data-root.sh are surfaced
verbatim — the skill does NOT reformat upstream errors.
/yci:switch widget-corp
/yci:blast-radius --change-file ./change.yaml --format both
# -> blast-radius: /Users/.../widget-corp/blast-radius/WIDGET-CR-2024-A.json
# -> blast-radius: /Users/.../widget-corp/blast-radius/WIDGET-CR-2024-A.md
references/label-schema.md — blast-radius label field definitionsreferences/label-schema.json — JSON Schema for machine validationreferences/change-input-schema.md — change-input file field definitionsreferences/file-adapter-layout.md — inventory directory layout expected by adapter-file.shreferences/error-messages.md — canonical error copy for this skillscripts/adapter-file.sh — normalizes a file-system inventory root to JSONscripts/reason.sh — produces the blast-radius label from inventory + change payloadscripts/render-markdown.sh — renders a label JSON to human-readable markdown../customer-profile/scripts/resolve-customer.sh — 4-tier customer resolver../customer-profile/scripts/load-profile.sh — profile YAML loader and validator../_shared/scripts/resolve-data-root.sh — data-root resolution helperyci:mop, which consumes a blast-radius label as input
to produce a method of procedure document.yci:cab-prep, which formats the label and
supporting evidence into the CAB package format.yci:evidence-bundle to collect the label
alongside audit artifacts.resolve-customer.sh — there is no override or fallback.adapter-file.sh rejects paths that canonicalize outside the resolved inventory
root, preventing symlink-based path-escape attacks.<data-root>/artifacts/<customer>/ — consistent
with PRD §5.1 customer-scoped data isolation. The --output override is validated
against this boundary and rejected with br-output-path-refused if it escapes it.npx claudepluginhub yandy-r/claude-infra-plugins --plugin yciGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.