Files
weatherreporter/docs/roadmap/daily.md

14 KiB

Daily Report Roadmap

Purpose

This roadmap defines the target state and implementation work needed to replace the existing daily report with a new generated-text-template daily report.

The new report is not implemented yet. Current report behavior remains documented outside docs/roadmap/.

Intent

Daily should be an independent generated-text-template report for a user-chosen local civil day. Its rendered Markdown should initially match the Tomorrow Report format exactly, but its identity, prompt, template, schema, valid-period resolver, config key, and planning module should be separate from Tomorrow from the start.

The important distinction is date selection:

  • tomorrow always targets the next local civil day.
  • daily targets the local civil day explicitly supplied by the user with --date YYYY-MM-DD.

This is a clean breaking replacement of the current Daily implementation:

  • The existing direct-Markdown daily report is removed.
  • The legacy daily_today report ID is removed from active report definitions.
  • weatherreporter generate daily remains the public command name, but it now runs the new generated-text-template Daily report.
  • weatherreporter generate daily requires --date YYYY-MM-DD.
  • Existing historical daily_today workspace artifacts do not need migration.

Locked Decisions

  • New report ID: daily.
  • Public command: generate daily.
  • generate daily must require --date YYYY-MM-DD.
  • The provided date is interpreted as a civil date in the effective report timezone.
  • The valid period is the selected local civil day, [00:00, next 00:00).
  • Daily should not be an alias for Today or Tomorrow.
  • Today remains the current-day scheduled morning product.
  • Tomorrow remains the next-day scheduled evening product.
  • Daily is manually targeted by date and is not added to morning or evening batch membership in this roadmap.
  • Daily must have its own template, generated-text schema, prompt asset, render-context type, and planning module.
  • Daily may share private helper functions with Tomorrow where mechanics are identical, but it must not expose Tomorrow-specific public types or stanzas.
  • The initial Daily output format should match Tomorrow's rendered Markdown format.

Target Report Shape

Daily should render the same Markdown structure as Tomorrow:

# Monday's Weather

**Forecast date:** Monday, June 15, 2026
**Updated:** Sunday, June 14, 2026 at 9:14 AM

<GeneratedText summary>

## Daypart Forecast

- **Morning:** <deterministic daypart line>
- **Midday:** <deterministic daypart line>
- **Afternoon:** <deterministic daypart line>
- **Evening:** <deterministic daypart line>

## Precipitation Timing

- **1:00 PM** to **5:00 PM**: Precipitation is expected during this period.
  The peak precipitation chance is 59% at 2:00 PM.
- <optional GeneratedText precipitation_timing>

## Forecast Discussion

<GeneratedText forecast_discussion paragraphs>

The precipitation section should render only when precipitation windows exist for the selected valid period.

The title should follow Tomorrow's day-name style, for example:

  • Monday's Weather
  • Tuesday's Weather
  • Sunday's Weather

Report Identity

Replace the existing active Daily report with:

  • report ID: daily
  • public generate command: daily
  • prompt ID: weather.daily_generated_text
  • generation mode: generated_text_template
  • template ID: daily
  • generated-text schema ID: daily
  • artifact group: daily
  • batch output name: daily.md
  • prior compatibility: Daily only
  • comparison strategy: same valid local date
  • valid period: selected local civil day in the effective report timezone, [00:00, next 00:00)

Remove the legacy active report identity:

  • remove active report ID daily_today
  • remove prompt ID weather.daily_report from the current Daily path
  • remove direct-Markdown generation mode from the Daily report definition
  • remove daily_today config-key support unless a separate migration roadmap explicitly reintroduces it

Historical artifacts with daily_today metadata may remain on disk. Do not migrate or rewrite old workspace files in this feature.

CLI Behavior

weatherreporter generate daily should require:

weatherreporter generate daily --date YYYY-MM-DD

Rules:

  • --date is required for generate daily.
  • --date accepts only YYYY-MM-DD.
  • The date is interpreted in the effective report timezone after config and --tz overrides are applied.
  • Omitting --date is an error.
  • A malformed date is an error.
  • The command should continue supporting the existing global generation flags: --config, --units, --tz, and --out.
  • Do not default daily to today or tomorrow.

Batch Behavior

Daily should not be added to scheduled batches in this roadmap.

Current intended scheduled behavior:

  • Morning batch: today, three_day, and conditional weekend.
  • Evening batch: tomorrow.

