Files
weatherreporter/docs/internal/briefing.md

104 lines
5.5 KiB
Markdown

# Module Builder Internals
`internal/briefing` builds typed module outputs from resolved report context,
collected facts, and derived facts. It owns the module registry, including
module support, fact requirements, option types, missing-data policy, builders,
and prompt-export hooks. It does not collect data, derive periods, write a
snapshot, construct YAML, invoke Promptkit, or render a report.
## Registry and construction
Every `ModuleDefinition` declares an ID, stanza name, default option value,
required collected and derived facts, supported report IDs, missing-data
behavior, duplicate policy, builder, and optional prompt exporter. The
briefing-owned fact-requirement vocabulary supplies each prerequisite's stable
identity, category, and availability predicate; registry construction rejects
unknown requirements and requirements listed under the wrong category.
`BuildModule` first verifies the requested module, report compatibility, and
option shape. It then applies the declared missing-data behavior:
- `omit` returns no output for unavailable optional facts;
- `error` returns the missing fact requirements; and
- `empty` allows the builder to emit an explicit checked-empty value.
Unsupported `warn` behavior, missing builders, duplicate registry IDs or
stanza names, output ID or stanza mismatches, and exporter failures all return
errors with module context. A successful builder gets a pass-through prompt
value unless its definition supplies an exporter.
## Built value families
Source-oriented builders shape report metadata, current conditions, narrative
and hourly forecasts, alert digest, SPC outlooks and discussion, area forecast
discussion, and weather story. Derived builders shape daily and daypart
summaries, precipitation timing, outdoor windows, and the report-specific
Daily, Today, and Tomorrow planning values.
The daily summary preserves generic feels-like values as
`apparent_temperature_max_f`; it does not label them as a heat index. Daypart
temperature phrases retain below-zero meaning, including through temperature
trends that cross zero. Outdoor windows add a 25-point risk penalty and an
explicit reason for each snow, ice, or fog indicator. Equal scores retain input
order for both best and worst windows.
The module registry preserves rich values for templates and snapshots while
curating prompt exports where needed. In particular, source warnings are a
metadata summary, checked-empty alerts and SPC outlooks remain distinct from
missing sources, and prompt-safe SPC values omit geometry and other
template-only or source details. The complete module composition is in
[module internals](module.md); fact derivation is in [fact contracts](facts.md).
Alert digests are built from selected alert items and source provenance, not a
provider response envelope.
Derived daypart-summary maps use the forecast package's canonical daypart
identity and reject any collision instead of replacing an earlier value.
Planning applies the same identity when recognizing morning, afternoon,
evening, and overnight windows; display labels remain separate and preserve
configured text with rune-safe first-letter capitalization.
The embedded SPC background-definition asset records its authoritative sources,
source update dates, and maintainer review schedule. Its categorical
`official_description` values transcribe the [SPC convective-outlook risk
table](https://www.spc.noaa.gov/about/outlooks/); its Conditional Intensity
Group entries follow the [SPC conditional-intensity
reference](https://www.spc.noaa.gov/exper/conditional-intensity-information).
`plain_language` values are Weatherreporter summaries. Weatherreporter
maintainers review the asset annually and whenever either source changes.
`area_forecast_discussion` accepts an optional typed section filter. Accepted
typed option pointers are normalized to the declared value type before builder
execution. Planning modules are report-specific: `daily_planning` supports Daily,
`today_planning` supports Today, and `tomorrow_planning` supports Tomorrow.
## Missing data and boundaries
Optional current conditions, narrative products, discussions, and weather
stories may be omitted. A weather story is usable only when it has non-blank
displayable content (title, description, alternate text, or download URL) or a
valid start/end period; otherwise collection applies its optional-source policy
and the module is omitted. Required derived modules fail when their declared facts
are unavailable. Empty alert and outlook runs can still produce checked-empty
modules. SPC discussion is omitted unless a retained categorical outlook meets
the package's severity criterion and matching discussion text exists.
`ModuleContext` carries the effective units, timezone, location context, and
prepared identity. Report preparation creates that one `PreparedIdentity` for
the shared report identity, timing, configuration context, and source warnings
before module construction. The metadata module projects its matching fields
from that value and retains its prompt-safe shape. Field defaults are owned by
[configuration](../config.md), and prompt-package layout is owned by [prompt
input](prompt-input.md).
## Verification and invariants
Focused tests cover source and derived values, registry validation, option
handling, prompt exporters, support rules, and missing-data behavior:
```sh
go test ./internal/briefing
```
Builders emit structured facts, never report prose. The app collects their
outputs into an in-memory module snapshot for prompt input and rendering.