Agent skill

write-canary-transformations

Write correct transform blocks for Mission Control canary checks including fan-out, inline, and generated canary patterns. Use when adding transformations to canary checks, splitting a single check into multiple results, modifying check output, or generating child canaries from discovered resources.

Stars 0
Forks 0

Install this agent skill to your Project

npx add-skill https://github.com/flanksource/claude-code-plugin/tree/main/skills/write-canary-transformations

SKILL.md

Write Canary Transformations

Goal

Generate correct, production-ready Canary transform blocks from user intent.


Quick Decision Tree

Use this to pick the right transform pattern:

  1. Need one check result per item in response?
    • Use fan-out transform (return JSON array of objects, each with name).
  2. Need to modify only the current check result?
    • Use inline transform (return one JSON object without name).
  3. Need to generate new canary/canaries from discovered resources?
    • Use canary transform (return object/array with top-level spec).

Golden Rules

  1. Prefer transform.expr (CEL) by default over transform.javascript and transform.template.
    • This is a convention for consistency and easier review, not a strict requirement.
    • If JS/template is a better fit for the case, use it.
  2. End CEL transforms with .toJSON().
  3. For fan-out transforms, always set deterministic name.
  4. Set pass explicitly in transformed checks (do not rely on defaults).
  5. Use deletedAt when events can resolve/disappear.
  6. Use markFailOnEmpty: true when empty output should fail the check.
  7. Keep check names stable across runs to avoid churn.

Output Contracts

A) Fan-out transformed checks

Return a JSON array (or object) of transformed check entries.

Field Required Description Example
name Yes Check name. Keep deterministic across runs. db/instance-1
pass Recommended Explicit pass/fail status. true
message No User-facing summary. Replication lag within threshold
description No Longer explanation/context. Replica is healthy
labels No Labels for filtering/relationships. { 'env': 'prod', 'team': 'platform' }
namespace No Override check namespace. production
icon No UI icon override. alert
duration No Duration in milliseconds. 1200
start No Start time. 2026-02-13T12:00:00Z
detail No Structured detail payload. { 'raw': r }
data No Additional arbitrary data. { 'source': 'prometheus' }
metrics No Emitted metrics from transform. [{ 'name': 'lag', 'type': 'gauge', ... }]
deletedAt No Mark transformed check as resolved/deleted at a time. r.endsAt
transformDeleteStrategy No Behavior when transformed check disappears (Mark*,Ignore). MarkHealthy

B) Inline transformed result

Return a single JSON object and omit name.

Field Required Description Example
name Must omit If set, this becomes fan-out behavior. omit
pass No Override pass/fail status. json.status == 'ok'
message No Override message. 'status=' + string(json.status)
description No Override description. 'Health summary'
error No Override error text. 'response missing key'
detail No Replace detail payload. { 'status': json.status }
data No Merge additional data into result data. { 'apiVersion': json.version }
duration No Override duration (milliseconds). 1200
metrics No Add metrics emitted from transform. [{ 'name': 'items', 'type': 'gauge', 'value': 10 }]

C) Transform into canary/canaries

Return either one canary object or an array of canary objects.

Field Required Description Example
name Yes Child canary name. generated-http-canary
namespace No Child canary namespace. default
spec Yes Full child canary spec. { 'schedule': '@every 5m', 'http': [...] }

Canonical Snippets

1) Fan-out alerts into checks

yaml
transform:
  expr: |
    results.alerts.map(r, {
      'name': r.name + r.fingerprint,
      'labels': r.labels,
      'icon': 'alert',
      'pass': false,
      'message': r.message,
      'description': r.message,
      'deletedAt': has(r.endsAt) ? r.endsAt : null
    }).toJSON()

2) Prometheus series to checks

yaml
transform:
  expr: |
    dyn(results).map(r, {
      'name': r.job,
      'namespace': 'namespace' in r ? r.namespace : '',
      'labels': r.omit(['value', '__name__']),
      'pass': r.value > 0,
      'message': 'job=' + r.job
    }).toJSON()

3) Inline transform (no new checks)

yaml
transform:
  expr: |
    {
      'pass': json.status == 'ok',
      'message': 'status=' + string(json.status),
      'detail': {
        'status': json.status,
        'checkedAt': string(time.Now())
      }
    }.toJSON()

4) Generate child canary from discovery

yaml
transform:
  expr: |
    {
      'name': 'generated-http-canary',
      'namespace': canary.namespace,
      'spec': {
        'schedule': '@every 5m',
        'http': dyn(results).map(r, {
          'name': r.Object.metadata.namespace + '/' + r.Object.metadata.name,
          'url': 'https://' + r.Object.spec.rules[0].host
        })
      }
    }.toJSON()

