Repository navigation
3.1.2
Breaking
Generated schedules now refuse members that contradict their own spec.
Constructing a WindowSchedule, LookbackSchedule or HorizonSchedule directly, or rehydrating one through from_dict, now raises ConfigError when:
- a member is below the recorded minimum, above the recorded maximum, or not a whole multiple of the recorded grain; or
- the parameters are a combination the generator functions already refuse (a log-spaced endpoint that quantizes outside its range; a metallic seed at or above its floor that quantizes below it).
Before this release these paths checked only emptiness, the cap, type, positivity and repeats. For example, WindowSchedule(LogSpacedSpec(count=2, minimum=60s, maximum=120s, grain=60s), windows=(180s,)) constructed, hashed and round-tripped, and LookbackSchedule accepted maximum=28 beside periods=(99,).
Who is affected: only code that builds or edits schedule payloads by hand. Every schedule produced by log_spaced, metallic_recurrence, explicit, their _lookback and _horizons variants round-trips unchanged, so no schedule id moves. Explicit schedules have no bounds, grain or endpoint rules and are untouched.
The refusal message names the offending member and the bound or grain it violates; horizon schedules say "horizon" where window schedules say "window". Members are never regenerated, repaired or replayed.
Fixed
- Unrepresentable magnitudes raise
ConfigError, notOverflowErrororValueError. An integer too large for a float reachedmath.isfinitein the recurrence coefficient validator andmath.isnanin the window-quality coverage validator; both now range-check before converting. A duration amount longer than the interpreter's integer-conversion limit is refused byDuration.parsewith a message naming the limit. Refusal messages echo the value through the bounded-echo helper, so a pathological input cannot put thousands of digits into a message. Accepted coefficients, thresholds and durations are unchanged. - The phased harness checks the anchor's phase even when no emit tick lands inside the frame. The check took its residue from the first emit tick and returned early when there was none, so an off-phase anchor was accepted exactly when the emit step cleared the frame, and the caller got an empty result instead of a refusal. The phase now comes from the anchor and the cadence. An in-phase anchor with no tick in the frame still returns the empty grid.
Removed
- The feature-identity window parser no longer wraps a
ValueErrorthatcoerce_durationcan no longer raise. Every input still refuses withConfigError; no observable refusal changed.