# 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: ```markdown # Monday's Weather **Forecast date:** Monday, June 15, 2026 **Updated:** Sunday, June 14, 2026 at 9:14 AM ## Daypart Forecast - **Morning:** - **Midday:** - **Afternoon:** - **Evening:** ## 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. - ## Forecast Discussion ``` 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: ```sh 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: ```json { "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: ```go 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: ```sh 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.