# Module Contract Internals This document describes the implemented module contract boundary. ## Purpose `internal/module` defines stable module IDs, typed configuration items, module outputs, and module snapshots. It is a shared contract imported by report definitions and module registry code. ## Inputs And Outputs Inputs: - ordered `module.ConfigItem` values from report definitions - `module.Output` values assembled by callers Outputs: - stable `module.ID` constants - typed option structs for known modules - `module.Snapshot` with ordered outputs and schema version - typed stanza lookup through `module.StanzaValue` ## Boundaries - This package owns shared module identifiers and output envelope contracts. - It does not define report IDs, build prompt stanzas, fetch weather data, derive facts, write state, or invoke Scriptorium. ## State Or Manifest Behavior `module.Snapshot` uses schema version `weatherreporter.modules.v1`. Snapshot validation rejects duplicate module outputs and duplicate stanza names while preserving output order. ## Failure Behavior - Snapshot validation fails when schema version, module ID, or stanza name is missing. - Snapshot validation fails on duplicate module IDs or duplicate stanza names. - Typed stanza lookup returns `found=false` for missing stanzas and 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 module output has exactly one stanza name and one typed value. - Snapshot output order is caller-owned and preserved.