Daily is a manually targeted report. A future roadmap may add scheduled Daily behavior if a concrete operational need appears.

GeneratedText Contract

Daily should use the same structured prose shape as Tomorrow:

{
  "summary": "string",
  "forecast_discussion": ["string"],
  "precipitation_timing": "string",
  "confidence": "string"
}

Required:

  • summary
  • forecast_discussion

Optional:

  • precipitation_timing
  • confidence

Validation should match Tomorrow semantics:

  • reject malformed JSON and unknown fields
  • reject trailing JSON values
  • trim summary, precipitation_timing, and confidence
  • trim each forecast_discussion paragraph
  • drop blank discussion paragraphs
  • require at least one nonblank discussion paragraph
  • return canonical normalized JSON with the same public field names

Add a dedicated prompt asset:

  • internal/reporttemplate/prompts/daily.generated_text.md

Scriptorium registration remains out of band. Weatherreporter should invoke the Daily prompt by prompt ID and pass the data package as it does for other generated-text reports.

Template Context

Add dedicated Daily types under internal/generatedtext, rather than reusing Tomorrow types directly:

type DailyRenderContext struct {
    Report        DailyReportContext
    GeneratedText Daily
    Modules       DailyTemplateModules
    Collected     facts.CollectedFacts
    Derived       facts.DerivedFacts
}

DailyReportContext should include:

  • Title, for example Monday's Weather
  • ForecastDate
  • ForecastDateLabel, for example Monday, June 15, 2026
  • ForecastDayName, for example Monday
  • GeneratedAt
  • GeneratedAtLabel
  • ValidPeriod
  • Timezone

DailyTemplateModules should expose the same categories the Daily template needs:

  • Metadata
  • CurrentConditions
  • HourlyForecast
  • DerivedDailySummary
  • DerivedDaypartSummaries
  • ordered daypart rows
  • PrecipTiming
  • AlertDigest
  • SPCConvectiveOutlooks
  • AreaForecastDiscussion
  • SPCConvectiveDiscussion
  • WeatherStory
  • OutdoorWindows
  • DailyPlanning

Daily may share private helper functions with Tomorrow render-context construction when the helper represents identical mechanics. Do not expose Tomorrow-specific types through the Daily template context.

Module Composition

The default module composition should initially mirror Tomorrow where the same facts are useful for a dated daily report, with a Daily-specific planning module:

  • metadata
  • current_conditions
  • narrative_forecast
  • derived_daily_summary
  • derived_daypart_summaries
  • precip_timing
  • alert_digest
  • spc_convective_outlooks
  • area_forecast_discussion
  • spc_convective_discussion
  • weather_story
  • outdoor_windows
  • daily_planning
  • hourly_forecast

The module order should match the intended data-package order unless tests show a stronger reason to mirror Tomorrow's exact current order.

Daily Planning Module

Add a Daily-specific deterministic planning module:

  • module ID: daily_planning
  • stanza name: daily_planning
  • options type: DailyPlanningOptions
  • output type: DailyPlanningModule
  • supported report: daily

The module should be initially equivalent to TomorrowPlanning, but independent from it:

  • do not reuse the public TomorrowPlanningModule type
  • do not emit the tomorrow_planning stanza
  • do not use module.TomorrowPlanning in the Daily default composition

Recommended initial fields should match Tomorrow planning:

  • morning_readiness
  • commute_school_workday_concerns
  • overnight_change_watch

Private helper functions may be shared with Tomorrow planning when the underlying logic is truly identical.

