Refresh report and template internals documentation
This commit is contained in:
@@ -1,149 +1,51 @@
|
||||
# Generated Text Internals
|
||||
|
||||
This document describes structured generated-text handling in
|
||||
`internal/generatedtext`.
|
||||
`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).
|
||||
|
||||
## Purpose
|
||||
## Catalog and validation
|
||||
|
||||
`internal/generatedtext` validates structured text returned for
|
||||
generated-text-template reports and builds curated render contexts for
|
||||
templates. It also owns the generated-text catalog that connects report
|
||||
definitions to validators, render-context builders, schema assets, and template
|
||||
assets.
|
||||
Only the Daily, Today, Tomorrow, and Hourly report definitions use the
|
||||
generated-text-template mode. `LookupDefinition` rejects a direct-Markdown
|
||||
definition, unknown schema or template IDs, and unsupported schema/template
|
||||
pairs before the run begins. A handler validates raw JSON, returns a typed
|
||||
value and canonical normalized JSON, loads its schema, builds a render context,
|
||||
and renders through `internal/reporttemplate`.
|
||||
|
||||
## Inputs And Outputs
|
||||
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. Each form permits optional trimmed
|
||||
precipitation-timing and confidence prose. Typed decoding rejects unknown JSON
|
||||
fields; no general-purpose JSON Schema engine is used at runtime.
|
||||
|
||||
Inputs:
|
||||
## Render contexts
|
||||
|
||||
- raw GeneratedText JSON for Daily, Today, Tomorrow Report, or Hourly Report
|
||||
- report metadata from `internal/briefing`
|
||||
- a module snapshot from `internal/module`
|
||||
- validated generated text
|
||||
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.
|
||||
|
||||
Outputs:
|
||||
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 Scriptorium output, state persistence, and template asset lookup
|
||||
remain outside this package.
|
||||
|
||||
- typed `Daily` generated text
|
||||
- typed `Today` generated text
|
||||
- typed `Tomorrow` generated text
|
||||
- typed `Hourly` generated text
|
||||
- normalized stable JSON for validated generated text
|
||||
- typed `DailyRenderContext` values for `internal/reporttemplate`
|
||||
- typed `TodayRenderContext` values for `internal/reporttemplate`
|
||||
- typed `TomorrowRenderContext` values for `internal/reporttemplate`
|
||||
- typed `HourlyRenderContext` values for `internal/reporttemplate`
|
||||
- generated-text catalog handlers for report definitions that use
|
||||
`generated_text_template`
|
||||
## Verification and invariants
|
||||
|
||||
## JSON Contracts
|
||||
Focused tests cover the catalog, each report-specific validator, normalization,
|
||||
schema/template mismatches, context construction, optional modules, and typed
|
||||
stanza errors:
|
||||
|
||||
Daily, Today, and Tomorrow use the same day-style generated-text JSON shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": "string",
|
||||
"forecast_discussion": ["string"],
|
||||
"precipitation_timing": "string",
|
||||
"confidence": "string"
|
||||
}
|
||||
```sh
|
||||
go test ./internal/generatedtext
|
||||
```
|
||||
|
||||
The day-style contract requires `summary` after trimming whitespace.
|
||||
`forecast_discussion` must contain at least one nonblank paragraph after
|
||||
trimming blank items. `precipitation_timing` and `confidence` are optional and
|
||||
omitted from normalized JSON when blank. Unknown fields are rejected.
|
||||
|
||||
The report-specific Go API is:
|
||||
|
||||
| Report | Type | Validator | Schema ID | Template ID | Prompt ID |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Daily Report | `Daily` | `ValidateDaily` | `daily` | `daily` | `weather.daily_generated_text` |
|
||||
| Today Report | `Today` | `ValidateToday` | `today` | `today` | `weather.today_generated_text` |
|
||||
| Tomorrow Report | `Tomorrow` | `ValidateTomorrow` | `tomorrow` | `tomorrow` | `weather.tomorrow_generated_text` |
|
||||
|
||||
Hourly generated text uses the same top-level field names, but
|
||||
`forecast_discussion` is a single string:
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": "string",
|
||||
"forecast_discussion": "string",
|
||||
"precipitation_timing": "string",
|
||||
"confidence": "string"
|
||||
}
|
||||
```
|
||||
|
||||
Hourly `summary` and `forecast_discussion` are required after trimming
|
||||
whitespace. `precipitation_timing` and `confidence` are optional and omitted
|
||||
from normalized JSON when blank. Unknown fields are rejected. The Hourly catalog
|
||||
entry uses type `Hourly`, validator `ValidateHourly`, schema ID `hourly`,
|
||||
template ID `hourly`, and prompt ID `weather.hourly_generated_text`.
|
||||
|
||||
## Render Contexts
|
||||
|
||||
Daily, Today, Tomorrow, and Hourly render contexts all include:
|
||||
|
||||
- display metadata derived from report metadata;
|
||||
- validated generated text;
|
||||
- typed module outputs decoded from the module snapshot;
|
||||
- collected facts;
|
||||
- derived facts.
|
||||
|
||||
Daily, Today, and Tomorrow share common civil-day render-context fields such as
|
||||
forecast date labels, valid period, generated-at labels, current conditions,
|
||||
hourly forecast, precipitation timing, alert digest, SPC outlooks, AFD, SPC
|
||||
discussion, weather story, daily summary, and ordered daypart summaries.
|
||||
|
||||
Each civil-day report keeps its report-specific planning module:
|
||||
|
||||
- Daily exposes `DailyPlanning`.
|
||||
- Today exposes `TodayPlanning`.
|
||||
- Tomorrow exposes `TomorrowPlanning`.
|
||||
|
||||
Today's ordered daypart context omits unavailable or elapsed dayparts according
|
||||
to Today report rules. Daily and Tomorrow use fallback daypart behavior.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package owns typed generated-text validation and render-context shaping.
|
||||
- It owns generated-text catalog lookup for schema/template combinations.
|
||||
- It uses typed module snapshot decoding through `module.StanzaValue`.
|
||||
- It does not invoke Scriptorium, write state artifacts, choose report
|
||||
definitions, compare snapshots, or own embedded template/schema files.
|
||||
- It renders through `internal/reporttemplate`; embedded asset lookup remains
|
||||
in `internal/reporttemplate`.
|
||||
- It does not use a Go JSON Schema dependency; schema enforcement in Go is
|
||||
limited to typed JSON decoding, unknown-field rejection, and required-field
|
||||
checks.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- Malformed generated-text JSON fails with decode context.
|
||||
- Unknown generated-text JSON fields fail during decoding.
|
||||
- Empty required fields fail after trimming whitespace.
|
||||
- Daily, Today, and Tomorrow forecast discussion fails when no nonblank
|
||||
paragraphs remain.
|
||||
- Missing optional render-context stanzas become nil module pointers.
|
||||
- Invalid render metadata, including missing timezone, missing generated time,
|
||||
or invalid valid period, fails before template rendering.
|
||||
- Unsupported generated-text schema IDs, template IDs, or schema/template
|
||||
combinations fail during catalog lookup with report ID context.
|
||||
|
||||
## Tests
|
||||
|
||||
Inspect:
|
||||
|
||||
- `internal/generatedtext/hourly_test.go`
|
||||
- `internal/generatedtext/daily_test.go`
|
||||
- `internal/generatedtext/today_test.go`
|
||||
- `internal/generatedtext/tomorrow_test.go`
|
||||
- `internal/generatedtext/catalog_test.go`
|
||||
- `internal/generatedtext/render_context_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Render contexts are curated structs, not raw prompt-input packages.
|
||||
- Required generated text is normalized before downstream artifact storage.
|
||||
- Generated-text-template reports must have one catalog entry matching their
|
||||
report definition schema and template IDs.
|
||||
- Missing optional weather narrative stanzas produce empty or fallback render
|
||||
context fields rather than forcing raw module data into templates.
|
||||
Generated text supplies prose slots only; deterministic weather facts remain in
|
||||
module and fact values. Every generated-text definition must resolve to exactly
|
||||
one supported catalog pair.
|
||||
|
||||
Reference in New Issue
Block a user