docs(392): record per-schedule clock-padding decision + domain-model field

This commit is contained in:
2026-07-23 08:03:31 +02:00
parent f4ba219000
commit e99e72ee71
3 changed files with 29 additions and 1 deletions
+27
View File
@@ -1305,6 +1305,8 @@ into a schedule item's roll slot. That toggle is mostly SPA work and is deferred
the #388 design-system sync epic** (all UI work is currently gated on #388), which also covers adding a
60-minute increment to the filler-preset editor's options (the backend already accepts any integer).
Extended by `sched.clock-padding-schedule-toggle` (#392).
## 2026-07-17 — Shuffle-source construction extracted to `ShuffleSourceBuilder`; per-family seam, not a god-factory (#380)
`key: sched.shuffle-source-builder` · `status: active` · `since: 2026-07-17` · `supersedes: none` · `superseded-by: none`
**Rule:** Shuffle-source construction moves to a static, DI-free `ShuffleSourceBuilder` (a shared seam, not a service) so Classic and Playlist stop cross-engine reaching into `PlayoutBuilder` statics; a unified Classic+Playlist enumerator factory is explicitly rejected as a god-factory. Block/Scripted/YAML duplication is left alone, deferred to a follow-up gated on #381.
@@ -3561,3 +3563,28 @@ no scheduling logic of its own. So "Scripted is un-golden-able" conflates two di
The #381 "documented decision" arm correctly deferred the *pipeline* golden; it overstated the case by writing
off engine-level coverage too. Scripted scheduling *behavior* is now covered in-process; only the
external-process pipeline remains #563's.
## 2026-07-22 — per-schedule clock-boundary padding is a synthetic content-less Pad over the existing per-episode machinery (#392)
`key: sched.clock-padding-schedule-toggle` · `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.