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:
tomorrowalways targets the next local civil day.dailytargets 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
dailyreport is removed. - The legacy
daily_todayreport ID is removed from active report definitions. weatherreporter generate dailyremains the public command name, but it now runs the new generated-text-template Daily report.weatherreporter generate dailyrequires--date YYYY-MM-DD.- Existing historical
daily_todayworkspace artifacts do not need migration.
Locked Decisions
- New report ID:
daily. - Public command:
generate daily. generate dailymust 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 WeatherTuesday's WeatherSunday'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_reportfrom the current Daily path - remove direct-Markdown generation mode from the Daily report definition
- remove
daily_todayconfig-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:
--dateis required forgenerate daily.--dateaccepts onlyYYYY-MM-DD.- The date is interpreted in the effective report timezone after config and
--tzoverrides are applied. - Omitting
--dateis 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
dailyto 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 conditionalweekend. - 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:
summaryforecast_discussion
Optional:
precipitation_timingconfidence
Validation should match Tomorrow semantics:
- reject malformed JSON and unknown fields
- reject trailing JSON values
- trim
summary,precipitation_timing, andconfidence - trim each
forecast_discussionparagraph - 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 exampleMonday's WeatherForecastDateForecastDateLabel, for exampleMonday, June 15, 2026ForecastDayName, for exampleMondayGeneratedAtGeneratedAtLabelValidPeriodTimezone
DailyTemplateModules should expose the same categories the Daily template
needs:
MetadataCurrentConditionsHourlyForecastDerivedDailySummaryDerivedDaypartSummaries- ordered daypart rows
PrecipTimingAlertDigestSPCConvectiveOutlooksAreaForecastDiscussionSPCConvectiveDiscussionWeatherStoryOutdoorWindowsDailyPlanning
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:
metadatacurrent_conditionsnarrative_forecastderived_daily_summaryderived_daypart_summariesprecip_timingalert_digestspc_convective_outlooksarea_forecast_discussionspc_convective_discussionweather_storyoutdoor_windowsdaily_planninghourly_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
TomorrowPlanningModuletype - do not emit the
tomorrow_planningstanza - do not use
module.TomorrowPlanningin the Daily default composition
Recommended initial fields should match Tomorrow planning:
morning_readinesscommute_school_workday_concernsovernight_change_watch
Private helper functions may be shared with Tomorrow planning when the underlying logic is truly identical.
Implementation Plan
-
Replace Daily report identity.
- Add
report.Dailywith valuedaily. - Remove active
report.DailyTodayand thedaily_todayreport definition. - Replace
dailyTodayDefinitionwith a generated-text-templatedailyDefinition. - Ensure
report.DefaultRegistry()includesdailyand notdaily_today. - Ensure
report.IDForCommandName("daily")returnsreport.Daily. - Ensure
report.IDForConfigKey("daily")returnsreport.Daily. - Ensure
report.IDForConfigKey("daily_today")is rejected. - Add a resolver that requires a supplied target date.
- Add
-
Update CLI date behavior.
- Keep parsing
--date YYYY-MM-DDforgenerate daily. - Change missing
--datefrom default-current-date behavior to an actionable error. - Keep
generate todayas the current-day report with its own date behavior as currently implemented. - Keep
generate tomorrowdate-free.
- Keep parsing
-
Add Daily planning module.
- Add
module.DailyPlanning. - Add
DailyPlanningOptions. - Add
DailyPlanningModuleand builder underinternal/briefing. - Register it only for
report.Daily. - Add tests for output shape, supported report, unsupported reports, and empty/fallback behavior.
- Add
-
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.
- Add
-
Add Daily template context.
- Add
DailyRenderContext,DailyReportContext, andDailyTemplateModules. - Add
BuildDailyRenderContext. - Use Daily-specific public types.
- Share private snapshot/daypart helper mechanics only where appropriate.
- Add
-
Integrate app workflow.
- Ensure
weatherreporter generate daily --date YYYY-MM-DDruns 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.
- Ensure
-
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_todayas an active report.
- Update
Test Plan
Add or update tests for:
- report registry membership for
daily - removal of active
daily_today dailycommand-name resolution todaily- config-key resolution for
reports.daily - rejection of
reports.daily_today - valid period for an explicit daily target date in the configured timezone
- missing
--dateerror forgenerate daily - malformed
--dateerror forgenerate 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
--outcopy 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: documentgenerate daily --date YYYY-MM-DDas required.docs/config.md: documentreports.dailymodule overrides and removereports.daily_todayfrom 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: documentdaily_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
dailyreplaces and removes old activedaily_today. - Date behavior:
--dateis 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_todayworkspace 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_todayworkspace artifacts should ever receive a migration or inspection compatibility layer.