146 lines
4.2 KiB
Markdown
146 lines
4.2 KiB
Markdown
# Module Contract Internals
|
|
|
|
This document describes the module contract in `internal/module`.
|
|
|
|
## Purpose
|
|
|
|
`internal/module` defines the shared identifiers and data envelopes used for
|
|
prompt-facing modules. Report definitions use module IDs for composition,
|
|
module builders produce outputs with stanza names, prompt input packages consume
|
|
snapshots, and Recent Changes compares snapshot stanzas.
|
|
|
|
## Inputs And Outputs
|
|
|
|
Inputs:
|
|
|
|
- ordered `module.ConfigItem` values from report definitions or config
|
|
overrides
|
|
- `module.Output` values produced by module builders
|
|
|
|
Outputs:
|
|
|
|
- stable `module.ID` constants
|
|
- typed option structs for registered modules
|
|
- `module.Snapshot` with schema version `weatherreporter.modules.v1`
|
|
- ordered snapshot outputs with module ID, stanza name, and typed value
|
|
- typed stanza lookup through `module.StanzaValue`
|
|
|
|
## Registered Module IDs
|
|
|
|
The registry recognizes these IDs:
|
|
|
|
- `metadata`
|
|
- `current_conditions`
|
|
- `narrative_forecast`
|
|
- `hourly_forecast`
|
|
- `derived_daily_summary`
|
|
- `derived_daypart_summaries`
|
|
- `precip_timing`
|
|
- `alert_digest`
|
|
- `spc_convective_outlooks`
|
|
- `area_forecast_discussion`
|
|
- `spc_convective_discussion`
|
|
- `weather_story`
|
|
- `outdoor_windows`
|
|
- `tomorrow_planning`
|
|
|
|
Every registered module has a builder. Report composition entries that refer to
|
|
unknown or unimplemented module IDs fail validation instead of being skipped.
|
|
|
|
## Hourly Composition
|
|
|
|
The default Hourly Report module order is:
|
|
|
|
1. `metadata`
|
|
2. `current_conditions`
|
|
3. `hourly_forecast`
|
|
4. `precip_timing`
|
|
5. `alert_digest`
|
|
6. `spc_convective_outlooks`
|
|
7. `area_forecast_discussion`
|
|
8. `spc_convective_discussion`
|
|
9. `weather_story`
|
|
|
|
Hourly Report does not include daily or daypart summary modules by default.
|
|
Its `area_forecast_discussion` item is configured to include only
|
|
`key_messages` and `short_term`.
|
|
|
|
## Options
|
|
|
|
Most modules use an empty options struct, including
|
|
`spc_convective_outlooks` and `spc_convective_discussion`.
|
|
`area_forecast_discussion` accepts:
|
|
|
|
```yaml
|
|
sections:
|
|
- product
|
|
- key_messages
|
|
- short_term
|
|
- long_term
|
|
```
|
|
|
|
An omitted or empty `sections` list includes all available discussion sections.
|
|
Invalid option shapes fail during config normalization or composition
|
|
validation.
|
|
|
|
## SPC Convective Module Outputs
|
|
|
|
`spc_convective_outlooks` emits a prompt-facing risk-product stanza with:
|
|
|
|
- `checked`
|
|
- `as_of`
|
|
- `issued_at`
|
|
- `location_id`
|
|
- `location_name`
|
|
- `outlook_count`
|
|
- `outlooks`
|
|
|
|
Each outlook entry may include `day`, `outlook_type`, `label`, `label_text`,
|
|
`period_begins`, `period_ends`, `issued_at`, `contains_location`, and
|
|
`image_url`. It omits GeoJSON geometry, source URL, expiration time, and
|
|
severity rank.
|
|
|
|
`spc_convective_discussion` emits a narrative stanza only when a retained
|
|
report-period categorical outlook has severity rank `3` or higher and matching
|
|
discussion text is available. Its output includes `included_because` and
|
|
`discussions`; each discussion may include `day`, `period_begins`,
|
|
`period_ends`, `headline`, `summary`, `discussion`, and `updated_at`.
|
|
Discussions are included only for SPC days whose retained categorical outlooks
|
|
meet the severity threshold.
|
|
|
|
## Boundaries
|
|
|
|
- This package owns module identifiers, config item envelopes, output
|
|
envelopes, snapshot validation, and typed stanza lookup.
|
|
- It does not define report IDs, execute builders, fetch weather data, derive
|
|
forecast facts, write state, or invoke Scriptorium.
|
|
|
|
## State Or Manifest Behavior
|
|
|
|
`module.Snapshot` values are persisted by `internal/state` as JSON. Snapshot
|
|
validation rejects missing schema version, missing module IDs, missing stanza
|
|
names, duplicate module outputs, and duplicate stanza names while preserving
|
|
output order.
|
|
|
|
## Failure Behavior
|
|
|
|
- Snapshot construction fails for duplicate module outputs or duplicate stanza
|
|
names.
|
|
- Typed stanza lookup returns `found=false` for missing stanzas.
|
|
- Typed stanza lookup wraps JSON marshal/decode failures with stanza context.
|
|
|
|
## Tests
|
|
|
|
Inspect:
|
|
|
|
- `internal/module/module_test.go`
|
|
- `internal/briefing/modules_test.go`
|
|
- `internal/report/period_test.go`
|
|
|
|
## Invariants
|
|
|
|
- `internal/module` does not import `internal/report`.
|
|
- Module IDs are stable strings.
|
|
- Each emitted module output has exactly one stanza name and one typed value.
|
|
- Snapshot output order is caller-owned and preserved.
|