Files
weatherreporter/docs/internal/facts.md

68 lines
3.0 KiB
Markdown

# 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](weather-data.md); report identity and valid-period
selection belong to [report registry internals](report-registry.md).
## 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 |
| Three-day, Weekend | One clipped daily summary for each overlapping local day |
| Storm | One summary for the explicit report window |
`DaypartSummaries` is collected from the resulting daily or storm summaries.
The detailed grouping, daypart-window, and alert rules are owned by
[forecast derivation](forecast-derivation.md).
## 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 and storm behavior, daily and partial-day summaries, and convective
outlook selection:
```sh
go test ./internal/facts
```
Facts are derived once for a resolved report from already collected data.
They remain reusable structured values: prompt wording, state persistence,
prior-report comparison, and template presentation are owned elsewhere.