# Forecast Derivation Internals `internal/forecast` deterministically selects and summarizes normalized forecast data. It has no transport, filesystem, CLI, subprocess, or report registry dependency. Its summaries are consumed by [fact contracts](facts.md) and later module builders. ## Period and daypart semantics Selections use `timeutil.Period` half-open overlap: a value is selected only when both intervals share time. `BuildDailySummary` creates one local civil day; `BuildPeriodDailySummaries` intersects every local civil day with the requested period, preserving partial first and last days. `ResolveDayparts` converts each configured name, start clock, and end clock into a local window. An end clock at or before its start clock wraps into the next civil day. The daypart and timezone defaults are defined in the [configuration reference](../config.md), not here. ## Deterministic summaries `BuildDailySummary` requires an hourly run with at least one period. It adds the selected narrative periods, discussion, alert overlaps, source provenance, source warnings, and one `DaypartSummary` per resolved window. A daypart keeps its selected hourly periods and derives temperature and apparent-temperature ranges, timed precipitation and wind maxima, dominant and notable conditions, and weather indicators. Indicators are deterministic checks over normalized values and condition text: heat, cold, and wind use package-owned numeric cutoffs; snow, ice, fog, and wind text are detected from the forecast description. `BuildPrecipTiming` sorts periods, records the maximum and first precipitation, groups contiguous periods at or above its package-owned probability threshold, and records thunder mentions. Alert overlap parsing supports the normalized alert payload's available timing fields. Unparseable alerts and invalid intervals are ignored; valid overlaps are clipped to the requested period and ordered by alert start time. ## Missing data and failures Empty selections yield empty summary fields rather than generated prose. Direct daily or period-summary calls fail when their required bundle, valid period, hourly data, or daypart definitions are invalid. A nil location uses UTC when these APIs are called directly. Optional narrative, discussion, and alerts remain absent when their normalized products are absent. Forecast thresholds used for brief indicators and precipitation timing are implementation rules. User-configurable Recent Changes thresholds are applied by [changes internals](changes.md), whose defaults are documented in [configuration](../config.md). ## Verification and invariants Focused tests cover local civil days, clipped periods, daypart resolution, summary metrics, precipitation windows, threshold helpers, and alert overlap: ```sh go test ./internal/forecast ./internal/timeutil ``` The package preserves normalized inputs as inspectable structured values and never decides report identity, delivery, or presentation wording.