5) Generate multiple child canaries (array output)

yaml
transform:
  expr: |
    dyn(results).map(r, {
      'name': 'http-' + r.Object.metadata.name,
      'namespace': r.Object.metadata.namespace,
      'spec': {
        'schedule': '@every 5m',
        'http': [{
          'name': r.Object.metadata.name,
          'url': 'https://' + r.Object.spec.rules[0].host
        }]
      }
    }).toJSON()

6) Empty output should fail

yaml
markFailOnEmpty: true
transform:
  expr: |
    dyn(results.rows).map(r, {
      'name': r.id,
      'pass': true
    }).toJSON()

Deletion / Lifecycle Controls

Use transformDeleteStrategy on the parent check when transformed checks may disappear.

Recommended values:

  • MarkHealthy
  • MarkUnhealthy
  • Ignore

Example:

yaml
transformDeleteStrategy: MarkHealthy

Stateful Transform Patterns

Use prior run state

  • last_result() gives previous result context.
  • Useful for cursors/time windows.

Pattern:

yaml
transform:
  expr: |
    {
      'detail': {
        'max': string(results.?newest.modified.orValue(last_result().results.?max.orValue('now-60d')))
      }
    }.toJSON()

Use outputs from dependency checks

If checks use dependsOn, you can use outputs.<checkName>... in expressions/tests.


Common Mistakes to Avoid

  1. Returning multiple transformed entries without name.
  2. Forgetting .toJSON() in CEL expressions.
  3. Non-deterministic names (e.g., random UUID every run).
  4. Forgetting to set pass for fan-out checks.
  5. Returning empty list unintentionally without markFailOnEmpty.
  6. Mixing canary-transform output (spec) with check-transform output in same object.

Authoring Workflow

When user asks for a transformation:

  1. Identify source payload shape (results, json, rows, messages).
  2. Pick transform mode (fan-out / inline / canary).
  3. Build minimal output contract.
  4. Add pass, message, stable name.
  5. Add lifecycle fields (deletedAt, transformDeleteStrategy) if needed.
  6. Return full YAML block ready to paste.

If user provides sample payload, always base transform logic directly on that payload.


References

Expand your agent's capabilities with these related and highly-rated skills.

flanksource/claude-code-plugin

troubleshooting-health-checks

Debugs and troubleshoots Mission Control health checks by analyzing check configurations, reviewing failure patterns, and identifying root causes. Use when users ask about failing health checks, mention specific health check names or IDs, inquire why a health check is failing or unhealthy, or need help understanding health check errors and timeouts.

0 0
Explore
flanksource/claude-code-plugin

write-canary-tests

Write correct test blocks and assertions for Mission Control canary health checks. Use when creating canaries that need pass/fail conditions, adding test expressions, or writing assertions based on HTTP status, JSON response, exec output, or Kubernetes health.

0 0
Explore
flanksource/claude-code-plugin

troubleshooting-notifications

Investigates Mission Control notifications to identify root causes and provide remediation. Use when users mention notification IDs, ask about alerts or notifications, request help understanding "why did I get this notification", want to troubleshoot a specific alert, or ask about notification patterns and history. This skill retrieves notification details, analyzes historical patterns, routes to resource-specific troubleshooting (config items or health checks), correlates findings, and delivers actionable remediation steps with prevention recommendations.

0 0
Explore
flanksource/claude-code-plugin

troubleshooting-config-item

Troubleshoots infrastructure and application configuration items in Mission Control by diagnosing health issues, analyzing recent changes, and investigating resource relationships. Use when users ask about unhealthy or failing resources, mention specific config items by name or ID, inquire about Kubernetes pods/deployments/services, AWS EC2 instances/volumes, Azure VMs, or other infrastructure components. Also use when investigating why a resource is down, stopped, degraded, or showing errors, or when analyzing what changed that caused an issue.

0 0
Explore
flanksource/claude-code-plugin

promotion-eval-create

Create a promotion evaluation template for any system by gathering requirements through structured questions and generating a reusable evaluation skill. Use when users ask to create a promotion check, release readiness evaluation, environment health template, or want to build a custom evaluation workflow for systems beyond Mission Control.

0 0
Explore
flanksource/claude-code-plugin

promotion-eval-mission-control

Evaluates a Mission Control environment's platform health for release or promotion readiness. Checks health check pipelines, config scrapers, background jobs, notifications, event queues, and MC infrastructure. Use for pre-release checks, environment promotion, or environment status. Triggers: "check environment health", "is it ready for release", "pre-release health check", "evaluate environment", "promotion readiness", "environment status"

0 0
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results