Files
weatherreporter/docs/roadmap/tomorrow.md

9.7 KiB

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:

# 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:

{
  "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:

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:

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.