Validation and repair
Run deterministic validators and route findings to the right specialist.
report = timeline.validate("all,-edit_quality.sfx", name="quality-check")Validation checks the current timeline deterministically and returns a
ValidationReport. Pass either a validator selection spec or an immutable,
serializable ValidationPolicy — never a natural-language prompt.
A selection is a comma-separated list of exact validator names or dotted group prefixes:
timeline.validate("all")
timeline.validate("edit_quality.caption")
timeline.validate("all,-edit_quality.sfx")
timeline.validate("edit_contract.duration_matches")allmeans every registered validator.noneselects no validators.- A prefix such as
edit_quality.captionselects that whole quality group. - A leading
-excludes a name or group. - With exclusions but no positive token, selection starts from all validators.
- An unknown token raises an error and lists the valid names.
Validator catalog
Validators split into two families. edit_contract.* checks are hard
invariants of a correct edit — the caller's declared canvas, target duration,
and plan are realized exactly. edit_quality.* checks are editorial judgments
you opt into and tune.
| Group | What it checks |
|---|---|
edit_contract.* | Canvas, optional target duration, plan realization, no video gaps, captions/titles/graphics/sound realization, and loaded fonts. |
edit_quality.pacing.* | Short shots and parent flashes, from both the live edit and the plan. |
edit_quality.caption.* | Cadence, segmentation, row layout, and balance. |
edit_quality.typography.* | Minimum text size and overlap. |
edit_quality.sfx.* | Density and mix levels. |
| Other quality | edit_quality.coverage.broll, edit_quality.structure.plan. |
edit_contract.duration_matches is skipped when the project has no declared
target duration. For a meaningful duration gate, give the storyboard or direct
author an explicit target duration.
program.safe and program.executable are mandatory specialist-transaction
verification — they are never selectable through timeline.validate(). A
specialist is promoted only after those checks and its relevant edit_contract.*
invariants pass. Specialists never run edit_quality.* automatically: editorial
acceptance is caller-owned, which is what the rest of this page is about.
Policies with settings
For quality checks you want to tune, build a ValidationPolicy. It bundles a
selection with per-validator settings, validates both at construction time, and
is immutable and serializable so you can reuse it across runs.
from scrambo import ValidationPolicy
policy = ValidationPolicy(
"edit_quality.caption,edit_quality.typography",
settings={
"edit_quality.caption.cadence.minimum_duration": {"min_duration": 0.25},
},
)
report = timeline.validate(policy, name="quality-check")Settings are keyed by a concrete edit_quality.* validator and use that
validator config's field names. Contract and program checks do not accept
caller settings — passing settings for them raises.
Inspecting a report
if report.passed:
print("ready")
else:
print(report.md)
for finding in report.findings:
print(finding)Call report.require_passed() to fail the program when any selected validator
fails.
The repair loop
To attempt repair, hand the failing report to the specialist that owns the
problem, then re-check. timeline.ensure() makes this caller-owned loop
transparent while keeping routing explicit:
report = timeline.ensure(
"edit_quality.caption,edit_quality.typography",
repair_with=timeline.captions_agent,
repairs=2,
name="caption-quality",
require_passed=True,
)ensure() runs the policy, hands any failure to the one repair_with
specialist, and revalidates — up to repairs times. Stages are deterministically
named caption-quality-repair-N and caption-quality-recheck-N. It performs no
routing inference: choose the one specialist that owns the selected quality
policy. With require_passed=False (the default), an exhausted loop returns the
final failed report for custom handling.
Use a focused specialist for focused findings — captions_agent for caption
layout or timing, sound_agent for mix levels, titles_agent for typography.
Use author_agent for cross-cutting or structural findings. If you want the loop
spelled out instead of ensure():
selection = "edit_contract,edit_quality.caption,edit_quality.typography"
report = timeline.validate(selection, name="quality-check")
for attempt in range(2):
if report.passed:
break
timeline.author_agent.edit(report, name=f"quality-repair-{attempt + 1}")
report = timeline.validate(selection, name=f"quality-check-{attempt + 2}")
report.require_passed()