# 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` - `derived_daily_summary` - `derived_daypart_summaries` - `precip_timing` - `alert_digest` - `area_forecast_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. ## Options Most modules use an empty options struct. `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. ## 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.