Files
weatherreporter/docs/internal/generatedtext.md

69 lines
3.5 KiB
Markdown

# 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 briefing metadata, a rich module
snapshot, collected facts, derived facts, and the matching validated generated
text. They decode the module stanzas needed by the template and build typed
Daily, Today, Tomorrow, or Hourly contexts. Context construction validates
metadata and periods, preserves rich module values, and uses ordered slices for
template iteration rather than maps.
Optional source stanzas become nil or fallback context fields. Missing required
stanzas, type-decoding failures, 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. Every report definition must resolve to exactly one
supported catalog pair.