| name | validate-pipeline |
| description | Lint a pipeline.yaml — schema check, DAG acyclicity, referenced-skill existence, precondition kind registration. Pure linter — prints a report, writes no files. Heartbeat does not require validation to have run; this is a developer convenience. |
| argument-hint | <pipeline-slug> |
| allowed-tools | Read, Bash, Glob, Grep |
| user-invocable | true |
| metadata | {"mirror":"abilities@70c1e60 plugins/agent-dev/skills/validate-pipeline","version":"1.3","created":"2026-05-23T00:00:00.000Z","author":"Ability.ai","changelog":["1.3: Stages with agent: <name> (remote playbook, add-pipeline 1.7) skip the local skill-existence check","1.2: Step 2 no longer hard-requires the legacy heartbeat.skill field (it failed the canonical template, which ships heartbeat.name/cron/message) — now requires heartbeat.message + heartbeat.name; Step 7 notes an uninstalled-skill message fails loudly as SKILL_NOT_FOUND at runtime (trinity#1410)","1.1: Heartbeat sanity matches the fixed schema (heartbeat.name/cron/message; 5-field cron — Trinity's scheduler format). heartbeat.pre_check now raises a WARNING: the pre-check hook is removed (Trinity's agent-global hook has no fire vocabulary — any stdout replaces the calling schedule's message); legacy skill/schedule_name fields get a rename note","1.0: Initial version — read-only pipeline.yaml linter checking schema, DAG acyclicity, referenced-skill existence, and precondition kinds; writes no files"]} |
| category | agent-development |
Validate Pipeline
ℹ️ First, set expectations: before anything else, print one short line with this skill's version and its most recent change — the top entry of metadata.changelog above — e.g. validate-pipeline vX.Y — recent: <summary>. Then proceed.
Read-only linter. Verify a pipeline.yaml is structurally sound. Surfaces errors and warnings; writes no files.
Run this:
- After any manual edit to
pipeline.yaml
- Automatically at the end of
/add-pipeline and /add-pipeline-stage
- Before deploying the agent to a new environment
The heartbeat (pipeline-tick) reads pipeline.yaml directly each tick. It does not require this skill to have run. If you ship a broken pipeline.yaml, the heartbeat will fail loudly on the next tick — running the linter just gets you that feedback sooner.
Process
Step 1: Resolve target
Expect <pipeline-slug> as the single positional argument. If missing, list pipelines and prompt.
Validate projects/<slug>/pipeline.yaml exists.
Step 2: Schema check
Required top-level keys: schema_version, pipeline_id, name, stages, heartbeat.
PIPELINE_FILE="projects/$SLUG/pipeline.yaml"
SCHEMA=$(yq '.schema_version // 0' "$PIPELINE_FILE")
[ "$SCHEMA" = "1" ] || error "schema_version must be 1 (got: $SCHEMA)"
ID=$(yq '.pipeline_id // ""' "$PIPELINE_FILE")
[ "$ID" = "$SLUG" ] || error "pipeline_id ($ID) doesn't match directory slug ()"
STAGE_COUNT=$(yq )
[ -gt 0 ] || error
yq >/dev/null || error
yq >/dev/null || error
yq >/dev/null || error