Files
weatherreporter/docs/internal/module.md

6.3 KiB

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
  • today_planning
  • tomorrow_planning
  • daily_planning

Every registered module has a builder. Report composition entries that refer to unknown or unimplemented module IDs fail validation instead of being skipped.

Today Composition

The default Today Report module order is:

  1. metadata
  2. current_conditions
  3. narrative_forecast
  4. derived_daily_summary
  5. derived_daypart_summaries
  6. precip_timing
  7. alert_digest
  8. spc_convective_outlooks
  9. area_forecast_discussion
  10. spc_convective_discussion
  11. weather_story
  12. outdoor_windows
  13. hourly_forecast
  14. today_planning

The embedded Today template uses selected deterministic fields from these module outputs after GeneratedText validation.

Tomorrow Composition

The default Tomorrow Report module order is:

  1. metadata
  2. current_conditions
  3. narrative_forecast
  4. derived_daily_summary
  5. derived_daypart_summaries
  6. precip_timing
  7. alert_digest
  8. spc_convective_outlooks
  9. area_forecast_discussion
  10. spc_convective_discussion
  11. weather_story
  12. outdoor_windows
  13. tomorrow_planning
  14. hourly_forecast

The embedded Tomorrow template uses selected deterministic fields from these module outputs after GeneratedText validation.

Daily Planning

daily_planning emits dated daily planning facts for the daily report ID. Its output stanza is also named daily_planning. The module is supported only by that report ID and depends on daily summaries for the selected local civil day. No active default report composition includes it yet.

The output uses this shape:

  • morning_readiness
  • commute_school_workday_concerns
  • overnight_change_watch

The type is briefing.DailyPlanningModule; it is independent from briefing.TomorrowPlanningModule.

Today Planning

today_planning emits current-day planning facts for Today Report. Its output stanza is also named today_planning. The module is supported only by Today Report and depends on daily and daypart summaries for the current local civil day.

The output uses this shape:

  • morning_readiness
  • commute_school_workday_concerns
  • outdoor_planning
  • late_day_change_watch

The type is briefing.TodayPlanningModule; it is independent from briefing.TomorrowPlanningModule.

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:

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.