---
key: sched.clock-padding-schedule-toggle
title: 2026-07-22 — per-schedule clock-boundary padding is a synthetic content-less Pad over the existing per-episode machinery (#392)
status: active
since: '2026-07-22'
supersedes: none
superseded-by: none
rule: A `ProgramSchedule.PadToNearestMinute` (nullable int; null = off) makes the Classic builder pad every content item up to the next N-minute clock boundary without a hand-wired Pad `FillerPreset`, by reusing the existing per-content-item Pad path in `PlayoutModeSchedulerBase.AddFiller`. It extends — does not supersede — `sched.clock-padding-existing` (#77/#388).
signals: 'per-schedule clock padding, PadToNearestMinute on ProgramSchedule, offline gap on pad, ClockPadOfflineTarget, synthetic Pad without FillerPreset · paths: `PlayoutModeSchedulerBase.AddFiller`, `PlayoutSchedulerResult.ClockPadOfflineTarget`, `FallbackFillerForPad`, `/app/schedules` · issues: #392, #77, #388'
mechanics: '`PlayoutBuildGoldenTests` (One/Flood/Duration/Multiple clock-pad cases), midnight-crossing invariant tests'
---

A `ProgramSchedule.PadToNearestMinute` (nullable int; null = off) makes the Classic builder pad every content
item up to the next N-minute clock boundary WITHOUT a hand-wired Pad `FillerPreset`. It reuses the existing
per-content-item Pad path (`PlayoutModeSchedulerBase.AddFiller`, already called once per emitted item): a
self-contained synthetic branch engages only when the item has no own `FillerMode.Pad` filler (the item's Pad
wins — no double-pad) and the parent schedule declares a positive divisor. The gap fills with the schedule
item's `FallbackFiller` via the existing `FallbackFillerForPad`; when no fallback content exists, the branch
records an offline target and the four schedulers advance `PlayoutBuilderState.CurrentTime` to the boundary,
leaving an implicit offline gap (the same representation fixed-start items use — absence of a `PlayoutItem`,
rendered as "Channel is Offline" at stream time). That advance is carried by a transient per-build
`PlayoutSchedulerResult.ClockPadOfflineTarget` (never serialized — no anchor schema, no migration); the
day-seam anchor clamp is exempted by exact equality with that target.

This is the per-schedule convenience layer deferred behind #388 in `sched.clock-padding-existing`; that
record's per-item Pad-preset behavior is unchanged. Determinism needs no new anchor/seed state (the pad math
is a pure function of offsets). Coverage is per-scheduler-mode (One/Flood/Duration/Multiple) via golden and
invariant tests across midnight crossings. The SPA schedule editor exposes it as a 5/10/15/30/60 minute
picker; TZ-independence holds only for divisors of 60. See #77 (prior art) and #392.
