Validation
Validators are automated checks that run against a stage's output the moment an execution finishes. They're how a stage refuses to pass malformed work downstream, and how you let a stage approve itself with confidence. Each execution is validated on its own, so in a multi-agent attempt every candidate gets its own verdict.
You declare validators in a stage's validators list. Ringmaster ships three built-in types, plus a fourth that runs a script you provide.
artifact_exists
Asserts that one or more named files were produced and aren't empty.
validators:
- type: artifact_exists
artifacts: [specification.md, api-reference.md]
| Field | Required | Notes |
|---|---|---|
artifacts | yes | The filenames that must exist in the execution's output. |
markdown_sections
Asserts that a Markdown file contains specific headings. Matching is case-insensitive and works at any heading level.
validators:
- type: markdown_sections
artifact: specification.md
required: [Overview, Requirements, Assumptions, Non-Goals]
| Field | Required | Notes |
|---|---|---|
artifact | yes | The Markdown file to check. |
required | yes | The heading texts that must be present. |
This is the workhorse for spec- and plan-shaped stages: it turns "the output should cover X, Y, and Z" into a check the stage actually enforces.
json_schema
Asserts that a file parses as JSON and validates against a JSON Schema you keep in the workspace.
validators:
- type: json_schema
artifact: result.json
schema: schemas/result.schema.json
| Field | Required | Notes |
|---|---|---|
artifact | yes | The file to parse as JSON. |
schema | yes | Path to a JSON Schema file, relative to the workflow (or absolute). Must resolve inside the workspace. |
Use it when a downstream stage or an external tool has to parse the output and you need to guarantee its shape.
custom_script
Runs an executable you supply and treats its exit code as the verdict: 0 passes, anything else fails. It's how you enforce a check the built-ins don't cover, like a linter, a type-checker, or a project-specific script. This one is a Professional feature, and it runs only in the Direct build. The App Store build can't run a custom script, and a workflow that declares one is rejected there rather than skipped quietly.
validators:
- type: custom_script
script: checks/validate.sh
timeout: 30
| Field | Required | Notes |
|---|---|---|
script | yes | Path to the executable, relative to the workflow (or absolute). Must resolve inside the workspace. |
timeout | no | Seconds to wait before the script is killed and the check fails. Defaults to 60. |
The script runs in the stage's output directory, so it can read the files the stage just produced. It's run directly rather than through a shell, so it needs to be executable (chmod +x) and start with a working interpreter line. The check is fail-closed: a non-zero exit, a script that won't start, or one that runs past its timeout all count as a failure at the validator's severity, which is blocking unless you set it otherwise. When a script fails, the tail of its output is shown with the result so you can see why.
Because a custom script runs arbitrary code on your Mac with your privileges, Ringmaster asks before it runs one for the first time, naming the script and waiting for you to allow it. Your answer is remembered for that version of the workflow; edit the script or the workflow and you'll be asked again. To withdraw consent, right-click the workflow in the Workflows list and choose Revoke Custom Validator Consent. A headless CLI run has no one to ask, so it refuses custom scripts unless you pass ringmaster run --allow-custom-scripts, which is your way of saying you've reviewed the script yourself. See The ringmaster CLI.
Severity
Every validator has a severity. Add it with severity:; the default is blocking.
| Severity | Effect |
|---|---|
blocking | A failure prevents auto-approval. This is the default. |
error | Shown as an error in the UI, but doesn't block. |
warning | Shown as a warning. |
info | Informational. |
validators:
- type: markdown_sections
artifact: spec.md
required: [Overview, Requirements]
severity: blocking
- type: markdown_sections
artifact: spec.md
required: [Open Questions]
severity: warning # nice to have, won't block
How validators meet the gate
Validators and the review gate work together:
- A stage with
review.required: falseauto-approves only if it succeeds and noblockingvalidator fails. A blocking failure stops it for you regardless. - A stage with the review gate on always stops for you; the validator results are shown alongside the output so you can see, at a glance, whether each candidate met its contract before you decide.
In a multi-agent attempt, the comparison table shows each candidate's validation verdict in its own column, handy when you're choosing which one to promote.
Checking a workflow's validators ahead of time
ringmaster validate confirms your validator blocks are well-formed (known types, required fields present, schema files that actually exist and resolve inside the workspace) before you ever run the workflow. See The ringmaster CLI.