Files
weatherreporter/docs/roadmap/tomorrow.md

277 lines
9.7 KiB
Markdown

# Tomorrow Report Roadmap
## Purpose
This roadmap defines the target state for making Tomorrow an independent
generated-text-template report. The feature is not implemented yet, so this
document lives under `docs/roadmap/`.
## Intent
Tomorrow should become its own report product, not a variant of the Daily
Report. The current CLI command `weatherreporter generate tomorrow` should
remain, but the internal report ID, prompt ID, template, schema, workspace
paths, and distributor identity should use `tomorrow`.
The report should combine deterministic daypart and precipitation facts with
LLM prose for the high-level summary, optional precipitation context, and
forecast discussion. The resulting Markdown should be predictable and
template-driven, similar to the implemented Hourly Report.
Longer term, Today, Tomorrow, and Daily may all become separate report products
with different prompts, templates, and deterministic sections. This roadmap
starts that split with Tomorrow.
## Target Report Shape
Example structure:
```markdown
# Sunday's Weather
**Forecast Date:** Sunday, June 15, 2026
**Generated:** Saturday, June 14, 2026 at 9:14 AM
<GeneratedText summary>
## Daypart Forecast
- **Overnight:** <deterministic daypart line>
- **Morning:** <deterministic daypart line>
- **Midday:** <deterministic daypart line>
- **Afternoon:** <deterministic daypart line>
- **Evening:** <deterministic daypart line>
## Precipitation Timing
- **1:00 AM** to **5:00 AM**: Precipitation is expected during this period. The peak precipitation chance is 59% at 2:00 AM.
- <optional GeneratedText precipitation_timing>
## Forecast Discussion
<GeneratedText forecast_discussion paragraphs>
```
`Precipitation Timing` should render only when at least one precipitation
window exists for the valid period. The threshold for precipitation windows
remains the existing precipitation-window threshold, currently 40%.
## Locked Decisions
- Replace report ID `daily_tomorrow` with `tomorrow`.
- Do not preserve compatibility aliases for `daily_tomorrow`; this is a
pre-release clean break.
- Keep public CLI syntax: `weatherreporter generate tomorrow`.
- Use generated-text-template generation for Tomorrow, not full Markdown
generation by Scriptorium.
- Use a dedicated Scriptorium prompt ID, template ID, and schema ID:
- prompt ID: `weather.tomorrow_generated_text`
- template ID: `tomorrow`
- generated-text schema ID: `tomorrow`
- Use `ArtifactGroup: "tomorrow"` and `BatchOutputName: "tomorrow.md"`.
- Use `CompatiblePriorIDs: []report.ID{report.Tomorrow}`.
- Keep valid-period behavior: Tomorrow covers the next local civil day.
- Keep Morning/Evening batch behavior unless explicitly changed later; evening
batch should still include Tomorrow.
- Future Today/Daily split is out of scope for this roadmap.
## GeneratedText Contract
Add a Tomorrow GeneratedText schema:
```json
{
"summary": "string",
"forecast_discussion": ["string"],
"precipitation_timing": "string",
"confidence": "string"
}
```
Required:
- `summary`
- `forecast_discussion`
Optional:
- `precipitation_timing`
- `confidence`
`forecast_discussion` should be an array of paragraph strings so Scriptorium
can return multi-paragraph discussion without embedding paragraph delimiters in
one string. Empty or whitespace-only discussion paragraphs should be rejected or
trimmed out during validation; after trimming, at least one paragraph is
required.
`confidence` may be validated and persisted but does not need to render in the
initial template.
## Template Context
Add a dedicated Tomorrow render context rather than reusing Hourly context
types.
Recommended top-level shape:
```go
type TomorrowRenderContext struct {
Report TomorrowReportContext
GeneratedText Tomorrow
Modules TomorrowTemplateModules
Collected facts.CollectedFacts
Derived facts.DerivedFacts
}
```
`TomorrowReportContext` should include:
- `Title`: for example `Sunday's Weather`
- `ForecastDate`: canonical local forecast date if useful
- `ForecastDateLabel`: for example `Sunday, June 15, 2026`
- `ForecastDayName`: for example `Sunday`
- `GeneratedAt`
- `GeneratedAtLabel`: for example `Saturday, June 14, 2026 at 9:14 AM`
- `ValidPeriod`
- `Timezone`
Do not derive the possessive title in the template. Go should provide `Title`
so wording is consistent and easy to test.
`TomorrowTemplateModules` should expose the module outputs needed by the
template:
- `Metadata`
- `DerivedDailySummary`
- `DerivedDaypartSummaries`
- `PrecipTiming`
- `AlertDigest`
- `SPCConvectiveOutlooks`
- `AreaForecastDiscussion`
- `SPCConvectiveDiscussion`
- `WeatherStory`
- `TomorrowPlanning`, if still useful
Current conditions and hourly forecast can remain in the module snapshot and
data package if useful for Scriptorium, but they do not need to render in the
initial Tomorrow template unless a later design calls for them.
## Daypart Forecast
The Daypart Forecast should be deterministic but composable. Avoid adding a
single prewritten Go `DaypartLine` string that makes template wording rigid.
Add presentation-friendly fields to `derived_daypart_summaries` only where they
avoid awkward template logic. Likely useful fields:
- display name, such as `Overnight` or `Morning`;
- lower-case dominant condition text for inline sentences;
- rounded temperature range phrase if available;
- precipitation mention flag using the existing hourly line mention threshold
concept, currently 20%;
- max precipitation probability and friendly max time;
- optional wind phrase or wind range only if deterministic wind wording is
clearly needed.
The initial implementation may keep daypart bullet wording simple. It should be
easy to revise the template text without editing Go unless new facts are
needed.
## Implementation Plan
1. Report identity split
- Rename `report.DailyTomorrow` to `report.Tomorrow` with ID `tomorrow`.
- Update registry order, resolver references, CLI mapping, batch selection,
state metadata expectations, docs, and tests.
- Preserve `weatherreporter generate tomorrow`.
- Accept that workspace paths, RunIDs, distributor bundle IDs, and report
URLs change from `daily_tomorrow` to `tomorrow`.
2. GeneratedText contract
- Add `generatedtext.Tomorrow`, validation, normalized JSON output, and
tests.
- Add `tomorrow.generated_text.schema.json`.
- Add `internal/reporttemplate/prompts/tomorrow.generated_text.md` as the
maintained prompt source asset.
- Update app validation dispatch to use the Tomorrow schema.
3. Template and render context
- Add `internal/reporttemplate/templates/tomorrow.md.tmpl`.
- Add Tomorrow template/schema lookup entries.
- Add `BuildTomorrowRenderContext`.
- Update app render-context dispatch for template ID `tomorrow`.
- Persist render context in the existing generated-text-template workflow.
4. Module presentation fields
- Add only the daypart presentation fields needed by the template.
- Reuse the existing precipitation window hour-label fields.
- Keep deterministic weather derivation in Go and wording/layout in the
template.
5. Report definition conversion
- Change Tomorrow report definition to:
- `PromptID: "weather.tomorrow_generated_text"`
- `GenerationMode: generated_text_template`
- `TemplateID: "tomorrow"`
- `GeneratedTextSchemaID: "tomorrow"`
- `ArtifactGroup: "tomorrow"`
- `BatchOutputName: "tomorrow.md"`
- compatible prior IDs containing only `tomorrow`
- Review module composition and keep only modules used by the prompt,
template, or future inspection value.
6. Documentation and examples
- After implementation, update non-roadmap docs for implemented behavior:
`docs/cli.md`, `docs/operations.md`, `docs/internal/report-registry.md`,
`docs/internal/generatedtext.md`, `docs/internal/reporttemplate.md`, and
`docs/templates.md`.
- Update examples that refer to `reports.tomorrow` or report module
overrides if the config key changes.
## Test Plan
- Report tests:
- registry contains `tomorrow`, not `daily_tomorrow`;
- `generate tomorrow` resolves report ID `tomorrow`;
- valid period remains next local civil day;
- evening batch still includes Tomorrow;
- RunID and artifact paths use `tomorrow`.
- GeneratedText tests:
- `summary` and non-empty `forecast_discussion` are required;
- `forecast_discussion` trims paragraph strings and rejects/omits blanks;
- optional `precipitation_timing` and `confidence` normalize correctly;
- unknown fields are rejected.
- Template tests:
- title renders as `<weekday>'s Weather`;
- forecast date and generated labels render;
- daypart bullets render in configured daypart order;
- precipitation section is omitted when no precipitation windows exist;
- precipitation section includes deterministic windows and optional LLM text
when windows exist;
- forecast discussion renders multiple paragraphs.
- App/CLI workflow tests:
- `weatherreporter generate tomorrow` uses structured Scriptorium output and
the template renderer;
- raw generated text, validated generated text, render context, report, and
metadata artifacts are persisted;
- optional `--out` behavior remains unchanged;
- distributor notification uses report ID/artifact group `tomorrow`.
Validation commands:
```bash
go test ./internal/report ./internal/generatedtext ./internal/reporttemplate ./internal/briefing ./internal/app ./internal/cli ./internal/state
go test ./...
go run ./cmd/weatherreporter --help
git diff --check
```
## Open Questions
None block implementation. Recommended defaults are:
- make `forecast_discussion` an array of strings for Tomorrow;
- keep Hourly GeneratedText unchanged for now;
- do not add Daily Today or generic Daily report splits in this change;
- do not preserve `daily_tomorrow` compatibility aliases.