2.8 KiB
Fact Contracts Internals
internal/facts is the deterministic boundary between a collected weather
bundle and report-scoped facts. It preserves normalized source values and then
selects and summarizes the values needed for one resolved report. Provider
transport and normalized bundle semantics belong to
weather-data internals; report identity and valid-period
selection belong to report registry internals.
Collected facts
BuildCollected projects a weatherdata.Bundle into CollectedFacts. It
retains the fetched timestamp and every normalized product: observations,
current conditions, hourly, narrative, alerts, discussion, daily, weather
story, and convective outlook data. Source provenance and warnings are copied
into their own slices so downstream consumers can inspect data completeness
without treating it as an ordinary weather fact.
A nil bundle produces an empty collected value. Collection itself, missing source policy, and source hashes are outside this package.
Report-scoped derivation
BuildDerived requires a valid resolved period and a valid report timezone. It
uses half-open period overlap to select hourly, narrative, daily, and alert
data; it also derives precipitation timing. Convective outlooks are retained
only when their valid interval overlaps the report period, with discussions
kept for represented outlook days. Both collections are sorted deterministically.
Report identity controls the summary shape:
| Report family | Derived summary |
|---|---|
| Hourly | Rolling-period selections and precipitation timing; no daily or daypart summary |
| Daily, Today, Tomorrow | One local civil-day summary and its dayparts |
DaypartSummaries is collected from the resulting daily summaries.
The detailed grouping, daypart-window, and alert rules are owned by
forecast derivation.
Missing data and failures
Optional normalized products remain nil or yield empty selections; the package does not create substitute values. A present convective-outlook run with no matching outlooks produces non-nil empty outlook and discussion slices, while a missing run produces nil slices.
Derivation fails for an invalid report period, invalid timezone, unsupported report ID, or when a requested daily summary has no hourly forecast data. Invalid daypart definitions surface from forecast derivation. The package does not access the CLI, filesystem, subprocesses, or network.
Verification and invariants
Focused tests cover collected-fact separation, report-period selection, hourly behavior, daily summaries, and convective outlook selection:
go test ./internal/facts
Facts are derived once for a resolved report from already collected data. They remain reusable structured values for prompt input and template presentation, which are owned elsewhere.