affaan-m/ECC · error · ContractError
stochastic schedule is periodic; intervals must vary
Error message
stochastic schedule is periodic; intervals must vary
What it means
ContractError raised when all intervals between consecutive effect event times are identical (or there is effectively one distinct interval, e.g. a single interval). The tasteforge contract enforces that stochastic schedules are not periodic; a schedule with uniform spacing is considered periodic and rejected. This guarantees empirically varied event spacing in generated media.
Solutions
- Generate event times with jitter, e.g. add random noise to each time before validation.
- Use a non-uniform distribution (Poisson process, exponential inter-arrival times) for event times.
- Ensure at least two distinct intervals exist (>=3 events with differing gaps).
- Increase rounding precision awareness: intervals are rounded to 6 decimals; near-identical intervals are treated as equal.
Example fix
// before
times = [i * 1.0 for i in range(5)] # all intervals 1.0
// after
import random
times = [0.0]
for _ in range(4):
times.append(round(times[-1] + random.uniform(0.4, 1.8), 6)) # intervals vary Defensive patterns
Strategy: validation
Validate before calling
intervals = [round(b - a, 6) for a, b in zip(times, times[1:])]
if len(set(intervals)) <= 1:
raise ValueError("schedule intervals must vary; add jitter or >= 3 distinct gaps") Type guard
def intervals_vary(events) -> bool:
times = [float(e["time"]) for e in events]
intervals = [round(b - a, 6) for a, b in zip(times, times[1:])]
return len(set(intervals)) > 1 Try / catch
try:
validate_effect_recipe(recipe, reference_durations)
except ContractError as exc:
if "intervals must vary" in str(exc):
recipe["events"] = add_jitter(recipe["events"])
validate_effect_recipe(recipe, reference_durations)
else:
raise Prevention
- Avoid linspace/arange for event-time generation; use random gaps
- Always generate at least 3 events with distinct gaps
- Add jitter proportional to a seed you control for reproducibility
- Lint generators with a periodicity check mirroring the contract
When it happens
Trigger: Calling validate_effect_recipe with events spaced at a constant delta (e.g. times [0, 1, 2, 3] -> all intervals 1.0), or a recipe with exactly two events yielding one interval (set of intervals has size 1).
Common situations: Using numpy.linspace or a fixed-tick generator to build event times; authoring a simple 'every N seconds' schedule by hand; test fixtures with evenly spaced events copied from an older contract version.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- stochastic schedule is periodic; repeating interval cycle
- anchor evidence source duration is not bound to its receipt…
- CV effect has an invalid subject anchor
- CV effect lacks a valid subject anchor
- CV effect must fail closed on anchor loss
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/9d2f347f247bfc6b.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:221
if float(start) + float(duration) > float(timeline) + 1e-9:
raise ContractError("effect event end exceeds the declared timeline")
evidence = event.get("evidence")
if not isinstance(evidence, dict):
raise ContractError(f"effect {event.get('effect')} lacks reference evidence")
_validate_media_time(
evidence.get("time"), evidence.get("source_duration"), label="effect evidence time"
)
if reference_durations is not None:
digest = evidence.get("reference_sha256")
expected_duration = reference_durations.get(digest) if isinstance(digest, str) else None
if expected_duration is None or evidence.get("source_duration") != expected_duration:
raise ContractError("effect evidence source duration is not bound to its receipt reference")
times = [float(event["time"]) for event in events]
if times != sorted(times) or len(times) != len(set(times)):
raise ContractError("effect event times must be unique and increasing")
intervals = [round(b - a, 6) for a, b in zip(times, times[1:])] # noqa: RUF007
if len(set(intervals)) <= 1:
raise ContractError("stochastic schedule is periodic; intervals must vary")
for period in range(1, len(intervals) // 2 + 1):
if all(intervals[index] == intervals[index % period] for index in range(len(intervals))):
raise ContractError("stochastic schedule is periodic; repeating interval cycle")
if recipe.get("periodic") is not False:
raise ContractError("effect recipe must explicitly declare periodic=false")
for event in events:
cv_effect = str(event.get("effect", "")).startswith("cv_")
if cv_effect and event.get("requires_subject_anchor") is not True:
raise ContractError(f"CV effect {event.get('effect')} must require a subject anchor")
if event.get("requires_subject_anchor"):
anchor = event.get("subject_anchor")
required = {
"mode", "target", "source_ref_sha256", "evidence_time",
"source_duration", "lost_policy",
}
if not isinstance(anchor, dict) or not required.issubset(anchor):
raise ContractError(f"CV effect {event.get('effect')} lacks a valid subject anchor")
if anchor.get("mode") not in {"object_track", "point_track", "segmentation_track"}:View on GitHub (pinned to 8321021c54)