# Generated Text Internals `internal/generatedtext` validates the structured prose produced for generated- text reports and turns validated prose plus rich module values into typed render contexts. It owns the catalog that pairs a generated-text report definition with its validator, schema ID, template ID, and context builder. The complete maintainer-facing context fields belong to [report templates](../templates.md). ## Catalog and validation The Daily, Today, Tomorrow, and Hourly report definitions each use structured generated text. `LookupDefinition` requires the exact report, schema, and template triple and rejects unknown IDs, unsupported pairs, and a pair that belongs to another report before the run begins. A handler validates raw JSON, returns a typed value and canonical normalized JSON, loads its canonical schema through `internal/promptassets`, builds a render context, and renders through `internal/reporttemplate`. Daily, Today, and Tomorrow use a day-style value with required trimmed summary and one or more nonblank discussion paragraphs. Hourly requires trimmed summary and a single trimmed discussion string. Every form also requires the `precipitation_timing` field; an empty string means there is no supported timing prose to render. Typed decoding requires the exact lowercase JSON field names, rejects missing, duplicate, case-variant, and unknown fields, and checks field shapes; no general-purpose JSON Schema engine is used at runtime. The validator accepts at most 64 KiB of raw JSON before it allocates typed values. Its JSON Schemas and typed checks limit `summary` and `precipitation_timing` to 4,000 characters each. Hourly `forecast_discussion` is limited to 12,000 characters. Day-style discussion accepts at most 12 paragraphs of at most 4,000 characters each. Across all prose fields, one report may contain at most 20,000 characters. These bounds apply before trimming, filtering, normalization, and template rendering. Malformed JSON and field values return short, content-safe errors. They name only canonical fields where useful and never echo provider values or unknown field names. The Promptkit adapter also drops an oversized provider result before copying it into execution or debug state; direct executor implementations receive the same enforcement in this package. ## Render contexts The catalog's report-specific builders receive the prepared report identity, a rich module snapshot, derived facts needed to order dayparts, and the matching validated generated text. They require the identity's report ID to match the selected builder. When the optional metadata stanza is present, every shared identity field must agree with that prepared authority before context construction continues. Builders then decode the module stanzas needed by the template and build typed Daily, Today, Tomorrow, or Hourly contexts. Contexts expose only display-ready report values, generated prose, and module values; they do not expose complete collected or derived fact bundles. Ordered slices remain the template iteration surface rather than maps. Optional source stanzas become nil or fallback context fields. Today also computes whether its ordered dayparts contain a displayable condition so the template can render either rows or its explicit no-details fallback. Missing required stanzas, type-decoding failures, conflicting identity values, invalid metadata, or a generated-text type that does not match the chosen handler fail before template execution. Prompt packages, raw Promptkit output handling, and template asset lookup remain outside this package. ## Verification and invariants Focused tests cover the catalog, each report-specific validator, normalization, schema/template mismatches, context construction, optional modules, and typed stanza errors: ```sh go test ./internal/generatedtext ``` Generated text supplies prose slots only; deterministic weather facts remain in module and fact values. The renderer applies its plain-text policy to every generated prose insertion, preserving ordinary text and paragraph breaks while preventing provider text from creating Markdown or HTML structure. Every report definition must resolve to exactly one supported catalog pair.