> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://onepin.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://onepin.ai/docs/_mcp/server.

# Validate every line

> Build a fully validated Onepin pipeline — chain the Accuracy, Naturalness, Noise, and Pronunciation validators with retry loops so every exported line has cleared every bar.

"It produced audio" isn't the bar — "every line cleared the checks" is. Onepin has four [validators](/docs/workflow/validators); wire them and a line is delivered only after it passes **accuracy** (said the words), **naturalness** (sounds human), **noise** (clean audio), and — on English branches — **pronunciation** (every word said correctly, sound by sound). Lines that miss a bar regenerate automatically.

## The shape

Chain the validators after the Generator, each `fail` wired back to it:

```
        ┌──────────── fail ─────────────┬──────────────┐
        ▼                               │              │
   Generator ──▶ Accuracy ─pass─▶ Naturalness ─pass─▶ Noise ─pass─▶ Export
```

Wire it on the canvas, or run a template that ships with validation. Each validator keeps its **own** retry budget; a line failing several checks in one round regenerates **once**, not once per check.

## Set the bars

Each validator takes a `threshold` (the score to beat) and `max_retries` (regeneration budget):

```python
for node in definition["graph"]["nodes"]:
    if node["type"] == "validator_error_rate":      # Accuracy
        node["config"] = {"threshold": 95.0, "max_retries": 5}
    elif node["type"] == "validator_naturalness":
        node["config"] = {"threshold": 75.0, "max_retries": 3}
    elif node["type"] == "validator_noise":
        node["config"] = {"threshold": 70.0, "max_retries": 3}
    elif node["type"] == "validator_pronunciation":
        node["config"] = {"threshold": 99.0, "max_retries": 3}
```

Raise a threshold for a stricter bar. Raise `max_retries` for stubborn content — names, numbers, dense technical text.

Note the odd one out: the [Pronunciation validator](/docs/workflow/pronunciation-validator) defaults to **99**, not 70. Its score is 100 minus the percentage of phonemes wrong, so a 90 bar still tolerates one sound in ten.

## What "delivered" means

* A line reaches Export only when **every** validator on its path has passed it.
* A line that exhausts its retries is delivered anyway — the **best-scoring attempt** across all tries, marked with its scores. A run never stalls on one stubborn line.
* After the run, every line shows each check's score and how many retries it took — so you can see exactly what was regenerated and why, and where to raise or lower a bar.

## When to use fewer checks

Every check scores every line, so validation adds run time and credits. Accuracy-only is a sensible floor for drafts; add Naturalness and Noise for anything you publish. Add [Pronunciation](/docs/workflow/pronunciation-validator) — last in the branch — when names and terms have to be right, and pair it with a [Pronunciation Corrector](/docs/workflow/pronunciation-corrector) to fix the flagged words in place instead of re-reading the whole line. To *drop* failing lines instead of retrying them, leave a validator's `fail` port unwired.

## Related

* [Validators](/docs/workflow/validators) — pass/fail routing and retry, in depth
* [Accuracy](/docs/workflow/accuracy-validator) · [Naturalness](/docs/workflow/naturalness-validator) · [Noise](/docs/workflow/noise-validator) · [Pronunciation](/docs/workflow/pronunciation-validator)
* [General rules](/docs/workflow/general-rules) — what makes validator wiring valid