Implementation Plan

  1. Replace Daily report identity.

    • Add report.Daily with value daily.
    • Remove active report.DailyToday and the daily_today report definition.
    • Replace dailyTodayDefinition with a generated-text-template dailyDefinition.
    • Ensure report.DefaultRegistry() includes daily and not daily_today.
    • Ensure report.IDForCommandName("daily") returns report.Daily.
    • Ensure report.IDForConfigKey("daily") returns report.Daily.
    • Ensure report.IDForConfigKey("daily_today") is rejected.
    • Add a resolver that requires a supplied target date.
  2. Update CLI date behavior.

    • Keep parsing --date YYYY-MM-DD for generate daily.
    • Change missing --date from default-current-date behavior to an actionable error.
    • Keep generate today as the current-day report with its own date behavior as currently implemented.
    • Keep generate tomorrow date-free.
  3. Add Daily planning module.

    • Add module.DailyPlanning.
    • Add DailyPlanningOptions.
    • Add DailyPlanningModule and builder under internal/briefing.
    • Register it only for report.Daily.
    • Add tests for output shape, supported report, unsupported reports, and empty/fallback behavior.
  4. Add Daily generated-text validation and assets.

    • Add generatedtext.Daily.
    • Add ValidateDaily.
    • Add daily.generated_text.schema.json.
    • Add daily.generated_text.md.
    • Add daily.md.tmpl.
    • Register Daily in the generated-text catalog and reporttemplate asset lookup.
  5. Add Daily template context.

    • Add DailyRenderContext, DailyReportContext, and DailyTemplateModules.
    • Add BuildDailyRenderContext.
    • Use Daily-specific public types.
    • Share private snapshot/daypart helper mechanics only where appropriate.
  6. Integrate app workflow.

    • Ensure weatherreporter generate daily --date YYYY-MM-DD runs through the generated-text-template workflow.
    • Persist raw generated text, structured run result, normalized generated text, render context, Markdown report, metadata, and optional output copy.
    • Ensure report metadata, RunID, artifact paths, data-package paths, distributor template variables, and rendered report use report ID daily.
    • Ensure Daily Recent Changes uses same-valid-date comparison against prior Daily snapshots.
  7. Update implemented documentation after code changes.

    • Update docs/cli.md, docs/config.md, docs/operations.md, docs/templates.md, docs/internal/report-registry.md, docs/internal/generatedtext.md, docs/internal/reporttemplate.md, docs/internal/module.md, docs/internal/app-orchestration.md, and maintained examples as needed.
    • Non-roadmap docs must describe only the implemented Daily behavior after the code changes land.
    • Remove implemented-doc references that describe daily_today as an active report.

Test Plan

Add or update tests for:

  • report registry membership for daily
  • removal of active daily_today
  • daily command-name resolution to daily
  • config-key resolution for reports.daily
  • rejection of reports.daily_today
  • valid period for an explicit daily target date in the configured timezone
  • missing --date error for generate daily
  • malformed --date error for generate daily
  • generated-text unknown fields, trailing JSON, missing required fields, blank fields, paragraph trimming, and canonical output
  • generated-text catalog completeness
  • template/schema asset lookup
  • render context labels, module extraction, nil optional modules, Daily planning extraction, and daypart ordering
  • Daily planning module output and supported-report validation
  • app workflow artifacts for generate daily --date YYYY-MM-DD
  • optional --out copy behavior
  • distributor template values and managed report notification source
  • config report module overrides for reports.daily
  • no scheduled batch membership for Daily

Suggested validation:

go test ./internal/report ./internal/generatedtext ./internal/reporttemplate
go test ./internal/briefing ./internal/module
go test ./internal/app ./internal/cli ./internal/config
go test ./...
go run ./cmd/weatherreporter --help
git diff --check

Documentation Updates After Implementation

Update implemented docs only after the code exists:

  • docs/cli.md: document generate daily --date YYYY-MM-DD as required.
  • docs/config.md: document reports.daily module overrides and remove reports.daily_today from implemented config docs.
  • docs/operations.md: document Daily artifact paths and manual dated report behavior.
  • docs/templates.md: document Daily template variables.
  • docs/internal/report-registry.md: document Daily report identity and removal of active Daily Today.
  • docs/internal/generatedtext.md: document Daily generated-text schema and validation behavior.
  • docs/internal/reporttemplate.md: document Daily template assets.
  • docs/internal/module.md: document daily_planning.
  • docs/internal/app-orchestration.md: document Daily workflow only if it differs from the generic generated-text-template flow.

Ambiguities Addressed

  • Replacement scope: new daily replaces and removes old active daily_today.
  • Date behavior: --date is required; no default date is used.
  • Output format: initial rendered Markdown matches Tomorrow.
  • Internal separation: Daily has its own template, schema, prompt, generated text type, render context, and planning module.
  • Batch behavior: Daily is not scheduled; Today remains the morning current-day scheduled product.
  • Historical artifacts: old daily_today workspace files are not migrated.

Open Decisions

No open decisions remain that block implementation.

Future decisions that should not be resolved in this roadmap:

  • Whether Daily should eventually support recurring scheduled generation.
  • Whether Daily should diverge from Tomorrow's template or planning logic.
  • Whether old daily_today workspace artifacts should ever receive a migration or inspection compatibility layer.