68 lines
3.0 KiB
Markdown
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.
|